
/* ============================================================
   GUARD: BASE_CSS is a tagged-template-literal string. Do NOT
   use backticks inside any block comment below — they terminate
   the string and break the build. Use single quotes when
   referencing CSS or JS snippets in comments. (D-093 + D-100 hit
   this; D-105 codified the rule.)
   ============================================================ */
/* D-115: Space Grotesk variable font, self-hosted via R2. wght axis 300-700. */
@font-face {
  font-family: 'Space Grotesk';
  src: url('/assets/r2/fonts/SpaceGrotesk-VariableFont_wght.woff2') format('woff2-variations'),
       url('/assets/r2/fonts/SpaceGrotesk-VariableFont_wght.woff2') format('woff2');
  font-weight: 300 700;
  font-style: normal;
  font-display: swap;
}

/* D-116: Locked-in palette. Supersedes prior aspirational tokens.
   Primary brand: Electric Cyan / Neon Teal / Signal Red / Deep Navy / Dark Navy
   Supporting: Cloud White / Steel Blue / Void Black
   Usage ratio: 70% dark backgrounds · 20% neutral text · 10% accent.
   "Accents are signals, not decoration." */
:root {
  /* §3.1 backgrounds */
  --color-bg: #050C1A;                    /* D-116 Deep Navy (was #08111F) */
  --color-bg-deep: #020810;               /* D-116 Void Black */
  --color-surface-elevated: #0A1628;      /* D-116 Dark Navy (was #152856) */
  --color-surface-muted: rgba(10, 22, 40, 0.60);

  /* §3.2 text */
  --color-text: #E8F0FF;                  /* D-116 Cloud White (was #E8EDF8) */
  --color-text-strong: #FFFFFF;
  --color-text-muted: #8093B5;            /* D-211 Steel Blue (lightened from D-116 #6B7FA3) — ~5.8:1 on --color-bg, ~4.6-5.5:1 on tinted/glass surfaces = AA on BOTH. Raised so muted text on .card / .partner-card__blurb / .faq-item / .testimonial-card__role / .field-help clears 4.5:1 (was 4.31-4.48 at #6B7FA3, a 1.4.3 AA fail on tinted surfaces). */
  --color-text-placeholder: #8093B5;

  /* §3.3 accents — single cyan, both tokens point at same value (D-116) */
  --color-primary: #00C2FF;               /* Electric Cyan */
  --color-emphasis: #00C2FF;              /* same — semantic alias kept for use-site clarity */

  /* §3.3.1 cool accent — D-116 Neon Teal. Metrics, data, success states, hover.
     Replaces retired --color-accent-green (D-074, retired by D-116). */
  --color-accent-teal: #00FFD1;
  --color-accent-teal-rgb: 0, 255, 209;

  /* §3.3.2 warm accent — D-085 (retuned D-086, D-087). Rim + accent only, not paint. */
  --color-accent-warm: #D2CFC0;
  --color-accent-warm-rgb: 210, 207, 192;

  /* §3.4 semantic. --color-success aliased to teal per D-116. */
  --color-success: #00FFD1;               /* was #22D68F — now Neon Teal */
  --color-warning: #F5A623;
  --color-danger: #FF4136;                /* D-116 Signal Red (was #FF4757) — use sparingly */

  /* §3.5 borders */
  --color-border: rgba(255, 255, 255, 0.08);
  --color-border-accent: rgba(0, 194, 255, 0.20);
  --color-border-glow: rgba(0, 194, 255, 0.40);

  /* §3.5.1 glass surface variants (D-116) — building blocks for new code.
     Existing glass recipes (.pillar-card / .showcase-card /
     .section--narrative / .flagship-hero) NOT migrated in D-116; they keep their
     hand-tuned dark-translucent fills. Future glass surfaces should reference these. */
  --glass-fill-subtle: rgba(255, 255, 255, 0.03);
  --glass-fill-default: rgba(255, 255, 255, 0.06);
  --glass-fill-strong: rgba(255, 255, 255, 0.09);
  --glass-fill-ultra: rgba(255, 255, 255, 0.12);
  --glass-blur-subtle: 12px;
  --glass-blur-default: 20px;
  --glass-blur-strong: 28px;
  --glass-blur-ultra: 40px;
  --glass-border-subtle: rgba(255, 255, 255, 0.08);
  --glass-border-default: rgba(255, 255, 255, 0.15);
  --glass-border-strong: rgba(255, 255, 255, 0.20);
  --glass-border-ultra: rgba(255, 255, 255, 0.28);

  /* §3.7 typography */
  --font-display: 'Space Grotesk', system-ui, -apple-system, sans-serif;
  --font-sans: 'Space Grotesk', system-ui, -apple-system, sans-serif;

  /* §3.8 type scale (mobile baseline; desktop overrides via @media) */
  --text-xs: 0.75rem;
  --text-sm: 0.875rem;
  --text-base: 1rem;
  --text-lg: 1.125rem;
  --text-xl: 1.25rem;
  --text-2xl: 1.5rem;
  --text-3xl: 1.875rem;
  --text-4xl: 2.25rem;
  --text-5xl: 2.75rem;

  --leading-tight: 1.1;
  --leading-snug: 1.25;
  --leading-normal: 1.5;
  --leading-relaxed: 1.65;

  --weight-regular: 400;
  --weight-medium: 500;
  --weight-semibold: 600;
  --weight-bold: 700;
  /* D-115: capped at 700 — Space Grotesk's heaviest weight. Was 800/900. */
  --weight-heavy: 700;
  --weight-black: 700;

  /* §3.9 spacing scale (8px base) */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.25rem;
  --space-6: 1.5rem;
  --space-8: 2rem;
  --space-10: 2.5rem;
  --space-12: 3rem;
  --space-16: 4rem;
  --space-20: 5rem;
  --space-24: 6rem;

  /* §3.9.1 section rhythm — see WIREFRAME-PRINCIPLES §2 */
  --section-gap: var(--space-16);

  /* §3.10 radius */
  --radius-md: 8px;
  --radius-lg: 12px;
  --radius-xl: 16px;
  --radius-pill: 9999px;

  /* §3.11 shadow + glow */
  --shadow-md: 0 4px 16px rgba(0,0,0,0.60), 0 0 0 1px var(--color-border-accent);
  --shadow-glow-sm: 0 0 16px rgba(0,150,255,0.20);
  --shadow-glow-md: 0 0 32px rgba(0,150,255,0.30), 0 0 64px rgba(0,150,255,0.10);

  /* §3.11 text-shadow — depth on display headings + emphasis numbers only.
     NOT applied to body, lead, captions, nav links. Subtle by design.
     D-056: --text-shadow-glow halo halved (24/0.18 → 14/0.09) — was reading
     as flashy-fintech instead of premium-fintech. */
  --text-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.45);
  --text-shadow-md: 0 2px 6px rgba(0, 0, 0, 0.55);
  --text-shadow-glow: 0 0 14px rgba(0, 194, 255, 0.09);

  /* §3.12 gradients (D-116 lock-in; supersedes D-057/D-056 cyan stops) */
  --gradient-cta: linear-gradient(135deg, #00C2FF 0%, #00A8E0 100%);
  --gradient-text-hero: linear-gradient(135deg, #FFFFFF 0%, #00C2FF 100%);
  --gradient-hero: linear-gradient(135deg, #050C1A 0%, #0D1F3C 50%, #071828 100%);
  --gradient-icon-bg: linear-gradient(135deg, rgba(0, 194, 255, 0.15) 0%, rgba(0, 255, 209, 0.10) 100%);
  --gradient-glow: radial-gradient(ellipse, rgba(0, 194, 255, 0.25) 0%, transparent 70%);

  /* layout containers */
  --container-max: 1200px;
  --container-narrow: 640px;
}

@media (min-width: 768px) {
  :root {
    /* §3.8 desktop overrides */
    --text-xl: 1.5rem;
    --text-2xl: 2rem;
    --text-3xl: 2.5rem;
    --text-4xl: 3.5rem;
    --text-5xl: 4.5rem;
  }
}

@media (min-width: 1024px) {
  :root {
    /* §3.9.1 section rhythm desktop step (WIREFRAME-PRINCIPLES §2) */
    --section-gap: var(--space-24);
  }
}

/* ============================================================
   Reset + base
   ============================================================ */
*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }
/* D-199: deliberately NO global overflow-x:clip. D-198 added it as an overflow
   net, but a clip ancestor stalls iOS Safari's young scroll-driven-animation
   engine, freezing the view() reveal cards (.crosslink-card + the pillar/feature
   reveals, animation-fill-mode:both) at opacity:0 — laid out and clickable but
   invisible. Horizontal overflow is fixed at SOURCE instead (min-width:0 on the
   flex/grid items — see .hero-asset and .addon-meta), which fully covers mobile.
   If a new breakout appears, clip its LOCAL wrapper, never html or body. */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

body {
  margin: 0;
  background-color: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-sans);
  font-size: var(--text-base);
  line-height: var(--leading-normal);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* Sitewide ambient lighting + grain — viewport-locked, painted behind all
   content via two fixed pseudo-elements. One continuous background; no
   section-level background overrides anywhere on the site.
   D-055: ambient toned down + brand-palette aligned. Off-palette indigo
   (rgba 60,0,180) was the loudest tell of "stock SaaS gradient" — replaced
   with a deeper cyan that reads as the same family. Opacities cut ~40–50%
   to match Apple-grade restraint while preserving the lit surface feel
   for frosted-glass cards above. */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: -2;
  pointer-events: none;
  /* D-116b: glow alphas dialed back ~30% for less-saturated ambient (10→07, 07→05, 04→03) */
  background:
    radial-gradient(ellipse 60% 50% at 10% 20%,
      rgba(0, 194, 255, 0.07) 0%, transparent 70%),
    radial-gradient(ellipse 50% 40% at 85% 75%,
      rgba(0, 90, 180, 0.05) 0%, transparent 65%),
    radial-gradient(ellipse 40% 30% at 60% 10%,
      rgba(0, 194, 255, 0.03) 0%, transparent 60%);
}
body::after {
  content: '';
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23n)' opacity='1'/%3E%3C/svg%3E");
  opacity: 0.04;
}

/* D-128: dot-grid lifted from .section--dot-grid modifier (retired in
   pillar.ts) to body-stack ambient layer. Sitewide except home — home
   opts out via bodyClass set on the route handler (home.ts). The
   override stacks dots ON TOP of the 3 ambient radial gradients from
   body::before above. Specificity 0,0,2,0 on body:not(.home)::before
   wins over body::before (0,0,1,0).

   D-116b alphas are mirrored from body::before — if you tune those,
   tune them here too. Dot alpha 0.07 cyan is the D-110c ratified value
   verified at 1.10:1 contrast on the body background (ambient texture
   rather than tier signal — per D-128 contrast math).

   Touch devices and reduced-motion get the 4-layer no-cursor version
   below; fine-pointer + motion-enabled get the 5-layer version with
   the D-129 cursor-brighten layer inside the @media block. */
body:not(.home)::before {
  background-image:
    radial-gradient(circle, rgba(0, 194, 255, 0.07) 1px, transparent 1.5px),
    radial-gradient(ellipse 60% 50% at 10% 20%,
      rgba(0, 194, 255, 0.07) 0%, transparent 70%),
    radial-gradient(ellipse 50% 40% at 85% 75%,
      rgba(0, 90, 180, 0.05) 0%, transparent 65%),
    radial-gradient(ellipse 40% 30% at 60% 10%,
      rgba(0, 194, 255, 0.03) 0%, transparent 60%);
  background-size: 32px 32px, 100% 100%, 100% 100%, 100% 100%;
  background-repeat: repeat, no-repeat, no-repeat, no-repeat;
}

/* D-129: extends D-022 glow-target system to the body-stack dot-grid
   surface. Compact radial cyan bloom following the cursor brightens the
   dots underneath. CSS variables --mouse-vx / --mouse-vy published by
   GLOW_TRACKER_JS (glow-tracker.ts) on document.documentElement; on load
   they default to 50%/50% — center — but the JS only runs on fine
   pointers with motion enabled, so this @media block is the only path
   that activates the brighten layer. B-004 pause toggle respects via
   body[data-paused] gating selector (extends naturally when B-004 lands).
   D-145: toned down from 200px @ 0.10α to 130px @ 0.04α per user feedback —
   "much more subtle, less noticeable with a smaller spread." Bloom now
   reads as a micro-presence-cue rather than a spotlight. */
@media (pointer: fine) and (prefers-reduced-motion: no-preference) {
  body:not(.home)::before {
    background-image:
      radial-gradient(circle 130px at var(--mouse-vx, 50%) var(--mouse-vy, 50%),
        rgba(0, 194, 255, 0.04), transparent),
      radial-gradient(circle, rgba(0, 194, 255, 0.07) 1px, transparent 1.5px),
      radial-gradient(ellipse 60% 50% at 10% 20%,
        rgba(0, 194, 255, 0.07) 0%, transparent 70%),
      radial-gradient(ellipse 50% 40% at 85% 75%,
        rgba(0, 90, 180, 0.05) 0%, transparent 65%),
      radial-gradient(ellipse 40% 30% at 60% 10%,
        rgba(0, 194, 255, 0.03) 0%, transparent 60%);
    background-size: 100% 100%, 32px 32px, 100% 100%, 100% 100%, 100% 100%;
    background-repeat: no-repeat, repeat, no-repeat, no-repeat, no-repeat;
  }
}

img, svg, video { max-width: 100%; height: auto; display: block; }

a { color: var(--color-primary); text-decoration: none; }
a:hover { color: var(--color-emphasis); }

/* D-117 Net Terms Plus hero logo — width-capped, vertically spaced */
.ntp-hero-logo {
  display: block;
  width: 100%;
  max-width: 560px;
  height: auto;
  margin: var(--space-6) auto var(--space-4);
}
a:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 3px; border-radius: 2px; }

button { font-family: inherit; }

::selection { background: rgba(0, 194, 255, 0.30); color: var(--color-text-strong); }

/* §9 skip link */
.skip-link {
  position: absolute;
  top: -100px;
  left: 0;
  background: var(--color-primary);
  color: var(--color-text-strong);
  padding: var(--space-3) var(--space-4);
  border-radius: 0 0 var(--radius-md) 0;
  z-index: 9999;
  font-weight: var(--weight-semibold);
  font-size: var(--text-sm);
}
.skip-link:focus { top: 0; }

/* ============================================================
   Typography
   ============================================================ */
h1, h2, h3, h4, h5, h6 {
  margin: 0 0 var(--space-4);
  color: var(--color-text-strong);
  font-family: var(--font-display);
  line-height: var(--leading-tight);
}
h1 { font-size: var(--text-5xl); font-weight: var(--weight-black); }
h2 { font-size: var(--text-3xl); font-weight: var(--weight-bold); line-height: var(--leading-snug); text-shadow: var(--text-shadow-sm); }
h3 { font-size: var(--text-2xl); font-weight: var(--weight-semibold); line-height: var(--leading-snug); }
h4 { font-size: var(--text-xl); font-weight: var(--weight-semibold); }

p { margin: 0 0 var(--space-4); }
.lead { font-size: var(--text-lg); color: var(--color-text); }
.eyebrow {
  text-transform: uppercase;
  letter-spacing: 0.12em;
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  /* D-084 + D-116: cyan emphasis (#00C2FF on #050C1A = 52:1 AAA per D-116 a11y). */
  color: var(--color-emphasis);
  margin-bottom: var(--space-3);
}

/* §3.15 gradient text — hero only */
.gradient-text {
  background: var(--gradient-text-hero);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
@media (prefers-contrast: more) {
  .gradient-text {
    background: none;
    -webkit-background-clip: unset;
    background-clip: unset;
    color: var(--color-text-strong);
  }
}
@media (forced-colors: active) {
  .gradient-text { color: ButtonText; }
}

/* ============================================================
   Layout primitives
   ============================================================ */
.container { max-width: var(--container-max); margin: 0 auto; padding: 0 var(--space-6); }
/* B-011: 640px base; widened to --container-max inside .section--narrative (D-109) */
.container-narrow { max-width: var(--container-narrow); margin: 0 auto; padding: 0 var(--space-6); }
.section { padding: var(--section-gap) 0; }

/* §3.13 + §3.14 — ambient gradient + grain are now sitewide on body::before
   and body::after (viewport-locked). The .hero-ambient-bg and .grain-overlay
   classes are retired; the hero inherits the same ambient as every other
   section by virtue of body painting it once for the whole page. */

/* §3.16 mouse glow — only on fine pointer per Compass §7 INP gate */
@media (pointer: fine) and (prefers-reduced-motion: no-preference) {
  .glow-target { position: relative; overflow: hidden; }
  .glow-target::before {
    content: '';
    position: absolute;
    inset: 0;
    background: radial-gradient(
      circle at var(--mouse-x, 50%) var(--mouse-y, 50%),
      rgba(0, 194, 255, 0.12) 0%,
      transparent 60%
    );
    opacity: 0;
    transition: opacity 200ms ease;
    pointer-events: none;
  }
  .glow-target:hover::before { opacity: 1; }
}

/* Hero float — D-120 reinstates D-060 (D-107 removed) at ±6px/6s.
   Reduced-motion gated, scoped to .hero-image-wrap (home only). */
@media (prefers-reduced-motion: no-preference) {
  .hero-image-wrap .hero-asset {
    animation: hero-float 6s ease-in-out infinite alternate;
  }
}
@keyframes hero-float {
  from { transform: translateY(0); }
  to   { transform: translateY(-6px); }
}

/* ============================================================
   §6.1 buttons
   ============================================================ */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-6);
  border-radius: var(--radius-md);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  text-decoration: none;
  border: none;
  cursor: pointer;
  min-height: 44px;
  transition: transform 150ms ease, box-shadow 200ms ease, background 200ms ease;
  position: relative;
}
.btn-primary {
  background: var(--gradient-cta);
  color: var(--color-bg); /* D-116 a11y fix: dark text on cyan = 51:1 AAA (was white at 2.3:1 FAIL) */
}
.btn-primary:hover {
  transform: scale(1.02);
  box-shadow: var(--shadow-glow-sm);
  /* D-226 a11y: no color flip on hover. White-on-cyan was ~2.3:1 (the exact D-116 fail); the dark base text (51:1) must persist on hover. */
}
.btn-primary:active { transform: scale(0.98); }
.btn-primary:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 3px; }
.btn-primary[disabled], .btn-primary[aria-disabled="true"] { opacity: 0.45; cursor: not-allowed; transform: none; }

.btn-secondary {
  background: transparent;
  color: var(--color-primary);
  border: 1px solid var(--color-border-accent);
}
.btn-secondary:hover {
  background: rgba(0, 194, 255, 0.08);
  border-color: var(--color-border-glow);
  color: var(--color-emphasis);
}

/* Glassmorphic — frosted-glass surface for secondary nav CTAs (Pricing).
   Sits beside the primary CTA without competing for attention. */
.btn-glass {
  background-color: rgba(255, 255, 255, 0.10);
  background-image: linear-gradient(180deg, rgba(255, 255, 255, 0.10) 0%, rgba(255, 255, 255, 0.04) 100%);
  color: var(--color-text-strong);
  border: 1px solid rgba(255, 255, 255, 0.22);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.16);
  backdrop-filter: blur(24px) saturate(200%);
  -webkit-backdrop-filter: blur(24px) saturate(200%);
}
.btn-glass:hover {
  background-color: rgba(255, 255, 255, 0.16);
  border-color: var(--color-border-glow);
  color: var(--color-emphasis);
  box-shadow: var(--shadow-glow-sm), inset 0 1px 0 rgba(255, 255, 255, 0.20);
}
.btn-glass:focus-visible {
  outline: 2px solid var(--color-emphasis);
  outline-offset: 3px;
}
@supports not (backdrop-filter: blur(1px)) {
  .btn-glass { background: rgba(40, 60, 95, 0.78); }
}

@media (max-width: 640px) {
  .btn-block-mobile { width: 100%; }
}

/* ============================================================
   §6.2 cards — frosted glass surface (D-052)
   Subtle white tint + backdrop-blur for depth without breaking
   the sitewide ambient (cards still read as outlined frames, just
   with a touch of frost milkiness). Performance: ≤16 cards per
   page = budget-safe for backdrop-filter compositor layers.
   ============================================================ */
.card {
  background-color: rgba(255, 255, 255, 0.04);
  background-image: linear-gradient(180deg, rgba(255, 255, 255, 0.05) 0%, rgba(255, 255, 255, 0.01) 100%);
  border: 1px solid var(--color-border-accent);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md), inset 0 1px 0 rgba(255, 255, 255, 0.08);
  padding: var(--space-6);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  transition: border-color 200ms ease, box-shadow 200ms ease, background-color 200ms ease;
}
.card:hover {
  background-color: rgba(255, 255, 255, 0.06);
  border-color: var(--color-border-glow);
  box-shadow: var(--shadow-glow-sm), inset 0 1px 0 rgba(255, 255, 255, 0.10);
}
@supports not (backdrop-filter: blur(1px)) {
  .card { background-color: rgba(20, 35, 65, 0.55); }
}
@media (max-width: 640px) { .card { padding: var(--space-4); } }

/* metric cards — outlined-frame depth (D-061): smaller numerals, layered
   shadow + top-anchored radial bloom for sense of weight without breaking
   the no-section-bg rule. Cohesion w/ pillar-card + convergence-card. */
.card-metric {
  text-align: center;
  position: relative;
  overflow: hidden;
  /* D-106: prevent metric-number ($1.2M, $250K+, etc.) from forcing the
     card wider than its grid cell. Combined with the clamp() on
     .metric-number below, the card now holds at any viewport. */
  min-width: 0;
  overflow-wrap: break-word;
}
.card-metric::before {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse 80% 50% at 50% 0%, rgba(0, 194, 255, 0.05) 0%, transparent 70%); /* D-116b: 0.07 → 0.05 */
  pointer-events: none;
  border-radius: inherit;
}
.card-metric > * { position: relative; }
.card-metric .metric-number {
  display: block;
  font-family: var(--font-display);
  /* D-106: clamp replaces @media override; tested $1.2M / 100% / #292 / $250K+ / 28K+ / 6M+ */
  font-size: clamp(1.875rem, 1.2rem + 2.4vw, 3.5rem);
  font-weight: var(--weight-black);
  color: var(--color-emphasis);
  line-height: 1;
  margin-bottom: var(--space-2);
  letter-spacing: -0.01em;
  text-shadow:
    0 1px 2px rgba(0, 0, 0, 0.50),
    0 4px 16px rgba(0, 0, 0, 0.35),
    0 0 18px rgba(0, 194, 255, 0.18);
}
.card-metric .metric-label {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  letter-spacing: 0.01em;
}

/* ============================================================
   §6.3 form fields
   ============================================================ */
.field { margin-bottom: var(--space-5); }
.field label {
  display: block;
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  color: var(--color-text);
  margin-bottom: var(--space-2);
}
.field input,
.field select,
.field textarea {
  width: 100%;
  background: var(--color-surface-elevated);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
  color: var(--color-text);
  font-family: var(--font-sans);
  font-size: var(--text-base);
  min-height: 44px;
}
.field input::placeholder { color: var(--color-text-placeholder); }
.field input:focus,
.field select:focus,
.field textarea:focus {
  outline: none;
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px rgba(0, 194, 255, 0.20);
}
.field input[aria-invalid="true"] {
  border-color: var(--color-danger);
  box-shadow: 0 0 0 3px rgba(255, 65, 54, 0.15); /* D-226: #FF4136 (D-116 danger); was the retired #FF4757 */
}
.field-error {
  display: block;
  margin-top: var(--space-2);
  font-size: var(--text-xs);
  color: var(--color-danger);
}
.field-help {
  display: block;
  margin-top: var(--space-2);
  font-size: var(--text-xs);
  color: var(--color-text-muted);
}

/* ============================================================
   B-004 — WCAG 2.2.2 (Pause, Stop, Hide) Level A pause toggle.

   Universal selector: when body[data-paused] is set, ALL CSS keyframe
   animations sitewide pause via animation-play-state. Transitions are
   unaffected, so hover states and the toggle button itself still respond.
   Reduced-motion (WCAG 2.3.3) operates independently — users with OS-level
   reduced-motion already see static rendering; the toggle button is
   hidden in that case so we do not present a redundant control.

   Cloudflare Stream iframes pause separately via postMessage in
   PAUSE_TOGGLE_JS (components/pause-toggle.ts). Same body[data-paused]
   signal, two coordinated effects (CSS animations + video loops).
   ============================================================ */
body[data-paused] *,
body[data-paused] *::before,
body[data-paused] *::after {
  animation-play-state: paused !important;
}

.pause-anim-toggle {
  position: fixed;
  bottom: var(--space-6);
  left: var(--space-6);                /* D-200/D-207: bottom-LEFT, 24px inset — mirrors the Orbit chat launcher (bottom-right, 24px) so the two read as a balanced pair */
  z-index: 100;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 44px;                    /* WCAG 2.5.5 target size */
  padding: var(--space-2) var(--space-3); /* D-182: tighter — single-word "Animations" label, less imposing */
  border-radius: var(--radius-md);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  cursor: pointer;
  /* Glass surface — sibling to .btn-glass but compact and pinned */
  background-color: rgba(255, 255, 255, 0.10);
  background-image: linear-gradient(180deg, rgba(255, 255, 255, 0.10) 0%, rgba(255, 255, 255, 0.04) 100%);
  color: var(--color-text-strong);
  border: 1px solid rgba(255, 255, 255, 0.22);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.16), 0 4px 16px rgba(0, 0, 0, 0.32);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  transition: background-color 200ms ease, border-color 200ms ease, transform 150ms ease, box-shadow 200ms ease;
}
.pause-anim-toggle:hover {
  background-color: rgba(255, 255, 255, 0.16);
  border-color: var(--color-border-glow);
  color: var(--color-emphasis);
}
.pause-anim-toggle:focus-visible {
  outline: 2px solid var(--color-emphasis);
  outline-offset: 3px;
}
.pause-anim-toggle:active {
  transform: scale(0.97);
}
@supports not (backdrop-filter: blur(1px)) {
  .pause-anim-toggle { background-color: rgba(40, 60, 95, 0.78); }
}

.pause-anim-toggle__icon {
  width: 16px;
  height: 16px;
  flex: 0 0 16px;
  color: var(--color-primary);
}
/* Show pause icon when animations are playing (default); show play icon
   when animations are paused. Swapped via body[data-paused]. */
.pause-anim-toggle__icon--play { display: none; }
body[data-paused] .pause-anim-toggle__icon--pause { display: none; }
body[data-paused] .pause-anim-toggle__icon--play { display: inline-block; }

.pause-anim-toggle__label {
  white-space: nowrap;
}

/* Hide the toggle on reduced-motion — users with OS preference set
   already see static rendering; the toggle is redundant + adds visual
   clutter for users who explicitly opted out of motion. */
@media (prefers-reduced-motion: reduce) {
  .pause-anim-toggle { display: none; }
}

/* Mobile: toggle stays visible but shrinks to icon-only to preserve
   thumb-reach and content readability on small screens. */
@media (max-width: 640px) {
  .pause-anim-toggle {
    padding: 0;
    width: 44px;
    justify-content: center;
  }
  .pause-anim-toggle__label { display: none; }
}

/* ============================================================
   §5 nav (header)
   ============================================================ */
.nav {
  position: sticky;
  top: 0;
  z-index: 100;
  background-color: rgba(15, 28, 52, 0.40);
  background-image: linear-gradient(180deg, rgba(255, 255, 255, 0.06) 0%, rgba(255, 255, 255, 0.02) 100%);
  backdrop-filter: blur(28px) saturate(200%);
  -webkit-backdrop-filter: blur(28px) saturate(200%);
  border-bottom: 1px solid rgba(255, 255, 255, 0.10);
}
@supports not (backdrop-filter: blur(1px)) {
  .nav { background: rgba(8, 17, 31, 0.96); }
}
.nav-inner {
  max-width: var(--container-max);
  margin: 0 auto;
  padding: var(--space-4) var(--space-6);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-6);
}
.nav-brand {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  color: var(--color-text-strong);
  font-family: var(--font-display);
  font-weight: var(--weight-heavy);
  font-size: var(--text-lg);
}
.nav-brand img {
  display: block;
  height: 36px;
  width: auto;
  max-width: 100%;
  /* White-tint the logo against the dark navy nav. brightness(0) flattens
     the source PNG to pure black; invert(1) flips that to pure white.
     Preserves wordmark shape; trades brand color for legibility.
     drop-shadow adds a very subtle cyan halo (D-116 --color-primary at
     0.18 alpha) so the white wordmark feels lit, not flat. */
  filter: brightness(0) invert(1)
          drop-shadow(0 0 4px rgba(0, 194, 255, 0.18));
}
.nav-brand:hover { color: var(--color-text-strong); }

.nav-links {
  display: none;
  gap: var(--space-6);
  list-style: none;
  margin: 0;
  padding: 0;
}
.nav-links a {
  color: var(--color-text);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  transition: color 150ms ease;
}
.nav-links a:hover { color: var(--color-text-strong); }
.nav-links a[aria-current="page"] { color: var(--color-emphasis); }

.nav-cta { display: none; }
.nav-cta-group { display: none; }

@media (min-width: 1024px) {
  .nav-links { display: flex; }
  .nav-cta { display: inline-flex; }
  .nav-cta-group { display: inline-flex; gap: var(--space-3); align-items: center; }
  .nav-toggle { display: none; }
}

.nav-toggle {
  background: none;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  color: var(--color-text-strong);
  padding: var(--space-2) var(--space-3);
  font-size: var(--text-sm);
  cursor: pointer;
  min-height: 44px;
  min-width: 44px;
}

.nav-drawer {
  display: none;
  background: rgba(8, 17, 31, 0.92);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--color-border);
}
.nav-drawer.open { display: block; }
.nav-drawer ul {
  list-style: none;
  margin: 0;
  padding: var(--space-4) var(--space-6);
}
.nav-drawer li { padding: var(--space-3) 0; border-bottom: 1px solid var(--color-border); }
.nav-drawer li:last-child { border-bottom: none; }
.nav-drawer a {
  color: var(--color-text);
  font-size: var(--text-base);
  font-weight: var(--weight-medium);
  display: block;
  padding: var(--space-2) 0;
}
.nav-drawer .nav-drawer-cta { padding: var(--space-4) var(--space-6) var(--space-6); }

/* ============================================================
   §6.5 hero
   ============================================================ */
.hero {
  padding: var(--space-16) 0 var(--space-20);
}
@media (min-width: 1024px) {
  .hero { padding: var(--space-24) 0; }
}
.hero-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-10);
  align-items: center;
}
@media (min-width: 1024px) {
  .hero-grid { grid-template-columns: 55fr 45fr; gap: var(--space-12); }
}
.hero h1 {
  font-size: var(--text-5xl);
  margin-bottom: var(--space-6);
  text-shadow: var(--text-shadow-md), var(--text-shadow-glow);
}
/* D-106: drop-shadow replaces text-shadow on .gradient-text (composites against glyph, not transparent fill) */
.hero h1.gradient-text {
  text-shadow: none;
  filter: drop-shadow(0 2px 6px rgba(0, 0, 0, 0.45));
}
/* D-235: the home hero carries .gradient-text on the CHILD spans (.hero-line +
   rotator phrases), so the .hero h1.gradient-text rule above never reaches them
   — they were left with the inherited .hero h1 text-shadow, which composites
   muddily against the transparent gradient fill (the D-106 problem) and read as
   washed-out vs the pillar heroes. Give them the same clean treatment plus extra
   layered depth and a top-edge emboss highlight, per Jake (home hero: more
   opaque, more depth/embossment). Home-only: these classes exist only here. */
.hero-line.gradient-text,
.rotator__phrase.gradient-text {
  text-shadow: none;
  filter:
    drop-shadow(0 -1px 0.5px rgba(255, 255, 255, 0.30))
    drop-shadow(0 1px 1px rgba(0, 0, 0, 0.55))
    drop-shadow(0 4px 10px rgba(0, 0, 0, 0.42));
}
.hero .hero-sub {
  font-size: var(--text-lg);
  color: var(--color-text);
  margin-bottom: var(--space-8);
  max-width: 56ch;
  line-height: var(--leading-normal);
}
@media (min-width: 1024px) {
  .hero .hero-sub { font-size: var(--text-xl); }
}
.hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-bottom: var(--space-6);
}
/* D-090: removed dead .hero-badges and .badge rules (zero markup refs). */
.hero-asset {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  /* Very faint ambient glow behind the transparent dashboard PNG —
     just enough to give the image atmosphere without becoming a card. */
  background:
    radial-gradient(ellipse 70% 60% at 50% 50%,
      rgba(0, 194, 255, 0.07) 0%,
      rgba(0, 194, 255, 0.04) 35%,
      transparent 75%);
}
/* D-198 mobile overflow fix: .hero-asset is a grid item in .hero-grid (1fr on
   mobile) AND a flex container; both default to min-width:auto, which let the
   bespoke pillar hero SVGs (intrinsic ~420px, no width attr — sized only by the
   global svg{max-width:100%} at base.ts:129) pin the single mobile column and
   overflow narrow viewports by ~100px. min-width:0 releases the grid+flex chain
   so the SVG scales down to fit. Scoped to the asset chain only (the text
   column has no wide intrinsic child); desktop 55fr/45fr is unaffected. */
.hero-asset,
.hero-asset > * { min-width: 0; }

/* =============================================================================
   D-215: /product hub hero — "Aurora Drift" (supersedes the D-214 folder PNG +
   the D-110-era renderOrbitalHero). Stripe flowing-gradient FEEL via cheap CSS:
   3 blurred radial-gradient ELEMENTS drifting on long sine loops, behind a
   static glass brand mark (the calm "one source of truth" focal point).
   GPU-only: animate transform + opacity + filter ONLY. NO color-stop /
   background-position / layout animation. NO mix-blend-mode (plain opacity
   layering inside isolation:isolate). The LCP H1 is NEVER animated. Hardened
   per the D-215 design workflow's 3-lens judging (Compass/Iris/Atlas).
   ============================================================================= */
.hero-asset--aurora {
  position: relative;
  isolation: isolate;          /* contain stacking/blend to this column */
  aspect-ratio: 1 / 1;         /* CLS guard: reserves final square space */
  width: 100%;
  max-width: 520px;
  margin-inline: auto;
  min-width: 0;                /* preserve the D-198 overflow chain */
}

/* Aurora field: 3 blurred gradient ELEMENTS, moved only by transform/opacity. */
.aurora {
  position: absolute;
  inset: -6%;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
  border-radius: var(--radius-xl);
  -webkit-mask-image: radial-gradient(closest-side, #000 52%, transparent 100%);
          mask-image: radial-gradient(closest-side, #000 52%, transparent 100%);
}
.aurora__blob {
  position: absolute;
  display: block;
  width: 86%;
  height: 86%;
  border-radius: 50%;
  filter: blur(72px);          /* plain opacity layering, no blend mode */
  will-change: transform, opacity;
}
/* BASE state == the hand-composed reduced-motion STILL POSE. The pose lives in
   the base rule (NOT keyframe-0) because the global reduced-motion clamp only
   zeroes animation DURATION and pins no transform. */
.aurora__blob--a {
  left: -10%; bottom: -12%;
  background: radial-gradient(circle at 50% 50%, rgba(0,194,255,0.50) 0%, rgba(0,194,255,0) 68%);
  transform: translate3d(3%, -2%, 0) scale(1.05);
  opacity: 0.50;
}
.aurora__blob--b {
  right: -12%; top: -10%;
  background: radial-gradient(circle at 50% 50%, rgba(0,255,209,0.38) 0%, rgba(0,255,209,0) 66%);
  transform: translate3d(-2%, 2%, 0) scale(1.0);
  opacity: 0.45;
}
.aurora__blob--c {
  right: 4%; top: 32%;
  width: 58%; height: 58%;
  background: radial-gradient(circle at 50% 50%, rgba(0,194,255,0.32) 0%, rgba(0,194,255,0) 70%);
  transform: translate3d(-2%, 1%, 0) scale(0.96);
  opacity: 0.42;
}

/* Centered 3D folder figure (D-216: replaces the glass brand-mark disc, which
   read too basic). Transparent PNG; the aurora glows around + through it. The
   flex wrapper centers; the float animates the inner <img> transform so it
   never conflicts with centering. */
.aurora-figure {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}
.aurora-figure picture {
  display: block;
  width: 80%;
  max-width: 400px;
}
.aurora-figure img {
  display: block;
  width: 100%;
  height: auto;
  filter: drop-shadow(0 12px 30px rgba(0,0,0,0.40)) drop-shadow(0 0 26px rgba(0,194,255,0.16));
}

/* MOTION — only when the user has not requested reduced motion. */
@media (prefers-reduced-motion: no-preference) {
  .aurora__blob--a { animation: aurora-a 18s cubic-bezier(0.4,0,0.2,1) infinite alternate; }
  .aurora__blob--b { animation: aurora-b 22s cubic-bezier(0.4,0,0.2,1) infinite alternate; }
  .aurora__blob--c { animation: aurora-c 14s cubic-bezier(0.4,0,0.2,1) infinite alternate; }

  /* Folder figure slow float — reuse the existing hero-float keyframe (base.ts). */
  .hero-asset--aurora .aurora-figure img { animation: hero-float 6s ease-in-out infinite alternate; }

  /* Materialize entrance — Premium tier, 480ms, 0% overshoot. SCOPED to the
     text column children EXCEPT the H1 (the LCP must paint final-state on the
     first pass) + the decorative asset column. */
  .hero-text > .eyebrow,
  .hero-text > .hero-sub,
  .hero-text > .hero-actions,
  .hero-asset--aurora {
    animation: hero-materialize 480ms cubic-bezier(0.4,0,0.2,1) both;
  }
  .hero-text > .eyebrow      { animation-delay: 0ms;   }
  .hero-text > .hero-sub     { animation-delay: 90ms;  }
  .hero-text > .hero-actions { animation-delay: 180ms; }
  .hero-asset--aurora        { animation-delay: 120ms; }
}

@keyframes hero-materialize {
  from { opacity: 0; transform: translateY(8px); filter: blur(4px); }
  to   { opacity: 1; transform: none;            filter: none;      }
}
@keyframes aurora-a {
  from { transform: translate3d(0,0,0) scale(1);       opacity: 0.45; }
  to   { transform: translate3d(6%,-4%,0) scale(1.12); opacity: 0.60; }
}
@keyframes aurora-b {
  from { transform: translate3d(0,0,0) scale(1.05);    opacity: 0.50; }
  to   { transform: translate3d(-5%,5%,0) scale(0.95); opacity: 0.35; }
}
@keyframes aurora-c {
  from { transform: translate3d(0,0,0) scale(0.9);     opacity: 0.30; }
  to   { transform: translate3d(-4%,3%,0) scale(1.08); opacity: 0.50; }
}

/* REDUCED MOTION — explicit composed still frame. The blob BASE rules already
   ARE the good pose; this belt-and-braces nukes animation + forces the text
   column to final state. */
@media (prefers-reduced-motion: reduce) {
  .aurora__blob { animation: none; }
  .hero-asset--aurora,
  .hero-asset--aurora .aurora-figure img { animation: none; }
  .hero-text > .eyebrow,
  .hero-text > .hero-sub,
  .hero-text > .hero-actions {
    animation: none; opacity: 1; transform: none; filter: none;
  }
}

/* THREE-VIEWPORT. Mobile + tablet (<1024px, single column): FREEZE the aurora
   to the still pose + shrink the blur so phone GPUs never composite perpetual
   large-area blur. Cap height so the square can't push CTAs below the fold. */
@media (max-width: 1023.98px) {
  .hero-asset--aurora { max-width: 360px; }
  .aurora__blob { animation: none !important; filter: blur(44px); }
  .hero-asset--aurora .aurora-figure img { animation: none !important; }
}
@media (max-width: 640px) {
  .hero-asset--aurora { max-width: 280px; }
  .aurora__blob { filter: blur(36px); }
}

/* D-106: orbit-line texture behind floating cv-card on Platform pillars (D-108: dropped from /product hub) */
:where(
  section.hero[aria-labelledby="pillar-h1"]
) .hero-asset:not(.hero-asset--orbital):not(.hero-asset--meter):not(.hero-asset--markup):not(.hero-asset--reconcile):not(.hero-asset--claims):not(.hero-asset--analytics):not(.hero-asset--orbit-ai):not(.hero-asset--comprehensive-billing)::before {
  content: '';
  position: absolute;
  /* Fill the entire hero-asset column edge-to-edge. */
  inset: 0;
  background-image: url('/assets/r2/backgrounds%2Fabstract-orbit-lines.png');
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  mix-blend-mode: screen;
  opacity: 0.22;
  pointer-events: none;
}

/* Home hero — vertical stack with full-container image below the text.
   The image gets a wider canvas than the old 50/50 grid, but text stays
   tight so the visual weight lands on the dashboard. */
.hero-image-wrap {
  margin-top: var(--space-10);
  position: relative;
  isolation: isolate; /* clamp ::before z-index inside this context */
}
@media (min-width: 1024px) {
  .hero-image-wrap { margin-top: var(--space-16); }
}
/* D-067 (revised D-068): bubble vector texture, viewport-width via calc(-50vw + 50%) breakout */
.hero-image-wrap::before {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  left: calc(-50vw + 50%);
  right: calc(-50vw + 50%);
  background-image: url('/assets/r2/backgrounds%2Fbubble%20vector%20background.svg');
  /* The SVG has an internal clipPath (1200×800 active inside a 1547×1171
     viewBox), so its content occupies only the middle 78% of the SVG's
     own width. With cover, the empty viewBox padding ends up at the
     viewport edges as visible gutters. Over-scaling to 135% forces the
     clipPath active region to extend past both viewport edges across
     1024-2560px screens (verified math). */
  background-size: 135% auto;
  background-position: center;
  background-repeat: no-repeat;
  /* D-070: soft top/bottom fade so texture doesn't end on hard edge */
  -webkit-mask-image: linear-gradient(180deg,
    transparent 0%,
    rgba(0, 0, 0, 0.4) 8%,
    #000 22%,
    #000 78%,
    rgba(0, 0, 0, 0.4) 92%,
    transparent 100%);
  mask-image: linear-gradient(180deg,
    transparent 0%,
    rgba(0, 0, 0, 0.4) 8%,
    #000 22%,
    #000 78%,
    rgba(0, 0, 0, 0.4) 92%,
    transparent 100%);
  opacity: 0.13;
  pointer-events: none;
  z-index: -1;
}

/* Rotating headline — block-level grid below "Hey 3PL,". Both phrases
   occupy the same grid cell so the container sizes to the wider phrase,
   keeping layout stable across the opacity swap. The h1's gradient-text
   class on the parent clips the gradient to all descendant text glyphs.
   SR users get the full text via the .sr-only sibling above. */
.hero-line {
  display: block;
}
.rotator {
  display: grid;
  grid-template-areas: 'phrase';
  justify-items: center;
}
/* 6-phrase rotator (D-054) — 18s cycle, 3s slot per phrase.
   Single shared keyframe; each phrase gets a different animation-delay so
   they cascade through one at a time. Each phrase: ~0.5s fade-in, ~2s
   hold, ~0.5s fade-out, then waits the rest of the cycle hidden. */
.rotator__phrase {
  grid-area: phrase;
  opacity: 0;
  animation: rotator-phrase 18s ease-in-out infinite;
}
.rotator__phrase:nth-child(1) { animation-delay: 0s; }
.rotator__phrase:nth-child(2) { animation-delay: 3s; }
.rotator__phrase:nth-child(3) { animation-delay: 6s; }
.rotator__phrase:nth-child(4) { animation-delay: 9s; }
.rotator__phrase:nth-child(5) { animation-delay: 12s; }
.rotator__phrase:nth-child(6) { animation-delay: 15s; }

@keyframes rotator-phrase {
  0%      { opacity: 0; }
  2.78%   { opacity: 1; }    /* fade-in done at 0.5s */
  13.89%  { opacity: 1; }    /* hold visible */
  16.67%  { opacity: 0; }    /* fade-out done at 3s */
  100%    { opacity: 0; }    /* hidden until next cycle */
}

@media (prefers-reduced-motion: reduce) {
  .rotator__phrase { animation: none; opacity: 1; }
  .rotator__phrase:not(:first-child) { display: none; }
}

/* ============================================================
   metrics strip
   ============================================================ */
.metrics-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-4);
}
@media (min-width: 640px) { .metrics-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .metrics-grid { grid-template-columns: repeat(4, 1fr); } }

/* ============================================================
   pillar grid + feature blocks
   ============================================================ */
.pillar-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-4);
}
@media (min-width: 640px) { .pillar-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .pillar-grid { grid-template-columns: repeat(3, 1fr); } }

.pillar-card {
  display: block;
  text-decoration: none;
  color: var(--color-text);
  background-color: rgba(255, 255, 255, 0.04);
  background-image: linear-gradient(180deg, rgba(255, 255, 255, 0.05) 0%, rgba(255, 255, 255, 0.01) 100%);
  border: 1px solid var(--color-border-accent);
  border-radius: var(--radius-lg);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08);
  padding: var(--space-5);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  transition: border-color 200ms ease, transform 200ms ease, box-shadow 200ms ease, background-color 200ms ease;
}
.pillar-card:hover {
  background-color: rgba(255, 255, 255, 0.07);
  border-color: var(--color-border-glow);
  box-shadow: var(--shadow-glow-sm), inset 0 1px 0 rgba(255, 255, 255, 0.10);
  color: var(--color-text);
}
@supports not (backdrop-filter: blur(1px)) {
  .pillar-card { background-color: rgba(20, 35, 65, 0.55); }
}
.pillar-card .pillar-title {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-family: var(--font-display);
  font-weight: var(--weight-bold);
  font-size: var(--text-lg);
  color: var(--color-text-strong);
  margin-bottom: var(--space-2);
}
.pillar-card .pillar-title::after {
  content: '→';
  color: var(--color-emphasis);
}
.pillar-card p {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  margin: 0;
}

/* feature alternating blocks */
.feature-block {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-8);
  align-items: center;
  padding: var(--space-12) 0;
  border-bottom: 1px solid var(--color-border);
}
.feature-block:last-child { border-bottom: none; }
@media (min-width: 1024px) {
  .feature-block { grid-template-columns: 1fr 1fr; gap: var(--space-12); }
  .feature-block.reverse > :first-child { order: 2; }
}
/* D-095 Phase 0: feature-art is now a slot for per-step visualizations
   (real SVG / image / component) — not a broken-image placeholder. The
   subtle gradient + border read as intentional empty space when a step
   has no visualization yet, and disappears entirely behind real content. */
.feature-block .feature-art {
  position: relative;
  background:
    radial-gradient(ellipse 70% 60% at 50% 30%, rgba(0, 194, 255, 0.06) 0%, transparent 70%),
    linear-gradient(180deg, rgba(20, 35, 65, 0.32) 0%, rgba(15, 28, 52, 0.55) 100%);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--space-8);
  min-height: 200px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--color-text-muted);
  font-size: var(--text-sm);
  overflow: hidden;
}
.feature-block .feature-art:empty::before {
  content: '';
  position: absolute;
  inset: 16px;
  border: 1px dashed rgba(125, 211, 252, 0.18);
  border-radius: var(--radius-md);
  pointer-events: none;
}

/* Video-fill variant — UX-in-action marketing demos (Cloudflare Stream
   iframe). Zeros padding so the video reaches the card's inner edge,
   aspect-ratio locks the height to the source 552/360 recording. */
.feature-block .feature-art--video {
  padding: 0;
  aspect-ratio: 552 / 360;
  min-height: 0;
  background: rgba(8, 18, 36, 0.85);
}
.feature-block .feature-art--video iframe {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
}

/* D-095 Phase 0: hero-asset placeholder—empty variant. Same gradient + dashed
   inner-border treatment as feature-art:empty so the two read as the same
   intentional preview-space pattern. Replaces the "asset pending" copy. */
.placeholder--empty {
  position: relative;
  background:
    radial-gradient(ellipse 60% 60% at 50% 30%, rgba(0, 194, 255, 0.05) 0%, transparent 70%),
    linear-gradient(180deg, rgba(20, 35, 65, 0.30) 0%, rgba(15, 28, 52, 0.50) 100%);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  min-height: 280px;
  overflow: hidden;
}
.placeholder--empty::before {
  content: '';
  position: absolute;
  inset: 16px;
  border: 1px dashed rgba(125, 211, 252, 0.18);
  border-radius: var(--radius-md);
  pointer-events: none;
}

/* D-095 Phase 1: ConvergenceCard primitive — port of the home-diagram visual
   language into pillar heroes. Mirrors .converge-card glass treatment + adds a
   card-shaped rail+particle SVG accent that visually rhymes with home without
   re-rendering the full 1400×800 diagram on every pillar page. */
.cv-card {
  position: relative;
  overflow: hidden;
  border-radius: var(--radius-lg);
  min-height: 280px;
  padding: var(--space-6);
  /* D-106: grid splits card into SVG zone (top) + content zone (bottom); fixes narrow-width collision */
  display: grid;
  grid-template-rows: minmax(0, 1fr) auto;
  gap: var(--space-3);
  background-color: rgba(15, 28, 52, 0.32);
  background-image:
    linear-gradient(180deg, rgba(0, 194, 255, 0.10) 0%, rgba(0, 194, 255, 0.03) 60%, rgba(0, 194, 255, 0.07) 100%),
    radial-gradient(ellipse 90% 60% at 50% 0%, rgba(0, 194, 255, 0.14) 0%, transparent 70%);
  border: 1px solid rgba(0, 194, 255, 0.28);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.12),
    inset 0 0 28px rgba(0, 194, 255, 0.08),
    0 8px 32px rgba(0, 0, 0, 0.32);
  backdrop-filter: blur(30px) saturate(220%);
  -webkit-backdrop-filter: blur(30px) saturate(220%);
}
@supports not (backdrop-filter: blur(1px)) {
  .cv-card { background-color: rgba(20, 35, 65, 0.65); }
}
.cv-card__bg {
  /* D-106: was position: absolute; inset: 0 so the SVG filled the card and
     content overlaid via z-index. Now occupies grid row 1 — content lives
     in row 2 with no z-stacking required. min-height: 0 lets the row
     shrink below SVG intrinsic height when card is tall. */
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-4);
  pointer-events: none;
  min-height: 0;
}
.cv-card__bg .cv-card__accent-svg {
  width: 100%;
  height: 100%;
  /* D-106: tightened from 60% → 50% per Iris. With the grid restructure
     above, the SVG zone is already constrained — 50% of that zone gives
     the SVG room without crowding the content row at narrow widths. */
  max-height: 50%;
  opacity: 0.85;
}
/* Charts variant: chart cycle fills the bg zone (lifts default 50% cap; visualization IS the value) */
.cv-card__bg .cv-card__accent-svg.cv-card__accent-svg--charts {
  max-height: 100%;
  opacity: 1;
}
/* Orbit AI variant — same reasoning as charts: the typing+results
   sequence IS the value proposition, not an accent. Fills the bg zone
   so the query field and result rows render at legible scale. */
.cv-card__bg .cv-card__accent-svg.cv-card__accent-svg--orbit {
  max-height: 100%;
  opacity: 1;
}

.cv-card__content {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}
.cv-card__eyebrow {
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--color-emphasis);
  font-weight: var(--weight-semibold);
}
.cv-card__title {
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: var(--weight-bold);
  color: var(--color-text-strong);
  letter-spacing: -0.015em;
  line-height: 1.15;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.45);
}
.cv-card__desc {
  margin: 0;
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  line-height: 1.45;
}

/* D-095 Phase 2: per-concept SVG motion. All gated to reduced-motion:
   no-preference; static state remains legible (the answer rows are visible,
   the resolver target is highlighted, the queue shows recovery total —
   motion adds momentum, not meaning). */

/* Orbit AI — type → "zoom out" → results sequence (9s loop). Replaces the
   prior static-with-blinking-cursor treatment. Three groups animate:
   - .orbit-query (translateY): starts shifted down so the query box reads
     as the visual focus during typing, settles to the natural top position
     as results appear below.
   - .orbit-query-text (clip-path inset): typewriter reveal driven by
     steps(43, end) — 43 chars in "Who are my top 10 customers by margin
     in Q4". Cursor (.orbit-cursor) tracks the same step rhythm via
     translateX, so it visually parks at the typed-text edge.
   - .orbit-results > * (opacity stagger): header + 4 rows fade in after
     the typing completes; brief hold; fade out before the loop reset.
   Reduced-motion: shows the static end state — query fully revealed,
   results visible, cursor parked at end. Cursor still blinks (single
   subtle blink is fine for a11y). */

/* Static defaults — apply when animations are off OR before the first
   animation tick. Reduced-motion users see this state. */
.cv-card__accent-svg--orbit .orbit-query-text {
  clip-path: inset(0 100% 0 0);
}
.cv-card__accent-svg--orbit .orbit-results > * {
  opacity: 0;
}
.cv-card__accent-svg--orbit .orbit-cursor {
  animation: orbit-cursor-blink 1.1s steps(2, end) infinite;
}

@media (prefers-reduced-motion: no-preference) {
  .cv-card__accent-svg--orbit .orbit-query {
    animation: orbit-zoom 9s ease-in-out infinite;
  }
  .cv-card__accent-svg--orbit .orbit-query-text {
    animation: orbit-type 9s steps(43, end) infinite;
  }
  .cv-card__accent-svg--orbit .orbit-cursor {
    animation:
      orbit-cursor-blink 1.1s steps(2, end) infinite,
      orbit-cursor-track 9s steps(43, end) infinite;
  }
  .cv-card__accent-svg--orbit .orbit-results-header {
    animation: orbit-fade 9s ease-out infinite;
  }
  .cv-card__accent-svg--orbit .orbit-row--1 { animation: orbit-fade 9s ease-out 0.10s infinite both; }
  .cv-card__accent-svg--orbit .orbit-row--2 { animation: orbit-fade 9s ease-out 0.20s infinite both; }
  .cv-card__accent-svg--orbit .orbit-row--3 { animation: orbit-fade 9s ease-out 0.30s infinite both; }
  .cv-card__accent-svg--orbit .orbit-row--more { animation: orbit-fade 9s ease-out 0.40s infinite both; }
}

/* Reduced-motion: show the resolved end state so the page still
   communicates the value (typed query + visible results). */
@media (prefers-reduced-motion: reduce) {
  .cv-card__accent-svg--orbit .orbit-query-text { clip-path: inset(0 0 0 0); }
  .cv-card__accent-svg--orbit .orbit-results > * { opacity: 1; }
  .cv-card__accent-svg--orbit .orbit-cursor { transform: translateX(232px); }
}

@keyframes orbit-cursor-blink {
  0%, 50% { opacity: 1; }
  50.01%, 100% { opacity: 0; }
}

/* Query group "zoom out" — translated down (focal) during type phase,
   settles to natural position as results appear. */
@keyframes orbit-zoom {
  0%, 40%   { transform: translateY(36px); }
  50%, 92%  { transform: translateY(0); }
  100%      { transform: translateY(36px); }
}

/* Typewriter reveal — clip-path inset shrinks from right as cycle
   progresses, exposing characters left-to-right. */
@keyframes orbit-type {
  0%, 3%    { clip-path: inset(0 100% 0 0); }
  40%       { clip-path: inset(0 0 0 0); }
  92%       { clip-path: inset(0 0 0 0); }
  93%, 100% { clip-path: inset(0 100% 0 0); }
}

/* Cursor x-translate tracks the typed-text edge in the same step rhythm.
   232 viewBox units ≈ end of "Q4" in the 9px monospace text starting at
   x=42. */
@keyframes orbit-cursor-track {
  0%, 3%    { transform: translateX(0); }
  40%       { transform: translateX(232px); }
  92%       { transform: translateX(232px); }
  93%, 100% { transform: translateX(0); }
}

/* Results stagger — base curve. orbit-row--1..--more each get an
   animation-delay so they cascade in. */
@keyframes orbit-fade {
  0%, 42%   { opacity: 0; }
  52%       { opacity: 1; }
  90%       { opacity: 1; }
  95%, 100% { opacity: 0; }
}

/* D-106: .cv-card__accent-svg--resolver / @keyframes resolver-target-pulse
   removed — Rate Markups now uses the bespoke .markup-hero component
   instead of the cv-card wrapper. */

/* (D-108i: pre-bespoke ConvergenceCard claims-particle / claims-flow /
   claims-queue-pulse rules removed — claims is now a flagship bespoke
   hero. New claims-hero animation block lives below near the
   .claims-hero wrapper rule.) */

/* ============================================================
   D-106: per-page bespoke hero customSvgs across the Platform.
   Four pages get unique visualizations (recharge meter battery,
   adjustment reconciliation lanes, comprehensive billing buckets,
   reporting & analytics chart cycle). All CSS-only, GPU-only
   transforms, gated to prefers-reduced-motion: no-preference,
   static fallback states are content-bearing. Combined budget:
   ~6 KB inline SVG + ~0.8 KB CSS = ~6.8 KB inside 8 KB ceiling.

   SPLIT-CANDIDATE markers below: each block is page-scoped, so
   the eventual BASE_CSS split (deferred per D-095) can extract
   them mechanically by CSS-class prefix.
   ============================================================ */

/* B-006 cleanup (2026-05-08): the .cv-card__accent-svg--battery and
   --reconcile rule blocks (~98 LOC + 6 keyframes) were deleted here.
   The cv-card customSvg consumers were superseded by the bespoke
   meter-hero (D-108b) and reconcile-hero (D-108g) components.
   .cv-card__accent-svg--orbit and --charts remain live below.
   Verified: zero consumers in src/routes/ or src/components/. */

/* Comprehensive Billing — bespoke flagship hero. Five-source data
   convergence story (WMS / Carrier / Spreadsheet / QBO / Stripe →
   RF hub → unified ledger). Replaces the prior 320×180 cv-card
   3-bucket viz. Composition + animation rationale live in
   src/components/comprehensive-billing-hero.ts.

   All timing encoded as percentages of an 8s master cycle so every
   element stays in lockstep on every loop. (Earlier draft used
   animation-delay with infinite, but per CSS spec animation-delay
   only applies to cycle 1 — subsequent cycles run back-to-back, which
   desyncs each element from the master cycle.)

   Master cycle (8s = 100%, three acts):
     Act 1 — sources illuminate cascade (0% → 30%, 6% per lane stagger)
     Act 2 — hub fires + output stroke draws (38% → 58%)
     Act 3 — ledger frame + rows + total cascade (52% → 86%, 4% per row)
     Reset — fade everything out (88% → 95%) and dim during 95-100%

   Static defaults below match the 0% keyframe values so there's no
   FOUC flash before the animation engine kicks in. The reduced-motion
   block overrides them with the final-visible state — composition
   reads as a complete "5 inputs → RF hub → unified ledger" diagram.

   Per web-motion-protocol hard gates: GPU-only properties (opacity,
   stroke-dashoffset, transform), CLS=0, reduced-motion meaningful,
   cyan-only per D-074. */

/* Static defaults — match keyframe 0% values so animated elements
   don't flash a different state before the engine starts. */
.comp-billing-hero__svg .cb-source { opacity: 0.35; }
.comp-billing-hero__svg .cb-line { stroke-dashoffset: 100; }
.comp-billing-hero__svg .cb-hub-glow {
  opacity: 0.4;
  transform: scale(1);
  transform-box: fill-box;
  transform-origin: center;
}
.comp-billing-hero__svg .cb-output { stroke-dashoffset: 100; }
.comp-billing-hero__svg .cb-ledger-header,
.comp-billing-hero__svg .cb-ledger-rule,
.comp-billing-hero__svg .cb-ledger-total-rule,
.comp-billing-hero__svg .cb-row { opacity: 0; }

/* Reduced-motion: show the resolved end-state diagram. */
@media (prefers-reduced-motion: reduce) {
  .comp-billing-hero__svg .cb-source { opacity: 1; }
  .comp-billing-hero__svg .cb-line { stroke-dashoffset: 0; }
  .comp-billing-hero__svg .cb-hub-glow { opacity: 0.7; }
  .comp-billing-hero__svg .cb-output { stroke-dashoffset: 0; }
  .comp-billing-hero__svg .cb-ledger-header,
  .comp-billing-hero__svg .cb-ledger-rule,
  .comp-billing-hero__svg .cb-ledger-total-rule,
  .comp-billing-hero__svg .cb-row { opacity: 1; }
}

@media (prefers-reduced-motion: no-preference) {
  /* No animation-delays anywhere — timing lives in keyframes. Every
     element shares the same 8s cycle so loops stay coordinated. */
  .comp-billing-hero__svg .cb-source--1 { animation: cb-source-1 8s ease-out infinite; }
  .comp-billing-hero__svg .cb-source--2 { animation: cb-source-2 8s ease-out infinite; }
  .comp-billing-hero__svg .cb-source--3 { animation: cb-source-3 8s ease-out infinite; }
  .comp-billing-hero__svg .cb-source--4 { animation: cb-source-4 8s ease-out infinite; }
  .comp-billing-hero__svg .cb-source--5 { animation: cb-source-5 8s ease-out infinite; }

  .comp-billing-hero__svg .cb-line--1 { animation: cb-line-1 8s ease-out infinite; }
  .comp-billing-hero__svg .cb-line--2 { animation: cb-line-2 8s ease-out infinite; }
  .comp-billing-hero__svg .cb-line--3 { animation: cb-line-3 8s ease-out infinite; }
  .comp-billing-hero__svg .cb-line--4 { animation: cb-line-4 8s ease-out infinite; }
  .comp-billing-hero__svg .cb-line--5 { animation: cb-line-5 8s ease-out infinite; }

  .comp-billing-hero__svg .cb-hub-glow {
    animation: cb-hub-pulse 8s cubic-bezier(0.4, 0, 0.2, 1) infinite;
  }

  .comp-billing-hero__svg .cb-output {
    animation: cb-output-draw 8s cubic-bezier(0.4, 0, 0.2, 1) infinite;
  }

  .comp-billing-hero__svg .cb-ledger-header,
  .comp-billing-hero__svg .cb-ledger-rule {
    animation: cb-ledger-frame 8s ease-out infinite;
  }

  .comp-billing-hero__svg .cb-row--1 { animation: cb-row-1 8s ease-out infinite; }
  .comp-billing-hero__svg .cb-row--2 { animation: cb-row-2 8s ease-out infinite; }
  .comp-billing-hero__svg .cb-row--3 { animation: cb-row-3 8s ease-out infinite; }
  .comp-billing-hero__svg .cb-row--4 { animation: cb-row-4 8s ease-out infinite; }
  .comp-billing-hero__svg .cb-row--5 { animation: cb-row-5 8s ease-out infinite; }
  .comp-billing-hero__svg .cb-ledger-total-rule {
    animation: cb-total-rule 8s ease-out infinite;
  }
  .comp-billing-hero__svg .cb-row--total {
    animation: cb-row-total 8s ease-out infinite;
  }
}

/* Source illumination — 5 lanes cascade 0% → 30% (6% stagger per lane). */
@keyframes cb-source-1 {
  0%        { opacity: 0.35; }
  6%, 88%   { opacity: 1; }
  95%, 100% { opacity: 0.35; }
}
@keyframes cb-source-2 {
  0%, 6%    { opacity: 0.35; }
  12%, 88%  { opacity: 1; }
  95%, 100% { opacity: 0.35; }
}
@keyframes cb-source-3 {
  0%, 12%   { opacity: 0.35; }
  18%, 88%  { opacity: 1; }
  95%, 100% { opacity: 0.35; }
}
@keyframes cb-source-4 {
  0%, 18%   { opacity: 0.35; }
  24%, 88%  { opacity: 1; }
  95%, 100% { opacity: 0.35; }
}
@keyframes cb-source-5 {
  0%, 24%   { opacity: 0.35; }
  30%, 88%  { opacity: 1; }
  95%, 100% { opacity: 0.35; }
}

/* Connector path draws — synchronized with each source's illumination. */
@keyframes cb-line-1 {
  0%        { stroke-dashoffset: 100; }
  6%, 88%   { stroke-dashoffset: 0; }
  95%, 100% { stroke-dashoffset: 100; }
}
@keyframes cb-line-2 {
  0%, 6%    { stroke-dashoffset: 100; }
  12%, 88%  { stroke-dashoffset: 0; }
  95%, 100% { stroke-dashoffset: 100; }
}
@keyframes cb-line-3 {
  0%, 12%   { stroke-dashoffset: 100; }
  18%, 88%  { stroke-dashoffset: 0; }
  95%, 100% { stroke-dashoffset: 100; }
}
@keyframes cb-line-4 {
  0%, 18%   { stroke-dashoffset: 100; }
  24%, 88%  { stroke-dashoffset: 0; }
  95%, 100% { stroke-dashoffset: 100; }
}
@keyframes cb-line-5 {
  0%, 24%   { stroke-dashoffset: 100; }
  30%, 88%  { stroke-dashoffset: 0; }
  95%, 100% { stroke-dashoffset: 100; }
}

/* Hub fires after sources are all illuminated (~38-52% of cycle). */
@keyframes cb-hub-pulse {
  0%, 38%   { opacity: 0.4; transform: scale(1); }
  44%       { opacity: 1; transform: scale(1.18); }
  52%, 88%  { opacity: 0.7; transform: scale(1); }
  95%, 100% { opacity: 0.4; transform: scale(1); }
}

/* Output stroke draws right after hub fires (50-58% of cycle). */
@keyframes cb-output-draw {
  0%, 50%   { stroke-dashoffset: 100; }
  56%, 88%  { stroke-dashoffset: 0; }
  95%, 100% { stroke-dashoffset: 100; }
}

/* Ledger frame (header + top rule) appears just before rows (52-58%). */
@keyframes cb-ledger-frame {
  0%, 52%   { opacity: 0; }
  58%, 88%  { opacity: 1; }
  95%, 100% { opacity: 0; }
}

/* Rows cascade in 56-76% (4% stagger per row). */
@keyframes cb-row-1 {
  0%, 56%   { opacity: 0; }
  60%, 88%  { opacity: 1; }
  95%, 100% { opacity: 0; }
}
@keyframes cb-row-2 {
  0%, 60%   { opacity: 0; }
  64%, 88%  { opacity: 1; }
  95%, 100% { opacity: 0; }
}
@keyframes cb-row-3 {
  0%, 64%   { opacity: 0; }
  68%, 88%  { opacity: 1; }
  95%, 100% { opacity: 0; }
}
@keyframes cb-row-4 {
  0%, 68%   { opacity: 0; }
  72%, 88%  { opacity: 1; }
  95%, 100% { opacity: 0; }
}
@keyframes cb-row-5 {
  0%, 72%   { opacity: 0; }
  76%, 88%  { opacity: 1; }
  95%, 100% { opacity: 0; }
}

/* Total rule + total row appear last (76-86%). */
@keyframes cb-total-rule {
  0%, 76%   { opacity: 0; }
  80%, 88%  { opacity: 1; }
  95%, 100% { opacity: 0; }
}
@keyframes cb-row-total {
  0%, 78%   { opacity: 0; }
  82%, 88%  { opacity: 1; }
  95%, 100% { opacity: 0; }
}

/* SPLIT-CANDIDATE: Reporting & Analytics — three chart views
   (bar, line, heatmap) crossfade in a 9s cycle, ~3s per view.
   Static fallback: bar chart visible. */
.cv-card__accent-svg--charts .charts-view {
  opacity: 0;
}
.cv-card__accent-svg--charts .charts-view--bar {
  opacity: 1;
}
@media (prefers-reduced-motion: no-preference) {
  .cv-card__accent-svg--charts .charts-view--bar {
    animation: cv-charts-cycle-1 9s ease-in-out infinite;
  }
  .cv-card__accent-svg--charts .charts-view--line {
    animation: cv-charts-cycle-2 9s ease-in-out infinite;
  }
  .cv-card__accent-svg--charts .charts-view--heat {
    animation: cv-charts-cycle-3 9s ease-in-out infinite;
  }
}
@keyframes cv-charts-cycle-1 {
  0%, 28%   { opacity: 1; }
  33%, 95%  { opacity: 0; }
  100%      { opacity: 1; }
}
@keyframes cv-charts-cycle-2 {
  0%, 28%   { opacity: 0; }
  33%, 61%  { opacity: 1; }
  66%, 100% { opacity: 0; }
}
@keyframes cv-charts-cycle-3 {
  0%, 61%   { opacity: 0; }
  66%, 95%  { opacity: 1; }
  100%      { opacity: 0; }
}

/* D-106/D-107: .flow-hero PROTOTYPE retired (replaced by .markup-hero) */

/* D-095 Phase 3: scroll-driven reveal via animation-timeline (gated to no-preference) */

@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    /* Feature blocks slide up + fade in as they enter the viewport.
       Pillar pages have 4–5 of these per page; the cumulative effect
       is a section reading like a controlled reveal as the user scrolls. */
    .feature-block {
      animation: pf-feature-block-reveal linear both;
      animation-timeline: view();
      animation-range: entry 0% entry 50%;
      will-change: opacity, transform;
    }

    /* Pillar hub cards reveal as the grid enters view. */
    .pillar-grid-hub > .pillar-card {
      animation: pf-card-reveal linear both;
      animation-timeline: view();
      animation-range: entry 0% entry 45%;
      will-change: opacity, transform;
    }

    /* Crosslink cards reveal as the related-pillars section enters view. */
    .crosslinks-grid > .crosslink-card {
      animation: pf-card-reveal linear both;
      animation-timeline: view();
      animation-range: entry 0% entry 50%;
      will-change: opacity, transform;
    }

    /* ConvergenceCard hero subtly scales + fades in on first paint as the
       hero enters view — the hero is already on-screen at page load so this
       is the introduction moment, not an in-scroll reveal. */
    .hero-asset .cv-card {
      animation: pf-cv-card-reveal 700ms cubic-bezier(0.2, 0.7, 0.2, 1) 200ms both;
      will-change: opacity, transform;
    }
  }
}

@keyframes pf-feature-block-reveal {
  from { opacity: 0; transform: translateY(24px); }
  to   { opacity: 1; transform: translateY(0); }
}

@keyframes pf-card-reveal {
  from { opacity: 0; transform: translateY(16px); }
  to   { opacity: 1; transform: translateY(0); }
}

@keyframes pf-cv-card-reveal {
  from { opacity: 0; transform: translateY(20px) scale(0.97); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}

/* ============================================================
   D-096: Ask Orbit AI bridge — section between the convergence
   diagram and the solutions showcase. Visually extends the
   convergence flow downward via a single thicker rail (6px stroke
   vs convergence-diagram's 3px) with faster particle output (4
   particles in a 1.6s cycle, staggered every 400ms = continuous
   stream vs convergence's 2.8-3.7s per-lane spawn intervals).
   The card uses the Orbit mascot inside its own frosted-glass
   inner panel — image positioned flush to the panel's bottom
   so the moon reads as the panel edge and the character rises
   from it rather than appearing cropped.
   ============================================================ */

/* D-097: orbit-bridge reshape — landscape card with two right-angle arms + ~9s particle fire */
.section--orbit-bridge {
  padding-top: 0;
  padding-bottom: var(--section-gap);
}
.orbit-bridge {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: var(--space-2);
}

/* Rail SVG — wide aspect, viewBox aligned to the convergence container so
   the arm starts at 20% (matches converge-card--l3 left:20%) and 80%
   (matches converge-card--r3 right:20%). 6px stroke = twice the visible
   weight of the convergence rails. */
.orbit-bridge__rail {
  width: 100%;
  max-width: 1400px;
  margin: 0 auto;
  aspect-ratio: 1400 / 200;
  display: block;
  flex: 0 0 auto;
}
.orbit-bridge__particle { opacity: 0; }
@supports (offset-path: path('M 0 0')) {
  .orbit-bridge__particle--left {
    offset-path: path('M 280 0 V 60 Q 280 80 300 80 H 700 V 200');
    offset-distance: 0%;
  }
  .orbit-bridge__particle--right {
    offset-path: path('M 1120 0 V 60 Q 1120 80 1100 80 H 700 V 200');
    offset-distance: 0%;
  }
  @media (prefers-reduced-motion: no-preference) {
    .orbit-bridge .orbit-bridge__particle--left,
    .orbit-bridge .orbit-bridge__particle--right {
      animation: orbit-bridge-arm-flow 9s ease-in-out infinite;
    }
  }
}
@keyframes orbit-bridge-arm-flow {
  0%, 5% { offset-distance: 0%; opacity: 0; }
  10% { opacity: 1; }
  /* Particles only "fire" for ~33% of the cycle; rest of the time
     they're invisible at the start. That gives the much-less-frequent
     feel the user asked for vs the convergence diagram's continuous
     spawn. */
  35% { offset-distance: 100%; opacity: 1; }
  40%, 100% { offset-distance: 100%; opacity: 0; }
}

/* Card — landscape proportions matching the solutions-showcase video frame.
   Two columns at desktop: title + CTA on the left, conversation animation
   on the right. Stacked on mobile. */
.orbit-card {
  position: relative;
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-6);
  padding: var(--space-8) var(--space-6);
  width: 100%;
  max-width: 1100px;
  margin: 0 auto;
  border-radius: var(--radius-xl, 24px);
  background-color: rgba(15, 28, 52, 0.42);
  background-image:
    linear-gradient(180deg, rgba(0, 194, 255, 0.10) 0%, rgba(0, 194, 255, 0.03) 60%, rgba(0, 194, 255, 0.06) 100%),
    radial-gradient(ellipse 90% 60% at 50% 0%, rgba(0, 194, 255, 0.14) 0%, transparent 70%);
  border: 1px solid rgba(0, 194, 255, 0.28);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.12),
    inset 0 0 32px rgba(0, 194, 255, 0.08),
    0 12px 36px rgba(0, 0, 0, 0.32);
  backdrop-filter: blur(30px) saturate(220%);
  -webkit-backdrop-filter: blur(30px) saturate(220%);
  overflow: hidden;
}
@supports not (backdrop-filter: blur(1px)) {
  .orbit-card { background-color: rgba(20, 35, 65, 0.70); }
}
.orbit-card__content {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}
.orbit-card__content h2 {
  margin: 0;
}
.orbit-card__cta {
  margin: var(--space-2) 0 0;
}

/* Conversation — fixed-height container so cycling pairs don't cause CLS.
   overflow: visible so the edge mascot can sit AT the chat boundary
   (partially extending past the right/bottom edges); the gradient and
   border-radius still clip via background-clip on the panel itself. */
.orbit-conversation {
  position: relative;
  min-height: 220px;
  border-radius: var(--radius-lg);
  background:
    radial-gradient(ellipse 90% 70% at 50% 100%, rgba(0, 194, 255, 0.10) 0%, transparent 70%),
    linear-gradient(180deg, rgba(20, 35, 65, 0.32) 0%, rgba(15, 28, 52, 0.55) 100%);
  background-clip: padding-box;
  border: 1px solid rgba(0, 194, 255, 0.22);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08);
  padding: var(--space-5);
  overflow: visible;
}

/* D-098: Orbit edge mascot — bottom-right of chat pane, aria-hidden, behind bubbles */
.orbit-conversation__edge-mascot {
  position: absolute;
  right: -28px;
  bottom: -22px;
  width: 110px;
  height: auto;
  pointer-events: none;
  z-index: 0;
  filter: drop-shadow(0 6px 14px rgba(0, 0, 0, 0.45));
  /* Subtle idle bob — gated to reduced-motion: no-preference. */
  transform-origin: 50% 100%;
}
@media (prefers-reduced-motion: no-preference) {
  .orbit-conversation__edge-mascot {
    animation: orbit-edge-mascot-bob 5.5s ease-in-out infinite;
  }
}
@keyframes orbit-edge-mascot-bob {
  0%, 100% { transform: translateY(0) rotate(-2deg); }
  50% { transform: translateY(-4px) rotate(2deg); }
}
.orbit-conversation__pair {
  position: absolute;
  inset: var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  opacity: 0;
}

/* Bubble shared shape — chat-style, alternating alignment. */
.orbit-bubble {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: var(--space-3) var(--space-4);
  border-radius: 14px;
  max-width: 90%;
  font-size: var(--text-sm);
  line-height: 1.4;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.18);
}
.orbit-bubble__label {
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight: var(--weight-semibold);
  opacity: 0.7;
}
.orbit-bubble__text {
  color: var(--color-text-strong);
}
.orbit-bubble--user {
  align-self: flex-end;
  background: rgba(0, 194, 255, 0.14);
  border: 1px solid rgba(0, 194, 255, 0.45);
  border-bottom-right-radius: 4px;
}
.orbit-bubble--user .orbit-bubble__label { color: rgba(125, 211, 252, 0.95); }
.orbit-bubble--orbit {
  align-self: flex-start;
  background: rgba(0, 255, 209, 0.10);
  border: 1px solid rgba(0, 255, 209, 0.40);
  border-bottom-left-radius: 4px;
}
.orbit-bubble--orbit .orbit-bubble__label { color: var(--color-accent-teal); }

/* Conversation cycle — 18s total, 3 pairs sharing the cycle. Each pair
   appears for ~5s with the question fading in first then the answer.
   Reduced-motion: pair 1 stays visible static. */
@media (prefers-reduced-motion: reduce) {
  .orbit-conversation__pair--1 { opacity: 1; }
}
@media (prefers-reduced-motion: no-preference) {
  /* animation-fill-mode: backwards applies the 0% keyframe (opacity 0) BEFORE
     each pair's delay completes — without it, pairs 2 and 3 fall back to
     default CSS opacity 1 during their delay window and overlap pair 1 at
     page load. */
  .orbit-conversation__pair--1 .orbit-bubble--user  { animation: orbit-bubble-q 18s linear 0s infinite backwards; }
  .orbit-conversation__pair--1 .orbit-bubble--orbit { animation: orbit-bubble-a 18s linear 0s infinite backwards; }
  .orbit-conversation__pair--2 .orbit-bubble--user  { animation: orbit-bubble-q 18s linear 6s infinite backwards; }
  .orbit-conversation__pair--2 .orbit-bubble--orbit { animation: orbit-bubble-a 18s linear 6s infinite backwards; }
  .orbit-conversation__pair--3 .orbit-bubble--user  { animation: orbit-bubble-q 18s linear 12s infinite backwards; }
  .orbit-conversation__pair--3 .orbit-bubble--orbit { animation: orbit-bubble-a 18s linear 12s infinite backwards; }
  /* Pair containers stay visible (opacity 1) so the bubbles' own animations
     drive visibility independently. */
  .orbit-conversation__pair { opacity: 1; }
}
@keyframes orbit-bubble-q {
  0% { opacity: 0; transform: translateY(8px); }
  3% { opacity: 1; transform: translateY(0); }
  30% { opacity: 1; transform: translateY(0); }
  33% { opacity: 0; transform: translateY(-8px); }
  100% { opacity: 0; transform: translateY(-8px); }
}
@keyframes orbit-bubble-a {
  0%, 8% { opacity: 0; transform: translateY(8px); }
  12% { opacity: 1; transform: translateY(0); }
  30% { opacity: 1; transform: translateY(0); }
  33% { opacity: 0; transform: translateY(-8px); }
  100% { opacity: 0; transform: translateY(-8px); }
}

/* Desktop — title left, conversation right. Conversation gets a bit more
   horizontal room to render bubbles cleanly. */
@media (min-width: 1024px) {
  .orbit-card {
    grid-template-columns: 1fr 1.2fr;
    gap: var(--space-10);
    padding: var(--space-10) var(--space-10);
  }
  .orbit-card__content {
    justify-content: center;
  }
  .orbit-conversation {
    min-height: 280px;
  }
}

/* Subtle hover polish on the cv-card itself — completes the convergence-card
   visual rhyme (the home convergence-card has a hover state; pillar heroes
   were missing one). Border + box-shadow only — no transform on the card
   itself since the hero is a focal element and shouldn't drift. */
.cv-card {
  transition: border-color 220ms ease, box-shadow 220ms ease;
}
.hero-asset .cv-card:hover,
.hero-asset .cv-card:focus-within {
  border-color: rgba(0, 194, 255, 0.55);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.16),
    inset 0 0 36px rgba(0, 194, 255, 0.18),
    0 0 28px rgba(0, 194, 255, 0.18),
    0 8px 32px rgba(0, 0, 0, 0.32);
}

/* D-095: cross-pillar links section */
.section--crosslinks {
  position: relative;
}

/* D-109: .section--narrative — glass panel for problem/proof/CTA blocks on pillar pages */
/* D-191: outer gutter so the glass card never goes full-bleed below --container-max
   (1200px). The card is max-width:1200 + margin:auto, so without an outer inset its
   border touches the viewport edges on mobile/tablet (and the translucent fill lets
   the section behind bleed through). 24px matches the standard .container gutter. */
.section--narrative {
  padding-inline: var(--space-6);
}
.section--narrative > .container-narrow {
  position: relative;
  /* D-109b: widened from --container-narrow to --container-max */
  max-width: var(--container-max);
  border-radius: var(--radius-lg);
  padding: var(--space-10) var(--space-12);
  background-color: rgba(15, 28, 52, 0.32);
  background-image:
    radial-gradient(ellipse 70% 60% at 50% 50%, rgba(0, 194, 255, 0.05) 0%, rgba(0, 194, 255, 0.02) 45%, transparent 80%),
    linear-gradient(180deg, rgba(0, 194, 255, 0.04) 0%, rgba(0, 194, 255, 0.012) 60%, rgba(0, 194, 255, 0.03) 100%);
  border: 1px solid rgba(0, 194, 255, 0.18);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06), inset 0 0 24px rgba(0, 194, 255, 0.04), 0 4px 24px rgba(0, 0, 0, 0.20);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
}
@supports not (backdrop-filter: blur(1px)) {
  .section--narrative > .container-narrow { background-color: rgba(20, 35, 65, 0.55); }
}
@media (max-width: 767px) {
  .section--narrative > .container-narrow {
    padding: var(--space-8) var(--space-6);
  }
}

/* D-128: .section--dot-grid retired (dot-grid lifted to body-stack ambient
   layer in base.ts as body:not(.home)::before). Only the centered ambient
   bloom remains, renamed .section--hero-bloom for clarity — opt-in hero
   spotlight ellipse that complements the body-stack ambient corners with
   a centered glow on the hero section itself. Three consumers:
   solutions.ts:43 (audience hero), solutions.ts:399 (hub hero),
   product-net-terms-plus.ts:46 (NTP hero). D-116b alpha 0.07 cyan. */
.section--hero-bloom {
  position: relative;
}
.section--hero-bloom::before {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse 75% 65% at 50% 50%, rgba(0, 194, 255, 0.07), transparent 75%);
  pointer-events: none;
  z-index: -1;
}

.crosslinks-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-4);
}
@media (min-width: 768px) {
  .crosslinks-grid { grid-template-columns: repeat(3, 1fr); }
}
.crosslink-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-6);
  background: rgba(15, 28, 52, 0.45);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  color: var(--color-text);
  text-decoration: none;
  transition: border-color 220ms ease, transform 220ms ease, background 220ms ease;
}
.crosslink-card:hover,
.crosslink-card:focus-visible {
  border-color: var(--color-border-accent);
  background: rgba(20, 35, 65, 0.65);
  transform: translateY(-2px);
  outline: none;
}
/* D-226 a11y: motion-independent focus ring (the shared hover/focus block above conveyed focus only via a low-alpha border + a transform that reduced-motion zeroes). */
.crosslink-card:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}
.crosslink-card__eyebrow {
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--color-emphasis);
  font-weight: var(--weight-semibold);
}
.crosslink-card__title {
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-weight: var(--weight-semibold);
  color: var(--color-text-strong);
}
.crosslink-card p {
  margin: 0;
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  line-height: var(--leading-snug);
}

/* ============================================================
   Solution-page WIREFRAME v2 (D-155) + scroll-driven replacement
   diagram (D-156). Center-justified rhythm with one asymmetric
   beat (Powered-by). The diagram: 3 old systems → RocketFuel logo
   → "The New Normal" card, revealed on scroll. Cyan/teal per
   D-074/D-116; GPU-only props; reduced-motion + no scroll-timeline
   support both fall back to the fully-resolved state.
   ============================================================ */

/* Centered hero — scope helpers to the text-center hero container so we
   reuse .container-narrow.text-center without new modifier classes. */
.hero .container-narrow.text-center .hero-sub { margin-inline: auto; }
.hero .container-narrow.text-center .hero-actions { justify-content: center; }

/* Powered-by — the one asymmetric section: text left, product animation right. */
.solution-powered {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-8);
  align-items: center;
}
@media (min-width: 1024px) {
  .solution-powered { grid-template-columns: 1fr 1fr; gap: var(--space-12); }
}
.solution-viz {
  border-radius: var(--radius-lg);
  padding: var(--space-6);
  background-color: rgba(15, 28, 52, 0.32);
  background-image:
    linear-gradient(180deg, rgba(0, 194, 255, 0.08) 0%, rgba(0, 194, 255, 0.02) 60%, rgba(0, 194, 255, 0.06) 100%),
    radial-gradient(ellipse 90% 60% at 50% 0%, rgba(0, 194, 255, 0.12) 0%, transparent 70%);
  border: 1px solid rgba(0, 194, 255, 0.24);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.10), 0 8px 28px rgba(0, 0, 0, 0.28);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
}
@supports not (backdrop-filter: blur(1px)) {
  .solution-viz { background-color: rgba(20, 35, 65, 0.6); }
}
.solution-viz .comp-billing-hero,
.solution-viz .reconcile-hero,
.solution-viz .reporting-hero { width: 100%; }
.solution-viz .reporting-hero svg { width: 100%; height: auto; display: block; }
.solution-viz .reconcile-hero__desc {
  text-align: center;
  margin: var(--space-3) 0 0;
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

/* -------- replacement diagram: old systems → RocketFuel → the new normal -------- */
.replacement-flow {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0;
  max-width: 920px;
  margin: var(--space-8) auto 0;
}

/* Old-system cards (top row) */
.rf2-olds {
  list-style: none;
  margin: 0;
  padding: 0;
  width: 100%;
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-4);
}
@media (min-width: 768px) {
  .rf2-olds { grid-template-columns: repeat(3, 1fr); gap: var(--space-6); }
}
.rf2-old {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  text-align: center;
  padding: var(--space-5) var(--space-4);
  border-radius: var(--radius-lg);
  background: rgba(15, 28, 52, 0.4);
  border: 1px solid var(--color-border);
}
.rf2-old__label {
  font-family: var(--font-display);
  font-weight: var(--weight-semibold);
  font-size: var(--text-base);
  color: var(--color-text);
}
.rf2-old__desc {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  line-height: var(--leading-snug);
}

/* Converge connector (3 old → logo), desktop SVG. Full row width;
   preserveAspectRatio="none" keeps endpoints column-aligned at any width. */
.rf2-converge { width: 100%; height: 100px; display: block; overflow: visible; }
/* Converging connectors — static thick glowing curves that funnel into the
   sphere core. No animation (D-167: the spark draw/loop was removed per user);
   these ARE the lit "thick glowing" lines. The convergence point sits inside
   the sphere so the tips are absorbed — no tangent-to-rim gap. vector-effect
   keeps the 2.5px stroke uniform under preserveAspectRatio="none" stretch. */
.rf2-in-line {
  stroke: rgba(125, 211, 252, 0.95);
  stroke-width: 2.5;
  fill: none;
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
  filter: drop-shadow(0 0 7px rgba(0, 194, 255, 0.9));
}

/* Vertical rails — mobile converge fallback + the outgoing connector */
.rf2-rail {
  --rail-h: var(--space-10);
  position: relative;
  width: 2px;
  height: var(--rail-h);
  flex: 0 0 auto;
  border-radius: 2px;
  background: rgba(0, 194, 255, 0.16);
}
.rf2-rail--out { --rail-h: 5rem; }
.rf2-rail__fill {
  position: absolute;
  inset: 0;
  transform-origin: top;
  transform: scaleY(1);
  border-radius: 2px;
  background: linear-gradient(180deg, rgba(0, 194, 255, 0.85), rgba(0, 255, 209, 0.9));
  box-shadow: 0 0 6px rgba(0, 194, 255, 0.5);
}
/* Comet head — round glowing dot that leads the fill down the rail and lands
   (glowing) where it shoots into the next card. */
.rf2-rail__head {
  position: absolute;
  left: 50%;
  top: -4px;
  width: 9px;
  height: 9px;
  margin-left: -4.5px;
  border-radius: 50%;
  background: var(--color-accent-teal);
  box-shadow: 0 0 12px 3px rgba(0, 255, 209, 0.75), 0 0 5px 1px rgba(255, 255, 255, 0.55);
  opacity: 0;
}
.rf2-rail--converge { display: none; }

/* RocketFuel logo — glassmorphic sphere (the convergence node). On desktop it
   overlaps the converge SVG's lower zone (negative margin) so the converging
   lines terminate INSIDE the sphere instead of floating above a bare logo; the
   outgoing rail tucks into its base. Off-center radial gives spherical depth. */
.rf2-logo {
  position: relative;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 134px;
  height: 134px;
  margin: 0 auto;
  border-radius: 50%;
  background-color: rgba(15, 28, 52, 0.66);
  background-image: radial-gradient(circle at 38% 30%, rgba(0, 194, 255, 0.20), rgba(0, 194, 255, 0.04) 55%, transparent 72%);
  border: 1px solid rgba(0, 194, 255, 0.5);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.16),
    inset 0 0 28px rgba(0, 194, 255, 0.14),
    0 0 30px rgba(0, 194, 255, 0.20);
  backdrop-filter: blur(10px) saturate(200%);
  -webkit-backdrop-filter: blur(10px) saturate(200%);
}
@supports not (backdrop-filter: blur(1px)) {
  .rf2-logo { background-color: rgba(20, 35, 65, 0.92); }
}
@media (min-width: 768px) {
  .rf2-logo { margin-top: -58px; margin-bottom: -12px; }
}
.rf2-logo__img {
  position: relative;
  z-index: 1;
  width: 70px;
  height: auto;
  opacity: 1;
}
.rf2-logo__glow {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 210px;
  height: 210px;
  margin: -105px 0 0 -105px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(0, 194, 255, 0.38), transparent 60%);
  opacity: 1;
  pointer-events: none;
  z-index: 0;
}

/* The New Normal card (bottom) — title left, outcome bullets right */
.rf2-newnormal {
  position: relative;
  width: 100%;
  max-width: 720px;
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-4);
  align-items: center;
  padding: var(--space-6) var(--space-8);
  border-radius: var(--radius-lg);
  background-color: rgba(15, 28, 52, 0.5);
  background-image: linear-gradient(180deg, rgba(0, 255, 209, 0.05) 0%, rgba(0, 194, 255, 0.03) 100%);
  border: 1px solid rgba(0, 194, 255, 0.4);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08);
  backdrop-filter: blur(16px) saturate(160%);
  -webkit-backdrop-filter: blur(16px) saturate(160%);
  overflow: hidden;
}
@supports not (backdrop-filter: blur(1px)) {
  .rf2-newnormal { background-color: rgba(20, 35, 65, 0.7); }
}
@media (min-width: 640px) {
  .rf2-newnormal { grid-template-columns: auto 1fr; gap: var(--space-8); }
}
.rf2-newnormal__glow {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(ellipse 60% 80% at 22% 50%, rgba(0, 255, 209, 0.14), transparent 70%);
  opacity: 1;
}
.rf2-newnormal__title {
  position: relative;
  z-index: 1;
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--text-2xl);
  font-weight: var(--weight-bold);
  color: var(--color-text-strong);
  line-height: 1.1;
}
.rf2-newnormal__list {
  position: relative;
  z-index: 1;
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}
.rf2-newnormal__list li {
  position: relative;
  padding-left: var(--space-6);
  color: var(--color-text);
  font-size: var(--text-base);
}
.rf2-newnormal__list li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.3em;
  width: 16px;
  height: 16px;
  background-color: var(--color-accent-teal);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E") no-repeat center / contain;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E") no-repeat center / contain;
}

@media (max-width: 767px) {
  .rf2-converge { display: none; }
  .rf2-rail--converge { display: block; }
}

/* Scroll-driven reveal (D-156). Base above = the resolved state (shown when
   scroll-timelines are unsupported OR reduced-motion is set). When supported
   AND motion is allowed, elements start dim and resolve as the diagram scrolls
   through the viewport: lines draw + glow into the logo, the logo lights, the
   outgoing rail fills teal, then the New Normal card gains a faint glow. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .replacement-flow {
      timeline-scope: --rf2flow;
      view-timeline-name: --rf2flow;
      view-timeline-axis: block;
    }
    /* Phased across the diagram's full viewport transit (cover 0–100%, where
       ~50% = diagram centered). The DESKTOP converging curves are static (no
       animation) — see .rf2-in-line above. Scroll drives the rest:
         Act 1 (cover 15–40%): mobile converge rail fills into the logo.
         Act 2 (cover 36–52%): logo lights up.
         — scroll delay —
         Act 3 (cover 56–76%): comet shoots down the outgoing rail.
         Act 4 (cover 72–88%): New Normal card glows. */
    .rf2-rail--converge .rf2-rail__fill {
      animation: rf2-rail-fill linear both;
      animation-timeline: --rf2flow;
      animation-range: cover 15% cover 40%;
    }
    .rf2-rail--converge .rf2-rail__head {
      animation: rf2-head-fall linear both;
      animation-timeline: --rf2flow;
      animation-range: cover 15% cover 40%;
    }
    .rf2-logo__img {
      animation: rf2-logo-lit linear both;
      animation-timeline: --rf2flow;
      animation-range: cover 36% cover 50%;
    }
    .rf2-logo__glow {
      animation: rf2-glow-in linear both;
      animation-timeline: --rf2flow;
      animation-range: cover 36% cover 52%;
    }
    /* Comet shoots down the (longer) outgoing rail into the New Normal card,
       after a deliberate scroll delay past the logo lighting up. */
    .rf2-rail--out .rf2-rail__fill {
      animation: rf2-rail-fill linear both;
      animation-timeline: --rf2flow;
      animation-range: cover 56% cover 76%;
    }
    .rf2-rail--out .rf2-rail__head {
      animation: rf2-head-fall linear both;
      animation-timeline: --rf2flow;
      animation-range: cover 56% cover 76%;
    }
    .rf2-newnormal__glow {
      animation: rf2-glow-in linear both;
      animation-timeline: --rf2flow;
      animation-range: cover 72% cover 88%;
    }
  }
}

@keyframes rf2-rail-fill {
  from { transform: scaleY(0); }
  to   { transform: scaleY(1); }
}
@keyframes rf2-logo-lit {
  from { opacity: 0.4; }
  to   { opacity: 1; }
}
@keyframes rf2-glow-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@keyframes rf2-head-fall {
  0%   { opacity: 0; transform: translateY(0); }
  12%  { opacity: 1; }
  88%  { opacity: 1; }
  100% { opacity: 1; transform: translateY(var(--rail-h)); }
}

/* ============================================================
   FeatureBulletGrid (D-103 Phase 1.5) — flat, text-dominant grid
   for "what it does" bullets below section heroes. Iris owns
   layout: no glass, line icons in emphasis cyan, mobile 1-col,
   tablet 2-col, desktop 2-or-3-col. No per-bullet motion.
   ============================================================ */
.feature-bullet-grid {
  list-style: none;
  margin: var(--space-8) 0 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-6) var(--space-8);
}
@media (min-width: 768px) {
  .feature-bullet-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 1024px) {
  .feature-bullet-grid--6 { grid-template-columns: repeat(3, 1fr); }
}
.feature-bullet {
  display: flex;
  align-items: flex-start;
  gap: var(--space-4);
}
.feature-bullet__icon {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: var(--radius-md);
  background: rgba(0, 194, 255, 0.08);
  border: 1px solid rgba(0, 194, 255, 0.18);
  color: var(--color-emphasis);
}
.feature-bullet__icon svg {
  display: block;
  width: 22px;
  height: 22px;
}
.feature-bullet__body {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  min-width: 0;
}
.feature-bullet__label {
  font-size: var(--text-base);
  font-weight: var(--weight-semibold);
  color: var(--color-text);
  line-height: var(--leading-snug);
}
.feature-bullet__desc {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  line-height: var(--leading-relaxed);
}

/* ============================================================
   pricing — §14
   ============================================================ */
.pricing-tiers {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-4);
}
@media (min-width: 1024px) { .pricing-tiers { grid-template-columns: repeat(3, 1fr); gap: var(--space-6); } }

.tier-card {
  background-color: rgba(255, 255, 255, 0.04);
  background-image: linear-gradient(180deg, rgba(255, 255, 255, 0.05) 0%, rgba(255, 255, 255, 0.01) 100%);
  border: 1px solid var(--color-border-accent);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-md), inset 0 1px 0 rgba(255, 255, 255, 0.08);
  padding: var(--space-8);
  display: flex;
  flex-direction: column;
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
}
@supports not (backdrop-filter: blur(1px)) {
  .tier-card { background-color: rgba(20, 35, 65, 0.55); }
}
.tier-card.featured {
  border-color: var(--color-border-glow);
  box-shadow: var(--shadow-glow-md);
  position: relative;
  order: -1;
}
@media (min-width: 1024px) { .tier-card.featured { order: 0; } }
.tier-card.featured::before {
  content: '';
  position: absolute;
  inset: 0 0 auto 0;
  height: 6px;
  background: var(--gradient-cta);
  border-radius: var(--radius-xl) var(--radius-xl) 0 0;
}
.tier-badge {
  position: absolute;
  top: var(--space-3);
  right: var(--space-4);
  background: var(--gradient-cta);
  color: var(--color-text-strong);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-pill);
}
.tier-name {
  font-family: var(--font-display);
  font-size: var(--text-sm);
  font-weight: var(--weight-bold);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--color-text-muted);
  margin-bottom: var(--space-3);
}
.tier-price {
  font-family: var(--font-display);
  font-size: var(--text-4xl);
  font-weight: var(--weight-black);
  color: var(--color-text-strong);
  margin-bottom: var(--space-2);
}
.tier-price small { font-size: var(--text-sm); color: var(--color-text-muted); font-weight: var(--weight-regular); display: block; }
/* D-246: quote-only tier price ("Talk to sales") — smaller than the 4xl numeric price */
.tier-price.is-quote { font-size: var(--text-2xl); }
.tier-features {
  list-style: none;
  margin: var(--space-6) 0;
  padding: 0;
  flex: 1;
}
.tier-features li {
  padding: var(--space-2) 0;
  color: var(--color-text);
  font-size: var(--text-sm);
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
}
.tier-features li::before {
  content: '';
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  margin-top: 4px;
  background-color: var(--color-success);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E") no-repeat center;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E") no-repeat center;
}
.tier-features li.includes {
  color: var(--color-primary);
  font-weight: var(--weight-medium);
}
.tier-features li.includes::before { display: none; }

/* Services we can do à la carte — no-price service list (D-246). The priced calculator
   below is dormant (retained for re-enable). */
.alacarte-list { list-style: none; margin: var(--space-6) 0; padding: 0; display: grid; gap: var(--space-3); }
@media (min-width: 768px) { .alacarte-list { grid-template-columns: 1fr 1fr; } }
.alacarte-item {
  padding: var(--space-4);
  border: 1px solid var(--color-border-accent);
  border-radius: var(--radius-lg);
  background-color: rgba(255, 255, 255, 0.03);
}
.alacarte-item .alacarte-name { display: block; color: var(--color-text-strong); font-weight: var(--weight-semibold); font-size: var(--text-base); margin-bottom: var(--space-1); }
.alacarte-item .alacarte-desc { display: block; color: var(--color-text-muted); font-size: var(--text-sm); }

/* à la carte calculator (dormant — D-246) */
.calculator {
  margin-top: var(--space-12);
  background-color: rgba(255, 255, 255, 0.04);
  background-image: linear-gradient(180deg, rgba(255, 255, 255, 0.05) 0%, rgba(255, 255, 255, 0.01) 100%);
  border: 1px solid var(--color-border-accent);
  border-radius: var(--radius-xl);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08);
  padding: var(--space-8);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
}
@supports not (backdrop-filter: blur(1px)) {
  .calculator { background-color: rgba(20, 35, 65, 0.55); }
}
.addon-row {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: var(--space-4);
  align-items: center;
  padding: var(--space-4) 0;
  border-bottom: 1px solid var(--color-border);
}
.addon-row:last-of-type { border-bottom: none; }
.addon-row .addon-meta { display: flex; flex-direction: column; gap: var(--space-1); min-width: 0; } /* D-198: 1fr col shrinks below content so the nowrap price doesn't overflow narrow viewports */
.addon-row .addon-name { color: var(--color-text-strong); font-weight: var(--weight-semibold); font-size: var(--text-base); }
.addon-row .addon-desc { color: var(--color-text-muted); font-size: var(--text-sm); overflow-wrap: break-word; }
.addon-row .addon-price { color: var(--color-emphasis); font-weight: var(--weight-bold); font-size: var(--text-base); white-space: nowrap; }

/* §14.3 toggle switch — role=switch */
.toggle {
  --toggle-w: 56px;
  --toggle-h: 32px;
  appearance: none;
  -webkit-appearance: none;
  width: var(--toggle-w);
  height: var(--toggle-h);
  border-radius: var(--radius-pill);
  background: var(--color-surface-elevated);
  border: 1px solid var(--color-border);
  position: relative;
  cursor: pointer;
  transition: background 200ms ease, border-color 200ms ease, box-shadow 200ms ease;
  flex-shrink: 0;
  margin: 0;
}
.toggle::before {
  content: '';
  position: absolute;
  top: 3px;
  left: 3px;
  width: calc(var(--toggle-h) - 8px);
  height: calc(var(--toggle-h) - 8px);
  border-radius: 50%;
  background: var(--color-text-strong);
  transition: transform 200ms ease;
}
.toggle[aria-checked="true"] {
  background: var(--color-primary);
  border-color: var(--color-primary);
  box-shadow: var(--shadow-glow-sm);
}
.toggle[aria-checked="true"]::before {
  transform: translateX(calc(var(--toggle-w) - var(--toggle-h)));
}
.toggle:focus-visible { outline: 2px solid var(--color-emphasis); outline-offset: 3px; }

.calculator-total {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  padding: var(--space-5) 0;
  margin-top: var(--space-3);
  border-top: 2px solid var(--color-border-accent);
  font-size: var(--text-lg);
}
.calculator-total .total-label { color: var(--color-text); font-weight: var(--weight-medium); }
.calculator-total .total-value {
  font-family: var(--font-display);
  font-size: var(--text-3xl);
  font-weight: var(--weight-black);
  color: var(--color-emphasis);
}
.calculator-note {
  font-size: var(--text-xs);
  color: var(--color-text-muted);
  margin: 0 0 var(--space-6);
}

/* ============================================================
   §6.7 footer
   ============================================================ */
/* D-182: footer reads as a distinct navy-glass shelf (was a bare transparent
   band that bled into the page bg). Translucent navy gradient + backdrop-blur
   softens the body grid behind it; lit top edge + cyan border-image gives the
   delineation/"pop". Gradient bottoms toward void-black so muted text contrast
   stays >= base-bg (AA holds). Solid fallback for no-backdrop browsers. */
.footer {
  border-top: 1px solid transparent;
  border-image: linear-gradient(90deg, transparent 0%, rgba(0, 194, 255, 0.32) 50%, transparent 100%) 1;
  padding: var(--space-16) 0 var(--space-8);
  margin-top: var(--space-24);
  background: linear-gradient(180deg, rgba(10, 22, 40, 0.55) 0%, rgba(2, 8, 16, 0.80) 100%);
  backdrop-filter: blur(24px) saturate(140%);
  -webkit-backdrop-filter: blur(24px) saturate(140%);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06);
}
@supports not (backdrop-filter: blur(1px)) {
  .footer { background: linear-gradient(180deg, #0A1628 0%, #020810 100%); }
}
.footer-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-8);
}
@media (min-width: 768px) { .footer-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .footer-grid { grid-template-columns: 1.5fr 1fr 1fr 1fr; } }
.footer-col h3 {
  font-family: var(--font-sans);
  font-size: 11px;
  font-weight: var(--weight-bold);
  color: var(--color-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.10em;
  margin-bottom: var(--space-4);
}
.footer-col ul { list-style: none; margin: 0; padding: 0; }
.footer-col li { padding: var(--space-1) 0; }
.footer-col a {
  color: var(--color-text);                /* D-182: was --color-text-muted; brighter on the new tinted glass keeps AA + sets link/label hierarchy */
  font-size: var(--text-sm);
  transition: color 180ms ease, text-shadow 180ms ease;
}
.footer-col a:hover,
.footer-col a:focus-visible {
  color: var(--color-text-strong);
  text-shadow: 0 0 12px rgba(0, 194, 255, 0.40);
  outline: none;
}
/* D-226 a11y: restore a conforming focus ring (the block above used a glow-only cue and overrode the global a:focus-visible outline). */
.footer-col a:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}
.footer-tagline { color: var(--color-text-muted); font-size: var(--text-sm); margin-top: var(--space-3); max-width: 32ch; }
.footer-bottom {
  margin-top: var(--space-12);
  padding-top: var(--space-6);
  border-top: 1px solid transparent;
  border-image: linear-gradient(90deg, transparent 0%, rgba(0, 194, 255, 0.20) 50%, transparent 100%) 1;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-4);
  color: var(--color-text-muted);
  font-size: var(--text-xs);
}
.footer-legal-links { display: flex; gap: var(--space-4); flex-wrap: wrap; list-style: none; margin: 0; padding: 0; }
.footer-legal-links a { color: var(--color-text-muted); }

/* ============================================================
   utility
   ============================================================ */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
.text-center { text-align: center; }
.text-emphasis { color: var(--color-emphasis); }
.text-muted { color: var(--color-text-muted); }
.mb-0 { margin-bottom: 0; }

/* utility — D-025 enforces classes over inline styles */
.mb-2 { margin-bottom: var(--space-2); }
.mb-3 { margin-bottom: var(--space-3); }
.mb-6 { margin-bottom: var(--space-6); }
.mb-10 { margin-bottom: var(--space-10); }
.mt-6 { margin-top: var(--space-6); }
.m-0 { margin: 0; }
.text-sm { font-size: var(--text-sm); }
.text-xs { font-size: var(--text-xs); }
.text-xl { font-size: var(--text-xl); }
.list-reset { list-style: none; margin: 0; padding: 0; }

/* Context-driven centering. When .hero-actions / .hero-sub live inside a
   .text-center container (the standard hero pattern on every audience hub
   and conversion page), they auto-center — no inline style="..." per route. */
.text-center .hero-actions { justify-content: center; }
.text-center .hero-sub { margin-inline: auto; }

/* FAQ accordions: every <details><summary><h3> on the site needs the
   heading rendered inline so the summary stays one-line. Single rule
   beats a per-route inline style="display:inline;" attribute. */
summary > h3 { display: inline; }

/* breadcrumb list — used by all pillar routes */
.breadcrumb-list {
  list-style: none;
  display: flex;
  gap: var(--space-2);
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  margin: 0;
  padding: 0;
}
.breadcrumb-nav { padding-top: var(--space-6); }

/* CTA trust list — small badges below primary CTA */
.cta-trust-list {
  list-style: none;
  padding: 0;
  margin-top: var(--space-6);
  display: flex;
  justify-content: center;
  gap: var(--space-6);
  flex-wrap: wrap;
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}

/* In-body text links — WCAG 1.4.1 distinguishability.
   Link color #0096FF on body color #E8EDF8 is 2.62:1, below the 3:1
   color-only threshold. Underline keeps the link distinguishable without
   color reliance. Excludes .btn (CTA buttons) and elements inside .nav-*
   header/footer surfaces (those have their own hover treatments). */
main p a:not(.btn),
main li > a:not(.btn),
main strong a:not(.btn),
.lead a:not(.btn) {
  text-decoration: underline;
  text-decoration-color: currentColor;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  text-decoration-skip-ink: auto;
}
main p a:not(.btn):hover,
main li > a:not(.btn):hover {
  text-decoration-thickness: 2px;
}

/* ============================================================
   §21.4 team grid — /about/team bio cards
   ============================================================ */
/* D-186: .founders-grid retired — every team row now uses .team-grid (below)
   so all cards are the same width. */
.founder-photo {
  aspect-ratio: 1 / 1;
  background: var(--color-surface-elevated);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  margin-bottom: var(--space-5);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}
.founder-photo img { width: 100%; height: 100%; object-fit: cover; }

/* D-194: /about/story founder intro — alternating photo/bio rows (replaces the
   retired .founders-grid, which had left these photos full-container-width-huge).
   Photo is a fixed ~220px square; --reverse flips it to the right (Josh). Stacks
   on mobile. */
.founder-rows {
  display: flex;
  flex-direction: column;
  gap: var(--space-10);
  max-width: 820px;
  margin: 0 auto;
}
.founder-row {
  display: flex;
  align-items: center;
  gap: var(--space-8);
}
.founder-row--reverse { flex-direction: row-reverse; }
.founder-row__photo { flex: 0 0 220px; }
.founder-row__photo img {
  display: block;
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  border-radius: var(--radius-lg);
  border: 1px solid var(--color-border);
}
@media (max-width: 767px) {
  .founder-row,
  .founder-row--reverse {
    flex-direction: column;
    gap: var(--space-5);
  }
  .founder-row__photo { flex-basis: auto; width: 200px; margin: 0 auto; }
}

/* D-194: generic 2-up card grid (replaces the retired .founders-grid on the
   /about hub's two "Start here" pillar cards). 1-col mobile -> 2-col at 768. */
.grid-2up {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-6);
}
@media (min-width: 768px) {
  .grid-2up { grid-template-columns: repeat(2, 1fr); gap: var(--space-8); }
}

/* D-186: every team row (Founders pair, Leadership trio, Client Success pair)
   shares ONE grid so all cards are identical width. Flex + center + a capped
   card width means a 2-card row sits centered at the same ~1/3 width as the
   3-card row instead of stretching to halves. --pair adds a little more air
   between the two cards (the "three columns, blank middle, pushed together"
   look) without an empty cell. */
.team-grid {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: flex-start;          /* D-187: expanding one bio must not stretch its row siblings */
  gap: var(--space-6);
}
.team-grid > .card {
  flex: 1 1 280px;
  max-width: 360px;
}
/* D-187: smaller name so long names (e.g. "Braden DiCristofano") stay on one
   line — keeps every card the same height. */
.team-grid .card h3 { font-size: var(--text-xl); }
.team-grid--pair { gap: var(--space-12); }
.founder-photo .placeholder {
  color: var(--color-text-muted);
  font-size: var(--text-sm);
  text-align: center;
  padding: var(--space-4);
}

/* D-186: LinkedIn icon link on each team card — transparent "in" glyph inside
   a circular ring; muted at rest, cyan on hover. */
.card-social { margin-top: var(--space-4); display: flex; gap: var(--space-3); }

/* D-187: bio clamp + read-more. Clamped to 3 lines so cards collapse to a
   uniform height; .is-expanded (toggled by ABOUT_TEAM_JS) removes the clamp.
   The toggle button ships hidden and is revealed by JS only when the bio
   overflows. */
.card-bio {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  line-clamp: 3;
  overflow: hidden;
}
.card-bio.is-expanded {
  display: block;
  -webkit-line-clamp: unset;
  line-clamp: unset;
  overflow: visible;
}
.card-bio__toggle {
  margin-top: var(--space-2);
  padding: 0;
  background: none;
  border: none;
  color: var(--color-emphasis);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  cursor: pointer;
}
.card-bio__toggle:hover { color: var(--color-text-strong); }
.card-bio__toggle:focus-visible {
  outline: 2px solid var(--color-emphasis);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}
/* D-189: .team-profile (author-page icon) shares the .team-linkedin ring exactly. */
.team-linkedin,
.team-profile {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: 1px solid var(--color-border-accent);
  color: var(--color-text);                  /* D-186 (Iris): was --color-text-muted; bumped so the "in" glyph clears WCAG 1.4.11 3:1 at rest */
  transition: color 180ms ease, border-color 180ms ease, background 180ms ease, transform 180ms ease;
}
.team-linkedin svg,
.team-profile svg { width: 18px; height: 18px; display: block; }
.team-linkedin:hover,
.team-profile:hover {
  color: var(--color-primary);
  border-color: var(--color-border-glow);
  background: rgba(0, 194, 255, 0.08);
  transform: translateY(-2px);
}
.team-linkedin:focus-visible,
.team-profile:focus-visible {
  outline: 2px solid var(--color-emphasis);
  outline-offset: 2px;
}

/* ============================================================
   Demo-success personalization (D-179) — VP-of-Sales 2-col +
   reused home walkthrough video + centered CTA row. Reuses
   .founder-photo for Roby's headshot + .solutions-showcase__video
   for the player; only the layout wrappers are new.
   ============================================================ */
.demo-success-personal {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-6);
  align-items: center;
  max-width: 860px;
  margin: 0 auto;
}
.demo-success-personal__photo {
  max-width: 200px;
  margin: 0 auto var(--space-2);
}
.demo-success-personal__copy h2 { margin-bottom: var(--space-3); }
@media (min-width: 768px) {
  .demo-success-personal { grid-template-columns: 200px 1fr; gap: var(--space-8); }
  .demo-success-personal__photo { margin: 0; }
}
.demo-success-video { max-width: 760px; margin: var(--space-6) auto 0; }
@media (min-width: 1024px) {
  /* The home applies a grid-fill (height:100%) override at desktop; standalone
     here, restore the frame's natural 16:9. */
  .demo-success-video .solutions-showcase__video {
    aspect-ratio: 16 / 9;
    height: auto;
    min-height: 0;
  }
}
.demo-success-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
  justify-content: center;
}

/* ============================================================
   §22.3 contact grid — /contact methods + form 2-col on desktop
   ============================================================ */
.contact-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-8);
}
@media (min-width: 1024px) {
  .contact-grid { grid-template-columns: 1fr 2fr; gap: var(--space-12); align-items: start; }
}
.contact-methods p { margin-bottom: var(--space-3); }

/* ============================================================
   §23.4 product hub pillar grid — wider 3-col cards with descriptions
   ============================================================ */
.pillar-grid-hub {
  grid-template-columns: 1fr;
  gap: var(--space-5);
}
@media (min-width: 640px) { .pillar-grid-hub { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .pillar-grid-hub { grid-template-columns: repeat(3, 1fr); gap: var(--space-6); } }
/* Orphan-row guard: when the last card lands in column 1 of a new row
   (count not a multiple of column count), stretch it to span the row. */
.pillar-grid-hub > :last-child:nth-child(3n + 1) { grid-column: 1 / -1; }
/* Hub variant bumps card body color from muted to body-tone — closes §20.4 P2 */
.pillar-grid-hub .pillar-card p {
  color: var(--color-text);
  margin: var(--space-3) 0;
  line-height: var(--leading-normal);
}
/* Inert (deferred) pillar cards — no link, no hover affordance, same surface */
.pillar-card-inert {
  display: block;
  color: var(--color-text);
  /* Flattened from glass (D-165 / Iris + Compass glass-budget fix): inert
     directory grids render up to ~37 of these on one page (e.g. /integrations/wms),
     well past the ~16-backdrop-filter ceiling. The opaque elevated fill (was the
     @supports-not fallback) holds the rhythm at zero per-frame paint cost. */
  background-color: rgba(20, 35, 65, 0.55);
  background-image: linear-gradient(180deg, rgba(255, 255, 255, 0.05) 0%, rgba(255, 255, 255, 0.01) 100%);
  border: 1px solid var(--color-border-accent);
  border-radius: var(--radius-lg);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08);
  padding: var(--space-5);
}
.pillar-card-inert .pillar-title {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-family: var(--font-display);
  font-weight: var(--weight-bold);
  font-size: var(--text-lg);
  color: var(--color-text-strong);
  margin-bottom: var(--space-2);
}
/* Small category tag inside partner / integration cards */
.partner-category {
  display: inline-block;
  margin: 0 0 var(--space-3);
  padding: 2px var(--space-2);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  letter-spacing: 0.04em;
  color: var(--color-emphasis);
  border: 1px solid var(--color-border-accent);
  border-radius: var(--radius-pill);
  text-transform: uppercase;
}
/* D-203/D-208: partner cards (full-bleed logo header + padded body) + per-partner
   detail hero. Logos sit on a white plate so dark/transparent PNGs stay legible
   on the dark theme; the plate now spans the full card top (no inset 'viewport'). */
.partner-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-4);
}
@media (min-width: 640px) { .partner-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .partner-grid { grid-template-columns: repeat(3, 1fr); } }
.partner-card {
  display: flex;
  flex-direction: column;
  padding: 0;
  overflow: hidden;
  border-radius: var(--radius-lg);
  background: rgba(15, 28, 52, 0.45);
  border: 1px solid var(--color-border);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08);
  color: var(--color-text);
  text-decoration: none;
  transition: border-color 200ms ease, transform 150ms ease, box-shadow 200ms ease;
}
.partner-card:hover {
  border-color: var(--color-border-glow);
  transform: translateY(-2px);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.12), 0 10px 30px rgba(5, 12, 26, 0.35);
}
.partner-card:focus-visible { outline: 2px solid var(--color-emphasis); outline-offset: 3px; }
.partner-card__logo {
  width: 100%;
  height: 168px;
  overflow: hidden;
  background: #ffffff; /* safety only — fills behind any transparent-source logo; badge logos cover it edge-to-edge */
}
.partner-card__logo img { display: block; width: 100%; height: 100%; object-fit: cover; }
.partner-card__body {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-2);
  padding: var(--space-5);
}
.partner-card__name {
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-weight: var(--weight-semibold);
  color: var(--color-text-strong);
}
.partner-card__blurb { font-size: var(--text-sm); color: var(--color-text-muted); margin: 0; }
.partner-card__cue {
  margin-top: var(--space-2);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  color: var(--color-emphasis);
}
.partner-detail__head {
  display: flex;
  align-items: center;
  gap: var(--space-6);
  margin-bottom: var(--space-6);
  flex-wrap: wrap;
}
.partner-detail__heading { min-width: 0; }
.partner-detail__tagline {
  margin: var(--space-2) 0 0;
  font-size: var(--text-lg);
  color: var(--color-text-muted);
}
/* D-208: bigger logo plate, minimal padding so the logo fills the panel
   (was a small logo floating in a heavily-padded 140x96 tile). */
.partner-logo-tile {
  width: clamp(220px, 44vw, 300px);
  height: 180px;
  flex: 0 0 auto;
  overflow: hidden;
  background: #ffffff; /* safety only — see .partner-card__logo */
  border-radius: var(--radius-lg);
}
.partner-logo-tile img { display: block; width: 100%; height: 100%; object-fit: cover; }
.partner-detail__summary { max-width: 64ch; }
/* Shared 'how this fits a 3PL stack' block atop each category page */
.partner-stackfit {
  margin: 0 auto var(--space-10);
  text-align: center;
}
@media (prefers-reduced-motion: reduce) { .partner-card { transition: none; } }

/* FAQ list — per-partner shared FAQ (details/summary base rules live above) */
.faq-list { display: flex; flex-direction: column; gap: var(--space-3); }
.faq-item {
  padding: var(--space-4) var(--space-5);
  background: rgba(15, 28, 52, 0.4);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
}
.faq-item > summary { list-style: none; }
.faq-item > summary::-webkit-details-marker { display: none; }
.faq-item p { margin: var(--space-2) 0 0; color: var(--color-text-muted); }

/* Radio group — hub press/partnership/affiliate inquiry selector */
.pf-radio-group { border: 0; padding: 0; margin: 0 0 var(--space-5); }
.pf-radio-group legend {
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  color: var(--color-text-strong);
  margin-bottom: var(--space-2);
  padding: 0;
}
.pf-radio {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-sm);
  color: var(--color-text);
  padding: var(--space-1) 0;
  cursor: pointer;
}
.pf-radio input { accent-color: var(--color-primary); }

.pillar-grid-hub .pillar-card-inert p {
  font-size: var(--text-sm);
  color: var(--color-text);
  margin: var(--space-3) 0;
  line-height: var(--leading-normal);
}
/* Global focus-visible outline — closes §20.4 P2 backlog item */
.pillar-card:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 4px;
}

/* D-110: Pillar showcase (product hub) — 2 groups of intro+3-card 2x2 grid.
   SPLIT-CANDIDATE: pillar-showcase block. */
.pillar-showcase {
  position: relative;
  /* D-110c dot-grid retired by D-128 — now inherits the body-stack
     ambient dot-grid sitewide-except-home. The section keeps
     position: relative so the per-section bloom pseudo below
     (or any cyan-glow bloom variant) anchors correctly. */
}

.pillar-group {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-6);
  position: relative;
  margin-bottom: var(--space-12);
  padding-bottom: var(--space-8);
}

.pillar-group:last-of-type {
  margin-bottom: 0;
}

/* D-110d: centered cyan ambient bloom */
.pillar-group::before {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse 75% 65% at 50% 50%, rgba(0, 194, 255, 0.08), transparent 75%); /* D-116b: 0.12 → 0.08 */
  pointer-events: none;
  z-index: -1;
}

/* B-010: 2-col activates at 900px (not 768) */
@media (min-width: 900px) {
  .pillar-group {
    grid-template-columns: 1fr 1fr;
    gap: var(--space-6);
  }
  .pillar-group--text-left {
    grid-template-areas:
      "intro    featured"
      "card-a   card-b";
  }
  .pillar-group--text-right {
    grid-template-areas:
      "featured intro"
      "card-a   card-b";
  }
  .pillar-group__intro { grid-area: intro; }
  .pillar-group > .showcase-card:nth-of-type(1) { grid-area: featured; }
  .pillar-group > .showcase-card:nth-of-type(2) { grid-area: card-a; }
  .pillar-group > .showcase-card:nth-of-type(3) { grid-area: card-b; }
}

/* Intro text block — sits in one quadrant of the 2x2 grid */
.pillar-group__intro {
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: var(--space-4) var(--space-6);
}

.pillar-group__intro .eyebrow {
  margin-bottom: var(--space-3);
}

.pillar-group__heading {
  font-family: var(--font-display);
  font-weight: var(--weight-bold);
  font-size: var(--text-3xl);
  color: var(--color-text-strong);
  line-height: var(--leading-tight);
  margin: 0 0 var(--space-4) 0;
}

.pillar-group__body {
  color: var(--color-text-muted);
  font-size: var(--text-base);
  line-height: var(--leading-relaxed);
  margin: 0;
}

/* Showcase cards — distinct from base .pillar-card. Glass treatment
   matches the flagship-hero family at subtler intensity (matches
   .section--narrative's secondary-surface posture so showcase cards
   read as siblings to the narrative panels above/below). */
.showcase-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-6);
  border-radius: var(--radius-lg);
  /* D-110c: bg opacity reduced from 0.32 → 0.22 so the dot-grid backdrop on
     .pillar-showcase shows through subtly behind cards. Cards now read as
     "floating on the grid" rather than blocking it. The cyan border still
     defines the card silhouette; backdrop-filter still adds glass character. */
  background-color: rgba(15, 28, 52, 0.22);
  background-image: linear-gradient(180deg, rgba(0, 194, 255, 0.04) 0%, transparent 60%);
  border: 1px solid rgba(0, 194, 255, 0.18);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06), 0 4px 24px rgba(0, 0, 0, 0.20);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  text-decoration: none;
  color: var(--color-text);
  transition: border-color 220ms ease, transform 220ms ease, box-shadow 220ms ease, background-color 220ms ease;
}

@supports not (backdrop-filter: blur(1px)) {
  .showcase-card { background-color: rgba(20, 35, 65, 0.55); }
}

.showcase-card:hover {
  border-color: rgba(0, 194, 255, 0.45);
  transform: translateY(-2px);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08), 0 8px 32px rgba(0, 194, 255, 0.12);
}

.showcase-card:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 4px;
  border-color: rgba(0, 194, 255, 0.45);
  transform: translateY(-2px);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08), 0 8px 32px rgba(0, 194, 255, 0.12);
}

/* D-110d: removed .showcase-card--featured variant per user feedback. The
   per-group "focal card" treatment was creating visual asymmetry that
   pulled attention away from the bloom-as-section-tying-element. All cards
   now render uniformly so the cyan ambient bloom is the single focal cue. */

.showcase-card__title {
  display: block;
  font-family: var(--font-display);
  font-weight: var(--weight-bold);
  font-size: var(--text-xl);
  color: var(--color-text-strong);
  margin-bottom: var(--space-1);
}

.showcase-card__body {
  font-size: var(--text-sm);
  color: var(--color-text);
  line-height: var(--leading-normal);
  margin: 0;
  flex: 1;
}

.showcase-card__cta {
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  color: var(--color-emphasis);
  margin-top: var(--space-3);
}

/* ============================================================
   D-110: Orbit AI standalone feature section. Distinct from the
   2x2 pillar-group layout — Orbit is the overarching layer, not a
   peer of the 6 features, so it gets its own wider full-width card
   with a complementary visual on the right side.
   ============================================================ */
.orbit-feature {
  position: relative;
  /* D-110c dot-grid retired by D-128 — now inherits the body-stack
     ambient dot-grid sitewide-except-home. The dotted continuity
     across .pillar-showcase and .orbit-feature is unchanged — both
     surfaces are non-home, so both inherit the same body-stack pattern.
     Position: relative kept so the bloom pseudo below anchors here. */
}

.orbit-feature::before {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse 60% 40% at 75% 50%, rgba(0, 194, 255, 0.06), transparent 65%); /* D-116b: 0.08 → 0.06 */
  pointer-events: none;
  z-index: -1;
}

.orbit-feature__card {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-6);
  padding: var(--space-10) var(--space-8);
  border-radius: var(--radius-lg);
  /* D-110c: bg opacity reduced from 0.42 → 0.30 to let the dot-grid backdrop
     show through. Border + radial cyan glow on the right + backdrop-filter
     keep the card distinctive without an opaque fill. */
  background-color: rgba(15, 28, 52, 0.30);
  background-image:
    radial-gradient(ellipse 60% 80% at 80% 50%, rgba(0, 194, 255, 0.10) 0%, transparent 70%),
    linear-gradient(180deg, rgba(0, 194, 255, 0.04) 0%, transparent 100%);
  border: 1px solid rgba(0, 194, 255, 0.32);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08), 0 8px 32px rgba(0, 194, 255, 0.14);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  text-decoration: none;
  color: var(--color-text);
  transition: border-color 220ms ease, box-shadow 220ms ease, transform 220ms ease;
  align-items: center;
}

@supports not (backdrop-filter: blur(1px)) {
  .orbit-feature__card { background-color: rgba(20, 35, 65, 0.55); }
}

@media (min-width: 768px) {
  .orbit-feature__card {
    grid-template-columns: 1fr auto;
    gap: var(--space-12);
    padding: var(--space-12) var(--space-10);
  }
}

.orbit-feature__card:hover {
  border-color: rgba(0, 194, 255, 0.45);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.10), 0 12px 40px rgba(0, 194, 255, 0.18); /* D-116b: glow 0.25 → 0.18 */
  transform: translateY(-2px);
}

.orbit-feature__card:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 4px;
  border-color: rgba(0, 194, 255, 0.55);
}

/* D-110b: H2 hoisted out of the clickable .orbit-feature__card per a11y
   audit (heading inside an interactive element confuses screen readers).
   The header now sits above the card; the card contains only lead + CTA
   + visual. */
.orbit-feature__header {
  text-align: center;
  margin-bottom: var(--space-6);
}

.orbit-feature__header .eyebrow {
  margin-bottom: var(--space-2);
}

.orbit-feature__title {
  font-family: var(--font-display);
  font-weight: var(--weight-bold);
  font-size: var(--text-3xl);
  color: var(--color-text-strong);
  line-height: var(--leading-tight);
  margin: 0;
}

.orbit-feature__content {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.orbit-feature__lead {
  font-size: var(--text-base);
  color: var(--color-text);
  line-height: var(--leading-relaxed);
  margin: 0;
}

.orbit-feature__cta {
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  color: var(--color-emphasis);
  margin-top: var(--space-2);
}

.orbit-feature__visual {
  display: flex;
  align-items: center;
  justify-content: center;
}

.orbit-feature__visual svg {
  filter: drop-shadow(0 4px 16px rgba(0, 194, 255, 0.28)); /* D-116b: 0.40 → 0.28 */
}

/* details/summary spacing for FAQ accordion */
details {
  margin-bottom: var(--space-4);
  padding: var(--space-4);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
}
details summary { cursor: pointer; }
details summary h3 { display: inline; margin: 0; font-size: var(--text-base); font-weight: var(--weight-semibold); }
details[open] summary { margin-bottom: var(--space-2); }

/* ============================================================
   §3.11 text-shadow overrides — clear shadows when user signals
   a preference for minimal visual noise or higher contrast.
   ============================================================ */
@media (prefers-reduced-motion: reduce), (prefers-contrast: more) {
  h2,
  .hero h1,
  .hero .gradient-text,
  .card-metric .metric-number { text-shadow: none; }
}

/* ============================================================
   §5.2 Mega-menu nav (D-046 IA + D-047 reactor pip)
   Outlined-frame translucent panels — no white surface change,
   continues the sitewide ambient. Reactor pip indicator + underline
   draw + curtain reveal. All animations transform/opacity/clip-path
   only — GPU compositor, no layout work.
   ============================================================ */
.nav { transition: backdrop-filter 280ms ease, background-color 280ms ease; }
.nav.is-scrolled {
  background-color: rgba(15, 28, 52, 0.58);
  backdrop-filter: blur(32px) saturate(220%);
  -webkit-backdrop-filter: blur(32px) saturate(220%);
  border-bottom-color: rgba(255, 255, 255, 0.14);
}

.nav-inner { position: relative; }

.nav-links { gap: var(--space-2); }

.nav-item { position: static; list-style: none; }
.nav-item--dropdown { position: static; }

/* Trigger — applies to both <button> dropdowns and flat <a> links */
.nav-trigger {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-4);
  background: transparent;
  border: 0;
  border-radius: var(--radius-md);
  color: var(--color-text);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  cursor: pointer;
  min-height: 44px;
  text-decoration: none;
  transition: color 150ms ease, background 200ms ease;
}
.nav-trigger:hover,
.nav-trigger[aria-expanded="true"] {
  color: var(--color-text-strong);
  background: rgba(0, 194, 255, 0.06);
}
.nav-trigger[aria-current="page"],
.nav-trigger[aria-current="true"] {
  color: var(--color-emphasis);
}
.nav-trigger:focus-visible {
  outline: 2px solid var(--color-emphasis);
  outline-offset: 2px;
}
.nav-trigger__label { position: relative; z-index: 1; }

/* D-050: indicator on the trigger is the underline-draw only. Mobile
   drawer uses a CSS-only +/− toggle (see §5.3 below). */

/* Underline draw — pure CSS, draws left→right on hover/focus/open. */
.nav-underline {
  position: absolute;
  left: var(--space-4);
  right: var(--space-4);
  bottom: 6px;
  height: 1px;
  background: var(--color-emphasis);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 220ms cubic-bezier(0.4, 0, 0.2, 1);
  pointer-events: none;
}
.nav-trigger:hover .nav-underline,
.nav-trigger:focus-visible .nav-underline,
.nav-trigger[aria-expanded="true"] .nav-underline {
  transform: scaleX(1);
}

/* Mega-menu panel — outlined frame, translucent over ambient.
   Curtain reveal: clip-path inset bottom collapses → opens. */
.megamenu {
  position: absolute;
  top: calc(100% + var(--space-2));
  left: var(--space-6);
  right: var(--space-6);
  margin: 0 auto;
  max-width: var(--container-max);
  padding: var(--space-6);
  /* D-053 + D-069 + Option C: dark base 0.985 (was 0.96) — kill background bleed-through under the panel */
  background-color: rgba(10, 20, 38, 0.985);
  background-image: linear-gradient(180deg, rgba(255, 255, 255, 0.06) 0%, rgba(255, 255, 255, 0.01) 100%);
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-glow-md), 0 24px 48px rgba(0, 0, 0, 0.55),
              inset 0 1px 0 rgba(255, 255, 255, 0.10);
  backdrop-filter: blur(28px) saturate(180%);
  -webkit-backdrop-filter: blur(28px) saturate(180%);
  z-index: 90;
  opacity: 0;
  transform: translateY(-4px);
  clip-path: inset(0 0 100% 0);
  pointer-events: none;
  transition: opacity 240ms ease,
              transform 280ms cubic-bezier(0.4, 0, 0.2, 1),
              clip-path 320ms cubic-bezier(0.4, 0, 0.2, 1);
}
@media (prefers-reduced-transparency: reduce) {
  .megamenu {
    background-color: rgba(10, 20, 38, 1);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }
}
@supports not (backdrop-filter: blur(1px)) {
  .megamenu { background-color: rgba(10, 20, 38, 0.98); }
}
.megamenu[data-state="open"] {
  opacity: 1;
  transform: translateY(0);
  clip-path: inset(0 0 0% 0);
  pointer-events: auto;
}
@supports not (clip-path: inset(0)) {
  .megamenu { clip-path: none; }
}
@supports not (backdrop-filter: blur(1px)) {
  .megamenu { background: rgba(8, 17, 31, 0.96); }
}

.megamenu__grid {
  display: grid;
  gap: var(--space-6);
  align-items: start;
}
.megamenu__grid--cols-1 { grid-template-columns: 1fr; }
.megamenu__grid--cols-2 { grid-template-columns: 1fr 1.2fr; }
.megamenu__grid--cols-3 { grid-template-columns: 1fr 1fr 1.2fr; }
.megamenu__grid--cols-4 { grid-template-columns: 1fr 1fr 1fr 1.2fr; }

/* D-185: compact dropdown (no featured slot) — a content-width panel anchored
   under its own trigger instead of the full-width mega-panel. Used by About,
   where a 2-link menu would look sparse spread across the full container.
   Reuses every .megamenu visual + open/close transition; only position + size
   are overridden. The trigger li becomes the positioning context. */
.nav-item--compact { position: relative; }
.megamenu.megamenu--compact {
  left: 0;
  right: auto;
  margin: 0;
  width: max-content;
  min-width: 220px;
  max-width: 340px;
  padding: var(--space-2);
}

.megamenu__cluster { min-width: 0; display: flex; flex-direction: column; }

/* Stacked sub-sections inside a single column (D-051). Each subsection
   has its own eyebrow + items, separated by spacing. Used by Platform to
   stack Recharge Billing on top of Margin Recovery. */
.megamenu__subsection + .megamenu__subsection { margin-top: var(--space-4); padding-top: var(--space-4); border-top: 1px solid rgba(255, 255, 255, 0.08); }
.megamenu__subsection-eyebrow {
  font-size: 11px;
  font-weight: var(--weight-bold);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  margin: 0 0 var(--space-3);
}

/* D-182 / D-183 / D-184: final-CTA arrow links differentiate from the plain
   leaf links by COLOR (cyan) only — no box/chip, no hover box (per user). The
   arrow is a decorative ::after (stripped from the label text → cleaner
   accessible name) that wiggles on hover/focus — transform-only + reduced-
   motion gated. Focus-visible keeps a real outline (a11y focus indicator that
   replaces the removed background; only shows for keyboard nav, never hover).
   D-184: selector is ANCESTOR-PREFIXED (.megamenu prefix, 0,2,0) ON PURPOSE —
   the broad '.nav-links a' rule (0,1,1) in styles/nav.ts otherwise wins and
   paints this anchor --color-text (white). Do NOT flatten the selector or the
   cyan silently reverts to white. (Leaf links dodge it via inner spans; see-all
   colors its anchor text directly, so it needs the specificity.) */
.megamenu .megamenu__see-all {
  display: inline-flex;
  align-items: center;
  margin-top: var(--space-3);
  padding: var(--space-2) var(--space-3);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  color: var(--color-emphasis);
  text-decoration: none;
  border-radius: var(--radius-md);
  transition: color 180ms ease;
}
.megamenu__see-all::after {
  content: "→";
  margin-left: 0.4em;
  transition: transform 200ms ease;
}
.megamenu .megamenu__see-all:hover {
  color: var(--color-text-strong);
}
.megamenu .megamenu__see-all:focus-visible {
  color: var(--color-text-strong);
  outline: 2px solid var(--color-emphasis);
  outline-offset: 2px;
}
.megamenu__see-all:hover::after,
.megamenu__see-all:focus-visible::after {
  animation: menu-cta-arrow 600ms ease;
}
@keyframes menu-cta-arrow {
  0%, 100% { transform: translateX(0); }
  25% { transform: translateX(4px); }
  55% { transform: translateX(1px); }
  80% { transform: translateX(3px); }
}
@media (prefers-reduced-motion: reduce) {
  .megamenu__see-all:hover::after,
  .megamenu__see-all:focus-visible::after { animation: none; }
}
.megamenu__cluster-eyebrow {
  font-size: 12px;
  font-weight: var(--weight-bold);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--color-text-strong);
  margin: 0 0 var(--space-3);
  padding-bottom: var(--space-2);
  border-bottom: 1px solid rgba(255, 255, 255, 0.10);
}
.megamenu__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}
.megamenu__link {
  position: relative;
  display: block;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-md);
  border: 1px solid transparent;
  color: var(--color-text);
  text-decoration: none;
  overflow: hidden;
  transition: background 180ms ease, border-color 180ms ease, transform 180ms ease;
}
/* Static top-center spotlight bloom (D-053) — replaces panel-wide
   cursor-follow gradient. Illuminates each card from above on hover. */
.megamenu__link::before {
  content: '';
  position: absolute;
  top: 0;
  left: 50%;
  width: 80%;
  height: 90%;
  transform: translateX(-50%);
  background: radial-gradient(ellipse at center top, rgba(0, 194, 255, 0.06) 0%, transparent 65%); /* Option C: very light cyan hover bloom (was 0.16) */
  opacity: 0;
  transition: opacity 220ms ease;
  pointer-events: none;
  z-index: 0;
}
.megamenu__link:hover::before,
.megamenu__link:focus-visible::before { opacity: 1; }
.megamenu__link > * { position: relative; z-index: 1; }
.megamenu__link:hover,
.megamenu__link:focus-visible {
  background: rgba(0, 194, 255, 0.05);
  border-color: transparent;
  color: var(--color-text-strong);
  outline: none;
}
/* D-226 a11y: focus ring distinct from hover (focus was sub-3:1, identical to hover). Inset offset so it reads inside the menu panel. */
.megamenu__link:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: -2px;
}
.megamenu__link-title {
  display: block;
  font-family: var(--font-display);
  font-size: var(--text-base);
  font-weight: var(--weight-semibold);
  color: var(--color-text-strong);
}
.megamenu__link-desc {
  display: block;
  margin-top: 2px;
  font-size: var(--text-xs);
  color: var(--color-text-muted);
  line-height: var(--leading-snug);
}
/* D-093: disabled mega-menu leaves render as <span aria-disabled="true">
   instead of <a>. Preserves IA signal for items the user has confirmed are
   coming (Glossary, Help & Docs) without click-through to a stand-in page.
   No hover/focus glow — the spotlight bloom is gated to anchors only. */
.megamenu__link--disabled {
  cursor: not-allowed;
  opacity: 0.55;
}
.megamenu__link--disabled .megamenu__link-title { color: var(--color-text-muted); }
.nav-drawer__link--disabled {
  display: block;
  padding: var(--space-2) 0;
  color: var(--color-text-muted);
  opacity: 0.65;
  cursor: not-allowed;
}

/* Featured slot — CTA variant uses gradient surface, card variant uses
   outlined-frame surface to read as content rather than action. */
.megamenu__featured {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-5);
  border-radius: var(--radius-lg);
  text-decoration: none;
  transition: transform 200ms ease, box-shadow 200ms ease, border-color 200ms ease;
}
.megamenu__featured--cta {
  background: linear-gradient(135deg, rgba(0, 194, 255, 0.18) 0%, rgba(0, 194, 255, 0.10) 100%);
  border: 1px solid var(--color-border-glow);
  color: var(--color-text-strong);
}
.megamenu__featured--card {
  background: rgba(14, 30, 64, 0.4);
  border: 1px solid var(--color-border-accent);
  color: var(--color-text);
}
.megamenu__featured:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-glow-sm);
  border-color: var(--color-border-glow);
}
.megamenu__featured-eyebrow {
  font-size: 10px;
  font-weight: var(--weight-bold);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--color-emphasis);
}
.megamenu__featured-title {
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-weight: var(--weight-bold);
  color: var(--color-text-strong);
  line-height: var(--leading-snug);
}
.megamenu__featured-desc {
  font-size: var(--text-sm);
  color: var(--color-text);
  line-height: var(--leading-snug);
}
.megamenu__featured-cta {
  margin-top: var(--space-2);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  color: var(--color-emphasis);
}

/* Item stagger — links cascade in 30ms apart when panel opens. */
@keyframes nav-item-in {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: translateY(0); }
}
.megamenu[data-state="open"] .megamenu__link,
.megamenu[data-state="open"] .megamenu__featured {
  animation: nav-item-in 280ms cubic-bezier(0.4, 0, 0.2, 1) both;
}
.megamenu[data-state="open"] .megamenu__link:nth-child(1) { animation-delay: 30ms; }
.megamenu[data-state="open"] .megamenu__link:nth-child(2) { animation-delay: 60ms; }
.megamenu[data-state="open"] .megamenu__link:nth-child(3) { animation-delay: 90ms; }
.megamenu[data-state="open"] .megamenu__link:nth-child(4) { animation-delay: 120ms; }
.megamenu[data-state="open"] .megamenu__link:nth-child(5) { animation-delay: 150ms; }
.megamenu[data-state="open"] .megamenu__link:nth-child(6) { animation-delay: 180ms; }
.megamenu[data-state="open"] .megamenu__link:nth-child(7) { animation-delay: 210ms; }
.megamenu[data-state="open"] .megamenu__link:nth-child(8) { animation-delay: 240ms; }
.megamenu[data-state="open"] .megamenu__featured { animation-delay: 100ms; }

/* Reduced motion — instant open, no stagger, no clip-path animation. */
@media (prefers-reduced-motion: reduce) {
  .megamenu {
    transition: opacity 0ms;
    clip-path: none;
    transform: none;
  }
  .megamenu[data-state="open"] .megamenu__link,
  .megamenu[data-state="open"] .megamenu__featured {
    animation: none;
  }
  .nav-underline { transition: none; }
  .megamenu__link::before { transition: none; }
}

/* ============================================================
   §5.3 Mobile drawer accordion
   Native <details> sections — free disclosure semantics.
   ============================================================ */
.nav-drawer__inner {
  padding: var(--space-2) var(--space-6) var(--space-4);
}
.nav-drawer__section {
  margin: 0;
  padding: var(--space-3) 0;
  border: 0;
  border-bottom: 1px solid var(--color-border);
  border-radius: 0;
}
.nav-drawer__section[open] { padding-bottom: var(--space-4); }
.nav-drawer__section > summary {
  list-style: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-3) 0;
  font-size: var(--text-base);
  font-weight: var(--weight-semibold);
  color: var(--color-text-strong);
  cursor: pointer;
}
.nav-drawer__section > summary::-webkit-details-marker { display: none; }
.nav-drawer__section > summary::marker { content: ''; }

/* CSS-only +/− toggle (replaces D-047 reactor pip on mobile per D-050).
   Pure pseudo-element. Closed → +, open → −. No JS, no dot. */
.nav-drawer__section > summary::after {
  content: '';
  display: inline-block;
  position: relative;
  width: 14px;
  height: 14px;
  flex-shrink: 0;
  background:
    linear-gradient(var(--color-emphasis), var(--color-emphasis)) center / 14px 2px no-repeat,
    linear-gradient(var(--color-emphasis), var(--color-emphasis)) center / 2px 14px no-repeat;
  transition: transform 240ms cubic-bezier(0.4, 0, 0.2, 1);
}
.nav-drawer__section[open] > summary::after {
  transform: rotate(45deg);
}
.nav-drawer__panel {
  padding: var(--space-2) 0 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}
.nav-drawer__cluster-eyebrow {
  font-size: 11px;
  font-weight: var(--weight-bold);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  margin: 0 0 var(--space-2);
}
.nav-drawer__panel ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}
.nav-drawer__panel ul li { padding: 0; border: 0; }
.nav-drawer__panel ul a {
  display: block;
  padding: var(--space-2) 0;
  color: var(--color-text);
  font-size: var(--text-sm);
}
.nav-drawer__subsection {
  margin-top: var(--space-4);
}
.nav-drawer__subsection:first-child { margin-top: 0; }
.nav-drawer__subsection-eyebrow {
  font-size: 11px;
  font-weight: var(--weight-bold);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  margin: 0 0 var(--space-2);
}
/* D-184: ancestor-prefixed (0,2,0) so it beats the broad '.nav-drawer a' rule
   (0,1,1) that otherwise paints this anchor white. Same root cause as the
   desktop see-all. Do not flatten. */
.nav-drawer .nav-drawer__see-all {
  display: inline-block;
  margin-top: var(--space-2);
  padding: var(--space-2) 0;
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  color: var(--color-emphasis);
}
.nav-drawer__see-all::after {
  content: "→";
  margin-left: 0.4em;
}
.nav-drawer-cta {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}
.nav-drawer__featured {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  margin-top: var(--space-3);
  padding: var(--space-4);
  border-radius: var(--radius-md);
  background: linear-gradient(135deg, rgba(0, 194, 255, 0.14) 0%, rgba(0, 194, 255, 0.08) 100%);
  border: 1px solid var(--color-border-glow);
  text-decoration: none;
}
.nav-drawer__featured-title {
  font-family: var(--font-display);
  font-weight: var(--weight-bold);
  font-size: var(--text-base);
  color: var(--color-text-strong);
}
.nav-drawer__featured-cta {
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  color: var(--color-emphasis);
}
.nav-drawer__flat {
  display: block;
  padding: var(--space-3) 0;
  border-bottom: 1px solid var(--color-border);
  font-size: var(--text-base);
  font-weight: var(--weight-semibold);
  color: var(--color-text-strong);
}

/* ============================================================
   §6.4 Convergence diagram (D-062)
   Six feature cards flanking a central RocketFuel Recharge hub.
   SVG layer absolute-fills the container (aspect-ratio 1400/800
   on desktop). Cards positioned absolutely via percentage to align
   with SVG path endpoints. Mobile/tablet: SVG hidden, cards stack
   in a responsive grid (no diagram below 1024px — too cramped).

   Particles: --color-accent-teal (#00FFD1) for color-pop against cyan rails.
   Animation: rAF + getPointAtLength in convergence-diagram.ts.
   IntersectionObserver pauses work when off-screen.
   ============================================================ */

.converge {
  position: relative;
  max-width: 1400px;
  margin: 0 auto;
}
@media (min-width: 1024px) {
  .converge { aspect-ratio: 1400 / 800; }
}
.converge-svg {
  display: none;
}
@media (min-width: 1024px) {
  .converge-svg {
    display: block;
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
  }
}

.rf-rail {
  fill: none;
  stroke-width: 10;
  stroke-linecap: round;
  stroke-linejoin: round;
  filter: drop-shadow(0 0 8px rgba(186, 230, 253, 0.50));
}
.rf-rail--l { stroke: url(#rfRailGradL); }
.rf-rail--r { stroke: url(#rfRailGradR); }

.rf-hub-glow { opacity: 0.30; }
.rf-hub-glow.rf-pulse-on { animation: rf-hub-pulse 620ms ease-out; }
@keyframes rf-hub-pulse {
  0%   { opacity: 0.30; }
  22%  { opacity: 0.70; }
  100% { opacity: 0.30; }
}

.rf-hub-ring {
  fill: none;
  stroke: rgba(125, 211, 252, 0.45);
  stroke-width: 1.25;
  filter: drop-shadow(0 0 10px rgba(0, 194, 255, 0.20));
}
.rf-hub { /* fill via gradient, no extra props needed */ }

/* Hub logo + per-particle teal glow pop — D-121 (extends D-062). */
.rf-hub-logo {
  filter: drop-shadow(0 0 4px rgba(var(--color-accent-teal-rgb), 0.20));
}
.rf-hub-logo.rf-glow-on {
  animation: rf-logo-glow-pop 850ms ease-out;
}
@keyframes rf-logo-glow-pop {
  0%   { filter: drop-shadow(0 0 4px rgba(var(--color-accent-teal-rgb), 0.20)); }
  18%  { filter: drop-shadow(0 0 22px rgba(var(--color-accent-teal-rgb), 0.95)); }
  100% { filter: drop-shadow(0 0 4px rgba(var(--color-accent-teal-rgb), 0.20)); }
}

/* Comet particles — lead is brightest with full glow; trails fade in
   radius + opacity + glow strength to read as motion blur / gradient. */
.rf-particle {
  fill: var(--color-accent-teal);
  opacity: 0;
}
.rf-particle--lead {
  filter: drop-shadow(0 0 7px rgba(var(--color-accent-teal-rgb), 0.95)) drop-shadow(0 0 14px rgba(var(--color-accent-teal-rgb), 0.50));
}
.rf-particle--t1 {
  filter: drop-shadow(0 0 4px rgba(var(--color-accent-teal-rgb), 0.65));
}
.rf-particle--t2 {
  filter: drop-shadow(0 0 2px rgba(var(--color-accent-teal-rgb), 0.40));
}

/* Convergence cards — cyan-tinted frosted glass (D-064).
   Heavier blur + cyan inner glow + cyan border. Title scales up to
   text-2xl on desktop so the feature name dominates the card. */
.converge-card {
  display: block;
  text-decoration: none;
  color: var(--color-text);
  background-color: rgba(15, 28, 52, 0.32);
  background-image:
    linear-gradient(180deg, rgba(0, 194, 255, 0.10) 0%, rgba(0, 194, 255, 0.03) 60%, rgba(0, 194, 255, 0.07) 100%),
    radial-gradient(ellipse 90% 60% at 50% 0%, rgba(0, 194, 255, 0.14) 0%, transparent 70%);
  border: 1px solid rgba(0, 194, 255, 0.28);
  border-radius: var(--radius-lg);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.12),
    inset 0 0 28px rgba(0, 194, 255, 0.08),
    0 8px 32px rgba(0, 0, 0, 0.32);
  padding: var(--space-5);
  backdrop-filter: blur(30px) saturate(220%);
  -webkit-backdrop-filter: blur(30px) saturate(220%);
  transition: border-color 200ms ease, box-shadow 200ms ease, background-color 200ms ease, transform 200ms ease;
}
.converge-card:hover {
  background-color: rgba(15, 28, 52, 0.44);
  border-color: rgba(0, 194, 255, 0.55);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.16),
    inset 0 0 36px rgba(0, 194, 255, 0.18),
    0 0 28px rgba(0, 194, 255, 0.22),
    0 8px 32px rgba(0, 0, 0, 0.32);
  color: var(--color-text);
}
@supports not (backdrop-filter: blur(1px)) {
  .converge-card { background-color: rgba(20, 35, 65, 0.65); }
}
.converge-card__title {
  display: block;
  font-family: var(--font-display);
  font-weight: var(--weight-bold);
  font-size: var(--text-lg);
  color: var(--color-text-strong);
  margin-bottom: var(--space-2);
  letter-spacing: -0.015em;
  line-height: 1.15;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.45);
}
@media (min-width: 1024px) {
  .converge-card__title {
    font-size: var(--text-xl);
    min-height: 2.3em; /* lock to 2-line height so cards stay equal */
  }
}
.converge-card p {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  margin: 0;
  line-height: 1.45;
}

/* Mobile/tablet: stacked grid, no positioning. */
.converge {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-3);
}
@media (min-width: 640px) and (max-width: 1023px) {
  .converge { grid-template-columns: repeat(2, 1fr); }
}

/* Desktop: cards absolute-positioned around the hub (D-064 sizing) */
@media (min-width: 1024px) {
  .converge { display: block; }
  .converge-card {
    position: absolute;
    width: 19%;
    transform: translateY(-50%);
  }
  .converge-card--l1 { left: 20%;  top: 15%; }
  .converge-card--l2 { left: 10%;  top: 50%; }
  .converge-card--l3 { left: 20%;  top: 85%; }
  .converge-card--r1 { right: 20%; top: 15%; }
  .converge-card--r2 { right: 10%; top: 50%; }
  .converge-card--r3 { right: 20%; top: 85%; }
}

@media (prefers-reduced-motion: reduce) {
  .rf-particle, .rf-particle--lead, .rf-particle--t1, .rf-particle--t2 { opacity: 0 !important; }
  .rf-hub-glow { opacity: 0.30 !important; animation: none !important; }
}

/* ============================================================
   §6.6.5 Solutions Showcase — home §4 (D-075)
   Video + 3 callout cards. Outer glass panel + inner glass cards.
   Mobile: video on top, cards horizontal scroll-snap with dot pagination.
   Desktop: cards left, video right (grid-template-areas swap).
   ============================================================ */
.solutions-showcase {
  position: relative;
  isolation: isolate;
}
/* D-100: grainy pixel substrate, z:-2, edge-to-edge via calc(-50vw + 50%) */
.solutions-showcase::before {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  left: calc(-50vw + 50%);
  right: calc(-50vw + 50%);
  z-index: -2;
  pointer-events: none;
  background-image: url('/assets/r2/backgrounds%2Fpixel-bg.jpg');
  background-size: cover;
  background-position: center center;
  background-repeat: no-repeat;
  opacity: 0.07;
  mask-image: linear-gradient(180deg,
    transparent 0%, rgba(0, 0, 0, 0.6) 6%, #000 18%,
    #000 82%, rgba(0, 0, 0, 0.6) 94%, transparent 100%);
  -webkit-mask-image: linear-gradient(180deg,
    transparent 0%, rgba(0, 0, 0, 0.6) 6%, #000 18%,
    #000 82%, rgba(0, 0, 0, 0.6) 94%, transparent 100%);
}
/* Green ambient: vertical fade (in from top, out to bottom) layered with
   horizontal side-emphasis. Sits OUTSIDE the bubble's opacity multiplier
   so the green wash is independent. Brighter at sides (12%) to read as
   a rest-stop, dimmer in the middle (5%) so it doesn't fight the panel. */
.solutions-showcase__green-ambient {
  position: absolute;
  top: 0;
  bottom: 0;
  left: calc(-50vw + 50%);
  right: calc(-50vw + 50%);
  z-index: -1;
  pointer-events: none;
  background-image:
    radial-gradient(ellipse 40% 80% at 0% 50%, rgba(var(--color-accent-teal-rgb), 0.12) 0%, transparent 65%),
    radial-gradient(ellipse 40% 80% at 100% 50%, rgba(var(--color-accent-teal-rgb), 0.12) 0%, transparent 65%),
    linear-gradient(180deg,
      transparent 0%,
      rgba(var(--color-accent-teal-rgb), 0.05) 25%,
      rgba(var(--color-accent-teal-rgb), 0.05) 75%,
      transparent 100%);
  mask-image: linear-gradient(180deg,
    transparent 0%, rgba(0, 0, 0, 0.6) 6%, #000 18%,
    #000 82%, rgba(0, 0, 0, 0.6) 94%, transparent 100%);
  -webkit-mask-image: linear-gradient(180deg,
    transparent 0%, rgba(0, 0, 0, 0.6) 6%, #000 18%,
    #000 82%, rgba(0, 0, 0, 0.6) 94%, transparent 100%);
}
/* Outer panel — frosted glass matching megamenu/convergence recipe */
.solutions-showcase__panel {
  background-color: rgba(10, 20, 38, 0.42);
  background-image:
    linear-gradient(180deg, rgba(0, 194, 255, 0.06) 0%, rgba(0, 194, 255, 0.02) 60%, rgba(0, 194, 255, 0.05) 100%),
    radial-gradient(ellipse 80% 50% at 50% 0%, rgba(0, 194, 255, 0.10) 0%, transparent 70%);
  border: 1px solid rgba(0, 194, 255, 0.20);
  border-radius: var(--radius-xl);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.10),
    inset 0 0 40px rgba(0, 194, 255, 0.06),
    0 12px 48px rgba(0, 0, 0, 0.40);
  backdrop-filter: blur(30px) saturate(200%);
  -webkit-backdrop-filter: blur(30px) saturate(200%);
  padding: var(--space-6);
}
@media (min-width: 1024px) {
  .solutions-showcase__panel { padding: var(--space-8); }
}

.solutions-showcase__layout {
  display: grid;
  grid-template-columns: 1fr;
  grid-template-areas: "video" "cards";
  gap: var(--space-6);
  align-items: stretch;
}
@media (min-width: 1024px) {
  .solutions-showcase__layout {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr);
    grid-template-areas: "cards video";
    gap: var(--space-6);
  }
}
.solutions-showcase__cards-col { grid-area: cards; min-width: 0; }
.solutions-showcase__video-col { grid-area: video; min-width: 0; }

/* Cards track — horizontal carousel on mobile (one card at a time, full-
   width, swipeable), vertical stack on desktop. Mobile gets zero horizontal
   padding so cards align flush with the panel edges; gap between cards
   creates clean snap stops. */
.solutions-showcase__cards-track {
  list-style: none;
  margin: 0;
  padding: 0 0 var(--space-2);
  display: flex;
  flex-direction: row;
  gap: var(--space-4);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.solutions-showcase__cards-track::-webkit-scrollbar { display: none; }
@media (prefers-reduced-motion: reduce) {
  .solutions-showcase__cards-track { scroll-behavior: auto; scroll-snap-type: none; }
}
@media (min-width: 1024px) {
  .solutions-showcase__cards-track {
    flex-direction: column;
    overflow: visible;
    padding: 0;
    gap: var(--space-4);
  }
}

/* Individual card — glass + hover bloom matching megamenu link recipe.
   Mobile: full-width swipeable (no peek of next card per Iris feedback).
   Desktop: vertical stack via flex: 1 1 auto.
   D-085: inner-glow alphas dropped ~30% so these read as quieter inner
   cards next to the convergence reference, not a third copy of the same
   recipe. Hover state still pops cyan. */
.solutions-card {
  position: relative;
  flex: 0 0 100%;
  scroll-snap-align: center;
  background-color: rgba(15, 28, 52, 0.32);
  background-image:
    linear-gradient(180deg, rgba(0, 194, 255, 0.07) 0%, rgba(0, 194, 255, 0.02) 60%, rgba(0, 194, 255, 0.05) 100%),
    radial-gradient(ellipse 90% 60% at 50% 0%, rgba(0, 194, 255, 0.10) 0%, transparent 70%);
  border: 1px solid rgba(0, 194, 255, 0.20);
  border-radius: var(--radius-lg);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.10),
    inset 0 0 28px rgba(0, 194, 255, 0.05),
    0 8px 32px rgba(0, 0, 0, 0.32);
  padding: var(--space-5);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  transition: border-color 220ms ease, transform 220ms ease, box-shadow 220ms ease;
  overflow: hidden;
  isolation: isolate;
}
@media (min-width: 1024px) {
  .solutions-card {
    flex: 1 1 auto;
    scroll-snap-align: none;
  }
}
/* Hover bloom — radial spotlight from top-center, mirrors .megamenu__link::before */
.solutions-card::before {
  content: '';
  position: absolute;
  top: 0;
  left: 50%;
  width: 80%;
  height: 90%;
  transform: translateX(-50%);
  background: radial-gradient(ellipse at center top, rgba(0, 194, 255, 0.16) 0%, transparent 65%); /* D-116b: 0.22 → 0.16 */
  opacity: 0;
  transition: opacity 220ms ease;
  pointer-events: none;
  z-index: 0;
}
.solutions-card:hover::before,
.solutions-card:focus-within::before { opacity: 1; }
.solutions-card > * { position: relative; z-index: 1; }
.solutions-card:hover {
  border-color: var(--color-border-glow);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.16),
    inset 0 0 32px rgba(0, 194, 255, 0.14),
    0 12px 40px rgba(0, 0, 0, 0.40);
  transform: translateY(-2px);
}
.solutions-card__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: var(--radius-md);
  background: rgba(0, 194, 255, 0.10);
  border: 1px solid rgba(0, 194, 255, 0.22);
  color: var(--color-emphasis);
  margin-bottom: var(--space-3);
}
.solutions-card__title {
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-weight: var(--weight-bold);
  color: var(--color-text-strong);
  margin: 0 0 var(--space-2);
  letter-spacing: -0.005em;
}
.solutions-card__desc {
  color: var(--color-text-muted);
  font-size: var(--text-sm);
  line-height: var(--leading-normal);
  margin: 0;
}

/* Dot pagination — mobile only, hidden on desktop */
.solutions-showcase__dots {
  display: flex;
  justify-content: center;
  gap: var(--space-2);
  margin-top: var(--space-4);
  padding: var(--space-1) 0;
}
.solutions-showcase__dots button {
  /* D-093: 24px hit target satisfies WCAG 2.5.8 Target Size (Minimum).
     Visible dot is the inner ::before pseudo-element so the green active-state
     indicator is not a button-fill (D-074: green allowed for active-state
     indicators, not button fills). */
  appearance: none;
  border: 0;
  background: transparent;
  padding: 0;
  width: 24px;
  height: 24px;
  border-radius: 4px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: width 220ms ease;
}
.solutions-showcase__dots button[aria-pressed="true"] { width: 36px; }
.solutions-showcase__dots button::before {
  content: '';
  display: block;
  width: 16px;
  height: 4px;
  border-radius: 2px;
  background: rgba(255, 255, 255, 0.22);
  transition: background 220ms ease, width 220ms ease;
}
.solutions-showcase__dots button:hover::before { background: rgba(0, 194, 255, 0.55); }
.solutions-showcase__dots button[aria-pressed="true"]::before {
  background: var(--color-accent-teal);
  width: 28px;
}
.solutions-showcase__dots button[aria-pressed="true"]:hover::before { background: var(--color-accent-teal); }
.solutions-showcase__dots button:focus-visible {
  outline: 2px solid var(--color-emphasis);
  outline-offset: 2px;
}
@media (min-width: 1024px) {
  .solutions-showcase__dots { display: none; }
}

/* Video frame — glass-bordered, custom play overlay.
   Mobile: aspect-ratio drives natural 16:9 sizing (no height constraint).
   Desktop: frame fills the grid cell height (matches cards-col); inner
   video uses object-fit: contain so it letterboxes inside the cyan glass
   frame — letterbox area shows through to the frame's bg gradient,
   creating a "viewport" feel rather than ugly black bars. */
.solutions-showcase__video {
  position: relative;
  aspect-ratio: 16 / 9;
  width: 100%;
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: linear-gradient(135deg, rgba(0, 30, 60, 0.80) 0%, rgba(0, 15, 35, 0.95) 100%);
  border: 1px solid rgba(0, 194, 255, 0.24);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.10),
    0 12px 40px rgba(0, 0, 0, 0.50);
  display: block;
}
@media (min-width: 1024px) {
  .solutions-showcase__video {
    aspect-ratio: auto;
    height: 100%;
    min-height: 320px;
  }
}
.solutions-showcase__video-el {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  background: transparent;
  object-fit: contain;
}
.solutions-showcase__play-btn {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 72px;
  height: 72px;
  border-radius: 50%;
  border: 1px solid rgba(0, 194, 255, 0.40);
  background: rgba(0, 30, 60, 0.65);
  color: var(--color-emphasis);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding-left: 4px;
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.16),
    0 8px 24px rgba(0, 0, 0, 0.50),
    0 0 32px rgba(0, 194, 255, 0.30);
  transition: transform 220ms ease, border-color 220ms ease, box-shadow 220ms ease, opacity 220ms ease;
  z-index: 2;
}
.solutions-showcase__play-btn:hover {
  transform: translate(-50%, -50%) scale(1.06);
  border-color: var(--color-emphasis);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.20),
    0 8px 24px rgba(0, 0, 0, 0.50),
    0 0 48px rgba(0, 194, 255, 0.50);
}
.solutions-showcase__play-btn:focus-visible {
  outline: 2px solid var(--color-emphasis);
  outline-offset: 4px;
}

/* CTA row below the panel */
.solutions-showcase__cta {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
  margin-top: var(--space-8);
}

/* ============================================================
   §6.6.6 Integrations orbit — home §5 (D-080)
   8 integration logos in glassmorphic circular badges arranged on a
   circle around a central RocketFuel gradient sphere with cyan glow
   + grain "parting" texture. Mobile (<1024px): orbit collapses to a
   4×2 grid; sphere stacks on top.
   ============================================================ */
.integrations {
  position: relative;
  isolation: isolate;
}
.integrations__bg {
  /* Soft cyan ambient wash behind the section, no texture (the orbit is
     the visual centerpiece — bg should not compete). */
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-image:
    radial-gradient(ellipse 60% 60% at 50% 50%, rgba(0, 194, 255, 0.06) 0%, transparent 70%);
}
.integrations__intro {
  text-align: center;
  max-width: 36rem;
  margin: 0 auto var(--space-12);
}
.integrations__intro h2 { margin: var(--space-2) 0 var(--space-3); }
.integrations__intro .lead { margin: 0; }

/* Stage: square aspect-ratio container that hosts the orbit on desktop.
   Mobile: aspect-ratio dropped, orbit reflows. */
.integrations__stage {
  position: relative;
  margin: 0 auto;
  max-width: 720px;
}

/* Orbit container — desktop. Square so badges sit on a circle.
   --r drives the orbit radius. --orbit-angle is animated by the
   @keyframes below; each badge reads it via inherits to compute its
   live position. Pure CSS, ~12 lines, GPU-compositor only. */
@property --orbit-angle {
  syntax: '<angle>';
  initial-value: 0deg;
  inherits: true;
}
.orbit {
  position: relative;
  aspect-ratio: 1 / 1;
  --r: 280px;
  --orbit-angle: 0deg;
  animation: orbit-revolve 90s linear infinite;
}
@keyframes orbit-revolve {
  to { --orbit-angle: 360deg; }
}
@media (max-width: 1199px) {
  .orbit { --r: 230px; }
}
@media (max-width: 1023px) {
  /* Mobile: ditch the orbital geometry, fall to a centered grid.
     Animation killed since the badges have no circle to follow. */
  .orbit {
    aspect-ratio: auto;
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: var(--space-3);
    padding-top: var(--space-12);
    --r: 0px;
    animation: none;
  }
}
@media (prefers-reduced-motion: reduce) {
  /* Vestibular-safe: hold initial positions, no rotation. Per
     web-motion-protocol gate #1 — meaningful fallback, not broken. */
  .orbit { animation: none; }
}

/* ---- Central sphere ---- */
.orbit-core {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 168px;
  height: 168px;
  z-index: 2;
  pointer-events: none;
}
@media (max-width: 1023px) {
  /* D-190: drop the central badge + glow entirely on mobile/tablet — the bare
     logo grid reads cleaner than the sphere + halos overlapping the badges. */
  .orbit-core { display: none; }
}

/* Layered halos — three concentric radial fades that create the "parting
   gradient" — outermost is largest + dimmest, innermost is tightest +
   most intense. Together they push outward from the sphere, dimming the
   surrounding orbit area like an aurora pushing through fog. */
.orbit-core__halo {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  pointer-events: none;
}
.orbit-core__halo--outer {
  width: 520px;
  height: 520px;
  background: radial-gradient(circle, rgba(0, 194, 255, 0.18) 0%, rgba(0, 194, 255, 0.06) 30%, transparent 65%);
}
.orbit-core__halo--mid {
  width: 320px;
  height: 320px;
  background: radial-gradient(circle, rgba(0, 194, 255, 0.30) 0%, rgba(0, 194, 255, 0.10) 40%, transparent 75%);
}
.orbit-core__halo--inner {
  width: 200px;
  height: 200px;
  background: radial-gradient(circle, rgba(186, 230, 253, 0.45) 0%, rgba(0, 194, 255, 0.22) 35%, transparent 75%);
}
/* D-190: mobile halo-resize removed — .orbit-core is display:none below 1024px. */

/* Grain texture — inline noise SVG via data-URL. Lives over the halos so
   the gradient feels textured/atmospheric rather than flat. mix-blend
   makes the grain modulate the halo light without darkening the sphere. */
.orbit-core__grain {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 480px;
  height: 480px;
  border-radius: 50%;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='220' height='220'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 1   0 0 0 0 1   0 0 0 0 1   0 0 0 0.22 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
  background-size: 220px 220px;
  mix-blend-mode: overlay;
  opacity: 0.65;
  mask-image: radial-gradient(circle, transparent 0%, transparent 18%, #000 35%, #000 65%, transparent 90%);
  -webkit-mask-image: radial-gradient(circle, transparent 0%, transparent 18%, #000 35%, #000 65%, transparent 90%);
  pointer-events: none;
}
@media (max-width: 1023px) {
  .orbit-core__grain { width: 320px; height: 320px; }
}

/* Sphere — circular glass disc holding the brand icon. The disc itself
   has a glass-bevel inner highlight + cyan rim border. */
.orbit-core__sphere {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background:
    radial-gradient(circle at 35% 30%, rgba(255, 255, 255, 0.16) 0%, transparent 50%),
    radial-gradient(circle at 50% 50%, rgba(0, 80, 130, 0.55) 0%, rgba(0, 30, 60, 0.95) 100%);
  border: 1px solid rgba(0, 194, 255, 0.50);
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, 0.20),
    inset 0 -8px 24px rgba(0, 60, 120, 0.40),
    0 12px 40px rgba(0, 0, 0, 0.50),
    0 0 60px rgba(0, 194, 255, 0.30);
  display: flex;
  align-items: center;
  justify-content: center;
  backdrop-filter: blur(8px) saturate(180%);
  -webkit-backdrop-filter: blur(8px) saturate(180%);
}
.orbit-core__icon {
  width: 60%;
  height: 60%;
  object-fit: contain;
  filter: drop-shadow(0 4px 12px rgba(0, 0, 0, 0.40));
}

/* ---- Orbital badges ---- */
/* Position formula: rotate to angle (60° × i, 6 badges), translate outward by
   radius, counter-rotate to keep upright. Container revolves via --orbit-angle. */
.orbit-badge {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 96px;
  height: 96px;
  margin: -48px;
  /* Spoke angle = static position (60deg × i, 6 badges) + animated revolve angle.
     Counter-rotation cancels both, keeping wordmarks upright at all times. */
  transform:
    rotate(calc(60deg * var(--i) + var(--orbit-angle)))
    translateY(calc(-1 * var(--r)))
    rotate(calc(-60deg * var(--i) - var(--orbit-angle)));
  z-index: 1;
}
@media (max-width: 1023px) {
  .orbit-badge {
    position: static;
    margin: 0;
    transform: none;
    width: auto;
    height: auto;
    aspect-ratio: 1 / 1;
  }
}
/* D-085: orbit badges drop the cyan inner-glow for a near-white "moonlit
   chrome" look. The central sphere becomes the only cyan source in the
   orbit, so the badges read as cooler/neutral satellites around it. */
.orbit-badge__inner {
  position: relative;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  background-color: rgba(15, 28, 52, 0.42);
  background-image:
    linear-gradient(180deg, rgba(220, 240, 255, 0.06) 0%, rgba(220, 240, 255, 0.02) 60%, rgba(220, 240, 255, 0.04) 100%),
    radial-gradient(ellipse 90% 60% at 50% 0%, rgba(220, 240, 255, 0.10) 0%, transparent 70%);
  border: 1px solid rgba(220, 240, 255, 0.22);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.14),
    inset 0 0 24px rgba(220, 240, 255, 0.05),
    0 8px 24px rgba(0, 0, 0, 0.40);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  transition: border-color 220ms ease, transform 220ms ease, box-shadow 220ms ease;
}
.orbit-badge__inner img {
  max-width: 78%;
  max-height: 56%;
  object-fit: contain;
  /* Most integration logos are dark-on-white wordmarks. Filter brings
     them to white-on-glass for legibility on the dark backdrop. */
  filter: brightness(0) invert(1) opacity(0.86);
  transition: filter 220ms ease, transform 220ms ease;
}
.orbit-badge:hover .orbit-badge__inner {
  border-color: var(--color-border-glow);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.18),
    inset 0 0 32px rgba(0, 194, 255, 0.18),
    0 12px 32px rgba(0, 0, 0, 0.44),
    0 0 24px rgba(0, 194, 255, 0.30);
  transform: scale(1.04);
}
.orbit-badge:hover .orbit-badge__inner img {
  filter: brightness(0) invert(1) opacity(1);
}

.integrations__cta {
  display: flex;
  justify-content: center;
  margin-top: var(--space-12);
}

/* ============================================================
   §6.6.7 Customer Voices — home §6 (D-083, D-088)
   Testimonial card section. Frosted glass card with photo left,
   quote + attribution right. Mobile: photo stacks on top.
   D-088: visible intro stripped — testimonial card IS the section
   header (audit Rec D). H2 retained as sr-only for SEO/a11y.
   Horizontal bubble bg added behind the section, full-viewport
   width, mask fades on all 4 sides so it dissolves at edges.
   ============================================================ */
/* §6 has no bg layer — testimonial card is the visual centerpiece against
   the sitewide ambient (D-039 body::before/::after). */

/* Warm palette per D-085 — testimonial is the page's humanity moment.
   Cyan glass recipe stripped, replaced with deep navy + warm amber rim
   to differentiate from the four cyan-glass sections preceding it. */
.testimonial-card {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0;
  background-color: rgba(20, 18, 30, 0.58);
  background-image:
    linear-gradient(180deg, rgba(var(--color-accent-warm-rgb), 0.06) 0%, rgba(var(--color-accent-warm-rgb), 0.02) 60%, rgba(var(--color-accent-warm-rgb), 0.05) 100%),
    radial-gradient(ellipse 80% 50% at 50% 0%, rgba(var(--color-accent-warm-rgb), 0.08) 0%, transparent 70%);
  border: 1px solid rgba(var(--color-accent-warm-rgb), 0.22);
  border-radius: var(--radius-xl);
  box-shadow:
    inset 0 1px 0 rgba(255, 235, 210, 0.08),
    inset 0 0 40px rgba(var(--color-accent-warm-rgb), 0.05),
    0 12px 48px rgba(0, 0, 0, 0.40);
  backdrop-filter: blur(28px) saturate(160%);
  -webkit-backdrop-filter: blur(28px) saturate(160%);
  overflow: hidden;
  max-width: 1100px;
  margin: 0 auto;
}
@media (min-width: 1024px) {
  .testimonial-card {
    grid-template-columns: minmax(0, 0.55fr) minmax(0, 1fr);
  }
}
.testimonial-card + .testimonial-card { margin-top: var(--space-6); }

.testimonial-card__media {
  position: relative;
  align-self: stretch;    /* D-205: photo fills the card column flush. D-204's centered */
  min-height: 280px;      /* 400² square left padding/margins around long-quote cards (Bill). */
}
@media (min-width: 1024px) {
  .testimonial-card__media { min-height: auto; }
}
.testimonial-card__photo {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  min-height: 280px;
}
/* D-189: review photos get a soft "greyed overlay" so the headshot sits
   cohesively in the dark card (revisits D-085, which had stripped grayscale —
   user wants it muted again, but softer than full B&W). Partial desaturate on
   the image + a navy wash via ::after, scoped to photo cards (not monograms). */
.testimonial-card__media--photo img.testimonial-card__photo {
  filter: grayscale(55%) brightness(1.02);
}
.testimonial-card__media--photo::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(160deg, rgba(8, 17, 31, 0.16) 0%, rgba(5, 12, 26, 0.36) 100%);
  pointer-events: none;
}
.testimonial-card__photo--placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 280px;
  background:
    radial-gradient(ellipse 70% 70% at 30% 20%, rgba(var(--color-accent-warm-rgb), 0.18) 0%, transparent 70%),
    linear-gradient(135deg, rgba(26, 26, 32, 0.92) 0%, rgba(14, 14, 18, 0.96) 100%);
  border-right: 1px solid rgba(var(--color-accent-warm-rgb), 0.16);
}
@media (max-width: 1023px) {
  .testimonial-card__photo--placeholder {
    border-right: none;
    border-bottom: 1px solid rgba(var(--color-accent-warm-rgb), 0.16);
  }
}
.testimonial-card__monogram {
  font-family: var(--font-display);
  font-size: 4rem;
  font-weight: var(--weight-bold);
  letter-spacing: -0.02em;
  background: linear-gradient(135deg, #EDEDE2 0%, var(--color-accent-warm) 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  text-shadow: 0 0 40px rgba(var(--color-accent-warm-rgb), 0.22);
}

.testimonial-card__body {
  padding: var(--space-8) var(--space-6);
  display: flex;
  flex-direction: column;
  justify-content: center;
}
@media (min-width: 1024px) {
  .testimonial-card__body { padding: var(--space-10) var(--space-10); }
}
.testimonial-card__quote {
  margin: 0;
  padding: 0;
  border: 0;
  font-size: var(--text-lg);
  line-height: 1.55;
  color: var(--color-text);
  font-weight: var(--weight-regular);
  letter-spacing: 0.005em;
}
.testimonial-card__quote p { margin: 0 0 var(--space-4); }
.testimonial-card__quote p:last-child { margin-bottom: 0; }

.testimonial-card__attribution {
  margin-top: var(--space-6);
  padding-top: var(--space-5);
  border-top: 1px solid rgba(var(--color-accent-warm-rgb), 0.18);
}
.testimonial-card__name {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--text-base);
  font-weight: var(--weight-semibold);
  color: var(--color-text-strong);
  letter-spacing: -0.005em;
}
.testimonial-card__role {
  margin: var(--space-1) 0 0;
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}

/* D-088: read-more toggle. Subtle glass-style button beneath the quote. */
.testimonial-card__toggle {
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-4);
  padding: var(--space-2) var(--space-4);
  background: rgba(var(--color-accent-warm-rgb), 0.06);
  border: 1px solid rgba(var(--color-accent-warm-rgb), 0.22);
  border-radius: var(--radius-pill);
  color: var(--color-accent-warm);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  letter-spacing: 0.01em;
  cursor: pointer;
  transition: background 200ms ease, border-color 200ms ease, color 200ms ease;
}
.testimonial-card__toggle:hover,
.testimonial-card__toggle:focus-visible {
  background: rgba(var(--color-accent-warm-rgb), 0.12);
  border-color: rgba(var(--color-accent-warm-rgb), 0.40);
  color: #FFFFFF;
  outline: none;
}
.testimonial-card__toggle:focus-visible {
  outline: 2px solid rgba(var(--color-accent-warm-rgb), 0.60);
  outline-offset: 3px;
}
.testimonial-card__toggle-icon {
  transition: transform 240ms ease;
}
.testimonial-card__toggle[aria-expanded="true"] .testimonial-card__toggle-icon {
  transform: rotate(180deg);
}
@media (prefers-reduced-motion: reduce) {
  .testimonial-card__toggle-icon { transition: none; }
}

/* D-202: rotating customer-voices carousel. One slide visible at a time; the
   rest carry [hidden]. Auto-advance is JS-driven and gated (reduced-motion,
   global pause toggle, hover/focus, open read-more) — see CUSTOMER_VOICES_JS. */
.customer-voices__slide[hidden] { display: none; }
@media (prefers-reduced-motion: no-preference) {
  .customer-voices__slide:not([hidden]) { animation: cv-fade 420ms ease both; }
}
@keyframes cv-fade { from { opacity: 0; } to { opacity: 1; } }
.customer-voices__controls {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-5);
  margin-top: var(--space-6);
}
.customer-voices__dots { display: flex; align-items: center; gap: var(--space-3); }
/* D-204: controls match the sitewide cyan/teal accents (NOT the amber testimonial
   card — the card is a standalone rest-stop). Dots = glassmorphic bubbles;
   arrows = subtle glowing cyan->teal chevron lines, no circles. */
.customer-voices__dot {
  width: 12px;
  height: 12px;
  padding: 0;
  border-radius: 50%;
  cursor: pointer;
  background: rgba(255, 255, 255, 0.07);
  border: 1px solid rgba(255, 255, 255, 0.22);
  box-shadow: inset 0 1px 1.5px rgba(255, 255, 255, 0.35), inset 0 -1px 2px rgba(0, 0, 0, 0.18);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  transition: background 220ms ease, border-color 220ms ease, box-shadow 220ms ease, transform 180ms ease;
}
.customer-voices__dot:hover {
  background: rgba(0, 194, 255, 0.16);
  border-color: rgba(0, 194, 255, 0.45);
}
.customer-voices__dot[aria-current="true"] {
  background: rgba(0, 194, 255, 0.28);
  border-color: rgba(0, 194, 255, 0.65);
  box-shadow: inset 0 1px 1.5px rgba(255, 255, 255, 0.45), 0 0 9px rgba(0, 194, 255, 0.55);
  transform: scale(1.18);
}
.customer-voices__dot:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 3px;
}
.customer-voices__arrow {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: auto;
  height: auto;
  flex: 0 0 auto;
  padding: var(--space-1);
  cursor: pointer;
  background: none;
  border: 0;
  border-radius: 6px;
  color: var(--color-primary);
  filter: drop-shadow(0 0 4px rgba(0, 194, 255, 0.45));
  transition: color 200ms ease, filter 200ms ease, transform 150ms ease;
}
.customer-voices__arrow svg { width: 24px; height: 24px; }
.customer-voices__arrow:hover {
  color: var(--color-accent-teal);
  filter: drop-shadow(0 0 9px rgba(var(--color-accent-teal-rgb), 0.7));
}
.customer-voices__arrow:active { transform: scale(0.88); }
.customer-voices__arrow:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 4px;
}
@media (prefers-reduced-motion: reduce) { .customer-voices__arrow { transition: none; } }

/* ============================================================
   §6.6.8 Final CTA — home §7 (D-085)
   Closing demo CTA. Green ambient layer reuses the §4 rest-stop
   pattern as a bookend (per D-074 budget — single per-section
   accent moment). Live-dot inside the button is the second green
   instance, kept restrained.
   ============================================================ */
.final-cta {
  position: relative;
  isolation: isolate;
}
.final-cta__bg {
  position: absolute;
  top: 0;
  bottom: 0;
  left: calc(-50vw + 50%);
  right: calc(-50vw + 50%);
  z-index: -1;
  pointer-events: none;
  background-image:
    radial-gradient(ellipse 38% 75% at 0% 50%, rgba(var(--color-accent-teal-rgb), 0.10) 0%, transparent 65%),
    radial-gradient(ellipse 38% 75% at 100% 50%, rgba(var(--color-accent-teal-rgb), 0.10) 0%, transparent 65%),
    linear-gradient(180deg,
      transparent 0%,
      rgba(var(--color-accent-teal-rgb), 0.04) 30%,
      rgba(var(--color-accent-teal-rgb), 0.04) 70%,
      transparent 100%);
  mask-image: linear-gradient(180deg,
    transparent 0%, rgba(0, 0, 0, 0.6) 6%, #000 18%,
    #000 82%, rgba(0, 0, 0, 0.6) 94%, transparent 100%);
  -webkit-mask-image: linear-gradient(180deg,
    transparent 0%, rgba(0, 0, 0, 0.6) 6%, #000 18%,
    #000 82%, rgba(0, 0, 0, 0.6) 94%, transparent 100%);
}
.final-cta__btn-row {
  margin-top: var(--space-6);
}

/* =============================================================================
   D-108 [STRUCTURAL]: Flagship-hero glass — shared frame for 6 bespoke heroes.
   Iris's D-085 4-recipe cap is superseded by this 5th "flagship-hero glass"
   recipe — explicitly named, justified, and DRY-extracted via the grouped
   selector below. Bespoke heroes need a deeper shadow + larger ambient halo
   than the 4 D-085 card recipes (primary/secondary/satellite/warm) because
   they live in 497x497 frames with rich animations inside.
   Per-hero selectors below add only the layout divergence (max-width,
   min-height, flex direction). All other shared declarations live here.
   SPLIT-CANDIDATE: when styles.ts splits, the 6 .{name}-hero rules belong
   together in the bespoke-hero file (~870 LOC across this section).
   ============================================================================= */

/* SPLIT-CANDIDATE: bespoke flagship-hero family begins */
.orbit-hero,
.meter-hero,
.markup-hero,
.reconcile-hero,
.claims-hero,
.comp-billing-hero {
  position: relative;
  aspect-ratio: 1 / 1;
  width: 100%;
  margin-inline: auto;
  border-radius: var(--radius-lg);
  overflow: hidden;
  isolation: isolate;
  background-color: rgba(15, 28, 52, 0.32);
  background-image:
    radial-gradient(ellipse 70% 60% at 50% 50%,
      rgba(0, 194, 255, 0.06) 0%,
      rgba(0, 194, 255, 0.025) 45%,
      transparent 80%),
    linear-gradient(180deg, rgba(0, 194, 255, 0.06) 0%, rgba(0, 194, 255, 0.015) 60%, rgba(0, 194, 255, 0.04) 100%);
  border: 1px solid rgba(0, 194, 255, 0.22);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.10),
    inset 0 0 32px rgba(0, 194, 255, 0.06),
    0 8px 32px rgba(0, 0, 0, 0.32);
  backdrop-filter: blur(30px) saturate(220%);
  -webkit-backdrop-filter: blur(30px) saturate(220%);
}
@supports not (backdrop-filter: blur(1px)) {
  .orbit-hero,
  .meter-hero,
  .markup-hero,
  .reconcile-hero,
  .claims-hero,
  .comp-billing-hero { background-color: rgba(20, 35, 65, 0.65); }
}

/* Per-hero layout overrides (the only divergence between the six). */
.orbit-hero { max-width: 480px; }
.meter-hero,
.markup-hero,
.reconcile-hero,
.claims-hero,
.comp-billing-hero {
  min-height: 420px;
  max-width: 540px;
}
.reconcile-hero,
.claims-hero,
.comp-billing-hero {
  display: flex;
  flex-direction: column;
}

/* Static radial halo behind the icon. Lowered intensity (D-108 follow-up).
   Stays perfectly centered — does not track cursor. */
.orbit-hero__core-glow {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 60%;
  height: 60%;
  transform: translate(-50%, -50%);
  background: radial-gradient(circle,
    rgba(0, 194, 255, 0.16) 0%,
    rgba(0, 194, 255, 0.05) 35%,
    transparent 70%);
  pointer-events: none;
  z-index: 0;
}

.orbit-hero__field {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 1;
}

/* Each <g> layer rotates around the SVG's user-space center (200,200 in a
   400×400 viewBox). transform-origin in pixel units on SVG elements maps
   to user-space coords in modern browsers. */
.orbit-hero__layer,
.orbit-hero__glint-orbit {
  transform-origin: 200px 200px;
  will-change: transform;
}

.orbit-hero__icon {
  position: absolute;
  top: 50%;
  left: 50%;
  width: clamp(56px, 14%, 96px);
  height: auto;
  transform: translate(-50%, -50%);
  filter: drop-shadow(0 0 14px rgba(0, 194, 255, 0.32)); /* D-116b: 0.45 → 0.32 */
  z-index: 2;
  pointer-events: none;
}

/* Glint — bright dot tracing the outer orbit. drop-shadow gives it a
   comet glow without a separate trail element. opacity fade makes it
   appear/disappear once per cycle so it reads as a sweeping pulse, not
   a constant marker. */
.orbit-hero__glint {
  filter:
    drop-shadow(0 0 6px rgba(125, 211, 252, 0.95))
    drop-shadow(0 0 14px rgba(0, 194, 255, 0.40)); /* D-116b: 0.55 → 0.40 */
  opacity: 0;
}

@media (prefers-reduced-motion: no-preference) {
  .orbit-hero__layer--inner { animation: orbit-rotate 64s linear infinite; }
  .orbit-hero__layer--mid   { animation: orbit-rotate 48s linear infinite reverse; }
  .orbit-hero__layer--outer { animation: orbit-rotate 96s linear infinite; }
  .orbit-hero__glint-orbit  { animation: orbit-rotate 12s linear infinite; }
  .orbit-hero__glint        { animation: orbit-glint-fade 12s ease-in-out infinite; }
}
@keyframes orbit-rotate {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}
@keyframes orbit-glint-fade {
  0%, 4%   { opacity: 0; }
  10%, 22% { opacity: 1; }
  30%      { opacity: 0; }
  100%     { opacity: 0; }
}

/* =============================================================================
   D-108b: Recharge Meter hero — vertical battery + 2 orbital rings + glint.
   Resolves D-107 Gate 1 (flagship hierarchy): 1.5x card size + unique shape
   no other pillar uses. Visual rhyme with /product hub orbit-hero (same
   particle-field language, different center). Cyan-only per D-074.
   ============================================================================= */
/* .meter-hero glass frame extracted to shared selector at line ~4076 (D-108).
   Min-height + max-width retained via per-hero override above. 1.5x cv-card
   target: cv-card min-height 280 -> meter-hero 420. */

.meter-hero__svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

/* Particle layers + glint orbit rotate around SVG user-space center (200,200
   in 400×400 viewBox). Slower than /product hub since the battery is the
   focal point here, not the orbit. */
.meter-hero__layer,
.meter-hero__glint-orbit {
  transform-origin: 200px 200px;
  will-change: transform;
}

/* Battery fill — clip-path drives drain (top-down) and recharge (bottom-up).
   inset(top% 0 0 0): top=100% = empty, top=0% = full. New 18s cycle
   replaces the prior 6.5s simple fill loop (D-108d). */
.meter-hero__fill {
  /* Static state = full, in case animation hasn't initialized yet */
  clip-path: inset(0% 0 0 0);
}

.meter-hero__cap-glow {
  opacity: 0;
  transform-origin: 200px 84px;
}

.meter-hero__glint {
  filter:
    drop-shadow(0 0 6px rgba(125, 211, 252, 0.95))
    drop-shadow(0 0 14px rgba(0, 194, 255, 0.40)); /* D-116b: 0.55 → 0.40 */
  opacity: 0;
}

/* Package + money glyphs — start invisible at their respective entry points
   so they don't render until their animation-delay elapses. */
.meter-hero__pkg {
  transform: translate(-30px, 275px);
  opacity: 0;
  will-change: transform, opacity;
}
.meter-hero__money {
  transform: translate(265px, 275px);
  opacity: 0;
  will-change: transform, opacity;
}

@media (prefers-reduced-motion: no-preference) {
  .meter-hero__layer--outer   { animation: orbit-rotate 130s linear infinite; }
  .meter-hero__glint-orbit    { animation: orbit-rotate 12s linear infinite; }
  .meter-hero__glint          { animation: orbit-glint-fade 12s ease-in-out infinite; }
  /* New 18s narrative cycle: drain (0-12s) -> pause (12-13s) ->
     recharge (13-16s) -> hold (16-18s) -> loop. */
  .meter-hero__fill           { animation: meter-cycle 18s linear infinite; }
  .meter-hero__cap-glow       { animation: meter-cap-recharge 18s linear infinite; }

  /* Package flow — 5 staggered packages over the 12s active phase.
     animation-delay shifts each package's appearance window inside the
     shared 18s cycle. After the master loop restarts every 18s, the
     stagger pattern naturally re-aligns. */
  .meter-hero__pkg            { animation: meter-pkg-flow 18s linear infinite; animation-fill-mode: backwards; }
  .meter-hero__pkg--1         { animation-delay: 0s; }
  .meter-hero__pkg--2         { animation-delay: 2.4s; }
  .meter-hero__pkg--3         { animation-delay: 4.8s; }
  .meter-hero__pkg--4         { animation-delay: 7.2s; }
  .meter-hero__pkg--5         { animation-delay: 9.6s; }

  /* Money flow — 5 staggered $ glyphs offset 0.4s after each package
     (so each $ emerges shortly after the corresponding package is
     consumed). */
  .meter-hero__money          { animation: meter-money-flow 18s linear infinite; animation-fill-mode: backwards; }
  .meter-hero__money--1       { animation-delay: 0.4s; }
  .meter-hero__money--2       { animation-delay: 2.8s; }
  .meter-hero__money--3       { animation-delay: 5.2s; }
  .meter-hero__money--4       { animation-delay: 7.6s; }
  .meter-hero__money--5       { animation-delay: 10.0s; }
}

/* Reduced-motion: static composition reads intentional. Fill held at 70%
   (mid-meter, suggests "in use"), cap-glow off, glint hidden, packages and
   money hidden, orbit frozen. */
@media (prefers-reduced-motion: reduce) {
  .meter-hero__fill { clip-path: inset(30% 0 0 0); }
  .meter-hero__pkg,
  .meter-hero__money { opacity: 0; }
}

/* 18s master cycle. Phases as % of total:
     0-66.7% (0-12s):  ACTIVE — drain from 0% inset (full) to 85% inset (~15% full)
     66.7-72.2% (12-13s): PAUSE — hold at 85% inset
     72.2-88.9% (13-16s): RECHARGE — fill back to 0% inset (full)
     88.9-100% (16-18s):  HOLD — stay at full */
@keyframes meter-cycle {
  0%      { clip-path: inset(0% 0 0 0); }
  66.7%   { clip-path: inset(85% 0 0 0); }
  72.2%   { clip-path: inset(85% 0 0 0); }
  88.9%   { clip-path: inset(0% 0 0 0); }
  100%    { clip-path: inset(0% 0 0 0); }
}

/* Cap glow — pulses at recharge complete (~88.9% of cycle = t=16s). */
@keyframes meter-cap-recharge {
  0%, 80%   { opacity: 0; transform: scale(1); }
  87%       { opacity: 0.6; transform: scale(1.2); }
  90%       { opacity: 1; transform: scale(1.45); }
  94%       { opacity: 0.4; transform: scale(1.1); }
  100%      { opacity: 0; transform: scale(1); }
}

/* Package flow — 18s keyframe with movement in the first ~7% of cycle
   (0-1.26s). Element travels from x=-30 (off-canvas left) to x=140 (just
   shy of battery left edge), then fades out. Stays invisible/parked at
   end position for the rest of the cycle until the master loop restarts. */
@keyframes meter-pkg-flow {
  0%      { transform: translate(-30px, 275px); opacity: 0; }
  3%      { opacity: 1; }
  6%      { transform: translate(140px, 275px); opacity: 1; }
  7%      { transform: translate(140px, 275px); opacity: 0; }
  100%    { transform: translate(140px, 275px); opacity: 0; }
}

/* Money flow — 18s keyframe with movement window slightly later than
   packages (4-11%). Element emerges at x=265 (just past battery right
   edge), travels to x=420 (off-canvas right), fades out. */
@keyframes meter-money-flow {
  0%      { transform: translate(265px, 275px); opacity: 0; }
  4%      { opacity: 0; }
  6%      { opacity: 1; }
  10%     { transform: translate(420px, 275px); opacity: 1; }
  11%     { opacity: 0; }
  100%    { transform: translate(420px, 275px); opacity: 0; }
}

/* =============================================================================
   D-108f: Advanced Rate Markups bespoke hero — vertical interactive viz.
   Cursor drags a slider, markup updates, customer price + margin update.
   ~10s loop. Cyan-only per D-074. Container styles clone meter-hero so
   the two flagships read at the same scale.
   ============================================================================= */
/* .markup-hero glass frame extracted to shared selector at line ~4076 (D-108). */

.markup-hero__svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

/* End-state values (--end suffix) start hidden; the start-state values
   (--start suffix) start visible. Crossfade swaps them at the midway
   point of the slider drag. */
.markup-hero__pct--end,
.markup-hero__price--end,
.markup-hero__margin--end {
  opacity: 0;
}

/* Slider handle starts at the bottom of the track (y=340 in viewBox),
   animation translates it upward by 260 user units to reach y=80 (top). */
.markup-hero__handle {
  will-change: transform;
}

/* Cursor starts off-canvas to the bottom-right (well outside viewBox).
   Animation: glide onto the handle (TRACK_X=340, TRACK_BOT=340),
   follow handle upward, then depart. */
.markup-hero__cursor {
  transform: translate(440px, 380px);
  opacity: 0;
  will-change: transform, opacity;
}

@media (prefers-reduced-motion: no-preference) {
  .markup-hero__handle           { animation: mh-handle 10s cubic-bezier(0.65, 0, 0.35, 1) infinite; }
  .markup-hero__cursor           { animation: mh-cursor 10s cubic-bezier(0.65, 0, 0.35, 1) infinite; }
  .markup-hero__pct--start,
  .markup-hero__price--start,
  .markup-hero__margin--start    { animation: mh-fade-start 10s ease-in-out infinite; }
  .markup-hero__pct--end,
  .markup-hero__price--end,
  .markup-hero__margin--end      { animation: mh-fade-end 10s ease-in-out infinite; }
}

/* Reduced-motion: composition reads as "set up your markup rule" with
   the slider at zero state (handle bottom, cursor hidden). */
@media (prefers-reduced-motion: reduce) {
  .markup-hero__cursor { opacity: 0; }
}

/* 10s master cycle:
     0-10%:    calm (handle bottom, cursor off-screen, values at start)
     10-25%:   cursor enters from bottom-right, glides onto handle
     25-50%:   cursor + handle drag upward together; values crossfade
               at midway (~37%)
     50-65%:   hold final state (handle top, cursor on handle)
     65-80%:   cursor departs to bottom-right; handle resets to bottom
     80-100%:  calm at start state */
@keyframes mh-handle {
  0%, 25%   { transform: translateY(0); }
  50%, 65%  { transform: translateY(-260px); }
  80%, 100% { transform: translateY(0); }
}
@keyframes mh-cursor {
  0%, 10%   { transform: translate(440px, 380px); opacity: 0; }
  18%       { opacity: 1; }
  25%       { transform: translate(360px, 348px); opacity: 1; }
  50%, 65%  { transform: translate(360px, 88px); opacity: 1; }
  78%       { transform: translate(440px, 380px); opacity: 0; }
  80%, 100% { transform: translate(440px, 380px); opacity: 0; }
}
/* Start-state values: visible at start, fade out around 35-40% (just past
   the midway of the slider drag), then fade back in as cursor departs. */
@keyframes mh-fade-start {
  0%, 30%   { opacity: 1; }
  40%       { opacity: 0; }
  72%       { opacity: 0; }
  82%, 100% { opacity: 1; }
}
/* End-state values: fade in around 35-40% (mid-drag), hold through the
   peak, fade out as cursor departs. */
@keyframes mh-fade-end {
  0%, 30%   { opacity: 0; }
  40%, 72%  { opacity: 1; }
  82%, 100% { opacity: 0; }
}

/* =============================================================================
   D-108g: Adjustment Reconciliation bespoke hero — flagship-tier scale.
   Same 3-lane carrier flow as the prior cv-card customSvg, scaled to
   497x497 glass card with smoother particle motion. Container clones
   meter-hero / markup-hero so the three flagships read at the same scale.
   ============================================================================= */
/* .reconcile-hero glass frame extracted to shared selector at line ~4076 (D-108).
   Flex layout (column) retained via per-hero override above for the
   SVG-on-top-of-text composition. */

.reconcile-hero__svg {
  flex: 1 1 auto;
  width: 100%;
  min-height: 0;
}

.reconcile-hero__desc {
  flex: 0 0 auto;
  margin: 0;
  padding: var(--space-3) var(--space-6) var(--space-5);
  font-size: var(--text-sm);
  line-height: 1.5;
  color: var(--color-text-muted);
  text-align: center;
}

/* D-108h: paired box + $ animation, 10s cycle (replaces single-particle reconcile-flow) */
.reconcile-hero__box,
.reconcile-hero__money {
  opacity: 0;
  will-change: transform, opacity;
}

@supports (offset-path: path('M 0 0')) {
  /* Box paths — terminate at the EDGE of the RF diamond (not the center).
     Diamond corners: top (220,118), right (242,140), bottom (220,162),
     left (198,140). Boxes hit the appropriate edge per their approach
     direction so they vanish at the line, not on top of the "RF" text. */
  .reconcile-hero__box--usps {
    offset-path: path('M 140 70 Q 200 70 214 124');
    offset-distance: 0%;
  }
  .reconcile-hero__box--ups {
    offset-path: path('M 140 140 L 198 140');
    offset-distance: 0%;
  }
  .reconcile-hero__box--fedex {
    offset-path: path('M 140 210 Q 200 210 214 156');
    offset-distance: 0%;
  }
  /* All $ glyphs share the RF -> battery line; staggered via animation-delay. */
  .reconcile-hero__money {
    offset-path: path('M 220 140 L 280 140');
    offset-distance: 0%;
  }

  @media (prefers-reduced-motion: no-preference) {
    /* 10s master cycle. Boxes stagger 0/2/4s. Each box's $ glyph emerges
       3s after the box starts (1s after the box arrives at the diamond). */
    .reconcile-hero__box--usps  { animation: reconcile-box-flow 10s 0s cubic-bezier(0.4, 0, 0.2, 1) infinite; }
    .reconcile-hero__box--ups   { animation: reconcile-box-flow 10s 2s cubic-bezier(0.4, 0, 0.2, 1) infinite; }
    .reconcile-hero__box--fedex { animation: reconcile-box-flow 10s 4s cubic-bezier(0.4, 0, 0.2, 1) infinite; }
    .reconcile-hero__money--1   { animation: reconcile-money-flow 10s 3s cubic-bezier(0.4, 0, 0.2, 1) infinite; }
    .reconcile-hero__money--2   { animation: reconcile-money-flow 10s 5s cubic-bezier(0.4, 0, 0.2, 1) infinite; }
    .reconcile-hero__money--3   { animation: reconcile-money-flow 10s 7s cubic-bezier(0.4, 0, 0.2, 1) infinite; }
    /* Battery fill increments at each $ arrival (4.5s, 6.5s, 8.5s into
       the 10s cycle = 45%, 65%, 85%). Cap glow pulses at the same beats. */
    .reconcile-hero__battery-fill {
      animation: reconcile-battery-charge 10s cubic-bezier(0.65, 0, 0.35, 1) infinite;
    }
    .reconcile-hero__cap-glow {
      animation: reconcile-cap-pulse 10s ease-in-out infinite;
    }
  }
}

@media (prefers-reduced-motion: reduce) {
  .reconcile-hero__box,
  .reconcile-hero__money { opacity: 0; }
  /* Show battery at full as the static intentional state */
  .reconcile-hero__battery-fill { clip-path: inset(0 0 0 0); }
  .reconcile-hero__cap-glow { opacity: 0.5; }
}

/* Battery starts empty until JS overrides via animation. */
.reconcile-hero__battery-fill { clip-path: inset(0 100% 0 0); }
.reconcile-hero__cap-glow { opacity: 0; }

/* Box flow — visible window 0-25% of 10s cycle (2.5s travel along the
   carrier-to-RF path). Stays parked + invisible the rest of the cycle
   until the next loop. */
@keyframes reconcile-box-flow {
  0%   { offset-distance: 0%; opacity: 0; }
  3%   { opacity: 1; }
  22%  { offset-distance: 100%; opacity: 1; }
  25%  { offset-distance: 100%; opacity: 0; }
  100% { offset-distance: 100%; opacity: 0; }
}

/* Money flow — visible window 0-15% of 10s cycle (1.5s travel along the
   RF-to-meter path). Each $ enters with a small fade-in, exits at the
   meter with a fade-out. */
@keyframes reconcile-money-flow {
  0%   { offset-distance: 0%; opacity: 0; }
  4%   { opacity: 1; }
  13%  { offset-distance: 100%; opacity: 1; }
  15%  { offset-distance: 100%; opacity: 0; }
  100% { offset-distance: 100%; opacity: 0; }
}

/* Battery charge — three discrete fill steps as $ glyphs arrive at the
   battery left edge (45%, 65%, 85% of 10s cycle). cubic-bezier easing
   gives a smooth 0.2s "pour" between steps. Snap-resets to empty at
   loop boundary (intentional discontinuity; the eye follows the rise). */
@keyframes reconcile-battery-charge {
  0%, 44%   { clip-path: inset(0 100% 0 0); }
  47%, 64%  { clip-path: inset(0 67% 0 0); }
  67%, 84%  { clip-path: inset(0 34% 0 0); }
  87%, 100% { clip-path: inset(0 0 0 0); }
}

/* Cap glow — pulses on each $ arrival (45%, 65%, 85%). Three blips
   reinforce the "charging" beat. */
@keyframes reconcile-cap-pulse {
  0%, 43%  { opacity: 0; }
  46%      { opacity: 1; }
  50%, 62% { opacity: 0.25; }
  66%      { opacity: 1; }
  70%, 82% { opacity: 0.25; }
  86%      { opacity: 1; }
  92%      { opacity: 0.5; }
  100%     { opacity: 0; }
}

/* =============================================================================
   D-108i: Claims & Disputes bespoke hero — flagship-tier scale.
   Brands -> AI -> Carriers (forward, dispute icons) then Carriers -> AI ->
   Brands (reverse, resolved icons). 10s cycle. Cyan-only per D-074.
   Container clones meter/markup/reconcile so all four flagships read at
   the same scale.
   ============================================================================= */
/* .claims-hero glass frame extracted to shared selector at line ~4076 (D-108). */

.claims-hero__svg {
  flex: 1 1 auto;
  width: 100%;
  min-height: 0;
}

.claims-hero__desc {
  flex: 0 0 auto;
  margin: 0;
  padding: var(--space-3) var(--space-6) var(--space-5);
  font-size: var(--text-sm);
  line-height: 1.5;
  color: var(--color-text-muted);
  text-align: center;
}

/* Claims & Disputes — bespoke flagship hero animation.

   Restart-from-scratch design: NO connector lines remain at end of
   cycle. Every cycle starts from a clean slate (just pills + AI hub),
   builds the topology, runs the response flow with thickening lines,
   then fades all connectors away before the next loop.

   14s master cycle (slowed from 8s for smoothness, per spec). All
   easing cubic-bezier(0.4, 0, 0.2, 1) — Premium / Corporate personality.

   Phase 1 (0-18%, 0-2.52s)    Brand→AI base wires flow in. Cascade
                               lanes 1/2/3 with 4% stagger (0-10%,
                               4-14%, 8-18%). Drawn left-to-right.
   Phase 2 (18-34%, 2.52-4.76s) AI→Carrier base wires flow in. Same
                               cascade pattern (18-26%, 22-30%, 26-34%).
   Pause  (34-44%, 4.76-6.16s) All six base wires visible at thin stroke.
   Phase 3 (44-58%, 6.16-8.12s) Thick overlay on AI-Carrier paths draws
                               in REVERSE direction (carrier→AI). Lanes
                               4% staggered (44-52%, 47-55%, 50-58%).
                               Visualizes the carrier processing and
                               sending the response back.
   Phase 4 (54-64%, 7.56-8.96s) Orbit AI hub pulses (radial glow scales
                               1→1.18 + opacity peak at 60%). The "AI
                               matched the response to the brand" moment.
   Phase 5 (62-76%, 8.68-10.64s) Thick overlay on Brand-AI paths draws
                               in REVERSE direction (AI→brand). Lanes
                               4% staggered (62-70%, 65-73%, 68-76%).
   Phase 6 (66-86%, 9.24-12.04s) Brand pill strokes brighten staggered to
                               match thick-overlay arrival (70-86%,
                               73-86%, 76-86%).
   Phase 7 (86-100%, 12.04-14s) ALL connector lines (base + thick) fade
                               opacity 1→0; dashoffset resets during the
                               opacity-0 window (invisible to the eye).
                               At 100% wrap the cycle restarts with
                               topology-only, ready for Phase 1 again.

   Implementation:
   - Each connection has TWO stacked path elements: a base "wire" (thin,
     stroke-width 1.6, dashoffset 100 = invisible from start side) and
     a "thick" overlay (stroke-width 3.4, dashoffset -100 = invisible
     from end side). Both use stroke-dasharray=100 + pathLength=100
     so dashoffset drives clean draw-in / draw-out.
   - Base draws via dashoffset 100→0 (left-to-right).
   - Thick draws via dashoffset -100→0 (RIGHT-to-LEFT, the response
     direction). For aic paths drawn AI→carrier, this is carrier→AI.
     For bai paths drawn brand→AI, this is AI→brand. ✓
   - All connectors share an opacity fade-out at 86-93%, with dashoffset
     reset during 93-100% (invisible window) so the cycle wraps cleanly
     to a no-lines starting state.
   - All timing in keyframe percentages, no animation-delay (per the
     comp-billing exemplar).
   - GPU-only (stroke-dashoffset, opacity, transform). Cyan-only per D-074. */

/* Static defaults — match keyframe 0% values so no FOUC. */
.claims-hero__svg .claims-hero__link {
  stroke-dashoffset: 100;
  opacity: 1;
}
.claims-hero__svg .claims-hero__thick {
  stroke-dashoffset: -100;
  opacity: 1;
}
.claims-hero__svg .claims-hero__ai-glow {
  opacity: 0.3;
  transform: scale(1);
  transform-box: fill-box;
  transform-origin: center;
}
.claims-hero__svg .claims-hero__brand-pill {
  stroke: rgba(125, 211, 252, 0.55);
}

/* Reduced-motion: show topology with thin base wires drawn, thick
   overlays hidden, brand pills at base color, hub gently lit. Reads
   as a static "brands ↔ Orbit AI ↔ carriers" infrastructure diagram. */
@media (prefers-reduced-motion: reduce) {
  .claims-hero__svg .claims-hero__link { stroke-dashoffset: 0; }
  .claims-hero__svg .claims-hero__thick { opacity: 0; }
  .claims-hero__svg .claims-hero__ai-glow { opacity: 0.5; }
  .claims-hero__svg .claims-hero__brand-pill { stroke: rgba(125, 211, 252, 0.55); }
}

@media (prefers-reduced-motion: no-preference) {
  /* Phase 1+2 — base wires draw in cascade. */
  .claims-hero__svg .claims-hero__link--bai-1 { animation: ch-link-bai-1 14s cubic-bezier(0.4, 0, 0.2, 1) infinite; }
  .claims-hero__svg .claims-hero__link--bai-2 { animation: ch-link-bai-2 14s cubic-bezier(0.4, 0, 0.2, 1) infinite; }
  .claims-hero__svg .claims-hero__link--bai-3 { animation: ch-link-bai-3 14s cubic-bezier(0.4, 0, 0.2, 1) infinite; }
  .claims-hero__svg .claims-hero__link--aic-1 { animation: ch-link-aic-1 14s cubic-bezier(0.4, 0, 0.2, 1) infinite; }
  .claims-hero__svg .claims-hero__link--aic-2 { animation: ch-link-aic-2 14s cubic-bezier(0.4, 0, 0.2, 1) infinite; }
  .claims-hero__svg .claims-hero__link--aic-3 { animation: ch-link-aic-3 14s cubic-bezier(0.4, 0, 0.2, 1) infinite; }

  /* Phase 3 — thick overlay on AI-Carrier paths (carrier→AI direction). */
  .claims-hero__svg .claims-hero__thick--aic-1 { animation: ch-thick-aic-1 14s cubic-bezier(0.4, 0, 0.2, 1) infinite; }
  .claims-hero__svg .claims-hero__thick--aic-2 { animation: ch-thick-aic-2 14s cubic-bezier(0.4, 0, 0.2, 1) infinite; }
  .claims-hero__svg .claims-hero__thick--aic-3 { animation: ch-thick-aic-3 14s cubic-bezier(0.4, 0, 0.2, 1) infinite; }

  /* Phase 4 — AI hub processing pulse. */
  .claims-hero__svg .claims-hero__ai-glow {
    animation: ch-ai-pulse 14s cubic-bezier(0.4, 0, 0.2, 1) infinite;
  }

  /* Phase 5 — thick overlay on Brand-AI paths (AI→brand direction). */
  .claims-hero__svg .claims-hero__thick--bai-1 { animation: ch-thick-bai-1 14s cubic-bezier(0.4, 0, 0.2, 1) infinite; }
  .claims-hero__svg .claims-hero__thick--bai-2 { animation: ch-thick-bai-2 14s cubic-bezier(0.4, 0, 0.2, 1) infinite; }
  .claims-hero__svg .claims-hero__thick--bai-3 { animation: ch-thick-bai-3 14s cubic-bezier(0.4, 0, 0.2, 1) infinite; }

  /* Phase 6 — brand pills brighten as thick overlay arrives. */
  .claims-hero__svg .claims-hero__brand--1 .claims-hero__brand-pill { animation: ch-brand-light-1 14s cubic-bezier(0.4, 0, 0.2, 1) infinite; }
  .claims-hero__svg .claims-hero__brand--2 .claims-hero__brand-pill { animation: ch-brand-light-2 14s cubic-bezier(0.4, 0, 0.2, 1) infinite; }
  .claims-hero__svg .claims-hero__brand--3 .claims-hero__brand-pill { animation: ch-brand-light-3 14s cubic-bezier(0.4, 0, 0.2, 1) infinite; }
}

/* === Phase 1+2 base wire draws ===
   Each base wire: invisible from start (dashoffset 100) → drawn in
   (dashoffset 0) at the cascade time → held visible → opacity fades
   at 86-93% → dashoffset resets to 100 during the invisible window. */
@keyframes ch-link-bai-1 {
  0%        { stroke-dashoffset: 100; opacity: 1; }
  10%, 86%  { stroke-dashoffset: 0; opacity: 1; }
  93%       { stroke-dashoffset: 0; opacity: 0; }
  100%      { stroke-dashoffset: 100; opacity: 0; }
}
@keyframes ch-link-bai-2 {
  0%, 4%    { stroke-dashoffset: 100; opacity: 1; }
  14%, 86%  { stroke-dashoffset: 0; opacity: 1; }
  93%       { stroke-dashoffset: 0; opacity: 0; }
  100%      { stroke-dashoffset: 100; opacity: 0; }
}
@keyframes ch-link-bai-3 {
  0%, 8%    { stroke-dashoffset: 100; opacity: 1; }
  18%, 86%  { stroke-dashoffset: 0; opacity: 1; }
  93%       { stroke-dashoffset: 0; opacity: 0; }
  100%      { stroke-dashoffset: 100; opacity: 0; }
}
@keyframes ch-link-aic-1 {
  0%, 18%   { stroke-dashoffset: 100; opacity: 1; }
  26%, 86%  { stroke-dashoffset: 0; opacity: 1; }
  93%       { stroke-dashoffset: 0; opacity: 0; }
  100%      { stroke-dashoffset: 100; opacity: 0; }
}
@keyframes ch-link-aic-2 {
  0%, 22%   { stroke-dashoffset: 100; opacity: 1; }
  30%, 86%  { stroke-dashoffset: 0; opacity: 1; }
  93%       { stroke-dashoffset: 0; opacity: 0; }
  100%      { stroke-dashoffset: 100; opacity: 0; }
}
@keyframes ch-link-aic-3 {
  0%, 26%   { stroke-dashoffset: 100; opacity: 1; }
  34%, 86%  { stroke-dashoffset: 0; opacity: 1; }
  93%       { stroke-dashoffset: 0; opacity: 0; }
  100%      { stroke-dashoffset: 100; opacity: 0; }
}

/* === Phase 3 thick overlay (carrier→AI direction) ===
   Thick paths: invisible from end side (dashoffset -100) until their
   cascade slot, then draw in via -100→0 = right-to-left fill. Held
   visible through pause. Opacity fades at 86-93%; dashoffset resets
   to -100 during the invisible window. */
@keyframes ch-thick-aic-1 {
  0%, 44%   { stroke-dashoffset: -100; opacity: 1; }
  52%, 86%  { stroke-dashoffset: 0; opacity: 1; }
  93%       { stroke-dashoffset: 0; opacity: 0; }
  100%      { stroke-dashoffset: -100; opacity: 0; }
}
@keyframes ch-thick-aic-2 {
  0%, 47%   { stroke-dashoffset: -100; opacity: 1; }
  55%, 86%  { stroke-dashoffset: 0; opacity: 1; }
  93%       { stroke-dashoffset: 0; opacity: 0; }
  100%      { stroke-dashoffset: -100; opacity: 0; }
}
@keyframes ch-thick-aic-3 {
  0%, 50%   { stroke-dashoffset: -100; opacity: 1; }
  58%, 86%  { stroke-dashoffset: 0; opacity: 1; }
  93%       { stroke-dashoffset: 0; opacity: 0; }
  100%      { stroke-dashoffset: -100; opacity: 0; }
}

/* === Phase 4 — Orbit AI hub processing pulse === */
@keyframes ch-ai-pulse {
  0%, 56%   { opacity: 0.3; transform: scale(1); }
  60%       { opacity: 0.95; transform: scale(1.18); }
  64%, 86%  { opacity: 0.5; transform: scale(1); }
  93%, 100% { opacity: 0.3; transform: scale(1); }
}

/* === Phase 5 thick overlay (AI→brand direction) === */
@keyframes ch-thick-bai-1 {
  0%, 62%   { stroke-dashoffset: -100; opacity: 1; }
  70%, 86%  { stroke-dashoffset: 0; opacity: 1; }
  93%       { stroke-dashoffset: 0; opacity: 0; }
  100%      { stroke-dashoffset: -100; opacity: 0; }
}
@keyframes ch-thick-bai-2 {
  0%, 65%   { stroke-dashoffset: -100; opacity: 1; }
  73%, 86%  { stroke-dashoffset: 0; opacity: 1; }
  93%       { stroke-dashoffset: 0; opacity: 0; }
  100%      { stroke-dashoffset: -100; opacity: 0; }
}
@keyframes ch-thick-bai-3 {
  0%, 68%   { stroke-dashoffset: -100; opacity: 1; }
  76%, 86%  { stroke-dashoffset: 0; opacity: 1; }
  93%       { stroke-dashoffset: 0; opacity: 0; }
  100%      { stroke-dashoffset: -100; opacity: 0; }
}

/* === Phase 6 — Brand pill stroke brightens as thick overlay arrives === */
@keyframes ch-brand-light-1 {
  0%, 66%   { stroke: rgba(125, 211, 252, 0.55); }
  70%, 86%  { stroke: rgba(0, 194, 255, 0.95); }
  93%, 100% { stroke: rgba(125, 211, 252, 0.55); }
}
@keyframes ch-brand-light-2 {
  0%, 69%   { stroke: rgba(125, 211, 252, 0.55); }
  73%, 86%  { stroke: rgba(0, 194, 255, 0.95); }
  93%, 100% { stroke: rgba(125, 211, 252, 0.55); }
}
@keyframes ch-brand-light-3 {
  0%, 72%   { stroke: rgba(125, 211, 252, 0.55); }
  76%, 86%  { stroke: rgba(0, 194, 255, 0.95); }
  93%, 100% { stroke: rgba(125, 211, 252, 0.55); }
}

/* Comprehensive Billing hero wrapper — mirrors .reconcile-hero / .claims-hero (D-108) */

.comp-billing-hero__svg {
  flex: 1 1 auto;
  width: 100%;
  min-height: 0;
}
/* SPLIT-CANDIDATE: bespoke flagship-hero family ends (D-108) */

/* ============================================================
   D-141 — Single-viewport crossfade sticky-steps.

   Replaces D-139's sibling-stack-cover pattern. D-139 required
   each step to have an opaque background so later sticky siblings
   could obscure earlier ones — but that opaque bg blocked the
   body-stack ambient (body:not(.home)::before, dot-grid + corner
   radials), creating a hard seam at the section boundary. User
   feedback (paraphrasing): "completely transparent so gradient
   glows match the rest of the site." Iris also flagged that
   min-height: 100vh + align-items: center parked step content
   ~50vh below the intro h2 — "more than double the expected
   distance from the header."

   New pattern (Iris Option B, ratified):
   - .pillar-steps-stack section provides scroll runway (height =
     --step-count × 100vh + tail) ONLY when JS hydrates the section
     (data-js-hydrated attribute) AND desktop+motion conditions
     are met. Otherwise it's a natural-flow section (linear stack).
   - .pillar-steps-stack__viewport is 'position: sticky; top: 0;
     height: 100vh'. Intro h2 lives INSIDE the viewport at top so
     the heading stays anchored while the user scrolls through
     all step slices ("the header remains there while it rolls
     through each option").
   - .pillar-steps-stack__stage holds N absolutely-positioned step
     articles. All N share the same coordinates; CSS transition
     drives opacity 0↔1 as JS toggles .is-active.
   - Step backgrounds are TRANSPARENT — body ambient bleeds
     through unbroken. No seam, no opaque void.

   Fallbacks (all collapse to identical linear stack):
   - No JS hydration → no data-js-hydrated → sticky CSS doesn't
     apply. STICKY_STEPS_JS also strips SSR inert from steps 2-N
     when falling back, so AT users see all steps as linear content.
   - prefers-reduced-motion: reduce → STICKY_STEPS_JS strips inert
     + the CSS sticky geometry doesn't apply (no transition either).
   - <1024px (mobile/tablet) → same linear stack.

   SSR HTML is identical in every mode. The sticky+crossfade is
   paint-only progressive enhancement.

   Iris-required invariants:
   - WCAG 2.4.7: inactive steps get 'inert' attribute (set in SSR
     for steps 2-N; toggled by JS as user scrolls). Opacity:0 alone
     would leave them as invisible tab-stops.
   - Reduced-motion: linear stack, NOT "all stacked at once opaque."
   - 360px portrait fit: panel + iframe stack vertically inside
     viewport at narrow widths so step content stays in one screen.
   ============================================================ */
.pillar-steps-stack {
  padding-top: var(--section-gap);
}

.pillar-steps-stack__viewport {
  /* Mobile/tablet/reduced-motion/no-JS default: just a normal block. */
  position: relative;
}

.pillar-steps-stack__intro {
  margin-bottom: var(--space-10);
}

/* D-145: progress pip indicator. Hidden by default — only renders in the
   sticky+crossfade mode below. Visually a row of thin horizontal ticks
   centered under the intro h2. Active pip widens + brightens to brand
   cyan. Reduced-motion + mobile collapse to display: none since the
   linear-stack rendering doesn't carry "current position" semantics. */
.pillar-steps-stack__pips {
  display: none;
}

.pillar-steps-stack__stage {
  display: flex;
  flex-direction: column;
}

/* Each step — default (mobile/tablet/reduced-motion/no-JS): natural flow,
   transparent bg. Body ambient owns the surface in linear-stack mode too. */
.pillar-steps-stack__step {
  padding: var(--space-10) 0;
  background: transparent;
}

.pillar-steps-stack__inner {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-8);
  align-items: center;
}

.pillar-steps-stack__panel {
  max-width: 36rem;
}

.pillar-steps-stack__eyebrow {
  text-transform: uppercase;
  letter-spacing: 0.12em;
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  color: var(--color-emphasis);
  margin: 0 0 var(--space-3);
}

.pillar-steps-stack__heading {
  font-family: var(--font-display);
  font-weight: var(--weight-bold);
  font-size: var(--text-3xl);
  line-height: var(--leading-tight);
  letter-spacing: -0.01em;
  margin: 0 0 var(--space-4);
  color: var(--color-text-strong);
}

.pillar-steps-stack__body {
  font-size: var(--text-lg);
  line-height: var(--leading-relaxed);
  color: var(--color-text);
  margin: 0;
}

/* Media — iframe wrapper. aspect-ratio reservation prevents CLS. Glass
   chrome matches the bespoke flagship demo cards (D-108 family). */
.pillar-steps-stack__media {
  position: relative;
  width: 100%;
  max-width: 552px;
  margin: 0 auto;
  aspect-ratio: 552 / 360;
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: rgba(15, 28, 52, 0.30);
  border: 1px solid rgba(0, 194, 255, 0.22);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.06),
    0 4px 24px rgba(0, 0, 0, 0.32);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
}

.pillar-steps-stack__media iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
}

@supports not (backdrop-filter: blur(1px)) {
  .pillar-steps-stack__media {
    background: rgba(20, 35, 65, 0.55);
  }
}

/* Desktop: two-column inside each step. */
@media (min-width: 1024px) {
  .pillar-steps-stack__inner {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: var(--space-12);
  }
  .pillar-steps-stack__panel {
    max-width: none;
  }
  .pillar-steps-stack__heading {
    font-size: var(--text-4xl);
  }
}

/* Desktop + motion + JS-hydrated: engage single-viewport crossfade.
   --step-count is set inline on the section by the renderer. Each step
   gets 0.65 viewport of runway (D-236: down from 1.0 — too much dead
   scroll between crossfades; the tracker reads progress as a scroll
   FRACTION, so compressing the section just shortens each step's window
   without desyncing the crossfade). The '+0.4' tail buys a small
   exit-window after the last step is fully visible (so the final
   crossfade-out completes before the section's sticky containment ends).

   Site nav (.nav) is sticky at top: 0; z-index: 100 with ~80px
   intrinsic height. The pillar-steps-stack__viewport stacks BELOW
   the nav by topping at 80px and reducing its own height to fit the
   remaining vertical room. Without this offset, the nav overlays
   the intro h2 and the user sees step content under the nav with
   no anchored heading. */
@media (min-width: 1024px) and (prefers-reduced-motion: no-preference) {
  .pillar-steps-stack[data-js-hydrated] {
    height: calc((var(--step-count, 4) * 0.65 + 0.4) * 100vh);
  }
  .pillar-steps-stack[data-js-hydrated] .pillar-steps-stack__viewport {
    position: sticky;
    top: 80px;
    height: calc(100vh - 80px);
    display: flex;
    flex-direction: column;
    overflow: hidden;
  }
  .pillar-steps-stack[data-js-hydrated] .pillar-steps-stack__intro {
    flex: 0 0 auto;
    padding-top: var(--space-6);
    margin-bottom: var(--space-6);
    text-align: center;
  }
  /* D-145: pip row — visible only in the sticky+crossfade mode. Horizontal
     ticks (24px wide × 2px tall) centered under the h2, with the active
     pip widening to 36px + brightening from a 0.18α dimmed cyan to the
     full brand emphasis cyan at 0.85α. Width + background-color transition
     in 280ms ease — matches the step-content opacity crossfade timing so
     the pip animation feels coupled to the step animation. */
  .pillar-steps-stack[data-js-hydrated] .pillar-steps-stack__pips {
    display: inline-flex;
    gap: 8px;
    margin: var(--space-3) 0 0;
    padding: 0;
    list-style: none;
  }
  .pillar-steps-stack[data-js-hydrated] .pillar-steps-stack__pip {
    display: block;
    width: 24px;
    height: 2px;
    border-radius: 1px;
    background: rgba(125, 211, 252, 0.18);
    transition: width 280ms cubic-bezier(0.4, 0, 0.2, 1),
                background-color 280ms cubic-bezier(0.4, 0, 0.2, 1);
  }
  .pillar-steps-stack[data-js-hydrated] .pillar-steps-stack__pip.is-active {
    width: 36px;
    background: rgba(0, 194, 255, 0.85);
  }
  .pillar-steps-stack[data-js-hydrated] .pillar-steps-stack__stage {
    position: relative;
    flex: 1 1 auto;
  }
  /* All N steps share the same stage coordinates. Only the active
     one is opacity:1 + visibility:visible. CSS transition handles the
     crossfade. z-index lifts the active step above the others so
     pointer events route to the visible content correctly.

     visibility: hidden does double duty: it hides the step from the
     accessibility tree AND removes it from the keyboard tab order
     (WCAG 2.4.7 — Iris stipulation). Transition-delay on visibility
     keeps it 'visible' during the 380ms opacity fade-out, then snaps
     to 'hidden' once the fade completes. Going the other way (fade-in)
     visibility flips to 'visible' instantly so the opacity transition
     is observable. */
  .pillar-steps-stack[data-js-hydrated] .pillar-steps-stack__step {
    position: absolute;
    inset: 0;
    padding: 0;
    display: flex;
    align-items: center;
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    z-index: 1;
    transition: opacity 380ms cubic-bezier(0.4, 0, 0.2, 1), visibility 0s linear 380ms;
    will-change: opacity;
  }
  .pillar-steps-stack[data-js-hydrated] .pillar-steps-stack__step.is-active {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
    z-index: 2;
    transition: opacity 380ms cubic-bezier(0.4, 0, 0.2, 1), visibility 0s linear 0s;
  }
}

/* Reduced-motion: hard linear collapse. Forces the section back to a
   natural-flow stack even if JS hydrated. The JS detector also strips
   SSR inert in this branch, so AT reads all steps as linear content.
   Iris WCAG 2.3.3 condition. */
@media (prefers-reduced-motion: reduce) {
  .pillar-steps-stack,
  .pillar-steps-stack[data-js-hydrated] {
    height: auto !important;
  }
  .pillar-steps-stack[data-js-hydrated] .pillar-steps-stack__viewport {
    position: static !important;
    height: auto !important;
    display: block !important;
    overflow: visible !important;
  }
  .pillar-steps-stack[data-js-hydrated] .pillar-steps-stack__step {
    position: static !important;
    opacity: 1 !important;
    visibility: visible !important;
    pointer-events: auto !important;
    padding: var(--space-10) 0 !important;
    transition: none !important;
    z-index: auto !important;
  }
}

/* ============================================================
   Integrations directory (/integrations + /integrations/:category)
   Two-level: hub of category cards -> per-category directory page.
   Cards reuse .pillar-card / .pillar-card-inert + .pillar-grid-hub.
   ============================================================ */

/* Vendor favicon + name row inside a directory card (D-245). Favicons are hotlinked from
   Google's faviconV2 service, so they are small square icons built for a light backdrop. */
.int-card__head {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-bottom: var(--space-2);
}
.int-card__head .pillar-title { margin-bottom: 0; }
.int-logo {
  flex: 0 0 auto;
  width: 38px;
  height: 38px;
  border-radius: 9px;
  background: #ffffff;
  padding: 5px;
  object-fit: contain;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.12), 0 1px 2px rgba(5, 12, 26, 0.25);
}
/* Letter-tile fallback when a vendor has no verified domain — glass-toned, not white */
.int-logo--ph {
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(160deg, rgba(0, 194, 255, 0.18), rgba(128, 147, 181, 0.10));
  color: var(--color-primary);
  font-family: var(--font-display);
  font-weight: var(--weight-bold);
  font-size: 1.05rem;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.10);
}

/* Cross-category nav chips (links) — shown on each category directory page */
.int-filters {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-2);
  max-width: 760px;
  margin: 0 auto var(--space-10);
}
.int-filter {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-4);
  font: inherit;
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  line-height: 1;
  text-decoration: none;
  color: var(--color-text-muted);
  background-color: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--color-border-accent);
  border-radius: var(--radius-pill);
  transition: color 0.18s ease, border-color 0.18s ease, background-color 0.18s ease;
}
.int-filter:hover {
  color: var(--color-text);
  border-color: var(--color-primary);
}
.int-filter:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 3px;
}
/* Active chip mirrors .btn-primary: dark text on cyan gradient = AAA contrast */
.int-filter[aria-current="page"] {
  color: var(--color-bg);
  background-color: transparent;
  background-image: var(--gradient-cta);
  border-color: transparent;
}
.int-filter__count {
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  opacity: 0.7;
}
.int-filter[aria-current="page"] .int-filter__count { opacity: 0.85; }

/* Hub: primary-category explainer cards (links into each directory) */
.int-hub-card__count {
  display: inline-block;
  margin-bottom: var(--space-3);
  font-size: var(--text-sm);
  font-weight: var(--weight-bold);
  color: var(--color-primary);
}
.int-hub-card__examples {
  display: block;
  margin-top: var(--space-4);
  font-size: var(--text-xs);
  color: var(--color-text-muted);
}

/* Per-category directory: center a lone card (e.g. Accounting, Other) instead
   of letting the hub orphan-row guard stretch it edge-to-edge. Falls back to
   the full-width orphan behavior where :has() is unsupported. */
.int-directory .pillar-grid-hub:has(> .pillar-card-inert:only-child) {
  grid-template-columns: minmax(0, 420px);
  justify-content: center;
}

/* ============================================================
   ROI Calculator (D-158) — resource tool + explainer
   ============================================================ */
.roi-calc { margin-top: var(--space-8); }

.roi-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-8);
}
@media (min-width: 900px) {
  .roi-grid { grid-template-columns: 5fr 6fr; gap: var(--space-10); align-items: stretch; }
}

.roi-inputs__intro {
  margin: 0 0 var(--space-6);
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}

.roi-field { margin-bottom: var(--space-6); }
.roi-field:last-child { margin-bottom: 0; }
.roi-field > label,
.roi-field__label {
  display: block;
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  color: var(--color-text);
  margin-bottom: var(--space-2);
}

.roi-input-wrap { position: relative; }
.roi-input-prefix {
  position: absolute;
  left: var(--space-4);
  top: 50%;
  transform: translateY(-50%);
  color: var(--color-text-muted);
  pointer-events: none;
  font-size: var(--text-lg);
}

.roi-num {
  width: 100%;
  background: var(--color-surface-elevated);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
  color: var(--color-text);
  font-family: var(--font-sans);
  font-size: var(--text-lg);
  font-variant-numeric: tabular-nums;
  min-height: 48px;
}
.roi-num--prefixed { padding-left: calc(var(--space-4) + 0.75em); }
.roi-num::placeholder { color: var(--color-text-placeholder); font-size: var(--text-base); }
.roi-num:focus {
  outline: none;
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px rgba(0, 194, 255, 0.20);
}
.roi-custom { margin-top: var(--space-3); }
.roi-custom[hidden] { display: none; }

/* net-terms quick buttons */
.roi-terms { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.roi-term {
  flex: 1 1 0;
  min-width: 60px;
  padding: var(--space-3) var(--space-2);
  background: var(--color-surface-elevated);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  color: var(--color-text);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  cursor: pointer;
  min-height: 44px;
  transition: border-color 150ms ease, background-color 150ms ease, color 150ms ease;
}
.roi-term:hover { border-color: var(--color-border-glow); }
.roi-term.is-active {
  border-color: var(--color-primary);
  background: rgba(0, 194, 255, 0.12);
  color: var(--color-text-strong);
}
.roi-term:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 2px; }

.roi-pay-note {
  margin: var(--space-3) 0 0;
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}
.roi-pay-note strong { color: var(--color-accent-teal); font-weight: var(--weight-semibold); }

/* shipments slider — native range, cyan accent */
.roi-slider {
  width: 100%;
  margin-top: var(--space-3);
  accent-color: var(--color-primary);
}
.roi-slider:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 4px; }

/* results panel — bespoke cyan accent surface */
.roi-results {
  border-radius: var(--radius-lg);
  padding: var(--space-8);
  background-color: rgba(15, 28, 52, 0.40);
  background-image:
    radial-gradient(ellipse 90% 55% at 50% 0%, rgba(0, 194, 255, 0.12) 0%, transparent 70%),
    linear-gradient(180deg, rgba(0, 194, 255, 0.06) 0%, rgba(0, 194, 255, 0.02) 100%);
  border: 1px solid rgba(0, 194, 255, 0.24);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08), 0 8px 28px rgba(0, 0, 0, 0.24);
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
}
@supports not (backdrop-filter: blur(1px)) {
  .roi-results { background-color: rgba(20, 35, 65, 0.72); }
}
@media (max-width: 640px) { .roi-results { padding: var(--space-6); } }

.roi-headline { text-align: center; }
.roi-headline__value {
  display: block;
  font-family: var(--font-display);
  font-size: clamp(2.75rem, 1.6rem + 4vw, 4.5rem);
  font-weight: var(--weight-black);
  color: var(--color-accent-teal);
  line-height: 1;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5), 0 0 24px rgba(0, 255, 209, 0.22);
}
.roi-headline__label {
  display: block;
  margin-top: var(--space-3);
  color: var(--color-text-muted);
  font-size: var(--text-sm);
  line-height: var(--leading-snug);
}

.roi-stats { list-style: none; padding: 0; margin: 0; }
.roi-stat {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--space-4);
  padding: var(--space-3) 0;
  border-top: 1px solid var(--color-border);
}
.roi-stat__label { color: var(--color-text-muted); font-size: var(--text-sm); }
.roi-stat__value {
  font-family: var(--font-display);
  font-weight: var(--weight-semibold);
  color: var(--color-text-strong);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.roi-punch {
  margin: 0;
  padding-top: var(--space-4);
  border-top: 1px solid var(--color-border);
  color: var(--color-text);
  line-height: var(--leading-normal);
}
.roi-punch strong { color: var(--color-accent-teal); font-weight: var(--weight-bold); }
.roi-fineprint { margin: 0; font-size: var(--text-xs); color: var(--color-text-muted); }

/* inline label helper on the ROI lead form */
.field-help-inline {
  color: var(--color-text-muted);
  font-weight: var(--weight-regular);
  font-size: var(--text-xs);
}

/* ============================================================
   ROI explainer — worked-example callout (prose itself uses the
   shared .longform system in styles/longform.ts, D-159)
   ============================================================ */
.roi-example {
  border-radius: var(--radius-lg);
  padding: var(--space-6);
  background-color: rgba(0, 194, 255, 0.05);
  border: 1px solid var(--color-border-accent);
}
.roi-example__rate {
  font-family: var(--font-display);
  font-weight: var(--weight-black);
  color: var(--color-accent-teal);
  font-size: var(--text-2xl);
}

/* ============================================================
   Long-form article layout (D-159) — shared shell + prose
   ============================================================ */
.longform {
  max-width: 1100px;
  margin-inline: auto;
  padding-inline: var(--space-4);

  /* D-221: longform fluid type scale. Heading + breakout sizes interpolate
     smoothly across the viewport via clamp() instead of snapping at the 768px
     breakpoint. Floors = the prior mobile --text-* values, ceilings = the prior
     desktop values (no new scale invented). Scoped to .longform so global tokens
     and every other surface are untouched (CWV/CLS blast radius = zero).
     Worked example for the cf-content-stack longform spec. */
  --lf-h2: clamp(1.5rem, 1.12rem + 1.9vw, 2rem);    /* was --text-2xl 1.5 to 2 */
  --lf-h3: clamp(1.25rem, 1.05rem + 1.0vw, 1.5rem);  /* was --text-xl 1.25 to 1.5 */
  --lf-stat: clamp(2.25rem, 1.4rem + 4.2vw, 3.5rem); /* was --text-4xl 2.25 to 3.5 */
}

/* With a TOC: 2-col grid on desktop (sticky TOC + prose), centered. Below
   1024px the TOC is dropped and prose takes the full readable measure. */
.longform--toc { display: block; }
@media (min-width: 1024px) {
  .longform--toc {
    display: grid;
    grid-template-columns: 220px minmax(0, 720px);
    gap: var(--space-12);
    justify-content: center;
    align-items: start;
  }
}

/* Sticky table of contents */
.longform__toc { display: none; }
@media (min-width: 1024px) {
  .longform__toc {
    display: block;
    position: sticky;
    top: 96px;
    align-self: start;
  }
}
.longform__toc-title {
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  margin: 0 0 var(--space-4);
}
.longform__toc nav ul { list-style: none; margin: 0; padding: 0; }
.longform__toc nav li { margin: 0; }
.longform__toc-link {
  display: block;
  padding: var(--space-2) 0 var(--space-2) var(--space-4);
  border-left: 2px solid var(--color-border);
  color: var(--color-text-muted);
  font-size: var(--text-sm);
  line-height: var(--leading-snug);
  text-decoration: none;
  transition: color 150ms ease, border-color 150ms ease;
}
.longform__toc-link:hover { color: var(--color-text); border-left-color: var(--color-border-glow); }
.longform__toc-link.is-active {
  color: var(--color-emphasis);
  border-left-color: var(--color-primary);
  font-weight: var(--weight-medium);
}
.longform__toc-link:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 2px; }

/* Prose column — the readable measure */
.longform__prose { max-width: 720px; min-width: 0; }
.longform__prose > * + * { margin-top: var(--space-5); }
.longform__prose > h2 + *,
.longform__prose > h3 + * { margin-top: var(--space-4); }
/* D-040: paragraph-to-paragraph separation must exceed the in-paragraph line
   height (text-lg x leading-relaxed = ~30px) so a paragraph break reads stronger
   than a line break. space-8 (32px ~ one line) gives that; the owl above stays
   tighter for mixed block transitions (p to list/figure). The first paragraph
   after a heading keeps its space-4 hug via the h2/h3 rule above. */
.longform__prose > p + p { margin-top: var(--space-8); }

.longform__prose h2 {
  font-family: var(--font-display);
  font-weight: var(--weight-bold);
  font-size: var(--lf-h2, var(--text-2xl));
  color: var(--color-text-strong);
  line-height: 1.2;
  margin-top: var(--space-10);
  scroll-margin-top: 96px;
}
.longform__prose h2:first-child { margin-top: 0; }
.longform__prose h3 {
  font-family: var(--font-display);
  font-weight: var(--weight-semibold);
  font-size: var(--lf-h3, var(--text-xl));
  color: var(--color-text-strong);
  line-height: 1.25;
  margin-top: var(--space-8);
  scroll-margin-top: 96px;
}
.longform__prose p {
  color: var(--color-text);
  font-size: var(--text-lg);
  line-height: var(--leading-relaxed);
  margin: 0;
}
.longform__prose p.lead { color: var(--color-text); font-size: var(--text-xl); }
.longform__prose ul,
.longform__prose ol { margin: 0; padding-left: var(--space-6); color: var(--color-text); }
.longform__prose li { margin-bottom: var(--space-2); line-height: var(--leading-normal); }
.longform__prose li strong { color: var(--color-text-strong); }
.longform__prose img { max-width: 100%; height: auto; border-radius: var(--radius-lg); }

/* Prose tables (blog data tables, e.g. recovery-range matrices). display:block +
   overflow-x keeps wide tables scrollable inside the 720px measure on mobile. */
.longform__prose table {
  display: block;
  width: 100%;
  overflow-x: auto;
  border-collapse: collapse;
  font-size: var(--text-base);
  line-height: var(--leading-normal);
  /* D-221: dark-theme scrollbar for the mobile horizontal scroll (parked D-035) */
  scrollbar-width: thin;
  scrollbar-color: var(--color-border-glow) transparent;
}
.longform__prose table::-webkit-scrollbar { height: 8px; }
.longform__prose table::-webkit-scrollbar-track { background: transparent; }
.longform__prose table::-webkit-scrollbar-thumb {
  background: var(--color-border-glow);
  border-radius: var(--radius-pill);
}
.longform__prose th,
.longform__prose td {
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--color-border);
  text-align: left;
  color: var(--color-text);
  white-space: nowrap;
}
.longform__prose th {
  color: var(--color-text-strong);
  font-weight: var(--weight-semibold);
  border-bottom: 1px solid var(--color-border-accent);
}

/* Figures (infographic embeds) - image + visible provisional/source caption */
.longform__prose figure.longform-figure { margin: var(--space-8) 0; text-align: center; }
.longform__prose figure.longform-figure figcaption {
  margin-top: var(--space-3);
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

/* D-221: breakout components injected into prose get explicit block rhythm —
   more breathing room than the body-copy owl selector (> * + *) provides. */
.longform__prose > .before-after { margin: var(--space-8) 0; }
.longform__prose > .card { margin: var(--space-10) 0; }

/* TL;DR callout (optional, top of prose) */
.longform__tldr {
  border-radius: var(--radius-lg);
  /* D-040 + Jake review follow-ups: space-3 (12px) block margin so the tinted
     block separates from the surrounding body text instead of crowding it;
     padding = space-6 (24px) + 5px internal breathing. */
  margin-block: var(--space-3);
  padding: calc(var(--space-6) + 5px);
  background-color: rgba(0, 194, 255, 0.05);
  border: 1px solid var(--color-border-accent);
  border-left: 3px solid var(--color-primary);
}
.longform__tldr-title {
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-emphasis);
  margin: 0 0 var(--space-3);
}
/* D-040: relaxed leading (was --leading-normal) so the dense summary breathes */
.longform__tldr p { margin: 0; color: var(--color-text); line-height: var(--leading-relaxed); }

/* ============================================================
   Article furniture (D-160) — full-width hero, reading-progress,
   scroll-reveal, before/after ledger, featured quote. Shared by
   case studies + blog posts. All motion below the fold + gated.
   ============================================================ */

/* reading-progress bar — CSS scroll-driven, 0 KB JS */
.reading-progress {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  background: var(--gradient-cta);
  transform: scaleX(0);
  transform-origin: 0 50%;
  z-index: 1200;
  pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: scroll()) {
    .reading-progress {
      animation: reading-progress-grow linear both;
      animation-timeline: scroll(root block);
    }
  }
}
@keyframes reading-progress-grow { to { transform: scaleX(1); } }

/* full-width article hero (static — keeps the LCP path clean) */
.article-hero {
  position: relative;
  padding: var(--space-12) 0 var(--space-10);
  overflow: hidden;
}
.article-hero::before {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse 80% 60% at 50% 0%, rgba(0, 194, 255, 0.10) 0%, transparent 70%);
  pointer-events: none;
}
.article-hero > * { position: relative; }
.article-hero__inner {
  max-width: 820px;
  margin-inline: auto;
  padding-inline: var(--space-4);
  text-align: center;
}
.article-hero .breadcrumb-list { justify-content: center; }
.article-hero h1 { margin: var(--space-4) 0; }
.article-hero__dek {
  font-size: var(--text-xl);
  color: var(--color-text);
  line-height: var(--leading-snug);
  max-width: 680px;
  margin: 0 auto;
}
.article-hero__tags {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-2);
  margin-top: var(--space-6);
}
.tag-pill {
  display: inline-block;
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-pill);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  letter-spacing: 0.02em;
  color: var(--color-emphasis);
  background: rgba(0, 194, 255, 0.08);
  border: 1px solid var(--color-border-accent);
}
.article-hero__meta {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  margin-top: var(--space-6);
}
.article-hero__avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  flex-shrink: 0;
  background-image: var(--gradient-icon-bg);
  border: 1px solid var(--color-border-accent);
  color: var(--color-text-strong);
  font-family: var(--font-display);
  font-weight: var(--weight-bold);
  font-size: var(--text-sm);
}
.article-hero__byline { text-align: left; line-height: 1.35; font-size: var(--text-sm); color: var(--color-text-muted); }
.article-hero__byline strong { display: block; color: var(--color-text); font-weight: var(--weight-semibold); }

/* generic scroll-reveal — below-the-fold only. Base state = visible, so
   no-support / reduced-motion / JS-off all render fully (CLS 0, gate #7). */
@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    .reveal {
      opacity: 0;
      transform: translateY(22px);
      animation: reveal-rise linear both;
      animation-timeline: view();
      animation-range: entry 0% entry 55%;
    }
  }
}
@keyframes reveal-rise { to { opacity: 1; transform: none; } }

/* before/after transformation ledger (replaces the flat comparison table) */
.before-after { max-width: 980px; margin-inline: auto; }
.before-after__heads { display: none; }
@media (min-width: 768px) {
  .before-after__heads {
    display: grid;
    grid-template-columns: 1fr 48px 1fr;
    gap: var(--space-4);
    margin-bottom: var(--space-4);
  }
}
.ba-head {
  font-family: var(--font-display);
  font-weight: var(--weight-semibold);
  font-size: var(--text-sm);
  letter-spacing: 0.05em;
  text-transform: uppercase;
}
.ba-head--before { color: var(--color-text-muted); }
.ba-head--after { color: var(--color-accent-teal); grid-column: 3; }
.before-after__rows {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}
.ba-row {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-3);
  align-items: center;
}
@media (min-width: 768px) {
  .ba-row { grid-template-columns: 1fr 48px 1fr; gap: var(--space-4); }
}
.ba-cell {
  border-radius: var(--radius-lg);
  padding: var(--space-4) var(--space-5);
  border: 1px solid var(--color-border);
  background-color: var(--color-surface-muted);
}
.ba-cell--before { border-left: 3px solid rgba(255, 255, 255, 0.20); }
.ba-cell--after {
  border-left: 3px solid var(--color-accent-teal);
  background-color: rgba(0, 255, 209, 0.04);
}
.ba-cell p { margin: 0; line-height: var(--leading-snug); font-size: var(--text-sm); }
.ba-cell--before p { color: var(--color-text-muted); }
.ba-cell--after p { color: var(--color-text); }
.ba-arrow {
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--color-primary);
  font-size: var(--text-2xl);
  line-height: 1;
}
@media (max-width: 767px) { .ba-arrow { transform: rotate(90deg); margin: calc(var(--space-1) * -1) 0; } }

/* featured pull quote (flagship scale) */
.article-quote { max-width: 860px; margin-inline: auto; padding-inline: var(--space-4); text-align: center; }
.article-quote blockquote { margin: 0; }
.article-quote blockquote p {
  font-family: var(--font-display);
  font-weight: var(--weight-medium);
  font-size: var(--text-3xl);
  line-height: 1.25;
  letter-spacing: -0.01em;
  color: var(--color-text-strong);
  margin: 0;
}
.article-quote blockquote p::before { content: '“'; color: var(--color-primary); }
.article-quote blockquote p::after { content: '”'; color: var(--color-primary); }
.article-quote footer { margin-top: var(--space-5); color: var(--color-text-muted); font-size: var(--text-base); }

/* quote attribution with photo (testimonial cite) */
.article-quote__cite {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  margin-top: var(--space-6);
}
.article-quote__photo {
  width: 64px;
  height: 64px;
  border-radius: 50%;
  object-fit: cover;
  border: 2px solid var(--color-border-accent);
  flex-shrink: 0;
  background: var(--color-surface-elevated);
}
.article-quote__who { text-align: left; line-height: 1.35; }
.article-quote__who strong { display: block; color: var(--color-text-strong); font-weight: var(--weight-semibold); }
.article-quote__who span { color: var(--color-text-muted); font-size: var(--text-sm); }

/* ---- in-prose breakouts (variability for long-form body copy) ---- */

/* indented pull-quote inside the prose flow */
.longform__prose blockquote {
  margin: var(--space-9) 0;
  /* Jake review follow-up: +10px top/bottom (24 to 34px) so the breakout box
     breathes around the quote; horizontal stays space-8. */
  padding: calc(var(--space-6) + 10px) var(--space-8);
  border-left: 3px solid var(--color-primary);
  border-radius: 0 var(--radius-lg) var(--radius-lg) 0;
  background-color: rgba(0, 194, 255, 0.04);
}
.longform__prose blockquote p {
  font-family: var(--font-display);
  font-size: var(--lf-h3, var(--text-xl));
  font-weight: var(--weight-medium);
  font-style: italic;
  color: var(--color-text-strong);
  line-height: 1.45;
}
/* D-040: attribution line under an in-prose pull-quote (when cite is supplied) */
.longform__prose blockquote footer {
  margin-top: var(--space-3);
  font-size: var(--text-sm);
  font-style: normal;
  color: var(--color-text-muted);
}
.longform__prose blockquote footer::before { content: '\\2014 '; }
/* In-prose aside — quieter than body copy, for meta notes / cross-links
   (e.g. "the full numbers live in the case study"). No bg or border so it
   doesn't read as a pull-quote. */
.longform__prose .prose-aside {
  margin: var(--space-6) 0;
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

/* stat breakout — big number that interrupts the column */
.prose-stat {
  margin: var(--space-8) 0;
  padding: var(--space-6);
  text-align: center;
  border-radius: var(--radius-lg);
  background-color: rgba(0, 194, 255, 0.05);
  border: 1px solid var(--color-border-accent);
}
.prose-stat__num {
  display: block;
  font-family: var(--font-display);
  font-weight: var(--weight-black);
  font-size: var(--lf-stat, var(--text-4xl));
  line-height: 1;
  color: var(--color-accent-teal);
  letter-spacing: -0.02em;
}
.prose-stat__cap { display: block; margin-top: var(--space-3); color: var(--color-text-muted); font-size: var(--text-sm); }

/* in-prose figure (Orbit mascot accent) — square ratio box = CLS 0 */
.longform__prose figure { margin: var(--space-8) 0; text-align: center; }
.prose-figure__media {
  display: block;
  width: 100%;
  max-width: 240px;
  margin-inline: auto;
  aspect-ratio: 1 / 1;
}
.prose-figure__media img { display: block; width: 100%; height: 100%; object-fit: contain; }
.longform__prose figcaption {
  margin-top: var(--space-3);
  color: var(--color-text-muted);
  font-size: var(--text-sm);
  font-style: italic;
}

/* insight list — icon + header + body cards (e.g. the 3 case-study surprises) */
.insight-list { list-style: none; margin: var(--space-6) 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-4); }
.insight-item {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-4);
  align-items: start;
  padding: var(--space-5);
  border-radius: var(--radius-lg);
  background-color: var(--color-surface-muted);
  border: 1px solid var(--color-border);
  border-left: 3px solid var(--color-primary);
}
.insight-item__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: var(--radius-md);
  background-image: var(--gradient-icon-bg);
  border: 1px solid var(--color-border-accent);
  color: var(--color-emphasis);
  flex-shrink: 0;
}
.insight-item__icon svg { width: 22px; height: 22px; }
.longform__prose .insight-item h3 {
  margin: 0 0 var(--space-2);
  scroll-margin-top: 0;
  font-family: var(--font-display);
  font-weight: var(--weight-semibold);
  font-size: var(--text-lg);
  color: var(--color-text-strong);
  line-height: 1.2;
}
.insight-item p { margin: 0; color: var(--color-text); line-height: var(--leading-normal); font-size: var(--text-base); }

/* full-width Orbit breakout band */
.orbit-band__inner {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-6);
  align-items: center;
  max-width: 980px;
  margin-inline: auto;
  border-radius: var(--radius-xl);
  padding: var(--space-8);
  background-color: rgba(15, 28, 52, 0.40);
  background-image: radial-gradient(ellipse 70% 80% at 15% 50%, rgba(0, 194, 255, 0.12) 0%, transparent 70%);
  border: 1px solid var(--color-border-accent);
}
@supports not (backdrop-filter: blur(1px)) {
  .orbit-band__inner { background-color: rgba(20, 35, 65, 0.7); }
}
@media (min-width: 768px) {
  .orbit-band__inner { grid-template-columns: 220px 1fr; gap: var(--space-10); padding: var(--space-10) var(--space-12); }
}
.orbit-band__media { display: block; width: 100%; max-width: 220px; margin-inline: auto; aspect-ratio: 1 / 1; }
.orbit-band__media img { display: block; width: 100%; height: 100%; object-fit: contain; }
.orbit-band__title {
  font-family: var(--font-display);
  font-weight: var(--weight-bold);
  font-size: var(--text-2xl);
  color: var(--color-text-strong);
  line-height: 1.2;
  margin: 0 0 var(--space-3);
}
.orbit-band__text { color: var(--color-text); line-height: var(--leading-relaxed); margin: 0; }

/* ============================================================
   Blog design wave (D-222) — cluster nav, linked category pill,
   mid-CTA card rhythm, FAQ accordion, dormant video cards.
   The repeatable longform design system (cf-content-stack ref).
   ============================================================ */

/* linked category pill (post hero) + index cluster pills */
a.tag-pill { text-decoration: none; transition: border-color 150ms ease, background 150ms ease; }
a.tag-pill:hover { border-color: var(--color-border-glow); background: rgba(0, 194, 255, 0.14); }
a.tag-pill:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 2px; }
.cluster-pills {
  list-style: none;
  margin: var(--space-8) auto 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-3);
  max-width: 760px;
}
.cluster-pills li { margin: 0; }

/* featured cluster-hub card on the index (full width above the spoke grid) */
.crosslink-card--featured {
  border-color: var(--color-border-accent);
  background: rgba(15, 28, 52, 0.62);
  margin-bottom: var(--space-4);
}
@media (min-width: 768px) { .crosslink-card--featured { padding: var(--space-8); } }
.crosslink-card--featured .crosslink-card__title { font-size: var(--text-xl); }
.crosslink-card__eyebrow--hub { color: var(--color-accent-teal); }

/* mid-post CTA card — neutralize prose-h3 margins inside .card, set internal rhythm */
.longform__prose .card h3 {
  margin: 0;
  scroll-margin-top: 0;
  font-size: var(--lf-h3, var(--text-xl));
}
.longform__prose .card h3 + p { margin-top: var(--space-3); }
.longform__prose .card p + p { margin-top: var(--space-4); }

/* FAQ accordion — native details/summary, keyboard-accessible with no JS */
.longform__prose details.longform-faq { border-bottom: 1px solid var(--color-border); }
.longform__prose details.longform-faq:first-of-type { border-top: 1px solid var(--color-border); }
.longform__prose > details.longform-faq + details.longform-faq { margin-top: 0; }
.longform__prose details.longform-faq > summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-4) 0;
  font-family: var(--font-display);
  font-weight: var(--weight-semibold);
  font-size: var(--text-lg);
  color: var(--color-text-strong);
  line-height: 1.35;
}
.longform__prose details.longform-faq > summary::-webkit-details-marker { display: none; }
.longform__prose details.longform-faq > summary::after {
  content: '';
  flex-shrink: 0;
  width: 11px;
  height: 11px;
  border-right: 2px solid var(--color-primary);
  border-bottom: 2px solid var(--color-primary);
  transform: rotate(45deg);
  transition: transform 200ms ease;
}
.longform__prose details.longform-faq[open] > summary::after { transform: rotate(-135deg); }
@media (prefers-reduced-motion: reduce) {
  .longform__prose details.longform-faq > summary::after { transition: none; }
}
.longform__prose details.longform-faq > summary:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
  border-radius: var(--radius-md);
}
.longform__prose details.longform-faq > div { padding: 0 0 var(--space-4); }
.longform__prose details.longform-faq > div p {
  margin: 0;
  font-size: var(--text-base);
  color: var(--color-text);
  line-height: var(--leading-relaxed);
}

/* figure lightbox (D-223) — click an infographic to view it full-size. The
   trigger button is JS-created (LONGFORM_LIGHTBOX_JS) and styled to render the
   wrapped img identically to the unwrapped figure (no shift on enhance). */
.lightbox-trigger {
  display: block;
  width: 100%;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  cursor: zoom-in;
}
.lightbox-trigger:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 3px;
  border-radius: var(--radius-lg);
}
dialog.lightbox {
  padding: 0;
  border: 0;
  background: transparent;
  max-width: 96vw;
  max-height: 92vh;
  overflow: visible;
}
dialog.lightbox::backdrop { background: rgba(2, 8, 16, 0.88); }
.lightbox__scroller {
  overflow: auto;
  max-width: 96vw;
  max-height: 86vh;
  border-radius: var(--radius-lg);
  border: 1px solid var(--color-border-accent);
  background: var(--color-surface-elevated);
  scrollbar-width: thin;
  scrollbar-color: var(--color-border-glow) transparent;
}
.lightbox__scroller::-webkit-scrollbar { width: 8px; height: 8px; }
.lightbox__scroller::-webkit-scrollbar-track { background: transparent; }
.lightbox__scroller::-webkit-scrollbar-thumb {
  background: var(--color-border-glow);
  border-radius: var(--radius-pill);
}
.lightbox__img { display: block; }
.lightbox__close {
  position: absolute;
  top: calc(-1 * (44px + var(--space-2)));
  right: 0;
  width: 44px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  border: 1px solid var(--color-border-accent);
  background: var(--color-surface-elevated);
  color: var(--color-text-strong);
  font-size: var(--text-2xl);
  line-height: 1;
  cursor: pointer;
}
.lightbox__close:hover { border-color: var(--color-border-glow); }
.lightbox__close:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 2px; }
@media (prefers-reduced-motion: no-preference) {
  dialog.lightbox[open] { animation: lightbox-in 160ms ease; }
}
@keyframes lightbox-in {
  from { opacity: 0; transform: scale(0.985); }
  to { opacity: 1; transform: none; }
}

/* video cards (DORMANT, D-H) — external links to real channel videos, no iframe =
   zero CWV cost. Rendered only when a post supplies videos[]. */
.video-grid { display: grid; grid-template-columns: 1fr; gap: var(--space-4); margin: var(--space-6) 0; }
@media (min-width: 640px) { .video-grid { grid-template-columns: repeat(2, 1fr); } }
.video-card {
  display: block;
  border-radius: var(--radius-lg);
  overflow: hidden;
  border: 1px solid var(--color-border);
  background: rgba(15, 28, 52, 0.45);
  text-decoration: none;
  color: var(--color-text);
  transition: border-color 200ms ease, transform 200ms ease;
}
.video-card:hover, .video-card:focus-visible { border-color: var(--color-border-accent); transform: translateY(-2px); outline: none; }
.video-card:focus-visible { outline: 2px solid var(--color-primary); outline-offset: 2px; } /* D-226 a11y: motion-independent focus ring */
.video-card__thumb { display: block; width: 100%; aspect-ratio: 16 / 9; object-fit: cover; background: var(--color-surface-elevated); }
.video-card__body { padding: var(--space-4); }
.video-card__title { font-family: var(--font-display); font-weight: var(--weight-semibold); font-size: var(--text-base); color: var(--color-text-strong); margin: 0; line-height: 1.3; }
.video-card__outlet { display: block; margin-top: var(--space-2); font-size: var(--text-sm); color: var(--color-text-muted); }
