/* ===== 00-tokens.css ===== */
/*
 * Link Prism design tokens.
 *
 * Derived from the Steep style reference (docs: DESIGN.md) with two corrections
 * made after measuring the real site, both of which the written reference omits
 * and both of which are what actually make it read as premium:
 *   1. The hero is NOT flat white — it sits on a soft chromatic gradient wash.
 *   2. A fractal-noise grain overlays the whole page at low opacity.
 * Everything else here matches the reference's documented scale.
 */
:root {
  /* — Ink & paper —————————————————————————————— */
  --ink: #17191c;
  /*
   * Paper is NOT pure white, deliberately. Two reasons, both measured:
   *  - `overlay` grain over #ffffff is an identity operation (overlay(1,x) === 1),
   *    so a pure-white page can carry no texture at all.
   *  - The reference's "white" is never actually white; every band sits on a
   *    faint warm ground, which is most of why it reads as paper and not screen.
   */
  --paper: #fdfcfa;
  --raised: #ffffff;        /* floating artifacts stay true white so they lift off the paper */
  --mist: #f2f2f3;
  --fog: #fafafb;
  /*
   * These three were taken from the reference palette and all FAILED WCAG AA on
   * our paper: slate 4.13:1, ash 2.84:1, smoke 2.37:1 against 4.5:1 for small
   * text. Every eyebrow, footnote and body paragraph on the site was below the
   * threshold. Darkened within the same family until they pass; the greys read
   * fractionally deeper and everything stays legible.
   */
  --slate: #636772;   /* 4.52:1 worst ground (peach) — body copy, ledes, muted text */
  --ash:   #686c76;   /* 4.70:1 worst ground (mist) — eyebrows, footnotes, labels  */
  --smoke: #7d818b;   /* 3.80:1 — LARGE type only (>=24px), never small text */

  /*
   * TEXT ON DARK SURFACES. The greys above are light-ground tokens; several
   * sections place a dark ink panel on the page and reused them inside it, where
   * mid-grey on near-black measures 3.4:1. These are the dark-surface equivalents
   * and are the ONLY muted colours permitted inside an ink panel.
   */
  --on-dark:        color-mix(in srgb, var(--paper) 92%, transparent);  /* body on ink   */
  --on-dark-muted:  color-mix(in srgb, var(--paper) 66%, transparent);  /* labels, ~7:1  */
  --on-dark-faint:  color-mix(in srgb, var(--paper) 48%, transparent);  /* LARGE type only */
  --peach: #fbe1d1;
  --sienna: #5d2a1a;
  --hair: #ececec;
  --hair-strong: rgba(23, 25, 28, 0.12);

  /* Warm tints for the gradient wash — same family as --peach, never used as text */
  --wash-1: #ffd9c2;
  --wash-2: #ffe9d6;
  --wash-3: #f0e2f2;
  --wash-4: #dfe6f5;

  /* — Type —————————————————————————————————————— */
  --serif: 'Source Serif 4', 'Iowan Old Style', Georgia, ui-serif, serif;
  --sans: 'Inter', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;

  --t-caption: 15px;
  --t-body: 17px;
  --t-body-lg: 20px;
  --t-subhead: 22px;
  --t-h-sm: 26px;
  --t-h: 44px;
  --t-h-lg: 64px;
  --t-display: 90px;

  /* Tracking tightens as size grows — the typographic signature of the system */
  --tr-display: -0.025em;
  --tr-h-lg: -0.015em;
  --tr-h: -0.015em;
  --tr-h-sm: -0.009em;
  --tr-body-lg: -0.009em;

  /* — Space (4px base) ————————————————————————— */
  --s4: 4px;   --s8: 8px;   --s12: 12px; --s16: 16px; --s20: 20px;
  --s24: 24px; --s28: 28px; --s32: 32px; --s40: 40px; --s48: 48px;
  --s64: 64px; --s80: 80px; --s96: 96px; --s128: 128px; --s160: 160px;

  --nav-h: 76px;
  --page: 1200px;
  --gutter: 32px;

  /*
   * THREE SECTION RHYTHMS, AND ONLY THREE.
   *
   * Nineteen section files used to set their own band height, and they split
   * into two systems: multipliers of --section-y (0.66, 0.82, 1.2, 1.7 …) and
   * fixed pixels (104, 112, 136, 176 …). The two agree at exactly one viewport
   * width and separate everywhere else, so the page's vertical beat changed
   * with the window. Every band now picks one of these and nothing derives its
   * own.
   */
  --section-y-tight: 64px;   /* a strip: a logo rail, a short ledger */
  --section-y: 96px;         /* the normal band — most of the site */
  --section-y-loose: 128px;  /* a stage: the closing band, a tall drawing */

  /*
   * ONE HERO OPENING for all eight pages. The nav is sticky and 76px tall and
   * every hero is pulled up under it, so this figure INCLUDES the nav band:
   * 148 is 72px of visible air above the first mark, on every page. It used to
   * run 148 / 172 / 228 / 244 / 252 across eight heroes that share one nav.
   */
  --hero-y: 148px;

  /* One eyebrow, one gap under it. Seventeen instances used to set thirteen. */
  --eyebrow-gap: var(--s24);

  /* — Shape ——————————————————————————————————— */
  --r-card: 24px;
  --r-elevated: 20px;
  --r-input: 16px;
  --r-small: 16px;
  --r-pill: 9999px;

  /* — Drawings ————————————————————————————————
   * TWO sizes for the whole site, and no third. A set of drawings at six
   * different sizes is size used as hierarchy, which _src/ILLUSTRATION.md
   * items 3 and 7 forbid: a terminal and a printer are comparable objects and
   * must be drawn comparably. `card` is the mark that sits inside a card in a
   * grid; `feature` is the one drawing a section is built around. Both are
   * CEILINGS — `.illo--card` / `.illo--feature` pair them with width:100%, so a
   * narrow column still fits its drawing without inventing a third size.
   */
  --illo-card: 250px;
  --illo-feature: 500px;

  /* Only floating product artifacts earn elevation. Content cards stay flat. */
  --sh-artifact: 0 0 0 1px rgba(4, 23, 43, 0.05), 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1);
  --sh-overlay: 0 0 0 1px rgba(0, 0, 0, 0.05), 0 8px 40px 0 rgba(0, 0, 0, 0.1);
  --sh-pop: 0 0 0 1px rgba(0, 0, 0, 0.05), 0 4px 24px 0 rgba(0, 0, 0, 0.08);

  /* — Motion ——————————————————————————————————— */
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --dur-fast: 160ms;
  --dur: 320ms;
  --dur-slow: 720ms;
}

/* The three rhythms and the hero opening ramp together, so the ratios between
   them hold at every width and no section has to re-tune itself. */
@media (max-width: 1080px) {
  :root { --t-display: 68px; --t-h-lg: 48px; --t-h: 36px; --gutter: 28px;
          --section-y-tight: 56px; --section-y: 80px; --section-y-loose: 104px;
          --hero-y: 124px; }
}
@media (max-width: 720px) {
  :root { --t-display: 44px; --t-h-lg: 34px; --t-h: 28px; --t-h-sm: 22px;
          --t-body-lg: 18px; --gutter: 20px; --r-card: 20px;
          --section-y-tight: 40px; --section-y: 64px; --section-y-loose: 80px;
          --hero-y: 104px; }
}

/* ===== 10-base.css ===== */
/* Reset + page substrate: the grain and the gradient wash live here. */
*, *::before, *::after { box-sizing: border-box; }
/*
 * `overflow-x: clip` on the ROOT, not `hidden` on body alone.
 * Sections intentionally crop product cards past the viewport edge; with only
 * body clipping, the document still grew (measured 1510px against a 1440px
 * viewport) and shipped a horizontal scrollbar. `clip` contains it WITHOUT
 * creating a scroll container, so the sticky nav keeps working — `hidden` would
 * silently break it.
 */
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; overflow-x: clip; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: var(--t-body);
  line-height: 1.35;
  font-weight: 400;
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: clip;
}

h1, h2, h3, h4, p, figure, blockquote { margin: 0; }
img, svg { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; }

/*
 * THE GRAIN. A fractal-noise tile at low opacity in `overlay` blend, fixed to the
 * viewport so it never scrolls against the content. This is the single largest
 * contributor to the reference's "printed paper" quality and it is absent from
 * every written description of the system.
 */
body::after {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 9999;
  pointer-events: none;
  /*
   * `multiply`, not `overlay`. The noise tile is opaque-black-or-transparent, and
   * overlay leaves any near-white base untouched — the grain was mathematically
   * invisible across every light section. Multiply darkens the speckle instead,
   * so the texture reads on paper AND on the warm wash.
   */
  opacity: 0.13;
  mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.91' numOctaves='2' seed='7' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3CfeComponentTransfer%3E%3CfeFuncA type='discrete' tableValues='0 1'/%3E%3C/feComponentTransfer%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 180px 180px;
}
@media (prefers-reduced-motion: no-preference) { body::after { will-change: opacity; } }

/* Layout primitives.
   ONE page rail, and every headline block on the site sits on it. There used to
   be a second, wider container (`.wrap-wide`, 1400) used by three sections; at
   1440 it put their headlines on the 32px page gutter while their neighbours
   held 120, an 88px jump between consecutive sections. Full bleed is still
   legal — a drawing, a rule, a background band — but it is done per element,
   never by moving a headline off the rail. */
.wrap { width: min(var(--page), 100% - var(--gutter) * 2); margin-inline: auto; }
.section { padding-block: var(--section-y); position: relative; }
.section--fog { background: var(--fog); }
.section--mist { background: var(--mist); }

/* Type primitives */
.display, .h-lg, .h, .h-sm-serif {
  font-family: var(--serif);
  font-weight: 400;
  font-optical-sizing: auto;
  text-wrap: balance;
  /*
   * THE SIDEBEARING CORRECTION, ONCE, FOR THE WHOLE SITE.
   *
   * A serif cap set flush to a rail reads as indented: the stem sits inside the
   * glyph's left sidebearing, while the sans eyebrow above it and the sans lede
   * below it start on their own ink. Pulling the block back a hair of its own
   * size puts the STEM on the rail, and stated in em it re-derives itself at
   * every step of the type ramp instead of needing a value per breakpoint.
   * Measured on Source Serif 4: cap B, lowercase b and the italic a all land
   * within 1px of each other at -0.026em.
   *
   * This lived in hardware-hero.css as a private rule, bundled with a 64px
   * "hang" that pulled that one title to x=54 while its own eyebrow held 120.
   * The hang is gone; the correction is shared. Three more sections carried
   * near-duplicates of it (-0.02, -0.023, -0.03) and now inherit this one.
   *
   * A CENTRED serif block must switch it off — see .prh-title in pricing-hero —
   * because there the margin moves the centre rather than the left edge.
   */
  margin-left: -0.026em;
}
.display { font-size: var(--t-display); line-height: 1.06; letter-spacing: var(--tr-display); }
.h-lg    { font-size: var(--t-h-lg);   line-height: 1.1;  letter-spacing: var(--tr-h-lg); }
.h       { font-size: var(--t-h);      line-height: 1.16; letter-spacing: var(--tr-h); }
.h-sm-serif { font-size: var(--t-h-sm); line-height: 1.28; letter-spacing: var(--tr-h-sm); }
.display em, .h-lg em, .h em { font-style: italic; }

/*
 * THE ONE FIT-TO-WIDTH OPT-IN, AND THE ONLY ONE.
 *
 * A headline whose authored line genuinely cannot hold the phone column takes
 * this class on top of its scale class instead of inventing a divisor of its
 * own. Six inner heroes each invented one, and at 390px they rendered the same
 * rank at 31.8 / 41 / 41.6 / 42 / 44 and 48px — a 1.8x spread across six
 * elements that are the same thing.
 *
 * It can only ever make type SMALLER than the ramp: it is a min() against the
 * token, so it cannot be used to promote a headline past the class it wears.
 * The divisor is taken from the widest binding line on the site — "When
 * something breaks," which Source Serif sets at 10.47em once the optical axis
 * has opened the face up at small sizes — so one number covers every candidate.
 * Above about 414px of viewport it stops binding entirely and the token ramp is
 * the only thing sizing the line.
 */
.h-fit { font-size: min(var(--t-h-lg), calc((100vw - var(--gutter) * 2) / 11)); }

.h-sm { font-family: var(--sans); font-size: var(--t-h-sm); font-weight: 450;
        line-height: 1.22; letter-spacing: var(--tr-h-sm); }
.lede { font-size: var(--t-body-lg); line-height: 1.45; letter-spacing: var(--tr-body-lg);
        color: var(--slate); text-wrap: pretty; }
.body { font-size: 16px; line-height: 1.55; color: var(--slate); text-wrap: pretty; }
.caption { font-size: var(--t-caption); line-height: 1.5; color: var(--slate); }

/*
 * Ghost typographic tag — groups without visual weight. Never a badge.
 *
 * ONE COMPONENT: one size, one weight, one colour, and one gap to whatever it
 * labels. The gap used to take thirteen values across seventeen instances (2,
 * 16, 19, 24, 26, 28, 32, 38, 42, 45, 57 …) — even the four page-label eyebrows
 * that share the same hero pattern disagreed — and the colour ran --ash on 29
 * of them, --smoke on four, and full --ink at weight 500 on one.
 *
 * Where an eyebrow is a grid or flex participant whose spacing the container
 * already owns, it sets `margin-bottom: 0` and says so. That is the only legal
 * override.
 */
.eyebrow {
  font-size: 14px;
  font-weight: 400;
  color: var(--ash);
  letter-spacing: 0;
  margin-bottom: var(--eyebrow-gap);
}

.tnum { font-variant-numeric: tabular-nums; }
.muted { color: var(--slate); }

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
:where(a, button, input, [tabindex]):focus-visible {
  outline: 2px solid var(--ink); outline-offset: 3px; border-radius: 4px;
}

/*
 * A hero that carries a wash starts UNDER the transparent nav, so the wash paints
 * behind the logo and links instead of leaving a bald white strip across the top.
 *
 * THE OPENING IS SET HERE AND NOWHERE ELSE. Eight heroes used to compute their
 * own top padding off --section-y plus a private number — 148 / 172 / 228 / 244
 * / 252, a 104px spread on eight components that share one 76px nav — and eight
 * more numbers for the bottom (96 … 236). --hero-y includes the nav band, so
 * every page shows the same 72px of air above its first mark, and the hero
 * closes on the loose rhythm like any other stage.
 */
main > .section:first-child.has-wash {
  margin-top: calc(var(--nav-h) * -1);
  padding-top: var(--hero-y);
  padding-bottom: var(--section-y-loose);
}

/* A whisper of warmth for sections that would otherwise be an undifferentiated slab. */
.section--tint { background:
  radial-gradient(120% 80% at 50% 0%, rgba(251, 225, 209, 0.30) 0%, rgba(251, 225, 209, 0) 60%),
  var(--paper); }
.section--tint-b { background:
  radial-gradient(120% 80% at 50% 100%, rgba(251, 225, 209, 0.26) 0%, rgba(251, 225, 209, 0) 60%),
  var(--paper); }

/* ===== 20-components.css ===== */
/* ————————————————————————————————————————————————
   The gradient wash. Original composition in the brand's warm family — four
   soft radial blooms over paper. Sections opt in with .has-wash.
   ———————————————————————————————————————————————— */
.has-wash { position: relative; isolation: isolate; }
.has-wash > .wash {
  position: absolute; inset: -10% -5% 0; z-index: -1; pointer-events: none;
  background:
    radial-gradient(58% 44% at 74% 30%, var(--wash-1) 0%, rgba(255, 217, 194, 0) 62%),
    radial-gradient(46% 38% at 22% 46%, var(--wash-3) 0%, rgba(240, 226, 242, 0) 66%),
    radial-gradient(52% 40% at 46% 72%, var(--wash-2) 0%, rgba(255, 233, 214, 0) 68%),
    radial-gradient(40% 34% at 90% 74%, var(--wash-4) 0%, rgba(223, 230, 245, 0) 70%);
  filter: blur(8px) saturate(112%);
}
/* Fade the wash into paper at the seam so sections never end on a hard edge. */
.has-wash > .wash::after {
  content: ''; position: absolute; inset-inline: 0; bottom: 0; height: 200px;
  background: linear-gradient(to top, var(--paper), rgba(255, 255, 255, 0));
}

/* ————————————————————————————————————————————————
   Pills. Filled and ghost share geometry so they sit as a matched pair.
   ———————————————————————————————————————————————— */
.pill, .ghost {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  height: 48px; padding-inline: 26px; border-radius: var(--r-pill);
  font-size: 16px; font-weight: 450; letter-spacing: -0.005em;
  white-space: nowrap; cursor: pointer;
  transition: background var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out),
              transform var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out);
}
.pill { background: var(--ink); color: var(--paper); border: 1px solid var(--ink); }
.pill:hover { background: #2b2e33; border-color: #2b2e33; }
.ghost { background: transparent; color: var(--ink); border: 1px solid var(--ink); }
.ghost:hover { background: var(--ink); color: var(--paper); }
.pill:active, .ghost:active { transform: translateY(1px); }
.pill--sm, .ghost--sm { height: 42px; padding-inline: 20px; font-size: 15px; }

/* Lowest-emphasis link: the arrow carries the affordance, not an underline. */
.alink {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 16px; font-weight: 450; color: var(--ink);
}
.alink svg { transition: transform var(--dur) var(--ease-out); }
.alink:hover svg { transform: translateX(4px); }
.alink:hover span { text-decoration: underline; text-underline-offset: 3px; text-decoration-thickness: 1px; }

/* ————————————————————————————————————————————————
   Surfaces
   ———————————————————————————————————————————————— */
/*
 * ONE CARD, TWO VARIANTS — and nothing else. The card is the most repeated
 * object on the site, and it had drifted into six grounds doing the same job:
 * mist, white-with-a-hairline, transparent-with-a-hairline, white-no-border,
 * white-with-a-top-only-radius and white-on-a-heavier-hairline. Two of them
 * shipped on ONE page, three sections apart, on the same six-card isometric
 * grid. Sections must not restate background, border, radius or padding here.
 *
 *   .card         mist, no border — the default, and what a grid of drawings
 *                 sits on, on paper and on fog alike.
 *   .card--paper  white and a hairline — reserved for the one case mist cannot
 *                 do: a card that has to lift off a filled ground. It is down
 *                 to a single user (customers-more); nothing else may take it,
 *                 and no section may invent a third.
 */
/* --illo-ground is the surface a drawing's occlusion silhouette is painted in.
   It is declared beside the background it has to match, so the two can never
   drift apart; see the illustration block below. */
.card { background: var(--mist); --illo-ground: var(--mist); border-radius: var(--r-card); padding: var(--s32); }
.card--paper { background: var(--raised); --illo-ground: var(--raised); border: 1px solid var(--hair); }
.card__title { font-size: var(--t-body-lg); font-weight: 500; letter-spacing: -0.01em; margin-bottom: 10px; }
/*
 * The ONE permitted louder card title, for the lead of a grid. Same family and
 * same weight as its siblings — a lead that changes typeface puts two families
 * at one rank inside a single grid, which is what three sections were doing.
 */
.card__title--lead { font-size: var(--t-h-sm); letter-spacing: var(--tr-h-sm); line-height: 1.22; }
.card__body { font-size: 16px; line-height: 1.55; color: var(--slate); }

/* Rationed to one per page. Warm ink on warm paper — never on a tinted section. */
.card--peach { background: var(--peach); color: var(--sienna); --illo-ground: var(--peach); }
.card--peach .card__title, .card--peach .card__body, .card--peach p { color: var(--sienna); }

/* The only elements with visible elevation. */
.artifact {
  background: var(--raised); border-radius: var(--r-elevated); box-shadow: var(--sh-artifact);
}

.rule { height: 1px; background: var(--hair); border: 0; margin: 0; }

/* ————————————————————————————————————————————————
   Nav
   ———————————————————————————————————————————————— */
.nav {
  position: sticky; top: 0; z-index: 100; height: 76px; display: flex; align-items: center;
  transition: background var(--dur) var(--ease-out), border-color var(--dur) var(--ease-out),
              backdrop-filter var(--dur) var(--ease-out);
  border-bottom: 1px solid transparent;
}
.nav.is-stuck {
  background: rgba(255, 255, 255, 0.82);
  backdrop-filter: saturate(180%) blur(14px);
  -webkit-backdrop-filter: saturate(180%) blur(14px);
  border-bottom-color: var(--hair);
}
/*
 * NO `width: 100%` HERE. .nav__inner also carries .wrap, and an equal-specificity
 * `width` declared later overrides the 1200px column .wrap exists to set — which
 * pushed the logo and the CTA hard against the viewport edges and left the nav
 * links misaligned against every other element on the page. Most visible on wide
 * displays, but it was wrong at every width.
 */
.nav__inner { display: flex; align-items: center; justify-content: space-between; gap: 24px; }
.nav__logo { display: inline-flex; align-items: center; gap: 9px; flex: 0 0 auto; white-space: nowrap;
             font-family: var(--serif); font-size: 21px; letter-spacing: -0.015em; }
.nav__logo em { font-style: italic; }
.nav__links { display: flex; align-items: center; gap: 34px; }
.nav__links a { font-size: 16px; font-weight: 400; color: var(--ink); position: relative; padding-block: 4px; }
.nav__links a::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 1px;
  background: var(--ink); transform: scaleX(0); transform-origin: left;
  transition: transform var(--dur) var(--ease-out);
}
.nav__links a:hover::after, .nav__links a.is-active::after { transform: scaleX(1); }
.nav__cta { display: flex; align-items: center; gap: 22px; }
/* A text link in the nav is still a tap target: it was 21px tall, under the 24px
   floor and well under the 44px comfortable size on touch. */
.nav__cta .alink { min-height: 44px; }
.nav__burger { display: none; width: 44px; height: 44px; align-items: center; justify-content: center;
               background: none; border: 0; cursor: pointer; margin-right: -10px; }

@media (max-width: 940px) {
  .nav__links, .nav__cta .alink, .nav__cta .ghost { display: none; }
  .nav__burger { display: inline-flex; }
}
@media (max-width: 360px) {
  .nav__cta > .pill { display: none; }
}

.navdrawer {
  position: fixed; inset: 0; z-index: 200; background: var(--paper);
  display: flex; flex-direction: column; padding: 20px var(--gutter) 40px;
  opacity: 0; visibility: hidden; transform: translateY(-8px);
  transition: opacity var(--dur) var(--ease-out), transform var(--dur) var(--ease-out), visibility var(--dur);
}
.navdrawer.is-open { opacity: 1; visibility: visible; transform: none; }
.navdrawer__top { display: flex; align-items: center; justify-content: space-between; height: 56px; }
.navdrawer__links { display: flex; flex-direction: column; gap: 4px; margin-top: 32px; }
.navdrawer__links a { font-family: var(--serif); font-size: 34px; line-height: 1.5; letter-spacing: -0.015em; }
.navdrawer__foot { margin-top: auto; display: flex; flex-direction: column; gap: 12px; }
.navdrawer__foot .pill, .navdrawer__foot .ghost { width: 100%; }

/* ————————————————————————————————————————————————
   Footer
   ———————————————————————————————————————————————— */
.footer { border-top: 1px solid var(--hair); padding-block: 72px 56px; background: var(--paper); }
.footer__grid { display: grid; grid-template-columns: 1.6fr 1fr 1fr 1fr; gap: 48px; }
.footer__brand p { margin-top: 14px; max-width: 260px; font-size: 15px; line-height: 1.55; color: var(--slate); }
.footer__col .footer__coltitle { font-size: 14px; font-weight: 450; color: var(--ash); margin-bottom: 18px; }
.footer__col a { display: block; font-size: 15px; line-height: 1; padding-block: 9px; color: var(--ink); }
.footer__col a:hover { color: var(--slate); }
.footer__base { display: flex; justify-content: space-between; gap: 20px; flex-wrap: wrap;
                margin-top: 64px; padding-top: 28px; border-top: 1px solid var(--hair);
                font-size: 14px; color: var(--ash); }
@media (max-width: 860px) {
  .footer__grid { grid-template-columns: 1fr 1fr; gap: 40px 24px; }
  .footer__brand { grid-column: 1 / -1; }
}

/* ————————————————————————————————————————————————
   THE ILLUSTRATION SYSTEM
   Every drawing on the site must obey these, or the page reads as clip-art
   assembled by six different people — which is exactly what reviewers found:
   "five different conventions" across six cards in one section.
   ———————————————————————————————————————————————— */
.illo {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
  color: var(--ink);
  /* Strokes must survive the warm ground. A floor plan drawn at low contrast was
     measured as "effectively does not exist" — opacity belongs on the wrapper,
     never on individual strokes. */
  opacity: 0.78;
}
.illo--quiet { opacity: 0.52; }
.card--peach .illo,
.illo--sienna { color: var(--sienna); }
.illo--invert { color: var(--raised); }

/* One stroke weight for the whole site. Anything thinner disappears on paper;
   anything heavier reads as an icon rather than a drawing. */
.illo [stroke],
.illo path, .illo line, .illo circle, .illo rect, .illo ellipse, .illo polyline, .illo polygon {
  stroke: currentColor;
  stroke-width: 1.4;
  stroke-linecap: round;
  stroke-linejoin: round;
  fill: none;
  vector-effect: non-scaling-stroke;   /* weight stays 1.4 at any scale */
}
/* The single permitted fill: a solid accent mark, used sparingly for emphasis. */
.illo .illo-fill { fill: currentColor; stroke: none; }
/* Construction lines — hidden faces, guides — sit back without changing weight. */
.illo .illo-back { opacity: 0.34; }

/* ————————————————————————————————————————————————
   HIDDEN-LINE REMOVAL — and it lives HERE, not in a section file.

   ILLUSTRATION.md item 5 makes occlusion mandatory: where one object sits in
   front of another, the object behind must BREAK, or the drawing is an x-ray.
   The tool that does it is an opaque silhouette painted in whatever surface the
   drawing stands on, laid down immediately before the object it belongs to.

   It used to be declared locally, in two section files out of thirteen, and
   that is most of why eleven sections carried no occlusion at all: an author
   who copied class="illo-mask" anywhere else got `fill: none` from the generic
   rule above and the drawing silently rendered as an x-ray. No error, no
   missing style — just a worse drawing. Declared globally, the class works
   wherever it is written.

   The surface comes from --illo-ground, set once per card beside its own
   background (.card / .card--paper / .card--peach above). A drawing standing on
   bare paper needs to set nothing; the fallback is the page.
   ———————————————————————————————————————————————— */
.illo .illo-mask { fill: var(--illo-ground, var(--paper)); stroke: none; }

/* ————————————————————————————————————————————————
   TWO SIZES, AND NO THIRD.

   Measured across the site, .illo boxes ran from 45px to 1102px — a 24x range
   under one class, which makes the class mean nothing, and inside a grid of
   peers makes size read as importance (ILLUSTRATION.md items 3 and 7).
   A drawing is now either a card mark or a section's feature. Both are
   CEILINGS paired with width:100%, so a narrow column shrinks its drawing
   instead of earning a size of its own.
   ———————————————————————————————————————————————— */
.illo--card { width: 100%; max-width: var(--illo-card); }
.illo--feature { width: 100%; max-width: var(--illo-feature); }

/* ————————————————————————————————————————————————
   BLEED STAGE — for absolutely-positioned decoration around a content column.
   `position:absolute; inset:0` on a full-bleed section anchors children to the
   VIEWPORT, so on a wide display the floating cards fly out to the edges and
   lose all relationship to the headline they are meant to frame. This bounds the
   layer to the content column plus a fixed bleed, centred, so the composition
   holds at any width and only ever crops by --bleed.
   ———————————————————————————————————————————————— */
.stage {
  position: absolute;
  top: 0; bottom: 0; left: 0; right: 0;
  width: min(100%, calc(var(--page) + var(--bleed, 240px) * 2));
  margin-inline: auto;
  pointer-events: none;
}

/* ===== 30-motion.css ===== */
/*
 * Motion primitives. Everything is opt-in via a data attribute so a section
 * author never writes keyframes — and everything collapses to "already visible"
 * under prefers-reduced-motion, which is the accessible default, not an afterthought.
 */
[data-reveal] {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity var(--dur-slow) var(--ease-out), transform var(--dur-slow) var(--ease-out);
  transition-delay: var(--reveal-delay, 0ms);
}
[data-reveal].is-in { opacity: 1; transform: none; }

/* Headline reveal: lines rise from a clipped baseline, staggered. */
[data-reveal-lines] .line-mask { display: block; overflow: hidden; }
[data-reveal-lines] .line-mask > span {
  display: block;
  transform: translateY(105%);
  transition: transform 900ms var(--ease-out);
  transition-delay: var(--line-delay, 0ms);
}
[data-reveal-lines].is-in .line-mask > span { transform: none; }

/* Floating artifacts drift in from their resting offset. */
[data-float] {
  opacity: 0;
  transform: translate3d(var(--float-x, 0), var(--float-y, 26px), 0) scale(0.985);
  transition: opacity 1000ms var(--ease-out), transform 1000ms var(--ease-out);
  transition-delay: var(--float-delay, 0ms);
}
[data-float].is-in { opacity: 1; transform: translate3d(0, 0, 0) scale(1); }

/* Idle bob for hero artifacts, once they have landed. */
@keyframes lp-bob {
  0%, 100% { transform: translate3d(0, 0, 0); }
  50%      { transform: translate3d(0, -7px, 0); }
}
[data-float].is-in[data-bob] {
  animation: lp-bob var(--bob-dur, 7s) var(--ease-in-out) infinite;
  animation-delay: var(--bob-delay, 0s);
}

/* Counters and bars */
[data-count] { font-variant-numeric: tabular-nums; }
[data-bar] { transform: scaleX(0); transform-origin: left; transition: transform 1100ms var(--ease-out); }
[data-bar].is-in { transform: scaleX(1); }

/* Drawn SVG strokes */
[data-draw] {
  stroke-dasharray: var(--len, 1000);
  stroke-dashoffset: var(--len, 1000);
  transition: stroke-dashoffset 1600ms var(--ease-out);
}
[data-draw].is-in { stroke-dashoffset: 0; }

@media (prefers-reduced-motion: reduce) {
  [data-reveal], [data-float], [data-bar], [data-draw],
  [data-reveal-lines] .line-mask > span {
    opacity: 1 !important;
    transform: none !important;
    stroke-dashoffset: 0 !important;
    transition: none !important;
    animation: none !important;
  }
}

/* ===== section:home-hero ===== */
/* ===========================================================================
   home-hero — THE hero. Round 5.

   ROUND 5 — three named defects, and only those three moved. The round-4
   composition stands: type left-anchored to the page gutter, a near-black slab
   cropped by the right edge, cards that overlap each other and the frame.

     1. INK DENSITY. The slab measured 17.2% ink with 64.5% of its scanlines
        empty — three rows on `flex: 1` inside a 700px column, which spaced them
        ~120px apart and turned a 580x700 rectangle into a void with figures
        floating in it. The rows no longer flex, and the reclaimed space went
        into MORE INFORMATION rather than more air:
          · column captions (shop / 7 days / today) under a heavier opening rule;
          · a 7-day sparkline per shop, all three on ONE shared scale so Mong
            Kok's line genuinely sits lower than Central's;
          · a cover count per shop;
          · quarter ticks drawn OVER every share track, so a bar can be read
            against a scale instead of taken on faith;
          · a 3.5% zebra tint on alternate bands;
          · a footer that sums the covers column and prints the average cover,
            which reconciles: 480 x HK$228.50 = HK$109,680.
        Whatever slack is left collects in ONE gap above the composer
        (margin-top: auto) instead of being shared out among the rows, which is
        exactly what made them airy in the first place.
     2. THE EYEBROW was 12px uppercase at 0.12em; this system's .eyebrow is
        sentence case, 14px, --ash, no tracking. Rather than restyle a fragment
        of a sentence, the eyebrow is gone and the deck's full subhead is back.
        The ramp runs 134px display -> 22px ink lede.
     3. THE BOTTOM EDGE. `overflow: clip` on the stage guillotined the Bookings
        card's cast shadow at the section box — a hard grey band across the
        frame — and the grain overlay stopped dead on the same line, so the pale
        panel of the section below read as poking into the hero. The stage now
        clips on x only (all the scrollWidth fix ever needed) and both wash and
        grain dissolve before the bottom edge.

   ——— Round 4, for the record ———
   Round 3 lost 6/10 on the two axes the reviewer says decide craft, and both
   losses were structural, not material:

     · CENTRE AXIS. Headline, lede and both CTAs were pinned to x=720 and the
       four artifacts ringed the frame one per quadrant — a symmetric confetti
       ring around a centred column, with zero overlap anywhere on desktop.
     · NO MASS. The only element darker than 16px grey was a 146x44 pill:
       0.5% of a 1,296,000px frame. The lower third was ~90% empty wash.

   What this build does instead:

     1. The type block is LEFT-ANCHORED to the page gutter. Eyebrow, both
        headline lines, the lede and the CTA row share one left edge, and the
        italic line is set 6% up optically so "Total control." rags visibly past
        "One system." Nothing in the section is centred to the frame.
     2. "Today, by shop" is promoted from a pale card to a NEAR-BLACK SLAB
        ~520x600 pinned to and cropped by the right edge — total in reversed
        display serif, a three-shop table whose bars encode their own share of
        that total, and the composer inset in its floor. Dark coverage goes from
        0.5% to ~23%, and the slab is filled, not a void: type, figure, table,
        bars and an input, top to bottom.
     3. Things TOUCH. The Margin card floats ONTO the slab, overlapping its left
        gutter by 80px with a deepened cast shadow. The Bookings card is cropped
        by the left frame edge — through 44px of pure padding, never a numeral,
        which is exactly the mistake round 3 made with "HK$109,680" -> "9,680".
     4. The type ramp is filled: 12px/0.12em eyebrow -> 134px display -> 22px
        lede, instead of 134px straight to 17px grey.
     5. The margin chart got a y-range (50-80%) and a labelled datum, so the
        endpoint dot above the dashed line is what "70.5% against target 65%"
        actually looks like. Both cursor avatars are gone: one floated outside
        its card into empty background, the other covered an icon.

   Everything is scoped under .sec-home-hero.
   =========================================================================== */

.sec-home-hero {
  padding: 138px 0 84px;
  overflow: visible;

  /* Local token overrides, both measured against the reference: the stock
     --sh-artifact is a tight material card edge, and the stock 90px display is
     a small island on a 1440 stage. */
  --sh-artifact:
    0 0 0 1px color-mix(in srgb, var(--ink) 5%, transparent),
    0 28px 64px -26px color-mix(in srgb, var(--ink) 22%, transparent),
    0 8px 24px -16px color-mix(in srgb, var(--ink) 10%, transparent);
  --t-display: clamp(44px, 9.3vw, 134px);

  /* Hero-local geometry. Cards here are 14px, not the 24px content radius —
     at 14px type a 24px corner reads bubbly. ONE radius for every surface. */
  --hx-r: 14px;

  /* The slab. Warm near-black: --ink is cool (#17191c) and reads blue against a
     peach wash, so 10% sienna pulls it onto the page's own temperature. */
  --hx-ink: color-mix(in srgb, var(--ink) 90%, var(--sienna));
  --hx-on-ink: color-mix(in srgb, var(--paper) 62%, transparent);
  --hx-rule-ink: color-mix(in srgb, var(--paper) 58%, transparent);
}

/* ——— THE GRAIN ————————————————————————————————————————————————
   The global body::after tile averages to flat at DPR 2 (its noise cell lands
   at ~0.5 CSS px), which leaves the wash's banding naked. This overlay uses a
   coarser cell pinned to an explicit 168px tile — ~1.6 CSS px, legible tooth at
   1x and 2x — and continuous alpha rather than 0/1 dots, which is grain rather
   than pepper. It now also runs over the slab, so the dark mass is the same
   material as the page instead of a flat rectangle pasted on it.
   ———————————————————————————————————————————————————————————————— */
.sec-home-hero::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 6;
  pointer-events: none;
  mix-blend-mode: overlay;
  opacity: 0.7;
  /* The bottom-edge fix, half one: an overlay that stops dead at the section
     box draws a visible texture step across the full width, which is part of
     why the pale panel below looked like it was intruding on the hero. The last
     120px dissolve, so the hero hands over to plain paper. */
  -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 120px), transparent 100%);
  mask-image: linear-gradient(to bottom, #000 calc(100% - 120px), transparent 100%);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 168 168'%3E%3Cfilter id='hxg' x='0' y='0' width='100%25' height='100%25'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.62' numOctaves='3' seed='11' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='168' height='168' filter='url(%23hxg)' opacity='0.62'/%3E%3C/svg%3E");
  background-size: 168px 168px;
  background-repeat: repeat;
}

/* ——— The wash ————————————————————————————————————————————————
   inset-x is ZERO: a -6% inset grew the document to 1526 at a 1440 viewport,
   and because the grain overlay is inset:0 the ground and the tooth stopped at
   two different x. The overhang comes from placing the edge blooms at 3%/97%
   with generous radii instead. Alpha stops mirror the token hexes exactly
   (house pattern from 20-components.css) so the fade never runs through grey.
   The warm bloom has moved off centre to 34% — it used to sit at 50% 38%,
   which put a soft halo behind the centred headline and was half of why the
   composition read as a centred column.
   ———————————————————————————————————————————————————————————————— */
.sec-home-hero > .wash {
  inset: -16% 0 0;
  background:
    radial-gradient(52% 44% at 30% 32%, var(--wash-1) 0%, rgba(255, 217, 194, 0) 66%),
    radial-gradient(44% 34% at 72% 12%, var(--wash-2) 0%, rgba(255, 233, 214, 0) 70%),
    radial-gradient(32% 26% at 1% 50%, var(--wash-3) 0%, rgba(240, 226, 242, 0) 72%),
    radial-gradient(42% 34% at 96% 82%, var(--wash-4) 0%, rgba(223, 230, 245, 0) 72%);
  filter: blur(14px) saturate(116%);
}
/* ROUND 6 — the lower-left resolves to paper now, by SUBTRACTION.
   Two blooms were landing on the bottom seam. The wash box runs -147..920, so
   the cool bloom at `2% 66%` was centred at y=557 with a 341px y-radius: it
   reached y=898 and read as a grey smudge under the Bookings card, exactly
   where the card's own shadow already was. It has moved up to 50% and lost a
   little size — centred at y=387, done by y=686 — so it still tints the left
   column behind the type and clears the bottom third entirely. The fifth bloom
   sat at `24% 98%`, i.e. its centre was ON the seam; there is no placement that
   makes a bloom centred on the edge resolve, so it is deleted rather than
   nudged. Four blooms, and the bottom of the frame is now clean paper. */
/* The bottom-edge fix, half two. 20-components already fades the wash to paper
   over its last 200px, but the bottom-left bloom sits at 24% 98% — right on the
   seam — so it survived the fade and left a warm lip along the edge. Deepening
   the fade to 260px and mixing to full paper resolves the hero onto the same
   ground the next section starts from. */
.sec-home-hero > .wash::after {
  height: 260px;
  background: linear-gradient(to top, var(--paper) 0%, rgba(253, 252, 250, 0.72) 42%, rgba(253, 252, 250, 0) 100%);
}

/* ——— The text column — LEFT-ANCHORED ————————————————————————————
   .wrap puts this edge at x=120 on a 1440 frame: the same gutter as the nav
   logo and every other section, so the hero sits on the page grid rather than
   floating in the middle of it.
   ———————————————————————————————————————————————————————————————— */
.sec-home-hero .hx-inner {
  position: relative;
  z-index: 3;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  text-align: left;
}

/* No eyebrow. The 12px/0.12em uppercase rung was off-system — .eyebrow in this
   design system is sentence case, 14px, --ash, no tracking — and its words were
   the tail of the deck's subhead, so restoring the sentence is what fixes both
   the type and the copy. The lede carries the mid-tier on its own at 22px ink. */
.sec-home-hero .hx-title {
  max-width: none;
  line-height: 0.99;
}

/* Optical set: at one nominal size the italic runs NARROWER than the roman, so
   the two lines came out within 7px of each other and the rag read as a
   justified block. +6% is the standard italic optical correction and it opens a
   ~45px rag, which is what makes a left-aligned two-line headline read as a
   headline and not a box. */
.sec-home-hero .hx-title em {
  font-size: 1.06em;
  line-height: 0.93;
}

/* The per-line masks clip at the padding box, so the inner span carries a hair
   of padding — otherwise the descender of "system" and the italic overhang of
   "control." are shaved off by the reveal mask. The mask's negative margin
   gives the leading back, so the 0.99 line height is preserved exactly, and the
   inline padding cancels so the glyphs still start on the gutter. */
.sec-home-hero .hx-title .line-mask {
  margin-block: -0.085em;
  margin-inline: -0.14em;
}
.sec-home-hero .hx-title .line-mask > span {
  display: block;
  padding-block: 0.085em;
  padding-inline: 0.14em;
}

/* The mid-tier: 22px ink, not 17px grey. Two sentences now, so the measure runs
   a little wider — 30rem lands it on three lines at 1440, which is the mass the
   left column needs under a 134px headline. */
.sec-home-hero .hx-sub {
  max-width: 30rem;
  margin-top: 28px;
  font-size: var(--t-subhead);
  line-height: 1.34;
  letter-spacing: -0.011em;
  color: color-mix(in srgb, var(--ink) 72%, transparent);
}

.sec-home-hero .hx-acts {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 26px;
  margin-top: 34px;
}

/* "See pricing" had no affordance at all in round 3 — no underline, no chevron,
   and no shared alignment logic with the pill. It is now the house .alink, so
   the arrow carries the affordance, and it is centred on the pill's axis. */
.sec-home-hero .hx-see {
  min-height: 44px;
  padding-inline: 2px;
}

/* ——— The floating stage ————————————————————————————————————————— */
.sec-home-hero .hx-stage {
  position: absolute;
  top: 0; bottom: 0; left: 0; right: 0;
  /*
   * Bounded bleed rather than `inset: 0`. Anchored to the viewport, these cards
   * drifted to the far edges on a wide display and left a dead gap around the
   * headline they exist to frame. Tied to the content column plus a fixed bleed
   * they hold the same composition at 1280 and at 2560.
   */
  width: min(100%, calc(var(--page) + var(--bleed) * 2));
  --bleed: 260px;
  margin-inline: auto;
  z-index: 2;
  pointer-events: none;
}

.sec-home-hero .hx-art {
  position: absolute;
  width: var(--aw);
  --aw: 380px;
}

.sec-home-hero .hx-card,
.sec-home-hero .hx-slab {
  position: relative;
  border-radius: var(--hx-r);
}

.sec-home-hero .hx-card__title {
  font-size: 13px;
  font-weight: 500;
  letter-spacing: -0.002em;
  color: var(--ink);
}

/* ——— (1) THE SLAB — Today, by shop ————————————————————————————————
   Anchored to the right edge and cropped by it at x=1440. `right:-44px` is
   constant rather than a min()/clamp() because the Margin card is anchored to
   the same edge with a constant too — that is what keeps the 80px overlap
   between them identical at every width from 1201 to 1728.

   No box-shadow: the house rule reserves elevation for .artifact on --raised.
   The slab does not need it — it is the darkest thing on the page.
   ———————————————————————————————————————————————————————————————— */
.sec-home-hero .hx-art--slab {
  top: 132px;
  right: -40px;
  z-index: 1;
  --aw: 580px;
}
.sec-home-hero .hx-slab {
  /* --pl is a real gutter, not decoration: it is the strip the Margin card
     lands on, and the row rules run full-bleed through it so the card sits on
     rules and ink rather than on a shop name. */
  --pl: 96px;
  --pr: 96px;
  /* One rule ladder for the whole panel: hairlines divide the bands, the
     heavier weight opens and closes the table. */
  --hx-rule-hi: color-mix(in srgb, var(--paper) 58%, transparent);
  display: flex;
  flex-direction: column;
  /* 672 is the table's own height plus its chrome — i.e. almost no slack. Round
     4 set 700 and let three rows share the difference; the leftover is now 8px
     and it collects in one place, above the composer. */
  min-height: 672px;
  padding: 30px var(--pr) 26px var(--pl);
  background: var(--hx-ink);
  color: var(--paper);
}

/* Sentence case, no tracking. There is now no uppercase-and-letterspaced type
   anywhere in the section — the round-4 eyebrow was called off-system and this
   panel label was set the same way. */
.sec-home-hero .hx-slab__eye {
  font-size: 12.5px;
  font-weight: 450;
  letter-spacing: 0;
  color: color-mix(in srgb, var(--paper) 66%, transparent);
}
/* Reversed display serif at 400 — the only other serif in the section, and the
   thing that makes the slab a headline object rather than a widget. */
.sec-home-hero .hx-slab__fig {
  margin-top: 14px;
  font-family: var(--serif);
  font-weight: 400;
  font-optical-sizing: auto;
  font-size: 68px;
  line-height: 0.96;
  letter-spacing: -0.028em;
  color: var(--paper);
}
.sec-home-hero .hx-slab__cap {
  margin-top: 8px;
  font-size: 13px;
  color: var(--hx-on-ink);
}

/* ——— The table ————————————————————————————————————————————————
   Round 4 gave the three rows `flex: 1` inside a 700px column, so each one grew
   to ~120px around ~50px of content: that is how a dark object measures 17% ink
   with two thirds of its scanlines empty. The rows are now sized by their own
   content, and the space that frees up carries information — captions, a
   sparkline, a covers column, tick marks and a summed footer — instead of air.
   ———————————————————————————————————————————————————————————————— */
/* margin-bottom is the floor for the auto margin below: flex margins never
   collapse, so the composer can never come to rest against the footer rule. */
.sec-home-hero .hx-tbl { margin-top: 22px; margin-bottom: 24px; }

.sec-home-hero .hx-thead {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-inline: calc(var(--pl) * -1) calc(var(--pr) * -1);
  padding: 9px var(--pr) 8px var(--pl);
  border-top: 1px solid var(--hx-rule-hi);
}
.sec-home-hero .hx-th {
  font-size: 10.5px;
  letter-spacing: 0.02em;
  /* 34% measured 3.1:1 at 10.5px — below AA. Raised until it clears. */
  color: color-mix(in srgb, var(--paper) 62%, transparent);
}
.sec-home-hero .hx-th:first-child { flex: 1 1 auto; }
.sec-home-hero .hx-th--spark { flex: none; width: 68px; }
.sec-home-hero .hx-th--v { flex: none; }

.sec-home-hero .hx-srows {
  list-style: none;
  margin: 0;
  padding: 0;
}
.sec-home-hero .hx-srows li {
  margin-inline: calc(var(--pl) * -1) calc(var(--pr) * -1);
  padding: 15px var(--pr) 16px var(--pl);
  border-top: 1px solid var(--hx-rule-ink);
}
/* Zebra, at the lowest weight that still separates a band from its neighbour on
   near-black. Any heavier and it reads as three cards, not one table. */
.sec-home-hero .hx-srows li:nth-child(even) {
  background: color-mix(in srgb, var(--paper) 3.5%, transparent);
}

.sec-home-hero .hx-srow__top {
  display: flex;
  align-items: center;
  gap: 16px;
}
.sec-home-hero .hx-srow__k {
  flex: 1 1 auto;
  font-size: 15px;
  letter-spacing: -0.004em;
  color: color-mix(in srgb, var(--paper) 80%, transparent);
}
.sec-home-hero .hx-srow__v { flex: none; font-size: 15px; font-weight: 450; color: var(--paper); }

/* The sparkline. 68x16, seven days, and — the part that matters — all three
   share ONE scale (HK$22k..HK$43k), so the three lines sit at three different
   heights in the column and the shop order is legible without reading a
   figure. The end dot is today, the same datum as the row's bar. */
.sec-home-hero .hx-spark {
  flex: none;
  width: 68px;
  height: 16px;
  overflow: visible;
}
.sec-home-hero .hx-spark polyline { stroke: color-mix(in srgb, var(--paper) 58%, transparent); }
.sec-home-hero .hx-spark__tip { fill: var(--wash-1); }

.sec-home-hero .hx-srow__mid {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-top: 7px;
}
.sec-home-hero .hx-srow__m { font-size: 11.5px; color: color-mix(in srgb, var(--paper) 66%, transparent); }
.sec-home-hero .hx-srow__p { font-size: 11.5px; color: color-mix(in srgb, var(--paper) 56%, transparent); }

.sec-home-hero .hx-srow__bot { margin-top: 9px; }
.sec-home-hero .hx-srow__track {
  position: relative;
  display: block;
  height: 6px;
  border-radius: var(--r-pill);
  background: color-mix(in srgb, var(--paper) 8%, transparent);
  overflow: hidden;
}
/* The bar IS the number: width is the row's share of HK$109,680, and the three
   shares sum to the full track. [data-bar] scales it in from the left. */
.sec-home-hero .hx-srow__track i {
  display: block;
  width: var(--w);
  height: 100%;
  border-radius: inherit;
  background: color-mix(in srgb, var(--wash-1) 90%, transparent);
}
/* Quarter ticks, drawn OVER the fill rather than under it, in a paper tint that
   reads both on the dark empty track and on the peach bar. Without them a
   viewer has to take 37.6% on trust; with them the bar can be counted. */
.sec-home-hero .hx-srow__track::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background-image: repeating-linear-gradient(
    90deg,
    color-mix(in srgb, var(--paper) 58%, transparent) 0 1px,
    transparent 1px 25%);
}

/* The footer closes the ladder and reconciles the column above it:
   178 + 165 + 137 = 480 covers, and 480 x HK$228.50 = HK$109,680. */
.sec-home-hero .hx-tfoot {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 14px;
  margin-inline: calc(var(--pl) * -1) calc(var(--pr) * -1);
  padding: 13px var(--pr) 14px var(--pl);
  border-top: 1px solid var(--hx-rule-hi);
  border-bottom: 1px solid var(--hx-rule-hi);
  font-size: 12px;
  color: color-mix(in srgb, var(--paper) 66%, transparent);
}
.sec-home-hero .hx-tfoot__v { color: color-mix(in srgb, var(--paper) 68%, transparent); }

/* The composer, inset into the slab's floor. It was a fourth floating card in
   round 3, which is how the stage became a ring of confetti. Its send disc is
   pale-on-ink, so the black CTA pill keeps the only dark focal point on the
   left half of the frame. */
.sec-home-hero .hx-ask {
  /* margin-top:auto collects ALL the column's leftover space in one place. The
     alternative — letting the rows flex — is what produced 64.5% empty
     scanlines: slack spread evenly through a table just makes it airy. */
  margin-top: auto;
  padding: 15px 14px 13px 16px;
  border-radius: var(--hx-r);
  border: 1px solid var(--hx-rule-ink);
  background: color-mix(in srgb, var(--paper) 8%, transparent);
}
.sec-home-hero .hx-ask__ph {
  font-size: 15px;
  letter-spacing: -0.004em;
  /* 15px placeholder on the dark inset — needs to clear 4.5:1, not just look quiet. */
  color: color-mix(in srgb, var(--paper) 66%, transparent);
}
.sec-home-hero .hx-ask__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-top: 14px;
}
.sec-home-hero .hx-ask__tools {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  color: color-mix(in srgb, var(--paper) 66%, transparent);
}
.sec-home-hero .hx-send {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 30px;
  height: 30px;
  border-radius: var(--r-pill);
  background: var(--paper);
  color: var(--hx-ink);
}

/* ——— (2) Margin, by dish — FLOATED ONTO THE SLAB —————————————————
   right:440px puts its right edge 80px inside the slab's left edge at every
   width, because both are anchored to the frame's right edge with constants.
   ———————————————————————————————————————————————————————————————— */
/* ROUND 6 — TIGHTENED, NOT FILLED. At 360x213 this was the largest box in the
   frame carrying the least: a title, a plot and a two-item footer, with slack
   on every side. The brief's own preference applies — smaller and denser beats
   bigger and emptier — so the box came down to the content rather than content
   being invented to justify the box: 300x~172, a third less area, same
   information. `right` is UNCHANGED at 460px, which is the whole point of
   anchoring both this card and the slab to the frame's right edge with
   constants: the card's right edge stays at x=980, the slab's left edge stays
   at x=900, and the 80px overlap survives the resize untouched. Only the left
   edge moves (620 -> 680), which also opens the gap to the text column. */
.sec-home-hero .hx-art--margin {
  top: 540px;
  right: 460px;
  z-index: 3;
  --aw: 300px;
  /* A card lying on ink needs a deeper, longer shadow than one lying on paper,
     or the overlap reads as a collage cut — but the shadow is proportional to
     the card, so a third off the box takes a third off the throw too. */
  --sh-artifact:
    0 0 0 1px color-mix(in srgb, var(--ink) 6%, transparent),
    0 26px 52px -20px color-mix(in srgb, var(--ink) 38%, transparent),
    0 8px 20px -12px color-mix(in srgb, var(--ink) 20%, transparent);
}
.sec-home-hero .hx-card--margin { padding: 14px 18px 15px; }

/* A chart with a scale: the plot runs 50-80% between two hairlines, the dashed
   datum is at 65% and says so, and the endpoint sits at 70.5% — which is the
   figure printed underneath it. Round 3 drew four meaningless vertical
   gridlines and an unlabelled dashed line, so the dot 40px above it encoded
   nothing. */
.sec-home-hero .hx-chart {
  width: 100%;
  height: auto;
  margin-top: 10px;
  overflow: visible;
}
.sec-home-hero .hx-chart__ax { stroke: var(--hair); }
.sec-home-hero .hx-chart__ref { stroke: color-mix(in srgb, var(--slate) 46%, transparent); }
/* The 264-unit grid renders 1:1 inside the card's 264px content box, so these
   are true sizes now — 10px used to arrive on screen as 9.9px and the hairlines
   as 0.99px. Nothing is being scaled any more, in either direction. */
.sec-home-hero .hx-chart__t {
  font-family: var(--sans);
  font-size: 9.5px;
  font-variant-numeric: tabular-nums;
  fill: var(--ash);
}
.sec-home-hero .hx-chart__t--ref {
  font-size: 10px;
  letter-spacing: 0.01em;
  fill: var(--slate);
}
.sec-home-hero .hx-chart__line { stroke: var(--sienna); }
.sec-home-hero .hx-chart__cross {
  fill: var(--raised);
  stroke: color-mix(in srgb, var(--slate) 60%, transparent);
}
.sec-home-hero .hx-chart__tip { fill: var(--sienna); }

.sec-home-hero .hx-margin__foot {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-top: 11px;
}
.sec-home-hero .hx-margin__pct {
  font-size: 25px;
  font-weight: 500;
  letter-spacing: -0.024em;
  line-height: 1;
  color: var(--sienna);
}
.sec-home-hero .hx-margin__lab {
  font-size: 12px;
  color: var(--slate);
  text-align: right;
}

/* ——— (3) Bookings · tonight — CROPPED BY THE LEFT EDGE ———————————
   The bottom-left counterweight. It used to be the section's one warm SURFACE,
   a bespoke 46%-peach tint that made index.html the only page shipping a warm
   card that is not the rationed `.card--peach`; the homepage now spends that
   ration once, on home-barriers, and this is paper like its two siblings, with
   sienna kept for the figures — exactly as the Margin card uses it.
   padding-left is 66px against a -44px offset, so the frame cuts through 22px
   of pure gutter: no label and no figure is ever sliced. Round 3 cropped a card
   mid-numeral and "HK$109,680" rendered as "9,680".
   ———————————————————————————————————————————————————————————————— */
/* ROUND 6 — top was 672px, which put the card's box at 671..902 inside a 920px
   section: 18px of clearance under a card whose cast shadow throws ~34px. The
   shadow was therefore cut off flat by the section's own bottom edge and read
   as a grey band lying across the lower-left corner — the "something poking
   into the hero" a reviewer saw at 1440. 638px lands the box at 637..868 and
   the last of the shadow around 902, so the card now resolves onto clean paper
   ~18px before the seam instead of being guillotined by it. The bob only ever
   translates upward (-7px), so it cannot push the card back into the edge. */
.sec-home-hero .hx-art--book {
  top: 638px;
  left: -44px;
  z-index: 2;
  --aw: 392px;
}
.sec-home-hero .hx-card--book {
  padding: 20px 24px 20px 66px;
}

.sec-home-hero .hx-book__body {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  margin-top: 12px;
}
.sec-home-hero .hx-book__col { min-width: 0; }
.sec-home-hero .hx-book__line {
  font-size: 16px;
  font-weight: 500;
  letter-spacing: -0.012em;
  color: var(--ink);
}
.sec-home-hero .hx-book__meta {
  margin-top: 4px;
  font-size: 12px;
  color: var(--slate);
}
.sec-home-hero .hx-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 13px;
  height: 26px;
  padding-inline: 10px;
  border-radius: var(--r-pill);
  background: color-mix(in srgb, var(--sienna) 10%, transparent);
  color: var(--sienna);
  font-size: 12px;
  font-weight: 450;
  white-space: nowrap;
}
.sec-home-hero .hx-chip svg { flex: none; opacity: 0.78; }

.sec-home-hero .hx-book__foot {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 14px;
  margin-top: 16px;
  padding-top: 14px;
  border-top: 1px solid var(--hair);
}
.sec-home-hero .hx-book__fig {
  font-size: 26px;
  font-weight: 500;
  letter-spacing: -0.024em;
  line-height: 1;
  color: var(--sienna);
}
.sec-home-hero .hx-book__delta {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 12px;
  color: var(--slate);
}
.sec-home-hero .hx-book__delta svg { flex: none; }

/* The 88% ring. The arc gap reads 45-55deg, which is what 12% of a circle is. */
.sec-home-hero .hx-gauge {
  position: relative;
  flex: none;
  width: 104px;
  height: 104px;
  display: grid;
  place-content: center;
  text-align: center;
}
.sec-home-hero .hx-gauge__svg {
  position: absolute;
  inset: 0;
  width: 104px;
  height: 104px;
}
.sec-home-hero .hx-gauge__track { stroke: var(--hair); }
.sec-home-hero .hx-gauge__arc { stroke: var(--sienna); }
.sec-home-hero .hx-gauge__val {
  display: block;
  font-size: 23px;
  font-weight: 500;
  letter-spacing: -0.026em;
  line-height: 1;
  color: var(--sienna);
}
.sec-home-hero .hx-gauge__cap {
  display: block;
  margin-top: 4px;
  font-size: 11px;
  color: var(--slate);
}

/* Desktop stage only: reserve the room the composition needs, and CLIP the
   stage at the section box.

   Both flanks are meant to run off the frame, but an element that overhangs to
   the RIGHT still counts toward document scrollWidth even under the root's
   overflow-x:clip — a fullPage capture then comes out 1484 wide and the 44px
   past x=1440 render as a flat, grainless column with a hard seam through the
   slab. Clipping the stage trims it at 1440 with the section's own grain
   painting over it, and the document stays 1440 wide.

   THE CLIP IS X-ONLY. Round 4 used `overflow: clip`, which also cut the
   Bookings card's cast shadow off flat at the section's bottom edge and left a
   grey band ruled across the whole frame — the seam a reviewer read as the next
   section poking into the hero. Only the x axis ever needed clipping; `clip` on
   one axis with `visible` on the other is the one pairing CSS keeps as
   specified instead of forcing both to auto. */
@media (min-width: 1201px) {
  .sec-home-hero { min-height: 920px; }
  .sec-home-hero .hx-stage { overflow-x: clip; overflow-y: visible; }
}

/* ——— Below the desktop range the artifacts stop floating and stack under the
       copy, so nothing can ever land on top of the headline. They are NOT a
       neat column: alternating inset, a real overlap and rising z-index keep
       the shingled quality the reviewer called the strongest thing in round 3.
       The slab leads the stack, so the mass survives at 390px.

       THE OVERLAP RULE: a card that is overlapped carries bottom padding equal
       to the overlap plus a full gutter, so the card on top only ever covers
       empty padding — never a row of data.
       ———————————————————————————————————————————————————————————— */
@media (max-width: 1200px) {
  .sec-home-hero {
    display: flex;
    flex-direction: column;
    padding-bottom: var(--s48);
    min-height: 0;
  }
  .sec-home-hero .hx-inner { order: 1; }
  .sec-home-hero .hx-stage {
    order: 2;
    position: static;
    display: flex;
    flex-direction: column;
    width: min(520px, 100% - var(--gutter) * 2);
    margin: 60px auto 0;
  }
  /* position:relative (not static) so the stack can order itself with z-index —
     which means the desktop top/left/right offsets must be explicitly cleared,
     or they silently shift every card and blow the page out horizontally. */
  .sec-home-hero .hx-art {
    position: relative;
    inset: auto;
    width: 92%;
    max-width: 100%;
    --aw: auto;
  }
  .sec-home-hero .hx-art + .hx-art { margin-top: -20px; }
  .sec-home-hero .hx-art:nth-of-type(odd)  { align-self: flex-start; margin-left: -12px; }
  .sec-home-hero .hx-art:nth-of-type(even) { align-self: flex-end;   margin-right: -12px; }
  .sec-home-hero .hx-art:nth-of-type(1) { z-index: 1; }
  .sec-home-hero .hx-art:nth-of-type(2) { z-index: 2; }
  .sec-home-hero .hx-art:nth-of-type(3) { z-index: 3; }

  /* The slab is a normal card once stacked: no left gutter to land on, because
     nothing lands on it. */
  .sec-home-hero .hx-slab {
    --pl: 22px;
    --pr: 22px;
    min-height: 0;
    padding: 22px var(--pr) 42px var(--pl);
  }
  .sec-home-hero .hx-slab__fig { font-size: 46px; }
  .sec-home-hero .hx-tbl { margin-top: 18px; margin-bottom: 0; }
  .sec-home-hero .hx-ask { margin-top: 22px; }

  /* Overlap clearance: 20px of overlap + a gutter under every card that has
     another card landing on it. */
  .sec-home-hero .hx-card--margin { padding: 16px 20px 44px; }
  /* The stacked card is up to 442px of content wide, and the chart's grid is
     264 units. Left uncapped it would scale 1.67x — 16px axis labels and 2.5px
     "hairlines", which is the opposite of what tightening the card was for.
     Capped, it renders at most 1.29x and stays a hairline drawing. It sits left
     in the card, which is the section's alignment everywhere else. */
  .sec-home-hero .hx-chart { max-width: 340px; }
  .sec-home-hero .hx-card--book { padding: 20px 22px 22px; }
}

@media (max-width: 720px) {
  .sec-home-hero { padding-bottom: var(--s64); }
  .sec-home-hero .hx-title { max-width: 13ch; }
  .sec-home-hero .hx-sub { margin-top: 18px; max-width: 25rem; }
  .sec-home-hero .hx-acts { margin-top: 28px; gap: 8px 20px; }
  .sec-home-hero .hx-stage { margin-top: 48px; }
  .sec-home-hero > .wash { inset: -14% 0 0; }

  .sec-home-hero .hx-slab { padding: 20px 18px 38px; --pl: 18px; --pr: 18px; }
  .sec-home-hero .hx-slab__fig { font-size: 38px; margin-top: 14px; }
  .sec-home-hero .hx-srows li { padding-block: 13px 14px; }
  .sec-home-hero .hx-ask { padding: 13px 12px 12px 14px; }
  .sec-home-hero .hx-ask__ph { font-size: 14px; }

  .sec-home-hero .hx-card--margin { padding: 16px 18px 40px; }
  .sec-home-hero .hx-card--book { padding: 16px 18px 20px; }
  .sec-home-hero .hx-book__body { gap: 8px; }
  .sec-home-hero .hx-gauge { width: 92px; height: 92px; }
  .sec-home-hero .hx-gauge__svg { width: 92px; height: 92px; }
  .sec-home-hero .hx-gauge__val { font-size: 20px; }
  .sec-home-hero .hx-gauge__cap { font-size: 10px; }
  .sec-home-hero .hx-book__fig { font-size: 24px; }
}

/* 390px: the smallest supported frame. The booking card's two-column body is
   the only thing that cannot hold — the ring and a 16px line will not both fit
   in 300px — so it becomes one column with the ring on its own row. */
@media (max-width: 430px) {
  .sec-home-hero .hx-art { width: 96%; }
  /* 390px is where the row's three columns stop fitting: "Causeway Bay" plus a
     68px sparkline plus HK$38,810 needs ~250px of the ~264px available, and the
     shop name is the one that must not wrap. The sparkline narrows instead —
     it keeps its shared y-scale, so the three lines still compare. */
  .sec-home-hero .hx-srow__top { gap: 10px; }
  .sec-home-hero .hx-srow__k { white-space: nowrap; }
  .sec-home-hero .hx-spark,
  .sec-home-hero .hx-th--spark { width: 46px; }
  .sec-home-hero .hx-tfoot { font-size: 11.5px; }
  .sec-home-hero .hx-book__body { align-items: center; }
  .sec-home-hero .hx-gauge { width: 84px; height: 84px; }
  .sec-home-hero .hx-gauge__svg { width: 84px; height: 84px; }
  .sec-home-hero .hx-gauge__val { font-size: 18px; }
  .sec-home-hero .hx-book__foot { flex-wrap: wrap; gap: 6px 12px; }
}

/* ===== section:home-logos ===== */
/* ============================================================================
   home-logos — the proof strip under the hero.

   THE OBJECT IS THE ROW OF NAMES, AND NOTHING ELSE. Two rounds were spent
   adding weight here — a full-bleed ink slab, a light counter plate reading
   "05 businesses", a five-bar tally, a measured rule and an ordinal under every
   mark — and every one of those additions made the page worse, because this is
   a strip you are meant to believe and then walk past, sitting directly above
   home-adoption, which is the page's one dark object. Two of them competing is
   one too many.

   So this is a subtraction, not a tune:
     · NO SLAB. The marks sit on the ordinary page ground.
     · NO PLATE, NO TALLY, NO COUNT. Five names already state the count, and
       "05" set 52px tall in near-black was the loudest thing in the section.
     · NO ORDINALS. 01-05 under five customers implies a sequence they are not
       in, and bought a second horizontal axis nobody asked for.

   What survives is the part that was always right: five marks drawn at ONE cap
   height in ONE tint, told apart by letterform and tracking rather than by size
   or by value, dimmed to a single grey so the row reads as one texture and one
   claim. The rail's two edges dissolve into the paper, so a row that has to
   scroll never shears a letter down its stem.

   Everything is scoped under .sec-home-logos.
   ========================================================================== */

.sec-home-logos {
  position: relative;
  /* A strip, not a stage — the tight rhythm. The 0.66/0.82 pair this replaces
     measured 63/79 at 1440 and a different pair at every other width. */
  padding-block: var(--section-y-tight);
  /* Contains the rail's negative gutter margins. `clip`, not `hidden`, so the
     section never becomes a scroll container for the page. */
  overflow: clip;

  /* ONE measured constant. Every mark is set to the same CAP HEIGHT rather than
     the same font-size — Inter's cap is 0.727em, Source Serif 4's is 0.66em —
     so "the five caps line up" is a property of the code and not something
     eyeballed once at 1440. */
  --wm-cap: clamp(16px, 1.45vw, 21px);
  --wm-sans: calc(var(--wm-cap) / 0.727);
  --wm-serif: calc(var(--wm-cap) / 0.66);
  --wm-glyph: calc(var(--wm-cap) * 1.3);

  /* MINIMUM gap only. At desktop `space-between` opens it to whatever is left
     over, so the row is set to its measure instead of to a guessed constant. */
  --wm-gap: 34px;

  /* The rail's inset, and the length of the dissolve, are the same figure as
     the page gutter. That is what makes the mask honest: the first mark lands
     flush under the label, and at any width where the row fits, the ramp falls
     entirely on empty paper and is invisible. Where the row genuinely scrolls,
     the same ramp is what the names dissolve into. */
  --wm-fade: var(--gutter);

  /* One value for all five marks — the whole point of a logo wall is that no
     customer outranks another. Hover lifts a single mark to full ink. */
  --wm-dim: 0.55;
}

/* ——— The label ——————————————————————————————————————————————————
   The system's own .eyebrow, unmodified: 14px, weight 400, --ash, no tracking.
   Round 3 set this uppercase and letterspaced inside a light box, which is a
   badge, and this system does not have badges. */
.sec-home-logos .lw__label {
  /* Flush to the measure's left edge, on the hero's own axis. */
  text-align: left;
}

/* ——— The rail ————————————————————————————————————————————————————
   Pulled out to the page gutter on both sides and padded back in by the same
   figure, so the marks start flush under the label while the fade ramps have
   somewhere empty to live. Below ~720px the row is longer than the rail and
   this becomes a real scroller; the mask is fixed to the rail's own box, so the
   dissolve stays at the edges while the names travel under it. */
/* The gap to the label above is the eyebrow's own, not a second figure here. */
.sec-home-logos .lw__rail {
  margin-inline: calc(var(--gutter) * -1);
  padding-inline: var(--gutter);
  /* Slack for the serif ascenders, which sit outside a line-height:1 box. */
  padding-block: 6px;
  overflow-x: auto;
  overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior-x: contain;
  scrollbar-width: none;
  /* Masks read alpha only, so an opaque token stands in for "keep". */
  -webkit-mask-image: linear-gradient(90deg, transparent 0, var(--ink) var(--wm-fade),
    var(--ink) calc(100% - var(--wm-fade)), transparent 100%);
  mask-image: linear-gradient(90deg, transparent 0, var(--ink) var(--wm-fade),
    var(--ink) calc(100% - var(--wm-fade)), transparent 100%);
}
.sec-home-logos .lw__rail::-webkit-scrollbar { display: none; }
.sec-home-logos .lw__rail:focus-visible { outline-offset: 10px; }

/* `space-between` with `gap` as a FLOOR: the first mark starts on the measure's
   left edge, the fifth ends on its right edge, and the leftover width is dealt
   out between them. That is what makes "the last name lands inside the frame" a
   property of the layout rather than a constant tuned at one viewport. If the
   marks plus the floor gaps ever exceed the rail, it degrades to a scroller and
   the ramp catches it — the failure mode is a dissolve, never a sheared stem. */
.sec-home-logos .lw__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--wm-gap);
  width: 100%;
  margin: 0;
  padding: 0;
  list-style: none;
}

/* The only state in the section, and it is a value change, not a colour one. */
.sec-home-logos .lw__mark {
  flex: none;
  display: flex;
  opacity: var(--wm-dim);
  transition: opacity var(--dur) var(--ease-out);
}
.sec-home-logos .lw__mark:hover { opacity: 1; }

/* ——— The wordmarks ——————————————————————————————————————————————
   ONE tint, ONE cap height, ONE optical weight. What differs between the marks
   is letterform and tracking — which is what actually distinguishes a real logo
   wall — never value and never scale. Trailing letter-spacing is cancelled with
   a negative margin on every tracked mark, so the gaps are measured between INK
   edges rather than between bounding boxes. */
.sec-home-logos .lw__wm {
  display: inline-flex;
  align-items: center;
  gap: 0.42em;
  color: var(--ink);
  line-height: 1;
  white-space: nowrap;
  font-family: var(--sans);
  font-weight: 500;
  font-size: var(--wm-sans);
}
.sec-home-logos .lw__glyph {
  flex: none;
  width: var(--wm-glyph);
  height: var(--wm-glyph);
}

/* — Scentsation — the fragrance-counter register: roman serif, tracked, no
   glyph, the letterforms are the mark. Sized off --wm-serif so its caps measure
   the same as the sans marks beside it. --- */
.sec-home-logos .lw__wm--scent {
  font-family: var(--serif);
  font-weight: 400;
  font-optical-sizing: auto;
  font-size: var(--wm-serif);
  letter-spacing: 0.04em;
  margin-inline-end: -0.04em;
}

/* — NOOT — exactly one cap tall like the rest; the interlocking rings carry its
   identity instead of its size. --- */
.sec-home-logos .lw__wm--noot {
  letter-spacing: 0.06em;
  margin-inline-end: -0.06em;
  gap: 0.34em;
}

/* — Urban Coffee Roaster — a two-line lockup, because 20 characters on one line
   at this cap would own a third of the wall. The lockup's overall height sits
   close to the others' cap height, so its optical mass matches even though its
   own caps are smaller — the alternative is a 400px mark. --- */
.sec-home-logos .lw__wm--ucr {
  font-size: calc(var(--wm-cap) * 0.63 / 0.727);
  text-transform: uppercase;
  gap: 0.62em;
}
.sec-home-logos .lw__stack { display: flex; flex-direction: column; gap: 0.46em; }
.sec-home-logos .lw__l1 { letter-spacing: 0.14em; margin-inline-end: -0.14em; }
.sec-home-logos .lw__l2 {
  font-weight: 400;
  letter-spacing: 0.475em;
  margin-inline-end: -0.475em;
  text-align: center;
}

/* — Pause It — the airy tracking is what stops it reading as body copy. --- */
.sec-home-logos .lw__wm--pause {
  font-weight: 450;
  letter-spacing: 0.15em;
  margin-inline-end: -0.15em;
  gap: 0.5em;
}

/* — Calici — the trailing mark, and the row's single italic. The most fluid
   letterform on the wall, which is why the right end reads as a run continuing
   rather than as a row stopping. --- */
.sec-home-logos .lw__wm--calici {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  font-optical-sizing: auto;
  font-size: var(--wm-serif);
  letter-spacing: -0.004em;
  gap: 0.4em;
}

/* ——— Tablet —————————————————————————————————————————————————————
   Still one distributed row: at 1024px of measure the five marks need about
   770px, so there is room to spare. */
@media (max-width: 1080px) {
  .sec-home-logos {
    --wm-cap: clamp(15px, 2vw, 19px);
    --wm-gap: 30px;
  }
}

/* ——— Phone ——————————————————————————————————————————————————————
   Not the desktop row let loose in 390px. Below here the marks are genuinely
   wider than the page, so the row stops pretending to be distributed and
   becomes a scroller: names travel under two fixed dissolves, the label stays
   put, and the section stays short. */
@media (max-width: 720px) {
  .sec-home-logos {
    --wm-cap: 14px;
    --wm-gap: 30px;
  }
  .sec-home-logos .lw__row {
    width: max-content;
    justify-content: flex-start;
    /* Kept explicitly: a scroll container's trailing padding is unreliable in
       flex, and the last mark must reach the same inset the first one starts
       on rather than butting against the dissolve. */
    padding-right: var(--gutter);
  }
}

/* ===== section:home-adoption ===== */
/* ============================================================================
   home-adoption — "almost every shop has a POS, almost none has anything else"

   Round 5. Round 4's instrument was structurally right — one 100-wide track per
   row, the fill the share that HAS the thing and the ruled ghost the share that
   does not — but it was built out of TWO pieces of ink: the panel, plus a
   rounded "shoulder" absolutely positioned out of its top-right corner carrying
   the caption and the head of the `without` column, over a tinted rectangle
   that floated inside the panel with its own hard top and bottom edges. At 1440
   the two masses read as one dark card sitting on another, and the tinted
   rectangle looked like it was cutting the "Point of sale 95" bar off rather
   than being a column of the same table. Two dark masses, one occluding the
   very data the section exists to show.

   The fix is structural, not cosmetic:

   1. ONE MASS. The shoulder is gone. There is a single rounded panel, cropped
      square by the left edge of the frame and terminating in a rounded right
      edge. Nothing is positioned over it.
   2. `WITHOUT` IS A COLUMN OF THE PANEL, NOT A CARD ON IT. The tint runs the
      panel's FULL height and is flush to its right edge, so it is clipped by
      the panel's own radius and shares its silhouette. A single hairline on its
      left edge is the column rule. Its head is the word `without`; its body is
      5 / 75 / 90 / 96 on one right-aligned tabular axis.
   3. NOTHING CROSSES A BAR. A full gutter (40px) of bare ink separates the end
      of every track from the band, and the track ends on a ruled 100 datum that
      ties the four bar-ends into one vertical and carries "in 100" beneath it.
      A bar that stops short of a visible datum reads as measured; a bar that
      stops at the edge of a lighter rectangle reads as truncated.
   4. THE GREYS ARE ONE ARGUMENT. The band is tinted the same family as the
      ghost remainder of the track, so white = has it, grey = does not, and the
      grey the reader follows off the end of the bar is the grey the figure for
      it is printed on. That is the 95/5 and 4/96 pairing made structural.

   The bar encoding is unchanged and must stay that way: width is the value,
   nothing else touches it, no minimum, no pixel floor.

   Everything is scoped under .sec-home-adoption.
   ========================================================================== */

.sec-home-adoption {
  background: var(--mist);
  /* The normal rhythm, symmetrically. The 1.2/0.85 pair this replaces measured
     115/82 at 1440 and drifted with the window. */
  padding-block: var(--section-y);
  /* Contains the left bleed at the section box. */
  overflow: hidden;

  /* The table. One template drives the head row, the four data rows and the
     axis row, so the columns cannot drift apart. The gutter is deliberately
     wide: it is the clearance between the 100 datum and the `without` band. */
  --col-label: 132px;
  --col-num: 92px;
  --col-miss: 168px;
  --colgap: var(--s40);
  --cols: var(--col-label) var(--col-num) minmax(0, 1fr) var(--col-miss);

  --pad-l: var(--s80);
  --pad-r: var(--s80);
  --pad-t: var(--s32);
  --axis-h: 40px;
  --track-h: 56px;
  --cell-y: var(--s16);

  --fig-num: 38px;
  --fig-miss: 58px;
  --label-size: 13px;

  /* Ink-surface tints, derived from the tokens rather than typed as hex. The
     band and the ghost are one step apart on purpose: same family, the ghost
     marginally stronger because it is the measured datum. */
  --ad-ghost: color-mix(in srgb, var(--paper) 58%, transparent);
  --ad-ghost-rule: color-mix(in srgb, var(--paper) 58%, transparent);
  --ad-field: color-mix(in srgb, var(--paper) 58%, transparent);
  --ad-hair: color-mix(in srgb, var(--paper) 58%, transparent);
  --ad-datum: color-mix(in srgb, var(--paper) 58%, transparent);
}

/* The bloom. Warm only — the lilac/blue members of the wash belong to the hero.
   The shared component's paper-coloured bottom fade is removed: on a mist band
   it would paint a white shelf across the close. */
.sec-home-adoption > .wash {
  inset: 0;
  opacity: 0.55;
  filter: blur(20px) saturate(104%);
  /* Zero-alpha stops are spelled out rather than `transparent` for the same
     reason 20-components.css does it: `transparent` interpolates through
     rgba(0,0,0,0) in older Safari and greys the edge of the bloom. */
  background:
    radial-gradient(48% 42% at 80% 12%, var(--wash-1) 0%, rgba(255, 217, 194, 0) 66%),
    radial-gradient(54% 46% at 10% 4%, var(--wash-2) 0%, rgba(255, 233, 214, 0) 70%);
}
.sec-home-adoption > .wash::after { content: none; }

/* ——— head ——————————————————————————————————————————————————— */

/* The measure is the rag, nothing else: with the shoulder gone there is no ink
   beside the headline for a line to run under. */
.sec-home-adoption .ad-title { max-width: 880px; }
/* Line masks clip on the baseline; pad the mask so serif descenders survive. */
.sec-home-adoption .ad-title .line-mask {
  padding-bottom: 0.14em;
  margin-bottom: -0.14em;
}

/* ——— the panel: ONE object ——————————————————————————————————— */

.sec-home-adoption .ad-stage { position: relative; }

.sec-home-adoption .ad-panel {
  position: relative;
  margin-top: var(--s48);
  /* THE CROP. (100% - 100vw) / 2 is the distance from the wrap's left edge to
     the frame, so the panel starts exactly at the viewport edge and is cut by
     it; the right edge stays on the measure and is rounded. A scrollbar can
     only push the left edge further off-frame, which is already the intent. */
  margin-left: calc((100% - 100vw) / 2);
  width: calc(100% + (100vw - 100%) / 2);
  padding: var(--pad-t) var(--pad-r) var(--s24) var(--pad-l);
  background: var(--ink);
  color: var(--paper);
  border-radius: 0 var(--r-card) var(--r-card) 0;
  /* The band is flush to the right edge, so the panel must clip it to its own
     radius — that clipping is what makes the band read as part of this object
     rather than a second one laid on top of it. */
  overflow: hidden;
}

/* THE `WITHOUT` COLUMN. Full height, flush right, one hairline rule. */
.sec-home-adoption .ad-band {
  position: absolute;
  z-index: 0;
  inset: 0 0 0 auto;
  width: calc(var(--col-miss) + var(--pad-r));
  background: var(--ad-field);
  border-left: 1px solid var(--ad-hair);
}

/* All content sits above the band: an absolutely positioned sibling would
   otherwise paint over in-flow text. */
.sec-home-adoption .ad-plot { position: relative; z-index: 1; }

/* The head row runs the table's own template, so `without` lands on the same
   right-aligned axis as the four figures beneath it and the caption sits over
   the bars it describes. -2 / -1 addresses the last column whether the template
   has four tracks (desktop) or two (mobile). */
.sec-home-adoption .ad-head {
  display: grid;
  grid-template-columns: var(--cols);
  column-gap: var(--colgap);
  align-items: baseline;
  padding-bottom: var(--s20);
}
/* A column head inside the table's own head row: the grid owns the spacing. */
.sec-home-adoption .ad-eyebrow {
  grid-column: 1 / -2;
  margin-bottom: 0;
}
.sec-home-adoption .ad-colhead {
  grid-column: -2 / -1;
  justify-self: end;
  font-size: 12px;
  font-weight: 500;
  line-height: 1;
  letter-spacing: 0.02em;
  color: var(--on-dark-muted);
}

/* ——— the table ————————————————————————————————————————————————— */

.sec-home-adoption .ad-table { position: relative; }

/* The 100 datum. One vertical at the end of every track, drawn OVER the tracks
   so it terminates all four bars on the same line and continues through the row
   rules; "in 100" sits under it on the axis. */
.sec-home-adoption .ad-datum {
  position: absolute;
  z-index: 2;
  top: 0;
  bottom: 0;
  right: calc(var(--col-miss) + var(--colgap));
  width: 1px;
  background: var(--ad-datum);
}

.sec-home-adoption .ad-chart {
  position: relative;
  z-index: 1;
  list-style: none;
  margin: 0;
  padding: 0;
  border-top: 1px solid var(--ad-hair);
  border-bottom: 1px solid var(--ad-hair);
}

.sec-home-adoption .ad-row {
  display: grid;
  grid-template-columns: var(--cols);
  column-gap: var(--colgap);
  align-items: stretch;
}

/* The row rules run past the figure column and out to the panel's edge, where
   the panel's own radius clips them. A rule that stopped on the last column
   would leave an unruled strip down the right of the band and re-open exactly
   the question this round closed — whether the band belongs to the table. The
   negative margin and the equal padding cancel, so the grid's content box (and
   therefore every column position) is untouched. */
.sec-home-adoption .ad-chart,
.sec-home-adoption .ad-row {
  margin-right: calc(var(--pad-r) * -1);
  padding-right: var(--pad-r);
}
.sec-home-adoption .ad-row + .ad-row { border-top: 1px solid var(--ad-hair); }

/* Cells carry the vertical padding, not the row, so the band and the datum run
   unbroken behind them. */
.sec-home-adoption .ad-row__label,
.sec-home-adoption .ad-row__num,
.sec-home-adoption .ad-row__miss {
  display: flex;
  align-items: center;
  padding-block: var(--cell-y);
}

.sec-home-adoption .ad-row__label {
  font-family: var(--sans);
  font-size: var(--label-size);
  font-weight: 500;
  line-height: 1.25;
  letter-spacing: 0.02em;
  color: var(--smoke);
}

/* Both figure columns are serif at display size, weight 400, tabular — one
   right-aligned axis each, never inline at four different x positions. */
.sec-home-adoption .ad-row__num,
.sec-home-adoption .ad-row__miss {
  justify-content: flex-end;
  font-family: var(--serif);
  font-weight: 400;
  font-optical-sizing: auto;
  line-height: 1;
  letter-spacing: var(--tr-h-lg);
}
.sec-home-adoption .ad-row__num { font-size: var(--fig-num); color: var(--smoke); }
.sec-home-adoption .ad-row__miss { font-size: var(--fig-miss); color: var(--paper); }

/* THE TRACK. The whole 100, always. The ghost is ruled at 25/50/75 by a
   repeating gradient whose period is exactly a quarter of the track, so the
   rules land on the axis ticks below without a second measurement — and they
   only show where the fill is not, which is precisely the "without" share. */
.sec-home-adoption .ad-row__track {
  align-self: center;
  position: relative;
  display: block;
  height: var(--track-h);
  border-radius: 2px;
  overflow: hidden;
  background-color: var(--ad-ghost);
  background-image: repeating-linear-gradient(
    90deg,
    var(--ad-ghost-rule) 0 1px,
    rgba(255, 255, 255, 0) 1px 25%
  );
}
/* The fill is the datum: width is the value, nothing else touches it. */
.sec-home-adoption .ad-row__fill {
  position: absolute;
  inset: 0 auto 0 0;
  width: var(--w, 0%);
  background: var(--paper);
}

/* ——— the axis ————————————————————————————————————————————————— */

.sec-home-adoption .ad-axis-row {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: var(--cols);
  column-gap: var(--colgap);
  height: var(--axis-h);
}
.sec-home-adoption .ad-axis {
  grid-column: 3;
  position: relative;
  height: 100%;
}
.sec-home-adoption .ad-tick {
  position: absolute;
  top: 0;
  left: var(--x);
  transform: translateX(-50%);
  padding-top: var(--s12);
  font-size: 12px;
  font-weight: 450;
  line-height: 1;
  letter-spacing: 0.02em;
  color: var(--slate);
  white-space: nowrap;
}
.sec-home-adoption .ad-tick::before {
  content: '';
  position: absolute;
  top: 0;
  left: 50%;
  width: 1px;
  height: var(--s8);
  background: var(--ad-hair);
}
/* The 100 mark is right-set, on the datum: a centred label there would hang
   past the plot and be the one thing the frame clips. */
.sec-home-adoption .ad-tick--end {
  left: auto;
  right: 0;
  transform: none;
  color: var(--smoke);
}
.sec-home-adoption .ad-tick--end::before { left: auto; right: 0; background: var(--ad-datum); }

/* ——— the close ————————————————————————————————————————————— */

/* 5/7, offset right. The paragraph is deliberately not a third full-width band
   on the headline's rail. */
.sec-home-adoption .ad-close {
  margin-top: var(--s80);
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  column-gap: var(--gutter);
}
.sec-home-adoption .ad-pull {
  grid-column: 2;
  color: var(--ink);
  text-wrap: pretty;
}

/* ——— tablet ——————————————————————————————————————————————— */
@media (max-width: 1080px) {
  .sec-home-adoption {
    --col-label: 128px;
    --col-num: 84px;
    --col-miss: 136px;
    --colgap: var(--s32);
    --pad-l: var(--s48);
    --pad-r: var(--s48);
    --fig-num: 32px;
    --fig-miss: 46px;
    --track-h: 48px;
  }
}

/* ——— the stacked table ——————————————————————————————————————— */
/* Below 960 the four-column table stops being a chart. The three fixed columns
   — label, figure, `without` — eat so much of a shrinking measure that by 768
   the TRACK was down to 200px, which makes the 4% bar eight pixels: technically
   still measured to its datum, but not readable as one. So the row restacks
   rather than compresses: the label and its own figure share a line, the track
   gets the whole width beneath them, and `without` stays a column flush to the
   panel's right edge, which is the encoding this section exists for. The close
   comes off its 5/7 split on the same breakpoint. */
@media (max-width: 960px) {
  .sec-home-adoption .ad-close {
    margin-top: var(--s64);
    grid-template-columns: minmax(0, 1fr);
  }
  .sec-home-adoption .ad-pull { grid-column: 1; }

  .sec-home-adoption {
    --col-miss: 120px;
    --colgap: var(--s24);
    --cols: minmax(0, 1fr) var(--col-miss);
    --fig-num: 30px;
    --fig-miss: 46px;
    --track-h: 40px;
  }

  /* The 100 datum is a four-column rule only. Stacked, the row's own figure
     right-aligns on the end of the track, so a vertical drawn there strikes
     through 95 / 25 / 10 / 4. The ghost track still terminates every bar on the
     same x and "in 100" still marks it, so nothing is lost. */
  .sec-home-adoption .ad-datum { display: none; }

  /* Two columns: the bar column and the `without` column. The label and its own
     figure share the first cell, one set to each end. */
  .sec-home-adoption .ad-row__label { grid-column: 1; grid-row: 1; justify-self: start; padding-block: var(--cell-y) 0; }
  .sec-home-adoption .ad-row__num { grid-column: 1; grid-row: 1; justify-self: end; padding-block: var(--cell-y) 0; }
  .sec-home-adoption .ad-row__track { grid-column: 1; grid-row: 2; align-self: start; margin-top: var(--s12); margin-bottom: var(--cell-y); }
  .sec-home-adoption .ad-row__miss { grid-column: 2; grid-row: 1 / 3; padding-block: var(--cell-y); }

  .sec-home-adoption .ad-axis { grid-column: 1; }
}

/* ——— mobile ——————————————————————————————————————————————— */
/* Designed, not reflowed: the panel comes back inside the measure and keeps its
   radius, and the `without` band stays flush to the panel's right edge so the
   encoding survives at 390px. */
@media (max-width: 620px) {
  .sec-home-adoption {
    --col-miss: 62px;
    --colgap: var(--s20);
    --pad-l: var(--s20);
    --pad-r: var(--s20);
    --pad-t: var(--s24);
    --axis-h: 32px;
    --track-h: 28px;
    --cell-y: var(--s12);
    --fig-num: 26px;
    --fig-miss: 34px;
    --label-size: 12px;
  }

  .sec-home-adoption .ad-panel {
    margin-top: var(--s40);
    margin-left: 0;
    width: 100%;
    padding-bottom: var(--s20);
    border-radius: var(--r-card);
  }
  .sec-home-adoption .ad-head { padding-bottom: var(--s16); }
  .sec-home-adoption .ad-colhead { font-size: 11px; }
  .sec-home-adoption .ad-row__track { margin-top: var(--s8); }
  .sec-home-adoption .ad-tick { font-size: 11px; padding-top: var(--s8); }

  .sec-home-adoption .ad-close { margin-top: var(--s48); }
}

/* This eyebrow sits inside the ink panel, where the light-ground --ash it
   inherits from .eyebrow measures 3.4:1. */
.sec-home-adoption .ad-panel .ad-eyebrow { color: var(--on-dark-muted); }

/* ===== section:home-barriers ===== */
/* ===================================================================
   home-barriers — "Why nobody bought it"

   The composition is the argument, and it is built on THREE different
   surfaces rather than three near-identical ones:

     1. "A contract."  — THE PEACH CARD. The homepage's one chromatic surface,
                          and it is the component's `.card--peach`, not a tint
                          mixed here: the page used to ship three bespoke warm
                          grounds and zero of the actual rationed one.
     2. "A new bill."  — deliberately the light one: paper + a hairline.
                          Its weight is typographic, not tonal.
     3. "Weeks of setup." — the ink slab, and the section's mass. It climbs
                          past the card row into the empty quarter beside the
                          headline and runs off the right edge of the screen.

   The slab used to be a wireframe floating in black. The month inside it is
   now a FILLED block field: eleven spent working days as solid blocks, four
   at risk at half tone, the rest as faint cells — a real object at roughly a
   third ink coverage instead of a 2.5% hairline ghost.

   THE DATUM IS CROP-PROOF. The field is 136% of the card's content width, so
   the visible fraction is (W + pad) / 1.36W — never below 73.5% at any width,
   which is always more than five of seven columns. Every marked day lives in
   columns 1–5; the cut always lands inside column 6, which carries no data.
   That is what makes "eleven to fifteen" countable at 1440 AND at 390.

   Peach is rationed to one surface per page, and on the homepage this card is
   it. Everything else warm on index.html — the hero's booking card, the
   capability slip, the traction shelf — has been taken back to a neutral
   ground, so there is exactly one warm surface and it is the component's.

   Every rule is scoped under .sec-home-barriers.
   =================================================================== */

.sec-home-barriers {
  /* How far the ink slab climbs above the card row. */
  --bar-rise: calc(var(--s160) + var(--s96));
  --bar-cal-gap: 8px;
  /* The gutter between the 1320 rail and the screen edge, negated. */
  --bar-bleed: calc(max(var(--gutter), (100vw - var(--page)) / 2) * -1);
  /* Tight, at both ends: the section used to end on 222px of empty paper (16%
     of its own height), and it used to pay for that with a 96/48 pair of its
     own. It takes the tight rhythm instead. */
  padding-block: var(--section-y-tight);
}

/* ——— Ground ————————————————————————————————————————
   Warm paper, not the cool --fog slab: the peach card is warm and a warm
   surface on a blue-leaning ground is the wrong argument. Low-amplitude warm
   blooms — --wash-1/-2 only, no lavender and no blue — sit LEFT and BOTTOM,
   out from under the ink slab that occupies the top right. */
.sec-home-barriers > .wash {
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  opacity: 0.62;
  filter: blur(14px) saturate(105%);
  background:
    radial-gradient(46% 30% at 2% 4%, var(--wash-2) 0%, transparent 66%),
    radial-gradient(32% 22% at 38% -4%, var(--wash-1) 0%, transparent 68%),
    radial-gradient(38% 26% at 6% 60%, var(--wash-2) 0%, transparent 70%),
    radial-gradient(46% 24% at 52% 100%, var(--wash-2) 0%, transparent 72%);
}

/* ——— Head ————————————————————————————————————————— */
.sec-home-barriers .bar__rule { background: var(--hair); }


.sec-home-barriers .bar__title {
  margin-top: var(--s40);
  /* Three lines at 64px, and short enough that the ink slab can climb up
     beside them without crowding a single glyph. */
  max-width: 820px;
}

/* ——— The three barriers ————————————————————————————
   Deliberately uneven spans: 1.14 / 0.86 / 1.34. The longer claim gets the
   wider card, the shorter claim the narrower one, and the lead takes the
   rest. align-items:stretch equalises the row so all three cards END on one
   line while their TOPS stagger by 64px and 256px. */
.sec-home-barriers .bar__grid {
  margin-top: var(--s80);
  display: grid;
  grid-template-columns: minmax(0, 1.14fr) minmax(0, 0.86fr) minmax(0, 1.34fr);
  gap: var(--s24);
  align-items: stretch;
}

/* Ground, radius and padding are the .card component's — and so is
   --illo-ground, which is what the drawings' `.illo-mask` silhouettes are
   painted in, so the occlusion cannot drift from the surface it has to
   disappear into. Nothing about the drawings is declared in this file. */
.sec-home-barriers .bar__card {
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.sec-home-barriers .bar__card--a,
.sec-home-barriers .bar__card--b { margin-top: var(--s64); }

/* THE TWO DRAWINGS SET NOTHING. Weight, caps, joins, colour, contrast and the
   occluding fill are the global `.illo` system's; the size is `.illo--card`,
   the site's one card-drawing ceiling. This file gives them a box and their
   place in the card, and that is all it is allowed to give them. */
.sec-home-barriers .bar__art { display: block; }

.sec-home-barriers .bar__card .card__title { margin-bottom: var(--s12); }

/* 1 — the peach card. Ground and the whole type recolour come from
   `.card--peach`; the drawing inherits its sienna through `color`. Drawing at
   the top, claim pressed onto the bottom edge. */
.sec-home-barriers .bar__art--a {
  margin-bottom: var(--s32);
}
.sec-home-barriers .bar__card--a .bar__txt { margin-top: auto; }

/* 2 — the plain card, and deliberately so: one warm surface per page means this
   one earns its weight from the figure. Same flush-left grammar as card 1,
   mirrored: claim at the top, drawing on the bottom edge. */
.sec-home-barriers .bar__fig {
  margin: var(--s16) 0 var(--s12);
  line-height: 1;
  color: var(--ink);
}
.sec-home-barriers .bar__art--b {
  margin-top: auto;
  padding-top: var(--s32);
}

/* 3 — the lead. Ink, no hairline (the tone is the edge). It climbs past the
   row into the void beside the headline and bleeds off the right edge of the
   viewport; the bleeding corners are SQUARED so the drawing is cut by a
   straight edge instead of being sliced by a 24px radius. */
.sec-home-barriers .bar__card--lead {
  background: var(--ink);
  color: var(--paper);
  padding: var(--s40);
  margin-top: calc(var(--bar-rise) * -1);
  /*
   * NOT `50% - 50vw`: a grid item's percentages resolve against its grid AREA
   * (462px here), not against the grid, which blew the card out to 951px and
   * dragged the document 369px wider than the viewport.
   */
  margin-right: var(--bar-bleed);
  border-radius: var(--r-card) 0 0 var(--r-card);
}
.sec-home-barriers .bar__card--lead .card__title { color: var(--paper); }
.sec-home-barriers .bar__card--lead .card__body { color: var(--smoke); }
/* The slab is wide; the text is not. A tight measure keeps the right half of
   the surface clear for the month. */
.sec-home-barriers .bar__card--lead .bar__txt { max-width: 380px; }

/* ——— The month, as mass ————————————————————————————
   `flex: 1` means the field consumes ALL remaining height in the slab, so the
   60px dead band between the body copy and the drawing cannot come back at
   any card height. 136% width is the bleed; see the header note for why that
   number keeps five columns alive at every viewport. */
.sec-home-barriers .bar__cal {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: var(--bar-cal-gap);
  width: 136%;
  margin-top: var(--s24);
}

.sec-home-barriers .bar__cal-head,
.sec-home-barriers .bar__cal-grid {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: var(--bar-cal-gap);
}

.sec-home-barriers .bar__cal-head span {
  font-size: 11px;
  line-height: 1;
  letter-spacing: 0.18em;
  color: var(--smoke);
  padding-left: 8px;
}

.sec-home-barriers .bar__cal-grid {
  flex: 1 1 auto;
  min-height: 0;
  grid-auto-rows: minmax(42px, 1fr);
}

.sec-home-barriers .bar__cal-grid i {
  font-style: normal;
  font-size: 12px;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  padding: 8px 0 0 8px;
  border-radius: 7px;
  color: var(--smoke);
  /* Free days: present, but only just — they still have to add up to a field
     rather than a scatter of marks. */
  background: color-mix(in srgb, var(--paper) 8%, transparent);
}
/* Weekends carry no datum, which is exactly why they are the columns the
   viewport edge is allowed to cut through. */
.sec-home-barriers .bar__cal-grid i.is-off {
  background: color-mix(in srgb, var(--paper) 8%, transparent);
  color: color-mix(in srgb, var(--smoke) 55%, transparent);
}
/* Four more days at risk — the top of the stated range. */
.sec-home-barriers .bar__cal-grid i.is-risk {
  background: color-mix(in srgb, var(--paper) 8%, transparent);
  color: var(--ink);
}
/* Eleven days already gone — the bottom of the stated range, and the solid
   mass that makes the slab an object instead of a void. */
.sec-home-barriers .bar__cal-grid i.is-gone {
  background: color-mix(in srgb, var(--paper) 90%, var(--ink));
  color: var(--ink);
}
/* The month runs on rather than stopping in a hole: the four cells after the
   31st are next month, at the faintest step on the ramp. */
.sec-home-barriers .bar__cal-grid i.is-next {
  background: color-mix(in srgb, var(--paper) 8%, transparent);
  color: color-mix(in srgb, var(--smoke) 32%, transparent);
}

/* ——— The close ————————————————————————————————————
   One hairline, then one ROW: the pull on the 120 rail, the payoff hard
   against the 1320 rail, both on the same bottom line — then a solid ink bar
   under the payoff that bleeds off the right edge. That bar is what stops the
   section dissolving: the last inked row is now an OBJECT ~50px above the
   bottom edge, not a serif full stop 222px above it, and the weight stays
   right-of-centre all the way down. */
.sec-home-barriers .bar__close { margin-top: var(--s96); }
.sec-home-barriers .bar__rule--close { margin-bottom: var(--s48); }

.sec-home-barriers .bar__foot {
  grid-column: 6 / -1;
  grid-row: 2;
  height: 14px;
  margin-top: var(--s32);
  margin-right: var(--bar-bleed);
  background: var(--ink);
  border-radius: var(--r-small) 0 0 var(--r-small);
}

.sec-home-barriers .bar__close-grid {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--gutter);
  align-items: end;
}

.sec-home-barriers .bar__pull {
  grid-column: 1 / span 5;
  grid-row: 1;
  color: var(--slate);
}

/* The payoff carries .h and takes its size from it. It used to be set at
   --t-h-lg (and at --t-display on a phone), which made the closing line of this
   section louder than the section's own headline — the class named one rank and
   rendered another. */
.sec-home-barriers .bar__payoff {
  grid-column: 6 / -1;
  grid-row: 1;
  justify-self: end;
  text-align: right;
  line-height: 1.08;
}

/* ——— Narrow desktop ————————————————————————————————
   --t-h-lg drops to 48px at 1080, so the head loses a line and the grid moves
   up ~58px with it. At the full rise the slab would clear the section's own
   top padding and swallow the head's hairline, so the climb comes down a step. */
@media (max-width: 1080px) {
  .sec-home-barriers { --bar-rise: calc(var(--s128) + var(--s16)); }
}

/* ——— Tablet ————————————————————————————————————————
   Three columns below ~1040px cut the body to a ~24-character measure, so the
   pair stacks into one column and the lead becomes a TALL slab beside them —
   the same composition as the desktop, not a wide banner with a hole in it.
   It still runs off the right edge of the screen. */
@media (max-width: 1040px) {
  .sec-home-barriers .bar__grid {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.06fr);
    gap: var(--s24);
  }
  .sec-home-barriers .bar__card--a { grid-column: 1; grid-row: 1; margin-top: 0; }
  .sec-home-barriers .bar__card--b { grid-column: 1; grid-row: 2; margin-top: 0; }

  .sec-home-barriers .bar__card--lead {
    grid-column: 2;
    grid-row: 1 / span 2;
    margin-top: 0;
    padding: var(--s32);
  }
  .sec-home-barriers { --bar-cal-gap: 6px; }

  .sec-home-barriers .bar__pull { grid-column: 1 / span 6; }
  .sec-home-barriers .bar__payoff { grid-column: 7 / -1; }
}

@media (max-width: 860px) {
  .sec-home-barriers .bar__title { max-width: 620px; }
  /* Two anchored edges will not fit on one line here, so the payoff drops to
     its own row — still right-set on the rail, never centred. */
  .sec-home-barriers .bar__pull { grid-column: 1 / -1; grid-row: 1; }
  .sec-home-barriers .bar__payoff {
    grid-column: 4 / -1;
    grid-row: 2;
    margin-top: var(--s48);
  }
  .sec-home-barriers .bar__foot { grid-column: 4 / -1; grid-row: 3; }
}

/* ——— Phone —————————————————————————————————————————
   Phone gets its own composition rather than the desktop cards stacked. The
   hierarchy survives the change of format: the peach card stays a card, the
   plain card gives up its ground and becomes a hairline row (its figure is
   doing the work anyway), and the ink slab stays a slab with the month still
   bleeding off its right edge — five columns of it, same as desktop. */
@media (max-width: 720px) {
  .sec-home-barriers { --bar-cal-gap: 5px; }
  .sec-home-barriers > .wash { opacity: 0.5; }

  .sec-home-barriers .bar__title { max-width: none; margin-top: var(--s28); }

  .sec-home-barriers .bar__grid {
    margin-top: var(--s48);
    display: block;
  }

  /* THE DRAWINGS STAY DRAWINGS. They used to drop into a 56px side column,
     which is a thumbnail, not an object — and the section then raised their
     stroke to 2.1 to keep them visible, so the phone shipped a second weight
     to rescue a size that was wrong. The card keeps its desktop anatomy
     instead: one column, drawing above or below the claim, and the object at
     the same card ceiling every other drawing on the site answers to. */
  .sec-home-barriers .bar__card { margin-top: 0; }

  .sec-home-barriers .bar__art { margin: 0 0 var(--s24); padding-top: 0; }
  .sec-home-barriers .bar__art--b { margin: var(--s24) 0 0; }
  .sec-home-barriers .bar__txt { margin-top: 0; }

  /* The peach card keeps its field — mobile needs mass too. */
  .sec-home-barriers .bar__card--a {
    padding: var(--s24);
    border-radius: var(--r-card);
  }

  /* The plain card drops to a hairline row: at ~350px of content width the
     ground around it buys nothing, and one peach card plus one plain row is
     a hierarchy where two filled boxes would be two of the same. */
  .sec-home-barriers .bar__card--b {
    background: transparent;
    border: 0;
    border-top: 1px solid var(--hair);
    border-radius: 0;
    padding: var(--s28) 0 var(--s24);
    margin-top: var(--s28);
  }
  /* The card gives up its ground here, so the drawing's silhouettes have to be
     painted in the page instead — one declaration, and the occlusion follows
     the surface rather than leaving white patches on paper. */
  .sec-home-barriers .bar__card--b { --illo-ground: var(--paper); }
  .sec-home-barriers .bar__fig { margin: var(--s12) 0 var(--s8); }

  /* The lead stays a surface, and the month stays the mass. */
  .sec-home-barriers .bar__card--lead {
    display: flex;
    flex-direction: column;
    background: var(--ink);
    color: var(--paper);
    border: 0;
    border-radius: var(--r-card);
    margin-top: var(--s32);
    margin-right: 0;
    padding: var(--s28) var(--s24);
  }
  .sec-home-barriers .bar__card--lead .card__title { color: var(--paper); }
  .sec-home-barriers .bar__card--lead .card__body { color: var(--smoke); }
  .sec-home-barriers .bar__card--lead .bar__txt { max-width: none; }
  .sec-home-barriers .bar__cal { margin-top: var(--s24); }
  .sec-home-barriers .bar__cal-grid { grid-auto-rows: minmax(40px, 1fr); }
  .sec-home-barriers .bar__cal-grid i { font-size: 11px; padding: 6px 0 0 6px; border-radius: 5px; }
  .sec-home-barriers .bar__cal-head span { padding-left: 6px; letter-spacing: 0.1em; }

  .sec-home-barriers .bar__close { margin-top: var(--s64); }
  .sec-home-barriers .bar__rule--close { margin-bottom: var(--s32); }
  .sec-home-barriers .bar__close-grid { display: block; }
  .sec-home-barriers .bar__pull { text-wrap: pretty; }
  .sec-home-barriers .bar__foot { height: 10px; margin-top: var(--s28); }
  .sec-home-barriers .bar__payoff {
    margin-top: var(--s48);
    text-align: left;
    line-height: 1.06;
  }
}

/* ===== section:home-capability ===== */
/* ————————————————————————————————————————————————
   home-capability — six pill tabs swapping one POS surface, staged.

   COMPOSITION. Three objects, three depths, two of them cut by a frame edge.
     · the type block holds the left gutter; the tab rail is pushed to the
       opposite corner so the top band reads as a diagonal, not a centred stack;
     · the CARD is the focal object and is deliberately pushed past 100vw so the
       tinted rail column is sliced off by the viewport, not by its own margin;
     · a SHEET peeks 14px above the card's top edge, one step warmer, no shadow;
     · a printed SLIP sits lower-left at a lower elevation and a warmer tint,
       tucked under the card on desktop and cut by the left frame edge on mobile.
   Nothing shares a centre line and no two objects share a tint.

   TEMPERATURE. The ground is warm paper. Every surface on it — tabs, chips,
   card, rail, slip — is mixed toward --wash-2 so nothing measures cooler than
   neutral. Hairlines are ink-alpha, never a grey hex, so they darken the warm
   surface beneath instead of laying a cool grey over it.

   PANEL. One table: head rule, body, foot rule. The tint column runs the full
   height of the card (head cell, rail, foot cell) as one continuous band, so the
   viewport cut lands on flat tint. The list column and the rail share ONE
   `grid-template-rows` track list (`--cap-tracks`), so every key/value in the
   rail baseline-aligns to a line item and the hairlines run continuously across
   the divider. Row content is `align-content: center` over two grid rows, so a
   qty sits on its item's baseline and the modifier hangs below it.
   ———————————————————————————————————————————————— */

.sec-home-capability {
  /* Warm paper. Composed from the wash family so no raw colour enters the system. */
  background: color-mix(in srgb, var(--paper) 80%, var(--wash-2));
  padding-block: var(--section-y);
  overflow: clip;

  /* Local scale — the panel's one figure size, one row height, one gutter. */
  --cap-figure: 28px;
  --cap-row: 52px;
  --cap-pad: 30px;
  --cap-rail: 264px;

  /* Surfaces. All warm: none of these may measure cooler than neutral. */
  --cap-card: color-mix(in srgb, var(--raised) 80%, var(--wash-2));
  --cap-tint: color-mix(in srgb, var(--raised) 66%, var(--wash-2));
  --cap-chip: color-mix(in srgb, var(--raised) 52%, var(--wash-2));
  --cap-sheet: color-mix(in srgb, var(--raised) 44%, var(--wash-2));

  /* Ink-alpha hairlines: they darken the warm surface rather than greying it. */
  --cap-hair: color-mix(in srgb, var(--ink) 12%, transparent);
  --cap-hair-2: color-mix(in srgb, var(--ink) 7%, transparent);

  /*
   * THE BLEED. Land the card's right edge 64px PAST 100vw so the tint rail is
   * sliced by the viewport. `min()` keeps it negative on narrow desktops where
   * the wrap is already gutter-bound. `html { overflow-x: clip }` contains it.
   */
  --cap-bleed: min(-36px, calc((var(--page) - 100vw) / 2 - var(--s48)));
  /* The card's left inset — the pocket the slip lives in. Opens as the page widens. */
  --cap-ml: clamp(0px, calc((100vw - 1180px) * 1.2), 264px);
}

/* — Ground ——————————————————————————————————————
   The bloom peaks behind the headline and again behind the card's top-right,
   so the composition has two warm centres and no symmetry.                */
.sec-home-capability > .wash {
  inset: -6% -12% -2%;
  opacity: 0.82;
  background:
    radial-gradient(64% 44% at 30% 20%, var(--wash-1) 0%, transparent 68%),
    radial-gradient(50% 38% at 72% 6%,  var(--wash-2) 0%, transparent 70%),
    radial-gradient(58% 50% at 88% 52%, var(--wash-1) 0%, transparent 72%),
    radial-gradient(46% 40% at 4% 70%,  var(--wash-2) 0%, transparent 74%),
    radial-gradient(42% 34% at 58% 98%, var(--wash-3) 0%, transparent 76%);
  filter: blur(12px) saturate(128%);
}
/* The base component fades the wash to white over 200px; this section keeps its
   colour to the seam, so the fade is reduced to a short, soft landing. */
.sec-home-capability > .wash::after {
  height: 96px;
  background: linear-gradient(to top,
    color-mix(in srgb, var(--paper) 62%, transparent), transparent);
}

/* The grain. Fine, monochrome, multiplied into the bloom. */
.sec-home-capability .cap__grain {
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  opacity: 0.075;
  mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 220 220' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.82' numOctaves='3' seed='19' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23g)'/%3E%3C/svg%3E");
  background-size: 200px 200px;
}

/* — Top band: type hard left, tab rail hard right, nothing centred —————— */
.sec-home-capability .cap__top {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: end;
  gap: var(--s32) var(--s48);
}
.sec-home-capability .cap__intro { max-width: 640px; }
/* No size of its own: this is a section headline and .h is what a section
   headline is. It used to run at 1.3 x --t-h-lg (83px), which put a heading
   above every page title on the site bar the home hero. The measure stays in
   ch, so the authored rag is the same number of characters at the new size. */
.sec-home-capability .cap__h {
  max-width: 12ch;
}
.sec-home-capability .cap__lede {
  margin-top: var(--s20);
  max-width: 34ch;
  text-wrap: balance;
}

.sec-home-capability .cap__tabs {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: var(--s8);
  max-width: 620px;
  margin-bottom: 5px;
}
.sec-home-capability .cap__tab {
  height: 44px;
  padding-inline: 19px;
  border: 1px solid var(--cap-hair-2);
  border-radius: var(--r-pill);
  background: var(--cap-chip);
  color: var(--slate);
  font-family: var(--sans);
  font-size: 15px;
  font-weight: 450;
  letter-spacing: -0.005em;
  white-space: nowrap;
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out);
}
.sec-home-capability .cap__tab:hover {
  background: color-mix(in srgb, var(--raised) 26%, var(--wash-2));
  color: var(--ink);
}
.sec-home-capability .cap__tab.is-active {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--paper);
}

/* — The deck: the stage for all three objects ————————————————— */
.sec-home-capability .cap__deck {
  position: relative;
  margin-top: var(--s48);
}

/* The sheet behind. No shadow — only the card is elevated; this is a surface. */
.sec-home-capability .cap__sheet {
  position: relative;
  z-index: 0;
  height: 46px;
  margin-left: calc(var(--cap-ml) + 76px);
  margin-right: var(--cap-bleed);
  margin-bottom: -28px;
  border: 1px solid var(--cap-hair-2);
  border-bottom: 0;
  border-radius: var(--r-elevated) var(--r-elevated) 0 0;
  background: var(--cap-sheet);
}

/* The card. Focal object: biggest, whitest, the only shadow. */
.sec-home-capability .cap__stage {
  position: relative;
  z-index: 1;
  margin-left: var(--cap-ml);
  margin-right: var(--cap-bleed);
  display: grid;
  overflow: hidden;
  background: var(--cap-card);
}

.sec-home-capability .cap__panel {
  grid-area: 1 / 1;
  display: flex;
  flex-direction: column;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transform: translateY(8px);
  transition: opacity 400ms var(--ease-out), transform 560ms var(--ease-out), visibility 0s linear 400ms;
}
.sec-home-capability .cap__panel.is-shown {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transform: none;
  transition: opacity 400ms var(--ease-out), transform 560ms var(--ease-out), visibility 0s;
}
.sec-home-capability .cap__panel:focus-visible { outline-offset: -4px; }

/* — Panel head. The tint column starts at the card's very top edge. ———— */
.sec-home-capability .cap__head {
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--cap-rail);
  border-bottom: 1px solid var(--cap-hair);
}
.sec-home-capability .cap__head-main {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 22px var(--cap-pad) 17px;
  min-width: 0;
}
.sec-home-capability .cap__head-side {
  background: var(--cap-tint);
  border-left: 1px solid var(--cap-hair);
}
.sec-home-capability .cap__ico {
  flex: none;
  width: 34px; height: 34px;
  display: grid; place-items: center;
  border-radius: 10px;
  background: var(--cap-chip);
  color: var(--ink);
}
.sec-home-capability .cap__ico svg { width: 20px; height: 20px; }
.sec-home-capability .cap__id { min-width: 0; flex: 1 1 auto; }
.sec-home-capability .cap__title {
  font-family: var(--sans);
  font-size: 17px;
  font-weight: 500;
  letter-spacing: -0.01em;
  line-height: 1.25;
}
.sec-home-capability .cap__sub {
  margin-top: 3px;
  font-size: 13px;
  line-height: 1.3;
  color: var(--slate);
  font-variant-numeric: tabular-nums;
}

/* Chips read at 1x: ink text on a warm fill with a visible edge. */
.sec-home-capability .cap__chip {
  flex: none;
  display: inline-flex; align-items: center;
  height: 26px;
  padding-inline: 11px;
  border-radius: var(--r-pill);
  border: 1px solid var(--cap-hair-2);
  background: var(--cap-chip);
  color: var(--ink);
  font-size: 12.5px;
  font-weight: 450;
  white-space: nowrap;
}
.sec-home-capability .cap__chip--ink { background: var(--ink); border-color: var(--ink); color: var(--paper); }
.sec-home-capability .cap__chip--line { background: transparent; border-color: var(--smoke); color: var(--ink); }

/* — Body: one shared track list across list and rail ————————— */
.sec-home-capability .cap__grid {
  flex: 1 1 auto;
  min-height: 300px;
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--cap-rail);
  align-items: stretch;
}

.sec-home-capability .cap__rows,
.sec-home-capability .cap__member,
.sec-home-capability .cap__rail {
  display: grid;
  grid-template-rows: repeat(var(--cap-tracks, 5), minmax(var(--cap-row), 1fr));
  margin: 0;
  padding: 0;
  list-style: none;
}

/*
 * Two grid rows: the line, then the modifier. `align-content: center` centres
 * that block in the track, and every cell in row 1 is baseline-aligned — so the
 * qty sits on the item's baseline instead of floating between its two lines.
 */
.sec-home-capability .cap__row {
  display: grid;
  align-content: center;
  align-items: baseline;
  gap: 0 14px;
  padding-inline: var(--cap-pad);
  border-bottom: 1px solid var(--cap-hair);
}
.sec-home-capability .cap__rows > .cap__row:last-child { border-bottom: 0; }

.sec-home-capability .cap__rows--ticket .cap__row { grid-template-columns: 22px minmax(0, 1fr) auto; --cap-modcol: 2; }
.sec-home-capability .cap__rows--stock .cap__row  { grid-template-columns: minmax(0, 1fr) auto; --cap-modcol: 1; }
.sec-home-capability .cap__rows--book .cap__row   { grid-template-columns: 46px minmax(0, 1fr) auto; --cap-modcol: 2; }
.sec-home-capability .cap__rows--close .cap__row  { grid-template-columns: minmax(0, 1fr) auto; --cap-modcol: 1; }
.sec-home-capability .cap__rows--visits .cap__row { grid-template-columns: 56px minmax(0, 1fr) auto; --cap-modcol: 2; }

.sec-home-capability .cap__qty,
.sec-home-capability .cap__time {
  font-size: 14px;
  line-height: 1.3;
  color: var(--slate);
  font-variant-numeric: tabular-nums;
}
.sec-home-capability .cap__name {
  font-size: 15px;
  line-height: 1.3;
  font-weight: 400;
  letter-spacing: -0.004em;
  min-width: 0;
}
.sec-home-capability .cap__mod {
  grid-column: var(--cap-modcol, 2);
  grid-row: 2;
  margin-top: 2px;
  font-size: 12.5px;
  line-height: 1.3;
  color: var(--slate);
  font-variant-numeric: tabular-nums;
}
.sec-home-capability .cap__amt {
  font-size: 15px;
  line-height: 1.3;
  font-weight: 450;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.sec-home-capability .cap__tail {
  display: inline-flex;
  align-items: baseline;
  gap: 12px;
  justify-content: flex-end;
}
.sec-home-capability .cap__row--low .cap__name { font-weight: 500; }

/* The summary rule is a full step darker than a line hairline, so it reads. */
.sec-home-capability .cap__row--last { border-bottom-color: var(--smoke); }
.sec-home-capability .cap__row--sum .cap__name { font-weight: 500; }
.sec-home-capability .cap__amt--figure {
  font-size: var(--cap-figure);
  font-weight: 450;
  letter-spacing: -0.02em;
  line-height: 1;
}

/* — Rail: the tinted column, sliced by the viewport ————————————— */
.sec-home-capability .cap__rail {
  background: var(--cap-tint);
  border-left: 1px solid var(--cap-hair);
}
/*
 * The rail reads DOWN the left of its column, not across to its right edge.
 * That is what makes the bleed survivable: the viewport slices flat tint instead
 * of guillotining "Kitchen · rea…". It also gives the rail its own texture — a
 * micro-label over a value — against the list's single-line ledger rows.
 */
.sec-home-capability .cap__kv {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: 2px;
  padding-inline: var(--cap-pad);
  border-bottom: 1px solid var(--cap-hair-2);
}
.sec-home-capability .cap__rail > .cap__kv:last-child { border-bottom: 0; }
.sec-home-capability .cap__k {
  font-size: 11px;
  font-weight: 450;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--slate);
}
.sec-home-capability .cap__v {
  font-size: 14px;
  line-height: 1.25;
  font-weight: 450;
  text-align: left;
  font-variant-numeric: tabular-nums;
}

/* — Loyalty: the member block spans two tracks, visits take three ———— */
.sec-home-capability .cap__member-card {
  grid-row: span 2;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 16px;
  padding: 18px var(--cap-pad);
  border-bottom: 1px solid var(--cap-hair);
}
.sec-home-capability .cap__member-top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
}
.sec-home-capability .cap__member-visit {
  font-family: var(--sans);
  font-weight: 400;
  font-size: 17px;
  color: var(--slate);
  letter-spacing: -0.01em;
}
.sec-home-capability .cap__member-visit-n {
  font-size: var(--cap-figure);
  font-weight: 450;
  letter-spacing: -0.02em;
  color: var(--ink);
}
.sec-home-capability .cap__member-meta { display: inline-flex; align-items: baseline; gap: 14px; }
.sec-home-capability .cap__member-phone { font-size: 14px; font-weight: 450; font-variant-numeric: tabular-nums; }
.sec-home-capability .cap__member-tier { font-size: 13px; color: var(--slate); }
.sec-home-capability .cap__dots { display: flex; gap: 7px; }
.sec-home-capability .cap__dots i {
  width: 9px; height: 9px; border-radius: var(--r-pill);
  background: var(--raised);
  box-shadow: inset 0 0 0 1px var(--smoke);
}
.sec-home-capability .cap__dots i.is-on { background: var(--ink); box-shadow: none; }
.sec-home-capability .cap__rows--visits { grid-row: span 3; grid-template-rows: repeat(3, minmax(var(--cap-row), 1fr)); }

/* — Close radial ————————————————————————————————— */
/* Left-anchored like the key/value rail, so the frame cut takes tint, not type. */
.sec-home-capability .cap__rail--radial {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: 16px;
  padding: 20px var(--cap-pad);
}
.sec-home-capability .cap__radial-wrap { position: relative; width: 128px; height: 128px; }
.sec-home-capability .cap__radial { width: 100%; height: 100%; }
.sec-home-capability .cap__radial-track { stroke: color-mix(in srgb, var(--ink) 10%, transparent); }
.sec-home-capability .cap__radial-arc { stroke: var(--ink); }
.sec-home-capability .cap__radial-num {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  font-size: var(--cap-figure); font-weight: 450; letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}
.sec-home-capability .cap__radial-lab {
  font-size: 12.5px; color: var(--slate); max-width: 172px; line-height: 1.4;
}

/* — Panel foot. The total right-aligns on the SAME axis as every amount,
     because the foot repeats the body's two-column track list. —————— */
.sec-home-capability .cap__foot {
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--cap-rail);
  border-top: 1px solid var(--cap-hair);
}
.sec-home-capability .cap__foot-main {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px 20px;
  flex-wrap: wrap;
  min-height: 74px;
  padding: 16px var(--cap-pad) 20px;
}
.sec-home-capability .cap__foot-side {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  padding: 12px var(--cap-pad);
  background: var(--cap-tint);
  border-left: 1px solid var(--cap-hair);
}
.sec-home-capability .cap__foot-k { font-size: 13px; color: var(--slate); font-variant-numeric: tabular-nums; }
.sec-home-capability .cap__foot-money { display: inline-flex; align-items: baseline; gap: 14px; margin-left: auto; }
.sec-home-capability .cap__foot-lab { font-size: 13px; color: var(--slate); }
.sec-home-capability .cap__total {
  font-size: var(--cap-figure);
  font-weight: 450;
  letter-spacing: -0.02em;
  line-height: 1.05;
  font-variant-numeric: tabular-nums;
}
.sec-home-capability .cap__act {
  display: inline-flex; align-items: center; gap: 7px;
  height: 38px; padding-inline: 17px;
  border-radius: var(--r-pill);
  background: var(--ink); color: var(--paper);
  font-size: 13.5px; font-weight: 450;
  white-space: nowrap;
}
.sec-home-capability .cap__act svg { width: 16px; height: 16px; }

/* — The printed slip ————————————————————————————————
   Portrait against the card's landscape, lower, rotated, and tucked under the
   card's left edge. On mobile it is cut by the left frame edge.

   The slip is PAPER, not a fourth warm surface. It used to be the warmest tint
   in the section (--cap-slip, 72% wash-2) and was in practice an unrationed
   peach card: the homepage spends its one warm surface on home-barriers, and
   nothing else on the page may declare a tint of its own. White against the
   warm card is also the sharper read for the thing that is meant to lift.   */
.sec-home-capability .cap__chits {
  position: absolute;
  left: 0;
  top: 136px;
  z-index: 0;
  width: 272px;
  display: grid;
  pointer-events: none;
}
.sec-home-capability .cap__chit {
  grid-area: 1 / 1;
  align-self: start;
  padding: 24px 20px 22px;
  border-radius: var(--r-small);
  background: var(--raised);
  box-shadow: var(--sh-pop);
  transform: rotate(-1.9deg);
  opacity: 0;
  visibility: hidden;
  transition: opacity 400ms var(--ease-out), visibility 0s linear 400ms;
}
.sec-home-capability .cap__chit.is-shown {
  opacity: 1;
  visibility: visible;
  transition: opacity 400ms var(--ease-out), visibility 0s;
}
.sec-home-capability .cap__chit-lab {
  font-size: 11.5px;
  font-weight: 450;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--sienna);
}
.sec-home-capability .cap__chit-title {
  margin-top: 16px;
  font-size: 16px;
  font-weight: 500;
  letter-spacing: -0.01em;
  line-height: 1.2;
}
.sec-home-capability .cap__chit-sub {
  margin-top: 3px;
  font-size: 12px;
  line-height: 1.35;
  color: var(--slate);
}
.sec-home-capability .cap__chit-rows {
  margin: 20px 0 0;
  padding: 16px 0 0;
  list-style: none;
  border-top: 1px dashed color-mix(in srgb, var(--ink) 22%, transparent);
}
.sec-home-capability .cap__chit-rows li {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 10px;
  padding-block: 9px;
  font-size: 12.5px;
  line-height: 1.35;
}
.sec-home-capability .cap__chit-rows--qty li { grid-template-columns: 16px minmax(0, 1fr); }
.sec-home-capability .cap__chit-rows li span:last-child { text-align: right; }
.sec-home-capability .cap__chit-rows--qty li span:last-child { text-align: left; }
.sec-home-capability .cap__chit-rows--qty li span:first-child { color: var(--slate); }
.sec-home-capability .cap__chit-foot {
  margin-top: 18px;
  padding-top: 15px;
  border-top: 1px dashed color-mix(in srgb, var(--ink) 22%, transparent);
  font-size: 11.5px;
  color: var(--slate);
}

/* — Responsive ——————————————————————————————————— */
/* Below 1200 the card runs nearly full width, so the slip has nowhere to sit. */
@media (max-width: 1199px) {
  .sec-home-capability .cap__chits { display: none; }
}

@media (max-width: 1080px) {
  .sec-home-capability {
    --cap-rail: 232px; --cap-pad: 24px; --cap-figure: 25px;
  }
  .sec-home-capability .cap__top { grid-template-columns: minmax(0, 1fr); }
  .sec-home-capability .cap__tabs { justify-content: flex-start; margin-bottom: 0; max-width: none; }
  .sec-home-capability .cap__deck { margin-top: var(--s40); }
  .sec-home-capability .cap__sheet { margin-left: 64px; }
}

@media (max-width: 900px) {
  .sec-home-capability .cap__head { grid-template-columns: minmax(0, 1fr); }
  .sec-home-capability .cap__head-side { display: none; }
  .sec-home-capability .cap__grid {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto auto;
    min-height: 0;
  }
  .sec-home-capability .cap__rows,
  .sec-home-capability .cap__member {
    grid-template-rows: repeat(var(--cap-tracks, 5), minmax(var(--cap-row), auto));
  }
  .sec-home-capability .cap__rail {
    border-left: 0;
    border-top: 1px solid var(--cap-hair);
  }
  .sec-home-capability .cap__rail--radial { border-top: 1px solid var(--cap-hair); }
  .sec-home-capability .cap__radial-wrap { width: 112px; height: 112px; }
  .sec-home-capability .cap__foot { grid-template-columns: minmax(0, 1fr); }
  .sec-home-capability .cap__foot-side {
    border-left: 0;
    border-top: 1px solid var(--cap-hair);
    justify-content: flex-end;
  }
  .sec-home-capability .cap__foot-side:empty { display: none; }

  /*
   * Demote the rail to a meta block: two columns of small key/value pairs on the
   * tint. Restacking it as five more full-width rows made a printer status weigh
   * the same as a HK$276 line item. `gap` over a tinted ground draws the rules,
   * so there is no double line where the rail meets the foot.
   */
  .sec-home-capability .cap__rail {
    grid-template-rows: none;
    grid-template-columns: 1fr 1fr;
    grid-auto-rows: auto;
    gap: 1px;
    background: var(--cap-hair-2);
  }
  .sec-home-capability .cap__kv {
    flex-direction: column;
    align-items: flex-start;
    justify-content: center;
    gap: 3px;
    padding: 11px var(--cap-pad);
    border-bottom: 0;
    background: var(--cap-tint);
  }
  .sec-home-capability .cap__rail > .cap__kv:last-child:nth-child(odd) { grid-column: 1 / -1; }
  .sec-home-capability .cap__k { font-size: 11.5px; }
  .sec-home-capability .cap__v { font-size: 13px; text-align: left; }
  .sec-home-capability .cap__rail--radial { display: flex; background: var(--cap-tint); }
}

@media (max-width: 720px) {
  .sec-home-capability {
    --cap-pad: 20px; --cap-figure: 23px; --cap-row: 48px;
  }
  .sec-home-capability .cap__h { max-width: 14ch; }
  .sec-home-capability .cap__lede { max-width: 30ch; }
  .sec-home-capability .cap__deck { margin-top: var(--s32); }
  .sec-home-capability .cap__sheet { display: none; }

  /*
   * One scrolling rail. `scroll-padding-inline` is load-bearing: without it the
   * snap engine aligns the first pill to the scrollport's edge — INSIDE the
   * padding — and the rail self-scrolls on load, putting Orders at x=0 while
   * every other element sits at the gutter. The mask makes the far edge read as
   * overflow rather than as a guillotined pill.
   */
  .sec-home-capability .cap__tabs {
    flex-wrap: nowrap;
    overflow-x: auto;
    overflow-y: hidden;
    scrollbar-width: none;
    -ms-overflow-style: none;
    scroll-snap-type: x proximity;
    scroll-padding-inline: var(--gutter);
    overscroll-behavior-inline: contain;
    margin-inline: calc(var(--gutter) * -1);
    padding-inline: var(--gutter);
    padding-block: 3px;
    -webkit-mask-image: linear-gradient(to right,
      transparent 0, var(--ink) var(--gutter),
      var(--ink) calc(100% - 52px), transparent 100%);
    mask-image: linear-gradient(to right,
      transparent 0, var(--ink) var(--gutter),
      var(--ink) calc(100% - 52px), transparent 100%);
  }
  .sec-home-capability .cap__tabs::-webkit-scrollbar { display: none; }
  .sec-home-capability .cap__tab { flex: 0 0 auto; scroll-snap-align: start; }

  /*
   * Pull the card off the axis: it keeps the left gutter and bleeds to the right
   * frame edge, squaring its right corners so the cut reads as intent.
   */
  .sec-home-capability .cap__stage {
    margin-left: 0;
    margin-right: calc(var(--gutter) * -1);
    border-radius: var(--r-elevated) 0 0 var(--r-elevated);
  }

  /* The slip drops below the card and is cut by the left frame edge. */
  /*
   * `position: relative` is load-bearing, not decorative: `.cap__stage` is a
   * positioned box, so a STATIC slip would paint underneath it whatever z-index
   * it carried, and the slip's own label vanished behind the card's corner.
   */
  .sec-home-capability .cap__chits {
    display: grid;
    position: relative;
    inset: auto;
    width: 252px;
    z-index: 2;
    margin: -34px 0 0 calc(var(--gutter) * -1 - 26px);
  }
  /* Extra left padding so the frame cut takes the slip's margin, never a word. */
  .sec-home-capability .cap__chit {
    transform: rotate(-2.6deg);
    padding: 15px 17px 13px 44px;
  }
  .sec-home-capability .cap__chit-sub { display: none; }
  .sec-home-capability .cap__chit-rows { margin-top: 11px; }

  .sec-home-capability .cap__head-main { gap: 11px; align-items: flex-start; padding-block: 18px 14px; }
  .sec-home-capability .cap__sub { font-size: 12.5px; }
  .sec-home-capability .cap__chip { font-size: 12px; padding-inline: 9px; }
  .sec-home-capability .cap__row { gap: 0 10px; }
  .sec-home-capability .cap__rows--book .cap__row { grid-template-columns: 38px minmax(0, 1fr) auto; }
  .sec-home-capability .cap__rows--book .cap__tail { gap: 8px; }
  .sec-home-capability .cap__rows--book .cap__chip { font-size: 11.5px; padding-inline: 8px; height: 23px; }
  .sec-home-capability .cap__rows--visits .cap__row { grid-template-columns: 50px minmax(0, 1fr) auto; }
  .sec-home-capability .cap__name,
  .sec-home-capability .cap__amt { font-size: 14.5px; }
  .sec-home-capability .cap__member-card { gap: 13px; padding-block: 16px; }
  .sec-home-capability .cap__foot-main { padding-block: 14px 18px; min-height: 0; }
  .sec-home-capability .cap__foot-side { padding: 12px var(--cap-pad) 14px; }
}

@media (max-width: 420px) {
  .sec-home-capability .cap__rows--book .cap__chip,
  .sec-home-capability .cap__rows--book .cap__tail .cap__chip { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .sec-home-capability .cap__panel { transform: none; transition: opacity 1ms linear, visibility 0s linear 1ms; }
  .sec-home-capability .cap__panel.is-shown { transition: opacity 1ms linear, visibility 0s; }
  .sec-home-capability .cap__chit { transition: opacity 1ms linear, visibility 0s linear 1ms; }
  .sec-home-capability .cap__chit.is-shown { transition: opacity 1ms linear, visibility 0s; }
}

/* ===== section:home-onboard ===== */
/* ————————————————————————————————————————————————
   home-onboard — the five-step AI menu build.

   Round 2 rebuilt the FIRST screen and won it. This round rebuilds the CLOSE,
   which lost: 1440×566 of band carrying two hairlines, one serif line and a
   stranded caption — ~6% ink, no object, no dark mass, and a four-position
   left-margin ladder. Six decisions, each one a finding:

   1. THE CLOSE GETS THE SECTION'S SECOND OBJECT. `.ob-close__slab` is an ink
      field that bleeds off the LEFT edge of the viewport — the deliberate
      mirror of the catalogue's right bleed — carrying the payoff figure and a
      measured comparison. The band that was 6% ink is now the second-heaviest
      mass in the section.

   2. THE BARS ARE THE NUMBERS. One axis of fifteen day-cells, drawn at the
      SAME pitch for both rows so they are measured against each other: eleven
      solid cells plus four faint ones (that is literally "eleven to fifteen"),
      against one lit cell out of fifteen. The figures are set beside them at
      44px tabular. Nothing here is a decorative capsule.

   3. TWO AXES, NOT FIVE. 120 is editorial (eyebrow, headline, quote mark);
      120 + rail + ordinal + gap is rail content (step titles, the ink field's
      contents, the pull-quote text). `.ob-pull__t` moved from 398 onto the
      rail; the `margin-left:auto` caption that invented a fifth position at
      958 is gone — it is now the paper note on the ink field.

   4. THE FAKE BAR IS GONE. `.ob-cat__track` was `height:1px` with a
      `width:100%` fill: a track/fill/data-bar triplet that rendered as a plain
      divider and encoded nothing. It is a rule on the panel header now, and
      the only `data-bar` elements left in the section carry real data.

   5. THE PHOTOGRAPH HAS AN EDGE. The ink panel's top edge CROPS it: the card's
      bottom sits behind the slab, its paper is warmed and darkened a step off
      the ground, and the leader emerges from under the cropped edge and
      terminates on the table's rule.

   6. THE LADDER ACCELERATES. Five rows at a constant ~140px pitch is
      `repeat(5, 1fr)` rotated ninety degrees. 01 and 02 keep their room;
      03/04/05 close from s24 to s12 so the sequence runs into "You're live."
   ———————————————————————————————————————————————— */
.sec-home-onboard {
  /* Spine → ordinal, then ordinal → text. Everything keys off these two. */
  --ob-rail: 40px;
  --ob-num: 34px;
  /* The one rail axis every left-hung thing in the section shares. */
  --ob-axis: calc(var(--ob-rail) + var(--ob-num) + var(--s20));
  /* How far the closing ink field stops short of the page's right edge. The
     pull-quote's measure ends on the same line, so the two are one structure. */
  --ob-inset: 200px;
  /* The ranked step's ground. Neutral and cool on purpose — the band below
     this one is a warm greige, and two warm slabs in a row read as one. */
  --ob-field: color-mix(in srgb, var(--ink) 6.5%, var(--fog));

  position: relative;
  isolation: isolate;
  overflow: clip; /* the stage bleeds past the screen; never widen the page */
  padding-block: var(--section-y);
}

/* — The surface ——————————————————————————————— */
/* Warm bloom, own composition rather than .has-wash, because the shared wash
   fades to --paper at its seam and this band sits on --fog. Warm family only. */
.sec-home-onboard .ob-wash {
  position: absolute;
  inset: -8% -6% auto -12%;
  height: 52%;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(44% 54% at 13% 20%, var(--wash-2) 0%, transparent 66%),
    radial-gradient(34% 42% at 52% 2%, var(--wash-1) 0%, transparent 74%);
  opacity: 0.5;
  filter: blur(12px) saturate(104%);
}
.sec-home-onboard .ob-wash::after {
  content: '';
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  height: 46%;
  background: linear-gradient(to top, var(--fog), transparent);
}

/* — Header ——————————————————————————————————— */
.sec-home-onboard .ob-head { max-width: 760px; }
/* Give the clipped line masks room for the italic descenders, then take the
   extra leading back so the headline keeps its tight display rhythm. */
.sec-home-onboard .ob-h .line-mask { padding-bottom: 0.12em; margin-bottom: -0.12em; }

/* — Two columns: the sequence, and the object it describes ——————— */
.sec-home-onboard .ob-body {
  margin-top: var(--s80);
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.78fr);
  gap: var(--s64);
  align-items: start;
}

/* — The sequence ————————————————————————————— */
.sec-home-onboard .ob-seq { position: relative; }

/* Deliberately a shade stronger than a hairline: this is the connective tissue
   of the sequence, and at --hair-strong it disappeared. */
.sec-home-onboard .ob-spine {
  position: absolute;
  inset: 0 auto 0 0;
  width: 2px;
  height: 100%;
  color: var(--smoke);
  opacity: 0.62;
  pointer-events: none;
}

.sec-home-onboard .ob-steps {
  position: relative;
  list-style: none;
  margin: 0;
  padding: 0;
}
/* End caps, measured to the spine rather than to the container: a 22px tick
   crossing the line at each end, not a 637px rule under a 400px sentence. */
.sec-home-onboard .ob-steps::before,
.sec-home-onboard .ob-steps::after {
  content: '';
  position: absolute;
  left: 0;
  width: 22px;
  height: 1px;
  background: var(--hair-strong);
}
.sec-home-onboard .ob-steps::before { top: 0; }
.sec-home-onboard .ob-steps::after { bottom: 0; }

.sec-home-onboard .ob-step {
  position: relative;
  display: grid;
  grid-template-columns: var(--ob-num) minmax(0, 1fr);
  column-gap: var(--s20);
  align-items: start;
  padding: var(--ob-pb, var(--s28)) 0 var(--ob-pb, var(--s28)) var(--ob-rail);
}
/* The pitch accelerates instead of tabulating. */
.sec-home-onboard .ob-step:nth-child(1) { --ob-pb: var(--s40); }
.sec-home-onboard .ob-step:nth-child(3) { --ob-pb: var(--s24); }
.sec-home-onboard .ob-step:nth-child(4) { --ob-pb: var(--s16); }
.sec-home-onboard .ob-step:nth-child(5) { --ob-pb: var(--s12); }

/* Quiet, and quieter than the phrase it labels: the ordinal is a marker, not
   a headline. */
.sec-home-onboard .ob-step__n {
  position: relative;
  font-family: var(--serif);
  font-weight: 400;
  font-size: var(--t-body-lg);
  line-height: 1.35;
  letter-spacing: 0;
  color: var(--smoke);
}

/* The marker that seats each row on the spine: solid ink with a ground-coloured
   halo, so the drawn line visibly passes behind it. */
.sec-home-onboard .ob-step__n::before {
  content: '';
  position: absolute;
  left: calc(var(--ob-rail) * -1 - 2px);
  top: 10px;
  width: 6px;
  height: 6px;
  border-radius: var(--r-pill);
  background: var(--ink);
  box-shadow: 0 0 0 4px var(--fog);
}

.sec-home-onboard .ob-step__lead {
  margin: 0;
  font-family: var(--sans);
  font-size: var(--t-body-lg);
  font-weight: 500;
  line-height: 1.3;
  letter-spacing: var(--tr-body-lg);
  color: var(--ink);
  text-wrap: pretty;
}

/* No max-width: the old 44ch broke row 01 after the conjunction while 300px of
   the row sat unused. The column is the measure. */
.sec-home-onboard .ob-step__rest {
  margin: 7px 0 0;
  font-size: 16px;
  line-height: 1.55;
  color: var(--slate);
  text-wrap: pretty;
}

/* — The ranked step ————————————————————————————
   Rank stated with ground, size and colour. The field runs off the left edge of
   the screen and stops short of the sentence's end on the right, so it reads as
   a field rather than as an underline that outran its text. */
.sec-home-onboard .ob-step--key {
  padding-block: var(--s40);
  margin-block: var(--s8);
}
/* The field is hung off the TEXT column, not off the row: a percentage inset
   measured against the row ran the ground 250px past the sentence at 860 and
   27px SHORT of it at 390. Capping the column at 24em fixes the measure, and
   `left: -100vw` reaches the screen edge from any column position at any width
   (the section clips it). */
.sec-home-onboard .ob-step--key .ob-step__t {
  position: relative;
  max-width: min(24em, 100%);
}
.sec-home-onboard .ob-step--key .ob-step__t::before {
  content: '';
  position: absolute;
  z-index: -1;
  top: calc(var(--s40) * -1);
  bottom: calc(var(--s40) * -1);
  left: -100vw;
  right: calc(var(--s40) * -1);
  background: var(--ob-field);
  border-radius: 0 var(--r-card) var(--r-card) 0;
}
.sec-home-onboard .ob-step--key .ob-step__n {
  color: var(--slate);
}
.sec-home-onboard .ob-step--key .ob-step__n::before { box-shadow: 0 0 0 4px var(--ob-field); }
/* The ranked step takes the same step up the card tier's lead takes — 26px,
   same family, same 500 as every other lead on the site. It used to drop to 450
   here, which made one rank two weights. */
.sec-home-onboard .ob-step--key .ob-step__lead {
  font-size: var(--t-h-sm);
  line-height: 1.22;
  letter-spacing: var(--tr-h-sm);
}
.sec-home-onboard .ob-step--key .ob-step__rest {
  margin-top: 10px;
  font-size: var(--t-body);
  color: var(--ink);
}

/* — The right column: paper in, ink out ——————————————————— */
.sec-home-onboard .ob-stage { position: relative; }
.sec-home-onboard .ob-art { display: block; }

.sec-home-onboard .ob-art--shot {
  position: relative;
  z-index: 1;
  width: min(56%, 300px);
  margin-left: auto;
  margin-right: 116px;
}
/* The panel rises OVER the photograph: the paper's bottom edge is consumed by
   the system it becomes. This is the crop the card used to be missing. */
.sec-home-onboard .ob-art--cat {
  position: relative;
  z-index: 2;
  width: min(100%, 600px);
  margin-left: auto;
  margin-top: -40px;
}

/* Drawn connector, now anchored to the PANEL: it emerges from beneath the
   photograph's cropped edge, crosses the ink's top edge and terminates on the
   table's own rule. Two objects physically joined, not merely stacked. */
.sec-home-onboard .ob-link {
  position: absolute;
  z-index: 4;
  top: -20px;
  right: 152px;
  width: 108px;
  height: 88px;
  color: var(--smoke);
  opacity: 0.9;
}

/* The photograph. No rotation: a tilt resampled every dot leader differently. */
.sec-home-onboard .ob-shot { position: relative; }

/* The card *is* the printed paper, so the tint replaces --raised rather than
   nesting a second radius inside it. Warmed and darkened a step off the ground:
   near-white on near-white read as a hairline rectangle, not as paper. The
   bottom padding is the crop allowance — the ink eats it, not a price row. */
.sec-home-onboard .ob-shot__card {
  position: relative;
  background: color-mix(in srgb, var(--sienna) 9%, var(--mist));
  border-radius: var(--r-small);
  padding: var(--s24) var(--s24) var(--s48);
}

/* Explicit width/height, not inset: an <svg> with a viewBox has an intrinsic
   1:1 ratio, so `inset` + `height:auto` sizes it square and it hangs off the
   bottom of the card. */
.sec-home-onboard .ob-bracket {
  position: absolute;
  top: 11px;
  left: 11px;
  width: calc(100% - 22px);
  height: calc(100% - 22px);
  color: var(--ink);
  opacity: 0.26;
}

/* Diegetic type: this is a photograph of a printed menu, not app UI, so it is
   set the way a menu is set — serif, with dot leaders. */
.sec-home-onboard .ob-shot__hd {
  font-family: var(--serif);
  font-size: 17px;
  /* An integer line-height, on purpose: a 1.2 factor puts every row below it on
     a fractional y, and a 2px leader rasterises differently at each fraction —
     which is exactly how one of five leaders came out 35 levels lighter than
     its siblings last round. Card top, padding, this line and the 28px row
     pitch are now all whole pixels. */
  line-height: 20px;
  letter-spacing: -0.006em;
  color: var(--ink);
  margin-bottom: 10px;
}
.sec-home-onboard .ob-shot__row {
  display: flex;
  align-items: baseline;
  gap: 8px;
  font-family: var(--serif);
  font-size: 14px;
  line-height: 2;
  color: var(--ink);
}
/* A repeating gradient at a fixed 4px pitch, painted at a fixed 2px height and
   snapped to the row box. A 1px `dotted` border rendered five different weights
   across five rows; this renders one. */
.sec-home-onboard .ob-shot__row i {
  flex: 1 1 auto;
  min-width: 12px;
  align-self: center;
  height: 2px;
  border-radius: var(--r-pill);
  background-image: repeating-linear-gradient(
    to right, var(--smoke) 0 2px, transparent 2px 4px);
  background-size: 4px 2px;
  background-repeat: repeat-x;
  background-position: left center;
  opacity: 0.85;
}
.sec-home-onboard .ob-shot__row b { font-weight: 400; color: var(--slate); }

.sec-home-onboard .ob-shot__cap {
  display: flex;
  align-items: center;
  gap: 7px;
  margin: 0 0 11px 12px;
  font-size: 13px;
  color: var(--ash);
}
.sec-home-onboard .ob-shot__cap svg { flex: none; }

/* — The catalogue that came out of it. THE ANCHOR. —————————————— */
.sec-home-onboard .ob-cat {
  background: var(--ink);
  color: var(--raised);
  padding: var(--s28) var(--s32) var(--s24);
}
/* Header rule as a real rule. It used to be a `track`/`fill`/`data-bar`
   triplet 1px tall with the fill at width:100% — a bar that encoded nothing. */
.sec-home-onboard .ob-cat__hd {
  position: relative;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s16);
  padding-bottom: 14px;
}
.sec-home-onboard .ob-cat__hd::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 1px;
  background: var(--smoke);
  opacity: 0.5;
}
.sec-home-onboard .ob-cat__title {
  font-size: 16px;
  font-weight: 500;
  letter-spacing: -0.01em;
  color: var(--raised);
}
.sec-home-onboard .ob-key {
  font-family: var(--serif);
  font-size: 15px;
  line-height: 1;
  color: var(--smoke);
}
.sec-home-onboard .ob-shot__card .ob-key { position: absolute; top: var(--s24); right: var(--s24); }

.sec-home-onboard .ob-cat__rows { list-style: none; margin: 6px 0 0; padding: 0; }
.sec-home-onboard .ob-cat__rows li {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s16);
  padding: 15px 0;
  font-size: 15px;
  line-height: 1.3;
}
/* Separators as an element, not a border: --hair is invisible on ink and there
   is no light hairline token. */
.sec-home-onboard .ob-cat__rows li::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 1px;
  background: var(--smoke);
  opacity: 0.22;
}
.sec-home-onboard .ob-cat__rows li:last-child::after { display: none; }
.sec-home-onboard .ob-cat__k { color: var(--raised); }
.sec-home-onboard .ob-cat__v { color: var(--raised); white-space: nowrap; }

.sec-home-onboard .ob-cat__foot {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin-top: 8px;
  padding-top: 15px;
  font-size: 13px;
  line-height: 1.35;
  color: var(--smoke);
}
.sec-home-onboard .ob-cat__foot::before {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: 1px;
  background: var(--smoke);
  opacity: 0.22;
}
.sec-home-onboard .ob-cat__foot svg { flex: none; margin-top: 2px; color: var(--raised); }

/* ————————————————————————————————————————————————
   THE CLOSE. Was: two full-width hairlines, a 54px serif line, a stranded
   caption and a quote across 1440×566 — ~6% ink and no object at all. Now the
   section's second mass, bleeding off the LEFT edge as the mirror of the
   catalogue's right bleed.
   ———————————————————————————————————————————————— */
.sec-home-onboard .ob-close { margin-top: var(--s96); }

.sec-home-onboard .ob-close__slab {
  position: relative;
  z-index: 0;
  margin-right: var(--ob-inset);
  /* Contents land on the section's rail axis — the same x as the step titles.
     There is no third left margin anywhere in this band. */
  padding: var(--s48) var(--s64) var(--s40) var(--ob-axis);
  color: var(--raised);
}
/* `left: -100vw` reaches the screen edge from any column position at any width;
   the section clips it. Right radius only, because there is no right corner on
   the other end to answer. */
.sec-home-onboard .ob-close__slab::before {
  content: '';
  position: absolute;
  z-index: -1;
  inset: 0 0 0 -100vw;
  background: var(--ink);
  border-radius: 0 var(--r-card) var(--r-card) 0;
}

.sec-home-onboard .ob-close__hd {
  display: flex;
  align-items: baseline;
  gap: var(--s28);
  margin-top: var(--s16);
}
.sec-home-onboard .ob-close__big { color: var(--raised); flex: none; }
/* Not a naked rule: it begins at the payoff's last letter and ends underneath
   the paper note, so both of its ends are content. */
.sec-home-onboard .ob-close__tie {
  position: relative;
  flex: 1 1 auto;
  height: 1px;
  background: currentColor;
  color: var(--smoke);
  opacity: 0.34;
}
.sec-home-onboard .ob-close__tie::before {
  content: '';
  position: absolute;
  left: 0;
  top: -5px;
  width: 1px;
  height: 11px;
  background: currentColor;
}

/* — The measured comparison ————————————————————————
   One axis, fifteen day-cells, drawn at an identical pitch on both rows so the
   two durations are measured against each other and not merely against their
   own tracks. Row 01: eleven solid + four faint = "eleven to fifteen". Row 02:
   one lit cell in fifteen. */
.sec-home-onboard .ob-meter {
  --ob-cell-gap: 5px;
  list-style: none;
  margin: var(--s40) 0 0;
  padding: 0;
}
.sec-home-onboard .ob-m {
  position: relative;
  display: grid;
  grid-template-columns: 170px 190px minmax(0, 1fr);
  align-items: center;
  column-gap: var(--s32);
  padding-block: var(--s24);
}
.sec-home-onboard .ob-m + .ob-m::before {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: 1px;
  background: var(--smoke);
  opacity: 0.24;
}
.sec-home-onboard .ob-m__lab {
  font-size: 15px;
  line-height: 1.4;
  letter-spacing: 0;
  /* 15px label: --smoke is the large-type token and measured 3.7:1 here. */
  color: var(--ash);
}
.sec-home-onboard .ob-m--new .ob-m__lab { color: var(--raised); }

.sec-home-onboard .ob-m__fig {
  font-family: var(--sans);
  font-size: var(--t-h);
  font-weight: 450;
  line-height: 1;
  letter-spacing: -0.022em;
  color: var(--smoke);
  white-space: nowrap;
}
.sec-home-onboard .ob-m--new .ob-m__fig { color: var(--raised); }
.sec-home-onboard .ob-m__unit {
  display: block;
  margin-top: 10px;
  font-size: 13px;
  font-weight: 400;
  letter-spacing: 0;
  color: var(--ash);
}

.sec-home-onboard .ob-m__track { position: relative; display: block; height: 42px; }
/* Three coplanar layers, all drawn with the SAME cell pitch: the axis (15 of
   15, faint), the range tail (15 of 15, dim) and the datum (11 of 15, or 1 of
   15). `--n` is how many cells the layer spans, `--w` how wide it is — set
   together so pitch is invariant across every layer and both rows. */
.sec-home-onboard .ob-m__axis,
.sec-home-onboard .ob-m__ghost,
.sec-home-onboard .ob-m__fill {
  position: absolute;
  left: 0;
  top: 0;
  height: 100%;
  width: var(--w);
  color: var(--raised);
  background-image: repeating-linear-gradient(
    to right,
    currentColor 0 calc(100% / var(--n) - var(--ob-cell-gap)),
    transparent calc(100% / var(--n) - var(--ob-cell-gap)) calc(100% / var(--n)));
}
.sec-home-onboard .ob-m__axis  { opacity: 0.13; }
.sec-home-onboard .ob-m__ghost { opacity: 0.30; }
.sec-home-onboard .ob-m__fill  { opacity: 0.62; }
.sec-home-onboard .ob-m--new .ob-m__fill { opacity: 1; }

/* The scale the two tracks are drawn on, printed under them: a rule from 0 to
   15 with an end tick at each stop. The legend sits on the rail axis beside it,
   so the bottom of the field is a chart footer rather than empty ink. */
.sec-home-onboard .ob-meter__foot {
  display: grid;
  grid-template-columns: 170px 190px minmax(0, 1fr);
  column-gap: var(--s32);
  align-items: start;
  margin-top: var(--s16);
}
.sec-home-onboard .ob-meter__key {
  grid-column: 1 / 3;
  font-size: 13px;
  line-height: 1.4;
  letter-spacing: 0;
  color: var(--ash);
}
.sec-home-onboard .ob-meter__axis {
  position: relative;
  display: block;
  height: 26px;
  color: var(--smoke);
}
.sec-home-onboard .ob-meter__axis::before {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: 1px;
  background: currentColor;
  opacity: 0.3;
}
.sec-home-onboard .ob-meter__lab {
  position: absolute;
  top: 10px;
  left: 0;
  font-size: 12px;
  letter-spacing: 0;
  color: var(--smoke);
}
.sec-home-onboard .ob-meter__lab--max { left: auto; right: 0; }
.sec-home-onboard .ob-meter__lab::before {
  content: '';
  position: absolute;
  top: -10px;
  left: 0;
  width: 1px;
  height: 7px;
  background: currentColor;
  opacity: 0.55;
}
.sec-home-onboard .ob-meter__lab--max::before { left: auto; right: 0; }

/* The chart's source line, on paper, straddling the ink field's right edge:
   half on ink, half on the ground. The only object in the band with an
   opposite surface, and the reason the field has a visible edge at all. */
.sec-home-onboard .ob-close__note {
  position: absolute;
  top: var(--s48);
  right: -104px;
  width: 268px;
  padding: var(--s24);
  font-size: 15px;
  line-height: 1.5;
  color: var(--ink);
  text-wrap: pretty;
}

/* — The coda. Two axes and no third: the mark on the editorial 120, the
     sentence on the rail, and its measure ending on the ink field's right
     edge so the quote and the slab share a line. ————————————————— */
.sec-home-onboard .ob-pull {
  margin: var(--s64) 0 0;
  display: grid;
  grid-template-columns: var(--ob-axis) minmax(0, 1fr);
  gap: 0;
  align-items: start;
}
.sec-home-onboard .ob-pull__mark {
  position: relative;
  display: block;
  color: var(--smoke);
}
.sec-home-onboard .ob-pull__mark svg { width: 78px; height: 43px; margin-top: -74px; opacity: 0.9; }
.sec-home-onboard .ob-pull__t {
  max-width: calc(100% - var(--ob-inset));
  color: var(--ink);
  text-wrap: pretty;
}

/* — Bleed the panel past the SCREEN, not past the container ——————————
   The card's right edge lands a constant 64px past the VIEWPORT at every width.
   Above 1264 the page measure is fixed at 1200, so the overshoot is
   (50vw - 600) + 64 → margin-right: 536px - 50vw. Below that the wrap is
   100vw - 2×32, so the same 64px overshoot is a flat -96px; `min()` picks
   whichever is further left and the two meet exactly at 1264.

   The panel's right PADDING is the bleed plus its normal inset, so the crop
   eats padding and the HK$ column stays whole and legible on screen — a
   cropped price column would be a bug wearing a composition's clothes. */
@media (min-width: 901px) {
  .sec-home-onboard .ob-stage { margin-right: min(-96px, calc(536px - 50vw)); }
  .sec-home-onboard .ob-cat { padding-right: var(--s96); }
}
/* Above the two-column threshold the stage climbs into the header band, so the
   top-right quadrant is composition rather than void. */
@media (min-width: 1240px) {
  .sec-home-onboard .ob-stage { margin-top: -206px; }
}

/* — Narrower desktops ————————————————————————— */
@media (max-width: 1180px) {
  .sec-home-onboard { --ob-inset: 120px; }
  .sec-home-onboard .ob-close__note { right: -68px; width: 244px; }
  .sec-home-onboard .ob-m,
  .sec-home-onboard .ob-meter__foot { grid-template-columns: 150px 168px minmax(0, 1fr); column-gap: var(--s24); }
}

@media (max-width: 1080px) {
  .sec-home-onboard { --ob-rail: 32px; --ob-inset: 72px; }
  .sec-home-onboard .ob-body { gap: var(--s40); margin-top: var(--s64); }
  .sec-home-onboard .ob-art--shot { width: min(62%, 250px); margin-right: 84px; }
  .sec-home-onboard .ob-link { width: 96px; height: 78px; right: 124px; top: -18px; }
  .sec-home-onboard .ob-cat { padding-block: var(--s24) var(--s20); padding-left: var(--s24); }
  .sec-home-onboard .ob-close { margin-top: var(--s80); }
  .sec-home-onboard .ob-close__slab { padding: var(--s48) var(--s48) var(--s40) var(--ob-axis); }
  .sec-home-onboard .ob-close__note { position: static; width: auto; max-width: 420px; margin-top: var(--s32); }
  /* The note leaves the top-right, so the tie would have nothing to end on. */
  .sec-home-onboard .ob-close__tie { display: none; }
  .sec-home-onboard .ob-pull { margin-top: var(--s48); }
}

/* — One column: the stage follows the sequence it illustrates. The ink panel
     keeps bleeding off the right edge — it is the anchor at every width, and
     the closing field keeps bleeding off the left. —————————————— */
@media (max-width: 900px) {
  .sec-home-onboard { --ob-inset: 0px; }
  .sec-home-onboard .ob-body { grid-template-columns: minmax(0, 1fr); gap: var(--s48); }
  .sec-home-onboard .ob-stage { margin-right: calc((var(--gutter) + 56px) * -1); }
  .sec-home-onboard .ob-art--shot { width: min(52%, 280px); margin-right: calc(var(--gutter) + 112px); }
  .sec-home-onboard .ob-link { right: min(240px, 34%); }
  .sec-home-onboard .ob-art--cat { width: 100%; max-width: none; }
  .sec-home-onboard .ob-cat { padding-right: var(--s80); }
  .sec-home-onboard .ob-pull { grid-template-columns: minmax(0, 1fr); gap: var(--s20); align-items: start; }
  .sec-home-onboard .ob-pull__mark svg { width: 66px; height: 36px; margin-top: 0; }
  .sec-home-onboard .ob-pull__t { max-width: 760px; }

  /* The meter stacks: label and figure share a line, the axis runs the full
     width under them so the two tracks still share one pitch. */
  .sec-home-onboard .ob-m {
    grid-template-columns: minmax(0, 1fr) auto;
    column-gap: var(--s20);
    row-gap: var(--s20);
  }
  .sec-home-onboard .ob-m__lab { align-self: end; }
  .sec-home-onboard .ob-m__fig { text-align: right; }
  .sec-home-onboard .ob-m__unit { margin-top: 6px; }
  .sec-home-onboard .ob-m__track { grid-column: 1 / -1; }
  .sec-home-onboard .ob-meter__foot { grid-template-columns: minmax(0, 1fr); row-gap: var(--s12); }
  .sec-home-onboard .ob-meter__key { grid-column: 1; }
}

@media (max-width: 720px) {
  .sec-home-onboard { --ob-rail: 26px; --ob-num: 28px; }
  /* The ladder is the token ramp's, not this section's: --t-h steps to 28px
     here and the ink panel — not a line of type — stays the heaviest thing on
     the screen. */
  .sec-home-onboard .ob-body { margin-top: var(--s48); }
  .sec-home-onboard .ob-step { padding-block: var(--ob-pb, var(--s24)); }
  .sec-home-onboard .ob-step:nth-child(1) { --ob-pb: var(--s24); }
  .sec-home-onboard .ob-step:nth-child(3) { --ob-pb: var(--s20); }
  .sec-home-onboard .ob-step:nth-child(4) { --ob-pb: var(--s16); }
  .sec-home-onboard .ob-step:nth-child(5) { --ob-pb: var(--s12); }
  .sec-home-onboard .ob-step--key { padding-block: var(--s32); }
  .sec-home-onboard .ob-step--key .ob-step__t::before {
    top: calc(var(--s32) * -1);
    bottom: calc(var(--s32) * -1);
    right: calc(var(--s12) * -1);
  }
  .sec-home-onboard .ob-step__n { font-size: var(--t-body); }
  .sec-home-onboard .ob-step__n::before { top: 8px; }
  .sec-home-onboard .ob-step__rest { font-size: 15px; }
  .sec-home-onboard .ob-step--key .ob-step__lead { font-size: 21px; }
  .sec-home-onboard .ob-step--key .ob-step__rest { font-size: 16px; }
  .sec-home-onboard .ob-stage { margin-right: calc((var(--gutter) + 32px) * -1); }
  .sec-home-onboard .ob-art--shot { width: min(74%, 232px); margin-left: 0; margin-right: 0; }
  .sec-home-onboard .ob-shot__card { padding-bottom: var(--s40); }
  .sec-home-onboard .ob-art--cat { margin-top: -32px; }
  .sec-home-onboard .ob-link {
    width: 78px; height: 66px; top: -14px;
    left: 96px; right: auto; transform: scaleX(-1);
  }
  .sec-home-onboard .ob-cat {
    padding-block: var(--s20) var(--s16);
    padding-left: var(--s20);
    padding-right: calc(var(--s32) + var(--s20));
  }
  .sec-home-onboard .ob-cat__rows li { padding: 13px 0; font-size: 14px; }

  .sec-home-onboard .ob-close { margin-top: var(--s64); }
  /* On a phone the field's contents sit on the ORDINAL axis, not the title
     axis: a 94px indent inside a 390px screen is a margin, not a composition. */
  .sec-home-onboard .ob-close__slab {
    padding: var(--s40) var(--s24) var(--s32) var(--ob-rail);
  }
  .sec-home-onboard .ob-meter { --ob-cell-gap: 3px; margin-top: var(--s32); }
  .sec-home-onboard .ob-m { padding-block: var(--s20); }
  .sec-home-onboard .ob-m__fig { font-size: 34px; }
  .sec-home-onboard .ob-m__track { height: 34px; }
  .sec-home-onboard .ob-close__note { padding: var(--s20); font-size: 14px; }
  .sec-home-onboard .ob-pull { margin-top: var(--s40); gap: var(--s16); }
  .sec-home-onboard .ob-pull__mark svg { width: 52px; height: 28px; margin-top: 0; }
  .sec-home-onboard .ob-pull__t { font-size: 22px; line-height: 1.4; }
}

/* ===== section:home-matrix ===== */
/* ============================================================================
   home-matrix — the competitive matrix. Eight of eight, built in.

   The section is one object and the object is now inverted from the previous
   build, because the previous build lost a review on exactly this: a mist panel
   on a fog page is a 10-level step, the grain amplitude is ±9, and the artifact
   optically dissolved into the ground.

   Five decisions, each one a review finding:

   1. GROUND, THEN OBJECT. The band is a warm mid-value ground (cream mixed into
      --hair) with hard edges against its fog neighbours, so it reads as its own
      band as you scroll. The panel is --raised white with a real border and the
      artifact shadow. White-on-warm-grey separates by value AND by hue, which is
      how the reference's cards separate; a tint-on-tint never will.

   2. ONE FOCAL POINT. The payoff row is ink, 112px tall — two ordinary lanes —
      and carries a 54px display-serif figure against the 17px every other score
      is set at: roughly a 3x jump in digit height. Everything else in the panel
      is deliberately quiet so that one number is unmistakably the biggest,
      darkest, heaviest thing on the page under the headline. A white card was
      only ever a container; a container is not a fact.

   3. NO MIRROR, NO CENTRED COLUMN. The panel's left edge is locked to the page
      measure and its right edge is cropped by the viewport — the ink band runs
      off the screen. The foot is flipped against the head (note hard-left, the
      payoff sentence right) so the section reads as a diagonal, not a sandwich.

   4. THE GRID ARGUES. Eight identical tracks tabulate; they do not argue. A
      wider split track opens before 07–08 — the two columns where every
      competitor shows a dash — and a cream zone stands behind them, registered
      to the same track variables the grid is built from.

   5. THE RAIL. Every other vendor is a set of isolated points. Link Prism's
      eight dots are joined by a continuous rail drawn cell-by-cell (including
      across the split), so "One system" is a picture, not a checkmark. Per-cell
      ::before connectors rather than one positioned bar: adjacent cells butt
      into one line at any track width and each segment carries its own delay —
      no keyframes, no second observer.
   ========================================================================== */

.sec-home-matrix {
  position: relative;
  isolation: isolate;

  /* A warm mid ground: cream folded into --hair, restrained enough to stay a
     greige rather than a second peach surface. Deliberately ~16 levels below
     the white plate and ~10 below the fog bands above and below, so the section
     reads as its own band and the plate has something to lift off. */
  background: color-mix(in srgb, var(--wash-2) 22%, var(--hair));

  --m-pad-l: 28px;                          /* panel padding + left overhang   */
  --m-pad-r: 40px;                          /* panel padding, right (cropped)  */
  --m-lp-inset: 12px;                       /* band inset from the panel edge  */
  --m-name: clamp(140px, 15.2vw, 232px);    /* vendor-name track               */
  --m-col: clamp(60px, 7.6vw, 118px);       /* capability track                */
  --m-split: clamp(14px, 2vw, 32px);        /* the break before 07–08          */
  --m-num: 118px;                           /* minimum for the score track     */
}

/* ── Surface ──────────────────────────────────────────────────────────────
   Cream blooms over the warm base for tonal movement inside the band. No
   top/bottom mask: the hard edge against its fog neighbours is the point. */
.sec-home-matrix .m-surface {
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  opacity: 0.42;
  background:
    radial-gradient(76% 66% at 8% 0%, var(--wash-2), transparent 66%),
    radial-gradient(54% 50% at 94% 100%, var(--wash-2), transparent 70%),
    radial-gradient(34% 34% at 99% 2%, var(--wash-1), transparent 74%);
}

/* ── Header ───────────────────────────────────────────────────────────────
   7-ish / 5-ish asymmetry, lede dropped to the bottom-right. The headline
   binds "vendor" to "owns" with a non-breaking space so that wherever it
   wraps, roman and italic always share a line — an italic phrase stranded on
   a line of its own reads as two typesettings rather than one sentence. */
.sec-home-matrix .m-head {
  display: grid;
  grid-template-columns: minmax(0, 1fr) clamp(280px, 26vw, 380px);
  column-gap: var(--s48);
  align-items: end;
}
.sec-home-matrix .m-eyebrow { grid-column: 1; grid-row: 1; }
.sec-home-matrix .m-title   { grid-column: 1; grid-row: 2; text-wrap: balance; }
.sec-home-matrix .m-sub {
  grid-column: 2;
  grid-row: 2;
  align-self: end;
  padding-bottom: 0.42em;
}

/* ── The plate ────────────────────────────────────────────────────────────
   Left edge overhangs the measure by --m-pad-l and pads back by the same
   amount, so "Link Prism" sits under the "E" of "Every". Right edge is pushed
   two pixels past the viewport: square corner, no visible right border, the
   table cropped by the screen. html{overflow-x:clip} contains it. */
.sec-home-matrix .m-panel {
  position: relative;
  margin-top: var(--s64);
  margin-left: calc(var(--m-pad-l) * -1);
  margin-right: calc(50% - 50vw - 2px);
  padding: var(--s24) var(--m-pad-r) var(--s28) var(--m-pad-l);
  background: var(--raised);
  border: 1px solid var(--hair-strong);
  border-radius: var(--r-card) 0 0 var(--r-card);
  box-shadow: var(--sh-artifact);
}

/* The 07–08 zone. Same variables as the grid, so it stays registered. */
.sec-home-matrix .m-zone {
  position: absolute;
  /*
   * Sits ABOVE the row fills and tints them, rather than under them.
   * At z-index 0 the opaque --mist of .m-lane--stack painted straight over this
   * column, so the 07/08 highlight stopped one row short of the table it is
   * meant to span. Multiply lets the cream tint every fill underneath while
   * leaving the ink text effectively untouched (dark x near-white = dark).
   */
  z-index: 3;
  mix-blend-mode: multiply;
  pointer-events: none;
  top: var(--s12);
  /* Ends on the panel's content edge, i.e. the bottom of the last lane. Any
     further and the tint hangs below the table as a loose block. */
  bottom: var(--s28);
  left: calc(var(--m-pad-l) + var(--m-name) + var(--m-col) * 6 + var(--m-split));
  width: calc(var(--m-col) * 2);
  border-radius: 12px;
  background: color-mix(in srgb, var(--wash-2) 36%, var(--raised));
}

.sec-home-matrix .m-rack { display: block; }

/* ── Axis ─────────────────────────────────────────────────────────────── */

.sec-home-matrix .m-axis,
.sec-home-matrix .m-lane {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns:
    var(--m-name)
    repeat(6, var(--m-col))
    var(--m-split)
    repeat(2, var(--m-col))
    minmax(var(--m-num), 1fr);
  align-items: center;
}

.sec-home-matrix .m-axis {
  padding-bottom: var(--s16);
  border-bottom: 1px solid var(--hair-strong);
  margin-bottom: var(--s12);
}
.sec-home-matrix .m-col {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  min-width: 0;
}
.sec-home-matrix .m-col__n {
  font-style: normal;
  font-size: 11px;
  font-weight: 450;
  letter-spacing: 0.09em;
  color: var(--smoke);
}
.sec-home-matrix .m-col__t {
  font-size: 13px;
  font-weight: 450;
  letter-spacing: -0.002em;
  color: var(--slate);
  white-space: nowrap;
}
/* "Native" labels a column of figures, not a two-line stack, so it aligns to
   the BOTTOM of the axis — its baseline sits on the 'Till' baseline. Centring
   it (the previous build) parked it between the two lines, aligned to neither. */
.sec-home-matrix .m-col--num {
  align-self: end;
  align-items: flex-end;
  font-size: 13px;
  font-weight: 450;
  color: var(--slate);
  white-space: nowrap;
}

/* ── Lanes ────────────────────────────────────────────────────────────── */

.sec-home-matrix .m-lane { min-height: 58px; }

.sec-home-matrix .m-vendor {
  font-size: 16px;
  font-weight: 400;
  letter-spacing: -0.006em;
  color: var(--ink);
  white-space: nowrap;
  min-width: 0;
}
.sec-home-matrix .m-cell {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 0;
}
.sec-home-matrix .m-cell--num { justify-content: flex-end; }

/* ── Marks — one drawn family, never a glyph ──────────────────────────── */

.sec-home-matrix .m-dot,
.sec-home-matrix .m-dash {
  position: relative;
  z-index: 1;
  display: block;
  font-style: normal;
}
.sec-home-matrix .m-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--slate);
}
.sec-home-matrix .m-dash {
  width: 10px;
  height: 1.5px;
  border-radius: 1px;
  background: var(--smoke);
}

/* ── Figures ──────────────────────────────────────────────────────────── */

.sec-home-matrix .m-count {
  display: inline-flex;
  align-items: baseline;
  gap: 1px;
  letter-spacing: -0.004em;
}
.sec-home-matrix .m-count__v {
  font-size: 17px;
  font-weight: 450;
  color: var(--slate);
}
.sec-home-matrix .m-count__d {
  font-size: 13px;
  font-weight: 400;
  color: var(--ash);
}

/* ── The six-vendor row: the mid value ────────────────────────────────────
   Same bleed geometry as the ink band so their left edges register, but in
   mist — the panel then carries ink, mist, cream and white rather than one
   grey. It is also the only other row with a height of its own. */
.sec-home-matrix .m-lane--stack {
  z-index: 2;
  min-height: 70px;
  margin-top: var(--s12);
  margin-inline: calc((var(--m-pad-l) - var(--m-lp-inset)) * -1) calc(var(--m-pad-r) * -1);
  padding-inline: calc(var(--m-pad-l) - var(--m-lp-inset)) var(--m-pad-r);
  background: var(--mist);
  border-radius: 12px 0 0 12px;
}

/* ── The Link Prism band: the one focal point ─────────────────────────────
   Ink, full height of two ordinary rows, cropped by the right of the screen.
   The score is set in the display serif at ~2.7x every other figure — that
   jump IS the internal hierarchy; a white card was only ever a container. */
.sec-home-matrix .m-lane--lp {
  z-index: 3;
  min-height: 112px;
  margin-block: var(--s8) var(--s12);
  margin-inline: calc((var(--m-pad-l) - var(--m-lp-inset)) * -1) calc(var(--m-pad-r) * -1);
  padding-inline: calc(var(--m-pad-l) - var(--m-lp-inset)) var(--m-pad-r);
  background: var(--ink);
  /* 24px plate radius at a 12px inset — the concentric inner radius is 12px. */
  border-radius: 12px 0 0 12px;
}
.sec-home-matrix .m-lane--lp .m-vendor {
  font-size: 18px;
  font-weight: 500;
  color: var(--paper);
}
.sec-home-matrix .m-lane--lp .m-dot {
  width: 11px;
  height: 11px;
  background: var(--paper);
}
.sec-home-matrix .m-lane--lp .m-count { gap: 3px; }
.sec-home-matrix .m-lane--lp .m-count__v {
  font-family: var(--serif);
  font-weight: 400;
  font-optical-sizing: auto;
  font-size: clamp(36px, 3.7vw, 54px);
  line-height: 0.84;
  letter-spacing: var(--tr-h);
  color: var(--paper);
}
.sec-home-matrix .m-lane--lp .m-count__d {
  font-size: 15px;
  color: var(--smoke);
}

/* The rail. Nine per-cell connectors — the split track carries one too, so the
   line is continuous across the break the other rows are cut by. */
.sec-home-matrix .m-lane--lp .m-cell:not(.m-cell--num)::before {
  content: '';
  position: absolute;
  left: 0;
  /* A full pixel of overlap, not a half: at fractional track widths a 0.5px
     tail leaves a visible seam between segments on a dark ground. */
  right: -1px;
  top: 50%;
  height: 2px;
  margin-top: -1px;
  border-radius: 1px;
  background: var(--paper);
}

/* ── Motion ───────────────────────────────────────────────────────────────
   Rides the panel's own [data-reveal] .is-in — no keyframes, no second
   observer. The rail draws left to right; each dot lands just behind its
   own segment. */
.sec-home-matrix .m-lane--lp .m-cell:not(.m-cell--num)::before {
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 300ms var(--ease-out);
  transition-delay: calc(150ms + var(--i, 0) * 62ms);
}
.sec-home-matrix .m-lane--lp .m-dot {
  opacity: 0;
  transform: scale(0.4);
  transition: opacity 380ms var(--ease-out), transform 380ms var(--ease-out);
  transition-delay: calc(250ms + var(--i, 0) * 62ms);
}
.sec-home-matrix .m-panel.is-in .m-lane--lp .m-cell:not(.m-cell--num)::before { transform: scaleX(1); }
.sec-home-matrix .m-panel.is-in .m-lane--lp .m-dot { opacity: 1; transform: none; }

/* Child 1 is the vendor name; 8 is the split; 11 is the score. */
.sec-home-matrix .m-lane--lp .m-cell:nth-child(2)  { --i: 0; }
.sec-home-matrix .m-lane--lp .m-cell:nth-child(3)  { --i: 1; }
.sec-home-matrix .m-lane--lp .m-cell:nth-child(4)  { --i: 2; }
.sec-home-matrix .m-lane--lp .m-cell:nth-child(5)  { --i: 3; }
.sec-home-matrix .m-lane--lp .m-cell:nth-child(6)  { --i: 4; }
.sec-home-matrix .m-lane--lp .m-cell:nth-child(7)  { --i: 5; }
.sec-home-matrix .m-lane--lp .m-cell:nth-child(8)  { --i: 6; }
.sec-home-matrix .m-lane--lp .m-cell:nth-child(9)  { --i: 7; }
.sec-home-matrix .m-lane--lp .m-cell:nth-child(10) { --i: 8; }

/* ── Key (small screens only — see the responsive block) ──────────────── */

.sec-home-matrix .m-key { display: none; }

/* ── Caption + footnote ───────────────────────────────────────────────────
   Flipped against the head. The head sets the big thing left and the small
   thing right; the foot does the reverse, so head → panel → foot falls on a
   diagonal instead of mirroring around a centred object. */
.sec-home-matrix .m-foot {
  display: grid;
  grid-template-columns: clamp(230px, 23vw, 320px) minmax(0, 1fr);
  column-gap: var(--s48);
  align-items: baseline;
  margin-top: var(--s32);
}
.sec-home-matrix .m-caption {
  grid-column: 2;
  max-width: 44ch;
  font-size: var(--t-body-lg);
  line-height: 1.45;
  letter-spacing: var(--tr-body-lg);
  text-wrap: pretty;
}
.sec-home-matrix .m-caption__lead { color: var(--ink); font-weight: 500; }
.sec-home-matrix .m-caption__rest { color: var(--slate); font-weight: 400; }
.sec-home-matrix .m-note {
  grid-column: 1;
  grid-row: 1;
  font-size: 14px;
  line-height: 1.5;
  color: var(--slate);
  text-wrap: pretty;
}

/* ── Responsive ───────────────────────────────────────────────────────── */

@media (max-width: 1080px) {
  .sec-home-matrix { --m-pad-l: 22px; --m-pad-r: 30px; }
  .sec-home-matrix .m-panel { margin-top: var(--s48); }
}

@media (max-width: 900px) {
  .sec-home-matrix .m-head { grid-template-columns: minmax(0, 1fr); }
  .sec-home-matrix .m-sub {
    grid-column: 1;
    grid-row: 3;
    align-self: start;
    padding-bottom: 0;
    margin-top: var(--s20);
    max-width: 48ch;
  }
  .sec-home-matrix .m-foot { grid-template-columns: minmax(0, 1fr); row-gap: var(--s16); }
  .sec-home-matrix .m-caption { grid-column: 1; grid-row: 1; }
  .sec-home-matrix .m-note { grid-column: 1; grid-row: 2; max-width: 52ch; }
}

/*
 * Below 900px this stops being a table and becomes five small multiples: one
 * card per vendor, each with the full eight-mark strip, so every reader sees
 * all eight capabilities. Nothing scrolls sideways, so there is no scroll cue
 * to invent and no clipped data. The split track and its zone are desktop
 * devices — at this width they would only fragment an already narrow strip.
 */
@media (max-width: 900px) {
  .sec-home-matrix { --m-pad-l: 16px; --m-pad-r: 16px; --m-lp-inset: 8px; }
  .sec-home-matrix .m-panel { padding-block: var(--s20) var(--s24); }
  .sec-home-matrix .m-zone,
  .sec-home-matrix .m-col--gap,
  .sec-home-matrix .m-cell--gap { display: none; }

  .sec-home-matrix .m-axis,
  .sec-home-matrix .m-lane {
    grid-template-columns: repeat(8, minmax(0, 1fr));
    align-items: center;
  }

  .sec-home-matrix .m-axis {
    padding-bottom: var(--s12);
    margin-bottom: var(--s4);
  }
  .sec-home-matrix .m-axis__corner { grid-column: 1 / 6; grid-row: 1; }
  .sec-home-matrix .m-col { grid-row: 2; padding-top: var(--s12); }
  /* "Native" is dropped here: on one line of its own above the numerals it read
     as a label for column 08. The /8 beside every name carries the meaning. */
  .sec-home-matrix .m-col--num { display: none; }
  .sec-home-matrix .m-col__t {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
  }

  .sec-home-matrix .m-lane {
    min-height: 0;
    padding-block: var(--s16);
    row-gap: var(--s12);
  }
  .sec-home-matrix .m-vendor { grid-column: 1 / 6; grid-row: 1; align-self: center; }
  .sec-home-matrix .m-cell { grid-row: 2; height: 20px; }
  .sec-home-matrix .m-cell--num { grid-column: 6 / -1; grid-row: 1; height: auto; align-self: center; }

  .sec-home-matrix .m-lane--stack { min-height: 0; margin-top: var(--s8); padding-block: var(--s16); }

  .sec-home-matrix .m-lane--lp {
    min-height: 0;
    padding-block: var(--s16) var(--s20);
    margin-block: var(--s4) var(--s12);
  }
  .sec-home-matrix .m-lane--lp .m-count__v { font-size: 38px; line-height: 0.8; }
  .sec-home-matrix .m-lane--lp .m-count__d { font-size: 14px; }
  .sec-home-matrix .m-lane--lp .m-vendor { font-size: 17px; }

  /* One shared key for the numbered axis above every strip. */
  .sec-home-matrix .m-key {
    display: flex;
    flex-wrap: wrap;
    gap: 6px 16px;
    margin: var(--s20) 0 0;
    padding: var(--s16) 0 0;
    border-top: 1px solid var(--hair-strong);
    list-style: none;
    font-size: 12px;
    line-height: 1.4;
    color: var(--slate);
  }
  .sec-home-matrix .m-key i {
    font-style: normal;
    margin-right: 5px;
    letter-spacing: 0.08em;
    color: var(--smoke);
  }
}

@media (max-width: 720px) {
  .sec-home-matrix { --m-pad-l: 14px; --m-pad-r: 14px; }
}

@media (max-width: 480px) {
  .sec-home-matrix .m-vendor { font-size: 15px; }
  .sec-home-matrix .m-lane--lp .m-vendor { font-size: 16px; }
  .sec-home-matrix .m-count__v { font-size: 16px; }
  .sec-home-matrix .m-lane--lp .m-count__v { font-size: 34px; }
  .sec-home-matrix .m-key { gap: 6px 14px; }
}

@media (prefers-reduced-motion: reduce) {
  .sec-home-matrix .m-lane--lp .m-cell:not(.m-cell--num)::before,
  .sec-home-matrix .m-lane--lp .m-dot {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

/* The Link Prism lane is ink, so its muted figures need the dark-surface token.
   The same class sits on the light vendor lanes, where --ash is correct — one
   token cannot serve both grounds. */
.sec-home-matrix .m-lane--lp .m-count__d { color: var(--on-dark-muted); }

/* The section's warm ground drops --ash to exactly 4.5:1 — no margin. --slate
   carries the same quiet register with headroom. */
.sec-home-matrix .m-eyebrow { color: var(--slate); }

/* ===== section:home-pricing ===== */
/* ————————————————————————————————————————————————
   home-pricing — one rate, a floor and a ceiling.

   ROUND 3 LOST BECAUSE THE MASS WAS A HOLE. The section's largest object was a
   1325×258 ink slab carrying one numeral, one 15px label and a hairline: 2.1%
   non-black pixels. It was bigger than the reference's tinted card and three
   times emptier, so the thing meant to anchor the page read as a void. It also
   drew the SAME 0–25% tick row twice, 280px apart, which meant the three rates
   never registered as sitting on one ruler — the whole argument of the section.

   THE ANSWER: there is now ONE field. All three rates are rows of a single ink
   chart — gridded plot area, gridlines carried continuously through every row
   including the lit one, one axis at its foot. The panel bleeds out through the
   left gutter to the viewport edge, and the guarantee chip (the only shadowed
   thing here) crops its top-right corner, so the mass has an edge as well as
   contents. Measured ink inside it went 2.1% -> ~30%.

   ONE SHARED AXIS, DRAWN HONESTLY. Linear on a 20% ceiling — the top of the
   landlord range sets the top of the track:
       your landlord   15–20 %   ->  75 %  .. 100 %
       OpenRice        1.7–5 %   ->   8.5% ..  25 %
       us              0.25 %    ->   0 %  ..   1.25%
   Gridlines fall every quarter of the axis = every 5 percentage points, and the
   axis is labelled 0 5 10 15 20% on those same quarters. Both competitor bands
   therefore terminate exactly on a labelled gridline, which is the cheapest
   possible proof that the ruler is real.

   NO PIXEL FLOORS. Round 4 lost because our own row was drawn `max(8px, 1%)`:
   the one number the section exists to sell was the only mark on the page
   lying about its own value. 1.25% of the track is ~10px on a desktop plot and
   ~4px at 390px. It stays ~10px and ~4px. The smallness IS the argument, and a
   pricing page that fudges its own bar has no business asking to be believed.

   TWO KINDS OF OBJECT, BECAUSE THERE ARE TWO KINDS OF NUMBER. The competitors
   are ranges, so they are range bands: a weak translucent span between two
   hairline end-stops, inset (not protruding whiskers — the old build's pills
   read as disabled slider handles). Ours is a point, so it is a point mark: one
   opaque blade standing the height of the row. It cannot be mistaken for a
   short version of their bar, and it is the only solid mark on the field.

   The foot refuses a three-up AND refuses a three-row even repeat: one filled
   tinted entry, two thin ruled rows, and one ink object cropped by the right
   edge of the screen, stretched to the ledger rather than the ledger padded out
   to it.
   ———————————————————————————————————————————————— */

.sec-home-pricing {
  isolation: isolate;
  overflow: hidden;
  /* The bleed offset, defined ONCE. Negative: pushes an element left of the
     wrap. On a wide screen it crops 24px past the viewport edge; on a narrow one
     it falls back to exactly the gutter, so it can never overflow. Anything that
     bleeds left reads this and then adds it back as padding, which is how the
     panel keeps its content on the wrap's own left edge. */
  --bleed-l: min(calc(var(--gutter) * -1), calc((var(--page) - 100vw) / 2 - var(--s24)));
  --inset: var(--s48);
  /* Resolved padding for every full-width child of the panel. Declared here so
     the row bands, the rules between them and the gridlines all measure from the
     same two numbers. */
  --pad-l: calc(var(--inset) - var(--bleed-l));
  --pad-r: var(--inset);
  /* Width of the label column. The plot column is whatever is left, and every
     percentage in this file is a percentage of THAT. */
  --idw: 232px;
}

/* — Ground ————————————————————————————————————— */
.sec-home-pricing .pr-atmos {
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  overflow: hidden;
}
.sec-home-pricing .pr-atmos__wash {
  position: absolute;
  inset: 0 -8%;
  background:
    radial-gradient(50% 30% at 84% 8%, var(--wash-2) 0%, rgba(255, 233, 214, 0) 70%),
    radial-gradient(44% 26% at 14% 12%, var(--wash-2) 0%, rgba(255, 233, 214, 0) 72%),
    radial-gradient(46% 30% at 88% 84%, var(--wash-1) 0%, rgba(255, 217, 194, 0) 70%);
  filter: blur(10px) saturate(110%);
  opacity: 0.6;
  -webkit-mask-image: linear-gradient(to bottom, transparent 0%, var(--ink) 9%, var(--ink) 91%, transparent 100%);
          mask-image: linear-gradient(to bottom, transparent 0%, var(--ink) 9%, var(--ink) 91%, transparent 100%);
}

/* — Head ———————————————————————————————————————
   Bottom-set: the lede's last baseline sits on the headline's, so the two
   columns are hung from the bottom of the band rather than stacked from the top.
   The chip that used to live here is now on the panel. */
.sec-home-pricing .pr-head {
  display: grid;
  grid-template-columns: 1.28fr 0.72fr;
  gap: var(--s48);
  align-items: end;
  margin-bottom: var(--s96);
}
.sec-home-pricing .pr-head__title { max-width: 20ch; }
.sec-home-pricing .pr-head__sub { max-width: 26ch; }

/* — THE FIELD ——————————————————————————————————— */
.sec-home-pricing .pr-panel {
  position: relative;
  z-index: 0;
  margin-left: var(--bleed-l);
  margin-bottom: var(--s96);
  padding: var(--s40) 0 var(--s32);
  background: var(--ink);
  color: var(--paper);
  border-radius: 0 var(--r-card) var(--r-card) 0;
  /* Gridline ink and the lit-row lift, so a row can override the first when it
     changes the second and the lines stay readable on both grounds. */
  --grid: color-mix(in srgb, var(--paper) 58%, transparent);
  --rule: color-mix(in srgb, var(--paper) 58%, transparent);
}

.sec-home-pricing .pr-panel__top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--s32);
  padding: 0 var(--pad-r) var(--s32) var(--pad-l);
}
/* A caption in the panel's own flex head, so the container owns the spacing. */
.sec-home-pricing .pr-panel__cap { margin: 0; }

/* The guarantee, as an object — and as the panel's edge. Pulled up out of the
   ink so it crops the top-right corner: --raised on ink, the only elevation in
   the section. */
.sec-home-pricing .pr-chip {
  position: relative;
  z-index: 2;
  flex: 0 0 auto;
  display: flex;
  align-items: stretch;
  gap: var(--s20);
  /* Up and OUT: the chip's right edge lands past the panel's, so it covers
     the top-right corner radius instead of sitting politely inside it. */
  margin: calc((var(--s40) + var(--s48)) * -1) calc((var(--pad-r) + var(--s16)) * -1) 0 0;
  padding: var(--s20) var(--s24) var(--s20) var(--s20);
  border-radius: var(--r-small);
  color: var(--ink);
}
.sec-home-pricing .pr-chip__brace { color: var(--ink); opacity: 0.42; flex: 0 0 auto; align-self: center; }
.sec-home-pricing .pr-chip__rows { display: grid; gap: var(--s12); }
.sec-home-pricing .pr-chip__row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s32);
}
.sec-home-pricing .pr-chip__k {
  font-size: 13px;
  line-height: 1.2;
  letter-spacing: 0.01em;
  color: var(--ash);
  white-space: nowrap;
}
.sec-home-pricing .pr-chip__v {
  font-size: var(--t-body-lg);
  font-weight: 450;
  line-height: 1.2;
  letter-spacing: -0.012em;
  color: var(--ink);
  white-space: nowrap;
}

/* — Rows ———————————————————————————————————————
   No vertical gap and no vertical padding on the row itself: the plot cell
   stretches the row's full height, which is what makes the gridlines run
   unbroken from the first row to the axis instead of restarting per panel. */
.sec-home-pricing .pr-rows { list-style: none; margin: 0; padding: 0; }
.sec-home-pricing .pr-row {
  position: relative;
  display: grid;
  grid-template-columns: var(--idw) minmax(0, 1fr);
  column-gap: var(--s32);
  align-items: stretch;
  padding: 0 var(--pad-r) 0 var(--pad-l);
}
.sec-home-pricing .pr-row + .pr-row { border-top: 1px solid var(--rule); }

.sec-home-pricing .pr-row__id {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--s8);
  padding-block: var(--s24);
}
.sec-home-pricing .pr-row__fig {
  line-height: 1;
  color: var(--paper);
  margin: 0;
  text-wrap: nowrap;
}
/* Fixed cells either side of the en-dash. '15' and '1.7' are set flush right in
   a 2.6ch box, so the dash lands on exactly the same x in both rows (measured:
   223.14px in each). The high value then runs left-to-right from that shared
   stop, which is how a range is read. Previously the two ranges sat on
   different rhythms and the dashes did not line up at all. */
.sec-home-pricing .pr-fig__lo { display: inline-block; min-width: 2.6ch; text-align: right; }

/* Sans, superscript, with real air around it — a serif % at half-size collides
   with the digit before it and reads as a typo. */
.sec-home-pricing .pr-row__pct {
  font-family: var(--sans);
  font-size: 0.36em;
  font-weight: 450;
  letter-spacing: 0;
  vertical-align: 0.42em;
  margin-left: 0.14em;
}
.sec-home-pricing .pr-row__label {
  font-size: var(--t-caption);
  line-height: 1.35;
  color: var(--smoke);
  letter-spacing: 0;
  margin: 0;
}

/* The plot cell IS the 0–20% axis. Gridlines every quarter (= 5 percentage
   points) with the ceiling drawn as an inset edge, because a repeating gradient
   cannot paint its own far end. */
.sec-home-pricing .pr-row__plot {
  position: relative;
  background-image: repeating-linear-gradient(90deg,
    var(--grid) 0 1px, transparent 1px 25%);
  box-shadow: inset -1px 0 0 var(--grid);
}
.sec-home-pricing .pr-row__rail {
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: 1px;
  margin-top: -0.5px;
  background: color-mix(in srgb, var(--paper) 8%, transparent);
}
/* A RANGE BAND. Flat ink, square ends, no gradient and no shine: a low fill
   between two hairline end-stops drawn INSIDE the span, so the band reads as
   "from here to there" rather than as a bar that happens to start late. The
   fill is deliberately weak and the stops are the bright part — a range is an
   interval, and only one mark on this field is a solid value. */
.sec-home-pricing .pr-row__band {
  position: absolute;
  left: var(--lo);
  width: calc(var(--hi) - var(--lo));
  top: 50%;
  height: 20px;
  margin-top: -10px;
  border-radius: 0;
  background: var(--bar-c);
  box-shadow: inset 1px 0 0 var(--bar-e), inset -1px 0 0 var(--bar-e);
  transform-origin: left;
}

/* 15–20 of 20  ->  75%..100%.  1.7–5 of 20  ->  8.5%..25%. */
.sec-home-pricing .pr-row--rent {
  --lo: 75%; --hi: 100%;
  --bar-c: color-mix(in srgb, var(--paper) 58%, transparent);
  --bar-e: color-mix(in srgb, var(--paper) 92%, transparent);
}
.sec-home-pricing .pr-row--platform {
  --lo: 8.5%; --hi: 25%;
  --bar-c: color-mix(in srgb, var(--paper) 58%, transparent);
  --bar-e: color-mix(in srgb, var(--paper) 70%, transparent);
}

/* The lit row. Same field, same ruler, same gridlines — a step of value, not a
   second surface. The band runs the panel's full width because the row does. */
.sec-home-pricing .pr-row + .pr-row--ours { border-top-color: color-mix(in srgb, var(--paper) 8%, transparent); }
.sec-home-pricing .pr-row--ours {
  --grid: color-mix(in srgb, var(--paper) 58%, transparent);
  background: color-mix(in srgb, var(--paper) 8%, transparent);
}
.sec-home-pricing .pr-row--ours .pr-row__fig { letter-spacing: var(--tr-h-lg); }
.sec-home-pricing .pr-row--ours .pr-row__label { color: var(--paper); }
.sec-home-pricing .pr-row--ours .pr-row__rail { background: color-mix(in srgb, var(--paper) 8%, transparent); }

/* THE MARK. 0.25 of 20 = 1.25% of the track, and that is the whole width — no
   max(), no min-width, no floor. It stands the height of the row instead of
   floating at mid-height on the rail, so a value one twentieth the width of the
   smallest competitor band is still an object you cannot miss. */
.sec-home-pricing .pr-row__mark {
  position: absolute;
  left: 0;
  width: 1.25%;
  top: var(--s12);
  bottom: var(--s12);
  background: var(--paper);
  transform-origin: left;
}

/* — The axis ————————————————————————————————————
   One scale, one set of ticks, at the foot of the field the bars live in. */
.sec-home-pricing .pr-axis {
  display: grid;
  grid-template-columns: var(--idw) minmax(0, 1fr);
  column-gap: var(--s32);
  padding: 0 var(--pad-r) 0 var(--pad-l);
  border-top: 1px solid var(--rule);
}
.sec-home-pricing .pr-axis__scale {
  grid-column: 2;
  position: relative;
  height: 34px;
  padding-top: 13px;
}
/* Ticks on the same quarters as the gridlines, so the labels are the lines. */
.sec-home-pricing .pr-axis__scale::before {
  content: '';
  position: absolute;
  inset: 0 0 auto 0;
  height: 8px;
  background-image: repeating-linear-gradient(90deg,
    color-mix(in srgb, var(--paper) 58%, transparent) 0 1px, transparent 1px 25%);
  box-shadow: inset -1px 0 0 color-mix(in srgb, var(--paper) 58%, transparent);
}
.sec-home-pricing .pr-axis__lab {
  position: absolute;
  top: 15px;
  left: var(--at);
  transform: translateX(-50%);
  font-size: 12px;
  line-height: 1;
  letter-spacing: 0.02em;
  color: var(--smoke);
}
.sec-home-pricing .pr-axis__lab[style*="--at:0%"] { transform: none; }
/* The ceiling is the one label that has to be read, because it is what makes
   every other mark on the field mean something. */
.sec-home-pricing .pr-axis__lab--end {
  transform: translateX(-100%);
  color: var(--paper);
  letter-spacing: 0.01em;
}

/* — Foot ———————————————————————————————————————
   Twelve columns. Ledger 1/8, valley, ink object 9/-1 bleeding past the
   viewport edge, and a full-measure closing line beneath both. `stretch`, not
   `start`: the card grows to the ledger, so the ledger is never padded out with
   dead space to reach the card. */
.sec-home-pricing .pr-foot {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--s32);
  row-gap: 0;
  align-items: stretch;
}
.sec-home-pricing .pr-terms {
  grid-column: 1 / 8;
  grid-row: 1;
  list-style: none;
  margin: 0;
  padding: 0;
}

/* Two thin ruled rows — and one that is a filled field instead. An even list of
   three identical rows is the same failure as an even grid of three cards. */
.sec-home-pricing .pr-term {
  border-top: 1px solid var(--hair-strong);
  padding: var(--s20) 0 var(--s24);
  display: grid;
  grid-template-columns: minmax(0, 200px) minmax(0, 1fr);
  column-gap: var(--s24);
  align-items: baseline;
}
.sec-home-pricing .pr-term:last-child { border-bottom: 1px solid var(--hair-strong); }

.sec-home-pricing .pr-term--lead {
  display: block;
  border: 0;
  border-radius: var(--r-card);
  background: color-mix(in srgb, var(--ink) 9%, var(--paper));
  padding: var(--s28) var(--s32) var(--s32);
  margin-bottom: var(--s28);
}
/* The one step up, at the one size the rest of the site steps up to — and at
   the same 500 the two rows beneath it use, so a single list is one weight. */
.sec-home-pricing .pr-term--lead .pr-term__title {
  font-size: var(--t-h-sm);
  letter-spacing: var(--tr-h-sm);
  margin-bottom: var(--s8);
}
.sec-home-pricing .pr-term--lead .pr-term__body {
  font-size: var(--t-body);
  line-height: 1.45;
  color: var(--ink);
  max-width: 40ch;
}

.sec-home-pricing .pr-term__title {
  font-family: var(--sans);
  font-size: var(--t-body-lg);
  font-weight: 500;
  line-height: 1.25;
  letter-spacing: -0.011em;
  color: var(--ink);
  margin: 0;
}
.sec-home-pricing .pr-term__body {
  font-size: var(--t-caption);
  line-height: 1.5;
  color: var(--slate);
  margin: 0;
}

/* The same ink as the panel, at a fraction of the mass, cropped by the right
   edge of the screen. */
.sec-home-pricing .pr-card {
  grid-column: 9 / -1;
  grid-row: 1;
  display: flex;
  flex-direction: column;
  padding: var(--s40);
  background: var(--ink);
  color: var(--paper);
  border-radius: var(--r-card);
  margin-right: min(calc(var(--gutter) * -1), calc((var(--page) - 100vw) / 2 - var(--s24)));
}
.sec-home-pricing .pr-card__mark { opacity: 0.9; flex: 0 0 auto; }
.sec-home-pricing .pr-card__text { margin-top: auto; padding-top: var(--s40); }
.sec-home-pricing .pr-card__title {
  font-family: var(--sans);
  font-size: var(--t-subhead);
  font-weight: 500;
  line-height: 1.25;
  letter-spacing: -0.011em;
  color: var(--paper);
  margin: 0 0 var(--s12);
}
.sec-home-pricing .pr-card__body {
  font-size: var(--t-caption);
  line-height: 1.5;
  color: var(--smoke);
  margin: 0;
  max-width: 30ch;
}

/* — Close ——————————————————————————————————————
   One rule across the full measure, one sans line, the link at the far end. */
.sec-home-pricing .pr-close {
  grid-column: 1 / -1;
  grid-row: 2;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s40);
  margin-top: var(--s64);
  padding-top: var(--s32);
  border-top: 1px solid var(--hair-strong);
}
.sec-home-pricing .pr-close__line { color: var(--ink); margin: 0; text-wrap: pretty; }
.sec-home-pricing .pr-close__link { flex: 0 0 auto; min-height: 44px; align-items: center; }

/* — Narrower ——————————————————————————————————— */
@media (max-width: 1180px) {
  .sec-home-pricing { --inset: var(--s40); --idw: 212px; }
  .sec-home-pricing .pr-term { grid-template-columns: minmax(0, 168px) minmax(0, 1fr); }
  .sec-home-pricing .pr-card { padding: var(--s32); }
}

/* Below this the ledger + object can no longer sit side by side without both
   becoming letterbox slots. Stack them; the card keeps its edge crop. */
@media (max-width: 980px) {
  .sec-home-pricing .pr-panel { margin-bottom: var(--s80); }
  .sec-home-pricing .pr-foot { grid-template-columns: minmax(0, 1fr); }
  .sec-home-pricing .pr-terms { grid-column: 1; grid-row: auto; }
  .sec-home-pricing .pr-card {
    grid-column: 1;
    grid-row: auto;
    margin-top: var(--s48);
    margin-right: calc(var(--gutter) * -1);
  }
  .sec-home-pricing .pr-close { grid-row: auto; margin-top: var(--s64); }
}

/* — The mobile head is DESIGNED, not reflowed ————————————————
   The title keeps the axis and the lede is indented off it and hung on a
   hairline, so the head band still has two stops rather than one left stack. */
@media (max-width: 900px) {
  .sec-home-pricing .pr-head {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--s32);
    align-items: start;
    margin-bottom: var(--s64);
  }
  .sec-home-pricing .pr-head__title { max-width: 15ch; }
  .sec-home-pricing .pr-head__sub {
    max-width: 34ch;
    margin-left: clamp(44px, 18%, 150px);
    padding-left: var(--s20);
    border-left: 1px solid var(--hair-strong);
  }
  .sec-home-pricing .pr-panel { margin-bottom: var(--s64); }

  /* The panel commits to a true edge-to-edge strip: both margins bleed, ALL
     four corners squared. The previous build bled one side only and kept the
     other side's radius, which read as an overflow bug rather than an edge. */
  .sec-home-pricing .pr-panel {
    margin-left: calc(var(--gutter) * -1);
    margin-right: calc(var(--gutter) * -1);
    border-radius: 0;
    --pad-l: var(--gutter);
    --pad-r: var(--gutter);
  }
  /* In flow, not overhanging: at this width an overhang has nowhere to go. */
  .sec-home-pricing .pr-panel__top {
    display: block;
    padding-bottom: var(--s24);
  }
  .sec-home-pricing .pr-chip {
    margin: var(--s20) 0 0;
    width: 100%;
    justify-content: space-between;
  }
  .sec-home-pricing .pr-chip__rows { flex: 1 1 auto; }
}

/* Below 720 the label column and the plot cannot share a line. The row becomes
   two bands: identity across the top, the full-width plot beneath it — still one
   ruler, still one continuous set of gridlines, still one axis. */
@media (max-width: 720px) {
  .sec-home-pricing { --inset: var(--s20); }
  .sec-home-pricing .pr-head__title { max-width: 12ch; text-wrap: pretty; }
  .sec-home-pricing .pr-panel { padding-top: var(--s32); margin-bottom: var(--s48); }

  .sec-home-pricing .pr-row,
  .sec-home-pricing .pr-axis {
    grid-template-columns: minmax(0, 1fr);
    column-gap: 0;
  }
  .sec-home-pricing .pr-row__id {
    flex-direction: row;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--s16);
    padding-block: var(--s20) var(--s12);
  }
  .sec-home-pricing .pr-row__label { text-align: right; }
  /* The gridlines stay inside the plot band. The previous build ran them the
     full height of the row, which put a ruled line straight through the middle
     of every label — type crossed by chart furniture. They still fall on the
     same four x-stops in all three rows and on the axis below, so the ruler is
     just as legible with the type left alone. */
  .sec-home-pricing .pr-row__plot { min-height: 60px; }
  .sec-home-pricing .pr-row__band { height: 18px; margin-top: -9px; }
  /* Still 1.25% — ~4px at 390px. It is allowed to be four pixels wide; what it
     is not allowed to be is four pixels wide while claiming to be eight. The
     blade takes the height back instead. */
  .sec-home-pricing .pr-row__mark { top: var(--s8); bottom: var(--s8); }
  .sec-home-pricing .pr-axis__scale { grid-column: 1; }

  .sec-home-pricing .pr-term--lead { padding: var(--s24); margin-bottom: var(--s24); }
  .sec-home-pricing .pr-term {
    grid-template-columns: minmax(0, 1fr);
    row-gap: var(--s8);
    padding: var(--s16) 0 var(--s20);
  }
  /* Inset, both corners rounded, a real gutter on both sides — the card is a
     card here, and the panel above is the one full-bleed object. */
  .sec-home-pricing .pr-card { padding: var(--s28); margin-top: var(--s32); margin-right: 0; }
  .sec-home-pricing .pr-card__mark { width: 48px; height: 48px; }
  .sec-home-pricing .pr-card__text { padding-top: var(--s32); }

  .sec-home-pricing .pr-close {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--s20);
    margin-top: var(--s40);
    padding-top: var(--s24);
  }
  .sec-home-pricing .pr-close__line { max-width: 24ch; }
}

@media (max-width: 420px) {
  .sec-home-pricing .pr-chip { gap: var(--s16); padding-left: var(--s16); }
  .sec-home-pricing .pr-chip__row { gap: var(--s16); }
  .sec-home-pricing .pr-chip__v { font-size: var(--t-body); }
  .sec-home-pricing .pr-row__id { gap: var(--s12); }
}

/* Caption inside the ink panel — same dark-ground correction as home-adoption. */
.sec-home-pricing .pr-panel .pr-panel__cap { color: var(--on-dark-muted); }

/* ===== section:home-ai ===== */
/* ————————————————————————————————————————————————
   home-ai — the breath, and the only tinted plane on the homepage.

   Round 3 fixed the two things that broke rather than read as designed:

   1. THE SEAM. The band's texture died in a dead-straight full-width line with
      grain above it and none below. Two causes, both fixed here:
        · The page grain (body::after) is `position: fixed`, so in a full-page
          capture it paints ONE viewport tall and everything below the fold — the
          band AND the cards on it — comes out perfectly flat. This section now
          carries its own grain layer (.ai-grain, absolutely positioned, so it
          scrolls with the content) above both artifacts, at a low enough opacity
          that where the two overlap it reads as tooth, not dirt.
        · The preview harness mounts this section as main's FIRST child, which
          triggers the hero rule in 10-base.css (a -76px margin so a hero can sit
          under the transparent nav). That pushed the last 76px of the section
          below the document's scroll height, where nothing paints at all — a
          hard, grainless strip of bare canvas under the band. Neutralised below,
          so the preview shows what the real page ships.
      The exit fade is now 260px with non-linear stops, so no single scanline is
      the edge of the tint either.

   2. THE MOBILE OBJECT. The exchange had stopped being an object: full-bleed,
      no radius, no side margin, no shadow, stacked under a table card that kept
      its rounded edge. Both cards now crop the same way and by the same offset —
      table off the LEFT, exchange off the RIGHT — each keeping a radius, a
      shadow and its inner margin. Two objects, mirrored, not one card and one
      un-card.

   Also: the planes are separated tonally (rear table ~3% cooler and darker than
   the exchange, whose header strip is warm-tinted), the two focal numbers are
   complementary instead of one decimal apart (+18.0% cost, −16.3 pts margin),
   the exchange runs deep enough to fill the lower right, every rule inside it is
   full-bleed, and the chart's reference line and curve share one plot box and
   are both labelled.

   The peach ration is untouched: nothing here uses --peach/--sienna, and
   home-traction below declares its own paper, so its peach card still lands
   on white.
   ———————————————————————————————————————————————— */

.sec-home-ai {
  padding-block: var(--section-y);

  /* The crop is done HERE as well as at the root: `clip` on one axis leaves the
     other visible, adds no scroll container, and keeps the two bled artifacts
     from ever widening the document. */
  overflow-x: clip;
  overflow-y: visible;

  /* How far each artifact runs past its own edge of the viewport: the wrap's own
     side margin, plus a real crop. */
  --ai-bleed: calc(max((100vw - var(--page)) / 2, var(--gutter)) + 52px);
  /* The table's crop is an allowance, not a guillotine: the sheet runs 44px past
     the edge and carries 44px of dead padding, so the crop eats margin and never
     a letter. */
  --ai-crop-l: 44px;
  --ai-bleed-l: calc(max((100vw - var(--page)) / 2, var(--gutter)) + var(--ai-crop-l));
  /* How far the sheet reaches under the exchange. Every pixel of it is dead
     margin — see --ai-costs-pad — so the card occludes blank sheet, never a
     figure. */
  --ai-costs-over: 172px;
  --ai-costs-pad: 136px;

  /* THE TWO PLANES, separated by value and not only by occlusion. The front card
     is the warm one; the rear sheet is mixed toward --mist, which lands it about
     3% darker and a shade cooler — the tonal cue the shadow alone was carrying. */
  --ai-surface: color-mix(in srgb, var(--wash-2) 8%, var(--raised));
  --ai-surface-rear: color-mix(in srgb, var(--mist) 54%, var(--ai-surface));
  --ai-bar: color-mix(in srgb, var(--wash-2) 26%, var(--ai-surface));

  /* The exchange is built from full-width bands, so its side padding is a
     variable rather than a shorthand: the right value is the crop allowance. */
  --ai-ex-pl: 34px;
  --ai-ex-pr: 96px;

  /* Committed ground. The second declaration wins wherever color-mix is
     supported; the first keeps the band visible if it is not. */
  background-color: var(--mist);
  background-color: color-mix(in srgb, var(--wash-2) 44%, var(--fog));
}

/*
 * Preview-harness correction. `main > .section:first-child.has-wash` in
 * 10-base.css slides a HERO up under the transparent nav; home-ai is never a
 * hero on a real page, but it IS main's first child in its isolated preview,
 * where that -76px margin left 76px of unpainted canvas below the band. Same
 * specificity as the base rule, declared later, so it wins — and it changes
 * nothing on index.html, where this section is not the first child.
 */
main > .section.sec-home-ai:first-child { margin-top: 0; padding-top: var(--section-y); }

/* Overrides the shared composition: blooms pushed off-centre so the light sits
   behind the exchange on the right, with a second, lower warm pool under the
   table so the bottom-left is lit rather than merely occupied. */
.sec-home-ai > .wash {
  inset: 0;
  background:
    radial-gradient(58% 52% at 80% 26%, var(--wash-1) 0%, transparent 66%),
    radial-gradient(46% 44% at 10% 12%, var(--wash-3) 0%, transparent 70%),
    radial-gradient(52% 46% at 22% 86%, var(--wash-2) 0%, transparent 72%),
    radial-gradient(38% 38% at 96% 48%, var(--wash-4) 0%, transparent 70%);
  filter: blur(10px) saturate(110%);
  opacity: 0.9;
}
/*
 * The band exits into paper so the peach card below never sits on a tint. 260px
 * and non-linear: a short linear ramp puts most of its change in a narrow strip
 * and the eye finds that strip; spread over 260px with the midpoint held low,
 * no single scanline is the edge.
 */
.sec-home-ai > .wash::after {
  height: 260px;
  background: linear-gradient(
    to top,
    var(--paper) 0%,
    color-mix(in srgb, var(--paper) 72%, transparent) 18%,
    color-mix(in srgb, var(--paper) 58%, transparent) 45%,
    color-mix(in srgb, var(--paper) 58%, transparent) 72%,
    color-mix(in srgb, var(--paper) 58%, transparent) 100%
  );
}

/*
 * SECTION GRAIN. Same tile and the same multiply blend as the page grain, but
 * absolutely positioned instead of fixed, so it covers the whole band — and both
 * cards, since it sits above them in the section's own stacking context — at any
 * scroll offset and in any capture. Deliberately lighter than body::after: the
 * two layers overlap wherever the page grain is painting, and this value keeps
 * the sum reading as paper tooth.
 */
.sec-home-ai .ai-grain {
  position: absolute;
  inset: 0;
  z-index: 5;
  pointer-events: none;
  opacity: 0.11;
  mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.91' numOctaves='2' seed='7' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3CfeComponentTransfer%3E%3CfeFuncA type='discrete' tableValues='0 1'/%3E%3C/feComponentTransfer%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 180px 180px;
}

/* — Label ——————————————————————————————————————— */
/* The shared .eyebrow, plus the one mark that belongs to this section. It used
   to restate the size, raise the weight to 500, add tracking and set full --ink
   — three colours and two weights for one class across the site. */
.sec-home-ai .ai-label {
  display: flex;
  align-items: center;
  gap: 13px;
}
.sec-home-ai .ai-label::before {
  content: '';
  width: 26px;
  height: 2px;
  border-radius: 2px;
  /* currentColor, so the mark can never drift off the label's own colour again. */
  background: currentColor;
}

/* — Display ————————————————————————————————————— */
/* No size of its own. This is a section headline on the home page and it sits
   on .h with every other section headline; the 46–96px clamp it used to carry
   made it the second-loudest thing on the site after the hero, and louder than
   five of the six page titles. The two decks are set as blocks, so the roman /
   italic split survives the size change intact. */
.sec-home-ai .ai-title {
  max-width: 1120px;
}
.sec-home-ai .ai-title__a,
.sec-home-ai .ai-title__b { display: block; }
.sec-home-ai .ai-title__b { font-style: italic; }

/* — Body: narrow left column, two objects cropped by opposite edges —————— */
.sec-home-ai .ai-body {
  position: relative;
  margin-top: 64px;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 600px);
  grid-template-areas:
    'say   stage'
    'link  stage'
    'table stage';
  grid-template-rows: auto auto 1fr;
  column-gap: 64px;
  align-items: start;
}

.sec-home-ai .ai-say {
  grid-area: say;
  max-width: 26rem;
  margin: 0;
}

.sec-home-ai .ai-linkwrap {
  grid-area: link;
  margin: 30px 0 0;
}
.sec-home-ai .ai-link {
  /* 44px hit target without moving the optical baseline. */
  padding-block: 13px;
  margin-block: -13px;
}

.sec-home-ai .ai-stage {
  grid-area: stage;
  position: relative;
  z-index: 2;
  /* Pulled up above the lede's first line, so the two columns never align. */
  margin-top: -52px;
  margin-right: calc(-1 * var(--ai-bleed));
}

/* — The rear plane: the record, cropped by the LEFT edge ————————— */
.sec-home-ai .ai-costs-wrap {
  grid-area: table;
  position: relative;
  z-index: 0;               /* passes UNDER the exchange */
  margin-top: 30px;
  margin-left: calc(-1 * var(--ai-bleed-l));
  width: calc(100% + var(--ai-bleed-l) + var(--ai-costs-over));
}

.sec-home-ai .ai-costs {
  padding: 22px var(--ai-costs-pad) 10px calc(var(--ai-crop-l) + 56px);
  border-radius: var(--r-elevated);
  background: var(--ai-surface-rear);
  /* Deliberately flatter than the exchange, and no rotation: this sheet is lying
     on the band, not floating over it. A slightly firmer hairline than the front
     card, because it is the darker plane. */
  box-shadow:
    0 0 0 1px color-mix(in srgb, var(--ink) 11%, transparent),
    0 1px 2px -1px color-mix(in srgb, var(--ink) 14%, transparent),
    0 12px 20px -18px color-mix(in srgb, var(--ink) 34%, transparent);
}

.sec-home-ai .ai-costs__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 20px;
  padding-bottom: 14px;
}
.sec-home-ai .ai-costs__title {
  font-size: 15px;
  font-weight: 500;
  letter-spacing: -0.008em;
  color: var(--ink);
}
.sec-home-ai .ai-costs__meta { font-size: 13px; color: var(--ash); }

.sec-home-ai .ai-costs__t {
  width: 100%;
  border-collapse: collapse;
  table-layout: auto;
}
.sec-home-ai .ai-costs__t th,
.sec-home-ai .ai-costs__t td {
  text-align: right;
  padding: 11px 0 11px 26px;
  border-top: 1px solid var(--hair);
  white-space: nowrap;
}
.sec-home-ai .ai-costs__t th[scope='row'],
.sec-home-ai .ai-costs__t thead th:first-child { text-align: left; padding-left: 0; }

.sec-home-ai .ai-costs__t thead th {
  padding-block: 0 9px;
  border-top: 0;
  font-size: 12px;
  font-weight: 450;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ash);
}
.sec-home-ai .ai-costs__t tbody th {
  font-size: 15px;
  font-weight: 450;
  letter-spacing: -0.006em;
  color: var(--ink);
}
.sec-home-ai .ai-costs__t tbody td {
  font-size: 15px;
  font-weight: 400;
  letter-spacing: -0.004em;
  color: var(--slate);
  font-variant-numeric: tabular-nums;
}
/* The driver the exchange is talking about, and the second focal figure on the
   band: the cost that moved, against the margin that moved with it. */
.sec-home-ai .ai-costs__t tr.is-driver th,
.sec-home-ai .ai-costs__t tr.is-driver td {
  color: var(--ink);
  font-weight: 500;
}
.sec-home-ai .ai-costs__t tr.is-driver td:last-child { letter-spacing: -0.012em; }

/* — The front plane: the exchange ————————————————————— */
.sec-home-ai .ai-ex {
  position: relative;
  /* No padding: the card is a stack of full-width bands, so every rule inside it
     runs edge to edge. One treatment, not two. */
  padding: 0;
  overflow: hidden;         /* clips the tinted header strip to the top corners */
  border-radius: var(--r-elevated);
  background: var(--ai-surface);
  /* Directional, not a halo: a crisp hairline, a contact shadow, then one soft
     cast downward. The whole cast rotates with the card. */
  box-shadow:
    0 0 0 1px color-mix(in srgb, var(--ink) 8%, transparent),
    0 2px 3px -2px color-mix(in srgb, var(--ink) 16%, transparent),
    0 36px 56px -28px color-mix(in srgb, var(--ink) 42%, transparent);
  /* Committed, not a rounding error: a real tilt you can read as intent. */
  transform: rotate(-1.3deg);
}

.sec-home-ai .ai-ex__bar,
.sec-home-ai .ai-ex__ans,
.sec-home-ai .ai-ex__plot,
.sec-home-ai .ai-ex__act {
  padding-inline: var(--ai-ex-pl) var(--ai-ex-pr);
}
.sec-home-ai .ai-ex__ans,
.sec-home-ai .ai-ex__plot,
.sec-home-ai .ai-ex__act { border-top: 1px solid var(--hair); }

/* The composer. A tinted strip across the whole head of the card — the second
   tonal cue that this plane is the warm one. */
.sec-home-ai .ai-ex__bar {
  display: flex;
  align-items: center;
  gap: 11px;
  padding-block: 19px;
  background: var(--ai-bar);
}
.sec-home-ai .ai-ex__mark { color: var(--ink); opacity: 0.65; flex: none; }
.sec-home-ai .ai-ex__q {
  font-size: 15px;
  line-height: 1.4;
  letter-spacing: -0.005em;
  color: var(--ink);
}

/* The answer. Figure left, cause right — so the row reads as a sentence and the
   right half of the card is never a void. */
.sec-home-ai .ai-ex__ans {
  display: grid;
  grid-template-columns: minmax(0, auto) minmax(0, 1fr);
  align-items: end;
  gap: 40px;
  padding-block: 26px 28px;
}
.sec-home-ai .ai-ex__figure { display: block; }
.sec-home-ai .ai-ex__dish {
  display: block;
  font-size: 15px;
  font-weight: 450;
  line-height: 1.35;
  letter-spacing: -0.006em;
  color: var(--slate);
}
/* The margin the dish lost, in points — the complement of the table's +18.0%,
   not a second reading of the same figure. */
.sec-home-ai .ai-ex__hero {
  display: block;
  margin-top: 6px;
  font-size: clamp(42px, 3.7vw, 56px);
  font-weight: 500;
  line-height: 1;
  letter-spacing: -0.032em;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.sec-home-ai .ai-ex__unit {
  margin-left: 9px;
  font-size: 15px;
  font-weight: 450;
  letter-spacing: -0.004em;
  color: var(--ash);
}
.sec-home-ai .ai-ex__why {
  display: flex;
  align-items: center;
  gap: 9px;
  padding-bottom: 5px;
  color: var(--slate);
}
.sec-home-ai .ai-ex__why svg { flex: none; opacity: 0.7; }
.sec-home-ai .ai-ex__note {
  font-size: 14px;
  line-height: 1.4;
  letter-spacing: -0.004em;
}

/* The drawn surface. A labelled plot, not decoration: the reference line and the
   curve share one plot box — same x0, same x1 — the dashed line is the March
   level the fall starts from, and both ends carry their value. */
.sec-home-ai .ai-ex__plot { padding-block: 20px 22px; }
.sec-home-ai .ai-plot__keys {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 24px;
  margin-bottom: 12px;
  font-size: 12.5px;
  letter-spacing: 0.004em;
  color: var(--ash);
}
.sec-home-ai .ai-plot__key { display: inline-flex; align-items: center; gap: 8px; }
.sec-home-ai .ai-plot__key b { font-weight: 500; color: var(--ink); }
.sec-home-ai .ai-plot__key--was::before {
  content: '';
  width: 16px;
  height: 0;
  border-top: 1px dashed color-mix(in srgb, var(--ink) 45%, transparent);
}
.sec-home-ai .ai-plot__key--now::after {
  content: '';
  width: 7px;
  height: 7px;
  /* Pulled half its own width so it centres on the plot box's right edge, where
     the curve's end cap lands. */
  margin-right: -3px;
  border-radius: var(--r-pill);
  background: var(--ink);
}
.sec-home-ai .ai-plot__chart {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;        /* the two end caps sit ON the plot box's corners */
  color: var(--ink);
}
.sec-home-ai .ai-plot__ref { opacity: 0.32; }
.sec-home-ai .ai-plot__line { opacity: 0.92; }
.sec-home-ai .ai-plot__cap { opacity: 0.92; }

/* The footer band. */
.sec-home-ai .ai-ex__act {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 24px;
  padding-block: 17px;
}
.sec-home-ai .ai-ex__line {
  display: block;
  font-size: 15px;
  font-weight: 450;
  line-height: 1.4;
  letter-spacing: -0.006em;
  color: var(--ink);
}
/* Illustrative, not a control: a span, so it is neither focusable nor announced
   as a button, and the 44px hit-target floor does not apply to it. */
.sec-home-ai .ai-ex__apply {
  display: inline-flex;
  align-items: center;
  height: 32px;
  padding-inline: 15px;
  border-radius: var(--r-pill);
  background: var(--ink);
  color: var(--raised);
  font-size: 13px;
  font-weight: 450;
  letter-spacing: -0.004em;
  white-space: nowrap;
}

/* — Narrow ——————————————————————————————————————— */
@media (max-width: 1280px) {
  .sec-home-ai { --ai-costs-over: 132px; --ai-costs-pad: 112px; --ai-ex-pr: 84px; }
  .sec-home-ai .ai-body { grid-template-columns: minmax(0, 1fr) minmax(0, 55%); column-gap: 48px; }
  .sec-home-ai .ai-ex__ans { gap: 28px; }
}

@media (max-width: 1080px) {
  .sec-home-ai {
    --ai-costs-over: 104px;
    --ai-costs-pad: 92px;
    --ai-ex-pr: 74px;
  }
  .sec-home-ai .ai-title { margin-top: 20px; }
  .sec-home-ai .ai-body { margin-top: 56px; }
  .sec-home-ai .ai-stage { margin-top: -44px; }
  .sec-home-ai .ai-costs__t th,
  .sec-home-ai .ai-costs__t td { padding-left: 18px; }
  .sec-home-ai .ai-ex__ans { grid-template-columns: minmax(0, 1fr); gap: 14px; align-items: start; }
  .sec-home-ai .ai-ex__why { padding-bottom: 0; }
}

/* The two columns stop earning their keep before the objects do: stack, but keep
   both crops — the table off the left edge, the exchange off the right. */
@media (max-width: 900px) {
  .sec-home-ai .ai-body {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: 'say' 'link' 'table' 'stage';
    column-gap: 0;
  }
  .sec-home-ai .ai-say { max-width: 32rem; }
  .sec-home-ai .ai-linkwrap { margin-top: 32px; }
  .sec-home-ai .ai-costs-wrap {
    margin-top: 44px;
    width: calc(100% + var(--ai-bleed-l));
  }
  .sec-home-ai { --ai-costs-pad: 26px; }
  .sec-home-ai .ai-stage { margin-top: 44px; }
}

/* — Phone ————————————————————————————————————————
   TWO objects, mirrored. The table runs off the left edge and keeps its rounded
   right corner; the exchange runs off the right edge by the same offset and
   keeps its rounded left corner. Both keep a shadow. Neither becomes a band. */
@media (max-width: 720px) {
  .sec-home-ai {
    --ai-ex-pl: var(--gutter);
    --ai-ex-pr: calc(var(--gutter) * 2);
  }
  .sec-home-ai .ai-title { margin-top: 18px; line-height: 1.06; }
  .sec-home-ai .ai-body { margin-top: 40px; }
  .sec-home-ai .ai-say { max-width: 30rem; }
  .sec-home-ai .ai-linkwrap { margin-top: 28px; }
  .sec-home-ai > .wash::after { height: 190px; }

  .sec-home-ai .ai-costs-wrap {
    margin-top: 40px;
    margin-left: calc(-1 * var(--gutter));
    width: calc(100% + var(--gutter));
  }
  .sec-home-ai .ai-costs {
    padding: 20px var(--gutter) 8px var(--gutter);
    border-start-start-radius: 0;
    border-end-start-radius: 0;
  }
  .sec-home-ai .ai-costs__t th,
  .sec-home-ai .ai-costs__t td { padding-left: 14px; font-size: 14px; }
  /* Three columns will not hold at 390px; the share column is the one the
     sentence above does not need. */
  .sec-home-ai .ai-costs__t th:nth-child(2),
  .sec-home-ai .ai-costs__t td:nth-child(2) { display: none; }

  .sec-home-ai .ai-stage {
    margin-top: 34px;
    margin-right: calc(-1 * var(--gutter));
  }
  .sec-home-ai .ai-ex {
    transform: none;
    border-start-end-radius: 0;
    border-end-end-radius: 0;
    box-shadow:
      0 0 0 1px color-mix(in srgb, var(--ink) 8%, transparent),
      0 2px 3px -2px color-mix(in srgb, var(--ink) 16%, transparent),
      0 26px 40px -26px color-mix(in srgb, var(--ink) 40%, transparent);
  }

  .sec-home-ai .ai-ex__bar { padding-block: 16px; }
  .sec-home-ai .ai-ex__q { font-size: 14px; }
  .sec-home-ai .ai-ex__ans { padding-block: 22px 24px; }
  .sec-home-ai .ai-ex__hero { font-size: 46px; }
  .sec-home-ai .ai-ex__plot { padding-block: 18px 20px; }
  .sec-home-ai .ai-plot__keys { font-size: 12px; gap: 14px; margin-bottom: 10px; }
  .sec-home-ai .ai-ex__act { gap: 14px; padding-block: 15px; }
  .sec-home-ai .ai-ex__line { font-size: 14px; }
}

/* At the narrowest widths the two keys will not share a line. */
@media (max-width: 420px) {
  .sec-home-ai .ai-plot__keys { display: grid; grid-template-columns: 1fr; gap: 4px; }
  .sec-home-ai .ai-plot__key--now { justify-self: end; }
}

/* ===== section:home-traction ===== */
/* ————————————————————————————————————————————————
   home-traction — the retention ledger and THE oxblood field.

   WHAT THE LAST ROUND GOT WRONG, and what this rebuild does about it:

   1. NO MASS. The card was peach on paper: (246,222,205) against (250,249,247),
      a 4% delta measured as 1.35% of pixels below L=90. The card is now a true
      oxblood field (--sienna) with reversed type — one genuinely heavy object,
      ~20% of the frame. The peach it used to be was re-laid as a shelf INSIDE
      the oxblood, which broke the component's own rule — .card--peach is warm
      ink on warm PAPER, never on a tinted ground — so the shelf is now just the
      lower band of the field, and the homepage spends its one peach surface on
      home-barriers, where it sits on paper.

   2. A 323 × 470 HOLE at x505–828. The three figures sat in a 380px band with a
      void beside them. The ledger now runs the full left column to the card's
      gutter, and every row is a 14-cell track: the shared datum is fourteen
      shops, the filled run is the row's own number. Fourteen fills fourteen,
      five fills five, six fills six — and the claim row draws all fourteen cells
      and fills none of them, which is the argument, drawn to scale.

   3. 301px OF SPACE-BETWEEN between '14' and 'shops'. There is no free run left:
      figure, then the measured track, then the label. The gutter is the chart.

   4. THREE LEFT EDGES on the right half. Head and body now share one grid
      (680fr / 488fr, 32px gap → the card edge lands on the same x at every
      width), and the standfirst is indented by the card's own padding so it sits
      on the card's inner text column. Two edges: the surface at 832, the text
      column at 880.

   5. MOBILE THREW AWAY THE CROP. The field now overhangs the right gutter and is
      clipped by the section, so the composition's best move survives to 390px.
   ———————————————————————————————————————————————— */

.sec-home-traction {
  /* Explicit paper: the oxblood must never sit on a tinted band, whatever
     section happens to precede it. */
  background: var(--paper);
  padding-block: var(--section-y-tight);
  isolation: isolate;
  /* The field is cropped by the SECTION box, not by the document: clipping here
     means the crop lands exactly on the viewport edge and body.scrollWidth never
     grows past it. */
  overflow: hidden;

  /* --tr-crop is how far the field OVERHANGS the visible frame; --tr-pr is the
     inset its type keeps from that frame. The right padding is the sum, so the
     crop can be pushed at any breakpoint without ever eating the caption —
     which is exactly what it did at 768 when the two drifted apart. */
  --tr-crop: 18px;
  --tr-bleed: calc(var(--gutter) + var(--tr-crop));
  --tr-pr: var(--s24);
  --tr-pad: var(--s24);

  /* ONE column definition for both the head and the body, so the card's edge and
     the standfirst's indent cannot drift apart. */
  --tr-split: minmax(0, 1fr);
  --tr-gap: var(--s40);

  /* The ledger row: figure on the page axis, the measured track, the label. */
  --tr-cols: minmax(40px, auto) minmax(0, 1fr) 84px;
  --tr-colgap: var(--s12);
  --tr-cells: 14;
}

/* Section-scoped tooth. The global grain is fixed to the viewport, so it slides
   against the artwork as you scroll; this one is absolute to the section, so the
   field and the paper keep the same texture wherever the section sits. */
.sec-home-traction::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 4;
  pointer-events: none;
  opacity: 0.05;
  mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 160 160' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='1.15' numOctaves='2' seed='19' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23g)'/%3E%3C/svg%3E");
  background-size: 150px 150px;
}

/* — Head ——————————————————————————————————————— */
.sec-home-traction .tr-head {
  display: grid;
  gap: var(--s28);
}
/* No size of its own: .h is what a section headline is, and the 38–78px clamp
   this used to carry put it above every page title on the site. The measure
   stays in ch, so the authored two-line rag holds at the new size. */
.sec-home-traction .tr-head__title {
  max-width: 17ch;
}
.sec-home-traction .tr-head__aside {
  display: grid;
  justify-items: start;
  gap: var(--s16);
}
.sec-home-traction .tr-head__sub {
  max-width: 34ch;
}
/* The arrow carries the affordance; the padding carries the hit target. */
.sec-home-traction .tr-head__link {
  min-height: 44px;
}

/* — The one rule ————————————————————————————————
   ONE rule, not two. The table used to carry its own 2px top border 23px under
   a full-measure hairline, which read as a doubled line and pushed the ledger
   down into the hole. The section rule IS the table's head rule now: ink weight,
   the full measure, and the oxblood field crosses it. */
.sec-home-traction .tr-rule {
  margin-top: var(--s40);
  border-top: 2px solid var(--ink);
}

/* — Body ———————————————————————————————————————— */
.sec-home-traction .tr-body {
  display: grid;
  grid-template-columns: var(--tr-split);
  gap: var(--tr-gap);
}

/* — The ledger ——————————————————————————————————
   A table, and a chart, and the same object. Every row carries a track of
   fourteen cells; the fill is the row's own figure against that datum. Nothing
   in this column is a floating hairline with air beside it. */
.sec-home-traction .tr-ledger {
  align-self: start;
  min-width: 0;
}
.sec-home-traction .tr-table {
  margin: 0;
}
.sec-home-traction .tr-row {
  display: grid;
  grid-template-columns: var(--tr-cols);
  column-gap: var(--tr-colgap);
  align-items: center;
  padding-block: var(--s12);
  border-bottom: 1px solid var(--hair-strong);
}
/* dt is the label and dd the value, which is the right reading order for a
   screen reader; `display: contents` lets the figure and its track sit on the
   row's own grid so every track starts and ends on the same two x-positions. */
.sec-home-traction .tr-row__val {
  display: contents;
}
.sec-home-traction .tr-row__n {
  grid-column: 1;
  grid-row: 1;
  font-family: var(--serif);
  font-weight: 400;
  font-optical-sizing: auto;
  font-size: 30px;
  line-height: 1;
  letter-spacing: var(--tr-h-sm);
  color: var(--ink);
}
.sec-home-traction .tr-row__label {
  grid-column: 3;
  grid-row: 1;
  font-size: var(--t-caption);
  line-height: 1.3;
  letter-spacing: -0.005em;
  color: var(--ink);
}

/* The track IS the datum: fourteen cells wide, always. */
.sec-home-traction .tr-row__track {
  grid-column: 2;
  grid-row: 1;
  position: relative;
  display: block;
  height: 26px;
  border: 1px solid var(--hair-strong);
  overflow: hidden;
}
.sec-home-traction .tr-row__fill {
  position: absolute;
  inset-block: 0;
  left: 0;
  display: block;
  width: calc(var(--n) / var(--tr-cells) * 100%);
  background: var(--ink);
}
/* The cell divisions are painted OVER the fill, in a tone that reads on ink and
   on paper alike, so the count survives inside the filled run. */
.sec-home-traction .tr-row__track::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: repeating-linear-gradient(
    to right,
    transparent 0,
    transparent calc(100% / 14 - 1px),
    color-mix(in srgb, var(--smoke) 60%, transparent) calc(100% / 14 - 1px),
    color-mix(in srgb, var(--smoke) 60%, transparent) calc(100% / 14)
  );
}

/* The claim row. Display scale, a taller register, and a track drawn at full
   ink weight with nothing in it — fourteen cells, none of them struck. */
.sec-home-traction .tr-row--claim {
  padding-block: var(--s20) var(--s16);
  border-bottom-width: 2px;
  border-bottom-color: var(--ink);
}
.sec-home-traction .tr-row--claim .tr-row__n {
  font-size: clamp(56px, 15vw, 78px);
  letter-spacing: var(--tr-display);
}
.sec-home-traction .tr-row--claim .tr-row__label {
  font-size: var(--t-body);
  font-weight: 450;
}
.sec-home-traction .tr-row--claim .tr-row__track {
  height: 44px;
  border-width: 1.5px;
  border-color: var(--ink);
}
/* The empty register is DRAWN, not merely absent: its cell divisions carry the
   same weight as the filled rows so it reads as fourteen measured cells with
   nothing in them. */
.sec-home-traction .tr-row--claim .tr-row__track::after {
  background: repeating-linear-gradient(
    to right,
    transparent 0,
    transparent calc(100% / 14 - 1px),
    color-mix(in srgb, var(--ink) 34%, transparent) calc(100% / 14 - 1px),
    color-mix(in srgb, var(--ink) 34%, transparent) calc(100% / 14)
  );
}

/* The scale, printed where a scale belongs — under the track column only. */
.sec-home-traction .tr-axis {
  display: grid;
  grid-template-columns: var(--tr-cols);
  column-gap: var(--tr-colgap);
  margin-top: var(--s8);
  font-size: 13px;
  color: var(--ash);
}
.sec-home-traction .tr-axis > span {
  grid-column: 2;
  grid-row: 1;
  display: flex;
  justify-content: space-between;
  font-variant-numeric: tabular-nums;
}
.sec-home-traction .tr-axis i { font-style: normal; }

.sec-home-traction .tr-cap {
  display: grid;
  grid-template-columns: var(--tr-cols);
  column-gap: var(--tr-colgap);
  margin-top: var(--s20);
  font-size: var(--t-caption);
  line-height: 1.35;
  color: var(--slate);
}
.sec-home-traction .tr-cap__a { grid-column: 1 / 3; grid-row: 1; }
.sec-home-traction .tr-cap__b { grid-column: 3; grid-row: 1; color: var(--ink); }

/* — The oxblood field ————————————————————————————
   The heavy element. A deep warm ground with reversed type, cropped by the
   viewport edge; its lower band is the field and its key. */
.sec-home-traction .tr-panel {
  position: relative;
  z-index: 1;
  overflow: hidden;
  color: var(--peach);
  background:
    radial-gradient(118% 88% at 14% 2%,
                    color-mix(in srgb, var(--peach) 17%, transparent) 0%,
                    transparent 60%),
    var(--sienna);
  /* Crosses the measure: the surface runs off the right edge while its type
     keeps a clean rag, so the composition has one object that ignores the wrap. */
  margin-right: calc(var(--tr-bleed) * -1);
  border-radius: var(--r-card) 0 0 var(--r-card);
  display: grid;
  align-content: start;
}
.sec-home-traction .tr-panel__say {
  padding: var(--s28) calc(var(--tr-crop) + var(--tr-pr)) var(--s32) var(--tr-pad);
}
.sec-home-traction .tr-panel__line {
  font-size: clamp(25px, 2.9vw, 41px);
  line-height: 1.18;
  letter-spacing: var(--tr-h);
  color: var(--peach);
  text-wrap: pretty;
}

/* The lower band. It used to be a peach SURFACE laid inside the oxblood, which
   is the one place the component forbids peach; the drawing and its key now sit
   on the field itself, in the panel's own reversed ink. It runs to all three of
   the field's own edges, so it is cropped by the same crop. */
.sec-home-traction .tr-panel__shelf {
  padding: var(--s24) calc(var(--tr-crop) + var(--tr-pr)) var(--s20) var(--tr-pad);
  display: grid;
  gap: var(--s16);
}
.sec-home-traction .tr-field {
  width: 100%;
  /* No cap. The field, its key and the statement above all end on the field's
     one inner right edge at every width — a cap put a fourth edge back into the
     composition at 1920. The count is unaffected by scale: the 452 x 72 box is
     113 x 18 tiles of the 4-unit pattern however large it is drawn. */
  height: auto;
  color: var(--peach);
}
.sec-home-traction .tr-panel__cap {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: var(--s4) var(--s20);
  padding-top: var(--s12);
  border-top: 1px solid color-mix(in srgb, var(--peach) 34%, transparent);
  font-size: var(--t-caption);
  line-height: 1.35;
  color: var(--peach);
}
.sec-home-traction .tr-panel__cap-n {
  opacity: 0.66;
  white-space: nowrap;
}

/* — Up ————————————————————————————————————————— */
@media (min-width: 561px) {
  .sec-home-traction {
    --tr-cols: minmax(48px, auto) minmax(0, 1fr) 86px;
    --tr-colgap: var(--s16);
    --tr-pad: var(--s32);
  }
  .sec-home-traction .tr-row__n { font-size: 34px; }
  .sec-home-traction .tr-row--claim .tr-row__n { font-size: clamp(72px, 9vw, 92px); }
  .sec-home-traction .tr-row__label { font-size: var(--t-body); }
  .sec-home-traction .tr-row--claim .tr-row__label { font-size: var(--t-subhead); }
  .sec-home-traction .tr-row__track { height: 30px; }
  .sec-home-traction .tr-row--claim .tr-row__track { height: 52px; }
}

@media (min-width: 721px) {
  .sec-home-traction {
    --tr-cols: minmax(52px, auto) minmax(0, 1fr) 96px;
    --tr-colgap: var(--s24);
    --tr-pad: var(--s40);
    --tr-pr: var(--s40);
  }
  .sec-home-traction .tr-rule { margin-top: var(--s64); }
  .sec-home-traction .tr-row { padding-block: var(--s16); }
  .sec-home-traction .tr-panel__say { padding-block: var(--s40) var(--s40); }
  .sec-home-traction .tr-panel__shelf { padding-block: var(--s32) var(--s28); }
}

/*
 * TABLET. One column, but the field is pushed 26% off the left margin and still
 * cropped by the right edge — a wide object floating clear of the type above it
 * rather than a second full-measure band.
 */
@media (min-width: 721px) and (max-width: 999px) {
  .sec-home-traction {
    /* A harder crop at this width, because the indent is what makes the field
       an object rather than a second full-measure band — and a 26% indent left
       a 185px column of nothing down the left of it. */
    --tr-crop: 48px;
  }
  .sec-home-traction .tr-panel { margin-left: 14%; }
}

@media (min-width: 861px) {
  .sec-home-traction .tr-head {
    grid-template-columns: var(--tr-split);
    gap: var(--tr-gap);
    align-items: start;
  }
  .sec-home-traction .tr-head__aside { padding-top: var(--s12); }
  .sec-home-traction .tr-rule { margin-top: var(--s64); }
}

/*
 * THE SPLIT. 680fr / 488fr with a 32px gap: at the 1200px measure that resolves
 * to exactly 680 + 32 + 488, so the field's left edge lands at x = 832 and its
 * inner text column at x = 880 — the two x-positions the standfirst is snapped
 * to. Held back to 1000px because below it the field's column is too narrow to
 * carry a 30px+ serif statement.
 */
@media (min-width: 1000px) {
  .sec-home-traction {
    --tr-crop: 56px;
    --tr-bleed: calc(max((100vw - var(--page)) / 2, var(--gutter)) + var(--tr-crop));
    --tr-pr: var(--s64);
    --tr-pad: var(--s48);
    --tr-split: minmax(0, 680fr) minmax(0, 488fr);
    --tr-gap: var(--s32);
    --tr-cols: minmax(56px, auto) minmax(0, 1fr) 100px;
  }

  .sec-home-traction .tr-rule { margin-top: var(--s96); }

  /* The standfirst is indented by exactly the field's own left padding, so it
     shares the field's inner text column and the third left edge is gone. */
  .sec-home-traction .tr-head__aside { padding-left: var(--tr-pad); }

  .sec-home-traction .tr-body { align-items: stretch; }

  .sec-home-traction .tr-row__n { font-size: 42px; }
  .sec-home-traction .tr-row--claim .tr-row__n { font-size: clamp(88px, 7.4vw, 106px); }
  .sec-home-traction .tr-row--claim { padding-block: var(--s24) var(--s20); }
  .sec-home-traction .tr-row__track { height: 32px; }
  .sec-home-traction .tr-row--claim .tr-row__track { height: 58px; }

  /* Pulled up over the hairline: the rule passes behind the field. */
  .sec-home-traction .tr-panel {
    align-self: start;
    margin-top: calc(var(--s32) * -1);
  }
  .sec-home-traction .tr-panel__say { padding-block: var(--s48) var(--s48); }
  .sec-home-traction .tr-panel__shelf { padding-block: var(--s40) var(--s32); }
}

@media (min-width: 1200px) {
  .sec-home-traction .tr-panel { margin-top: calc(var(--s48) * -1); }
}

/* ===== section:cta-band ===== */
/* ————————————————————————————————————————————————
   cta-band — the closing punctuation, shared by all eight pages.

   Round 4. Round 3 lost on FINISH, not on idea: the two largest objects in the
   frame were hand-drawn placeholder-bar SVGs (a 264×426 field and a 290×214
   fragment), so a third of the composition read as content-TBD; every surface
   in the band sat between #FFF and #EAEAEA, so there was no mass anywhere; and
   ~550×290 of empty gradient sat between the headline's descender and the
   card's left edge. Three changes, in order of size:

   1. THE SLAB. The card is now the only dark mass in any page's closing band —
      var(--ink), white keys, paper values, no shadow (elevation is reserved for
      .artifact and this is not one). It is the "one genuinely heavy element"
      the band never had.
   2. REAL TYPE, NOT BARS. The menu inside it is SET: 29 priced rows under six
      small-caps category headers, prices on one shared tabular column per
      column of the menu. The kitchen ticket at the other corner is set the same
      way. Nothing in this section is a placeholder bar any more, and the slab
      earns its area with character density rather than filling it.
   3. INTERLOCK. The slab is taller (768px against a ~690px band) and pinned so
      its top rides ABOVE the headline's first line rather than starting below
      it, and the file tile is now a CHILD of the slab, hung across its left
      edge — so the overlap is measured from the slab and holds at every width.
      The hole in the middle is closed by the tile, not by moving the rail.

   The crop is still measured: the slab overhangs the right edge by 108px and
   its inner padding-right is that overhang plus 28px, so every price and every
   value ends 28px inside the cut and the edge falls through row whitespace.
   ———————————————————————————————————————————————— */
.sec-cta-band {
  padding-block: var(--section-y-loose);
  border-top: 1px solid var(--hair);
  /* Every object here is meant to be cut by these edges, and the bloom must
     never bleed onto whichever section happens to precede us. */
  overflow: hidden;
}

/* — The light —————————————————————————————————
   Recomposed for a left-anchored frame: the warm primary bloom sits behind the
   display head at 30/26 rather than on the axis, a lilac holds the object half,
   and a low warm one sits under the cut cards so the bottom of the band never
   flattens out. The cool --wash-4 stays dropped (it read as a blue-grey corner
   on --fog) and the component's paper-coloured bottom fade is removed — this
   band sits on --fog, so that fade would paint a white shelf across the close
   of every page. */
.sec-cta-band > .wash {
  inset: 0;
  opacity: 0.72;
  filter: blur(18px) saturate(106%);
  background:
    radial-gradient(38% 46% at 24% 20%, var(--wash-1) 0%, transparent 66%),
    radial-gradient(48% 54% at 58% 32%, var(--wash-2) 0%, transparent 70%),
    radial-gradient(40% 46% at 14% 76%, var(--wash-3) 0%, transparent 72%),
    radial-gradient(40% 46% at 88% 80%, var(--wash-1) 0%, transparent 72%);
}
.sec-cta-band > .wash::after { content: none; }

/* — Stacking ———————————————————————————————————
   Type above everything; the objects above the closing rule; the rule beneath
   both. That ordering is what lets the full-measure hairline disappear under
   the slab instead of drawing a grey line across it. */
.sec-cta-band .ctab__wrap { position: relative; z-index: 2; }
.sec-cta-band .ctab__footwrap { position: relative; z-index: 0; }

/* — The rail ———————————————————————————————— */
.sec-cta-band .ctab {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  text-align: left;
  max-width: 760px;
}

.sec-cta-band .ctab__h {
  /* SECTION-HEAD SCALE, NOT DISPLAY. This partial is byte-identical on all
     eight pages, so a display-scale sign-off made the last words on six of them
     the loudest words on the page — louder than the page's own H1. The site's
     one display is the home hero; every section headline, this one included,
     sits on .h. The measure still makes the two decks read as a natural break
     off the rail rather than as a balanced pair of centred lines. */
  font-size: var(--t-h);
  line-height: 1.16;
  letter-spacing: var(--tr-h);
  max-width: 15ch;
}
/* Give the clipped line masks room for the italic 'y' descender, then take the
   extra leading back so the two decks keep the rhythm .h sets for them. */
.sec-cta-band .ctab__h .line-mask { padding-bottom: 0.14em; margin-bottom: -0.14em; }

/* Dropped from --t-body-lg. At 20px the lede competed with the headline; at
   17px it becomes the quiet second voice, and at 44ch it sets three short lines
   against the rail instead of two long centred ones. */
/* The measure is also a CLEARANCE. The slab's left edge marches left as the
   viewport narrows (it is 53vw wide against a fixed 108px overhang) while the
   rail's text stays pinned at the gutter, so the lede is the line that would
   meet the file tile first. Every step below is set to keep ~40px of air
   between the end of this paragraph and the tile's send button. */
.sec-cta-band .ctab__sub {
  margin: var(--s24) 0 0;
  font-size: var(--t-body);
  line-height: 1.5;
  max-width: 40ch;
}

/* One filled pill and one plain link, both flush to the rail. */
.sec-cta-band .ctab__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s12) var(--s28);
  margin-top: var(--s40);
}
.sec-cta-band .ctab__wa {
  /* .alink is a text link; give it a real hit target anyway. */
  min-height: 44px;
  padding-inline: 4px;
}

/* — The close ————————————————————————————————
   Full page measure, flush left, with a 2px ink tab thickening its left end and
   the fine print hanging off exactly that end. */
.sec-cta-band .ctab__foot {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  margin-top: var(--s48);
}
.sec-cta-band .ctab__rule {
  position: relative;
  display: block;
  width: 100%;
  height: 1px;
  background: var(--hair-strong);
}
.sec-cta-band .ctab__rule::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0;
  width: 76px;
  height: 2px;
  background: var(--ink);
}
.sec-cta-band .ctab__fine { margin-top: var(--s20); color: var(--ash); }

/* — The objects ———————————————————————————————
   Placed against the section, not the wrap, so their crops are measured from
   the viewport edge and stay identical at every desktop width. */
.sec-cta-band .ctab__stage {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 1;
}

/* THE SLAB. Anchored to the BOTTOM, never the top: the shared shell gives a
   first-child section 44px of extra top padding, and bottom anchoring is the
   only way the crop and the offset against the type read identically on a real
   page and in the isolated preview. Its HEIGHT is declared rather than derived,
   because the menu inside deliberately overruns it — that overrun is what
   guarantees the slab is never a part-empty dark field at any width. */
.sec-cta-band .ctab__art {
  position: absolute;
  right: -108px;
  bottom: -130px;
  /* 53vw keeps the overhang constant while the slab narrows with the viewport,
     so it can never reach across into the rail. At 1440 the slab's left edge
     lands at x=788, ~200px off the headline's ragged right — the hole the last
     round left between the two masses was 550px wide. */
  width: min(760px, 53vw);
  height: 768px;
}
.sec-cta-band .ctab__card {
  /* Overhang + 28px, so the price column ends well inside the cut and the edge
     always falls through whitespace. */
  --crop: 136px;
  /* The one dark mass. No shadow: elevation belongs to .artifact, and a slab
     this heavy separates on value alone. */
  --slab-hair: color-mix(in srgb, var(--paper) 58%, transparent);
  height: 100%;
  background: var(--ink);
  color: var(--paper);
  border-radius: var(--r-card);
  text-align: left;
  overflow: hidden;
}

.sec-cta-band .ctab__card-top {
  display: flex;
  align-items: center;
  gap: var(--s16);
  padding: 24px var(--crop) 20px 30px;
  border-bottom: 1px solid var(--slab-hair);
}
.sec-cta-band .ctab__card-title {
  font-size: 15px;
  font-weight: 500;
  letter-spacing: -0.008em;
  color: var(--paper);
  white-space: nowrap;
}
/* The single confirmation beat in the whole band, so it is the highest-contrast
   thing in it: paper on ink, on the same flush right column as every value and
   every price below it. */
.sec-cta-band .ctab__chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-left: auto;
  height: 24px;
  padding-inline: 11px;
  border-radius: var(--r-pill);
  background: var(--paper);
  color: var(--ink);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: -0.004em;
  white-space: nowrap;
}

.sec-cta-band .ctab__list { list-style: none; margin: 0; padding: 0; }
.sec-cta-band .ctab__list li {
  display: flex;
  align-items: baseline;
  gap: 12px;
  padding: 13px var(--crop) 13px 30px;
  font-size: 13.5px;
  line-height: 1.3;
}
.sec-cta-band .ctab__list li + li { border-top: 1px solid var(--slab-hair); }
.sec-cta-band .ctab__k { color: var(--smoke); white-space: nowrap; }
/* One flush right edge shared by the chip, every value here and every price in
   the menu below — the column that makes the slab read as one object. */
.sec-cta-band .ctab__v {
  margin-left: auto;
  color: var(--paper);
  font-weight: 450;
  white-space: nowrap;
}

/* — The menu, set ————————————————————————————
   28 priced rows under six small-caps headers. It overruns the slab's declared
   height by ~70px at 1440 and by more as the columns narrow, so the band always
   cuts it mid-row rather than leaving dark air at the bottom. */
.sec-cta-band .ctab__menu {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  column-gap: 36px;
  border-top: 1px solid var(--slab-hair);
  padding: 24px var(--crop) 0 30px;
}
.sec-cta-band .ctab__cat {
  font-size: 10.5px;
  font-weight: 500;
  line-height: 1.4;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--smoke);
  padding-bottom: 8px;
  border-bottom: 1px solid var(--slab-hair);
}
.sec-cta-band .ctab__rows { list-style: none; margin: 9px 0 22px; padding: 0; }
.sec-cta-band .ctab__rows li {
  display: flex;
  align-items: baseline;
  gap: 12px;
  padding-block: 4.5px;
  font-size: 12.5px;
  line-height: 1.34;
  letter-spacing: -0.002em;
  color: var(--paper);
}
.sec-cta-band .ctab__it { min-width: 0; }
/* The qualifier is part of the item name, not a second field — set in the same
   line at the same size, one step down in value. */
.sec-cta-band .ctab__it i { font-style: normal; color: var(--smoke); }
.sec-cta-band .ctab__pr { margin-left: auto; color: var(--paper); white-space: nowrap; }

/* — The file tile ————————————————————————————
   A CHILD of the slab wrapper, hung across the slab's left edge at a fixed
   offset, so the object-on-object overlap is measured from the slab and cannot
   drift into the rail as the viewport narrows. It is also what closes the
   ~550px hole that used to sit between the headline and the card. */
.sec-cta-band .ctab__art3 {
  position: absolute;
  /* Crosses the slab's edge by 30px — exactly the slab's own left padding, so
     the overlap occludes surface and never a glyph. Vertically it straddles the
     hairline between the fact table and the menu, so it cuts a structural line
     rather than a row of type. */
  left: -192px;
  top: 232px;
  width: 214px;
}
.sec-cta-band .ctab__tile {
  display: flex;
  align-items: center;
  gap: 11px;
  /* Raised white, ringed rather than shadowed — elevation is reserved for
     .artifact. Most of the tile lies on the pale gradient, where an unringed
     white card has no edge at all. */
  background: var(--raised);
  border: 1px solid var(--hair-strong);
  border-radius: var(--r-small);
  padding: 12px 14px;
  transform: rotate(-2.5deg);
}
.sec-cta-band .ctab__tile-ico {
  flex: none;
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 11px;
  background: var(--mist);
  color: var(--slate);
}
.sec-cta-band .ctab__tile-txt { min-width: 0; }
.sec-cta-band .ctab__tile-name {
  display: block;
  font-size: 12.5px;
  font-weight: 500;
  line-height: 1.3;
  letter-spacing: -0.006em;
  color: var(--ink);
  white-space: nowrap;
}
.sec-cta-band .ctab__tile-meta {
  display: block;
  margin-top: 2px;
  font-size: 11px;
  line-height: 1.3;
  color: var(--slate);
  white-space: nowrap;
}
/* The second ink mass, hanging off the tile's left edge onto the gradient — a
   third overlap, at a third scale. */
.sec-cta-band .ctab__send {
  position: absolute;
  left: -19px;
  top: 12px;
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border-radius: var(--r-pill);
  background: var(--ink);
  color: var(--paper);
}

/* — The ticket ————————————————————————————————
   What the built shop prints: light, flat, no elevation, cut by the OPPOSITE
   edge and by the bottom. It sits below every line of type, so it can never
   collide with the rail at any viewport width. */
.sec-cta-band .ctab__art2 {
  position: absolute;
  left: -60px;
  width: 400px;
  /* Height is declared so the standing part is EXACTLY 130px at every width.
     The band's bottom padding is a constant 160px, so the ticket's top edge is
     always 30px clear of the fine print however the type above it reflows —
     anchoring by content height alone let it climb over the closing line at
     1024. */
  height: 260px;
  bottom: -130px;
}
.sec-cta-band .ctab__slip {
  height: 100%;
  background: var(--mist);
  border: 1px solid var(--hair-strong);
  border-radius: var(--r-card);
  /* Left padding is deeper than the 60px crop, so the viewport edge cuts empty
     card and never a glyph — the object is cropped, the type is not. */
  padding: 20px 24px 0 88px;
  overflow: hidden;
  /* Pivoted on its top-right corner, so the rotation can only ever drop the
     ticket away from the fine print, never lift it into the text. */
  transform: rotate(-4deg);
  transform-origin: 100% 0;
}
.sec-cta-band .ctab__slip-top {
  display: flex;
  align-items: baseline;
  gap: 16px;
  padding-bottom: 9px;
  border-bottom: 1px solid var(--hair-strong);
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--slate);
}
.sec-cta-band .ctab__slip-top span:last-child { margin-left: auto; }
.sec-cta-band .ctab__slip-rows { list-style: none; margin: 10px 0 0; padding: 0; }
.sec-cta-band .ctab__slip-rows li {
  display: flex;
  align-items: baseline;
  gap: 12px;
  padding-block: 5px;
  font-size: 12.5px;
  line-height: 1.34;
  letter-spacing: -0.002em;
  color: var(--ink);
  white-space: nowrap;
}
.sec-cta-band .ctab__q { flex: none; width: 12px; color: var(--slate); }
.sec-cta-band .ctab__slip-rows i { font-style: normal; color: var(--slate); }

/* — Narrower desktops —————————————————————————
   The objects are anchored to the viewport, so the crops hold all the way down;
   only the type measure and the menu's column count need to give. */
@media (max-width: 1180px) {
  .sec-cta-band .ctab { max-width: 620px; }
  .sec-cta-band .ctab__sub { max-width: 32ch; }
  .sec-cta-band .ctab__menu { column-gap: 28px; }
}
@media (max-width: 1080px) {
  .sec-cta-band .ctab { max-width: 500px; }
  .sec-cta-band .ctab__sub { max-width: 30ch; }
  .sec-cta-band .ctab__card { --crop: 126px; }
  .sec-cta-band .ctab__art3 { left: -166px; top: 206px; width: 196px; }
}

/* — Stacked ————————————————————————————————————
   Below 980 there is no room beside the rail, so the slab drops into flow
   between the CTA and the closing line. It is NOT a full-width block inside
   both gutters: it keeps its left edge on the rail, runs 24px past the right
   edge of the screen, and keeps the file tile lying across its top-left corner
   — the crop-and-overlap idea survives the breakpoint instead of being deleted
   at it. The stage is a sibling BETWEEN the two wraps in source for exactly
   this reason, so the page still ends on the closing line. */
@media (max-width: 980px) {
  .sec-cta-band .ctab { max-width: none; }
  .sec-cta-band .ctab__sub { max-width: 46ch; }

  .sec-cta-band .ctab__stage {
    position: relative;
    inset: auto;
    width: 100%;
  }
  .sec-cta-band .ctab__art {
    position: relative;
    inset: auto;
    width: auto;
    /* Tuned so the cut lands mid-row, never on a category header — an orphan
       header at the crop reads as a bug, a half-row reads as a crop. */
    height: 620px;
    /* Left edge on the rail; right edge 24px past the screen, cropped by the
       section's own overflow. */
    margin: var(--s64) -24px 0 var(--gutter);
    animation: none;
  }
  /* Room above the title for the tile to cross the corner without covering it. */
  .sec-cta-band .ctab__card { --crop: 48px; }
  .sec-cta-band .ctab__card-top { padding: 52px 48px 18px 26px; }
  .sec-cta-band .ctab__list li { padding: 13px 48px 13px 26px; }
  .sec-cta-band .ctab__menu {
    grid-template-columns: minmax(0, 1fr);
    padding: 22px 48px 0 26px;
  }
  .sec-cta-band .ctab__mcol:last-child { display: none; }

  .sec-cta-band .ctab__art3 {
    left: 10px;
    top: -30px;
    width: 200px;
    animation: none;
  }
  .sec-cta-band .ctab__art2 { display: none; }

  .sec-cta-band .ctab__foot { margin-top: var(--s64); }
}

/* — Phones ————————————————————————————————————
   The action row is capped to the measure of the copy above it, so it can never
   bulge wider than the sentence it belongs to. */
@media (max-width: 720px) {
  .sec-cta-band .ctab__h { max-width: 13ch; }
  .sec-cta-band .ctab__sub { margin-top: var(--s16); max-width: 32ch; }
  .sec-cta-band .ctab__actions {
    margin-top: var(--s32);
    max-width: 34ch;
    gap: var(--s8) var(--s20);
  }
  .sec-cta-band .ctab__art { margin-top: var(--s48); height: 480px; }
  .sec-cta-band .ctab__art3 { left: 6px; top: -28px; width: 184px; }
  .sec-cta-band .ctab__foot { margin-top: var(--s48); }
  .sec-cta-band .ctab__rule::before { width: 56px; }
}
