/* =============================================================
   Core component library
   All styles read from tokens.css. No literal color values here
   except where explicitly brand (gradients declared in tokens).
   Components read --product-* / --section-* / surface tokens.
   Contract: see README.md "Minimum Token Contract".
   ============================================================= */

/* ---------- Reset ---------- */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { scroll-behavior: smooth; }
body {
  font-family: var(--font-body);
  color: var(--fg-body);
  line-height: var(--lh-relaxed);
  background: var(--bg-canvas);
  transition: background var(--dur-slow) var(--ease-standard),
              color var(--dur-slow) var(--ease-standard);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
a { color: inherit; text-decoration: none; }
img, svg { max-width: 100%; height: auto; display: block; }
button { font-family: inherit; }

/* ---------- Selection & focus ---------- */
::selection { background: var(--product-tint); color: var(--fg-primary); }
:focus-visible { outline: none; box-shadow: var(--focus-ring); border-radius: var(--r-sm); }

/* ---------- Layout ---------- */
.container {
  max-width: var(--container-max);
  margin: 0 auto;
  padding: 0 var(--container-pad);
}
.section { padding: var(--section-y) 0; }
.section-alt {
  background: var(--aura-alt), var(--bg-surface-2);
}
.row { display: flex; gap: var(--sp-4); flex-wrap: wrap; align-items: center; }

/* ---------- Typography ---------- */
h1, h2, h3, h4 { font-family: var(--font-display); color: var(--fg-primary); }
h1 {
  font-size: var(--fs-48);
  font-weight: var(--fw-bold);
  line-height: var(--lh-tight);
  letter-spacing: var(--tracking-tight);
}
h2 {
  font-size: var(--fs-32);
  font-weight: var(--fw-bold);
  line-height: var(--lh-snug);
  letter-spacing: var(--tracking-snug);
}
h3 {
  font-size: var(--fs-20);
  font-weight: var(--fw-semibold);
  line-height: 1.35;
}
h4 {
  font-size: var(--fs-16);
  font-weight: var(--fw-semibold);
  line-height: 1.35;
}
.display {
  font-family: var(--font-display);
  font-size: clamp(var(--fs-32), 6vw, var(--fs-56));
  font-weight: var(--fw-bold);
  line-height: var(--lh-tight);
  letter-spacing: var(--tracking-tight);
  color: var(--fg-primary);
  text-wrap: balance;
}
/* Pricing card uses a smaller display variant so "Free for 90 days"
   fits cleanly regardless of viewport. Caps at ~28px even on wide
   screens so the card reads as a single clean statement, not a billboard. */
.card .display,
.pricing-card .display {
  font-size: clamp(var(--fs-22), 4.5vw, var(--fs-28));
  line-height: 1.15;
  text-wrap: balance;
}
.subhead {
  font-size: var(--fs-20);
  color: var(--fg-muted);
  line-height: var(--lh-normal);
}
.body { font-size: var(--fs-16); color: var(--fg-body); line-height: var(--lh-relaxed); }
.small { font-size: var(--fs-14); color: var(--fg-muted); }
.fine { font-size: var(--fs-12); color: var(--fg-subtle); }
.mono { font-family: var(--font-mono); font-size: var(--fs-14); }

.label {
  font-size: var(--fs-13);
  font-weight: var(--fw-semibold);
  text-transform: uppercase;
  letter-spacing: var(--tracking-wide);
  background: var(--product-grad-label);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
  display: inline-block;
}

/* Warm amber variant — used on the mothership for a softer,
   less brand-loaded eyebrow (no pink/purple). */
.label.label-warm {
  background: var(--grad-label-warm);
  -webkit-background-clip: text;
          background-clip: text;
  -webkit-text-fill-color: transparent;
          color: transparent;
}

/* Solid variant. Use when the gradient label competes with a
   nearby gradient (hero headline, CTA button) and a calmer
   eyebrow reads better. Picks up --product-accent so it still
   themes per product. */
.label.label-solid {
  background: none;
  -webkit-background-clip: initial;
          background-clip: initial;
  -webkit-text-fill-color: initial;
  color: var(--section-accent);
}

/* Section rhythm: alternating sections flip the label accent
   to the secondary stop from the product gradient. Scoped to
   --section-accent only (does not affect --product-accent). */
.section-alt {
  --section-accent: var(--section-accent-b);
  --section-tint: var(--section-tint-b);
  --section-border: var(--section-border-b);
}

/* ---------- Gradient text ----------
   Fills the text with the product gradient. For hero-scale
   headlines that want the wordmark feel, use .text-neon below
   instead (adds a soft glow). */
.text-gradient {
  /* Reads --product-grad-label (not --product-grad) so headline and button
     sweeps can differ. Falls back to --product-grad via tokens.css default. */
  background: var(--product-grad-label);
  -webkit-background-clip: text;
          background-clip: text;
  -webkit-text-fill-color: transparent;
          color: transparent;
}

/* Deprecated alias — kept so existing consumers don't break
   mid-migration. Prefer .text-gradient. Remove once consumer
   migrations complete. */
.gradient-text {
  background: var(--product-grad);
  -webkit-background-clip: text;
          background-clip: text;
  -webkit-text-fill-color: transparent;
          color: transparent;
}

/* ---------- Neon text ----------
   Gradient fill + product-glow drop-shadow. Combine with
   display-weight type (h1, .display) — the glow reads flat on
   body copy. Use .text-gradient when you don't want the glow. */
.text-neon {
  background: var(--product-grad);
  -webkit-background-clip: text;
          background-clip: text;
  -webkit-text-fill-color: transparent;
          color: transparent;
  filter: drop-shadow(0 4px 20px var(--product-glow));
}

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  padding: 14px var(--sp-8);
  border-radius: var(--r-sm);
  font-size: var(--fs-16);
  font-weight: var(--fw-semibold);
  font-family: inherit;
  border: none;
  cursor: pointer;
  transition: transform var(--dur-base) var(--ease-standard),
              box-shadow var(--dur-base) var(--ease-standard),
              background var(--dur-base) var(--ease-standard),
              border-color var(--dur-base) var(--ease-standard),
              color var(--dur-base) var(--ease-standard);
  text-decoration: none;
  line-height: 1;
  white-space: nowrap;
}
.btn:disabled, .btn[aria-disabled="true"] {
  opacity: 0.5;
  cursor: not-allowed;
  pointer-events: none;
}

.btn-primary {
  background: var(--section-grad, var(--product-grad));
  color: var(--fg-on-brand);
}
.btn-primary:hover {
  transform: translateY(-1px);
  box-shadow: var(--shadow-glow);
}

.btn-outline {
  background: color-mix(in oklab, var(--product-end) 8%, transparent);
  color: var(--product-accent);
  border: 2px solid color-mix(in oklab, var(--product-accent) 40%, transparent);
}
.btn-outline:hover {
  background: color-mix(in oklab, var(--product-end) 20%, transparent);
  color: var(--fg-primary);
  border-color: var(--product-accent);
}
[data-theme="light"] .btn-outline { color: var(--product-end); }
[data-theme="light"] .btn-outline:hover { color: var(--fg-on-brand); background: var(--product-grad); border-color: transparent; }

.btn-ghost {
  background: transparent;
  color: var(--fg-body);
  border: 1px solid var(--border-default);
}
.btn-ghost:hover { background: var(--tint-06); border-color: var(--border-strong); color: var(--fg-primary); }

.btn-sm { padding: 8px var(--sp-4); font-size: var(--fs-14); }
.btn-lg { padding: var(--sp-4) var(--sp-10); font-size: var(--fs-18); }
.btn-block { display: flex; width: 100%; }

/* ---------- Nav ---------- */
nav.nav {
  position: sticky;
  top: 0;
  z-index: var(--z-sticky);
  background: var(--bg-surface-glass);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-bottom: 1px solid transparent;
  padding: var(--sp-6) 0;
  transition: border-color var(--dur-slow);
}
nav.nav.scrolled { border-bottom-color: var(--bg-nav-border); }
nav.nav > .container { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-6); }
.nav-logo { display: flex; align-items: center; gap: var(--sp-3); font-size: var(--fs-22); font-weight: var(--fw-bold); }
.nav-logo img { height: 36px; width: auto; }
.nav-links { display: flex; gap: var(--sp-8); align-items: center; }
/* Underline-tab style — a 2px product-gradient underline slides in on hover
   and stays on the link that matches the current scroll section.
   Add .active to any <a> (typically via JS scroll-spy) to show the
   resting-state underline. Add to any anchor the site nav uses. */
.nav-links a {
  position: relative;
  font-size: var(--fs-16);
  color: var(--fg-muted);
  padding: var(--sp-2) 0;
  transition: color var(--dur-base);
}
.nav-links a::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: -2px;
  height: 2px;
  background: var(--product-grad);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--dur-base) var(--ease-out);
  border-radius: 2px;
}
.nav-links a:hover { color: var(--fg-primary); }
.nav-links a:hover::after,
.nav-links a.active::after { transform: scaleX(1); }
.nav-links a.active { color: var(--fg-primary); }
/* The CTA button in the nav keeps its own style — no underline. */
.nav-links a.btn { color: var(--fg-on-brand); padding: 14px var(--sp-8); }
.nav-links a.btn::after { content: none; }

.nav-logo .nav-icon { width: 36px; height: 36px; flex-shrink: 0; display: block; margin-bottom: -4px; }
.nav-logo .nav-wordmark { height: 36px; width: auto; }
.nav-logo .nav-home-logo { height: 56px; width: auto; display: block; }
.nav-logo .nav-name {
  font-family: var(--font-brand);
  color: var(--fg-primary);
  line-height: var(--lh-tight);
  transform: translateY(-1px);
}
.nav-logo .nav-subtitle {
  font-size: var(--fs-13);
  font-weight: var(--fw-regular);
  color: var(--fg-quiet);
  transition: color var(--dur-fast);
}
.nav-logo a.nav-subtitle:hover { color: var(--product-accent); }

.nav-brand-link { display: flex; align-items: center; align-self: center; }
.nav-links .nav-brand-icon {
  height: 44px;
  width: auto;
  opacity: 0.6;
  transition: opacity var(--dur-fast);
}
.nav-links .nav-brand-icon:hover { opacity: 1; }

@media (max-width: 768px) {
  .nav-links a:not(.btn),
  .nav-links .menu-dropdown,
  .nav-links .nav-brand-link { display: none; }
  nav.nav:not(:has(.nav-links .btn)) .nav-links { display: none; }
  nav.nav:not(:has(.nav-links .btn)) > .container { justify-content: center; }
}

/* ---------- Cards ---------- */
.card {
  background: var(--bg-surface-3);
  border: 1px solid var(--border-default);
  border-radius: var(--r-lg);
  padding: var(--sp-8);
  transition: transform var(--dur-base) var(--ease-standard),
              box-shadow var(--dur-base) var(--ease-standard),
              border-color var(--dur-base) var(--ease-standard);
  position: relative;
}
.card:hover { border-color: var(--border-strong); }
.card.interactive:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); }

/* ---------- Card icon ----------
   Stacked or inline icon for any card variant. Use with Lucide SVGs
   (stroke="currentColor") so the icon picks up --product-accent. */
.card-icon {
  font-size: var(--fs-28);
  margin-bottom: var(--sp-3);
  color: var(--section-accent);
}
.card-icon svg {
  width: 28px;
  height: 28px;
}
.card-showcase .card-icon,
.card-product .card-icon {
  width: 44px;
  height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: inherit;
}
.card-showcase .card-icon img,
.card-showcase .card-icon svg,
.card-product .card-icon img,
.card-product .card-icon svg { width: 100%; height: 100%; object-fit: contain; }
.card-icon-inline {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  margin-bottom: var(--sp-2);
}
.card-icon-inline svg {
  width: 28px;
  height: 28px;
  color: var(--section-accent);
  flex-shrink: 0;
}
.card-icon-inline h3 {
  font-size: var(--fs-20);
  margin: 0;
}
.card-icon-inline .card-showcase-name,
.card-icon-inline .card-product-name {
  margin: 0;
}

/* Inline icon sized to sit next to heading text. Tints from
   `--section-accent` so it picks up per-section accent. */
.h2-icon {
  display: inline-block;
  width: 0.85em;
  height: 0.85em;
  vertical-align: -0.05em;
  margin-right: 0.35em;
  color: var(--section-accent, currentColor);
}

/* ---------- Icon chip ----------
   Small circular tinted background for an icon, themed per-section
   via `--section-accent`. Use in accordion summaries, side-card
   headers, list rows, anywhere the "icon-in-a-pill" treatment fits. */
.icon-chip {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: color-mix(in oklab, var(--section-accent) 18%, transparent);
  color: var(--section-accent);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.icon-chip svg {
  width: 20px;
  height: 20px;
}

/* ---------- Audience strip ----------
   Horizontal row of "who this is for" chips. Barebones by design:
   no surface, no border, no padding, no hover. The icon picks up
   `--section-accent` so consumers tint per-segment by setting
   --section-accent on a per-chip modifier class (e.g.
   `.audience-startups { --section-accent: <color>; }`).

   For the accent to apply, inline SVGs must use `fill="currentColor"`
   or `stroke="currentColor"`. Hardcoded fills won't pick up the token.

   Per-segment modifier classes are consumer-owned (e.g. .audience-barbers,
   .audience-startups). The DS ships only the base pattern. */
.audience-strip {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2) var(--sp-3);
  margin: var(--sp-5) 0;
}
.audience-strip-label {
  flex-basis: 100%;
  font-size: var(--fs-12);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  opacity: 0.55;
}
.audience-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  font-size: var(--fs-14);
  opacity: 0.9;
}
.audience-chip svg {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  color: var(--section-accent, currentColor);
}

.card-glass {
  background: var(--tint-03);
  border: 1px solid var(--border-default);
  border-radius: var(--r-md);
  padding: var(--sp-8) var(--sp-6);
}

/* Shared spacing for direct-child headings inside any card — so a
   <h3> followed by <p> breathes without every consumer hand-rolling
   margin. Uses :where() for zero specificity so component-specific
   rules (e.g. .card-product h3) always win. */
.card > :where(h1, h2, h3, h4, h5, h6),
.card-glass > :where(h1, h2, h3, h4, h5, h6),
.card-showcase > :where(h1, h2, h3, h4, h5, h6),
.card-product > :where(h1, h2, h3, h4, h5, h6) {
  margin-bottom: var(--sp-3);
}
.card > :where(p + h1, p + h2, p + h3, p + h4, p + h5, p + h6),
.card-glass > :where(p + h1, p + h2, p + h3, p + h4, p + h5, p + h6) {
  margin-top: var(--sp-4);
}

/* .card-showcase (.card-product is a deprecated alias) — modifier on .card. */
.card-showcase,
.card-product {
  padding: var(--sp-10) var(--sp-8);
  background: linear-gradient(160deg,
    color-mix(in oklab, var(--product-start) 12%, transparent) 0%,
    color-mix(in oklab, var(--product-mid) 8%, transparent) 40%,
    var(--bg-surface-3) 100%);
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}
/* Conic gradient border sweep (brand signature effect) */
.card-sweep {
  position: relative;
  transition: transform var(--dur-base) var(--ease-out),
              box-shadow var(--dur-base) var(--ease-out),
              border-color var(--dur-base) var(--ease-out);
}
.card-sweep:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-lg);
  border-color: var(--border-strong);
}
.card-sweep::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 1px;
  background: conic-gradient(from 140deg,
    transparent 0%,
    color-mix(in oklab, var(--product-mid) 55%, transparent) 15%,
    color-mix(in oklab, var(--product-start) 55%, transparent) 25%,
    transparent 45%);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  opacity: 0;
  transition: opacity var(--dur-slow) var(--ease-standard);
  pointer-events: none;
}
.card-sweep:hover::before { opacity: 1; }

/* Card-product internal typography. The icon slot, product name
   (gradient fill via --product-grad-label), tagline, and desc
   all reskin under [data-product="…"] automatically.

   Usage:
     <article class="card-product" data-product="...">
       <div class="card-product-icon"><img src="…" alt=""></div>
       <h3 class="card-product-name">Product name</h3>
       <p class="card-product-tagline">One-line tagline</p>
       <p class="card-product-desc">One line of description, wrapping.</p>
     </article> */
.card-showcase-name,
.card-product-name {
  font-family: var(--font-display);
  font-size: var(--fs-28);
  font-weight: var(--fw-bold);
  line-height: var(--lh-tight);
  margin-bottom: var(--sp-1);
  color: var(--fg-primary);
}
.card-showcase-tagline,
.card-product-tagline {
  font-size: var(--fs-16);
  font-weight: var(--fw-semibold);
  color: var(--fg-muted);
  margin-bottom: var(--sp-4);
}
.card-showcase-desc,
.card-product-desc {
  font-size: var(--fs-15);
  color: var(--fg-muted);
  line-height: var(--lh-relaxed);
  flex-grow: 1;
  margin-bottom: var(--sp-6);
}

/* ---------- Cards grid ----------
   Generic 2-up, 3-up, and 4-up card grids. Container for any row of
   cards (card-product, card, card-glass, problem-card, category-card).
   2-up and 3-up collapse to 1 column under 768px. 4-up steps down to
   2 columns under 880px and 1 column under 560px.

   2-up and 3-up cap at 960px so a small number of wide cards don't
   stretch into billboards inside a 1120px container. 4-up has no cap:
   per-card width is already narrow at 4 columns, and the cap left
   visible gutters in wider section containers. Consumers that want a
   narrower 4-up can wrap it or set max-width locally. */
/* Width tokens are exposed so consumers (sibling sections, sub-grids) can
   align to the same row width without hardcoding. */
:root {
  --cards-grid-2-max: 960px;
  --cards-grid-3-max: 960px;
  --cards-grid-4-max: none;
}
.cards-grid-2,
.cards-grid-3,
.cards-grid-4 {
  display: grid;
  margin-top: var(--sp-10);
  margin-left: auto;
  margin-right: auto;
}
.cards-grid-2 { max-width: var(--cards-grid-2-max); grid-template-columns: 1fr 1fr; gap: var(--sp-8); }
.cards-grid-3 { max-width: var(--cards-grid-3-max); grid-template-columns: repeat(3, 1fr); gap: var(--sp-6); }
.cards-grid-4 { max-width: var(--cards-grid-4-max); grid-template-columns: repeat(4, 1fr); gap: var(--sp-5); }
@media (max-width: 880px) {
  .cards-grid-4 { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 768px) {
  .cards-grid-2,
  .cards-grid-3 { grid-template-columns: 1fr; }
}
@media (max-width: 560px) {
  .cards-grid-4 { grid-template-columns: 1fr; }
}

/* ---------- Badges / Pills ---------- */
.badge {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  padding: 6px var(--sp-4);
  background: var(--section-tint);
  color: var(--section-accent);
  border: 1px solid var(--section-border);
  border-radius: var(--r-xl);
  font-size: var(--fs-13);
  font-weight: var(--fw-semibold);
  letter-spacing: 0.02em;
}

.badge-uppercase {
  text-transform: uppercase;
  letter-spacing: var(--tracking-wide);
  font-size: var(--fs-12);
  padding: 6px var(--sp-5);
  font-weight: var(--fw-bold);
}

.pill {
  display: inline-block;
  padding: 2px var(--sp-2);
  /* Reads --section-* (not --product-*) so pills track per-section rhythm. */
  background: var(--section-tint);
  color: var(--section-accent);
  border-radius: var(--r-xl);
  font-size: var(--fs-12);
  font-weight: var(--fw-semibold);
  text-transform: uppercase;
  letter-spacing: 0.03em;
  vertical-align: middle;
  margin-bottom: var(--sp-1);
}
[data-theme="light"] .pill { color: var(--product-end); }

.pill-status-success { background: var(--semantic-success-bg); color: var(--semantic-success-fg); border: 1px solid var(--semantic-success-border); }
.pill-status-warning { background: var(--semantic-warning-bg); color: var(--semantic-warning-fg); border: 1px solid var(--semantic-warning-border); }
.pill-status-danger  { background: var(--semantic-danger-bg);  color: var(--semantic-danger-fg);  border: 1px solid var(--semantic-danger-border); }
.pill-status-info    { background: var(--semantic-info-bg);    color: var(--semantic-info-fg);    border: 1px solid var(--semantic-info-border); }

/* ---------- Forms ---------- */
.field { display: flex; flex-direction: column; gap: var(--sp-2); }
.field-label { font-size: var(--fs-14); font-weight: var(--fw-semibold); color: var(--fg-body); font-family: var(--font-display); }
.field-help { font-size: var(--fs-13); color: var(--fg-subtle); }
.field-error { font-size: var(--fs-13); color: var(--semantic-danger-fg); display: flex; align-items: center; gap: var(--sp-1); }

.input, .textarea, .select {
  width: 100%;
  padding: 12px var(--sp-4);
  background: var(--tint-03);
  border: 1px solid var(--border-default);
  border-radius: var(--r-sm);
  font-family: var(--font-body);
  font-size: var(--fs-16);
  color: var(--fg-primary);
  transition: border-color var(--dur-base), background var(--dur-base), box-shadow var(--dur-base);
}
.input::placeholder, .textarea::placeholder { color: var(--fg-quiet); }
.input:hover, .textarea:hover, .select:hover { border-color: var(--border-strong); }
.input:focus, .textarea:focus, .select:focus {
  outline: none;
  border-color: var(--product-accent);
  box-shadow: 0 0 0 3px var(--product-tint);
  background: var(--tint-06);
}
.input[aria-invalid="true"], .textarea[aria-invalid="true"] { border-color: var(--semantic-danger-border); }
.textarea { min-height: 96px; resize: vertical; line-height: var(--lh-normal); }
.select { appearance: none; -webkit-appearance: none; background-image:
  linear-gradient(45deg, transparent 50%, currentColor 50%),
  linear-gradient(-45deg, transparent 50%, currentColor 50%);
  background-position: calc(100% - 20px) center, calc(100% - 14px) center;
  background-size: 6px 6px, 6px 6px;
  background-repeat: no-repeat;
  padding-right: var(--sp-10);
}

/* Checkbox / Radio */
.check, .radio { display: inline-flex; align-items: center; gap: var(--sp-2); cursor: pointer; user-select: none; }
.check input, .radio input { position: absolute; opacity: 0; pointer-events: none; }
.check-box, .radio-dot {
  width: 18px; height: 18px;
  background: var(--tint-03);
  border: 1.5px solid var(--border-strong);
  border-radius: 4px;
  display: inline-flex; align-items: center; justify-content: center;
  transition: all var(--dur-base);
  flex-shrink: 0;
}
.radio-dot { border-radius: var(--r-full); }
.check input:checked ~ .check-box,
.radio input:checked ~ .radio-dot {
  background: var(--product-grad);
  border-color: transparent;
}
.check-box::after {
  content: ''; width: 10px; height: 6px;
  border-left: 2px solid #fff; border-bottom: 2px solid #fff;
  transform: rotate(-45deg) translate(1px, -1px) scale(0);
  transition: transform var(--dur-base) var(--ease-out);
}
.check input:checked ~ .check-box::after { transform: rotate(-45deg) translate(1px, -1px) scale(1); }
.radio-dot::after {
  content: ''; width: 8px; height: 8px; border-radius: var(--r-full); background: #fff;
  transform: scale(0); transition: transform var(--dur-base) var(--ease-out);
}
.radio input:checked ~ .radio-dot::after { transform: scale(1); }
.check input:focus-visible ~ .check-box,
.radio input:focus-visible ~ .radio-dot { box-shadow: var(--focus-ring); }

/* Switch */
.switch { display: inline-flex; align-items: center; gap: var(--sp-3); cursor: pointer; user-select: none; }
.switch input { position: absolute; opacity: 0; pointer-events: none; }
.switch-track {
  width: 40px; height: 22px;
  background: var(--tint-10);
  border-radius: var(--r-full);
  position: relative;
  transition: background var(--dur-base);
}
.switch-track::after {
  content: ''; position: absolute; top: 2px; left: 2px;
  width: 18px; height: 18px; background: #fff;
  border-radius: var(--r-full); transition: left var(--dur-base) var(--ease-out);
  box-shadow: var(--shadow-sm);
}
.switch input:checked ~ .switch-track { background: var(--product-grad); }
.switch input:checked ~ .switch-track::after { left: 20px; }
.switch input:focus-visible ~ .switch-track { box-shadow: var(--focus-ring); }

/* ---------- Alert / Banner ---------- */
.alert {
  display: flex;
  gap: var(--sp-3);
  padding: var(--sp-4) var(--sp-5);
  border-radius: var(--r-md);
  background: var(--tint-03);
  border: 1px solid var(--border-default);
  align-items: flex-start;
}
.alert-icon { flex-shrink: 0; width: 20px; height: 20px; }
.alert-body { flex: 1; }
.alert-title { font-weight: var(--fw-semibold); color: var(--fg-primary); margin-bottom: var(--sp-1); font-family: var(--font-display); }
.alert-text { color: var(--fg-muted); font-size: var(--fs-14); line-height: var(--lh-normal); }
.alert-success { background: var(--semantic-success-bg); border-color: var(--semantic-success-border); }
.alert-success .alert-title { color: var(--semantic-success-fg); }
.alert-warning { background: var(--semantic-warning-bg); border-color: var(--semantic-warning-border); }
.alert-warning .alert-title { color: var(--semantic-warning-fg); }
.alert-danger  { background: var(--semantic-danger-bg);  border-color: var(--semantic-danger-border); }
.alert-danger  .alert-title { color: var(--semantic-danger-fg); }
.alert-info    { background: var(--semantic-info-bg);    border-color: var(--semantic-info-border); }
.alert-info    .alert-title { color: var(--semantic-info-fg); }

/* Collapsible alert — useful for inline form feedback that animates
   in on submit. JS contract: toggle `.is-visible` on the alert to
   show/hide. Without `.is-visible` it is fully collapsed (zero
   height, no margin). max-height is set generously to cover any
   realistic alert body; the actual height is content-driven. */
.alert.is-collapsible {
  max-height: 0;
  opacity: 0;
  margin: 0;
  padding-top: 0;
  padding-bottom: 0;
  border-top-width: 0;
  border-bottom-width: 0;
  overflow: hidden;
  transition:
    max-height var(--dur-base) var(--ease-standard),
    opacity var(--dur-base) var(--ease-standard),
    margin var(--dur-base) var(--ease-standard),
    padding var(--dur-base) var(--ease-standard);
}
.alert.is-collapsible.is-visible {
  max-height: 400px;
  opacity: 1;
  padding-top: var(--sp-4);
  padding-bottom: var(--sp-4);
  border-top-width: 1px;
  border-bottom-width: 1px;
}

/* ---------- Divider ---------- */
.divider { height: 1px; background: var(--border-default); border: none; margin: var(--sp-8) 0; }
.divider-soft { background: var(--border-subtle); }
.divider-labeled {
  display: flex; align-items: center; gap: var(--sp-4);
  color: var(--fg-subtle); font-size: var(--fs-13);
  text-transform: uppercase; letter-spacing: var(--tracking-wide);
  margin: var(--sp-8) 0;
}
.divider-labeled::before, .divider-labeled::after {
  content: ''; flex: 1; height: 1px; background: var(--border-default);
}

/* ---------- Avatar ---------- */
.avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px; height: 40px;
  background: var(--product-grad);
  color: var(--fg-on-brand);
  font-family: var(--font-display);
  font-weight: var(--fw-semibold);
  border-radius: var(--r-full);
  font-size: var(--fs-14);
  overflow: hidden;
}
.avatar img { width: 100%; height: 100%; object-fit: cover; }
.avatar-sm { width: 28px; height: 28px; font-size: var(--fs-12); }
.avatar-lg { width: 56px; height: 56px; font-size: var(--fs-18); }
.avatar-xl { width: 80px; height: 80px; font-size: var(--fs-24); }

/* ---------- Tooltip (pure CSS, data-tooltip attr) ---------- */
[data-tooltip] { position: relative; }
[data-tooltip]::after {
  content: attr(data-tooltip);
  position: absolute;
  bottom: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%) translateY(4px);
  background: var(--fg-primary);
  color: var(--bg-canvas);
  padding: 6px var(--sp-3);
  border-radius: var(--r-sm);
  font-size: var(--fs-13);
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur-base), transform var(--dur-base);
  z-index: var(--z-dropdown);
}
[data-tooltip]:hover::after,
[data-tooltip]:focus-visible::after { opacity: 1; transform: translateX(-50%) translateY(0); }

/* ---------- Tabs ---------- */
.tabs {
  display: flex;
  gap: 2px;
  border-bottom: 1px solid var(--border-default);
  overflow-x: auto;
}
.tab {
  padding: var(--sp-3) var(--sp-5);
  background: transparent;
  border: none;
  color: var(--fg-muted);
  font-family: var(--font-display);
  font-size: var(--fs-15);
  font-weight: var(--fw-semibold);
  cursor: pointer;
  position: relative;
  transition: color var(--dur-base);
  white-space: nowrap;
}
.tab:hover { color: var(--fg-primary); }
.tab[aria-selected="true"] { color: var(--fg-primary); }
.tab[aria-selected="true"]::after {
  content: '';
  position: absolute;
  left: var(--sp-5); right: var(--sp-5);
  bottom: -1px;
  height: 2px;
  background: var(--product-grad);
  border-radius: 2px;
}

/* ---------- Accordion / FAQ ----------
   Canonical: .accordion-item / .accordion-body / .accordion-list.
   Deprecated aliases: .faq-item / .faq-answer / .faq-list (kept for back-compat). */
.accordion-item, .faq-item {
  background: var(--tint-03);
  border: 1px solid var(--border-default);
  border-radius: var(--r-md);
  margin-bottom: var(--sp-3);
  overflow: hidden;
  transition: border-color var(--dur-base), background var(--dur-base);
}
.accordion-item[open], .faq-item[open] { border-color: var(--section-border); }
.accordion-item > summary, .faq-item > summary {
  cursor: pointer;
  padding: var(--sp-5) 56px var(--sp-5) var(--sp-6);
  font-weight: var(--fw-semibold);
  font-size: var(--fs-16);
  color: var(--fg-primary);
  position: relative;
  list-style: none;
  user-select: none;
  font-family: var(--font-display);
}
.accordion-item > summary::-webkit-details-marker,
.faq-item > summary::-webkit-details-marker { display: none; }
.accordion-item > summary::after, .faq-item > summary::after {
  content: '';
  position: absolute;
  right: var(--sp-6);
  top: 50%;
  width: 9px; height: 9px;
  border-right: 2px solid var(--section-accent);
  border-bottom: 2px solid var(--section-accent);
  transform: translateY(-70%) rotate(45deg);
  transition: transform var(--dur-base);
}
.accordion-item[open] > summary::after,
.faq-item[open] > summary::after { transform: translateY(-30%) rotate(-135deg); }
.accordion-item > .accordion-body, .faq-item > .faq-answer {
  padding: 0 var(--sp-6) var(--sp-5);
  color: var(--fg-muted);
  font-size: var(--fs-15);
  line-height: var(--lh-relaxed);
}
.accordion-item > .accordion-body a,
.faq-item > .faq-answer a { color: var(--section-accent); text-decoration: underline; }

.accordion-list, .faq-list {
  max-width: 720px;
  margin: var(--sp-10) auto 0;
  text-align: left;
}

/* ---------- Progress ---------- */
.progress {
  height: 6px;
  background: var(--tint-06);
  border-radius: var(--r-full);
  overflow: hidden;
}
.progress-bar {
  height: 100%;
  background: var(--product-grad);
  border-radius: var(--r-full);
  transition: width var(--dur-slow) var(--ease-standard);
}

/* ---------- Skeleton ---------- */
.skeleton {
  background: linear-gradient(90deg,
    var(--tint-03) 0%,
    var(--tint-10) 50%,
    var(--tint-03) 100%);
  background-size: 200% 100%;
  border-radius: var(--r-sm);
  animation: skeleton-shimmer 1.4s infinite linear;
}
@keyframes skeleton-shimmer {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

/* ---------- Modal ---------- */
.modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(15, 14, 42, 0.7);
  backdrop-filter: blur(4px);
  z-index: var(--z-modal);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--sp-6);
  animation: fadeIn var(--dur-base) var(--ease-out);
}
.modal {
  background: var(--bg-surface-3);
  border: 1px solid var(--border-default);
  border-radius: var(--r-lg);
  padding: var(--sp-8);
  max-width: 480px;
  width: 100%;
  box-shadow: var(--shadow-xl);
  animation: modalIn var(--dur-slow) var(--ease-out);
}
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes modalIn {
  from { opacity: 0; transform: translateY(16px) scale(0.96); }
  to { opacity: 1; transform: none; }
}

/* ---------- Toast ---------- */
.toast {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-5);
  background: var(--bg-surface-3);
  border: 1px solid var(--border-default);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-lg);
  color: var(--fg-primary);
  font-size: var(--fs-15);
}
.toast-dot { width: 8px; height: 8px; border-radius: var(--r-full); background: var(--product-grad); flex-shrink: 0; }

/* ---------- Chat bubble ---------- */
.bubble {
  display: inline-block;
  padding: var(--sp-2) var(--sp-4);
  background: var(--product-tint);
  border: 1px solid var(--product-border);
  border-radius: var(--r-speech-tail);
  color: var(--product-accent);
  font-size: var(--fs-15);
  max-width: 260px;
  line-height: var(--lh-normal);
}
[data-theme="light"] .bubble { color: var(--product-end); }
.bubble-inbound {
  border-radius: 12px 12px 2px 12px;
}

/* ---------- Table ---------- */
.tbl { width: 100%; border-collapse: collapse; }
.tbl th, .tbl td {
  padding: var(--sp-3) var(--sp-4);
  text-align: left;
  border-bottom: 1px solid var(--border-subtle);
  font-size: var(--fs-15);
}
.tbl th {
  font-family: var(--font-display);
  font-size: var(--fs-13);
  font-weight: var(--fw-semibold);
  text-transform: uppercase;
  letter-spacing: var(--tracking-wide);
  color: var(--fg-subtle);
}
.tbl tbody tr:hover { background: var(--tint-03); }

/* ---------- Comparison table ----------
   Two- or three-column comparison (e.g. "Old way" vs "With us").
   Header row picks up product accent; body rows use subtle striping.
   Use .compare--highlight on a column to emphasize "our" side. */
.compare {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  border: 1px solid var(--border-default);
  border-radius: var(--r-lg);
  overflow: hidden;
  font-size: var(--fs-15);
  background: var(--bg-surface-1);
}
.compare thead th {
  padding: var(--sp-5) var(--sp-5);
  text-align: left;
  font-family: var(--font-display);
  font-size: var(--fs-13);
  font-weight: var(--fw-semibold);
  text-transform: uppercase;
  letter-spacing: var(--tracking-wide);
  color: var(--fg-subtle);
  background: var(--bg-surface-2);
  border-bottom: 1px solid var(--border-default);
  vertical-align: middle;
}
.compare thead th:first-child {
  color: var(--fg-quiet);
  width: 28%;
}
/* Highlighted column gets extra width so the product-of-focus
   reads bigger than the comparator(s). Applies to both 2-col
   and 3-col layouts. */
.compare thead th.compare-col-highlight { width: 44%; }
.compare tbody td.compare-col-highlight { width: 44%; }
.compare thead th.compare-col-highlight {
  color: var(--fg-primary);
  background: linear-gradient(135deg, var(--section-tint-a) 0%, var(--section-tint-b) 100%);
  position: relative;
}
.compare thead th.compare-col-highlight::after {
  content: "";
  position: absolute; left: 0; right: 0; bottom: -1px; height: 2px;
  background: var(--product-grad);
}
.compare thead th .compare-col-title {
  display: flex; align-items: center; gap: var(--sp-2);
  font-family: var(--font-display); font-weight: var(--fw-bold);
  font-size: var(--fs-16);
  text-transform: none; letter-spacing: 0;
}
.compare thead th .compare-col-title img { width: 20px; height: 20px; }
.compare thead th:not(.compare-col-highlight) .compare-col-title {
  font-weight: var(--fw-semibold);
  color: var(--fg-muted);
}
.compare-centered { max-width: 720px; margin: var(--sp-10) auto 0; text-align: left; }
.compare tbody td {
  padding: var(--sp-4) var(--sp-5);
  border-bottom: 1px solid var(--border-subtle);
  vertical-align: top;
  color: var(--fg-body);
}
.compare tbody tr:last-child td { border-bottom: none; }
.compare tbody td:first-child {
  font-weight: var(--fw-semibold);
  color: var(--fg-primary);
  font-family: var(--font-display);
  background: var(--bg-surface-2);
  width: 32%;
}
.compare tbody td.compare-col-highlight {
  background: linear-gradient(135deg, var(--section-tint-a) 0%, var(--section-tint-b) 100%);
}
.compare-mark {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  font-weight: var(--fw-medium);
}
.compare-mark::before {
  content: ""; width: 18px; height: 18px; flex: 0 0 18px;
  border-radius: var(--r-full);
  display: inline-block;
  background-size: 12px; background-repeat: no-repeat; background-position: center;
}
.compare-mark--yes { color: var(--fg-body); }
.compare-mark--yes::before {
  background-color: var(--status-success-bg);
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%2334d399' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'><polyline points='3,8.5 7,12 13,4'/></svg>");
}
.compare-mark--no { color: var(--fg-muted); }
.compare-mark--no::before {
  background-color: var(--status-danger-bg);
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23f87171' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'><line x1='4' y1='4' x2='12' y2='12'/><line x1='12' y1='4' x2='4' y2='12'/></svg>");
}
.compare-mark--partial { color: var(--fg-body); }
.compare-mark--partial::before {
  background-color: var(--status-warning-bg);
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23fbbf24' stroke-width='2.5' stroke-linecap='round'><line x1='4' y1='8' x2='12' y2='8'/></svg>");
}
@media (max-width: 640px) {
  .compare thead th:first-child, .compare tbody td:first-child { width: 34%; }
  .compare thead th.compare-col-highlight,
  .compare tbody td.compare-col-highlight { width: 40%; }
  .compare thead th, .compare tbody td { padding: var(--sp-3); font-size: var(--fs-14); }
}

/* Collapsible variant — add .compare--collapsible to the table.
   On ≤640px: the leading "label" column is hidden and its text
   inlines as a mini-eyebrow above each cell's content, so you get
   a clean side-by-side "Old way / With us" view on phones.
   Requires data-label="…" on each <td> that isn't the first column.

   Also activates inside a [data-force-narrow] ancestor — the design-system
   docs use this to show the mobile layout without resizing the window. */
.compare--collapsible tbody td[data-label]::before { content: none; }

/* Shared collapsed styles, reused by both the media-query and the force-narrow ancestor. */
[data-force-narrow] .compare--collapsible thead th:first-child,
[data-force-narrow] .compare--collapsible tbody td:first-child {
  display: none;
}
[data-force-narrow] .compare--collapsible thead th.compare-col-highlight,
[data-force-narrow] .compare--collapsible tbody td.compare-col-highlight,
[data-force-narrow] .compare--collapsible thead th:not(:first-child):not(.compare-col-highlight),
[data-force-narrow] .compare--collapsible tbody td:not(:first-child):not(.compare-col-highlight) {
  width: 50%;
}
[data-force-narrow] .compare--collapsible tbody td[data-label]::before {
  content: attr(data-label);
  display: block;
  font-size: var(--fs-12);
  font-weight: var(--fw-semibold);
  text-transform: uppercase;
  letter-spacing: var(--tracking-wide);
  color: var(--fg-quiet);
  margin-bottom: 4px;
}
[data-force-narrow] .compare--collapsible thead th,
[data-force-narrow] .compare--collapsible tbody td {
  padding: var(--sp-3);
  font-size: var(--fs-14);
}

@media (max-width: 640px) {
  .compare--collapsible thead th:first-child,
  .compare--collapsible tbody td:first-child {
    display: none;
  }
  .compare--collapsible thead th.compare-col-highlight,
  .compare--collapsible tbody td.compare-col-highlight,
  .compare--collapsible thead th:not(:first-child):not(.compare-col-highlight),
  .compare--collapsible tbody td:not(:first-child):not(.compare-col-highlight) {
    width: 50%;
  }
  .compare--collapsible tbody td[data-label]::before {
    content: attr(data-label);
    display: block;
    font-size: var(--fs-12);
    font-weight: var(--fw-semibold);
    text-transform: uppercase;
    letter-spacing: var(--tracking-wide);
    color: var(--fg-quiet);
    margin-bottom: 4px;
  }
}

/* ---------- Prose (long-form / legal) ----------
   Container for privacy, terms, and any article-length text.
   Constrains measure to 68ch for comfortable reading, restores
   vertical rhythm between block elements, and styles nested
   lists/links/headings without class-per-element. */
.prose {
  max-width: 68ch;
  margin-left: auto;
  margin-right: auto;
  color: var(--fg-body);
  font-size: var(--fs-16);
  line-height: var(--lh-relaxed);
}
.prose > * + * { margin-top: var(--sp-4); }
.prose h1 { font-size: var(--fs-40); line-height: var(--lh-tight); margin-top: 0; margin-bottom: var(--sp-6); color: var(--fg-primary); }
.prose h2 { font-size: var(--fs-24); line-height: var(--lh-snug); margin-top: var(--sp-12); margin-bottom: var(--sp-3); color: var(--fg-primary); }
.prose h3 { font-size: var(--fs-20); line-height: var(--lh-snug); margin-top: var(--sp-8); margin-bottom: var(--sp-2); color: var(--fg-primary); }
.prose h2 + p, .prose h3 + p { margin-top: var(--sp-2); }
.prose p { margin-top: var(--sp-4); }
.prose a {
  color: var(--product-accent);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
  transition: color var(--dur-base);
}
[data-theme="light"] .prose a { color: var(--product-end); }
.prose a:hover { text-decoration-thickness: 2px; }
.prose ul, .prose ol { padding-left: var(--sp-6); margin-top: var(--sp-4); }
.prose li { margin-top: var(--sp-2); }
.prose li::marker { color: var(--fg-quiet); }
.prose strong { color: var(--fg-primary); font-weight: var(--fw-semibold); }
.prose em { color: var(--fg-body); }
.prose code {
  font-family: var(--font-mono);
  font-size: 0.925em;
  padding: 2px 6px;
  border-radius: var(--r-xs);
  background: var(--tint-06);
  color: var(--fg-primary);
}
.prose blockquote {
  margin: var(--sp-6) 0;
  padding: var(--sp-2) var(--sp-5);
  border-left: 2px solid var(--product-accent);
  color: var(--fg-muted);
  font-style: italic;
}
.prose hr {
  border: 0;
  border-top: 1px solid var(--border-default);
  margin: var(--sp-10) 0;
}
.prose table { margin-top: var(--sp-6); }
.prose .prose-meta {
  display: block;
  font-size: var(--fs-14);
  color: var(--fg-subtle);
  margin-top: calc(-1 * var(--sp-4));
  margin-bottom: var(--sp-8);
}

/* ---------- Feature list (inside cards) ----------
   Plain checkmark-style list used inside pricing cards and
   anywhere a card needs "what's included." The ✓ glyph is
   authored inline in the HTML (not pseudo-generated) so it
   stays copyable and screen-reader friendly. */
.feature-list {
  list-style: none;
  padding: 0;
  margin: 0;
  text-align: left;
  display: inline-block;
  color: var(--fg-body);
}
.feature-list li {
  padding: var(--sp-1) 0;
  color: var(--fg-body);
}
.feature-list li::before {
  content: "\2713  ";
  color: var(--section-accent);
  font-weight: var(--fw-bold);
}
.feature-list li + li { border-top: 0; }

/* ---------- Site footer ----------
   Used at the bottom of every marketing page. 4-column grid
   on desktop (brand column 2fr, then three link columns 1fr
   each), stacks to 2-col then 1-col on narrow screens. */
.site-footer {
  width: 100%;
  padding: var(--sp-12) var(--sp-10) var(--sp-6);
  border-top: 1px solid var(--border-default);
  color: var(--fg-subtle);
  font-size: var(--fs-14);
  background: var(--bg-canvas);
}
.site-footer-grid {
  display: grid;
  grid-template-columns: 2fr 1fr 1fr 1fr;
  gap: var(--sp-8);
  margin-bottom: var(--sp-8);
}
.site-footer-brand img { height: 40px; margin-bottom: var(--sp-3); }
.site-footer-brand p { color: var(--fg-quiet); font-size: var(--fs-13); }
.site-footer-heading {
  font-family: var(--font-display);
  font-size: var(--fs-12);
  font-weight: var(--fw-semibold);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--fg-muted);
  margin-bottom: var(--sp-3);
}
.site-footer-links {
  list-style: none;
  padding: 0;
  margin: 0;
}
.site-footer-links li + li { margin-top: var(--sp-2); }
.site-footer-links a {
  color: var(--fg-subtle);
  transition: color var(--dur-base);
}
.site-footer-links a:hover { color: var(--fg-primary); }
.site-footer-copyright {
  padding-top: var(--sp-4);
  border-top: 1px solid var(--border-subtle);
  font-size: var(--fs-13);
  color: var(--fg-quiet);
}
.site-footer-copyright p + p { margin-top: var(--sp-2); }
@media (max-width: 768px) {
  .site-footer { padding: var(--sp-10) var(--sp-6) var(--sp-5); }
  .site-footer-grid { grid-template-columns: 1fr 1fr; gap: var(--sp-6); }
  .site-footer-brand { grid-column: 1 / -1; }
}
@media (max-width: 480px) {
  .site-footer-grid { grid-template-columns: 1fr; }
  .site-footer-brand { grid-column: auto; }
}

/* ---------- Hero ----------
   Variants, sharing the same `.hero` base. All wrap their content
   in `.hero-inner` so consumer markup is consistent across variants.
   - `.hero.hero-centered` — product landing. Badge + gradient
     headline + subhead + CTA row, centered over aurora.
     `.hero-centered .hero-inner` carries its own inline padding so
     it stays clear of viewport edges.
   - `.hero.hero-split` — two-column: copy left, visual right (phone
     mockup, screenshot, whatever). Add `.reverse` to flip sides.
     Collapses to one column (copy first, visual second) under 768px.
   - `.hero.hero-home` — mothership / top-level landing. Multi-aurora
     background, taller padding, paired with `.home-page .nav-home-logo`
     which enlarges the nav logo. `.hero-home .hero-inner` mirrors
     `.container` width and gutter.
   - `.hero` on its own — bare container; caller composes inside.
     Wrap children in `.container` to align with section content
     below. The base `.hero` has no inline padding so a child
     `.container` can supply the canonical gutter without fighting. */
.hero {
  padding: var(--sp-20) 0;
  background: var(--aura-core), var(--bg-canvas);
  position: relative;
  overflow: hidden;
}
.hero-centered {
  text-align: center;
}
/* Force text-align on children too — otherwise a <p> or sub-copy
   inside .hero-inner can end up flex-stretched and read as
   left-aligned on narrow screens even though the block is centered. */
.hero-centered .hero-inner,
.hero-centered .hero-inner > * {
  text-align: center;
}
.hero-centered .hero-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-4);
  max-width: 620px;
  margin: 0 auto;
  padding-inline: var(--sp-10);
}
.hero h1 {
  font-size: var(--fs-48);
  line-height: var(--lh-tight);
}
.hero-lg h1 { font-size: var(--fs-56); }
/* Centered-only overrides for subhead/CTA row. Scope matters —
   .hero-split has its own left-aligned layout and must not inherit
   these auto-margins or justify:center rules. */
.hero-centered .subhead { max-width: 52ch; margin-left: auto; margin-right: auto; }
.hero-centered .row { justify-content: center; }

/* ---------- Home hero ----------
   Mothership landing variant with multi-aurora background.
   Use on the homepage or any top-level landing page.
   Two-class selector (`.hero.hero-home`) on the padding rule so
   it beats the 640px `.hero` mobile padding override below — the
   pre-rename `.home-hero` was not a `.hero` and kept its desktop
   padding on mobile, and we preserve that. */
.hero.hero-home {
  padding: 120px 0 80px;
  text-align: center;
  background:
    radial-gradient(ellipse 50% 60% at 50% 40%, rgba(130,58,188,0.12) 0%, transparent 70%),
    radial-gradient(ellipse 40% 50% at 30% 70%, rgba(247,127,0,0.06) 0%, transparent 70%),
    var(--bg-canvas);
}
.hero-home .hero-inner {
  max-width: var(--container-max);
  margin: 0 auto;
  padding: 0 var(--container-pad);
}
.hero-home h1 { margin-bottom: var(--sp-4); }
.hero-home .subhead { max-width: 52ch; margin: 0 auto var(--sp-10); text-wrap: balance; }
.hero-home .small { margin-bottom: var(--sp-10); }
.home-page .nav-home-logo { height: 64px; }

/* ---------- Hero split ----------
   Two-column hero: copy left, visual right. Copy column is
   narrower so the visual leads. Reverse the order with
   `.hero-split.reverse` (copy right, visual left). Both
   columns stack on mobile (copy on top) with the visual
   centered in its column.

   Usage:
     <section class="hero hero-split">
       <div class="hero-inner">
         <div class="hero-copy">
           <span class="badge">Badge</span>
           <h1>Headline with <span class="text-gradient">accent</span></h1>
           <p class="subhead">Supporting line.</p>
           <div class="row">
             <a class="btn btn-primary">Primary</a>
             <a class="btn btn-outline">Secondary</a>
           </div>
         </div>
         <div class="hero-visual">
           <img src="phone.png" alt="" class="mockup-frame">
         </div>
       </div>
     </section> */
.hero-split { padding-left: 0; padding-right: 0; }
.hero-split .hero-inner {
  display: grid;
  grid-template-columns: minmax(0, 6fr) minmax(0, 5fr);
  gap: var(--sp-15);
  align-items: center;
  max-width: var(--container-max);
  margin: 0 auto;
  padding: 0 var(--container-pad);
}
.hero-split.reverse .hero-inner {
  grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
}
.hero-split.reverse .hero-copy { order: 2; }
.hero-split.reverse .hero-visual { order: 1; }

/* Base hero-copy layout — applies to any hero variant.
   `.hero-split` adds the 560px measure cap below so the copy
   column doesn't outrun its grid track. */
.hero-copy {
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
}
.hero-copy .badge { align-self: flex-start; }
.hero-copy .row { margin-top: var(--sp-2); }
.hero-split .hero-copy { max-width: 560px; }

.hero-split .hero-visual {
  display: flex;
  justify-content: center;
  align-items: center;
}
/* Give bare <img> inside hero-visual a sensible default — if
   you want the full mockup-frame treatment, add that class. */
.hero-split .hero-visual > img {
  width: 300px;
  max-width: 100%;
  height: auto;
  display: block;
  border-radius: var(--r-2xl);
  filter: drop-shadow(0 20px 40px rgba(0,0,0,0.3));
}

@media (max-width: 768px) {
  .hero-split .hero-inner,
  .hero-split.reverse .hero-inner {
    grid-template-columns: 1fr;
    gap: var(--sp-10);
  }
  .hero-split.reverse .hero-copy { order: 1; }
  .hero-split.reverse .hero-visual { order: 2; }
  .hero-split .hero-copy { max-width: 100%; }
}

@media (max-width: 640px) {
  .hero { padding: var(--sp-12) 0; }
  .hero-centered .hero-inner { padding-inline: var(--sp-5); }
  .hero h1 { font-size: var(--fs-32); }
  .hero-lg h1 { font-size: var(--fs-40); }
}

/* ---------- Feature row ----------
   Workhorse of product pages. Two-column grid (copy + visual),
   alternates direction via `.feature-row.reverse`. On narrow
   screens collapses to stacked with copy on top. */
.feature-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sp-12);
  align-items: center;
  padding: var(--sp-12) 0;
}
.feature-row.reverse { direction: rtl; }
.feature-row.reverse > * { direction: ltr; }
.feature-row .feature-copy h2 {
  margin: var(--sp-2) 0 var(--sp-3);
}
.feature-row .feature-copy p:not(.label) {
  color: var(--fg-muted);
  margin-bottom: var(--sp-4);
}
.feature-row .feature-visual {
  display: flex;
  justify-content: center;
  align-items: center;
}
.feature-row .feature-visual > img {
  width: 280px;
  max-width: 100%;
  border-radius: var(--r-2xl);
  filter: drop-shadow(0 12px 32px rgba(0,0,0,0.3));
}
@media (max-width: 768px) {
  .feature-row {
    grid-template-columns: 1fr;
    gap: var(--sp-8);
    padding: var(--sp-8) 0;
  }
  .feature-row.reverse { direction: ltr; }
}

/* ---------- Section header ----------
   Centered intro block: label + heading + optional subhead/button.
   Add .section-header-spaced when the following content needs
   breathing room (e.g. before a category-grid). */
.section-header { text-align: center; }
.section-header-spaced { margin-bottom: var(--sp-12); }
.section-header .subhead { max-width: 52ch; margin: var(--sp-3) auto 0; }
.section-header .subhead + p,
.section-header p + p { max-width: 60ch; margin: var(--sp-3) auto 0; color: var(--fg-muted); }
.section-header .btn { margin-top: var(--sp-6); }

/* ---------- Section CTA ----------
   Centered button wrapper after a content block (e.g. steps grid). */
.section-cta { text-align: center; margin-top: var(--sp-10); }
.section-cta .badge { margin-bottom: var(--sp-2); }
.section-cta-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: var(--sp-3);
}

/* ---------- Trial notice ----------
   Promotional fine print below a CTA (trial terms, pricing note). */
.trial-notice { margin-top: var(--sp-4); font-size: var(--fs-15); color: var(--fg-muted); }
.cta-inner .trial-notice { opacity: 0.85; }

/* ---------- CTA block ----------
   Closing call-to-action. Centered, aurora background,
   one primary action. Use at the bottom of marketing pages. */
.cta {
  padding: var(--sp-20) var(--sp-10);
  text-align: center;
  background: var(--aura-alt), var(--bg-surface-1);
}
.cta-inner {
  max-width: 560px;
  margin: 0 auto;
}
.cta-inner h2 { margin-bottom: var(--sp-3); }
.cta-inner .subhead { margin: var(--sp-3) 0 var(--sp-6); }
.cta-inner .badge { margin-bottom: var(--sp-4); }
@media (max-width: 640px) {
  .cta { padding: var(--sp-12) var(--sp-5); }
}

/* ---------- Stacked mockups ----------
   Two overlapping screenshots used in feature rows to imply
   depth without a full device frame. Back image is rotated,
   front image sits flat and slightly inset. On hover the two
   split apart slightly. Size is fixed so the aspect stays
   predictable across breakpoints.

   Usage:
     <div class="mockup-stack">
       <img class="mockup-back"  src="..." alt="">
       <img class="mockup-front" src="..." alt="">
     </div>

   Pair with .reveal on the parent .feature-row for the
   split-entrance animation. */
.mockup-stack {
  position: relative;
  width: 420px;
  height: 560px;
  margin: 0 auto;
  perspective: 900px;
}
.mockup-stack img {
  position: absolute;
  width: 240px;
  height: auto;
  border-radius: 20px;
  box-shadow: var(--shadow-lg);
  overflow: hidden;
  transition: transform var(--dur-slow) var(--ease-out);
}
.mockup-stack .mockup-back {
  top: 30px; right: 0;
  transform: rotate(6deg);
  z-index: 1;
}
.mockup-stack .mockup-front {
  top: 0; left: 0;
  z-index: 2;
}
.mockup-stack:hover .mockup-front {
  transform: translate(-10px, -6px) scale(1.02);
}
.mockup-stack:hover .mockup-back {
  transform: rotate(4deg) translate(10px, 6px) scale(0.98);
}

/* Single screenshot variant — same slot as .mockup-stack but
   flat. Use when one image is enough. */
.mockup-single {
  display: flex;
  justify-content: center;
  align-items: center;
}
.mockup-single img {
  width: 280px;
  max-width: 100%;
  border-radius: 20px;
  box-shadow: var(--shadow-lg);
}

/* ---------- Mockup frame ----------
   Generic "this is a product screenshot" treatment: rounded
   corners + soft shadow, sized to its container. Use anywhere
   you'd drop a raw <img> of the product into a feature row or
   hero and want it to look intentional.

   Apply to either the <img> itself, or a wrapper — rules nest
   so both work.

   Usage:
     <img src="phone.png" alt="" class="mockup-frame">
     — or —
     <div class="mockup-frame"><img src="phone.png" alt=""></div>
*/
.mockup-frame,
.mockup-frame > img {
  max-width: 100%;
  border-radius: var(--r-2xl);
  box-shadow: var(--shadow-lg);
  display: block;
}
.mockup-frame > img { width: 100%; height: auto; }

@media (max-width: 640px) {
  .mockup-stack { width: 280px; height: 440px; }
  .mockup-stack img { width: 220px; }
}

/* ---------- Scroll reveal ----------
   Progressive-enhancement entrance for sections, feature rows,
   product cards, etc. Add `.reveal` to any element; JS toggles
   `.is-visible` when it enters the viewport.

   Required JS (drop once per page, before </body>):

     document.documentElement.classList.add('js');
     const io = new IntersectionObserver((entries) => {
       entries.forEach(e => {
         if (e.isIntersecting) {
           e.target.classList.add('is-visible');
           io.unobserve(e.target);
         }
       });
     }, { threshold: 0.15, rootMargin: '0px 0px -10% 0px' });
     document.querySelectorAll('.reveal').forEach(el => io.observe(el));

   Reduced-motion users get the final state immediately (no
   opacity/transform in the @media no-preference block below). */
@media (prefers-reduced-motion: no-preference) {
  html.js .reveal {
    opacity: 0;
    transform: translateY(24px);
    transition: opacity var(--dur-reveal) var(--ease-out),
                transform var(--dur-reveal) var(--ease-out);
    will-change: opacity, transform;
  }
  html.js .reveal.is-visible {
    opacity: 1;
    transform: none;
  }

  /* Mockup stack gets a split entrance — front slides in from
     the left, back from the right with a slight delay. */
  html.js .mockup-stack .mockup-front {
    opacity: 0;
    transform: translateX(-40px) rotate(-4deg);
    transition: opacity var(--dur-slow) var(--ease-out),
                transform var(--dur-slow) var(--ease-out);
  }
  html.js .mockup-stack .mockup-back {
    opacity: 0;
    transform: translateX(40px) rotate(6deg);
    transition: opacity var(--dur-slow) var(--ease-out) 0.2s,
                transform var(--dur-slow) var(--ease-out) 0.2s;
  }
  html.js .mockup-stack.is-visible .mockup-front,
  html.js .reveal.is-visible .mockup-stack .mockup-front {
    opacity: 1;
    transform: none;
  }
  html.js .mockup-stack.is-visible .mockup-back,
  html.js .reveal.is-visible .mockup-stack .mockup-back {
    opacity: 1;
    transform: rotate(2deg);
  }

  /* Single images inside a revealing feature row */
  html.js .feature-row.reveal .feature-visual > img,
  html.js .feature-row.reveal .mockup-single > img {
    opacity: 0;
    transform: translateY(20px) scale(0.97);
    transition: opacity var(--dur-slow) var(--ease-out) 0.15s,
                transform var(--dur-slow) var(--ease-out) 0.15s;
  }
  html.js .feature-row.reveal.is-visible .feature-visual > img,
  html.js .feature-row.reveal.is-visible .mockup-single > img {
    opacity: 1;
    transform: none;
  }
}

/* ---------- Breadcrumb ---------- */
.crumbs { display: flex; align-items: center; gap: var(--sp-2); font-size: var(--fs-14); color: var(--fg-subtle); }
.crumbs a { color: var(--fg-muted); transition: color var(--dur-base); }
.crumbs a:hover { color: var(--product-accent); }
.crumbs .sep { color: var(--fg-quiet); }

/* ---------- Empty state ---------- */
.empty {
  text-align: center;
  padding: var(--sp-15) var(--sp-6);
  border: 1px dashed var(--border-strong);
  border-radius: var(--r-lg);
  background: var(--tint-03);
}
.empty h3 { margin-bottom: var(--sp-2); }
.empty p { color: var(--fg-muted); margin-bottom: var(--sp-6); max-width: 36ch; margin-left: auto; margin-right: auto; }

/* ---------- Steps (numbered) ----------
   Numbered process steps — section wrapper, grid, and step.
   The number badge reskins per product via --product-grad.

   Usage:
     <section class="steps-section">
       <h2>How it works</h2>
       <div class="steps-grid">
         <div class="step">
           <div class="step-number">1</div>
           <h3>Step name</h3>
           <p>Short description.</p>
         </div>
       </div>
     </section> */
.steps-section { text-align: center; }
.steps-section > h2 { margin-bottom: var(--sp-12); }

.steps-grid {
  margin-top: var(--sp-10);
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--sp-10);
}
.step { text-align: center; }
.step h3 { margin-bottom: var(--sp-2); }
.step p { color: var(--fg-muted); font-size: var(--fs-15); }
.step .step-number { margin-bottom: var(--sp-4); }

.step-number {
  width: 48px; height: 48px;
  background: var(--section-grad, var(--product-grad));
  color: var(--fg-on-brand);
  border-radius: var(--r-full);
  display: inline-flex; align-items: center; justify-content: center;
  font-family: var(--font-display);
  font-size: var(--fs-20);
  font-weight: var(--fw-bold);
}
/* 2-column variant. Centered within the section with a constrained
   max-width so two cards don't stretch to the full container width.
   Use when you have 2 parallel options (not a progression). */
.steps-grid.steps-2 {
  grid-template-columns: repeat(2, 1fr);
  max-width: 720px;
  margin-left: auto;
  margin-right: auto;
}

/* 4-column variant. Collapses to 2 columns on tablet, 1 on mobile.
   Use when you have 4 parallel steps (not a progression). */
.steps-grid.steps-4 { grid-template-columns: repeat(4, 1fr); }

/* Connecting line variant — dashed line stitches the .step-number
   bubbles together horizontally. Adds sequence reading to a
   stepped flow. Hidden below 768px where the grid stacks. */
.steps-grid.steps-connected { position: relative; }
.steps-grid.steps-connected::before {
  content: "";
  position: absolute;
  top: 24px; /* half of step-number height */
  left: calc(100% / 8);  /* center of first column */
  right: calc(100% / 8); /* center of last column */
  border-top: 2px dashed var(--border-subtle);
  z-index: 0;
  pointer-events: none;
}
.steps-grid.steps-connected .step { position: relative; z-index: 1; }
.steps-grid.steps-connected .step-number { position: relative; }

@media (max-width: 768px) {
  .steps-grid { grid-template-columns: 1fr; gap: var(--sp-8); }
  .steps-grid.steps-2 { grid-template-columns: 1fr; }
  .steps-grid.steps-4 { grid-template-columns: repeat(2, 1fr); }
  .steps-grid.steps-connected::before { display: none; }
}
@media (max-width: 540px) {
  .steps-grid.steps-4 { grid-template-columns: 1fr; }
}

/* ---------- Problem section ----------
   Centered section intro + 3-up card grid. Each card gets the
   conic border sweep on hover via .card-sweep.

   Usage:
     <section class="problem-section">
       <h2>The gap we're closing</h2>
       <p class="subhead">One line of context.</p>
       <div class="problem-grid">
         <article class="problem-card card-sweep">
           <div class="problem-icon">…</div>
           <h3>Title</h3>
           <p>One sentence.</p>
         </article>
       </div>
     </section> */
.problem-section { text-align: center; }
.problem-section > h2 { margin-bottom: var(--sp-3); }
.problem-section > .subhead {
  max-width: 52ch;
  margin: 0 auto;
}
.problem-grid {
  margin-top: var(--sp-10);
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--sp-6);
  text-align: left;
}
.problem-grid-2 { grid-template-columns: repeat(2, 1fr); }
/* .card-compact (.card-problem is a deprecated alias) — modifier on .card. */
.card-compact,
.card-problem {
  padding: var(--sp-8) var(--sp-6);
  border-color: var(--border-subtle);
  border-radius: var(--r-md);
}
.card-compact h3,
.card-problem h3 { margin-bottom: var(--sp-2); }
/* Reset the title's bottom margin when it sits inside an icon row.
   The flex row centers vertically, so a stray margin-bottom shifts
   the title's center and breaks optical alignment with the icon. */
.card-compact .card-icon-inline > h3,
.card-problem .card-icon-inline > h3 { margin-bottom: 0; }
.card-compact p,
.card-problem p { color: var(--fg-muted); font-size: var(--fs-15); }

.section-alt .card-compact,
.section-alt .card-problem {
  background: var(--bg-surface-1);
  border-color: var(--border-default);
}
.section-alt .card-compact:hover,
.section-alt .card-problem:hover { border-color: var(--border-strong); }

@media (max-width: 768px) {
  .problem-grid,
  .problem-grid-2 { grid-template-columns: 1fr; }
}

/* ---------- Quote block ----------
   Pull-quote / testimonial. Centered, constrained width. The optional
   .insight-note follows for a reflection/callback after the quote.

   Usage:
     <section class="quote-block">
       <blockquote class="quote">"…"</blockquote>
       <cite class="quote-attr">— Name, Role</cite>
       <p class="insight-note">Optional follow-up line.</p>
     </section> */
.quote-block { text-align: center; padding-left: var(--container-pad); padding-right: var(--container-pad); }
.quote-block .quote {
  max-width: 52ch;
  margin: 0 auto;
  font-size: var(--fs-22);
  font-style: italic;
  color: var(--fg-muted);
  line-height: var(--lh-relaxed);
  quotes: "\201C" "\201D";
}
.quote-block .quote-attr {
  display: block;
  margin-top: var(--sp-4);
  font-size: var(--fs-15);
  font-style: normal;
  color: var(--fg-subtle);
}
.quote-block .insight-note {
  max-width: 48ch;
  margin: var(--sp-8) auto 0;
  font-size: var(--fs-18);
  color: var(--fg-body);
  line-height: var(--lh-relaxed);
}

/* ---------- Dropdown menu ----------
   Hover-reveal nav menu. Trigger is .menu-trigger; panel is
   .menu-panel with an 8px "hover bridge" gap so the cursor can
   travel from trigger to panel without the menu closing.

   Usage:
     <div class="menu-dropdown">
       <button class="menu-trigger" aria-haspopup="true">
         EN <span aria-hidden="true">▾</span>
       </button>
       <div class="menu-panel" role="menu">
         <a href="/en/" role="menuitem">English</a>
         <a href="/es/" role="menuitem">Español</a>
       </div>
     </div> */
.menu-dropdown { position: relative; display: inline-block; }
.menu-dropdown .menu-trigger {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  font-size: var(--fs-14);
  color: var(--fg-muted);
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  transition: color var(--dur-fast) var(--ease-out);
}
.menu-dropdown:hover .menu-trigger,
.menu-dropdown:focus-within .menu-trigger { color: var(--product-accent); }

.menu-dropdown .menu-panel {
  display: none;
  position: absolute;
  top: 100%;
  right: 0;
  min-width: 160px;
  padding-top: var(--sp-2); /* hover bridge */
  z-index: var(--z-sticky, 100);
}
.menu-dropdown:hover .menu-panel,
.menu-dropdown:focus-within .menu-panel { display: block; }

.menu-dropdown .menu-panel > a,
.menu-dropdown .menu-panel > [role="menuitem"] {
  display: block;
  padding: var(--sp-2) var(--sp-4);
  font-size: var(--fs-14);
  color: var(--fg-muted);
  background: var(--bg-surface-3);
  border: 1px solid var(--border-subtle);
  box-shadow: var(--shadow-md);
  border-radius: var(--r-sm);
  transition: background var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out);
}
.menu-dropdown .menu-panel > a:hover,
.menu-dropdown .menu-panel > [role="menuitem"]:hover {
  background: linear-gradient(var(--product-tint), var(--product-tint)), var(--bg-surface-3);
  color: var(--product-accent);
}

/* ---------- Category cards ----------
   2-up grid of topical cards, each with an icon, heading, short
   copy, and a list of feature sub-links. Topical background tints
   are page-local decoration — pages add their own .cat-<name> class.

   Usage:
     <section class="category-section">
       <div class="category-grid">
         <article class="category-card cat-finance card-sweep">
           <div class="cat-icon">…</div>
           <h3>Finance</h3>
           <p>One line of pitch.</p>
           <ul>
             <li>Feature A</li>
             <li>Feature B <span class="pill-coming-soon">Coming soon</span></li>
           </ul>
         </article>
       </div>
     </section> */
.category-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sp-8);
}
.category-card {
  padding: var(--sp-8);
  border-radius: var(--r-lg);
  border: 1px solid var(--border-subtle);
  background: linear-gradient(145deg, var(--section-tint) 0%, transparent 50%, var(--bg-surface-3) 100%);
}
.category-card h3 {
  font-size: var(--fs-20);
  margin-bottom: var(--sp-2);
}
.category-card > p {
  color: var(--fg-muted);
  font-size: var(--fs-15);
  margin-bottom: var(--sp-4);
}
.category-card ul { list-style: none; padding: 0; margin: 0; }
.category-card ul li {
  padding: var(--sp-1) 0;
  color: var(--fg-body);
  font-size: var(--fs-14);
}
.category-card ul li::before {
  content: "→  ";
  color: var(--product-accent);
  font-weight: var(--fw-semibold);
}

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

/* ---------- Marquee ----------
   Infinite horizontal-scroll strip. Ambient pattern for logo
   rows, press quotes, product tags. The content is DUPLICATED
   inside `.marquee-track` so the loop joins seamlessly; a
   single copy will snap when it resets.

   Pause-on-hover is on by default. Under prefers-reduced-motion,
   the animation is disabled entirely (the strip sits static,
   showing only the first copy).

   Usage:
     <div class="marquee">
       <div class="marquee-track">
         <div class="marquee-item">Logo 1</div>
         <div class="marquee-item">Logo 2</div>
         <div class="marquee-item">Logo 3</div>
         <!-- duplicate the items so the loop is seamless -->
         <div class="marquee-item" aria-hidden="true">Logo 1</div>
         <div class="marquee-item" aria-hidden="true">Logo 2</div>
         <div class="marquee-item" aria-hidden="true">Logo 3</div>
       </div>
     </div>

   Set speed via the --marquee-duration custom property on the
   .marquee element. Default is 40s — longer = slower. */
.marquee {
  --marquee-duration: 40s;
  overflow: hidden;
  position: relative;
  mask-image: linear-gradient(
    90deg,
    transparent 0,
    #000 var(--sp-12),
    #000 calc(100% - var(--sp-12)),
    transparent 100%
  );
  -webkit-mask-image: linear-gradient(
    90deg,
    transparent 0,
    #000 var(--sp-12),
    #000 calc(100% - var(--sp-12)),
    transparent 100%
  );
}
.marquee-track {
  display: flex;
  gap: var(--sp-10);
  width: max-content;
  animation: marquee-scroll var(--marquee-duration) linear infinite;
  will-change: transform;
}
.marquee:hover .marquee-track { animation-play-state: paused; }

.marquee-item {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  color: var(--fg-muted);
  font-size: var(--fs-15);
}

@keyframes marquee-scroll {
  from { transform: translateX(0); }
  /* -50% because we duplicate the content inside .marquee-track,
     so one full pass scrolls us to the start of the second copy. */
  to   { transform: translateX(-50%); }
}

@media (prefers-reduced-motion: reduce) {
  .marquee-track { animation: none; }
}

/* ---------- Pricing cards ----------
   Multi-tier pricing layout. Two to four cards side-by-side. When
   more than one card exists, add `.featured` to the preferred tier
   to highlight it with a gradient border + elevation.

   A single card doesn't need the grid — use a plain .card.
   This pattern is for comparison.

   Structure:
     <div class="pricing-cards">
       <article class="pricing-card">
         <div class="pricing-tier">Starter</div>
         <div class="pricing-price">
           <span class="pricing-amount">$0</span>
           <span class="pricing-period">/mo</span>
         </div>
         <p class="pricing-tagline">For trying things out</p>
         <ul class="feature-list"> … </ul>
         <a class="btn btn-outline">Get started</a>
       </article>
       <article class="pricing-card featured">…</article>
       <article class="pricing-card">…</article>
     </div>

   The `.pricing-toggle` below is a visual monthly/yearly switch —
   page owns the state binding. */
.pricing-grid,
.pricing-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: var(--sp-6);
  align-items: stretch;
  margin-top: var(--sp-10);
}
.pricing-grid:has(:only-child),
.pricing-cards:has(:only-child) {
  max-width: 440px;
  margin-inline: auto;
}

.pricing-card {
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
  padding: var(--sp-8);
  background: var(--bg-surface-3);
  border: 1px solid var(--border-subtle);
  border-radius: var(--r-lg);
  position: relative;
  transition: transform var(--dur-base) var(--ease-out),
              border-color var(--dur-base) var(--ease-out),
              box-shadow var(--dur-base) var(--ease-out);
}
.pricing-card:hover {
  transform: translateY(-2px);
  border-color: var(--border-strong);
  box-shadow: var(--shadow-lg);
}

/* Featured tier — gradient border via conic sweep + sits 8px
   higher than its neighbors so it reads as "this one." The
   .featured-badge is an optional floating label at the top. */
.pricing-card.featured {
  border-color: transparent;
  background:
    linear-gradient(var(--bg-surface-3), var(--bg-surface-3)) padding-box,
    var(--product-grad) border-box;
  border: 1px solid transparent;
  box-shadow: var(--shadow-glow);
  transform: translateY(-8px);
}
.pricing-card.featured:hover {
  transform: translateY(-10px);
  box-shadow: var(--shadow-xl), var(--shadow-glow);
}
.pricing-card .featured-badge {
  position: absolute;
  top: calc(var(--sp-3) * -1);
  left: 50%;
  transform: translateX(-50%);
  padding: var(--sp-1) var(--sp-3);
  background: var(--product-grad);
  color: var(--fg-on-brand);
  border-radius: var(--r-full);
  font-size: var(--fs-12);
  font-weight: var(--fw-bold);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  white-space: nowrap;
}

.pricing-tier {
  font-family: var(--font-display);
  font-size: var(--fs-15);
  font-weight: var(--fw-semibold);
  color: var(--fg-muted);
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.pricing-price {
  display: flex;
  align-items: baseline;
  gap: var(--sp-1);
}
.pricing-amount {
  font-family: var(--font-display);
  font-size: var(--fs-48);
  font-weight: var(--fw-bold);
  line-height: var(--lh-tight);
  color: var(--fg-primary);
}
.pricing-period {
  font-size: var(--fs-15);
  color: var(--fg-muted);
}
.pricing-tagline {
  color: var(--fg-muted);
  font-size: var(--fs-15);
  margin: 0;
}
.pricing-card .feature-list { flex-grow: 1; }
.pricing-card .badge { align-self: center; }
.pricing-card .btn { width: 100%; justify-content: center; }

/* ---------- Pricing toggle ----------
   Visual monthly/yearly switch. Page owns the state — you toggle
   [data-active="monthly"] / [data-active="yearly"] on this element
   and the pill slides. Both labels stay clickable.

   Structure:
     <div class="pricing-toggle" data-active="monthly">
       <button type="button" data-value="monthly">Monthly</button>
       <button type="button" data-value="yearly">Yearly <span class="pill-coming-soon">-20%</span></button>
     </div> */
.pricing-toggle {
  display: inline-flex;
  padding: 4px;
  background: var(--bg-surface-3);
  border: 1px solid var(--border-subtle);
  border-radius: var(--r-full);
  position: relative;
}
.pricing-toggle button {
  position: relative;
  z-index: 1;
  flex: 1;
  padding: var(--sp-2) var(--sp-5);
  background: transparent;
  border: 0;
  color: var(--fg-muted);
  font-family: inherit;
  font-size: var(--fs-14);
  font-weight: var(--fw-semibold);
  cursor: pointer;
  border-radius: var(--r-full);
  transition: color var(--dur-base) var(--ease-out);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
}
.pricing-toggle button:hover { color: var(--fg-primary); }
.pricing-toggle[data-active="monthly"] button[data-value="monthly"],
.pricing-toggle[data-active="yearly"] button[data-value="yearly"] {
  color: var(--fg-on-brand);
}
/* Sliding highlight — the pill that sits behind the active label. */
.pricing-toggle::before {
  content: "";
  position: absolute;
  top: 4px; bottom: 4px;
  left: 4px;
  width: calc(50% - 4px);
  background: var(--product-grad);
  border-radius: var(--r-full);
  transition: transform var(--dur-base) var(--ease-standard);
  z-index: 0;
}
.pricing-toggle[data-active="yearly"]::before {
  transform: translateX(100%);
}

@media (max-width: 768px) {
  .pricing-grid,
  .pricing-cards { grid-template-columns: 1fr; }
  .pricing-card.featured { transform: none; }
  .pricing-card.featured:hover { transform: translateY(-2px); }
}

/* ---------- Coming-soon pill ----------
   Small status pill for "not yet" features. Uses the product accent
   tint so it reskins per product. */
.pill-coming-soon {
  display: inline-block;
  padding: 1px var(--sp-2);
  background: var(--section-tint);
  color: var(--section-accent);
  border-radius: var(--r-full);
  font-size: var(--fs-12);
  font-weight: var(--fw-semibold);
  text-transform: uppercase;
  letter-spacing: 0.03em;
  vertical-align: middle;
  margin-left: var(--sp-1);
}

/* ---------- Rotator ----------
   Inline span whose text content cycles through a list of strings
   defined in `data-rotate` (JSON array). Driven by rotator.js. The
   `.is-out` state is toggled by JS to fade the word during the swap.
   Width is intentionally not pinned: variants can have different
   widths and the layout reflows around them. */
.rotator {
  display: inline-block;
  line-height: inherit;
  padding-bottom: 0.12em;
  margin-bottom: -0.12em;
  transition: opacity 220ms ease, transform 220ms ease;
}
.rotator.is-out {
  opacity: 0;
  transform: translateY(-0.15em);
}
@media (prefers-reduced-motion: reduce) {
  .rotator { transition: none; }
  .rotator.is-out { transform: none; }
}
