/* ============================================================
   Catalation / Synapse — one-page landing
   Light-first, green, with an opt-in dark theme, driven by [data-theme] on
   <html>.

   COLOUR LIVES IN css/theme.css. Nothing in this file may contain a hex,
   rgb() or hsl() literal — every colour is `var(--token)`, and tools/lint.mjs
   fails the build if a literal creeps back in. Read theme.css first: it
   explains the five-step green scale, the three named roles (--primary /
   --accent / --deep) and the `--tone` inheritance the few local overrides
   below rely on.

   Reproduced from the previous catalation.com build. Differences from that
   build are deliberate and are called out inline:
     · the palette is one anchor hue — green — used at five depths, with colour
       living in the accents, the hero and the CTA while backgrounds stay
       light and near-neutral (test/theme.test.js asserts the hue, the depths
       and the contrast ratios)
     · fonts self-hosted from public/fonts instead of fonts.googleapis.com
     · build-mode tabs driven by radio inputs, so they work with CSS alone
     · the nav collapses to a disclosure below 900px
     · scroll reveals only hide content when JS is available
   ============================================================ */

/* ---------- Fonts (self-hosted subsets; see tools/fetch-fonts.sh) ---------- */

@font-face {
  font-family: 'Syne';
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url('/fonts/syne-subset.woff2') format('woff2');
  unicode-range: U+20-7e, U+a9, U+b0, U+b7, U+d7, U+2013-2014, U+2018-2019,
    U+201c-201d, U+2026, U+2039-203a, U+20ac, U+2122, U+2191-2193, U+25cf, U+2713;
}
@font-face {
  font-family: 'DM Sans';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url('/fonts/dmsans-subset.woff2') format('woff2');
  unicode-range: U+20-7e, U+a9, U+b0, U+b7, U+d7, U+2013-2014, U+2018-2019,
    U+201c-201d, U+2026, U+2039-203a, U+20ac, U+2122, U+2191-2193, U+25cf, U+2713;
}
@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 400 500;
  font-display: swap;
  src: url('/fonts/jetbrainsmono-subset.woff2') format('woff2');
  unicode-range: U+20-7e, U+a9, U+b0, U+b7, U+d7, U+2013-2014, U+2018-2019,
    U+201c-201d, U+2026, U+2039-203a, U+20ac, U+2122, U+2191-2193, U+25cf, U+2713;
}

/* ---------- Non-colour tokens ---------- */

:root {
  --text-xs:   11px;
  --text-sm:   13px;
  --text-base: 16px;
  --text-lg:   20px;
  --text-xl:   28px;
  --text-hero: clamp(44px, 6.4vw, 92px);

  --font-head: 'Syne', 'DM Sans', system-ui, sans-serif;
  --font-body: 'DM Sans', system-ui, sans-serif;
  --font-mono: 'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, monospace;

  --max-w: 1200px;
  --radius: 16px;
  --radius-sm: 10px;
  --ease: cubic-bezier(0.22, 1, 0.36, 1);

  --nav-h: 88px;
}

/* ============================================================
   Where the green goes

   The whole colour scheme is `--tone`, and theme.css sets it once: every
   eyebrow, marker, icon, rule and card border below reads `var(--tone)` and
   gets the anchor forest green. There is no positional walk and no
   per-section step any more — one anchor hue means one accent, used the same
   way from the top of the page to the bottom, which is what keeps green an
   accent rather than a flood. Where an older palette separated a set's members
   by hue, they now share the accent and are separated by the number, label or
   shape they already carried.

   Exactly three rules re-point `--tone`, each to `--deep`, and each on a pair
   whose members are already told apart in words:

     · .btn-primary        — so the button's hover glow follows the button
                             rather than whatever sits behind it;
     · .org-svg .is-ceo    — the second tier of the org chart;
     · .role-type.is-human — the "Human" badge beside the "Agent" one.

   Depth is never the only signal in any of the three: the button carries its
   label, the org nodes carry theirs, and both role badges spell the word out.
   ============================================================ */

* { box-sizing: border-box; margin: 0; padding: 0; }

html { scroll-behavior: smooth; }

body {
  background: var(--bg);
  color: var(--body);
  font-family: var(--font-body);
  font-size: var(--text-base);
  font-weight: 400;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  min-height: 100vh;
  overflow-x: hidden;
  position: relative;
  transition: background-color 0.4s var(--ease), color 0.4s var(--ease);
}

/* ---------- Accessibility helpers ---------- */

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

/* One focus ring for the whole page, and it has to survive being drawn on a
   light card *and* on a solid green button — a single-colour green ring would
   vanish against the CTA it is most likely to land on. So it is two rings:

     · an inner halo in `--on-accent`, hugging the element. On the green button
       that is white on forest green (7.6:1); on a light card it is white on
       white and simply invisible, which is fine because…
     · …the outer ring in `--cta` carries it there — the anchor forest green at
       6.99:1 on the page and 7.58:1 on a card, both well past 1.4.11's 3:1.

   The pair inverts correctly in the dark theme, where `--on-accent` is a
   near-black and `--cta` is a light green. test/theme.test.js measures all four
   pairings. */
:focus-visible {
  outline: 3px solid var(--cta);
  outline-offset: 3px;
  box-shadow: 0 0 0 3px var(--on-accent);
  border-radius: 6px;
}

.skip-link {
  position: absolute;
  left: 16px;
  top: -100px;
  z-index: 100;
  background: var(--surface);
  color: var(--text-strong);
  border: 1px solid var(--cta);
  border-radius: 10px;
  padding: 12px 18px;
  font-size: var(--text-sm);
  font-weight: 600;
  text-decoration: none;
  transition: top 0.2s var(--ease);
}
.skip-link:focus { top: 16px; }

/* ---------- Ambient background ---------- */

body::before {
  content: '';
  position: fixed;
  inset: 0;
  background-image:
    linear-gradient(var(--grid-line) 1px, transparent 1px),
    linear-gradient(90deg, var(--grid-line) 1px, transparent 1px);
  background-size: 56px 56px;
  mask-image: radial-gradient(ellipse 90% 70% at 50% 0%, black 10%, transparent 75%);
  -webkit-mask-image: radial-gradient(ellipse 90% 70% at 50% 0%, black 10%, transparent 75%);
  pointer-events: none;
  z-index: 0;
}

/* Three ambient blobs, taken from the three depths of the scale rather than
   from `--tone` — this layer is fixed to the viewport and must not change as
   the page scrolls under it. Held at the 4% wash strength so the page
   background stays light and near-neutral. */
body::after {
  content: '';
  position: fixed;
  inset: 0;
  background:
    radial-gradient(ellipse 620px 460px at 12% 4%,
      color-mix(in srgb, var(--accent) var(--tint-wash), transparent), transparent 60%),
    radial-gradient(ellipse 540px 440px at 88% 8%,
      color-mix(in srgb, var(--primary) var(--tint-wash), transparent), transparent 62%),
    radial-gradient(ellipse 700px 520px at 80% 95%,
      color-mix(in srgb, var(--deep) var(--tint-wash), transparent), transparent 60%);
  pointer-events: none;
  z-index: 0;
  transition: opacity 0.4s var(--ease);
}

.noise {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 1;
  opacity: 0.03;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='200' height='200'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
}

.site-nav, main, footer { position: relative; z-index: 2; }

/* ---------- Layout primitives ---------- */

.wrap {
  width: 100%;
  max-width: var(--max-w);
  margin: 0 auto;
  padding: 0 32px;
}

@media (max-width: 640px) { .wrap { padding: 0 20px; } }

/* ---------- Navigation ---------- */

.site-nav {
  position: sticky;
  top: 0;
  z-index: 50;
  padding: 16px 0;
  background: color-mix(in srgb, var(--bg) 72%, transparent);
  /* Blur plus a light saturation lift. The monochrome pass dropped the lift
     because a grey page has no chroma under the bar to boost; with the
     palette chromatic it keeps a card scrolling under the nav from going grey
     behind the frosting. */
  backdrop-filter: blur(14px) saturate(150%);
  -webkit-backdrop-filter: blur(14px) saturate(150%);
  border-bottom: 1px solid transparent;
  transition: border-color 0.3s var(--ease), background-color 0.3s var(--ease), padding 0.3s var(--ease);
}

.site-nav.is-scrolled {
  border-bottom-color: var(--border);
  padding: 11px 0;
}

.site-nav .wrap {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
}

/* The logo is unchanged by the recolour: the wordmark stays --text-strong, the
   near-black neutral, so it is the one mark on the page that does not move with
   the palette. The dot beside it takes the section tone, as it always has. */
.brand {
  display: flex;
  align-items: baseline;
  gap: 12px;
  text-decoration: none;
  color: var(--text-strong);
}

.brand-mark {
  font-family: var(--font-head);
  font-weight: 800;
  font-size: 17px;
  letter-spacing: 0.16em;
  color: var(--text-strong);
}

.brand-tag {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--tone);
  display: inline-flex;
  align-items: center;
  gap: 7px;
}

.brand-tag::before {
  content: '';
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--tone);
  box-shadow: 0 0 10px var(--tone);
  animation: pulse 2.4s var(--ease) infinite;
}

@keyframes pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50% { opacity: 0.45; transform: scale(0.8); }
}

.nav-right {
  display: flex;
  align-items: center;
  gap: 8px;
}

.nav-links {
  display: flex;
  gap: 26px;
  align-items: center;
  margin-right: 12px;
}

.nav-links a {
  color: var(--body);
  text-decoration: none;
  font-size: var(--text-sm);
  font-weight: 500;
  letter-spacing: 0.01em;
  position: relative;
  padding: 4px 0;
  transition: color 0.2s ease;
}

/* The hover underline is the CTA in miniature: it wipes in left to right and
   it wipes forest → pine, the same two stops the button is filled with.
   Only `width` transitions, so there is one property for reduced motion to
   zero. */
.nav-links a::after {
  content: '';
  position: absolute;
  left: 0; bottom: -2px;
  height: 2px; width: 0;
  background-color: var(--tone);
  background-image: linear-gradient(90deg, var(--cta), var(--cta-2));
  border-radius: 2px;
  transition: width 0.25s var(--ease);
}

.nav-links a:hover { color: var(--text-strong); }
.nav-links a:hover::after { width: 100%; }

/* Theme toggle */
.theme-toggle {
  width: 38px;
  height: 38px;
  border-radius: 10px;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text);
  cursor: pointer;
  display: inline-grid;
  place-items: center;
  position: relative;
  overflow: hidden;
  flex-shrink: 0;
  transition: border-color 0.2s ease, background-color 0.2s ease, transform 0.2s var(--ease);
}
.theme-toggle:hover { border-color: var(--cta); transform: translateY(-1px); }
.theme-toggle svg { width: 17px; height: 17px; transition: opacity 0.3s var(--ease), transform 0.4s var(--ease); position: absolute; }
.theme-toggle .icon-sun  { opacity: 0; transform: rotate(-90deg) scale(0.5); }
.theme-toggle .icon-moon { opacity: 1; transform: rotate(0) scale(1); }
[data-theme="dark"] .theme-toggle .icon-sun  { opacity: 1; transform: rotate(0) scale(1); }
[data-theme="dark"] .theme-toggle .icon-moon { opacity: 0; transform: rotate(90deg) scale(0.5); }

/* Mobile disclosure. Driven by a checkbox rather than JS so the menu still
   opens when scripting is unavailable; the label is the visible control and
   mirrors the checkbox's focus ring. */
.nav-check { position: absolute; opacity: 0; width: 1px; height: 1px; }
.nav-burger {
  display: none;
  width: 38px;
  height: 38px;
  border-radius: 10px;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text);
  cursor: pointer;
  place-items: center;
  flex-shrink: 0;
}
.nav-burger svg { width: 18px; height: 18px; }
.nav-burger .icon-close { display: none; }
.nav-check:checked ~ .nav-right .nav-burger .icon-close { display: block; }
.nav-check:checked ~ .nav-right .nav-burger .icon-open  { display: none; }
.nav-check:focus-visible ~ .nav-right .nav-burger {
  outline: 3px solid var(--cta);
  outline-offset: 3px;
  box-shadow: 0 0 0 3px var(--on-accent);
}

/* Off the small-screen breakpoint the disclosure does not exist, so keep its
   checkbox out of the tab order rather than leaving an invisible stop. */
@media (min-width: 901px) {
  .nav-check { display: none; }
}

@media (max-width: 900px) {
  .nav-burger { display: inline-grid; }
  .nav-links {
    display: none;
    position: absolute;
    top: calc(100% + 8px);
    right: 20px;
    left: 20px;
    flex-direction: column;
    align-items: stretch;
    gap: 2px;
    margin-right: 0;
    padding: 10px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow-lg);
  }
  .nav-check:checked ~ .nav-right .nav-links { display: flex; }
  .nav-links a { padding: 12px 14px; border-radius: var(--radius-sm); font-size: var(--text-base); }
  .nav-links a::after { content: none; }
  .nav-links a:hover { background: var(--surface-2); }
}

/* ---------- Buttons ----------
   The primary action is one fixed green for the whole page: `--cta` is the
   anchor forest green from the top of the page to the bottom, so the click
   target stays learnable. `--cta-2` is that same green at depth, and exists
   only so the fill can be a gradient rather than a flat rectangle — which is
   the "buttons get depth" half of the brief, not a second CTA colour.

   Because the fill is a gradient the label sits on a different colour at each
   end of the button. Both stops clear 4.5:1 against `--on-accent`, and sRGB
   interpolation between two such colours can only land between their
   luminances — so every pixel of the fill clears it too. test/theme.test.js
   samples across the button rather than taking that on trust.

   Every state change here is a transition, and the reduced-motion block at the
   foot of this file zeroes all of them. */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: var(--text-sm);
  letter-spacing: 0.01em;
  text-decoration: none;
  padding: 13px 22px;
  border-radius: 10px;
  border: 1px solid transparent;
  cursor: pointer;
  transition: transform 0.18s var(--ease), background-color 0.2s ease, border-color 0.2s ease, box-shadow 0.25s var(--ease), color 0.2s ease;
  white-space: nowrap;
}
.btn svg { width: 16px; height: 16px; }

.btn-primary {
  --tone: var(--cta);
  /* `background-color` first as the fallback the gradient paints over, so a
     browser that drops the image still has an AA-passing fill under the
     label rather than a transparent button. */
  background-color: var(--cta);
  background-image: linear-gradient(135deg, var(--cta) 0%, var(--cta-2) 100%);
  color: var(--on-accent);
  /* A hairline of the pine along the edge, so the fill reads as a raised
     object rather than as a flat rectangle of colour. */
  border-color: color-mix(in srgb, var(--cta-2) 55%, transparent);
  box-shadow: var(--shadow-sm);
}
.btn-primary:hover {
  transform: translateY(-2px);
  border-color: color-mix(in srgb, var(--cta-2) 80%, transparent);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--cta-2) 42%, transparent),
    0 12px 40px color-mix(in srgb, var(--cta) 30%, transparent);
}

.btn-ghost {
  background-color: var(--surface);
  /* The same two anchors at wash strength: enough for the ghost button to
     belong to the pair without competing with the filled one next to it. */
  background-image: linear-gradient(135deg,
    color-mix(in srgb, var(--cta) var(--tint-wash), transparent) 0%,
    color-mix(in srgb, var(--cta-2) var(--tint-wash), transparent) 100%);
  color: var(--text-strong);
  border-color: var(--border);
}
.btn-ghost:hover {
  transform: translateY(-2px);
  border-color: var(--border-strong);
  color: var(--cta);
  box-shadow: 0 8px 24px color-mix(in srgb, var(--cta) 18%, transparent);
}

/* ---------- Typography ---------- */

h1, h2, h3, h4 {
  font-family: var(--font-head);
  font-weight: 700;
  color: var(--text-strong);
  line-height: 1.06;
  letter-spacing: -0.025em;
}

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--tone);
  margin-bottom: 22px;
  padding: 7px 14px;
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  background: var(--fill);
}

.accent { color: var(--tone); }

/* ---------- Sections ---------- */

main { padding-bottom: 40px; }
main[id], section[id], div[id] { scroll-margin-top: var(--nav-h); }
main:focus { outline: none; }
.section { padding: 96px 0; }
.section--tight { padding: 64px 0; }

@media (max-width: 640px) {
  .section { padding: 64px 0; }
}

.section-head { max-width: 720px; margin: 0 auto 56px; text-align: center; position: relative; }

/* Abstract header visual (web-site#5).

   A fan of thin geometric rays over a soft tonal core, generated entirely from
   gradients in the section's own `--tone` — so it costs no request, needs no
   raster file, and re-themes with the palette instead of having to be re-cut.
   That is why the brief's "prefer CSS/SVG-generated backgrounds over external
   stock files" line is easy to honour here: the palette is already a token.

   It is decorative in the strict sense — `pointer-events: none`, no content, and
   nothing below it depends on it being painted. Both layers are held at
   `--tint-wash`, the cap theme.css sets for anything section-sized, so the page
   background stays near-neutral and the heading keeps its measured contrast.
   Nothing here animates, so there is no motion for reduced-motion to disable. */
.section-head::before {
  content: '';
  position: absolute;
  left: 50%;
  top: -68px;
  width: min(640px, 132%);
  height: 250px;
  transform: translateX(-50%);
  pointer-events: none;
  background-image:
    repeating-conic-gradient(from 200deg at 50% 76%,
      color-mix(in srgb, var(--tone) var(--tint-wash), transparent) 0deg 2.4deg,
      transparent 2.4deg 11deg),
    radial-gradient(ellipse 44% 56% at 50% 54%,
      color-mix(in srgb, var(--tone) var(--tint-wash), transparent), transparent 72%);
  mask-image: radial-gradient(ellipse 54% 58% at 50% 56%, black 6%, transparent 78%);
  -webkit-mask-image: radial-gradient(ellipse 54% 58% at 50% 56%, black 6%, transparent 78%);
}
/* A short green rule closing every section head. It runs bright → anchor →
   deep, so the rule is a three-step sample of the scale at 88px wide. It sits
   inside the head's existing 56px bottom margin, so nothing moves. */
.section-head::after {
  content: '';
  position: absolute;
  left: 50%;
  bottom: -24px;
  width: 88px;
  height: 3px;
  transform: translateX(-50%);
  border-radius: 3px;
  pointer-events: none;
  background-image: linear-gradient(90deg, var(--accent), var(--tone), var(--deep));
}

/* Lift the heading, eyebrow and lead above the decorative layer. Same idiom the
   CTA band uses, and preferred over a negative z-index, which would drop the
   graphic behind the section background instead of behind the text. */
.section-head > * { position: relative; }

.section-head h2 {
  font-size: clamp(30px, 4.2vw, 50px);
  letter-spacing: -0.03em;
}
.section-head p {
  margin-top: 18px;
  font-size: var(--text-lg);
  color: var(--body);
  line-height: 1.55;
}

/* ---------- Hero ----------
   The section the brief asks to carry the green gradient outright, and the one
   place a strength above the page-background cap is allowed. Three static
   layers, all running the same way — bright leaf green to deep pine:

     · a three-stop wash across the whole section, held at `--tint-wash`;
     · the same three stops again at `--tint-hero`, masked to an ellipse
       behind the headline so the gradient is strongest where the eye lands
       and gone by the edges of the section;
     · a forest → pine gradient clipped to the accented half of the
       headline.

   Why a wash and not a saturated flood: the primary call to action sits in
   this section and is itself one fixed green, so a solid green hero would
   hide the one element the page most needs to be findable. `--tint-hero`
   (10%) is the compromise — enough that the band reads as a green gradient at
   a glance (it flattens to #D2E8D2 at the bright end), while the CTA stays a
   solid green object on a light ground and every piece of copy keeps a
   measured ratio.
   test/theme.test.js measures the headline, the lead and the hero meta over
   the flattened band rather than over the plain page background, so the
   exception is paid for in contrast rather than asserted by eye. Nothing here
   animates. */

.hero {
  padding: clamp(56px, 9vw, 120px) 0 clamp(56px, 8vw, 100px);
  text-align: center;
  position: relative;
  background-image: linear-gradient(100deg,
    color-mix(in srgb, var(--accent) var(--tint-wash), transparent) 0%,
    color-mix(in srgb, var(--primary) var(--tint-wash), transparent) 52%,
    color-mix(in srgb, var(--deep) var(--tint-wash), transparent) 100%);
}
.hero::before {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image: linear-gradient(104deg,
    color-mix(in srgb, var(--accent) var(--tint-hero), transparent) 0%,
    color-mix(in srgb, var(--primary) var(--tint-hero), transparent) 52%,
    color-mix(in srgb, var(--deep) var(--tint-hero), transparent) 100%);
  mask-image: radial-gradient(ellipse 82% 64% at 50% 32%, black 6%, transparent 78%);
  -webkit-mask-image: radial-gradient(ellipse 82% 64% at 50% 32%, black 6%, transparent 78%);
}
/* Lift the hero's content above the band, the same stacking idiom the section
   heads and the CTA band use — a negative z-index would drop the gradient
   behind the page background instead of behind the copy. */
.hero .wrap { display: flex; flex-direction: column; align-items: center; position: relative; }

.hero h1 {
  font-size: var(--text-hero);
  font-weight: 800;
  letter-spacing: -0.04em;
  margin-bottom: 26px;
  max-width: 17ch;
}
.hero h1 .accent { font-style: italic; font-weight: 700; }

/* `color` stays a real, AA-passing value so the text is legible if the clip is
   unsupported, and so anything measuring the computed colour reads something
   genuine. The gradient runs between the two *text-weight* steps — the anchor
   forest and the pine — rather than starting on `--accent`, because this
   is copy and `--accent` is only held to the 3:1 non-text bar.
   test/theme.test.js samples the interpolation over the hero band rather than
   trusting the endpoints. */
.hero h1 .accent {
  color: var(--tone);
  background-image: linear-gradient(100deg, var(--tone) 0%, var(--deep) 100%);
}
@supports (background-clip: text) or (-webkit-background-clip: text) {
  .hero h1 .accent {
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
  }
}
/* In a forced-colours or high-contrast context the gradient is dropped and the
   system colour wins outright. */
@media (forced-colors: active) {
  .hero h1 .accent {
    background-image: none;
    -webkit-text-fill-color: currentColor;
  }
}

.lead {
  font-size: clamp(17px, 2.1vw, 21px);
  color: var(--body);
  max-width: 56ch;
  line-height: 1.55;
}

.hero-cta {
  display: flex;
  gap: 14px;
  margin-top: 38px;
  flex-wrap: wrap;
  justify-content: center;
}

.hero-meta {
  margin-top: 26px;
  display: flex;
  gap: 22px;
  flex-wrap: wrap;
  justify-content: center;
  font-size: var(--text-sm);
  color: var(--muted);
  list-style: none;
}
.hero-meta li { display: inline-flex; align-items: center; gap: 8px; }
.hero-meta li::before {
  content: '';
  width: 5px; height: 5px; border-radius: 50%;
  background: var(--tone);
  flex-shrink: 0;
}

/* Hero pipeline visual */
.flow {
  margin: 64px auto 0;
  max-width: 980px;
  width: 100%;
  display: grid;
  grid-template-columns: 1fr auto 1fr auto 1fr;
  align-items: stretch;
  gap: 0;
}
.flow-step {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 24px 22px;
  text-align: left;
  box-shadow: var(--shadow-sm);
  transition: transform 0.3s var(--ease), box-shadow 0.3s var(--ease), border-color 0.3s var(--ease);
}
/* Validate / Build / Operate are the same three stages the timeline restates.
   They used to take three steps of a two-hue ramp; on one anchor hue they
   share the accent and are separated by the 01/02/03 they already carry. */
.flow-step:hover { transform: translateY(-4px); box-shadow: var(--shadow-md); border-color: var(--tone); }
.flow-k {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--tone);
}
.flow-step h4 { font-size: var(--text-lg); margin: 12px 0 6px; }
.flow-step p { font-size: var(--text-sm); color: var(--body); }
.flow-arrow {
  display: grid;
  place-items: center;
  color: var(--muted);
  font-size: 22px;
  padding: 0 8px;
}
@media (max-width: 820px) {
  .flow { grid-template-columns: 1fr; gap: 12px; }
  .flow-arrow { transform: rotate(90deg); padding: 2px 0; }
}

/* ---------- Legal-footing / trust strip ---------- */

/* The strip immediately under the hero, so its two rules are where the hero's
   gradient hands over to the rest of the page: both are painted with the same
   bright → anchor → deep sweep via `border-image`. The solid `border-color`
   underneath is a real fallback — a browser without border-image support
   still draws a visible 1px edge rather than nothing at all. */
.trust {
  padding: 40px 0;
  border-top: 1px solid var(--border-strong);
  border-bottom: 1px solid var(--border-strong);
  border-image: linear-gradient(90deg, var(--accent), var(--primary), var(--deep)) 1;
}
.trust p {
  text-align: center;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 22px;
}
.trust-row {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: clamp(24px, 5vw, 60px);
  flex-wrap: wrap;
  list-style: none;
}
/* The previous build faded these with `opacity: .55`, which dropped the
   effective contrast to ~3:1. Same visual weight, solid colour instead. */
.trust-row li {
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 19px;
  letter-spacing: -0.01em;
  color: var(--body);
  transition: color 0.2s ease;
}
.trust-row li:hover { color: var(--text-strong); }

/* ---------- Bento concept grid ---------- */

.bento {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 16px;
  list-style: none;
}
.card {
  background: var(--surface);
  /* The card's own tone, tinted into the existing 1px border, so the set
     mapping reads without hovering. Recolouring rather than thickening keeps
     this purely visual — a 2px edge would move the content by 1px. */
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  padding: 30px;
  box-shadow: var(--shadow-sm);
  position: relative;
  overflow: hidden;
  transition: transform 0.3s var(--ease), box-shadow 0.3s var(--ease), border-color 0.3s var(--ease);
}
.card:hover { transform: translateY(-4px); box-shadow: var(--shadow-md); border-color: var(--tone); }
/* Abstract corner geometry: hairline diagonals in the accent, masked to a
   soft bloom in the top-right so they never run under the body copy.
   Generated, static, and clipped by the card's existing `overflow: hidden`. */
.card::before {
  content: '';
  position: absolute;
  top: -40%;
  right: -18%;
  width: 76%;
  height: 158%;
  pointer-events: none;
  background-image: repeating-linear-gradient(58deg,
    color-mix(in srgb, var(--tone) var(--tint-wash), transparent) 0 1px,
    transparent 1px 9px);
  mask-image: radial-gradient(ellipse 60% 48% at 76% 28%, black, transparent 72%);
  -webkit-mask-image: radial-gradient(ellipse 60% 48% at 76% 28%, black, transparent 72%);
}
.card > * { position: relative; }
.card-icon {
  width: 44px; height: 44px;
  border-radius: 12px;
  display: grid; place-items: center;
  background: var(--fill);
  color: var(--tone);
  margin-bottom: 18px;
}
.card-icon svg { width: 22px; height: 22px; }
.card h3 { font-size: var(--text-xl); margin-bottom: 10px; }
.card p { color: var(--body); font-size: var(--text-base); line-height: 1.55; }

.col-3 { grid-column: span 3; }

@media (max-width: 900px) {
  .bento { grid-template-columns: repeat(2, 1fr); }
  .col-3 { grid-column: span 2; }
}
@media (max-width: 560px) {
  .bento { grid-template-columns: 1fr; }
  .col-3 { grid-column: span 1; }
}

/* ---------- Pillars ---------- */

.pillars {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
  list-style: none;
}
.pillar {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 32px 30px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  box-shadow: var(--shadow-sm);
  transition: transform 0.3s var(--ease), box-shadow 0.3s var(--ease), border-color 0.3s var(--ease);
}
.pillar:hover { transform: translateY(-4px); box-shadow: var(--shadow-md); border-color: var(--tone); }
.pillar-num {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.16em;
  color: var(--tone);
  text-transform: uppercase;
}
.pillar h3 { font-size: var(--text-xl); }
.pillar p { color: var(--body); line-height: 1.55; }

@media (max-width: 820px) { .pillars { grid-template-columns: 1fr; } }

/* ---------- Org chart (inline SVG) ----------
   web-site#5 replaced the stack of HTML boxes with a single inline <svg>. It
   scales to any width without a raster asset and costs no extra request, and
   because every fill and stroke is set from *this file* rather than from a
   presentation attribute on the element, the diagram reads the same `--tone`
   the rest of the section does and re-themes with the page for free. (A
   `fill="var(--tone)"` attribute would not: custom properties are not resolved
   in SVG presentation attributes.)

   The graphic is aria-hidden like every other on the page; the figcaption below
   it is the text description that actually carries the structure. */

.org {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 32px 24px 28px;
  box-shadow: var(--shadow-sm);
  margin: 0;
  position: relative;
  overflow: hidden;
}

/* Blueprint backdrop for the diagram panel: a fine token-coloured grid and one
   soft wash, both generated from gradients rather than an image file, and both
   masked out towards the edges so the panel stays near-neutral. Held at
   `--tint-wash` because this is a panel-sized area, not a chip. */
.org::before {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image:
    linear-gradient(color-mix(in srgb, var(--tone) var(--tint-wash), transparent) 1px, transparent 1px),
    linear-gradient(90deg, color-mix(in srgb, var(--tone) var(--tint-wash), transparent) 1px, transparent 1px),
    radial-gradient(ellipse 70% 55% at 50% 0%,
      color-mix(in srgb, var(--tone) var(--tint-wash), transparent), transparent 70%);
  background-size: 24px 24px, 24px 24px, 100% 100%;
  mask-image: radial-gradient(ellipse 82% 76% at 50% 45%, black 30%, transparent 100%);
  -webkit-mask-image: radial-gradient(ellipse 82% 76% at 50% 45%, black 30%, transparent 100%);
}
.org > * { position: relative; }

.org-svg { display: block; width: 100%; height: auto; }
/* Node fills are mixed into an opaque surface rather than into `transparent`,
   so the blueprint grid behind the panel cannot show through a label. */
.org-svg .org-box { fill: var(--surface-2); stroke: var(--border); stroke-width: 1.5; }
.org-svg .org-link {
  fill: none;
  stroke: var(--border-strong);
  stroke-width: 2;
  stroke-linecap: round;
}
.org-svg .org-label {
  fill: var(--text-strong);
  font-family: var(--font-mono);
  font-size: 17px;
  letter-spacing: 0.04em;
}
/* Chairman takes the anchor forest green; the CEO node takes `--deep`, so the two
   tiers of the diagram are told apart by depth as well as by position. Both
   are labelled in text — which is what actually carries the distinction. */
.org-svg .org-box.is-lead,
.org-svg .org-box.is-ceo {
  fill: var(--fill);
  stroke: var(--border-strong);
}
.org-svg .org-label.is-lead,
.org-svg .org-label.is-ceo { fill: var(--tone); }
.org-svg .is-ceo { --tone: var(--deep); }

.org figcaption { margin-top: 20px; text-align: center; font-size: var(--text-sm); color: var(--body); }

/* ---------- Journey timeline ---------- */

.timeline {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 0;
  position: relative;
  list-style: none;
}
.tl-item {
  position: relative;
  padding: 0 16px;
}
/* The connector is the visible-edge token, so the rail reads as one
   continuous line from Discover to Operate. */
.tl-item::before {
  content: '';
  position: absolute;
  top: 13px; left: 0; right: 0;
  height: 2px;
  background: var(--border-strong);
}
.tl-item:first-child::before { left: 50%; }
.tl-item:last-child::before { right: 50%; }
.tl-dot {
  position: relative;
  z-index: 1;
  width: 28px; height: 28px;
  border-radius: 50%;
  background: var(--surface);
  border: 2px solid var(--tone);
  color: var(--tone);
  display: grid; place-items: center;
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 600;
  margin: 0 auto 14px;
  box-shadow: 0 0 0 5px var(--bg);
}
/* One icon per phase (web-site#5), in the accent on a chip fill. A
   rounded *square* rather than another circle, so it reads as a distinct object
   next to the numbered marker on the rail above it. Purely reinforcing: the
   number, the duration and the phase name all still say what this is. */
.tl-icon {
  width: 38px;
  height: 38px;
  border-radius: 11px;
  display: grid;
  place-items: center;
  margin: 0 auto 14px;
  color: var(--tone);
  background: var(--fill);
  border: 1px solid var(--border-strong);
}
.tl-icon svg { width: 19px; height: 19px; }
.tl-k { font-family: var(--font-mono); font-size: var(--text-xs); letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted); display: block; text-align: center; margin-bottom: 6px; }
.tl-item h4 { font-size: var(--text-lg); text-align: center; margin-bottom: 8px; }
.tl-item p { font-size: var(--text-sm); color: var(--body); text-align: center; line-height: 1.5; }

@media (max-width: 860px) {
  .timeline { grid-template-columns: 1fr; gap: 8px; }
  .tl-item { padding: 18px 0 18px 52px; text-align: left; }
  .tl-item::before { top: 0; bottom: 0; left: 13px; right: auto; width: 2px; height: auto; }
  .tl-item:first-child::before { top: 14px; left: 13px; }
  .tl-item:last-child::before { bottom: 50%; left: 13px; }
  .tl-dot { position: absolute; left: 0; top: 0; margin: 0; }
  /* The rail runs down the left edge below this breakpoint and the marker is
     lifted out of the flow onto it, so the icon leads the text column instead
     of being centred over it. */
  .tl-icon { margin: 0 0 12px; }
  .tl-k, .tl-item h4, .tl-item p { text-align: left; }
}

/* ---------- Build modes (CSS-only tabs) ----------
   Three radios sit as siblings of both the label row and the panel stack, so
   `:checked ~` switches panels with no JavaScript at all. With CSS disabled the
   panels simply stack, which is the required fallback.

   All three modes share the accent — they are a segmented control, not the
   page's call to action — and every tab carries its 01/02/03 number, so what
   tells the three apart is the label and the mini-diagram beside it, never
   the colour. */

.modes { position: relative; }
.mode-radio { position: absolute; opacity: 0; width: 1px; height: 1px; }

.tabs {
  display: flex;
  gap: 8px;
  justify-content: center;
  margin-bottom: 36px;
  flex-wrap: wrap;
}
.tab {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: var(--text-sm);
  color: var(--body);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 11px 20px;
  cursor: pointer;
  transition: background-color 0.2s var(--ease), border-color 0.2s var(--ease), color 0.2s var(--ease);
  display: inline-flex; align-items: center; gap: 9px;
}
.tab .tab-k { font-family: var(--font-mono); font-size: 11px; color: var(--muted); }
.tab:hover { border-color: var(--tone); color: var(--text-strong); }

#mode-1:checked ~ .tabs [for="mode-1"],
#mode-2:checked ~ .tabs [for="mode-2"],
#mode-3:checked ~ .tabs [for="mode-3"] {
  background: var(--tone);
  border-color: var(--tone);
  color: var(--on-accent);
  box-shadow: var(--shadow-sm);
}
#mode-1:checked ~ .tabs [for="mode-1"] .tab-k,
#mode-2:checked ~ .tabs [for="mode-2"] .tab-k,
#mode-3:checked ~ .tabs [for="mode-3"] .tab-k { color: var(--on-accent); }

/* The same two-ring treatment as the page-wide rule: a focused tab that is
   also the *selected* one is filled with the anchor green, so a single green ring
   around it would be no ring at all. */
#mode-1:focus-visible ~ .tabs [for="mode-1"],
#mode-2:focus-visible ~ .tabs [for="mode-2"],
#mode-3:focus-visible ~ .tabs [for="mode-3"] {
  outline: 3px solid var(--cta);
  outline-offset: 3px;
  box-shadow: 0 0 0 3px var(--on-accent);
}

.tab-panels { position: relative; }
.tab-panel { display: none; }
#mode-1:checked ~ .tab-panels #panel-1,
#mode-2:checked ~ .tab-panels #panel-2,
#mode-3:checked ~ .tab-panels #panel-3 { display: block; animation: fadeUp 0.5s var(--ease); }

@keyframes fadeUp {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: translateY(0); }
}

.mode {
  display: grid;
  grid-template-columns: 1fr 1.1fr;
  gap: 40px;
  align-items: center;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  padding: 40px;
  box-shadow: var(--shadow-md);
}
/* A mini-diagram per build mode (web-site#5): one finished block for Template,
   four assembled parts for Modular, a field of raw parts for From scratch — so
   the three modes differ by *shape*, which is the whole point now that they
   also share one hue. Inline SVG painted from the accent; the badge, heading,
   copy and spec list carry every fact. */
.mode-glyph { width: 64px; height: 40px; margin-bottom: 16px; }
.mode-glyph svg { display: block; width: 100%; height: 100%; }
/* Filled = a part you are given, outlined = a part still to be written. The two
   are told apart by fill, so the outline still has to be legible on its own —
   which is what `--border-strong` is for: theme.css picks the one value that
   keeps a 1.5px stroke at or above 3:1 on every surface, in both themes. */
.mode-glyph .g-fill {
  fill: var(--fill);
  stroke: var(--tone);
  stroke-width: 1.5;
}
.mode-glyph .g-line {
  fill: none;
  stroke: var(--border-strong);
  stroke-width: 1.5;
  stroke-linecap: round;
}

.mode-info .badge {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.1em;
  color: var(--tone);
  text-transform: uppercase;
}
.mode-info h3 { font-size: clamp(26px, 3.4vw, 38px); margin: 12px 0 14px; }
.mode-info p { color: var(--body); font-size: var(--text-lg); line-height: 1.55; margin-bottom: 20px; }
.mode-spec { display: flex; gap: 24px; flex-wrap: wrap; }
.mode-spec div { display: flex; flex-direction: column; gap: 2px; }
.mode-spec dt { font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--muted); }
.mode-spec dd { font-size: var(--text-base); color: var(--text-strong); font-weight: 600; margin: 0; }

@media (max-width: 820px) {
  .mode { grid-template-columns: 1fr; padding: 28px; gap: 28px; }
}

/* ---------- Code / terminal block ----------
   The terminal is a dark surface in both themes, so it uses the fixed on-dark
   `--term-*` tokens rather than `--tone`: the light-theme forest green would
   be unreadable here. Three syntax roles need three separable colours, and
   they are drawn from hues the page already owns — the brand green for
   keywords, the Watch amber for functions, the Fund emerald for strings. The
   two greens are the pair that could collide, so they are separated by
   lightness as well as by the 35° between them. Each clears 4.5:1 on the code
   background. */

.code {
  background: var(--code-bg);
  border: 1px solid var(--border);
  border-radius: 12px;
  overflow: hidden;
  box-shadow: var(--shadow-md);
}
.code-bar {
  display: flex; align-items: center; gap: 7px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--code-border);
}
/* The three window dots get their red / amber / green back, taken from the
   verdict tokens rather than from three new literals — one red, one amber and
   one green on the page, each used for one idea. They are aria-hidden chrome,
   so nothing depends on telling them apart; the `:nth-child` mapping is what
   keeps that possible without touching the markup. */
.code-bar i { width: 11px; height: 11px; border-radius: 50%; display: inline-block; }
.code-bar i:nth-child(1) { background: var(--verdict-pass); }
.code-bar i:nth-child(2) { background: var(--verdict-watch); }
.code-bar i:nth-child(3) { background: var(--verdict-fund); }
.code-bar span { margin-left: 8px; font-family: var(--font-mono); font-size: 11px; color: var(--code-dim); }
.code pre {
  margin: 0;
  padding: 20px;
  font-family: var(--font-mono);
  font-size: 12.5px;
  line-height: 1.7;
  color: var(--code-text);
  overflow-x: auto;
}
.code pre .c-key { color: var(--term-key); }
.code pre .c-fn  { color: var(--term-fn); }
.code pre .c-str { color: var(--term-str); }
.code pre .c-dim { color: var(--code-dim); }

/* ---------- Pricing ---------- */

.pricing {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 14px;
  align-items: stretch;
  list-style: none;
}
.tier {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 28px 22px;
  display: flex;
  flex-direction: column;
  box-shadow: var(--shadow-sm);
  transition: transform 0.3s var(--ease), box-shadow 0.3s var(--ease), border-color 0.3s var(--ease);
}
.tier:hover { transform: translateY(-5px); box-shadow: var(--shadow-md); border-color: var(--tone); }
.tier.is-featured {
  border-color: var(--tone);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--tone) 30%, transparent),
    0 12px 40px color-mix(in srgb, var(--tone) 24%, transparent);
  position: relative;
}
.tier.is-featured .tier-flag {
  position: absolute;
  top: -11px; left: 50%; transform: translateX(-50%);
  background: var(--tone);
  color: var(--on-accent);
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 4px 12px;
  border-radius: 999px;
  white-space: nowrap;
}
.tier-name {
  font-family: var(--font-head);
  font-weight: 700;
  font-size: var(--text-lg);
  color: var(--text-strong);
  letter-spacing: 0.02em;
}
.tier-price {
  display: flex;
  align-items: baseline;
  gap: 4px;
  margin: 14px 0 4px;
}
.tier-price b { font-family: var(--font-head); font-size: 40px; font-weight: 800; color: var(--text-strong); letter-spacing: -0.03em; }
.tier-price span { font-size: var(--text-sm); color: var(--muted); }
.tier-tagline { font-size: var(--text-sm); color: var(--body); min-height: 38px; }
.tier-mode {
  margin: 14px 0;
  padding: 10px 12px;
  border-radius: 8px;
  background: var(--fill);
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.04em;
  color: var(--tone);
  text-align: center;
}
.tier ul { list-style: none; display: flex; flex-direction: column; gap: 10px; margin-top: 4px; }
.tier li { font-size: var(--text-sm); color: var(--body); display: flex; gap: 9px; line-height: 1.4; }
.tier li svg { width: 15px; height: 15px; color: var(--tone); flex-shrink: 0; margin-top: 2px; }
/* Push the CTA to the bottom of the card so every tier's button lands on one
   baseline regardless of how many lines the feature list wraps to. */
.tier-foot { margin-top: auto; padding-top: 20px; }
.tier-foot .btn { width: 100%; }

@media (max-width: 1180px) { .pricing { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 760px)  { .pricing { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 460px)  { .pricing { grid-template-columns: 1fr; } }

/* ---------- Principles ---------- */

.principles {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 0 48px;
  list-style: none;
  counter-reset: principle;
}
.principle {
  display: flex;
  gap: 18px;
  padding: 22px 0;
  border-bottom: 1px solid var(--border-soft);
  align-items: baseline;
}
.principle-n {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--tone);
  flex-shrink: 0;
  width: 30px;
}
.principle h4 { font-size: var(--text-lg); margin-bottom: 4px; }
.principle p { font-size: var(--text-sm); color: var(--body); }

@media (max-width: 720px) { .principles { grid-template-columns: 1fr; gap: 0; } }

/* ---------- Marquee ----------
   Six words, doubled to make the loop seamless, all in the anchor forest green.
   The strip is aria-hidden — it restates section headings — so its colour is
   decorative and carries no meaning of its own. */

.marquee {
  overflow: hidden;
  border-top: 1px solid var(--border-soft);
  border-bottom: 1px solid var(--border-soft);
  padding: 26px 0;
  -webkit-mask-image: linear-gradient(90deg, transparent, black 12%, black 88%, transparent);
  mask-image: linear-gradient(90deg, transparent, black 12%, black 88%, transparent);
}
.marquee-track {
  display: flex;
  gap: 44px;
  width: max-content;
  animation: scroll 38s linear infinite;
}
.marquee:hover .marquee-track { animation-play-state: paused; }
.marquee-track span {
  font-family: var(--font-head);
  font-weight: 700;
  font-size: clamp(20px, 3vw, 30px);
  letter-spacing: -0.02em;
  color: var(--tone);
  display: inline-flex;
  align-items: center;
  gap: 44px;
  white-space: nowrap;
}
.marquee-track span::after { content: '·'; color: var(--tone); }
@keyframes scroll { to { transform: translateX(-50%); } }

/* ---------- CTA band ---------- */

.cta {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 24px;
  padding: clamp(40px, 6vw, 72px);
  text-align: center;
  box-shadow: var(--shadow-md);
  position: relative;
  overflow: hidden;
}
.cta::before {
  content: '';
  position: absolute; inset: 0;
  background:
    radial-gradient(ellipse 500px 300px at 20% 0%, color-mix(in srgb, var(--tone) var(--tint-wash), transparent), transparent 60%),
    radial-gradient(ellipse 500px 300px at 85% 100%,
      color-mix(in srgb, var(--cta) var(--tint-wash), transparent), transparent 60%);
  pointer-events: none;
}
.cta > * { position: relative; }
.cta h2 { font-size: clamp(30px, 4.4vw, 54px); letter-spacing: -0.03em; margin-bottom: 16px; }
.cta > p { font-size: var(--text-lg); color: var(--body); max-width: 50ch; margin: 0 auto 8px; }

/* ---------- Waitlist form ---------- */

.waitlist { margin: 32px auto 0; max-width: 480px; }
.waitlist-row { display: flex; gap: 8px; }
.waitlist input[type="email"] {
  flex: 1;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 10px;
  outline: 0;
  color: var(--text-strong);
  font-family: var(--font-body);
  font-size: var(--text-base);
  padding: 14px 16px;
  min-width: 0;
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
}
.waitlist input::placeholder { color: var(--muted); }
.waitlist input:focus-visible { border-color: var(--cta); }
.waitlist .btn { padding: 14px 22px; }
.waitlist .note { margin-top: 12px; font-size: var(--text-xs); color: var(--muted); }
.waitlist .status {
  display: none;
  margin-top: 16px;
  padding: 16px 18px;
  font-size: var(--text-sm);
  border-radius: 10px;
  border: 1px solid var(--tone);
  background: var(--fill);
  color: var(--text-strong);
}
.waitlist.is-success .status { display: block; }
.waitlist.is-success .waitlist-row,
.waitlist.is-success .note { display: none; }
.waitlist .error { display: none; margin-top: 10px; font-size: var(--text-sm); color: var(--danger); }
.waitlist.is-error .error { display: block; }
.waitlist.is-error input[type="email"] { border-color: var(--danger); }
.waitlist noscript p { margin-top: 14px; font-size: var(--text-sm); color: var(--body); }
.waitlist a { color: var(--tone); }

@media (max-width: 480px) {
  .waitlist-row { flex-direction: column; }
  .waitlist .btn { width: 100%; }
}

/* ---------- Enquiry form (lead capture) ---------- */

/* Sits in a `.cta` band, which centres its children — a labelled multi-field
   form reads far better ranged left, so it opts out for its own subtree. */
.enquiry { margin: 32px auto 0; max-width: 560px; text-align: left; }
.enquiry .field { display: flex; flex-direction: column; gap: 6px; margin-bottom: 16px; }
.enquiry label {
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--text);
}
.enquiry input,
.enquiry textarea {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 10px;
  outline: 0;
  color: var(--text-strong);
  font-family: var(--font-body);
  font-size: var(--text-base);
  padding: 14px 16px;
  width: 100%;
  min-width: 0;
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
}
.enquiry textarea { resize: vertical; min-height: 120px; line-height: 1.6; }
.enquiry input::placeholder,
.enquiry textarea::placeholder { color: var(--muted); }
.enquiry input:focus-visible,
.enquiry textarea:focus-visible { border-color: var(--cta); }
.enquiry .btn { padding: 14px 22px; width: 100%; }
.enquiry .note { margin-top: 12px; font-size: var(--text-xs); color: var(--muted); }
.enquiry .status {
  display: none;
  margin-top: 16px;
  padding: 16px 18px;
  font-size: var(--text-sm);
  border-radius: 10px;
  border: 1px solid var(--tone);
  background: var(--fill);
  color: var(--text-strong);
}
/* Success replaces the form: every control goes, the thank-you appears. The
   `.status` node is a live region already in the markup, so the swap is
   announced — which replacing the form's innerHTML would not be. */
.enquiry.is-success .status { display: block; }
.enquiry.is-success .field,
.enquiry.is-success .trap,
.enquiry.is-success .btn,
.enquiry.is-success .note { display: none; }
.enquiry .error { display: none; margin-top: 10px; font-size: var(--text-sm); color: var(--danger); }
.enquiry.is-error .error { display: block; }
.enquiry.is-error input[type="email"] { border-color: var(--danger); }
.enquiry noscript p { margin-top: 14px; font-size: var(--text-sm); color: var(--body); }
.enquiry a { color: var(--tone); }

/* The spam trap. Off-screen rather than `display: none`: a bot that skips
   hidden fields is exactly the bot this is meant to catch. */
.trap {
  position: absolute;
  left: -9999px;
  width: 1px; height: 1px;
  overflow: hidden;
}

/* ---------- Split (CEO / hybrid teams) ---------- */

.split { display: grid; grid-template-columns: 1fr 1fr; gap: 56px; align-items: center; }
.split h2 { font-size: clamp(28px, 4vw, 46px); margin-bottom: 18px; }
.split p { font-size: var(--text-lg); line-height: 1.6; margin-bottom: 18px; color: var(--body); }
.split p:last-child { margin-bottom: 0; }
.split strong { color: var(--text-strong); font-weight: 600; }
@media (max-width: 880px) { .split { grid-template-columns: 1fr; gap: 40px; } }

/* ---------- Stats band ---------- */

.stats {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 16px;
  list-style: none;
}
.stat {
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  padding: 28px 24px;
  box-shadow: var(--shadow-sm);
  transition: transform 0.3s var(--ease), box-shadow 0.3s var(--ease), border-color 0.3s var(--ease);
}
.stat:hover { transform: translateY(-4px); box-shadow: var(--shadow-md); border-color: var(--tone); }
.stat b {
  font-family: var(--font-head);
  font-weight: 800;
  font-size: clamp(34px, 4.4vw, 48px);
  letter-spacing: -0.03em;
  color: var(--text-strong);
  line-height: 1;
  font-variant-numeric: tabular-nums;
  display: block;
}
.stat span {
  display: block;
  margin-top: 10px;
  font-size: var(--text-sm);
  color: var(--body);
}
@media (max-width: 760px) { .stats { grid-template-columns: repeat(2, 1fr); } }

/* ---------- VC Audit: axes + verdicts ---------- */

.axes {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 14px;
  margin-bottom: 32px;
  list-style: none;
}
.axis {
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  padding: 24px 22px;
  box-shadow: var(--shadow-sm);
  transition: transform 0.3s var(--ease), box-shadow 0.3s var(--ease), border-color 0.3s var(--ease);
}
.axis:hover { transform: translateY(-3px); box-shadow: var(--shadow-md); border-color: var(--tone); }
.axis-n {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.14em;
  color: var(--tone);
}
.axis h4 { font-size: var(--text-lg); margin: 10px 0 6px; }
.axis p { font-size: var(--text-sm); color: var(--body); line-height: 1.5; }
.axis.is-key { border-color: var(--tone); background: var(--fill); }
@media (max-width: 760px) { .axes { grid-template-columns: 1fr; } }

/* Verdicts keep their semantic tokens whatever else is on the page: Fund
   green, Watch amber, Pass red. With a green brand, Fund is the one at risk
   of reading as "just the brand colour", so it is resolved three ways at once
   (see the Verdict bands note in theme.css):

     · SHAPE — `.verdict-dot` is masked to a check, a bar-and-dot and a cross.
       The markup is untouched: the span was already there and already
       aria-hidden, so the icon costs no element and no request. Where
       `mask-image` is unsupported the mask is ignored and the element falls
       back to the round coloured dot it was before, which is exactly the old
       behaviour rather than a broken one.
     · LABEL — the band's name and score range were already in the markup.
     · SHADE — Fund is an emerald at 148°, 28° off every step of the brand
       scale and 1.49:1 (light) / 1.37:1 (dark) from `--primary`.

   Colour therefore reinforces the band and never carries it. */
.verdicts { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; list-style: none; }
.verdict {
  background: var(--surface);
  border: 1px solid var(--border);
  border-left-width: 3px;
  border-radius: var(--radius);
  padding: 24px 22px;
  box-shadow: var(--shadow-sm);
}
.verdict-top {
  display: flex; align-items: center; gap: 10px;
  margin-bottom: 12px;
}
.verdict-dot {
  width: 17px;
  height: 17px;
  border-radius: 50%;
  flex-shrink: 0;
  background-color: currentColor;
  mask-repeat: no-repeat;
  -webkit-mask-repeat: no-repeat;
  mask-size: 100% 100%;
  -webkit-mask-size: 100% 100%;
}
.verdict-name {
  font-family: var(--font-head);
  font-weight: 700;
  font-size: var(--text-lg);
  color: var(--text-strong);
  letter-spacing: 0.02em;
}
.verdict-score {
  margin-left: auto;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.06em;
  color: var(--muted);
}
.verdict p { font-size: var(--text-sm); color: var(--body); line-height: 1.5; }
.verdict.is-fund  { border-left-color: var(--verdict-fund); }
.verdict.is-watch { border-left-color: var(--verdict-watch); }
.verdict.is-pass  { border-left-color: var(--verdict-pass); }

/* A check, a bar-and-dot and a cross. The shapes carry no colour of their own
   — the paths take SVG's default black fill and are used only as a mask, so
   the visible colour is the verdict token underneath and theme.css stays the
   single source of colour truth. */
.verdict.is-fund .verdict-dot {
  color: var(--verdict-fund);
  mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M9.2 16.4 5 12.2l-1.6 1.6 5.8 5.8L21.4 7.4 19.8 5.8z'/></svg>");
  -webkit-mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M9.2 16.4 5 12.2l-1.6 1.6 5.8 5.8L21.4 7.4 19.8 5.8z'/></svg>");
}
.verdict.is-watch .verdict-dot {
  color: var(--verdict-watch);
  mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M10.6 3.6h2.8l-.5 10.4h-1.8zM10.6 17.2h2.8v3.2h-2.8z'/></svg>");
  -webkit-mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M10.6 3.6h2.8l-.5 10.4h-1.8zM10.6 17.2h2.8v3.2h-2.8z'/></svg>");
}
.verdict.is-pass .verdict-dot {
  color: var(--verdict-pass);
  mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M19.6 6.2 17.8 4.4 12 10.2 6.2 4.4 4.4 6.2 10.2 12l-5.8 5.8 1.8 1.8 5.8-5.8 5.8 5.8 1.8-1.8L13.8 12z'/></svg>");
  -webkit-mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M19.6 6.2 17.8 4.4 12 10.2 6.2 4.4 4.4 6.2 10.2 12l-5.8 5.8 1.8 1.8 5.8-5.8 5.8 5.8 1.8-1.8L13.8 12z'/></svg>");
}
@media (max-width: 760px) { .verdicts { grid-template-columns: 1fr; } }

/* ---------- Hybrid roster ---------- */

.roster {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 22px;
  box-shadow: var(--shadow-sm);
  display: flex;
  flex-direction: column;
  gap: 10px;
  list-style: none;
  margin: 0;
}
.role-card {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 16px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  transition: border-color 0.2s ease, transform 0.2s var(--ease);
}
.role-card:hover { border-color: var(--border-strong); transform: translateX(3px); }
.role-type {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 4px 9px;
  border-radius: 999px;
  flex-shrink: 0;
  min-width: 62px;
  text-align: center;
}
/* Agent takes the anchor forest green; Human takes `--deep` — two clearly separate
   depths rather than two neighbouring ones, because at 10px anything closer
   would not read. Both badges spell the word out, so depth is a second
   signal, never the only one. */
.role-type.is-agent { background: var(--fill); color: var(--tone); border: 1px solid var(--border-strong); }
.role-type.is-human { --tone: var(--deep); background: var(--fill); color: var(--tone); border: 1px solid var(--border-strong); }
.role-name { font-size: var(--text-sm); color: var(--text-strong); font-weight: 600; }
.role-task { margin-left: auto; font-size: var(--text-xs); color: var(--muted); font-family: var(--font-mono); }
@media (max-width: 520px) { .role-task { display: none; } }

/* ---------- Marketplace ---------- */

.markets { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; margin-bottom: 28px; list-style: none; }
.market {
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  padding: 28px 26px;
  box-shadow: var(--shadow-sm);
  transition: transform 0.3s var(--ease), box-shadow 0.3s var(--ease), border-color 0.3s var(--ease);
}
.market:hover { transform: translateY(-4px); box-shadow: var(--shadow-md); border-color: var(--tone); }
.market-tag {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--tone);
}
.market h3 { font-size: var(--text-xl); margin: 12px 0 8px; }
.market p { font-size: var(--text-sm); color: var(--body); line-height: 1.55; }
@media (max-width: 820px) { .markets { grid-template-columns: 1fr; } }

.gets {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 12px 32px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 28px 30px;
  box-shadow: var(--shadow-sm);
}
.gets li { display: flex; gap: 11px; font-size: var(--text-sm); color: var(--body); line-height: 1.45; }
.gets li svg { width: 16px; height: 16px; color: var(--tone); flex-shrink: 0; margin-top: 2px; }
.gets li strong { color: var(--text-strong); font-weight: 600; }
@media (max-width: 640px) { .gets { grid-template-columns: 1fr; } }

/* ---------- FAQ ---------- */

.faq { max-width: 820px; margin: 0 auto; }
.faq-item {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  margin-bottom: 12px;
  box-shadow: var(--shadow-sm);
  overflow: hidden;
  transition: border-color 0.2s ease;
}
.faq-item[open] { border-color: var(--tone); }
.faq-item summary {
  list-style: none;
  cursor: pointer;
  padding: 22px 24px;
  display: flex;
  align-items: center;
  gap: 16px;
  font-family: var(--font-head);
  font-weight: 600;
  font-size: var(--text-lg);
  color: var(--text-strong);
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary::after {
  content: '';
  margin-left: auto;
  width: 11px; height: 11px;
  flex-shrink: 0;
  border-right: 2px solid var(--tone);
  border-bottom: 2px solid var(--tone);
  transform: rotate(45deg);
  transition: transform 0.25s var(--ease);
}
.faq-item[open] summary::after { transform: rotate(-135deg); }
.faq-item summary:hover { color: var(--tone); }
.faq-item p {
  padding: 0 24px 24px;
  font-size: var(--text-base);
  color: var(--body);
  line-height: 1.6;
}
.faq-item p strong { color: var(--text-strong); font-weight: 600; }

/* ---------- Card depth ----------
   One shared sheen for every raised surface on the page: a diagonal wash of
   the accent, fading out before the halfway mark, over the flat `--surface`
   fill each rule above already sets. It is what stops a card reading as a
   white rectangle with a coloured border stuck on it.

   Two reasons this is one block rather than a line in each rule. Each of those
   rules sets `background` as a shorthand, which resets `background-image` — so
   the sheen has to be declared after all of them to survive. And keeping the
   treatment in one place is what makes it a treatment: change the angle here
   and every card on the page changes with it.

   Held at `--tint-wash`, the 4% cap theme.css sets for anything larger than a
   chip, so the "backgrounds stay near-neutral" rule survives the polish pass —
   `test/theme.test.js` measures body copy over the flattened result. */
.flow-step, .card, .pillar, .stat, .axis, .market, .tier,
.mode, .org, .gets, .roster, .faq-item, .cta {
  background-image: linear-gradient(158deg,
    color-mix(in srgb, var(--tone) var(--tint-wash), transparent) 0%,
    transparent 52%);
}

/* ---------- Footer ---------- */

/* The page closes on the same rule it opened with — bright on the left, deep
   on the right — with the plain border as the no-border-image fallback. */
footer {
  border-top: 1px solid var(--border-strong);
  border-image: linear-gradient(90deg, var(--accent), var(--primary), var(--deep)) 1;
  padding: 56px 0 40px;
  margin-top: 40px;
}
.footer-top {
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr;
  gap: 40px;
  margin-bottom: 44px;
}
.footer-brand .brand-mark { font-size: 20px; }
.footer-brand p { margin-top: 14px; font-size: var(--text-sm); color: var(--body); max-width: 34ch; }
.footer-col h2 {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 16px;
}
.footer-col ul { list-style: none; }
.footer-col a {
  display: block;
  color: var(--body);
  text-decoration: none;
  font-size: var(--text-sm);
  margin-bottom: 11px;
  transition: color 0.2s ease;
}
.footer-col a:hover { color: var(--tone); }
.footer-bot {
  display: flex; justify-content: space-between; align-items: center;
  gap: 20px; flex-wrap: wrap;
  padding-top: 28px;
  border-top: 1px solid var(--border-soft);
}
.footer-bot .copy { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--muted); letter-spacing: 0.04em; }
.footer-bot a { color: var(--body); text-decoration: none; font-size: var(--text-xs); }
.footer-bot a:hover { color: var(--tone); }

@media (max-width: 720px) {
  .footer-top { grid-template-columns: 1fr 1fr; gap: 32px; }
  .footer-brand { grid-column: span 2; }
}

/* ---------- Reveal animation ----------
   Only ever hides content once the inline head script has proved scripting is
   on. Without JS the `.js` class is absent and everything renders immediately,
   so the page can never end up blank. */

.js .reveal {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 0.7s var(--ease), transform 0.7s var(--ease);
}
.js .reveal.is-visible { opacity: 1; transform: translateY(0); }
.js .reveal[data-delay="1"] { transition-delay: 0.08s; }
.js .reveal[data-delay="2"] { transition-delay: 0.16s; }
.js .reveal[data-delay="3"] { transition-delay: 0.24s; }
.js .reveal[data-delay="4"] { transition-delay: 0.32s; }

/* ---------- Reduced motion ---------- */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0s !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0s !important;
    scroll-behavior: auto !important;
  }
  .js .reveal { opacity: 1; transform: none; }
  /* Stop the marquee outright rather than letting a zero-duration animation
     snap it to its end position, which would hide the first half of the strip.
     Every gradient on the page is static, so there is nothing else to
     disable. */
  .marquee-track { animation: none !important; transform: none !important; }
}
