:root {
  --color--text: #16161a;
  --color--text-mu: #6b6b73;
  /* --color--text-inverse, --color--surface-alt, --color--surface-inverse and
     --color--border are set by BOTH axes (theme AND direction) — see the
     "aliases: tokens set by both axes" comment in the DIRECTION AXIS section
     below for what these var()s resolve through. The alias formula has to
     stay THIS early in the file (before `.theme-dark`, same as it was raw
     hex before): same-specificity (0,1,0) rules resolve by source order, and
     `.theme-dark` below has to be able to override these. */
  --color--surface-alt: var(--direction--surface-alt-light);
  --color--border: var(--direction--border-light);
  --color--surface-inverse: var(--direction--surface-inverse-light);
  --color--text-inverse: var(--direction--text-inverse-light);
  --color--surface: #ffffff;
  --color--primary: #e8480c;
  --color--accent: #e8480c;
  --color--accent-deep: #16161a;
  --color--success: #166534;
  --color--warning: #b45309;
  --color--danger: #b91c1c;
  --color--neutral-100: #f7f7f8;
  --color--neutral-200: #ececee;
  --color--neutral-300: #e1e1e4;
  --color--neutral-400: #9a9aa2;
  --color--neutral-500: #6b6b73;
  --color--neutral-700: #3b3b42;
  --color--neutral-800: #16161a;
  --color--neutral-900: #16161a;
  /* Ink that sits ON the primary orange fill — fixed dark ink in both themes
     (see .button.is-primary below), independent of the neutral scale so the
     scale is safe to invert per-theme. */
  --color--on-primary: #16161a;
  /* A fixed ink FILL, the mirror of --color--on-primary above. Deliberately
     NOT redefined per theme: the neutral scale inverts in dark, so anything
     that must stay ink in both themes cannot draw from it. */
  --color--ink-fixed: #16161a;
  --color--primary-500: #e8480c;
  --color--primary-600: #eb5e29;
  --color--primary-700: #16161a;
  --color--accent-500: #e8480c;
  --color--accent-600: #16161a;
  --color--success-300: #5fd08a;
  --color--success-500: #166534;
  --color--warning-300: #f0b544;
  --color--warning-500: #b45309;
  --color--danger-300: #f28b82;
  --color--danger-500: #b91c1c;
  --color--paper: #ffffff;
  /* On-inverse alpha ramp — text/border/wash tones for content that sits on an
     inverse (dark) surface, e.g. hero/CTA/footer bands. Direction axis blocks
     below redefine this ramp to dark ink when a direction's surface-inverse
     goes light. */
  --color--on-inverse-strong: rgba(255,255,255,0.88);
  --color--on-inverse-body: rgba(255,255,255,0.72);
  --color--on-inverse-mu: rgba(255,255,255,0.60);
  --color--on-inverse-line: rgba(255,255,255,0.28);
  --color--on-inverse-faint: rgba(255,255,255,0.14);
  --color--on-inverse-wash: rgba(255,255,255,0.08);
  /* Hero process-panel schematic grays (BP-195/BP-231) — the mini pages in the
     Pitch and Proof widgets are literal white pages whatever the band or
     theme, so their chrome carries these exact fixed values rather than the
     neutral ramp, which flips in dark mode. */
  --color--schematic-fixed: #e1e1e4;
  --color--schematic-mid-fixed: #c9c9ce;
  --color--schematic-dark-fixed: #b5b5bb;
  --color--schematic-on-dark-strong-fixed: rgba(255,255,255,0.55);
  --color--schematic-on-dark-faint-fixed: rgba(255,255,255,0.16);
  --effect--shadow-sm: 0 1px 2px rgba(16, 16, 20, 0.06), 0 1px 3px rgba(16, 16, 20, 0.10);
  --effect--shadow-lg: 0 4px 12px -2px rgba(16, 16, 20, 0.12), 0 2px 4px -1px rgba(16, 16, 20, 0.08);
  --effect--transition-base: 0.2s ease;
  --radius--sm: 4px;
  --radius--md: 6px;
  --radius--lg: 8px;
  --space--xs: 0.25rem;
  --space--sm: 0.5rem;
  --space--md: 1rem;
  --space--lg: 2rem;
  --space--xl: 3.5rem;
  --space--2xl: 6.5rem;
  /* Fluid so the headline doesn't run to five lines on a phone: floors at
     2.15rem, reaches the original 3.25rem at ~830px and stops there. */
  --type--display: clamp(2.15rem, 6.5vw, 3.25rem);
  --type--h2: 2rem;
  --type--h3: 1.5rem;
  --type--body: 1rem;
  --type--small: 0.8125rem;
  --type--family-sans: 'Inter', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Helvetica Neue', Arial, sans-serif;
  --type--family-heading: 'Inter', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Helvetica Neue', Arial, sans-serif;
  --type--family-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Monaco, 'Cascadia Code', 'Roboto Mono', monospace;
}
/* THEME AXIS — light/dark. In Webflow this block is not authored CSS at all: it
   is a native variable mode (Colors collection > `Dark`), which Webflow
   publishes as exactly this selector, `.theme-dark` at specificity (0,1,0).
   The rule is duplicated here by hand so this file still themes itself when the
   page is opened straight off the filesystem, where no Webflow stylesheet and
   no Webflow variables exist. Selector and values are kept character-identical
   to what the mode emits, so the local page and the published page resolve the
   same cascade — only the origin of the rule differs.

   Bare `.theme-dark`, NOT `html.theme-dark`: Webflow always publishes a mode
   class bare, at (0,1,0), same as `.direction-proof` / `.direction-receipt`
   below (the DIRECTION axis's own native modes — see that section). The two
   axes now compose as two independent mode classes on the same <html>
   element rather than one hand-written and one native: this block and the
   direction mode classes never redeclare the same custom property, so which
   one comes later in source order never matters. The four tokens both axes
   affect (surface-alt, border, surface-inverse, text-inverse) are ALIASES
   declared in the DIRECTION AXIS section below — this block only sets the
   theme-side half of each alias, `--direction--<name>-dark`. */
.theme-dark {
  --color--text: #f7f7f8;
  --color--text-mu: #9a9aa2;
  --color--text-inverse: var(--direction--text-inverse-dark);
  --color--surface: #16161a;
  --color--surface-alt: var(--direction--surface-alt-dark);
  --color--surface-inverse: var(--direction--surface-inverse-dark);
  --color--primary: #e8480c;
  --color--border: var(--direction--border-dark);
  --color--accent: #e8480c;
  --color--accent-deep: #e8480c;
  --color--success: #5fd08a;
  --color--warning: #f0b544;
  --color--danger: #f28b82;
  /* Neutral scale inverted for dark: -900 is now the lightest step (pairs
     with --color--text), -100 the darkest (pairs with --color--surface-alt).
     -800/-700/-500/-400/-300/-100 reuse the same 8 primitives the light
     scale draws from, just walked in the opposite direction; -200 is a new
     interpolated step between -300 and -100 to keep the ramp even (the
     light scale has no -600 either, so none is added here). */
  --color--neutral-100: #1f1f23;
  --color--neutral-200: #2d2d33;
  --color--neutral-300: #3b3b42;
  --color--neutral-400: #6b6b73;
  --color--neutral-500: #9a9aa2;
  --color--neutral-700: #e1e1e4;
  --color--neutral-800: #ececee;
  --color--neutral-900: #f7f7f8;
}
@media (prefers-color-scheme: dark) {
  /* The OS-preference default, and the ONE part of the theme axis that cannot
     become a variable mode: a Webflow mode binds to a class or to a width
     breakpoint, never to a media feature. So this block stays hand-written CSS
     in both the local file and the Webflow head custom code.

     `.theme-light` is the escape hatch, not a styling class — it carries no
     declarations anywhere. Without it a visitor whose OS is dark could never
     choose light: removing `.theme-dark` would just fall back into this block.
     The toggle therefore always sets exactly one of the two.

     `html:not(…)` not `:root:not(…)`. `:root:not(.x)` computes to (0,2,0),
     which outranks the direction blocks at (0,1,1) — receipt's orange surface
     lost to this block while receipt's ink text still applied, giving
     dark-on-dark copy in receipt + dark. `html:not(.x)` is (0,1,1), tying with
     the direction blocks so later source order lets them win. Also keeps this
     rule out of the export's `:root` discard path. */
  html:not(.theme-light) {
    --color--text: #f7f7f8;
    --color--text-mu: #9a9aa2;
    --color--text-inverse: var(--direction--text-inverse-dark);
    --color--surface: #16161a;
    --color--surface-alt: var(--direction--surface-alt-dark);
    --color--surface-inverse: var(--direction--surface-inverse-dark);
    --color--primary: #e8480c;
    --color--border: var(--direction--border-dark);
    --color--accent: #e8480c;
    --color--accent-deep: #e8480c;
    --color--success: #5fd08a;
    --color--warning: #f0b544;
    --color--danger: #f28b82;
    /* Kept in sync with the `.theme-dark` block above — see comment there.
       These 21 values are the ones the Colors > Dark variable mode carries. */
    --color--neutral-100: #1f1f23;
    --color--neutral-200: #2d2d33;
    --color--neutral-300: #3b3b42;
    --color--neutral-400: #6b6b73;
    --color--neutral-500: #9a9aa2;
    --color--neutral-700: #e1e1e4;
    --color--neutral-800: #ececee;
    --color--neutral-900: #f7f7f8;
  }
}
/* House-default components — S2-named CSS. :root token custom properties are
   emitted by the build step from tokens/ (dist/tokens.json), so this file only
   references them via var(--<category>--<name>). Colors use the semantic roles
   from color.json (S2 tier 2); a few genuinely shade-specific uses reference
   palette primitives (palette.json) directly. Compact seed stylesheet: it
   covers the shared atoms and the main section components the patterns emit. */

/* ---------- Reset / base ---------- */
* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
.body {
  margin: 0;
  font-family: var(--type--family-sans);
  font-size: var(--type--body);
  color: var(--color--text);
  background: var(--color--surface);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}
img { max-width: 100%; display: block; }
a { text-decoration: none; color: inherit; }
ul, ol { margin: 0; padding: 0; list-style: none; }
h1, h2, h3, h4, p, blockquote { margin: 0; }
button { font-family: inherit; cursor: pointer; border: none; background: none; }

/* ---------- Layout ---------- */
/* `clip`, not `hidden`: hidden would make .page a scroll container and stop
   the sticky .site-nav sticking. */
.page { overflow-x: clip; }
.container { width: 100%; max-width: 73.75rem; margin: 0 auto; padding: 0 var(--space--md); }
.container.is-8c { max-width: 48.75rem; }
.section { padding: var(--space--2xl) 0; }
.section.is-alt { background: var(--color--surface-alt); }

/* ---------- Atoms ---------- */
.eyebrow {
  display: inline-block;
  font-family: var(--type--family-mono);
  font-size: var(--type--small);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--color--accent-deep);
  margin-bottom: var(--space--sm);
}
/* Headings: S2 heading-<size> classes on the t-shirt scale (DESIGN.md §4).
   Shared styling, then per-size font-size. */
.heading-2xl, .heading-xl, .heading-lg {
  font-family: var(--type--family-heading);
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.02em;
  color: var(--color--text);
}
.heading-2xl { font-size: var(--type--display); line-height: 1.1; letter-spacing: -0.032em; }
.heading-xl { font-size: var(--type--h2); }
.heading-lg { font-size: var(--type--h3); }
/* Body copy: text-<size>. Muted by default in this system (opt out with a color
   utility once utilities land). */
.text-lg { font-size: 1.125rem; color: var(--color--text-mu); max-width: 620px; }
.text-base { font-size: var(--type--body); color: var(--color--text-mu); }
.text-sm { font-size: var(--type--small); color: var(--color--text-mu); max-width: 320px; }
.is-white-text { color: var(--color--text-inverse); }
.title-set { max-width: 720px; margin-bottom: var(--space--xl); }
.title-set.is-center { text-align: center; margin-left: auto; margin-right: auto; }

/* ---------- Buttons ---------- */
.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space--sm);
  padding: 0.875rem 1.875rem;
  border-radius: var(--radius--sm);
  font-family: var(--type--family-heading);
  font-size: inherit; /* a native <button> otherwise falls back to the browser's 13.33px */
  font-weight: 600;
  border: 2px solid transparent;
  transition: transform var(--effect--transition-base), background var(--effect--transition-base), color var(--effect--transition-base);
  white-space: nowrap;
}
/* Safety Orange is too bright for light text — primary fills carry fixed ink
   text (--color--on-primary) in both light and dark mode. */
.button.is-primary { background: var(--color--primary); color: var(--color--on-primary); }
.button.is-primary:hover { background: var(--color--primary-600); transform: translateY(-2px); box-shadow: var(--effect--shadow-sm); }
.button.is-secondary { background: var(--color--accent); color: var(--color--on-primary); }
.button.is-outline { background: transparent; border-color: currentColor; color: var(--color--accent-deep); }
.button.is-outline:hover { background: var(--color--surface-alt); }
.button-group { display: flex; gap: var(--space--md); flex-wrap: wrap; }
.button-group.is-center { justify-content: center; margin-top: var(--space--md); }  /* majority pattern across pages, checked directly; 404.html keeps its own inline override for now */
/* Keyboard focus ring — dual-tone (inner light + outer brand) so it stays
   visible on both paper surfaces and the dark CTA band / footer. */
.button:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--color--surface), 0 0 0 4px var(--color--primary); }

/* ---------- Nav ---------- */
/* site-nav:start */
.site-nav { position: sticky; top: 0; z-index: 50; background: var(--color--surface, var(--surface, #ffffff)); color: var(--color--text, var(--text, #16161a)); box-shadow: 0 1px 0 var(--color--border, var(--border, #e1e1e4)); }
.site-nav_inner { box-sizing: border-box; width: 100%; max-width: 1180px; margin: 0 auto; padding: 14px 1rem 12px; display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; column-gap: 1.5rem; transition: padding .25s ease; }
.site-nav_inner.is-narrow { max-width: 1040px; padding-left: 1.25rem; padding-right: 1.25rem; }
.site-nav_inner.is-collapsed { padding-top: 10px; padding-bottom: 10px; }
.site-nav_side { display: flex; align-items: center; gap: 1.5rem; min-width: 0; }
.site-nav_side.is-left { justify-self: start; }
.site-nav_side.is-right { justify-self: end; }
.site-nav_links { display: flex; align-items: center; gap: 1.5rem; }
.site-nav_link { font-weight: 500; color: var(--color--neutral-700, var(--text-mu, #3b3b42)); text-decoration: none; white-space: nowrap; }
.site-nav_link:hover { color: var(--color--text, var(--text, #16161a)); }
.site-nav_link.is-menu-cta, .site-nav_link.is-menu-lang { display: none; }
.site-nav_logo { display: inline-flex; flex-direction: row; align-items: flex-end; color: var(--color--text, var(--text, #16161a)); text-decoration: none; line-height: 1; }
.site-nav_mark { display: block; flex: none; width: 37.02px; height: 32.68px; }
.site-nav_name { display: block; overflow: hidden; max-width: 160px; margin-left: 11.37px; margin-bottom: -0.11px; opacity: 1; transition: max-width .25s ease, margin-left .25s ease, opacity .15s ease; }
.site-nav_name.is-collapsed { max-width: 0; margin-left: 0; opacity: 0; }
.site-nav_wordmark { display: block; width: 151.97px; height: 27.27px; }
.site-nav_cta { display: inline-flex; align-items: center; padding: 0.6rem 1.15rem; border: 2px solid transparent; border-radius: 4px; background: var(--color--primary, var(--primary, #e8480c)); color: var(--color--on-primary, #16161a); font-weight: 600; text-decoration: none; white-space: nowrap; transition: transform .2s ease, background .2s ease; }
.site-nav_lang { font-weight: 500; color: var(--color--neutral-700, var(--text-mu, #3b3b42)); text-decoration: none; white-space: nowrap; }
.site-nav_lang:hover { color: var(--color--text, var(--text, #16161a)); }
.site-nav_cta:hover { background: var(--color--primary-600, #eb5e29); transform: translateY(-2px); }
.site-nav_theme, .site-nav_menu-button { display: inline-flex; align-items: center; padding: 0.4rem 0.9rem; border: 2px solid currentColor; border-radius: 4px; background: transparent; color: var(--color--accent-deep, var(--text, #16161a)); font: inherit; font-size: 0.875rem; font-weight: 600; line-height: 1.2; cursor: pointer; }
.site-nav_theme:hover, .site-nav_menu-button:hover { background: var(--color--surface-alt, var(--surface-alt, #f7f7f8)); }
.site-nav_menu-button { display: none; }
.site-nav_theme:focus-visible, .site-nav_menu-button:focus-visible, .site-nav_cta:focus-visible, .site-nav_link:focus-visible, .site-nav_lang:focus-visible, .site-nav_logo:focus-visible { outline: 2px solid var(--color--primary, var(--primary, #e8480c)); outline-offset: 2px; }
.site-nav_inner.is-strip { padding-top: 20px; padding-bottom: 18px; column-gap: 2rem; }
.site-nav_inner.is-strip.is-collapsed { padding-top: 12px; padding-bottom: 12px; }
.site-nav_side.is-strip, .site-nav_links.is-strip { gap: 2.25rem; }
.site-nav_menu-button.is-ghost { gap: 0.4rem; padding: 0.29rem 0.55rem; border-color: transparent; color: var(--color--text, var(--text, #16161a)); font-size: 0.9375rem; }
.site-nav_menu-button.is-ghost:hover { background: var(--color--surface-alt, var(--surface-alt, #f7f7f8)); }
.site-nav_bars { display: block; flex: none; }
.site-strip { position: relative; z-index: 51; background: var(--color--surface-alt, var(--surface-alt, #f7f7f8)); color: var(--color--neutral-700, var(--text-mu, #3b3b42)); box-shadow: 0 1px 0 var(--color--border, var(--border, #e1e1e4)); font-size: 0.875rem; }
.site-strip.is-hot { background-color: var(--color--primary, var(--primary, #e8480c)); transition: background-color .25s ease; }
.site-strip.is-cooling { transition: background-color 1.2s ease; }
.site-strip_inner { position: relative; box-sizing: border-box; display: flex; align-items: center; justify-content: flex-end; width: 100%; max-width: 1180px; height: 40px; margin: 0 auto; padding: 0 1rem; }
.site-strip_inner.is-narrow { max-width: 1040px; padding-left: 1.25rem; padding-right: 1.25rem; }
.site-strip_switches { position: relative; display: flex; align-items: center; gap: 1.5rem; }
.site-strip_item { display: inline-flex; align-items: center; gap: 0.375rem; padding: 0; border: 0; background: transparent; color: var(--color--neutral-700, var(--text-mu, #3b3b42)); font: inherit; font-weight: 500; line-height: 1; text-decoration: none; white-space: nowrap; cursor: pointer; }
.site-strip_item:hover { color: var(--color--text, var(--text, #16161a)); }
.site-strip_item:focus-visible { outline: 2px solid var(--color--primary, var(--primary, #e8480c)); outline-offset: 3px; }
.site-strip_item.is-hot, .site-strip_item.is-hot:hover { color: var(--color--on-primary, #16161a); transition: color .25s ease; }
.site-strip_item.is-hot:focus-visible { outline-color: var(--color--on-primary, #16161a); }
.site-strip_item.is-cooling { transition: color 1.2s ease; }
.site-strip_rule { display: block; width: 1px; height: 16px; background: var(--color--border, var(--border, #e1e1e4)); }
.site-strip_rule.is-hot { background: color-mix(in srgb, var(--color--on-primary, #16161a) 35%, transparent); transition: background-color .25s ease; }
.site-strip_rule.is-cooling { transition: background-color 1.2s ease; }
.site-strip_icon { display: block; flex: none; }
.site-strip_icon.is-sun { display: none; }
.site-strip_icon.is-sun.is-dark { display: block; }
.site-strip_icon.is-moon.is-dark { display: none; }
.site-strip_reel-window { display: block; height: 1.4em; margin: -0.2em 0; line-height: 1.4em; overflow: hidden; }
.site-strip_reel { display: block; }
.site-strip_reel-line { display: block; height: 1.4em; white-space: nowrap; }
.site-strip_sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.site-tour { position: absolute; top: 50%; right: 100%; display: none; align-items: center; gap: 0.4rem; margin-right: 14px; color: var(--color--neutral-700, var(--text-mu, #3b3b42)); font-size: 0.875rem; font-weight: 500; line-height: 1; white-space: nowrap; opacity: 0; transform: translateY(-50%); transition: opacity .2s ease; }
.site-tour.is-open { display: flex; }
.site-tour.is-shown { opacity: 1; }
.site-tour.is-hot { color: var(--color--on-primary, #16161a); transition: opacity .2s ease, color .25s ease; }
.site-tour.is-cooling { transition: opacity .2s ease, color 1.2s ease; }
.site-tour_text { position: relative; margin: 0; white-space: nowrap; }
.site-tour_text.is-hot { font-weight: 600; }
.site-tour_short { display: none; }
.site-tour_close { position: relative; display: inline-flex; align-items: center; justify-content: center; flex: none; width: 32px; height: 30px; margin-left: -4px; padding: 0; border: 0; border-radius: 3px; background: transparent; color: var(--color--primary, var(--primary, #e8480c)); cursor: pointer; }
.site-tour_close:hover, .site-tour_close:focus-visible { color: var(--color--text, var(--text, #16161a)); --site-tour-arrow-opacity: 0; --site-tour-arrow-transform: rotate(90deg) scale(.6); --site-tour-x-opacity: 1; --site-tour-x-transform: none; --site-tour-nudge: none; }
.site-tour_close:focus-visible { outline: 2px solid var(--color--primary, var(--primary, #e8480c)); outline-offset: 1px; }
.site-tour_close.is-hot, .site-tour_close.is-hot:hover { color: var(--color--on-primary, #16161a); transition: color .25s ease; }
.site-tour_close.is-hot:focus-visible { color: var(--color--on-primary, #16161a); outline-color: var(--color--on-primary, #16161a); }
.site-tour_close.is-cooling { transition: color 1.2s ease; }
.site-tour_icon { display: block; width: 21px; height: 14px; overflow: visible; animation-name: var(--site-tour-nudge, site-tour-nudge); animation-duration: 2.2s; animation-timing-function: ease-in-out; animation-delay: .4s; animation-iteration-count: infinite; }
.site-tour_arrow, .site-tour_x { transform-box: view-box; transform-origin: 18px 12px; transition: opacity .18s ease, transform .22s ease; }
.site-tour_arrow { opacity: var(--site-tour-arrow-opacity, 1); transform: var(--site-tour-arrow-transform, none); }
.site-tour_x { opacity: var(--site-tour-x-opacity, 0); transform: var(--site-tour-x-transform, rotate(-90deg) scale(.6)); }
@keyframes site-tour-nudge { 0%, 55%, 100% { transform: translateX(0); opacity: .7; } 20% { transform: translateX(4px); opacity: 1; } 35% { transform: translateX(0); opacity: .85; } 45% { transform: translateX(2px); opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .site-nav_inner, .site-nav_name, .site-nav_cta, .site-tour, .site-tour_arrow, .site-tour_x { transition: none; } .site-tour_icon { animation-name: none; } }
@media (max-width: 767px) {
  .site-nav_inner { padding-top: 10px; padding-bottom: 10px; column-gap: 0.75rem; }
  .site-nav_menu-button { display: inline-flex; }
  .site-nav_menu-button.is-open { background: var(--color--surface-alt, var(--surface-alt, #f7f7f8)); }
  .site-nav_links { display: none; position: absolute; top: 100%; left: 0; right: 0; flex-direction: column; align-items: stretch; gap: 0; padding: 4px 1rem 1rem; background: var(--color--surface, var(--surface, #ffffff)); box-shadow: 0 1px 0 var(--color--border, var(--border, #e1e1e4)), 0 12px 24px -12px rgba(16, 16, 20, 0.25); }
  .site-nav_links.is-open { display: flex; }
  .site-nav_link { padding: 0.85rem 0; border-bottom: 1px solid var(--color--border, var(--border, #e1e1e4)); }
  .site-nav_link.is-menu-cta { display: flex; justify-content: center; margin-top: 1rem; padding: 0.75rem 1rem; border: 0; border-radius: 4px; background: var(--color--primary, var(--primary, #e8480c)); color: var(--color--on-primary, #16161a); font-weight: 600; }
  .site-nav_link.is-menu-lang { display: flex; }
  .site-nav_cta.is-hidden-in-menu, .site-nav_lang.is-hidden-in-menu { display: none; }
  .site-nav_mark { width: 29.45px; height: 26px; }
  .site-nav_name { max-width: 128px; margin-left: 9.05px; margin-bottom: -0.09px; }
  .site-nav_wordmark { width: 120.89px; height: 21.69px; }
  .site-nav_inner.is-strip { grid-template-columns: 0 auto 1fr; column-gap: 0; padding-top: 14px; padding-bottom: 14px; }
  .site-nav_links.is-strip { gap: 0; }
  .site-tour { gap: 0.3rem; margin-right: 8px; font-size: 0.8125rem; }
  .site-tour_long { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  .site-tour_short { display: inline; }
  .site-tour_close { width: 26px; }
  .site-tour_icon { width: 18px; }
}
/* site-nav:end */
/* The homepage's logo-cloud client names still use this old nav class. */
.main-nav_logo { display: inline-flex; align-items: center; gap: 0.5rem; font-family: var(--type--family-heading); font-weight: 700; letter-spacing: -0.02em; color: var(--color--text); }

/* ---------- Hero ---------- */
/* Hero — signature dark editorial band: ink surface, orange mono eyebrow,
   light-ghost secondary. Content that needs to flip for the dark band
   carries an explicit `is-on-inverse` combo class in the markup — Webflow's
   Designer canvas only expresses classes/combo classes, so a descendant
   selector like `.hero .text-lg` has no Webflow style and falls through to
   head custom code, which the canvas doesn't render. Shared with
   `.cta-section` below, the other dark inverse band. */
.hero { padding: var(--space--2xl) 0; background: var(--color--surface-inverse); color: var(--color--text-inverse); }
.hero_content { max-width: 780px; display: grid; grid-template-columns: 1fr; gap: var(--space--md); }
.heading-2xl.is-on-inverse, .heading-xl.is-on-inverse, .heading-lg.is-on-inverse { color: var(--color--text-inverse); }
.text-lg.is-on-inverse { color: var(--color--on-inverse-body); }
/* Eyebrow's actual inverse color is set once, below, alongside
   --color--accent-on-inverse (see the "accent-on-inverse" block) — this
   just zeroes the margin the hero_content grid's own gap already supplies. */
.eyebrow.is-on-inverse-tight { margin-bottom: 0; }
/* `is-outline-inverse` folds the outline variant and the inverse-band
   recolor into one combo (design.md rule 8: two classes per element, max —
   stacking `is-outline` + `is-on-inverse` would be a third). */
.button.is-outline-inverse { background: transparent; border-color: var(--color--on-inverse-line); color: var(--color--text-inverse); }
.button.is-outline-inverse:hover { background: var(--color--on-inverse-wash); border-color: var(--color--on-inverse-line); }

/* ---------- Stats ---------- */
.stats-set { display: flex; flex-wrap: wrap; gap: var(--space--xl); justify-content: center; }
.stats-set_item { text-align: center; }
.stats-set_number { display: block; font-family: var(--type--family-heading); font-size: var(--type--display); font-weight: 700; letter-spacing: -0.02em; color: var(--color--primary); }
.stats-set_label { display: block; color: var(--color--text-mu); }

/* ---------- Programs / feature grid ---------- */
.program-section { padding: var(--space--2xl) 0; }
.program-list { display: grid; gap: var(--space--lg); grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); margin-top: var(--space--xl); }
.program-item { padding: var(--space--lg); border-radius: var(--radius--md); background: var(--color--surface); box-shadow: var(--effect--shadow-sm); }
.program-item_icon { width: 48px; height: 48px; }
.program-item_title { font-family: var(--type--family-heading); font-size: var(--type--h3); margin: var(--space--sm) 0; }
.program-item_text { color: var(--color--text-mu); }

/* ---------- Testimonials ---------- */
.testimonial-section { padding: var(--space--2xl) 0; background: var(--color--surface-alt); }
.testimonial-slider { display: grid; grid-template-columns: 1fr; gap: var(--space--lg); }
.testimonial-slide { background: var(--color--surface); border-radius: var(--radius--lg); padding: var(--space--xl); box-shadow: var(--effect--shadow-lg); }
.testimonial-slide_quote { font-size: var(--type--h2); line-height: 1.3; letter-spacing: -0.01em; color: var(--color--text); }
.testimonial-slide_quote::before { content: "\201C"; display: block; font-family: var(--type--family-heading); font-size: 3rem; line-height: 0.4; color: var(--color--primary); margin-bottom: var(--space--sm); }
.testimonial-slide_author { margin-top: var(--space--md); font-weight: 600; color: var(--color--accent-deep); }

/* ---------- FAQ (hairline-divided Q/A list) ---------- */
.faq { display: grid; grid-template-columns: 1fr; margin-top: var(--space--lg); }
.faq_item { padding: var(--space--md) 0; border-top: 1px solid var(--color--border); }
.faq_item:first-child { border-top: none; padding-top: 0; }
.faq_question { font-family: var(--type--family-heading); font-size: var(--type--h3); font-weight: 600; letter-spacing: -0.01em; color: var(--color--text); margin-bottom: var(--space--xs); }
.faq_answer { color: var(--color--text-mu); line-height: 1.6; max-width: 60ch; }

/* ---------- Feature split (alternating media + text rows) ---------- */
.feature-split { display: grid; grid-template-columns: 1fr; gap: var(--space--2xl); margin-top: var(--space--xl); }
.feature-split_row { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space--2xl); align-items: center; }
.feature-split_media { grid-column: 1; grid-row: 1 / -1; width: 100%; height: 100%; min-height: 14rem; object-fit: cover; border-radius: var(--radius--lg); background: var(--color--surface-alt); }
.feature-split_row > :not(.feature-split_media) { grid-column: 2; }
.feature-split_row h3 { align-self: end; }
.feature-split_row p { align-self: start; }
.feature-split_row:nth-child(even) .feature-split_media { grid-column: 2; }
.feature-split_row:nth-child(even) > :not(.feature-split_media) { grid-column: 1; }
@media (max-width: 767px) {
  .feature-split_row, .feature-split_row:nth-child(even) { grid-template-columns: 1fr; }
  /* Selectors mirror the desktop column-pin rules above (line 258/261/262)
     so the mobile override matches their specificity — a plain `> *` here
     loses to `> :not(.feature-split_media)` and the column pin never clears. */
  .feature-split_row > :not(.feature-split_media),
  .feature-split_row:nth-child(even) > :not(.feature-split_media) { grid-column: 1; }
  .feature-split_media, .feature-split_row:nth-child(even) .feature-split_media { grid-column: 1; grid-row: auto; }
}

/* ---------- Logo cloud (grayscale brand marks) ---------- */
.logo-cloud { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: var(--space--xl); margin-top: var(--space--md); }
.logo-cloud_item { display: inline-flex; }
.logo-cloud_logo { height: 1.75rem; width: auto; opacity: 0.6; filter: grayscale(1); transition: opacity var(--effect--transition-base), filter var(--effect--transition-base); }
.logo-cloud_logo:hover { opacity: 1; filter: none; }

/* ---------- Steps (numbered process) ---------- */
.steps { counter-reset: step; display: grid; gap: var(--space--lg); grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); margin-top: var(--space--xl); }
.steps_item { counter-increment: step; padding-top: var(--space--md); border-top: 2px solid var(--color--primary); }
.steps_item::before { content: counter(step, decimal-leading-zero); display: block; font-family: var(--type--family-mono); font-size: var(--type--h3); font-weight: 700; color: var(--color--primary); margin-bottom: var(--space--sm); }
.steps_title { font-family: var(--type--family-heading); font-size: var(--type--h3); font-weight: 600; letter-spacing: -0.01em; color: var(--color--text); margin-bottom: var(--space--xs); }
.steps_text { color: var(--color--text-mu); }

/* ---------- Team (people grid) ---------- */
.team { display: grid; gap: var(--space--lg); grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); margin-top: var(--space--xl); }
.team_member { text-align: center; }
.team_photo { width: 100%; aspect-ratio: 1 / 1; object-fit: cover; border-radius: var(--radius--lg); background: var(--color--surface-alt); margin-bottom: var(--space--sm); }
.team_name { font-family: var(--type--family-heading); font-size: var(--type--h3); font-weight: 600; letter-spacing: -0.01em; color: var(--color--text); }
.team_role { color: var(--color--text-mu); font-size: var(--type--small); }

/* ---------- Pricing (tiered plan cards) ---------- */
.pricing { display: grid; gap: var(--space--lg); grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); margin-top: var(--space--xl); align-items: start; }
.pricing_tier { display: grid; grid-template-columns: 1fr; gap: var(--space--sm); padding: var(--space--lg); border: 1px solid var(--color--border); border-radius: var(--radius--lg); background: var(--color--surface); }
.pricing_tier.is-featured { border-color: var(--color--primary); box-shadow: var(--effect--shadow-lg); }
.pricing_name { font-family: var(--type--family-heading); font-size: var(--type--h3); font-weight: 600; letter-spacing: -0.01em; }
.pricing_price { font-family: var(--type--family-heading); font-size: var(--type--display); font-weight: 700; letter-spacing: -0.02em; color: var(--color--text); }
.pricing_note { color: var(--color--text-mu); font-size: var(--type--small); }
.pricing_features { display: grid; grid-template-columns: 1fr; gap: var(--space--xs); color: var(--color--text-mu); margin: var(--space--sm) 0; }

/* ---------- Locations / gallery ---------- */
.locations-section { padding: var(--space--2xl) 0; }
.location-list { display: grid; gap: var(--space--md); grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); margin-top: var(--space--lg); }
.location-item_dot { font-family: var(--type--family-heading); font-size: var(--type--h3); color: var(--color--primary-600); }

/* ---------- Newsletter / form ---------- */
.newsletter-section { padding: var(--space--2xl) 0; }
.newsletter-box { max-width: 560px; margin: 0 auto; text-align: center; display: grid; grid-template-columns: 1fr; gap: var(--space--md); }
.newsletter-form { display: grid; grid-template-columns: 1fr; gap: var(--space--sm); }
.newsletter-form input, .newsletter-form textarea, .newsletter-form select {
  padding: 0.75rem 1rem; border: 1px solid var(--color--border); border-radius: var(--radius--sm); font: inherit;
}

/* ---------- CTA ---------- */
/* The other dark inverse band — see the Hero comment above for why its
   children carry combo classes (`is-on-inverse*`) instead of a descendant
   selector. `.heading-2xl.is-on-inverse` and `.button.is-outline-inverse`
   are shared with Hero and defined there; the eyebrow color is shared too,
   set once alongside --color--accent-on-inverse below. Body copy here reads
   at the stronger on-inverse-strong tone rather than Hero's on-inverse-body,
   so it gets its own combo. The button-group below reuses the existing
   `.button-group.is-center` utility instead of minting a new one. */
.cta-section { padding: var(--space--2xl) 0; background: var(--color--surface-inverse); color: var(--color--text-inverse); text-align: center; }
.text-lg.is-on-inverse-strong, .text-base.is-on-inverse-strong, .text-sm.is-on-inverse-strong { color: var(--color--on-inverse-strong); }

/* ---------- Footer ---------- */
.footer { background: var(--color--surface-inverse); color: var(--color--text-inverse); padding: var(--space--xl) 0; }
.footer_layout { display: grid; gap: var(--space--lg); grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); }
.footer_heading { font-family: var(--type--family-heading); font-size: var(--type--h3); margin-bottom: var(--space--sm); }
.footer_link-list { display: grid; grid-template-columns: 1fr; gap: var(--space--xs); }
.footer_link { color: var(--color--on-inverse-body); }
.footer_link:hover { color: var(--color--text-inverse); }
.footer_copyright { color: var(--color--on-inverse-mu); font-size: var(--type--small); }

/* ==========================================================================
   Catalog elements (DESIGN.md §7)
   Reusable atoms composed into components. Token-driven; the primary/accent
   text colors and brand-as-text shade follow this system's .button
   convention. Status variants (message is-success/is-warning) are deferred
   until the semantic color roles are decided (§11).
   ========================================================================== */

/* ---------- Card ---------- */
.card { background: var(--color--surface); border: 1px solid var(--color--border); border-radius: var(--radius--md); padding: var(--space--lg); box-shadow: var(--effect--shadow-sm); }
.card.is-heavy { box-shadow: var(--effect--shadow-lg); }
.card.is-flush { box-shadow: none; }
.card_title { font-family: var(--type--family-heading); font-size: var(--type--h3); margin-bottom: var(--space--sm); }
.card_text { color: var(--color--text-mu); }

/* ---------- Pill — rounded inline label ---------- */
.pill { display: inline-flex; align-items: center; gap: var(--space--xs); padding: 0.25em 0.75em; border-radius: 999px; font-size: var(--type--small); font-weight: 600; line-height: 1.4; background: var(--color--surface-alt); color: var(--color--text); }
.pill.is-primary { background: var(--color--primary); color: var(--color--on-primary); }
.pill.is-accent { background: var(--color--accent); color: var(--color--on-primary); }
.pill.is-outline { background: transparent; border: 1px solid var(--color--border); color: var(--color--text-mu); }

/* ---------- Tag — compact label ---------- */
.tag { display: inline-flex; align-items: center; gap: var(--space--xs); padding: 0.15em 0.55em; border-radius: var(--radius--sm); font-size: var(--type--small); font-weight: 500; line-height: 1.5; background: var(--color--surface-alt); color: var(--color--text-mu); border: 1px solid var(--color--border); }
.tag.is-primary { background: var(--color--primary); color: var(--color--on-primary); border-color: transparent; }
.tag.is-accent { background: var(--color--accent); color: var(--color--on-primary); border-color: transparent; }
.tag.is-sm { font-size: 0.75rem; padding: 0.1em 0.4em; }

/* ---------- Dot — status indicator ---------- */
.dot { display: inline-block; width: 0.6em; height: 0.6em; border-radius: 999px; background: var(--color--text-mu); vertical-align: middle; }
.dot.is-primary { background: var(--color--primary); }
.dot.is-accent { background: var(--color--accent); }

/* ---------- Icon + icon-wrapper ---------- */
.icon { display: inline-flex; align-items: center; justify-content: center; width: 1.25em; height: 1.25em; flex: none; }
.icon svg, .icon img { width: 100%; height: 100%; display: block; }
.icon.is-lg { width: 1.75em; height: 1.75em; }
.icon-wrapper { display: inline-flex; align-items: center; justify-content: center; width: 3rem; height: 3rem; border-radius: var(--radius--md); background: var(--color--surface-alt); color: var(--color--primary-600); flex: none; }
.icon-wrapper.is-primary { background: var(--color--primary); color: var(--color--on-primary); }
.icon-wrapper.is-round { border-radius: 999px; }

/* ---------- Avatar ---------- */
.avatar { display: inline-block; width: 3rem; height: 3rem; border-radius: 999px; overflow: hidden; background: var(--color--surface-alt); flex: none; }
.avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
.avatar.is-sm { width: 2rem; height: 2rem; }
.avatar.is-lg { width: 4.5rem; height: 4.5rem; }

/* ==========================================================================
   Catalog forms (DESIGN.md §7)
   Skin-agnostic: neutral surfaces + a primary focus/checked indicator drawn ON
   the surface (never text on a primary fill), so this block is identical across
   systems — reskinned only by tokens. Inserted before the utilities block so
   utilities still win at equal specificity. Uses only the §7 form vocabulary
   (no invented class names); labeled checkboxes/radios compose `checkbox`/
   `radio` with a flex utility. Error/success field states await the §11
   semantic color-role decision.
   ========================================================================== */

/* ---------- form-wrapper / form ---------- */
.form-wrapper { background: var(--color--surface); border: 1px solid var(--color--border); border-radius: var(--radius--md); padding: var(--space--lg); }
.form { display: grid; grid-template-columns: 1fr; gap: var(--space--md); }

/* ---------- form_row — fields side by side, stacks on small ---------- */
.form_row { display: flex; flex-wrap: wrap; gap: var(--space--md); }
.form_row > * { flex: 1 1 0; min-width: 0; }
@media (max-width: 767px) { .form_row > * { flex-basis: 100%; } }

/* ---------- input-field — label + control + help, stacked ---------- */
.input-field { display: grid; grid-template-columns: 1fr; gap: var(--space--xs); }
.input-field_label { font-size: var(--type--small); font-weight: 600; color: var(--color--text); }
.input-field_help { font-size: var(--type--small); color: var(--color--text-mu); }

/* ---------- input (text / select / textarea) ---------- */
.input { width: 100%; padding: 0.6rem 0.85rem; font: inherit; line-height: 1.4; color: var(--color--text); background: var(--color--surface); border: 1px solid var(--color--border); border-radius: var(--radius--sm); transition: border-color var(--effect--transition-base), box-shadow var(--effect--transition-base); }
.input::placeholder { color: var(--color--text-mu); }
.input:focus { outline: none; border-color: var(--color--primary); box-shadow: inset 0 0 0 1px var(--color--primary); }
.input:disabled { background: var(--color--surface-alt); color: var(--color--text-mu); cursor: not-allowed; }
.input.is-textarea { min-height: 7rem; resize: vertical; }
.input.is-select { appearance: none; -webkit-appearance: none; padding-right: 2.25rem; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%237a7f8a' stroke-width='1.6'%3E%3Cpath d='M4 6l4 4 4-4'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right 0.8rem center; background-size: 0.75rem; }

/* ---------- checkbox / radio — primary indicator on surface (no fill) ---------- */
.checkbox, .radio { appearance: none; -webkit-appearance: none; width: 1.15em; height: 1.15em; margin: 0; flex: none; position: relative; border: 1px solid var(--color--border); background: var(--color--surface); cursor: pointer; transition: border-color var(--effect--transition-base); }
.checkbox { border-radius: var(--radius--sm); }
.radio { border-radius: 999px; }
.checkbox:checked, .radio:checked { border-color: var(--color--primary); }
.checkbox:checked::after { content: ""; position: absolute; left: 34%; top: 14%; width: 26%; height: 52%; border: solid var(--color--primary); border-width: 0 2px 2px 0; transform: rotate(45deg); }
.radio:checked::after { content: ""; position: absolute; inset: 22%; border-radius: 999px; background: var(--color--primary); }
.checkbox:disabled, .radio:disabled { background: var(--color--surface-alt); cursor: not-allowed; }
.checkbox:focus-visible, .radio:focus-visible { outline: 2px solid var(--color--primary); outline-offset: 2px; }

/* ==========================================================================
   Catalog content (DESIGN.md §4, §7)
   richtext re-enables the prose flow the global reset strips (list markers,
   block spacing). Links use this system's dark brand shade for AA contrast;
   decorative marks use accent (shared). list / list-h / list-custom are the
   §7 list family; list-item_icon is the per-item icon. Inserted before the
   utilities block so utilities still win at equal specificity.
   ========================================================================== */

/* ---------- richtext — prose container ---------- */
.richtext { color: var(--color--text); line-height: 1.7; }
.richtext > * + * { margin-top: var(--space--md); }
.richtext h2 { font-family: var(--type--family-heading); font-size: var(--type--h2); font-weight: 700; line-height: 1.2; margin-top: var(--space--xl); }
.richtext h3 { font-family: var(--type--family-heading); font-size: var(--type--h3); font-weight: 700; margin-top: var(--space--lg); }
.richtext h4 { font-family: var(--type--family-heading); font-size: 1.125rem; font-weight: 700; margin-top: var(--space--lg); }
.richtext p { color: var(--color--text-mu); }
.richtext a { color: var(--color--accent-deep); text-decoration: underline; text-underline-offset: 2px; }
.richtext a:hover { text-decoration: none; }
.richtext strong, .richtext b { color: var(--color--text); font-weight: 700; }
.richtext ul, .richtext ol { padding-left: 1.5em; color: var(--color--text-mu); }
.richtext ul { list-style: disc; }
.richtext ol { list-style: decimal; }
.richtext li + li { margin-top: var(--space--xs); }
.richtext blockquote { padding-left: var(--space--md); border-left: 3px solid var(--color--accent); color: var(--color--text); font-style: italic; }
.richtext code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.9em; background: var(--color--surface-alt); border: 1px solid var(--color--border); border-radius: var(--radius--sm); padding: 0.1em 0.35em; }
.richtext pre { background: var(--color--surface-alt); border: 1px solid var(--color--border); border-radius: var(--radius--md); padding: var(--space--md); overflow-x: auto; }
.richtext pre code { background: none; border: none; padding: 0; }
.richtext hr { border: none; border-top: 1px solid var(--color--border); }
.richtext img { border-radius: var(--radius--md); }
.richtext.is-richtext-lg { font-size: 1.125rem; line-height: 1.75; }

/* ---------- list family ---------- */
.list { display: grid; grid-template-columns: 1fr; gap: var(--space--sm); }
.list-h { display: flex; flex-wrap: wrap; gap: var(--space--md); }
.list-custom { display: grid; grid-template-columns: 1fr; gap: var(--space--sm); list-style: none; padding-left: 0; }
.list_item { display: flex; gap: var(--space--sm); align-items: flex-start; color: var(--color--text-mu); }
/* `list_item is-h` not `.list-h .list_item` — a Webflow combo class, not a
   descendant selector off the `list-h` wrapper (not used in this site's
   markup yet; converted for Webflow-portability parity with the rest of the
   catalog). */
.list_item.is-h { align-items: center; }
.list-item_icon { flex: none; display: inline-flex; align-items: center; justify-content: center; width: 1.25em; height: 1.25em; margin-top: 0.1em; color: var(--color--accent); }
.list-item_icon svg, .list-item_icon img { width: 100%; height: 100%; display: block; }

/* ==========================================================================
   Catalog navigation & disclosure (DESIGN.md §7)
   breadcrumb is CSS-only; dropdown / tabs / slider are driven by the system's
   script.js (data-attribute wired, dependency-free). Skin-agnostic: accents use
   primary fills/underlines (no text on a primary fill), so this block is
   identical across systems. Inserted before the utilities block so utilities
   still win at equal specificity.
   ========================================================================== */

/* ---------- Breadcrumb (CSS-only) ---------- */
.breadcrumb { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space--xs); font-size: var(--type--small); color: var(--color--text-mu); }
.breadcrumb_item { color: var(--color--text-mu); }
.breadcrumb_item:hover { color: var(--color--text); }
.breadcrumb_item.is-current { color: var(--color--text); font-weight: 600; }
.breadcrumb_sep { color: var(--color--border); user-select: none; }

/* ---------- Dropdown ---------- */
.dropdown { position: relative; display: inline-block; }
.dropdown_trigger { display: inline-flex; align-items: center; gap: var(--space--xs); cursor: pointer; }
.dropdown_menu { position: absolute; top: calc(100% + 0.25rem); left: 0; min-width: 12rem; background: var(--color--surface); border: 1px solid var(--color--border); border-radius: var(--radius--md); box-shadow: var(--effect--shadow-lg); padding: var(--space--xs); display: none; z-index: 20; }
/* State on the menu itself, not `.dropdown.is-open .dropdown_menu` — Webflow
   has no ancestor-state selector (design.md rule 12). Toggle is-open here. */
.dropdown_menu.is-open { display: block; }
.dropdown.is-right .dropdown_menu { left: auto; right: 0; }
.dropdown_item { display: block; width: 100%; text-align: left; padding: var(--space--xs) var(--space--sm); border-radius: var(--radius--sm); color: var(--color--text); background: none; }
.dropdown_item:hover { background: var(--color--surface-alt); }

/* ---------- Tabs ---------- */
.tabs_nav { display: flex; flex-wrap: wrap; gap: var(--space--sm); border-bottom: 1px solid var(--color--border); }
.tabs_tab { padding: var(--space--sm) var(--space--md); border: none; background: none; color: var(--color--text-mu); font-family: inherit; font-weight: 600; cursor: pointer; border-bottom: 2px solid transparent; margin-bottom: -1px; }
.tabs_tab:hover { color: var(--color--text); }
.tabs_tab.is-active { color: var(--color--text); border-bottom-color: var(--color--primary); }
.tabs_panel { display: none; padding-top: var(--space--md); }
.tabs_panel.is-active { display: block; }

/* ---------- Slider ---------- */
.slider { position: relative; }
.slider_viewport { overflow: hidden; }
.slider_track { display: flex; transition: transform var(--effect--transition-base); }
.slider_slide { flex: 0 0 100%; min-width: 0; }
.slider_nav { position: absolute; top: 50%; transform: translateY(-50%); display: inline-flex; align-items: center; justify-content: center; width: 2.5rem; height: 2.5rem; border-radius: 999px; background: var(--color--surface); border: 1px solid var(--color--border); box-shadow: var(--effect--shadow-sm); cursor: pointer; color: var(--color--text); }
.slider_nav.is-prev { left: var(--space--sm); }
.slider_nav.is-next { right: var(--space--sm); }
.slider_nav:disabled { opacity: 0.4; cursor: default; }
.slider_dots { display: flex; justify-content: center; gap: var(--space--xs); margin-top: var(--space--md); }
.slider_dot { width: 0.5rem; height: 0.5rem; padding: 0; border: none; border-radius: 999px; background: var(--color--border); cursor: pointer; }
.slider_dot.is-active { background: var(--color--primary); }

/* ==========================================================================
   Catalog message / info (DESIGN.md §7)
   Notice panels. Skin-agnostic: the tinted background is derived from the
   status color via color-mix() on the surface, so this block is identical
   across systems and needs only the success/warning/danger tokens (§11).
   is-note reuses the neutral surface; is-callout tints with primary. Text sits
   on a light tint, so it stays the default dark `text` (AA); status colors are
   dark enough to pass AA as the left rule and title. Inserted before the
   utilities block so utilities still win at equal specificity.
   ========================================================================== */

.message, .info { padding: var(--space--md); border-radius: var(--radius--sm); border-left: 4px solid var(--color--border); background: var(--color--surface-alt); color: var(--color--text); }
.message_title, .info_title { font-family: var(--type--family-heading); font-weight: 700; margin-bottom: var(--space--xs); }
.message_text, .info_text { color: var(--color--text); }

.message.is-success { border-left-color: var(--color--success); background: color-mix(in srgb, var(--color--success) 10%, var(--color--surface)); }
.message.is-warning { border-left-color: var(--color--warning); background: color-mix(in srgb, var(--color--warning) 12%, var(--color--surface)); }
.message.is-danger { border-left-color: var(--color--danger); background: color-mix(in srgb, var(--color--danger) 10%, var(--color--surface)); }
.message.is-note { border-left-color: var(--color--border); background: var(--color--surface-alt); }
.message.is-callout { border-left-color: var(--color--primary); background: color-mix(in srgb, var(--color--primary) 8%, var(--color--surface)); }

.message.is-success .message_title { color: var(--color--success); }
.message.is-warning .message_title { color: var(--color--warning); }
.message.is-danger .message_title { color: var(--color--danger); }

/* ==========================================================================
   Utilities & column system (DESIGN.md §7–§8)
   Skin-agnostic layer: every rule is var()-driven or pure layout, so this
   block is identical across systems (like patterns/ + components/). Kept at
   the end of components.css so utilities win over component defaults.
   Responsive tiers are Webflow-native, desktop-first:
     base (desktop) · -md ≤991px (tablet) · -sm ≤767px (landscape) · -xs ≤479px (mobile)
   Combo classes use a -tier dash suffix (is-span-6-md); utilities use a
   _tier underscore suffix (u-hide_md).
   ========================================================================== */

/* ---------- Fixed-count grid: grid-cols is-Ncol ---------- */
.grid-cols { display: grid; grid-template-columns: repeat(1, minmax(0, 1fr)); gap: var(--space--lg); }
.grid-cols.is-1col { grid-template-columns: repeat(1, minmax(0, 1fr)); }
.grid-cols.is-2col { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid-cols.is-3col { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid-cols.is-4col { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.grid-cols.is-5col { grid-template-columns: repeat(5, minmax(0, 1fr)); }
.grid-cols.is-6col { grid-template-columns: repeat(6, minmax(0, 1fr)); }

@media (max-width: 991px) {
  .grid-cols.is-1col-md { grid-template-columns: repeat(1, minmax(0, 1fr)); }
  .grid-cols.is-2col-md { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .grid-cols.is-3col-md { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .grid-cols.is-4col-md { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .grid-cols.is-5col-md { grid-template-columns: repeat(5, minmax(0, 1fr)); }
  .grid-cols.is-6col-md { grid-template-columns: repeat(6, minmax(0, 1fr)); }
}
@media (max-width: 767px) {
  .grid-cols.is-1col-sm { grid-template-columns: repeat(1, minmax(0, 1fr)); }
  .grid-cols.is-2col-sm { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .grid-cols.is-3col-sm { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .grid-cols.is-4col-sm { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .grid-cols.is-5col-sm { grid-template-columns: repeat(5, minmax(0, 1fr)); }
  .grid-cols.is-6col-sm { grid-template-columns: repeat(6, minmax(0, 1fr)); }
}
@media (max-width: 479px) {
  .grid-cols.is-1col-xs { grid-template-columns: repeat(1, minmax(0, 1fr)); }
  .grid-cols.is-2col-xs { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .grid-cols.is-3col-xs { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .grid-cols.is-4col-xs { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .grid-cols.is-5col-xs { grid-template-columns: repeat(5, minmax(0, 1fr)); }
  .grid-cols.is-6col-xs { grid-template-columns: repeat(6, minmax(0, 1fr)); }
}

/* ---------- Flex columns: equal-width row that wraps ---------- */
.flex-cols { display: flex; flex-wrap: wrap; gap: var(--space--lg); }
.flex-cols > * { flex: 1 1 0; min-width: 0; }
.flex-cols.is-gap-sm { gap: var(--space--sm); }
.flex-cols.is-gap-lg { gap: var(--space--xl); }
@media (max-width: 767px) { .flex-cols.is-stack-sm > * { flex-basis: 100%; } }
@media (max-width: 479px) { .flex-cols.is-stack-xs > * { flex-basis: 100%; } }

/* ---------- Bento: dense auto-flow grid ---------- */
.bento { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); grid-auto-rows: minmax(180px, auto); grid-auto-flow: dense; gap: var(--space--lg); }
.bento_item { min-width: 0; }
.bento_item.is-wide { grid-column: span 2; }
.bento_item.is-tall { grid-row: span 2; }
.bento_item.is-big { grid-column: span 2; grid-row: span 2; }
@media (max-width: 767px) { .bento { grid-template-columns: repeat(2, minmax(0, 1fr)); } .bento_item.is-big { grid-column: span 2; } }
@media (max-width: 479px) { .bento { grid-template-columns: minmax(0, 1fr); } .bento_item.is-wide, .bento_item.is-big { grid-column: span 1; } }

/* ---------- u-Nc: quick grid of N equal columns ---------- */
.u-1c { display: grid; grid-template-columns: repeat(1, minmax(0, 1fr)); gap: var(--space--lg); }
.u-2c { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space--lg); }
.u-3c { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space--lg); }
.u-4c { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--space--lg); }
.u-5c { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: var(--space--lg); }
.u-6c { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: var(--space--lg); }
.u-7c { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: var(--space--lg); }
.u-8c { display: grid; grid-template-columns: repeat(8, minmax(0, 1fr)); gap: var(--space--lg); }
.u-9c { display: grid; grid-template-columns: repeat(9, minmax(0, 1fr)); gap: var(--space--lg); }
.u-10c { display: grid; grid-template-columns: repeat(10, minmax(0, 1fr)); gap: var(--space--lg); }
.u-11c { display: grid; grid-template-columns: repeat(11, minmax(0, 1fr)); gap: var(--space--lg); }
.u-12c { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: var(--space--lg); }

/* ---------- Text ---------- */
.u-text-left { text-align: left; }
.u-text-center { text-align: center; }
.u-text-right { text-align: right; }
.u-font-normal { font-weight: 400; }
.u-font-medium { font-weight: 500; }
.u-font-bold { font-weight: 700; }
.u-uppercase { text-transform: uppercase; letter-spacing: 0.06em; }
.u-text-mu { color: var(--color--text-mu); }
.u-text-inverse { color: var(--color--text-inverse); }
.u-text-primary { color: var(--color--primary); }

/* ---------- Flex (u-hflex-<justify>-<align> row · u-vflex-<align>-<justify> column) ---------- */
.u-hflex-left-center { display: flex; flex-direction: row; justify-content: flex-start; align-items: center; gap: var(--space--md); }
.u-hflex-left-top { display: flex; flex-direction: row; justify-content: flex-start; align-items: flex-start; gap: var(--space--md); }
.u-hflex-center-center { display: flex; flex-direction: row; justify-content: center; align-items: center; gap: var(--space--md); }
.u-hflex-center-top { display: flex; flex-direction: row; justify-content: center; align-items: flex-start; gap: var(--space--md); }
.u-hflex-right-center { display: flex; flex-direction: row; justify-content: flex-end; align-items: center; gap: var(--space--md); }
.u-hflex-between-center { display: flex; flex-direction: row; justify-content: space-between; align-items: center; gap: var(--space--md); }
.u-hflex-between-top { display: flex; flex-direction: row; justify-content: space-between; align-items: flex-start; gap: var(--space--md); }
.u-hflex-around-center { display: flex; flex-direction: row; justify-content: space-around; align-items: center; gap: var(--space--md); }
.u-vflex-left-top { display: flex; flex-direction: column; align-items: flex-start; justify-content: flex-start; gap: var(--space--md); }
.u-vflex-left-center { display: flex; flex-direction: column; align-items: flex-start; justify-content: center; gap: var(--space--md); }
.u-vflex-center-top { display: flex; flex-direction: column; align-items: center; justify-content: flex-start; gap: var(--space--md); }
.u-vflex-center-center { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--space--md); }
.u-vflex-stretch-top { display: flex; flex-direction: column; align-items: stretch; justify-content: flex-start; gap: var(--space--md); }
.u-vflex-center-between { display: flex; flex-direction: column; align-items: center; justify-content: space-between; gap: var(--space--md); }
.u-flex-grow { flex: 1 1 0; min-width: 0; }
.u-gap-sm { gap: var(--space--sm); }
.u-gap-md { gap: var(--space--md); }
.u-gap-lg { gap: var(--space--lg); }

/* ---------- Background ---------- */
.u-bg-surface { background: var(--color--surface); }
.u-bg-surface-alt { background: var(--color--surface-alt); }
.u-bg-surface-inverse { background: var(--color--surface-inverse); color: var(--color--text-inverse); }
.u-bg-primary { background: var(--color--primary); color: var(--color--on-primary); }
.u-bg-accent { background: var(--color--accent); color: var(--color--on-primary); }

/* ---------- Spacing (margin u-m*, padding u-p*; steps 0 xs sm md lg xl 2xl) ---------- */
.u-mt-0 { margin-top: 0; }
.u-mt-xs { margin-top: var(--space--xs); }
.u-mt-sm { margin-top: var(--space--sm); }
.u-mt-md { margin-top: var(--space--md); }
.u-mt-lg { margin-top: var(--space--lg); }
.u-mt-xl { margin-top: var(--space--xl); }
.u-mt-2xl { margin-top: var(--space--2xl); }
.u-mb-0 { margin-bottom: 0; }
.u-mb-xs { margin-bottom: var(--space--xs); }
.u-mb-sm { margin-bottom: var(--space--sm); }
.u-mb-md { margin-bottom: var(--space--md); }
.u-mb-lg { margin-bottom: var(--space--lg); }
.u-mb-xl { margin-bottom: var(--space--xl); }
.u-mb-2xl { margin-bottom: var(--space--2xl); }
.u-ml-0 { margin-left: 0; }
.u-ml-xs { margin-left: var(--space--xs); }
.u-ml-sm { margin-left: var(--space--sm); }
.u-ml-md { margin-left: var(--space--md); }
.u-ml-lg { margin-left: var(--space--lg); }
.u-ml-xl { margin-left: var(--space--xl); }
.u-ml-2xl { margin-left: var(--space--2xl); }
.u-mr-0 { margin-right: 0; }
.u-mr-xs { margin-right: var(--space--xs); }
.u-mr-sm { margin-right: var(--space--sm); }
.u-mr-md { margin-right: var(--space--md); }
.u-mr-lg { margin-right: var(--space--lg); }
.u-mr-xl { margin-right: var(--space--xl); }
.u-mr-2xl { margin-right: var(--space--2xl); }
.u-mx-0 { margin-left: 0; margin-right: 0; }
.u-mx-xs { margin-left: var(--space--xs); margin-right: var(--space--xs); }
.u-mx-sm { margin-left: var(--space--sm); margin-right: var(--space--sm); }
.u-mx-md { margin-left: var(--space--md); margin-right: var(--space--md); }
.u-mx-lg { margin-left: var(--space--lg); margin-right: var(--space--lg); }
.u-mx-xl { margin-left: var(--space--xl); margin-right: var(--space--xl); }
.u-mx-2xl { margin-left: var(--space--2xl); margin-right: var(--space--2xl); }
.u-my-0 { margin-top: 0; margin-bottom: 0; }
.u-my-xs { margin-top: var(--space--xs); margin-bottom: var(--space--xs); }
.u-my-sm { margin-top: var(--space--sm); margin-bottom: var(--space--sm); }
.u-my-md { margin-top: var(--space--md); margin-bottom: var(--space--md); }
.u-my-lg { margin-top: var(--space--lg); margin-bottom: var(--space--lg); }
.u-my-xl { margin-top: var(--space--xl); margin-bottom: var(--space--xl); }
.u-my-2xl { margin-top: var(--space--2xl); margin-bottom: var(--space--2xl); }
.u-m-0 { margin: 0; }
.u-m-xs { margin: var(--space--xs); }
.u-m-sm { margin: var(--space--sm); }
.u-m-md { margin: var(--space--md); }
.u-m-lg { margin: var(--space--lg); }
.u-m-xl { margin: var(--space--xl); }
.u-m-2xl { margin: var(--space--2xl); }
.u-pt-0 { padding-top: 0; }
.u-pt-xs { padding-top: var(--space--xs); }
.u-pt-sm { padding-top: var(--space--sm); }
.u-pt-md { padding-top: var(--space--md); }
.u-pt-lg { padding-top: var(--space--lg); }
.u-pt-xl { padding-top: var(--space--xl); }
.u-pt-2xl { padding-top: var(--space--2xl); }
.u-pb-0 { padding-bottom: 0; }
.u-pb-xs { padding-bottom: var(--space--xs); }
.u-pb-sm { padding-bottom: var(--space--sm); }
.u-pb-md { padding-bottom: var(--space--md); }
.u-pb-lg { padding-bottom: var(--space--lg); }
.u-pb-xl { padding-bottom: var(--space--xl); }
.u-pb-2xl { padding-bottom: var(--space--2xl); }
.u-pl-0 { padding-left: 0; }
.u-pl-xs { padding-left: var(--space--xs); }
.u-pl-sm { padding-left: var(--space--sm); }
.u-pl-md { padding-left: var(--space--md); }
.u-pl-lg { padding-left: var(--space--lg); }
.u-pl-xl { padding-left: var(--space--xl); }
.u-pl-2xl { padding-left: var(--space--2xl); }
.u-pr-0 { padding-right: 0; }
.u-pr-xs { padding-right: var(--space--xs); }
.u-pr-sm { padding-right: var(--space--sm); }
.u-pr-md { padding-right: var(--space--md); }
.u-pr-lg { padding-right: var(--space--lg); }
.u-pr-xl { padding-right: var(--space--xl); }
.u-pr-2xl { padding-right: var(--space--2xl); }
.u-px-0 { padding-left: 0; padding-right: 0; }
.u-px-xs { padding-left: var(--space--xs); padding-right: var(--space--xs); }
.u-px-sm { padding-left: var(--space--sm); padding-right: var(--space--sm); }
.u-px-md { padding-left: var(--space--md); padding-right: var(--space--md); }
.u-px-lg { padding-left: var(--space--lg); padding-right: var(--space--lg); }
.u-px-xl { padding-left: var(--space--xl); padding-right: var(--space--xl); }
.u-px-2xl { padding-left: var(--space--2xl); padding-right: var(--space--2xl); }
.u-py-0 { padding-top: 0; padding-bottom: 0; }
.u-py-xs { padding-top: var(--space--xs); padding-bottom: var(--space--xs); }
.u-py-sm { padding-top: var(--space--sm); padding-bottom: var(--space--sm); }
.u-py-md { padding-top: var(--space--md); padding-bottom: var(--space--md); }
.u-py-lg { padding-top: var(--space--lg); padding-bottom: var(--space--lg); }
.u-py-xl { padding-top: var(--space--xl); padding-bottom: var(--space--xl); }
.u-py-2xl { padding-top: var(--space--2xl); padding-bottom: var(--space--2xl); }
.u-p-0 { padding: 0; }
.u-p-xs { padding: var(--space--xs); }
.u-p-sm { padding: var(--space--sm); }
.u-p-md { padding: var(--space--md); }
.u-p-lg { padding: var(--space--lg); }
.u-p-xl { padding: var(--space--xl); }
.u-p-2xl { padding: var(--space--2xl); }
.u-mx-auto { margin-left: auto; margin-right: auto; }

/* ---------- Visibility ---------- */
.u-hide { display: none !important; }
@media (max-width: 991px) { .u-hide_md { display: none !important; } }
@media (max-width: 767px) { .u-hide_sm { display: none !important; } }
@media (max-width: 479px) { .u-hide_xs { display: none !important; } }
.u-hide-base { display: none !important; }
@media (max-width: 991px) { .u-hide-base.is-show_md { display: revert !important; } }
@media (max-width: 767px) { .u-hide-base.is-show_sm { display: revert !important; } }
@media (max-width: 479px) { .u-hide-base.is-show_xs { display: revert !important; } }

/* ---------- Width ---------- */
.u-w-full { width: 100%; }
.u-mw-none { max-width: none; }


/* Page-level decoration shared by the 3 Batey design versions. Everything here
   is composition scaffolding (theme-toggle chip, product mockups, hero
   graphics) built ONLY from house-default tokens — it adds no new design-system
   vocabulary, it just arranges the system's atoms into a marketing page. */

/* Theme toggle chip (fixed) */
.theme-toggle {
  position: fixed; top: auto; bottom: 12px; right: 12px; z-index: 9999;
  font: 600 12px/1 var(--type--family-mono);
  padding: 8px 12px; border-radius: var(--radius--md);
  border: 1px solid var(--color--border);
  background: var(--color--surface); color: var(--color--text);
  box-shadow: var(--effect--shadow-sm); cursor: pointer;
}

/* Brand wordmark: monospace tag feel */
.brand { font-family: var(--type--family-heading); font-weight: 800; letter-spacing: -0.03em; }
.brand-dot { color: var(--color--primary); }

/* ---------- Browser-chrome mockup frame (product screenshots) ---------- */
.mock {
  border: 1px solid var(--color--border);
  border-radius: var(--radius--lg);
  overflow: hidden;
  background: var(--color--surface);
  box-shadow: var(--effect--shadow-lg);
}
.mock_bar {
  display: flex; align-items: center; gap: var(--space--sm);
  padding: 0.6rem 0.9rem;
  background: var(--color--surface-alt);
  border-bottom: 1px solid var(--color--border);
}
.mock_dots { display: flex; gap: 6px; }
.mock_dots span { width: 10px; height: 10px; border-radius: 999px; background: var(--color--border); display: block; }
.mock_url {
  flex: 1; font-family: var(--type--family-mono); font-size: 0.72rem;
  color: var(--color--text-mu); background: var(--color--surface);
  border: 1px solid var(--color--border); border-radius: 999px;
  padding: 0.28rem 0.75rem; text-align: center; max-width: 320px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.mock_body { padding: var(--space--lg); }

/* Skeleton rows used to fake a rendered page inside a mockup */
.skel { display: grid; grid-template-columns: 1fr; gap: 0.7rem; }
.skel-row { height: 12px; border-radius: 999px; background: var(--color--surface-alt); }
.skel-row.is-title { height: 22px; width: 62%; background: var(--color--border); }
.skel-row.is-accent { background: color-mix(in srgb, var(--color--primary) 55%, var(--color--surface-alt)); width: 38%; }
.skel-cta { height: 34px; width: 130px; border-radius: var(--radius--sm); background: var(--color--primary); margin-top: 0.4rem; }
.skel-grid { display: grid; grid-template-columns: repeat(3,1fr); gap: 0.7rem; margin-top: 0.9rem; }
.skel-card { height: 68px; border-radius: var(--radius--md); border: 1px solid var(--color--border); background: var(--color--surface-alt); }

/* Before/after split for the product version */
.ba { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space--lg); align-items: stretch; }
.ba_label {
  display: inline-flex; align-items: center; gap: var(--space--xs);
  font-family: var(--type--family-mono); font-size: var(--type--small);
  text-transform: uppercase; letter-spacing: 0.05em; color: var(--color--text-mu);
  margin-bottom: var(--space--sm);
}
/* `mock is-before` not `.ba_before .mock` — descendant selectors have no
   Webflow expression (see the hero-split comment below). */
.mock.is-before { opacity: 0.92; filter: grayscale(0.35); }
@media (max-width: 767px) { .ba { grid-template-columns: 1fr; } }

/* ---------- Hero graphic: URL → directions flow (editorial version) ---------- */
.flowcard {
  background: var(--color--on-inverse-wash);
  border: 1px solid var(--color--on-inverse-faint);
  border-radius: var(--radius--lg);
  padding: var(--space--lg);
  backdrop-filter: blur(2px);
}
.flow-url {
  font-family: var(--type--family-mono); font-size: 0.85rem;
  color: var(--color--on-inverse-strong);
  background: rgba(0,0,0,0.35); border: 1px solid var(--color--on-inverse-faint);
  border-radius: var(--radius--sm); padding: 0.7rem 0.9rem;
  display: flex; align-items: center; gap: var(--space--sm);
}
/* `.flow-url .dot { background: var(--color--primary); }` removed — that's
   the existing `.dot.is-primary` utility (defined above with `.dot`); the
   descendant selector duplicated it for no reason. */
.flow-arrow { color: var(--color--primary); font-family: var(--type--family-mono); text-align: center; margin: var(--space--sm) 0; }
.flow-dirs { display: grid; grid-template-columns: repeat(3,1fr); gap: var(--space--sm); }
.flow-dir {
  border: 1px solid var(--color--on-inverse-faint); border-radius: var(--radius--md);
  padding: var(--space--md) var(--space--sm); text-align: center;
}
.flow-dir_sw { height: 30px; border-radius: var(--radius--sm); margin-bottom: var(--space--sm); }
.flow-dir_name { font-family: var(--type--family-mono); font-size: 0.7rem; color: var(--color--on-inverse-body); text-transform: uppercase; letter-spacing: 0.04em; }

/* Two-column hero layout (editorial + conversion) */
/* A MODIFIER on `.container`, not a standalone `.hero-split`. Webflow refuses
   to create a combo whose tail name already exists as a global — so
   `class="container hero-split"` could not become `.container.hero-split` and
   the converter dropped `container`, folding its box properties in. As an
   `is-*` modifier the name exists only in the chain, so Webflow expresses it
   natively and `.container` stays one shared class.

   Not `.hero .hero-split` either: Webflow's style system expresses only
   classes and combo classes, so a descendant selector cannot become a style —
   it falls through to head custom code, which the Designer canvas does not
   run. Anything structural must live on one class or the canvas loses it. */
.container.is-hero-split { display: grid; grid-template-columns: 1.28fr 0.72fr; gap: var(--space--2xl); align-items: center; }
@media (max-width: 900px) { .container.is-hero-split { grid-template-columns: 1fr; gap: var(--space--xl); } }

/* Big terminal-ish code card */
.term {
  background: #0d0d10; border: 1px solid var(--color--on-inverse-faint);
  border-radius: var(--radius--lg); overflow: hidden;
  font-family: var(--type--family-mono); font-size: 0.82rem; line-height: 1.7;
  box-shadow: var(--effect--shadow-lg);
}
.term_bar { display: flex; gap: 6px; padding: 0.7rem 0.9rem; border-bottom: 1px solid var(--color--on-inverse-faint); }
.term_bar span { width: 11px; height: 11px; border-radius: 999px; background: var(--color--on-inverse-line); }
.term_body { padding: var(--space--lg); color: var(--color--on-inverse-strong); }

/* Metric row inside cards */
.kpi { display: grid; grid-template-columns: 1fr; gap: var(--space--xs); }
.kpi_num { font-family: var(--type--family-heading); font-weight: 800; font-size: 2.25rem; letter-spacing: -0.03em; color: var(--color--primary); line-height: 1; }
.kpi_label { color: var(--color--text-mu); font-size: var(--type--small); }

/* Feature card with leading icon-wrapper (uses system atoms) */
.feature { display: grid; grid-template-columns: 1fr; gap: var(--space--md); }
.feature_head { display: flex; align-items: center; gap: var(--space--md); }

/* Simple glyphs (no icon font needed) */
.glyph { font-family: var(--type--family-mono); font-weight: 700; font-size: 1.15rem; line-height: 1; }

/* Section max-width helper for centered intros already covered by .title-set */
.lead-narrow { max-width: 640px; }

/* Marquee-free logo row baseline spacing handled by .logo-cloud */
.wordmark { font-family: var(--type--family-heading); font-weight: 700; letter-spacing: -0.02em; color: var(--color--text-mu); font-size: 1.15rem; opacity: 0.7; }

/* ==========================================================================
   Intake wiring (BP-46) — the design surface for the intake.js REQUIRED_HOOKS
   contract. This block styles the real url/email/tos capture form and the
   status view (token, stages, activation hint, terminal message, variants)
   that intake.js drives, dressed in the same house-default vocabulary as the
   rest of the page. Nothing here is skin-specific; it is all token-driven.
   ========================================================================== */

/* The house system's display rules (.form { display:grid } etc.) beat the
   UA's `[hidden] { display:none }`, so an element intake.js hides via the
   `hidden` attribute would otherwise still render. Restore hidden's meaning. */
[hidden] { display: none !important; }

/* Intake capture form — rides inside the dark hero band. Fields are drawn on
   a translucent dark surface so they read on the ink background. Descendant
   selectors off `.intake-form` have no Webflow expression, so each field
   that needs the dark-band look carries its own combo class instead (see the
   Hero comment above). */
.intake-form { display: grid; grid-template-columns: 1fr; gap: var(--space--md); max-width: 520px; margin: var(--space--md) auto 0; text-align: left; }
.input-field_label.is-on-inverse { color: var(--color--text-inverse); }
.input.is-on-inverse {
  background: rgba(0, 0, 0, 0.25);
  border-color: var(--color--on-inverse-line);
  color: var(--color--text-inverse);
}
.input.is-on-inverse::placeholder { color: var(--color--on-inverse-mu); }
/* `.intake-form .input:focus` removed — it duplicated the base `.input:focus`
   (same primary border/ring) exactly, so it never had a job. */
.intake-form_tos { display: flex; align-items: flex-start; gap: var(--space--sm); font-size: var(--type--small); color: var(--color--on-inverse-body); cursor: pointer; }
.checkbox.is-on-inverse { margin-top: 0.15em; background: rgba(0, 0, 0, 0.25); border-color: var(--color--on-inverse-line); }
/* Layout, not color — the button needs to not stretch to the grid's full
   width, unrelated to the inverse-band modifiers above. */
.button.is-self-start { justify-self: start; }
.intake-form_note { color: var(--color--on-inverse-mu); font-size: var(--type--small); max-width: none; text-align: center; margin-top: var(--space--sm); }

/* Form error — a danger notice that collapses when empty (intake.js writes
   textContent, never toggles `hidden`). */
#form-error {
  max-width: 520px; margin: var(--space--md) auto 0; text-align: left;
  padding: var(--space--md); border-radius: var(--radius--sm);
  border-left: 4px solid var(--color--danger);
  background: rgba(0, 0, 0, 0.28); color: var(--color--text-inverse);
  font-size: var(--type--small);
}
#form-error:empty { display: none; }

/* Status view — replaces the form in place after a successful submit. Lives on
   the dark hero band, so its text is inverse. */
.status-view { max-width: 520px; margin: var(--space--md) auto 0; text-align: left; display: grid; grid-template-columns: 1fr; gap: var(--space--md); }
.status-view_token { color: var(--color--on-inverse-body); font-size: var(--type--small); }
.status-view_token code {
  font-family: var(--type--family-mono); color: var(--color--accent-on-inverse);
  background: rgba(0, 0, 0, 0.3); border-radius: var(--radius--sm); padding: 0.1em 0.4em;
}
/* `status-view_note`, matching `status-view_token` above, not
   `.status-view .note` — `.note` was never a reusable atom on its own, so
   this is a plain child-element class rather than an `is-on-inverse` combo. */
.status-view_note { color: var(--color--on-inverse-body); font-size: var(--type--small); }

/* Stages checklist — intake.js sets .done / .current per <li>. */
.stages { list-style: none; padding-left: 0; display: grid; grid-template-columns: 1fr; gap: var(--space--sm); font-family: var(--type--family-mono); font-size: var(--type--small); }
.stages li { color: var(--color--on-inverse-mu); }
.stages li.done { color: var(--color--success-300); }
.stages li.current { color: var(--color--text-inverse); font-weight: 600; }

/* Activation hint + terminal message — house `.message` panels re-toned for the
   dark band (light text on a translucent tint). */
.intake-notice {
  padding: var(--space--md); border-radius: var(--radius--sm);
  border-left: 4px solid var(--color--primary);
  background: var(--color--on-inverse-wash); color: var(--color--on-inverse-strong);
  font-size: var(--type--small); line-height: 1.55;
}
.intake-notice.is-terminal { border-left-color: var(--color--danger); }

/* Ready variants list. */
.variants { display: grid; grid-template-columns: 1fr; gap: var(--space--sm); }
.variants li { color: var(--color--on-inverse-body); font-size: var(--type--small); }
.variants a { color: var(--color--primary); font-weight: 600; text-decoration: underline; text-underline-offset: 2px; }
.variants a:hover { text-decoration: none; }

/* ==========================================================================
   BIZ-12 marketing-site modifiers (mirror of ds-house-default DS-20/DS-21).
   Keep in sync with systems/house-default/components.css in design-system-library.
   ========================================================================== */
/* hero is-minimal — light interior-page title band */
.hero.is-minimal { padding: var(--space--xl) 0; background: var(--color--surface); color: var(--color--text); }
/* `.hero.is-minimal .heading-2xl/.heading-xl` and `.hero.is-minimal .text-lg`
   are gone — now that `.hero`'s inverse colors only apply via the explicit
   `is-on-inverse` combo (above), a heading/text-lg on a minimal hero that
   never gets that combo already renders at its plain default color, which
   is exactly what those two rules set. They were dead weight even before
   this pass: identical to the base `.heading-2xl`/`.text-lg` colors, just
   winning the specificity fight against `.hero .heading-2xl` etc. */
/* `is-outline-minimal` folds the outline variant and the minimal-hero
   recolor into one combo, same reasoning as `is-outline-inverse` above —
   this one IS a real look (ink text/border, not the base outline's
   accent-deep), not dead code, so it still needs its own rule. */
.button.is-outline-minimal { background: transparent; border-color: var(--color--border); color: var(--color--text); }
.button.is-outline-minimal:hover { background: var(--color--surface-alt); border-color: var(--color--border); }
/* steps is-timeline — vertical left-rail delivery tracker */
.steps.is-timeline { grid-template-columns: 1fr; gap: 0; margin-top: var(--space--lg); }
.steps_item.is-timeline { border-top: none; border-left: 2px solid var(--color--border); margin-left: var(--space--md); padding: 0 0 var(--space--xl) var(--space--lg); position: relative; }
.steps_item.is-timeline:last-child { padding-bottom: 0; }
.steps_item.is-timeline::before { position: absolute; left: 0; top: -0.1em; transform: translateX(-50%); margin-bottom: 0; padding: 0 var(--space--xs); background: var(--color--surface); line-height: 1.1; }


/* ==========================================================================
   Newer house-default roles/atoms (from ds-house-default dist/components.css)
   not present in the original intake.html seed copy: comparison,
   case-study, browser-frame, terminal, metric. Token-driven; keep in sync.
   ========================================================================== */
/* ---------- Comparison (us-vs-them) ---------- */
.comparison { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space--lg); margin-top: var(--space--xl); align-items: start; }
.comparison_col { border: 1px solid var(--color--border); border-radius: var(--radius--lg); padding: var(--space--lg); background: var(--color--surface); }
/* `is-featured`, not `:last-child`, and a real marker element, not
   `.comparison_col:first-child .comparison_list li::before` — Webflow has no
   pseudo-qualified ancestor and no ::before. */
.comparison_col.is-featured { border-color: var(--color--primary); box-shadow: var(--effect--shadow-lg); }
.comparison_label { font-family: var(--type--family-heading); font-size: var(--type--h3); font-weight: 600; letter-spacing: -0.01em; margin-bottom: var(--space--sm); }
.comparison_note { color: var(--color--text-mu); font-size: var(--type--small); margin-bottom: var(--space--md); }
.comparison_list { list-style: none; padding: 0; display: grid; grid-template-columns: 1fr; gap: var(--space--sm); }
.comparison_item { padding-left: 1.75em; position: relative; color: var(--color--text); }
.comparison_mark { position: absolute; left: 0; color: var(--color--text-mu); font-weight: 700; }
.comparison_mark.is-pro { color: var(--color--accent-deep); }
@media (max-width: 767px) { .comparison { grid-template-columns: 1fr; } }
/* ---------- Case-study teaser (before/after) ---------- */
.case-study { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space--lg); align-items: start; margin-top: var(--space--xl); }
.case-study_panel { display: grid; grid-template-columns: 1fr; gap: var(--space--sm); }
.case-study_label { display: inline-flex; align-items: center; gap: var(--space--xs); font-family: var(--type--family-mono); font-size: var(--type--small); text-transform: uppercase; letter-spacing: 0.05em; color: var(--color--text-mu); }
.case-study_media { border-radius: var(--radius--lg); overflow: hidden; border: 1px solid var(--color--border); }
.case-study_panel:first-child .case-study_media { opacity: 0.92; filter: grayscale(0.35); }
.case-study_metric { font-family: var(--type--family-heading); font-weight: 800; font-size: var(--type--h2); letter-spacing: -0.02em; color: var(--color--primary); line-height: 1; }
.case-study_note { color: var(--color--text-mu); font-size: var(--type--small); }
@media (max-width: 767px) { .case-study { grid-template-columns: 1fr; } }
/* ---------- Browser frame ---------- */
.browser-frame { border: 1px solid var(--color--border); border-radius: var(--radius--lg); overflow: hidden; background: var(--color--surface); box-shadow: var(--effect--shadow-lg); }
.browser-frame.is-flush { box-shadow: none; }
.browser-frame_bar { display: flex; align-items: center; gap: var(--space--sm); padding: 0.6rem 0.9rem; background: var(--color--surface-alt); border-bottom: 1px solid var(--color--border); }
.browser-frame_dots { display: flex; gap: 6px; flex: none; }
.browser-frame_dots span { width: 10px; height: 10px; border-radius: 999px; background: var(--color--border); display: block; }
.browser-frame_url { flex: 1; font-family: var(--type--family-mono); font-size: 0.72rem; color: var(--color--text-mu); background: var(--color--surface); border: 1px solid var(--color--border); border-radius: 999px; padding: 0.28rem 0.75rem; text-align: center; max-width: 320px; margin: 0 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.browser-frame_body { padding: var(--space--lg); }
/* ---------- Terminal ---------- */
.terminal { background: var(--color--surface-inverse); color: var(--color--text-inverse); border: 1px solid var(--color--on-inverse-faint); border-radius: var(--radius--lg); overflow: hidden; font-family: var(--type--family-mono); font-size: 0.82rem; line-height: 1.7; box-shadow: var(--effect--shadow-lg); }
.terminal_bar { display: flex; gap: 6px; padding: 0.7rem 0.9rem; border-bottom: 1px solid var(--color--on-inverse-faint); }
.terminal_bar span { width: 11px; height: 11px; border-radius: 999px; background: var(--color--on-inverse-line); display: block; }
.terminal_body { padding: var(--space--lg); color: var(--color--on-inverse-strong); }
/* 0.4 measured at 3.83:1 on --color--surface-inverse — below the 4.5:1 AA
   floor for body text. 0.5 gives 5.27:1 in light theme, 5.09:1 in dark. */
.terminal_dim { color: var(--color--on-inverse-mu); }
.terminal_accent { color: var(--color--accent-on-inverse); }
/* ---------- Metric ---------- */
.metric { display: grid; grid-template-columns: 1fr; gap: var(--space--xs); }
.metric.is-center { justify-items: center; text-align: center; }
.metric_value { font-family: var(--type--family-heading); font-weight: 800; font-size: 2.25rem; letter-spacing: -0.03em; line-height: 1; color: var(--color--primary); }
.metric_label { color: var(--color--text-mu); font-size: var(--type--small); }

/* ============================================================================
   DIRECTION AXIS  —  data-direction="pitch|proof|receipt"
   ----------------------------------------------------------------------------
   A second, independent token axis composing with the theme. `pitch` is the
   default and reproduces today's design exactly, so nothing changes until a
   visitor opts in.

   These three are concepts, not colorways: each names what leads and how the
   hero is organised (see the hero-widget block below), not just a palette.
   Pitch — headline + form lead, the sales case. Proof — a before/after visual
   leads, full width, everything else follows it. Receipt — a stamped,
   itemized ticket leads, centered and narrow, set partly in Kankles. Fonts,
   radii and spacing below are still the floor every direction shares; the
   widget markup in index.html is the actual difference.

   In Webflow this is a second native variable mode collection ("Direction",
   modes Pitch/Proof/Receipt), shaped exactly like the THEME axis above: Pitch
   is the base mode, so its values sit at `:root`; Proof and Receipt publish
   as bare mode classes, `.direction-proof` / `.direction-receipt`, both
   (0,1,0) — same specificity as `.theme-dark`, and the two axes now compose
   as two independent classes on <html> rather than one native mode and one
   hand-written block. `html[data-direction=…]` selectors still exist below,
   but ONLY for the structural/descendant rules a variable mode can't express
   (hero reading order, widget show/hide, per-direction copy) — those stay
   attribute-based custom code (BP-206) and are unaffected by this axis being
   native now. `data-direction` keeps being set alongside the classes purely
   so those rules keep matching.

   --- aliases: tokens set by BOTH axes ---------------------------------------
   --color--surface-alt, --color--border, --color--surface-inverse and
   --color--text-inverse depend on theme AND direction together, so neither
   collection can own them outright — each is declared here as a THEME alias
   (`--color--<name>: var(--direction--<name>-light|dark)`, set at `:root` and
   in `.theme-dark`/the prefers-color-scheme block above) that resolves
   through a pair of DIRECTION variables (`--direction--<name>-light` and
   `--direction--<name>-dark`) which each direction mode supplies below. This
   is what lets the old `html[data-direction="receipt"].theme-dark` compose
   rule go away: receipt + dark now resolves like every other combination,
   through the alias, with no selector that needs to match both an attribute
   and a class at once. No variable is ever declared in both `.theme-dark`
   and a `.direction-*` block — the two write disjoint property names — so
   there is no same-specificity source-order coin flip left to resolve.
   ========================================================================== */

/* --- Pitch (base mode): every direction token's default value, including the
   four aliases' light/dark halves — today's design, reproduced exactly. --- */
:root {
  --type--weight-display: 800;
  --type--tracking-display: -0.036em;
  --type--leading-display: 1.05;
  --radius--control: 4px;
  --radius--sm: 4px;
  --radius--md: 6px;
  --radius--lg: 8px;
  --space--section: 6.5rem;
  --space--stack: 1rem;
  --border--hairline-width: 1px;
  --border--control-width: 2px;
  --type--eyebrow-transform: uppercase;
  --type--eyebrow-tracking: 0.04em;
  --type--eyebrow-family: var(--type--family-mono);
  --direction--hero-align: left;
  /* Display font — see "Kankles" below. First attempt on the hero H1 looked
     like colliding lines and got misdiagnosed as "illegible past one word";
     the real cause was forcing font-weight 700 on a font that only ships
     Regular (synthetic bold thickens strokes without widening advances) on
     top of Kankles' own space glyph, which is ~200 units wide against
     ~950-1150 for a letter — a fifth-width space. Fixed at the source: every
     element below that turns this token on also sets font-weight: 400 and
     word-spacing: 0.3em. Every direction but Receipt just aliases the normal
     heading font, so this costs nothing elsewhere. */
  --type--family-display: var(--type--family-heading);
  /* Alias halves — Pitch's own surface-alt/border/surface-inverse/text-inverse,
     same values light and dark carried today (see the THEME AXIS block
     above, which reads the dark half back through the alias). */
  --direction--surface-alt-light: #f7f7f8;
  --direction--surface-alt-dark: #1f1f23;
  --direction--border-light: #e1e1e4;
  --direction--border-dark: #3b3b42;
  --direction--surface-inverse-light: #16161a;
  --direction--surface-inverse-dark: #1f1f23;
  --direction--text-inverse-light: #ffffff;
  --direction--text-inverse-dark: #ffffff;
}

/* 02 proof — airy and paper-first, but the real difference is structural:
   the hero's before/after visual leads (full width, first in reading order),
   headline and form follow it. See ".hero_widget.is-proof" and the hero-split
   overrides below. */
.direction-proof {
  --type--weight-display: 500;
  --type--tracking-display: -0.018em;
  --type--leading-display: 1.2;
  --radius--control: 999px;
  --radius--sm: 10px;
  --radius--md: 14px;
  --radius--lg: 20px;
  --space--section: 8rem;
  --space--stack: 1.5rem;
  --border--hairline-width: 1px;
  --border--control-width: 1px;
  --type--eyebrow-transform: none;
  --type--eyebrow-tracking: 0.01em;
  --type--eyebrow-family: var(--type--family-sans);
  --direction--hero-align: center;
  /* Ramp flipped to dark ink so a light-direction hero/CTA/footer band can go
     light without its on-inverse text disappearing. */
  --color--on-inverse-strong: rgba(22,22,26,0.92);
  --color--on-inverse-body: rgba(22,22,26,0.78);
  --color--on-inverse-mu: rgba(22,22,26,0.62);
  --color--on-inverse-line: rgba(22,22,26,0.30);
  --color--on-inverse-faint: rgba(22,22,26,0.16);
  --color--on-inverse-wash: rgba(22,22,26,0.08);
  /* Proof doesn't distinguish light/dark theme — same value both halves. */
  --direction--surface-inverse-light: #faf8f5;
  --direction--surface-inverse-dark: #faf8f5;
  --direction--text-inverse-light: #16161a;
  --direction--text-inverse-dark: #16161a;
}

/* 03 receipt — square-edged, mono-heavy rhythm, and structurally the hero
   becomes a centered, narrow ticket: see the hero-split overrides below. The
   hero/CTA/footer bands turn orange (surface-inverse) with dark-ink
   on-inverse text, since the component CSS's white-alpha text was tokenized
   above and this direction can now redefine what those tokens resolve to.
   The hero heading, the ticket's "Verified" stamp, and every big short
   number (stats, prices, the ticket serial) switch to Kankles here — see the
   @font-face and --type--family-display override below. */
.direction-receipt {
  --type--weight-display: 700;
  --type--tracking-display: -0.024em;
  --type--leading-display: 1.15;
  --radius--control: 0px;
  --radius--sm: 0px;
  --radius--md: 0px;
  --radius--lg: 0px;
  --space--section: 5.5rem;
  --space--stack: 0.75rem;
  --border--hairline-width: 2px;
  --border--control-width: 2px;
  --type--eyebrow-tracking: 0.12em;
  --direction--hero-align: left;
  /* Alias halves — was the hand-written receipt+dark compose rule; that
     selector is gone now, its light/dark values just live here instead. */
  --direction--surface-alt-light: #fff4ea;   /* palette primitive: warm paper tint */
  --direction--surface-alt-dark: #241d18;    /* palette primitive: warm ink tint */
  --direction--border-light: #e8d5c2;        /* palette primitive: warm hairline */
  --direction--border-dark: #4a3b2e;         /* palette primitive: warm hairline, dark */
  /* Dark-ink ramp, same values as the proof direction — see comment there. */
  --color--on-inverse-strong: rgba(22,22,26,0.92);
  --color--on-inverse-body: rgba(22,22,26,0.78);
  --color--on-inverse-mu: rgba(22,22,26,0.62);
  --color--on-inverse-line: rgba(22,22,26,0.30);
  --color--on-inverse-faint: rgba(22,22,26,0.16);
  --color--on-inverse-wash: rgba(22,22,26,0.08);
  /* Receipt doesn't distinguish light/dark theme either — same both halves. */
  --direction--surface-inverse-light: #e8480c;
  --direction--surface-inverse-dark: #e8480c;
  --direction--text-inverse-light: #16161a;
  --direction--text-inverse-dark: #16161a;
  /* Kankles is a heavy display face. Render-tested 2026-09-18 at every size
     the page uses: it holds at display size (.heading-2xl), on big numerals
     and on the one-word nav wordmark. It fails at h2/h3 (counters close up,
     every section shouts, the hero stops being the loud thing), and is mush
     on buttons and eyebrows (13-16px). Several glyphs misread at any size —
     P reads "IO", V/v read "U/u", Y and 4 are ambiguous — so copy set in it
     avoids them: hence Receipt's own hero line and the "Owned" stamp. */
  --type--family-display: 'Kankles', var(--type--family-heading);
}

/* Kankles — self-hosted, ships one weight (Regular). Every rule that turns
   it on (below and above) sets font-weight: 400 explicitly rather than
   trusting inheritance: this file's shared component rules default several
   of those elements to 700, and a browser asked for a weight a font doesn't
   have synthesizes it (thickens the strokes without widening the advance
   widths), which is what actually broke the hero heading the first time —
   see --type--family-display above. Registering font-weight: 400 here also
   stops the browser matching this face for an unrelated bold request under
   receipt. Modern browsers only fetch a @font-face file when something on
   the page actually resolves to it, so this costs nothing under Pitch or
   Proof. */
@font-face {
  font-family: 'Kankles';
  src: url('/es/fonts/Kankles.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

/* --- consume the new tokens in the existing components --- */
.section { padding: var(--space--section) 0; }
.heading-2xl, .heading-xl, .heading-lg {
  font-weight: var(--type--weight-display);
  letter-spacing: var(--type--tracking-display);
}
.heading-2xl { line-height: var(--type--leading-display); font-family: var(--type--family-display); }
/* Receipt's heading runs through Kankles — see the --type--family-display
   comment above for why weight/word-spacing/line-height are overridden
   together here rather than left at the shared heading defaults. */
html[data-direction="receipt"] .heading-2xl {
  font-weight: 400;
  word-spacing: 0.3em;
  line-height: 1.25;
}
/* Receipt's section headings (h2s). Kankles on the whole heading failed the
   render test, but leaving them as plain 700 Inter made every section below
   the hero look like a different site (owner, 2026-09-18). Two moves tie them
   back: the Inter goes to 800 and 2.5rem so it can sit beside Kankles' mass,
   and ONE word per heading (.heading-accent, a bare span that does nothing
   under Pitch/Proof) is set in Kankles. Accent words are picked to avoid the
   glyphs Kankles misreads (P, V/v, Y, 4) — check that before adding one. */
html[data-direction="receipt"] .heading-xl {
  font-weight: 800;
  font-size: 2.5rem;
  letter-spacing: -0.04em;
  /* 1.2, not tighter: when a heading wraps, a Kankles ascender on line two
     collides with an Inter descender on line one at 1.1 (seen in render).
     balance stops a wrapped heading leaving one word alone on its last line. */
  line-height: 1.2;
  text-wrap: balance;
}
html[data-direction="receipt"] .heading-accent {
  font-family: var(--type--family-display);
  font-weight: 400;
  word-spacing: 0.3em;
  letter-spacing: 0;
  font-size: 0.92em;
  margin-left: 0.12em;
  margin-right: 0.12em;
}
.eyebrow {
  font-family: var(--type--eyebrow-family);
  text-transform: var(--type--eyebrow-transform);
  letter-spacing: var(--type--eyebrow-tracking);
}
.button { border-radius: var(--radius--control); border-width: var(--border--control-width); }
.title-set { display: grid; grid-template-columns: 1fr; gap: var(--space--stack); }
.hero { padding: var(--space--section) 0; }
.hero_content { gap: var(--space--stack); }
.cta-section { padding: var(--space--section) 0; }

/* Composition differences that tokens can't carry — this is the actual
   "different concept" per direction, not the palette above it. No new page
   sections, but the hero's own grid and reading order genuinely change. */
html[data-direction="proof"] .hero_content { margin-inline: auto; text-align: center; justify-items: center; }
html[data-direction="proof"] .hero_content .text-lg { margin-inline: auto; }
html[data-direction="proof"] .title-set { margin-inline: auto; text-align: center; }
html[data-direction="proof"] .title-set .text-lg { margin-inline: auto; }

/* Proof: the before/after visual leads. Full-width single column (explicit
   1fr, not an implicit auto-fit — see webflow-grids-need-explicit-columns),
   visual first in both source order via `order` and reading order. */
html[data-direction="proof"] .container.is-hero-split { grid-template-columns: 1fr; }
html[data-direction="proof"] .hero_content { order: 2; }
html[data-direction="proof"] .hero_widget.is-proof { order: 1; }

/* Receipt: a centered, narrow ticket — the hero reads top-to-bottom like a
   checkout flow, not a wide two-column split. */
html[data-direction="receipt"] .container.is-hero-split { grid-template-columns: 1fr; justify-items: center; }
/* The heading gets 860px so "Three designs out." holds one line in Kankles
   (measured ~800px at 52px); the paragraph and form keep the 640px ticket
   measure. justify-items centers the narrower children in the wider grid. */
html[data-direction="receipt"] .hero_content { max-width: 860px; text-align: center; justify-items: center; }
html[data-direction="receipt"] .hero_content .text-lg { margin-inline: auto; max-width: 640px; }
html[data-direction="receipt"] .hero-capture { margin-inline: auto; width: 100%; max-width: 640px; }

/* Per-direction copy. Receipt sets its hero/CTA line in Kankles, which can't
   carry the 13-word sentence Pitch and Proof share (five lines, and "Pay" /
   "love" misread — see the receipt token block). Same show/hide pattern as
   .hero_widget; display:none keeps the unused line out of the accessibility
   tree, so there is one h1 text per direction. */
.dir-copy.is-receipt { display: none; }
html[data-direction="receipt"] .dir-copy.is-default { display: none; }
html[data-direction="receipt"] .dir-copy.is-receipt { display: inline; }
html[data-direction="receipt"] .hero_widget.is-receipt { width: 100%; max-width: 420px; }

/* --- the direction control (7e): floating pill stack, right edge --- */
/* A full-width band directly under the nav, sitting on the same surface as the
   hero it introduces, separated by a wash rather than a different hue so it
   reads as part of the band in all three directions. */
.dirswitch {
  position: fixed; right: var(--space--md); top: 50%; transform: translateY(-50%);
  z-index: 40;
}
.dirswitch_inner { display: grid; grid-template-columns: 1fr; gap: var(--space--xs); }
.dirswitch_lead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.dirswitch_group { display: grid; grid-template-columns: 1fr; gap: var(--space--xs); }
.dirswitch_pill {
  display: flex; align-items: center; gap: 0.55rem;
  min-height: 44px; padding: 0.5rem 0.9rem;   /* 44px = touch target floor */
  background: var(--color--surface); color: var(--color--text-mu);
  border: var(--border--hairline-width) solid var(--color--border);
  border-radius: var(--radius--control);
  box-shadow: var(--effect--shadow-sm);
  font: inherit; cursor: pointer;
  /* Colour only — never layout, so switching cannot shift the page. */
  transition: background var(--effect--transition-base), color var(--effect--transition-base), border-color var(--effect--transition-base);
}
.dirswitch_pill:hover { color: var(--color--text); }
.dirswitch_pill[aria-checked="true"] { color: var(--color--text); border-color: var(--color--text); }
.dirswitch_pill:focus-visible {
  outline: none;
  /* Deliberately not --color--primary: under a direction that makes the
     surface orange, an orange ring on orange is invisible. */
  box-shadow: 0 0 0 2px var(--color--surface), 0 0 0 4px var(--color--text);
}
.dirswitch_label { font-family: var(--type--family-mono); font-size: var(--type--small); white-space: nowrap; }
.dirswitch_num { color: var(--color--accent-deep); }
.dirswitch_sep { opacity: 0.5; }
.dirswitch_live { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }

/* The floating stack needs the page gutter to itself. Measured: the pill stack
   is 111px wide plus a 16px margin, and the container is 1180px — so the page
   must be at least 1180 + 2×127 = 1434px before the stack clears the hero
   plate. (At 1400px it overlapped by 1px.) Below that, dock it to the bottom. */
@media (max-width: 1440px) {
  .dirswitch {
    top: auto; bottom: var(--space--md); right: 0; left: 0;
    transform: none;
    display: flex; justify-content: center;   /* don't stretch edge to edge */
  }
  .dirswitch_group {
    grid-auto-flow: column; gap: 0;
    background: var(--color--surface);
    border: var(--border--hairline-width) solid var(--color--border);
    border-radius: var(--radius--control);
    box-shadow: var(--effect--shadow-lg);
    overflow: hidden;
  }
  .dirswitch_pill { border: 0; border-radius: 0; box-shadow: none; }
  .dirswitch_pill[aria-checked="true"] { background: var(--color--surface-alt); }
}

/* --- hero split: content on one side, the direction's own widget on the
   other (Pitch) — or leading/centered, per the overrides above (Proof,
   Receipt). Three widgets share `.hero_widget` for the show/hide toggle and
   shared responsive rules; each has its own variant (`is-pitch`, `is-proof`,
   `is-receipt`) for its actual look. --- */
.hero_widget { display: none; }
html[data-direction="pitch"] .hero_widget[data-widget="pitch"] { display: flex; }
html[data-direction="proof"] .hero_widget[data-widget="proof"] { display: flex; }
html[data-direction="receipt"] .hero_widget[data-widget="receipt"] { display: flex; }

.hero_widget-tag {
  font-family: var(--type--family-mono); font-size: var(--type--small);
  letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--color--accent-on-inverse);
}

/* Pitch — the plate has to read as a panel against whatever band it sits on.
   In proof and receipt the band isn't ink, so a solid ink plate is the strong
   contrast the design wants. In pitch the band IS ink — a solid ink plate is
   invisible — so it lifts off the band instead, using the on-inverse wash
   that already flips per direction. One token, so Webflow can express it as
   a real style. */
:root { --color--plate-surface: var(--color--on-inverse-wash); }
.direction-proof,
.direction-receipt { --color--plate-surface: var(--color--ink-fixed); }

.hero_widget.is-pitch {
  background: var(--color--plate-surface);
  border: var(--border--hairline-width) solid var(--color--on-inverse-line);
  border-radius: var(--radius--md);
  min-height: 340px;
  padding: var(--space--lg);
  flex-direction: column; justify-content: flex-end;
  gap: var(--space--sm);
}
.hero_plate-rule { width: 92px; height: 2px; background: var(--color--primary); }

/* Proof — the before/after visual. Explicit column template (1fr auto 1fr),
   not an implicit grid — see webflow-grids-need-explicit-columns. */
.hero_widget.is-proof { flex-direction: column; gap: var(--space--sm); }
.hero_proof-row { display: grid; grid-template-columns: 1fr auto 1fr; gap: var(--space--sm); align-items: stretch; }
.hero_proof-pane { border-radius: var(--radius--md); padding: var(--space--lg); min-height: 160px; display: flex; align-items: flex-end; }
.hero_proof-pane.is-before { background: var(--color--on-inverse-wash); border: var(--border--hairline-width) dashed var(--color--on-inverse-line); }
.hero_proof-pane.is-after { background: var(--color--plate-surface); border: var(--border--hairline-width) solid var(--color--primary); }
.hero_proof-tag { font-family: var(--type--family-mono); font-size: var(--type--small); text-transform: uppercase; letter-spacing: 0.08em; color: var(--color--text-mu); }
.hero_proof-tag.is-after { color: var(--color--accent-on-inverse); }
.hero_proof-arrow { display: flex; align-items: center; font-size: 1.5rem; color: var(--color--on-inverse-mu); }

/* Receipt — the stamped ticket. Reuses the surface-inverse/text-inverse pair
   the receipt direction already sets above (measured 5.10:1, see the
   accent-on-inverse comment below), so this widget is correctly contrasted
   automatically rather than carrying its own hand-picked colors. */
.hero_widget.is-receipt {
  flex-direction: column; gap: var(--space--md);
  background: var(--color--surface-inverse); color: var(--color--text-inverse);
  border: var(--border--hairline-width) solid var(--color--on-inverse-line);
  border-radius: var(--radius--md);
  padding: var(--space--lg);
}
/* Column, not a row: at Kankles' width + 0.3em word-spacing, "NO. 0001"
   beside the direction label doesn't fit the ticket's 420px on one line and
   wraps mid-number. Stacked, each gets the full width. */
.hero_receipt-head { display: flex; flex-direction: column; align-items: flex-start; gap: var(--space--xs); }
/* .hero_widget-tag is styled --color--primary for the pitch/proof widgets,
   which sit on non-orange backgrounds. Receipt's ticket panel background IS
   primary orange (--color--surface-inverse here), so that same orange text
   would be invisible on it — inherit the ticket's own ink instead. */
.hero_widget-tag.is-receipt { color: inherit; }
.hero_receipt-no { font-family: var(--type--family-mono); font-size: var(--type--small); letter-spacing: 0.08em; }
/* Kankles gets real presence on Receipt: the hero heading above, plus every
   short, big number on the page — stat callouts, prices, the ticket serial.
   Every consumer repeats font-weight: 400 + word-spacing: 0.3em — see the
   --type--family-display comment above for why both are load-bearing, not
   decorative. Prices stay in Kankles by owner decision (2026-09-18), chosen
   from a side-by-side render against Inter and JetBrains Mono, knowing the
   "4" in "$2,450" is one of the ambiguous glyphs. */
html[data-direction="receipt"] .stats-set_number,
html[data-direction="receipt"] .pricing_price {
  font-family: var(--type--family-display);
  font-weight: 400;
  word-spacing: 0.3em;
  line-height: 1.3;
}
/* A price that is words, not digits ("Let's talk"): at display size in
   Kankles it wraps to two lines and pushes its card out of row with the
   other two. Same face, h2 size, so the three cards stay aligned. */
html[data-direction="receipt"] .pricing_price.is-text {
  font-size: var(--type--h2);
  line-height: calc(var(--type--display) * 1.3);
}
html[data-direction="receipt"] .hero_receipt-no {
  font-family: var(--type--family-display);
  font-weight: 400;
  word-spacing: 0.3em;
  font-size: 1.15rem;
  letter-spacing: 0.02em;
}
.hero_receipt-items { list-style: none; padding: 0; display: grid; grid-template-columns: 1fr; gap: var(--space--sm); border-top: var(--border--hairline-width) dashed var(--color--on-inverse-line); padding-top: var(--space--md); }
.hero_receipt-item { display: flex; justify-content: space-between; gap: var(--space--sm); font-family: var(--type--family-mono); font-size: var(--type--small); }
/* Same -7deg a stamped seal turns at (casabe-conformance-kickoff.md) — this
   widget is where that mark's language belongs until the real seal exists. */
.hero_receipt-stamp {
  align-self: flex-end;
  font-family: var(--type--family-display);
  font-weight: 400;
  word-spacing: 0.3em;
  font-size: 1.75rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  transform: rotate(-7deg);
  opacity: 0.9;
}

@media (max-width: 900px) {
  .container.is-hero-split { grid-template-columns: 1fr; gap: var(--space--lg); }
  .hero_widget { min-height: 200px; }
}
@media (prefers-reduced-motion: reduce) {
  .dirswitch_pill { transition: none; }
}

/* --- accent-on-inverse -------------------------------------------------------
   Anything using --color--primary as a FOREGROUND on an inverse band vanishes
   when that band is itself orange (receipt). Route those through their own
   token so a direction can move them without touching the accent everywhere
   else. Measured: #16161a on #e8480c is 4.61:1; white on the same is 3.92:1,
   which is why receipt inverts to ink rather than lightening.
   -------------------------------------------------------------------------- */
:root { --color--accent-on-inverse: var(--color--primary); }
/* Proof's inverse bands are light paper in both themes, so orange text on
   them would fail the kit's rule (small text is never orange on light). */
.direction-proof   { --color--accent-on-inverse: #16161a; }
.direction-receipt { --color--accent-on-inverse: #16161a; }

.eyebrow.is-on-inverse,
.eyebrow.is-on-inverse-tight { color: var(--color--accent-on-inverse); }

/* A solid orange fill is invisible on an orange band — swap receipt's primary
   buttons to an ink fill inside the inverse bands only. */
html[data-direction="receipt"] .hero .button.is-primary,
html[data-direction="receipt"] .cta-section .button.is-primary {
  background: var(--color--ink-fixed);
  color: #ffffff;
}
html[data-direction="receipt"] .hero .button.is-primary:hover,
html[data-direction="receipt"] .cta-section .button.is-primary:hover {
  background: #2d2d33;
}


/* --- responsive repairs (measured at 375px: 86px of horizontal scroll) ------
   1. The column ratio now lives on `.container.is-hero-split`, so the existing
      single-column rules in the 900px and 620px queries apply on a phone
      without a specificity fight. (It was `.hero .hero-split`, which
      outranked them and left the plate hanging 85px past the viewport.)
   2. The plate is decorative; below 900px it becomes a short band rather than
      a tall panel, so it doesn't push the form off the first screen.
   3. The docked switcher is fixed to the bottom and was sitting on top of the
      hero form. Reserve its height at the foot of the page.
   -------------------------------------------------------------------------- */
@media (max-width: 900px) {
  /* No `order: -1` on Pitch — hoisting the widget above the copy handed the
     entire first screen to a decorative panel and pushed the headline below
     the fold. Proof's own order:1/2 above still applies; this just caps
     height so the widget doesn't run long on a narrow phone. */
  .hero_widget { min-height: 110px; }
  .hero_widget.is-pitch { min-height: 110px; }
}
/* Matches the switcher's dock breakpoint so the reserved space appears exactly
   when the bar does. 44px pill + padding + margin. */
@media (max-width: 1440px) {
  .page { padding-bottom: 5.5rem; }
}

/* Nothing may exceed the viewport width — the plate proved this needs saying. */
.hero_widget { max-width: 100%; }

/* --- inline-style hoist: index.html blockers, resolved as named classes ---
   Each of these previously carried its declarations as a raw style="" attr.
   Webflow gives every inline-styled element its own untracked one-off style,
   so none of the site-wide fixes (shorthand expansion, token binding) ever
   reached them. See webflow-inline-styles-must-be-classes memory. */


/* The hero capture form and its parts — one-off, so block_element naming
   rather than combos. */
.hero-capture { display: grid; grid-template-columns: 1fr; gap: var(--space--sm); max-width: 560px; margin-top: var(--space--sm); }
.hero-capture_row { display: flex; gap: var(--space--sm); flex-wrap: wrap; }
.hero-capture_tos { display: flex; gap: var(--space--sm); align-items: flex-start; font-size: var(--type--small); color: var(--color--on-inverse-body); }
.hero-capture_tos-link { color: var(--color--accent-on-inverse); }
.hero-capture_input { height: auto; margin-bottom: 0; padding: 0.875rem 1rem; border: 1px solid var(--color--border); border-radius: var(--radius--sm); font: inherit; background: var(--color--surface); color: var(--color--text); }
.hero-capture_input.is-url { flex: 1; min-width: 220px; }
.hero-capture_checkbox { margin-top: 0.2em; }
/* Card eyebrows on the three-directions strip. */
/* accent-deep, not primary: ink on light, orange on dark (kit rule: small text is never orange on light). */
.eyebrow.is-primary { color: var(--color--accent-deep); }
/* The minimal hero is a LIGHT band in light theme, so its eyebrow can't use the orange on-inverse tone. */
.hero.is-minimal .eyebrow.is-on-inverse-tight { color: var(--color--accent-deep); }

.text-sm.is-on-inverse-mu { color: var(--color--on-inverse-mu); max-width: none; }
/* "Trusted by local businesses" lead-in. */
.text-sm.is-centered { text-align: center; max-width: none; margin-bottom: var(--space--md); }

/* Same background as .is-alt, tighter section rhythm — the logo-cloud band
   only, so a distinct modifier rather than overloading .is-alt everywhere
   else it's used. */
.section.is-alt-tight { background: var(--color--surface-alt); padding-top: var(--space--xl); padding-bottom: var(--space--xl); }

/* Every one of the 7 pages using .text-lg.is-on-inverse-strong wants it
   centered — checked directly, no exceptions — so this is folded into the
   shared combo rather than kept as a per-page inline override. */
.text-lg.is-on-inverse-strong { margin: 0 auto; }

/* Column sub-headings in the footer ("Product", "Company") — smaller than
   the brand heading, which stays plain .footer_heading. */
.footer_heading.is-column { font-size: var(--type--body); }

/* --- hero process panels (BP-195) ---------------------------------------------
   Pitch and Proof's hero widgets draw the PROCESS, not a client's result:
   Pitch = one URL in, three structurally different designs out; Proof = the
   same five pieces of content, a dated layout before and the redesign after.
   Schematic blocks only (classed <i> elements, aria-hidden). The mini pages
   are literal white pages whatever the band or theme, so they carry fixed
   values rather than the neutrals, which flip in dark mode. The build plays
   once on load; prefers-reduced-motion shows the finished frame.
   -------------------------------------------------------------------------- */
/* Colors: paper and ink come from the fixed (theme-proof) tokens, including
   the five schematic grays below (--color--schematic-*-fixed, declared with
   the on-inverse ramp) — the neutral ramp flips in dark mode, so it can't
   stand in for these literal mini-page tones. */
.hero_mini-bar, .hero_mini-line, .hero_mini-media, .hero_mini-card,
.hero_page-logo, .hero_page-banner, .hero_page-title, .hero_page-text, .hero_page-button {
  display: block; border-radius: 2px; background: var(--color--schematic-fixed);
}

/* Pitch: URL chip -> stem -> three pages */
.hero_flow { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 0; }
.hero_flow-url {
  font-family: var(--type--family-mono); font-size: var(--type--small);
  color: var(--color--ink-fixed); background: var(--color--paper);
  border-radius: 999px; padding: 0.4rem 1rem; box-shadow: 0 0 0 3px var(--color--primary);
}
.hero_flow-typed { display: inline-block; white-space: nowrap; overflow: hidden; vertical-align: bottom; }
.hero_flow-stem { width: 2px; height: 28px; background: var(--color--on-inverse-line); }
.hero_flow-sites {
  width: 100%; display: grid; grid-template-columns: 1fr 1fr 1fr; gap: var(--space--sm);
  border-top: 2px solid var(--color--on-inverse-line); padding-top: 18px; position: relative;
}
.hero_mini {
  background: var(--color--paper); border-radius: var(--radius--sm); aspect-ratio: 3 / 4;
  padding: 10% 9%; display: flex; flex-direction: column; gap: 6%;
}
.hero_mini.is-split { flex-direction: row; gap: 8%; }
/* A bar is a line of copy; its variant folds color and width into one combo
   (design.md rule 8). `hero_mini-line` is the same bar in the split page's
   text column, which runs a touch taller. */
.hero_mini-bar { height: 6%; }
.hero_mini-bar.is-ink-70 { background: var(--color--ink-fixed); width: 70%; }
.hero_mini-bar.is-ink-45 { background: var(--color--ink-fixed); width: 45%; }
.hero_mini-bar.is-accent-35 { background: var(--color--primary); width: 35%; }
.hero_mini-bar.is-ink-60 { background: var(--color--ink-fixed); width: 60%; align-self: center; }
.hero_mini-bar.is-accent-30 { background: var(--color--primary); width: 30%; align-self: center; }
.hero_mini-media { flex: 1; }
.hero_mini-media.is-split { flex: 0 0 42%; }
.hero_mini-column { flex: 1; display: flex; flex-direction: column; justify-content: center; gap: 8%; }
.hero_mini-line { height: 7%; }
.hero_mini-line.is-ink-90 { background: var(--color--ink-fixed); width: 90%; }
.hero_mini-line.is-ink-60 { background: var(--color--ink-fixed); width: 60%; }
.hero_mini-line.is-gray-80 { width: 80%; }
.hero_mini-line.is-accent-50 { background: var(--color--primary); width: 50%; }
.hero_mini-cards { flex: 1; display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 6%; align-items: end; }
.hero_mini-card { height: 70%; }

/* Proof: same five pieces, two layouts. The base classes draw the Before
   page; `is-after` re-composes the same pieces. */
.hero_proof-pane { flex-direction: column; align-items: stretch; justify-content: space-between; gap: var(--space--sm); }
.hero_page { flex: 1; display: grid; grid-template-columns: 1fr; gap: 7px; border-radius: var(--radius--sm); padding: 12px; }
.hero_page-logo, .hero_page-title, .hero_page-text { height: 7px; }
.hero_page-banner { min-height: 30px; }
/* Before: everything centred, grey, cramped — a template from a decade ago */
.hero_page.is-before { background: var(--color--paper); justify-items: center; align-content: start; opacity: 0.85; }
.hero_page-logo { width: 22%; height: 10px; }
.hero_page-banner { width: 100%; background: var(--color--schematic-mid-fixed); }
.hero_page-title { width: 90%; }
.hero_page-text { width: 80%; }
.hero_page-button { width: 18%; height: 9px; background: var(--color--schematic-dark-fixed); }
/* After: same pieces, re-composed — logo top-left, the lines become the
   headline, the banner becomes the image, the button becomes the CTA */
.hero_page.is-after {
  grid-template-columns: 1.1fr 1fr; grid-template-rows: auto 1fr auto auto;
  grid-template-areas: "logo ." "h1 media" "h2 media" "btn media";
  column-gap: 12px; align-content: stretch; padding: 4px 0 0;
}
.hero_page-logo.is-after { grid-area: logo; width: 22%; height: 7px; background: var(--color--schematic-on-dark-strong-fixed); }
.hero_page-title.is-after { grid-area: h1; align-self: end; height: 12px; width: 100%; background: var(--color--paper); }
.hero_page-text.is-after { grid-area: h2; height: 12px; width: 70%; background: var(--color--paper); }
.hero_page-button.is-after { grid-area: btn; width: 45%; height: 12px; margin-top: 4px; background: var(--color--primary); }
.hero_page-banner.is-after { grid-area: media; height: 100%; background: var(--color--schematic-on-dark-faint-fixed); border-radius: var(--radius--sm); }

/* Motion: plays once, ends on the finished frame. Set on each moving piece
   directly rather than scoped under the widget — these pieces only exist
   inside the Pitch and Proof widgets. */
/* Typing reveals the text with clip-path, not width: `width: 0` -> the
   element's natural width animates to `auto`, which browsers can't
   interpolate, so it jumped from empty to full at the halfway point
   (measured: 0px until ~760ms, then 117px, no steps between). A clip-path
   inset interpolates, and with steps(15) over the 15 monospace characters of
   "yourwebsite.com" each step uncovers exactly one character. */
@keyframes hero-type { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 0 0 0); } }
@keyframes hero-rise { from { opacity: 0; transform: translateY(10px); } }
@keyframes hero-fade { from { opacity: 0; } }
.hero_flow-typed { animation: hero-type 0.9s steps(15, end) 0.3s both; }
.hero_flow-stem, .hero_flow-sites { animation: hero-fade 0.3s ease-out 1.3s both; }
.hero_mini { animation: hero-rise 0.5s cubic-bezier(0.22,0.61,0.36,1) both; }
.hero_mini.is-stack { animation-delay: 1.5s; }
.hero_mini.is-split { animation-delay: 1.65s; }
.hero_mini.is-cards { animation-delay: 1.8s; }
.hero_page-logo.is-after, .hero_page-banner.is-after, .hero_page-title.is-after,
.hero_page-text.is-after, .hero_page-button.is-after { animation: hero-rise 0.45s cubic-bezier(0.22,0.61,0.36,1) both; }
.hero_page-logo.is-after   { animation-delay: 0.6s; }
.hero_page-banner.is-after { animation-delay: 0.8s; }
.hero_page-title.is-after  { animation-delay: 1.0s; }
.hero_page-text.is-after   { animation-delay: 1.1s; }
.hero_page-button.is-after { animation-delay: 1.3s; }
@media (prefers-reduced-motion: reduce) {
  .hero_flow-typed, .hero_flow-stem, .hero_flow-sites, .hero_mini,
  .hero_page-logo.is-after, .hero_page-banner.is-after, .hero_page-title.is-after,
  .hero_page-text.is-after, .hero_page-button.is-after { animation: none !important; }
}
@media (max-width: 620px) {
  .hero_page { gap: 5px; padding: 8px; }
  .hero_page.is-after { padding: 2px 0 0; }
}

/* Phone width (<=480px): the long email placeholder must fit the field, and the
   docked direction switcher (fixed to the bottom) must not sit on top of the
   fine print under the form — so the hero gets room below its content. */
@media (max-width: 480px) {
  .hero-capture_input { padding-inline: 0.75rem; font-size: 0.8125rem; }
  .hero { padding-bottom: calc(var(--space--xl) + 4rem); }
}
