/* ==========================================================================
   AdminLess, company.adminless.ai, the landing page (company-v4, M3 build)

   THE DIRECTION IS "THE INDEX" (round 5, C3): the hero is a contents page.
   The first screen carries the h1, the lede, the ask and then the page's
   own four claims as a numbered index (§6b), each row an anchor to the
   band that proves it; the bar keeps only the wordmark and the ask, and
   the three bands the index points at open with their index entry (§5).

   One page, eight bands, paper and navy ink alternating: the hero on its
   steel-blue plate, #build on paper, #how on the ink-navy plate, #work on
   the facade at dusk, then #why-us, #book and #faq on paper and a flat deep
   footer. Colour and type are read from custom properties (§1), so a
   re-skin is one block, but nothing at runtime writes them.

   Tokens, gutters, buttons and credentials come from tokens.css (imported
   before this file). This page may not redefine them. Its one declared
   exception (website/LANDING_PAGES.md): the h1 is 72px here, 56 from 1279
   down and 40 on a phone (§3, §16).

   ⚠ NO INLINE STYLE ANYWHERE IN index.html. The nginx.conf beside this file
   serves `style-src 'self'` with no 'unsafe-inline', which blocks a style=""
   attribute exactly as hard as a <style> block. Anything new goes here.

   House rules honoured in CSS, not just in copy:
     · the hero entrance (§6) and the loop (§7) are the only authored motion;
       nothing below the hero animates on scroll, there is no reveal;
     · elevation is declared once, the loop card's shadow (§7), and nothing
       else casts one; no cards, no hairline between bands, no monospace,
       and the only uppercase left on the page is the loop's week labels
       W1..W8 and the wordmark;
     · no opacity on a meaningful graphic.
   ========================================================================== */

/* --------------------------------------------------------------------------
   0. Type, self-hosted. No Google Fonts request: `font-src 'self'` forbids
      it, and a third-party font origin hands that third party the IP address
      of every visitor to a page that sets no cookie and shows no banner.
      Fraunces is variable, so one file per subset covers 400 and 500; the
      italic is a separate file and carries the h1's second beat and every
      accented phrase in an h2.
   -------------------------------------------------------------------------- */

/* ⚠ THE FOUR latin FILES BELOW ARE SUBSET TO THIS SITE, AND THERE IS NO BUILD
   STEP TO DO IT AGAIN (Jake, 2026-09-15). They went from 184.8 KB to 102.0 KB
   - all of it on the critical path, three of them preloaded - by keeping only
   the glyphs these four pages render and only the axis ranges they ask for:

     glyphs   U+0020-007E, plus A0 B7 D7 2013 2018 2019 201C 201D 2026
              2039 203A 2192 21BB   (106 codepoints)
     axes     fraunces-var-latin          wght 400:500, opsz 20:76
              fraunces-var-italic-latin   opsz 20:76   (it has no wght axis)
              plex-sans-var-latin         wght 400:600

   The opsz bounds are MEASURED, not chosen: font-optical-sizing is auto, so
   the browser feeds the used font-size straight into opsz, and the display
   face renders between 20px (.h3 at 320) and 76px (the h1 at 1440). The wght
   bounds are the two values --display-weight and --display-weight-strong
   resolve to, and 400/600 for the body face.

   SO: A COPY EDIT THAT INTRODUCES A NEW CHARACTER NEEDS THIS DONE AGAIN, or
   that character falls back to Georgia mid-word. Re-run it with fonttools
   (pip install fonttools brotli) - load the file, limit the axes with
   fontTools.varLib.instancer, subset with the codepoints above, save with
   flavor woff2. The -ext files are NOT subset and are untouched: their
   unicode-range holds nothing these pages use, so a browser never requests
   one, and they stay whole as the fallback if that ever stops being true. */


@font-face {
  font-family: Fraunces;
  font-style: normal;
  font-weight: 400 500;
  font-display: swap;
  src: url("fonts/fraunces-var-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: Fraunces;
  font-style: normal;
  font-weight: 400 500;
  font-display: swap;
  src: url("fonts/fraunces-var-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: Fraunces;
  font-style: italic;
  font-weight: 400 500;
  font-display: swap;
  src: url("fonts/fraunces-var-italic-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: Fraunces;
  font-style: italic;
  font-weight: 400 500;
  font-display: swap;
  src: url("fonts/fraunces-var-italic-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url("fonts/plex-sans-var-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url("fonts/plex-sans-var-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* --------------------------------------------------------------------------
   1. The world (company-v4 DESIGN contract): paper, ink, muted ink, the navy
      accent kept from the brand, and the deep band. Every rule below reads
      these through the custom properties, so a re-skin is an edit here.
   -------------------------------------------------------------------------- */

:root {
  --paper:   #F7F5F0;   /* the paper */
  --paper-2: #FFFFFF;   /* raised surface: the loop's card, the one thing that casts a shadow */
  --paper-3: #EEEBE4;   /* recessed surface */
  --ink:     #141821;
  --accent:  #27506F;   /* navy: CTA, links, active states */
  --accent-deep: #1D3F58;
  --accent2: #27506F;
  --accent2-ink: #27506F;
  --muted:   #A9A69E;   /* hairlines and decoration, never text */
  --muted-ink: #5B6270; /* muted at text sizes, 5.6:1 on the paper */
  --rule:    #E2DED5;
  --on-accent: #FFFFFF;
  --deep:    #0E1420;   /* the dark band */
  --logo-blend: multiply;
  /* every credential mark in one value: grey, at .78 (§10b), so no lockup
     outweighs another */
  --logo-filter: grayscale(1);

  /* The one colour the preset never supplied: an invalid form field has to
     be told apart from a valid one by something other than the accent, and
     the accent is the only non-neutral in this palette. 7.4:1 on the paper,
     so it is AA at any size. It is a red, not a green, "never a green on
     this page" (LANDING_PAGES.md) is about the brand accent and stands. */
  --error:   #A3231D;

  --font-display: Fraunces, "Iowan Old Style", Georgia, serif;
  --font-body: "IBM Plex Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  /* NO MONOSPACE ANYWHERE ON THE PAGE (DESIGN contract): every label - the
     wordmark, the device labels, the step numbers - reads the sans through
     this one token. The monospace faces and their files are gone. */
  --font-label: var(--font-body);
  /* the light steel tint: the second beat of an h2 on a dark band, and the
     step numbers in #how. 7.2:1 on the deep navy. */
  --steel:   #9FB8CC;
  --display-weight: 400;
  --display-weight-strong: 500;
  --display-style: normal;

  /* The sticky bar's height, and the only number the one-screen contract
     (§5) and the anchor offset (§17) read. The bar measures 65px at desk
     widths (64px min-height plus its hairline) and 78px is that plus the
     13px of air every anchored jump on this page has always landed with, so
     a section sized 100svh - var(--navh) sits exactly between the bar and
     the fold.

     ⚠ THE VALUE HERE IS THE FALLBACK. .nav__links wraps as the window
     narrows, the bar is 115px at 700 and 167px at 375, so mnc.js §4
     measures it and writes the real number onto the root element. This is
     what a reader with that file blocked gets, and it is right wherever the
     bar is one row. */
  --navh: 78px;

  /* The band rhythm: fluid clamp for clean fit from 1280x800 to 4K */
  --band-top: clamp(40px, 5vh, 72px);
  --band-bottom: clamp(30px, 4vh, 60px);
  --band-gap: clamp(20px, 3vh, 40px);
}

/* --------------------------------------------------------------------------
   2. Reset and page shell. The page IS the frame this round: no dark stage,
      paper runs to the edge of the window.
   -------------------------------------------------------------------------- */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-snap-type: y proximity;
}
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
    scroll-snap-type: none;
  }
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--body);
  line-height: 1.6;
}

img { max-width: 100%; display: block; }

/* one global focus treatment for every interactive element on the page */
:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
/* Selection: the accent at 22% over the paper, flattened to one hex
   (#27506F over #F7F5F0 at .22 = #C9D1D4), ink on top. Page-wide. */
::selection { background: #C9D1D4; color: var(--ink); }

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 20;
  background: var(--accent);
  color: var(--on-accent);
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: 500;
  padding: 12px 18px;
  text-decoration: none;
}
.skip:focus { left: 0; }

.page {
  position: relative;
  width: 100%;
  max-width: 1440px;
  margin: 0 auto;
  background: var(--paper);
}

/* Clip horizontally at the page edges, never a scroll, while vertical motion
   stays untouched. (clip, not hidden: a clip box never becomes a scroll
   container, so the fixed nav keeps behaving.) */
html, body { overflow-x: clip; }

/* Fine paper grain, inline feTurbulence, ~3.5%. Decorative, never a photo. */
.page::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 9;
  pointer-events: none;
  opacity: 0.035;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='200' height='200'><filter id='g'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='4' stitchTiles='stitch'/></filter><rect width='200' height='200' filter='url(%23g)'/></svg>");
}

/* Content width from the shared tokens: 1152px measure, side padding from
   --gutter (136.5px at 1440, 28px below 880). */
.wrap {
  position: relative;
  width: 100%;
  max-width: 1220px;
  margin: 0 auto;
  padding: 0 40px;
  box-sizing: border-box;
}

/* --------------------------------------------------------------------------
   3. Type primitives, sizes from the shared tokens, never redefined here
   -------------------------------------------------------------------------- */

/* Harvey's measure: 72px, weight 400, 1.05, -0.02em, two lines. The size is
   the shared token, never a second number: --h1 is 72 and steps to 40 at
   880 (tokens.css); this page's one declared exception is the 56px middle
   step at 1279 (§16), which tokens.css has no tier for. */
.h1 {
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-weight: var(--display-weight);
  font-style: var(--display-style);
  font-size: var(--h1);
  line-height: 1.05;
  letter-spacing: -0.02em;
  margin: 0;
  color: var(--ink);
}
/* Two beats, one per line, the headline never wraps mid-phrase. */
.h1 span { display: block; }
.h1 em { font-style: italic; color: var(--accent2); font-weight: var(--display-weight); }

.h2 {
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-weight: var(--display-weight);
  font-style: var(--display-style);
  font-size: var(--h2);
  line-height: 1.1;
  letter-spacing: -0.014em;
  margin: 0;
  color: var(--ink);
  max-width: 22ch;
}
.h2 em { font-style: italic; color: var(--accent2-ink); }

.h3 {
  font-family: var(--font-display);
  font-weight: var(--display-weight-strong);
  font-style: var(--display-style);
  font-size: var(--h3);
  line-height: 1.22;
  letter-spacing: -0.008em;
  margin: 0;
  color: var(--ink);
}

.lede { font-size: var(--body); line-height: 1.6; margin: 22px 0 0; color: var(--ink); max-width: 50ch; }
.body { font-size: var(--body); line-height: 1.62; color: var(--ink); margin: 0; }
.small { font-size: var(--label); line-height: 1.55; color: var(--muted-ink); margin: 0; }

/* THE FAMILY'S ONE INLINE EMPHASIS DEVICE (ROUND5.md §7). On this page it is
   colour and weight only - the accent at 500, no ground, no padding, no box
   (the world: no boxes anywhere but the loop card). ONE PHRASE PER SECTION:
   a band with three highlights has none. Never inside a heading; on the dark
   bands the second beat is the h2's own <em> in the steel tint (§5), which
   this rule does not touch. Page-wide, hero card included: .vp__cap needs no
   override of its own. */
.em { color: var(--accent); font-weight: 500; }

/* --------------------------------------------------------------------------
   4. Nav and buttons. THE BAR IS NOT THE NAVIGATION HERE - the hero's
      index is (§6b) - so the bar is the wordmark and the ask and nothing
      between them, at every width. It is fixed and transparent OVER the
      hero plate: no ground, no hairline. Once the page has scrolled past
      the hero (mnc.js §5 watches #hero and toggles .is-scrolled) it takes
      the paper and a 1px hairline, the only hairline the bar ever has.
      mnc.js §4 measures it into --navh, which is what the anchored jumps
      below the fold land with as air above the heading. Hit boxes ≥ 44px.
   -------------------------------------------------------------------------- */

.navbar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 8;
  background: transparent;
  border-bottom: 1px solid transparent;
  transition: background-color 180ms ease, border-color 180ms ease;
}
.navbar.is-scrolled {
  background: var(--paper);
  border-bottom-color: rgba(20, 24, 33, .08);
}
/* the bar stays disciplined inside the 1220px container */
.navbar .wrap {
  max-width: 1220px;
  margin: 0 auto;
  padding: 0 40px;
  box-sizing: border-box;
}

.nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  row-gap: 10px;
  min-height: 64px;
  padding: 8px 0;
}

.nav__mark {
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.08em;
  color: var(--ink);
  text-decoration: none;
  white-space: nowrap;
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}
.nav__mark span,
.nav__slash { color: var(--accent); }

.nav__links { display: flex; align-items: center; flex-wrap: wrap; gap: 8px 28px; }

/* every anchor carries a 44px-tall hit box, whether it is a text link or
   the filled CTA, the family floor, not a per-element decision */
.nav__links a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}

.nav__links a:not(.btn) {
  font-family: var(--font-body);
  font-size: 15px;
  font-weight: 500;
  color: var(--ink);
  text-decoration: none;
  padding: 0 2px;
  border-bottom: 1px solid transparent;
  white-space: nowrap;
}
.nav__links a:not(.btn):hover { color: var(--accent); border-bottom-color: var(--accent); }

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: var(--btn-h);
  padding: 12px 22px;
  border-radius: 4px;
  border: 1px solid transparent;
  font-family: var(--font-body);
  font-size: 15px;
  font-weight: 500;
  line-height: 1.2;
  text-decoration: none;
  cursor: pointer;
  transition: background-color 120ms ease, color 120ms ease, border-color 120ms ease, transform 120ms ease;
}
/* a label swap must not change the primary button's shape */
.btn--primary { min-width: var(--btn-min); }

.btn--primary { background: var(--accent); color: var(--on-accent); }
/* THE HOVER HAS TO BE FELT (round 5). The ground steps to --accent-deep and
   the button lifts 1px; on the dark bands the ground is already paper, so
   the lift is the whole of the answer there. */
.btn--primary:hover { background: var(--accent-deep); transform: translateY(-1px); }

.btn--ghost { border-color: var(--rule); color: var(--ink); background: transparent; }
.btn--ghost:hover { border-color: var(--accent); color: var(--accent); }
@media (prefers-reduced-motion: reduce) {
  .btn:hover { transform: none; }
}

.cta-row { display: flex; align-items: center; gap: 18px; margin-top: 34px; flex-wrap: wrap; }

/* --------------------------------------------------------------------------
   5. Section scaffolding. No hairline between bands and no tint: a band is
      paper or it is a plate. The rhythm is §1's three numbers, and there is
      more space above a heading than below it.
   -------------------------------------------------------------------------- */

.sec {
  position: relative;
  box-sizing: border-box;
  scroll-margin-top: 0;
}

@media (min-width: 601px) {
  #hero,
  .sec {
    scroll-snap-align: start;
    scroll-snap-stop: normal;
    min-height: 100svh;
    display: flex;
    flex-direction: column;
    justify-content: center;
    box-sizing: border-box;
    padding: clamp(28px, 4.5vh, 60px) 0;
  }
  .sec .sec__inner {
    width: 100%;
    position: relative;
  }
  #book {
    scroll-snap-align: none !important;
    min-height: auto;
    display: flex;
    flex-direction: column;
    justify-content: flex-start;
    padding-top: calc(var(--navh, 72px) + 16px);
    padding-bottom: clamp(24px, 3.5vh, 44px);
  }
  #close {
    scroll-snap-align: start;
    min-height: calc(100svh - 100px);
    display: flex;
    flex-direction: column;
    justify-content: center;
  }
}

@media (max-width: 600px) {
  html { scroll-snap-type: none; }
  #hero, .sec, #close {
    scroll-snap-align: none;
    min-height: auto;
    padding: 56px 0;
  }
}
/* ROUND5.md §3: every section carries exactly ONE heading, which states the
   reader's gain in the second person. .h2's own 22ch measure is for a
   three-word headline; these are a sentence and a half. */
.sec__title { max-width: 30ch; margin-bottom: 36px; }

/* THE INDEX'S KEY, the one numbering on this page (round 5, "the index").
   The hero prints the page's contents as four numbered rows; the three
   bands those rows point at open with the entry that points at them - the
   number, then the same words. It is shaped like an eyebrow and it is not
   one: an eyebrow is a category written to fill the space over a heading,
   this is the line the reader clicked, printed where they landed, so the
   jump is confirmed by the words they chose. Two entries point at #how, so
   #how carries both; the "·" belongs to the item BEFORE it (the footer's
   rule, §15), so a wrapped line can never begin with a separator. */
.sec__key {
  margin: 0 0 20px;
  display: flex;
  flex-wrap: wrap;
  font-size: 15px;
  line-height: 1.5;
  color: var(--muted-ink);
}
.sec__key-n { font-weight: 500; color: var(--accent); font-variant-numeric: tabular-nums; }
.sec__key-i:not(:last-child)::after { content: "\00b7"; margin: 0 0.6em; color: var(--muted); }
.sec--plate .sec__key { color: rgba(247, 245, 240, .72); }
.sec--plate .sec__key-n { color: var(--steel); }
.sec--plate .sec__key-i:not(:last-child)::after { color: rgba(247, 245, 240, .38); }

/* ONE SECTION, ONE SCREEN, for the hero and the first paper band only
   (Jake, 2026-09-15): the hero is the first screen and a jump to #build
   lands the whole band between the bar and the fold. The bands below are
   sized by the rhythm above; a floor there would leave empty paper under a
   short band. 100vh first, 100svh second: a browser without svh keeps the
   old unit. */
/* ONE SECTION, ONE SCREEN applies to hero only; subsequent sections flow naturally. */

/* THE PLATE BANDS (#how, #work). The plate is absolute under the band and a
   navy veil sits over it, so the band's copy is always on the dark whatever
   the plate's lightest area is; isolation keeps the two negative layers under
   the copy and above the page. --veil is set per band and is a background
   list, so a band can grade its veil:
     · #how: .40 flat, plus a ramp that darkens from 40% down to .55 at the
       bottom - the brushwork shows where the copy is not (the top, between
       the columns) and the price line still sits on dark;
     · #work: .55 at the top, .78 by the text band (--band-top), so the two
       plates read as two materials at the join with no rule between them;
       then the last 120px grade into the page's paper, so the band ends
       in paper and not on a hard cut mid-building.
   The type is paper, the h2's second beat in the steel tint, body at .82
   paper (9.8:1 on the veiled navy). The primary button turns paper on the
   dark, and the focus ring with it. */
.sec--plate {
  isolation: isolate;
  color: var(--paper);
  background: var(--deep);
}
.plate,
.plate img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
.plate { z-index: -2; }
.plate img { object-fit: cover; object-position: 50% 50%; }
.sec--plate::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: var(--veil);
}
#how  { --veil: linear-gradient(to bottom, transparent 40%, rgba(14, 20, 32, .55)), rgba(14, 20, 32, .40); }
/* the grade is 80px, not 120: the index direction puts the example screen's
   caption at the band's foot, and 80 leaves it 24px of dark to sit on while
   keeping the whole of the band's closing air to 104px */
#work { --veil: linear-gradient(to bottom, rgba(14, 20, 32, .55), rgba(14, 20, 32, .78) var(--band-top), rgba(14, 20, 32, .78) calc(100% - 80px), #F7F5F0); }
.sec--plate .h2 { color: var(--paper); font-size: 48px; }
.sec--plate .h2 em { color: var(--steel); }
.sec--plate .h3 { color: var(--paper); }
.sec--plate .btn--primary { background: var(--paper); color: var(--ink); }
.sec--plate .btn--primary:hover { background: var(--paper-2); }
.sec--plate :focus-visible { outline-color: var(--paper); }

/* --------------------------------------------------------------------------
   6. Hero: THE HERO IS THE PLATE. The steel-blue gouache covers the whole
      first screen (100svh, never under 760px) and a paper veil runs over it
      left to right - solid paper to 48%, clear by 68% - so the copy sits on
      paper and the brushwork stays visible on the right, under the loop's
      card. The plate is MIRRORED: its dark slate mass is painted on the
      left of the file, and the copy owns the left here. The file is a
      painted card, and its paper edge shows at the top right and the
      bottom, so the crop goes INTO the brushwork: cover, anchored to the
      file's right (the mirrored copy side, under the solid veil), then
      scaled 1.3 about the centre. Checked by rendering the crop at
      1440x900, 1280x800, 1024x768, 768x1024 and 375x667/890: no card edge
      in the window at any of them; the slate mass sits under the card.
      isolation: isolate keeps the plate (z -2) and the veil (z -1) under
      the in-flow content and above the section's own paper.
      The h1 lines rise 12px and fade in over 560ms, staggered 70ms, the
      lede and the CTA 80ms behind; once, on load, and not at all under
      prefers-reduced-motion. Nothing else on the page animates on scroll.
   -------------------------------------------------------------------------- */

#hero {
  position: relative;
  isolation: isolate;
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  box-sizing: border-box;
  padding: clamp(72px, 9vh, 100px) 0 clamp(36px, 5vh, 48px);
  background: var(--paper);
}
.hero__plate,
.hero__plate img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
.hero__plate { z-index: -2; }
.hero__plate img {
  object-fit: cover;
  object-position: 100% 50%;
  transform: scaleX(-1) scale(1.3);
}
#hero::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: linear-gradient(90deg, #F7F5F0 0%, #F7F5F0 48%, rgba(247, 245, 240, 0) 68%);
}

/* Refined executive spread: Headline/CTA + interactive cycle card side by side,
   anchored by the 4-pillar Ledger bar below. Fluid clamp fit ensures natural
   window fitting from 1280x800 to 4K displays without truncation or voids. */
.hero {
  display: grid;
  grid-template-columns: 1fr 1fr;
  align-items: center;
  column-gap: 56px;
  row-gap: clamp(16px, 2.5vh, 28px);
  padding: 0;
  width: 100%;
  box-sizing: border-box;
}
.hero__copy { max-width: 100%; grid-column: 1; }
.hero .lede { max-width: 48ch; font-size: var(--body); line-height: 1.6; margin-top: clamp(14px, 2vh, 20px); }
.hero .cta-row {
  margin-top: clamp(16px, 2.4vh, 26px);
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 14px 22px;
}
.hero__aud { margin: 0; font-size: 15px; line-height: 1.5; color: var(--accent); }

/* --------------------------------------------------------------------------
   6b. THE LEDGER INDEX (C3-C "The Modern Enterprise Ledger").
       The index is styled as a sleek horizontal 4-pillar bar directly
       beneath the executive spread. Spans full hero width with tabular
       numerals, category tags, and responsive column division.
   -------------------------------------------------------------------------- */

.hero__index {
  grid-column: 1 / -1;
  width: 100%;
  margin-top: clamp(16px, 2.4vh, 28px);
  max-width: none;
}
.idx--ledger {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  list-style: none;
  margin: 0;
  padding: 0;
  background: rgba(255, 255, 255, 0.85);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border: 1px solid var(--rule);
  border-radius: 8px;
  box-shadow: 0 4px 20px -8px rgba(20, 24, 33, 0.08);
  overflow: hidden;
}
.idx__pillar {
  border-right: 1px solid var(--rule);
  display: flex;
}
.idx__pillar:last-child {
  border-right: none;
}
.idx__link {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 8px;
  width: 100%;
  padding: clamp(12px, 1.5vh, 18px) clamp(14px, 1.4vw, 22px);
  text-decoration: none;
  color: var(--ink);
  min-height: 52px;
  transition: background 150ms ease, color 150ms ease;
}
.idx__link:hover {
  background: rgba(39, 80, 111, 0.05);
}
.idx__link:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}
.idx__pillar-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.idx__no {
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--accent);
  letter-spacing: 0.04em;
}
.idx__tag {
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted-ink);
  padding: 2px 6px;
  background: rgba(20, 24, 33, 0.05);
  border-radius: 3px;
}
.idx__chev {
  width: 8px;
  height: 12px;
  stroke: var(--accent);
  fill: none;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: transform 140ms ease;
}
.idx__link:hover .idx__chev {
  transform: translateX(3px);
}
.idx__lbl {
  font-family: var(--font-display);
  font-size: clamp(14px, 1.1vw, 16px);
  font-weight: 500;
  line-height: 1.35;
  color: var(--ink);
  letter-spacing: -0.01em;
}
@media (prefers-reduced-motion: reduce) {
  .idx__chev { transition: none; }
  .idx__link:hover .idx__chev { transform: none; }
}

@media (prefers-reduced-motion: no-preference) {
  @keyframes hero-rise {
    from { opacity: 0; transform: translateY(12px); }
    to   { opacity: 1; transform: none; }
  }
  .hero .h1 span,
  .hero .lede,
  .hero .cta-row,
  .hero__index,
  .hero__aud { animation: hero-rise 560ms cubic-bezier(.16, 1, .3, 1) both; }
  .hero .h1 span:nth-child(2) { animation-delay: 70ms; }
  .hero .lede { animation-delay: 150ms; }
  .hero .cta-row { animation-delay: 230ms; }
  .hero__aud { animation-delay: 310ms; }
  .hero__index { animation-delay: 380ms; }
}

/* --------------------------------------------------------------------------
   7. Hero cycle: tabs, stage, and the three panels' shared frame.
      Three reasons to buy, one drawing each, no two in the same grammar:
      01 the app growing across eight demo screens (.demo), 02 a plan sheet
      with its price tag stamped in week 1, unchanged while eight week ticks
      light up under it (.plan), 03 one person-mark walking
      PLAN -> BUILD -> PHONE and the data box leaving through the door (.ct).
      THE FINISHED FRAME IS THE DEFAULT STATE. Every draw lives under
      @media (prefers-reduced-motion: no-preference) and under .is-playing,
      which mnc.js puts on the panel it activates and takes off the one it
      leaves; a reader who blocks motion, or has no JS, meets each device
      finished; the only motion left to them is a 150ms opacity crossfade
      between panels. Easing is one curve, cubic-bezier(.23,1,.32,1); only
      transform, opacity, filter (2px of blur, panel crossfade only),
      stroke-dashoffset, background-color and (the stage, on a phone) height
      ever move.
   -------------------------------------------------------------------------- */
/* THE CARD. Paper-white, radius 12, the page's one shadow. It floats over
   the slate side of the plate, right-aligned to the 32px margin the nav CTA
   sits on; 560px wide, narrower where the column is. The tabs sit at its
   top edge, over the device and its caption. */
.hero__cycle {
  grid-column: 2;
  display: flex;
  flex-direction: column;
  justify-self: end;
  width: 100%;
  max-width: 540px;
  margin: 0;
  padding: 12px 28px 24px;
  background: var(--paper-2);
  border-radius: 12px;
  box-shadow: 0 20px 50px -24px rgba(14, 20, 32, .4);
}

/* The tabs: text, 15px sans, muted ink, the active one in ink over a 2px
   hairline track; a 44px hit box on every width. No pill. Transitions on
   colour and (the press) transform only. */
.cycle-tabs {
  display: flex;
  align-items: center;
  column-gap: 24px;
  row-gap: 0;
  margin: 0 0 18px;
  flex-wrap: wrap;
}

.cycle-tab {
  position: relative;
  min-height: 44px;
  font-family: var(--font-body);
  font-size: 15px;
  font-weight: 500;
  color: var(--muted-ink);
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  line-height: 1.3;
  user-select: none;
  -webkit-appearance: none;
  appearance: none;
  transition: color 180ms cubic-bezier(.23, 1, .32, 1), transform 120ms cubic-bezier(.23, 1, .32, 1);
}
.cycle-tab:active { transform: scale(.97); }
.cycle-tab.is-active { color: var(--ink); }
/* A HOVER GOES DARKER, NEVER LIGHTER: the label to ink, and the track under
   it to a hairline darker than the active tab's own - so the active tab
   answers a pointer too, which it did not before. */
.cycle-tab:hover { color: var(--ink); }
/* the track the fill runs on: a hairline under the active tab only, so the
   active one is told apart even where the fill never draws (JS off, reduced
   motion) */
.cycle-tab::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 6px;
  height: 2px;
  background: transparent;
  transition: background-color 180ms cubic-bezier(.23, 1, .32, 1);
}
.cycle-tab.is-active::before { background: var(--rule); }
.cycle-tab:hover::before { background: rgba(20, 24, 33, .28); }
.cycle-tab:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; border-radius: 2px; }

/* THE FILL IS THE TIMER (Linear's pattern): a 2px accent underline scaled
   from 0 to 1 across the dwell by mnc.js §1 (WAAPI, linear); the slide
   advances when it lands. Resting scaleX(0): an inactive tab, a paused
   page, a reader who blocks motion, and JS off all show no fill. */
.cycle-tab__fill {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 6px;
  height: 2px;
  background: var(--accent);
  transform-origin: left;
  transform: scaleX(0);
  pointer-events: none;
}

/* One grid cell, three panels stacked in it: the stage is as tall as the
   tallest panel, so the CTA under it never moves when the slide changes.
   On a phone (7e) the stage is instead as tall as the ACTIVE panel and
   mnc.js §1 animates its height between slides.

   THE CROSSFADE IS ASYMMETRIC: the leaving panel is gone in 200ms (up 4px,
   2px of blur), the arriving one takes 320ms (from 6px below, the same 2px
   of blur, to clear). mnc.js §1 puts .is-leaving on the panel it leaves
   and takes it off at animationend; .is-entering rides with .is-active and
   is re-added on every activation so the arrival replays. The blur is on
   the panel only, never on the page. No animation is keyed on .is-active
   itself: panel 1 is active in the HTML and must paint finished, not fade
   in. Base state = finished. */
.cycle-stage {
  display: grid;
  grid-template-columns: 1fr;
  align-items: start;
  position: relative;
  width: 100%;
}
.cycle-panel {
  grid-column: 1;
  grid-row: 1;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  width: 100%;
}
.cycle-panel.is-active {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  position: relative;
  z-index: 1;
}
.cycle-panel.is-leaving { visibility: visible; }
@media (prefers-reduced-motion: no-preference) {
  @keyframes cycle-out {
    from { opacity: 1; transform: none; filter: blur(0); }
    to   { opacity: 0; transform: translateY(-4px); filter: blur(2px); }
  }
  @keyframes cycle-in {
    from { opacity: 0; transform: translateY(6px); filter: blur(2px); }
    to   { opacity: 1; transform: none; filter: blur(0); }
  }
  .cycle-panel.is-leaving { animation: cycle-out 200ms cubic-bezier(.23, 1, .32, 1) both; }
  .cycle-panel.is-active.is-entering { animation: cycle-in 320ms cubic-bezier(.23, 1, .32, 1) both; }
}
@media (prefers-reduced-motion: reduce) {
  @keyframes cycle-out-still { from { opacity: 1; } to { opacity: 0; } }
  @keyframes cycle-in-still  { from { opacity: 0; } to { opacity: 1; } }
  .cycle-panel.is-leaving { animation: cycle-out-still 150ms linear both; }
  .cycle-panel.is-active.is-entering { animation: cycle-in-still 150ms linear both; }
}

/* Kicker above the device: 13px sans, sentence case, muted ink, numbered
   like a figure series; caption under it in ink with the reason's payoff in
   the accent, no highlight box. */
.vp__k {
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 500;
  color: var(--muted-ink);
  margin: 0 0 14px;
}
.vp__dev { width: 100%; }
.vp__cap {
  margin: 16px 0 0;
  font-size: 16px;
  line-height: 1.5;
  color: var(--ink);
}

/* THE DEVICE LABELS ARE SENTENCE CASE IN MUTED INK, like every other label
   on this page: these three devices were the only things breaking the
   page's own rule. Single-class specificity on purpose, so a device's own
   colour rule below wins by order.
   The week labels are the exception and they keep the uppercase: W1..W8 is
   a week number, not a phrase, and they are the only uppercase left inside
   the card. */
.plan__k,
.plan__same {
  font-family: var(--font-label);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
  line-height: 1.4;
  color: var(--muted-ink);
}
.demo__lbl,
.demo__live,
.plan__wks li {
  font-family: var(--font-label);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  line-height: 1.3;
  color: var(--muted-ink);
}

/* --------------------------------------------------------------------------
   7a. 01 THE OUTCOME: eight demo screens, W1..W8, the app growing one bar a
       week, the eighth screen filled and ticked, "live".
   -------------------------------------------------------------------------- */
.demo {
  display: grid;
  grid-template-columns: repeat(8, 1fr);
  gap: 6px;
  list-style: none;
  margin: 0;
  padding: 0;
}
.demo__wk { display: flex; flex-direction: column; align-items: center; gap: 6px; }
.demo__scr { width: 100%; height: auto; display: block; overflow: visible; }
.demo__fr { fill: none; stroke: var(--muted); stroke-width: 1.5; }
.demo__wk--live .demo__fr { stroke: var(--accent); }
.demo__fill { fill: var(--accent); }
.demo__bar { fill: var(--accent); fill-opacity: 0.55; transform-box: fill-box; transform-origin: left center; }
.demo__wk--live .demo__bar { fill: var(--on-accent); fill-opacity: 0.4; }
.demo__tick { fill: none; stroke: var(--on-accent); stroke-width: 3.5; stroke-linecap: round; stroke-linejoin: round; }
.demo__wk--live .demo__lbl,
.demo__live { color: var(--accent); }
.demo__live { margin-top: -4px; }

/* --------------------------------------------------------------------------
   7b. 02 THE PRICE: stillness under a moving clock. A plan sheet (a heading,
       a rule, five hairlines of text) with the price tag stamped over its
       lower right corner; eight week ticks beneath it light up one after
       another; the sheet and the tag never change, and "unchanged at week 8"
       lands beside the tag when the clock reaches W8.
   -------------------------------------------------------------------------- */
.plan { display: grid; row-gap: 10px; }
.plan__k {
  font-family: var(--font-label);
  font-size: 13px;
  font-weight: 500;
  color: var(--muted-ink);
}
.plan__desk {
  display: flex;
  align-items: center;
  gap: 24px;
}
.plan__sheet {
  flex: none;
  width: 100px;
  height: auto;
  aspect-ratio: 120 / 88;
  display: block;
  overflow: visible;
}
.plan__page { fill: #FFFFFF; stroke: var(--ink); stroke-width: 1.5; }
.plan__head { fill: none; stroke: var(--ink); stroke-width: 2.5; stroke-linecap: round; }
.plan__rule { fill: none; stroke: var(--rule); stroke-width: 1; }
.plan__line { fill: none; stroke: var(--muted); stroke-width: 1.2; stroke-linecap: round; }

.plan__stamp {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: flex-start;
  gap: 8px;
  margin: 0;
  min-width: 0;
  flex: 1;
}
.plan__tag {
  display: inline-flex;
  align-items: center;
  padding: 4px 10px;
  border-radius: 4px;
  border: 1px solid var(--rule);
  background: #FFFFFF;
  box-shadow: 0 1px 3px rgba(20, 24, 33, 0.05);
  font-family: var(--font-label);
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
  white-space: nowrap;
}
.plan__same {
  display: inline-flex;
  align-items: center;
  font-family: var(--font-label);
  font-size: 13px;
  font-weight: 500;
  line-height: 1.4;
  color: var(--accent);
  white-space: nowrap;
}
.plan__wks {
  display: grid;
  grid-template-columns: repeat(8, 1fr);
  list-style: none;
  margin: 4px 0 0;
  padding: 0;
  border-top: 1px solid var(--rule);
}
.plan__wks li {
  position: relative;
  padding-top: 8px;
  text-align: center;
  font-family: var(--font-label);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  color: var(--accent);
}
.plan__wks li::before {
  content: "";
  position: absolute;
  top: 0;
  left: 50%;
  width: 1px;
  height: 6px;
  background-color: currentColor;
}

/* --------------------------------------------------------------------------
   7c. 03 ONE TEAM, YOUR DATA (.ct): THE SAME DRAWING AS THE AGENCY PAGE,
       lifted verbatim, only the tag text differs. Three seats under three
       station names; ONE person-mark that rests at PHONE by two nested hops
       of 100 units, and the trail it leaves: an outlined ghost of the same
       mark on each seat it departed and a hairline joining seat to seat at
       shoulder height, so the resting frame still reads as one person in
       three places. The box and the door share a row that is its own
       container, so the box's landing is its width and the row's width
       whatever the column measures.
   -------------------------------------------------------------------------- */
.ct { display: grid; row-gap: 8px; }

.ct__stations {
  margin: 0;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  text-align: center;
  font-family: var(--font-label);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
  line-height: 1.4;
  color: var(--muted-ink);
}

.ct__row { display: block; width: 100%; height: auto; overflow: visible; }
.ct__seat { fill: none; stroke: var(--muted); stroke-width: 1.2; stroke-linecap: round; }

/* ONE mark. It rests at PHONE: two nested hops of 100 units each. */
.ct__person { fill: var(--accent); transform-box: fill-box; transform-origin: center; }
.ct__hop1, .ct__hop2 { transform: translateX(100px); }

/* the trail: as the mark departs a seat, an outlined copy of the same mark
   stays behind at 35%, and a hairline joins seat to seat at shoulder height.
   Finished frame: two ghosts, one solid mark, one line. */
.ct__ghost { fill: none; stroke: var(--accent); stroke-width: 1.2; opacity: 0.35; }
.ct__link { fill: none; stroke: var(--rule); stroke-width: 1; }

.ct__own {
  container-type: inline-size;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: 4px;
  overflow: visible;
}
.ct__box {
  position: relative;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 0;
  font-family: var(--font-label);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0;
  line-height: 1.4;
  color: var(--muted-ink);
  white-space: nowrap;
  transform: translateX(calc(100cqw - 100% - 46px));
}
.ct__lock { width: 11px; height: 13px; display: block; fill: none; stroke: currentColor; stroke-width: 1.4; stroke-linejoin: round; }
.ct__door {
  flex: none;
  display: block;
  width: 30px;
  height: 44px;
  margin-left: auto;
  overflow: visible;
}
.ct__frame { fill: none; stroke: var(--ink); stroke-width: 1.5; stroke-linejoin: round; }
.ct__leaf  { fill: none; stroke: var(--muted-ink); stroke-width: 1.2; stroke-linejoin: round; }

.ct__go {
  margin: 0;
  text-align: right;
  font-family: var(--font-label);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
  line-height: 1.4;
  color: var(--muted-ink);
}

/* --------------------------------------------------------------------------
   7d. The draws. Start frames live in the keyframes (fill-mode: both), so
       nothing here touches the resting state above; total per device <= 1.4s.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: no-preference) {
  @keyframes vp-stroke { from { stroke-dashoffset: 1; } to { stroke-dashoffset: 0; } }
  @keyframes vp-fade   { from { opacity: 0; } to { opacity: 1; } }
  @keyframes vp-grow-x { from { opacity: 0; transform: scaleX(0); } to { opacity: 1; transform: scaleX(1); } }
  @keyframes vp-grow-y { from { transform: scaleY(0); } to { transform: scaleY(1); } }
  @keyframes vp-pop    { from { opacity: 0; transform: scale(0); } to { opacity: 1; transform: scale(1); } }
  @keyframes vp-pop-in { from { opacity: 0; transform: scale(0.6); } to { opacity: 1; transform: scale(1); } }

  /* 01: frame i strokes in at (i-1)*90ms; its bars grow from the left 120ms
     later, 25ms apart; W8 fills at 1.05s, ticks at 1.15s, "live" at 1.2s. */
  .is-playing .demo__fr { stroke-dasharray: 1; animation: vp-stroke 300ms cubic-bezier(.23, 1, .32, 1) both; animation-delay: var(--d); }
  .is-playing .demo__lbl { animation: vp-fade 200ms cubic-bezier(.23, 1, .32, 1) both; animation-delay: var(--d); }
  .is-playing .demo__bar { animation: vp-grow-x 220ms cubic-bezier(.23, 1, .32, 1) both; animation-delay: calc(var(--d) + 120ms + var(--b)); }
  .is-playing .demo__fill { animation: vp-fade 220ms cubic-bezier(.23, 1, .32, 1) 1050ms both; }
  .is-playing .demo__tick { stroke-dasharray: 1; animation: vp-stroke 250ms cubic-bezier(.23, 1, .32, 1) 1150ms both; }
  .is-playing .demo__live { animation: vp-fade 200ms cubic-bezier(.23, 1, .32, 1) 1200ms both; }
  .demo__wk:nth-child(1) { --d: 0ms; }
  .demo__wk:nth-child(2) { --d: 90ms; }
  .demo__wk:nth-child(3) { --d: 180ms; }
  .demo__wk:nth-child(4) { --d: 270ms; }
  .demo__wk:nth-child(5) { --d: 360ms; }
  .demo__wk:nth-child(6) { --d: 450ms; }
  .demo__wk:nth-child(7) { --d: 540ms; }
  .demo__wk:nth-child(8) { --d: 630ms; }
  .demo__bar:nth-child(1) { --b: 0ms; }
  .demo__bar:nth-child(2) { --b: 25ms; }
  .demo__bar:nth-child(3) { --b: 50ms; }
  .demo__bar:nth-child(4) { --b: 75ms; }
  .demo__bar:nth-child(5) { --b: 100ms; }
  .demo__bar:nth-child(6) { --b: 125ms; }
  .demo__bar:nth-child(7) { --b: 150ms; }
  .demo__bar:nth-child(8) { --b: 175ms; }

  /* 02: the label lands at 0; the page strokes 0..300, its heading 100..280,
     the rule 140..320, the five lines from 180, 45ms apart, 160ms each, the
     last done at 520; the tag stamps down 380..580; then the clock: W1 lights
     at 580 and each next week 100ms later, W8 at 1280; "unchanged at week 8"
     lands 1280..1400. Nothing on the sheet moves after 580. Done at 1.40s. */
  @keyframes plan-stamp { from { opacity: 0; transform: scale(1.6); } to { opacity: 1; transform: none; } }
  @keyframes plan-lit { from { opacity: 0.25; } to { opacity: 1; } }
  .is-playing .plan__k { animation: vp-fade 250ms cubic-bezier(.23, 1, .32, 1) both; }
  .is-playing .plan__page { stroke-dasharray: 1; animation: vp-stroke 300ms cubic-bezier(.23, 1, .32, 1) both; }
  .is-playing .plan__head { stroke-dasharray: 1; animation: vp-stroke 180ms cubic-bezier(.23, 1, .32, 1) 100ms both; }
  .is-playing .plan__rule { stroke-dasharray: 1; animation: vp-stroke 180ms cubic-bezier(.23, 1, .32, 1) 140ms both; }
  .is-playing .plan__line { stroke-dasharray: 1; animation: vp-stroke 160ms cubic-bezier(.23, 1, .32, 1) both; animation-delay: var(--d); }
  .is-playing .plan__tag { animation: plan-stamp 200ms cubic-bezier(.23, 1, .32, 1) 380ms both; }
  .is-playing .plan__wks li { animation: plan-lit 120ms cubic-bezier(.23, 1, .32, 1) both; animation-delay: var(--d); }
  .is-playing .plan__same { animation: vp-fade 120ms cubic-bezier(.23, 1, .32, 1) 1280ms both; }
  .plan__line:nth-child(4) { --d: 180ms; }
  .plan__line:nth-child(5) { --d: 225ms; }
  .plan__line:nth-child(6) { --d: 270ms; }
  .plan__line:nth-child(7) { --d: 315ms; }
  .plan__line:nth-child(8) { --d: 360ms; }
  .plan__wks li:nth-child(1) { --d: 580ms; }
  .plan__wks li:nth-child(2) { --d: 680ms; }
  .plan__wks li:nth-child(3) { --d: 780ms; }
  .plan__wks li:nth-child(4) { --d: 880ms; }
  .plan__wks li:nth-child(5) { --d: 980ms; }
  .plan__wks li:nth-child(6) { --d: 1080ms; }
  .plan__wks li:nth-child(7) { --d: 1180ms; }
  .plan__wks li:nth-child(8) { --d: 1280ms; }

  /* 03: the agency page's timings, as keyframes. Stations and seats on a
     stagger (60/120/180ms); the one mark pops in at PLAN (180ms), hops to
     BUILD (520..840), hops to PHONE (880..1200); each time it leaves a seat
     its ghost fades in there (180ms) and the hairline draws to the next seat
     (320ms, the hop's own length): PLAN ghost + link 1 at 520, BUILD ghost +
     link 2 at 880. The door draws (300, 550); the box slides through it
     (950..1330); the label lands at 1.2s. Done at 1.40s. */
  @keyframes ct-hop { from { transform: translateX(0); } to { transform: translateX(100px); } }
  @keyframes ct-go  { from { transform: translateX(0); } to { transform: translateX(calc(100cqw - 100% - 46px)); } }
  @keyframes ct-ghost { from { opacity: 0; } to { opacity: 0.35; } }
  .is-playing .ct__station { animation: vp-fade 250ms cubic-bezier(.23, 1, .32, 1) both; animation-delay: var(--d); }
  .is-playing .ct__seat { stroke-dasharray: 1; animation: vp-stroke 300ms cubic-bezier(.23, 1, .32, 1) both; animation-delay: var(--d); }
  .ct__station:nth-child(1), .ct__seat:nth-child(1) { --d: 60ms; }
  .ct__station:nth-child(2), .ct__seat:nth-child(2) { --d: 120ms; }
  .ct__station:nth-child(3), .ct__seat:nth-child(3) { --d: 180ms; }
  .is-playing .ct__person { animation: vp-pop-in 250ms cubic-bezier(.23, 1, .32, 1) 180ms both; }
  .is-playing .ct__hop1 { animation: ct-hop 320ms cubic-bezier(.23, 1, .32, 1) 520ms both; }
  .is-playing .ct__hop2 { animation: ct-hop 320ms cubic-bezier(.23, 1, .32, 1) 880ms both; }
  .is-playing .ct__ghost--plan  { animation: ct-ghost 180ms cubic-bezier(.23, 1, .32, 1) 520ms both; }
  .is-playing .ct__ghost--build { animation: ct-ghost 180ms cubic-bezier(.23, 1, .32, 1) 880ms both; }
  .is-playing .ct__link--1 { stroke-dasharray: 1; animation: vp-stroke 320ms cubic-bezier(.23, 1, .32, 1) 520ms both; }
  .is-playing .ct__link--2 { stroke-dasharray: 1; animation: vp-stroke 320ms cubic-bezier(.23, 1, .32, 1) 880ms both; }
  .is-playing .ct__frame { stroke-dasharray: 1; animation: vp-stroke 300ms cubic-bezier(.23, 1, .32, 1) 300ms both; }
  .is-playing .ct__leaf  { stroke-dasharray: 1; animation: vp-stroke 250ms cubic-bezier(.23, 1, .32, 1) 550ms both; }
  .is-playing .ct__box { animation: vp-fade 200ms cubic-bezier(.23, 1, .32, 1) 150ms both, ct-go 380ms cubic-bezier(.23, 1, .32, 1) 950ms both; }
  .is-playing .ct__go { animation: vp-fade 200ms cubic-bezier(.23, 1, .32, 1) 1200ms both; }
}

@media (prefers-reduced-motion: reduce) {
  .cycle-tab,
  .cycle-tab::before,
  .cycle-stage { transition: none !important; }
}

/* --------------------------------------------------------------------------
   7e. Phone. Two things happen at 560, the same breakpoint mnc.js §1 asks
       for and the page's own phone tier (§16).
       THE TABS FIT ONE ROW AT 375: 14px, 20px apart, the 44px hit box
       unchanged.
       THE STAGE IS AS TALL AS THE ACTIVE PANEL, not the tallest: the
       inactive panels are lifted out of flow, so with no JS the stage is
       panel 1's height at first paint, and mnc.js §1 writes the active
       panel's height inline on every switch so the change is a 320ms
       transition and not a jump. Above 560 the grid keeps the tallest
       panel's height and the card never changes height between slides.
   -------------------------------------------------------------------------- */
@media (max-width: 600px) {
  .vp__k { margin-bottom: 8px; }
  .vp__cap { margin-top: 10px; }
  .demo { gap: 4px; }
}
@media (max-width: 560px) {
  .cycle-tabs { column-gap: 20px; margin-bottom: 14px; }
  .cycle-tab { font-size: 14px; }
  .cycle-stage { transition: height 320ms cubic-bezier(.23, 1, .32, 1); }
  .cycle-panel:not(.is-active) { position: absolute; top: 0; left: 0; }
  /* the 02 sheet: 92px wide is 67px tall, and the panel lands near 210px */
  .plan__sheet { width: 92px; }
}

/* --------------------------------------------------------------------------
   7f. THE FOLD CLOSES (round 5, re-measured for the index). The copy column
       now ends with the page's own contents, so it is the tall one: at
       1440x900 it starts 176px down and closes at 887 of 900 with the
       band's 96px of air under it. The loop card keeps its 600x480 and
       centres against that column (§6, align-items: center), which is what
       stops a 480px card leaving a quarter of the screen of unpainted
       plate below itself.
       Scoped to windows with the room for it: below 1280, or under 860px
       tall, the hero keeps the 160px composition, which already fitted.
   -------------------------------------------------------------------------- */
/* Fold fits naturally inside balanced container */

/* THE PLATE RAMPS INTO #build. The hero's bottom edge was a hard horizontal
   cut straight across the brushwork, landing at the fold; the last 200px
   now grade into the paper the next band is printed on, the way #work
   already grades into the page under it. Same layer as the veil (z -1),
   painted after it, and under everything in flow. */
#hero::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 200px;
  z-index: -1;
  pointer-events: none;
  background: linear-gradient(180deg, rgba(247, 245, 240, 0), #F7F5F0);
}

/* --------------------------------------------------------------------------
   8. build, the second screen: on paper, 160px above the heading, then the
      four project kinds as an editorial list. One hairline-separated row
      each, the h3 (Fraunces 28px, weight 400) left and the sentence right.
      No cards, no numbers, no left rules, no hover.
   -------------------------------------------------------------------------- */

#build { border-top: 0; background: var(--paper); }
#build .sec__title { margin-bottom: 36px; }

.types { border-bottom: 1px solid var(--rule); }
/* THE TITLE COLUMN IS CAPPED AND THE SENTENCE IS PULLED BACK (round 5). Two
   equal halves of the 1152px measure left a 291px trench between a title
   and the sentence that belongs to it. The title column is 360px - the 28px
   display face sets all four of these titles in two lines inside it - and
   the sentence starts 56px after it, inside the 64px a pair may be apart. */
.types > div {
  display: grid;
  grid-template-columns: minmax(0, 360px) minmax(0, 1fr);
  column-gap: 56px;
  align-items: start;
  padding: 32px 0;
  border-top: 1px solid var(--rule);
}
.types .h3 {
  font-size: 28px;
  font-weight: var(--display-weight);
  line-height: 1.2;
  letter-spacing: -0.01em;
  /* every one of the four wraps, and three of them wrapped to an orphan */
  text-wrap: balance;
}
/* 4px puts the sentence's x-height on the h3's: a 28px/1.2 line has 34px of
   box, an 18px/1.6 line has 29px */
.types p { margin: 0; padding-top: 4px; max-width: 46ch; font-size: var(--body); line-height: 1.6; color: var(--ink); }

/* --------------------------------------------------------------------------
   9. how, on the ink-navy plate: four columns of light type, then the price
      as one body paragraph and the CTA under it. Four across on desktop, two
      by two from 1024 down, one column on a phone (§16). No boxes, no
      hairlines. "Step 01 of 4" counts a sequence and says so in words, so
      it does not compete with the index's key above the heading (§5); it
      is sentence-case small text in the steel tint.
   -------------------------------------------------------------------------- */

.steps {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 48px 40px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.steps__no {
  display: block;
  font-size: 15px;
  line-height: 1.4;
  color: var(--steel);
  font-variant-numeric: tabular-nums;
  margin: 0 0 14px;
}
.steps .h3 {
  font-size: 24px;
  font-weight: var(--display-weight);
  line-height: 1.2;
  letter-spacing: -0.01em;
  margin: 0 0 12px;
  text-wrap: balance;
}
.steps p { margin: 0; font-size: 17px; line-height: 1.6; color: rgba(247, 245, 240, .82); }

/* THE PRICE IS THE BAND'S SECOND FOCAL POINT. It was five sentences in one
   paragraph and the one number the page makes was unfindable inside it. The
   range is now set in the display face at the page's sub-head size, so a
   reader scanning the dark band lands on it; its own sentence runs into it
   rather than around it, and every other fact keeps its assumption beside
   it (PRODUCT.md: never a bare figure without its assumption printed next
   to it). Two facts sit under the range and two in the column beside it,
   which is the empty dark the old paragraph left to its right. */
.price {
  margin: clamp(40px, 5vh, 60px) 0 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  column-gap: 64px;
  align-items: start;
  color: var(--paper);
}
.price__lead {
  grid-column: 1;
  grid-row: 1;
  margin: 0;
  max-width: 34ch;
  font-size: var(--body);
  line-height: 1.5;
}
.price__fig {
  display: block;
  margin-top: 6px;
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-weight: var(--display-weight);
  font-size: 28px;
  line-height: 1.15;
  letter-spacing: -0.01em;
  color: var(--paper);
}
.price__note { margin: 0; max-width: 42ch; font-size: 17px; line-height: 1.6; color: rgba(247, 245, 240, .82); }
.price__note--under { grid-column: 1; grid-row: 2; margin-top: 18px; }
.price__side { grid-column: 2; grid-row: 1 / span 2; display: grid; align-content: start; row-gap: 18px; }
#how .cta-row { margin-top: 40px; }

/* --------------------------------------------------------------------------
   10. work, on the facade at dusk: two clients as two columns of light type,
      the name in the display face over the line. No cards, no rules, no
      hover. The seven credential marks moved to #why-us on 2026-09-18.
   -------------------------------------------------------------------------- */

#work {
  padding: clamp(28px, 4.5vh, 60px) 0 clamp(24px, 4vh, 48px);
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  box-sizing: border-box;
}
.sec__lead {
  font-size: 17.5px;
  line-height: 1.55;
  color: rgba(247, 245, 240, 0.84);
  margin: 10px 0 0;
  max-width: 58ch;
}
@media (max-height: 820px) and (min-width: 601px) {
  #work { padding: clamp(14px, 2vh, 28px) 0; }
  #work .sec__title {
    font-size: 30px;
    line-height: 1.18;
    max-width: 52ch;
    margin-bottom: 10px;
  }
  .work-deck { margin-top: 10px; gap: 24px; }
  .client--card { padding: 10px 14px; }
  .client--card .client__name { font-size: 19px; margin: 0; }
  .client--card .client__role { font-size: 12px; margin-bottom: 4px; }
  .client--card .client__desc { font-size: 13px; line-height: 1.4; margin-bottom: 6px; }
  .client--card .client__meta { padding-top: 4px; font-size: 11px; }
  .work-deck__systems { gap: 10px; }
  .work-deck__visual .shot-frame { max-height: clamp(180px, 28vh, 240px); }
  #book { padding: clamp(14px, 2vh, 22px) 0; }
  #book .sec__title { margin-bottom: 18px; }
}
.work-deck {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
  gap: clamp(24px, 3.5vw, 44px);
  align-items: center;
  margin-top: clamp(24px, 3.5vh, 36px);
}
.work-deck__systems {
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.client--card {
  background: rgba(14, 20, 32, 0.75);
  border: 1px solid rgba(247, 245, 240, 0.16);
  border-radius: 6px;
  padding: 18px 22px;
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.25);
}
.client__badge {
  font-family: var(--font-body);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--steel);
  margin-bottom: 6px;
}
.client--card .client__name {
  margin: 0 0 2px;
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-weight: var(--display-weight);
  font-size: 24px;
  line-height: 1.2;
  letter-spacing: -0.01em;
  color: var(--paper);
}
.client__role {
  font-family: var(--font-body);
  font-size: 13.5px;
  font-weight: 500;
  color: rgba(247, 245, 240, 0.9);
  margin: 0 0 8px;
}
.client__desc {
  font-family: var(--font-body);
  font-size: 14px;
  line-height: 1.55;
  color: rgba(247, 245, 240, 0.78);
  margin: 0 0 10px;
}
.client__meta {
  font-family: var(--font-body);
  font-size: 12px;
  color: var(--steel);
  border-top: 1px solid rgba(247, 245, 240, 0.1);
  padding-top: 8px;
  display: flex;
  align-items: center;
  gap: 6px;
}
.client__meta span {
  color: rgba(247, 245, 240, 0.45);
}
.work-deck__visual .shot {
  margin: 0;
}
.work-deck__visual .shot-frame {
  position: relative;
  border: 1px solid rgba(247, 245, 240, 0.22);
  border-radius: 8px;
  overflow: hidden;
  background: #0E1420;
  box-shadow: 0 12px 36px -4px rgba(0, 0, 0, 0.5), 0 0 0 1px rgba(247, 245, 240, 0.08);
  max-height: clamp(200px, 32vh, 280px);
}
.work-deck__visual .shot-frame picture {
  display: block;
}
.work-deck__visual .shot-frame img {
  width: 100%;
  height: auto;
  max-height: none;
  aspect-ratio: 1600 / 893;
  display: block;
  object-fit: cover;
  object-position: top center;
  border: none;
  border-radius: 0;
  box-shadow: none;
}
.work-deck__visual .shot-frame::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(to bottom, transparent 55%, rgba(14, 20, 32, 0.75) 85%, rgba(14, 20, 32, 0.98) 100%);
}
.work-deck__visual .shot__cap {
  margin: 10px 0 0;
  font-size: 13.5px;
  line-height: 1.45;
  color: rgba(247, 245, 240, 0.68);
}
@media (max-width: 900px) {
  .work-deck { grid-template-columns: 1fr; gap: 24px; }
  #work { min-height: auto; padding: 64px 0; }
}

/* --------------------------------------------------------------------------
   10b. #why-us: Institutional Provenance Ledger
   -------------------------------------------------------------------------- */
.why { display: grid; grid-template-columns: 1fr 1fr; gap: 44px; }
.why__k {
  font-size: 15px;
  font-weight: 500;
  line-height: 1.4;
  color: var(--muted-ink);
  margin: 0 0 10px;
}
.why__col p.body { color: var(--ink); }

.creds {
  margin-top: clamp(28px, 4vh, 48px);
  border-top: 1px solid var(--rule);
  padding-top: clamp(16px, 2.5vh, 24px);
  display: flex;
  flex-direction: column;
  gap: clamp(16px, 2.2vh, 22px);
}
.ledger-provenance {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(16px, 3vw, 36px);
}
.ledger-item {
  border-left: 2px solid var(--accent, #27506F);
  padding-left: clamp(10px, 1.5vw, 16px);
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.ledger-item:first-child {
  border-left-color: var(--steel, #9FB8CC);
}
.ledger-role {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--accent, #27506F);
}
.ledger-name {
  font-family: var(--font-body);
  font-size: clamp(15px, 1.3vw, 17.5px);
  font-weight: 600;
  line-height: 1.25;
  color: var(--ink);
}
.ledger-programs {
  display: flex;
  align-items: center;
  gap: clamp(16px, 2.5vw, 28px);
  padding-top: clamp(10px, 1.6vh, 16px);
  border-top: 1px dashed var(--rule);
  flex-wrap: wrap;
}
.ledger-programs-label {
  font-size: 11.5px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted-ink);
  white-space: nowrap;
}
.ledger-logos {
  display: flex;
  align-items: center;
  gap: clamp(20px, 2.8vw, 36px);
  flex-wrap: wrap;
}
.ledger-logos img {
  height: 20px;
  width: auto;
  opacity: 0.82;
  filter: var(--logo-filter, grayscale(1) contrast(1.15));
  mix-blend-mode: var(--logo-blend, multiply);
  transition: opacity 0.2s ease, filter 0.2s ease;
}
.ledger-logos img:hover {
  opacity: 1;
  filter: none;
}
@media (max-width: 680px) {
  .ledger-provenance {
    grid-template-columns: 1fr;
    gap: 14px;
  }
}
/* --------------------------------------------------------------------------
   13. faq, one column at every width, click-to-reveal, on paper

   The rows are <details>/<summary> (the family pattern), so the section is a
   list of five questions until one is asked for, and the state belongs to the
   element rather than to a script, which is what keeps this working under
   `script-src 'self'` with no inline script on the page. The question is in
   the display face at 22, the answer 17 in muted ink; a 1px hairline BETWEEN
   items only (it is a list), none above the first or under the last.
   -------------------------------------------------------------------------- */

.faq { display: grid; grid-template-columns: 1fr; gap: 0; }
.faq__i + .faq__i { border-top: 1px solid var(--rule); }
.faq__q {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 24px;
  padding: 22px 0;
  cursor: pointer;
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-weight: var(--display-weight);
  font-size: 22px;
  line-height: 1.3;
  letter-spacing: -0.008em;
  color: var(--ink);
  /* both spellings: `list-style: none` is the modern one, the -webkit
     pseudo-element is what older WebKit reads. */
  list-style: none;
}
.faq__q::-webkit-details-marker { display: none; }
.faq__q::after {
  content: "+";
  flex: 0 0 auto;
  font-family: var(--font-body);
  font-weight: 400;
  font-size: 20px;
  line-height: 1;
  color: var(--muted-ink);
  transition: color 180ms ease;
}
.faq__i[open] > .faq__q::after { content: "\2013"; }
.faq__q:hover,
.faq__q:hover::after { color: var(--accent); }
.faq__a {
  margin: 0 0 24px;
  font-size: 17px;
  line-height: 1.6;
  color: var(--muted-ink);
  max-width: 66ch;
}

/* --------------------------------------------------------------------------
   14. book, the native slot picker and a live form, on paper with no card.

   THE PICKER IS A FULL-WIDTH ROW OF .book, and "Or write instead" drops
   below it: the day strip reads far better as one wide row than as a 546px
   column, and the form beside it would be cramped either way.
   -------------------------------------------------------------------------- */

.book { display: grid; grid-template-columns: 1fr 1fr; gap: 60px; align-items: start; }
.book > :first-child { grid-column: 1 / -1; }
/* ⚠ CONTAINMENT, NOT DECORATION. A grid item's automatic minimum is
   min-content, so anything inside the picker card that refuses to shrink
   sizes the TRACK instead of overflowing its own box, and a track wider than
   the viewport drags the whole document sideways - invisibly here, because
   html/body clip the x axis. The card's interior belongs to #picker
   (book-picker.css); this floor is what keeps a change in there from
   reaching the document. */
.book > * { min-width: 0; }
/* was a style="margin-top:12px" attribute on each column's intro line */
.book__intro { margin-top: 12px; }

/* No card: the picker sits on the paper. #book-embed keeps its id (book.js
   and the fallback line hang off it) and nothing else. */
.slot { margin: 0; }
.slot__note {
  margin: 0;
  font-size: 15px;
  line-height: 1.5;
  color: var(--muted-ink);
}

/* THE PICKER'S CHROME, restyled from here and never from book-picker.css
   (byte-identical on three sites). Everything it draws reads a custom
   property with a fallback, so the page sets the properties inside #book -
   4px radii, the .18 ink hairline on every control - and overrides by id
   the few things no property reaches: the 2px tab rule to 1px, 44px day
   cells and month buttons, 48px inputs, sentence-case labels, and the two
   end states: the only bordered boxes the picker keeps on this page, 16px
   inset behind the .18 ink hairline at the 4px radius, no ground. Neither
   the picker nor #book carries a min-height or a fixed height; in the bail
   state the band is heading, tabs and the bail box, and the band's bottom
   rhythm closes to 64px (the :has rule below) so the box is not followed by
   280px of bare paper. Every prose link book.js can show inside #book (the
   bail and status lines, the fallback line, the done box) is the accent
   with a .35 accent underline, 3px under the baseline. */
#book {
  --r-card: 4px;
  --r-btn: 4px;
  --field-line: rgba(20, 24, 33, .18);
  --rule: rgba(20, 24, 33, .18);
}
/* The strip is flush left with everything else on the page - book-picker.css
   ships it centred - and a hover is a DARKER rule under the tab, never a
   lighter colour on it. */
#book .bk__tabs { justify-content: flex-start; }
#book .bk__tab { border-bottom-width: 1px; }
#book .bk__tab:hover { color: var(--ink); }
#book .bk__tab:hover:not([aria-selected="true"]) { border-bottom-color: rgba(20, 24, 33, .28); }
#book .bk__day { min-height: 44px; }
#book .bk__nav { width: 44px; height: 44px; }
#book .bk__input { min-height: 48px; padding: 12px 14px; }
#book .bk__textarea { min-height: 48px; }
#book .bk__label,
#book .bk__dow span,
#book .bk__dur,
#book .bk__status,
#book .bk__summary,
#book .bk__doneslot { letter-spacing: 0; text-transform: none; }
#book .bk__label { font-size: 15px; font-weight: 500; margin-bottom: 8px; }
#book .bk__dow span { font-size: 13px; }
#book .bk__dur,
#book .bk__summary,
#book .bk__doneslot { font-size: 15px; }
#book .bk__bail,
#book .bk__done {
  padding: 16px;
  background: none;
  border: 1px solid rgba(20, 24, 33, .18);
  border-radius: 4px;
}
#book .bk__bail a:not(.btn),
#book .bk__status a,
#book .bk__alt a,
#book .bk__done a {
  color: var(--accent);
  text-decoration-color: rgba(39, 80, 111, .35);
  text-underline-offset: 3px;
}
/* THE BAIL STATE IS THE BAND, NOT A FOOTNOTE (round 5; this was the open
   question in DESIGN.md). book.js puts .bk--bailed on the card whenever the
   picker cannot open, and the state is the whole recovery: the sentence,
   then the mailto button at full button size beside the retry. The stage
   height is reserved, so the band never renders short where the picker
   would have been, and the band's bottom rhythm closes to 64px so the
   recovery is not followed by 280px of bare paper. The bordered box goes
   with it - on this page a box is not how a state is told apart. */
#book .bk--bailed {
  display: grid;
  align-content: center;
  min-height: 300px;
}
#book .bk--bailed .bk__bail {
  padding: 0;
  border: 0;
  border-radius: 0;
}
/* The band's own body size, and the mail button keeps the 48px/200px every
   other primary on the page has: the recovery is a button, not a line of
   small grey prose. */
#book .bk--bailed .bk__bail .body { font-size: var(--body); max-width: 52ch; }
#book .sec__inner:has(.bk--bailed) { padding-bottom: 64px; }

.form { margin-top: 24px; }
.field { margin-bottom: 20px; }
.field label {
  display: block;
  font-size: 15px;
  font-weight: 500;
  line-height: 1.4;
  color: var(--muted-ink);
  margin-bottom: 8px;
}
.field input {
  width: 100%;
  min-height: 48px;
  padding: 12px 14px;
  background: var(--paper);
  border: 1px solid rgba(20, 24, 33, .18);
  border-radius: 4px;
  font-family: var(--font-body);
  font-size: 16px;
  color: var(--ink);
}
.field input::placeholder { color: var(--muted); }
/* the ring is the page's one (§2); the edge takes the accent with it */
.field input:focus-visible { border-color: var(--accent); }

/* Invalid state. The value the visitor typed is never cleared, only marked,
   with the reason next to the field it belongs to. */
.field input[aria-invalid="true"] { border-color: var(--error); }
.field__err {
  display: none;
  margin: 8px 0 0;
  font-size: 13.5px;
  line-height: 1.5;
  color: var(--error);
}
.field__err.is-shown { display: block; }

/* Honeypot: present for a bot, gone for everyone else. Not display:none -
   some bots skip what is display:none, which is the whole point of the
   field. Off-screen, zero-size, out of the tab order (tabindex="-1" in the
   markup) and aria-hidden, so no assistive technology meets it either. */
.hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* The one aria-live region on the page: what happened to the submission. */
.form__status {
  margin: 14px 0 0;
  font-size: var(--label);
  line-height: 1.55;
  color: var(--muted-ink);
}
.form__status:empty { margin: 0; }
.form__status--ok { color: var(--accent); font-weight: 500; }
.form__status--bad { color: var(--error); }
.form__note { margin-top: 14px; }

/* --------------------------------------------------------------------------
   14b. close, the repeated ask. No heading and no new sentence anywhere in
        it: the range from #how, the button label the nav, the hero and #how
        already carry, and the address the footer carries, at 18px so it
        reads as the second way to answer and not as a footnote. The band is
        deliberately short - 96px of air above and below, against the
        160/120 every other band gets - because it repeats, it does not add.
   -------------------------------------------------------------------------- */

.close { padding: clamp(64px, 7vh, 96px) 0; }
.close__title {
  margin: 0 0 16px;
  max-width: 28ch;
}
.close__line {
  margin: 0 0 28px;
  max-width: 44ch;
  font-family: var(--font-body);
  font-size: 20px;
  line-height: 1.45;
  color: var(--muted-ink);
}
.close .cta-row { margin-top: 0; }

.close__mail {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-size: 18px;
  line-height: 1.5;
  font-weight: 500;
  color: var(--accent);
  text-decoration: underline;
  text-decoration-color: rgba(39, 80, 111, .35);
  text-underline-offset: 3px;
}
.close__mail:hover { text-decoration-color: var(--accent); }

/* --------------------------------------------------------------------------
   15. Footer: flat deep navy, the legal line at .62 paper, the links in
       paper with a 44px hit box each (the line pitch is the hit box, so
       wrapped lines never overlap).
   -------------------------------------------------------------------------- */

.foot { background: var(--deep); color: var(--paper); }
.foot__inner { padding: 56px 0 48px; }
/* No sites directory: this page stands on its own, so the footer is the
   company line and nothing else. */
.foot__legal {
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  font-size: 14px;
  line-height: 1.7;
  color: rgba(247, 245, 240, .62);
}
.foot__legal a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  color: var(--paper);
  text-decoration: underline;
  text-decoration-color: rgba(247, 245, 240, .35);
  text-underline-offset: 0.18em;
  transition: text-decoration-color 120ms ease;
}
.foot__legal a:hover { text-decoration-color: var(--paper); }
/* THE SEPARATOR BELONGS TO THE ITEM BEFORE IT, never to the one after it: a
   leading "·" - whether it was typed or drawn by a ::before - starts a
   wrapped line with a separator, which is what this line did at 375. Each
   item is its own flex item, so it wraps as a whole and the line it starts
   begins with a word. At 560 they stack and the separators go entirely. */
.foot__item:not(:last-child)::after {
  content: "\00b7";
  margin: 0 0.55em;
  color: rgba(247, 245, 240, .45);
}
.foot :focus-visible { outline-color: var(--paper); }

/* --------------------------------------------------------------------------
   16. Breakpoints. The hero steps at 1279 (56px h1, wider copy column) and
      980 (stacked, veil top-to-bottom); the shared 880px step moves the
      token scale; 560 is the phone. The old 1300 tier for the four-column
      .types is gone with the columns: the list is one row per item at every
      width and only folds its two halves at 560.
   -------------------------------------------------------------------------- */

/* Harvey's second step: 56px from 1279 down, and the copy column widens to
   half so "Working software" stays one line (it is 8em of Fraunces, 448px
   at 56, and 46% of a 1024 window is 442). */
@media (max-width: 1279px) {
  .h1 { font-size: 56px; }
  .hero { grid-template-columns: 50% minmax(0, 1fr); }
}

/* The split gives out at 980 (half of 916 is 458, the h1's floor at 56px,
   and the card would be 426): copy first, the card under it, and the veil
   turns top-to-bottom - solid paper under the copy to 44%, clear by 50%,
   which is ABOVE the card (it starts near 46-48% at 768x1024 and 375x890),
   so the plate under and beside the card is unveiled and has a horizon
   instead of dissolving under it. The crop moves to 30% of the file's width
   (the same 30% on the 960 variant a phone loads): at 375 that is the
   window 246-420 of 960, where the veil's end lands on the top edge of the
   dark stroke against the pale wash - a value break, not a flat passage -
   and the file's own paper corner at 0% is out of the window. */
@media (max-width: 980px) {
  .hero {
    grid-template-columns: minmax(0, 1fr);
    align-content: start;
    row-gap: 28px;
    padding: 0;
  }
  .hero__cycle { justify-self: stretch; max-width: 100%; }
  .idx--ledger { grid-template-columns: repeat(2, 1fr); }
  .idx__pillar:nth-child(2) { border-right: none; }
  .idx__pillar:nth-child(-n+2) { border-bottom: 1px solid var(--rule); }
  .awards-shelf { flex-direction: column; align-items: flex-start; }
  .awards-shelf__items { grid-template-columns: 1fr; width: 100%; }
  #hero::before { background: linear-gradient(180deg, #F7F5F0 0%, #F7F5F0 44%, rgba(247, 245, 240, 0) 50%); }
  .hero__plate img { object-position: 30% 50%; }
}

/* The measure shrinks with the window from 1425 down (`--gutter` does not
   move until 880). What folds here is #why-us's two columns. */

@media (max-width: 1180px) {
  /* --gutter holds at 136.5px until 880, so the measure at 1024 is 751px and
     each .why track is 353px - about 40 characters of 18px prose, which is
     the floor for a four-line paragraph. It folds here, at the same width the
     agency page folds the same grid. */
  .why { grid-template-columns: 1fr; gap: 26px; }
  .creds__pair { grid-template-columns: 1fr; gap: 40px; }
  .creds__line--pro { justify-items: start; text-align: left; }
  .creds__line--pro .logos { justify-content: flex-start; }
}

/* the four steps go two by two: a 1024 window has 751px of measure, which
   is 158px a column at four across, under the 24px h3's shortest line */
@media (max-width: 1024px) {
  .steps { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 44px 40px; }
}

@media (max-width: 880px) {
  /* .h1 is stepped in the 1279 and 560 tiers above and below, not here */
  .clients { grid-template-columns: 1fr; gap: 28px; }
  /* minmax(0, 1fr), not 1fr: a `1fr` track floors at the item's min-content,
     and the picker's day strip refuses to shrink below ~940px, so the single
     track grew to 994px inside a 319px column and the card was clipped by
     the page's overflow-x:clip with no way to scroll to it. */
  .book { grid-template-columns: minmax(0, 1fr); gap: 40px; }
  .sec--plate .h2 { font-size: 36px; }
  .price { grid-template-columns: minmax(0, 1fr); }
  .price__lead, .price__note--under, .price__side { grid-column: 1; }
  .price__side { grid-row: auto; margin-top: 18px; }
}

@media (max-width: 560px) {
  .types > div { grid-template-columns: minmax(0, 1fr); row-gap: 10px; padding: 24px 0; }
  .types .h3 { font-size: 24px; }
  :root { --band-top: 48px; --band-bottom: 40px; --band-gap: 28px; }
  .sec { padding: clamp(40px, 6vh, 64px) 0; }
  .sec__inner { padding: 0; }
  .sec__title { margin-bottom: 28px; }
  .sec--plate .h2 { font-size: 32px; }
  .steps { grid-template-columns: 1fr; gap: 36px; }
  .price { margin-top: 40px; }
  .clients { gap: 28px; }
  .creds { margin-top: 40px; }
  .faq__q { font-size: 20px; padding: 18px 0; }
  .foot__inner { padding: 48px 0 40px; }
  .cta-row { flex-direction: column; align-items: stretch; }
  .cta-row .btn { width: 100%; }
  .awards-shelf { padding: 0; gap: 14px; }
  .awards-shelf__seal { width: 56px; height: 56px; }
  .awards-shelf__seal img { height: 44px; }
  .award-pill { width: 100%; }
  .logos {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 24px 20px;
    justify-items: start;
  }
  .navbar { max-height: 64px; }
  .nav {
    min-height: 52px;
    height: 52px;
    padding: 4px 0;
    flex-wrap: nowrap;
    align-items: center;
  }
  .nav__mark {
    font-size: 12px;
    letter-spacing: 0.1em;
    min-height: 44px;
    min-width: 44px;
  }
  .nav__links { flex-wrap: nowrap; }
  .nav__links .btn {
    font-size: 12px;
    padding: 8px 12px;
    min-height: 44px;
    min-width: 44px;
    white-space: nowrap;
  }
  .h1 { font-size: var(--h1); }
  :root { --body: 17px; }
  .wrap { padding: 0 20px; }
  .navbar .wrap { padding: 0 20px; }
  #hero { min-height: auto; padding: 76px 0 36px; }
  .hero { padding: 0; row-gap: 24px; }
  .hero .lede { margin-top: 16px; }
  .hero .cta-row { margin-top: 24px; }
  .hero__aud { margin-top: 14px; }
  .hero__cycle { padding: 4px 20px 22px; }
  .hero__index { margin-top: 20px; }
  .idx--ledger { grid-template-columns: 1fr; }
  .idx__pillar { border-right: none; border-bottom: 1px solid var(--rule); }
  .idx__pillar:last-child { border-bottom: none; }
  .idx__link { padding: 12px 14px; }
  .sec__key { margin-bottom: 16px; }
  .types p { max-width: none; }
  .price__fig { font-size: 24px; }
  .shot { margin: 32px 0 20px; }
  .close { padding: 64px 0; }
  .close__line { font-size: 20px; }
  .foot__legal { flex-direction: column; align-items: flex-start; }
  .foot__item:not(:last-child)::after { content: none; }
  #hero::before { background: linear-gradient(180deg, #F7F5F0 0%, #F7F5F0 52%, rgba(247, 245, 240, 0) 58%); }
}

/* --------------------------------------------------------------------------
   17. Anchors must clear the sticky nav
   -------------------------------------------------------------------------- */

#main, #hero, .sec, #book, #foot { scroll-margin-top: var(--navh); }

/* mnc.js scrolls to an in-page target itself and never writes location.hash,
   so the target has to take focus for the keyboard and the screen reader to
   follow the pointer. The script stamps tabindex="-1" and this class on
   whatever it jumps to; the ring is suppressed because the reader did not
   focus a control, the page moved them - the heading they asked for is the
   feedback. Scoped to the class so the picker's own tabindex="-1" steps
   (book-picker.css) keep their focus styling. */
.jump-target:focus { outline: none; }

/* --------------------------------------------------------------------------
   18. The 470px tier that used to live here is gone with the iframe it
       existed for: it bled #book-embed edge to edge because Bookings' own
       page overflows below 350px and the frame needed the whole viewport.
       #picker has no such floor - its day strip scrolls inside itself and its
       time chips go to two columns at 560px - so the card keeps its normal
       padding at every width.
   -------------------------------------------------------------------------- */
