/* Astro AI — shared design system stylesheet.
   Extracted from index.html's inline <style> block, 1 Sept 2026, as the
   first step of the site-wide stylesheet consolidation (Astro_todo.md).
   This is the single source of truth for the design system (palette,
   type, nav/footer, cards/buttons, blue-border-only rule, Option A
   scroll-reveal, hero/video-scrub system) going forward — edit here,
   not in a page's own <style> block. Page-specific selectors (e.g.
   #hero, .problem-card) are harmless no-ops on pages that don't use
   them; see Astro_brain.md Task 'Audit other 28 pages for structural
   CSS gaps' for what still needs page-specific additions. */

  /* Font paths fixed 6 Sept 2026 (James caught it) -- these are relative to
     THIS file (assets/css/astro-system.css), not to the HTML pages, so they
     need '../fonts/...' to reach assets/fonts/. They were 'assets/fonts/...'
     since the 1 Sept CSS extraction, resolving to a non-existent
     assets/css/assets/fonts/ and silently failing -- confirmed via
     document.fonts showing every weight as status:'error'. Every self-hosted
     font on the site (Inter incl.) has been falling back to the system
     default sans-serif this whole time. */
  @font-face { font-family: 'Inter'; font-style: normal; font-weight: 300; font-display: swap; src: url('../fonts/Inter-Light.woff2') format('woff2'); }
  @font-face { font-family: 'Inter'; font-style: normal; font-weight: 400; font-display: swap; src: url('../fonts/Inter-Regular.woff2') format('woff2'); }
  @font-face { font-family: 'Inter'; font-style: normal; font-weight: 500; font-display: swap; src: url('../fonts/Inter-Medium.woff2') format('woff2'); }
  @font-face { font-family: 'Inter'; font-style: normal; font-weight: 600; font-display: swap; src: url('../fonts/Inter-SemiBold.woff2') format('woff2'); }
  @font-face { font-family: 'Inter'; font-style: normal; font-weight: 700; font-display: swap; src: url('../fonts/Inter-Bold.woff2') format('woff2'); }
  @font-face { font-family: 'Inter'; font-style: normal; font-weight: 800; font-display: swap; src: url('../fonts/Inter-ExtraBold.woff2') format('woff2'); }

  /* FAMILJEN GROTESK -- 6 Sept 2026, James. Sourced free/OFL from Fontesk
     (fonts/ttf, converted to woff2 here) specifically to mimic the mood of
     a font called 'Astro Futuristic Font' James liked (thin, wide-set,
     circular-geometric) -- that font itself is personal-use-only (demo
     from nestypefont.com), so instead of licensing it we approximate the
     same feel with a real webfont-safe family via CSS treatment (uppercase
     + wide tracking + its lightest weight) rather than sourcing/paying for
     a lookalike. Family only ships 400-700, no true Light/Thin -- Regular
     is as light as it gets. Applied to the wordmark only (.hero-h1,
     .nav-brand) since that is what a display/wordmark face is for; body
     copy and section headlines stay on Inter, untouched. */
  @font-face { font-family: 'Familjen Grotesk'; font-style: normal; font-weight: 400; font-display: swap; src: url('../fonts/familjen-grotesk/FamiljenGrotesk-Regular.woff2') format('woff2'); }
  @font-face { font-family: 'Familjen Grotesk'; font-style: normal; font-weight: 500; font-display: swap; src: url('../fonts/familjen-grotesk/FamiljenGrotesk-Medium.woff2') format('woff2'); }
  @font-face { font-family: 'Familjen Grotesk'; font-style: normal; font-weight: 600; font-display: swap; src: url('../fonts/familjen-grotesk/FamiljenGrotesk-SemiBold.woff2') format('woff2'); }
  @font-face { font-family: 'Familjen Grotesk'; font-style: normal; font-weight: 700; font-display: swap; src: url('../fonts/familjen-grotesk/FamiljenGrotesk-Bold.woff2') format('woff2'); }

  /* Astrohead -- wordmark font, 6 Sept 2026 (James), replacing the Familjen
     Grotesk mimic above (kept but unreferenced, in case of a future change of
     mind). Sourced by James directly (Headfonts, AstroheadFREE.otf) --
     licence per its own bundled readme.txt: "Free for personal and
     commercial use". Single Regular weight only. */
  @font-face { font-family: 'Astrohead'; font-style: normal; font-weight: 400; font-display: swap; src: url('../fonts/astrohead/Astrohead-Regular.woff2') format('woff2'); }

  /* Playfair Bold -- title font, 7 Sept 2026 (James), applied to the four big-headline
     selectors below (.hero-tagline/.section-headline/.cta-headline/.m-headline). Not the wordmark
     (.hero-h1/.nav-brand stays Astrohead) and not smaller card/UI titles (stay Familjen Grotesk/Inter).
     SWAPPED same day from Playfair Display to Playfair proper -- a distinct, newer Google Fonts serif
     family (not a version of Playfair Display, despite the similar name). Playfair ships as a variable
     font across two axes (optical size 9pt/144pt, width Condensed/Normal/Expanded); self-hosted the
     144pt (display-optimised) Bold static instance specifically, since 144pt is the cut Google Fonts
     recommends for large headline-scale text -- 9pt is tuned for small/body sizes, wrong instance for
     this use. Sourced from Google Fonts (OFL), self-hosted, Bold (700) only -- the only weight these
     selectors use. Old Playfair Display Bold file/@font-face left unreferenced in
     assets/fonts/playfair-display/ rather than deleted, in case of a future change of mind (same
     pattern as the retired Familjen-Grotesk-as-wordmark @font-face). */
  @font-face { font-family: 'Playfair'; font-style: normal; font-weight: 700; font-display: swap; src: url('../fonts/playfair/Playfair144pt-Bold.woff2') format('woff2'); }
  /* italic emphasis within Playfair titles, 9 Sept 2026 (James) -- no italic cut is self-hosted, so this synthesises a slant on the bold face; that reads fine at display size and keeps the file count down. */
  .hero-tagline em, .section-headline em, .cta-headline em, .m-headline em { font-style: italic; }

  /* ════════════════════════════════════════════════════════════════════
     TITANIUM — 4 September 2026, James's pick, applied over the restored
     dark-ground stylesheet. Warm metal against cool grey. Supersedes both
     the original #000000 ground and the Bone and Ink inversion built and
     reverted earlier the same session (that version is kept whole at
     astro-system.css.bak-boneink-final if it is ever wanted back).
     Reversal map, one edit each:
       black ground  --bg #000000  --card #0A0A0A  --text #F5F4F2  --blue #3B5FCC
       bone ground   --bg #F2F0EC  --card #FFFFFF  --text #0C0D0F  --blue #1B3AAE
     ════════════════════════════════════════════════════════════════════ */
  :root {
    --bg:          #040406; /* Slash-migration, CORRECTED 11 Sept 2026 -- James flagged the first pass didn't match the real site. Pixel-sampled the actual Slash screenshot/frames: real page ground clusters at ~#040306, matching DESIGN.md's own "Onyx/Card" hex, NOT the "Void" hex the doc's table names for page canvas. Doc's role labels don't match this page's real rendering -- going by sampled evidence over the stated names. Was Titanium #0E0F11, then wrongly #08080A (Void) in the first pass. */
    --card:        #121317; /* Slash-migration, CORRECTED 11 Sept 2026 -- sampled the real card panel in James's screenshot: modal fill is ~#0E1218, matching DESIGN.md's own "Panel" hex almost exactly, NOT "Card". Restores card-lighter-than-page (the original convention, and what the pixels actually show) -- the first pass had this inverted. Was #191A1D pre-Slash, then wrongly #040406 (doc's "Card" hex) in the first pass. */
    --panel:       #08080A; /* Slash-migration, CORRECTED 11 Sept 2026 -- Slash's own "Void" hex, now used as a genuine middle step between --bg and --card (4 < 8 < 19) rather than page ground. Still the former-light-section ground (see below) -- was #121317 (doc's "Panel" hex) in the first pass, reassigned since --card needed that value instead. */
    --floating:    #1C1D22; /* Slash-migration, 11 Sept 2026 -- unchanged, Slash's literal Floating value, brightest step. Reserve for icon-well fills / small floating chips if needed; hairline tokens below stay alpha-based. */
    --divider:     rgba(237,233,227,0.11);
    --chip-bg:     rgba(237,233,227,0.07);
    --meta:        #7A7770;
    --text:        #EDE9E3;
    --text-dim:    rgba(237,233,227,0.62);
    --text-faint:  rgba(237,233,227,0.30);
    /* Astro AI — electric blue accent, border-only per the locked design decision
       (Brain Section 22, approved 21 Aug 2026): no fill, no glow, no dot/icon colour use. */
    --blue:             #C99A6E;   /* Slash-migration Step 1, 11 Sept 2026 -- nudged from Titanium sand (#C0A98A) toward Refero Slash's copper (#CC9166) without matching it exactly. 7.6:1 on --bg, still comfortably AA/AAA as link text. Perimeter-and-interaction rule unchanged -- this only changes the hue/value, not how it's used. */
    --blue-border:      rgba(201,154,110,0.55);
    --blue-border-soft: rgba(201,154,110,0.30);
    /* BLUE RULE, amended 4 Sept 2026 (James) — supersedes the 21 Aug
       border-only wording. Blue marks the perimeter of an interactive or
       contained object, and marks interaction. It is never a decorative
       fill, a glow, a shadow, a dot, an icon colour, or the colour of body
       text. Permitted: borders, link text, and a hover wash at or below
       12% alpha. --blue-tint below IS that hover wash — it is compliant,
       not a violation; do not "fix" it back to neutral. */
    --blue-tint:        rgba(201,154,110,0.12);
    /* Light-section theme — added 24 Aug 2026 for black/white section alternation.
       Used on .section--light and .module-band.band-light (currently #flagship,
       #process on index.html; both module-band bands on services.html). Blue
       border-only rule is unchanged on light sections; only bg/text/card fills invert.
       --bg-light REPOINTED 5 Sept 2026 (audit for the alternating-grounds build):
       was #F5F4F2, a cool white left over from the black-ground era — against
       Titanium's warm #EDE9E3 text/ground it read as two different sites stapled
       together. Now the exact value of --text, so light bands read as the same
       material at a different exposure, not a different site. Audited the rest of
       this block against the new value: --card-light/--text-on-light/-dim/-faint/
       --divider-light are all near-black at fixed alpha over a light ground — the
       new warmth doesn't change any of those ratios meaningfully, no changes needed. */
    /* "-light" tokens RETIRED as literal white, 11 Sept 2026 (James, Slash-migration full-dark ladder) --
       repointed onto the dark ladder instead of deleted, so every .section--light/.band-light/.on-light
       rule sitewide keeps working unchanged and just renders dark. --card-light now resolves DARKER than
       --bg-light (panel > card, matching the base-page relationship) instead of both being flat #FFFFFF --
       this also fixes the "flat hairline-only cards on light bands" flagged after Step 2's Part B check,
       since cards now get real luminance separation from their section ground again. */
    --bg-light:        var(--panel);
    --card-light:      var(--card);
    --text-on-light:      var(--text);
    --text-on-light-dim:  var(--text-dim);
    --text-on-light-faint:var(--text-faint);
    --divider-light:   var(--divider);
    --chip-bg-light:   var(--chip-bg);
    /* On-light accent, added 5 Sept 2026 — sand (--blue, #C0A98A) measures only
       ~1.9:1 against --bg-light, failing AA badly (it was tuned for ~8.4:1 on the
       dark ground only). Same class of fix as the bone-ground blue deepening
       (#3B5FCC -> #1B3AAE) — a darker value in the same family for light grounds.
       Measures ~7:1 on --bg-light. Found as a live, pre-existing bug on
       services.html's .on-light module cards (.m-link), not just new work. */
    --blue-on-light:      var(--blue); /* Slash-migration full-dark ladder, 11 Sept 2026 -- no longer a separately-darkened value now every ground is dark; was #7A4E2C, tuned for AA on white, no longer needed. */

    /* SLASH-MIGRATION TOKENS, added 11 Sept 2026 (Step 1 -- global foundation only).
       Radius/shadow/tracking scale adapted from the Refero "Slash" DESIGN.md
       reference per James's approved Step 1 spec. Not yet wired into existing
       component selectors (module-card, problem-card, chat-panel, etc. still
       use their own hardcoded radius/shadow values) -- that wiring is Step 2
       (Shared Components), a separate approved pass. */
    --radius-pill: 9999px;
    --radius-card: 10px;
    --radius-nav:  2px;
    --shadow-subtle: 0 0 0 1px rgba(255,255,255,0.2);
    --tracking-display: 0.01em;
    /* Component tokens -- Slash Step 2, 11 Sept 2026 (DESIGN.md radius table + its
       hairline-not-shadow rule). Hairlines are the warm Titanium equivalent of
       Slash's Graphite/Slate edges. Buttons now use a neutral ghost outline
       (James, 11 Sept: Slash's "never copper on buttons" wins over the 4 Sept
       accent-perimeter rule FOR BUTTONS). Copper stays on links, focus rings,
       labels and the journey/step accents. */
    --radius-input: 9999px;
    --hairline:             rgba(237,233,227,0.11);
    --hairline-hover:       rgba(237,233,227,0.26);
    --hairline-light:       var(--hairline);
    --hairline-light-hover: var(--hairline-hover);
    --tag-border:           rgba(237,233,227,0.32);
    --tag-border-light:     var(--tag-border);
    --ghost-border:         var(--text);
    --ghost-hover:          rgba(237,233,227,0.08);
    --ghost-border-light:   var(--text-on-light);
    --ghost-hover-light:    var(--ghost-hover);
  }

  *, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
  html { scroll-behavior: smooth; overflow-x: hidden; }

  /* STARFIELD -- retired as a body-level CSS pattern, 6 Sept 2026 (round 2).
     James rejected the radial-gradient dot version outright ("don't look
     like actual stars... how they would look in space") even after two
     rounds of tuning opacity/size/tile -- the repeating-tile approach was
     the actual problem, not the values. Replaced with a real image, see the
     #products rule below (narrowed from #problem/#products/#chat-cta, 7 Sept
     2026 black/white rebalance); body itself no longer carries
     any starfield layer (a single non-tiled photo stretched over the whole
     page via `cover` would distort badly at page-length proportions, so the
     image is applied per-section at each section's own aspect ratio instead,
     same pattern as `.page-header-space`). */
  body {
    background-color: var(--bg);
    color: var(--text);
    font-family: 'Inter', sans-serif;
    font-size: 16px;
    line-height: 1.6;
    -webkit-font-smoothing: antialiased;
    overflow-x: hidden;
  }

  /* body::before grid-line overlay removed 26 Aug 2026 — faint 72px grid was
     visible across the whole page over the video; removed per feedback. */

  /* ── PREMIUM BG (test): film grain — global, fixed, above content, below nav ── */
  body::after {
    content: '';
    position: fixed;
    inset: 0;
    z-index: 3;
    pointer-events: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)'/%3E%3C/svg%3E");
    background-size: 180px 180px;
    opacity: 0.08;
  }

  .container {
    max-width: 1040px;
    margin: 0 auto;
    padding: 0 40px;
    position: relative;
    z-index: 2;
  }

  /* ── NAV ── */
  nav {
    position: fixed;
    top: 0; left: 0; right: 0;
    z-index: 100;
    height: 64px;
    background: rgba(15,13,12,0.88);
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    border-bottom: 1px solid var(--divider);
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 40px;
  }

  .nav-brand {
    font-family: 'Astrohead', 'Inter', sans-serif; /* 6 Sept 2026 -- see .hero-h1 comment */
    font-size: 14px;
    font-weight: 400;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text);
    text-decoration: none;
  }

  .nav-links {
    display: flex;
    gap: 12px; /* Slash Step 2, 11 Sept 2026: was 32px -- links now carry 6px 10px click padding, visual gap unchanged */
    align-items: center;
  }
  /* NAV LINK -- Slash Step 2, 11 Sept 2026. DESIGN.md "Navigation Link": 14px, no
     background/border, dim inactive -> text colour on hover/active, 6px 10px
     click target, 2px-radius (--radius-nav) underline indicator in the link's
     own neutral colour, never copper. Was 12px uppercase 0.06em tracking. */
  .nav-links a {
    position: relative;
    font-size: 14px;
    color: rgba(245,244,242,0.65);
    text-decoration: none;
    letter-spacing: -0.007em;
    font-weight: 400;
    padding: 6px 10px;
    transition: color 0.18s;
  }
  .nav-links a::after {
    content: '';
    position: absolute;
    left: 10px; right: 10px; bottom: 0;
    height: 2px;
    border-radius: var(--radius-nav);
    background: currentColor;
    opacity: 0;
    transform: scaleX(0.4);
    transition: opacity 0.18s, transform 0.22s cubic-bezier(0.22,1,0.36,1);
  }
  .nav-links a:hover { color: var(--text); }
  .nav-links a:hover::after,
  .nav-links a.active::after { opacity: 1; transform: scaleX(1); }
  .nav-links a.active {
    color: var(--text);
    font-weight: 500;
  }

  /* Slash Step 2, 11 Sept 2026 -- DESIGN.md "Ghost Outline Button": transparent,
     1px neutral outline, pill, 14px/500, 10px 20px. Was copper border, 12px/700
     uppercase, 12px radius. */
  .nav-btn {
    display: inline-block;
    background: transparent;
    color: var(--text);
    border: 1px solid var(--ghost-border);
    font-size: 14px;
    font-weight: 500;
    line-height: 1.2;
    text-decoration: none;
    padding: 10px 20px;
    border-radius: var(--radius-pill);
    transition: border-color 0.18s, background 0.18s;
  }
  .nav-btn:hover { background: var(--ghost-hover); }

  /* ── MOBILE NAV ── */
  .nav-hamburger {
    display: none;
    flex-direction: column;
    justify-content: center;
    gap: 5px;
    background: none;
    border: none;
    cursor: pointer;
    padding: 4px;
    width: 36px;
    height: 36px;
  }
  .nav-hamburger span {
    display: block;
    width: 22px;
    height: 2px;
    background: var(--text);
    border-radius: 1px;
    transition: transform 0.22s, opacity 0.22s;
  }
  .nav-hamburger.open span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
  .nav-hamburger.open span:nth-child(2) { opacity: 0; }
  .nav-hamburger.open span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

  .mobile-menu {
    display: none;
    position: fixed;
    top: 64px; left: 0; right: 0;
    background: rgba(15,13,12,0.97);
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    border-bottom: 1px solid var(--divider);
    z-index: 99;
    padding: 8px 40px 24px;
    flex-direction: column;
  }
  .mobile-menu.open { display: flex; }
  .mobile-menu a {
    font-size: 15px; /* Slash Step 2, 11 Sept 2026: was 13px uppercase 0.06em */
    color: rgba(245,244,242,0.65);
    text-decoration: none;
    letter-spacing: -0.007em;
    font-weight: 400;
    padding: 15px 0;
    border-bottom: 1px solid var(--divider);
    transition: color 0.18s;
  }
  .mobile-menu a.active { color: var(--text); font-weight: 500; }
  .mobile-menu a:hover  { color: var(--text); }
  .mobile-menu .mobile-cta {
    margin-top: 16px;
    background: transparent; /* Slash Step 2, 11 Sept 2026: ghost pill */
    color: var(--text);
    border: 1px solid var(--ghost-border);
    font-size: 14px;
    font-weight: 500;
    line-height: 1.2;
    padding: 13px 0;
    border-radius: var(--radius-pill);
    text-align: center;
    text-decoration: none;
    display: block;
    transition: border-color 0.18s, background 0.18s;
  }
  .mobile-menu .mobile-cta:hover { background: var(--ghost-hover); }

  /* ══════════════════════════════════════════════════════════════════════
     HERO — rebuilt 14 September 2026 (James, one-shot homepage brief).
     Was: full-bleed looping video with a centred wordmark and a
     bottom-right tagline block. Now: a two-column product hero —
     typography + a live Astro system panel on the left, the celestial
     object contained in its own slot on the right.

     Why the change: the brief's hero must contain "a major animated system
     interface" and must not be primarily a text block. Containing the video
     instead of full-bleeding it also resolves the 14 Sept open flag that
     hero body copy was sitting over bright cloud and ocean — the copy now
     sits on the page ground, and the footage is an object in the composition
     rather than a backdrop behind the text.

     The video in the right slot is a PLACEHOLDER. James is generating a
     black-hole clip to replace it (accretion disk, lensing, photon ring —
     specified so it reads as astronomy, not a glowing AI orb). The slot is
     sized and masked for that clip; swapping it is a one-line src change.

     Two stale values fixed in this pass, both predating this work:
       - .hero-grid-overlay drew its grid in rgba(59,95,204,0.05), the
         pre-Slash ELECTRIC BLUE, long after the accent moved to copper.
         Element and rules removed entirely — the brief also explicitly
         bans "random futuristic grids", so it had no defence left.
       - .hero-video had background:#0E0F11, the retired Titanium ground,
         sitting behind the dissolve instead of --bg (#040406).

     Motion values come from Astro_motion_spec.md (Brain folder), measured
     off Linear/Stripe/Vercel/Raycast. Easing is the site's existing locked
     curve cubic-bezier(0.22,1,0.36,1) — confirmed to be the same curve as
     Raycast's signature easing, so no new easing is introduced.
     ══════════════════════════════════════════════════════════════════════ */
  #hero {
    position: relative;
    width: 100%;
    min-height: 100vh;          /* was height:100vh — min-height lets a short
                                   viewport grow rather than clip the panel */
    display: flex;
    align-items: center;
    overflow: hidden;
    background: transparent;
    z-index: 1;
  }
  .hero-content {
    position: relative; z-index: 10;
    width: 100%;
    max-width: 1280px;
    margin: 0 auto;
    /* 16 Sept 2026: side padding and gap are tokens because .hero-orb's width and
       right edge are computed from them (see HERO ORB below). Values unchanged. */
    --hero-pad-x: 48px;
    --hero-gap: 56px;
    padding: 74px var(--hero-pad-x) 56px;    /* clears the 64px fixed nav (Brain 9.1 rule 4).
                                   25 Sept 2026 (James): was 112px. First cut to 93px,
                                   but #hero is a min-height:100vh flex box that centres
                                   this block, so a padding cut only moves the content by
                                   half while it fits the window; 74px gives the intended
                                   ~19px visible move at 1440x900 and 1920x1080. Desktop
                                   only; the 1040px (106px) and 860px (96px) values are
                                   unchanged. */
    display: grid;
    grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);   /* 16 Sept 2026: was 1.04fr/0.96fr.
                                   The black hole is wide (16:9), so the right
                                   column takes the larger share. */
    align-items: center;
    gap: var(--hero-gap);
  }

  /* ── left column ── */
  .hero-text { min-width: 0; }
  .hero-h1 {
    font-family: 'Astrohead', 'Inter', sans-serif;
    font-weight: 400;
    font-size: clamp(28px, 3.4vw, 44px);   /* was clamp(34px,4.8vw,56px) and
                                              centred; in a two-column hero the
                                              wordmark yields to the tagline */
    letter-spacing: 0.06em;
    text-transform: uppercase;
    text-align: left;
    color: var(--text);
  }
  .hero-tagline {
    font-family: 'Playfair', 'Familjen Grotesk', 'Inter', sans-serif;
    font-weight: 700;
    font-size: clamp(32px, 4.2vw, 58px);   /* Slash Step 1 set clamp(38px,6vw,76px)
                                              for a full-width hero. At 58px max this
                                              returns to the pre-Step-1 ceiling, which
                                              is what a half-width column can carry.
                                              Tracking and face are unchanged. */
    line-height: 1.06;
    letter-spacing: var(--tracking-display);
    color: var(--text);
    margin-top: 18px;
  }
  .hero-sub {
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    margin-top: 18px;
    font-size: 15px;
    line-height: 1.6;
    color: var(--text-dim);
    max-width: 420px;
  }
  .hero-cta-row {
    margin-top: 28px;
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 14px 22px;
  }
  /* secondary pathways — the brief asks the hero to expose Increase Leads /
     Reduce Admin as routes, not as a third and fourth button. Text links with
     a chevron, so there is still exactly one filled action on the screen
     (Slash's one-filled-pill rule, Brain Section 8 Step 3). */
  .hero-path {
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 14px;
    font-weight: 500;
    color: var(--text-dim);
    text-decoration: none;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    transition: color 140ms cubic-bezier(0.22, 1, 0.36, 1);
  }
  .hero-path::after { content: '\203A'; font-size: 16px; line-height: 1; }
  .hero-path:hover, .hero-path:focus-visible { color: var(--text); }

  /* ── the live system panel ──────────────────────────────────────────────
     The page's first demonstration of Astro, and the place the site's status
     vocabulary is established: ring = live, arc = processing, check = done.
     Every indicator is a RING, never a filled dot — the locked accent rule
     (Brain Section 2, amended 4 Sept) forbids the accent as a dot or icon
     colour but permits it on a perimeter. */
  .sys-panel {
    margin-top: 44px;
    max-width: 480px;
    background: var(--card);
    border: 1px solid var(--hairline);
    border-radius: var(--radius-card);
    overflow: hidden;
  }
  .sys-panel-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 16px;
    padding: 14px 16px;
    border-bottom: 1px solid var(--hairline);
  }
  .sys-panel-id {
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 11px; font-weight: 600; line-height: 1.2;
    letter-spacing: 0.14em; text-transform: uppercase;
    color: var(--text);
  }
  .sys-panel-meta {
    display: block; margin-top: 5px;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 11px; font-weight: 500; line-height: 1.2;
    letter-spacing: 0.04em;
    color: var(--meta);
  }
  .sys-live { display: inline-flex; align-items: center; gap: 7px; flex: none; }
  .sys-live-ring {
    width: 7px; height: 7px; border-radius: 50%;
    border: 1px solid var(--blue-border);
    background: transparent;                 /* ring, never a fill */
    animation: sysLivePulse 2400ms cubic-bezier(0.22, 1, 0.36, 1) infinite;
  }
  @keyframes sysLivePulse { 0%,100% { opacity: 0.45; } 50% { opacity: 1; } }
  .sys-live-label {
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 10px; font-weight: 600; letter-spacing: 0.1em;
    text-transform: uppercase; color: var(--text-dim);
  }

  .sys-feed { list-style: none; margin: 0; padding: 10px 16px 14px; }
  .sys-row {
    position: relative;
    display: grid;
    grid-template-columns: 16px 42px minmax(0, 1fr) 16px;
    align-items: start;
    column-gap: 11px;
    padding: 7px 0;
    opacity: 0;
    transform: translateY(8px);
    transition: opacity 420ms cubic-bezier(0.22, 1, 0.36, 1),
                transform 420ms cubic-bezier(0.22, 1, 0.36, 1);
  }
  .sys-row.is-live, .sys-row.is-done { opacity: 1; transform: none; }

  .sys-rail { position: relative; display: block; height: 16px; }
  .sys-node {
    position: absolute; top: 4px; left: 3px;
    width: 9px; height: 9px; border-radius: 50%;
    border: 1px solid var(--hairline-hover);
    background: var(--card);
    transition: border-color 260ms cubic-bezier(0.22, 1, 0.36, 1);
  }
  .sys-row.is-live .sys-node, .sys-row.is-done .sys-node { border-color: var(--blue-border); }
  /* connector segment down to the next node — scaleY only, no layout cost.
     Uses the accent under the existing journey/step-marker precedent. */
  .sys-rail::after {
    content: '';
    position: absolute; top: 14px; left: 7px;
    width: 1.5px; height: calc(100% + 14px);
    background: var(--blue-border);
    transform: scaleY(0); transform-origin: top;
    transition: transform 340ms cubic-bezier(0.22, 1, 0.36, 1);
  }
  .sys-row:last-child .sys-rail::after { display: none; }
  .sys-row.is-done .sys-rail::after { transform: scaleY(1); }

  .sys-time {
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 11px; font-weight: 500; line-height: 16px;
    letter-spacing: 0.05em; color: var(--meta);
    font-variant-numeric: tabular-nums;
  }
  .sys-body { min-width: 0; }
  .sys-label {
    display: block;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 13px; font-weight: 500; line-height: 16px;
    letter-spacing: 0.01em; color: var(--text-dim);
    transition: color 260ms cubic-bezier(0.22, 1, 0.36, 1);
  }
  .sys-row.is-done .sys-label { color: var(--text); }
  .sys-detail {
    display: block; margin-top: 3px;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 11px; font-weight: 400; line-height: 1.35;
    color: var(--text-faint);
  }

  .sys-state { position: relative; display: block; width: 14px; height: 16px; }
  .sys-spin {
    position: absolute; top: 3px; left: 1px;
    width: 11px; height: 11px; border-radius: 50%;
    border: 1.5px solid var(--hairline-hover);
    border-top-color: var(--text-dim);
    opacity: 0;
    transition: opacity 160ms linear;
  }
  .sys-row.is-live .sys-spin { opacity: 1; animation: sysSpin 900ms linear infinite; }
  @keyframes sysSpin { to { transform: rotate(360deg); } }
  .sys-check {
    position: absolute; top: 3px; left: 1px;
    width: 11px; height: 11px;
    fill: none; stroke: var(--text); stroke-width: 1.6;
    stroke-linecap: round; stroke-linejoin: round;
    opacity: 0; transform: scale(0.8);
    transition: opacity 260ms cubic-bezier(0.22, 1, 0.36, 1),
                transform 260ms cubic-bezier(0.22, 1, 0.36, 1);
  }
  .sys-row.is-done .sys-check { opacity: 1; transform: none; }

  /* ── right column: the celestial slot ──
     BLACK HOLE, 16 Sept 2026 (James). Replaces the square slot, cover-fit and
     circular radial mask built for the Earth placeholder, all of which would
     crop this clip: its spiral arms run to the frame edges.
     - 16:9 slot + object-fit:contain (NEVER cover): the whole black hole is
       always in frame, disk, both arms, and the lensed arcs above and below.
     - no filter: James approved the footage as generated, no regrade.
     - edge-only masks, horizontal and vertical, intersected: the arm tips
       taper out over the outer 7% and the top/bottom over 10%, so there is no
       visible rectangle and nothing is cut.
     Still the 9.5 #4 amendment: the element fades its OWN alpha, nothing is
     laid over it, no pixel is darkened, no colour introduced. */
  .hero-orb {
    position: relative;
    width: 100%;
    max-width: 720px;
    aspect-ratio: 16 / 9;
    margin-inline: auto;
    justify-self: end;
  }
  .hero-orb .hero-video {
    position: absolute; inset: 0;
    width: 100%; height: 100%;
    object-fit: contain;
    background: transparent;      /* was #0E0F11 — retired Titanium ground */
    pointer-events: none;
    -webkit-mask-image:
      linear-gradient(to right, transparent 0%, #000 7%, #000 93%, transparent 100%),
      linear-gradient(to bottom, transparent 0%, #000 10%, #000 90%, transparent 100%);
    mask-image:
      linear-gradient(to right, transparent 0%, #000 7%, #000 93%, transparent 100%),
      linear-gradient(to bottom, transparent 0%, #000 10%, #000 90%, transparent 100%);
    -webkit-mask-composite: source-in;
    mask-composite: intersect;
    -webkit-mask-mode: alpha; mask-mode: alpha;
  }

  /* ── load sequence — restrained, per the brief: page, then typography, then
     the system activating. No cinematic intro; the CTA is clickable at once. */
  .hero-text  { animation: heroRise 560ms cubic-bezier(0.22,1,0.36,1) 120ms both; }
  .sys-panel  { animation: heroRise 560ms cubic-bezier(0.22,1,0.36,1) 300ms both; }
  .hero-orb   { animation: heroFade 700ms cubic-bezier(0.22,1,0.36,1) 200ms both; }
  @keyframes heroRise { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
  @keyframes heroFade { from { opacity: 0; } to { opacity: 1; } }

  .m-br { display: none; }   /* mobile-only line break — hidden on desktop */

  /* ── tablet ── */
  @media (max-width: 1040px) {
    .hero-content { --hero-pad-x: 32px; --hero-gap: 36px; padding: 106px var(--hero-pad-x) 64px; }
    .hero-orb { max-width: 480px; }   /* 16 Sept 2026: was 360px (square slot) */
    .sys-panel { margin-top: 34px; }
  }

  /* ── HERO ORB: SIZE, POSITION AND LAYERING — desktop + tablet (>=861px) ──
     16 Sept 2026, two passes after James's live reviews.
     SIZE (pass 1, approved, unchanged here): 1.25x the width the orb rendered at
     as a grid item, i.e. the right grid track (content width - gap) x 1.1/2.0,
     capped at 720px (480px at tablet), times 1.25; never wider than 1280px, the
     clip's native width. 775.5px at every desktop width, 600px at 1024px.
     POSITION (pass 2): the centre of the black shadow sits at the vertical
     midpoint of the first screen below the fixed nav,
         64px + (viewport height - 64px) / 2
     measured from the top of the page, which is #hero's top. The shadow is NOT
     the box centre: measured on decoded frames at 0/2/4/6s it sits 44.0-44.4%
     down the 1280x720 frame (0.442 used), so the box is offset by that, not by
     50%. The top lensed arc sits 16.39% down the frame; a floor keeps it at
     least 80px from the top (64px nav + 16px air) on short windows. It is part
     of the page, not fixed: it scrolls away with the hero. svh after vh so the
     mobile-browser toolbar can't push it off-centre where svh is supported.
     Right edge: the content box's right edge, exactly where it was.
     CONTAINING BLOCK: the orb is anchored to #hero, not .hero-content, because
     .hero-content is vertically centred inside #hero on tall windows (1920x1080,
     2560x1440), so its top is not the page top. Two things made .hero-content
     the containing block and are switched off here: its entrance transform
     (translateY, kept by animation-fill forwards) and container-type. Its
     entrance becomes a pure fade at these widths; .hero-text's own 14px rise
     (heroRise) still runs. #hero is the size container instead; :has() scopes
     that to the homepage (ask-astro.html has its own #hero, no .hero-content).
     LAYERING: behind the text. Orb z-index 0 + pointer-events none (wrapper and
     video); .hero-text and .sys-panel position:relative z-index 1. Nothing is
     laid over the footage (9.5 #4). */
  @media (min-width: 861px) {
    #hero:has(> .hero-content) { container-type: inline-size; }
    #hero > .hero-content {
      position: static;
      transform: none;
      animation-name: heroContentFade;
    }
    .hero-text { position: relative; z-index: 1; }
    .sys-panel { position: relative; z-index: 1; top: 30px; }
    /* Brain 9.7, applied only where text measurably meets the orb: .hero-sub is
       the only hero text whose glyph box intersects the orb (re-measured for the
       centred position; see the Brain's 16 Sept entries for the numbers).
       Wordmark, tagline, CTA row and links do not. Where the orb passes behind
       .sys-panel, the panel is opaque var(--card) and sits above it. */
    .hero-sub { color: var(--text); text-shadow: 0 1px 3px rgba(0,0,0,0.85), 0 3px 18px rgba(0,0,0,0.65); }
    .hero-orb {
      --orb-cap: 720px;
      --content-w: calc(min(100cqw, 1280px) - 2 * var(--hero-pad-x));
      --orb-w: min(calc(min((var(--content-w) - var(--hero-gap)) * 0.55, var(--orb-cap)) * 1.25), 1280px);
      --orb-h: calc(var(--orb-w) * 0.5625);
      position: absolute;
      z-index: 0;
      /* 27-28 Sept 2026 (James): moved right only, --orb-shift of the hero's
         width, so the headline owns the left. Pass 1 tried 10cqw (too far);
         5cqw is the middle ground with the original 0. top and width
         unchanged. */
      --orb-shift: 5cqw;
      right: calc((100cqw - min(100cqw, 1280px)) / 2 + var(--hero-pad-x) - var(--orb-shift));
      top: max(calc(64px + (100vh - 64px) / 2 - var(--orb-h) * 0.442 - 20px), calc(80px - var(--orb-h) * 0.1639));
      top: max(calc(64px + (100svh - 64px) / 2 - var(--orb-h) * 0.442 - 20px), calc(80px - var(--orb-h) * 0.1639));
      width: var(--orb-w);
      max-width: none;
      margin: 0;
      pointer-events: none;
    }
  }
  @keyframes heroContentFade { to { opacity: 1; } }
  @media (min-width: 861px) and (max-width: 1040px) {
    .hero-orb { --orb-cap: 480px; }   /* tablet: 1.25x its old 480px cap = 600px */
  }
  @media (min-width: 861px) and (prefers-reduced-motion: reduce) {
    #hero > .hero-content { animation: none; opacity: 1; }
  }

  /* ── mobile: deliberate stack, not a shrunk desktop.
     Order is text → celestial slot → panel, so the brand lands first, the
     object confirms it, and the panel is the thing the visitor scrolls into. */
  @media (max-width: 860px) {
    #hero { min-height: 0; }
    .hero-content {
      grid-template-columns: minmax(0, 1fr);
      padding: 96px 22px 56px;
      gap: 0;                    /* 16 Sept 2026: was 30px; spacing now comes from
                                    the children's own margins, see below */
    }
    /* FIXED 16 Sept 2026 — the stated order never actually happened. .sys-panel
       is nested INSIDE .hero-text, so the whole text column including the panel
       was one grid item and order:3 on the panel did nothing: the orb rendered
       below the panel (text → panel → orb), for the Earth clip too.
       display:contents lifts .hero-text's children into the grid so they can be
       ordered around the orb. Their own margins (tagline 18, sub 18, CTA row 28)
       keep the column's rhythm; orb and panel take 30px, the old gap. The
       heroRise entrance on .hero-text does not apply to a contents box on phones;
       .hero-content's own heroContentIn entrance still runs. */
    .hero-text { display: contents; }
    .hero-h1, .hero-tagline, .hero-sub, .hero-cta-row { order: 1; }
    /* full column width at 16:9, was capped at 260px. A narrow cap would
       shrink the arms to a sliver; full width keeps the whole black hole
       legible on a phone. */
    .hero-orb { order: 2; max-width: none; justify-self: center; margin-top: 30px; }
    .sys-panel { order: 3; margin-top: 30px; max-width: 100%; }
    .hero-sub { max-width: 100%; }
    .sys-row { grid-template-columns: 16px 40px minmax(0, 1fr) 16px; column-gap: 9px; }
  }

  /* ── reduced motion: the panel renders COMPLETE, never empty.
     Every row visible, every connector drawn, every status a check. The
     sequence driver in index.html short-circuits to the same state. */
  @media (prefers-reduced-motion: reduce) {
    .hero-text, .sys-panel, .hero-orb { animation: none; opacity: 1; transform: none; }
    .sys-row { opacity: 1; transform: none; transition: none; }
    .sys-rail::after { transform: scaleY(1); transition: none; }
    .sys-live-ring { animation: none; opacity: 1; }
    .sys-spin { display: none; }
    .sys-check { opacity: 1; transform: none; transition: none; }
    .sys-label { color: var(--text); }
  }

  /* Slash Step 2, 11 Sept 2026 -- ghost pill, same spec as .nav-btn at CTA scale.
     Was copper border, 13px/700 uppercase 0.08em, 15px 40px, 12px radius. */
  .btn-primary {
    display: inline-block;
    background: transparent;
    color: var(--text);
    border: 1px solid var(--ghost-border);
    font-size: 14px;
    font-weight: 500;
    line-height: 1.2;
    text-decoration: none;
    padding: 14px 28px;
    border-radius: var(--radius-pill);
    transition: border-color 0.18s, background 0.18s;
  }
  .btn-primary:hover { background: var(--ghost-hover); }
  .section--light .btn-primary, .band-light .btn-primary, .on-light .btn-primary { color: var(--text-on-light); border-color: var(--ghost-border-light); }
  .section--light .btn-primary:hover, .band-light .btn-primary:hover, .on-light .btn-primary:hover { background: var(--ghost-hover-light); }

  /* Hero content entrance — simple fade/rise on load */
  .hero-content {
    opacity: 0;
    transform: translateY(16px);
    animation: heroContentIn 0.9s cubic-bezier(0.22, 1, 0.36, 1) 0.3s forwards;
  }
  @keyframes heroContentIn {
    to { opacity: 1; transform: translateY(0); }
  }
  @media (prefers-reduced-motion: reduce) {
    .hero-content { animation: none; opacity: 1; transform: none; }
  }

  /* ── SCROLL REVEALS (#3) — OPTION A: amplified travel, no wipe ──
     28 Aug 2026. Replaces Option C (scroll-linked continuous convergence) at
     James's request. Back to a one-way entrance: an IntersectionObserver adds
     an `.is-in` class (to each `.section` for titles, to each individual
     card/step for cards, and to `#cta` itself) the first time an element
     scrolls into view; a fixed-duration CSS transition then animates
     transform/opacity off that class flip. Not reversible on scroll-up
     (unlike Option C) — once revealed, stays revealed, matching the
     original 26 Aug behaviour.

     This is Option B's mechanism (27 Aug) with the clip-path wipe and the
     120ms interior-content lag removed — just the amplified translate
     distances carried over: titles 90/120px per-section (48/60 mobile);
     cards ±64px (±32 mobile) by column; ±36px vertical for the middle
     Problem card and the full-width Blueprint card; CTA fades up 56px
     (headline) / 44px (sub/button/urgency/guarantee-strip), no horizontal
     offset — it's the symmetric bookend.

     SPECIFICITY: every hidden/offset declaration below is gated behind
     `:not(.is-in)` (never a bare selector overridden by a separate release
     rule) — this is the fix for the 27 Aug bug where an ID-scoped offset
     rule permanently out-ranked a class-scoped release rule and silently
     broke the entire 26 Aug reveal system. Do not reintroduce a
     same-specificity release-rule pattern here.

     ROLLBACK: Option B (clip-path wipe + interior lag) and Option C
     (scroll-linked continuous, no transition) are recorded in the 27/28 Aug
     Brain entries and this file's prior versions if either needs restoring
     — swapping options means replacing this block (and its paired script
     near the end of <body>) wholesale. */

  .js-reveal .section .section-label,
  .js-reveal .section .section-headline,
  .js-reveal .section .section-sub,
  .js-reveal .section .problem-card,
  .js-reveal .section .product-card,
  .js-reveal .section .process-step,
  .js-reveal #cta .cta-headline,
  .js-reveal #cta .cta-sub,
  .js-reveal #cta .btn-primary,
  .js-reveal #cta .cta-urgency,
  .js-reveal #cta .guarantee-strip,
  .js-reveal #chat-cta .cta-headline,
  .js-reveal #chat-cta .section-sub,
  .js-reveal #chat-cta .chat-cta-box,
  .js-reveal #chat-cta .guarantee-strip {
    transition: transform 0.9s cubic-bezier(0.22,1,0.36,1), opacity 0.9s cubic-bezier(0.22,1,0.36,1);
  }
  .js-reveal .section .problem-card,
  .js-reveal .section .product-card,
  .js-reveal .section .process-step {
    transition-duration: 1.05s;
  }
  .js-reveal .section .section-label::before,
  .js-reveal .section .section-label::after {
    transition: width 0.9s cubic-bezier(0.22,1,0.36,1);
  }

  /* Section titles — direction matches each section's header alignment */
  .js-reveal #problem:not(.is-in) .section-label,
  .js-reveal #process:not(.is-in) .section-label,
  .js-reveal #problem:not(.is-in) .section-sub,
  .js-reveal #process:not(.is-in) .section-sub {
    opacity: 0; transform: translateX(-90px);
  }
  .js-reveal #problem:not(.is-in) .section-headline,
  .js-reveal #process:not(.is-in) .section-headline {
    opacity: 0; transform: translateX(-120px);
  }
  .js-reveal #products:not(.is-in) .section-label,
  .js-reveal #products:not(.is-in) .section-sub {
    opacity: 0; transform: translateX(90px);
  }
  .js-reveal #products:not(.is-in) .section-headline {
    opacity: 0; transform: translateX(120px);
  }
  .js-reveal .section:not(.is-in) .section-label::before,
  .js-reveal .section:not(.is-in) .section-label::after {
    width: 0;
  }

  /* Cards/steps — direction by column, converging on their fixed grid position */
  .js-reveal #problem .problem-card:nth-child(1):not(.is-in),
  .js-reveal #products .product-card:nth-child(odd):not(.product-card--blueprint):not(.is-in),
  .js-reveal #process .process-step:nth-child(odd):not(.is-in) {
    opacity: 0; transform: translateX(-64px) scale(0.96);
  }
  .js-reveal #problem .problem-card:nth-child(3):not(.is-in),
  .js-reveal #products .product-card:nth-child(even):not(.product-card--blueprint):not(.is-in),
  .js-reveal #process .process-step:nth-child(even):not(.is-in) {
    opacity: 0; transform: translateX(64px) scale(0.96);
  }
  .js-reveal #problem .problem-card:nth-child(2):not(.is-in),
  .js-reveal #products .product-card--blueprint:not(.is-in) {
    opacity: 0; transform: translateY(36px) scale(0.98);
  }

  /* CTA — vertical fade-up bookend, no horizontal offset */
  .js-reveal #cta:not(.is-in) .cta-headline {
    opacity: 0; transform: translateY(56px);
  }
  .js-reveal #cta:not(.is-in) .cta-sub,
  .js-reveal #cta:not(.is-in) .btn-primary,
  .js-reveal #cta:not(.is-in) .cta-urgency,
  .js-reveal #cta:not(.is-in) .guarantee-strip {
    opacity: 0; transform: translateY(44px);
  }

  /* ── services.html reveal selectors — rewritten 1 Sept 2026 for the v2
     module-band layout (was the card-grid version from the first pass,
     now replaced). #page-header keeps the simple left-aligned intro
     pattern (matching Problem/Process, not the right-aligned Products
     convention — this page no longer uses .products-header at all).
     Module cards are full-width unified boxes, so directional left/right
     sliding doesn't read the way it does for a grid of separate cards —
     each .module-card fades up with a slight scale instead, same as
     index.html's full-width Blueprint card treatment. */
  .js-reveal #page-header:not(.is-in) .section-label,
  .js-reveal #page-header:not(.is-in) .section-sub,
  .js-reveal #how-built:not(.is-in) .section-label,
  .js-reveal #how-built:not(.is-in) .section-sub {
    opacity: 0; transform: translateX(-90px);
  }
  .js-reveal #page-header:not(.is-in) .section-headline,
  .js-reveal #how-built:not(.is-in) .section-headline {
    opacity: 0; transform: translateX(-120px);
  }
  .js-reveal .module-band .module-card:not(.is-in) {
    opacity: 0; transform: translateY(40px) scale(0.98);
  }
  .js-reveal .module-band .module-card {
    transition: transform 1.05s cubic-bezier(0.22,1,0.36,1), opacity 1.05s cubic-bezier(0.22,1,0.36,1);
  }
  .js-reveal #chat-cta:not(.is-in) .cta-headline {
    opacity: 0; transform: translateY(56px);
  }
  .js-reveal #chat-cta:not(.is-in) .chat-cta-box,
  .js-reveal #chat-cta:not(.is-in) .section-sub,
  .js-reveal #chat-cta:not(.is-in) .guarantee-strip {
    opacity: 0; transform: translateY(44px);
  }

  @media (max-width: 720px) {
    .js-reveal #problem:not(.is-in) .section-label,
    .js-reveal #process:not(.is-in) .section-label,
    .js-reveal #problem:not(.is-in) .section-sub,
    .js-reveal #process:not(.is-in) .section-sub {
      transform: translateX(-48px);
    }
    .js-reveal #problem:not(.is-in) .section-headline,
    .js-reveal #process:not(.is-in) .section-headline {
      transform: translateX(-60px);
    }
    .js-reveal #products:not(.is-in) .section-label,
    .js-reveal #products:not(.is-in) .section-sub {
      transform: translateX(48px);
    }
    .js-reveal #products:not(.is-in) .section-headline {
      transform: translateX(60px);
    }
    .js-reveal #problem .problem-card:nth-child(1):not(.is-in),
    .js-reveal #products .product-card:nth-child(odd):not(.product-card--blueprint):not(.is-in),
    .js-reveal #process .process-step:nth-child(odd):not(.is-in) {
      transform: translateX(-32px) scale(0.96);
    }
    .js-reveal #problem .problem-card:nth-child(3):not(.is-in),
    .js-reveal #products .product-card:nth-child(even):not(.product-card--blueprint):not(.is-in),
    .js-reveal #process .process-step:nth-child(even):not(.is-in) {
      transform: translateX(32px) scale(0.96);
    }
  }

  /* safety: never hide content if motion is reduced, or if the reveal script
     fails to run for any reason (nothing else sets these inline styles) */
  @media (prefers-reduced-motion: reduce) {
    .js-reveal .section .section-label,
    .js-reveal .section .section-headline,
    .js-reveal .section .section-sub,
    .js-reveal .section .problem-card,
    .js-reveal .section .product-card,
    .js-reveal .section .process-step,
    .js-reveal #cta .cta-headline,
    .js-reveal #cta .cta-sub,
    .js-reveal #cta .btn-primary,
    .js-reveal #cta .cta-urgency,
    .js-reveal #cta .guarantee-strip {
      opacity: 1 !important;
      transform: none !important;
    }
    .js-reveal .section .section-label::before,
    .js-reveal .section .section-label::after { width: 20px !important; }
  }

  /* ── HERO VIDEO — the full-bleed .hero-video rule that lived here (4 Sept
     2026) was removed 14 Sept 2026 when the hero became two columns. The video
     is no longer a page background: it is contained in .hero-orb and styled
     there, with a radial edge dissolve replacing the old bottom-edge one, and
     background:#0E0F11 (the retired Titanium ground) dropped. See HERO above.
     The reduced-motion belt-and-braces rule moved up there too. */

  /* ── SECTIONS ── */
  /* SECTION RHYTHM, locked 4 Sept 2026 (James): one value sitewide, 96px
     desktop / 56px mobile. Replaces .section 56px vs .module-band 100px —
     nearly a 2x difference between the two finished pages, and a large part
     of why grafting one page's structure onto the other read as jumbled.
     A new vertical-padding value on a section is a decision, not a
     convenience — put it on the scale or don't use it. */
  .section {
    padding: 105px 0; /* Reverted to Slash Step 1's 140px then decreased 25% (105px), 11 Sept 2026 -- 44px was clipping page-header/hero labels under the 64px fixed nav. */
    position: relative;
    z-index: 2;
    background: transparent;
    overflow: hidden;
  }
  @media (max-width: 720px) {
    .section { padding: 54px 0; } /* Reverted to Slash Step 1's 72px then decreased 25% (54px), 11 Sept 2026 */
  }

  /* OPAQUE GROUND, 4 Sept 2026 — index.html's video is now confined to the
     hero (it plays once and holds), so the sections below no longer have a
     video to show through and are painted flat instead. This is the enabling
     change for imagery-led module cards: a borderless card needs a flat,
     predictable background to have any contrast edge at all. Do not revert
     these to transparent without also restoring a full-page video.
     #process REMOVED from this id-scoped rule, 5 Sept 2026 (alternating-grounds
     build) — it now carries the .section--light class instead and takes its
     background from that class rule below. Left here on an id, it would have
     out-ranked .section--light at equal specificity by pure source order
     (gotcha 9.5 #6) and stayed silently dark. #problem/#chat-cta REMOVED from
     this id-scoped rule, 7 Sept 2026 (James: black/white rebalance to a
     repeating Black/White/White pattern, 2/3 white overall) -- both now carry
     .section--light instead, same reasoning as #process above. Only
     #products stays forced dark by id, and is now the sole starfield section
     on index.html (hero stays its own black via the video/mask system,
     untouched). */
  #products {
    /* 6 Sept 2026 -- CSS radial-gradient dots replaced with a real
       astrophotography image (James generated it himself, AI-generated
       image, watermark removed before use -- not a NASA source this time,
       so the 9.8 sourcing/licence method doesn't apply here). Applied per
       section via `cover`/`center` like `.page-header-space` rather than
       tiled, so real stars at their natural size/scatter, no repeating-grid
       tell. A dark overlay (linear-gradient layer under the image, over the
       flat colour) keeps it from reading too bright against body copy --
       tune the 0.6 alpha below if James wants it darker/lighter. Still
       fully opaque underneath (var(--bg) as background-color), same
       no-video-tint guarantee as the 4 Sept change above. */
    background-image:
      linear-gradient(rgba(6,6,8,0.6), rgba(6,6,8,0.6)),
      url('../images/starfield/deep-sky-starfield.jpg');
    background-size: cover, cover;
    background-position: center, center;
    background-repeat: no-repeat, no-repeat;
    background-color: var(--bg);
  }

  /* GENERALISED STARFIELD CLASS, 9 Sept 2026 -- home restructure added two
     more black sections (#problem, #faq-preview) alongside #products, so
     the id-scoped rule above is now also exposed as a reusable class.
     Same image/overlay, applied via class instead of id so new black
     sections don't need a bespoke id rule each time. */
  .section.starfield {
    background-image:
      linear-gradient(rgba(6,6,8,0.6), rgba(6,6,8,0.6)),
      url('../images/starfield/deep-sky-starfield.jpg');
    background-size: cover, cover;
    background-position: center, center;
    background-repeat: no-repeat, no-repeat;
    background-color: var(--bg);
  }

  /* HERO -> #problem seam, 7 Sept 2026 (James): #problem is now a white section
     (black/white rebalance), so the old pitch-black top-fade scrim is gone --
     hero (black) cuts straight to #problem (white) with no transition, per
     the approved straight-split rule. Full history of the fade's tuning
     (rounds 2-6) is preserved in the Brain History Log if this is ever
     revisited. */

  /* Black/white section alternation (24 Aug 2026) retired 26 Aug 2026 in favour
     of the scroll-scrubbed video background above — sections are transparent
     now so the video shows through untinted. .section--light is unused (kept,
     not applied in HTML) in case a future page wants the light-panel look. */
  .section--light {
    background: var(--bg-light);
    color: var(--text-on-light);
  }

  .section-canvas {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    z-index: 0;
    pointer-events: none;
  }

  /* ── PAGE-HEADER SPACE IMAGE ── node-network canvas retired sitewide,
     2 Sept 2026, per James's direction — every #page-header now carries a
     real NASA/JWST/Hubble image instead of the node-network signature.
     Each page sets its own image via inline background-image on
     #page-header; this class carries the shared overlay + sizing so future
     stop-*.html pages just swap the URL. Overlay darkens left-to-right
     (text sits left-aligned) without tinting the image itself — same
     legibility-not-decoration principle as index.html's scroll-video rule,
     applied here via a scrim since a static photo (unlike the untinted
     video) can take one without violating that rule. */
  .page-header-space {
    background-size: cover;
    background-position: center;
  }
  .page-header-space::before {
    content: "";
    position: absolute; inset: 0; z-index: 0;
    background: linear-gradient(100deg, rgba(0,0,0,0.78) 0%, rgba(0,0,0,0.5) 45%, rgba(0,0,0,0.15) 100%);
  }
  /* PAGE-HEADER GROUND FADE — 6 Sept 2026, James: the space photo cut hard
     into the module band below. Same idea as the hero's own dissolve
     (astro-hero.mp4 fades to --bg via an alpha mask on the video layer),
     adapted here since this section is a flat background-image on the
     section itself rather than a separate video element masking would
     leave text-safe. Instead of masking to transparency, phase the
     bottom band to a solid color matching the ground it lands on — same
     visual result since what is underneath is a flat card color, not
     more imagery. Defaults to --bg-light (services.html's page-header is
     followed by a light module band); a page-header followed by a dark
     band should override --page-header-fade-to on that page. */
  .page-header-space::after {
    content: "";
    position: absolute; left: 0; right: 0; bottom: 0; z-index: 0;
    height: 30%;
    background: linear-gradient(to bottom, transparent 0%, var(--page-header-fade-to, var(--bg)) 100%);
    pointer-events: none;
  }
  /* Text-shadow re-added here, scoped to #page-header only — the base
     .section-label/.section-headline/.section-sub rules stay shadow-free
     (v3 fix, Section 9.7) since flat module bands below don't need it;
     this section now sits over a photo and does. */
  #page-header .section-headline {
    text-shadow: 0 1px 3px rgba(0,0,0,0.85), 0 3px 18px rgba(0,0,0,0.65);
  }
  /* .section-label excluded here, 6 Sept 2026 (James) -- shadow removed from
     smallest text sizes; 11px label relies on the page-header's own scrim instead.
     .section-sub excluded here too, same day, second pass -- James expanded the
     shadow-removal scope from just smallest-text to tagline/sub text generally. */

  .section-label { /* Slash-migration Step 3, 11 Sept 2026: unified with .m-eyebrow's spec (12px/600/0.08em, closer to Slash's own tighter eyebrow tracking) -- was 11px/600/0.18em, the two unreconciled eyebrow specs flagged in Brain Section 2. */
    display: inline-flex;
    align-items: center;
    gap: 10px;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--text);
    margin-bottom: 20px;
  }
  .section-label::before,
  .section-label::after {
    content: '';
    display: block;
    width: 20px;
    height: 1px;
    background: var(--text);
    opacity: 0.45;
  }

  /* Text-shadow on bare headings/copy below is for legibility over the
     scroll-scrubbed video (26 Aug 2026) — the video itself is untinted, so
     the text carries its own contrast instead of a background scrim. */
  .section-headline {
    font-family: 'Playfair', 'Familjen Grotesk', 'Inter', sans-serif; /* was Familjen Grotesk, then Playfair Display, 7 Sept 2026 (James) -- title font */
    font-size: clamp(36px, 5.2vw, 64px); /* Slash-migration Step 1, 11 Sept 2026 -- was clamp(36px,5vw,58px), moderate bump (this role repeats far more often than hero/CTA, so kept smaller than those) */
    font-weight: 700; /* 800 -> 600 -> 700, locked 3 Sept 2026 as the standard title-card weight sitewide (James) */
    line-height: 1.08;
    letter-spacing: var(--tracking-display); /* Slash-migration Step 1, 11 Sept 2026 -- was -0.032em */
    margin-bottom: 16px;
  }

  .section-sub {
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 15px;
    font-weight: 500; /* bumped from inherited 400, +30% per James's request, 2 Sept 2026 — nearest self-hosted weight */
    color: var(--text);
    max-width: 480px;
    line-height: 1.65;
  }

  /* light-section text overrides — everything below hardcodes light-on-dark
     colours, so .section--light needs explicit dark-on-light equivalents */
  .section--light .section-label { color: var(--text-on-light); }
  .section--light .section-label::before,
  .section--light .section-label::after { background: var(--text-on-light); }
  .section--light .section-sub { color: var(--text-on-light-dim); }

  /* ── PROBLEM ──
     Left-aligned per the mixed-alignment pass (25 Aug 2026) — the hero is the
     one asymmetric moment on the old layout; everything else was centred by
     default. Problem/Process lean left, Products leans right, CTA stays
     centred as a deliberate bookend echoing the hero. */
  .problem-center {
    max-width: 640px;
    margin: 0 0 52px;
  }
  .problem-center .section-sub { max-width: 520px; }

  /* Static grid — replaces the 24 Aug horizontal-scroll/carousel version.
     Three items fit one row cleanly at this width; no scrolling needed. */
  .problem-cards {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 20px;
    padding: 12px 4px 24px;
  }
  @media (max-width: 720px) {
    .problem-cards { grid-template-columns: 1fr; }
  }

  .problem-calc-link {
    display: flex;
    justify-content: flex-start;
    margin-top: 40px;
  }
  .problem-calc-link a {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    font-size: 14px; /* Slash Step 2, 11 Sept 2026: ghost pill, was 11px/700 uppercase copper-bordered */
    font-weight: 500;
    line-height: 1.2;
    color: var(--text);
    background: transparent;
    border: 1px solid var(--ghost-border);
    padding: 12px 24px;
    border-radius: var(--radius-pill);
    text-decoration: none;
    transition: background 0.2s, border-color 0.2s;
  }
  .problem-calc-link a:hover {
    background: var(--ghost-hover);
  }
  /* on the light section, the low-alpha black chip reads as washed-out grey —
     go solid dark so the white text stays legible */
  .section--light .problem-calc-link a { background: transparent; color: var(--text-on-light); border-color: var(--ghost-border-light); }
  .section--light .problem-calc-link a:hover { background: var(--ghost-hover-light); }

  .problem-card {
    background: rgba(17,18,20,0.6);
    backdrop-filter: blur(5px);
    -webkit-backdrop-filter: blur(5px);
    border: 1px solid var(--hairline); /* Slash Step 2, 11 Sept 2026: was copper --blue-border-soft */
    border-radius: var(--radius-card); /* Slash Step 2, 11 Sept 2026, was 28px. Earlier: was 22px, bumped to match .module-card, 2 Sept 2026 —
       branding-unification pass. Blur/border kept: this card sits over the
       scroll video, which needs the background-adaptive contrast the flat
       module-card shadow-only style can't provide over moving footage. */
    padding: 40px 34px;
    box-shadow: none; /* Slash Step 2, 11 Sept 2026: hairline, never drop shadows */
    text-align: center;
  }
  .section--light .problem-card {
    background: var(--card-light); /* Slash-migration full-dark fix, 11 Sept 2026 -- was hardcoded rgba(255,255,255,0.9), invisible white-on-white now the ground is dark (the card's own text already correctly repointed, only the background literal was missed). */
    border-color: var(--hairline-light);
    box-shadow: none;
  }

  .problem-icon {
    font-size: 20px;
    color: var(--text);
    font-weight: 700;
    margin-bottom: 16px;
  }
  .section--light .problem-icon { color: var(--text-on-light); }

  .problem-card-title {
    font-size: 17px;
    font-weight: 700; /* 800 -> 600 -> 700, locked 3 Sept 2026 as the standard title-card weight sitewide (James) */
    margin-bottom: 10px;
    line-height: 1.25;
  }

  .problem-card-desc {
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 13px;
    color: var(--text);
    line-height: 1.65;
  }
  .section--light .problem-card-desc { color: var(--text-on-light-dim); }
  /* 9 Sept 2026 -- .problem-card can now contain a trailing .m-link (used
     on the new #problem "Increase Leads / Reduce Admin" cards and the
     #pricing-intro Implementation/Ongoing cards). Card is text-align:center
     with no flex layout, so this is just spacing/display, no positioning
     change needed. */
  .problem-card .m-link { display: inline-block; margin-top: 16px; }

  /* ── PRODUCTS ── */
  /* #products used to force `background: transparent` here so the full-page
     scroll video showed through. The video is hero-confined as of 4 Sept 2026
     and this rule sat AFTER the opaque-ground rule at equal specificity, so it
     silently won and left this one section transparent. Painted flat like its
     neighbours now — see the opaque-ground note near .section. */

  /* Right-aligned per the mixed-alignment pass (25 Aug 2026) — the section
     most worth making visually distinct, since it's the core offer. */
  .products-header {
    margin-bottom: 44px;
    text-align: right;
  }
  .products-header .section-label { justify-content: flex-end; }
  .products-header .section-sub   { margin-left: auto; margin-right: 0; }

  /* Static grid — replaces the 24 Aug horizontal-scroll/carousel version.
     2×2 for the four core cards, Blueprint spans full width as a 5th row —
     close to the original pre-scroll shape, now with real gaps and full
     rounding on every card instead of the old joined hairline-grid strip. */
  .product-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 20px;
    padding: 12px 4px 24px;
  }
  @media (max-width: 720px) {
    .product-grid { grid-template-columns: 1fr; }
  }

  .product-card--blueprint {
    grid-column: 1 / -1;
  }

  .product-card {
    background: rgba(17,18,20,0.6);
    backdrop-filter: blur(5px);
    -webkit-backdrop-filter: blur(5px);
    border: 1px solid var(--hairline); /* Slash Step 2, 11 Sept 2026: was copper --blue-border */
    border-radius: var(--radius-card); /* Slash Step 2, 11 Sept 2026, was 28px */
    padding: 32px 28px;
    transition: background 0.2s, border-color 0.25s ease;
    box-shadow: none;
    text-align: center;
  }
  .product-card:hover { background: rgba(24,25,28,0.75); }

  .product-num {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.12em;
    color: var(--text);
    margin-bottom: 14px;
  }
  .product-num::before {
    content: '';
    display: inline-block;
    width: 6px;
    height: 6px;
    background: var(--text);
    border-radius: 50%;
    flex-shrink: 0;
    transition: box-shadow 0.2s;
  }
  @keyframes node-ping {
    0%   { box-shadow: 0 0 0 0   rgba(245,244,242,0.5); }
    100% { box-shadow: 0 0 0 10px rgba(245,244,242,0);  }
  }
  .product-card:hover .product-num::before {
    animation: node-ping 1s ease-out infinite;
  }

  /* ── CARD MICRO-INTERACTIONS (desktop hover only) ── */
  @media (hover: hover) and (pointer: fine) {
    /* Slash Step 2, 11 Sept 2026: no lift, no shadow growth -- the hairline
       brightens instead (DESIGN.md: never drop shadows for elevation). */
    .problem-card {
      transition: border-color 0.25s ease;
    }
    .problem-card:hover {
      border-color: var(--hairline-hover);
    }
    .section--light .problem-card:hover {
      border-color: var(--hairline-light-hover);
    }

    .process-step {
      transition: border-color 0.25s ease;
    }
    .process-step:hover {
      border-color: var(--hairline-hover);
    }
    .section--light .process-step:hover {
      border-color: var(--hairline-light-hover);
    }

    .problem-icon {
      position: relative;
      display: inline-block;
      transition: opacity 0.25s ease;
    }
    .problem-icon::after {
      content: '';
      position: absolute;
      left: 0;
      top: 50%;
      width: 8px;
      height: 8px;
      border-radius: 50%;
      background: var(--text);
      opacity: 0;
      transform: translateY(-50%);
      transition: opacity 0.25s ease;
    }
    .section--light .problem-icon::after { background: var(--text-on-light); }
    .problem-card:hover .problem-icon { opacity: 0; }
    .problem-card:hover .problem-icon::after {
      opacity: 1;
      animation: node-ping 1s ease-out infinite;
    }

    .product-card {
      transition: border-color 0.25s ease, background 0.2s ease;
    }
    .product-card:hover {
      border-color: var(--hairline-hover);
    }
    .section--light .product-card:hover {
      border-color: var(--hairline-light-hover);
    }
  }

  .product-name {
    font-size: 17px; /* 13 -> 17, card-title role unified 4 Sept 2026 (James). The old 13px existed only because five cards had to fit a row; there are four now. */
    font-weight: 700; /* was 700 -> 600 -> back to 700, locked 3 Sept 2026 as the standard title-card weight sitewide (James) */
    margin-bottom: 8px;
    line-height: 1.3;
  }

  .product-desc {
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 13px; /* 12 -> 13, "small" step of the body scale, 4 Sept 2026 */
    color: var(--text);
    line-height: 1.55;
  }

  /* #products HORIZONTAL SCROLL, 12 Sept 2026 (James) — layout-only
     conversion of the "ASTRO Systems" demo grid to a horizontal scroll-snap
     row, Apple-carousel style. (It was modelled on the .story-scroll
     component, which had its own section further down until 19 Sept 2026;
     this one is unaffected by that removal.)
     ID-scoped so the shared .product-grid/.product-card classes are
     completely untouched everywhere else they're used (ask-astro.html,
     insights.html and pricing.html still render the static grid;
     increase-leads.html and reduce-admin.html were rebuilt off it). Same .product-card content/copy
     and reveal-in animation, unchanged -- only the arrangement changed.
     Confined to the .container's own width (no viewport edge-bleed, which
     the retired narrative story-scroll did have) since this grid sits inside
     .container in the markup and this is a lighter demonstrations teaser,
     not a narrative arc -- cards still peek at the container's own edge,
     especially on mobile where the container's side padding is smaller.
     Reverses the 24 Aug decision to move #products away from a carousel --
     that was the right call for the old cramped 5-across layout; this is a
     deliberate, explicit re-introduction per James's 12 Sept instruction,
     not an oversight of that decision. */
  #products .product-grid {
    display: flex;
    grid-template-columns: none;
    gap: 20px;
    overflow-x: auto;
    overflow-y: hidden;
    scroll-snap-type: x proximity;
    scroll-padding-inline: 4px;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: thin;
    scrollbar-color: var(--hairline-hover) transparent;
  }
  #products .product-grid:focus-visible { outline: 2px solid var(--blue); outline-offset: 4px; border-radius: 4px; }
  #products .product-grid::-webkit-scrollbar { height: 6px; }
  #products .product-grid::-webkit-scrollbar-thumb { background: var(--hairline-hover); border-radius: 999px; }
  #products .product-grid::-webkit-scrollbar-track { background: transparent; }
  #products .product-card {
    flex: 0 0 auto;
    width: 240px;
    scroll-snap-align: start;
  }
  @media (min-width: 900px) { #products .product-card { width: 280px; } }

  /* ── PROCESS ── — left-aligned, matching Problem (mixed-alignment pass, 25 Aug 2026) */
  .process-header {
    margin-bottom: 44px;
  }

  /* Static grid — replaces the 24 Aug horizontal-scroll/carousel version.
     2×2 so each step (number + tag + title + description) has room to
     breathe, rather than cramming four across in one row. */
  .process-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 20px;
    padding: 12px 4px 24px;
  }
  @media (max-width: 720px) {
    .process-grid { grid-template-columns: 1fr; }
  }
  /* 3-step variant (index.html, 3 Sept 2026) — Ask Astro / The Right Fit /
     Full Deployment. Scoped modifier so the base 2-column rule above stays
     untouched for any future 2- or 4-step usage elsewhere. */
  .process-grid--3 {
    grid-template-columns: repeat(3, 1fr);
  }
  @media (max-width: 960px) {
    .process-grid--3 { grid-template-columns: repeat(2, 1fr); }
  }
  @media (max-width: 720px) {
    .process-grid--3 { grid-template-columns: 1fr; }
  }

  .process-step {
    background: rgba(17,18,20,0.6);
    backdrop-filter: blur(5px);
    -webkit-backdrop-filter: blur(5px);
    border: 1px solid var(--hairline); /* Slash Step 2, 11 Sept 2026: was copper, 22px, drop shadow */
    border-radius: var(--radius-card);
    padding: 38px 32px;
    box-shadow: none;
    text-align: center;
  }
  .section--light .process-step {
    background: var(--card-light); /* same fix, 11 Sept 2026 */
    border-color: var(--hairline-light);
    box-shadow: none;
  }

  .step-ghost {
    font-size: 52px;
    font-weight: 700;
    font-family: 'Courier New', Courier, monospace;
    color: rgba(245,244,242,0.22);
    line-height: 1;
    letter-spacing: 0.02em;
    margin-bottom: 18px;
    min-width: 2ch;
  }
  .section--light .step-ghost { color: var(--text-on-light-faint); }

  .step-tag {
    display: inline-block;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--text);
    background: var(--chip-bg);
    padding: 3px 9px;
    border-radius: var(--radius-pill);
    margin-bottom: 12px;
  }
  .section--light .step-tag { color: var(--text-on-light); background: var(--chip-bg-light); }

  .step-title {
    font-size: 17px; /* 15 -> 17, card-title role unified 4 Sept 2026 (James) */
    font-weight: 700;
    margin-bottom: 10px;
    line-height: 1.25;
  }

  .step-desc {
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 13px;
    color: var(--text);
    line-height: 1.65;
  }
  .section--light .step-desc { color: var(--text-on-light-dim); }

  /* ── STEPPED PROGRESS SCROLL, 7 Sept 2026 (James) ── #process on index.html
     only, replacing the old .process-grid 3-card layout. Built from
     steppedprogressscroll.md; mechanics-only classes below (.journey/
     .journey-rule/.journey-fill/.journey-marker/.journey-step/.journey-num)
     -- the actual tag/title/desc content reuses .step-tag/.step-title/
     .step-desc as-is, no duplicate styling. Marker/rule default to the
     dark-ground colours (matches every other component's default-dark,
     .section--light-overridden pattern); #process itself is currently
     always light, so the .section--light rules below are what actually
     render, but writing it this way keeps the component portable to a
     dark section later without rework. */
  .journey { position: relative; list-style: none; margin: 0; padding: 56px 0 0; }

  /* Rule sits BEHIND the markers (z-index) and the markers carry a solid,
     section-matched background -- so the line visually stops at each
     circle instead of running through it, no manual gap math needed.
     UNIFIED 12 Sept 2026 (James): the connecting line now draws itself with
     the exact same technique as the ring markers (stroke-dashoffset), not a
     separate CSS scaleY block -- one continuous "buffered" stroke-draw
     mechanic runs through circle -> line -> circle -> line down the whole
     path. viewBox is a fixed 0 0 2 100 with preserveAspectRatio="none", so
     the SVG stretches to the container's real height with no JS geometry
     needed -- dasharray/dashoffset stay in that 100-unit space regardless
     of how tall the rendered line actually is, so the revealed FRACTION is
     always exactly --fill, whatever the pixel height. vector-effect:
     non-scaling-stroke keeps the stroke a constant pixel width despite the
     vertical stretch. Reuses the same --fill custom property the JS already
     sets (no JS change needed for this part) and the same 700ms
     cubic-bezier(0.22,1,0.36,1) timing the ring-sweep uses, so both halves
     of the path move in lockstep. */
  .journey-rule {
    position: absolute;
    top: 4px; bottom: 4px;
    left: 22px; /* marker is 44px wide -- rule runs through its centre */
    width: 2px;
    z-index: 0;
  }
  .journey-rule-svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
  .journey-line-track {
    stroke: var(--divider);
    stroke-width: 1.5;
    vector-effect: non-scaling-stroke;
    opacity: 0.6;
  }
  .section--light .journey-line-track { stroke: var(--divider-light); }
  /* FIXED 14 Sept 2026 — vector-effect:non-scaling-stroke removed from the
     sweep only. With it, Chromium measures stroke-dasharray in SCREEN pixels,
     so "100" became a 100px dash repeating down the rail: the line rendered as
     copper dashes with dark gaps at every fill value (confirmed on the
     pre-rebuild page, --fill 0.88). Without it the dash is measured in viewBox
     units, so the revealed fraction is exactly --fill as intended. The width
     stays 1.5px because this viewBox's horizontal scale is exactly 1 (2 units
     across a 2px-wide rule). The track has no dash and keeps the property. */
  .journey-line-sweep {
    stroke: var(--blue);
    stroke-width: 1.5;
    stroke-linecap: round;
    stroke-dasharray: 100;
    stroke-dashoffset: calc(100 - (100 * var(--fill, 0)));
    transition: stroke-dashoffset 700ms cubic-bezier(0.22, 1, 0.36, 1);
  }
  .section--light .journey-line-sweep {
    stroke: var(--blue-on-light);
  }
  @media (max-width: 720px) { .journey-rule { display: none; } }

  .journey-step { position: relative; padding: 0 0 40px 72px; }
  .journey-step:last-child { padding-bottom: 0; }
  @media (max-width: 720px) { .journey-step { padding-left: 0; } }

  .journey-marker {
    position: absolute;
    z-index: 1;
    top: 0; left: 0;
    display: flex;
    align-items: center; justify-content: center;
    width: 44px; height: 44px;
    border-radius: 50%;
    background: var(--bg);
    font-size: 11px; font-weight: 700;
    color: var(--text-faint);
    transition: color 400ms, background 400ms, box-shadow 400ms;
  }
  .section--light .journey-marker { background: var(--card-light); color: var(--text-on-light-faint); }

  /* Static ring track, always visible at low contrast */
  .journey-ring { position: absolute; inset: 0; width: 44px; height: 44px; transform: rotate(-90deg); pointer-events: none; }
  .journey-ring-track { fill: none; stroke: var(--blue-border-soft); stroke-width: 1; }
  .journey-ring-sweep {
    fill: none;
    stroke: var(--blue);
    stroke-width: 1.5;
    stroke-linecap: round;
    stroke-dasharray: 125.6;
    stroke-dashoffset: 125.6;
    transition: stroke-dashoffset 700ms cubic-bezier(0.22, 1, 0.36, 1);
  }
  .section--light .journey-ring-sweep { stroke: var(--blue-on-light); }
  .journey-marker-num { position: relative; z-index: 1; }

  .journey-step.is-active .journey-marker {
    color: var(--text);
    box-shadow: 0 0 0 1px var(--blue-border);
  }
  .section--light .journey-step.is-active .journey-marker {
    color: var(--text-on-light);
    box-shadow: 0 0 0 1px var(--blue-border);
  }
  /* the ring "runs around and lights up" -- draws itself from empty to a
     full circle in step with the vertical fill reaching this marker */
  .journey-step.is-active .journey-ring-sweep { stroke-dashoffset: 0; }
  @media (max-width: 720px) { .journey-marker { display: none; } }

  .journey-num {
    display: none;
    font-size: 11px; font-weight: 700;
    letter-spacing: 0.15em;
    color: var(--text-faint);
    margin-bottom: 8px;
  }
  .section--light .journey-num { color: var(--text-on-light-faint); }
  @media (max-width: 720px) { .journey-num { display: block; } }

  /* The .step-tag/.step-title/.step-desc reused here already carry full
     colour handling (see their rules above) -- no journey-scoped override
     needed for any of them. */

  @media print {
    .journey-line-sweep { stroke-dashoffset: 0 !important; transition: none !important; filter: none !important; }
    .journey-ring-sweep { stroke-dashoffset: 0 !important; }
    .journey-marker {
      background: var(--card-light) !important;
      color: var(--text-on-light) !important;
    }
  }

  /* ── CTA ── */
  #cta {
    text-align: center;
    padding: 64px 0 52px;
    background: transparent;
  }

  .cta-headline {
    font-family: 'Playfair', 'Familjen Grotesk', 'Inter', sans-serif; /* was Familjen Grotesk, then Playfair Display, 7 Sept 2026 (James) -- title font */
    font-size: clamp(38px, 6vw, 76px); /* Slash-migration Step 1, 11 Sept 2026 -- was clamp(36px,5vw,58px); matched to .hero-tagline's new scale, both are the biggest editorial moments */
    font-weight: 700; /* matched to .section-headline's title-card weight, 3 Sept 2026 (was 800) */
    line-height: 1.08;
    letter-spacing: var(--tracking-display); /* Slash-migration Step 1, 11 Sept 2026 -- was -0.032em */
    margin-bottom: 20px;
  }

  .cta-sub {
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 17px;
    color: var(--text);
    max-width: 380px;
    margin: 0 auto 40px;
    line-height: 1.6;
    /* text-shadow removed, 6 Sept 2026 (James) -- expanded beyond the smallest-text pass to tagline/sub text */
  }

  .cta-urgency {
    display: block;
    font-size: 11px;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--text);
    margin-top: 18px;
    font-weight: 600;
    /* text-shadow removed, 6 Sept 2026 (James) -- smallest text sizes, see 9.7 */
  }

  .guarantee-strip {
    display: flex;
    justify-content: center;
    margin-top: 52px;
  }

  .g-item {
    padding: 0 36px;
    border-right: 1px solid var(--divider);
  }
  .g-item:first-child { padding-left: 0; }
  .g-item:last-child  { border-right: none; padding-right: 0; }

  .g-title {
    font-size: 14px;
    font-weight: 700;
    color: var(--text);
    margin-bottom: 5px;
  }

  .g-desc {
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 13px;
    font-weight: 500; /* bumped from inherited 400, 2 Sept 2026, to match .section-sub/.m-body consistency fix */
    color: var(--text);
    line-height: 1.5;
    max-width: 155px;
  }



    /* ── FOOTER ── */
  footer {
    padding: 36px 48px;
    border-top: 1px solid var(--divider);
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;
    z-index: 2;
    background: var(--bg);
  }

  .footer-center {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
  }

  .footer-brand {
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--text);
    text-align: center;
  }

  /* FOOTER CONTACT, 9 Sept 2026 -- contact.html was cut this session (Ask
     Astro is now the whole conversion path); its one piece of durable
     info, a way to reach a person directly, moved here instead of being
     lost. Same email as the JSON-LD contactPoint -- one source of truth. */
  .footer-contact {
    font-size: 12px;
  }
  .footer-contact a {
    color: var(--meta);
    text-decoration: none;
    transition: color 0.18s;
  }
  .footer-contact a:hover { color: var(--text); }

  .footer-legal {
    display: flex;
    align-items: center;
    gap: 8px;
  }

  .footer-legal-link {
    font-size: 10px;
    color: var(--meta);
    text-decoration: none;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    transition: color 0.18s;
  }
  .footer-legal-link:hover { color: var(--text); }
  .footer-legal-sep { color: var(--meta); opacity: 0.35; font-size: 10px; }

  /* FLOW STRIP, 9 Sept 2026 -- new, shared by increase-leads.html
     ("Enquiry -> Response -> Qualification -> Follow-Up -> Appointment ->
     CRM") and reduce-admin.html ("Manual Process -> ASTRO System -> Human
     Only Handles What Requires Human Input"). Plain text steps, arrow
     separators, wraps on mobile -- deliberately not a new interactive
     component, just a typographic device restating the page's journey. */
  .flow-strip {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px 14px;
    margin-top: 28px;
  }
  .flow-step {
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 13px;
    font-weight: 700;
    letter-spacing: 0.02em;
    color: var(--text);
    background: rgba(255,255,255,0.06);
    border: 1px solid var(--tag-border); /* Slash Step 2, 11 Sept 2026: Slash Pill Tag outline, was copper */
    border-radius: var(--radius-pill);
    padding: 8px 16px;
    white-space: nowrap;
  }
  .section--light .flow-step,
  .band-light .flow-step {
    color: var(--text-on-light);
    background: var(--ghost-hover-light); /* Slash-migration full-dark fix, 11 Sept 2026 -- was hardcoded rgba(10,10,10,0.05), a near-invisible wash now the ground is dark; missed by the earlier token repoint since it was a literal, not a var(). */
    border-color: var(--tag-border-light);
  }
  .flow-arrow {
    color: var(--meta);
    font-size: 14px;
  }

  /* LIGHT CARD GRID, 9 Sept 2026 -- product-card on a .section--light
     background (increase-leads.html/reduce-admin.html "more systems"
     grids). product-card's existing background/border was tuned for dark
     grounds only; this gives it a light-ground equivalent, same pattern
     as .section--light .problem-card above. */
  .section--light .product-card {
    background: var(--card-light); /* same fix, 11 Sept 2026 */
    border-color: var(--hairline-light);
    box-shadow: none;
  }
  .section--light .product-name { color: var(--text-on-light); }
  .section--light .product-desc { color: var(--text-on-light-dim); }
  .section--light .product-num { color: var(--text-on-light-faint, rgba(10,10,10,0.3)); }
  .section--light .product-num::before { background: var(--text-on-light-faint, rgba(10,10,10,0.3)); }

  /* WORK BREAKDOWN, 9 Sept 2026 -- new, work.html. Problem/System/Workflow/
     Outcome for each demonstration, per the brief. Small 2x2 label/text
     grid sitting inside .module-text alongside the existing m-body copy --
     not a new card type, just a structured expansion of what m-body
     already does in prose elsewhere. */
  .work-breakdown {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 20px 24px;
    margin: 24px 0;
  }
  .wb-item { }
  .wb-label {
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--blue);
    margin-bottom: 6px;
  }
  .on-light .wb-label,
  .section--light .wb-label { color: var(--blue-on-light); }
  .wb-text {
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 14px;
    font-weight: 500;
    line-height: 1.5;
    color: var(--text);
  }
  .on-light .wb-text,
  .section--light .wb-text { color: var(--text-on-light); }
  @media (max-width: 720px) {
    .work-breakdown { grid-template-columns: 1fr; gap: 18px; }
  }

  /* DEMO LABEL, 9 Sept 2026 -- work.html. Small explicit "this is a
     demonstration, not a client result" chip, required by the brief
     ("clearly presented as demonstrations ... not client case studies")
     and consistent with the Claim Verification Standard already applied
     to .still-note copy sitewide. */
  .demo-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.10em;
    text-transform: uppercase;
    color: #8C8980; /* was var(--meta), 4.15:1 on --card -- bumped for 4.5:1 AA, Step 4 review */
    border: 1px solid var(--divider);
    border-radius: var(--radius-pill);
    padding: 6px 14px;
    margin-bottom: 16px;
  }
  .section--light .demo-chip,
  .band-light .demo-chip { border-color: var(--divider-light); color: var(--text-on-light-dim); }

  /* FAQ PREVIEW LIST, 9 Sept 2026 -- new, #faq-preview on index.html. Plain
     stacked Q/A, no accordion/toggle JS -- kept deliberately simple for a
     home-section teaser; faq.html carries the full page. */
  .faq-preview-list {
    display: flex;
    flex-direction: column;
    gap: 28px;
    max-width: 640px;
    margin-top: 32px;
  }
  .faq-q {
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 16px;
    font-weight: 700;
    color: var(--text);
    margin-bottom: 6px;
  }
  .faq-a {
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 14px;
    font-weight: 500;
    color: var(--text-dim);
    line-height: 1.5;
  }

  /* ── RESPONSIVE ── */
  @media (max-width: 960px) {
    .nav-links      { display: none; }
    .nav-hamburger  { display: flex; }
    .nav-btn        { display: none; }
  }

  @media (max-width: 640px) {
    nav              { padding: 0 20px; }
    .container       { padding: 0 20px; }
    .section         { padding: 54px 0; } /* Reverted to Slash Step 1's 72px then decreased 25% (54px), 11 Sept 2026 -- kept in sync with the 720px rule above to avoid reintroducing gotcha 9.5 #6 */
    #cta             { padding: 64px 0 52px; }
    .hero-content .btn-primary { font-size: 15px; padding: 15px 32px; }   /* larger CTA on phones -- rescaled to the pill spec, Slash Step 2, 11 Sept 2026 */
    .guarantee-strip { flex-direction: column; gap: 20px; align-items: center; }
    .g-item          { border-right: none; padding: 0 0 20px; border-bottom: 1px solid var(--divider); text-align: center; width: 100%; }
    .g-item:last-child { border-bottom: none; padding-bottom: 0; }
    .g-desc          { max-width: none; margin: 0 auto; }
    footer           { padding: 24px 20px 20px; justify-content: center; }
  }

  /* ── SPACE MOTIF SYSTEM ── built 1 Sept 2026, Astro_brain.md Section 1 spec.
     Three ambient layers (starfield, orbit-rings, particle drift) for the
     other 28 pages + the node-network signature for product-story pages.
     JS for starfield/particle-drift/node-network lives in
     assets/js/astro-motifs.js — call AstroMotifs.initX() per page. Orbit
     rings are pure SVG + CSS below, no JS needed. */

  #astro-starfield, #astro-particle-drift {
    position: fixed; inset: 0; z-index: -2; pointer-events: none;
  }

  /* Orbit-path rings — thin elliptical ring lines behind section content/
     module cards. Deliberately white/divider-coloured, not blue: the
     locked blue-border-only rule (Section 2) reserves blue for real card/
     button perimeters, and a dot riding this path would read as a "blue
     dot" if the ring itself were blue-tinted, which the rule explicitly
     bans. Kept ambient like the starfield rather than a second signature —
     see the frontend-design skill's restraint note in Astro_brain.md.
     Markup pattern (place behind a section's content, e.g. as the first
     child of a .section wrapper with position:relative):
       <svg class="orbit-ring" viewBox="0 0 400 400" aria-hidden="true">
         <ellipse cx="200" cy="200" rx="170" ry="70" transform="rotate(-18 200 200)"/>
         <circle class="orbit-ring-dot" r="3" />
       </svg>
     The dot's position is animated along the ellipse via offset-path in the
     .orbit-ring-dot rule below — supported in all evergreen browsers this
     site targets; if offset-path support is ever a concern, the dot can be
     dropped and the ring alone still reads fine as ambient texture. */
  .orbit-ring {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    z-index: 0;
    pointer-events: none;
    overflow: visible;
  }
  .orbit-ring ellipse {
    fill: none;
    stroke: var(--divider);
    stroke-width: 1;
  }
  .orbit-ring-dot {
    fill: rgba(245,244,242,0.4);
    offset-path: path('M 30,200 A 170 70 -18 1 1 370,200 A 170 70 -18 1 1 30,200');
    animation: orbit-travel 42s linear infinite;
  }
  @keyframes orbit-travel {
    from { offset-distance: 0%; }
    to   { offset-distance: 100%; }
  }
  @media (prefers-reduced-motion: reduce) {
    .orbit-ring-dot { animation: none; offset-distance: 0%; }
  }

  /* ── SHARED PAGE COMPONENTS ── added 1 Sept 2026 during the site-wide
     stylesheet-consolidation sweep, restyled off Astro's black/white/
     blue-border-only system (was CE gold throughout on every source page).
     Covers the four widget types found in the "audit other 28 pages"
     pass: FAQ accordion, form fields, calculator inputs, insights-article
     cards. Legal pages (privacy/terms/cookie) need no special component —
     the base h2/h3/p typography above already covers them. */

  /* FAQ accordion — native <details>/<summary>, no JS needed. */
  .faq-item { border-bottom: 1px solid var(--divider); }
  .faq-item:last-child { border-bottom: none; }
  .faq-question {
    display: flex; align-items: center; justify-content: space-between;
    padding: 22px 4px; cursor: pointer; list-style: none;
    font-weight: 600; font-size: 17px; color: var(--text);
    transition: color 0.25s ease;
  }
  .faq-question::-webkit-details-marker { display: none; }
  .faq-question::marker { display: none; }
  .faq-question::after {
    content: '+'; font-size: 22px; font-weight: 300; color: var(--text-dim);
    transition: transform 0.3s ease;
  }
  details[open] > .faq-question::after { transform: rotate(45deg); }
  .faq-question:hover { color: var(--blue); } /* text-colour hover is fine — not a fill/border/dot use */
  .faq-answer { padding: 0 4px 24px; color: var(--text); }
  .faq-answer p { margin-bottom: 12px; }

  /* Form fields — contact.html. Netlify form handling (data-netlify,
     honeypot field) is markup, not styling — unaffected by this pass. */
  .form-label { display: block; font-size: 14px; color: var(--text-dim); margin-bottom: 8px; }
  .form-input, .form-textarea {
    width: 100%; background: var(--card); border: 1px solid var(--divider);
    border-radius: var(--radius-input); padding: 14px 20px; color: var(--text); /* Slash Step 2, 11 Sept 2026: pill inputs */
    font-family: 'Inter', sans-serif; font-size: 15px;
    transition: border-color 0.25s ease;
  }
  .form-input:focus, .form-textarea:focus {
    outline: none; border-color: var(--blue-border); /* border-only on focus — matches the locked rule */
  }
  .form-textarea { resize: vertical; min-height: 120px; border-radius: var(--radius-card); } /* multi-line: card radius, a pill textarea reads wrong */
  .form-honeypot { position: absolute; left: -9999px; } /* bot-field stays hidden, unchanged behaviour */

  /* Calculator inputs — roi-calculator.html. Same visual language as form
     fields above; .calc-grid is a simple responsive grid, no accent needed. */
  .calc-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; }
  @media (max-width: 720px) { .calc-grid { grid-template-columns: 1fr; } }
  .calc-grid input[type="number"] {
    width: 100%; background: var(--card); border: 1px solid var(--divider);
    border-radius: var(--radius-input); padding: 12px 18px; color: var(--text); font-size: 15px;
  }
  .calc-grid input[type="number"]:focus { outline: none; border-color: var(--blue-border); }
  #calc-canvas { position: absolute; inset: 0; z-index: 0; pointer-events: none; }
  /* Wire with: AstroMotifs.initNodeNetwork('calc-canvas', {nodeCount: 18, linkDist: 120})
     — the calculator is a live product tool, a legitimate second place for
     the node-network signature alongside services.html/stop-*.html. */

  /* Insights article-card grid — insights.html. Reuses the product-card
     visual language (card surface, radius, shadow) already defined above. */
  .article-card {
    display: block; background: var(--card); border-radius: var(--radius-card);
    border: 1px solid var(--hairline); /* Slash Step 2, 11 Sept 2026: hairline, was 22px + drop shadow + lift */
    padding: 28px; text-decoration: none; color: var(--text);
    transition: border-color 0.25s ease;
  }
  .article-card:hover { border-color: var(--hairline-hover); }

  /* ── MODULE BAND SYSTEM ── added 1 Sept 2026, services.html rebuild v2.
     Porsche-style alternating full-width black/white page bands, each
     containing ONE unified rounded card (not two flush-to-edge halves —
     the first pass got this wrong; James caught the symmetry issue and
     the "should be one curved box" note). Image bleeds to the CARD's own
     rounded edge, not the page edge. Fixed 44/56 text/image split, same
     proportions whichever side the image sits on via .reverse. Apple's
     type hierarchy: eyebrow / bold headline / dim body / blue text link
     with chevron — three distinct weights, not one uniform paragraph. */
  .module-band { padding: 105px 40px; } /* Reverted to Slash Step 1's 140px then decreased 25% (105px, vertical only), 11 Sept 2026 */
  /* REVERTED, 7 Sept 2026, same day -- the white-band padding bump above (152px,
     then 230px) was a ratio-forcing hack: it padded services.html's white bands
     purely to chase the black/white 2:1 height target, with no content
     justification. James's follow-up instruction retired this approach as a
     STANDING RULE (see Section 9.9 below): padding fits each section's own
     content, full stop -- the black/white ratio is allowed to drift as a
     consequence and is never corrected by inflating padding again. Reverted to
     the plain .module-band base (96px/40px, 56px/20px mobile per the existing
     720px override) for every band, light or dark, both pages. */
  /* Starfield on black module-bands, 7 Sept 2026 (James, black/white rebalance:
     "no part of the black pages should not have the star system"). Same photo/
     overlay treatment as #products on index.html. Currently only matches
     services.html's Outbound Sales Agent band (the one module-band that landed
     on Black in the repeating B/W/W pattern) -- scoped to the class, not an id,
     so it will pick up automatically if a future band flips to dark too. */
  .module-band.band-dark  {
    background-image:
      linear-gradient(rgba(6,6,8,0.6), rgba(6,6,8,0.6)),
      url('../images/starfield/deep-sky-starfield.jpg');
    background-size: cover, cover;
    background-position: center, center;
    background-repeat: no-repeat, no-repeat;
    background-color: var(--bg);
  }
  .module-band.band-light { background: var(--bg-light); } /* was hardcoded #F5F4F2, same stale-cool-value bug as the token above */

  /* #chat-cta on services.html stays Black in the repeating pattern (its
     inline `style="background:var(--bg)"` was removed 7 Sept 2026 -- an
     inline background shorthand blocks an external background-image rule
     from ever applying, since the shorthand implicitly resets
     background-image to none at higher specificity). Scoped with the
     .band-dark class so this never matches index.html's #chat-cta, which
     is White in the same pattern and carries no band-dark class. */
  #chat-cta.band-dark {
    background-image:
      linear-gradient(rgba(6,6,8,0.6), rgba(6,6,8,0.6)),
      url('../images/starfield/deep-sky-starfield.jpg');
    background-size: cover, cover;
    background-position: center, center;
    background-repeat: no-repeat, no-repeat;
    background-color: var(--bg);
  }
  /* Light-band text override — base .section-label/.section-headline/
     .section-sub are hardcoded white (var(--text)), correct for the
     black page background everywhere else on the site. Reusable for any
     future page that sits content directly on a light band. */
  .band-light .section-label,
  .band-light .section-headline { color: var(--text-on-light); } /* Slash-migration full-dark fix, 11 Sept 2026 -- was hardcoded #0A0A0A, invisible black-on-black now band-light is dark; live on increase-leads/reduce-admin/work.html. */
  .band-light .section-sub { color: var(--text-on-light-dim); } /* same fix, 11 Sept 2026 */

  .module-card {
    max-width: 1200px; margin: 0 auto;
    display: flex; align-items: stretch;
    border-radius: var(--radius-card); overflow: hidden; /* Slash Step 2, 11 Sept 2026, was 28px */
    min-height: 380px;
  }
  .module-card.reverse { flex-direction: row-reverse; }
  /* 1 Sept 2026 fix: dropped the full-card blue perimeter — a flat dark
     card with only a blue outline read as inert (James's "black on black"
     note). Porsche's own card treatment lifts with shadow, not an outline;
     matched here. Blue stays reserved for .m-link only on this component. */
  /* Slash Step 2, 11 Sept 2026: shadow lift replaced by a neutral hairline (DESIGN.md). */
  .module-card.on-dark  { background: var(--card); border: 1px solid var(--hairline); }
  .module-card.on-light { background: var(--card-light); border: 1px solid var(--hairline-light); } /* Slash-migration full-dark ladder, 11 Sept 2026 -- was hardcoded #FFFFFF, missed by the token repoint since it didn't go through --card-light. */

  .module-text  { flex: 0 0 44%; display: flex; flex-direction: column; justify-content: center; padding: 56px; }
  .module-image { flex: 0 0 56%; display: flex; align-items: center; justify-content: center; }
  /* 2 Sept 2026 fix: the image slot's own fill was a low-alpha BLUE gradient
     — a fill use, which breaks the site's blue-border-only rule, and was
     too faint against #0A0A0A to register at all ("too faint to see the
     difference"). Replaced with a flat neutral panel so the slot reads as
     a distinct surface regardless of what's in it — moved to .module-image
     itself (not just the placeholder text layer) so it survives once real
     illustrations replace the placeholder. */
  .on-dark  .module-image { background: var(--chip-bg); }
  .on-light .module-image { background: var(--bg-light); } /* was hardcoded #F5F4F2 */
  .module-image-placeholder {
    width: 100%; height: 100%; display: flex; align-items: center; justify-content: center;
    font-family: 'Inter', sans-serif; font-size: 13px; text-align: center; padding: 20px;
  }
  .on-dark .module-image-placeholder  { color: var(--text-dim); }
  .on-light .module-image-placeholder { color: var(--text-on-light-faint); } /* same fix, 11 Sept 2026 */

  .m-eyebrow { font-size: 12px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; margin-bottom: 14px; opacity: 0.5; }
  .m-headline { font-family: 'Playfair', 'Familjen Grotesk', 'Inter', sans-serif; font-size: clamp(26px, 3.4vw, 34px); font-weight: 700; line-height: 1.15; margin: 0 0 14px; letter-spacing: var(--tracking-display); } /* 700 -> 600 -> 700, locked 3 Sept 2026 as the standard title-card weight sitewide (James); font-family Playfair Display added then swapped to Playfair, 7 Sept 2026. Tracking flipped positive, Slash-migration Step 1, 11 Sept 2026 -- was -0.02em. Size clamped, Slash-migration Step 3, 11 Sept 2026 -- was a bare unclamped 34px, the one off-scale role flagged in Brain Section 2; now on-scale, closing that flag. */
  .m-body { font-size: 15px; line-height: 1.55; font-weight: 500; opacity: 0.68; margin: 0 0 20px; max-width: 340px; } /* bumped 400->500 2 Sept 2026 to match .section-sub, consistency fix */
  .m-link { font-size: 15px; font-weight: 700; letter-spacing: -0.01em; color: var(--blue); text-decoration: none; } /* weight 500->700, 2 Sept 2026. Blue link text is explicitly permitted under the amended blue rule (4 Sept 2026, see :root) — blue marks interaction. */
  .m-link:hover { text-decoration: underline; }

  .on-dark .m-eyebrow, .on-dark .m-headline, .on-dark .m-body { color: var(--text); }
  /* .on-light text colour: see the consolidated #14150F rule further down (was a
     duplicate #0A0A0A declaration here, superseded by source order per gotcha 9.5
     #6 -- removed 5 Sept 2026 rather than left as a silent dead rule). */
  .module-card.on-light .m-body { opacity: 0.6; }
  /* On-light link colour, added 5 Sept 2026 -- .m-link's base colour is var(--blue)
     (sand), which measures ~1.9:1 on a light ground and is effectively invisible.
     This was a live bug on services.html's existing on-light module cards, not just
     new work -- see --blue-on-light in :root. */
  .on-light .m-link { color: var(--blue-on-light); }
  .section--light .m-link { color: var(--blue-on-light); } /* 9 Sept 2026 -- same contrast fix as .on-light .m-link, needed once #pricing-intro used m-link on a white section directly */

  @media (max-width: 860px) {
    .module-card, .module-card.reverse { flex-direction: column; }
    .module-text, .module-image { flex: 1 1 auto; }
    .module-image { min-height: 220px; }
    .module-text { padding: 40px 32px; }
  }

  /* ── CHAT-AGENT CTA BRIDGE ── replaces the audit-based CTA on
     services.html per James's 1 Sept decision to scrap the audit funnel
     on this page (sitewide rollout still pending, see Astro_brain.md).
     Styled as a chat-window teaser — frontend only in this pass, not yet
     wired to a live Vapi/Chat Receptionist backend (flagged as a Known
     Gap). Dogfoods Astro's own Chat Receptionist product as the site's
     own funnel bridge, per the "conversational agent replaces the demo
     form" research finding. */
  .chat-cta-box {
    max-width: 640px; margin: 0 auto; background: var(--card);
    border: 1px solid var(--tag-border); border-radius: var(--radius-input); padding: 6px;
  } /* Slash Step 2, 11 Sept 2026: DESIGN.md "Email Capture Input" -- pill field + button reading as one unit, larger left padding */
  .chat-cta-input-row { display: flex; align-items: center; gap: 10px; padding: 4px 4px 4px 20px; }
  .chat-cta-input {
    flex: 1; background: transparent; border: none; outline: none;
    color: var(--text); font-family: 'Inter', sans-serif; font-size: 15px;
  }
  .chat-cta-input::placeholder { color: var(--text-dim); }
  .chat-cta-send {
    background: transparent; border: 1px solid var(--ghost-border); border-radius: var(--radius-pill);
    color: var(--text); font-family: 'Inter', sans-serif; font-size: 14px; font-weight: 500; line-height: 1.2;
    padding: 10px 20px; cursor: pointer; white-space: nowrap;
    transition: background 0.18s;
  }
  .chat-cta-send:hover { background: var(--ghost-hover); }
  .chat-cta-fallback { margin-top: 18px; font-size: 14px; }
  .chat-cta-fallback a { color: var(--blue); text-decoration: none; }
  .chat-cta-fallback a:hover { text-decoration: underline; }

  /* PROSE LINKS -- added 11 Sept 2026, Slash Step 4 review. Plain <a> tags
     inside legal-page clauses and insights-article bodies had no colour
     rule at all, so they rendered the browser's default link blue
     (#0000EE) -- fine on the pre-migration white legal pages, ~2.1:1 and
     effectively invisible since Step 3 went full-dark. */
  .legal-clause a, #article-body a, #method a {
    color: var(--blue);
    text-decoration: underline;
  }

  /* On-light equivalents for the CTA/guarantee-strip block, 7 Sept 2026 --
     needed now that #chat-cta is a .section--light section (black/white
     rebalance). These elements previously assumed the dark ground (var(--text)/
     var(--card)/var(--divider)) unconditionally; scoped overrides below flip
     them for a light ground exactly like the existing .section--light rules
     for #problem/#process content. */
  .section--light .cta-sub { color: var(--text-on-light-dim); }
  .section--light .cta-urgency { color: var(--text-on-light); }
  .section--light .g-item { border-right-color: var(--divider-light); }
  .section--light .g-title { color: var(--text-on-light); }
  .section--light .g-desc { color: var(--text-on-light-dim); }
  .section--light .chat-cta-box {
    background: var(--card-light);
    border-color: var(--tag-border-light);
    box-shadow: none;
  }
  .section--light .chat-cta-input { color: var(--text-on-light); }
  .section--light .chat-cta-input::placeholder { color: var(--text-on-light-faint); }
  .section--light .chat-cta-send { color: var(--text-on-light); border-color: var(--ghost-border-light); }
  .section--light .chat-cta-send:hover { background: var(--ghost-hover-light); }


  /* ══ PRODUCT-IN-USE INTERFACE STILL ══════════════════════════════════
     Added 4 Sept 2026, session 4. Replaces the rejected 3D module-render
     direction: the object standing on the card is the system doing its
     job, not a fabricated prop standing in for software. James's ruling
     was that the render idea was wrong at the concept level, not badly
     executed, so the whole imagery route for module cards changes here.
     Built as DOM rather than an image on purpose: crisp at any width,
     ~0KB, no generator/watermark/seed dependency, no transparency
     workaround for services.html's light bands, and replaceable by a
     real anonymised record later without redesigning the slot.
     Blue rule, unchanged and observed: the still carries ONE 1px
     perimeter border and the outcome row ONE 2px left rule. No blue
     text inside it, no fill, no glow, nothing emissive.
     Claim Verification Standard: every value shown is Astro's own
     stated system behaviour. Nothing here is a result or a benchmark. */

  .module-image--still { padding: 44px 40px; align-items: center; }

  /* .still needs no .on-light variant (checked 5 Sept 2026, alternating-grounds
     audit): it is a self-contained dark UI screen -- background, dividers and text
     inside it are all fixed values that don't reference the page ground, the same
     way a phone screenshot stays dark regardless of the page it sits on. Its border
     (--blue-border-soft) and outcome rule (--blue, full sand) are both read against
     the still's own near-black background, not the surrounding card, so the on-light
     sand-contrast fix above doesn't apply here. */
  .still {
    width: 100%; max-width: 420px;
    background: #050505;
    border: 1px solid var(--blue-border-soft);
    border-radius: 20px; overflow: hidden;
    box-shadow: 0 2px 5px rgba(0,0,0,0.30), 0 18px 40px rgba(0,0,0,0.45);
  }

  .still-head {
    display: flex; align-items: baseline; justify-content: space-between;
    gap: 12px; padding: 15px 20px; border-bottom: 1px solid var(--divider);
  }
  .still-src {
    font-size: 11px; font-weight: 600; letter-spacing: 0.18em;
    text-transform: uppercase; color: var(--text);
  }
  .still-time {
    font-family: 'Courier New', Courier, monospace;
    font-size: 12px; color: var(--text-dim); white-space: nowrap;
  }

  .still-body { padding: 4px 20px 8px; }
  .still-line { padding: 10px 0; border-bottom: 1px solid var(--divider); }
  .still-line:last-child { border-bottom: 0; }
  .still-who {
    display: block; margin-bottom: 4px;
    font-size: 10px; font-weight: 700; letter-spacing: 0.08em;
    text-transform: uppercase; color: var(--text-faint);
  }
  .still-said { font-size: 13px; font-weight: 500; line-height: 1.5; color: var(--text); }

  .still-out {
    display: flex; align-items: baseline; gap: 14px; flex-wrap: wrap;
    margin: 2px 20px 18px; padding: 11px 0 11px 16px;
    border-left: 2px solid var(--blue);
  }
  .still-out-key {
    font-size: 11px; font-weight: 600; letter-spacing: 0.18em;
    text-transform: uppercase; color: var(--text);
  }
  .still-out-val {
    font-family: 'Courier New', Courier, monospace;
    font-size: 12px; color: var(--text-dim);
  }

  /* ══ STORY SCROLL ═════════════════════════════════════════════════
     REMOVED 19 September 2026. The horizontal scroll-snap carousel built
     12 Sept 2026 had exactly one user, reduce-admin.html's
     #admin-assistant-story, and that page was rebuilt around the
     interface kit. Grepped across every non-backup .html and .js first:
     zero remaining references to .story-scroll*, .story-card* or the
     section id, so the 21 rules went with the markup they styled.
     The .still card they reused is untouched and still used elsewhere.
     If a horizontal narrative carousel is ever wanted again, the Brain's
     12 Sept History Log entry records why a comparison-style carousel
     was the wrong fit for a linear one. */
  /* ══ SPEC ROW ════════════════════════════════════════════════════════
     The one Porsche device agreed as transferable (4 Sept 2026): hard
     numbers under the module, no adjectives anywhere near them, the copy
     doing nothing but labelling. Every cell is governed by the Claim
     Verification Standard. Astro's own stated terms state flat; anything
     shaped like "saves N hours a week" needs a named source or benchmark
     framing and does not belong in this component. */
  .spec-row {
    display: flex; flex-wrap: wrap;
    margin-top: 28px; border-top: 1px solid var(--divider);
  }
  .spec-cell { flex: 1 1 0; min-width: 96px; padding: 16px 18px 0 0; }
  /* Inter, not the mono placeholder. Courier's wide advance opened a
     visible gap inside "10 days" and read as typewriter rather than
     spec sheet. Mono stays where it means machine output: the still's
     timestamp and outcome line. Tabular figures keep the three cells
     optically aligned. */
  .spec-num {
    font-family: 'Inter', sans-serif;
    font-size: 24px; font-weight: 700; line-height: 1.1;
    letter-spacing: -0.02em; color: var(--text);
    font-variant-numeric: tabular-nums;
  }
  .spec-key {
    margin-top: 6px; font-size: 11px; font-weight: 600; letter-spacing: 0.18em;
    text-transform: uppercase; color: var(--text-dim);
  }
  .on-light .spec-row  { border-top-color: var(--divider-light); } /* same fix, 11 Sept 2026 */
  .on-light .spec-num  { color: var(--text-on-light); }
  .on-light .spec-key  { color: var(--text-on-light-dim); }


  /* ── DOUBLED BLOCK HEIGHT — RETIRED, 7 Sept 2026 (James, same-day follow-up) ──
     Was: alternating-grounds round 2 (5 Sept), doubling #problem/#products/#process/
     #chat-cta/#flagship from the shared 96px/56px rhythm to 128px/84px, because
     flipping ground every 96px read as flicker back when sections alternated on
     every flip with a wavy strip between them. That concern no longer applies --
     the wave is gone (7 Sept, this session), boundaries are hard straight cuts,
     and the B/W/W pattern doesn't flip every single section any more. Removing
     this override lets these five sections fall back to the plain .section base
     (96px/56px), sized to their actual content like everything else on the site,
     per the new standing content-fit-padding rule (Section 9.9). Content, not a
     visual rhythm target or a colour-ratio target, decides section height now.
  */

  /* Support row: three cards, not the 2x2 the four-module grid used. */
  .product-grid--3 { grid-template-columns: repeat(3, 1fr); }
  @media (max-width: 900px) { .product-grid--3 { grid-template-columns: repeat(2, 1fr); } }
  @media (max-width: 720px) { .product-grid--3 { grid-template-columns: 1fr; } }

  @media (max-width: 860px) {
    .module-image--still { padding: 32px 24px; }
    .still { max-width: 100%; }
  }

  /* Honesty marker on the still. It is an illustration of system
     behaviour, not a real customer record, and it says so quietly.
     Replace both the note and the transcript with a real anonymised
     record once a client system is live. */
  .still-note {
    padding: 0 20px 16px;
    font-size: 10px; line-height: 1.5; font-weight: 500;
    color: var(--text-faint);
  }

  /* ══ LIGHT-CHROME STILL VARIANT — channel-specific mockups, 5 Sept 2026 ══
     James asked for the Chat Receptionist still to read as WhatsApp and the
     Admin Assistant still to read as an email inbox, not the generic dark
     call-log chrome. `.still--light` swaps just the head/body/outcome/note
     colours to a light UI (same reasoning as the near-black `.still`: a
     self-contained screen with its own fixed palette, independent of the
     card it sits in — documented above). Border, radius, shadow and overall
     sizing are unchanged, still governed by the same rules.
     Brand-safety note, deliberate: neither mockup uses WhatsApp's or
     Gmail's actual logo, wordmark, or exact UI chrome — the chat mock is
     generic bubbles + a phone-style status strip, the inbox mock is a
     generic email-list layout. Both read as "that kind of app" without
     claiming to be a real screenshot from either company's product. */
  .still--light { background: #F3F1EE; border-color: rgba(10,10,10,0.10); }
  .still--light .still-head { border-bottom-color: rgba(10,10,10,0.10); }
  .still--light .still-src { color: #14150F; }
  .still--light .still-time { color: rgba(10,10,10,0.55); }
  .still--light .still-out { border-left-color: var(--blue-on-light); }
  .still--light .still-out-key { color: #14150F; }
  .still--light .still-out-val { color: rgba(10,10,10,0.6); }
  .still--light .still-note { color: rgba(10,10,10,0.35); }

  /* Chat bubbles — WhatsApp-style, generic (no logo/wordmark). Green is a
     deliberate, contained exception to the sand-only accent rule: this one
     component is depicting a real third-party app's own UI convention, not
     an Astro interface surface, the same carve-out already used for the
     page-header space photography. */
  .chat-mock-status-bar {
    display: flex; justify-content: space-between; padding: 6px 20px 0;
    font-size: 10px; font-weight: 600; color: rgba(10,10,10,0.4);
  }
  .chat-mock-body { padding: 14px 16px; display: flex; flex-direction: column; gap: 8px; }
  .chat-bubble {
    max-width: 78%; padding: 8px 12px; border-radius: 14px;
    font-size: 13px; font-weight: 500; line-height: 1.45; color: #14150F;
  }
  .chat-bubble.in { align-self: flex-start; background: #FFFFFF; border-bottom-left-radius: 4px; box-shadow: 0 1px 2px rgba(10,10,10,0.08); }
  .chat-bubble.out { align-self: flex-end; background: #CFEFC0; border-bottom-right-radius: 4px; }
  .chat-bubble-time {
    display: block; margin-top: 3px; font-size: 10px; font-weight: 500;
    color: rgba(10,10,10,0.4); text-align: right;
  }

  /* Inbox rows — generic email-list layout (no logo/wordmark). */
  .inbox-mock-body { padding: 6px 20px 4px; }
  .inbox-row { display: flex; align-items: baseline; gap: 10px; padding: 10px 0 2px; }
  .inbox-row-dot { width: 6px; height: 6px; border-radius: 50%; background: rgba(10,10,10,0.35); flex: none; margin-top: 5px; }
  .inbox-row-main { flex: 1; min-width: 0; }
  .inbox-row-sender { display: block; font-size: 13px; font-weight: 700; color: #14150F; }
  .inbox-row-subject { display: block; font-size: 12px; font-weight: 500; color: rgba(10,10,10,0.55); }
  .inbox-row-time { font-size: 11px; font-weight: 500; color: rgba(10,10,10,0.4); white-space: nowrap; }
  .inbox-row-action {
    margin: 2px 0 4px 16px; padding: 6px 0 6px 12px;
    border-left: 2px solid var(--blue-on-light);
    font-size: 12px; font-weight: 500; line-height: 1.5; color: rgba(10,10,10,0.7);
  }
  .inbox-row-action:last-of-type { margin-bottom: 8px; }

  .products-link { text-align: right; padding: 4px 4px 0; }

  /* Rhythm conformance fix, 4 Sept 2026 session 4. The 96/56 unification
     gave .section a 720px override but .module-band never got one, so
     module bands stayed at 96px on phones while every .section around
     them dropped to 56px. Same class of inconsistency the unification was
     written to remove. Affects services.html as well as index.html's new
     flagship band. Horizontal drops 40 -> 20 to match .container. */
  @media (max-width: 720px) {
    .module-band { padding: 54px 20px; } /* Reverted to Slash Step 1's 72px then decreased 25% (54px, vertical only), 11 Sept 2026 */
  }

  /* Spec row on phones. Three cells in a 286px column left an orphan on
     a second line and forced the keys to wrap unevenly. Stacked as
     hairline-separated rows with the number left and the label right,
     which keeps the component's meaning intact instead of shrinking it
     until it breaks. */
  @media (max-width: 720px) {
    .spec-row { flex-direction: column; }
    .spec-cell {
      display: flex; align-items: baseline; justify-content: space-between;
      gap: 16px; padding: 13px 0; border-bottom: 1px solid var(--divider);
    }
    .spec-cell:last-child { border-bottom: 0; }
    .spec-num { font-size: 20px; }
    .spec-key { margin-top: 0; }
  }

  /* ── TITANIUM, override layer. Every rule below hardcoded the old cool
     white (245,244,242) or the pure-black card fills back when the ground
     was #000000. Repointed to the warm off-white so the page reads as one
     temperature rather than two. ── */
  .nav-links a, .mobile-menu a { color: rgba(237,233,227,0.72); }
  .problem-card, .product-card, .process-step { background: rgba(25,26,29,0.72); }
  .step-ghost { color: rgba(237,233,227,0.20); }
  svg { fill: rgba(237,233,227,0.4); }
  @keyframes nodePing {
    0%   { box-shadow: 0 0 0 0   rgba(237,233,227,0.5); }
    100% { box-shadow: 0 0 0 10px rgba(237,233,227,0);  }
  }
  .band-light .section-headline,
  .on-light .m-eyebrow, .on-light .m-headline, .on-light .m-body,
  .on-light .spec-num { color: var(--text-on-light); } /* Slash-migration full-dark fix, 11 Sept 2026 -- was hardcoded #14150F, same invisible-text bug as the block above (this rule wins on source order, so it was the one actually live). */

  /* The still sits deeper than the card it lives in, which is what gives it
     an edge on a ground this close in value.
     :not(.still--light) added 5 Sept 2026 -- this rule sits later in the file
     than .still--light's own background override, and at equal specificity
     source order would silently win here and re-darken the two channel
     mockups (gotcha 9.5 #6, again -- found this one myself before it shipped). */
  .still:not(.still--light) { background: #0A0B0C; }

  /* The hero's blue grid overlay was removed entirely 14 Sept 2026 — it drew in
     the pre-Slash electric blue rgba(59,95,204,0.05) long after the accent moved
     to copper, and the homepage brief bans decorative futuristic grids. The
     element and both of its rules are gone. */


/* ══════════════════════════════════════════════════════════════════════
   ASTRO CHAT PANEL — 9 Sept 2026, built from prompts/chat-panel.md.
   Sitewide UI shell, one adapter integration point (see assets/js/
   astro-chat.js). Always dark-themed regardless of the section it floats
   over — a persistent app-like widget, not a page section, so it doesn't
   follow the B/W/W section pattern. Accent (sand) stays perimeter-only per
   the standing rule: borders and focus rings, never a filled button.
   ══════════════════════════════════════════════════════════════════════ */

.astro-chat-launcher {
  position: fixed;
  right: 24px;
  bottom: calc(24px + env(safe-area-inset-bottom, 0px));
  z-index: 60;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 48px;
  padding: 0 22px;
  border-radius: var(--radius-pill);
  background: var(--card);
  border: 1px solid var(--ghost-border); /* Slash Step 2, 11 Sept 2026: ghost outline, Inter 14/500, no drop shadow */
  color: var(--text);
  font-family: 'Inter', sans-serif;
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  box-shadow: none;
  transition: background 0.2s, border-color 0.2s, transform 0.2s;
}
.astro-chat-launcher:hover { background-image: linear-gradient(var(--ghost-hover), var(--ghost-hover)); }

/* HOMEPAGE ONLY — launcher hidden while the hero is on screen, 16 Sept 2026.
   .js-home, .hero-in-view and .hero-io-init are set by assets/js/astro-home.js,
   which only index.html loads, so every other page keeps the launcher as-is.
   The transition lives on an always-present rule so the launcher fades BACK in
   too (a transition declared only on the hidden state would snap on removal).
   visibility waits out the 260ms fade on the way out (so the fade is seen) and
   flips immediately on the way in; hidden elements cannot receive Tab focus.
   :not([aria-hidden="true"]) keeps the launcher visible while the chat panel is
   open (astro-chat.js sets that attribute on open), so the panel never loses its
   context. Specificity (0,3,1)+ beats the base rule above regardless of order.
   State band 260ms, locked easing (Astro_motion_spec.md). */
html.js-home .astro-chat-launcher {
  transition: background 0.2s, border-color 0.2s, transform 0.2s,
              opacity 260ms cubic-bezier(0.22, 1, 0.36, 1), visibility 0s linear 0s;
}
html.js-home.hero-in-view .astro-chat-launcher:not([aria-hidden="true"]) {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: background 0.2s, border-color 0.2s, transform 0.2s,
              opacity 260ms cubic-bezier(0.22, 1, 0.36, 1), visibility 0s linear 260ms;
}
/* !important is deliberate: the hidden-state rule above is (0,4,1) and would
   otherwise out-rank this two-frame load guard (gotcha 9.5 #1). */
html.js-home.hero-io-init .astro-chat-launcher { transition: none !important; }
@media (prefers-reduced-motion: reduce) {
  html.js-home .astro-chat-launcher,
  html.js-home.hero-in-view .astro-chat-launcher:not([aria-hidden="true"]) { transition: none; }
}
.astro-chat-launcher:focus-visible { outline: 2px solid var(--blue); outline-offset: 3px; }

.astro-chat-scrim {
  position: fixed;
  inset: 0;
  z-index: 61;
  background: rgba(6,6,8,0.5);
  opacity: 0;
  transition: opacity 0.24s cubic-bezier(0.22,1,0.36,1);
  pointer-events: none;
}
.astro-chat-scrim.is-open { opacity: 1; pointer-events: auto; }
@media (min-width: 721px) {
  /* desktop: side panel doesn't need a full scrim to read as modal, but a
     faint one still helps focus -- kept subtle so page content behind
     stays legible for anyone glancing past the panel */
  .astro-chat-scrim { background: rgba(6,6,8,0.28); }
}

.astro-chat-panel {
  position: fixed;
  z-index: 62;
  right: 24px;
  bottom: calc(24px + env(safe-area-inset-bottom, 0px));
  width: 24rem;
  max-width: calc(100vw - 32px);
  height: min(640px, calc(100vh - 100px));
  background: var(--card);
  border: 1px solid var(--hairline-hover); /* Slash Step 2, 11 Sept 2026: surface step + hairline, no drop shadow */
  border-radius: var(--radius-card);
  box-shadow: none;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  opacity: 0;
  transform: translateY(16px) scale(0.98);
  transition: opacity 0.24s cubic-bezier(0.22,1,0.36,1), transform 0.24s cubic-bezier(0.22,1,0.36,1);
}
.astro-chat-panel.is-open { opacity: 1; transform: translateY(0) scale(1); }
/* 11 Sept 2026: closed panel keeps display:flex (overrides [hidden], author CSS beats UA [hidden] rule regardless of source order), so without this it silently intercepts clicks meant for the launcher/page beneath it even though invisible. */
.astro-chat-panel:not(.is-open) { pointer-events: none; }
@media (prefers-reduced-motion: reduce) {
  .astro-chat-panel, .astro-chat-scrim { transition: none; }
}

@media (max-width: 720px) {
  .astro-chat-panel {
    left: 0;
    right: 0;
    bottom: 0;
    width: 100%;
    max-width: 100%;
    height: 86dvh;
    border-radius: var(--radius-card) var(--radius-card) 0 0;
    transform: translateY(100%);
  }
  .astro-chat-panel.is-open { transform: translateY(0); }
}

.astro-chat-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  padding: 18px 18px 14px;
  border-bottom: 1px solid var(--divider);
  flex-shrink: 0;
}
.astro-chat-title {
  font-family: 'Familjen Grotesk', 'Inter', sans-serif;
  font-size: 16px;
  font-weight: 700;
  color: var(--text);
}
.astro-chat-subtitle {
  font-size: 12px;
  color: var(--text-dim);
  margin-top: 3px;
}
.astro-chat-close {
  flex-shrink: 0;
  width: 32px;
  height: 32px;
  min-width: 44px;
  min-height: 44px;
  margin: -6px -6px 0 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: none;
  color: var(--text-dim);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  border-radius: var(--radius-pill);
  transition: color 0.18s, background 0.18s;
}
.astro-chat-close:hover { color: var(--text); background: rgba(255,255,255,0.06); }
.astro-chat-close:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }

.astro-chat-transcript {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: 16px 18px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.astro-chat-msg { display: flex; }
.astro-chat-msg--user { justify-content: flex-end; }
.astro-chat-msg--assistant { justify-content: flex-start; }
.astro-chat-bubble {
  max-width: 84%;
  padding: 10px 14px;
  border-radius: 14px;
  font-family: 'Familjen Grotesk', 'Inter', sans-serif;
  font-size: 14px;
  font-weight: 500;
  line-height: 1.5;
  white-space: pre-wrap;
  word-break: break-word;
}
.astro-chat-msg--user .astro-chat-bubble {
  background: rgba(255,255,255,0.08);
  color: var(--text);
  border: 1px solid var(--blue-border-soft);
}
.astro-chat-msg--assistant .astro-chat-bubble {
  background: transparent;
  color: var(--text);
  border: 1px solid var(--divider);
}

.astro-chat-typing {
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 0 18px 10px;
  flex-shrink: 0;
}
.astro-chat-typing span {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--text-dim);
  animation: astroChatTyping 1.1s ease-in-out infinite;
}
.astro-chat-typing span:nth-child(2) { animation-delay: 0.15s; }
.astro-chat-typing span:nth-child(3) { animation-delay: 0.30s; }
@keyframes astroChatTyping {
  0%, 60%, 100% { opacity: 0.25; transform: translateY(0); }
  30% { opacity: 1; transform: translateY(-3px); }
}
@media (prefers-reduced-motion: reduce) {
  .astro-chat-typing span { animation: none; opacity: 0.7; }
}

.astro-chat-composer {
  flex-shrink: 0;
  border-top: 1px solid var(--divider);
  padding: 14px 18px calc(14px + env(safe-area-inset-bottom, 0px));
}
.astro-chat-error {
  font-size: 12px;
  font-weight: 600;
  color: #E08A6B;
  margin-bottom: 8px;
}
.astro-chat-input-row {
  display: flex;
  align-items: flex-end;
  gap: 10px;
}
.astro-chat-input {
  flex: 1 1 auto;
  resize: none;
  min-height: 44px;
  max-height: 160px;
  padding: 12px 14px;
  border-radius: var(--radius-card); /* Slash Step 2, 11 Sept 2026: multi-line field keeps card radius */
  border: 1px solid var(--tag-border);
  background: rgba(255,255,255,0.04);
  color: var(--text);
  font-family: 'Familjen Grotesk', 'Inter', sans-serif;
  font-size: 16px; /* minimum -- prevents iOS zoom-on-focus, a deliberate
                       exception to the 15px body-copy scale */
  line-height: 1.4;
}
.astro-chat-input::placeholder { color: var(--text-faint); }
.astro-chat-input:focus-visible {
  outline: none;
  border-color: var(--blue);
  box-shadow: 0 0 0 3px var(--blue-tint);
}
.astro-chat-send {
  flex-shrink: 0;
  width: 44px;
  height: 44px;
  border-radius: var(--radius-pill);
  background: transparent;
  border: 1px solid var(--ghost-border);
  color: var(--text);
  font-size: 18px;
  cursor: pointer;
  transition: background 0.18s, border-color 0.18s;
}
.astro-chat-send:hover:not(:disabled) { background: var(--ghost-hover); }
.astro-chat-send:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
.astro-chat-send:disabled { opacity: 0.5; cursor: default; }


/* ════════════════════════════════════════════════════════════════
   ASTRO COOKIE CONSENT BANNER — 9 Sept 2026, built from assets/js/
   astro-consent.js. Fixes the PECR/GDPR gap flagged in the Brain: GA4
   ran site-wide with no consent mechanism. Bottom bar, always dark-
   themed (same convention as the chat panel above), perimeter-accent
   only — no filled buttons, matching the sitewide blue/sand rule.
   ══════════════════════════════════════════════════════════════════════ */

.astro-consent-banner {
  position: fixed;
  left: 16px;
  right: 16px;
  bottom: calc(16px + env(safe-area-inset-bottom, 0px));
  z-index: 70;
  max-width: 560px;
  margin: 0 auto;
  background: var(--card);
  border: 1px solid var(--hairline-hover); /* Slash Step 2, 11 Sept 2026: surface step + hairline, no drop shadow */
  border-radius: var(--radius-card);
  box-shadow: none;
  padding: 18px 20px;
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 0.24s cubic-bezier(0.22,1,0.36,1), transform 0.24s cubic-bezier(0.22,1,0.36,1);
}
.astro-consent-banner.is-in { opacity: 1; transform: translateY(0); }
@media (prefers-reduced-motion: reduce) {
  .astro-consent-banner { transition: none; }
}

.astro-consent-body {
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.astro-consent-text {
  font-family: 'Familjen Grotesk', 'Inter', sans-serif;
  font-size: 14px;
  line-height: 1.5;
  color: var(--text);
  margin: 0;
}
.astro-consent-text a { color: var(--blue); text-decoration: underline; }

.astro-consent-actions {
  display: flex;
  gap: 10px;
  justify-content: flex-end;
}
.astro-consent-btn {
  min-height: 40px;
  padding: 0 18px;
  border-radius: var(--radius-pill);
  background: transparent;
  border: 1px solid var(--ghost-border);
  color: var(--text);
  font-family: 'Inter', sans-serif;
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  transition: background 0.2s, border-color 0.2s;
}
.astro-consent-btn:hover { background: var(--ghost-hover); }
.astro-consent-btn:focus-visible { outline: 2px solid var(--blue); outline-offset: 3px; }
/* Slash Step 2, 11 Sept 2026: Accept no longer gets a stronger (copper) border than Reject -- both
   are the same ghost pill, keeping Accept and Reject equally prominent. */

@media (max-width: 480px) {
  .astro-consent-actions { justify-content: stretch; }
  .astro-consent-btn { flex: 1; }
}

.astro-consent-manage {
  background: none;
  border: none;
  padding: 0;
  font-family: inherit; /* Slash Step 2 fix, 11 Sept 2026: was `font: inherit`, which reset font-size and made "Cookie Preferences" render ~16px beside the 10px .footer-legal-link siblings it shares a class with */
  line-height: inherit;
  cursor: pointer;
}


/* ══════════════════════════════════════════════════════════════════════
   SLASH-MIGRATION: FILLED BUTTON — 11 Sept 2026, Step 1 (global foundation).
   Adapted from Refero "Slash"'s single-white-filled-pill-per-screen pattern
   (DESIGN.md's Primary Action Button component). Defined here as a token-
   level component only — not yet applied to any page markup. Which CTA
   becomes .btn-filled is a Step 3 (homepage) decision, approved separately.
   Reserve this for exactly one action per viewport, per Slash's own rule —
   its whole effect depends on scarcity. This does NOT touch the existing
   .btn-primary/.nav-btn border-only pattern, which stays the default for
   every other CTA.
   ══════════════════════════════════════════════════════════════════════ */

.btn-filled {
  display: inline-block;
  background: var(--text);
  color: var(--bg);
  border: none;
  font-family: 'Inter', sans-serif;
  font-size: 14px; /* Slash Step 2, 11 Sept 2026: aligned to DESIGN.md Primary Action Button type (14/500, no uppercase) */
  font-weight: 500;
  line-height: 1.2;
  text-decoration: none;
  padding: 14px 28px;
  border-radius: var(--radius-pill);
  transition: background 0.18s, transform 0.18s;
  cursor: pointer;
}
.btn-filled:hover { background: var(--text-dim); }
.btn-filled:focus-visible { outline: 2px solid var(--blue); outline-offset: 3px; }

/* Step 3, 11 Sept 2026: the one CTA per screen that actually becomes .btn-filled -- the nav's
   persistent "Ask Astro" (desktop .nav-btn, mobile .mobile-cta), matching how Slash itself uses
   its single filled pill (nav-persistent "Get Started", never repeated in the hero or elsewhere).
   Explicit compound selectors, not a bare added class, because .mobile-menu .mobile-cta outranks
   a single .btn-filled class on specificity alone. Every other #chat-cta link (.btn-primary in the
   hero, .chat-cta-send) stays ghost -- reinforcing the same action, not competing with it. */
.nav-btn.btn-filled { background: var(--text); color: var(--bg); border: none; }
.nav-btn.btn-filled:hover { background: var(--text-dim); }
.mobile-menu .mobile-cta.btn-filled { background: var(--text); color: var(--bg); border: none; }
.mobile-menu .mobile-cta.btn-filled:hover { background: var(--text-dim); }

/* Light-section equivalent -- Slash's fill is always the highest-contrast
   neutral against its ground, not a fixed color, so this inverts rather
   than reusing the dark-ground values. */
.section--light .btn-filled,
.on-light .btn-filled {
  background: var(--text-on-light);
  color: var(--bg-light);
}
.section--light .btn-filled:hover,
.on-light .btn-filled:hover {
  background: var(--text-on-light-dim);
}


/* ══════════════════════════════════════════════════════════════════════
   HOMEPAGE SECTIONS 02-10 — 14 September 2026 (one-shot homepage brief
   §10-18). index.html only; every selector below is namespaced so it is a
   no-op on the other 26 pages. Behaviour lives in assets/js/astro-home.js.

   Governing references, not re-decided here:
     - Brain Section 2 accent rule: copper on perimeters, links, focus and
       active connectors only. Every status indicator is a RING or a stroke,
       never a filled copper dot. Selected radio uses a NEUTRAL fill.
     - Astro_motion_spec.md: one easing, cubic-bezier(0.22,1,0.36,1); bands
       140 / 260 / 420 / 560ms; 1.5px non-scaling connectors; hairlines, no
       drop shadows, no hover lift.
     - Interface text is Familjen Grotesk; Playfair stays on the section
       headlines only; Astrohead only where the brand mark itself appears.

   One new token, --meta-ui. The existing --meta (#7A7770) measures 4.15:1
   on --card, under AA for the 10-11px interface meta text these panels are
   full of. #8C8980 is the value Step 4 already chose for .demo-chip for the
   same reason (5.3:1 on --card), promoted to a token rather than repeated.
   --meta itself is untouched; the hero panel still uses it (flagged).
   ══════════════════════════════════════════════════════════════════════ */
  :root {
    --meta-ui: #8C8980;
    --ease: cubic-bezier(0.22, 1, 0.36, 1);
  }

  /* STICKY FIX. html and body both carry overflow-x:hidden. html's value is
     the one propagated to the viewport, so body's makes BODY a scroll
     container (overflow-y computes to auto) and position:sticky can never
     engage anywhere beneath it: it measured top:-675px against a 64px target.
     overflow-x:clip clips identically but creates no scroll container.
     Homepage only (.js-home is set by astro-home.js); no other page on the
     site uses sticky. Browsers without clip keep hidden and simply scroll the
     stage past, which is degraded but never broken. */
  html.js-home body { overflow-x: clip; }

  .container.home-wide { max-width: 1240px; }

  .sr-only {
    position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
  }

  /* ── shared interface primitives ── */
  .ui-panel {
    background: var(--card);
    border: 1px solid var(--hairline);
    border-radius: var(--radius-card);
  }
  .ui-head {
    display: flex; align-items: flex-start; justify-content: space-between; gap: 16px;
    padding: 14px 18px;
    border-bottom: 1px solid var(--hairline);
  }
  .ui-title {
    display: block;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 15px; font-weight: 600; line-height: 1.25; letter-spacing: 0.005em;
    color: var(--text);
  }
  .ui-eyebrow {
    display: block;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 11px; font-weight: 600; line-height: 1.3; letter-spacing: 0.8px;
    text-transform: uppercase; color: var(--text-dim);
  }
  .ui-meta {
    display: block;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 11px; font-weight: 500; line-height: 1.3; letter-spacing: 0.5px;
    text-transform: uppercase; color: var(--meta-ui);
  }
  .ui-head .ui-meta { margin-top: 4px; }
  .ui-time {
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 11px; font-weight: 500; letter-spacing: 0.04em;
    color: var(--meta-ui); font-variant-numeric: tabular-nums; white-space: nowrap;
  }
  .ui-btn {
    display: inline-flex; align-items: center; justify-content: center;
    min-height: 30px; padding: 6px 13px;
    background: transparent; color: var(--text);
    border: 1px solid var(--tag-border); border-radius: var(--radius-pill);
    font-family: 'Inter', sans-serif; font-size: 12px; font-weight: 500; line-height: 1;
    cursor: pointer;
    transition: background 140ms var(--ease), border-color 140ms var(--ease);
  }
  .ui-btn:hover { background: var(--ghost-hover); border-color: var(--hairline-hover); }
  /* author display values beat the UA [hidden] rule (the 11 Sept chat-panel
     trap, Brain Section 8), so every toggled component here restates it */
  .ui-btn[hidden], .wf-panel[hidden], .map-demo[hidden], .map-panel[hidden],
  .pr-panel[hidden], .ask-resp[hidden], .ask-idle[hidden] { display: none !important; }
  .ui-panel .demo-chip { margin: 0; padding: 5px 11px; white-space: nowrap; }

  .ui-btn:focus-visible, .wf-node:focus-visible, .map-node:focus-visible, .day-btn:focus-visible,
  .pr-tab:focus-visible, .wk-open:focus-visible, .env-link:focus-visible,
  .ask-talk:focus-visible, .ask-actions .btn-primary:focus-visible {
    outline: 2px solid var(--blue); outline-offset: 3px;
  }
  .wf-node:focus-visible { outline-offset: -2px; }

  /* status glyphs — injected into [data-st] by astro-home.js. The state lives
     on the glyph's direct parent (.is-live / .is-done), child combinators
     only, so a finished group never forces checks onto rows inside it. */
  .st { position: relative; display: inline-block; flex: none; width: 14px; height: 14px; }
  .st-spin {
    position: absolute; top: 1.5px; left: 1.5px; width: 11px; height: 11px;
    border-radius: 50%;
    border: 1.5px solid var(--hairline-hover); border-top-color: var(--text-dim);
    opacity: 0; transition: opacity 160ms linear;
  }
  .st-check {
    position: absolute; top: 1.5px; left: 1.5px; width: 11px; height: 11px;
    fill: none; stroke: var(--text); stroke-width: 1.6;
    stroke-linecap: round; stroke-linejoin: round;
    opacity: 0; transform: scale(0.8);
    transition: opacity 260ms var(--ease), transform 260ms var(--ease);
  }
  .is-live > .st > .st-spin, .st-spin.is-on { opacity: 1; animation: sysSpin 900ms linear infinite; }
  .is-done > .st > .st-check { opacity: 1; transform: none; }

  /* sequence player — hidden states exist only once JS has armed a root,
     so without JS every row simply shows. Space is always reserved. */
  [data-at] { transition: opacity 420ms var(--ease), transform 420ms var(--ease); }
  .seq-armed [data-at]:not(.is-in) { opacity: 0; transform: translateY(6px); }

  /* mini interfaces */
  .mini-head {
    display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
    margin-bottom: 12px;
  }
  .mini-steps { list-style: none; margin: 0; padding: 0; }
  .mini-steps > li {
    position: relative;
    display: grid; grid-template-columns: 14px minmax(0, 1fr) auto;
    align-items: center; column-gap: 10px;
    padding: 7px 0;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 13px; font-weight: 500; line-height: 1.35;
    color: var(--text-dim);
  }
  .mini-steps > li.is-done, .mini-steps > li.is-live { color: var(--text); }
  .mini-steps > li.is-key.is-done { font-weight: 600; }
  .mini-steps > li.is-wait { color: var(--meta-ui); }
  .mini-steps > li.is-wait::before {
    content: ''; width: 14px; height: 0;
    border-top: 1px dashed var(--hairline-hover);
  }
  .mini-detail {
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 11px; font-weight: 500; letter-spacing: 0.02em;
    color: var(--meta-ui); text-align: right; white-space: nowrap;
    font-variant-numeric: tabular-nums;
  }
  /* rail variant: a connector runs glyph to glyph and turns copper once the
     step above it has completed (active-connector precedent, motion spec §3) */
  .mini-steps.is-rail > li:not(:last-child)::after {
    content: ''; position: absolute;
    left: 6.25px; top: calc(50% + 9px); height: calc(100% - 18px); width: 1.5px;
    background: var(--hairline);
    transition: background 260ms var(--ease);
  }
  .mini-steps.is-rail > li.is-done:not(:last-child)::after { background: var(--blue-border); }

  .mini-quote {
    margin: 0 0 8px;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 13.5px; font-weight: 500; line-height: 1.45; color: var(--text);
  }
  .mini-quote.is-astro { padding-left: 10px; border-left: 1px solid var(--hairline-hover); color: var(--text-dim); }
  .mini-who {
    display: block; margin-bottom: 2px;
    font-size: 10px; font-weight: 600; letter-spacing: 0.08em;
    text-transform: uppercase; color: var(--meta-ui);
  }

  /* transcript rows */
  .act-transcript, .wk-msgs { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 11px; }
  .msg {
    display: grid; grid-template-columns: 76px minmax(0, 1fr); column-gap: 12px;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 13.5px; font-weight: 500; line-height: 1.5; color: var(--text-dim);
  }
  .msg.is-astro { color: var(--text); }
  .msg-who {
    padding-top: 3px;
    font-size: 10px; font-weight: 600; letter-spacing: 0.8px; line-height: 1.4;
    text-transform: uppercase; color: var(--meta-ui);
  }
  .msg.is-astro .msg-who { color: var(--text-dim); }
  .msg.is-sys {
    display: flex; align-items: center; gap: 10px;
    font-size: 10.5px; font-weight: 500; letter-spacing: 0.5px;
    text-transform: uppercase; color: var(--meta-ui);
  }
  .msg.is-sys::before, .msg.is-sys::after { content: ''; flex: 1; height: 1px; background: var(--hairline); }

  /* reveal: interface panels enter as full-width cards do under Option A
     (Brain 9.2: ±36px vertical, slight scale), gated behind :not(.is-in) */
  .js-reveal .reveal-panel { transition: transform 1.05s var(--ease), opacity 1.05s var(--ease); }
  .js-reveal .reveal-panel:not(.is-in) { opacity: 0; transform: translateY(36px) scale(0.98); }

  .js-reveal #in-action:not(.is-in) .section-label,
  .js-reveal #in-action:not(.is-in) .section-sub,
  .js-reveal #manual-automated:not(.is-in) .section-label,
  .js-reveal #day:not(.is-in) .section-label,
  .js-reveal #work:not(.is-in) .section-label,
  .js-reveal #work:not(.is-in) .section-sub {
    opacity: 0; transform: translateX(-90px);
  }
  .js-reveal #in-action:not(.is-in) .section-headline,
  .js-reveal #manual-automated:not(.is-in) .section-headline,
  .js-reveal #day:not(.is-in) .section-headline,
  .js-reveal #work:not(.is-in) .section-headline {
    opacity: 0; transform: translateX(-120px);
  }
  @media (max-width: 720px) {
    .js-reveal #in-action:not(.is-in) .section-label,
    .js-reveal #in-action:not(.is-in) .section-sub,
    .js-reveal #manual-automated:not(.is-in) .section-label,
    .js-reveal #day:not(.is-in) .section-label,
    .js-reveal #work:not(.is-in) .section-label,
    .js-reveal #work:not(.is-in) .section-sub { transform: translateX(-48px); }
    .js-reveal #in-action:not(.is-in) .section-headline,
    .js-reveal #manual-automated:not(.is-in) .section-headline,
    .js-reveal #day:not(.is-in) .section-headline,
    .js-reveal #work:not(.is-in) .section-headline { transform: translateX(-60px); }
  }

  /* ── 02 TWO OUTCOMES ── */
  #problem .problem-center { max-width: 880px; margin-bottom: 44px; }   /* two-line headline at desktop, like every other section */
  .env-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 20px; }
  .env { overflow: hidden; display: flex; flex-direction: column; }
  .env-link {
    flex: none; margin-top: -3px;
    display: inline-flex; align-items: center; min-height: 28px;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 13px; font-weight: 500; color: var(--blue); text-decoration: none;
  }
  .env-link:hover { text-decoration: underline; }
  .env-link > span, .ask-talk > span { margin-left: 4px; }   /* inline-flex collapses the leading space */
  .env-body { flex: 1; display: grid; grid-template-columns: 208px minmax(0, 1fr); min-height: 318px; }
  .wf {
    display: flex; flex-direction: column;
    padding: 14px 10px 14px 12px;
    border-right: 1px solid var(--hairline);
  }
  .wf-node {
    position: relative;
    display: flex; align-items: center; gap: 12px;
    width: 100%; height: 40px; padding: 0 10px;
    background: transparent; border: 0; border-radius: 8px;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 13px; font-weight: 500; text-align: left; white-space: nowrap;
    color: var(--text-dim);
    cursor: pointer;
    transition: color 140ms var(--ease), background 140ms var(--ease);
  }
  .wf-node:hover { background: var(--ghost-hover); color: var(--text); }
  /* connector segment above each node: hairline track (::before) with a
     copper draw (::after) once the flow has reached this node */
  .wf-node:not(:first-child)::before,
  .wf-node:not(:first-child)::after {
    content: ''; position: absolute;
    left: 15.25px; bottom: calc(50% + 6px); height: 28px; width: 1.5px;
    background: var(--hairline);
  }
  .wf-node:not(:first-child)::after {
    background: var(--blue-border);
    transform: scaleY(0); transform-origin: top;
    transition: transform 260ms var(--ease);
  }
  .wf-node.is-past::after, .wf-node.is-active::after { transform: scaleY(1); }
  .wf-ring {
    position: relative; z-index: 1; flex: none;
    width: 11px; height: 11px; border-radius: 50%;
    border: 1px solid var(--hairline-hover); background: var(--card);
    transition: border-color 260ms var(--ease), outline-color 260ms var(--ease);
    outline: 1px solid transparent; outline-offset: 3px;
  }
  .wf-label { overflow: hidden; text-overflow: ellipsis; }
  .wf-node.is-past .wf-ring { border-color: var(--blue-border); }
  .wf-node.is-active { color: var(--text); background: rgba(237,233,227,0.05); }
  .wf-node.is-active .wf-ring { border-color: var(--blue); outline-color: var(--blue-border-soft); }
  .wf-node.is-next { color: var(--text); }
  .wf-node.is-next .wf-ring { border-color: var(--text-dim); }
  .env-inspect { padding: 16px 20px 18px; min-width: 0; }

  @media (max-width: 1080px) { .env-grid { grid-template-columns: minmax(0, 1fr); } }
  @media (max-width: 560px) {
    .env-body { grid-template-columns: minmax(0, 1fr); }
    .wf { border-right: 0; border-bottom: 1px solid var(--hairline); }
    .env-inspect { min-height: 230px; }
  }

  /* ── 03 ASTRO IN ACTION ── */
  .act-header { margin-bottom: 40px; }
  .act { overflow: hidden; }
  .act-bar {
    display: flex; align-items: center; justify-content: space-between; gap: 12px 20px; flex-wrap: wrap;
    padding: 12px 18px;
  }
  .act-bar-id { display: flex; align-items: center; gap: 12px; }
  .act-controls { display: flex; align-items: center; gap: 8px; }
  .act-stage {
    min-width: 12em; margin-right: 6px; text-align: right;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 11px; font-weight: 500; letter-spacing: 0.5px;
    text-transform: uppercase; color: var(--meta-ui);
  }
  .act-progress { position: relative; height: 1px; background: var(--hairline); }
  .act-progress-fill {
    position: absolute; inset: 0; background: var(--blue-border);
    transform-origin: left; transform: scaleX(var(--p, 0));
    transition: transform 420ms var(--ease);
  }
  .act-grid { display: grid; grid-template-columns: minmax(0, 1.12fr) minmax(0, 0.88fr); }
  .act-col { padding: 20px 24px 26px; min-width: 0; }
  .act-actions { border-left: 1px solid var(--hairline); background: var(--panel); }
  .act-col-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin-bottom: 16px; }
  .act-callcard {
    display: grid; grid-template-columns: 14px minmax(0, 1fr) auto; align-items: center; column-gap: 10px;
    margin-bottom: 16px; padding: 10px 12px;
    border: 1px solid var(--hairline); border-radius: 8px;
    transition: opacity 420ms var(--ease), transform 420ms var(--ease), border-color 260ms var(--ease);
  }
  .act-callcard.is-live { border-color: var(--blue-border); }
  .act-callcard-title {
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 13.5px; font-weight: 600; color: var(--text);
  }
  .act-group { padding: 12px 0; border-top: 1px solid var(--hairline); }
  .act-group:first-of-type { border-top: 0; padding-top: 0; }
  .act-group-name {
    display: block; margin-bottom: 4px;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 10.5px; font-weight: 600; letter-spacing: 0.8px;
    text-transform: uppercase; color: var(--text-dim);
  }
  .act-items { list-style: none; margin: 0; padding: 0; }
  .act-items > li {
    display: grid; grid-template-columns: 14px minmax(0, 1fr); align-items: center; column-gap: 10px;
    padding: 4px 0;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 13px; font-weight: 500; color: var(--text-dim);
  }
  .act-items > li.is-done { color: var(--text); }
  .act-slots { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
  .act-slot {
    padding: 4px 10px;
    border: 1px solid var(--hairline-hover); border-radius: var(--radius-pill);
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 11.5px; font-weight: 500; color: var(--text-dim); font-variant-numeric: tabular-nums;
    transition: border-color 260ms var(--ease), color 260ms var(--ease);
  }
  .act-slot.is-on { border-color: var(--blue); color: var(--text); }
  .act-record {
    display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px 14px;
    margin: 8px 0 0; padding: 10px 12px;
    border: 1px solid var(--hairline); border-radius: 8px;
  }
  .act-record dt, .wk-record dt, .pr-config dt {
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 10px; font-weight: 600; letter-spacing: 0.6px;
    text-transform: uppercase; color: var(--meta-ui);
  }
  .act-record dd, .wk-record dd, .pr-config dd {
    margin: 0;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 12.5px; font-weight: 500; color: var(--text);
  }
  @media (max-width: 860px) {
    .act-grid { grid-template-columns: minmax(0, 1fr); }
    .act-actions { border-left: 0; border-top: 1px solid var(--hairline); }
    .act-stage { min-width: 0; text-align: left; }
    .act-col { padding: 18px 18px 22px; }
    .msg { grid-template-columns: 58px minmax(0, 1fr); }
  }

  /* ── 04 ASTRO SYSTEMS: system map ── */
  #products .products-header { margin-bottom: 36px; }
  .map-wrap {
    display: grid; grid-template-columns: minmax(0, 1.12fr) minmax(0, 0.88fr);
    gap: 36px; align-items: center;
  }
  .map { position: relative; width: 100%; max-width: 620px; aspect-ratio: 1 / 0.9; margin: 0 auto; }
  .map-lines { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
  .map-edge {
    stroke: var(--hairline); stroke-width: 1.5; vector-effect: non-scaling-stroke;
    transition: stroke 260ms var(--ease), opacity 260ms var(--ease);
  }
  .map-edge.is-rim { opacity: 0.7; }
  .map-edge.is-rel { stroke: var(--hairline-hover); opacity: 1; }
  .map-edge.is-lit { stroke: var(--blue-border); opacity: 1; }
  .map-edge.is-quiet { opacity: 0.35; }
  /* no vector-effect here: combined with pathLength it breaks dash maths in
     Chromium. The map box scales viewBox units ~6x, so 0.25 renders ~1.5px. */
  .map-flow {
    stroke: var(--blue); stroke-width: 0.25; stroke-linecap: round;
    stroke-dasharray: 10 100; stroke-dashoffset: 10; opacity: 0;
  }
  .map-flow.is-run { animation: mapFlow 700ms var(--ease) forwards; }
  @keyframes mapFlow {
    0%   { stroke-dashoffset: 10; opacity: 1; }
    85%  { opacity: 1; }
    100% { stroke-dashoffset: -90; opacity: 0; }
  }
  .map-core {
    position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
    display: flex; flex-direction: column; align-items: center; gap: 6px;
    padding: 16px 20px; background: var(--bg);
    text-align: center;
  }
  .map-core-ring {
    width: 30px; height: 30px; border-radius: 50%;
    border: 1px solid var(--blue-border); position: relative;
  }
  .map-core-ring::after {
    content: ''; position: absolute; inset: 8px; border-radius: 50%;
    border: 1px solid var(--hairline-hover);
  }
  .map-core-name {
    font-family: 'Astrohead', 'Inter', sans-serif;
    font-size: 14px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--text);
  }
  .map-nodes { list-style: none; margin: 0; padding: 0; }
  .map-item { position: absolute; transform: translate(-50%, -50%); z-index: 1; }
  /* four systems since 26 Sept 2026: Voice top, Chat left, Admin right,
     Outbound (Phase 2) below, its spoke and node dashed as planned */
  .map-item[data-sys="voice"] { left: 50%; top: 12%; }
  .map-item[data-sys="chat"]  { left: 15%; top: 50%; }
  .map-item[data-sys="admin"] { left: 85%; top: 50%; }
  .map-item[data-sys="out"]   { left: 50%; top: 88%; }
  .map-edge.is-planned { stroke-dasharray: 3 4; }
  .map-item.is-planned .map-node { border-style: dashed; }
  .map-item.is-planned .map-ring { border-style: dashed; }
  .map-node {
    display: flex; flex-direction: column; align-items: center; gap: 5px;
    min-width: 148px; padding: 10px 14px;
    background: var(--bg); color: var(--text);
    border: 1px solid var(--hairline); border-radius: var(--radius-card);
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    cursor: pointer;
    transition: border-color 140ms var(--ease), opacity 260ms var(--ease), background 140ms var(--ease);
  }
  .map-node:hover { border-color: var(--hairline-hover); }
  .map-ring {
    width: 9px; height: 9px; border-radius: 50%;
    border: 1px solid var(--hairline-hover);
    transition: border-color 260ms var(--ease);
  }
  .map-name { font-size: 13px; font-weight: 600; line-height: 1.2; white-space: nowrap; }
  .map-cat { font-size: 10px; font-weight: 500; letter-spacing: 0.5px; text-transform: uppercase; color: var(--meta-ui); white-space: nowrap; }
  .map-item.is-active .map-node { border-color: var(--blue-border); background: var(--card); }
  .map-item.is-active .map-ring { border-color: var(--blue); }
  .map-item.is-rel .map-node { border-color: var(--hairline-hover); }
  /* quiet, never hidden: the map must stay legible. Quieted by colour, not
     opacity: the spec's opacity 0.4 (and even 0.55) measured the 10px
     category text at 2.43:1. Name drops to --text-dim (still AA), the border
     and ring recede, the category keeps --meta-ui. */
  .map-item.is-quiet .map-node { border-color: rgba(237,233,227,0.06); }
  .map-item.is-quiet .map-name { color: var(--text-dim); }
  .map-item.is-quiet .map-ring { border-color: var(--hairline); }
  .map-item.is-quiet .map-node:hover { border-color: var(--hairline-hover); }

  .map-panel { min-width: 0; }
  .map-panel-title { font-size: 18px; margin-top: 3px; }
  .map-desc {
    margin: 0; padding: 14px 18px 2px;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 14px; line-height: 1.55; color: var(--text-dim);
  }
  .map-demo { padding: 10px 18px 8px; }
  .map-works {
    display: flex; align-items: baseline; flex-wrap: wrap; gap: 4px 10px;
    padding: 12px 18px 16px; border-top: 1px solid var(--hairline);
  }
  .map-works-list {
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 13px; font-weight: 500; color: var(--text-dim);
  }
  .map-go { padding: 0 18px 16px; }
  .map-spec { margin-top: 56px; max-width: 540px; }

  @media (max-width: 900px) {
    .map-wrap { grid-template-columns: minmax(0, 1fr); gap: 0; }
    .map { aspect-ratio: auto; max-width: none; }
    .map-lines, .map-core { display: none; }
    .map-nodes { display: flex; flex-direction: column; gap: 8px; }
    .map-item { position: static; transform: none; }
    .map-node {
      flex-direction: row; justify-content: flex-start; gap: 12px;
      width: 100%; min-width: 0; padding: 14px 16px;
      background: var(--card);
    }
    .map-cat { margin-left: auto; }
    .map-item.is-quiet .map-name { color: var(--text); }
    .map-item > .map-panel { margin-top: 8px; }
    .map-name { white-space: normal; text-align: left; }
  }

  /* ── 05 MANUAL → AUTOMATED ── */
  .xf-section { overflow: visible; overflow: clip; }
  .xf-live { display: none; }
  .xf-header { margin-bottom: 28px; }
  .xf-static { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 20px; }
  .xf-list { list-style: none; margin: 0; padding: 6px 0 10px; }
  .xf-list > li {
    display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 12px;
    padding: 10px 18px;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 13.5px; font-weight: 500; color: var(--text-dim);
  }
  .xf-list > li + li { border-top: 1px dashed var(--hairline-hover); }
  .xf-flow { padding: 20px 18px 22px; display: flex; flex-direction: column; align-items: flex-start; gap: 16px; }
  .xf-chip {
    position: relative;
    display: inline-flex; align-items: center; gap: 10px;
    padding: 8px 14px;
    border: 1px solid var(--hairline-hover); border-radius: var(--radius-pill);
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 13.5px; font-weight: 600; color: var(--text);
  }
  .xf-chip.is-core {
    border-color: var(--blue-border);
    font-family: 'Astrohead', 'Inter', sans-serif; font-weight: 400;
    font-size: 13px; letter-spacing: 0.08em; text-transform: uppercase;
  }
  /* 4px clear of the chip above and the chip below (30 Sept 2026,
     snagging pass): it used to butt into both borders */
  .xf-flow > * + *::before {
    content: ''; position: absolute; left: 24px; top: -13px; height: 8px; width: 1.5px;
    background: var(--blue-border);
  }
  .xf-core-ring { width: 10px; height: 10px; border-radius: 50%; border: 1px solid var(--blue); }
  .xf-outs {
    position: relative; list-style: none; margin: 0; padding: 0;
    display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; width: 100%;
  }
  .xf-outs > li {
    display: grid; grid-template-columns: 14px minmax(0, 1fr) auto; align-items: center; column-gap: 8px;
    padding: 10px 12px;
    border: 1px solid var(--hairline); border-radius: 8px;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 13px; font-weight: 600; color: var(--text);
  }

  /* scrub mode — set by astro-home.js through gsap.matchMedia on desktop with
     motion allowed. The pin is CSS sticky (native scroll, no pin-spacer
     jump); ScrollTrigger only supplies progress. overflow:clip above keeps
     sticky working where .section's overflow:hidden would break it. */
  .xf-section.is-scrub { padding-top: 0; padding-bottom: 0; }
  .is-scrub .xf-track { height: 250vh; }
  .is-scrub .xf-sticky {
    position: sticky; top: 64px; height: calc(100vh - 64px);
    display: flex; align-items: center;
  }
  .is-scrub .xf-sticky > .container { width: 100%; }
  .is-scrub .xf-static { display: none; }
  .is-scrub .xf-live { display: block; }
  .xf-modes {
    display: flex; align-items: center; justify-content: center; gap: 14px;
    max-width: 440px; margin: 0 auto 22px;
  }
  .xf-mode {
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 11px; font-weight: 600; letter-spacing: 0.8px; text-transform: uppercase;
    color: var(--meta-ui); transition: color 260ms var(--ease);
  }
  .xf-mode.is-on { color: var(--text); }
  .xf-meter { position: relative; flex: 1; height: 1px; background: var(--hairline); }
  .xf-meter-fill {
    position: absolute; inset: 0; background: var(--blue-border);
    transform-origin: left; transform: scaleX(0);
  }
  .xf-stage {
    position: relative;
    width: min(100%, calc((100vh - 64px - 250px) * 2.2727));
    aspect-ratio: 1000 / 440;
    margin: 0 auto;
  }
  .xf-lines { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
  .xf-broken {
    fill: none; stroke: var(--hairline-hover); stroke-width: 1.5;
    stroke-dasharray: 3 5; vector-effect: non-scaling-stroke;
  }
  .xf-path {
    fill: none; stroke: var(--blue-border); stroke-width: 1.3;
    stroke-dasharray: 1; stroke-dashoffset: 1;
  }
  /* width floor (28 Sept 2026): the stage narrows with window height, so on
     short windows (now allowed down to 560px) 15% cut every name to a few
     letters. 116px is 15% of the stage at 654px tall, where the layout was
     approved; above that nothing changes. Rows stay apart down to 560px. */
  /* 30 Sept 2026 (final refinement pass): the names were single-line with an
     ellipsis, so at the 116px floor "Remember later" read "Remembe..." and
     "Open the practice system" read "Open the p...". The card is now wider
     (17% of the stage, 146px to 200px) and a name that still does not fit
     wraps onto a second line, balanced, instead of being cut. The manual
     label is taken out of flow once it has faded (astro-home.js), so the
     automated column is sized by its own short labels and its rows never
     collide. The x positions of the manual scatter were spread to match. */
  .xf-block {
    position: absolute; left: 0; top: 0; width: clamp(146px, 17%, 200px);
    display: grid; grid-template-columns: 14px minmax(0, 1fr); column-gap: 9px; row-gap: 2px;
    align-items: center;
    padding: 9px 11px;
    background: var(--card);
    border: 1px solid var(--hairline); border-radius: 8px;
    will-change: transform;
  }
  .xf-block .st { grid-row: span 2; }
  .xf-name, .xf-meta { display: grid; min-width: 0; }
  .xf-name > span, .xf-meta > span { grid-area: 1 / 1; white-space: normal; overflow-wrap: break-word; text-wrap: balance; }
  .xf-name {
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 13px; font-weight: 600; line-height: 1.25; color: var(--text);
  }
  .xf-meta {
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 10.5px; font-weight: 500; letter-spacing: 0.3px; line-height: 1.3;
    color: var(--meta-ui); font-variant-numeric: tabular-nums;
  }
  .xf-n-a { opacity: 0; }
  .xf-block .st-check { transition: none; }
  /* sized by its content since 30 Sept 2026 (snagging pass): at 12% of the
     stage it was narrower than its wordmark on short windows. astro-home.js
     measures it to place the connectors. */
  .xf-core {
    position: absolute; left: 0; top: 0; width: max-content;
    display: flex; align-items: center; justify-content: center; gap: 9px;
    padding: 12px 20px; white-space: nowrap;
    background: var(--card);
    border: 1px solid var(--blue-border); border-radius: var(--radius-pill);
    font-family: 'Astrohead', 'Inter', sans-serif;
    font-size: 14px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--text);
  }

  @media (max-width: 760px) { .xf-static { grid-template-columns: minmax(0, 1fr); } }
  @media (max-width: 440px) { .xf-outs { grid-template-columns: minmax(0, 1fr); } }

  /* ── 06 A DAY WITH ASTRO ── */
  .day-section { overflow: visible; overflow: clip; }
  .day-header { display: flex; align-items: flex-end; justify-content: space-between; gap: 24px; margin-bottom: 32px; }
  .day-header .section-headline { margin-bottom: 0; }
  .day-clock { flex: none; text-align: right; }
  .day-clock-time {
    display: block; margin-top: 4px;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 40px; font-weight: 500; line-height: 1; letter-spacing: 0.01em;
    color: var(--text); font-variant-numeric: tabular-nums;
  }
  .day-axis { display: none; }
  .day-section:not(.is-scrub) .day-clock { display: none; }  /* a clock only means something when scroll drives it */

  /* static: vertical timeline, same events */
  .day-events {
    position: relative; list-style: none; margin: 0; padding: 0;
    display: flex; flex-direction: column; gap: 14px; max-width: 760px;
  }
  .day-events::before {
    content: ''; position: absolute; left: 5px; top: 18px; bottom: 18px; width: 1.5px;
    background: var(--hairline);
  }
  .day-event { position: relative; display: grid; grid-template-columns: 250px minmax(0, 1fr); gap: 16px; align-items: start; }
  .day-btn {
    position: relative;
    display: flex; align-items: center; gap: 12px;
    padding: 10px 0; background: none; border: 0; text-align: left;
    color: var(--text); cursor: pointer;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
  }
  .day-dot {
    position: relative; z-index: 1; flex: none;
    width: 11px; height: 11px; border-radius: 50%;
    border: 1px solid var(--hairline-hover); background: var(--bg);
    transition: border-color 260ms var(--ease), outline-color 260ms var(--ease);
    outline: 1px solid transparent; outline-offset: 3px;
  }
  .day-time { width: 42px; font-size: 12px; font-weight: 500; color: var(--meta-ui); font-variant-numeric: tabular-nums; }
  .day-title { font-size: 14px; font-weight: 600; }
  .day-event.is-done .day-dot { border-color: var(--blue-border); }
  .day-event.is-active .day-dot { border-color: var(--blue); outline-color: var(--blue-border-soft); }
  .day-mini { padding: 8px 14px; }
  /* static timeline: an event's automation expands when the event is reached
     (brief §14 "active event expands"), so no empty card ever waits below.
     Reduced motion marks every event done on load, so all render expanded. */
  .js-home .day-section:not(.is-scrub) .day-event:not(.is-active):not(.is-done) .day-mini { display: none; }
  .js-home .day-section:not(.is-scrub) .day-event:not(.is-active):not(.is-done) .day-title { color: var(--text-dim); }
  @media (max-width: 720px) {
    .day-header { flex-direction: column; align-items: flex-start; }
    .day-clock { display: none; }
    .day-event { grid-template-columns: minmax(0, 1fr); gap: 4px; }
    .day-mini { margin-left: 23px; }
  }

  /* scrub: horizontal, sticky, clock tied to scroll */
  .day-section.is-scrub { padding-top: 0; padding-bottom: 0; }
  .is-scrub .day-track { height: 270vh; }
  /* 30 Sept 2026 (final refinement pass): the stage was centred with no
     floor, so on short windows (1272x588, James's own) "A Day with Astro"
     sat 6px under the section boundary. A 44px top clearance is now
     guaranteed at every height ("safe" keeps any overflow at the bottom),
     and on short windows the line box drops the empty band it reserved
     below the mini panels (they end 297px down it). */
  .is-scrub .day-sticky {
    position: sticky; top: 64px; height: calc(100vh - 64px);
    box-sizing: border-box; padding-top: 44px;
    display: flex; align-items: safe center;
  }
  .is-scrub .day-sticky > .container { width: 100%; }
  .is-scrub .day-line { position: relative; height: 380px; }
  @media (max-height: 720px) { .is-scrub .day-line { height: 320px; } }
  .is-scrub .day-axis { display: block; position: absolute; left: 0; right: 0; top: 122px; height: 40px; }
  .day-track-line { position: absolute; left: 0; right: 0; top: 0; height: 1.5px; background: var(--hairline); }
  .day-fill {
    position: absolute; inset: 0; background: var(--blue-border);
    transform-origin: left; transform: scaleX(var(--dp, 0));
  }
  .day-shift {
    position: absolute; top: -9px; height: 19px;
    left: 11.111%; width: 52.778%;                 /* 08:00 to 17:30 on a 06:00-24:00 axis */
    border: 1px solid var(--hairline); border-radius: var(--radius-pill);
    background: rgba(237,233,227,0.025);
  }
  .day-shift .ui-meta { position: absolute; left: 10px; top: 26px; }
  .day-tick {
    position: absolute; top: 18px; transform: translateX(-50%);
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 10.5px; font-weight: 500; color: var(--meta-ui); font-variant-numeric: tabular-nums;
  }
  .day-tick[data-tick="06:00"] { left: 0; transform: none; }
  .day-tick[data-tick="12:00"] { left: 33.333%; }
  .day-tick[data-tick="18:00"] { left: 66.667%; }
  .day-tick[data-tick="24:00"] { left: auto; right: 0; transform: none; }
  .is-scrub .day-events { position: absolute; inset: 0; display: block; max-width: none; }
  .is-scrub .day-events::before { display: none; }
  .is-scrub .day-event {
    position: absolute; top: 0; left: calc(var(--x, 0) * 100%);
    display: block; width: 0;
  }
  .is-scrub .day-event:nth-child(even) { top: 46px; }
  .is-scrub .day-btn {
    position: absolute; left: 0; top: 0; transform: translateX(-50%);
    flex-direction: column; align-items: center; gap: 1px;
    padding: 0 6px; height: 38px; white-space: nowrap;
  }
  .is-scrub .day-time { width: auto; }
  .is-scrub .day-title { font-size: 13px; color: var(--text-dim); transition: color 260ms var(--ease); }
  .is-scrub .day-event.is-active .day-title, .is-scrub .day-event.is-done .day-title { color: var(--text); }
  .is-scrub .day-dot { position: absolute; left: 50%; top: 116px; margin-left: -5.5px; }
  .is-scrub .day-event:nth-child(even) .day-dot { top: 70px; }
  .is-scrub .day-btn::after {
    content: ''; position: absolute; left: 50%; top: 42px; height: 72px; width: 1px;
    background: var(--hairline);
  }
  .is-scrub .day-event:nth-child(even) .day-btn::after { height: 26px; }
  .is-scrub .day-event.is-active .day-btn::after,
  .is-scrub .day-event.is-done .day-btn::after { background: var(--hairline-hover); }
  .is-scrub .day-mini {
    position: absolute; top: 184px; left: 0; width: 290px;
    opacity: 0; visibility: hidden;
    transform: translateX(calc(-50% + var(--shift, 0px))) translateY(8px);
    transition: opacity 420ms var(--ease), transform 420ms var(--ease), visibility 0s linear 420ms;
  }
  .is-scrub .day-event:nth-child(even) .day-mini { top: 138px; }
  .is-scrub .day-event.is-active .day-mini {
    opacity: 1; visibility: visible;
    transform: translateX(calc(-50% + var(--shift, 0px)));
    transition-delay: 0s;
  }

  /* ── 07 THE ASTRO SYSTEM ── */
  .arch { margin-top: 40px; overflow: hidden; }
  .arch-head-right { display: flex; align-items: center; gap: 14px; }
  .arch-live { display: inline-flex; align-items: center; gap: 7px; opacity: 0; transition: opacity 420ms var(--ease); }
  .arch.is-s6 .arch-live { opacity: 1; }
  .arch-body {
    position: relative;
    display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
    align-items: center; gap: 72px;
    padding: 34px 44px 38px;
  }
  .arch-lines { position: absolute; left: 0; top: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none; }
  .arch-lines path { fill: none; stroke-width: 1.5; stroke-dasharray: 1; stroke-dashoffset: 1; transition: stroke-dashoffset 560ms var(--ease); }
  .arch-lines .arch-in-path { stroke: var(--hairline-hover); }
  .arch-lines .arch-out-path { stroke: var(--blue-border); }
  .arch.is-s2 .arch-in-path, .arch.is-s5 .arch-out-path { stroke-dashoffset: 0; }
  .arch-lines .arch-flow { stroke: var(--blue); stroke-dasharray: 0.07 0.93; stroke-dashoffset: 0.07; opacity: 0; transition: none; }
  .arch.is-s4 .arch-flow { animation: archFlow 1000ms var(--ease) forwards; animation-delay: calc(var(--i, 0) * 90ms); }
  @keyframes archFlow {
    0%   { stroke-dashoffset: 0.07; opacity: 1; }
    90%  { opacity: 1; }
    100% { stroke-dashoffset: -0.93; opacity: 0; }
  }
  .arch-col { position: relative; z-index: 1; display: flex; flex-direction: column; align-items: flex-start; gap: 10px; min-width: 0; }
  .arch-in { align-items: flex-start; }
  .arch-out { align-items: flex-start; justify-self: end; }
  .arch-mid { align-items: center; }
  .arch-cap { margin-bottom: 2px; }
  .arch-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
  .arch-tool, .arch-branch {
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 13px; font-weight: 500; line-height: 1.2; color: var(--text);
    background: var(--card); border-radius: var(--radius-pill);
    width: fit-content;
    transition: opacity 420ms var(--ease), transform 420ms var(--ease), border-color 260ms var(--ease);
  }
  .arch-tool { padding: 8px 14px; border: 1px solid var(--hairline-hover); }
  .arch-branch {
    display: grid; grid-template-columns: 14px auto; align-items: center; column-gap: 8px;
    padding: 7px 14px 7px 9px; border: 1px solid var(--hairline);
  }
  .arch-branch.is-done { border-color: var(--hairline-hover); }
  .arch-core {
    display: flex; flex-direction: column; align-items: center; gap: 12px;
    padding: 24px 30px;
    background: var(--card);
    border: 1px solid var(--blue-border); border-radius: var(--radius-card);
    transition: opacity 560ms var(--ease), transform 560ms var(--ease);
  }
  .arch-core-ring { position: relative; width: 38px; height: 38px; border-radius: 50%; border: 1px solid var(--blue-border); }
  .arch-core-ring::after { content: ''; position: absolute; inset: 9px; border-radius: 50%; border: 1px solid var(--hairline-hover); }
  .arch-core-name {
    font-family: 'Astrohead', 'Inter', sans-serif;
    font-size: 16px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--text);
  }
  .arch-mid .arch-cap { transition: opacity 420ms var(--ease); }
  /* staged assembly, armed only once JS is running */
  .js-home .arch:not(.is-s1) .arch-tool { opacity: 0; transform: translateX(-10px); }
  .js-home .arch:not(.is-s3) .arch-core { opacity: 0; transform: scale(0.92); }
  .js-home .arch:not(.is-s5) .arch-branch { opacity: 0; transform: translateX(10px); }
  .js-home .arch:not(.is-s5) .arch-mid .arch-cap,
  .js-home .arch:not(.is-s5) .arch-out .arch-cap { opacity: 0; }
  .arch-out .arch-cap { transition: opacity 420ms var(--ease); }
  .arch-tool:nth-child(2), .arch-branch:nth-child(2) { transition-delay: 60ms; }
  .arch-tool:nth-child(3), .arch-branch:nth-child(3) { transition-delay: 120ms; }
  .arch-tool:nth-child(4), .arch-branch:nth-child(4) { transition-delay: 180ms; }
  .arch-tool:nth-child(5), .arch-branch:nth-child(5) { transition-delay: 240ms; }
  .arch-branch:nth-child(6) { transition-delay: 300ms; }

  @media (max-width: 900px) {
    .arch-body { grid-template-columns: minmax(0, 1fr); gap: 44px; padding: 28px 20px 30px; justify-items: center; }
    .arch-col, .arch-in, .arch-out { align-items: center; justify-self: center; }
    .arch-list { flex-direction: row; flex-wrap: wrap; justify-content: center; }
    .arch-head-right .arch-live { display: none; }
  }

  /* principles */
  .pr { margin-top: 20px; display: grid; grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr); gap: 20px; align-items: stretch; }
  .pr-tabs { display: flex; flex-direction: column; gap: 8px; }
  .pr-tab {
    display: grid; grid-template-columns: 30px minmax(0, 1fr); column-gap: 10px; row-gap: 3px;
    padding: 16px 18px; text-align: left;
    background: transparent; color: var(--text);
    border: 1px solid var(--hairline); border-radius: var(--radius-card);
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    cursor: pointer;
    transition: border-color 140ms var(--ease), background 140ms var(--ease);
  }
  .pr-tab:hover { border-color: var(--hairline-hover); }
  .pr-tab[aria-selected="true"] { border-color: var(--blue-border); background: var(--card); }
  .pr-num { grid-row: span 2; padding-top: 3px; font-size: 11px; font-weight: 600; color: var(--meta-ui); font-variant-numeric: tabular-nums; }
  .pr-name { font-size: 15px; font-weight: 600; }
  .pr-line { font-size: 13px; font-weight: 500; color: var(--text-dim); }
  .pr-panel { padding: 18px 20px; min-height: 262px; }
  .pr-config { margin: 0; }
  .pr-config > div {
    display: grid; grid-template-columns: 14px 130px minmax(0, 1fr); align-items: center; column-gap: 10px;
    padding: 8px 0; border-bottom: 1px solid var(--hairline);
  }
  .pr-config > div:last-child { border-bottom: 0; }
  .pr-conn { list-style: none; margin: 0; padding: 0; }
  .pr-conn > li {
    display: grid; grid-template-columns: 96px minmax(40px, 1fr) auto 84px; align-items: center; column-gap: 12px;
    padding: 9px 0; border-bottom: 1px solid var(--hairline);
    font-family: 'Familjen Grotesk', 'Inter', sans-serif; font-size: 13px; font-weight: 500; color: var(--text);
  }
  .pr-conn > li:last-child { border-bottom: 0; }
  .pr-conn .ui-meta { text-align: right; }
  .pr-link { position: relative; height: 1px; background: var(--hairline-hover); }
  .pr-link::before, .pr-link::after {
    content: ''; position: absolute; top: -3px; width: 7px; height: 7px; border-radius: 50%;
    border: 1px solid var(--hairline-hover); background: var(--card);
  }
  .pr-link::before { left: -4px; } .pr-link::after { right: -4px; }
  .pr-conn-astro { font-family: 'Astrohead', 'Inter', sans-serif; font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase; }
  .loop { list-style: none; margin: 18px 0 0; padding: 0; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 14px; }
  .loop-node {
    position: relative; padding: 13px 6px; text-align: center;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 11.5px; font-weight: 600; letter-spacing: 0.8px; text-transform: uppercase; color: var(--text-dim);
    border: 1px solid var(--hairline); border-radius: var(--radius-card);
  }
  .loop-node + .loop-node::before {
    content: '\2192'; position: absolute; left: -7px; top: 50%; transform: translate(-50%, -50%);
    font-size: 12px; color: var(--meta-ui); letter-spacing: 0;
  }
  .loop-node.is-live { border-color: var(--blue-border); color: var(--text); }
  .loop-node.is-done { border-color: var(--hairline-hover); color: var(--text); }
  .loop-return { margin-top: 2px; text-align: center; }
  .loop-return svg { display: block; width: calc(100% - 12%); height: 28px; margin: 0 auto; overflow: visible; }
  .loop-return path {
    fill: none; stroke: var(--blue-border); stroke-width: 1.5;
    stroke-dasharray: 1; stroke-dashoffset: 1; transition: stroke-dashoffset 560ms var(--ease) 120ms;
  }
  .loop-return.is-in path, .loop-return:not([data-at]) path { stroke-dashoffset: 0; }
  :not(.seq-armed) > .loop-return path { stroke-dashoffset: 0; }
  .loop-return .ui-meta { margin-top: 6px; }
  @media (max-width: 900px) { .pr { grid-template-columns: minmax(0, 1fr); } }
  @media (max-width: 520px) {
    .pr-config > div { grid-template-columns: 14px minmax(0, 1fr); row-gap: 2px; }
    .pr-config dd { grid-column: 2; }
    .pr-conn > li { grid-template-columns: 84px minmax(24px, 1fr) auto; }
    .pr-conn .ui-meta { display: none; }
    .loop { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .loop-node:nth-child(3)::before { display: none; }
    .loop-return svg { display: none; }
  }

  /* ── 08 WORK ── */
  .work-header { margin-bottom: 36px; }
  .wk-grid { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 16px; }
  .wk-card { display: flex; }
  .wk-open {
    width: 100%;
    display: flex; flex-direction: column; gap: 10px;
    padding: 18px 18px 20px; text-align: left;
    background: var(--card); color: var(--text);
    border: 1px solid var(--hairline); border-radius: var(--radius-card);
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    cursor: pointer;
    transition: border-color 140ms var(--ease), background 140ms var(--ease);
  }
  .wk-open:hover { border-color: var(--hairline-hover); }
  .wk-top { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
  .wk-top .demo-chip { margin: 0; padding: 4px 10px; }
  .wk-preview { display: block; width: 100%; height: auto; margin: 14px 0 10px; overflow: visible; }
  .wk-track { fill: none; stroke: var(--hairline-hover); stroke-width: 1.5; vector-effect: non-scaling-stroke; }
  .wk-track.is-dashed { stroke-dasharray: 3 5; }
  .wk-draw {
    fill: none; stroke: var(--blue-border); stroke-width: 1.5;
    stroke-dasharray: 1; stroke-dashoffset: 1;
    transition: stroke-dashoffset 560ms var(--ease);
  }
  .wk-preview circle { fill: var(--card); stroke: var(--hairline-hover); stroke-width: 1.5; vector-effect: non-scaling-stroke; transition: stroke 260ms var(--ease); }
  .wk-open:hover .wk-draw, .wk-open:focus-visible .wk-draw { stroke-dashoffset: 0; }
  .wk-open:hover .wk-preview circle, .wk-open:focus-visible .wk-preview circle { stroke: var(--text-dim); }
  .wk-name { font-size: 17px; font-weight: 600; line-height: 1.25; }
  .wk-line { flex: 1; font-size: 13px; font-weight: 500; line-height: 1.5; color: var(--text-dim); }
  .wk-explore { display: inline-flex; align-items: center; gap: 6px; margin-top: 6px; font-size: 13px; font-weight: 500; color: var(--blue); }
  .wk-arrow { display: inline-block; transition: transform 140ms var(--ease); }
  .wk-open:hover .wk-arrow, .wk-open:focus-visible .wk-arrow { transform: translateX(3px); }
  @media (max-width: 1100px) { .wk-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
  @media (max-width: 560px) { .wk-grid { grid-template-columns: minmax(0, 1fr); } }

  .wk-dialog {
    width: min(980px, calc(100vw - 32px)); max-width: none;
    max-height: calc(100dvh - 48px);
    padding: 0; margin: auto;
    background: var(--card); color: var(--text);
    border: 1px solid var(--hairline-hover); border-radius: var(--radius-card);
    overflow: auto; overscroll-behavior: contain;
  }
  .wk-dialog::backdrop { background: rgba(4,4,6,0.74); backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px); }
  .wk-dialog[open] { animation: wkIn 420ms var(--ease); }
  @keyframes wkIn { from { opacity: 0; transform: translateY(12px) scale(0.985); } to { opacity: 1; transform: none; } }
  .wk-dlg-head {
    position: sticky; top: 0; z-index: 1;
    display: flex; align-items: flex-start; justify-content: space-between; gap: 16px;
    padding: 18px 22px; background: var(--card); border-bottom: 1px solid var(--hairline);
  }
  .wk-dlg-title { margin: 3px 0 0; font-family: 'Familjen Grotesk', 'Inter', sans-serif; font-size: 20px; font-weight: 600; line-height: 1.2; }
  .wk-dlg-actions { display: flex; align-items: center; gap: 8px; }
  .wk-dlg-actions .demo-chip { margin: 0; padding: 5px 11px; }
  .wk-close {
    width: 34px; height: 34px; border-radius: 50%;
    background: transparent; color: var(--text);
    border: 1px solid var(--tag-border);
    font-size: 19px; line-height: 1; cursor: pointer;
    transition: background 140ms var(--ease);
  }
  .wk-close:hover { background: var(--ghost-hover); }
  /* 5 Oct 2026: the close control never takes a copper ring. Opening the
     dialog focuses it, which drew the site's copper focus outline as a
     halo. Focus is shown by a brighter neutral border and fill instead,
     still clearly visible for keyboard users. */
  .wk-close:focus { outline: none; }
  .wk-close:focus-visible { border-color: rgba(237,233,227,0.7); background: var(--ghost-hover); }
  .wk-close:active { background: var(--ghost-hover); }
  .wk-dlg-body { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr); }
  .wk-in, .wk-flow { padding: 20px 22px 22px; min-width: 0; }
  .wk-flow { border-left: 1px solid var(--hairline); background: var(--panel); }
  .wk-record { margin: 0; }
  .wk-record > div { display: grid; grid-template-columns: 110px minmax(0, 1fr); align-items: baseline; padding: 10px 0; border-bottom: 1px solid var(--hairline); }
  .wk-record dd { font-size: 13.5px; }
  .wk-note {
    margin: 0; padding: 12px 22px 16px; border-top: 1px solid var(--hairline);
    font-family: 'Familjen Grotesk', 'Inter', sans-serif; font-size: 11px; color: var(--meta-ui);
  }
  html.wk-lock { overflow: hidden; }
  @media (max-width: 720px) {
    .wk-dlg-body { grid-template-columns: minmax(0, 1fr); }
    .wk-flow { border-left: 0; border-top: 1px solid var(--hairline); }
    .wk-dlg-head { flex-wrap: wrap; padding: 16px 18px; }
    .wk-dlg-actions .demo-chip { display: none; }
  }

  /* ── 09 HOW ASTRO WORKS: scenes ──
     One custom property per scene, --lp (0 to 1), drives every transform
     below through clamp(). ScrollTrigger writes it on desktop; on mobile and
     under reduced motion the existing journey script's .is-active sets it to
     1. Without JS it defaults to 1, so every scene renders complete. */
  #process { overflow: visible; overflow: clip; }
  .proc-stage { display: none; }
  .proc-scene {
    --lp: 1;
    position: relative;
    margin-top: 18px; max-width: 470px; padding: 16px 18px;
    background: var(--card-light);
    border: 1px solid var(--hairline); border-radius: var(--radius-card);
  }
  .js-home .proc-scene { --lp: 0; }
  .js-home .journey-step.is-active .proc-scene { --lp: 1; }
  .proc-scene [style*="--a"], .proc-scene .pb-part, .proc-scene .pb-plus, .proc-scene .pb-join,
  .proc-scene .pb-system, .proc-scene .pl-state, .proc-scene .pl-bar-fill, .proc-scene .pi-sweep,
  .proc-scene .pi-centre, .proc-scene::after, .proc-scene .pd-chain::before, .proc-scene .pl::after {
    transition: opacity 560ms var(--ease), transform 560ms var(--ease), stroke-dashoffset 560ms var(--ease);
    transition-delay: calc(var(--a, 0) * 900ms);
  }
  .proc-scrub .proc-stage .proc-scene *,
  .proc-scrub .proc-stage .proc-scene *::before,
  .proc-scrub .proc-stage .proc-scene *::after { transition: none !important; }

  /* discover */
  .pd-chain { position: relative; list-style: none; margin: 0; padding: 0 0 0 24px; }
  .pd-chain::before {
    content: ''; position: absolute; left: 5px; top: 18px; bottom: 18px; width: 1.5px;
    background: var(--blue-border); transform-origin: top;
    transform: scaleY(clamp(0, calc(var(--lp) / 0.75), 1));
  }
  .pd-node {
    --k: clamp(0, calc((var(--lp) - var(--a, 0)) / 0.2), 1);
    position: relative;
    display: grid; grid-template-columns: 112px minmax(0, 1fr); align-items: center; column-gap: 12px;
    padding: 10px 0;
    opacity: var(--k); transform: translateY(calc((1 - var(--k)) * 10px));
  }
  .pd-node + .pd-node { border-top: 1px solid var(--hairline); }
  .pd-node::after {
    content: ''; position: absolute; left: -24px; top: 50%; margin-top: -5.5px;
    width: 11px; height: 11px; border-radius: 50%;
    border: 1px solid var(--blue-border); background: var(--card);
  }
  .pd-val { font-family: 'Familjen Grotesk', 'Inter', sans-serif; font-size: 13.5px; font-weight: 500; color: var(--text); }
  .pd-chips { display: flex; flex-wrap: wrap; gap: 6px; }
  .pd-chip {
    padding: 4px 10px; border: 1px solid var(--hairline-hover); border-radius: var(--radius-pill);
    font-family: 'Familjen Grotesk', 'Inter', sans-serif; font-size: 12px; font-weight: 500; color: var(--text);
  }
  .pd-node.is-key .pd-chip { border-color: var(--blue-border); }

  /* build */
  .pb { display: flex; flex-direction: column; align-items: stretch; }
  .pb-parts { display: flex; align-items: stretch; gap: 8px; }
  .pb-part {
    --k: clamp(0, calc((var(--lp) - var(--a)) / 0.3), 1);
    flex: 1; min-width: 0;
    display: flex; flex-direction: column; gap: 4px;
    padding: 10px 11px;
    border: 1px solid var(--hairline-hover); border-radius: 8px; background: var(--card);
    opacity: calc(0.25 + var(--k) * 0.75);
  }
  .pb-part.is-l { --a: 0.02; transform: translateX(calc((1 - var(--k)) * -44px)); }
  .pb-part.is-c { --a: 0.14; transform: translateY(calc((1 - var(--k)) * -28px)); }
  .pb-part.is-r { --a: 0.26; transform: translateX(calc((1 - var(--k)) * 44px)); }
  .pb-part .pd-val { font-size: 12.5px; }
  .pb-plus { --a: 0.4; align-self: center; font-size: 14px; color: var(--meta-ui); opacity: clamp(0, calc((var(--lp) - 0.4) / 0.15), 1); }
  .pb-join {
    --a: 0.5;
    display: block; width: 1.5px; height: 30px; margin: 0 auto;
    background: var(--blue-border); transform-origin: top;
    transform: scaleY(clamp(0, calc((var(--lp) - 0.5) / 0.14), 1));
  }
  .pb-system {
    --a: 0.62;
    --k: clamp(0, calc((var(--lp) - 0.62) / 0.2), 1);
    display: flex; align-items: center; justify-content: center; gap: 12px;
    padding: 16px; border: 1px solid var(--blue-border); border-radius: var(--radius-card);
    opacity: var(--k); transform: scale(calc(0.94 + var(--k) * 0.06));
  }
  .pb-ring { width: 14px; height: 14px; border-radius: 50%; border: 1px solid var(--blue); }
  .pb-system-name { font-family: 'Astrohead', 'Inter', sans-serif; font-size: 13px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--text); }

  /* launch */
  .pl {
    --kl: clamp(0, calc((var(--lp) - 0.74) / 0.12), 1);
    position: relative; padding: 14px 16px;
    border: 1px solid var(--hairline); border-radius: 8px;
  }
  .pl::after {
    content: ''; position: absolute; inset: -1px; border-radius: inherit; pointer-events: none;
    border: 1px solid var(--blue-border); opacity: var(--kl);
  }
  .pl-head { display: grid; margin-bottom: 8px; }
  .pl-state {
    grid-area: 1 / 1; display: inline-flex; align-items: center; gap: 8px;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 11.5px; font-weight: 600; letter-spacing: 0.8px; text-transform: uppercase; color: var(--text);
  }
  .pl-state.is-testing { opacity: calc(1 - var(--kl)); }
  .pl-state.is-live { opacity: var(--kl); }
  .pl-spin {
    width: 11px; height: 11px; border-radius: 50%;
    border: 1.5px solid var(--hairline-hover); border-top-color: var(--text-dim);
    animation: sysSpin 900ms linear infinite;
  }
  .pl-checks { list-style: none; margin: 0; padding: 0; }
  .pl-checks > li {
    --k: clamp(0, calc((var(--lp) - var(--a)) / 0.1), 1);
    position: relative; padding: 8px 0 8px 24px; border-bottom: 1px solid var(--hairline);
    font-family: 'Familjen Grotesk', 'Inter', sans-serif; font-size: 13.5px; font-weight: 500;
    color: var(--text);
  }
  .pl-checks > li::before {
    content: ''; position: absolute; left: 4px; top: 50%; width: 4px; height: 8px; margin-top: -6px;
    border: solid var(--text); border-width: 0 1.5px 1.5px 0;
    opacity: var(--k); transform: rotate(45deg) scale(calc(0.6 + var(--k) * 0.4));
  }
  .pl-bar { position: relative; height: 1px; margin-top: 12px; background: var(--hairline); }
  .pl-bar-fill {
    position: absolute; inset: 0; background: var(--blue-border); transform-origin: left;
    transform: scaleX(clamp(0, calc(var(--lp) / 0.72), 1));
  }

  /* improve */
  .pi { position: relative; width: 250px; height: 250px; margin: 6px auto; }
  .pi-loop { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; transform: rotate(-90deg); }
  .pi-track { fill: none; stroke: var(--hairline); stroke-width: 1.5; vector-effect: non-scaling-stroke; }
  .pi-sweep {
    fill: none; stroke: var(--blue-border); stroke-width: 1.25;
    stroke-dasharray: 1; stroke-dashoffset: calc(1 - var(--lp));
  }
  .pi-node {
    --k: clamp(0, calc((var(--lp) - var(--a)) / 0.08), 1);
    position: absolute; transform: translate(-50%, -50%);
    padding: 5px 11px; background: var(--card);
    border: 1px solid var(--hairline-hover); border-radius: var(--radius-pill);
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 11px; font-weight: 600; letter-spacing: 0.8px; text-transform: uppercase; color: var(--text);
    white-space: nowrap;
  }
  .pi-node::after {
    content: ''; position: absolute; inset: -1px; border-radius: inherit;
    border: 1px solid var(--blue-border); opacity: var(--k);
  }
  .pi-node.is-n { left: 50%; top: calc(50% - 90px); }
  .pi-node.is-e { left: calc(50% + 90px); top: 50%; }
  .pi-node.is-s { left: 50%; top: calc(50% + 90px); }
  .pi-node.is-w { left: calc(50% - 90px); top: 50%; }
  .pi-centre {
    position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
    display: flex; flex-direction: column; align-items: center; gap: 4px;
    opacity: clamp(0, calc((var(--lp) - 0.88) / 0.1), 1);
  }
  .pi-glyph { font-size: 24px; line-height: 1; color: var(--text); }

  /* desktop scrub layout: rail left, sticky stage right */
  .proc-scrub .proc-layout { display: grid; grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr); gap: 72px; align-items: start; }
  .proc-scrub .journey-step { min-height: 64vh; }
  .proc-scrub .journey-step:last-child { min-height: 52vh; }
  .proc-scrub .proc-stage { display: block; position: sticky; top: calc(64px + (100vh - 64px - 500px) / 2); }
  .proc-stage-inner { overflow: hidden; }
  .proc-stage-title { font-size: 18px; margin-top: 3px; }
  .proc-scenes { position: relative; height: 430px; }
  .proc-scrub .proc-stage .proc-scene {
    position: absolute; inset: 0; margin: 0; max-width: none;
    display: flex; flex-direction: column; justify-content: center;
    padding: 26px 30px; background: transparent; border: 0; border-radius: 0;
    opacity: 0; visibility: hidden;
    transition: opacity 420ms var(--ease), visibility 0s linear 420ms;
  }
  .proc-scrub .proc-stage .proc-scene.is-current { opacity: 1; visibility: visible; transition-delay: 0s; }
  @media (max-width: 520px) {
    .proc-scene { padding: 14px; }
    .pd-node { grid-template-columns: minmax(0, 1fr); row-gap: 4px; }
    .pb-parts { flex-direction: column; }
    .pb-plus { display: none; }
    .pi { transform: scale(0.9); }
  }

  /* ── 10 ASK ASTRO ── */
  .container.ask-container { max-width: 980px; }
  .ask-header { text-align: center; }
  .ask-header .section-label { justify-content: center; }
  .ask-header .cta-headline { margin-bottom: 34px; }
  .ask { display: grid; grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr); overflow: hidden; text-align: left; }
  .ask-q { min-width: 0; margin: 0; padding: 24px 22px 26px; border: 0; border-right: 1px solid var(--hairline); }
  /* float + clear takes the legend out of the fieldset's border slot, where
     browsers otherwise render it straddling the top edge */
  .ask-legend {
    float: left; width: 100%;
    padding: 0; margin-bottom: 16px;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 17px; font-weight: 600; line-height: 1.3; color: var(--text);
  }
  .ask-options { clear: both; display: flex; flex-direction: column; gap: 8px; }
  .ask-opt { position: relative; display: block; cursor: pointer; }
  .ask-opt input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; }
  .ask-opt span {
    display: flex; align-items: center; gap: 11px;
    padding: 11px 16px;
    border: 1px solid var(--tag-border); border-radius: var(--radius-pill);
    font-family: 'Familjen Grotesk', 'Inter', sans-serif; font-size: 14px; font-weight: 500; color: var(--text);
    transition: border-color 140ms var(--ease), background 140ms var(--ease);
  }
  .ask-opt span::before {
    content: ''; flex: none; width: 12px; height: 12px; border-radius: 50%;
    border: 1px solid var(--hairline-hover);
    transition: border-color 140ms var(--ease), box-shadow 140ms var(--ease);
  }
  .ask-opt:hover span { background: var(--ghost-hover); }
  .ask-opt input:checked + span { border-color: var(--blue-border); background: rgba(237,233,227,0.05); }
  /* selected radio: copper perimeter, NEUTRAL centre (accent rule: never a copper dot) */
  .ask-opt input:checked + span::before { border-color: var(--blue); box-shadow: inset 0 0 0 2.5px var(--card), inset 0 0 0 6px var(--text); }
  .ask-opt input:focus-visible + span { outline: 2px solid var(--blue); outline-offset: 2px; }
  .ask-out { display: flex; flex-direction: column; min-height: 400px; padding: 22px 24px 24px; background: var(--panel); }
  .ask-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; min-height: 20px; margin-bottom: 18px; }
  .ask-id {
    display: inline-flex; align-items: center; gap: 8px;
    font-family: 'Astrohead', 'Inter', sans-serif; font-size: 12px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--text);
  }
  .ask-thinking {
    display: inline-flex; align-items: center; gap: 8px;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 11px; font-weight: 500; letter-spacing: 0.5px; text-transform: uppercase; color: var(--meta-ui);
  }
  .ask-thinking[hidden] { display: none; }
  .ask-thinking .st-spin { position: relative; top: auto; left: auto; display: inline-block; }
  .ask-live { flex: 1; display: flex; flex-direction: column; }
  .ask-idle {
    margin: auto 0; max-width: 30ch;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif; font-size: 15px; line-height: 1.55; color: var(--text-dim);
  }
  .ask-idle[hidden], .ask-resp[hidden] { display: none; }
  .ask-resp { flex: 1; display: flex; flex-direction: column; gap: 10px; }
  .ask-finding {
    margin: 0 0 14px;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif; font-size: 19px; font-weight: 500; line-height: 1.4; color: var(--text);
  }
  .ask-could { list-style: none; margin: 0 0 20px; padding: 0; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px 18px; }
  .ask-could > li {
    display: grid; grid-template-columns: 14px minmax(0, 1fr); align-items: center; column-gap: 9px;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif; font-size: 13.5px; font-weight: 500; line-height: 1.4; color: var(--text);
  }
  .ask-resp .ask-finding, .ask-resp .ui-eyebrow, .ask-resp .ask-actions { transition: opacity 420ms var(--ease), transform 420ms var(--ease); }
  .ask-resp:not(.is-shown) .ask-finding, .ask-resp:not(.is-shown) .ui-eyebrow, .ask-resp:not(.is-shown) .ask-actions { opacity: 0; transform: translateY(6px); }
  .ask-actions { display: flex; align-items: center; flex-wrap: wrap; gap: 12px 22px; margin-top: auto; }
  .ask-talk { display: inline-flex; align-items: center; min-height: 32px; font-family: 'Familjen Grotesk', 'Inter', sans-serif; font-size: 14px; font-weight: 500; color: var(--blue); text-decoration: none; }
  #chat-cta .chat-cta-fallback a:focus-visible { outline: 2px solid var(--blue); outline-offset: 3px; border-radius: 2px; }
  /* mobile step numbers: were --text-faint, 2.27:1. Specificity (1,1,0) beats
     the .section--light .journey-num rule without touching the component. */
  #process .journey-num { color: var(--meta-ui); }
  .ask-talk:hover { text-decoration: underline; }
  #chat-cta .chat-cta-fallback { margin-top: 30px; text-align: center; }
  #chat-cta .guarantee-strip { margin-top: 40px; }
  @media (max-width: 760px) {
    .ask { grid-template-columns: minmax(0, 1fr); }
    .ask-q { border-right: 0; border-bottom: 1px solid var(--hairline); }
    .ask-out { min-height: 0; }
    .ask-idle { margin: 0; }
    .ask-could { grid-template-columns: minmax(0, 1fr); }
  }

  /* ── reduced motion: every sequence complete, every state change instant ── */
  @media (prefers-reduced-motion: reduce) {
    [data-at], .st-spin, .st-check, .wf-node, .wf-node::after, .wf-ring, .map-edge, .map-node,
    .act-progress-fill, .act-callcard, .act-slot, .arch-tool, .arch-branch, .arch-core, .arch-lines path,
    .arch-live, .wk-draw, .wk-arrow, .loop-return path, .ask-opt span, .ask-resp *, .day-mini, .day-dot,
    .proc-scene, .proc-scene *, .proc-scene *::before, .proc-scene *::after, .xf-mode {
      transition: none !important; animation: none !important;
    }
    .st-spin, .pl-spin { display: none; }
    .map-flow { display: none; }
    .wk-dialog[open] { animation: none; }
    .js-reveal .reveal-panel { opacity: 1 !important; transform: none !important; }
  }


/* ══════════════════════════════════════════════════════════════════════
   ASTRO INTERFACE KIT — 19 September 2026 (Brain/CC_prompt_00_interface_
   kit.md). Extracted from the shipped increase-leads.html so the product
   pages assemble the same components instead of re-implementing them.

   OPT IN: put `ak-page` on <body>, alongside the page's own `page-<name>`
   class. Every selector here is `.ak-page .ak-*`, so the block is a no-op
   on any page that does not opt in, and a page-specific rule written as
   `.page-<name> .<page-class>` has the same specificity but comes later in
   this file, so it wins a tie. Behaviour: assets/js/astro-kit.js
   (`window.AstroKit`), loaded deferred before the page's own script.

   ONE CAVEAT on that tie-break, and it will bite eventually. A media query
   adds no specificity, and every @media block in this kit sits ABOVE the
   page blocks. So a page's UNCONDITIONAL rule on an `.ak-*` element beats
   this kit's MOBILE rule for the same property at every width, not just on
   desktop. If a page needs to override a kit component, write the override
   inside the same @media the kit used, or give the element a page class of
   its own. Increase Leads never hits this; a page that restyles a kit
   component's mobile layout will.

   Builds on the already-global primitives, which are NOT repeated here:
   .ui-panel, .ui-head/.ui-title/.ui-meta/.ui-eyebrow/.ui-time/.ui-btn,
   the .st status glyphs, .seq-armed [data-at], .mini-steps.is-rail,
   .demo-chip, the .ask pattern, .sys-feed/.sys-row/.sys-live-ring, .still.

   GOVERNING RULES, not re-decided here: copper on perimeters, strokes,
   links, focus rings, active connectors and step markers only, never a
   fill, glow, shadow, dot or text colour; status is a ring, an arc or a
   check; motion bands 140/260/420/560/900ms on var(--ease); transform and
   opacity only, except SVG connector dash offsets (motion spec 4); no drop
   shadows, no hover lift; interface text is Familjen Grotesk, never
   Playfair; interface meta text uses --meta-ui.

   TWO SANCTIONED DEPARTURES from the motion spec's band table, both
   carried over from the shipped Increase Leads demo rather than invented
   here, and both allowed because the band table paces a machine and these
   pace a reader:
     - a transcript advances on reading time, not on a band: roughly
       1250ms plus 34ms per character, capped at 3800ms, and 1600ms for a
       system line. A fixed 900ms step makes a conversation unreadable.
     - a carousel of example records steps on the 2400ms HOLD band rather
       than a step band, because each record has to be read before the
       next replaces it.
   Anything else uses the table. Do not add a third.

   ONE DEGENERATE CASE in the sequence vocabulary: a row whose data-live
   equals its data-done can never be `is-live`, so it appears already
   checked rather than spinning first. That is a legitimate way to say "this
   happened at the same moment as the step before it"; it is not a typo.

   One deliberate departure from the motion spec, carried over from the
   homepage map (.map-item.is-quiet): a "quieted" node puts opacity 0.4 on
   the RING and a receding border only. Labels drop to --text-dim instead,
   because opacity 0.4 on text measures under 4.5:1.

   ────────────────────────────────────────────────────────────────────
   COMPONENTS. What each is for, its markup shape, its ARIA contract and
   its mobile behaviour. A worked example follows.
   ────────────────────────────────────────────────────────────────────

   .ak-sec / .ak-intro  a page section and its label, headline and sub.
     Shape: <section class="section ak-sec"> with an optional
       <div class="ak-intro"><div class="section-label"><h2
       class="section-headline"><p class="section-sub">.
     Reveal: register the section id in the page's reveal script; the
       intro slides in from the left, gated :not(.is-in) (Brain 9.5 #1).
       .ak-sec--panel repoints the ground to --panel.
     Mobile: the reveal travel shortens at 720px.

   .ak-stage  the stage spine. A numbered horizontal stepper that is also
     the tablist for one panel.
     Shape: <div class="ak-stage" role="tablist" aria-label="...">
       <button role="tab" class="ak-stage-tab" id="..." aria-controls="<the
       panel id>" aria-selected="..." tabindex="0|-1"><span
       class="ak-stage-num"><span class="ak-stage-name">.
     ARIA: exactly one tab has aria-selected="true" and tabindex="0", the
       rest "false" and -1. Every tab points at the SAME panel id, and the
       panel's aria-labelledby is retargeted to the selected tab. Arrows,
       Home and End move selection (AstroKit.tablist). .is-past marks a
       completed step and is presentation only.
       The panel itself needs tabindex="0" whenever its content is text
       rather than controls, or a keyboard visitor can select a stage and
       never reach what it revealed. Both .ak-stage and .ak-tabs panels
       take it.
       If the spine autoplays, pause it on focusin as well as on the arrow
       keys: re-rendering moves the roving tabindex, and a visitor sitting
       on the spine would have the selection change under them.
     Mobile: at 760px the spine becomes a horizontally scrolling snap
       strip that scrolls inside itself, never the page; tabs go to 50px.

   .ak-split  the signature two-pane view: the raw input on the left, what
     Astro made of it on the right, both advancing on the same beat.
     Shape: <div class="ak-split"><div class="ak-convo">...</div><div
       class="ak-state">...</div></div>, each opening with an .ak-pane-head.
     Mobile: at 760px it stacks, the divider becomes a top border, and
       .ak-msg.is-earlier collapses to an "n earlier messages" note so the
       record sits under the message that changed it.

   .ak-convo / .ak-msgs / .ak-msg  a conversation transcript, rendered on
     the light chat ground (#F3F1EE) as .still--light is, so every
     simulated consumer messaging surface on the site reads as one.
     Shape: <ol class="ak-msgs"><li class="ak-msg is-in|is-out|is-sys">
       <span class="ak-msg-who">...</span>text</li>.
     .is-compact drops the 400px minimum height. .is-entering runs the
     420ms entrance, on the newest message only.

   .ak-record  the structured record: a two-column dl of captured fields.
     Shape: <dl class="ak-record"><div data-f="name"><dt>Name</dt><dd>...
       </dd></div>...; .is-wide spans both columns.
     States: .is-empty shows an .ak-empty dashed placeholder and must also
       carry an .sr-only "Not captured yet"; .is-fresh marks the field
       captured in the current stage with a copper leading edge.
     .ak-recgrid is the compact variant for a hero panel: a bordered
       two-column grid with the same dt and dd typography.
     .ak-badge is the status pill for the pane head. .ak-outcome is the
       closing statement, copper leading edge when settled, neutral and
       --text-dim while .is-pending.

   .ak-scenarios / .ak-seg / .ak-toggles  the scenario and configuration
     controls. .ak-toggles stacks several labelled .ak-toggle-row controls.
     Shape: <div class="ak-scenarios" role="group" aria-label="Scenario">
       <span class="ak-scenarios-label" aria-hidden="true">Scenario</span>
       <div class="ak-seg"><button class="ak-seg-btn" aria-pressed="true"
       aria-controls="<the id this changes>" data-v="...">...</button>...
     Use .ak-toggle-row with .ak-toggle-k for a labelled inline control.
     ARIA: aria-pressed carries the state and aria-controls names the
       region that actually changes. Selected is a copper perimeter plus a
       neutral 5% wash, never a copper fill.
     Mobile: the group wraps before anything shrinks; at 760px buttons go
       to a 44px minimum height.

   .ak-diagram  the node-and-connector system diagram. DOM nodes in
     columns, SVG connectors measured from their real positions and drawn
     by AstroKit.diagram, so the geometry survives reflow and font loading.
     Shape: <div class="ak-diagram"><svg class="ak-diagram-lines"
       aria-hidden="true"></svg><div class="ak-diagram-col">...<span
       class="ak-node" data-en="key"><span class="ak-ring"></span>Label
       </span>...</div>...</div>, wrapped in a role="img" carrying a
       written aria-label for the whole diagram, because the SVG has no
       text of its own.
     States: .is-lit on a node or an .ak-edge-flow path; .is-quiet for a
       node off the active path. .ak-core with .ak-core-ring is the central
       Astro node.
     Motion: connectors draw by stroke-dashoffset with pathLength="1" over
       560ms. Never vector-effect on a dash-animated stroke (Brain 9.5 #9).
     Mobile: at 900px the columns stack and the connectors re-measure.

   .ak-node-btn / .ak-rail-end  a diagram node, or a rail node, that is
     also a real <button>, keeping the node's look. Added 21 Sept 2026 for
     Work (its hero canvas and its 04 workflow) from Reduce Admin, which had
     both page-scoped. Full contract in the block at the END of this kit.

   .ak-rails / .ak-track / .ak-rail  the before-and-after comparison: two
     tracks of the same steps, one degraded and one carried through.
     Shape: <div class="ak-rails"><div class="ak-track is-degraded"
       role="img" aria-label="..."><div class="ak-track-head">...<span
       class="ak-track-end is-cold">...</span></div><ol class="ak-rail"><li
       class="ak-rail-node is-fail" data-on="2" data-link="3">...</ol></div>
     data-on marks the step reached, data-link the connector drawn.
     .is-degraded dashes the connectors and steps the ring opacity down.
     Mobile: at 720px each rail turns vertical, same nodes, same order.

   .ak-timeline  the timed state machine: timestamped events with a drawn
     connector between them.
     Shape: <ol class="ak-timeline"><li data-live="1" data-done="2" data-st>
       <span class="ak-timeline-t">09:14</span><span class="ak-timeline-e">
       ...</span></li>. data-st is where AstroKit.glyphs injects the arc
       and the check. .is-wait-row dashes the connector below a wait.

   .ak-route  the routing decision fan: one input, the business's rules,
     and the branches the work can take.
     Shape: <div class="ak-route"><div class="ak-route-in">...<dl
       class="ak-route-inputs">...</dl></div><div class="ak-route-rules">
       <span class="ak-core-ring"></span><span class="ak-route-rules-name">
       </span></div><ol class="ak-route-outs"><li class="is-active"
       data-route-out="0">...</ol></div>.
     Exactly one branch is .is-active; the rest take .is-quiet.
     .is-changing replays the 420ms settle on the input values.
     Mobile: at 860px it becomes one column, the rules box turns
       horizontal, and the fan's connectors are dropped rather than bent.

   .ak-tabs / .ak-tab / .ak-tabpanel  pill tabs over separate panels, for
     switching between whole views rather than stages.
     ARIA: role="tablist" on .ak-tabs; role="tab" with aria-controls on
       each .ak-tab; role="tabpanel" with aria-labelledby and tabindex="0"
       on each .ak-tabpanel, with hidden on the inactive ones.
     Mobile: at 420px the tabs become an equal three-column grid.

   .ak-seq  the sequence controls. .ak-pause is the play and pause button
     every looping component must carry, placed in the .ui-head or the
     .ak-pane-head. AstroKit.bindToggle keeps its label and aria-label in
     step and hides it under reduced motion, where nothing loops.

   .ak-ring / .ak-core-ring / .ak-checks  the status set. A ring is a
     perimeter, never a filled dot; the global .st supplies the rotating
     arc and the check. .ak-checks is the labelled completion list, each
     row data-live, data-done and data-st, with an .ak-check-meta
     qualifier such as "Where configured".

   .ak-caption  the four-column explanation strip under a demo: what
     happens, what Astro does, what was captured, what is next.
     Live region contract: ship it as aria-live="off" with
     aria-atomic="true", and have the page switch it to "polite" the first
     time the VISITOR changes something. All four values describe one
     state, so atomic is right, but an autoplaying loop that announces them
     every few seconds is noise rather than help. Announce what the visitor
     asked for, not what the page did on its own.
     Mobile: two columns at 1000px, one at 760px.

   .ak-subpanel / .ak-pane-head / .ak-note / .ak-h3 / .ak-flow / .ak-arrow /
   .ak-link / .ak-empty  the small shared pieces: an inset panel on
     --panel, a panel's header row, the 11px "Example" or "Illustrative
     workflow" note every simulated interface must carry, the Playfair
     sub-headline inside a panel, the inline step strip, the connector
     between two stacked panels, the copper text link, and the dashed
     placeholder for a field not captured yet.

   ────────────────────────────────────────────────────────────────────
   WORKED EXAMPLE. A stage spine driving a split panel, as increase-leads
   uses it. The markup is the complete default state, so the section reads
   correctly before the script runs.

     <div class="ui-panel" data-demo>
       <div class="ak-bar">
         <div class="ak-bar-id"><span class="ui-title">Example
           conversation</span><span class="demo-chip">Illustrative
           workflow</span></div>
         <button type="button" class="ui-btn ak-pause" data-demo-toggle
           aria-label="Play the example">Play</button>
       </div>
       <div class="ak-stage" role="tablist" aria-label="Stages">
         <button type="button" role="tab" class="ak-stage-tab" id="s-1"
           aria-controls="p" aria-selected="true" tabindex="0">
           <span class="ak-stage-num">1</span>
           <span class="ak-stage-name">Enquiry</span></button>
       </div>
       <div role="tabpanel" id="p" aria-labelledby="s-1">
         <div class="ak-split">
           <div class="ak-convo"><div class="ak-pane-head"></div>
             <ol class="ak-msgs" data-msgs></ol></div>
           <div class="ak-state"><div class="ak-pane-head"></div>
             <dl class="ak-record" data-fields></dl>
             <p class="ak-outcome" data-outcome></p></div>
         </div>
         <div class="ak-caption" aria-live="polite"></div>
       </div>
       <p class="ak-note">Example conversation. Illustrative workflow.</p>
     </div>

     var tabs = AstroKit.tablist({
       tabs: AstroKit.$$('[role="tab"]', root),
       panel: document.getElementById('p'),
       onSelect: function (i) { jumpToStage(i + 1); }
     });
     var player = AstroKit.player({ max: 8, loop: false,
       render: renderStep, stepMs: function () { return 900; } });
     AstroKit.bindToggle(root.querySelector('[data-demo-toggle]'), player,
       'the example conversation');
     AstroKit.watch(root, function (v) { player.setView(v); }, 0.3);

   ────────────────────────────────────────────────────────────────────
   SHARED PROCESS AND ASK (19 Sept 2026). Two things Pricing and About both
   needed went into the kit rather than a page, because the two pages must
   say the same thing the same way:
     - AstroKit.process(root) and the .ak-stagerail* block: the Discover,
       Build, Launch, Improve rail. Its WORDING is one block of markup that
       pricing.html and about.html carry byte for byte (diffed at the end of
       the About pass); the kit only wires its tabs and panels. If the
       wording changes, change it in both pages in the same edit.
     - AstroKit.runOnce(root, stepMs) and .ak-statement: a comparison that plays
       once and stays, and the display-type line set under it (Pricing 02,
       About 02).
     - AstroKit.ask(root, lead) and .ak-ask-sub: the selectable-choice Ask
       Astro CTA and its supporting line. reduce-admin.html and
       increase-leads.html still carry their own copies of the same logic in
       astro-admin.js and astro-leads.js (untouched, so those pages could not
       regress); they are the next candidates to move onto ask().

   STATE OF THE UNPROVEN FACTORIES. store(initial) is exercised by Reduce
   Admin (the queue drives the engine) and Pricing (the scope builder).
   inspector(opts) is still run by no page: Work 04 was its named user and
   work.html has not been rebuilt (19 Sept). If Work turns out not to need
   it, delete it rather than leaving it unused. complete(root) is a one-line
   convenience over seq(); every page so far has rendered its own
   reduced-motion state instead.
   ────────────────────────────────────────────────────────────────────
   ══════════════════════════════════════════════════════════════════════ */

.ak-page .ak-intro { max-width: 780px; margin-bottom: 40px; }
.ak-page .ak-intro .section-sub { max-width: 560px; }
.ak-page .ak-sec--panel { background: var(--panel); }
.ak-page .ak-note {
    margin: 0;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 11px; font-weight: 500; letter-spacing: 0.03em; line-height: 1.5;
    color: var(--meta-ui);
  }
.ak-page .ak-ring {
    position: relative; z-index: 1; display: block; flex: none;
    width: 11px; height: 11px; border-radius: 50%;
    border: 1px solid var(--hairline-hover); background: var(--card);
    transition: border-color 260ms var(--ease), opacity 260ms var(--ease);
  }
.ak-page .ak-empty {
    position: absolute; left: 0; top: 9px; display: block;
    width: 44px; height: 0; border-top: 1px dashed var(--hairline-hover);
    transition: opacity 260ms var(--ease);
  }
.ak-page .ak-pause { min-width: 64px; }
.ak-page .ak-seg { display: flex; flex-wrap: wrap; gap: 6px; }
.ak-page .ak-seg-btn {
    display: inline-flex; align-items: center; justify-content: center;
    min-height: 36px; padding: 7px 14px;
    background: transparent; color: var(--text-dim);
    border: 1px solid var(--hairline-hover); border-radius: var(--radius-pill);
    font-family: 'Familjen Grotesk', 'Inter', sans-serif; font-size: 13px; font-weight: 500; line-height: 1.2;
    cursor: pointer; touch-action: manipulation;
    transition: color 140ms var(--ease), border-color 140ms var(--ease), background 140ms var(--ease);
  }
.ak-page .ak-seg-btn:hover { color: var(--text); border-color: var(--tag-border); }
.ak-page .ak-seg-btn[aria-pressed="true"] { color: var(--text); border-color: var(--blue-border); background: rgba(237,233,227,0.05); }
.ak-page .ak-seg-btn:focus-visible,
.ak-page .ak-stage-tab:focus-visible,
.ak-page .ak-tab:focus-visible,
.ak-page .ak-link:focus-visible,
.ak-page .ak-hero .hero-path:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
.ak-page .ak-tabpanel[hidden] { display: none !important; }
@keyframes akIn { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
@keyframes akFresh { from { opacity: 0.25; } to { opacity: 1; } }
.ak-page .sys-detail { color: var(--meta-ui); }
.ak-page .still { box-shadow: none; max-width: 460px; }
.ak-page .still-who,
.ak-page .still-note { color: var(--meta-ui); }
.ak-page .still--light .still-note,
.ak-page .still--light .still-time,
.ak-page .still--light .chat-bubble-time,
.ak-page .still--light .chat-mock-status-bar { color: rgba(10,10,10,0.64); }
.ak-page .still--light .still-out-val { color: rgba(10,10,10,0.7); }
.js-reveal .ak-page .ak-sec:not(.is-in) .section-label,
.js-reveal .ak-page .ak-sec:not(.is-in) .section-sub { opacity: 0; transform: translateX(-90px); }
.js-reveal .ak-page .ak-sec:not(.is-in) .section-headline { opacity: 0; transform: translateX(-120px); }
@media (max-width: 720px) {
  .js-reveal .ak-page .ak-sec:not(.is-in) .section-label,
.js-reveal .ak-page .ak-sec:not(.is-in) .section-sub { transform: translateX(-48px); }
  .js-reveal .ak-page .ak-sec:not(.is-in) .section-headline { transform: translateX(-60px); }
}  /* ── hero ── */
  /* Every product page leads with the same shape: copy on the left, a live
     interface on the right, no photograph, and a hairline foot so the eye
     knows where the hero ends on a ground whose tone never changes. The
     page supplies its own top padding for nav clearance. */
.ak-page .ak-hero { border-bottom: 1px solid var(--hairline); }
.ak-page .ak-hero-grid {
    display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 460px);
    gap: 56px; align-items: center;
  }
.ak-page .ak-hero .section-sub { max-width: 520px; margin-top: 16px; }
.ak-page .ak-hero-paths { display: flex; flex-wrap: wrap; gap: 4px 26px; margin-top: 24px; }
.ak-page .ak-hero .hero-path { min-height: 44px; color: var(--text); }
.ak-page .ak-hero .hero-path:hover { text-decoration: underline; text-underline-offset: 4px; }
@media (max-width: 960px) {
  .ak-page .ak-hero-grid { grid-template-columns: minmax(0, 1fr); gap: 36px; }
}

  /* ── selectable rows: a list where choosing one drives a section ──
     Shape: <ul class="ak-rows"><li><button class="ak-row" data-<key>="..."
       aria-pressed="true|false" aria-controls="<the id this changes>">
       <span class="ak-row-src">Category</span>
       <span class="ak-row-title">What it is</span>
       <span class="ak-row-meta">Who and what it belongs to</span></button>.
     Selected is a copper LEFT BORDER plus a neutral wash. The border sits
       transparent on every row so selecting one shifts nothing, and it is a
       border rather than an inset shadow because copper is never a shadow.
     ARIA: aria-pressed carries the state; aria-controls names what changes.
     Keyboard: wire it with AstroKit.tabKeys so arrows, Home and End move
       between rows, the same idiom as every other selection list here.
     Mobile: at 760px the row stacks to one column and takes the 44px floor.
   */
  .ak-page .ak-rows { list-style: none; margin: 0; padding: 0; }
  .ak-page .ak-row {
    display: grid; grid-template-columns: 132px minmax(0, 1fr) auto; align-items: baseline; column-gap: 18px;
    width: 100%; min-height: 56px; padding: 14px 20px 14px 18px;
    background: transparent; border: 0; border-top: 1px solid var(--hairline);
    border-left: 2px solid transparent;
    text-align: left; cursor: pointer; touch-action: manipulation;
    transition: background 140ms var(--ease);
  }
  .ak-page .ak-row:hover { background: rgba(237,233,227,0.03); }
  .ak-page .ak-row:focus-visible { outline: 2px solid var(--blue); outline-offset: -2px; }
  /* selected: a copper leading edge, the step-marker precedent, never a fill */
  .ak-page .ak-row[aria-pressed="true"] { background: rgba(237,233,227,0.05); border-left-color: var(--blue); }
  .ak-page .ak-row-src {
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 10.5px; font-weight: 600; letter-spacing: 0.8px; text-transform: uppercase; color: var(--meta-ui);
  }
  .ak-page .ak-row[aria-pressed="true"] .ak-row-src { color: var(--text); }
  .ak-page .ak-row-title {
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 14px; font-weight: 500; line-height: 1.4; color: var(--text-dim);
  }
  .ak-page .ak-row[aria-pressed="true"] .ak-row-title { color: var(--text); font-weight: 600; }
  .ak-page .ak-row-meta {
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 11px; font-weight: 500; letter-spacing: 0.04em; color: var(--meta-ui); white-space: nowrap;
  }
  @media (max-width: 760px) {
    .ak-page .ak-row { grid-template-columns: minmax(0, 1fr); row-gap: 4px; min-height: 44px; padding: 12px 16px 12px 14px; }
    .ak-page .ak-row-meta { white-space: normal; }
  }


  /* ── stage rail: a vertical list of stages driving one panel ──
     The counterpart to .ak-stage. Where .ak-stage is a numbered horizontal
     spine walking ONE item through its stages with that item's real content
     at each, this is a vertical list for the RULES view: what governs a
     stage, and where work can leave the automatic path. A page that shows
     both must make them structurally different, or it has drawn the same
     diagram twice.
     Shape: <div class="ak-stagerail-grid">
       <div class="ak-stagerail-list" role="tablist" aria-label="..."> of
       <button role="tab" class="ak-stagerail-item"><span class="ak-ring">
       <span class="ak-stagerail-name">, then
       <div class="ak-stagerail-panel" role="tabpanel" aria-labelledby="..."
       tabindex="0"> holding an .ak-h3, an .ak-stagerail-lead and an
       <ol class="ak-branches"> of <li><span class="ak-ring">
       <span class="ak-branch-k"><span class="ak-branch-v">.
     ARIA: do NOT set aria-orientation. The list is vertical on desktop and
       a horizontal strip below 860px, so neither value is true at both, and
       AstroKit.tabKeys accepts either axis.
     A branch takes .is-active only when something has actually selected it.
       In a rules view, where no particular task is running, nothing is
       active: marking the first branch would read as "the answer is the
       first one".
     Mobile: at 860px the list becomes a scroll-snap strip that scrolls
       inside itself, never the page. */
    .ak-page .ak-stagerail-grid { display: grid; grid-template-columns: minmax(0, 208px) minmax(0, 1fr); }
  .ak-page .ak-stagerail-list {
    display: flex; flex-direction: column; gap: 2px;
    padding: 20px 14px; border-right: 1px solid var(--hairline); background: var(--panel);
  }
  .ak-page .ak-stagerail-item {
    position: relative;
    display: grid; grid-template-columns: 11px minmax(0, 1fr); align-items: center; column-gap: 12px;
    min-height: 46px; padding: 10px 12px;
    background: transparent; border: 1px solid transparent; border-radius: 8px;
    text-align: left; cursor: pointer; touch-action: manipulation;
    transition: color 140ms var(--ease), border-color 140ms var(--ease), background 140ms var(--ease);
  }
  .ak-page .ak-stagerail-name {
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 13.5px; font-weight: 500; line-height: 1.3; color: var(--text-dim);
    transition: color 140ms var(--ease);
  }
  .ak-page .ak-stagerail-item:hover .ak-stagerail-name { color: var(--text); }
  .ak-page .ak-stagerail-item[aria-selected="true"] { border-color: var(--blue-border); background: rgba(237,233,227,0.05); }
  .ak-page .ak-stagerail-item[aria-selected="true"] .ak-stagerail-name { color: var(--text); font-weight: 600; }
  .ak-page .ak-stagerail-item[aria-selected="true"] .ak-ring { border-color: var(--blue); }
  .ak-page .ak-stagerail-item:focus-visible { outline: 2px solid var(--blue); outline-offset: -2px; }
  /* the connector down the stage list, drawn as a stroke like every other.
     Rebuilt 30 Sept 2026 (final refinement pass): it used to be one short
     tick across the boundary between two items, which ran through the
     border of the selected card. Now every item draws its own two halves,
     ::before from the gap above down to its ring and ::after from its ring
     to the gap below, so each half depends only on its own item's height
     (items of two lines are fine). The selected item draws neither, and its
     neighbours pull their halves back from it, so the line stops above the
     selected card, leaves it uninterrupted, and resumes below it.
     --rail-x is the line's left edge; --rail-gap is half the list's 2px
     gap plus the 1px border, since offsets start inside the border. */
  .ak-page .ak-stagerail-item { --rail-x: 17.25px; --rail-gap: 2px; --rail-clear: 5px; }
  .ak-page .ak-stagerail-item:not(:first-child)::before,
  .ak-page .ak-stagerail-item:not(:last-child)::after {
    content: ''; position: absolute; left: var(--rail-x); width: 0;
    border-left: 1.5px solid var(--hairline); pointer-events: none;
  }
  .ak-page .ak-stagerail-item:not(:first-child)::before { top: calc(0px - var(--rail-gap)); bottom: calc(50% + 9.5px); }
  .ak-page .ak-stagerail-item:not(:last-child)::after { top: calc(50% + 9.5px); bottom: calc(0px - var(--rail-gap)); }
  .ak-page .ak-stagerail-item[aria-selected="true"]::before,
  .ak-page .ak-stagerail-item[aria-selected="true"]::after { display: none; }
  .ak-page .ak-stagerail-item[aria-selected="true"] + .ak-stagerail-item::before { top: var(--rail-clear); }
  .ak-page .ak-stagerail-item:has(+ .ak-stagerail-item[aria-selected="true"])::after { bottom: var(--rail-clear); }
  .ak-page .ak-stagerail-panel { padding: 26px 28px 28px; }
  .ak-page .ak-stagerail-panel:focus-visible { outline: 2px solid var(--blue); outline-offset: -2px; }
  .ak-page .ak-stagerail-lead {
    margin: 0 0 22px; max-width: 640px;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 15px; font-weight: 500; line-height: 1.6; color: var(--text-dim);
  }
  .ak-page .ak-branches { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
  .ak-page .ak-branches > li {
    display: grid; grid-template-columns: 11px minmax(0, 1fr); align-items: start; column-gap: 14px; row-gap: 3px;
    padding: 14px 16px;
    border: 1px solid var(--hairline); border-radius: 8px;
    transition: border-color 260ms var(--ease);
  }
  .ak-page .ak-branches > li .ak-ring { margin-top: 3px; }
  .ak-page .ak-branches > li.is-active { border-color: var(--blue-border); }
  .ak-page .ak-branches > li.is-active .ak-ring { border-color: var(--blue); }
  .ak-page .ak-branch-k {
    grid-column: 2;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 14px; font-weight: 600; line-height: 1.35; color: var(--text);
  }
  .ak-page .ak-branch-v {
    grid-column: 2;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 13.5px; font-weight: 500; line-height: 1.5; color: var(--text-dim);
  }
  @media (max-width: 860px) {
    .ak-page .ak-stagerail-grid { grid-template-columns: minmax(0, 1fr); }
    /* the stage list turns into a scrolling strip, inside itself, never the page */
    .ak-page .ak-stagerail-list {
      flex-direction: row; gap: 6px; padding: 12px;
      border-right: 0; border-bottom: 1px solid var(--hairline);
      overflow-x: auto; overscroll-behavior-x: contain; scroll-snap-type: x mandatory; scrollbar-width: none;
    }
    .ak-page .ak-stagerail-list::-webkit-scrollbar { display: none; }
    .ak-page .ak-stagerail-item { flex: none; min-height: 44px; scroll-snap-align: start; }
    .ak-page .ak-stagerail-item:not(:first-child)::before,
    .ak-page .ak-stagerail-item:not(:last-child)::after { display: none; }
    .ak-page .ak-stagerail-panel { padding: 22px 18px 24px; }
  }

  /* ── record, compact grid variant ── */
.ak-page .ak-recgrid {
    display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px 16px;
    margin: 0 0 8px; padding: 12px 14px;
    border: 1px solid var(--hairline); border-radius: 8px;
  }
.ak-page .ak-recgrid > .is-wide { grid-column: 1 / -1; }
.ak-page .ak-recgrid dt,
.ak-page .ak-record dt,
.ak-page .ak-route-inputs dt {
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 10px; font-weight: 600; letter-spacing: 0.6px; line-height: 1.3;
    text-transform: uppercase; color: var(--meta-ui);
  }
.ak-page .ak-recgrid dd {
    position: relative; min-height: 18px; margin: 3px 0 0;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 13px; font-weight: 500; line-height: 18px; color: var(--text);
  }
.ak-page .sys-row.is-live .sys-label { color: var(--text); }
@media (max-width: 420px) {
  .ak-page .ak-recgrid { grid-template-columns: minmax(0, 1fr); }
}
.ak-page .ak-rails { display: grid; gap: 30px; padding: 26px 28px 20px; }
.ak-page .ak-track-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 16px; }
.ak-page .ak-track-end {
    display: inline-flex; align-items: center; gap: 8px;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 11px; font-weight: 600; letter-spacing: 0.8px; text-transform: uppercase;
  }
.ak-page .ak-track-end.is-cold { color: var(--text-dim); }
.ak-page .ak-track-end.is-done { color: var(--text); }
.ak-page .ak-track-end-ring { width: 11px; height: 11px; border-radius: 50%; border: 1px dashed var(--hairline-hover); }
.ak-page .ak-track-end-check { width: 12px; height: 12px; fill: none; stroke: var(--text); stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.ak-page .ak-rail { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); }
.ak-page .ak-rail-node { position: relative; display: flex; flex-direction: column; align-items: flex-start; gap: 10px; padding-right: 12px; }
.ak-page .ak-rail-label {
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 13px; font-weight: 500; line-height: 1.35; color: var(--text-dim);
    transition: color 260ms var(--ease);
  }
.ak-page .ak-rail-node:not(:last-child)::before,
.ak-page .ak-rail-node:not(:last-child)::after {
    content: ''; position: absolute; left: 17px; right: 6px; top: 4.75px; height: 0;
    border-top: 1.5px solid var(--hairline);
  }
.ak-page .ak-rail-node:not(:last-child)::after {
    border-top-color: var(--blue-border);
    transform: scaleX(0); transform-origin: left;
    transition: transform 560ms var(--ease);
  }
.ak-page .ak-rail-node.is-linked::after { transform: scaleX(1); }
.ak-page .ak-rail-node.is-on .ak-ring { border-color: var(--blue-border); }
.ak-page .ak-rail-node.is-on .ak-rail-label { color: var(--text); }
.ak-page .is-degraded .ak-rail-node:not(:last-child)::after {
    border-top-style: dashed; border-top-color: var(--hairline-hover);
  }
.ak-page .is-degraded .ak-rail-node.is-fail.is-on .ak-ring { border-color: var(--hairline-hover); border-style: dashed; }
.ak-page .is-degraded .ak-rail-node.is-fail.is-on .ak-rail-label { color: var(--text-dim); }
.ak-page .is-degraded .ak-rail-node.is-on:nth-child(2) .ak-ring { opacity: 0.85; }
.ak-page .is-degraded .ak-rail-node.is-on:nth-child(3) .ak-ring { opacity: 0.7; }
.ak-page .is-degraded .ak-rail-node.is-on:nth-child(4) .ak-ring { opacity: 0.58; }
.ak-page .is-degraded .ak-rail-node.is-on:nth-child(5) .ak-ring { opacity: 0.48; }
.ak-page .is-degraded .ak-rail-node.is-on:nth-child(6) .ak-ring { opacity: 0.4; }
@media (max-width: 720px) {
  .ak-page .ak-rails { padding: 20px 18px 16px; gap: 26px; }
  .ak-page .ak-rail { grid-template-columns: minmax(0, 1fr); }
  .ak-page .ak-rail-node { flex-direction: row; align-items: center; gap: 12px; padding: 0 0 16px; }
  .ak-page .ak-rail-node:last-child { padding-bottom: 0; }
  .ak-page .ak-rail-node:not(:last-child)::before,
.ak-page .ak-rail-node:not(:last-child)::after {
      left: 4.75px; right: auto; top: calc(50% - 2px); width: 0; height: calc(100% - 4px);
      border-top: 0; border-left: 1.5px solid var(--hairline);
    }
  .ak-page .ak-rail-node:not(:last-child)::after { border-left-color: var(--blue-border); }
  .ak-page .ak-rail-node:not(:last-child)::after { transform: scaleY(0); transform-origin: top; }
  .ak-page .ak-rail-node.is-linked::after { transform: scaleY(1); }
  .ak-page .is-degraded .ak-rail-node:not(:last-child)::after { border-left-style: dashed; border-left-color: var(--hairline-hover); }
}
.ak-page .ak-diagram {
    position: relative;
    display: grid;
    grid-template-columns: minmax(0, 1.35fr) minmax(0, 0.65fr) minmax(0, 0.85fr) minmax(0, 0.8fr);
    column-gap: 56px; align-items: center;
    padding: 36px 32px 40px;
  }
.ak-page .ak-diagram-lines { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none; }
.ak-page .ak-edge { fill: none; stroke: var(--hairline); stroke-width: 1.5; }
.ak-page .ak-edge-flow {
    fill: none; stroke: var(--blue-border); stroke-width: 1.5;
    stroke-dasharray: 1 1; stroke-dashoffset: 1;
    transition: stroke-dashoffset 560ms var(--ease);
  }
.ak-page .ak-edge-flow.is-lit { stroke-dashoffset: 0; }
.ak-page .ak-diagram-col { position: relative; z-index: 1; display: flex; flex-direction: column; gap: 16px; min-width: 0; }
.ak-page .ak-diagram-col.is-core { align-items: center; }
.ak-page .ak-diagram-col.is-caps { align-items: center; gap: 28px; }
.ak-page .ak-diagram-col.is-outs { align-items: flex-start; gap: 22px; }
  /* a named group of nodes inside a diagram. This is the box
     diagram()'s boxSelector measures from, so a connector leaves the
     group's edge rather than from under one of its nodes. */
.ak-page .ak-group {
    padding: 12px 14px 14px;
    background: var(--card); border: 1px solid var(--hairline); border-radius: var(--radius-card);
    transition: border-color 260ms var(--ease);
  }
.ak-page .ak-group.is-lit { border-color: var(--blue-border); }
.ak-page .ak-group.is-quiet { border-color: rgba(237,233,227,0.05); }
.ak-page .ak-group-name { display: block; font-family: 'Familjen Grotesk', 'Inter', sans-serif; font-size: 13.5px; font-weight: 600; line-height: 1.3; color: var(--text); }
.ak-page .ak-group-tag { display: block; margin-top: 3px; font-family: 'Familjen Grotesk', 'Inter', sans-serif; font-size: 10px; font-weight: 600; letter-spacing: 0.6px; text-transform: uppercase; color: var(--meta-ui); }
.ak-page .ak-group-nodes { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.ak-page .ak-node {
    display: inline-flex; align-items: center; gap: 9px;
    padding: 7px 12px;
    background: var(--card); border: 1px solid var(--hairline); border-radius: var(--radius-pill);
    font-family: 'Familjen Grotesk', 'Inter', sans-serif; font-size: 13px; font-weight: 500; line-height: 1.2;
    color: var(--text-dim); white-space: nowrap;
    transition: color 260ms var(--ease), border-color 260ms var(--ease);
  }
.ak-page .ak-node .ak-ring { width: 9px; height: 9px; }
.ak-page .ak-node.is-lit { color: var(--text); border-color: var(--hairline-hover); }
.ak-page .ak-node.is-lit .ak-ring { border-color: var(--blue); }
.ak-page .ak-node.is-quiet { border-color: rgba(237,233,227,0.05); }
.ak-page .ak-node.is-quiet .ak-ring { opacity: 0.4; }
.ak-page .ak-core {
    flex-direction: column; gap: 8px; padding: 16px 22px;
    border-radius: var(--radius-card);
    font-family: 'Astrohead', 'Inter', sans-serif; font-size: 14px; font-weight: 400;
    letter-spacing: 0.08em; text-transform: uppercase;
  }
.ak-page .ak-core-ring {
    position: relative; display: block; width: 26px; height: 26px; border-radius: 50%;
    border: 1px solid var(--hairline-hover);
    transition: border-color 260ms var(--ease);
  }
.ak-page .ak-core-ring::after { content: ''; position: absolute; inset: 7px; border-radius: 50%; border: 1px solid var(--hairline-hover); }
.ak-page .ak-core.is-lit { border-color: var(--blue-border); }
.ak-page .ak-core.is-lit .ak-core-ring { border-color: var(--blue-border); }
@media (max-width: 900px) {
  .ak-page .ak-diagram { grid-template-columns: minmax(0, 1fr); row-gap: 44px; justify-items: center; padding: 28px 16px 32px; }
  .ak-page .ak-diagram-col.is-inputs { flex-direction: row; align-items: stretch; justify-content: center; gap: 10px; width: 100%; }
  .ak-page .ak-diagram-col.is-inputs .ak-group { flex: 1 1 0; min-width: 0; max-width: 260px; }
  .ak-page .ak-group-nodes { flex-direction: column; align-items: flex-start; }
  .ak-page .ak-diagram-col.is-caps { align-items: center; }
  .ak-page .ak-diagram-col.is-outs { flex-direction: row; flex-wrap: wrap; justify-content: center; gap: 10px; }
}
@media (max-width: 380px) {
  .ak-page .ak-group { padding: 10px 10px 12px; }
  .ak-page .ak-group-name { font-size: 12.5px; }
  .ak-page .ak-node { padding: 7px 10px; font-size: 12.5px; }
}
.ak-page .ak-bar {
    display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 12px;
    padding: 12px 18px; border-bottom: 1px solid var(--hairline);
  }
.ak-page .ak-bar-id { display: flex; align-items: center; flex-wrap: wrap; gap: 8px 12px; }
.ak-page .ak-scenarios { display: flex; align-items: center; gap: 10px 14px; padding: 14px 18px; border-bottom: 1px solid var(--hairline); }
.ak-page .ak-scenarios-label,
.ak-page .ak-toggle-k {
    flex: none;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 10.5px; font-weight: 600; letter-spacing: 0.8px; text-transform: uppercase; color: var(--meta-ui);
  }
.ak-page .ak-stage {
    display: grid; grid-template-columns: repeat(6, minmax(0, 1fr));
    padding: 0 8px; border-bottom: 1px solid var(--hairline);
  }
.ak-page .ak-stage-tab {
    position: relative;
    display: flex; align-items: center; gap: 10px;
    min-height: 54px; padding: 10px;
    background: transparent; border: 0; border-radius: 8px;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif; font-size: 13px; font-weight: 500; text-align: left;
    color: var(--text-dim); cursor: pointer; touch-action: manipulation;
    transition: color 140ms var(--ease);
  }
.ak-page .ak-stage-tab:hover { color: var(--text); }
.ak-page .ak-stage-num {
    display: inline-flex; flex: none; align-items: center; justify-content: center;
    width: 22px; height: 22px; border-radius: 50%;
    border: 1px solid var(--hairline-hover);
    font-size: 11px; font-weight: 600; color: var(--meta-ui); font-variant-numeric: tabular-nums;
    transition: border-color 260ms var(--ease), color 260ms var(--ease);
  }
.ak-page .ak-stage-tab::after {
    content: ''; position: absolute; left: 10px; right: 10px; bottom: -1px; height: 0;
    border-top: 1.5px solid var(--blue-border);
    transform: scaleX(0); transform-origin: left;
    transition: transform 260ms var(--ease);
  }
.ak-page .ak-stage-tab.is-past .ak-stage-num { border-color: var(--blue-border); }
.ak-page .ak-stage-tab[aria-selected="true"] { color: var(--text); }
.ak-page .ak-stage-tab[aria-selected="true"] .ak-stage-num { border-color: var(--blue); color: var(--text); }
.ak-page .ak-stage-tab[aria-selected="true"]::after { transform: scaleX(1); }
.ak-page .ak-stage-tab:focus-visible { outline-offset: -3px; }
.ak-page .ak-split { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr); }
.ak-page .ak-convo { min-width: 0; padding: 18px 22px 20px; }
.ak-page .ak-state { min-width: 0; padding: 18px 22px 20px; background: var(--panel); border-left: 1px solid var(--hairline); }
.ak-page .ak-pane-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; min-height: 26px; margin-bottom: 12px; }
.ak-page .ak-msgs {
    list-style: none; margin: 0;
    display: flex; flex-direction: column; gap: 8px;
    min-height: 400px; padding: 14px;
    background: #F3F1EE; border-radius: 14px;
  }
.ak-page .ak-msgs.is-compact { min-height: 0; }
.ak-page .ak-msg {
    max-width: 86%; padding: 8px 12px; border-radius: 14px;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif; font-size: 13.5px; font-weight: 500; line-height: 1.45;
    color: #14150F;
  }
.ak-page .ak-msg.is-in { align-self: flex-start; background: #FFFFFF; border-bottom-left-radius: 4px; }
.ak-page .ak-msg.is-out { align-self: flex-end; background: #E4E0DA; border-bottom-right-radius: 4px; }
.ak-page .ak-msg-who {
    display: block; margin-bottom: 2px;
    font-size: 10px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase;
    color: rgba(10,10,10,0.64);
  }
.ak-page .ak-msg.is-sys {
    align-self: center; max-width: 100%; padding: 3px 0;
    font-size: 10.5px; font-weight: 600; letter-spacing: 0.5px; text-transform: uppercase;
    color: rgba(10,10,10,0.64);
  }
.ak-page .ak-msg.is-earlier-note { display: none; }
.ak-page .ak-msg.is-entering { animation: akIn 420ms var(--ease) both; }
.ak-page .ak-badge {
    display: inline-flex; align-items: center; min-height: 24px; padding: 3px 11px;
    border: 1px solid var(--blue-border); border-radius: var(--radius-pill);
    font-family: 'Familjen Grotesk', 'Inter', sans-serif; font-size: 11px; font-weight: 600; letter-spacing: 0.6px;
    text-transform: uppercase; color: var(--text); white-space: nowrap;
  }
.ak-page .ak-record { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 18px; margin: 0; }
.ak-page .ak-record > div { position: relative; min-width: 0; padding: 8px 0 9px; border-top: 1px solid var(--hairline); }
.ak-page .ak-record > .is-wide { grid-column: 1 / -1; }
.ak-page .ak-record dd {
    position: relative; min-height: 18px; margin: 3px 0 0;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif; font-size: 13px; font-weight: 500; line-height: 18px; color: var(--text);
  }
.ak-page .ak-record > .is-fresh dd { animation: akFresh 420ms var(--ease) both; }
.ak-page .ak-record > .is-fresh::before {
    content: ''; position: absolute; left: -9px; top: 10px; bottom: 10px; width: 0;
    border-left: 1.5px solid var(--blue-border);
  }
.ak-page .ak-outcome {
    margin: 14px 0 0; padding: 8px 0 8px 12px;
    border-left: 2px solid var(--blue);
    font-family: 'Familjen Grotesk', 'Inter', sans-serif; font-size: 13.5px; font-weight: 500; line-height: 1.45; color: var(--text);
  }
.ak-page .ak-outcome.is-pending { border-left-color: var(--hairline-hover); color: var(--text-dim); }
.ak-page .ak-caption {
    display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 14px 24px;
    padding: 16px 22px 18px; border-top: 1px solid var(--hairline);
  }
.ak-page .ak-cap-k {
    display: block; margin-bottom: 4px;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif; font-size: 10.5px; font-weight: 600; letter-spacing: 0.8px;
    text-transform: uppercase; color: var(--meta-ui);
  }
.ak-page .ak-cap-v { display: block; font-family: 'Familjen Grotesk', 'Inter', sans-serif; font-size: 13.5px; font-weight: 500; line-height: 1.45; color: var(--text); }
@media (max-width: 1000px) {
  .ak-page .ak-caption { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ak-page .ak-stage-tab { flex-direction: column; align-items: flex-start; gap: 6px; }
}
@media (max-width: 760px) {
  .ak-page .ak-scenarios { flex-direction: column; align-items: flex-start; }
  .ak-page .ak-seg-btn,
.ak-page .ak-pause,
.ak-page .ak-tab { min-height: 44px; }
  .ak-page .ak-stage {
      display: flex; gap: 2px; overflow-x: auto; overscroll-behavior-x: contain;
      scroll-snap-type: x mandatory; scrollbar-width: none; padding: 0 6px;
    }
  .ak-page .ak-stage::-webkit-scrollbar { display: none; }
  .ak-page .ak-stage-tab { flex: none; flex-direction: row; align-items: center; min-height: 50px; padding: 10px 12px; scroll-snap-align: start; }
  .ak-page .ak-split { grid-template-columns: minmax(0, 1fr); }
  .ak-page .ak-convo { padding: 16px 16px 12px; }
  .ak-page .ak-state { border-left: 0; border-top: 1px solid var(--hairline); padding: 16px; }
  .ak-page .ak-msgs { min-height: 0; }
  .ak-page .ak-msg.is-earlier { display: none; }
  .ak-page .ak-msg.is-earlier-note {
      display: block; align-self: center; padding: 2px 0;
      font-size: 10.5px; font-weight: 600; letter-spacing: 0.5px; text-transform: uppercase;
      color: rgba(10,10,10,0.64);
    }
  .ak-page .ak-caption { grid-template-columns: minmax(0, 1fr); padding: 14px 16px 16px; }
  .ak-page .ak-record > .is-fresh::before { left: -8px; }
}
.ak-page .ak-toggles { display: flex; flex-direction: column; gap: 12px; margin-top: 28px; }
/* an explanatory note directly under a control row is subordinate to it,
   not part of it (30 Sept 2026: Reduce Admin's rule note sat 0px under the
   rule buttons, in both states) */
.ak-page :is(.ak-toggles, .ak-seg, .ak-scenarios) + .ak-note { margin-top: 16px; }
.ak-page .ak-toggle-row { display: flex; align-items: center; flex-wrap: wrap; gap: 8px 14px; }
.ak-page .ak-toggle-k { width: 56px; }
.ak-page #chat .ak-toggle-row { margin-top: 26px; }
.ak-page .ak-flow { list-style: none; display: flex; flex-wrap: wrap; justify-content: center; gap: 8px 0; width: 100%; max-width: 460px; margin: 0; padding: 0; }
.ak-page .ak-flow > li {
    display: inline-flex; align-items: center;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif; font-size: 12px; font-weight: 600; letter-spacing: 0.02em; line-height: 1.3;
    color: var(--text);
    opacity: 0; transform: translateY(4px);
    transition: opacity 260ms var(--ease), transform 260ms var(--ease);
  }
.ak-page .ak-flow > li.is-done { opacity: 1; transform: none; }
.ak-page .ak-flow > li + li::before {
    content: ''; display: block; width: 16px; height: 0; margin: 0 8px;
    border-top: 1.5px solid var(--hairline-hover);
  }
.ak-page .still-line.is-entering { animation: akIn 420ms var(--ease) both; animation-delay: calc(var(--i, 0) * 60ms); }
.ak-page .ak-tabs { display: flex; flex-wrap: wrap; gap: 6px; padding: 10px 12px; border-bottom: 1px solid var(--hairline); }
.ak-page .ak-tab {
    min-height: 40px; padding: 8px 18px;
    background: transparent; color: var(--text-dim);
    border: 1px solid transparent; border-radius: var(--radius-pill);
    font-family: 'Familjen Grotesk', 'Inter', sans-serif; font-size: 14px; font-weight: 500;
    cursor: pointer; touch-action: manipulation;
    transition: color 140ms var(--ease), border-color 140ms var(--ease), background 140ms var(--ease);
  }
.ak-page .ak-tab:hover { color: var(--text); border-color: var(--hairline-hover); }
.ak-page .ak-tab[aria-selected="true"] { color: var(--text); border-color: var(--blue-border); background: rgba(237,233,227,0.05); }
.ak-page .ak-tabpanel { padding: 26px 24px 28px; }
.ak-page .ak-tabpanel:focus-visible { outline: 2px solid var(--blue); outline-offset: -2px; }
.ak-page .ak-h3 {
    margin: 0 0 22px;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: clamp(22px, 2.6vw, 30px); font-weight: 700; line-height: 1.15;
    letter-spacing: var(--tracking-display); color: var(--text);
  }
.ak-page .ak-h3 em { font-style: italic; }
.ak-page .ak-subpanel { min-width: 0; padding: 16px 18px 18px; background: var(--panel); border: 1px solid var(--hairline); border-radius: var(--radius-card); }
.ak-page .ak-subpanel .ak-pane-head { flex-wrap: wrap; row-gap: 4px; }
.ak-page .ak-timeline { list-style: none; margin: 0; padding: 0; }
.ak-page .ak-timeline > li {
    position: relative;
    display: grid; grid-template-columns: 14px 52px minmax(0, 1fr); align-items: center; column-gap: 12px;
    padding: 8px 0;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif; font-size: 13.5px; font-weight: 500; line-height: 1.4;
    color: var(--text-dim);
  }
.ak-page .ak-timeline > li.is-live,
.ak-page .ak-timeline > li.is-done { color: var(--text); }
.ak-page .ak-timeline-t { font-size: 11px; font-weight: 500; letter-spacing: 0.04em; color: var(--meta-ui); font-variant-numeric: tabular-nums; }
.ak-page .ak-timeline > li:not(:last-child)::after {
    content: ''; position: absolute; left: 6.25px; top: calc(50% + 9px); height: calc(100% - 18px); width: 0;
    border-left: 1.5px solid var(--hairline);
  }
.ak-page .ak-timeline > li.is-done:not(:last-child)::after { border-left-color: var(--blue-border); }
.ak-page .ak-timeline > li.is-wait-row.is-done::after { border-left-style: dashed; border-left-color: var(--hairline-hover); }
.ak-page .ak-resume {
    margin: 12px 0 0; padding-left: 26px;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif; font-size: 13.5px; font-weight: 600; color: var(--text);
  }
.ak-page .ak-route { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); gap: 0 40px; align-items: center; }
.ak-page .ak-route-in { min-width: 0; padding: 14px 18px 12px; background: var(--panel); border: 1px solid var(--hairline); border-radius: var(--radius-card); }
.ak-page .ak-route-lead { margin: 0 0 8px; font-family: 'Familjen Grotesk', 'Inter', sans-serif; font-size: 15px; font-weight: 600; line-height: 1.35; color: var(--text); }
.ak-page .ak-route-inputs { margin: 0; }
.ak-page .ak-route-inputs > div { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; padding: 7px 0; border-top: 1px solid var(--hairline); }
.ak-page .ak-route-inputs dd { margin: 0; text-align: right; font-family: 'Familjen Grotesk', 'Inter', sans-serif; font-size: 13px; font-weight: 500; color: var(--text); }
.ak-page .ak-route.is-changing .ak-route-lead,
.ak-page .ak-route.is-changing .ak-route-inputs dd { animation: akFresh 420ms var(--ease) both; }
.ak-page .ak-route-rules {
    position: relative; max-width: 132px;
    display: flex; flex-direction: column; align-items: center; gap: 8px;
    padding: 16px 14px; text-align: center;
    border: 1px solid var(--hairline-hover); border-radius: var(--radius-card);
  }
.ak-page .ak-route-rules::before,
.ak-page .ak-route-rules::after {
    content: ''; position: absolute; top: 50%; width: 40px; height: 0; border-top: 1.5px solid var(--hairline-hover);
  }
.ak-page .ak-route-rules::before { right: 100%; }
.ak-page .ak-route-rules::after { left: 100%; width: 20px; }
.ak-page .ak-route-rules-name { font-family: 'Familjen Grotesk', 'Inter', sans-serif; font-size: 13px; font-weight: 600; line-height: 1.3; color: var(--text); }
.ak-page .ak-route-outs { position: relative; list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.ak-page .ak-route-outs::before { content: ''; position: absolute; left: -20px; top: 22px; bottom: 22px; width: 0; border-left: 1.5px solid var(--hairline); }
.ak-page .ak-route-outs > li {
    position: relative;
    display: grid; grid-template-columns: 11px minmax(0, 1fr) auto; align-items: center; column-gap: 10px;
    padding: 11px 14px;
    border: 1px solid var(--hairline); border-radius: 8px;
    transition: border-color 260ms var(--ease);
  }
.ak-page .ak-route-outs > li::before { content: ''; position: absolute; left: -21px; top: 50%; width: 20px; height: 0; border-top: 1.5px solid var(--hairline); }
.ak-page .ak-route-outs > li.is-active { border-color: var(--blue-border); }
.ak-page .ak-route-outs > li.is-active::before { border-top-color: var(--blue-border); }
.ak-page .ak-route-outs > li.is-active .ak-ring { border-color: var(--blue); }
.ak-page .ak-route-outs > li.is-quiet .ak-ring { opacity: 0.4; }
.ak-page .ak-route-k { font-family: 'Familjen Grotesk', 'Inter', sans-serif; font-size: 13.5px; font-weight: 600; color: var(--text); }
.ak-page .ak-route-v { font-family: 'Familjen Grotesk', 'Inter', sans-serif; font-size: 11px; font-weight: 500; letter-spacing: 0.5px; text-transform: uppercase; color: var(--meta-ui); text-align: right; }
/* measured connectors (30 Sept 2026): AstroKit.routeLines() draws the fan
   as one SVG, so the bus meets every stub exactly and the chosen path is
   one continuous copper stroke. The pseudo-element lines stand down on
   desktop while the SVG is present; stacked, the SVG is empty and they
   return. */
.ak-page .ak-route { position: relative; }
.ak-page .ak-route-lines { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none; }
.ak-page .ak-route-edge { fill: none; stroke: var(--hairline); stroke-width: 1.5; }
.ak-page .ak-route-edge.is-lit { stroke: var(--blue-border); }
.ak-page .ak-route-edge.is-drawing { stroke-dasharray: 1; animation: akRouteDraw 520ms var(--ease) both; }
@keyframes akRouteDraw { from { stroke-dashoffset: 1; } to { stroke-dashoffset: 0; } }
@media (min-width: 861px) {
  .ak-page .ak-route.has-lines .ak-route-rules::before,
  .ak-page .ak-route.has-lines .ak-route-rules::after,
  .ak-page .ak-route.has-lines .ak-route-outs::before,
  .ak-page .ak-route.has-lines .ak-route-outs > li::before { display: none; }
}
@media (prefers-reduced-motion: reduce) { .ak-page .ak-route-edge.is-drawing { animation: none; stroke-dasharray: none; } }
.ak-page .ak-route-msg { margin: 20px 0 0; font-family: 'Familjen Grotesk', 'Inter', sans-serif; font-size: 14px; font-weight: 500; line-height: 1.5; color: var(--text-dim); }
.ak-page .ak-arrow { height: 0; border-top: 1.5px solid var(--hairline-hover); }
.ak-page .ak-checks { list-style: none; display: flex; flex-direction: column; gap: 6px; margin: 12px 0 0; padding: 12px 0 0; border-top: 1px solid var(--hairline); }
.ak-page .ak-checks > li {
    display: grid; grid-template-columns: 14px minmax(0, 1fr) auto; align-items: center; column-gap: 10px;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif; font-size: 13.5px; font-weight: 500; color: var(--text-dim);
  }
.ak-page .ak-checks > li.is-live,
.ak-page .ak-checks > li.is-done { color: var(--text); }
.ak-page .ak-check-meta { font-size: 10.5px; font-weight: 500; letter-spacing: 0.5px; text-transform: uppercase; color: var(--meta-ui); }
@media (max-width: 860px) {
  .ak-page .ak-route { grid-template-columns: minmax(0, 1fr); gap: 28px 0; }
  .ak-page .ak-route-rules { justify-self: center; max-width: none; flex-direction: row; padding: 12px 18px; }
  .ak-page .ak-route-rules::before,
.ak-page .ak-route-rules::after {
      left: 50%; right: auto; width: 0; height: 28px; border-top: 0; border-left: 1.5px solid var(--hairline-hover);
    }
  .ak-page .ak-route-rules::before { top: auto; bottom: 100%; }
  .ak-page .ak-route-rules::after { top: 100%; }
  .ak-page .ak-route-outs::before,
.ak-page .ak-route-outs > li::before { display: none; }
  .ak-page .ak-arrow { justify-self: center; width: 0; height: 28px; border-top: 0; border-left: 1.5px solid var(--hairline-hover); }
  .ak-page .ak-tabpanel { padding: 22px 16px 22px; }
  .ak-page .ak-tab,
.ak-page .ask-talk { min-height: 44px; }
}
@media (max-width: 420px) {
  .ak-page .ak-tabs { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .ak-page .ak-tab { padding: 8px 6px; font-size: 13.5px; }
  .ak-page .ak-route-outs > li { grid-template-columns: 11px minmax(0, 1fr); row-gap: 2px; }
  .ak-page .ak-route-v { grid-column: 2; text-align: left; }
}
.ak-page .ak-link {
    display: inline-flex; align-items: center; min-height: 44px; margin-top: 10px;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif; font-size: 14px; font-weight: 500;
    color: var(--blue); text-decoration: none;
  }
.ak-page .ak-link > span { margin-left: 4px; }
.ak-page .ak-link:hover { text-decoration: underline; }
.ak-page .sys-rail::after { width: 0; background: none; border-left: 1.5px solid var(--blue-border); }
.ak-page .mini-steps.is-rail > li:not(:last-child)::after { width: 0; background: none; border-left: 1.5px solid var(--hairline); }
.ak-page .mini-steps.is-rail > li.is-done:not(:last-child)::after { background: none; border-left-color: var(--blue-border); }
  /* the CTA's supporting line, centred under the headline; Pricing and About */
.ak-page .ak-ask-sub { max-width: 540px; margin: -14px auto 30px; text-align: center; }
  /* a closing line set as display type under a comparison; Pricing 02 and
     About 02. Playfair is editorial display, so it may appear here but
     never inside an interface. */
.ak-page .ak-statement {
    max-width: 980px; margin: 40px 0 0;
    font-family: 'Playfair', 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: clamp(22px, 2.8vw, 32px); font-weight: 700; line-height: 1.2;
    letter-spacing: var(--tracking-display); color: var(--text);
  }
.ak-page .ak-statement em { font-style: italic; }
@media (max-width: 760px) { .ak-page .ak-statement { margin-top: 28px; } }
  /* the shared process rail (AstroKit.process): the panel-toned stage list
     is square, so the card clips it to its own radius, and the panel's
     eyebrow, title and lead sit closer than the generic .ak-h3 spacing.
     Scoped to [data-process] so the Reduce Admin rules view, which also uses
     .ak-stagerail*, is untouched. */
  /* every focusable kit control clears the fixed 64px nav when focus scrolls it
     into view (WCAG 2.2 focus not obscured). Written once here for every
     opted-in page; a page whose own sticky bar needs more says so in its own
     block (Pricing's builder does, at 190px). */
.ak-page :is([role="tab"], .ak-link, .ak-seg-btn, .ui-btn, .hero-path, .ask-opt, .ak-row) { scroll-margin-top: 88px; }
.ak-page [data-process] { overflow: hidden; }
.ak-page [data-process] .ak-stagerail-panel > .ui-eyebrow { margin-bottom: 10px; }
.ak-page [data-process] .ak-h3 { margin-bottom: 12px; }
@media (prefers-reduced-motion: reduce) {
  .ak-page .ak-ring,
.ak-page .ak-empty,
.ak-page .ak-rail-label,
.ak-page .ak-rail-node::after,
.ak-page .ak-edge-flow,
.ak-page .ak-node,
.ak-page .ak-core-ring,
.ak-page .ak-seg-btn,
.ak-page .ak-stage-tab,
.ak-page .ak-stage-tab::after,
.ak-page .ak-group,
.ak-page .ak-row,
.ak-page .ak-stagerail-item,
.ak-page .ak-stagerail-name,
.ak-page .ak-branches > li,
.ak-page .ak-stage-num,
.ak-page .ak-msg,
.ak-page .ak-record dd,
.ak-page .ak-flow > li,
.ak-page .still-line,
.ak-page .ak-route *,
.ak-page .ak-tab,
.ak-page .ak-timeline > li,
.ak-page .ak-checks > li,
.ak-page .sys-rail::after {
      transition: none !important; animation: none !important;
    }
  .ak-page .ak-flow > li { opacity: 1; transform: none; }
}

  /* Placed LAST in the kit on purpose: these two override the plain
     node and rail rules above (font, ring colour), so they must come after
     them. Moved here from the Reduce Admin block, where they sat after the
     whole kit for the same reason; inserted any earlier, the ring of a
     selected rail end dropped to 55% copper and a source button's weight
     changed. Measured, not assumed. */
  /* ── a node that is also a control ──
     .ak-node-btn: a diagram node (.ak-node) that is a real <button>. It
       keeps the node's look rather than taking a button's, so a diagram can
       mix live controls and plain nodes. State is aria-pressed (a choice
       among siblings) or aria-expanded (it opens an inspector panel); the
       selected node takes a copper perimeter and its ring brightens.
     .ak-rail-end: the same idea for a rail node. The button wraps the ring
       and the label and stays a COLUMN, like every other rail node, so all
       labels sit on one line. Drive it with aria-pressed, or with
       AstroKit.inspector(), which sets aria-expanded.
     Both take the 44px touch floor on a phone. A page that restyles either
     inside a diagram must do it inside the same @media (9.5 #15). */
.ak-page .ak-node-btn {
    /* no font reset here: .ak-node sets family, size, weight and line
       height itself, and a reset would replace them with the button's */
    justify-content: flex-start; text-align: left;
    cursor: pointer; touch-action: manipulation;
  }
.ak-page .ak-node-btn[aria-pressed="true"],
.ak-page .ak-node-btn[aria-expanded="true"] { border-color: var(--blue-border); color: var(--text); }
.ak-page .ak-node-btn[aria-pressed="true"] .ak-ring,
.ak-page .ak-node-btn[aria-expanded="true"] .ak-ring { border-color: var(--blue); }
.ak-page .ak-node-btn:hover { color: var(--text); border-color: var(--hairline-hover); }
.ak-page .ak-node-btn:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
.ak-page .ak-rail-end {
    display: flex; flex-direction: column; align-items: flex-start; gap: 10px;
    width: 100%; padding: 0; background: transparent; border: 0;
    text-align: left; cursor: pointer; touch-action: manipulation; font: inherit;
  }
.ak-page .ak-rail-node:has(> .ak-rail-end) { gap: 0; }
.ak-page .ak-rail-end:focus-visible { outline: 2px solid var(--blue); outline-offset: 3px; border-radius: 6px; }
.ak-page .ak-rail-end[aria-pressed="true"] .ak-rail-label,
.ak-page .ak-rail-end[aria-expanded="true"] .ak-rail-label { color: var(--text); font-weight: 600; }
.ak-page .ak-rail-end[aria-pressed="true"] .ak-ring,
.ak-page .ak-rail-end[aria-expanded="true"] .ak-ring { border-color: var(--blue); }
.ak-page .ak-rail-end:hover .ak-rail-label { color: var(--text); }
@media (max-width: 760px) {
  .ak-page .ak-node-btn { min-height: 44px; padding: 8px 12px; font-size: 13px; }
}
@media (max-width: 720px) {
  .ak-page .ak-rail-end { flex-direction: row; align-items: center; gap: 12px; min-height: 44px; }
}

/* ══════════════════════════════════════════════════════════════════════
   INCREASE LEADS PAGE — 16 September 2026, reduced to page-specific rules
   19 September 2026 when the shared components moved into the ASTRO
   INTERFACE KIT block above (Brain/CC_prompt_00_interface_kit.md).

   increase-leads.html only: every selector is under .page-leads (set on
   <body>, alongside the kit's ak-page) or uses a lead- class that exists
   nowhere else, so this block is a no-op on every other page. Behaviour:
   assets/js/astro-leads.js, which is this page's config for the kit.

   What is left here, and why it did not go into the kit: the hero's Lead
   Operations panel (.lead-ops*, .lead-val), the two-column product
   sections (.lead-product*, .lead-tags), the website and
   WhatsApp chat chrome (.lead-chat*), the containers the kit components
   sit in (.lead-demo, .lead-engine, .lead-next, .lead-next-grid,
   .lead-hand), and the Phase 2 Outbound panel (.lead-outbound*,
   .lead-future, .lead-h2-sm). None of those is needed by two or more of
   the pages that assemble the kit.

   The hero shell (.ak-hero*) and the diagram's group box (.ak-group*) are
   in the kit: every later page leads with the same hero shape, and Work's
   system canvas groups its nodes exactly as the engine diagram does.

   Governing rules are the kit block's; they are not re-decided here.
   ══════════════════════════════════════════════════════════════════════ */

.js-reveal .page-leads .ak-sec:not(.is-in) .lead-product-body { opacity: 0; transform: translateX(-90px); }
.js-reveal .page-leads .ak-sec .lead-product-body { transition: transform 0.9s var(--ease), opacity 0.9s var(--ease); }
@media (max-width: 720px) {
  .js-reveal .page-leads .ak-sec:not(.is-in) .lead-product-body { transform: translateX(-48px); }
}
  /* 19 Sept 2026: the Carina photograph came off this page-header, so the
     9.7 text-shadows that existed only for legibility over it come off
     too. #page-header .section-headline is (1,1,0) in the shared
     page-header block; this is (1,2,0), so it wins. The hero now sits on
     the flat --bg ground like every other section, and takes a hairline
     foot so the eye still knows where it ends. */
.page-leads #page-header .section-headline { text-shadow: none; }
.page-leads .lead-ops { position: relative; z-index: 1; overflow: hidden; }
.page-leads .lead-ops-visual { padding: 14px 18px 12px; }
.page-leads .lead-ops-status {
    display: flex; align-items: center; gap: 9px; margin-bottom: 12px;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 11px; font-weight: 600; letter-spacing: 0.8px; line-height: 1.2;
    text-transform: uppercase; color: var(--text);
  }
.page-leads .lead-val { display: block; }
.page-leads .lead-ops:not(.seq-armed) .ak-empty { display: none; }
.page-leads .ak-recgrid dd:has(> .lead-val.is-in) .ak-empty { opacity: 0; }
.page-leads .lead-ops-feed { padding: 2px 0 0; }
.page-leads .lead-ops-feed .sys-row,
.page-leads .lead-chat-flow .sys-row {
    grid-template-columns: 16px minmax(0, 1fr) 16px;
    opacity: 1; transform: none;
  }
.page-leads .lead-ops-feed .sys-row { padding: 5px 0; }
.page-leads .lead-ops-feed .sys-rail::after { height: 16px; }
.page-leads .lead-chat-flow .sys-rail::after { height: 20px; }
.page-leads .lead-ops-feed .sys-body { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.page-leads .lead-ops-feed .sys-detail { margin-top: 0; text-align: right; white-space: nowrap; }
@media (max-width: 960px) {
  .page-leads .lead-ops { max-width: 560px; }
}
@media (max-width: 420px) {
  .page-leads .lead-ops-feed .sys-detail { white-space: normal; }
}
.page-leads .lead-engine { overflow: hidden; }
  /* this page's product column width, and the Chat section's control
     spacing: both were in the kit and are specific to Increase Leads */
.page-leads .lead-product-view .still { max-width: 460px; }
.page-leads #chat .ak-toggle-row { margin-top: 26px; }
.page-leads .lead-demo { overflow: hidden; }
.page-leads .lead-demo > .ak-note { padding: 10px 22px 14px; border-top: 1px solid var(--hairline); }
@media (max-width: 760px) {
  .page-leads .lead-demo > .ak-note { padding: 10px 16px 14px; }
}
.page-leads .lead-product { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 64px; align-items: center; }
.page-leads .lead-product.is-reverse .lead-product-text { order: 2; }
.page-leads .lead-product-body {
    margin: 10px 0 0; max-width: 480px;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif; font-size: 15px; font-weight: 500; line-height: 1.65; color: var(--text-dim);
  }
.page-leads .lead-tags { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 22px; }
.page-leads .lead-tags .demo-chip { margin: 0; }
.page-leads .lead-product-view { display: flex; flex-direction: column; align-items: center; gap: 18px; min-width: 0; }
.page-leads .lead-chat-flow { max-width: 320px; margin-top: 26px; padding: 0; }
.page-leads .lead-chat-chrome { display: none; }
.page-leads .lead-chat.is-web .lead-chat-chrome.is-web {
    display: flex; align-items: center; gap: 6px; padding: 10px 16px;
    border-bottom: 1px solid rgba(10,10,10,0.10);
  }
.page-leads .lead-chat.is-wa .lead-chat-chrome.is-wa { display: flex; }
.page-leads .lead-chat-dot { width: 8px; height: 8px; border-radius: 50%; border: 1px solid rgba(10,10,10,0.3); }
.page-leads .lead-chat-url {
    flex: 1; margin-left: 10px; padding: 3px 10px;
    background: rgba(10,10,10,0.06); border-radius: var(--radius-pill);
    font-size: 11px; font-weight: 500; color: rgba(10,10,10,0.64);
  }
.page-leads .lead-chat.is-web .chat-bubble.out { background: #E4E0DA; }
@media (max-width: 900px) {
  .page-leads .lead-product { grid-template-columns: minmax(0, 1fr); gap: 36px; }
  .page-leads .lead-product.is-reverse .lead-product-text { order: 0; }
}
.page-leads .lead-next { overflow: hidden; }
.page-leads .lead-next-grid { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr); gap: 18px; }
.page-leads .lead-hand { display: grid; grid-template-columns: minmax(0, 0.8fr) 36px minmax(0, 1.2fr); align-items: center; }
@media (max-width: 860px) {
  .page-leads .lead-next-grid { grid-template-columns: minmax(0, 1fr); }
  .page-leads .lead-hand { grid-template-columns: minmax(0, 1fr); }
}
.page-leads .container.lead-outbound-wrap { max-width: 960px; }
.page-leads .lead-outbound {
    display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr); gap: 40px; align-items: center;
    padding: 34px 36px; background: var(--panel);
  }
.page-leads .lead-outbound-top { display: flex; align-items: center; flex-wrap: wrap; gap: 10px 16px; }
.page-leads .lead-outbound-top .section-label { margin-bottom: 0; }
.page-leads .lead-outbound-top .demo-chip { margin: 0; }
.page-leads .lead-h2-sm { margin-top: 18px; font-size: clamp(28px, 3.2vw, 40px); }
.page-leads .lead-outbound .section-sub { color: var(--text-dim); }
.page-leads .lead-future { list-style: none; margin: 0; padding: 0; }
.page-leads .lead-future > li {
    position: relative; display: flex; align-items: center; gap: 12px; padding: 8px 0;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif; font-size: 13.5px; font-weight: 500; line-height: 1.35; color: var(--text-dim);
  }
.page-leads .lead-future > li:not(:last-child)::after {
    content: ''; position: absolute; left: 4.75px; top: calc(50% + 8px); height: calc(100% - 16px); width: 0;
    border-left: 1.5px dashed var(--hairline-hover);
  }
.page-leads .lead-future > li.is-first { color: var(--text); font-weight: 600; }
.page-leads .lead-future > li.is-first .ak-ring { border-color: var(--blue-border); }
@media (max-width: 760px) {
  .page-leads .lead-outbound { grid-template-columns: minmax(0, 1fr); gap: 24px; padding: 24px 20px; }
}

/* ══════════════════════════════════════════════════════════════════════
   REDUCE ADMIN PAGE — 19 September 2026 (Brain/CC_prompt_02_reduce_admin.md).
   reduce-admin.html only: every selector is under .page-admin (set on
   <body>, alongside the kit's ak-page) or uses an admin- class that exists
   nowhere else, so this block is a no-op on every other page. Behaviour:
   assets/js/astro-admin.js, which is this page's config for the kit.

   Everything shared is the kit's and is NOT repeated here: .ak-hero*,
   .ak-diagram, .ak-group*, .ak-node, .ak-core*, .ak-stage*, .ak-split,
   .ak-record, .ak-badge, .ak-outcome, .ak-caption, .ak-seg*, .ak-toggles,
   .ak-tabs/.ak-tab/.ak-tabpanel, .ak-timeline, .ak-checks, .ak-rails,
   .ak-subpanel, .ak-pane-head, .ak-note, .ak-h3, .ak-flow, .ak-arrow,
   .ak-link, .ak-bar, .ak-intro, .ak-sec.

   What is here and why it did not go into the kit: the hero's admin
   operations panel (.admin-ops*), the plain document card used as a source
   in two sections (.admin-doc*), the controls grid (.admin-ctrl*), the
   review queue's two columns (.admin-review*), the work-type panel
   (.admin-types*), and the closing product strip (.admin-prod*).

   Three things this page introduced went INTO the kit instead, because
   Pricing and About both need them and Pricing 06 and About 06 have to
   render the same four stages with the same wording, which a page-scoped
   component cannot do: the stage rail and its branch list (.ak-stagerail*,
   .ak-branches, .ak-branch-k/-v) and the selectable row list (.ak-rows,
   .ak-row*). This page uses them under those names.

   Governing rules are the kit block's; they are not re-decided here.
   ══════════════════════════════════════════════════════════════════════ */

  /* ── 01 HERO: admin operations ── */
  .page-admin .admin-ops { position: relative; z-index: 1; overflow: hidden; }
  .page-admin .admin-ops > .ak-note { padding: 10px 18px 14px; border-top: 1px solid var(--hairline); }
  .page-admin .admin-ops-body { display: grid; grid-template-columns: minmax(0, 1fr); }
  /* The hero panel is 460px wide, so the engine diagram's four side-by-side
     columns do not fit: they clip the outcomes and crowd the core. Here the
     same four columns are placed as sources on the left and one continuous
     vertical flow on the right, which is also the better reading of this
     page: work goes in at the side and comes down through the system. */
  .page-admin .admin-ops-diagram {
    grid-template-columns: minmax(0, 132px) minmax(0, 1fr);
    grid-template-rows: auto auto auto;
    column-gap: 30px; row-gap: 14px;
    align-items: start; padding: 18px 16px 20px;
  }
  /* 30 Sept 2026 (final refinement pass): the flow column is centred on one
     axis so the core, the five stages and the branch share a single
     straight spine (astro-admin.js draws it orthogonally), and the group is
     top-aligned with the core so Work arrives meets Astro in one straight
     line. Row and stage gaps are equal, so every spine segment is the same
     length; the outcomes sit a little lower to leave room for the branch. */
  .page-admin .admin-ops-diagram { row-gap: 12px; }
  .page-admin .admin-ops-diagram .ak-diagram-col.is-inputs { grid-column: 1; grid-row: 1 / -1; align-self: start; }
  .page-admin .admin-ops-diagram .ak-diagram-col.is-core { grid-column: 2; grid-row: 1; align-items: center; }
  .page-admin .admin-ops-diagram .ak-diagram-col.is-caps { grid-column: 2; grid-row: 2; align-items: center; gap: 12px; }
  .page-admin .admin-ops-diagram .ak-diagram-col.is-outs {
    grid-column: 2; grid-row: 3; margin-top: 10px;
    flex-direction: row; flex-wrap: wrap; align-items: center; justify-content: center; gap: 12px;
  }
  .page-admin .admin-ops-diagram .ak-node {
    font-size: 11.5px; padding: 5px 9px; gap: 7px; white-space: normal; line-height: 1.25;
  }
  .page-admin .admin-ops-diagram .ak-node .ak-ring { width: 8px; height: 8px; }
  .page-admin .admin-ops-diagram .ak-core { flex-direction: row; font-size: 11.5px; padding: 8px 14px; gap: 10px; }
  .page-admin .admin-ops-diagram .ak-core-ring { width: 18px; height: 18px; }
  .page-admin .admin-ops-diagram .ak-core-ring::after { inset: 5px; }
  .page-admin .admin-ops-diagram .ak-group { padding: 9px 10px 10px; }
  .page-admin .admin-ops-diagram .ak-group-name { font-size: 12px; }
  .page-admin .admin-ops-diagram .ak-group-nodes { flex-direction: column; align-items: stretch; gap: 5px; margin-top: 9px; }
  /* the sources are the kit's .ak-node-btn (a diagram node that is a button) */
  .page-admin .admin-ops-out { padding: 14px 18px 16px; border-top: 1px solid var(--hairline); }
  .page-admin .admin-ops-item {
    margin: 0 0 6px;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 14px; font-weight: 600; line-height: 1.4; color: var(--text);
  }
  .page-admin .admin-ops-result {
    margin: 0; padding-left: 12px; border-left: 2px solid var(--blue);
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 13.5px; font-weight: 500; line-height: 1.5; color: var(--text-dim);
  }
  /* the one outcome that is not Astro's to complete reads as a hold, not a
     failure: a dashed edge rather than the settled copper one */
  .page-admin .admin-ops-out.is-human .admin-ops-result { border-left-style: dashed; border-left-color: var(--hairline-hover); }
  @media (max-width: 960px) {
    .page-admin .admin-ops { max-width: 560px; }
  }
  @media (max-width: 900px) {
    /* The kit stacks .ak-diagram here. This page's unconditional
       grid-template-columns above is the same specificity and comes later,
       so it would beat that mobile rule at every width and leave the right
       column 155px wide on a phone. That is exactly the trap the kit block
       documents, so the override is repeated inside the same media query. */
    .page-admin .admin-ops-diagram {
      grid-template-columns: minmax(0, 1fr);
      grid-template-rows: auto auto auto auto;
      row-gap: 12px; column-gap: 0;
      justify-items: stretch;
    }
    /* stacked: one centred column, so the spine runs straight from the
       group down through Astro and the stages to the branch (30 Sept 2026;
       the stages were a wrapped row, which no connector can follow cleanly) */
    .page-admin .admin-ops-diagram .ak-diagram-col.is-inputs { grid-column: 1; grid-row: 1; align-self: stretch; }
    .page-admin .admin-ops-diagram .ak-diagram-col.is-core { grid-column: 1; grid-row: 2; align-items: center; }
    .page-admin .admin-ops-diagram .ak-diagram-col.is-caps { grid-column: 1; grid-row: 3; flex-direction: column; flex-wrap: nowrap; align-items: center; gap: 12px; }
    .page-admin .admin-ops-diagram .ak-diagram-col.is-outs { grid-column: 1; grid-row: 4; justify-content: center; }
    .page-admin .admin-ops-diagram .ak-group-nodes { flex-direction: column; align-items: stretch; }
  }

  /* ── 02 THE QUEUE ── */
  .page-admin .admin-queue { overflow: hidden; }
  /* ── the document card: a source item, used by 03 and 04 ── */
  .page-admin .admin-source { display: flex; flex-direction: column; }
  .page-admin .admin-doc {
    flex: 1; padding: 14px 16px 16px;
    background: var(--card); border: 1px solid var(--hairline); border-radius: var(--radius-card);
  }
  .page-admin .admin-doc-head { display: flex; flex-direction: column; gap: 2px; padding-bottom: 10px; margin-bottom: 12px; border-bottom: 1px solid var(--hairline); }
  .page-admin .admin-doc-from {
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 13px; font-weight: 600; line-height: 1.3; color: var(--text);
  }
  .page-admin .admin-doc-sub {
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 11px; font-weight: 500; letter-spacing: 0.5px; text-transform: uppercase; color: var(--meta-ui);
  }
  .page-admin .admin-doc-body {
    margin: 0;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 13.5px; font-weight: 500; line-height: 1.55; color: var(--text-dim);
  }
  .page-admin .admin-source .ak-note { margin-top: 12px; }

  /* ── 03 THE ENGINE ── */
  .page-admin .admin-engine { overflow: hidden; }
  .page-admin .admin-engine .ak-split { min-height: 340px; }

  /* ── 04 THE DEMO ── */
  .page-admin .admin-demo { overflow: hidden; }
  .page-admin .admin-demo-controls { display: flex; flex-wrap: wrap; gap: 8px; }
  .page-admin .admin-demo-flow { max-width: none; justify-content: flex-start; padding: 14px 18px; border-bottom: 1px solid var(--hairline); }
  .page-admin .admin-demo-flow > li { opacity: 1; transform: none; color: var(--text-dim); }
  .page-admin .admin-demo-flow > li.is-done { color: var(--text); }
  /* the step just completed takes the step-marker accent, a perimeter only */
  .page-admin .admin-demo-flow > li.is-current::after {
    content: ''; display: block; width: 100%; height: 0; margin-top: 3px;
    border-top: 1.5px solid var(--blue-border);
  }
  .page-admin .admin-demo-flow > li.is-current { display: inline-flex; flex-direction: column; align-items: stretch; }
  .page-admin .admin-demo-panel { min-height: 380px; }
  .page-admin .admin-demo .ui-btn[aria-disabled="true"] { opacity: 0.45; cursor: default; }
  @media (max-width: 760px) {
    .page-admin .admin-demo-controls { width: 100%; }
    .page-admin .admin-demo-controls .ui-btn { flex: 1 1 0; min-height: 44px; }
    .page-admin .admin-demo-flow { overflow-x: auto; overscroll-behavior-x: contain; scrollbar-width: none; flex-wrap: nowrap; }
    .page-admin .admin-demo-flow::-webkit-scrollbar { display: none; }
    .page-admin .admin-demo-flow > li { flex: none; }
    .page-admin .admin-demo-panel { min-height: 0; }
  }

  /* ── 06 CONTROLS ── */
  .page-admin .admin-ctrl { overflow: hidden; padding: 0 0 22px; }
  .page-admin .admin-ctrl-chain { max-width: none; justify-content: flex-start; padding: 16px 22px; border-bottom: 1px solid var(--hairline); }
  .page-admin .admin-ctrl-grid {
    display: grid; grid-template-columns: minmax(0, 1fr) 36px minmax(0, 1fr); align-items: center;
    gap: 0; padding: 24px 22px 18px;
  }
  .page-admin .admin-ctrl-out { transition: border-color 260ms var(--ease); }
  /* waiting on a person: a dashed perimeter, the same language the rest of
     the site uses for "not finished", never a colour change */
  .page-admin .admin-ctrl-out.is-waiting { border-style: dashed; border-color: var(--hairline-hover); }
  .page-admin .admin-ctrl .ak-checks > li.is-waiting { color: var(--text-dim); }
  .page-admin .admin-ctrl .ak-checks > li.is-waiting .st-check { opacity: 0; }
  .page-admin .admin-ctrl .ak-route-inputs { margin-bottom: 18px; }
  .page-admin .admin-ctrl .ak-toggles { margin-top: 0; }
  .page-admin .admin-ctrl > .ak-note { padding: 0 22px; }
  @media (max-width: 860px) {
    .page-admin .admin-ctrl-grid { grid-template-columns: minmax(0, 1fr); gap: 0; padding: 20px 16px 16px; }
    /* the kit already turns .ak-arrow vertical at 860px; this only adds
       the breathing room this grid needs */
    .page-admin .admin-ctrl .ak-arrow { margin: 14px 0; }
    .page-admin .admin-ctrl-chain { overflow-x: auto; overscroll-behavior-x: contain; scrollbar-width: none; flex-wrap: nowrap; padding: 14px 16px; }
    .page-admin .admin-ctrl-chain::-webkit-scrollbar { display: none; }
    .page-admin .admin-ctrl-chain > li { flex: none; }
    .page-admin .admin-ctrl > .ak-note { padding: 0 16px; }
  }

  /* ── 07 THE REVIEW QUEUE ── */
  .page-admin .admin-review { overflow: hidden; padding: 0 0 22px; }
  .page-admin .admin-review-grid { display: grid; grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr); align-items: start; gap: 18px; padding: 24px 22px 18px; }
  .page-admin .admin-review-needs { border-color: var(--hairline-hover); transition: border-color 260ms var(--ease); }
  .page-admin .admin-review-needs.is-approved,
  .page-admin .admin-review-needs.is-editing,
  .page-admin .admin-review-needs.is-escalated { border-color: var(--blue-border); }
  .page-admin .admin-review-title {
    margin: 4px 0 2px;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 15px; font-weight: 600; line-height: 1.35; color: var(--text);
  }
  .page-admin .admin-review-sub {
    margin: 0 0 18px;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 12px; font-weight: 500; letter-spacing: 0.04em; color: var(--meta-ui);
  }
  .page-admin .admin-review-prep { margin-top: 10px; padding-top: 10px; }
  .page-admin .admin-review-done + .ak-note { margin-top: 14px; }
  .page-admin .admin-review-decision {
    margin: 18px 0 16px; padding: 12px 14px;
    border: 1px dashed var(--hairline-hover); border-radius: 8px;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 13.5px; font-weight: 500; line-height: 1.5; color: var(--text);
  }
  .page-admin .admin-review-decision .ui-eyebrow { display: block; margin-bottom: 5px; }
  .page-admin .admin-review-actions { display: flex; flex-wrap: wrap; gap: 8px; }
  .page-admin .admin-review-actions .ui-btn.is-chosen { border-color: var(--blue-border); color: var(--text); }
  .page-admin .admin-review > .ak-note { padding: 0 22px; }
  @media (max-width: 860px) {
    .page-admin .admin-review-grid { grid-template-columns: minmax(0, 1fr); padding: 20px 16px 16px; }
    .page-admin .admin-review-actions .ui-btn { flex: 1 1 auto; min-height: 44px; }
    .page-admin .admin-review > .ak-note { padding: 0 16px; }
  }

  /* ── 09 THE RESULT: the end piles ── */
  /* the two rail ends are the kit's .ak-rail-end */
  .page-admin .admin-pile {
    margin-top: 6px; padding: 16px 18px 14px;
    background: var(--panel); border: 1px solid var(--hairline); border-radius: var(--radius-card);
    transition: border-color 260ms var(--ease);
  }
  .page-admin .is-human-pile .admin-pile { border-style: dashed; border-color: var(--hairline-hover); }
  .page-admin .admin-pile .ak-checks { margin-top: 0; padding-top: 0; border-top: 0; }
  .page-admin .admin-pile .ak-note { margin-top: 12px; }
  .page-admin .ak-rails > .ak-bar { margin: -26px -28px 4px; }
  @media (max-width: 720px) {
    .page-admin .ak-rails > .ak-bar { margin: -20px -18px 4px; }
  }

  /* a completed row added while the visitor is looking at it */
  .page-admin .admin-review-done > li.is-new { animation: akIn 420ms var(--ease) both; }

  /* ── 08 WORK TYPES ── */
  .page-admin .admin-types { overflow: hidden; }
  .page-admin .admin-types-lead {
    margin: 0 0 22px; max-width: 640px;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 15px; font-weight: 500; line-height: 1.6; color: var(--text-dim);
  }
  .page-admin .admin-types-flow { max-width: 620px; }
  .page-admin .admin-types-flow .ak-timeline-t { text-transform: uppercase; }

  /* ── 10 THE PRODUCT STRIP ── */
  .page-admin .container.admin-prod-wrap { max-width: 960px; }
  .page-admin .admin-prod {
    display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr); gap: 40px; align-items: center;
    padding: 34px 36px; background: var(--panel);
  }
  .page-admin .admin-h2-sm { margin-top: 18px; font-size: clamp(26px, 3vw, 36px); }
  .page-admin .admin-prod .section-sub { margin-top: 14px; color: var(--text-dim); }
  .page-admin .admin-prod-caps {
    list-style: none; margin: 0; padding: 0;
    display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px 16px;
  }
  .page-admin .admin-prod-caps > li {
    display: flex; align-items: center; gap: 11px;
    padding: 11px 14px;
    border: 1px solid var(--hairline); border-radius: 8px;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 13.5px; font-weight: 500; line-height: 1.3; color: var(--text);
  }
  @media (max-width: 760px) {
    .page-admin .admin-prod { grid-template-columns: minmax(0, 1fr); gap: 24px; padding: 24px 20px; }
  }

  /* ── reduced motion: complete, static, instant ── */
  @media (prefers-reduced-motion: reduce) {
    .page-admin .admin-ctrl-out,
    .page-admin .admin-review-needs {
      transition: none !important; animation: none !important;
    }
  }

/* ══════════════════════════════════════════════════════════════════════
   PRICING PAGE — 19 September 2026 (Brain/CC_prompt_03_pricing.md).
   pricing.html only: every selector is under .page-pricing (set on <body>,
   alongside the kit's ak-page) or uses a pr- class that exists nowhere
   else, so this block is a no-op on every other page. Behaviour:
   assets/js/astro-pricing.js, which is this page's config for the kit.

   Everything shared is the kit's and is NOT repeated here: .ak-hero*,
   .ak-sec, .ak-intro, .ak-bar, .ak-stage*, .ak-stagerail*, .ak-branches,
   .ak-seg*, .ak-timeline, .ak-arrow, .ak-subpanel, .ak-pane-head, .ak-badge,
   .ak-outcome, .ak-link, .ak-note, .ak-h3, .ak-ask-sub, and the [data-process]
   rail (AstroKit.process, byte-identical with About 06).

   What is here and why it did not go into the kit: the hero's scope chain
   (.pr-chain, .pr-scope*), the two-column comparison (.pr-compare, .pr-col,
   .pr-steps), the Scope Builder (.pr-builder*, .pr-group*,
   .pr-out*, .pr-rows, .pr-chip*, .pr-sticky*), the two-phase strip
   (.pr-phases, .pr-frame) and the four-stage panel (.pr-stage*). None is
   wanted by another page.

   No price, no score, no total: nothing here draws a number.
   Governing rules are the kit block's; they are not re-decided here.
   ══════════════════════════════════════════════════════════════════════ */

  /* position:sticky (the Scope Builder's phone bar) cannot engage under a
     body that is itself a scroll container, and html and body both carry
     overflow-x:hidden. clip clips the same and makes no scroll container
     (Brain 9.5 #8). Scoped to this page. */
  .page-pricing { overflow-x: clip; }
  /* the shared #page-header text-shadow exists only for legibility over the
     retired space photograph; (1,2,0) beats its (1,1,0) */
  .page-pricing #page-header .section-headline { text-shadow: none; }

  /* ── 01 HERO: the scope chain ── */
  .page-pricing .pr-scope { position: relative; z-index: 1; overflow: hidden; }
  .page-pricing .pr-chain { display: flex; flex-direction: column; gap: 2px; padding: 14px 14px 10px; }
  .page-pricing .pr-chain .ak-stagerail-item { padding: 6px 12px; min-height: 44px; }
  /* the connector is the kit's (ring to ring, in two halves, interrupted
     by the selected card; 30 Sept 2026). The kit turns it OFF at 860px
     because its own list becomes a scrolling strip there; this list stays a
     column at every width, so it is switched back on here, except on the
     selected item (the tie-break caveat in the kit header). */
  .page-pricing .pr-chain .ak-stagerail-item:not(:first-child):not([aria-selected="true"])::before,
  .page-pricing .pr-chain .ak-stagerail-item:not(:last-child):not([aria-selected="true"])::after { display: block; }
  @media (min-width: 861px) {
    .page-pricing .pr-chain .ak-stagerail-item { min-height: 38px; }
  }
  .page-pricing .pr-chain .ak-stagerail-item.is-past .ak-ring { border-color: var(--blue-border); }
  /* the stretch already walked: both halves of every segment between two
     reached stages */
  .page-pricing .pr-chain .ak-stagerail-item.is-past:not(:last-child)::after,
  .page-pricing .pr-chain .ak-stagerail-item.is-past + .ak-stagerail-item::before { border-left-color: var(--blue-border); }
  .page-pricing .pr-scope-detail { min-height: 112px; padding: 16px 18px 6px; border-top: 1px solid var(--hairline); }
  .page-pricing .pr-scope-detail:focus-visible { outline: 2px solid var(--blue); outline-offset: -2px; }
  .page-pricing .pr-scope-line {
    margin: 0;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 14.5px; font-weight: 500; line-height: 1.55; color: var(--text);
  }
  .page-pricing .pr-scope > .ak-note { padding: 8px 18px 14px; }
  @media (max-width: 960px) {
    .page-pricing .pr-scope { max-width: 560px; }
  }

  /* ── 02 WHY THERE ISN'T A STANDARD PRICE ── */
  .page-pricing .pr-compare { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 18px; }
  .page-pricing .pr-col { padding: 18px 24px 22px; }
  .page-pricing .pr-steps { list-style: none; margin: 0; padding: 0; }
  .page-pricing .pr-steps > li {
    display: grid; grid-template-columns: 22px minmax(0, 1fr); align-items: baseline; column-gap: 14px;
    padding: 12px 0 12px 12px; border-top: 1px solid var(--hairline); border-left: 2px solid transparent;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 15px; font-weight: 500; line-height: 1.4; color: var(--text);
  }
  .page-pricing .pr-steps > li:first-child { border-top: 0; }
  .page-pricing .pr-n {
    font-size: 11px; font-weight: 600; letter-spacing: 0.04em; color: var(--meta-ui); font-variant-numeric: tabular-nums;
  }
  /* where each model ends. Astro's last step takes the settled copper
     leading edge; the fixed model's is dashed, the site's word for "not
     finished", because the business is what has to give. */
  .page-pricing .pr-col:last-child .pr-steps > li.is-end { border-left-color: var(--blue); font-weight: 600; }
  .page-pricing .pr-col:first-child .pr-steps > li.is-end { border-left: 2px dashed var(--hairline-hover); }
  @media (max-width: 760px) {
    .page-pricing .pr-compare { grid-template-columns: minmax(0, 1fr); }
    .page-pricing .pr-col { padding: 16px 18px 18px; }
  }

  /* ── 03 THE SCOPE BUILDER ──
     No overflow:hidden anywhere up the chain: it would break the phone
     bar's position:sticky. The summary column carries its own corner. */
  .page-pricing .pr-builder { position: relative; }
  /* .section carries overflow:hidden, which makes it the sticky bar's scroll
     container and pins nothing. clip keeps the same horizontal clipping of
     the intro's reveal travel without making a scroll container. */
  .page-pricing #scope-builder { overflow-x: clip; overflow-y: visible; }
  .page-pricing .pr-builder-grid { display: grid; grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr); }
  .page-pricing .pr-controls { display: flex; flex-direction: column; gap: 22px; padding: 24px 24px 28px; min-width: 0; }
  .page-pricing .pr-group { display: flex; flex-direction: column; gap: 10px; }
  .page-pricing .pr-group[hidden] { display: none !important; }
  .page-pricing .pr-group-k { width: auto; }
  .page-pricing .pr-controls .ak-seg-btn { white-space: normal; text-align: center; line-height: 1.25; }
  .page-pricing .pr-hint {
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 11.5px; font-weight: 500; letter-spacing: 0.03em; color: var(--meta-ui);
  }
  .page-pricing .pr-out {
    min-width: 0; background: var(--panel); border-left: 1px solid var(--hairline);
    border-radius: 0 0 var(--radius-card) 0;
  }
  .page-pricing .pr-out-inner { position: sticky; top: 88px; padding: 24px 26px 24px; }
  .page-pricing .pr-sys-name {
    margin: 4px 0 8px;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 20px; font-weight: 700; line-height: 1.25; letter-spacing: 0.005em; color: var(--text);
  }
  .page-pricing .pr-sentence {
    margin: 0;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 14.5px; font-weight: 500; line-height: 1.55; color: var(--text-dim);
  }
  .page-pricing .pr-changed {
    margin: 16px 0 0; padding: 8px 0 8px 12px; border-left: 2px solid var(--blue);
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 13.5px; font-weight: 500; line-height: 1.45; color: var(--text);
  }
  .page-pricing .pr-changed .ui-eyebrow { margin-bottom: 3px; }
  .page-pricing .pr-changed [data-o="changed"] { animation: akFresh 420ms var(--ease) both; }
  .page-pricing .pr-rows { margin-top: 22px; }
  .page-pricing .pr-row {
    display: grid; grid-template-columns: 104px minmax(0, 1fr); gap: 8px 14px; align-items: start;
    padding: 13px 0; border-top: 1px solid var(--hairline);
  }
  .page-pricing .pr-row-k {
    padding-top: 7px;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 10.5px; font-weight: 600; letter-spacing: 0.8px; text-transform: uppercase; color: var(--meta-ui);
  }
  .page-pricing .pr-chips { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 8px; min-width: 0; }
  .page-pricing .pr-chip {
    position: relative; display: inline-flex; align-items: center;
    padding: 6px 12px;
    background: var(--card); border: 1px solid var(--hairline); border-radius: var(--radius-pill);
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 12.5px; font-weight: 500; line-height: 1.25; color: var(--text);
    transition: border-color 260ms var(--ease);
  }
  .page-pricing .pr-chip.is-extra { color: var(--text-dim); }
  /* a person is in the loop: the dashed perimeter, never a colour change */
  .page-pricing .pr-chip.is-control { border-style: dashed; border-color: var(--hairline-hover); }
  /* what the last change added to the scope */
  .page-pricing .pr-chip.is-new { border-color: var(--blue-border); animation: akFresh 420ms var(--ease) both; }
  /* a multi-step workflow is one path: its parts are joined */
  .page-pricing .pr-chips.is-seq { flex-direction: column; align-items: flex-start; gap: 14px; }
  .page-pricing .pr-chips.is-seq > li:not(:last-child)::after {
    content: ''; position: absolute; left: 21px; top: 100%; width: 0; height: 14px;
    border-left: 1.5px solid var(--hairline-hover);
  }
  .page-pricing .pr-out .ak-note { margin-top: 6px; }
  .page-pricing .pr-sticky { display: none; }
  @media (max-width: 900px) {
    .page-pricing .pr-builder-grid { grid-template-columns: minmax(0, 1fr); }
    .page-pricing .pr-controls { padding: 20px 16px 22px; gap: 20px; }
    .page-pricing .pr-controls .ak-seg-btn { min-height: 44px; }
    .page-pricing .pr-out { border-left: 0; border-top: 1px solid var(--hairline); border-radius: 0 0 var(--radius-card) var(--radius-card); }
    .page-pricing .pr-out-inner { position: static; padding: 22px 16px 20px; }
    /* the summary sits below six groups of controls, so on a phone it would
       be out of sight while the visitor works. This bar repeats what they
       have chosen and what it just did, under the fixed 64px nav. It is
       aria-hidden: the real summary is the one announced. */
    .page-pricing .pr-sticky {
      display: block; position: sticky; top: 64px; z-index: 5;
      padding: 9px 16px 10px; background: var(--panel); border-bottom: 1px solid var(--hairline);
    }
    .page-pricing .pr-sticky-line {
      display: block;
      font-family: 'Familjen Grotesk', 'Inter', sans-serif;
      font-size: 12px; font-weight: 600; line-height: 1.35; color: var(--text);
    }
    .page-pricing .pr-sticky-changed {
      display: block; margin-top: 2px;
      font-family: 'Familjen Grotesk', 'Inter', sans-serif;
      font-size: 11.5px; font-weight: 500; line-height: 1.4; color: var(--text-dim);
    }
    /* a focused control must clear the nav and this bar, or a keyboard
       visitor tabs into something they cannot see (WCAG 2.2 focus not
       obscured) */
    .page-pricing .pr-controls .ak-seg-btn,
    .page-pricing .pr-builder .ui-btn { scroll-margin-top: 190px; }
    .page-pricing .pr-builder .ui-btn { min-height: 44px; }
  }
  @media (max-width: 560px) {
    .page-pricing .pr-row { grid-template-columns: minmax(0, 1fr); gap: 4px; }
    .page-pricing .pr-row-k { padding-top: 0; }
  }

  /* ── 04 WHAT YOU PAY FOR ── */
  .page-pricing .pr-phases { display: grid; grid-template-columns: minmax(0, 1fr) 44px minmax(0, 1fr); align-items: center; }
  .page-pricing .pr-phases .ak-subpanel { align-self: stretch; }
  /* hierarchy (30 Sept 2026, final refinement pass): muted number, then a
     bold white action word, then a softer explanation, so each list scans
     by its verbs. Copper stays on the rings. The number column was 52px
     wide for clock times; two digits need 22px. */
  .page-pricing .pr-phases .ak-timeline > li { grid-template-columns: 14px 22px minmax(0, 1fr); color: var(--text-dim); font-weight: 400; }
  .page-pricing .pr-phases .ak-timeline > li.is-in .ak-ring { border-color: var(--blue-border); }
  .page-pricing .pr-phases .ak-timeline-e strong { font-weight: 700; color: var(--text); letter-spacing: 0.005em; }
  .page-pricing .pr-phases .ak-timeline > li:nth-child(2) { transition-delay: 60ms; }
  .page-pricing .pr-phases .ak-timeline > li:nth-child(3) { transition-delay: 120ms; }
  .page-pricing .pr-phases .ak-timeline > li:nth-child(4) { transition-delay: 180ms; }
  .page-pricing .pr-phases .ak-timeline > li:nth-child(5) { transition-delay: 240ms; }
  .page-pricing .pr-phases .ak-timeline > li:nth-child(6) { transition-delay: 300ms; }
  .page-pricing .pr-frame {
    max-width: 640px; margin: 26px 0 0;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 14.5px; font-weight: 500; line-height: 1.55; color: var(--text-dim);
  }
  @media (max-width: 860px) {
    .page-pricing .pr-phases { grid-template-columns: minmax(0, 1fr); row-gap: 14px; }
  }

  /* ── 05 BEFORE A PROPOSAL ──
     The kit's spine is six columns; this one has four. Only the grid is
     overridden, and at 760px the kit switches the spine to a scrolling
     strip with display:flex, where this rule has no effect. */
  .page-pricing .ak-stage { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .page-pricing .pr-stage-panel { padding: 28px 28px 10px; }
  .page-pricing .pr-stage-panel[hidden] { display: none !important; }
  .page-pricing .pr-stage-panel:focus-visible { outline: 2px solid var(--blue); outline-offset: -2px; }
  .page-pricing .pr-stage-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 24px 48px; }
  .page-pricing .pr-stage-panel .ui-eyebrow { margin-bottom: 10px; }
  .page-pricing .pr-stage-panel .ak-h3 { margin-bottom: 12px; }
  .page-pricing .pr-stage-lead {
    max-width: 460px; margin: 0;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 15px; font-weight: 500; line-height: 1.6; color: var(--text-dim);
  }
  .page-pricing .pr-stage-panel .ak-branches { margin: 0; }
  /* .ak-link was written for an anchor; here it is a button that moves the stage */
  .page-pricing .pr-stage-panel button.ak-link {
    margin-top: 18px; padding: 0; background: none; border: 0; text-align: left;
    cursor: pointer; touch-action: manipulation;
  }
  .page-pricing .pr-stages > .ak-note { padding: 4px 28px 18px; }
  @media (max-width: 860px) {
    .page-pricing .pr-stage-grid { grid-template-columns: minmax(0, 1fr); }
    .page-pricing .pr-stage-panel { padding: 22px 16px 8px; }
    .page-pricing .pr-stage-panel .ak-link { min-height: 44px; }
    .page-pricing .pr-stages > .ak-note { padding: 4px 16px 16px; }
  }

  /* ── reduced motion: complete, static, instant ── */
  @media (prefers-reduced-motion: reduce) {
    .page-pricing .pr-chip,
    .page-pricing .pr-changed [data-o="changed"] {
      transition: none !important; animation: none !important;
    }
  }

/* ══════════════════════════════════════════════════════════════════════
   ABOUT PAGE — 20 September 2026 (Brain/CC_prompt_04_about.md).
   about.html only: every selector is under .page-about (set on <body>,
   alongside the kit's ak-page) or uses an ab- class that exists nowhere
   else, so this block is a no-op on every other page. Behaviour:
   assets/js/astro-about.js, which is this page's config for the kit.

   THE LIGHTEST PAGE IN THE SERIES. Two entrances play once, four things
   are interactive, and everything else is type and space. If this block
   ever grows to feel like Work, cut motion, not content.

   Everything shared is the kit's and is NOT repeated here: .ak-hero*,
   .ak-sec, .ak-intro, .ak-bar, .ak-rails/.ak-track/.ak-rail, .ak-route*,
   .ak-scenarios, .ak-seg*, .ak-rows/.ak-row*, .ak-group*, .ak-node, .ak-core*,
   .ak-badge, .ak-note, .ak-link, .ak-statement, .ak-ask-sub, and the
   [data-process] rail (AstroKit.process, byte-identical with Pricing 06).

   What is here and why it did not go into the kit: the hero introduction
   (.ab-intro*, .ab-drop), the decision panel's branch descriptions
   (.ab-route-d), the business-first path (.ab-built*, .ab-path*, .ab-msg),
   the routing split (.ab-split*, .ab-side, .ab-traits), the after-launch
   panel (.ab-partner*), the comparison table (.ab-vs) and the closing type
   (.ab-big*). None is wanted by another page.

   Governing rules are the kit block's; they are not re-decided here.
   ══════════════════════════════════════════════════════════════════════ */

  /* the shared #page-header text-shadow exists only for legibility over the
     retired space photograph; (1,2,0) beats its (1,1,0) */
  .page-about #page-header .section-headline { text-shadow: none; }

  /* ── 01 HERO: a short introduction, not a simulator ── */
  .page-about .ab-intro { position: relative; z-index: 1; overflow: hidden; }
  .page-about .ab-intro-body { display: flex; flex-direction: column; align-items: center; padding: 20px 20px 8px; }
  .page-about .ab-intro .ak-group { width: 100%; }
  /* each part is quiet until the entrance reaches it, then takes the
     perimeter accent; nothing is filled */
  .page-about .ab-intro [data-on].is-on { border-color: var(--blue-border); }
  .page-about .ab-intro .ak-group.is-on .ak-ring { border-color: var(--blue-border); }
  .page-about .ab-intro .ak-core.is-on .ak-core-ring { border-color: var(--blue-border); }
  .page-about .ab-drop { position: relative; display: block; width: 0; height: 26px; border-left: 1.5px solid var(--hairline); }
  .page-about .ab-drop::after {
    content: ''; position: absolute; left: -1.5px; top: 0; width: 0; height: 100%;
    border-left: 1.5px solid var(--blue-border);
    transform: scaleY(0); transform-origin: top;
    transition: transform 560ms var(--ease);
  }
  .page-about .ab-drop.is-linked::after { transform: scaleY(1); }
  .page-about .ab-intro > .ak-note { padding: 8px 20px 14px; }
  @media (max-width: 960px) {
    .page-about .ab-intro { max-width: 560px; }
  }

  /* ── 02 WHY ASTRO EXISTS: the kit's rails, four steps each ──
     The kit's rail is six columns. Only the column count is overridden, and
     only above the kit's own 720px stacking point, so its mobile rule (one
     vertical column) still applies. */
  @media (min-width: 721px) {
    .page-about .ak-rails .ak-rail { grid-template-columns: repeat(4, minmax(0, 1fr)) minmax(0, 1.15fr); }
  }

  /* the kit fades a degraded track's rings down a six-step ramp; over four
     steps that reads as a verdict on other tools. The dashed connectors and
     the end cap carry the contrast, so the rings stay at full strength. */
  .page-about .is-degraded .ak-rail-node.is-on:nth-child(2) .ak-ring,
  .page-about .is-degraded .ak-rail-node.is-on:nth-child(3) .ak-ring,
  .page-about .is-degraded .ak-rail-node.is-on:nth-child(4) .ak-ring { opacity: 1; }

  /* ── 03 THE PRINCIPLE ── */
  .page-about .ab-principle { overflow: hidden; }
  .page-about .ab-principle-body { padding: 24px 22px 8px; }
  .page-about .ab-route-d {
    grid-column: 2 / -1;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 12.5px; font-weight: 500; line-height: 1.4; color: var(--text-dim);
  }
  .page-about .ak-route-outs > li.is-quiet .ak-route-k { color: var(--text-dim); }
  /* the outcomes are buttons (30 Sept 2026): the card keeps the kit's
     border and state, the button inside takes its grid and padding */
  .page-about .ak-route-outs > li { display: block; padding: 0; }
  .page-about .ab-out {
    display: grid; grid-template-columns: 11px minmax(0, 1fr) auto; align-items: center; column-gap: 10px; row-gap: 2px;
    width: 100%; min-height: 44px; padding: 11px 14px;
    background: transparent; border: 0; border-radius: 8px; color: inherit; font: inherit;
    text-align: left; cursor: pointer; touch-action: manipulation;
  }
  .page-about .ab-out:hover .ak-route-k { color: var(--text); }
  .page-about .ab-out:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
  .page-about .ak-route-outs > li.is-active .ak-route-v { color: var(--text); font-weight: 600; }
  @media (max-width: 420px) {
    .page-about .ab-out { grid-template-columns: 11px minmax(0, 1fr); }
    .page-about .ab-out .ak-route-v { grid-column: 2; text-align: left; }
  }
  .page-about .ab-principle > .ak-note,
  .page-about .ab-built .ak-note,
  .page-about .ab-split > .ak-note { padding: 10px 22px 16px; margin: 0; }
  @media (max-width: 760px) {
    .page-about .ab-principle-body { padding: 20px 16px 6px; }
    .page-about .ab-principle > .ak-note,
    .page-about .ab-split > .ak-note { padding: 10px 16px 16px; }
  }

  /* ── 04 BUILT AROUND YOUR BUSINESS ──
     Rebuilt 30 Sept 2026 as cause and effect: What we learn (left), What it
     changes (right), one fact chosen at a time, joined by a measured copper
     wire (.ab-wire, drawn by astro-about.js) that runs from the chosen row
     across the divider, down the right pane's gutter and into the one part
     that fact creates. That part is lit as a card; the parts of the other
     facts stay quiet, and the three base steps stay neutral. The complete
     view (.is-all) lights every part with its source and draws no wire. */
  .page-about .ab-built { overflow: hidden; }
  .page-about .ab-built-btns { display: flex; flex-wrap: wrap; gap: 8px; }
  .page-about .ab-built .ui-btn[aria-pressed="true"] { border-color: var(--blue-border); color: var(--text); }
  .page-about .ab-built-grid { position: relative; display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .page-about .ab-wire { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none; z-index: 1; }
  .page-about .ab-wire-line { fill: none; stroke: var(--blue-border); stroke-width: 1.5; }
  .page-about .ab-wire-line.is-drawing { stroke-dasharray: 1; animation: akRouteDraw 520ms var(--ease) both; }
  .page-about .ab-learn { min-width: 0; border-right: 1px solid var(--hairline); }
  .page-about .ab-col-head { padding: 16px 20px 10px; margin: 0; }
  .page-about .ab-inputs { padding: 0 0 14px; min-width: 0; }
  .page-about .ab-system { min-width: 0; padding: 0 24px 20px; background: var(--panel); }
  .page-about .ab-system .ab-col-head { padding: 16px 0 10px; }
  .page-about .ab-msg {
    margin: 0 0 14px; padding: 8px 0 8px 12px; border-left: 2px solid var(--blue);
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 13.5px; font-weight: 500; line-height: 1.45; color: var(--text);
  }
  .page-about .ab-msg.is-fresh { animation: akFresh 420ms var(--ease) both; }
  .page-about .ab-path { list-style: none; margin: 0; padding: 0; }
  .page-about .ab-path > li {
    position: relative;
    display: grid; grid-template-columns: 11px 92px minmax(0, 1fr); align-items: center; column-gap: 12px;
    padding: 8px 0;
    border: 1px solid transparent; border-radius: 8px;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 14px; font-weight: 500; line-height: 1.4; color: var(--text);
    transition: color 260ms var(--ease), border-color 260ms var(--ease);
  }
  /* the spine, in two halves per step (the stage rail's method): the lit
     card draws neither, and its neighbours stop short of it */
  .page-about .ab-path > li:not(:first-child)::before,
  .page-about .ab-path > li:not(:last-child)::after {
    content: ''; position: absolute; left: 5.25px; width: 0; pointer-events: none;
    border-left: 1.5px solid var(--hairline);
  }
  .page-about .ab-path > li:not(:first-child)::before { top: -1px; bottom: calc(50% + 9px); }
  .page-about .ab-path > li:not(:last-child)::after { top: calc(50% + 9px); bottom: -1px; }
  .page-about .ab-path > li.is-cause::before,
  .page-about .ab-path > li.is-cause::after { display: none; }
  .page-about .ab-path > li.is-cause + li::before { top: 6px; }
  .page-about .ab-path > li:has(+ li.is-cause)::after { bottom: 6px; }
  .page-about .ab-path-k {
    font-size: 10.5px; font-weight: 600; letter-spacing: 0.8px; text-transform: uppercase; color: var(--meta-ui);
  }
  .page-about .ab-path-v { min-width: 0; }
  .page-about .ab-path-why {
    display: block; margin-top: 2px;
    font-size: 11px; font-weight: 500; letter-spacing: 0.03em; color: var(--meta-ui);
  }
  /* the base steps: neutral; the parts of facts not chosen: quiet */
  .page-about .ab-path > li.is-quiet { color: var(--text-dim); }
  .page-about .ab-path > li.is-quiet .ak-ring { opacity: 0.4; }
  /* the part the chosen fact creates: a card, pulled out by its own padding
     so its ring stays on the spine */
  .page-about .ab-path > li.is-cause {
    margin: 4px -11px; padding: 9px 10px;
    border-color: var(--blue-border); background: rgba(237,233,227,0.04);
  }
  .page-about .ab-path > li.is-cause .ak-ring,
  .page-about .ab-path > li.is-lit .ak-ring { border-color: var(--blue); }
  .page-about .ab-path > li.is-cause .ab-path-k { color: var(--text); }
  .page-about .ab-path > li.is-new { animation: akFresh 420ms var(--ease) both; }
  .page-about .ab-path .ak-ring { background: var(--panel); }
  .page-about .ab-system .ak-note { margin-top: 14px; }
  @media (max-width: 860px) {
    .page-about .ab-built-grid { grid-template-columns: minmax(0, 1fr); }
    .page-about .ab-learn { border-right: 0; border-bottom: 1px solid var(--hairline); }
    .page-about .ab-col-head { padding: 14px 16px 8px; }
    .page-about .ab-system { padding: 0 16px 18px; }
    .page-about .ab-path > li { grid-template-columns: 11px 84px minmax(0, 1fr); }
    .page-about .ab-wire { display: none; }
  }
  @media (max-width: 420px) {
    .page-about .ab-path > li { grid-template-columns: 11px minmax(0, 1fr); row-gap: 1px; }
    .page-about .ab-path-k { grid-column: 2; }
    .page-about .ab-path-v { grid-column: 2; }
    .page-about .ab-path > li .ak-ring { grid-row: 1 / span 2; }
  }
  @media (prefers-reduced-motion: reduce) {
    .page-about .ab-wire-line.is-drawing { animation: none; stroke-dasharray: none; }
    .page-about .ab-path > li { transition: none; }
  }

  /* touch floor on a portrait tablet too: the kit's 44px for these starts at
     760px, this page's controls need it up to the point the layout stacks */
  @media (max-width: 900px) {
    .page-about .ak-seg-btn,
    .page-about .ab-built .ui-btn { min-height: 44px; }
  }

  /* ── 05 HUMAN AND AI ── */
  .page-about .ab-split { overflow: hidden; }
  .page-about .ab-split-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .page-about .ab-work { padding: 10px 0 14px; min-width: 0; border-right: 1px solid var(--hairline); }
  .page-about .ab-work li:first-child .ak-row { border-top: 0; }
  .page-about .ab-sides {
    display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; align-content: start;
    padding: 20px 22px; background: var(--panel); min-width: 0;
  }
  .page-about .ab-side {
    padding: 14px 16px 10px; min-width: 0;
    background: var(--card); border: 1px solid var(--hairline); border-radius: var(--radius-card);
    transition: border-color 260ms var(--ease);
  }
  .page-about .ab-side.is-lit { border-color: var(--blue-border); }
  .page-about .ab-side.is-quiet { border-color: rgba(237,233,227,0.05); }
  .page-about .ab-side .ak-badge[hidden] { display: none !important; }
  .page-about .ab-traits { list-style: none; margin: 4px 0 0; padding: 0; }
  .page-about .ab-traits > li {
    padding: 8px 0 8px 10px; border-top: 1px solid var(--hairline); border-left: 2px solid transparent;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 13.5px; font-weight: 500; line-height: 1.4; color: var(--text-dim);
  }
  .page-about .ab-side.is-lit .ab-traits > li { color: var(--text); }
  /* the trait that made the work theirs takes the settled leading edge */
  .page-about .ab-traits > li.is-hit { border-left-color: var(--blue); font-weight: 600; }
  .page-about .ab-split-foot { padding: 16px 22px 8px; border-top: 1px solid var(--hairline); }
  .page-about .ab-split-foot .ab-msg { margin-bottom: 8px; }
  @media (max-width: 860px) {
    .page-about .ab-split-grid { grid-template-columns: minmax(0, 1fr); }
    .page-about .ab-work { border-right: 0; border-bottom: 1px solid var(--hairline); }
    .page-about .ab-sides { padding: 16px; }
    .page-about .ab-split-foot { padding: 14px 16px 8px; }
  }
  @media (max-width: 560px) {
    .page-about .ab-sides { grid-template-columns: minmax(0, 1fr); }
  }

  /* ── 07 AFTER LAUNCH: the improvement loop (30 Sept 2026) ──
     Five stage tabs on a measured ellipse (astro-about.js places them and
     draws the arcs, each stopping 7px short of the pills at both ends), a
     live-system core at the centre, and the explanation beside it. The arc
     into the chosen stage and its direction mark are copper; every other
     arc is a hairline. The chosen stage reads by its copper border, its
     filled ring edge and its weight, not by colour alone. */
  .page-about .ab-partner { overflow: hidden; }
  .page-about .ab-loop-grid {
    display: grid; grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr); align-items: center; gap: 12px 40px;
    padding: 26px 28px 8px;
  }
  .page-about .ab-loop { position: relative; width: min(100%, 470px); aspect-ratio: 47 / 34; justify-self: center; }
  .page-about .ab-loop-lines { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none; }
  .page-about .ab-loop-arc { fill: none; stroke: var(--hairline-hover); stroke-width: 1.5; }
  .page-about .ab-loop-arc.is-lit { stroke: var(--blue-border); }
  .page-about .ab-loop-arc.is-drawing { stroke-dasharray: 1; animation: akRouteDraw 520ms var(--ease) both; }
  .page-about .ab-loop-dir { fill: none; stroke: var(--hairline-hover); stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
  .page-about .ab-loop-dir.is-lit { stroke: var(--blue); }
  .page-about .ab-loop-core {
    position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
    display: flex; flex-direction: column; align-items: center; gap: 6px; text-align: center;
  }
  .page-about .ab-loop-core .ak-core-ring { width: 22px; height: 22px; }
  .page-about .ab-loop-core-k {
    font-family: 'Familjen Grotesk', 'Inter', sans-serif; font-size: 10.5px; font-weight: 600;
    letter-spacing: 0.8px; text-transform: uppercase; color: var(--meta-ui);
  }
  .page-about .ab-loop-core-v { font-family: 'Familjen Grotesk', 'Inter', sans-serif; font-size: 14px; font-weight: 600; color: var(--text); }
  .page-about .ab-loop-node {
    position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
    display: inline-flex; align-items: center; gap: 8px; min-height: 36px;
    padding: 7px 13px; white-space: nowrap;
    background: var(--card); border: 1px solid var(--hairline); border-radius: var(--radius-pill);
    font-family: 'Familjen Grotesk', 'Inter', sans-serif; font-size: 13px; font-weight: 500; color: var(--text-dim);
    cursor: pointer; touch-action: manipulation;
    transition: color 260ms var(--ease), border-color 260ms var(--ease);
  }
  .page-about .ab-loop-node .ak-ring { width: 9px; height: 9px; }
  .page-about .ab-loop-node:hover { color: var(--text); border-color: var(--hairline-hover); }
  .page-about .ab-loop-node[aria-selected="true"] { color: var(--text); font-weight: 600; border-color: var(--blue-border); }
  .page-about .ab-loop-node[aria-selected="true"] .ak-ring { border-color: var(--blue); border-width: 2px; }
  .page-about .ab-loop-node:focus-visible { outline: 2px solid var(--blue); outline-offset: 3px; }
  .page-about .ab-loop-panel { min-width: 0; padding: 4px 0; }
  .page-about .ab-loop-panel:focus-visible { outline: 2px solid var(--blue); outline-offset: 6px; border-radius: 4px; }
  .page-about .ab-loop-panel.is-fresh .ak-h3,
  .page-about .ab-loop-panel.is-fresh .ab-loop-text { animation: akFresh 420ms var(--ease) both; }
  .page-about .ab-loop-panel .ui-eyebrow { display: block; margin-bottom: 10px; }
  .page-about .ab-loop-panel .ak-h3 { margin: 0 0 10px; }
  .page-about .ab-loop-text {
    margin: 0 0 20px; max-width: 420px;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif; font-size: 15px; font-weight: 500; line-height: 1.6; color: var(--text-dim);
  }
  .page-about .ab-loop-next { min-height: 40px; }
  .page-about .ab-partner-copy {
    display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px 40px;
    margin: 18px 0 0; padding: 20px 28px 26px; border-top: 1px solid var(--hairline);
  }
  .page-about .ab-partner-copy p {
    margin: 0; max-width: 460px;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 15px; font-weight: 500; line-height: 1.6; color: var(--text-dim);
  }
  @media (max-width: 860px) {
    .page-about .ab-loop-grid { grid-template-columns: minmax(0, 1fr); padding: 22px 18px 6px; gap: 22px; }
    .page-about .ab-loop { width: min(100%, 440px); aspect-ratio: 11 / 10; }
    .page-about .ab-loop-node { font-size: 12.5px; padding: 6px 11px; min-height: 36px; }
  }
  @media (max-width: 760px) {
    .page-about .ab-partner-copy { grid-template-columns: minmax(0, 1fr); padding: 18px 18px 20px; }
  }
  @media (prefers-reduced-motion: reduce) {
    .page-about .ab-loop-arc.is-drawing { animation: none; stroke-dasharray: none; }
    .page-about .ab-loop-node { transition: none; }
    .page-about .ab-loop-panel.is-fresh .ak-h3,
    .page-about .ab-loop-panel.is-fresh .ab-loop-text { animation: none; }
  }

  /* ── 08 WHAT ASTRO ISN'T: one ruled table, five pairs ── */
  .page-about .ab-vs { width: 100%; border-collapse: collapse; table-layout: fixed; }
  .page-about .ab-vs th {
    padding: 0 20px 14px 22px; text-align: left;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 10.5px; font-weight: 600; letter-spacing: 0.8px; text-transform: uppercase; color: var(--meta-ui);
  }
  .page-about .ab-vs td {
    padding: 20px 20px 20px 22px; vertical-align: top;
    border-top: 1px solid var(--hairline);
    font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 16px; font-weight: 500; line-height: 1.45;
  }
  /* what it is not: the dashed edge, the site's word for "not finished".
     What it is: the settled copper leading edge. */
  .page-about .ab-vs td:first-child { color: var(--text-dim); border-left: 2px dashed var(--hairline-hover); }
  .page-about .ab-vs td:last-child { color: var(--text); border-left: 2px solid var(--blue); }
  @media (max-width: 720px) {
    .page-about .ab-vs thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
    .page-about .ab-vs, .page-about .ab-vs tbody, .page-about .ab-vs tr, .page-about .ab-vs td { display: block; width: 100%; }
    .page-about .ab-vs tr { margin-top: 18px; }
    .page-about .ab-vs td { padding: 12px 16px; border-top: 0; }
    .page-about .ab-vs td:first-child { border-top: 1px solid var(--hairline); }
    .page-about .ab-vs td::before {
      content: attr(data-label); display: block; margin-bottom: 3px;
      font-size: 10.5px; font-weight: 600; letter-spacing: 0.8px; text-transform: uppercase; color: var(--meta-ui);
    }
  }

  /* ── 09 THE BIGGER IDEA: type and space only ── */
  .page-about .ab-big { max-width: none; font-size: clamp(36px, 5.4vw, 76px); line-height: 1.1; }  /* floor = the section headline's phone size (3 Oct 2026) */
  .page-about .ab-big-a, .page-about .ab-big-b { display: block; }
  .page-about .ab-big-a { color: var(--text-dim); }

  /* ── reduced motion: complete, static, instant ── */
  @media (prefers-reduced-motion: reduce) {
    .page-about .ab-drop::after,
    .page-about .ab-side,
    .page-about .ab-msg,
    .page-about .ab-path > li {
      transition: none !important; animation: none !important;
    }
  }


/* ═══════════════════════════════════════════════════════════════════════
   WORK PAGE — rebuilt 21 September 2026 (Brain/CC_prompt_01_work.md).
   work.html, behaviour in assets/js/astro-work.js. Built on the ASTRO
   INTERFACE KIT above; everything here is scoped to .page-work or a work-
   class and is page-only. Nothing in this block is needed by another page.

   One environment: sections 03 to 08 are views into one store, and each
   opens with a .work-ctx line naming what is running. Copper stays on
   borders, strokes, links and focus: the hit phrase in 07 is a copper
   underline border, never a highlight fill.

   Kit overrides that affect the hero and its diagram sit INSIDE a
   min-width @media matching the kit's breakpoint, so the kit's own mobile
   rules still win below it (Brain 9.5 #15).

   Kit components used: .ak-hero*, .ak-diagram, .ak-group*, .ak-node,
   .ak-node-btn, .ak-core*, .ak-rows/.ak-row*, .ak-pane-head, .ak-badge,
   .ak-toggles/.ak-toggle-row/.ak-seg*, .ak-scenarios, .ak-bar, .ak-rail,
   .ak-rail-end, .ak-split, .ak-convo, .ak-state, .ak-timeline, .ak-outcome,
   .ak-route*, .ak-record, .ak-stagerail*, .ak-tabs/.ak-tab/.ak-tabpanel,
   .ak-flow, .ak-note, .ak-link, .ak-sec, .ak-intro, and AstroKit.store(),
   inspector(), diagram(), tablist(), tabKeys(), glyphs(), watch(),
   onHidden() and ask(). This page is the first user of inspector().
   ═══════════════════════════════════════════════════════════════════════ */

  /* the nav is sticky: keep a keyboard-focused control clear of it when
     the browser scrolls it into view */
  html:has(> body.page-work) { scroll-padding-top: 88px; }

  /* ── shared: the Phase 2 tag and the context line ── */
  .page-work .work-phase {
    display: inline-block; margin-left: 6px; padding: 2px 7px;
    border: 1px solid var(--hairline-hover); border-radius: var(--radius-pill);
    font-family: 'Familjen Grotesk', 'Inter', sans-serif; font-size: 10px; font-weight: 600;
    letter-spacing: 0.5px; text-transform: uppercase; line-height: 1.3; color: var(--meta-ui);
    white-space: nowrap; vertical-align: middle;
  }
  .page-work .work-ctx {
    display: flex; align-items: center; flex-wrap: wrap; gap: 4px 12px;
    padding: 0 18px; min-height: 44px;
    border-bottom: 1px solid var(--hairline);
    font-family: 'Familjen Grotesk', 'Inter', sans-serif; font-size: 13px; font-weight: 500; line-height: 1.4;
  }
  .page-work .work-ctx-k { font-size: 10px; font-weight: 600; letter-spacing: 0.6px; text-transform: uppercase; color: var(--meta-ui); }
  .page-work .work-ctx-sys { font-weight: 600; color: var(--text); }
  .page-work .work-ctx-v { color: var(--text-dim); }
  .page-work .work-ctx-link { margin: 0 0 0 auto; font-size: 13px; }
  /* 03 is where the inputs are changed, so its own line has no link */
  .page-work .work-input .work-ctx-link { display: none; }
  .page-work .work-btns { display: flex; flex-wrap: wrap; gap: 6px; }
  /* a finished run: the label still says something ("Complete"), so it
     stays readable. Dim text and a dashed edge, not a faded button */
  .page-work .ui-btn[aria-disabled="true"],
  .page-work .ui-btn[aria-disabled="true"]:hover {
    color: var(--text-dim); background: transparent;
    border-color: var(--hairline-hover); border-style: dashed; cursor: default;
  }

  /* ── 01 hero: the system canvas ── */
  .page-work .work-canvas .ak-group-nodes { flex-direction: column; align-items: stretch; }
  /* the system names may wrap rather than push a node out of its group */
  .page-work .work-canvas .ak-node-btn { white-space: normal; min-width: 0; }
  .page-work .work-sys-name { min-width: 0; line-height: 1.35; }
  .page-work .work-sys-name .work-phase { margin-left: 4px; }
  .page-work .work-canvas .ak-note { margin: 0; padding: 12px 18px 16px; border-top: 1px solid var(--hairline); }
  @media (min-width: 961px) {
    .page-work .work-hero-grid { grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr); gap: 48px; }
  }
  @media (min-width: 901px) {
    .page-work .work-canvas-diagram {
      grid-template-columns: minmax(0, 1.3fr) auto minmax(0, 1fr);
      column-gap: 32px; padding: 30px 24px 32px;
    }
  }

  /* ── 02 selector ── */
  .page-work .work-select-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .page-work .work-select .ak-rows { margin: 0; padding: 0; list-style: none; border-right: 1px solid var(--hairline); }
  .page-work .work-about { min-width: 0; padding: 20px 24px 22px; }
  .page-work .work-about-name {
    margin: 0 0 12px; font-family: 'Familjen Grotesk', 'Inter', sans-serif;
    font-size: 20px; font-weight: 600; line-height: 1.3; color: var(--text);
  }
  .page-work .work-about-list { margin: 0; }
  .page-work .work-about-list > div { padding: 10px 0; border-top: 1px solid var(--hairline); }
  .page-work .work-about-list dt { font-family: 'Familjen Grotesk', 'Inter', sans-serif; font-size: 10.5px; font-weight: 600; letter-spacing: 0.6px; text-transform: uppercase; color: var(--meta-ui); }
  .page-work .work-about-list dd { margin: 4px 0 0; font-size: 14.5px; line-height: 1.55; color: var(--text); }
  .page-work .work-about .ak-note { margin-top: 14px; }

  /* ── 03 the input ── */
  .page-work .work-input-grid { display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr); }
  .page-work .work-artifact { min-width: 0; padding: 18px 22px 20px; }
  .page-work .work-art-body,
  .page-work .work-raw { display: flex; flex-direction: column; gap: 10px; }
  .page-work .work-line { margin: 0; font-size: 14.5px; line-height: 1.55; color: var(--text); }
  .page-work .work-who {
    display: block; margin-bottom: 2px;
    font-family: 'Familjen Grotesk', 'Inter', sans-serif; font-size: 10.5px; font-weight: 600;
    letter-spacing: 0.6px; text-transform: uppercase; color: var(--meta-ui);
  }
  .page-work .work-artifact .ak-note { margin-top: 16px; }
  .page-work .work-controls { min-width: 0; padding: 18px 22px 22px; background: var(--panel); border-left: 1px solid var(--hairline); }
  .page-work .work-controls .ak-toggles { margin-top: 14px; }
  .page-work .ak-toggle-row { align-items: flex-start; flex-direction: column; gap: 6px; }

  /* ── 04 the system: rail and inspector ── */
  .page-work .work-rail { padding: 26px 28px 22px; }
  .page-work .work-rail .ak-rail-node.is-quiet .ak-ring { opacity: 0.4; }
  .page-work .work-rail .ak-rail-node.is-quiet .ak-rail-label { color: var(--text-dim); }
  .page-work .work-inspect {
    margin: 0 28px 18px; padding: 14px 18px 16px;
    background: var(--panel); border: 1px solid var(--hairline-hover); border-radius: var(--radius-card);
    transition: border-color 260ms var(--ease);
  }
  .page-work .work-inspect.is-quiet { border-style: dashed; }
  .page-work .work-inspect:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
  .page-work .work-inspect .ak-pane-head { margin-bottom: 6px; }
  .page-work .work-insp-name { margin: 0 0 4px; font-family: 'Familjen Grotesk', 'Inter', sans-serif; font-size: 16px; font-weight: 600; color: var(--text); }
  .page-work .work-insp-text { margin: 0; max-width: 720px; font-size: 14.5px; line-height: 1.55; color: var(--text-dim); }
  .page-work .work-system > .ak-note { margin: 0; padding: 0 28px 20px; }

  /* ── 05 run it ── */
  .page-work .work-quote {
    margin: 0; padding-left: 14px; border-left: 1.5px solid var(--hairline-hover);
    font-size: 15px; line-height: 1.55; color: var(--text);
  }
  .page-work .work-run-from { margin: 12px 0 0; font-family: 'Familjen Grotesk', 'Inter', sans-serif; font-size: 12.5px; font-weight: 500; color: var(--meta-ui); }
  .page-work .work-run-cond-k { display: block; margin-top: 22px; margin-bottom: 4px; }
  .page-work .work-run-cond { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .page-work .work-run-steps > li { grid-template-columns: 14px 22px minmax(0, 1fr); align-items: start; }
  .page-work .work-run-steps > li > .st { margin-top: 2px; }
  .page-work .work-run-steps .ak-timeline-t { padding-top: 2px; }
  .page-work .work-run-steps .ak-timeline-e > strong { display: block; font-weight: 600; }
  .page-work .work-run-steps .ak-timeline-e > span { display: block; margin-top: 1px; font-size: 13px; font-weight: 400; color: var(--text-dim); }
  .page-work .work-run-steps > li:not(:last-child)::after { top: 26px; height: calc(100% - 22px); }
  .page-work .work-run .ak-outcome { margin-top: 12px; }
  .page-work .work-run > .ak-note { margin: 0; padding: 12px 18px 16px; border-top: 1px solid var(--hairline); }

  /* ── 06 branches ── */
  .page-work .work-route { padding: 26px 28px 20px; }
  .page-work .work-route .ak-toggles { margin-top: 4px; }
  .page-work .work-route .ak-route-outs > li.is-quiet .ak-route-k { color: var(--text-dim); font-weight: 500; }
  .page-work .work-branch-why {
    margin: 0 28px 16px; padding: 10px 14px; border-left: 1.5px solid var(--blue-border);
    font-family: 'Familjen Grotesk', 'Inter', sans-serif; font-size: 14.5px; font-weight: 500; line-height: 1.5; color: var(--text);
  }
  .page-work .work-branch > .ak-note { margin: 0; padding: 0 28px 20px; }

  /* ── 07 understanding ── */
  .page-work .work-under-grid { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr) minmax(0, 0.9fr); }
  .page-work .work-under-col { min-width: 0; padding: 18px 20px 20px; }
  .page-work .work-under-col + .work-under-col { border-left: 1px solid var(--hairline); }
  .page-work .work-under-col > .ui-eyebrow { display: block; margin-bottom: 12px; }
  .page-work .work-src { border-bottom: 1px dotted var(--hairline-hover); transition: border-color 260ms var(--ease), color 260ms var(--ease); }
  .page-work .work-art-body .work-src { border-bottom: 0; }
  .page-work .work-src.is-hit { border-bottom: 1.5px solid var(--blue-border); color: var(--text); }
  .page-work .work-fields { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }
  .page-work .work-field {
    display: flex; flex-direction: column; align-items: flex-start; gap: 2px; width: 100%; min-height: 44px;
    padding: 7px 10px; background: transparent; border: 1px solid transparent; border-radius: 8px;
    text-align: left; cursor: pointer; touch-action: manipulation; font: inherit;
    transition: border-color 260ms var(--ease), background 260ms var(--ease);
  }
  .page-work .work-field:hover { border-color: var(--hairline); }
  .page-work .work-field[aria-pressed="true"] { border-color: var(--blue-border); background: rgba(237,233,227,0.05); }
  .page-work .work-field:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
  .page-work .work-field-k { font-family: 'Familjen Grotesk', 'Inter', sans-serif; font-size: 10.5px; font-weight: 600; letter-spacing: 0.6px; text-transform: uppercase; color: var(--meta-ui); }
  .page-work .work-field-v { font-family: 'Familjen Grotesk', 'Inter', sans-serif; font-size: 14px; font-weight: 600; color: var(--text); }
  .page-work .work-out { grid-template-columns: minmax(0, 1fr); }
  .page-work .work-used {
    margin: 12px 0 0; padding: 10px 14px; border-left: 1.5px solid var(--blue-border);
    font-size: 14px; line-height: 1.55;
  }
  .page-work .work-used-k { display: block; font-family: 'Familjen Grotesk', 'Inter', sans-serif; font-weight: 600; color: var(--text); }
  .page-work .work-used-v { display: block; margin-top: 2px; color: var(--text-dim); }
  .page-work .work-under > .ak-note { margin: 0; padding: 0 20px 20px; }

  /* ── 08 downstream ── */
  .page-work .work-card .ak-record { grid-template-columns: minmax(0, 1fr); }
  .page-work .work-down .ak-stagerail-panel .ak-note { margin-top: 16px; }

  /* ── 09 your business ── */
  .page-work .work-biz-q { margin: 0 0 8px; font-family: 'Familjen Grotesk', 'Inter', sans-serif; font-size: 18px; font-weight: 600; color: var(--text); }
  .page-work .work-biz-a { margin: 0; max-width: 620px; font-size: 15px; line-height: 1.6; color: var(--text-dim); }
  .page-work .work-biz-flow { margin: 0 auto; padding: 4px 24px 24px; }
  .page-work .work-biz-flow > li > span,
  .page-work .work-biz-flow > li { color: var(--text-dim); }
  .page-work .work-biz-flow > li.is-current { color: var(--text); text-decoration: underline; text-decoration-color: var(--blue-border); text-decoration-thickness: 1.5px; text-underline-offset: 5px; }
  .page-work .work-biz > .ak-note { margin: 0; padding: 12px 24px 18px; border-top: 1px solid var(--hairline); }

  /* ── 10 CTA ── */
  .page-work .work-cta-sub { margin-left: auto; margin-right: auto; }

  /* ── tablet and phone ── */
  @media (max-width: 960px) {
    .page-work .work-under-grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
    .page-work .work-under-col:last-child { grid-column: 1 / -1; border-left: 0; border-top: 1px solid var(--hairline); }
  }
  @media (max-width: 860px) {
    .page-work .work-select-grid,
    .page-work .work-input-grid { grid-template-columns: minmax(0, 1fr); }
    .page-work .work-select .ak-rows { border-right: 0; border-bottom: 1px solid var(--hairline); }
    .page-work .work-controls { border-left: 0; border-top: 1px solid var(--hairline); }
    .page-work .work-route { padding: 20px 18px 16px; }
    .page-work .work-branch-why { margin: 0 18px 14px; }
    .page-work .work-branch > .ak-note { padding: 0 18px 18px; }
  }
  /* touch minimum on tablets as well as phones, as Pricing and About do:
     the kit's segmented and ghost buttons are shorter than 44px at 768 */
  @media (max-width: 900px) {
    .page-work .work-btns .ui-btn,
    .page-work .ak-seg-btn,
    .page-work .work-canvas .ak-node-btn,
    .page-work .work-rail .ak-rail-end,
    .page-work .ak-tab { min-height: 44px; }
  }
  @media (max-width: 720px) {
    .page-work .work-ctx { padding: 4px 16px; }
    .page-work .work-rail { padding: 20px 18px 16px; }
    .page-work .work-inspect { margin: 0 16px 16px; }
    .page-work .work-rail .ak-rail-node:has(> .work-inspect) { flex-wrap: wrap; row-gap: 10px; }
    .page-work .work-rail .work-inspect { flex: 0 0 calc(100% - 24px); min-width: 0; margin: 0 0 4px 24px; }
    .page-work .work-system > .ak-note { padding: 0 16px 18px; }
    .page-work .work-about,
    .page-work .work-artifact,
    .page-work .work-controls { padding: 16px; }
    .page-work .work-under-grid { grid-template-columns: minmax(0, 1fr); }
    .page-work .work-under-col { padding: 16px; }
    .page-work .work-under-col + .work-under-col { border-left: 0; border-top: 1px solid var(--hairline); }
    .page-work .work-under > .ak-note { padding: 0 16px 18px; }
    .page-work .work-biz-flow { padding: 4px 16px 20px; }
  }

  /* ── reduced motion: complete, static, instant ── */
  @media (prefers-reduced-motion: reduce) {
    .page-work .work-src,
    .page-work .work-field,
    .page-work .work-inspect {
      transition: none !important; animation: none !important;
    }
  }

/* ═══════════════════════════════════════════════════════════════════════
   LEGAL PAGES, 25 Sept 2026 (privacy-policy.html, terms-of-use.html,
   cookie-policy.html). Every selector sits under #legal-content, which
   exists on those three pages only, so this block is inert everywhere else.
   Before this pass the clause markup had no rules at all: prose and clause
   headings fell back to the body default (Inter 400) and browser h2/h3
   sizes, the global reset left paragraphs with no spacing and list bullets
   hanging outside the column, and .table-wrap, .callout, .contact-card,
   .rights-list and .security-list had no styling (their rules did not
   survive the 1 Sept consolidation). This puts them on the site type
   system: Playfair clause headings on the .ak-h3 scale, Familjen Grotesk
   prose, 17px/700 subheads (the card-title role), neutral hairlines and
   --card surfaces. No copper except the existing link rule above.
   ═══════════════════════════════════════════════════════════════════════ */
#legal-content .legal-clause { margin: 0 0 56px; }
#legal-content .legal-clause:last-child { margin-bottom: 0; }
#legal-content .legal-clause h2 {
  margin: 0 0 18px;
  font-family: 'Playfair', 'Familjen Grotesk', 'Inter', sans-serif;
  font-size: clamp(22px, 2.6vw, 30px); font-weight: 700; line-height: 1.15;
  letter-spacing: var(--tracking-display); color: var(--text);
}
#legal-content .legal-clause h3 {
  margin: 28px 0 8px;
  font-family: 'Familjen Grotesk', 'Inter', sans-serif;
  font-size: 17px; font-weight: 700; line-height: 1.3; color: var(--text);
}
#legal-content .legal-clause h2 + h3 { margin-top: 0; }
#legal-content .legal-clause p,
#legal-content .legal-clause li,
#legal-content .legal-clause td,
#legal-content .legal-clause th {
  font-family: 'Familjen Grotesk', 'Inter', sans-serif;
  font-size: 16px; line-height: 1.65;
}
#legal-content .legal-clause p + p,
#legal-content .legal-clause p + ul,
#legal-content .legal-clause ul + p,
#legal-content .legal-clause p + .table-wrap,
#legal-content .legal-clause .table-wrap + p,
#legal-content .legal-clause p + .callout,
#legal-content .legal-clause .callout + p,
#legal-content .legal-clause p + .contact-card,
#legal-content .legal-clause .contact-card + p { margin-top: 16px; }
#legal-content .legal-clause strong { font-weight: 700; color: var(--text); }

#legal-content .legal-clause ul { padding-left: 22px; }
#legal-content .legal-clause li + li { margin-top: 10px; }
#legal-content .legal-clause li::marker { color: var(--text-dim); }
#legal-content .rights-list strong { display: block; }

#legal-content .table-wrap { overflow-x: auto; }
#legal-content .legal-clause table { width: 100%; border-collapse: collapse; }
#legal-content .legal-clause th {
  padding: 0 16px 10px 0; text-align: left; vertical-align: bottom;
  font-weight: 700; color: var(--text);
  border-bottom: 1px solid var(--tag-border);
}
#legal-content .legal-clause td {
  padding: 12px 16px 12px 0; vertical-align: top; color: var(--text);
  border-bottom: 1px solid var(--hairline);
}
#legal-content .legal-clause th:last-child,
#legal-content .legal-clause td:last-child { padding-right: 0; }

#legal-content .callout,
#legal-content .contact-card {
  padding: 20px 24px;
  background: var(--card);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-card);
}
#legal-content .callout p + p,
#legal-content .contact-card p + p { margin-top: 8px; }

@media (max-width: 600px) {
  #legal-content .legal-clause { margin-bottom: 44px; }
  #legal-content .legal-clause td,
  #legal-content .legal-clause th { font-size: 14px; padding-right: 12px; }
  #legal-content .callout,
  #legal-content .contact-card { padding: 16px 18px; }
}

/* The legal pages' long-section starfield override (25 Sept 2026) moved into the
   SITEWIDE STARFIELD rule at the end of this file the same day. */

/* ═══════════════════════════════════════════════════════════════════════
   SITEWIDE STARFIELD, 25 Sept 2026 (James). Every section on every page
   carries .starfield except index.html's #hero (the black-hole video,
   untouched). The Carina page-header photo is retired. This rule is the one
   definition of the treatment and sits last so it wins over every earlier
   ground: .ak-page .ak-sec--panel (0,2,0, later than .section.starfield,
   hence section.section.starfield at 0,2,1), ask-astro.html's `#hero {
   background: transparent }` (hence #hero.starfield; index's #hero has no
   class, so it can never match), and the two legacy band-dark rules.
   Sizing, generalised from the legal pages (Brain 9.5 #21): `cover` scaled
   the 1408x768 photo by section HEIGHT, 8x to 11x on long sections, and the
   stars blurred into JPEG blocks. The photo layer is sized by WIDTH instead
   (never under 1100px wide, about 0.78x on a phone, 1.02x at 1440) and
   repeats down the section, so every section shows stars at one scale
   whatever its height. The overlay and colour are the original class's.
   ═══════════════════════════════════════════════════════════════════════ */
section.section.starfield,
#hero.starfield,
#chat-cta.band-dark,
.module-band.band-dark {
  background-image:
    linear-gradient(rgba(6,6,8,0.6), rgba(6,6,8,0.6)),
    url('../images/starfield/deep-sky-starfield.jpg');
  background-size: cover, max(100%, 1100px) auto;
  background-position: center, center top;
  background-repeat: no-repeat, repeat-y;
  background-color: var(--bg);
}

/* ═══════════════════════════════════════════════════════════════════════
   CONTRAST FIXES, 25 Sept 2026. Pre-existing text under AA, found by the
   pixel-measured contrast pass of the sitewide starfield rollout (Brain 9.5
   #22). Colour only; no layout, timing or content change. Both use
   --meta-ui (#8C8980), the token promoted on 19 Sept for exactly this
   10-13px interface meta text because --meta (#7A7770) measures 4.15:1 on
   --card and --text-faint (30% alpha) about 2.4:1.
   ═══════════════════════════════════════════════════════════════════════ */
/* index.html hero system panel: the "Example activity" label (the page's
   required Example marker), the row timestamps and the row details are all
   read, not ornament. The panel is an opaque --card box that fully occludes
   the orb, so 9.7's over-video shadow does not apply; the kit already gives
   .sys-detail --meta-ui on Increase Leads. Scoped to #hero: the homepage's
   hero is the only #hero that contains a .sys-panel. */
#hero .sys-panel-meta,
#hero .sys-time,
#hero .sys-detail { color: var(--meta-ui); }
/* ask-astro.html "01" to "05": 10px/700 labels on the five topic cards.
   They number readable items, so they are text, not the large ghost
   numerals 9.7 exempts. .section--light .product-num was written for the
   old white bands and resolves to --text-faint on today's dark ground. */
#what-to-tell-it .product-num { color: var(--meta-ui); }


/* ═══════════════════════════════════════════════════════════════════════
   INSIGHTS/ARTICLES, 25 Sept 2026 (the 14 insights/*.html articles). Every
   selector sits under #article-body, which exists on the articles only.
   Like the legal clauses before their pass, the article prose had no rules
   beyond the link colour: body-default Inter 400, browser h2 sizes and,
   after the global reset, no paragraph spacing at all. Same treatment as
   the LEGAL PAGES block: Playfair h2 on the .ak-h3 scale, Familjen Grotesk
   400 16px prose, .formula on --card with a hairline. No copper beyond the
   existing link rule.
   ═══════════════════════════════════════════════════════════════════════ */
#article-body p {
  font-family: 'Familjen Grotesk', 'Inter', sans-serif;
  font-size: 16px; line-height: 1.7; color: var(--text);
}
#article-body p + p,
#article-body p + .formula,
#article-body .formula + p { margin-top: 18px; }
#article-body h2 {
  margin: 48px 0 16px;
  font-family: 'Playfair', 'Familjen Grotesk', 'Inter', sans-serif;
  font-size: clamp(22px, 2.6vw, 30px); font-weight: 700; line-height: 1.15;
  letter-spacing: var(--tracking-display); color: var(--text);
}
#article-body h2:first-child { margin-top: 0; }
#article-body .formula {
  padding: 16px 20px;
  background: var(--card);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-card);
  font-family: 'Familjen Grotesk', 'Inter', sans-serif;
  font-size: 15px; font-weight: 600; line-height: 1.5; color: var(--text);
}
@media (max-width: 600px) {
  #article-body h2 { margin-top: 40px; }
  #article-body .formula { padding: 14px 16px; }
}
/* FAQ answers and the Insights index cards, same day. Both fell back to the
   body's Inter: `.faq-answer p` sets spacing only, and the cards' h2 and p
   carry inline size and colour but no family. Family only; sizes, weights
   and colours unchanged. `.faq-answer` exists on faq.html only and
   `.article-card` on insights.html only. */
.faq-answer p,
.article-card h2,
.article-card p { font-family: 'Familjen Grotesk', 'Inter', sans-serif; }

/* ══════════════════════════════════════════════════════════════════════
   UX AUDIT — 26 September 2026
   Rules added by the sitewide UX, visual and interaction audit. Each group
   is namespaced to the page or section it serves.
   ══════════════════════════════════════════════════════════════════════ */

/* HOMEPAGE 03 — the call simulator's caller choice. Neutral pills with a
   copper perimeter when chosen (accent rule: perimeter and interaction
   only), the same shape as .act-slot so the choice and the branch it
   produces read as one vocabulary. */
.act-scen {
  display: flex; align-items: center; flex-wrap: wrap; gap: 10px 14px;
  padding: 12px 18px;
  border-top: 1px solid var(--hairline);
}
.act-scen .ui-meta { flex: none; }
.act-scen-opts { display: flex; flex-wrap: wrap; gap: 8px; }
.act-scen-btn {
  display: inline-flex; align-items: center; min-height: 36px;
  padding: 7px 14px;
  background: transparent; color: var(--text-dim);
  border: 1px solid var(--hairline-hover); border-radius: var(--radius-pill);
  font-family: 'Familjen Grotesk', 'Inter', sans-serif;
  font-size: 13px; font-weight: 500; line-height: 1.2;
  cursor: pointer;
  transition: background 140ms var(--ease), border-color 140ms var(--ease), color 140ms var(--ease);
}
.act-scen-btn:hover { background: var(--ghost-hover); color: var(--text); }
.act-scen-btn[aria-pressed="true"] { border-color: var(--blue); color: var(--text); }
.act-scen-btn:focus-visible { outline: 2px solid var(--blue); outline-offset: 3px; }
.act .ui-btn { min-height: 36px; }
.act .ui-btn[aria-disabled="true"] { opacity: 0.45; cursor: default; }
.act .ui-btn[aria-disabled="true"]:hover { background: transparent; border-color: var(--tag-border); }
/* understood / did rows carry a value on the right */
.act-items > li:has(> .mini-detail) { grid-template-columns: 14px minmax(0, 1fr) auto; }
.act-items .mini-detail { margin-left: 10px; }
.act-note {
  margin: 0; padding: 12px 18px 14px;
  border-top: 1px solid var(--hairline);
  font-family: 'Familjen Grotesk', 'Inter', sans-serif;
  font-size: 12px; line-height: 1.45; color: var(--meta-ui);
}
@media (max-width: 860px) {
  .act-controls { flex-wrap: wrap; }
  .act-stage { flex-basis: 100%; margin: 0 0 2px; }
}
@media (pointer: coarse), (max-width: 720px) {
  .act .ui-btn, .act-scen-btn { min-height: 44px; }
}

/* ASK ASTRO — the real journey under every CTA (Brain\Astro_cta_sales_
   process.md): four quiet steps, hairline connectors, no copper. It says
   what happens after asking without turning the CTA into a funnel. */
#chat-cta .ask-journey {
  display: flex; flex-wrap: wrap; justify-content: center; align-items: center;
  gap: 8px 0;
  list-style: none; margin: 28px auto 0; padding: 0;
  font-family: 'Familjen Grotesk', 'Inter', sans-serif;
  font-size: 12px; font-weight: 500; letter-spacing: 0.5px;
  text-transform: uppercase; color: var(--meta-ui);
}
#chat-cta .ask-journey > li { display: inline-flex; align-items: center; }
#chat-cta .ask-journey > li + li::before {
  content: ''; display: inline-block;
  width: 28px; height: 1px; margin: 0 12px;
  background: var(--hairline-hover);
}
#chat-cta .ask-journey + .chat-cta-fallback { margin-top: 18px; }
/* at phone width a wrapped line would start with a dangling connector, so
   the four steps become a numbered two-by-two grid: every step's ::before
   is a small numbered ring instead of a connector */
@media (max-width: 560px) {
  #chat-cta .ask-journey {
    display: grid; grid-template-columns: repeat(2, max-content);
    justify-content: center; gap: 10px 28px; counter-reset: journey;
  }
  #chat-cta .ask-journey > li { gap: 8px; counter-increment: journey; }
  #chat-cta .ask-journey > li::before,
  #chat-cta .ask-journey > li + li::before {
    content: counter(journey);
    display: inline-flex; align-items: center; justify-content: center;
    width: 18px; height: 18px; margin: 0;
    background: none;
    border: 1px solid var(--hairline-hover); border-radius: 50%;
    font-size: 10px; letter-spacing: 0;
  }
}

/* REDUCE ADMIN 03 — Run, Step and Reset moved onto the engine */
.page-admin .admin-engine .ak-bar { flex-wrap: wrap; gap: 12px 20px; }
.page-admin .admin-engine .ui-btn[aria-disabled="true"] { opacity: 0.45; cursor: default; }
.page-admin .admin-engine .ui-btn[aria-disabled="true"]:hover { background: transparent; }
@media (max-width: 720px) {
  .page-admin .admin-engine .admin-demo-controls { width: 100%; }
  .page-admin .admin-engine .admin-demo-controls .ui-btn { flex: 1 1 0; min-height: 44px; }
}

/* the panel-foot notes on the queue and the engine sat flush against the
   panel's left edge (found by the audit, padding 0 on a direct child of
   .ui-panel); the same inset as the other panels' notes */
.page-admin .admin-queue > .ak-note,
.page-admin .admin-engine > .ak-note { padding: 12px 18px 14px; }

/* INCREASE LEADS 03 — the entry channels are buttons now */
.page-leads .lead-engine .ak-node-btn[aria-pressed="true"] { border-color: var(--blue); }

/* HOME VISUAL ART, 27 Sept 2026 — two bespoke plates (ASTRO-HOMEPAGE-COSMIC-01
   in #products, ASTRO-HOMEPAGE-ARCHITECTURAL-01 in #day). Decorative only:
   aria-hidden, alt="". Each sits at z-index -1 inside its section's stacking
   context (.section is position:relative; z-index:2), so it paints over the
   starfield ground and under every panel and line of type. Screen blend is
   what embeds them: the plates' near-black grounds (#030305 / #09090d, the
   same value as --bg) add nothing, so only the lit forms and their stars
   come through, with no rectangle edge. Masks only feather the edges that
   would otherwise meet content. Hidden, not squeezed, where the layout has
   no room for them (display:none also stops the lazy image loading). */
.sec-art {
  position: absolute; z-index: -1; pointer-events: none;
  mix-blend-mode: screen;
}
.sec-art img { display: block; width: 100%; height: 100%; }

/* 04: the planet's horizon crosses the empty centre-right of the section and
   carries on over the boundary into #manual-automated, dissolving just above
   its headline, so the sky reads as one space through the transition.
   28 Sept 2026 (James): 1.9x the section width, so only the lit horizon of
   something far bigger enters the frame.
   Two layers, one plate. Each section paints its own opaque starfield, so a
   plate overflowing #products would vanish under the next section; instead
   #manual-automated carries a second copy (same file, same srcset, so no
   second download) with identical scale and x, positioned against the same
   boundary: #products anchors the plate's bottom to its bottom edge, the
   bridge anchors (plate bottom - 100%) to its top edge. Both are screen-
   blended into their own section's starfield.
   Fade: one linear ramp across the boundary. Full strength 200px above it,
   0.35 at it, zero --pl-bridge below it. --pl-bridge follows the headline,
   which sits in a sticky stage centred in the viewport, so its distance from
   the boundary grows with viewport height (measured: 80px at 800 tall, 118px
   at 900, 208px at 1080). The plate keeps its own left/top fades. */
.sec-art--planet, .sec-art--planet-bridge {
  --pl-scale: 1.9; --pl-x: 7%; --pl-y: 36%;
  --pl-bridge: clamp(60px, 50vh - 335px, 200px);
  overflow: hidden; opacity: 0.85;
}
.sec-art--planet {
  inset: 0;
  -webkit-mask-image: linear-gradient(to top, rgba(0,0,0,0.35) 0, #000 200px);
          mask-image: linear-gradient(to top, rgba(0,0,0,0.35) 0, #000 200px);
}
.sec-art--planet-bridge {
  top: 0; left: 0; right: 0; height: var(--pl-bridge);
  -webkit-mask-image: linear-gradient(to bottom, rgba(0,0,0,0.35) 0, transparent 100%);
          mask-image: linear-gradient(to bottom, rgba(0,0,0,0.35) 0, transparent 100%);
}
/* without the sticky stage the headline sits at the section's own padding */
.xf-section:not(.is-scrub) .sec-art--planet-bridge { --pl-bridge: 90px; }
.sec-art--planet img, .sec-art--planet-bridge img {
  position: absolute; right: 0;
  width: calc(100% * var(--pl-scale)); height: auto; aspect-ratio: 2400 / 1018;
  -webkit-mask-image: linear-gradient(to right, transparent 30%, #000 62%), linear-gradient(to bottom, transparent 0%, #000 38%);
          mask-image: linear-gradient(to right, transparent 30%, #000 62%), linear-gradient(to bottom, transparent 0%, #000 38%);
  -webkit-mask-composite: source-in; mask-composite: intersect;
}
.sec-art--planet img { bottom: 0; transform: translate(var(--pl-x), var(--pl-y)); }
.sec-art--planet-bridge img { top: 0; transform: translate(var(--pl-x), calc(var(--pl-y) - 100%)); }
/* once the map stacks into the accordion, the lower right is the spec row */
@media (max-width: 900px) { .sec-art--planet, .sec-art--planet-bridge { display: none; } }

/* 06: the architecture is sized and placed from the timeline's width, not
   the viewport's, so the lit doorway always lands on the same hours: just
   after 18:00, clear of the 18:00 tick and of the 21:47 label, at every
   desktop width. --w is the timeline's width (the .home-wide container's
   content box: 1240 max less 2x40 padding); the plate is 1.3x that wide and
   shifted so image x 0.665-0.75 (the doorway and its lit wall) falls at
   roughly 0.71-0.82 of the axis. It is feathered on its own edges, since at
   wide screens it ends short of the viewport edge. */
.day-sticky { position: relative; }
.sec-art--arch {
  inset: 0; overflow: hidden; opacity: 0.46;
  --w: min(100% - 80px, 1160px);
}
.sec-art--arch img {
  position: absolute; top: 50%; height: auto;
  width: calc(var(--w) * 1.3);
  left: calc((100% - var(--w)) / 2 - var(--w) * 0.225);
  transform: translateY(-50%);
  -webkit-mask-image: linear-gradient(to right, transparent 8%, #000 64%, #000 84%, transparent 100%), linear-gradient(to bottom, transparent 0%, rgba(0,0,0,0.4) 22%, #000 42%, #000 76%, transparent 100%);
          mask-image: linear-gradient(to right, transparent 8%, #000 64%, #000 84%, transparent 100%), linear-gradient(to bottom, transparent 0%, rgba(0,0,0,0.4) 22%, #000 42%, #000 76%, transparent 100%);
  -webkit-mask-composite: source-in; mask-composite: intersect;
}
/* narrower desktops scale the plate down, which lifts the lit face towards
   the 16:31 label row; a touch less strength keeps it at AA */
@media (max-width: 1199px) { .sec-art--arch { opacity: 0.38; } }
.day-section:not(.is-scrub) .sec-art--arch { display: none; }


/* ═══════════════════════════════════════════════════════════════════════
   ASK ASTRO LINK FIELD, 27 Sept 2026 (delta pass, Claude Code). The
   reference pages' closing CTA (FAQ, Ask Astro, ROI, Insights, articles,
   legal) was a DISABLED input and a DISABLED button: a dead control that
   implied a chat that could not be reached. It is now one real link with
   the same look. astro-chat.js already intercepts any #chat-cta link and
   opens the chat panel, which states honestly that the assistant is not
   connected yet and gives the direct email. No new behaviour; the copper
   use is the focus ring only (permitted, CR-36).
   ═══════════════════════════════════════════════════════════════════════ */
a.chat-cta-link { display: block; text-decoration: none; color: inherit; cursor: pointer; transition: border-color 0.18s; }
a.chat-cta-link .chat-cta-input-row { display: flex; }
a.chat-cta-link .chat-cta-input { color: var(--text-dim); text-align: left; }
a.chat-cta-link:hover { border-color: var(--hairline-hover); }
a.chat-cta-link:hover .chat-cta-send { background: var(--ghost-hover); }
a.chat-cta-link:focus-visible { outline: 2px solid var(--blue); outline-offset: 3px; }


/* ═══════════════════════════════════════════════════════════════════════
   PAGE IMAGE PASS, 28 Sept 2026 (final photographic art direction). Six
   plates on four pages, built on the homepage .sec-art pattern: decorative
   (aria-hidden, alt=""), z-index -1 inside the section's stacking context,
   so each sits over the starfield and under every panel and line of type.
   Each file carries its own grade and its own grain (baked per file size by
   `Astro AI Offers\Images\Other pages\grade_astro_plates.py`), so no CSS
   filter or overlay is applied here.
     About    #page-header      ASTRO-ABOUT-HUMAN-01   the window, full bleed
     About    #how-astro-works  ASTRO-ABOUT-HUMAN-02   the process table
     Admin    #admin-queue      ASTRO-ADMIN-HUMAN-01   the desk
     Admin    #review-queue     ASTRO-ADMIN-COSMIC-01  star trails (screen)
     Pricing  #scope-builder    ASTRO-PRICING-ARCHITECTURAL-01  the beam
     Work     #system-selector  ASTRO-WORK-COSMIC-01   the planet
   Photographs use normal blending (screen washes out skin and cloth, and
   would let stars show through a room), and so does the planet, whose body
   must hide the stars behind it; the star trails keep screen, as on the
   homepage. Masks only feather the edges that meet content.
   Desktop (1100px and up): a plate sits in the space right of a section's
   intro, and the intro gets a min-height so the subject clears the panel
   below. Under 1100px there is no such space, so a plate becomes a band at
   the top of its section, cropped to its subject, with the intro starting
   over the band's faded foot.
   ═══════════════════════════════════════════════════════════════════════ */
.pg-art img { object-fit: cover; }
/* the planet too: a solid body should hide the stars behind it, which
   screen blending cannot do; its frame's black is the page's black */
.pg-art--window, .pg-art--discover, .pg-art--desk, .pg-art--concrete, .pg-art--planet { mix-blend-mode: normal; }

/* About 01: the window. In flow after the hero grid, full bleed; the top
   runs up behind the hero's foot (the photograph's ceiling is dark there)
   and the bottom reaches the section edge. City and scale first, then the
   person, then the lamp. */
.pg-art--window {
  position: relative; inset: auto; display: block;
  height: clamp(440px, 44vw, 720px);
  margin: -150px 0 -105px;
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 26%, #000 70%, transparent 100%), linear-gradient(to right, transparent 0, #000 12%, #000 90%, transparent 100%);
          mask-image: linear-gradient(to bottom, transparent 0, #000 26%, #000 70%, transparent 100%), linear-gradient(to right, transparent 0, #000 12%, #000 90%, transparent 100%);
  -webkit-mask-composite: source-in; mask-composite: intersect;
}
.pg-art--window img { object-position: 52% 58%; }

@media (min-width: 1100px) {
  .pg-art--discover, .pg-art--desk, .pg-art--trails {
    top: 0; right: 0;
    -webkit-mask-composite: source-in; mask-composite: intersect;
  }
  /* About 06: two people over the maps, right of "How Astro works." */
  .page-about #how-astro-works .ak-intro { min-height: 300px; }
  .pg-art--discover {
    width: 62%; height: 480px;
    -webkit-mask-image: linear-gradient(to right, transparent 0, transparent 8%, #000 60%), linear-gradient(to bottom, transparent 0, #000 34%, #000 70%, transparent 100%);
            mask-image: linear-gradient(to right, transparent 0, transparent 8%, #000 60%), linear-gradient(to bottom, transparent 0, #000 34%, #000 70%, transparent 100%);
  }
  .pg-art--discover img { object-position: 100% 72%; }

  /* Reduce Admin 02: the desk. The photograph's dark left half runs in
     under the headline; its lit left windows are masked away. */
  .page-admin #admin-queue .ak-intro { min-height: 320px; }
  .pg-art--desk {
    width: 66%; height: 490px;
    -webkit-mask-image: linear-gradient(to right, transparent 0, transparent 14%, #000 50%), linear-gradient(to bottom, transparent 0, #000 30%, #000 72%, transparent 100%);
            mask-image: linear-gradient(to right, transparent 0, transparent 14%, #000 50%), linear-gradient(to bottom, transparent 0, #000 30%, #000 72%, transparent 100%);
  }
  .pg-art--desk img { object-position: 100% 60%; }

  /* Reduce Admin 06: star trails around a pole off the top right corner,
     the queue that keeps turning while only the exception reaches you */
  .pg-art--trails {
    width: 74%; height: 100%; opacity: 0.85;
    -webkit-mask-image: linear-gradient(to right, transparent 0, transparent 26%, #000 64%), linear-gradient(to bottom, #000 0, #000 40%, transparent 85%);
            mask-image: linear-gradient(to right, transparent 0, transparent 26%, #000 64%), linear-gradient(to bottom, #000 0, #000 40%, transparent 85%);
  }
  .pg-art--trails img { object-position: 100% 0; }

  /* Pricing 03: the ground of the whole intro. The room's left half is
     already black, so the headline sits in it; the beam comes down to the
     top of the scope panel. Kept clear of copy: an architectural pause. */
  .page-pricing #scope-builder .ak-intro { min-height: 400px; }
  .pg-art--concrete {
    top: 0; left: 0; right: 0; height: 620px; opacity: 0.92;
    -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 16%, #000 80%, transparent 100%);
            mask-image: linear-gradient(to bottom, transparent 0, #000 16%, #000 80%, transparent 100%);
  }
  .pg-art--concrete img { object-position: 50% 64%; }

  /* Work 02: the planet, sized from its own radius (--r) and placed from
     the content column's centre, so its top sits 60px into the section and
     its lit rim arcs through the space right of the intro, then down past
     the panel's right edge. The body is black, so the panel hides nothing
     that matters. Plate geometry: centre (0.68, 0.475) of the frame,
     radius 0.2125 of its width, 2400x1493. The moon lands just under the
     panel's lower right; the last 140px fade so the next section's
     starfield meets no edge. */
  .page-work #system-selector .ak-intro { min-height: 250px; }
  .pg-art--planet {
    inset: 0; --r: clamp(300px, 25vw, 400px); opacity: 0.9;
    -webkit-mask-image: linear-gradient(to right, transparent 0, transparent 40%, #000 56%), linear-gradient(to bottom, #000 0, #000 calc(100% - 140px), transparent 100%);
            mask-image: linear-gradient(to right, transparent 0, transparent 40%, #000 56%), linear-gradient(to bottom, #000 0, #000 calc(100% - 140px), transparent 100%);
    -webkit-mask-composite: source-in; mask-composite: intersect;
  }
  .pg-art--planet img {
    position: absolute; object-fit: fill;
    width: calc(var(--r) * 4.706); height: auto; aspect-ratio: 2400 / 1493;
    left: calc(50% + 470px - var(--r) * 3.2);
    top: calc(60px - var(--r) * 0.39);
  }
}

/* Under 1100px: a band at the top of the section, cropped to its subject */
@media (max-width: 1099px) {
  .pg-art--discover, .pg-art--desk, .pg-art--trails, .pg-art--concrete, .pg-art--planet {
    position: relative; inset: auto; display: block;
    height: clamp(230px, 52vw, 440px);
    margin: -105px 0 -48px;
    -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 18%, #000 60%, transparent 100%);
            mask-image: linear-gradient(to bottom, transparent 0, #000 18%, #000 60%, transparent 100%);
  }
  .pg-art--discover img { object-position: 74% 66%; }
  .pg-art--desk img { object-position: 80% 56%; }
  .pg-art--trails { opacity: 0.8; }
  .pg-art--trails img { object-position: 100% 0; }
  .pg-art--concrete img { object-position: 72% 50%; }
  .pg-art--planet { height: clamp(250px, 60vw, 470px); }
  .pg-art--planet img { object-position: 70% 50%; }
  .pg-art--window { height: clamp(300px, 64vw, 560px); margin-top: -40px; }
  .pg-art--window img { object-position: 46% 58%; }
}
@media (max-width: 720px) {
  .pg-art--discover, .pg-art--desk, .pg-art--trails, .pg-art--concrete, .pg-art--planet { margin-top: -54px; margin-bottom: -28px; }
  .pg-art--window { margin-bottom: -54px; height: clamp(300px, 86vw, 420px); }
  /* on a phone the person matters more than the room: a taller band,
     and a closer crop scaled from the subject so no face is cut */
  .pg-art--discover, .pg-art--desk { height: clamp(250px, 72vw, 340px); }
  .pg-art--discover img { transform: scale(1.4); transform-origin: 72% 62%; }
  .pg-art--desk img { transform: scale(1.45); transform-origin: 80% 52%; }
  .pg-art--window img { object-position: 42% 58%; }
}


/* ═══════════════════════════════════════════════════════════════════════
   FINAL REFINEMENT PASS, 30 Sept 2026 (Claude Code). Image blending.
   The 28 Sept plates were masked with two-stop linear fades, which band
   and read as edges, and two of the photographs carry a hard dark pillar of
   their own on the left (the desk and the process table), so the fade ran
   straight across a crisp vertical line. Each plate now fades on an eased
   curve (smoothstep, nine stops), is fully transparent until past its own
   pillar, and is rounded by a radial term, so the photograph emerges from
   the starfield: stars, then darkness, then the shadowed room, then the
   lit subject. The star trails also fade at the section's top edge, where
   they used to start at full strength against the section above, and their
   outline is two offset ellipses rather than one, so the fade is not
   concentric with the trails. Nothing is laid over any image; no filter.
   ═══════════════════════════════════════════════════════════════════════ */
@media (min-width: 1100px) {
  .pg-art--desk {
    -webkit-mask-image:
    linear-gradient(to right, transparent 22.0%, rgba(0,0,0,0.04) 27.5%, rgba(0,0,0,0.16) 33.0%, rgba(0,0,0,0.32) 38.5%, rgba(0,0,0,0.50) 44.0%, rgba(0,0,0,0.68) 49.5%, rgba(0,0,0,0.84) 55.0%, rgba(0,0,0,0.96) 60.5%, #000 66.0%),
    linear-gradient(to bottom, transparent 0.0%, rgba(0,0,0,0.04) 5.0%, rgba(0,0,0,0.16) 10.0%, rgba(0,0,0,0.32) 15.0%, rgba(0,0,0,0.50) 20.0%, rgba(0,0,0,0.68) 25.0%, rgba(0,0,0,0.84) 30.0%, rgba(0,0,0,0.96) 35.0%, #000 40.0%, #000 62.0%, rgba(0,0,0,0.96) 66.8%, rgba(0,0,0,0.84) 71.5%, rgba(0,0,0,0.68) 76.2%, rgba(0,0,0,0.50) 81.0%, rgba(0,0,0,0.32) 85.8%, rgba(0,0,0,0.16) 90.5%, rgba(0,0,0,0.04) 95.2%, transparent 100.0%),
    radial-gradient(ellipse 78% 92% at 68% 48%, #000 58.0%, rgba(0,0,0,0.93) 65.0%, rgba(0,0,0,0.74) 72.0%, rgba(0,0,0,0.50) 79.0%, rgba(0,0,0,0.26) 86.0%, rgba(0,0,0,0.07) 93.0%, transparent 100.0%);
            mask-image:
    linear-gradient(to right, transparent 22.0%, rgba(0,0,0,0.04) 27.5%, rgba(0,0,0,0.16) 33.0%, rgba(0,0,0,0.32) 38.5%, rgba(0,0,0,0.50) 44.0%, rgba(0,0,0,0.68) 49.5%, rgba(0,0,0,0.84) 55.0%, rgba(0,0,0,0.96) 60.5%, #000 66.0%),
    linear-gradient(to bottom, transparent 0.0%, rgba(0,0,0,0.04) 5.0%, rgba(0,0,0,0.16) 10.0%, rgba(0,0,0,0.32) 15.0%, rgba(0,0,0,0.50) 20.0%, rgba(0,0,0,0.68) 25.0%, rgba(0,0,0,0.84) 30.0%, rgba(0,0,0,0.96) 35.0%, #000 40.0%, #000 62.0%, rgba(0,0,0,0.96) 66.8%, rgba(0,0,0,0.84) 71.5%, rgba(0,0,0,0.68) 76.2%, rgba(0,0,0,0.50) 81.0%, rgba(0,0,0,0.32) 85.8%, rgba(0,0,0,0.16) 90.5%, rgba(0,0,0,0.04) 95.2%, transparent 100.0%),
    radial-gradient(ellipse 78% 92% at 68% 48%, #000 58.0%, rgba(0,0,0,0.93) 65.0%, rgba(0,0,0,0.74) 72.0%, rgba(0,0,0,0.50) 79.0%, rgba(0,0,0,0.26) 86.0%, rgba(0,0,0,0.07) 93.0%, transparent 100.0%);
    -webkit-mask-composite: source-in, source-in;
            mask-composite: intersect, intersect;
  }
  .pg-art--discover {
    -webkit-mask-image:
    linear-gradient(to right, transparent 31.0%, rgba(0,0,0,0.04) 35.1%, rgba(0,0,0,0.16) 39.2%, rgba(0,0,0,0.32) 43.4%, rgba(0,0,0,0.50) 47.5%, rgba(0,0,0,0.68) 51.6%, rgba(0,0,0,0.84) 55.8%, rgba(0,0,0,0.96) 59.9%, #000 64.0%),
    linear-gradient(to bottom, transparent 0.0%, rgba(0,0,0,0.04) 4.0%, rgba(0,0,0,0.16) 8.0%, rgba(0,0,0,0.32) 12.0%, rgba(0,0,0,0.50) 16.0%, rgba(0,0,0,0.68) 20.0%, rgba(0,0,0,0.84) 24.0%, rgba(0,0,0,0.96) 28.0%, #000 32.0%, #000 66.0%, rgba(0,0,0,0.96) 70.2%, rgba(0,0,0,0.84) 74.5%, rgba(0,0,0,0.68) 78.8%, rgba(0,0,0,0.50) 83.0%, rgba(0,0,0,0.32) 87.2%, rgba(0,0,0,0.16) 91.5%, rgba(0,0,0,0.04) 95.8%, transparent 100.0%),
    radial-gradient(ellipse 76% 92% at 70% 50%, #000 58.0%, rgba(0,0,0,0.93) 65.0%, rgba(0,0,0,0.74) 72.0%, rgba(0,0,0,0.50) 79.0%, rgba(0,0,0,0.26) 86.0%, rgba(0,0,0,0.07) 93.0%, transparent 100.0%);
            mask-image:
    linear-gradient(to right, transparent 31.0%, rgba(0,0,0,0.04) 35.1%, rgba(0,0,0,0.16) 39.2%, rgba(0,0,0,0.32) 43.4%, rgba(0,0,0,0.50) 47.5%, rgba(0,0,0,0.68) 51.6%, rgba(0,0,0,0.84) 55.8%, rgba(0,0,0,0.96) 59.9%, #000 64.0%),
    linear-gradient(to bottom, transparent 0.0%, rgba(0,0,0,0.04) 4.0%, rgba(0,0,0,0.16) 8.0%, rgba(0,0,0,0.32) 12.0%, rgba(0,0,0,0.50) 16.0%, rgba(0,0,0,0.68) 20.0%, rgba(0,0,0,0.84) 24.0%, rgba(0,0,0,0.96) 28.0%, #000 32.0%, #000 66.0%, rgba(0,0,0,0.96) 70.2%, rgba(0,0,0,0.84) 74.5%, rgba(0,0,0,0.68) 78.8%, rgba(0,0,0,0.50) 83.0%, rgba(0,0,0,0.32) 87.2%, rgba(0,0,0,0.16) 91.5%, rgba(0,0,0,0.04) 95.8%, transparent 100.0%),
    radial-gradient(ellipse 76% 92% at 70% 50%, #000 58.0%, rgba(0,0,0,0.93) 65.0%, rgba(0,0,0,0.74) 72.0%, rgba(0,0,0,0.50) 79.0%, rgba(0,0,0,0.26) 86.0%, rgba(0,0,0,0.07) 93.0%, transparent 100.0%);
    -webkit-mask-composite: source-in, source-in;
            mask-composite: intersect, intersect;
  }
  .pg-art--trails {
    -webkit-mask-image:
    linear-gradient(to bottom, transparent 0.0%, rgba(0,0,0,0.04) 3.2%, rgba(0,0,0,0.16) 6.5%, rgba(0,0,0,0.32) 9.8%, rgba(0,0,0,0.50) 13.0%, rgba(0,0,0,0.68) 16.2%, rgba(0,0,0,0.84) 19.5%, rgba(0,0,0,0.96) 22.8%, #000 26.0%),
    linear-gradient(to right, transparent 20.0%, rgba(0,0,0,0.04) 25.2%, rgba(0,0,0,0.16) 30.5%, rgba(0,0,0,0.32) 35.8%, rgba(0,0,0,0.50) 41.0%, rgba(0,0,0,0.68) 46.2%, rgba(0,0,0,0.84) 51.5%, rgba(0,0,0,0.96) 56.8%, #000 62.0%),
    radial-gradient(ellipse 88% 78% at 90% 14%, #000 34.0%, rgba(0,0,0,0.93) 45.0%, rgba(0,0,0,0.74) 56.0%, rgba(0,0,0,0.50) 67.0%, rgba(0,0,0,0.26) 78.0%, rgba(0,0,0,0.07) 89.0%, transparent 100.0%),
    radial-gradient(ellipse 52% 46% at 66% 64%, #000 0.0%, rgba(0,0,0,0.93) 16.7%, rgba(0,0,0,0.74) 33.3%, rgba(0,0,0,0.50) 50.0%, rgba(0,0,0,0.26) 66.7%, rgba(0,0,0,0.07) 83.3%, transparent 100.0%);
            mask-image:
    linear-gradient(to bottom, transparent 0.0%, rgba(0,0,0,0.04) 3.2%, rgba(0,0,0,0.16) 6.5%, rgba(0,0,0,0.32) 9.8%, rgba(0,0,0,0.50) 13.0%, rgba(0,0,0,0.68) 16.2%, rgba(0,0,0,0.84) 19.5%, rgba(0,0,0,0.96) 22.8%, #000 26.0%),
    linear-gradient(to right, transparent 20.0%, rgba(0,0,0,0.04) 25.2%, rgba(0,0,0,0.16) 30.5%, rgba(0,0,0,0.32) 35.8%, rgba(0,0,0,0.50) 41.0%, rgba(0,0,0,0.68) 46.2%, rgba(0,0,0,0.84) 51.5%, rgba(0,0,0,0.96) 56.8%, #000 62.0%),
    radial-gradient(ellipse 88% 78% at 90% 14%, #000 34.0%, rgba(0,0,0,0.93) 45.0%, rgba(0,0,0,0.74) 56.0%, rgba(0,0,0,0.50) 67.0%, rgba(0,0,0,0.26) 78.0%, rgba(0,0,0,0.07) 89.0%, transparent 100.0%),
    radial-gradient(ellipse 52% 46% at 66% 64%, #000 0.0%, rgba(0,0,0,0.93) 16.7%, rgba(0,0,0,0.74) 33.3%, rgba(0,0,0,0.50) 50.0%, rgba(0,0,0,0.26) 66.7%, rgba(0,0,0,0.07) 83.3%, transparent 100.0%);
    -webkit-mask-composite: source-in, source-in, source-over;
            mask-composite: intersect, intersect, add;
  }
  .pg-art--trails { opacity: 0.8; }
}
@media (max-width: 1099px) {
  .pg-art--discover, .pg-art--desk, .pg-art--trails, .pg-art--concrete, .pg-art--planet {
    -webkit-mask-image:
    linear-gradient(to bottom, transparent 0.0%, rgba(0,0,0,0.04) 2.8%, rgba(0,0,0,0.16) 5.5%, rgba(0,0,0,0.32) 8.2%, rgba(0,0,0,0.50) 11.0%, rgba(0,0,0,0.68) 13.8%, rgba(0,0,0,0.84) 16.5%, rgba(0,0,0,0.96) 19.2%, #000 22.0%, #000 56.0%, rgba(0,0,0,0.96) 61.5%, rgba(0,0,0,0.84) 67.0%, rgba(0,0,0,0.68) 72.5%, rgba(0,0,0,0.50) 78.0%, rgba(0,0,0,0.32) 83.5%, rgba(0,0,0,0.16) 89.0%, rgba(0,0,0,0.04) 94.5%, transparent 100.0%);
            mask-image:
    linear-gradient(to bottom, transparent 0.0%, rgba(0,0,0,0.04) 2.8%, rgba(0,0,0,0.16) 5.5%, rgba(0,0,0,0.32) 8.2%, rgba(0,0,0,0.50) 11.0%, rgba(0,0,0,0.68) 13.8%, rgba(0,0,0,0.84) 16.5%, rgba(0,0,0,0.96) 19.2%, #000 22.0%, #000 56.0%, rgba(0,0,0,0.96) 61.5%, rgba(0,0,0,0.84) 67.0%, rgba(0,0,0,0.68) 72.5%, rgba(0,0,0,0.50) 78.0%, rgba(0,0,0,0.32) 83.5%, rgba(0,0,0,0.16) 89.0%, rgba(0,0,0,0.04) 94.5%, transparent 100.0%);
    -webkit-mask-composite: source-over;
            mask-composite: add;
  }

}

/* ── About 01, the window (30 Sept 2026, final refinement pass) ──
   The hero's interface panel sat over the photograph's upper half and hid
   most of the window. At 1100px and up the hero is recomposed: copy and a
   compacted introduction panel take the left 45% or so, and the photograph
   is the ground of the right two thirds, full height, unobstructed. Its
   left third is the room's own dark wall, which carries the feather:
   fully transparent at the plate's left edge, eased to opaque by 30% of
   its width, so the starfield darkens into the wall and the wall opens
   onto the window. The man, the Empire State Building, the window bars
   and the desk lamp all sit in the opaque part at every desktop width.
   Top and bottom feather into the nav shadow and the hero's foot. Under
   1100px the 28 Sept band after the content is unchanged. */
@media (min-width: 1100px) {
  .page-about #page-header { padding-bottom: 76px; }
  .page-about #page-header .ak-hero-grid {
    position: relative; z-index: 1;
    grid-template-columns: minmax(0, min(520px, 44vw)); gap: 34px; align-items: start;
  }
  .page-about #page-header .section-headline { max-width: 520px; }
  .page-about .ab-intro { max-width: 470px; }
  .page-about .ab-intro > .ui-head { padding-top: 12px; padding-bottom: 12px; }
  .page-about .ab-intro-body { padding: 14px 16px 4px; }
  .page-about .ab-intro .ak-group { padding: 10px 12px 12px; }
  .page-about .ab-intro .ak-group-nodes { gap: 6px; margin-top: 8px; }
  .page-about .ab-intro .ak-node { font-size: 12px; padding: 5px 10px; gap: 7px; }
  .page-about .ab-intro .ak-core { padding: 8px 14px; }
  .page-about .ab-drop { height: 16px; }
  .page-about .ab-intro > .ak-note { padding: 6px 16px 12px; }
  .pg-art--window {
    position: absolute; top: 0; right: 0; bottom: 0; left: 34%;
    height: auto; margin: 0;
    -webkit-mask-image:
      linear-gradient(to right, transparent 0.0%, rgba(0,0,0,0.04) 3.8%, rgba(0,0,0,0.16) 7.5%, rgba(0,0,0,0.32) 11.2%, rgba(0,0,0,0.50) 15.0%, rgba(0,0,0,0.68) 18.8%, rgba(0,0,0,0.84) 22.5%, rgba(0,0,0,0.96) 26.2%, #000 30.0%),
      linear-gradient(to bottom, transparent 0.0%, rgba(0,0,0,0.04) 2.0%, rgba(0,0,0,0.16) 4.0%, rgba(0,0,0,0.32) 6.0%, rgba(0,0,0,0.50) 8.0%, rgba(0,0,0,0.68) 10.0%, rgba(0,0,0,0.84) 12.0%, rgba(0,0,0,0.96) 14.0%, #000 16.0%, #000 78.0%, rgba(0,0,0,0.96) 80.8%, rgba(0,0,0,0.84) 83.5%, rgba(0,0,0,0.68) 86.2%, rgba(0,0,0,0.50) 89.0%, rgba(0,0,0,0.32) 91.8%, rgba(0,0,0,0.16) 94.5%, rgba(0,0,0,0.04) 97.2%, transparent 100.0%);
            mask-image:
      linear-gradient(to right, transparent 0.0%, rgba(0,0,0,0.04) 3.8%, rgba(0,0,0,0.16) 7.5%, rgba(0,0,0,0.32) 11.2%, rgba(0,0,0,0.50) 15.0%, rgba(0,0,0,0.68) 18.8%, rgba(0,0,0,0.84) 22.5%, rgba(0,0,0,0.96) 26.2%, #000 30.0%),
      linear-gradient(to bottom, transparent 0.0%, rgba(0,0,0,0.04) 2.0%, rgba(0,0,0,0.16) 4.0%, rgba(0,0,0,0.32) 6.0%, rgba(0,0,0,0.50) 8.0%, rgba(0,0,0,0.68) 10.0%, rgba(0,0,0,0.84) 12.0%, rgba(0,0,0,0.96) 14.0%, #000 16.0%, #000 78.0%, rgba(0,0,0,0.96) 80.8%, rgba(0,0,0,0.84) 83.5%, rgba(0,0,0,0.68) 86.2%, rgba(0,0,0,0.50) 89.0%, rgba(0,0,0,0.32) 91.8%, rgba(0,0,0,0.16) 94.5%, rgba(0,0,0,0.04) 97.2%, transparent 100.0%);
    -webkit-mask-composite: source-in;
            mask-composite: intersect;
  }
  .pg-art--window img { object-position: 72% 40%; }
}
/* narrower desktops: the plate is taller for its width, so more of the
   frame is cropped; showing more of its left moves the man clear of the
   compacted panel (measured at 1100 and 1200) */
@media (min-width: 1100px) and (max-width: 1239px) {
  .pg-art--window img { object-position: 45% 40%; }
}

/* ── Reduce Admin 05, the governance answers are controls (30 Sept 2026,
   snagging pass). The kit's branch card keeps its border and its copper
   selected state; the button inside takes the card's grid and padding, so
   the whole card is the target. Hover lifts the border to the hover
   hairline, focus draws the ring, and the chosen answer carries the copper
   border, a copper ring and full-weight text, so selection does not rest
   on colour alone. "Then" states where the item goes next. ── */
.page-admin .admin-life .ak-branches > li { display: block; padding: 0; }
.page-admin .admin-life-opt {
  display: grid; grid-template-columns: 11px minmax(0, 1fr); align-items: start; column-gap: 14px; row-gap: 3px;
  width: 100%; min-height: 44px; padding: 14px 16px;
  background: transparent; border: 0; border-radius: 8px; color: inherit;
  text-align: left; cursor: pointer; touch-action: manipulation;
}
.page-admin .admin-life-opt .ak-ring { margin-top: 3px; }
.page-admin .admin-life .ak-branches > li:not(.is-active):hover { border-color: var(--hairline-hover); }
.page-admin .admin-life .ak-branches > li:not(.is-active) .ak-branch-k { color: var(--text-dim); }
.page-admin .admin-life-opt:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
.page-admin .admin-life-then {
  margin: 14px 0 10px; padding-left: 12px; border-left: 2px solid var(--blue-border);
  font-family: 'Familjen Grotesk', 'Inter', sans-serif; font-size: 14px; font-weight: 600; line-height: 1.45; color: var(--text);
}

/* ── Work 02, the planet into the starfield (30 Sept 2026, snagging pass) ──
   The plate's container fade was a narrow linear band (40% to 56%) and the
   unlit edge of the planet ended as a hard silhouette against the stars,
   so the image read as image, dark overlay, background. Two masks now,
   each doing one job, and nothing laid over the image:
   - on the image itself, in the frame's own coordinates (planet centre
     0.68 x 0.475, radius 0.2125 of the width), so it holds at every crop:
     an ellipse centred up and right of the planet keeps the lit limb, its
     upper-left crescent and the atmosphere beyond it fully opaque, and
     eases the dark body out towards the lower left (about half strength at
     the unlit edge, near nothing at the lower left), so the silhouette
     dissolves into the stars instead of cutting them off; a small second
     ellipse keeps the moon;
   - on the container, the section-edge feathers only, both eased: the
     left third towards the intro, and the last 200px into the next
     section. No brightness, saturation or filter change. */
@media (min-width: 1100px) {
  .pg-art--planet {
    -webkit-mask-image: linear-gradient(to right, transparent 26.0%, rgba(0,0,0,0.04) 30.0%, rgba(0,0,0,0.16) 34.0%, rgba(0,0,0,0.32) 38.0%, rgba(0,0,0,0.50) 42.0%, rgba(0,0,0,0.68) 46.0%, rgba(0,0,0,0.84) 50.0%, rgba(0,0,0,0.96) 54.0%, #000 58.0%), linear-gradient(to bottom, #000 0, #000 calc(100% - 200px), rgba(0,0,0,0.96) calc(100% - 175px), rgba(0,0,0,0.84) calc(100% - 150px), rgba(0,0,0,0.68) calc(100% - 125px), rgba(0,0,0,0.50) calc(100% - 100px), rgba(0,0,0,0.32) calc(100% - 75px), rgba(0,0,0,0.16) calc(100% - 50px), rgba(0,0,0,0.04) calc(100% - 25px), transparent calc(100% - 0px));
            mask-image: linear-gradient(to right, transparent 26.0%, rgba(0,0,0,0.04) 30.0%, rgba(0,0,0,0.16) 34.0%, rgba(0,0,0,0.32) 38.0%, rgba(0,0,0,0.50) 42.0%, rgba(0,0,0,0.68) 46.0%, rgba(0,0,0,0.84) 50.0%, rgba(0,0,0,0.96) 54.0%, #000 58.0%), linear-gradient(to bottom, #000 0, #000 calc(100% - 200px), rgba(0,0,0,0.96) calc(100% - 175px), rgba(0,0,0,0.84) calc(100% - 150px), rgba(0,0,0,0.68) calc(100% - 125px), rgba(0,0,0,0.50) calc(100% - 100px), rgba(0,0,0,0.32) calc(100% - 75px), rgba(0,0,0,0.16) calc(100% - 50px), rgba(0,0,0,0.04) calc(100% - 25px), transparent calc(100% - 0px));
    -webkit-mask-composite: source-in;
            mask-composite: intersect;
  }
  .pg-art--planet img {
    -webkit-mask-image: radial-gradient(ellipse 36% 58% at 74% 30%, #000 62.0%, rgba(0,0,0,0.96) 66.8%, rgba(0,0,0,0.84) 71.5%, rgba(0,0,0,0.68) 76.2%, rgba(0,0,0,0.50) 81.0%, rgba(0,0,0,0.32) 85.8%, rgba(0,0,0,0.16) 90.5%, rgba(0,0,0,0.04) 95.2%, transparent 100.0%), radial-gradient(ellipse 6% 10% at 50% 85.6%, #000 35.0%, rgba(0,0,0,0.93) 45.8%, rgba(0,0,0,0.74) 56.7%, rgba(0,0,0,0.50) 67.5%, rgba(0,0,0,0.26) 78.3%, rgba(0,0,0,0.07) 89.2%, transparent 100.0%);
            mask-image: radial-gradient(ellipse 36% 58% at 74% 30%, #000 62.0%, rgba(0,0,0,0.96) 66.8%, rgba(0,0,0,0.84) 71.5%, rgba(0,0,0,0.68) 76.2%, rgba(0,0,0,0.50) 81.0%, rgba(0,0,0,0.32) 85.8%, rgba(0,0,0,0.16) 90.5%, rgba(0,0,0,0.04) 95.2%, transparent 100.0%), radial-gradient(ellipse 6% 10% at 50% 85.6%, #000 35.0%, rgba(0,0,0,0.93) 45.8%, rgba(0,0,0,0.74) 56.7%, rgba(0,0,0,0.50) 67.5%, rgba(0,0,0,0.26) 78.3%, rgba(0,0,0,0.07) 89.2%, transparent 100.0%);
    -webkit-mask-composite: source-over;
            mask-composite: add;
  }
}

/* ── About 02, each journey ends in its conclusion (30 Sept 2026, snagging
   pass). The two conclusions sat as badges in the top right corner of each
   track, detached from the paths. Each is now the fifth and last step of
   its own rail: the fourth step's connector runs into an end marker level
   with the rings (a dashed ring on the software path, a copper ring with a
   check on Astro's), with the conclusion as its label. The software path
   stays neutral; only Astro's end takes copper, on its ring. Stacked, it
   is simply the last item of each column. ── */
.page-about .ab-rail-end .ab-end-mark {
  position: relative; z-index: 1; display: flex; align-items: center; justify-content: center;
  width: 16px; height: 16px; margin: -2.5px 0; border-radius: 50%;
  background: transparent; border: 1px dashed var(--hairline-hover);
}
.page-about .ab-rail-end.is-done .ab-end-mark { border: 1px solid var(--blue-border); }
.page-about .ab-rail-end .ak-track-end-check { width: 10px; height: 10px; }
.page-about .ab-rail-end .ab-end-label {
  margin-top: 0;
  font-size: 11px; font-weight: 600; letter-spacing: 0.8px; text-transform: uppercase; line-height: 1.5;
}
.page-about .ab-rail-end.is-cold .ab-end-label { color: var(--text-dim); }
.page-about .ab-rail-end.is-done .ab-end-label { color: var(--text); }
/* the end appears with the rest of the entrance, and is complete without it */
.page-about .seq-armed .ab-rail-end:not(.is-on) { opacity: 0.35; }
.page-about .ab-rail-end { transition: opacity 420ms var(--ease); }
@media (max-width: 720px) {
  .page-about .ab-rail-end .ab-end-mark { margin: 0 -2.5px; }
}
@media (prefers-reduced-motion: reduce) { .page-about .ab-rail-end { transition: none; } }

/* ── Pricing 03, Ongoing is a given (30 Sept 2026, retainer correction) ──
   The "Implementation only / Implementation and ongoing involvement" choice
   is gone: Astro builds, maintains and improves every system it implements.
   The group keeps its place and label but holds a statement, deliberately
   not styled as a control (no pill, no border) so it cannot read as a
   button that does nothing; its ring carries the copper of something that
   is on. What the ongoing work involves still follows the other controls,
   in the scope's Ongoing row. */
.page-pricing .pr-given-line {
  display: flex; align-items: center; gap: 10px; margin: 0;
  font-family: 'Familjen Grotesk', 'Inter', sans-serif; font-size: 14px; font-weight: 600; line-height: 1.4; color: var(--text);
}
.page-pricing .pr-given-line .ak-ring { border-color: var(--blue); }

/* ── Work, 30 Sept 2026 (final pass) ──
   Labels: Work stacks each condition's label above its buttons, so the
   kit's fixed 56px label column only forced "Nature of the request" onto
   three lines; the label takes its own width here (both 03 and 06).
   06 outcomes are controls: choosing one sets an example of the conditions
   that lead there. The card keeps the kit's border and copper selected
   state; the button inside takes its grid and padding. */
.page-work .ak-toggle-row .ak-toggle-k { width: auto; white-space: nowrap; }
.page-work .work-route .ak-route-outs > li { display: block; padding: 0; }
.page-work .work-outcome {
  display: grid; grid-template-columns: 11px minmax(0, 1fr) auto; align-items: center; column-gap: 10px;
  width: 100%; min-height: 44px; padding: 11px 14px;
  background: transparent; border: 0; border-radius: 8px; color: inherit; font: inherit;
  text-align: left; cursor: pointer; touch-action: manipulation;
}
.page-work .work-route .ak-route-outs > li:not(.is-active):hover { border-color: var(--hairline-hover); }
.page-work .work-outcome:hover .ak-route-k { color: var(--text); }
.page-work .work-outcome:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
.page-work .work-route .ak-route-outs > li.is-active .ak-route-v { color: var(--text); font-weight: 600; }
@media (max-width: 420px) {
  .page-work .work-outcome { grid-template-columns: 11px minmax(0, 1fr); row-gap: 2px; }
  .page-work .work-outcome .ak-route-v { grid-column: 2; text-align: left; }
}
@media (max-width: 360px) { .page-work .ak-toggle-row .ak-toggle-k { white-space: normal; } }

/* ── About 09, the closing image (30 Sept 2026, James's supplied image) ──
   ASTRO-ABOUT-HUMAN-03: a man seen from behind at an office window over a
   city at sunset. Headline and photograph are one composition: the
   headline stands in the left column on starfield and deep shadow, and
   the photograph emerges to its right through the room's own dark side,
   then the man, then the city and the sun. The file is the supplied image,
   resized only; the grade is CSS and per image: saturation eased so the
   sunset reads amber rather than orange, a little exposure taken off, and
   a touch of contrast to keep the blacks rich. No filter elsewhere.
   Desktop: the plate is the ground of the right 74% at full section
   height; three masks, intersected: an eased fade from the plate's left
   edge to 36% of its width (over the dark office, so no bright edge ever
   meets the stars), eased top and bottom feathers, and a radial term
   centred on the man so the corners round away instead of meeting at a
   rectangle. Under 1100px it becomes a band after the headline, cropped
   to the man and the sun, feathered on all four sides. */
.pg-art--horizon { mix-blend-mode: normal; }
.pg-art--horizon img { object-fit: cover; filter: saturate(0.84) brightness(0.9) contrast(1.05); }
@media (min-width: 1100px) {
  .page-about #bigger-idea { min-height: clamp(560px, 42vw, 760px); display: flex; align-items: center; }
  .page-about #bigger-idea > .container { position: relative; z-index: 1; width: 100%; }
  .page-about #bigger-idea .ab-big { max-width: min(44vw, 620px); font-size: clamp(42px, 4.3vw, 68px); }
  .pg-art--horizon {
    top: 0; bottom: 0; left: 26%; right: 0;
    -webkit-mask-image: linear-gradient(to right, transparent 0.0%, rgba(0,0,0,0.04) 4.5%, rgba(0,0,0,0.16) 9.0%, rgba(0,0,0,0.32) 13.5%, rgba(0,0,0,0.50) 18.0%, rgba(0,0,0,0.68) 22.5%, rgba(0,0,0,0.84) 27.0%, rgba(0,0,0,0.96) 31.5%, #000 36.0%), linear-gradient(to bottom, transparent 0.0%, rgba(0,0,0,0.04) 2.5%, rgba(0,0,0,0.16) 5.0%, rgba(0,0,0,0.32) 7.5%, rgba(0,0,0,0.50) 10.0%, rgba(0,0,0,0.68) 12.5%, rgba(0,0,0,0.84) 15.0%, rgba(0,0,0,0.96) 17.5%, #000 20.0%, #000 74.0%, rgba(0,0,0,0.96) 77.2%, rgba(0,0,0,0.84) 80.5%, rgba(0,0,0,0.68) 83.8%, rgba(0,0,0,0.50) 87.0%, rgba(0,0,0,0.32) 90.2%, rgba(0,0,0,0.16) 93.5%, rgba(0,0,0,0.04) 96.8%, transparent 100.0%), radial-gradient(ellipse 78% 92% at 66% 46%, #000 62.0%, rgba(0,0,0,0.93) 68.3%, rgba(0,0,0,0.74) 74.7%, rgba(0,0,0,0.50) 81.0%, rgba(0,0,0,0.26) 87.3%, rgba(0,0,0,0.07) 93.7%, transparent 100.0%);
            mask-image: linear-gradient(to right, transparent 0.0%, rgba(0,0,0,0.04) 4.5%, rgba(0,0,0,0.16) 9.0%, rgba(0,0,0,0.32) 13.5%, rgba(0,0,0,0.50) 18.0%, rgba(0,0,0,0.68) 22.5%, rgba(0,0,0,0.84) 27.0%, rgba(0,0,0,0.96) 31.5%, #000 36.0%), linear-gradient(to bottom, transparent 0.0%, rgba(0,0,0,0.04) 2.5%, rgba(0,0,0,0.16) 5.0%, rgba(0,0,0,0.32) 7.5%, rgba(0,0,0,0.50) 10.0%, rgba(0,0,0,0.68) 12.5%, rgba(0,0,0,0.84) 15.0%, rgba(0,0,0,0.96) 17.5%, #000 20.0%, #000 74.0%, rgba(0,0,0,0.96) 77.2%, rgba(0,0,0,0.84) 80.5%, rgba(0,0,0,0.68) 83.8%, rgba(0,0,0,0.50) 87.0%, rgba(0,0,0,0.32) 90.2%, rgba(0,0,0,0.16) 93.5%, rgba(0,0,0,0.04) 96.8%, transparent 100.0%), radial-gradient(ellipse 78% 92% at 66% 46%, #000 62.0%, rgba(0,0,0,0.93) 68.3%, rgba(0,0,0,0.74) 74.7%, rgba(0,0,0,0.50) 81.0%, rgba(0,0,0,0.26) 87.3%, rgba(0,0,0,0.07) 93.7%, transparent 100.0%);
    -webkit-mask-composite: source-in, source-in;
            mask-composite: intersect, intersect;
  }
  .pg-art--horizon img { object-position: 40% 46%; }
}
@media (max-width: 1099px) {
  .pg-art--horizon {
    position: relative; inset: auto; display: block;
    height: clamp(260px, 50vw, 460px); margin: 18px 0 -40px;
    -webkit-mask-image: linear-gradient(to right, transparent 0.0%, rgba(0,0,0,0.04) 1.8%, rgba(0,0,0,0.16) 3.5%, rgba(0,0,0,0.32) 5.2%, rgba(0,0,0,0.50) 7.0%, rgba(0,0,0,0.68) 8.8%, rgba(0,0,0,0.84) 10.5%, rgba(0,0,0,0.96) 12.2%, #000 14.0%, #000 86.0%, rgba(0,0,0,0.96) 87.8%, rgba(0,0,0,0.84) 89.5%, rgba(0,0,0,0.68) 91.2%, rgba(0,0,0,0.50) 93.0%, rgba(0,0,0,0.32) 94.8%, rgba(0,0,0,0.16) 96.5%, rgba(0,0,0,0.04) 98.2%, transparent 100.0%), linear-gradient(to bottom, transparent 0.0%, rgba(0,0,0,0.04) 3.8%, rgba(0,0,0,0.16) 7.5%, rgba(0,0,0,0.32) 11.2%, rgba(0,0,0,0.50) 15.0%, rgba(0,0,0,0.68) 18.8%, rgba(0,0,0,0.84) 22.5%, rgba(0,0,0,0.96) 26.2%, #000 30.0%, #000 68.0%, rgba(0,0,0,0.96) 72.0%, rgba(0,0,0,0.84) 76.0%, rgba(0,0,0,0.68) 80.0%, rgba(0,0,0,0.50) 84.0%, rgba(0,0,0,0.32) 88.0%, rgba(0,0,0,0.16) 92.0%, rgba(0,0,0,0.04) 96.0%, transparent 100.0%);
            mask-image: linear-gradient(to right, transparent 0.0%, rgba(0,0,0,0.04) 1.8%, rgba(0,0,0,0.16) 3.5%, rgba(0,0,0,0.32) 5.2%, rgba(0,0,0,0.50) 7.0%, rgba(0,0,0,0.68) 8.8%, rgba(0,0,0,0.84) 10.5%, rgba(0,0,0,0.96) 12.2%, #000 14.0%, #000 86.0%, rgba(0,0,0,0.96) 87.8%, rgba(0,0,0,0.84) 89.5%, rgba(0,0,0,0.68) 91.2%, rgba(0,0,0,0.50) 93.0%, rgba(0,0,0,0.32) 94.8%, rgba(0,0,0,0.16) 96.5%, rgba(0,0,0,0.04) 98.2%, transparent 100.0%), linear-gradient(to bottom, transparent 0.0%, rgba(0,0,0,0.04) 3.8%, rgba(0,0,0,0.16) 7.5%, rgba(0,0,0,0.32) 11.2%, rgba(0,0,0,0.50) 15.0%, rgba(0,0,0,0.68) 18.8%, rgba(0,0,0,0.84) 22.5%, rgba(0,0,0,0.96) 26.2%, #000 30.0%, #000 68.0%, rgba(0,0,0,0.96) 72.0%, rgba(0,0,0,0.84) 76.0%, rgba(0,0,0,0.68) 80.0%, rgba(0,0,0,0.50) 84.0%, rgba(0,0,0,0.32) 88.0%, rgba(0,0,0,0.16) 92.0%, rgba(0,0,0,0.04) 96.0%, transparent 100.0%);
    -webkit-mask-composite: source-in;
            mask-composite: intersect;
  }
  .pg-art--horizon img { object-position: 64% 48%; }
}
@media (max-width: 720px) {
  .pg-art--horizon { height: clamp(260px, 82vw, 380px); margin-top: 8px; margin-bottom: -28px; }
  .pg-art--horizon img { object-position: 67% 48%; }
}

/* the band rounds away at its corners too (a radial term, as on desktop),
   and the headline breaks in balanced lines rather than orphaning "AI." */
.page-about #bigger-idea .ab-big-a, .page-about #bigger-idea .ab-big-b { text-wrap: balance; }
@media (max-width: 1099px) {
  .pg-art--horizon {
    -webkit-mask-image: linear-gradient(to right, transparent 0.0%, rgba(0,0,0,0.04) 1.8%, rgba(0,0,0,0.16) 3.5%, rgba(0,0,0,0.32) 5.2%, rgba(0,0,0,0.50) 7.0%, rgba(0,0,0,0.68) 8.8%, rgba(0,0,0,0.84) 10.5%, rgba(0,0,0,0.96) 12.2%, #000 14.0%, #000 86.0%, rgba(0,0,0,0.96) 87.8%, rgba(0,0,0,0.84) 89.5%, rgba(0,0,0,0.68) 91.2%, rgba(0,0,0,0.50) 93.0%, rgba(0,0,0,0.32) 94.8%, rgba(0,0,0,0.16) 96.5%, rgba(0,0,0,0.04) 98.2%, transparent 100.0%), linear-gradient(to bottom, transparent 0.0%, rgba(0,0,0,0.04) 4.0%, rgba(0,0,0,0.16) 8.0%, rgba(0,0,0,0.32) 12.0%, rgba(0,0,0,0.50) 16.0%, rgba(0,0,0,0.68) 20.0%, rgba(0,0,0,0.84) 24.0%, rgba(0,0,0,0.96) 28.0%, #000 32.0%, #000 66.0%, rgba(0,0,0,0.96) 70.2%, rgba(0,0,0,0.84) 74.5%, rgba(0,0,0,0.68) 78.8%, rgba(0,0,0,0.50) 83.0%, rgba(0,0,0,0.32) 87.2%, rgba(0,0,0,0.16) 91.5%, rgba(0,0,0,0.04) 95.8%, transparent 100.0%), radial-gradient(ellipse 72% 86% at 62% 52%, #000 55.0%, rgba(0,0,0,0.93) 62.5%, rgba(0,0,0,0.74) 70.0%, rgba(0,0,0,0.50) 77.5%, rgba(0,0,0,0.26) 85.0%, rgba(0,0,0,0.07) 92.5%, transparent 100.0%);
            mask-image: linear-gradient(to right, transparent 0.0%, rgba(0,0,0,0.04) 1.8%, rgba(0,0,0,0.16) 3.5%, rgba(0,0,0,0.32) 5.2%, rgba(0,0,0,0.50) 7.0%, rgba(0,0,0,0.68) 8.8%, rgba(0,0,0,0.84) 10.5%, rgba(0,0,0,0.96) 12.2%, #000 14.0%, #000 86.0%, rgba(0,0,0,0.96) 87.8%, rgba(0,0,0,0.84) 89.5%, rgba(0,0,0,0.68) 91.2%, rgba(0,0,0,0.50) 93.0%, rgba(0,0,0,0.32) 94.8%, rgba(0,0,0,0.16) 96.5%, rgba(0,0,0,0.04) 98.2%, transparent 100.0%), linear-gradient(to bottom, transparent 0.0%, rgba(0,0,0,0.04) 4.0%, rgba(0,0,0,0.16) 8.0%, rgba(0,0,0,0.32) 12.0%, rgba(0,0,0,0.50) 16.0%, rgba(0,0,0,0.68) 20.0%, rgba(0,0,0,0.84) 24.0%, rgba(0,0,0,0.96) 28.0%, #000 32.0%, #000 66.0%, rgba(0,0,0,0.96) 70.2%, rgba(0,0,0,0.84) 74.5%, rgba(0,0,0,0.68) 78.8%, rgba(0,0,0,0.50) 83.0%, rgba(0,0,0,0.32) 87.2%, rgba(0,0,0,0.16) 91.5%, rgba(0,0,0,0.04) 95.8%, transparent 100.0%), radial-gradient(ellipse 72% 86% at 62% 52%, #000 55.0%, rgba(0,0,0,0.93) 62.5%, rgba(0,0,0,0.74) 70.0%, rgba(0,0,0,0.50) 77.5%, rgba(0,0,0,0.26) 85.0%, rgba(0,0,0,0.07) 92.5%, transparent 100.0%);
    -webkit-mask-composite: source-in, source-in;
            mask-composite: intersect, intersect;
  }
}

/* ═══════════════════════════════════════════════════════════════════════
   SHORT DESKTOP WINDOWS, 2 Oct 2026 (polish pass). The homepage's three
   scroll-scrubbed sections (05 manual to automated, 06 a day, 09 the
   process) used to switch off below 560 to 580px of window height, which a
   smaller laptop at 100% zoom reaches once the browser and taskbar take
   their share. They now stay on down to 500px (astro-home.js) and, below
   660px tall, tighten their spacing. 3 Oct 2026 (type pass): the headline
   is NOT reduced here any more (it was clamped to 30-44px, which made "The
   same missed call" and "Working while your team is away" smaller than
   every other section heading on short windows). The rule is: animations
   adapt to typography. astro-home.js measures the height left under each
   full-size header and sizes 05's stage (--xf-h) and scales 06's timeline
   (--day-s) to it. Above 660px only that measurement applies.
   ═══════════════════════════════════════════════════════════════════════ */
@media (max-height: 660px) {
  .is-scrub .xf-header { margin-bottom: 12px; }
  .is-scrub .xf-header .section-label,
  .day-section.is-scrub .day-header .section-label { margin-bottom: 8px; }
  .is-scrub .xf-modes { margin-bottom: 10px; }
  .is-scrub .day-sticky { padding-top: 20px; }
  .day-section.is-scrub .day-header { margin-bottom: 14px; }
  .proc-scrub .proc-scenes { height: max(320px, calc(100vh - 64px - 24px - 76px)); }
  .proc-scrub .proc-stage { top: 76px; }
}


/* ═══════════════════════════════════════════════════════════════════════
   HERO BLACK HOLE ON PHONES, AND ITS STILL, 2 Oct 2026 (polish pass).
   Still: superseded 5 Oct 2026 by the still-first layer (img.hero-still,
   below), which covers the video until a confirmed frame. The WebKit
   start-button pseudo is hidden as well, belt and braces.
   Phones (720px and below): the clip is no longer fitted into the column.
   The slot runs edge to edge of the screen (100vw by 96vw), and the clip
   inside it is 210vw wide, centred on the black hole's shadow (44% down
   the frame), so the event horizon, the copper ring and the lensed arcs
   above and below are large and the disk runs off both sides of the
   screen. The slot fades at top and bottom; its sides are the screen's.
   #hero clips its overflow, so nothing scrolls sideways.
   ═══════════════════════════════════════════════════════════════════════ */
.hero-orb .hero-video::-webkit-media-controls,
.hero-orb .hero-video::-webkit-media-controls-start-playback-button,
.hero-orb .hero-video::-webkit-media-controls-overlay-play-button { display: none !important; -webkit-appearance: none; }
/* still first (5 Oct 2026, final): img.hero-still sits over the video with
   the video's own geometry and masks (desktop: 16:9 slot, contain, edge
   masks; phones: the bleed rules below, which list both layers), so the
   two are the same object. It is opaque until astro-home.js confirms a
   moving frame and adds .is-playing; then it fades out in 140ms. */
.hero-orb .hero-still {
  position: absolute; inset: 0; z-index: 1;
  width: 100%; height: 100%; object-fit: contain;
  pointer-events: none; user-select: none; -webkit-user-select: none; -webkit-touch-callout: none;
  opacity: 1; transition: opacity 140ms linear;
  -webkit-mask-image:
    linear-gradient(to right, transparent 0%, #000 7%, #000 93%, transparent 100%),
    linear-gradient(to bottom, transparent 0%, #000 10%, #000 90%, transparent 100%);
          mask-image:
    linear-gradient(to right, transparent 0%, #000 7%, #000 93%, transparent 100%),
    linear-gradient(to bottom, transparent 0%, #000 10%, #000 90%, transparent 100%);
  -webkit-mask-composite: source-in; mask-composite: intersect;
}
.hero-orb.is-playing .hero-still { opacity: 0; }
.hero-orb .hero-video { pointer-events: none; }
@media (prefers-reduced-motion: reduce) { .hero-orb .hero-still { transition: none; } }
@media (max-width: 720px) {
  #hero { overflow: hidden; }
  .hero-orb {
    width: 100vw; max-width: none; height: 58vw; aspect-ratio: auto; margin-top: 6px; margin-bottom: -10px;
    /* a grid item wider than its track is not centred, so it is pulled out
       to the screen's left edge explicitly */
    justify-self: start; margin-left: calc(50% - 50vw); margin-right: 0; overflow: hidden;
    -webkit-mask-image: linear-gradient(to bottom, transparent 0%, rgba(0,0,0,0.35) 6%, #000 16%, #000 84%, rgba(0,0,0,0.35) 94%, transparent 100%);
            mask-image: linear-gradient(to bottom, transparent 0%, rgba(0,0,0,0.35) 6%, #000 16%, #000 84%, rgba(0,0,0,0.35) 94%, transparent 100%);
  }
  .hero-orb .hero-video,
  .hero-orb .hero-still {
    inset: auto; left: 50%; top: 50%;
    /* 5 Oct 2026 (James, after checking on his iPhone): the clip itself is
       now 140vw wide (it was 210vw, then 184vw). The earlier change mostly
       cropped empty space out of the window; the black hole only shrank by
       about 12%, so on the phone it looked unchanged. 140vw is a third
       smaller than the original and a quarter smaller than 184vw, and the
       disk still runs off both edges. Height is set explicitly (16:9 of the
       width) rather than through aspect-ratio, which older iOS ignores on
       a replaced element with height:auto. */
    width: 140vw; height: 78.75vw; aspect-ratio: auto;
    transform: translate(-50%, -47%);
    object-fit: cover;
    -webkit-mask-image: none; mask-image: none;
  }
}

/* ═══════════════════════════════════════════════════════════════════════
   ASTRO NAVIGATION RAIL, 2 Oct 2026 (polish pass, James's brief). The
   full-width black header with a white underline became a slim floating
   control rail, in the same language as the site's interfaces.
   Geometry: <nav> keeps its fixed 64px band (every sticky offset and
   scroll margin on the site assumes it) but paints nothing; the rail is
   <nav> itself, inset 10px from the top and from the sides, 48px tall,
   max 1240px wide. Surface: near-black at 82% with a light blur, a
   graphite hairline, a 14px radius and a soft black drop (never copper).
   Groups: wordmark | links | Ask Astro, divided by hairlines.
   3 Oct 2026 (type and nav pass, James): the copper ring beside the
   wordmark is gone (the wordmark is the original .nav-brand, unchanged),
   and so is the active dot-and-line, which read as squashed. The active
   page now sits in a capsule of dark optical glass: a 32px fully rounded
   shape inside the 48px rail, a very faint neutral fill, a neutral inner
   highlight along its top edge, and a thin copper perimeter (the accent
   rule: copper on borders only, never fill, shadow or glow). It also
   carries aria-current="page", brighter text and medium weight, so the
   state does not rest on colour. Hover: the same capsule as a neutral
   hairline, no copper. The rail itself is slightly more glass than
   before: a little more translucent, a light saturating blur and a top
   sheen, still read as black. Reduced motion: no transition. Phones and tablets (960px and below): the rail keeps the
   wordmark, Ask Astro and a ringed menu button; the menu opens as a
   floating panel of the same surface under the rail.
   ═══════════════════════════════════════════════════════════════════════ */
nav {
  top: 10px; left: 50%; right: auto;
  width: min(1240px, calc(100% - 40px));
  transform: translateX(-50%);
  height: 48px;
  padding: 0 8px 0 20px;
  background: linear-gradient(180deg, rgba(237,233,227,0.035) 0%, rgba(237,233,227,0) 55%), rgba(9,9,11,0.74);
  -webkit-backdrop-filter: blur(14px) saturate(125%); backdrop-filter: blur(14px) saturate(125%);
  border: 1px solid rgba(237,233,227,0.09);
  border-radius: 14px;
  box-shadow: 0 12px 32px -14px rgba(0,0,0,0.75), inset 0 1px 0 rgba(237,233,227,0.06), inset 0 -1px 0 rgba(0,0,0,0.35);
  gap: 18px;
}
.nav-brand { flex: none; }
.nav-links {
  gap: 2px; align-self: stretch; padding: 0 14px;
  border-left: 1px solid rgba(237,233,227,0.08); border-right: 1px solid rgba(237,233,227,0.08);
}
.nav-links a {
  display: flex; align-items: center; height: 100%;
  padding: 0 12px; font-size: 13.5px;
  color: rgba(237,233,227,0.72);
}
.nav-links a { padding: 0 15px; }
/* the capsule: ::after, 32px tall, centred in the link's full-height box;
   the base rule's underline geometry is fully replaced here */
.nav-links a::after {
  left: 3px; right: 3px; top: 50%; bottom: auto; height: 32px; margin-top: -16px;
  border-radius: 999px; box-sizing: border-box;
  background: transparent; border: 1px solid transparent;
  opacity: 1; transform: none;
  transition: border-color 220ms var(--ease), background-color 220ms var(--ease), box-shadow 220ms var(--ease);
  pointer-events: none;
}
.nav-links a:hover { color: var(--text); }
.nav-links a:hover::after { border-color: rgba(237,233,227,0.12); }
.nav-links a.active { color: var(--text); font-weight: 500; }
.nav-links a.active::after {
  border-color: rgba(201,154,110,0.46);
  background-color: rgba(237,233,227,0.035);
  box-shadow: inset 0 1px 0 rgba(237,233,227,0.08), inset 0 -6px 12px -10px rgba(0,0,0,0.6);
}
.nav-links a:focus-visible { outline: 2px solid var(--blue); outline-offset: -8px; border-radius: 999px; }
.nav-brand:focus-visible { outline: 2px solid var(--blue); outline-offset: 4px; border-radius: 4px; }
.nav-btn.btn-filled { flex: none; padding: 9px 18px; font-size: 13.5px; }
.nav-btn.btn-filled:focus-visible { outline: 2px solid var(--blue); outline-offset: 3px; }

/* phones and tablets: the same rail, carrying what fits */
@media (max-width: 960px) {
  /* 5 Oct 2026: 44px tall (was 48), a quieter menu button and a softer
     drop, so the rail reads as an instrument strip, not an app toolbar */
  nav { top: 9px; height: 44px; width: calc(100% - 24px); padding: 0 5px 0 16px; gap: 10px;
        box-shadow: 0 8px 22px -14px rgba(0,0,0,0.7), inset 0 1px 0 rgba(237,233,227,0.05); border-color: rgba(237,233,227,0.08); }
  .nav-btn.btn-filled { display: inline-block; margin-left: auto; padding: 7px 14px; font-size: 13px; }
  .nav-hamburger {
    width: 34px; height: 34px; padding: 0; align-items: center; gap: 4px;
    border: 1px solid rgba(237,233,227,0.08); border-radius: 9px;
  }
  .nav-hamburger span { width: 16px; height: 1.5px; }
  .nav-hamburger.open span:nth-child(1) { transform: translateY(5.5px) rotate(45deg); }
  .nav-hamburger.open span:nth-child(3) { transform: translateY(-5.5px) rotate(-45deg); }
  .nav-hamburger.open { border-color: var(--blue-border); }
  .nav-hamburger:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
  .mobile-menu {
    top: 61px; left: 12px; right: 12px;
    padding: 8px 18px 18px;
    background: rgba(10,10,12,0.96);
    border: 1px solid rgba(237,233,227,0.09); border-radius: 14px;
    box-shadow: 0 18px 40px -16px rgba(0,0,0,0.8);
  }
  .mobile-menu a { position: relative; display: flex; align-items: center; min-height: 48px; padding: 0 14px; margin: 0 -14px; font-size: 15px; }
  /* the active page: the rail's glass capsule, full row width (3 Oct 2026;
     the ring markers it replaces read as the retired copper dot) */
  .mobile-menu a.active { color: var(--text); font-weight: 500; border-bottom-color: transparent; }
  .mobile-menu a.active::after {
    content: ''; position: absolute; inset: 6px 0; border-radius: 999px; pointer-events: none;
    border: 1px solid rgba(201,154,110,0.46); background-color: rgba(237,233,227,0.035);
    box-shadow: inset 0 1px 0 rgba(237,233,227,0.08);
  }
  .mobile-menu a:last-of-type:not(.mobile-cta) { border-bottom: 0; }
  .mobile-menu .mobile-cta { justify-content: center; margin-top: 12px; }
  .mobile-menu a:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; border-radius: 6px; }
}
@media (max-width: 640px) { nav { padding: 0 6px 0 14px; } }
@media (max-width: 360px) { .nav-btn.btn-filled { padding: 8px 12px; } }
@media (prefers-reduced-motion: reduce) {
  .nav-links a, .nav-links a::after, .nav-hamburger span { transition: none; }
}
/* the open menu carries its own Ask Astro, so the rail's steps aside */
@media (max-width: 960px) { nav:has(.nav-hamburger.open) .nav-btn.btn-filled { visibility: hidden; } }

/* ── homepage 05 and 06: the animation fits the space the heading leaves
   (3 Oct 2026). --xf-h is the stage height available under the header and
   the mode meter, measured by astro-home.js; the stage keeps its 1000:440
   shape inside it. --day-s scales 06's timeline (labels, axis and panels
   together, from the top centre) when its 380px box does not fit under the
   header; the box's own height shrinks with it so nothing below shifts. ── */
.is-scrub .xf-stage { width: min(100%, calc(var(--xf-h, 9999px) * 2.2727)); }
.is-scrub .day-line { transform: scale(var(--day-s, 1)); transform-origin: 50% 0; margin-bottom: calc((var(--day-s, 1) - 1) * var(--day-h, 380px)); }

/* ═══════════════════════════════════════════════════════════════════════
   MOBILE AUDIT FIXES, 3 Oct 2026. Defects found by the phone audit only;
   nothing here applies above 720px except the touch-target floor, which is
   keyed to a coarse pointer (any touch screen) rather than to a width.
   ═══════════════════════════════════════════════════════════════════════ */
/* footer legal row: it was one nowrap line, which ran off both edges at
   320px and broke "Terms of Use" into three stacked words at 390px; it now
   wraps as whole items, centred, with 44px tap rows */
@media (max-width: 720px) {
  .footer-legal { flex-wrap: wrap; justify-content: center; gap: 0 14px; max-width: 100%; }
  .footer-legal-link { white-space: nowrap; min-height: 40px; display: inline-flex; align-items: center; }
  .footer-legal-sep { display: none; }
}
/* homepage 04: the right-aligned desktop composition (mixed alignment) is
   read on a phone as ragged text against the right edge; left on phones */
@media (max-width: 720px) {
  .products-header { text-align: left; }
  .products-header .section-label { justify-content: flex-start; }
  .products-header .section-sub { margin-left: 0; }
}
/* touch-target floor on touch screens: text links and small interface
   buttons measured 22 to 32px tall on phones */
@media (pointer: coarse) {
  .hero-path, .env-link { display: inline-flex; align-items: center; min-height: 44px; }
  .ui-btn { min-height: 40px; }
  nav .nav-btn.btn-filled { min-height: 36px; display: inline-flex; align-items: center; }
  .nav-brand { display: inline-flex; align-items: center; min-height: 44px; }
}
/* a kit link that sits INSIDE a sentence (Reduce Admin 03 and 05, Work 02)
   flows with the text: as an inline-flex 44px box it opened a tall gap in
   the middle of the line on phones (3 Oct 2026). Its tap area is padded
   vertically instead. Stand-alone .ak-link blocks are unchanged. */
.ak-page p > .ak-link { display: inline; min-height: 0; margin-top: 0; padding: 12px 0; }


/* ═══════════════════════════════════════════════════════════════════════
   MOBILE POLISH, 4 Oct 2026 (James's annotated phone screenshots). Shared
   fixes first; each names the defect it removes.
   ═══════════════════════════════════════════════════════════════════════ */

/* 1. Horizontal stage strips (.ak-stage tabs on phones, the stage rail's
   strip under 860px): the first item sat 6 to 12px from the panel edge and
   the last one was cut by the edge with nothing saying the strip scrolls.
   Both strips now have a 16px safe area at each end, scroll-padding so a
   snapped or auto-scrolled item keeps it, proximity snapping (mandatory
   snapping fought diagonal swipes), and a soft fade at each edge that only
   ever covers the safe area. astro-kit.js scrolls the selected item into
   view inside the strip (never the page) when autoplay moves it. */
@media (max-width: 760px) {
  .ak-page .ak-stage { padding: 0 16px; scroll-padding-inline: 16px; scroll-snap-type: x proximity; }
}
@media (max-width: 860px) {
  .ak-page .ak-stagerail-list { padding: 12px 16px; scroll-padding-inline: 16px; scroll-snap-type: x proximity; }
}
@media (max-width: 860px) {
  .ak-page .ak-stage, .ak-page .ak-stagerail-list {
    -webkit-mask-image: linear-gradient(to right, transparent 0, #000 8px, #000 calc(100% - 8px), transparent 100%);
            mask-image: linear-gradient(to right, transparent 0, #000 8px, #000 calc(100% - 8px), transparent 100%);
  }
  .ak-page .ak-stage::after, .ak-page .ak-stagerail-list::after { content: ''; flex: 0 0 1px; }
}

/* 2. Hover never sticks on touch screens: after a tap, a touch browser keeps
   :hover on the tapped element, so a second step or row looked selected
   (homepage 02 showed two highlighted steps). On devices without hover the
   hover fills are neutralised; selection keeps its own state styling. */
@media (hover: none) {
  .wf-node:not(.is-active):hover { background: transparent; color: var(--text-dim); }
  .ui-btn:hover, .act-scen-btn:hover, .btn-primary:hover, .nav-btn:hover, .chat-cta-send:hover { background: transparent; }
  .act-scen-btn:not([aria-pressed="true"]):hover { color: var(--text-dim); }
  .ak-page .ak-row:hover, .product-card:hover { background: transparent; }
  .ak-page .ak-row[aria-pressed="true"]:hover { background: rgba(237,233,227,0.05); }
}

/* 3. Homepage 02's step rail: the selected step's tinted card had the
   connector running into it from above and below. Same rule as the stage
   rail: the line stops 3px short of the selected card and resumes after it. */
.wf-node.is-active:not(:first-child)::before,
.wf-node.is-active:not(:first-child)::after { bottom: calc(100% + 3px); height: 11px; }
.wf-node.is-active + .wf-node::before,
.wf-node.is-active + .wf-node::after { height: 11px; }

/* 4. Copper selection edges at rounded corners: a selected row's 2px copper
   left edge in a list that starts at the panel's corner (Work 02, Reduce
   Admin 02, About 04) ran square past the rounded corner. Panels that hold
   a selectable row list clip to their own radius; clip, not hidden, so no
   scroll container is created and sticky children keep working. */
.ak-page .ui-panel:has(.ak-rows) { overflow: clip; }

/* 5. Work's "Running" context header: it had no vertical padding, only a
   44px minimum, so once it wrapped to two lines on a phone the text sat on
   the top border. Balanced 12px above and below at every width. */
.page-work .work-ctx { padding: 12px 18px; }
@media (max-width: 720px) { .page-work .work-ctx { padding: 12px 16px; } }

/* 6. Increase Leads 07 routing outcomes are buttons now (kit-level, so any
   fan can use them): the card keeps the kit's border and copper selected
   state; the button takes its grid and padding. */
.ak-page .ak-route-outs > li:has(> .ak-route-btn) { display: block; padding: 0; }
.ak-page .ak-route-btn {
  display: grid; grid-template-columns: 11px minmax(0, 1fr) auto; align-items: center; column-gap: 10px; row-gap: 2px;
  width: 100%; min-height: 44px; padding: 11px 14px;
  background: transparent; border: 0; border-radius: 8px; color: inherit; font: inherit;
  text-align: left; cursor: pointer; touch-action: manipulation;
}
.ak-page .ak-route-outs > li:not(.is-active):has(> .ak-route-btn):hover { border-color: var(--hairline-hover); }
.ak-page .ak-route-btn:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
.ak-page .ak-route-outs > li.is-quiet .ak-route-btn .ak-route-k { color: var(--text-dim); }
@media (max-width: 420px) {
  .ak-page .ak-route-btn { grid-template-columns: 11px minmax(0, 1fr); }
  .ak-page .ak-route-btn .ak-route-v { grid-column: 2; text-align: left; }
}

/* 7. Homepage hero actions on phones: the 44px tap floor made the wrapped
   "Reduce Admin" link sit alone a full row below. Ask Astro takes its own
   row; the two route links share the next, close under it. */
@media (max-width: 560px) {
  .hero-cta-row { gap: 6px 22px; }
  .hero-cta-row .btn-primary { flex: 0 0 100%; text-align: center; margin-bottom: 6px; }
}

/* 8. Node and connector geometry, one rule set (4 Oct 2026). Every vertical
   connector now runs from 2px below one node's edge to 2px above the next
   node's edge, measured from the node's own centre, never from the row box.
   - .ak-timeline (Increase Leads 07, Pricing 04, Work 05): glyph and ring
     nodes are 11px on a 14px column, centred at 7px; the segments were
     inset 9px from each centre and read as fragments between the checks.
   - .ak-rail stacked on phones (Increase Leads 02, About 02): the segment
     started 6px below a ring's centre but ended 2px PAST the next ring's
     centre, so on the dashed track the line showed inside each ring. The
     ring centre on a stacked row is (row height - 16px padding) / 2.
   - About 02's end marks take the panel ground like every ring, so no line
     shows through them. */
.ak-page .ak-timeline > li:not(:last-child)::after { top: calc(50% + 7.5px); height: calc(100% - 15px); }
@media (max-width: 720px) {
  .ak-page .ak-rail-node:not(:last-child)::before,
  .ak-page .ak-rail-node:not(:last-child)::after { top: calc(50% - 0.5px); height: calc(100% - 15px); }
}
.page-about .ab-rail-end .ab-end-mark { background: var(--card); }


/* 9. Image bands under 1100px (4 Oct 2026): STARS, IMAGE EMERGES, IMAGE,
   IMAGE DISSOLVES, STARS. The bands pulled the next eyebrow 28 to 48px up
   into the image's foot, so "THE QUEUE", "THE SCOPE" and "THE PROCESS"
   began while the photograph was still visible. Now each band fades out
   completely by 92% of its height on an eased curve and the eyebrow starts
   after it (no negative bottom margin); the sides soften too, so no band
   edge meets the stars as a vertical line. About's window photograph had
   a negative top margin that tucked it under the intro panel; it now has
   breathing room above and a longer top fade, so it reads as the next beat
   rather than part of the panel. Desktop (1100px and up) is unchanged. */
@media (max-width: 1099px) {
  .pg-art--discover, .pg-art--desk, .pg-art--trails, .pg-art--concrete, .pg-art--planet {
    margin-bottom: 4px;
    -webkit-mask-image: linear-gradient(to bottom, transparent 0.0%, rgba(0,0,0,0.04) 3.0%, rgba(0,0,0,0.16) 6.0%, rgba(0,0,0,0.32) 9.0%, rgba(0,0,0,0.50) 12.0%, rgba(0,0,0,0.68) 15.0%, rgba(0,0,0,0.84) 18.0%, rgba(0,0,0,0.96) 21.0%, #000 24.0%, #000 50.0%, rgba(0,0,0,0.96) 55.2%, rgba(0,0,0,0.84) 60.5%, rgba(0,0,0,0.68) 65.8%, rgba(0,0,0,0.50) 71.0%, rgba(0,0,0,0.32) 76.2%, rgba(0,0,0,0.16) 81.5%, rgba(0,0,0,0.04) 86.8%, transparent 92.0%), linear-gradient(to right, transparent 0.0%, rgba(0,0,0,0.04) 1.0%, rgba(0,0,0,0.16) 2.0%, rgba(0,0,0,0.32) 3.0%, rgba(0,0,0,0.50) 4.0%, rgba(0,0,0,0.68) 5.0%, rgba(0,0,0,0.84) 6.0%, rgba(0,0,0,0.96) 7.0%, #000 8.0%, #000 92.0%, rgba(0,0,0,0.96) 93.0%, rgba(0,0,0,0.84) 94.0%, rgba(0,0,0,0.68) 95.0%, rgba(0,0,0,0.50) 96.0%, rgba(0,0,0,0.32) 97.0%, rgba(0,0,0,0.16) 98.0%, rgba(0,0,0,0.04) 99.0%, transparent 100.0%);
            mask-image: linear-gradient(to bottom, transparent 0.0%, rgba(0,0,0,0.04) 3.0%, rgba(0,0,0,0.16) 6.0%, rgba(0,0,0,0.32) 9.0%, rgba(0,0,0,0.50) 12.0%, rgba(0,0,0,0.68) 15.0%, rgba(0,0,0,0.84) 18.0%, rgba(0,0,0,0.96) 21.0%, #000 24.0%, #000 50.0%, rgba(0,0,0,0.96) 55.2%, rgba(0,0,0,0.84) 60.5%, rgba(0,0,0,0.68) 65.8%, rgba(0,0,0,0.50) 71.0%, rgba(0,0,0,0.32) 76.2%, rgba(0,0,0,0.16) 81.5%, rgba(0,0,0,0.04) 86.8%, transparent 92.0%), linear-gradient(to right, transparent 0.0%, rgba(0,0,0,0.04) 1.0%, rgba(0,0,0,0.16) 2.0%, rgba(0,0,0,0.32) 3.0%, rgba(0,0,0,0.50) 4.0%, rgba(0,0,0,0.68) 5.0%, rgba(0,0,0,0.84) 6.0%, rgba(0,0,0,0.96) 7.0%, #000 8.0%, #000 92.0%, rgba(0,0,0,0.96) 93.0%, rgba(0,0,0,0.84) 94.0%, rgba(0,0,0,0.68) 95.0%, rgba(0,0,0,0.50) 96.0%, rgba(0,0,0,0.32) 97.0%, rgba(0,0,0,0.16) 98.0%, rgba(0,0,0,0.04) 99.0%, transparent 100.0%);
    -webkit-mask-composite: source-in;
            mask-composite: intersect;
  }
  .pg-art--window {
    margin-top: 28px;
    -webkit-mask-image: linear-gradient(to bottom, transparent 0.0%, rgba(0,0,0,0.04) 3.8%, rgba(0,0,0,0.16) 7.5%, rgba(0,0,0,0.32) 11.2%, rgba(0,0,0,0.50) 15.0%, rgba(0,0,0,0.68) 18.8%, rgba(0,0,0,0.84) 22.5%, rgba(0,0,0,0.96) 26.2%, #000 30.0%, #000 60.0%, rgba(0,0,0,0.96) 64.2%, rgba(0,0,0,0.84) 68.5%, rgba(0,0,0,0.68) 72.8%, rgba(0,0,0,0.50) 77.0%, rgba(0,0,0,0.32) 81.2%, rgba(0,0,0,0.16) 85.5%, rgba(0,0,0,0.04) 89.8%, transparent 94.0%), linear-gradient(to right, transparent 0.0%, rgba(0,0,0,0.04) 0.8%, rgba(0,0,0,0.16) 1.5%, rgba(0,0,0,0.32) 2.2%, rgba(0,0,0,0.50) 3.0%, rgba(0,0,0,0.68) 3.8%, rgba(0,0,0,0.84) 4.5%, rgba(0,0,0,0.96) 5.2%, #000 6.0%, #000 94.0%, rgba(0,0,0,0.96) 94.8%, rgba(0,0,0,0.84) 95.5%, rgba(0,0,0,0.68) 96.2%, rgba(0,0,0,0.50) 97.0%, rgba(0,0,0,0.32) 97.8%, rgba(0,0,0,0.16) 98.5%, rgba(0,0,0,0.04) 99.2%, transparent 100.0%);
            mask-image: linear-gradient(to bottom, transparent 0.0%, rgba(0,0,0,0.04) 3.8%, rgba(0,0,0,0.16) 7.5%, rgba(0,0,0,0.32) 11.2%, rgba(0,0,0,0.50) 15.0%, rgba(0,0,0,0.68) 18.8%, rgba(0,0,0,0.84) 22.5%, rgba(0,0,0,0.96) 26.2%, #000 30.0%, #000 60.0%, rgba(0,0,0,0.96) 64.2%, rgba(0,0,0,0.84) 68.5%, rgba(0,0,0,0.68) 72.8%, rgba(0,0,0,0.50) 77.0%, rgba(0,0,0,0.32) 81.2%, rgba(0,0,0,0.16) 85.5%, rgba(0,0,0,0.04) 89.8%, transparent 94.0%), linear-gradient(to right, transparent 0.0%, rgba(0,0,0,0.04) 0.8%, rgba(0,0,0,0.16) 1.5%, rgba(0,0,0,0.32) 2.2%, rgba(0,0,0,0.50) 3.0%, rgba(0,0,0,0.68) 3.8%, rgba(0,0,0,0.84) 4.5%, rgba(0,0,0,0.96) 5.2%, #000 6.0%, #000 94.0%, rgba(0,0,0,0.96) 94.8%, rgba(0,0,0,0.84) 95.5%, rgba(0,0,0,0.68) 96.2%, rgba(0,0,0,0.50) 97.0%, rgba(0,0,0,0.32) 97.8%, rgba(0,0,0,0.16) 98.5%, rgba(0,0,0,0.04) 99.2%, transparent 100.0%);
    -webkit-mask-composite: source-in;
            mask-composite: intersect;
  }
  .pg-art--horizon { margin-bottom: 0; }
}
@media (max-width: 720px) {
  .pg-art--discover, .pg-art--desk, .pg-art--trails, .pg-art--concrete, .pg-art--planet { margin-bottom: 0; }
  .pg-art--window { margin-top: 24px; margin-bottom: -24px; }
}

/* 10. Closing CTA composition (4 Oct 2026). The journey, the "Prefer to
   talk" line and the guarantee floated as three separate lines in a tall
   gap. The journey and fallback now sit as one block under the panel, and
   the guarantee closes the section after a short centred hairline, with
   balanced space above and below. Wording and terms unchanged. */
#chat-cta .ask-journey { margin-top: 24px; }
#chat-cta .ask-journey + .chat-cta-fallback { margin-top: 14px; }
#chat-cta .guarantee-strip {
  position: relative; margin-top: 36px; padding-top: 28px;
}
#chat-cta .guarantee-strip::before {
  content: ''; position: absolute; top: 0; left: 50%; width: 48px; height: 0; margin-left: -24px;
  border-top: 1px solid var(--hairline-hover);
}
#chat-cta .g-item { text-align: center; }
#chat-cta .g-desc { max-width: none; color: var(--text-dim); }
@media (max-width: 640px) { #chat-cta .guarantee-strip { margin-top: 30px; padding-top: 24px; } }
/* the journey's numbered rings: digits centred on the ring, not on the
   text baseline */
@media (max-width: 560px) {
  #chat-cta .ask-journey > li::before,
  #chat-cta .ask-journey > li + li::before { line-height: 1; font-variant-numeric: tabular-nums; padding: 0 0 1px; box-sizing: border-box; }  /* digits sit low in this face; 1px lifts them to the ring's optical centre */
}


/* ═══════════════════════════════════════════════════════════════════════
   FINAL POLISH, 5 Oct 2026. Only what the 4 Oct block did not already
   settle; each item names the defect.
   ═══════════════════════════════════════════════════════════════════════ */

/* G/H. Work 05 "Astro · this run": its glyphs sit at the top of each
   two-line row, but the 4 Oct timeline rule (later in the file, same
   specificity) measured the connector from the row's middle, so segments
   started halfway down each row and stopped short of the next glyph. The
   glyph centre is 17px down a row (8px padding + 2px + 7px), so each
   segment runs from 2px below this glyph to 2px above the next. Steps not
   reached yet show an empty hairline ring, so the line always meets a node. */
.page-work .work-run-steps > li:not(:last-child)::after { top: 24.5px; height: calc(100% - 15px); }
.page-work .work-run-steps > li > .st::before {
  content: ''; position: absolute; top: 1.5px; left: 1.5px; width: 11px; height: 11px; box-sizing: border-box;
  border: 1px solid var(--hairline-hover); border-radius: 50%; transition: opacity 160ms linear;
}
.page-work .work-run-steps > li.is-live > .st::before,
.page-work .work-run-steps > li.is-done > .st::before { opacity: 0; }

/* I. Work 04 on phones: the open step's detail card wraps inside the step
   row, so the row is tall and the rail's connector (placed from 50% of the
   row) started halfway down the card and left the spine broken above it.
   The connector now starts from the ring, which is 21.5px down every row,
   so the spine runs unbroken past the card on its left; the card stays to
   the right of the timeline column, attached to its step. */
@media (max-width: 720px) {
  .page-work .work-rail .ak-rail-node:not(:last-child)::before,
  .page-work .work-rail .ak-rail-node:not(:last-child)::after { top: 29px; height: calc(100% - 15px); }
  .page-work .work-rail .work-inspect { padding: 14px 16px; }
}

/* J. Four-tab lists on phones (Work 09): the kit lays tabs three across
   under 420px, which orphaned "Approval" on a row of its own. A list of
   exactly four tabs is a 2 x 2 grid instead; three-tab lists are unchanged. */
@media (max-width: 560px) {
  .ak-page .ak-tabs:has(> .ak-tab:nth-child(4):last-child) { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
/* the "Your process — Astro — Your systems — Your team" line under those
   tabs wrapped with a connector starting the second row; on phones it is
   two by two without connectors before a row start */
@media (max-width: 560px) {
  .page-work .work-biz .ak-flow { display: grid; grid-template-columns: repeat(2, max-content); justify-content: center; gap: 10px 22px; }
  .page-work .work-biz .ak-flow > * + *::before { display: none; }
}

/* K. Phones: three decorative images take part in the section that follows
   instead of standing as their own block. Each moves down behind the
   section's label and heading and dissolves to black well before the text
   (the lower 45% of the image is the fade), so the copy always sits on
   near-black. Review's star trails, Pricing's beam, Work's planet. */
@media (max-width: 720px) {
  .pg-art--trails, .pg-art--concrete, .pg-art--planet {
    margin-top: -64px; margin-bottom: -150px;
    -webkit-mask-image: linear-gradient(to bottom, transparent 0%, rgba(0,0,0,0.5) 12%, #000 26%, #000 44%, rgba(0,0,0,0.55) 62%, rgba(0,0,0,0.18) 78%, transparent 92%), linear-gradient(to right, transparent 0, #000 8%, #000 92%, transparent 100%);
            mask-image: linear-gradient(to bottom, transparent 0%, rgba(0,0,0,0.5) 12%, #000 26%, #000 44%, rgba(0,0,0,0.55) 62%, rgba(0,0,0,0.18) 78%, transparent 92%), linear-gradient(to right, transparent 0, #000 8%, #000 92%, transparent 100%);
    -webkit-mask-composite: source-in; mask-composite: intersect;
  }
  .pg-art--trails { height: 320px; }
  .pg-art--concrete { height: 330px; }
  .pg-art--planet { height: 330px; }
  .pg-art--planet img { object-position: 74% 40%; }
}

/* C. The improvement loop: one continuous hairline track around the
   ellipse (astro-about.js), under the stage pills; the copper arc into the
   chosen stage and every direction mark sit on it. The separate hairline
   arcs it replaces left gaps that read as five arrows, not one loop. */
.page-about .ab-loop-track { fill: none; stroke: var(--hairline-hover); stroke-width: 1.5; }
.page-about .ab-loop-arc:not(.is-lit) { stroke: transparent; }
/* L. Reduce Admin 06's control chain is the one other horizontal strip on
   phones; it takes the same safe area and edge fade as the stage strips */
@media (max-width: 760px) {
  .page-admin .admin-ctrl-chain {
    padding-left: 16px; padding-right: 16px; scroll-padding-inline: 16px;
    -webkit-mask-image: linear-gradient(to right, transparent 0, #000 8px, #000 calc(100% - 8px), transparent 100%);
            mask-image: linear-gradient(to right, transparent 0, #000 8px, #000 calc(100% - 8px), transparent 100%);
  }
}


/* ═══════════════════════════════════════════════════════════════════════
   MOBILE HERO COMPOSITION, 5 Oct 2026 (final hero pass, James). Phones
   only. The nav already says ASTRO, so the large wordmark is visually
   hidden (it stays the page's h1 for assistive tech), and the stack is
   proposition, visual, explanation, action:
     Cut loose. Reach orbit.  ->  black hole  ->  sub copy  ->  Ask Astro
     ->  Increase Leads / Reduce Admin  ->  live panel
   The black hole keeps its 4 Oct scale and bleed exactly (140vw clip in
   a 58vw window); only its place in the order and its spacing change. Its
   window already fades in from darkness at the top and back out at the
   bottom, so it rises out of the space under the headline and settles
   back into black above the copy. Landscape phones get the same order
   with the contained 16:9 black hole capped, so it fits a short screen.
   ═══════════════════════════════════════════════════════════════════════ */
@media (max-width: 720px), (max-width: 960px) and (max-height: 500px) and (orientation: landscape) {
  .hero-h1 {
    position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden;
    clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
  }
  .hero-tagline { order: 1; margin-top: 0; }
  .hero-orb { order: 2; }
  .hero-sub { order: 3; }
  .hero-cta-row { order: 4; }
  .sys-panel { order: 5; }
}
@media (max-width: 720px) {
  .hero-content { padding-top: 84px; }
  .hero-orb { margin-top: 2px; margin-bottom: 6px; }
  .hero-sub { margin-top: 0; }
  .hero-cta-row { margin-top: 22px; }
  .hero-content .btn-primary { padding-top: 13px; padding-bottom: 13px; }
}
@media (max-width: 960px) and (max-height: 500px) and (orientation: landscape) {
  .hero-content { padding-top: 76px; }
  .hero-orb { max-width: min(560px, 100%); width: 100%; justify-self: center; margin: 6px auto 0; }
  .hero-sub { margin-top: 10px; }
}

/* ── Final mobile hero micro-polish, 4 Oct 2026 (James) ──
   1. The explanation began 21-23px under the black hole's lowest visible
      light (its soft lower trails), against a 27-32px gap from the
      headline's glyphs down to the artwork's top arc, and the trails ran
      down towards the text. 18px more room below the artwork; the black
      hole, the headline and everything above it are untouched.
   2. The nav's Ask Astro pill, phones and tablets: 33px tall (was 36px,
      8.3% thinner) and exactly 5% narrower: the label is 60.125px wide, so
      side padding 11.8px gives 83.72px (was 88.125px), and 9.9px under
      361px gives 79.92px (was 84.125px). Font, colour and shape unchanged;
      the label stays centred both ways. */
@media (max-width: 720px) { .hero-sub { margin-top: 18px; } }
@media (max-width: 960px) {
  nav .nav-btn.btn-filled { min-height: 33px; height: 33px; padding: 0 11.8px; display: inline-flex; align-items: center; justify-content: center; line-height: 1; }
}
@media (max-width: 360px) { nav .nav-btn.btn-filled { padding: 0 9.9px; } }


/* ═══════════════════════════════════════════════════════════════════════
   FINAL MOBILE QA PASS, 5 Oct 2026 (James). Seven jobs; each block below
   is labelled with its job.
   ═══════════════════════════════════════════════════════════════════════ */
/* Job 1: the Voice Receptionist demo runs at 2x (astro-home.js, RATE).
   The transitions that carry each step in are halved with it. */
#in-action [data-at] { transition-duration: 210ms; }
#in-action .act-progress-fill { transition-duration: 210ms; }
#in-action .st > .st-check, #in-action .st > .st-spin { transition-duration: 130ms; }

/* Job 2: the improvement loop on phones is one closed clockwise circuit
   around the four cards: Live -> Monitor (right), Monitor -> Optimise
   (down), Optimise -> Refine (left), Refine -> Live (up). Every connector
   is anchored to the cards' outer borders, so it starts and ends exactly
   on them whatever the card height; each line belongs to the card it
   leaves (::after) and each arrowhead to the card it reaches (::before).
   A connector turns copper once the card it leaves is done; the circuit
   makes the return to Live, so the "Back to live" line is not shown here.
   Desktop keeps its row and return bracket. */
@media (max-width: 520px) {
  .loop { --lg: 26px; column-gap: var(--lg); row-gap: var(--lg); }
  .loop-return { display: none; }
  .loop > .loop-node::before, .loop > .loop-node::after {
    content: ''; display: block; position: absolute; transform: none;
    font-size: 0; background: var(--meta-ui); transition: background-color 260ms var(--ease);
  }
  .loop > .loop-node::after { background: var(--hairline-hover); }
  /* lines (1px, outer border to outer border) */
  .loop > .loop-node:nth-child(1)::after { left: calc(100% + 1px); top: calc(50% - 0.5px); width: var(--lg); height: 1px; }
  .loop > .loop-node:nth-child(2)::after { top: calc(100% + 1px); left: calc(50% - 0.5px); width: 1px; height: var(--lg); }
  .loop > .loop-node:nth-child(4)::after { right: calc(100% + 1px); top: calc(50% - 0.5px); width: var(--lg); height: 1px; }
  .loop > .loop-node:nth-child(3)::after { bottom: calc(100% + 1px); left: calc(50% - 0.5px); width: 1px; height: var(--lg); }
  /* arrowheads, tip on the receiving card's outer border */
  .loop > .loop-node:nth-child(2)::before { left: -7px; top: calc(50% - 3.5px); width: 6px; height: 7px; clip-path: polygon(0 0, 100% 50%, 0 100%); }
  .loop > .loop-node:nth-child(4)::before { top: -7px; left: calc(50% - 3.5px); width: 7px; height: 6px; clip-path: polygon(0 0, 100% 0, 50% 100%); }
  .loop > .loop-node:nth-child(3)::before { left: calc(100% + 1px); top: calc(50% - 3.5px); width: 6px; height: 7px; clip-path: polygon(100% 0, 0 50%, 100% 100%); }
  .loop > .loop-node:nth-child(1)::before { top: calc(100% + 1px); left: calc(50% - 3.5px); width: 7px; height: 6px; clip-path: polygon(50% 0, 100% 100%, 0 100%); }
  /* lit: the connector leaving a finished card */
  .loop > .loop-node.is-done::after,
  .loop:has(> .loop-node:nth-child(1).is-done) > .loop-node:nth-child(2)::before,
  .loop:has(> .loop-node:nth-child(2).is-done) > .loop-node:nth-child(4)::before,
  .loop:has(> .loop-node:nth-child(4).is-done) > .loop-node:nth-child(3)::before,
  .loop:has(> .loop-node:nth-child(3).is-done) > .loop-node:nth-child(1)::before { background: var(--blue-border); }
}

/* Job 3: vertical rails. Each connector runs from the bottom edge of one
   node to the top edge of the next, measured from the nodes themselves by
   astro-rails.js (--rail-y, --rail-h on the row), never from the row box,
   so a taller row, a wrapped label or a state change cannot break it.
   Dashed connectors are a drawn pattern (3px mark, 3px space, starting
   with a mark at the node) instead of border-style: dashed, which on a
   short segment rendered as one or two fragments and differs by browser.
   Colours, widths and x positions are unchanged. */
.ak-timeline.is-railfit > li:not(:last-child)::after,
.lead-future.is-railfit > li:not(:last-child)::after,
.mini-steps.is-rail.is-railfit > li:not(:last-child)::after { top: var(--rail-y); height: var(--rail-h); bottom: auto; }
@media (max-width: 720px) {
  .ak-page .ak-rail.is-railfit > .ak-rail-node:not(:last-child)::before,
  .ak-page .ak-rail.is-railfit > .ak-rail-node:not(:last-child)::after { top: var(--rail-y); height: var(--rail-h); bottom: auto; }
  .ak-page .is-degraded .ak-rail-node:not(:last-child)::after {
    border-left-width: 0; width: 1.5px;
    background: repeating-linear-gradient(to bottom, var(--hairline-hover) 0 3px, transparent 3px 6px);
  }
  .ak-page .is-degraded .ak-rail-node:not(:last-child)::before { border-left-color: transparent; }
}
.page-leads .lead-future > li:not(:last-child)::after,
.ak-page .ak-timeline > li.is-wait-row.is-done::after {
  border-left-width: 0; width: 1.5px;
  background: repeating-linear-gradient(to bottom, var(--hairline-hover) 0 3px, transparent 3px 6px);
}
/* Job 3, two-half rails: the stage rail (Pricing 03, the kit) and About's
   "What it changes" path draw each connector as two halves meeting at the
   row boundary, which already follows any row height. The halves stopped
   9 to 9.5px from the ring's centre, short of its 11px ring (5.5px radius),
   leaving a 3.5 to 4px gap at every node; they now end on the ring. The
   interruption around a selected card is unchanged. */
.ak-page .ak-stagerail-item:not(:first-child)::before { bottom: calc(50% + 5.5px); }
.ak-page .ak-stagerail-item:not(:last-child)::after { top: calc(50% + 5.5px); }
.page-about .ab-path > li:not(:first-child)::before { bottom: calc(50% + 5.5px); }
.page-about .ab-path > li:not(:last-child)::after { top: calc(50% + 5.5px); }
/* Job 4: horizontal strips have no vertical axis. Each strip set only
   overflow-x: auto, and CSS then computes overflow-y as auto as well, so a
   strip whose content was a pixel taller than its box (the stage strips on
   Increase Leads, Reduce Admin and Pricing measured 1px) became a second,
   vertical scroller inside the page, which is the bounce a vertical swipe
   produced there. The Y axis is now hidden on every strip, at exactly the
   widths where it scrolls sideways, so a vertical swipe can only move the
   page; horizontal swipes, snapping and the kit's scroll-into-view are
   unchanged. touch-action is Job 6. No script reads or writes a strip's
   vertical position (audited: only scrollLeft is ever set). */
@media (max-width: 860px) {
  .ak-page .ak-stagerail-list { overflow-y: hidden; overscroll-behavior-y: auto; touch-action: manipulation; }
  .page-admin .admin-ctrl-chain { overflow-y: hidden; overscroll-behavior-y: auto; touch-action: manipulation; }
}
@media (max-width: 760px) {
  .ak-page .ak-stage { overflow-y: hidden; overscroll-behavior-y: auto; touch-action: manipulation; }
  .page-admin .admin-demo-flow { overflow-y: hidden; overscroll-behavior-y: auto; touch-action: manipulation; }
}
/* Job 6: no double-tap zoom on anything you tap, pinch zoom kept. Safari
   zooms the page on two quick taps unless the touched element says its
   gestures are only pans and pinches. touch-action: manipulation does
   exactly that (pan-x pan-y pinch-zoom): taps fire at once, a second
   quick tap is a second tap, vertical and horizontal swipes still scroll,
   and a two-finger pinch still zooms the page. Until now only the kit's
   tabs and rows had it; the homepage controls and every .ui-btn (Pause,
   Step, Outcome, Replay, Run...) did not. It now covers every control, and
   the demonstration panels themselves (.ui-panel), because quick taps on
   a demo land between its buttons as often as on them. Ordinary page
   content keeps the browser's default gestures. The viewport meta is
   unchanged (width=device-width, initial-scale=1): no user-scalable=no,
   no maximum-scale. */
a[href], button, [role="button"], [role="tab"], summary, label, input, select, textarea,
.ui-panel, nav { touch-action: manipulation; }

/* Job 5: About, three photographs that become their sections (phones
   only, up to 720px; tablet and desktop unchanged). The homepage black
   hole's principle: the picture is still on screen when the words arrive,
   and dissolves into the Astro ground behind them, so photo and section
   read as one composition, never "image, then section". Each keeps its
   own image, subject and crop family; the overlaps differ by image.
   Every band is masked on all four sides with eased (smoothstep) fades,
   so no rectangle edge exists; words only ever sit over the faded, dark
   part of a picture, never over a face or the desk's detail. */
.pg-art--window-m { display: none; }
@media (max-width: 720px) {
  /* 5A, the window. The hero's own layer gives way to this one, inside
     "Why Astro exists": it starts at the section top, holds the city and
     the man, and its dark floor runs under the eyebrow and the title
     (which sit over the last 30% of the band, at 40% opacity and below). */
  #page-header .pg-art--window { display: none; }
  .pg-art--window-m {
    display: block; position: relative; inset: auto; mix-blend-mode: normal;
    height: clamp(290px, 92vw, 430px);
    margin: -54px 0 clamp(-128px, -30vw, -88px);
    -webkit-mask-image: linear-gradient(to bottom, rgba(0,0,0,0.00) 0.0%, rgba(0,0,0,0.04) 3.0%, rgba(0,0,0,0.16) 6.0%, rgba(0,0,0,0.32) 9.0%, rgba(0,0,0,0.50) 12.0%, rgba(0,0,0,0.68) 15.0%, rgba(0,0,0,0.84) 18.0%, rgba(0,0,0,0.96) 21.0%, rgba(0,0,0,1.00) 24.0%, rgba(0,0,0,0.96) 58.0%, rgba(0,0,0,0.84) 64.0%, rgba(0,0,0,0.68) 70.0%, rgba(0,0,0,0.50) 76.0%, rgba(0,0,0,0.32) 82.0%, rgba(0,0,0,0.16) 88.0%, rgba(0,0,0,0.04) 94.0%, rgba(0,0,0,0.00) 100.0%), linear-gradient(to right, rgba(0,0,0,0.00) 0.0%, rgba(0,0,0,0.04) 1.1%, rgba(0,0,0,0.16) 2.2%, rgba(0,0,0,0.32) 3.4%, rgba(0,0,0,0.50) 4.5%, rgba(0,0,0,0.68) 5.6%, rgba(0,0,0,0.84) 6.8%, rgba(0,0,0,0.96) 7.9%, rgba(0,0,0,1.00) 9.0%, rgba(0,0,0,0.96) 92.1%, rgba(0,0,0,0.84) 93.2%, rgba(0,0,0,0.68) 94.4%, rgba(0,0,0,0.50) 95.5%, rgba(0,0,0,0.32) 96.6%, rgba(0,0,0,0.16) 97.8%, rgba(0,0,0,0.04) 98.9%, rgba(0,0,0,0.00) 100.0%);
          mask-image: linear-gradient(to bottom, rgba(0,0,0,0.00) 0.0%, rgba(0,0,0,0.04) 3.0%, rgba(0,0,0,0.16) 6.0%, rgba(0,0,0,0.32) 9.0%, rgba(0,0,0,0.50) 12.0%, rgba(0,0,0,0.68) 15.0%, rgba(0,0,0,0.84) 18.0%, rgba(0,0,0,0.96) 21.0%, rgba(0,0,0,1.00) 24.0%, rgba(0,0,0,0.96) 58.0%, rgba(0,0,0,0.84) 64.0%, rgba(0,0,0,0.68) 70.0%, rgba(0,0,0,0.50) 76.0%, rgba(0,0,0,0.32) 82.0%, rgba(0,0,0,0.16) 88.0%, rgba(0,0,0,0.04) 94.0%, rgba(0,0,0,0.00) 100.0%), linear-gradient(to right, rgba(0,0,0,0.00) 0.0%, rgba(0,0,0,0.04) 1.1%, rgba(0,0,0,0.16) 2.2%, rgba(0,0,0,0.32) 3.4%, rgba(0,0,0,0.50) 4.5%, rgba(0,0,0,0.68) 5.6%, rgba(0,0,0,0.84) 6.8%, rgba(0,0,0,0.96) 7.9%, rgba(0,0,0,1.00) 9.0%, rgba(0,0,0,0.96) 92.1%, rgba(0,0,0,0.84) 93.2%, rgba(0,0,0,0.68) 94.4%, rgba(0,0,0,0.50) 95.5%, rgba(0,0,0,0.32) 96.6%, rgba(0,0,0,0.16) 97.8%, rgba(0,0,0,0.04) 98.9%, rgba(0,0,0,0.00) 100.0%);
  -webkit-mask-composite: source-in; mask-composite: intersect;
  }
  .pg-art--window-m img { object-fit: cover; object-position: 42% 56%; }

  /* 5B, the desk. A taller band with the two people held higher in it,
     so its lower part is the dark front of the desk and the room; "The
     process" and the title enter over that, below the papers and faces. */
  .pg-art--discover {
    height: clamp(290px, 88vw, 400px);
    margin-bottom: clamp(-84px, -19vw, -58px);
    -webkit-mask-image: linear-gradient(to bottom, rgba(0,0,0,0.00) 0.0%, rgba(0,0,0,0.04) 2.2%, rgba(0,0,0,0.16) 4.5%, rgba(0,0,0,0.32) 6.8%, rgba(0,0,0,0.50) 9.0%, rgba(0,0,0,0.68) 11.2%, rgba(0,0,0,0.84) 13.5%, rgba(0,0,0,0.96) 15.8%, rgba(0,0,0,1.00) 18.0%, rgba(0,0,0,0.96) 63.2%, rgba(0,0,0,0.84) 68.5%, rgba(0,0,0,0.68) 73.8%, rgba(0,0,0,0.50) 79.0%, rgba(0,0,0,0.32) 84.2%, rgba(0,0,0,0.16) 89.5%, rgba(0,0,0,0.04) 94.8%, rgba(0,0,0,0.00) 100.0%), linear-gradient(to right, rgba(0,0,0,0.00) 0.0%, rgba(0,0,0,0.04) 1.1%, rgba(0,0,0,0.16) 2.2%, rgba(0,0,0,0.32) 3.4%, rgba(0,0,0,0.50) 4.5%, rgba(0,0,0,0.68) 5.6%, rgba(0,0,0,0.84) 6.8%, rgba(0,0,0,0.96) 7.9%, rgba(0,0,0,1.00) 9.0%, rgba(0,0,0,0.96) 92.1%, rgba(0,0,0,0.84) 93.2%, rgba(0,0,0,0.68) 94.4%, rgba(0,0,0,0.50) 95.5%, rgba(0,0,0,0.32) 96.6%, rgba(0,0,0,0.16) 97.8%, rgba(0,0,0,0.04) 98.9%, rgba(0,0,0,0.00) 100.0%);
          mask-image: linear-gradient(to bottom, rgba(0,0,0,0.00) 0.0%, rgba(0,0,0,0.04) 2.2%, rgba(0,0,0,0.16) 4.5%, rgba(0,0,0,0.32) 6.8%, rgba(0,0,0,0.50) 9.0%, rgba(0,0,0,0.68) 11.2%, rgba(0,0,0,0.84) 13.5%, rgba(0,0,0,0.96) 15.8%, rgba(0,0,0,1.00) 18.0%, rgba(0,0,0,0.96) 63.2%, rgba(0,0,0,0.84) 68.5%, rgba(0,0,0,0.68) 73.8%, rgba(0,0,0,0.50) 79.0%, rgba(0,0,0,0.32) 84.2%, rgba(0,0,0,0.16) 89.5%, rgba(0,0,0,0.04) 94.8%, rgba(0,0,0,0.00) 100.0%), linear-gradient(to right, rgba(0,0,0,0.00) 0.0%, rgba(0,0,0,0.04) 1.1%, rgba(0,0,0,0.16) 2.2%, rgba(0,0,0,0.32) 3.4%, rgba(0,0,0,0.50) 4.5%, rgba(0,0,0,0.68) 5.6%, rgba(0,0,0,0.84) 6.8%, rgba(0,0,0,0.96) 7.9%, rgba(0,0,0,1.00) 9.0%, rgba(0,0,0,0.96) 92.1%, rgba(0,0,0,0.84) 93.2%, rgba(0,0,0,0.68) 94.4%, rgba(0,0,0,0.50) 95.5%, rgba(0,0,0,0.32) 96.6%, rgba(0,0,0,0.16) 97.8%, rgba(0,0,0,0.04) 98.9%, rgba(0,0,0,0.00) 100.0%);
  -webkit-mask-composite: source-in; mask-composite: intersect;
  }
  .pg-art--discover img { transform: scale(1.4); transform-origin: 72% 100%; }

  /* 5C, the window at sunset: the most overlap. The statement owns the
     upper left; the picture rises behind its last lines (still at a low
     opacity there, and further held back on the left by the radial term
     centred on the man), is full at the man and the sun, lower right,
     then returns to black before the next section. */
  .pg-art--horizon {
    height: clamp(320px, 104vw, 460px);
    margin-top: clamp(-138px, -30vw, -92px); margin-bottom: 0;
    -webkit-mask-image: linear-gradient(to bottom, rgba(0,0,0,0.00) 0.0%, rgba(0,0,0,0.04) 5.8%, rgba(0,0,0,0.16) 11.5%, rgba(0,0,0,0.32) 17.2%, rgba(0,0,0,0.50) 23.0%, rgba(0,0,0,0.68) 28.8%, rgba(0,0,0,0.84) 34.5%, rgba(0,0,0,0.96) 40.2%, rgba(0,0,0,1.00) 46.0%, rgba(0,0,0,0.96) 77.2%, rgba(0,0,0,0.84) 80.5%, rgba(0,0,0,0.68) 83.8%, rgba(0,0,0,0.50) 87.0%, rgba(0,0,0,0.32) 90.2%, rgba(0,0,0,0.16) 93.5%, rgba(0,0,0,0.04) 96.8%, rgba(0,0,0,0.00) 100.0%), linear-gradient(to right, rgba(0,0,0,0.00) 0.0%, rgba(0,0,0,0.04) 1.1%, rgba(0,0,0,0.16) 2.2%, rgba(0,0,0,0.32) 3.4%, rgba(0,0,0,0.50) 4.5%, rgba(0,0,0,0.68) 5.6%, rgba(0,0,0,0.84) 6.8%, rgba(0,0,0,0.96) 7.9%, rgba(0,0,0,1.00) 9.0%, rgba(0,0,0,0.96) 92.1%, rgba(0,0,0,0.84) 93.2%, rgba(0,0,0,0.68) 94.4%, rgba(0,0,0,0.50) 95.5%, rgba(0,0,0,0.32) 96.6%, rgba(0,0,0,0.16) 97.8%, rgba(0,0,0,0.04) 98.9%, rgba(0,0,0,0.00) 100.0%), radial-gradient(ellipse 80% 90% at 66% 58%, #000 52%, rgba(0,0,0,0.75) 66%, rgba(0,0,0,0.35) 82%, transparent 100%);
          mask-image: linear-gradient(to bottom, rgba(0,0,0,0.00) 0.0%, rgba(0,0,0,0.04) 5.8%, rgba(0,0,0,0.16) 11.5%, rgba(0,0,0,0.32) 17.2%, rgba(0,0,0,0.50) 23.0%, rgba(0,0,0,0.68) 28.8%, rgba(0,0,0,0.84) 34.5%, rgba(0,0,0,0.96) 40.2%, rgba(0,0,0,1.00) 46.0%, rgba(0,0,0,0.96) 77.2%, rgba(0,0,0,0.84) 80.5%, rgba(0,0,0,0.68) 83.8%, rgba(0,0,0,0.50) 87.0%, rgba(0,0,0,0.32) 90.2%, rgba(0,0,0,0.16) 93.5%, rgba(0,0,0,0.04) 96.8%, rgba(0,0,0,0.00) 100.0%), linear-gradient(to right, rgba(0,0,0,0.00) 0.0%, rgba(0,0,0,0.04) 1.1%, rgba(0,0,0,0.16) 2.2%, rgba(0,0,0,0.32) 3.4%, rgba(0,0,0,0.50) 4.5%, rgba(0,0,0,0.68) 5.6%, rgba(0,0,0,0.84) 6.8%, rgba(0,0,0,0.96) 7.9%, rgba(0,0,0,1.00) 9.0%, rgba(0,0,0,0.96) 92.1%, rgba(0,0,0,0.84) 93.2%, rgba(0,0,0,0.68) 94.4%, rgba(0,0,0,0.50) 95.5%, rgba(0,0,0,0.32) 96.6%, rgba(0,0,0,0.16) 97.8%, rgba(0,0,0,0.04) 98.9%, rgba(0,0,0,0.00) 100.0%), radial-gradient(ellipse 80% 90% at 66% 58%, #000 52%, rgba(0,0,0,0.75) 66%, rgba(0,0,0,0.35) 82%, transparent 100%);
  -webkit-mask-composite: source-in, source-in; mask-composite: intersect, intersect;
  }
  .pg-art--horizon img { object-position: 68% 50%; }
}
/* Job 7: the Voice Receptionist's controls never move under a finger.
   Found by the rapid-tap tests: (1) Play and Pause differ by 11px, so each
   toggle shifted Step, Outcome and Replay sideways; the toggle now keeps
   the width of "Pause" at every size. (2) From 721 to 860px the controls
   shared the bar's row with the system name only while the stage label was
   short, so a label change ("Waiting" -> "Understanding the request")
   threw them onto the next row and a second quick tap on Step landed on
   Outcome. Up to 860px the controls now always take their own row, which
   is where a long label already put them. Wording and order unchanged. */
[data-act-toggle] { min-width: 5.2em; text-align: center; }
@media (max-width: 860px) {
  .act-bar > .act-controls { flex-basis: 100%; }
}
