﻿/* ============================================
   Elvisto Premium Layout & Design System
   ============================================ */

/* ────────────────────────────────────────────────────────────────
   Shared empty-state animations
   Used by <SaEmptyState /> component and any hand-rolled empty
   panels. Keep here so every page can `class="sa-empty-…"` without
   duplicating keyframes into scoped <style> blocks.
   ──────────────────────────────────────────────────────────────── */
.sa-empty-panel {
  text-align: center;
  padding: 56px 24px;
  max-width: 480px;
  margin-left: auto;
  margin-right: auto;
}
.sa-empty-icon {
  width: 64px;
  height: 64px;
  border-radius: 16px;
  background: linear-gradient(135deg, rgba(37, 99, 255, 0.10), rgba(6, 214, 209, 0.10));
  color: #2563FF;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 16px;
  animation: sa-empty-float 3s ease-in-out infinite, sa-empty-glow 2.6s ease-out infinite;
}
.sa-empty-icon svg { animation: sa-empty-icon-pulse 2s ease-in-out infinite; }
.sa-empty-title {
  font-size: 18px;
  font-weight: 700;
  color: #0f172a;
  margin: 0 0 6px;
}
.sa-empty-desc {
  font-size: 14px;
  color: #64748b;
  line-height: 1.55;
  margin: 0 0 20px;
}
.sa-empty-actions {
  display: inline-flex;
  gap: 10px;
  flex-wrap: wrap;
  justify-content: center;
}

/* Small variant — for inline empty states (tables, dashboards, lists). */
.sa-empty-panel-sm { padding: 32px 20px; max-width: 380px; }
.sa-empty-panel-sm .sa-empty-icon { width: 48px; height: 48px; border-radius: 12px; }
.sa-empty-panel-sm .sa-empty-title { font-size: 15px; }
.sa-empty-panel-sm .sa-empty-desc { font-size: 13px; margin-bottom: 14px; }

@keyframes sa-empty-float {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-6px); }
}
@keyframes sa-empty-icon-pulse {
  0%, 100% { opacity: 0.9; }
  50%      { opacity: 1; }
}
@keyframes sa-empty-glow {
  0%, 100% { box-shadow: 0 0 0 0 rgba(37, 99, 255, 0.15); }
  50%      { box-shadow: 0 0 0 12px rgba(37, 99, 255, 0); }
}

/* Respect user's OS-level reduced-motion preference — accessibility. */
@media (prefers-reduced-motion: reduce) {
  .sa-empty-icon,
  .sa-empty-icon svg {
    animation: none !important;
  }
}


/* ────────────────────────────────────────────────────────────────
   Shared error-state panel — mirrors SaEmptyState layout but with
   a warning/error visual language (amber icon chip, no floating
   animation). Used by <SaErrorState /> and <SaLoadState /> to make
   failed data loads visually distinct from genuine empty states.
   ──────────────────────────────────────────────────────────────── */
.sa-error-panel {
  text-align: center;
  padding: 56px 24px;
  max-width: 480px;
  margin-left: auto;
  margin-right: auto;
}
.sa-error-icon {
  width: 64px;
  height: 64px;
  border-radius: 16px;
  background: linear-gradient(135deg, rgba(180, 83, 9, 0.10), rgba(212, 24, 61, 0.10));
  color: #b45309;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 16px;
}
.sa-error-title {
  font-size: 18px;
  font-weight: 700;
  color: #0f172a;
  margin: 0 0 6px;
}
.sa-error-desc {
  font-size: 14px;
  color: #4b5563;
  line-height: 1.55;
  margin: 0 0 20px;
}
.sa-error-actions {
  display: inline-flex;
  gap: 10px;
  flex-wrap: wrap;
  justify-content: center;
}
.sa-error-panel-sm { padding: 32px 20px; max-width: 380px; }
.sa-error-panel-sm .sa-error-icon { width: 48px; height: 48px; border-radius: 12px; }
.sa-error-panel-sm .sa-error-title { font-size: 15px; }
.sa-error-panel-sm .sa-error-desc { font-size: 13px; margin-bottom: 14px; }

/* Loading fallback used by <SaLoadState /> when no custom LoadingContent is given. */
.sa-loadstate-loading {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 48px 24px;
  min-height: 160px;
}


/* --- CSS Custom Properties --- */
:root {
  /* Brand colors — aligned to Figma design system */
  --sa-primary: #2563FF;
  --sa-primary-dark: #1C4CC4;
  --sa-primary-light: rgba(37, 99, 255, 0.1);
  --sa-cyan: #06D6D1;
  --sa-purple: #7e22ce;         /* was #9333ea (3.5:1 on white — fail) → now 5.5:1 ✓ AA */
  --sa-purple-light: rgba(147, 51, 234, 0.1);
  --sa-success: #047857;        /* was #10b981 (2.5:1 on white — fail) → now 6.1:1 ✓ AA */
  --sa-warning: #b45309;        /* was #f97316 (2.8:1 on white — fail) → now 4.6:1 ✓ AA */
  --sa-error: #d4183d;          /* 6.4:1 on white — already passes ✓ */

  /* Gradients — updated to new primary */
  --sa-gradient-hero: linear-gradient(135deg, #1C4CC4 0%, #2563FF 40%, #06D6D1 100%);
  --sa-gradient-sidebar: linear-gradient(160deg, #1d4ed8, #2563eb 50%, #0a5e8c);
  --sa-gradient-btn: linear-gradient(135deg, #2563eb, #1d4ed8);
  --sa-gradient-icon: linear-gradient(135deg, #2563eb, #06D6D1);
  --sa-gradient-ai: linear-gradient(135deg, #9333ea, #2563eb);

  /* Text colors — chosen to meet WCAG AA (4.5:1) on white surfaces. Previously
     --sa-text-muted was #717182 which came in at 4.49:1 (just under AA); bumping
     it slightly darker fixes ~15 contrast-ratio failures flagged by axe-core
     across the app without visibly changing the design. */
  --sa-text-primary: #111827;
  --sa-text-secondary: #1e293b;
  --sa-text-tertiary: #374151;
  --sa-text-muted: #575866;      /* was #717182 — now ~7.4:1 on white ✓ WCAG AA */
  --sa-text-faint: #4b5563;      /* was #6b7280 — now ~8.3:1 on white ✓ WCAG AA */
  --sa-text-placeholder: #6b7280; /* was #9ca3af — now 4.8:1 on white ✓ WCAG AA (placeholders only) */

  /* Surfaces */
  --sa-surface-dark: #1a1a2e;
  --sa-surface-light: #fafafa;
  --sa-border: rgba(0, 0, 0, 0.1);
  --sa-input-bg: #f3f3f5;

  /* Severity colors — Figma 10% opacity pattern. Foregrounds tuned to pass WCAG AA
     (≥4.5:1) on both the light tinted background AND plain white text usage. */
  --sa-severity-critical-bg: rgba(212, 24, 61, 0.1);
  --sa-severity-critical: #d4183d;                            /* 6.4:1 on white ✓ */
  --sa-severity-critical-border: rgba(212, 24, 61, 0.2);
  --sa-severity-warning-bg: rgba(249, 115, 22, 0.1);
  --sa-severity-warning: #b45309;                             /* was #f97316 → now 4.6:1 ✓ */
  --sa-severity-warning-border: rgba(249, 115, 22, 0.2);
  --sa-severity-good-bg: rgba(16, 185, 129, 0.1);
  --sa-severity-good: #047857;                                /* was #10b981 → now 6.1:1 ✓ */
  --sa-severity-good-border: rgba(16, 185, 129, 0.2);
  --sa-severity-info-bg: rgba(37, 99, 235, 0.1);
  /* Text color darkened from #2563eb -> #1d4ed8 to pass WCAG AA (was 4.48:1
     against the light-blue background, needed ≥4.5:1; now ~5.9:1). Used
     across .sa-badge-info, info banners, and .sa-severity-info-* utilities. */
  --sa-severity-info: #1d4ed8;
  --sa-severity-info-border: rgba(37, 99, 235, 0.2);

  /* Radius — Figma standard */
  --sa-radius-card: 12px;
  --sa-radius-btn: 10px;
  --sa-radius-input: 10px;
  --sa-radius-badge: 9999px;
  --sa-radius-icon: 10px;
  --sa-radius-sm: 8px;

  /* Shadows — simplified from Figma */
  --sa-shadow-card: none;
  --sa-shadow-hover: 0 4px 12px rgba(0, 0, 0, 0.08);
  --sa-shadow-dropdown: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1);
  --sa-shadow-modal: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1);

  --sa-nav-height: 76px;      /* was 64 - see the NAV BAR block near the end */
}

/* ============================================
   Landing Navbar
   ============================================ */
.sa-landing-nav {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 1100;
  background: rgba(255, 255, 255, 0.95);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border-bottom: 1px solid rgba(0, 0, 0, 0.08);
  height: var(--sa-nav-height);
  display: flex;
  align-items: center;
  padding: 0 24px;
}
.sa-landing-nav .sa-nav-inner {
  display: flex;
  align-items: center;
  width: 100%;
  max-width: 1200px;
  margin: 0 auto;
}
.sa-landing-nav .sa-nav-links {
  display: flex;
  align-items: center;
  gap: 4px;
  margin-left: auto;
}
.sa-landing-nav .sa-nav-link {
  padding: 8px 16px;
  font-size: 14px;
  font-weight: 500;
  color: var(--sa-text-tertiary);
  text-decoration: none;
  border-radius: 8px;
  transition: color 0.2s, background 0.2s;
}
.sa-landing-nav .sa-nav-link:hover {
  color: var(--sa-primary);
  background: rgba(37, 99, 235, 0.06);
}
.sa-nav-divider {
  width: 1px;
  height: 24px;
  background: #e5e7eb;
  margin: 0 8px;
}
.sa-nav-mobile-btn {
  display: none;
  background: none;
  border: none;
  cursor: pointer;
  padding: 8px;
  margin-left: auto;
  color: var(--sa-text-primary);
}
.sa-mobile-menu {
  position: fixed;
  top: var(--sa-nav-height);
  left: 0;
  right: 0;
  z-index: 1099;
  background: white;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.sa-mobile-menu a, .sa-mobile-menu button {
  display: block;
  width: 100%;
  padding: 12px 16px;
  font-size: 15px;
  text-align: left;
  border: none;
  background: none;
  cursor: pointer;
  text-decoration: none;
  color: var(--sa-text-tertiary);
  border-radius: 8px;
}
.sa-mobile-menu a:hover, .sa-mobile-menu button:hover {
  background: rgba(37, 99, 235, 0.06);
}

@media (max-width: 768px) {
  .sa-landing-nav .sa-nav-links { display: none; }
  .sa-nav-mobile-btn { display: block; }
}

/* ============================================
   Premium Buttons
   ============================================ */
.sa-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  font-family: inherit;
  font-weight: 600;
  font-size: 15px;
  border: none;
  cursor: pointer;
  transition: all 0.2s ease;
  text-decoration: none;
  line-height: 1;
}
/* Keep icons perfectly centered & never squished inside any button.
   margin auto absorbs cross-axis free space to vertically center the icon;
   !important defends against framework/global svg margin resets. */
.sa-btn svg {
  display: block;
  flex-shrink: 0;
  margin-top: auto !important;
  margin-bottom: auto !important;
}
/* Primary — flat solid fill (Figma pattern) */
.sa-btn-primary {
  background: var(--sa-primary);
  color: white;
  padding: 12px 24px;
  border-radius: var(--sa-radius-btn);
}
.sa-btn-primary:hover {
  opacity: 0.9;
}
.sa-btn-primary:disabled, .sa-btn-primary.disabled {
  background: #cbd5e1;
  color: #6b7280;
  cursor: not-allowed;
  opacity: 1;
}
/* ── Disabled affordance, global safety net ──────────────────────────────────
   Only .sa-btn-primary used to define one, so a disabled secondary/outline/ghost
   button still looked fully interactive and silently did nothing on click — worse
   feedback than no gating at all.

   The icon variants (.sa-action-btn / .sa-row-btn) DO define :disabled, but only
   inside the <style> block of whichever page happens to use them — and those blocks
   are duplicated per page. ProjectSchedulesList copied .sa-row-btn's hover rule and
   dropped the :disabled one, reintroducing the same bug on Project Detail. Declaring
   it globally means a new page can't miss it; a page block can still override. */
.sa-btn-secondary:disabled, .sa-btn-secondary.disabled,
.sa-btn-outline:disabled,   .sa-btn-outline.disabled,
.sa-btn-outline-brand:disabled, .sa-btn-outline-brand.disabled,
.sa-btn-ghost:disabled,     .sa-btn-ghost.disabled,
.sa-action-btn:disabled,    .sa-action-btn.disabled,
.sa-row-btn:disabled,       .sa-row-btn.disabled {
  opacity: 0.45;
  filter: grayscale(1);
  cursor: not-allowed;
}
.sa-btn-secondary:disabled:hover,
.sa-btn-outline:disabled:hover,
.sa-btn-outline-brand:disabled:hover,
.sa-btn-ghost:disabled:hover,
.sa-action-btn:disabled:hover,
.sa-row-btn:disabled:hover {
  opacity: 0.45;
  filter: grayscale(1);
  transform: none;
  box-shadow: none;
}
/* Secondary — gray fill */
.sa-btn-secondary {
  background: var(--sa-input-bg);
  color: var(--sa-text-primary);
  padding: 12px 24px;
  border-radius: var(--sa-radius-btn);
}
.sa-btn-secondary:hover {
  background: #e5e5e5;
}
/* White — for dark backgrounds */
.sa-btn-white {
  background: white;
  color: var(--sa-primary);
  padding: 12px 24px;
  border-radius: var(--sa-radius-btn);
}
.sa-btn-white:hover {
  opacity: 0.9;
}
/* Outline — border only (light bg) */
.sa-btn-outline {
  background: transparent;
  color: white;
  padding: 11px 24px;
  border-radius: var(--sa-radius-btn);
  border: 1px solid rgba(255, 255, 255, 0.4);
}
.sa-btn-outline:hover {
  background: rgba(255, 255, 255, 0.1);
  border-color: rgba(255, 255, 255, 0.6);
}
/* Outline brand — border only (brand color) */
.sa-btn-outline-brand {
  background: transparent;
  color: var(--sa-primary);
  padding: 11px 24px;
  border-radius: var(--sa-radius-btn);
  border: 1px solid var(--sa-border);
}
.sa-btn-outline-brand:hover {
  background: rgba(37, 99, 235, 0.06);
  border-color: var(--sa-primary);
}
/* A disabled outline-brand button must not light up on hover. The shared disabled:hover
   rule above resets opacity and transform but leaves the fill alone, so this one needs its
   own reset: without it Export on the Schedules page tinted and took a brand border while
   disabled, which read as clickable. */
.sa-btn-outline-brand:disabled:hover {
  background: transparent;
  border-color: var(--sa-border);
}
/* Ghost — no bg */
.sa-btn-ghost {
  background: transparent;
  color: var(--sa-text-tertiary);
  padding: 12px 24px;
  border-radius: var(--sa-radius-btn);
}
.sa-btn-ghost:hover {
  background: rgba(0, 0, 0, 0.04);
  color: var(--sa-text-primary);
}
/* Destructive */
.sa-btn-destructive {
  background: var(--sa-error);
  color: white;
  padding: 12px 24px;
  border-radius: var(--sa-radius-btn);
}
.sa-btn-destructive:hover {
  opacity: 0.9;
}
/* Size modifiers */
.sa-btn-sm {
  padding: 8px 16px;
  font-size: 14px;
}
.sa-btn-lg {
  padding: 14px 32px;
  font-size: 16px;
}

/* ============================================
   Hero Section
   ============================================ */
.sa-hero {
  background: var(--sa-gradient-hero);
  padding: 140px 24px 100px;
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  overflow: hidden;
}
.sa-hero-inner {
  max-width: 1200px;
  width: 100%;
  display: flex;
  align-items: center;
  gap: 60px;
}
.sa-hero-content {
  max-width: 560px;
  flex-shrink: 0;
}
.sa-hero-badge {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: rgba(255, 255, 255, 0.15);
  border: 1px solid rgba(255, 255, 255, 0.25);
  border-radius: var(--sa-radius-badge);
  padding: 6px 16px;
  font-size: 13px;
  font-weight: 500;
  color: rgba(255, 255, 255, 0.9);
  margin-bottom: 24px;
}
.sa-hero h1 {
  font-size: 3rem;
  font-weight: 800;
  color: white;
  line-height: 1.15;
  margin: 0 0 20px;
  letter-spacing: -0.02em;
}
.sa-hero-subtitle {
  font-size: 1.15rem;
  color: rgba(255, 255, 255, 0.85);
  line-height: 1.6;
  margin-bottom: 32px;
}
.sa-hero-buttons {
  display: flex;
  gap: 12px;
  margin-bottom: 20px;
}
.sa-hero-note {
  font-size: 13px;
  color: rgba(255, 255, 255, 0.6);
}

/* Trust logos row */
.sa-trust-logos {
  margin-top: 28px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 12px;
}
.sa-trust-label {
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: rgba(255, 255, 255, 0.4);
  font-weight: 500;
}
.sa-trust-logos-row {
  display: flex;
  align-items: center;
  gap: 24px;
  flex-wrap: wrap;
}
.sa-trust-logo {
  font-size: 15px;
  font-weight: 700;
  color: rgba(255, 255, 255, 0.35);
  letter-spacing: 0.02em;
  transition: color 0.2s;
}
.sa-trust-logo:hover {
  color: rgba(255, 255, 255, 0.6);
}
@media (max-width: 768px) {
  .sa-trust-logos-row {
    gap: 16px;
  }
  .sa-trust-logo {
    font-size: 13px;
  }
}

.sa-hero-visual {
  flex: 1;
  display: flex;
  justify-content: center;
  position: relative;
}

/* Dashboard Mock */
.sa-dashboard-mock {
  width: 420px;
  background: white;
  border-radius: var(--sa-radius-card);
  overflow: hidden;
  box-shadow: 0 24px 80px rgba(0, 0, 0, 0.3);
  position: relative;
}
.sa-mock-header {
  background: #f8f9fa;
  padding: 12px 16px;
  display: flex;
  align-items: center;
  gap: 8px;
  border-bottom: 1px solid #eee;
}
.sa-mock-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
}
.sa-mock-url {
  flex: 1;
  height: 24px;
  background: #e8ecf4;
  border-radius: 8px;
  margin-left: 8px;
  display: flex;
  align-items: center;
  padding: 0 10px;
  font-size: 11px;
  color: var(--sa-text-faint);
}
.sa-mock-body {
  padding: 24px;
  text-align: center;
}
.sa-mock-score-ring {
  width: 120px;
  height: 120px;
  border-radius: 50%;
  border: 6px solid #e8ecf4;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0 auto 20px;
  position: relative;
}
.sa-mock-score-fill {
  position: absolute;
  inset: -6px;
  border-radius: 50%;
  border: 6px solid transparent;
  border-top-color: var(--sa-primary);
  border-right-color: var(--sa-primary);
  border-bottom-color: var(--sa-primary);
  transform: rotate(-30deg);
}
.sa-mock-score-text {
  font-size: 2rem;
  font-weight: 800;
  color: var(--sa-primary);
}
.sa-mock-score-label {
  font-size: 12px;
  color: var(--sa-text-faint);
  margin-top: 2px;
}
.sa-mock-grade {
  font-size: 14px;
  font-weight: 700;
  color: var(--sa-success);
}
.sa-mock-metrics {
  display: flex;
  gap: 12px;
  margin-top: 20px;
}
.sa-mock-metric {
  flex: 1;
  background: var(--sa-surface-light);
  border-radius: 12px;
  padding: 12px 8px;
  text-align: center;
}
.sa-mock-metric-value {
  font-size: 1.1rem;
  font-weight: 700;
  color: var(--sa-text-primary);
}
.sa-mock-metric-label {
  font-size: 11px;
  color: var(--sa-text-faint);
  margin-top: 2px;
}


/* ── Hero card deck ────────────────────────────────────────────────────────────
   Five separate cards on a horizontal track — each one mirrors a real page of the
   product (dashboard, audit, seo-health, issues, projects) with that page's real
   numbers. The active card sits centred at full scale; its neighbours peek in
   dimmed and scaled back, so the motion reads as cards moving past each other.
   Only .sa-deck-track transforms — the cards never reflow. */
.sa-deck {
  position: relative;
  width: 560px;
  max-width: 100%;
}
.sa-deck-viewport {
  overflow: hidden;
  /* Feather the edges so the peeking cards fade out rather than being cut by a
     hard boundary — this is most of what sells the depth. */
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 13%, #000 87%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 13%, #000 87%, transparent);
  padding: 16px 0 20px;
}
.sa-deck-track {
  display: flex;
  gap: 20px;
  transition: transform 0.62s cubic-bezier(0.65, 0, 0.35, 1);
  will-change: transform;
}
.sa-deck-card {
  position: relative;
  flex: 0 0 400px;
  width: 400px;
  height: 396px;
  background: #fff;
  border: 1px solid rgba(15, 23, 42, 0.06);
  border-radius: 20px;
  padding: 22px 24px 18px;
  display: flex;
  flex-direction: column;
  gap: 16px;
  text-align: left;
  overflow: hidden;
  box-shadow: 0 8px 26px rgba(8, 18, 45, 0.16);
  opacity: 0.34;
  transform: scale(0.88);
  transition: opacity 0.62s ease, transform 0.62s cubic-bezier(0.65, 0, 0.35, 1),
              box-shadow 0.62s ease;
}
.sa-deck-card.active {
  opacity: 1;
  transform: scale(1);
  box-shadow: 0 30px 70px rgba(8, 18, 45, 0.32), 0 2px 8px rgba(8, 18, 45, 0.1);
}
/* Accent rail across the top — gives each card its own identity at a glance. */
.sa-deck-accent {
  position: absolute;
  inset: 0 0 auto 0;
  height: 4px;
}

/* Card header — icon chip, page title + route, status badge */
.sa-deck-head {
  display: flex;
  align-items: center;
  gap: 12px;
  padding-bottom: 15px;
  border-bottom: 1px solid #f1f3f8;
}
.sa-deck-icon {
  width: 34px;
  height: 34px;
  border-radius: 12px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.sa-deck-titles { flex: 1; display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.sa-deck-title {
  font-size: 15px;
  font-weight: 700;
  color: var(--sa-text-primary);
  letter-spacing: -0.015em;
  line-height: 1.2;
}
.sa-deck-route {
  font-size: 11px;
  color: var(--sa-text-faint);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.sa-deck-badge {
  font-size: 11px;
  font-weight: 700;
  padding: 5px 11px;
  border-radius: 999px;
  flex-shrink: 0;
}
.sa-deck-badge.sa-good    { color: #15803d; background: rgba(22, 163, 74, 0.12); }
.sa-deck-badge.sa-warn    { color: #b45309; background: rgba(245, 158, 11, 0.15); }
.sa-deck-badge.sa-ai      { color: #0e7490; background: rgba(6, 214, 209, 0.15); }
.sa-deck-badge.sa-neutral { color: #475569; background: rgba(71, 85, 105, 0.1); }

.sa-deck-body {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 14px;
  min-height: 0;
}
.sa-deck-body-center { justify-content: center; align-items: center; gap: 18px; }
.sa-deck-foot {
  font-size: 11.5px;
  color: var(--sa-text-faint);
  padding-top: 13px;
  border-top: 1px dashed #eef0f5;
}

/* Dashboard stat grid */
.sa-deck-grid {
  flex: 1;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}
.sa-deck-stat {
  background: var(--sa-surface-light);
  border: 1px solid #f1f3f8;
  border-radius: 12px;
  padding: 14px 14px 12px;
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.sa-deck-stat-val {
  font-size: 1.75rem;
  font-weight: 800;
  line-height: 1.05;
  letter-spacing: -0.03em;
  color: var(--sa-text-primary);
}
.sa-deck-stat-val span { font-size: 0.95rem; font-weight: 600; color: var(--sa-text-faint); }
.sa-deck-stat-lbl { font-size: 11px; color: var(--sa-text-faint); margin-top: 5px; }

/* Generic row list (seo-health priorities, project rows) */
.sa-deck-list { display: flex; flex-direction: column; gap: 7px; }
.sa-deck-li {
  display: flex;
  align-items: center;
  gap: 9px;
  font-size: 12.5px;
  padding: 8px 11px;
  border-radius: 8px;
  background: var(--sa-surface-light);
}
.sa-deck-li-dot { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; }
.sa-deck-li-txt { flex: 1; color: var(--sa-text-primary); font-weight: 500; }
.sa-deck-li-meta { font-size: 11px; color: var(--sa-text-faint); flex-shrink: 0; }

.sa-deck-proj {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 12px;
  border-radius: 8px;
  background: var(--sa-surface-light);
}
.sa-deck-proj-name {
  flex: 1;
  font-size: 12.5px;
  font-weight: 500;
  color: var(--sa-text-primary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.sa-deck-proj-score {
  font-size: 12px;
  font-weight: 800;
  padding: 3px 10px;
  border-radius: 999px;
  flex-shrink: 0;
}
.sa-deck-proj-score.sa-s-good { color: #15803d; background: rgba(22, 163, 74, 0.13); }
.sa-deck-proj-score.sa-s-mid  { color: #b45309; background: rgba(245, 158, 11, 0.15); }

/* Optimizer deliverables — a check rail instead of a severity dot. */
.sa-deck-chk {
  width: 17px;
  height: 17px;
  border-radius: 50%;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 9.5px;
  font-weight: 700;
  color: #15803d;
  background: rgba(22, 163, 74, 0.15);
}

/* Schedule summary strip — the cadence line the /schedules page leads with. */
.sa-deck-sched {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 12px 14px;
  border-radius: 12px;
  background: var(--sa-surface-light);
  border: 1px solid #f1f3f8;
}
.sa-deck-sched-site {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--sa-text-primary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.sa-deck-sched-when { font-size: 11px; color: var(--sa-primary); font-weight: 600; }

/* Issue split by category — the three numbers sum to the badge total. */
.sa-deck-cats { display: flex; gap: 9px; }
.sa-deck-cat {
  flex: 1;
  background: var(--sa-surface-light);
  border: 1px solid #f1f3f8;
  border-radius: 12px;
  padding: 10px 6px;
  text-align: center;
}
.sa-deck-cat-val {
  font-size: 1.2rem;
  font-weight: 800;
  line-height: 1;
  color: var(--sa-text-primary);
  letter-spacing: -0.02em;
}
.sa-deck-cat-lbl { font-size: 10.5px; color: var(--sa-text-faint); margin-top: 5px; }

/* Ring + metrics sized for the larger card */
.sa-deck-card .sa-mock-score-ring { width: 132px; height: 132px; margin: 0 auto 4px; }
.sa-deck-card .sa-mock-score-text { font-size: 2.3rem; letter-spacing: -0.03em; }
.sa-deck-card .sa-mock-grade { font-size: 12px; }
.sa-deck-card .sa-mock-metrics { width: 100%; margin: 0; gap: 9px; }
.sa-deck-card .sa-mock-metric { padding: 11px 6px; border: 1px solid #f1f3f8; }
.sa-deck-card .sa-mock-metric-value { font-size: 1.15rem; }
.sa-deck-card .sa-mock-metric-label { font-size: 10.5px; }
.sa-deck-card .sa-mock-ai-quote { font-size: 12.5px; padding: 12px 14px; }
.sa-deck-card .sa-mock-sev { gap: 13px; }
.sa-deck-card .sa-mock-sev-label { width: 82px; font-size: 12px; }
.sa-deck-card .sa-mock-bar { height: 7px; }
.sa-deck-card .sa-mock-worst { padding: 10px 12px; }
.sa-deck-card .sa-mock-worst-url { font-size: 12px; }

@media (max-width: 1180px) {
  .sa-deck { width: 460px; }
}


/* ── Floating glass cards ──────────────────────────────────────────────────────
   Three decorative satellites around the deck. Two layers per card: .sa-float
   owns position and the entrance fade/scale, .sa-float-inner owns the glass and
   the endless drift — separating them lets both animations run without fighting
   over `transform`. Each card gets its own size, blur, opacity, rotation and
   drift duration, which is what produces the parallax and the sense of depth.
   Never interactive: the carousel underneath owns every click. */
.sa-float {
  position: absolute;
  z-index: 3;
  pointer-events: none;
  opacity: 0;
  animation: sa-float-in 0.9s cubic-bezier(0.22, 0.7, 0.3, 1) forwards;
}
@keyframes sa-float-in {
  from { opacity: 0; transform: scale(0.94) translateY(10px); }
  to   { opacity: 1; transform: scale(1) translateY(0); }
}

.sa-float-inner {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 13px 16px;
  border-radius: 16px;
  color: #fff;
  /* Smoked glass, not white glass. These cards necessarily overlap the white
     deck card — there is no room for three of them in the gutters — and white
     translucency would put white text on a white surface. A dark tint keeps the
     type legible over both the blue field and the card, and reads richer. */
  background: rgba(9, 20, 48, 0.52);
  -webkit-backdrop-filter: blur(22px) saturate(150%);
  backdrop-filter: blur(22px) saturate(150%);
  border: 1px solid rgba(255, 255, 255, 0.16);
  /* Outer drop + a 1px inner highlight along the top edge — the highlight is
     what makes the surface read as glass rather than flat translucency. */
  box-shadow: 0 18px 44px rgba(3, 12, 38, 0.34),
              inset 0 1px 0 rgba(255, 255, 255, 0.16);
  will-change: transform;
}
.sa-float-stack {
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
  padding: 16px 20px 17px;
  /* Its content is short ("78/100"), so without a floor this card renders much
     smaller than the other two and breaks the size hierarchy. */
  min-width: 138px;
}

.sa-float-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.sa-float-title {
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: rgba(255, 255, 255, 0.96);
  white-space: nowrap;
}
.sa-float-sub {
  font-size: 10.5px;
  font-weight: 500;
  color: rgba(255, 255, 255, 0.62);
  white-space: nowrap;
}
.sa-float-metric {
  font-size: 1.65rem;
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.03em;
  color: #fff;
}
.sa-float-metric span {
  font-size: 0.8rem;
  font-weight: 500;
  color: rgba(255, 255, 255, 0.55);
}
.sa-float-ico {
  width: 26px;
  height: 26px;
  border-radius: 8px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  color: rgba(255, 255, 255, 0.9);
  background: rgba(255, 255, 255, 0.14);
  border: 1px solid rgba(255, 255, 255, 0.16);
}
.sa-float-ico-up { color: #86efac; background: rgba(134, 239, 172, 0.16); border-color: rgba(134, 239, 172, 0.22); }

/* Status indicator — a soft breathing halo, not a hard blink. */
.sa-float-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex-shrink: 0;
  background: #4ade80;
  box-shadow: 0 0 0 3px rgba(74, 222, 128, 0.18), 0 0 12px rgba(74, 222, 128, 0.5);
  animation: sa-float-breathe 3.4s ease-in-out infinite;
}
@keyframes sa-float-breathe {
  0%, 100% { box-shadow: 0 0 0 3px rgba(74, 222, 128, 0.16), 0 0 10px rgba(74, 222, 128, 0.42); }
  50%      { box-shadow: 0 0 0 5px rgba(74, 222, 128, 0.07), 0 0 16px rgba(74, 222, 128, 0.62); }
}

/* Placement + per-card depth. Offsets stay inside the 60px hero gutter so the
   cards never crowd the headline, and sit over the deck's peek zone rather than
   the centred card. */
.sa-float-1 { top: -30px; left: -52px; animation-delay: 0.25s; }
.sa-float-1 .sa-float-inner { animation: sa-float-drift-1 12s ease-in-out infinite; }

.sa-float-2 { top: 150px; right: -12px; animation-delay: 0.45s; }
.sa-float-2 .sa-float-inner {
  animation: sa-float-drift-2 15s ease-in-out infinite;
  /* Nearest card: crisper, brighter, heavier shadow. */
  background: rgba(9, 20, 48, 0.62);
  -webkit-backdrop-filter: blur(26px) saturate(165%);
  backdrop-filter: blur(26px) saturate(165%);
  box-shadow: 0 26px 62px rgba(3, 12, 38, 0.44),
              inset 0 1px 0 rgba(255, 255, 255, 0.22);
}

/* Sits below the card rather than across it: at bottom:30px it covered the first
   56px of the footer line, and there is no room to shift it left without
   reaching the headline column. */
.sa-float-3 { bottom: -22px; left: -46px; animation-delay: 0.65s; }
.sa-float-3 .sa-float-inner {
  animation: sa-float-drift-3 10s ease-in-out infinite;
  /* Furthest card: softer, flatter, more diffuse. */
  background: rgba(9, 20, 48, 0.44);
  -webkit-backdrop-filter: blur(18px) saturate(140%);
  backdrop-filter: blur(18px) saturate(140%);
  box-shadow: 0 14px 36px rgba(3, 12, 38, 0.28),
              inset 0 1px 0 rgba(255, 255, 255, 0.12);
}

/* Distinct amplitudes and rotations = parallax. Kept small and slow on purpose. */
@keyframes sa-float-drift-1 {
  0%, 100% { transform: translate3d(0, 0, 0) rotate(-3.5deg); }
  50%      { transform: translate3d(4px, -15px, 0) rotate(-2.2deg); }
}
@keyframes sa-float-drift-2 {
  0%, 100% { transform: translate3d(0, 0, 0) rotate(2.8deg); }
  50%      { transform: translate3d(-5px, -22px, 0) rotate(1.4deg); }
}
@keyframes sa-float-drift-3 {
  0%, 100% { transform: translate3d(0, 0, 0) rotate(-1.8deg); }
  50%      { transform: translate3d(3px, -9px, 0) rotate(-0.7deg); }
}

/* Below ~1240px the hero gutters are too tight to hold these without them
   landing on top of the deck card — measured at 1170px, the readiness card
   overlapped it by 138px, its full width. They are decorative, so they retire
   rather than crowd the carousel. The deck itself stays down to 1024px. */
@media (max-width: 1239px) {
  .sa-float { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .sa-float { animation: none !important; opacity: 1 !important; transform: none !important; }
  .sa-float-inner { animation: none !important; }
  .sa-float-1 .sa-float-inner { transform: rotate(-3.5deg); }
  .sa-float-2 .sa-float-inner { transform: rotate(2.8deg); }
  .sa-float-3 .sa-float-inner { transform: rotate(-1.8deg); }
  .sa-float-dot { animation: none !important; }
}

/* Shared bar primitive (live progress + severity rows) */
.sa-mock-bar {
  flex: 1;
  height: 6px;
  background: #e8ecf4;
  border-radius: 999px;
  overflow: hidden;
}
.sa-mock-bar-fill {
  height: 100%;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--sa-primary), var(--sa-cyan));
}

/* 2 · Live crawl */
.sa-mock-live-head {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12px;
  font-weight: 600;
  color: var(--sa-text-primary);
}
.sa-mock-live-title {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.sa-mock-live-pct { color: var(--sa-primary); font-weight: 700; }
.sa-mock-live-pulse {
  display: inline-block;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #16a34a;
  flex-shrink: 0;
  box-shadow: 0 0 0 0 rgba(22, 163, 74, 0.55);
  animation: sa-mock-pulse 1.8s ease-out infinite;
}
@keyframes sa-mock-pulse {
  70%  { box-shadow: 0 0 0 8px rgba(22, 163, 74, 0); }
  100% { box-shadow: 0 0 0 0 rgba(22, 163, 74, 0); }
}
.sa-mock-live-url {
  font-size: 11px;
  color: var(--sa-text-faint);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 3 · AI summary */
.sa-mock-ai-head { display: flex; align-items: center; gap: 8px; }
.sa-mock-ai-spark { color: var(--sa-cyan); font-size: 14px; }
.sa-mock-ai-title { font-size: 13px; font-weight: 700; color: var(--sa-text-primary); flex: 1; }
.sa-mock-ai-badge {
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  padding: 3px 8px;
  border-radius: 999px;
  color: #0e7490;
  background: rgba(6, 214, 209, 0.14);
}
.sa-mock-ai-quote {
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--sa-text-primary);
  padding: 10px 12px;
  border-left: 3px solid var(--sa-cyan);
  background: var(--sa-surface-light);
  border-radius: 0 8px 8px 0;
}
.sa-mock-ai-list { display: flex; flex-direction: column; gap: 7px; }
.sa-mock-ai-item {
  display: flex;
  align-items: center;
  gap: 9px;
  font-size: 12px;
  color: var(--sa-text-faint);
}
.sa-mock-ai-num {
  width: 19px;
  height: 19px;
  flex-shrink: 0;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 10px;
  font-weight: 700;
  color: #fff;
  background: var(--sa-primary);
}

/* 4 · Issues by severity + 5 · AI readiness — shared header */
.sa-mock-sec-head { display: flex; align-items: center; gap: 8px; }
.sa-mock-sec-title { font-size: 13px; font-weight: 700; color: var(--sa-text-primary); flex: 1; }
.sa-mock-sec-total { font-size: 11px; color: var(--sa-text-faint); }
.sa-mock-sev { display: flex; flex-direction: column; gap: 11px; margin-top: 4px; }
.sa-mock-sev-row { display: flex; align-items: center; gap: 10px; }
.sa-mock-sev-label {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 74px;
  flex-shrink: 0;
  font-size: 11.5px;
  color: var(--sa-text-faint);
}
.sa-mock-sev-label i { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; }
.sa-mock-sev-num {
  width: 26px;
  flex-shrink: 0;
  text-align: right;
  font-size: 12px;
  font-weight: 700;
  color: var(--sa-text-primary);
}
.sa-mock-sev-foot,
.sa-mock-foot {
  font-size: 11px;
  color: var(--sa-text-faint);
  padding-top: 8px;
  border-top: 1px dashed #e8ecf4;
}

/* Worst-offending page — gives the severity slide a concrete anchor instead of
   three bars floating in space. */
.sa-mock-worst {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  border-radius: 8px;
  background: var(--sa-surface-light);
}
.sa-mock-worst-url {
  flex: 1;
  font-size: 11px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  color: var(--sa-text-faint);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.sa-mock-worst-count {
  font-size: 10px;
  font-weight: 700;
  color: #b45309;
  background: rgba(245, 158, 11, 0.16);
  padding: 3px 8px;
  border-radius: 999px;
  flex-shrink: 0;
}

/* 5 · AI readiness */
.sa-mock-readiness { text-align: center; padding: 6px 0 2px; }
.sa-mock-readiness-score {
  font-size: 2.6rem;
  font-weight: 800;
  line-height: 1;
  background: linear-gradient(135deg, var(--sa-primary), var(--sa-cyan));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.sa-mock-readiness-score span { font-size: 1rem; font-weight: 600; color: var(--sa-text-faint); -webkit-text-fill-color: var(--sa-text-faint); }
.sa-mock-readiness-sub { font-size: 11.5px; color: var(--sa-text-faint); margin-top: 5px; }
.sa-mock-chips { display: flex; flex-wrap: wrap; gap: 6px; justify-content: center; margin-top: 12px; }
.sa-mock-chip {
  font-size: 11px;
  font-weight: 600;
  padding: 4px 10px;
  border-radius: 999px;
}
.sa-mock-chip.sa-ok   { color: #15803d; background: rgba(22, 163, 74, 0.12); }
.sa-mock-chip.sa-warn { color: #b45309; background: rgba(245, 158, 11, 0.14); }

/* Slide indicators — the active dot stretches into a pill and fills over the
   5s dwell, so the card telegraphs when it is about to move. */
/* The dots sit below the deck on the blue hero, not inside a white card, so they
   are tinted for a dark ground. */
.sa-mock-dots {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 6px 0 0;
}
.sa-mock-dot-btn {
  width: 7px;
  height: 7px;
  padding: 0;
  border: none;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.34);
  cursor: pointer;
  overflow: hidden;
  transition: width 0.45s cubic-bezier(0.65, 0, 0.35, 1), background 0.3s;
}
.sa-mock-dot-btn:hover { background: rgba(255, 255, 255, 0.55); }
.sa-mock-dot-btn:focus-visible { outline: 2px solid #fff; outline-offset: 3px; }
.sa-mock-dot-btn.active { width: 26px; background: rgba(255, 255, 255, 0.28); }
.sa-mock-dot-fill { display: block; width: 0; height: 100%; border-radius: 999px; }
.sa-mock-dot-btn.active .sa-mock-dot-fill {
  background: #fff;
  animation: sa-mock-dot-fill 5s linear forwards;
}
@keyframes sa-mock-dot-fill {
  from { width: 0; }
  to   { width: 100%; }
}

@media (prefers-reduced-motion: reduce) {
  .sa-deck-track, .sa-deck-card { transition: none !important; }
  .sa-mock-live-pulse,
  .sa-mock-dot-btn.active .sa-mock-dot-fill { animation: none !important; }
  .sa-mock-dot-btn.active .sa-mock-dot-fill { width: 100%; }
}
@media (max-width: 1024px) {
  .sa-hero { padding: 120px 24px 60px; }
  .sa-hero-inner { flex-direction: column; text-align: center; }
  .sa-hero-content { max-width: 640px; }
  .sa-hero-buttons { justify-content: center; }
  .sa-hero-visual { display: none; }
  .sa-hero h1 { font-size: 2.4rem; }
}
@media (max-width: 480px) {
  .sa-hero { padding: 100px 16px 48px; }
  .sa-hero h1 { font-size: 1.8rem; }
  .sa-hero-subtitle { font-size: 1rem; }
  .sa-hero-buttons { flex-direction: column; }
}

/* --- Hero floating orbs --- */
.sa-hero-orb {
  position: absolute;
  border-radius: 50%;
  filter: blur(60px);
  opacity: 0.35;
  animation: sa-orb-float 8s ease-in-out infinite;
}
.sa-hero-orb-1 {
  width: 300px; height: 300px;
  background: #2563eb;
  top: -60px; right: 10%;
  animation-delay: 0s;
}
.sa-hero-orb-2 {
  width: 200px; height: 200px;
  background: #9333ea;
  bottom: -40px; left: 15%;
  animation-delay: 2.5s;
}
.sa-hero-orb-3 {
  width: 160px; height: 160px;
  background: #06D6D1;
  top: 40%; left: 5%;
  animation-delay: 5s;
}
@keyframes sa-orb-float {
  0%, 100% { transform: translate(0, 0) scale(1); }
  33% { transform: translate(20px, -15px) scale(1.05); }
  66% { transform: translate(-15px, 10px) scale(0.95); }
}

/* --- Hero gradient text --- */
.sa-hero-gradient-text {
  background: linear-gradient(135deg, #ffffff 0%, #06D6D1 100%);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}

/* ============================================
   Stats Bar
   ============================================ */
.sa-stats-bar {
  background: #e8eefb;
  border-bottom: 1px solid #d5e0f2;
  padding: 40px 24px;
}
.sa-stats-inner {
  max-width: 1200px;
  margin: 0 auto;
  display: flex;
  justify-content: center;
  gap: 48px;
  flex-wrap: wrap;
}
.sa-stat {
  text-align: center;
}
.sa-stat-number {
  font-size: 2.4rem;
  font-weight: 800;
  color: #2563FF;
  line-height: 1;
}
.sa-stat-label {
  font-size: 14px;
  color: #64748b;
  margin-top: 6px;
}

@media (max-width: 520px) {
  .sa-stats-inner { gap: 24px; }
  .sa-stat-number { font-size: 1.8rem; }
}

/* ============================================
   Landing Sections
   ============================================ */
.sa-section {
  padding: 100px 24px;
}
.sa-section-alt {
  background: var(--sa-surface-light);
}
.sa-section-inner {
  max-width: 1200px;
  margin: 0 auto;
}
/* Deep-linked sections (#features, #pricing, #faq, …) must stop below the fixed navbar —
   without this, scrollIntoView puts the heading flush at viewport top, behind the nav. */
.sa-section[id],
.sa-stats-bar[id],
.sa-cta[id] {
  scroll-margin-top: calc(var(--sa-nav-height, 64px) + 16px);
}
.sa-section-header {
  text-align: center;
  margin-bottom: 56px;
}
.sa-section .sa-section-title {
  font-size: 2.2rem;
  font-weight: 800;
  color: var(--sa-text-primary);
  margin: 0 0 12px;
  letter-spacing: -0.01em;
  display: block;
  text-align: center;
}
.sa-section .sa-section-title::before { content: none; }
.sa-section-subtitle {
  font-size: 1.1rem;
  color: var(--sa-text-muted);
  max-width: 600px;
  margin: 0 auto;
  line-height: 1.6;
}

@media (max-width: 768px) {
  .sa-section { padding: 60px 16px; }
  .sa-section .sa-section-title { font-size: 1.7rem; }
  .sa-section-subtitle { font-size: 1rem; }
  .sa-section-header { margin-bottom: 36px; }
}

/* --- Feature cards grid --- */
.sa-features-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 24px;
}
.sa-feature-card {
  background: white;
  border-radius: var(--sa-radius-card);
  padding: 24px;
  border: 1px solid var(--sa-border);
}
.sa-feature-icon {
  width: 40px;
  height: 40px;
  border-radius: var(--sa-radius-icon);
  background: var(--sa-primary-light);
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 16px;
  color: var(--sa-primary);
}
.sa-feature-card h3 {
  font-size: 1.1rem;
  font-weight: 700;
  color: var(--sa-text-primary);
  margin: 0 0 8px;
}
.sa-feature-card p {
  font-size: 14px;
  color: var(--sa-text-muted);
  line-height: 1.6;
  margin: 0;
}

/* --- Deep dive rows --- */
.sa-deep-dive {
  display: flex;
  align-items: center;
  gap: 80px;
  margin-bottom: 80px;
}
.sa-deep-dive:last-child { margin-bottom: 0; }
.sa-deep-dive.sa-reversed { flex-direction: row-reverse; }
.sa-deep-dive-content { flex: 1; }
.sa-deep-dive-visual { flex: 1; }
.sa-deep-dive-label {
  display: inline-block;
  font-size: 13px;
  font-weight: 600;
  color: var(--sa-primary);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin-bottom: 8px;
}
.sa-deep-dive-content h3 {
  font-size: 1.6rem;
  font-weight: 700;
  color: var(--sa-text-primary);
  margin: 0 0 16px;
}
.sa-deep-dive-content p {
  font-size: 15px;
  color: var(--sa-text-muted);
  line-height: 1.7;
  margin: 0 0 20px;
}
.sa-deep-dive-content ul {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.sa-deep-dive-content li {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 14px;
  color: var(--sa-text-tertiary);
}
.sa-deep-dive-visual-card {
  background: var(--sa-surface-light);
  border: 1px solid var(--sa-border);
  border-radius: var(--sa-radius-card);
  padding: 32px;
}
.sa-visual-bar-row {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 12px;
}
.sa-visual-bar-row:last-child { margin-bottom: 0; }
.sa-visual-bar-label {
  font-size: 13px;
  color: var(--sa-text-muted);
  width: 100px;
  flex-shrink: 0;
}
.sa-visual-bar-track {
  flex: 1;
  height: 8px;
  background: #e8ecf4;
  border-radius: 4px;
  overflow: hidden;
}
.sa-visual-bar-fill {
  height: 100%;
  border-radius: 4px;
  transition: width 1s ease-out;
}
.sa-visual-bar-value {
  font-size: 13px;
  font-weight: 600;
  color: var(--sa-text-primary);
  width: 36px;
  text-align: right;
  flex-shrink: 0;
}

@media (max-width: 900px) {
  .sa-deep-dive, .sa-deep-dive.sa-reversed { flex-direction: column; gap: 40px; }
}

/* --- Steps --- */
.sa-steps-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 32px;
}
.sa-step-card { text-align: center; }
.sa-step-number {
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: var(--sa-gradient-icon);
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0 auto 20px;
  font-size: 1.3rem;
  font-weight: 700;
  color: white;
}
.sa-step-card h3 {
  font-size: 1.1rem;
  font-weight: 700;
  color: var(--sa-text-primary);
  margin: 0 0 8px;
}
.sa-step-card p {
  font-size: 14px;
  color: var(--sa-text-muted);
  line-height: 1.6;
  margin: 0;
}

@media (max-width: 768px) {
  .sa-steps-grid { grid-template-columns: 1fr; max-width: 400px; margin: 0 auto; }
}

/* --- Analysis categories --- */

/* --- Use cases --- */
.sa-usecases-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 24px;
}
.sa-usecase-card {
  background: white;
  border-radius: var(--sa-radius-card);
  padding: 32px;
  border: 1px solid var(--sa-border);
}
.sa-usecase-icon {
  width: 44px;
  height: 44px;
  border-radius: 12px;
  background: rgba(37, 99, 235, 0.06);
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 16px;
  color: var(--sa-primary);
}
.sa-usecase-card h3 {
  font-size: 1.1rem;
  font-weight: 700;
  color: var(--sa-text-primary);
  margin: 0 0 8px;
}
.sa-usecase-card > p {
  font-size: 14px;
  color: var(--sa-text-muted);
  line-height: 1.6;
  margin: 0 0 16px;
}
.sa-usecase-card ul {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.sa-usecase-card li {
  font-size: 13px;
  color: var(--sa-text-tertiary);
  display: flex;
  align-items: center;
  gap: 8px;
}

/* --- Comparison table --- */
.sa-comparison-table {
  width: 100%;
  border-collapse: collapse;
  border-radius: var(--sa-radius-card);
  overflow: hidden;
  border: 1px solid var(--sa-border);
  background: white;
}
.sa-comparison-table th, .sa-comparison-table td {
  padding: 16px 20px;
  text-align: left;
  font-size: 14px;
}
.sa-comparison-table thead th {
  background: var(--sa-surface-light);
  font-weight: 500;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--sa-text-muted);
  border-bottom: 1px solid var(--sa-border);
}
.sa-comparison-table thead th.sa-brand-col {
  color: var(--sa-primary);
  text-align: center;
}
.sa-comparison-table thead th:last-child { text-align: center; }
.sa-comparison-table tbody td { border-bottom: 1px solid var(--sa-border); }
.sa-comparison-table tbody tr:last-child td { border-bottom: none; }
.sa-comparison-table td:nth-child(2), .sa-comparison-table td:nth-child(3) { text-align: center; }

/* --- AI Features Grid --- */
.sa-ai-section-badge {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: var(--sa-gradient-ai);
  color: white;
  font-size: 13px;
  font-weight: 600;
  padding: 6px 16px;
  border-radius: var(--sa-radius-badge);
  margin-bottom: 16px;
}
.sa-ai-features-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 16px;
}
.sa-ai-feature-card {
  background: white;
  border: 1px solid var(--sa-border);
  border-radius: var(--sa-radius-card);
  padding: 24px 20px;
  transition: box-shadow 0.2s, border-color 0.2s;
}
.sa-ai-feature-card:hover {
  box-shadow: var(--sa-shadow-hover);
  border-color: rgba(147, 51, 234, 0.2);
}
.sa-ai-feature-icon {
  width: 40px;
  height: 40px;
  border-radius: var(--sa-radius-icon);
  background: var(--sa-purple-light);
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 14px;
  color: var(--sa-purple);
}
.sa-ai-feature-card h4 {
  font-size: 15px;
  font-weight: 600;
  color: var(--sa-text-primary);
  margin: 0 0 6px;
}
.sa-ai-feature-card p {
  font-size: 13px;
  color: var(--sa-text-muted);
  line-height: 1.5;
  margin: 0;
}
@media (max-width: 1024px) {
  .sa-ai-features-grid { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 768px) {
  .sa-ai-features-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 480px) {
  .sa-ai-features-grid { grid-template-columns: 1fr; }
}

/* --- Testimonials --- */
.sa-social-proof {
  display: flex;
  justify-content: center;
  gap: 48px;
  flex-wrap: wrap;
  margin-bottom: 48px;
}
.sa-proof-stat {
  text-align: center;
}
.sa-proof-number {
  font-size: 2rem;
  font-weight: 800;
  color: var(--sa-primary);
  line-height: 1;
}
.sa-proof-label {
  font-size: 13px;
  color: var(--sa-text-muted);
  margin-top: 6px;
}
.sa-testimonials-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
}
.sa-testimonial-card {
  background: white;
  border: 1px solid var(--sa-border);
  border-radius: var(--sa-radius-card);
  padding: 24px;
  display: flex;
  flex-direction: column;
  transition: box-shadow 0.2s;
}
.sa-testimonial-card:hover {
  box-shadow: var(--sa-shadow-hover);
}
.sa-testimonial-stars {
  display: flex;
  gap: 2px;
  margin-bottom: 14px;
  color: #f59e0b;
  font-size: 16px;
}
.sa-testimonial-text {
  font-size: 14px;
  color: var(--sa-text-tertiary);
  line-height: 1.6;
  margin: 0 0 16px;
  flex: 1;
}
.sa-testimonial-author {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 12px;
}
.sa-testimonial-name {
  font-size: 14px;
  font-weight: 600;
  color: var(--sa-text-primary);
}
.sa-testimonial-role {
  font-size: 12px;
  color: var(--sa-text-faint);
}
.sa-testimonial-metric {
  display: flex;
  align-items: center;
  gap: 8px;
  padding-top: 12px;
  border-top: 1px solid var(--sa-border);
}
.sa-testimonial-metric-value {
  font-size: 16px;
  font-weight: 700;
}
.sa-testimonial-metric-label {
  font-size: 12px;
  color: var(--sa-text-muted);
}
@media (max-width: 900px) {
  .sa-testimonials-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 600px) {
  .sa-testimonials-grid { grid-template-columns: 1fr; }
  .sa-social-proof { gap: 24px; }
  .sa-proof-number { font-size: 1.5rem; }
}

/* --- Pricing --- */
/* ── Pricing cards ─────────────────────────────────────────────────────────────
   White cards on the section ground with hairline borders; the featured plan is
   inverted to dark navy and lifted, so the eye lands on it before reading any
   copy. Quotas sit in their own block above the feature checklist — they are
   what people actually compare. */
.sa-pricing-grid {
  display: grid;
  /* 200px floor, not 224: with five plans, 20px gaps and the 1200px cap, a
     higher floor drops Enterprise onto a second row by itself. Kept as auto-fit
     rather than repeat(5) so an admin adding a sixth plan still lays out. */
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 20px;
  max-width: 1200px;
  margin: 0 auto;
  /* Room for the featured card's scale + badge to breathe without clipping. */
  padding: 18px 0 8px;
  align-items: stretch;
}
.sa-pricing-card {
  background: #fff;
  border-radius: 16px;
  padding: 30px 24px 26px;
  border: 1px solid rgba(15, 23, 42, 0.08);
  display: flex;
  flex-direction: column;
  position: relative;
  box-shadow: 0 1px 2px rgba(8, 18, 45, 0.04);
  transition: transform 0.28s cubic-bezier(0.2, 0.7, 0.3, 1),
              box-shadow 0.28s ease, border-color 0.28s ease;
}
.sa-pricing-card:hover {
  transform: translateY(-4px);
  border-color: rgba(37, 99, 255, 0.22);
  box-shadow: 0 18px 44px rgba(8, 18, 45, 0.12);
}

/* Featured plan — inverted, lifted, and the only card with a coloured glow. */
/* No scale() here on purpose. Scaling the featured card shifts every row inside
   it, so the plan name, price and quota lines no longer align with the cards
   either side — across a row of pricing cards that reads as a layout bug. The
   inversion, the shadow and the badge carry the emphasis on their own. */
.sa-pricing-card.sa-featured {
  background: linear-gradient(165deg, #123f9e 0%, #1C4CC4 55%, #0a2a67 100%);
  border-color: rgba(255, 255, 255, 0.14);
  z-index: 2;
  box-shadow: 0 26px 62px rgba(10, 42, 103, 0.42),
              inset 0 1px 0 rgba(255, 255, 255, 0.14);
}
.sa-pricing-card.sa-featured:hover {
  transform: translateY(-4px);
  box-shadow: 0 34px 74px rgba(10, 42, 103, 0.5),
              inset 0 1px 0 rgba(255, 255, 255, 0.16);
}
.sa-pricing-card.sa-featured .sa-pricing-name { color: rgba(255, 255, 255, 0.72); }
.sa-pricing-card.sa-featured .sa-pricing-price { color: #fff; }
.sa-pricing-card.sa-featured .sa-pricing-period { color: rgba(255, 255, 255, 0.5); }
.sa-pricing-card.sa-featured .sa-pricing-features { border-color: rgba(255, 255, 255, 0.14); }
.sa-pricing-card.sa-featured .sa-pricing-features li { color: rgba(255, 255, 255, 0.82); }
.sa-pricing-card.sa-featured .sa-plan-tick { color: #7dd3fc; background: rgba(125, 211, 252, 0.16); }

/* Plan name + price */
.sa-pricing-name {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--sa-text-faint);
  margin-bottom: 10px;
}
.sa-pricing-priceline {
  display: flex;
  align-items: baseline;
  gap: 6px;
  margin-bottom: 22px;
}
.sa-pricing-price {
  font-size: 2.6rem;
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.04em;
  color: var(--sa-text-primary);
}
.sa-pricing-period {
  font-size: 13px;
  font-weight: 500;
  color: var(--sa-text-faint);
}

/* Feature checklist. Carries the rule under the price now that the quota block
   is gone — without it the price and the first tick run together. */
.sa-pricing-features {
  list-style: none;
  padding: 20px 0 0;
  margin: 0 0 24px;
  border-top: 1px solid rgba(15, 23, 42, 0.08);
  display: flex;
  flex-direction: column;
  gap: 10px;
  flex: 1;
}
.sa-pricing-features li {
  font-size: 13px;
  color: var(--sa-text-tertiary);
  display: flex;
  align-items: center;
  gap: 9px;
  line-height: 1.35;
}
.sa-plan-tick {
  width: 17px;
  height: 17px;
  border-radius: 50%;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 9.5px;
  font-weight: 700;
  color: #15803d;
  background: rgba(22, 163, 74, 0.13);
}

/* Badges */
.sa-pricing-badge {
  position: absolute;
  top: -11px;
  left: 50%;
  transform: translateX(-50%);
  background: linear-gradient(135deg, #06D6D1, #05A8A4);
  color: white;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  padding: 5px 14px;
  border-radius: 999px;
  white-space: nowrap;
  box-shadow: 0 6px 16px rgba(8, 145, 178, 0.4);
}
/* Current plan highlight (logged-in visitors only). Placed after .sa-featured so a
   card that is both "Most Popular" and the user's current plan shows the green
   current-plan treatment. The current-plan badge sits top-right, clear of the
   centered "Most Popular" badge. */
.sa-pricing-card.sa-current {
  border-color: #16a34a;
  box-shadow: 0 10px 34px rgba(22, 163, 74, 0.16);
}
.sa-pricing-badge-current {
  left: auto;
  right: 14px;
  transform: none;
  background: linear-gradient(135deg, #22c55e, #16a34a);
  box-shadow: 0 6px 16px rgba(22, 163, 74, 0.36);
}
.sa-pricing-badge-free {
  background: linear-gradient(135deg, #2563FF, #1C4CC4);
  box-shadow: 0 6px 16px rgba(37, 99, 255, 0.34);
}
.sa-btn.sa-btn-current {
  border-color: #16a34a;
  color: #16a34a;
  background: rgba(22, 163, 74, 0.06);
  cursor: default;
  opacity: 1;
}

/* CTAs */
.sa-btn-free {
  background: linear-gradient(135deg, #2563FF, #1C4CC4);
  color: #fff;
  border: none;
  padding: 12px 24px;
  border-radius: var(--sa-radius-btn);
  font-weight: 600;
  box-shadow: 0 8px 18px -8px rgba(37, 99, 255, 0.55);
}
.sa-btn-free:hover { filter: brightness(1.06); color: #fff; }
.sa-btn-soft {
  background: #eef1f6;
  color: var(--sa-text-primary);
  border: 1px solid rgba(15, 23, 42, 0.06);
  padding: 12px 24px;
  border-radius: var(--sa-radius-btn);
  font-weight: 600;
  transition: background 0.2s, border-color 0.2s;
}
.sa-btn-soft:hover { background: #e4e9f1; border-color: rgba(37, 99, 255, 0.2); }
/* On the inverted card the primary CTA flips to white-on-navy. */
.sa-pricing-card.sa-featured .sa-btn-primary,
.sa-pricing-card.sa-featured .sa-btn-soft {
  background: #fff;
  color: #1C4CC4;
  border: none;
  box-shadow: 0 10px 24px -10px rgba(0, 0, 0, 0.55);
}
.sa-pricing-card.sa-featured .sa-btn-primary:hover,
.sa-pricing-card.sa-featured .sa-btn-soft:hover { background: #eaf1ff; color: #1C4CC4; }
.sa-pricing-card.sa-featured .sa-btn-outline-brand {
  border-color: rgba(255, 255, 255, 0.3);
  color: rgba(255, 255, 255, 0.85);
}

@media (prefers-reduced-motion: reduce) {
  .sa-pricing-card { transition: none !important; }
}

/* --- FAQ --- */
.sa-faq-section {
  max-width: 800px;
  margin: 0 auto;
}

/* --- CTA Section --- */

@media (max-width: 480px) {
  .sa-cta h2 { font-size: 1.6rem; }
  .sa-cta-perks { flex-direction: column; align-items: center; gap: 12px; }
}

/* ============================================
   Auth Pages — Split Layout with Branding Panel
   ============================================ */

/* Split layout: branding panel (left) + form panel (right) */
.sa-auth-split {
  display: flex;
  min-height: 100vh;
  background: white;
}

/* --- Left: Branding Panel --- */
.sa-auth-brand {
  flex: 0 0 460px;
  background: linear-gradient(160deg, #1C4CC4 0%, #2563FF 50%, #0a5e8c 100%);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 40px 48px;
  position: sticky;
  top: 0;
  align-self: flex-start;
  height: 100vh;
  overflow: hidden;
}
/* Fine grid texture overlay for depth */
.sa-auth-brand-inner::before {
  content: '';
  position: absolute;
  inset: -56px -48px;
  background-image:
    linear-gradient(rgba(255,255,255,0.04) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,0.04) 1px, transparent 1px);
  background-size: 40px 40px;
  pointer-events: none;
  z-index: -1;
}
/* Floating orb decorations (animated) */
.sa-auth-brand::before {
  content: '';
  position: absolute;
  top: -18%;
  right: -28%;
  width: 520px;
  height: 520px;
  background: radial-gradient(circle, rgba(125, 211, 252, 0.22) 0%, transparent 70%);
  pointer-events: none;
  animation: sa-orb-float-a 14s ease-in-out infinite;
}
.sa-auth-brand::after {
  content: '';
  position: absolute;
  bottom: -12%;
  left: -22%;
  width: 440px;
  height: 440px;
  background: radial-gradient(circle, rgba(6, 214, 209, 0.16) 0%, transparent 70%);
  pointer-events: none;
  animation: sa-orb-float-b 18s ease-in-out infinite;
}
@keyframes sa-orb-float-a {
  0%, 100% { transform: translate(0, 0) scale(1); }
  50% { transform: translate(-24px, 30px) scale(1.08); }
}
@keyframes sa-orb-float-b {
  0%, 100% { transform: translate(0, 0) scale(1); }
  50% { transform: translate(28px, -24px) scale(1.1); }
}

.sa-auth-brand-inner {
  position: relative;
  z-index: 1;
  max-width: 360px;
  width: 100%;
}

.sa-auth-brand-logo {
  height: 42px;
  margin-bottom: 24px;
  display: block;
}

.sa-auth-brand-inner h2 {
  font-size: 1.85rem;
  font-weight: 700;
  color: white;
  line-height: 1.25;
  margin: 0 0 12px;
  letter-spacing: -0.01em;
}

.sa-auth-brand-desc {
  font-size: 15px;
  color: rgba(255, 255, 255, 0.75);
  line-height: 1.6;
  margin: 0 0 20px;
}

/* Feature checkmarks */
.sa-auth-brand-features {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-bottom: 24px;
}
.sa-auth-brand-feature {
  display: flex;
  align-items: center;
  gap: 12px;
  color: rgba(255, 255, 255, 0.9);
  font-size: 14px;
  font-weight: 500;
}
.sa-auth-brand-feature svg {
  flex-shrink: 0;
  color: rgba(134, 239, 172, 0.9);
}

/* Stats row */
.sa-auth-brand-stats {
  display: flex;
  align-items: center;
  gap: 0;
  padding: 20px 0;
  border-top: 1px solid rgba(255, 255, 255, 0.15);
}
.sa-auth-brand-stat {
  flex: 1;
  text-align: center;
}
.sa-auth-brand-stat-value {
  display: block;
  font-size: 20px;
  font-weight: 700;
  color: white;
  letter-spacing: -0.01em;
}
.sa-auth-brand-stat-label {
  display: block;
  font-size: 12px;
  color: rgba(255, 255, 255, 0.6);
  margin-top: 2px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.sa-auth-brand-stat-divider {
  width: 1px;
  height: 32px;
  background: rgba(255, 255, 255, 0.15);
}

/* --- Branding dashboard illustration (login / register) --- */
.sa-auth-illustration {
  max-width: 224px;
  margin: 0 0 18px;
  animation: sa-ill-float 6s ease-in-out infinite;
}
.sa-auth-illustration svg { width: 100%; height: auto; display: block; }
/* Trend line draws itself (path carries pathLength="1") */
.sa-ill-line {
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  animation: sa-ill-line-draw 1.6s ease-out 0.3s forwards;
}
.sa-ill-area    { animation: sa-ill-fade 1s ease 0.6s both; }
.sa-ill-end     { transform-box: fill-box; transform-origin: center; animation: sa-ill-pop 0.5s cubic-bezier(0.16, 1, 0.3, 1) 1.4s both; }
.sa-ill-endring { transform-box: fill-box; transform-origin: center; animation: sa-ill-ping 2.2s ease-out 1.7s infinite; }
.sa-ill-pill    { animation: sa-ill-fade 0.6s ease 1.2s both; }
.sa-ill-score   { animation: sa-ill-fade 0.6s ease 1.6s both; }
@keyframes sa-ill-float     { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-7px); } }
@keyframes sa-ill-line-draw { to { stroke-dashoffset: 0; } }
@keyframes sa-ill-fade      { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
@keyframes sa-ill-pop       { from { opacity: 0; transform: scale(0); } to { opacity: 1; transform: scale(1); } }
@keyframes sa-ill-ping      { 0% { transform: scale(0.6); opacity: 0.7; } 100% { transform: scale(1.9); opacity: 0; } }
@media (prefers-reduced-motion: reduce) {
  .sa-auth-illustration, .sa-ill-line, .sa-ill-area, .sa-ill-end, .sa-ill-endring, .sa-ill-pill, .sa-ill-score { animation: none !important; }
  .sa-ill-line { stroke-dashoffset: 0 !important; }
  .sa-ill-endring { display: none; }
}

/* --- Right: Form Panel --- */
.sa-auth-form-panel {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  overflow-y: auto;
}

/* Mobile header (hidden on desktop, shown on mobile when brand panel is hidden) */
.sa-auth-mobile-header {
  display: none;
  border-bottom: 1px solid var(--sa-border, rgba(0,0,0,0.1));
  padding: 16px 24px;
  background: white;
}

/* Centered form area */
.sa-auth-form-centered {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 48px 32px;
}

/* Container */
.sa-auth-container {
  width: 100%;
  max-width: 448px;
}
.sa-auth-container.sa-auth-container-wide {
  max-width: 520px;
}

/* Responsive: hide brand panel on small screens */
@media (max-width: 900px) {
  .sa-auth-split {
    flex-direction: column;
  }
  .sa-auth-brand {
    display: none;
  }
  .sa-auth-mobile-header {
    display: block;
  }
  .sa-auth-form-panel {
    min-height: calc(100vh);
  }
  .sa-auth-form-centered {
    padding: 32px 16px;
  }
}

/* Title block */
.sa-auth-title-block {
  text-align: center;
  margin-bottom: 32px;
}
.sa-auth-title-block h1 {
  font-size: 1.75rem;
  font-weight: 700;
  color: var(--sa-text-primary, #0a0a0a);
  margin: 0 0 8px;
}
.sa-auth-title-block p {
  font-size: 15px;
  color: var(--sa-text-muted, #717182);
  margin: 0;
}
.sa-auth-icon-circle {
  width: 52px;
  height: 52px;
  border-radius: 50%;
  background: rgba(37, 99, 235, 0.1);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 16px;
  color: var(--sa-primary, #2563eb);
}

/* Card */
.sa-auth-card {
  background: #ffffff;
  border: 1px solid rgba(15, 23, 42, 0.06);
  border-radius: 16px;
  padding: 24px 28px;
  box-shadow:
    0 1px 2px rgba(15, 23, 42, 0.04),
    0 8px 24px rgba(15, 23, 42, 0.06),
    0 24px 48px -24px rgba(15, 23, 42, 0.10);
}
@media (min-width: 640px) {
  .sa-auth-card { padding: 32px; }
}

/* Fields stack */
.sa-auth-fields {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

/* Individual field */
.sa-auth-field label {
  display: block;
  font-size: 14px;
  font-weight: 500;
  color: var(--sa-text-primary, #0a0a0a);
  margin-bottom: 8px;
}
.sa-auth-optional {
  color: var(--sa-text-faint, #717182);
  font-weight: 400;
}

/* Required-field marker (red asterisk) */
.sa-required {
  color: var(--sa-error, #d4183d);
  font-weight: 700;
  margin-left: 2px;
  line-height: 1;
}

/* Input wrapper with icon */
.sa-auth-input-wrap {
  position: relative;
  display: flex;
  align-items: center;
}
.sa-auth-input-icon {
  position: absolute;
  left: 12px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--sa-text-faint, #717182);
  pointer-events: none;
  flex-shrink: 0;
}
.sa-auth-input {
  width: 100%;
  min-height: 46px;
  padding: 12px 16px 12px 42px;
  background: #ffffff;
  border: 1.5px solid var(--sa-border, rgba(15, 23, 42, 0.12));
  border-radius: 12px;
  font-size: 15px;
  font-family: inherit;
  color: var(--sa-text-primary, #0a0a0a);
  outline: none;
  transition: border-color 0.18s ease, box-shadow 0.18s ease, background 0.18s ease;
}
.sa-auth-input::placeholder {
  color: var(--sa-text-faint, #9ca3af);
}
.sa-auth-input:hover {
  border-color: rgba(37, 99, 235, 0.45);
}
.sa-auth-input:focus {
  border-color: var(--sa-primary, #2563eb);
  box-shadow: 0 0 0 4px rgba(37, 99, 235, 0.14);
  background: #ffffff;
}
/* Icon shifts to primary color when the field is focused */
.sa-auth-input-wrap:focus-within .sa-auth-input-icon {
  color: var(--sa-primary, #2563eb);
}
.sa-auth-input.sa-auth-input-no-icon {
  padding-left: 16px;
}
.sa-auth-input.sa-auth-input-password {
  padding-right: 48px;
}

/* ── URL field with inline "https://" prefix ──
   One seamless input. Prefix and input share font metrics so the text
   sits on the same baseline — no vertical drift. */
.sa-auth-url-wrap {
  display: flex;                    /* explicit so we own the flex behavior */
  align-items: stretch;             /* full-height children — easier vertical centering */
  background: #ffffff;
  border: 1.5px solid var(--sa-border, rgba(15, 23, 42, 0.12));
  border-radius: 12px;
  overflow: hidden;
  padding: 0;
  min-height: 46px;                 /* matches the base .sa-auth-input height */
  transition: border-color 0.18s ease, box-shadow 0.18s ease;
}
.sa-auth-url-wrap:hover {
  border-color: rgba(37, 99, 235, 0.45);
}
.sa-auth-url-wrap:focus-within {
  border-color: var(--sa-primary, #2563eb);
  box-shadow: 0 0 0 4px rgba(37, 99, 235, 0.14);
}
.sa-auth-url-wrap.invalid {
  border-color: #dc2626;
  box-shadow: 0 0 0 4px rgba(220, 38, 38, 0.12);
}
/* Higher specificity than .sa-auth-field label so it actually wins.
   Without this, the global label rule forces display:block + font-size:14px
   and the prefix renders as a stacked block above the input. */
.sa-auth-field label.sa-auth-url-prefix,
.sa-auth-url-wrap > label.sa-auth-url-prefix {
  flex-shrink: 0;
  display: flex !important;         /* MudBlazor's bare label rule sets inline-block */
  align-items: center;
  padding: 0 2px 0 14px;
  margin: 0;
  background: transparent;
  border: 0;
  color: var(--sa-text-muted, #6b7280);
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: 15px;                   /* match the input so baselines line up */
  font-weight: 500;
  line-height: 1;
  letter-spacing: normal;
  text-transform: none;
  cursor: text;
  user-select: none;
}
.sa-auth-url-wrap:focus-within label.sa-auth-url-prefix {
  color: var(--sa-primary, #2563eb);
}
.sa-auth-input.sa-auth-url-input {
  /* The wrap owns the border / focus ring. */
  flex: 1;
  border: 0 !important;
  border-radius: 0 !important;
  background: transparent !important;
  box-shadow: none !important;
  padding: 0 16px 0 4px;            /* match prefix vertical (none — wrap centers) */
  min-height: 0;                    /* wrap supplies the height; stretch fills it */
  height: auto;
  line-height: 1;                   /* match the prefix */
  /* font-size 15px is inherited from .sa-auth-input base — same as prefix */
}
.sa-auth-input.sa-auth-url-input:focus {
  box-shadow: none !important;
}
/* Placeholder color stays consistent with the prefix tone */
.sa-auth-input.sa-auth-url-input::placeholder {
  color: var(--sa-text-faint, #9ca3af);
}

/* Password toggle */
.sa-auth-input-toggle {
  position: absolute;
  right: 12px;
  top: 50%;
  transform: translateY(-50%);
  background: none;
  border: none;
  cursor: pointer;
  color: var(--sa-text-faint, #717182);
  padding: 0;
  display: flex;
  align-items: center;
}
.sa-auth-input-toggle:hover {
  color: var(--sa-text-primary, #0a0a0a);
}

/* Password show/hide toggle (markup uses .sa-auth-toggle-pw) — sits INSIDE the
   input on the right. The matching CSS was missing, so the eye floated outside. */
.sa-auth-toggle-pw {
  position: absolute;
  right: 12px;
  top: 50%;
  transform: translateY(-50%);
  background: none;
  border: none;
  cursor: pointer;
  color: var(--sa-text-faint, #717182);
  padding: 0;
  display: flex;
  align-items: center;
}
.sa-auth-toggle-pw:hover {
  color: var(--sa-text-primary, #0a0a0a);
}
/* Reserve room on the right so the typed text never runs under the eye icon. */
.sa-auth-input-wrap:has(.sa-auth-toggle-pw) .sa-auth-input {
  padding-right: 44px;
}

/* Input status indicators */
.sa-auth-input-status {
  position: absolute;
  right: 12px;
  top: 50%;
  transform: translateY(-50%);
  width: 8px;
  height: 8px;
  border-radius: 50%;
}
.sa-auth-input-status.checking { background: var(--sa-text-faint); animation: pulse 1s infinite; }
.sa-auth-input-status.error { background: var(--sa-error, #d4183d); }
.sa-auth-input-status.success { background: var(--sa-success, #10b981); }
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.4; } }

/* Row of fields (side by side) */
.sa-auth-field-row {
  display: flex;
  gap: 12px;
}
.sa-auth-field-row > .sa-auth-field { flex: 1; }

/* Remember me / checkbox */
.sa-auth-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.sa-auth-checkbox {
  display: flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
  font-size: 14px;
  color: var(--sa-text-primary, #0a0a0a);
}
.sa-auth-checkbox input[type="checkbox"] {
  width: 16px;
  height: 16px;
  border-radius: 4px;
  border: 1px solid var(--sa-border, rgba(0,0,0,0.2));
  accent-color: var(--sa-primary, #2563eb);
  cursor: pointer;
  flex-shrink: 0;
}
.sa-auth-link {
  font-size: 14px;
  color: var(--sa-primary, #2563eb);
  text-decoration: none;
  font-weight: 500;
}
.sa-auth-link:hover { text-decoration: underline; }

/* Submit button */
.sa-auth-submit {
  width: 100%;
  min-height: 48px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 13px 24px;
  background: linear-gradient(135deg, #2563FF 0%, #1C4CC4 100%);
  color: white;
  border: none;
  border-radius: 12px;
  font-size: 15px;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
  box-shadow: 0 4px 14px rgba(37, 99, 255, 0.30);
  transition: transform 0.15s ease, box-shadow 0.18s ease, filter 0.15s ease;
}
.sa-auth-submit:hover {
  transform: translateY(-1px);
  box-shadow: 0 8px 22px rgba(37, 99, 255, 0.38);
  filter: brightness(1.08);
}
.sa-auth-submit:active {
  transform: translateY(0);
  box-shadow: 0 3px 10px rgba(37, 99, 255, 0.28);
}
.sa-auth-submit:disabled {
  background: #e2e8f0;
  color: #94a3b8;
  cursor: not-allowed;
  box-shadow: none;
  transform: none;
  filter: none;
}
.sa-auth-submit svg { transition: transform 0.2s ease; }
.sa-auth-submit:hover:not(:disabled) svg { transform: translateX(3px); }

/* Spinner */
/* Sign-in / auth submit button spinner — same comet sweep as .sa-spinner, inheriting the
   button's text colour so it stays legible. Too small (18px) to carry the lens. */
.sa-auth-spinner {
  width: 18px;
  height: 18px;
  border: none;
  border-radius: 50%;
  background: conic-gradient(from 0deg, transparent 0 50%, currentColor 97%);
  -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 24%), #000 calc(100% - 22%));
          mask: radial-gradient(farthest-side, transparent calc(100% - 24%), #000 calc(100% - 22%));
  animation: sa-spin 0.7s linear infinite;
  flex-shrink: 0;
}
@keyframes sa-spin { to { transform: rotate(360deg); } }

/* Common app loader — orbit ring + logo (matches the boot loader) */
/* Page-level loader — anchored to the content area (below the top bar, right of the
   sidebar) and centered, so it sits in the same spot on every page regardless of how
   much content/header is above it. */
.sa-loading {
  position: fixed;
  top: var(--sa-nav-height);
  left: 260px;
  right: 0;
  bottom: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  z-index: 20;
  transition: left 0.2s cubic-bezier(0.4, 0, 0.2, 1);
}
.sa-shell.sidebar-collapsed .sa-loading {
  left: 68px;
}
@media (max-width: 900px) {
  .sa-loading { left: 0; }
}
/* Inline variant — keeps the spinner in normal flow (e.g. inside a card/section). */
.sa-loading.sa-loading-inline {
  position: static;
  inset: auto;
  padding: 60px 20px;
}
/* ── Canonical Elvisto loader ──────────────────────────────────────────────
   ONE loading indicator for the whole app: a cyan comet sweeping around the
   Elvisto lens — identical to the boot screen in index.html. Every existing
   `<div class="sa-loading"><div class="sa-spinner"></div></div>` inherits this,
   so page loads, data fetches, section loaders and navigation all match without
   touching call sites. Ring/lens are sized in %, so the modifiers scale cleanly. */
.sa-spinner {
  position: relative;
  width: 60px;
  height: 60px;
  border: none;
  border-radius: 50%;
  background: none;
}
/* Comet: cyan tail sweeping clockwise, brightest at the leading head. The
   drop-shadow gives that head the same glow as the boot loader's leading dot. */
.sa-spinner::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: conic-gradient(from 0deg, transparent 0 55%, rgba(6, 214, 209,0.12) 68%, rgba(6, 214, 209,0.5) 86%, #06D6D1 97%);
  -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 14%), #000 calc(100% - 13%));
          mask: radial-gradient(farthest-side, transparent calc(100% - 14%), #000 calc(100% - 13%));
  filter: drop-shadow(0 0 6px rgba(6, 214, 209, 0.65));
  animation: sa-spin 1.05s linear infinite;
}
/* Center lens — zooms gently, like a magnifier focusing. */
.sa-spinner::after {
  content: '';
  position: absolute;
  inset: 0;
  margin: auto;
  width: 48%;
  height: 48%;
  background: url('/logo-icon.svg') center / contain no-repeat;
  filter: drop-shadow(0 4px 10px rgba(37, 99, 255, 0.15));
  animation: sa-loader-zoom 1.6s ease-in-out infinite;
}
/* Size modifiers — e.g. <div class="sa-spinner sa-spinner-sm"></div> */
.sa-spinner-lg { width: 72px; height: 72px; }
.sa-spinner-sm { width: 36px; height: 36px; }
.sa-spinner-xs { width: 22px; height: 22px; }
/* Below ~28px the lens is unreadable, so show the comet ring alone. */
.sa-spinner-xs::after { display: none; }

/* Optional caption beneath a loader, matching the boot screen's wording. */
.sa-loading-label {
  margin: 14px 0 0;
  color: #64748b;
  font-size: 13px;
  font-weight: 500;
  text-align: center;
}

@keyframes sa-loader-zoom { 0%, 100% { transform: scale(0.82); } 50% { transform: scale(1.16); } }
@keyframes sa-loader-pulse { 0%, 100% { transform: scale(1); opacity: 1; } 50% { transform: scale(0.88); opacity: 0.8; } }

/* Small inline spinner for buttons — sized to a 14px icon so the button keeps its
   dimensions. The ring inherits the button's text color via currentColor, so it's white
   on primary buttons and themed on icon buttons. */
.sa-btn-spinner {
  display: inline-block;
  width: 14px;
  height: 14px;
  border: none;
  border-radius: 50%;
  /* Same comet sweep as .sa-spinner, but inheriting the button's text colour so it stays
     legible on primary / ghost / destructive buttons alike. Too small to carry the lens. */
  background: conic-gradient(from 0deg, transparent 0 50%, currentColor 97%);
  -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 28%), #000 calc(100% - 26%));
          mask: radial-gradient(farthest-side, transparent calc(100% - 28%), #000 calc(100% - 26%));
  animation: sa-btn-spin 0.7s linear infinite;
  vertical-align: middle;
  flex-shrink: 0;
  opacity: 0.9;
}
@keyframes sa-btn-spin { to { transform: rotate(360deg); } }

/* Divider */
.sa-auth-divider {
  position: relative;
  margin: 24px 0;
  text-align: center;
}
.sa-auth-divider::before {
  content: '';
  position: absolute;
  top: 50%;
  left: 0;
  right: 0;
  height: 1px;
  background: var(--sa-border, rgba(0,0,0,0.1));
}
.sa-auth-divider span {
  position: relative;
  background: white;
  padding: 0 8px;
  font-size: 12px;
  text-transform: uppercase;
  color: var(--sa-text-faint, #717182);
  letter-spacing: 0.02em;
}

/* Social login */
.sa-auth-social {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}
.sa-auth-social-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 10px 16px;
  border: 1px solid var(--sa-border, rgba(0,0,0,0.1));
  border-radius: 12px;
  background: white;
  font-size: 14px;
  font-weight: 500;
  font-family: inherit;
  color: var(--sa-text-primary, #0a0a0a);
  cursor: pointer;
  transition: background 0.15s;
}
.sa-auth-social-btn:hover { background: var(--sa-input-bg, #f3f3f5); }
.sa-auth-social-btn:disabled { opacity: 0.5; cursor: not-allowed; }

/* Footer link */
.sa-auth-footer-link {
  text-align: center;
  font-size: 14px;
  color: var(--sa-text-muted, #717182);
  margin-top: 24px;
}
.sa-auth-footer-link a {
  color: var(--sa-primary, #2563eb);
  text-decoration: none;
  font-weight: 600;
}
.sa-auth-footer-link a:hover { text-decoration: underline; }

/* Back to login link */
.sa-auth-back-link {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  margin-top: 24px;
  font-size: 14px;
  font-weight: 500;
  color: var(--sa-text-muted, #717182);
  text-decoration: none;
  transition: color 0.15s ease;
}
.sa-auth-back-link:hover { color: var(--sa-primary, #2563eb); }
.sa-auth-back-link svg { transition: transform 0.15s ease; }
.sa-auth-back-link:hover svg { transform: translateX(-3px); }

/* Back button (in register step 2) */
.sa-auth-back-btn {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 12px 24px;
  background: white;
  border: 1px solid var(--sa-border, rgba(0,0,0,0.1));
  border-radius: 12px;
  font-size: 14px;
  font-weight: 600;
  font-family: inherit;
  color: var(--sa-text-primary, #0a0a0a);
  cursor: pointer;
  transition: background 0.15s;
}
.sa-auth-back-btn:hover { background: var(--sa-input-bg, #f3f3f5); }

/* Error alert */
.sa-auth-alert {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px 16px;
  border-radius: 12px;
  font-size: 14px;
  margin-bottom: 20px;
}
.sa-auth-alert-error {
  background: rgba(212, 24, 61, 0.08);
  color: var(--sa-error, #d4183d);
  border: 1px solid rgba(212, 24, 61, 0.15);
}

/* Field hints (validation) */
.sa-auth-field-hint {
  display: block;
  font-size: 12px;
  margin-top: 6px;
  line-height: 1.4;
}
.sa-auth-field-hint-error { color: var(--sa-error, #d4183d); }
.sa-auth-field-hint-warn { color: var(--sa-warning, #f97316); }

/* ── Brand-align MudBlazor validation errors ──────────────────────────────
   MudBlazor's default validation red is Material #f44336. Override it to the
   app's brand error color (#d4183d) so dialog forms (Add/Edit User, Create
   Project, etc.) match the auth forms' validation styling. */
.mud-input-helper-text.mud-input-error,
.mud-input-label.mud-input-error,
.mud-input.mud-input-error input,
.mud-input.mud-input-error .mud-input-slot { color: var(--sa-error, #d4183d) !important; }
.mud-input.mud-input-error .mud-input-outlined-border { border-color: var(--sa-error, #d4183d) !important; }

/* Invalid inputs — Blazor adds the `invalid` class after a failed validation */
.sa-auth-input.invalid {
  border-color: var(--sa-error, #d4183d);
}
.sa-auth-input.invalid:focus {
  border-color: var(--sa-error, #d4183d);
  box-shadow: 0 0 0 4px rgba(212, 24, 61, 0.14);
}

/* Step indicators (register) */
.sa-auth-steps-indicator {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0;
  margin-bottom: 24px;
}
.sa-auth-step-pill {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 16px;
  border-radius: 999px;
  font-size: 14px;
  font-weight: 500;
  color: var(--sa-text-faint, #9ca3af);
  background: var(--sa-input-bg, #f3f3f5);
  transition: all 0.2s;
}
.sa-auth-step-pill span {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: rgba(0,0,0,0.06);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  font-weight: 700;
}
.sa-auth-step-pill.active {
  background: var(--sa-primary, #2563eb);
  color: white;
}
.sa-auth-step-pill.active span {
  background: rgba(255,255,255,0.2);
}
.sa-auth-step-pill.done {
  background: rgba(16, 185, 129, 0.1);
  color: var(--sa-success, #10b981);
}
.sa-auth-step-pill.done svg {
  color: var(--sa-success, #10b981);
}
.sa-auth-step-line {
  width: 40px;
  height: 2px;
  background: #e5e7eb;
  margin: 0 8px;
  transition: background 0.2s;
}
.sa-auth-step-line.done { background: var(--sa-success, #10b981); }

/* Plan chips (register) */
.sa-auth-plan-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.sa-auth-plan-chip {
  flex: 1;
  min-width: 90px;
  padding: 12px 14px;
  border: 2px solid var(--sa-border, rgba(0,0,0,0.1));
  border-radius: 12px;
  background: white;
  text-align: center;
  cursor: pointer;
  transition: all 0.2s;
  font-family: inherit;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
}
.sa-auth-plan-chip:hover:not(.disabled):not(:disabled) { border-color: var(--sa-primary); }
.sa-auth-plan-chip.selected {
  border-color: var(--sa-primary);
  background: rgba(37, 99, 235, 0.06);
}
/* Disabled by the "Paid Subscriptions" admin toggle.
   Bumped opacity 0.45 → 0.75 so users can still clearly read plan name + price,
   while the neutral border + soft gray fill keep the "not clickable" signal. */
.sa-auth-plan-chip.disabled,
.sa-auth-plan-chip:disabled {
  opacity: 0.75;
  cursor: not-allowed;
  border-color: var(--sa-border, rgba(15, 23, 42, 0.10));
  background: rgba(15, 23, 42, 0.03);
  pointer-events: none;
}
/* Inside the disabled chip, mute only the PRICE — keep the plan name readable
   so users can still see what's available, just not selectable. */
.sa-auth-plan-chip.disabled .sa-auth-plan-price,
.sa-auth-plan-chip:disabled .sa-auth-plan-price {
  color: var(--sa-text-faint, #9ca3af);
}
.sa-auth-plan-name {
  font-size: 14px;
  font-weight: 600;
  color: var(--sa-text-primary);
}
.sa-auth-plan-price {
  font-size: 12px;
  color: var(--sa-text-faint);
}

/* Forgot password steps */
.sa-auth-steps {
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.sa-auth-step {
  display: flex;
  align-items: flex-start;
  gap: 12px;
}
.sa-auth-step-num {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: rgba(37, 99, 235, 0.1);
  color: var(--sa-primary, #2563eb);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  font-weight: 600;
  flex-shrink: 0;
  margin-top: 2px;
}
.sa-auth-step p {
  font-size: 14px;
  color: var(--sa-text-muted, #717182);
  margin: 0;
  line-height: 1.5;
}

/* Resend button */
.sa-auth-resend-btn {
  width: 100%;
  margin-top: 24px;
  padding: 10px 16px;
  border: 1px solid var(--sa-border, rgba(0,0,0,0.1));
  border-radius: 12px;
  background: white;
  font-size: 14px;
  font-family: inherit;
  color: var(--sa-text-primary, #0a0a0a);
  cursor: pointer;
  transition: background 0.15s;
}
.sa-auth-resend-btn:hover { background: var(--sa-input-bg, #f3f3f5); }
.sa-auth-resend-btn:disabled { opacity: 0.5; cursor: not-allowed; }

/* MudBlazor input override for auth pages */
.sa-auth-mud-input .mud-input-outlined .mud-input-outlined-border {
  border-radius: 12px;
  border-color: var(--sa-border, rgba(0,0,0,0.1));
}
.sa-auth-mud-input .mud-input.mud-input-outlined {
  border-radius: 12px;
}
.sa-auth-mud-input .mud-input-slot {
  background: var(--sa-input-bg, #f3f3f5);
  border-radius: 12px;
  font-size: 14px;
}
.sa-auth-mud-input .mud-input-outlined:focus-within .mud-input-outlined-border {
  border-color: var(--sa-primary, #2563eb);
  box-shadow: 0 0 0 1px var(--sa-primary, #2563eb);
}

/* ---------------------------------------------
   Auth Accessibility
   --------------------------------------------- */
/* Keyboard focus rings (only for keyboard users, not mouse clicks) */
.sa-auth-submit:focus-visible,
.sa-auth-back-btn:focus-visible,
.sa-auth-social-btn:focus-visible,
.sa-auth-resend-btn:focus-visible,
.sa-auth-link:focus-visible,
.sa-auth-footer-link a:focus-visible,
.sa-auth-input-toggle:focus-visible,
.sa-auth-plan-chip:focus-visible {
  outline: 3px solid rgba(37, 99, 235, 0.45);
  outline-offset: 2px;
  border-radius: 8px;
}
.sa-auth-input:focus-visible {
  outline: none; /* handled by the focus box-shadow ring */
}
/* Ensure interactive targets meet the 44px minimum tap-target guideline */
.sa-auth-input-toggle,
.sa-auth-social-btn,
.sa-auth-checkbox input[type="checkbox"] {
  min-height: 44px;
}
.sa-auth-checkbox input[type="checkbox"] {
  min-height: 18px;
  width: 18px;
  height: 18px;
}
/* Respect users who prefer reduced motion */
@media (prefers-reduced-motion: reduce) {
  .sa-auth-brand::before,
  .sa-auth-brand::after,
  .sa-auth-submit,
  .sa-auth-submit svg,
  .sa-auth-input,
  .sa-auth-spinner {
    animation: none !important;
    transition: none !important;
  }
}

/* ---------------------------------------------
   Auth Responsive
   --------------------------------------------- */
/* Tablet: narrow the brand panel so the form has room */
@media (max-width: 1100px) and (min-width: 901px) {
  .sa-auth-brand { flex: 0 0 380px; padding: 40px 32px; }
  .sa-auth-brand-inner h2 { font-size: 1.6rem; }
}
/* Small screens: brand panel already hidden via the 900px rule above */
@media (max-width: 640px) {
  .sa-auth-form-centered { padding: 28px 18px; }
  .sa-auth-title-block { margin-bottom: 24px; }
  .sa-auth-title-block h1 { font-size: 1.5rem; }
}
@media (max-width: 520px) {
  .sa-auth-form-centered { padding: 24px 14px; }
  .sa-auth-card { padding: 20px; border-radius: 16px; }
  .sa-auth-field-row { flex-direction: column; }
  .sa-auth-field-row > .sa-auth-field[style] { flex: unset !important; }
  .sa-auth-plan-grid { flex-direction: column; }
  .sa-auth-title-block h1 { font-size: 1.4rem; }
  .sa-auth-social { grid-template-columns: 1fr; } /* stack Google/GitHub on tiny screens */
  .sa-auth-steps-indicator { gap: 0; }
  .sa-auth-step-pill { padding: 8px 12px; font-size: 13px; }
  .sa-auth-step-line { width: 24px; margin: 0 4px; }
}
/* Landscape phones / very short viewports: reduce vertical padding */
@media (max-height: 680px) and (max-width: 900px) {
  .sa-auth-form-centered { align-items: flex-start; padding-top: 24px; }
}

/* ============================================
   Figma Design System — Component Library
   ============================================ */

/* --- Severity Badges (10% opacity pattern) --- */
.sa-badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 12px;
  font-weight: 500;
  padding: 2px 8px;
  border-radius: var(--sa-radius-badge);
  border: 1px solid;
  line-height: 1.5;
}
.sa-badge-critical {
  background: var(--sa-severity-critical-bg);
  color: var(--sa-severity-critical);
  border-color: var(--sa-severity-critical-border);
}
.sa-badge-warning {
  background: var(--sa-severity-warning-bg);
  color: var(--sa-severity-warning);
  border-color: var(--sa-severity-warning-border);
}
.sa-badge-good {
  background: var(--sa-severity-good-bg);
  color: var(--sa-severity-good);
  border-color: var(--sa-severity-good-border);
}
.sa-badge-info {
  background: var(--sa-severity-info-bg);
  color: var(--sa-severity-info);
  border-color: var(--sa-severity-info-border);
}
.sa-badge-md {
  padding: 4px 12px;
  font-size: 13px;
}
.sa-badge-purple {
  background: var(--sa-purple-light);
  color: var(--sa-purple);
  border-color: rgba(147, 51, 234, 0.2);
}

/* --- Card (Figma pattern) --- */
.sa-card {
  background: white;
  border: 1px solid rgba(15, 23, 42, 0.06);
  border-radius: var(--sa-radius-card);
  box-shadow:
    0 1px 2px rgba(15, 23, 42, 0.04),
    0 4px 16px -8px rgba(15, 23, 42, 0.08);
  transition: box-shadow 0.2s ease, transform 0.2s ease;
}
.sa-card-padded {
  padding: 24px;
}
.sa-card:hover {
  box-shadow:
    0 2px 4px rgba(15, 23, 42, 0.05),
    0 12px 28px -12px rgba(15, 23, 42, 0.14);
}

/* --- MudPaper content cards: soft shadow so white cards stand out on the
   light-gray page background. Scoped to .sa-main so dropdowns/popovers
   (rendered outside the content area) keep their own elevation. --- */
.sa-main .mud-paper {
  box-shadow:
    0 1px 2px rgba(15, 23, 42, 0.04),
    0 8px 24px -12px rgba(15, 23, 42, 0.10) !important;
  border-color: rgba(15, 23, 42, 0.06) !important;
}

/* --- Stat Card (Dashboard) --- */
.sa-stat-card {
  position: relative;
  background: white;
  border: 1px solid rgba(15, 23, 42, 0.06);
  border-radius: var(--sa-radius-card);
  padding: 24px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  box-shadow:
    0 1px 2px rgba(15, 23, 42, 0.04),
    0 4px 16px -8px rgba(15, 23, 42, 0.08);
  transition: box-shadow 0.2s ease, transform 0.2s ease, border-color 0.2s ease;
}
.sa-stat-card:hover {
  box-shadow:
    0 2px 4px rgba(15, 23, 42, 0.05),
    0 12px 28px -12px rgba(15, 23, 42, 0.14);
}
.sa-stat-card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.sa-stat-card-title {
  font-size: 13px;
  font-weight: 500;
  color: var(--sa-text-muted);
}
.sa-stat-card-icon {
  width: 40px;
  height: 40px;
  border-radius: var(--sa-radius-icon);
  display: flex;
  align-items: center;
  justify-content: center;
}
/* Soft tinted tile + coloured glyph, replacing the saturated gradient + white
   glyph. Six blocks of vivid colour across a row of stat cards competed with the
   figures the cards exist to show; a pale wash of the same hue identifies the
   card just as well and lets the number lead.

   Each glyph colour is the darkened shade of its tint, so it clears WCAG AA on
   the pale background — the vivid brand values (#10b981, #f59e0b, #06D6D1) sit
   at roughly 2–3:1 there and would fail.

   `amber` is included: SchedulesPage and ManageUsers both pass it, and it had no
   rule at all, which under the old white-glyph default meant white on white. */
.sa-stat-card-icon.blue   { background: rgba(37, 99, 235, 0.10);  color: #1d4ed8; }
.sa-stat-card-icon.green  { background: rgba(16, 185, 129, 0.12); color: #047857; }
.sa-stat-card-icon.orange { background: rgba(245, 158, 11, 0.14); color: #b45309; }
.sa-stat-card-icon.amber  { background: rgba(245, 158, 11, 0.14); color: #b45309; }
.sa-stat-card-icon.red    { background: rgba(239, 68, 68, 0.10);  color: #b91c1c; }
.sa-stat-card-icon.purple { background: rgba(124, 58, 237, 0.10); color: #6d28d9; }
.sa-stat-card-icon.cyan   { background: rgba(6, 214, 209, 0.14);  color: #0e7490; }

/* Any colour name without a rule above still gets a visible tile rather than an
   invisible one. */
.sa-stat-card-icon { background: rgba(15, 23, 42, 0.06); color: #475569; }
.sa-stat-card-value {
  font-size: 30px;
  font-weight: 700;
  color: var(--sa-text-primary);
  line-height: 1;
  letter-spacing: -0.02em;
}
.sa-stat-card-trend {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 13px;
  font-weight: 500;
}
.sa-stat-card-trend.up { color: var(--sa-success); }
.sa-stat-card-trend.down { color: var(--sa-error); }
.sa-stat-card-subtitle {
  font-size: 12px;
  color: var(--sa-text-faint);
}
.sa-stat-card-clickable {
  cursor: pointer;
}
.sa-stat-card-clickable:hover {
  border-color: rgba(37, 99, 235, 0.4);
  box-shadow:
    0 2px 4px rgba(15, 23, 42, 0.05),
    0 12px 28px -12px rgba(37, 99, 235, 0.25);
}
.sa-stat-card-clickable:focus-visible {
  outline: 3px solid rgba(37, 99, 235, 0.45);
  outline-offset: 2px;
}
/* Clickable affordance — plain arrow in the bottom-right corner */
.sa-stat-card-arrow {
  position: absolute;
  bottom: 16px;
  right: 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--sa-text-faint, #9ca3af);
  opacity: 0.5;
  transition: opacity 0.2s ease, transform 0.2s ease, color 0.2s ease;
}
.sa-stat-card-clickable:hover .sa-stat-card-arrow {
  opacity: 1;
  color: var(--sa-primary, #2563eb);
  transform: translateX(2px);
}

/* --- Table (Figma pattern) --- */
.sa-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
}
.sa-table th {
  height: 40px;
  padding: 0 12px;
  font-weight: 500;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--sa-text-muted);
  background: var(--sa-surface-light);
  text-align: left;
  white-space: nowrap;
  border-bottom: 1px solid var(--sa-border);
}
.sa-table td {
  padding: 10px 12px;
  color: var(--sa-text-secondary);
  border-bottom: 1px solid rgba(0, 0, 0, 0.06);
  white-space: nowrap;
}
.sa-table tbody tr:hover {
  background: rgba(0, 0, 0, 0.02);
}
.sa-table tbody tr:last-child td {
  border-bottom: none;
}

/* --- Input Fields (Figma pattern) --- */
.sa-input {
  width: 100%;
  background: var(--sa-input-bg);
  border: 1px solid var(--sa-border);
  border-radius: var(--sa-radius-input);
  padding: 12px 16px;
  font-size: 14px;
  font-family: inherit;
  color: var(--sa-text-primary);
  transition: border-color 0.15s, box-shadow 0.15s;
  outline: none;
}
.sa-input::placeholder {
  color: var(--sa-text-placeholder);
}
.sa-input:focus {
  border-color: transparent;
  box-shadow: 0 0 0 2px var(--sa-primary);
}
.sa-input-with-icon {
  padding-left: 40px;
}
.sa-input-icon {
  position: absolute;
  left: 12px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--sa-text-faint);
  pointer-events: none;
}

/* --- Progress Bar (Figma pattern) --- */
.sa-progress {
  width: 100%;
  height: 8px;
  background: rgba(37, 99, 235, 0.15);
  border-radius: 999px;
  overflow: hidden;
}
.sa-progress-fill {
  height: 100%;
  border-radius: 999px;
  background: var(--sa-primary);
  transition: width 0.3s ease;
}
.sa-progress-fill.green { background: var(--sa-success); }
.sa-progress-fill.orange { background: var(--sa-warning); }
.sa-progress-fill.red { background: var(--sa-error); }
.sa-progress-fill.purple { background: var(--sa-purple); }
.sa-progress-sm { height: 4px; }
.sa-progress-lg { height: 12px; }

/* --- Quick Action Cards --- */
.sa-action-card {
  background: white;
  border: 1px solid rgba(15, 23, 42, 0.06);
  border-radius: var(--sa-radius-card);
  padding: 20px;
  display: flex;
  align-items: center;
  gap: 16px;
  cursor: pointer;
  box-shadow:
    0 1px 2px rgba(15, 23, 42, 0.04),
    0 4px 16px -8px rgba(15, 23, 42, 0.08);
  transition: box-shadow 0.2s ease, border-color 0.2s ease, transform 0.2s ease;
}
.sa-action-card:hover {
  box-shadow:
    0 2px 4px rgba(15, 23, 42, 0.05),
    0 12px 28px -12px rgba(15, 23, 42, 0.16);
  border-color: rgba(37, 99, 235, 0.4);
}
.sa-action-card:focus-visible {
  outline: 3px solid rgba(37, 99, 235, 0.45);
  outline-offset: 2px;
}
.sa-action-card-icon {
  width: 44px;
  height: 44px;
  border-radius: var(--sa-radius-icon);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  transition: transform 0.2s ease;
}
.sa-action-card:hover .sa-action-card-icon {
  transform: scale(1.08);
}
.sa-action-card-content h4 {
  font-size: 14px;
  font-weight: 600;
  color: var(--sa-text-primary);
  margin: 0 0 2px;
}
.sa-action-card-content p {
  font-size: 13px;
  color: var(--sa-text-muted);
  margin: 0;
}

/* --- Dashboard Grid Layouts --- */
.sa-grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 20px; }
.sa-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
.sa-grid-4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: 20px; }
.sa-grid-5 { display: grid; grid-template-columns: repeat(5, 1fr); gap: 20px; }
@media (max-width: 1280px) {
  .sa-grid-5 { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 1024px) {
  .sa-grid-4 { grid-template-columns: repeat(2, 1fr); }
  .sa-grid-3 { grid-template-columns: repeat(2, 1fr); }
  .sa-grid-5 { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 640px) {
  .sa-grid-4, .sa-grid-3, .sa-grid-2, .sa-grid-5 { grid-template-columns: 1fr; }
}

/* --- Back Button (icon-only, consistent across all pages) --- */
.sa-back-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  padding: 0;
  flex-shrink: 0;
  background: #ffffff;
  border: 1px solid rgba(15, 23, 42, 0.12);
  border-radius: 12px;
  color: var(--sa-text-secondary, #475569);
  text-decoration: none;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
}
.sa-back-btn svg {
  width: 20px;
  height: 20px;
  flex-shrink: 0;
}
.sa-back-btn:hover {
  background: #f8fafc;
  border-color: rgba(37, 99, 235, 0.4);
  color: var(--sa-primary, #2563eb);
  box-shadow: 0 1px 4px rgba(15, 23, 42, 0.08);
}
.sa-back-btn:focus-visible {
  outline: 3px solid rgba(37, 99, 235, 0.45);
  outline-offset: 2px;
}

/* --- Section Title (Dashboard & content section headers) --- */
.sa-section-title {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 18px;
  font-weight: 700;
  color: #0f172a;
  letter-spacing: -0.01em;
  line-height: 1.3;
}
/* Brand accent bar before the title */
.sa-section-title::before {
  content: '';
  flex-shrink: 0;
  width: 4px;
  height: 20px;
  border-radius: 3px;
  background: linear-gradient(to bottom, #2563eb, #06D6D1);
}

/* --- Table Pagination (reusable Pagination component) --- */
.sa-pager {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 16px;
  padding: 16px 4px 4px;
}
.sa-pager-left {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 14px;
  color: var(--sa-text-muted, #6b7280);
}
.sa-pager-size {
  height: 34px;
  padding: 0 10px;
  border: 1px solid rgba(15, 23, 42, 0.12);
  border-radius: 8px;
  background: #fff;
  font-family: inherit;
  font-size: 14px;
  color: var(--sa-text-primary, #111827);
  cursor: pointer;
}
.sa-pager-right {
  display: flex;
  align-items: center;
  gap: 6px;
}
.sa-pager-btn {
  min-width: 34px;
  height: 34px;
  padding: 0 8px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid rgba(15, 23, 42, 0.12);
  border-radius: 8px;
  background: #fff;
  color: var(--sa-text-secondary, #475569);
  font-family: inherit;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s, color 0.15s;
}
.sa-pager-btn:hover:not(:disabled):not(.active) {
  border-color: rgba(37, 99, 235, 0.4);
  color: var(--sa-primary, #2563eb);
  background: rgba(37, 99, 235, 0.06);
}
.sa-pager-btn.active {
  background: var(--sa-primary, #2563eb);
  border-color: var(--sa-primary, #2563eb);
  color: #fff;
  cursor: default;
}
.sa-pager-btn:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}
.sa-pager-btn:focus-visible,
.sa-pager-size:focus-visible {
  outline: 3px solid rgba(37, 99, 235, 0.35);
  outline-offset: 2px;
}
.sa-pager-ellipsis {
  min-width: 24px;
  text-align: center;
  color: var(--sa-text-faint, #9ca3af);
}
@media (max-width: 560px) {
  .sa-pager { justify-content: center; }
}

/* --- AI Accent Gradient Card --- */
.sa-ai-card {
  background: var(--sa-gradient-ai);
  border-radius: var(--sa-radius-card);
  padding: 24px;
  color: white;
}
.sa-ai-card h3 {
  font-size: 18px;
  font-weight: 700;
  margin: 0 0 8px;
}
.sa-ai-card p {
  font-size: 14px;
  color: rgba(255, 255, 255, 0.85);
  margin: 0;
}

/* --- Tab Bar (Figma pattern) --- */
.sa-tabs {
  display: flex;
  gap: 4px;
  background: var(--sa-input-bg);
  padding: 3px;
  border-radius: var(--sa-radius-card);
}
.sa-tab {
  padding: 8px 16px;
  font-size: 14px;
  font-weight: 500;
  color: var(--sa-text-muted);
  border-radius: var(--sa-radius-sm);
  cursor: pointer;
  transition: all 0.15s;
  border: none;
  background: none;
  font-family: inherit;
}
.sa-tab:hover {
  color: var(--sa-text-primary);
}
.sa-tab.active {
  background: white;
  color: var(--sa-text-primary);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
}

/* --- Avatar --- */
.sa-avatar {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  font-weight: 600;
  color: white;
  background: var(--sa-primary);
  flex-shrink: 0;
}
.sa-avatar-sm { width: 32px; height: 32px; font-size: 12px; }
.sa-avatar-lg { width: 48px; height: 48px; font-size: 16px; }

/* --- Notification Bell --- */
.sa-notification-badge {
  position: relative;
}
.sa-notification-badge .sa-bell-count {
  position: absolute;
  top: -4px;
  right: -4px;
  min-width: 18px;
  height: 18px;
  border-radius: 999px;
  background: var(--sa-error);
  color: white;
  font-size: 10px;
  font-weight: 600;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 4px;
  animation: sa-sparkle 2.5s ease-in-out infinite;
}

/* --- Focus visible utility --- */
*:focus-visible {
  outline: 2px solid var(--sa-primary);
  outline-offset: 2px;
}

/* Disable MudBlazor's default ALL-CAPS button text globally so toolbar buttons
   (Export / Share / Refresh / Filter) match the rest of the platform's title-cased
   buttons. Letter-spacing reset so text doesn't look stretched after losing uppercase.
   Same override is applied in JobPortal/AdminPortal premium.css for cross-portal
   consistency. The .mud-dialog-actions block below stays — it adds extra polish
   (border-radius, padding) specific to modal action rows. */
.mud-button-root {
  text-transform: none !important;
  letter-spacing: 0 !important;
  font-weight: 600;
}

/* --- Polished dialog action buttons (applies to ALL MudBlazor modals:
   create/edit/confirm forms) so Cancel + primary look consistent --- */
.mud-dialog-actions {
  padding: 14px 24px 20px !important;
  gap: 10px;
}
.mud-dialog-actions .mud-button-root {
  border-radius: 12px;
  font-weight: 600;
  text-transform: none;
  padding: 8px 18px;
  min-height: 40px;
  transition: background 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
}
/* Secondary / Cancel (text variant) — give it a clean outlined look instead of bare grey */
.mud-dialog-actions .mud-button-text {
  color: var(--sa-text-secondary, #374151) !important;
  background: #ffffff !important;
  border: 1px solid var(--sa-border, rgba(15, 23, 42, 0.14)) !important;
}
.mud-dialog-actions .mud-button-text:hover {
  background: #f3f4f6 !important;
  border-color: rgba(15, 23, 42, 0.24) !important;
}
/* Primary / filled (Save, Create) — subtle lift on hover */
.mud-dialog-actions .mud-button-filled.mud-button-filled-primary {
  box-shadow: 0 1px 2px rgba(37, 99, 255, 0.25);
}
.mud-dialog-actions .mud-button-filled.mud-button-filled-primary:hover {
  box-shadow: 0 4px 12px rgba(37, 99, 255, 0.30);
}

/* --- Frosted-glass blur behind modals (matches Admin Portal) --- */
.mud-overlay-dialog .mud-overlay-scrim {
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
}

/* Mobile: keep dialogs and popovers (selects, menus) within the viewport so
   their content can't be cut off at the right edge. */
@media (max-width: 600px) {
  .mud-dialog {
    max-width: calc(100vw - 24px) !important;
    margin: 12px !important;
  }
  /* Dialog bodies often set an inline min-width for a comfortable desktop
     size; on phones that forces an inner horizontal scrollbar, so drop it
     and let the content fill the (already viewport-capped) dialog. */
  .mud-dialog [style*="min-width"] {
    min-width: 0 !important;
  }
  .mud-popover {
    max-width: calc(100vw - 16px) !important;
  }
}

/* --- Card ⋮ action menu (Edit / Delete) ---
   Rounded card with a soft shadow; each row is a rounded pill with its icon in a tinted chip
   (blue for Edit, red for Delete). MudBlazor 9 renders the icon as the <svg> itself
   (.mud-menu-item-icon), so the chip is painted straight onto the svg via padding + background. */
.mud-popover.sa-card-actions-menu {
  border-radius: 12px !important;
  border: 1px solid rgba(15, 23, 42, 0.08);
  box-shadow: 0 12px 32px -8px rgba(15, 23, 42, 0.18), 0 2px 6px rgba(15, 23, 42, 0.06) !important;
}
/* Compact: the menu shrink-wraps its two rows instead of reserving a wide empty column. */
.sa-card-actions-menu .mud-menu-list {
  padding: 4px;
  min-width: 0;
}
.sa-card-actions-menu .mud-menu-item {
  gap: 10px;
  padding: 4px 14px 4px 4px;
  border-radius: 8px;
  font-size: 14px;
  font-weight: 500;
  color: var(--sa-text-primary, #111827);
  transition: background 0.15s ease;
}
.sa-card-actions-menu .mud-menu-item:hover {
  background: #f3f6fc;
}
.sa-card-actions-menu .mud-menu-item .mud-menu-item-icon {
  box-sizing: border-box;
  width: 28px;
  height: 28px;
  padding: 5px;
  margin-inline-end: 0;
  border-radius: 8px;
  background: #eef3fd;
  color: var(--sa-primary, #2563FF);
  transition: background 0.15s ease;
}
.sa-card-actions-menu .mud-menu-item-text {
  margin: 0;
}
/* width:auto, not MudBlazor's width:100% — with the side margins that overflowed the list by
   12px and put a horizontal scrollbar on the menu. */
.sa-card-actions-menu .mud-divider {
  width: auto;
  margin: 2px 4px !important;
  border-color: rgba(15, 23, 42, 0.07);
}
/* Delete row — red text, red chip, red-tinted hover */
.sa-card-actions-menu .sa-menu-danger,
.sa-card-actions-menu .sa-menu-danger .mud-menu-item-icon {
  color: var(--sa-error, #d4183d) !important;
}
.sa-card-actions-menu .sa-menu-danger .mud-menu-item-icon {
  background: #fdecef;
}
.sa-card-actions-menu .sa-menu-danger:hover {
  background: #fff1f3;
}
.sa-card-actions-menu .sa-menu-danger:hover .mud-menu-item-icon {
  background: #fbdbe1;
}
/* No permission — keep the row visible but clearly inactive */
.sa-card-actions-menu .mud-menu-item.mud-disabled {
  opacity: 0.45;
}

/* --- Floating "scroll to top" button (landing page) --- */
.sa-scroll-top {
  position: fixed;
  bottom: 24px;
  right: 24px;
  z-index: 1000;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  border: none;
  background: linear-gradient(135deg, #2563FF, #06D6D1);
  color: #ffffff;
  cursor: pointer;
  box-shadow: 0 4px 12px rgba(37, 99, 255, 0.35);
  opacity: 0;
  visibility: hidden;
  transform: translateY(16px);
  transition: opacity 0.3s ease, visibility 0.3s ease, transform 0.3s ease, box-shadow 0.2s ease;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
}
.sa-scroll-top.sa-visible {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}
.sa-scroll-top:hover {
  box-shadow: 0 6px 18px rgba(37, 99, 255, 0.5);
  transform: translateY(-2px);
}
.sa-scroll-top:focus-visible {
  outline: 2px solid #06D6D1;
  outline-offset: 3px;
}
.sa-scroll-top .mud-icon-root {
  font-size: 24px;
  color: inherit;
}
@media (max-width: 640px) {
  .sa-scroll-top {
    bottom: 16px;
    right: 16px;
    width: 44px;
    height: 44px;
  }
}
@media (prefers-reduced-motion: reduce) {
  .sa-scroll-top {
    transition: opacity 0.15s ease, visibility 0.15s ease;
  }
  .sa-scroll-top.sa-visible,
  .sa-scroll-top:hover {
    transform: none;
  }
}

/* ============================================
   Legal Pages (Privacy Policy / Terms of Service)
   Shared by Privacy.razor + Terms.razor.
   ============================================ */
.sa-legal-hero {
  background: var(--sa-gradient-hero);
  /* top = fixed navbar height + breathing room (the first nav-height sits behind the nav) */
  padding: calc(var(--sa-nav-height, 64px) + 32px) 24px 40px;
  color: #fff;
}
.sa-legal-hero-inner {
  max-width: 1080px;
  margin: 0 auto;
}
.sa-legal-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: rgba(255, 255, 255, 0.15);
  border: 1px solid rgba(255, 255, 255, 0.25);
  border-radius: var(--sa-radius-badge, 9999px);
  padding: 5px 14px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  margin-bottom: 16px;
}
.sa-legal-hero h1 {
  font-size: 2.6rem;
  font-weight: 800;
  letter-spacing: -0.02em;
  margin: 0 0 10px;
  line-height: 1.1;
}
.sa-legal-hero-sub {
  font-size: 1rem;
  color: rgba(255, 255, 255, 0.85);
  margin: 0 0 18px;
  max-width: 620px;
  line-height: 1.6;
}
.sa-legal-updated {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 13px;
  color: rgba(255, 255, 255, 0.75);
  font-weight: 500;
}

/* --- Body: sticky TOC + content --- */
.sa-legal-body {
  background: var(--sa-surface-light, #f6f9ff);
  padding: 48px 24px 72px;
}
.sa-legal-inner {
  max-width: 1080px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: 240px 1fr;
  gap: 32px;
  align-items: start;
}
.sa-legal-toc {
  position: sticky;
  top: calc(var(--sa-nav-height, 64px) + 20px);
  background: #fff;
  border: 1px solid var(--sa-border, rgba(0, 0, 0, 0.1));
  border-radius: var(--sa-radius-card, 12px);
  padding: 18px;
}
.sa-legal-toc-title {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--sa-text-placeholder, #9ca3af);
  margin-bottom: 12px;
}
.sa-legal-toc a {
  display: block;
  padding: 7px 10px;
  border-radius: var(--sa-radius-sm, 8px);
  font-size: 13px;
  font-weight: 500;
  color: var(--sa-text-muted, #717182);
  text-decoration: none;
  transition: color 0.15s, background 0.15s;
}
.sa-legal-toc a:hover {
  color: var(--sa-primary);
  background: var(--sa-primary-light, rgba(37, 99, 255, 0.1));
}

/* --- Content card --- */
.sa-legal-content {
  background: #fff;
  border: 1px solid var(--sa-border, rgba(0, 0, 0, 0.1));
  border-radius: var(--sa-radius-card, 12px);
  padding: 40px 44px;
  box-shadow: 0 1px 2px rgba(16, 40, 90, 0.04), 0 10px 30px rgba(16, 40, 90, 0.05);
}
.sa-legal-section {
  /* Clear the fixed navbar when jumping from the table of contents */
  scroll-margin-top: calc(var(--sa-nav-height, 64px) + 20px);
}
.sa-legal-section + .sa-legal-section {
  margin-top: 34px;
  padding-top: 34px;
  border-top: 1px solid var(--sa-border, rgba(0, 0, 0, 0.08));
}
.sa-legal-section h2 {
  display: flex;
  align-items: center;
  gap: 12px;
  font-size: 1.2rem;
  font-weight: 700;
  color: var(--sa-text-primary, #111827);
  margin: 0 0 12px;
  letter-spacing: -0.01em;
}
.sa-legal-num {
  flex-shrink: 0;
  width: 28px;
  height: 28px;
  border-radius: 8px;
  background: var(--sa-primary-light, rgba(37, 99, 255, 0.1));
  color: var(--sa-primary);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  font-weight: 800;
}
.sa-legal-section p {
  font-size: 15px;
  line-height: 1.8;
  color: var(--sa-text-tertiary, #374151);
  margin: 0;
}
.sa-legal-section p + p {
  margin-top: 12px;
}
.sa-legal-section a {
  color: var(--sa-primary);
  font-weight: 600;
  text-decoration: none;
}
.sa-legal-section a:hover {
  text-decoration: underline;
}

/* --- Contact CTA at the end --- */
.sa-legal-cta {
  margin-top: 34px;
  padding: 22px 24px;
  border-radius: var(--sa-radius-card, 12px);
  background: var(--sa-primary-light, rgba(37, 99, 255, 0.1));
  border: 1px solid rgba(37, 99, 255, 0.18);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 18px;
  flex-wrap: wrap;
}
.sa-legal-cta-text strong {
  display: block;
  font-size: 15px;
  color: var(--sa-text-primary, #111827);
  margin-bottom: 3px;
}
.sa-legal-cta-text span {
  font-size: 13.5px;
  color: var(--sa-text-muted, #717182);
}

@media (max-width: 900px) {
  .sa-legal-inner { grid-template-columns: 1fr; }
  .sa-legal-toc { display: none; }   /* sticky rail adds nothing on narrow screens */
  .sa-legal-content { padding: 28px 22px; }
  .sa-legal-hero h1 { font-size: 2rem; }
  .sa-legal-hero { padding: calc(var(--sa-nav-height, 64px) + 20px) 16px 28px; }
  .sa-legal-body { padding: 24px 16px 40px; }
}


/* ── MudBlazor progress → canonical Elvisto loader ─────────────────────────
   MudProgressCircular renders its own SVG ring. Rather than editing every
   call site, we hide that SVG and paint the same comet used by .sa-spinner, so
   Mud-based dialogs, tables and submit buttons match the rest of the app. */
.mud-progress-circular { position: relative; }
.mud-progress-circular > svg { visibility: hidden; }
.mud-progress-circular::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: conic-gradient(from 0deg, transparent 0 55%, rgba(6, 214, 209,0.12) 68%, rgba(6, 214, 209,0.5) 86%, #06D6D1 97%);
  -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 14%), #000 calc(100% - 13%));
          mask: radial-gradient(farthest-side, transparent calc(100% - 14%), #000 calc(100% - 13%));
  filter: drop-shadow(0 0 5px rgba(6, 214, 209, 0.6));
  animation: sa-spin 1.05s linear infinite;
}
/* Lens only on the large variant — at small/medium sizes it's unreadable. */
.mud-progress-circular.mud-progress-circular-size-large::after {
  content: '';
  position: absolute;
  inset: 0;
  margin: auto;
  width: 48%;
  height: 48%;
  background: url('/logo-icon.svg') center / contain no-repeat;
  animation: sa-loader-zoom 1.6s ease-in-out infinite;
}
/* Indeterminate linear bars get the brand gradient too. */
.mud-progress-linear.mud-progress-indeterminate .mud-progress-linear-bar {
  background: linear-gradient(90deg, #2563FF, #06D6D1) !important;
}

/* --- Accessibility utility: visually-hidden --- */
/* Content stays in the accessibility tree for screen readers but is hidden visually.
   Used for <caption> elements on data tables and any label that would look cluttered
   on screen but is essential for assistive tech. Standard "clip" pattern. */
.sa-visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* --- Score period picker label (Dashboard) --- */
/* Replaces the old plain <span> that used to sit next to the period <select>. Same
   visual weight, but semantically a <label for="..."> for screen-reader users. */
.sa-score-period-label {
  font-size: 13px;
  color: var(--sa-text-muted);
  font-weight: 500;
}

/* ===========================================================================
   SHARE AUDIT DIALOG  (.sa-share-dlg)

   Lives here rather than in AuditDetail.razor.css because MudBlazor renders
   dialogs outside the page's component tree, where scoped CSS cannot reach.

   Brand note: MudBlazor's default primary is purple (#594AE2) and the theme
   does not override it, so Color.Primary buttons render off-brand. Rather
   than retheme the whole portal from one dialog, the action buttons here are
   plain elements painted in Elvisto blue.
   =========================================================================== */

.sa-share-dlg { border-radius: 16px !important; }

.sa-share-dlg .mud-dialog-title { padding: 22px 24px 4px !important; }
.sa-share-dlg .mud-dialog-content { padding: 16px 24px 4px !important; }

/* --- Header --- */

.sa-share-head {
  display: flex;
  align-items: center;
  gap: 12px;
}

.sa-share-head-icon {
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  flex-shrink: 0;
  border-radius: 12px;
  background: #eef3fc;
  color: #2563FF;
}

.sa-share-head-title {
  font-size: 17px;
  font-weight: 700;
  line-height: 1.25;
  color: #0f1a2e;
}

/* --- Fields ---
   Both inputs are Outlined + Dense in the markup; this is just the rhythm
   between them and a softer corner than MudBlazor's 4px default. */

.sa-share-dlg .sa-share-input { margin-bottom: 18px; }
.sa-share-dlg .sa-share-input:last-child { margin-bottom: 6px; }

.sa-share-dlg .sa-share-input .mud-input-outlined-border { border-radius: 12px; }

.sa-share-dlg .sa-share-input .mud-input-helper-text {
  margin-top: 5px;
  font-size: 11.5px;
  color: #64728c;
}

/* --- Success state --- */

.sa-share-done-head {
  display: flex;
  align-items: center;
  gap: 9px;
  margin-bottom: 13px;
  font-size: 14px;
  font-weight: 700;
  color: #0f1a2e;
}

.sa-share-done-tick {
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  flex-shrink: 0;
  border-radius: 50%;
  background: #0f7a48;
  color: #ffffff;
}

/* The URL is the payload. Monospaced and on its own fill so it reads as
   something to copy rather than something to read. */
.sa-share-url {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 10px 10px 14px;
  border-radius: 12px;
  background: #f4f7fc;
}

.sa-share-url-text {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-family: ui-monospace, SFMono-Regular, Consolas, monospace;
  font-size: 12px;
  color: #3d4a61;
}

.sa-share-copy {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
  padding: 8px 13px;
  border: 0;
  border-radius: 8px;
  background: #2563FF;
  color: #ffffff;
  font: 700 12.5px/1 inherit;
  font-family: inherit;
  cursor: pointer;
  transition: background 0.14s ease;
}

.sa-share-copy:hover { background: #1C4CC4; }

/* --- Actions --- */

.sa-share-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 40px;
  padding: 9px 20px;
  border-radius: 12px;
  font: 700 13.5px/1 inherit;
  font-family: inherit;
  cursor: pointer;
  transition: background 0.14s ease, border-color 0.14s ease, box-shadow 0.14s ease;
}

.sa-share-btn-ghost {
  border: 1px solid rgba(15, 23, 42, 0.14);
  background: #ffffff;
  color: #3d4a61;
}

.sa-share-btn-ghost:hover {
  background: #f3f4f6;
  border-color: rgba(15, 23, 42, 0.24);
}

.sa-share-btn-solid {
  border: 1px solid #2563FF;
  background: #2563FF;
  color: #ffffff;
  box-shadow: 0 1px 2px rgba(37, 99, 255, 0.25);
}

.sa-share-btn-solid:hover:not(:disabled) {
  background: #1C4CC4;
  border-color: #1C4CC4;
  box-shadow: 0 4px 12px rgba(37, 99, 255, 0.30);
}

.sa-share-btn-solid:disabled {
  opacity: 0.6;
  cursor: default;
  box-shadow: none;
}

@media (max-width: 600px) {
  .sa-share-url { flex-wrap: wrap; }
  .sa-share-url-text { flex-basis: 100%; }
}

/* =============================================================================
   LANDING: fluid type scale, product demo, book-a-demo
   =============================================================================
   The headings were fixed pixel sizes with one mobile breakpoint, so between
   480px and 1400px they were the wrong size everywhere except at the two widths
   that had been checked. clamp() sizes them continuously instead, which is what
   makes a page feel considered at any width rather than only at the designer's.
   ============================================================================= */

.sa-hero h1 {
  font-size: clamp(2.1rem, 1.25rem + 3.4vw, 4rem);
  line-height: 1.08;
  letter-spacing: -0.033em;
}
.sa-hero-subtitle {
  font-size: clamp(1.02rem, 0.94rem + 0.42vw, 1.32rem);
  line-height: 1.62;
}
.sa-section .sa-section-title {
  font-size: clamp(1.65rem, 1.15rem + 1.75vw, 2.85rem);
  line-height: 1.13;
  letter-spacing: -0.028em;
}
.sa-section-subtitle {
  font-size: clamp(1rem, 0.94rem + 0.3vw, 1.2rem);
  line-height: 1.66;
  max-width: 620px;
}
.sa-section { padding: clamp(64px, 4.4vw + 40px, 116px) 24px; }

/* Scroll reveal with more travel and a spring, rather than the flat fade it had.
   Reduced-motion is already neutralised in animations.css. */
.sa-animate-on-scroll {
  transform: translateY(26px);
  transition: opacity .72s cubic-bezier(.16, 1, .3, 1), transform .72s cubic-bezier(.16, 1, .3, 1);
}

/* -----------------------------------------------------------------------------
   Product demo
   -------------------------------------------------------------------------- */
/* Two soft brand lights behind the frame. Pure CSS, so they cost nothing to load
   and cannot 404 the way a background image can. */
.sa-demo::before,

.sa-demo .sa-section-header { text-align: center; margin-bottom: 42px; }

/* The shared title carries a gradient bar via ::before that only reads on a light
   background, and centring a flex heading needs saying explicitly. */

.sa-demo-stage { position: relative; }
.sa-demo-frame {
  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 16px;
  overflow: hidden;
  background: linear-gradient(150deg, #12306b, #0a1f4d 60%, #071634);
  box-shadow: 0 34px 80px rgba(3, 12, 33, 0.55);
}
.sa-demo-frame iframe { width: 100%; height: 100%; border: 0; display: block; }

.sa-demo-poster {
  cursor: pointer;
  padding: 0;
  text-align: center;
  transition: transform .4s cubic-bezier(.16, 1, .3, 1), box-shadow .4s ease;
}
.sa-demo-poster:hover { transform: translateY(-4px); box-shadow: 0 42px 96px rgba(3, 12, 33, 0.62); }
.sa-demo-poster:focus-visible { outline: 3px solid #7fe6f4; outline-offset: 4px; }

/* Mock browser bar - it reads as "this is the actual product" faster than a
   caption can say it. */
.sa-demo-chrome {
  position: absolute;
  inset: 0 0 auto 0;
  display: flex;
  align-items: center;
  gap: 7px;
  height: 40px;
  padding: 0 15px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.09);
  background: rgba(255, 255, 255, 0.05);
}
.sa-demo-dot { width: 10px; height: 10px; border-radius: 50%; background: rgba(255, 255, 255, 0.22); }
.sa-demo-addr {
  margin-left: 12px;
  padding: 3px 12px;
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.08);
  color: rgba(226, 240, 255, 0.6);
  font-size: 11.5px;
  font-family: 'Cascadia Code', 'Consolas', monospace;
}


.sa-demo-play {
  position: absolute;
  left: 50%;
  top: 52%;
  transform: translate(-50%, -50%);
  display: grid;
  place-items: center;
  width: 76px;
  height: 76px;
  padding-left: 5px;                 /* optical centring: a triangle is not a square */
  border-radius: 50%;
  background: #fff;
  color: var(--sa-primary);
  box-shadow: 0 12px 34px rgba(0, 0, 0, 0.34);
  transition: transform .28s cubic-bezier(.16, 1, .3, 1);
}
.sa-demo-poster:hover .sa-demo-play { transform: translate(-50%, -50%) scale(1.09); }


/* -----------------------------------------------------------------------------
   Book a demo
   -------------------------------------------------------------------------- */
.sa-bd { padding: clamp(64px, 4.4vw + 40px, 116px) 24px; background: var(--sa-surface-light); }

.sa-bd-title {
  margin: 0 0 15px;
  font-size: clamp(1.65rem, 1.15rem + 1.75vw, 2.7rem);
  font-weight: 800;
  line-height: 1.12;
  letter-spacing: -0.028em;
  color: var(--sa-text-primary);
}
.sa-bd-lede { margin: 0 0 26px; font-size: 1.06rem; line-height: 1.66; color: var(--sa-text-muted); }


.sa-bd-field { margin-bottom: 15px; }
.sa-bd-field label {
  display: block;
  margin-bottom: 6px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--sa-text-secondary);
}
.sa-bd-opt { font-weight: 400; color: var(--sa-text-placeholder); }
.sa-bd-field input,
.sa-bd-field textarea {
  width: 100%;
  padding: 11px 13px;
  border: 1px solid var(--sa-border);
  border-radius: 12px;
  background: #fff;
  font-family: inherit;
  font-size: 14px;
  color: var(--sa-text-primary);
  transition: border-color .16s ease, box-shadow .16s ease;
}
.sa-bd-field input:focus,
.sa-bd-field textarea:focus {
  outline: none;
  border-color: var(--sa-primary);
  box-shadow: 0 0 0 3px var(--sa-primary-light);
}
.sa-bd-field textarea { resize: vertical; min-height: 74px; }

/* Collapsed until the captcha is armed on first interaction, so the layout does
   not reserve a gap for a widget nobody has asked for yet. */
.sa-bd-turnstile { max-height: 0; overflow: hidden; transition: max-height .3s ease, margin .3s ease; }
.sa-bd-turnstile.is-armed { max-height: 90px; margin-bottom: 15px; }

.sa-bd-error { margin: 0 0 13px; font-size: 13px; color: var(--sa-error); }

.sa-bd-submit {
  width: 100%;
  padding: 13px 20px;
  border: 0;
  border-radius: 12px;
  background: var(--sa-gradient-btn);
  color: #fff;
  font-family: inherit;
  font-size: 15px;
  font-weight: 700;
  cursor: pointer;
  transition: transform .16s ease, box-shadow .16s ease, opacity .16s ease;
}
.sa-bd-submit:hover:not(:disabled) { transform: translateY(-2px); box-shadow: 0 12px 26px rgba(37, 99, 235, 0.32); }
.sa-bd-submit:disabled { opacity: .5; cursor: not-allowed; }

.sa-bd-fine { margin: 13px 0 0; font-size: 11.5px; line-height: 1.5; color: var(--sa-text-placeholder); text-align: center; }

.sa-bd-done { text-align: center; padding: 26px 0; }
.sa-bd-done-icon {
  display: grid;
  place-items: center;
  width: 56px;
  height: 56px;
  margin: 0 auto 17px;
  border-radius: 50%;
  background: rgba(4, 120, 87, 0.12);
  color: var(--sa-success);
}
.sa-bd-done-icon svg { width: 27px; height: 27px; }
.sa-bd-done h3 { margin: 0 0 8px; font-size: 19px; font-weight: 700; color: var(--sa-text-primary); }
.sa-bd-done p { margin: 0; font-size: 14px; line-height: 1.6; color: var(--sa-text-muted); }

@media (max-width: 520px) {
  .sa-demo-play { width: 60px; height: 60px; }
  .sa-demo-caption { bottom: 16px; font-size: 12.5px; }
}

/* =============================================================================
   HERO — depth, motion, entrance
   =============================================================================
   The previous hero was one flat 135deg ramp from navy to cyan. A single linear
   gradient has no depth cue anywhere on it, which is why a large one reads as
   "unfinished template" however good the colours are. What follows keeps the
   brand hues but builds them in layers: a deep base, three slow-drifting light
   sources, a fine grid for scale, and a vignette to hold the edges.
   ============================================================================= */

.sa-hero {
  /* Deeper and darker than before. White text on the old mid-blue sat around
     5:1; on this base it clears 12:1, and the cyan accents finally read as
     accents rather than competing with the headline. */
  background:
    radial-gradient(1200px 620px at 78% 12%, rgba(6, 214, 209, 0.20), transparent 62%),
    radial-gradient(980px 560px at 12% 82%, rgba(59, 130, 246, 0.24), transparent 64%),
    linear-gradient(168deg, #040b24 0%, #071744 34%, #0b2568 66%, #0a1b4d 100%);
  padding: clamp(104px, 7vw + 60px, 168px) 24px clamp(72px, 4vw + 44px, 112px);
  isolation: isolate;
}

/* --- Drifting light sources ------------------------------------------------
   Two blurred blobs on long, mismatched loops (19s and 27s) so the pair never
   settles into a visible repeat. Blur is heavy enough that the shapes read as
   light rather than as circles. */
.sa-hero::before,
.sa-hero::after {
  content: '';
  position: absolute;
  z-index: -1;
  border-radius: 50%;
  filter: blur(110px);
  pointer-events: none;
}
.sa-hero::before {
  width: 620px;
  height: 620px;
  top: -180px;
  right: -120px;
  background: radial-gradient(circle, rgba(6, 214, 209, 0.38), transparent 68%);
  animation: sa-hero-drift-a 19s ease-in-out infinite;
}
.sa-hero::after {
  width: 720px;
  height: 720px;
  bottom: -300px;
  left: -180px;
  background: radial-gradient(circle, rgba(99, 102, 241, 0.34), transparent 70%);
  animation: sa-hero-drift-b 27s ease-in-out infinite;
}
@keyframes sa-hero-drift-a {
  0%, 100% { transform: translate(0, 0) scale(1); }
  50%      { transform: translate(-70px, 60px) scale(1.13); }
}
@keyframes sa-hero-drift-b {
  0%, 100% { transform: translate(0, 0) scale(1); }
  50%      { transform: translate(90px, -60px) scale(1.09); }
}

/* --- Grid + vignette -------------------------------------------------------
   The grid gives the eye a sense of scale behind the product deck; the mask
   fades it out before it reaches the text, where it would only add noise. */
.sa-hero-inner::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image:
    linear-gradient(rgba(255, 255, 255, 0.045) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.045) 1px, transparent 1px);
  background-size: 56px 56px;
  mask-image: radial-gradient(circle at 50% 40%, #000 0%, transparent 74%);
  -webkit-mask-image: radial-gradient(circle at 50% 40%, #000 0%, transparent 74%);
  pointer-events: none;
}
.sa-hero-inner { position: relative; }

/* --- Badge ---------------------------------------------------------------- */
.sa-hero-badge {
  border: 1px solid rgba(127, 230, 244, 0.28);
  background: rgba(6, 214, 209, 0.11);
  color: #9ceefa;
  backdrop-filter: blur(8px);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.04) inset;
}

/* --- Headline -------------------------------------------------------------
   The accent half now animates its own gradient rather than sitting static.
   Slow (7s) and low-contrast on purpose: a headline that shimmers quickly
   reads as a banner advert. */
.sa-hero h1 { text-wrap: balance; }
.sa-hero-gradient-text {
  background: linear-gradient(100deg, #ffffff 0%, #7fe6f4 32%, #06D6D1 52%, #7fe6f4 72%, #ffffff 100%);
  background-size: 220% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  animation: sa-hero-sheen 7s ease-in-out infinite;
}
@keyframes sa-hero-sheen {
  0%, 100% { background-position: 0% 50%; }
  50%      { background-position: 100% 50%; }
}

.sa-hero-subtitle { color: rgba(219, 234, 254, 0.86); max-width: 560px; }
.sa-hero-note { color: rgba(191, 219, 254, 0.68); }

/* --- Single CTA -----------------------------------------------------------
   One button now carries the whole decision, so it earns more presence: a
   resting glow, and a sweep that crosses on hover. */
.sa-hero-cta {
  position: relative;
  overflow: hidden;
  box-shadow: 0 14px 40px rgba(6, 214, 209, 0.28);
  transition: transform .22s cubic-bezier(.16, 1, .3, 1), box-shadow .22s ease;
}
.sa-hero-cta:hover {
  transform: translateY(-3px);
  box-shadow: 0 20px 52px rgba(6, 214, 209, 0.42);
}
.sa-hero-cta::after {
  content: '';
  position: absolute;
  top: 0;
  left: -120%;
  width: 60%;
  height: 100%;
  background: linear-gradient(100deg, transparent, rgba(255, 255, 255, 0.55), transparent);
  transition: left .62s cubic-bezier(.16, 1, .3, 1);
}
.sa-hero-cta:hover::after { left: 140%; }

/* --- Entrance -------------------------------------------------------------
   Children rise in sequence instead of the whole block appearing at once. The
   delays are on nth-child so no markup carries animation bookkeeping. */
/* The entrance animates transform only - it never touches opacity.

   The first version faded in from opacity:0, and testing showed the hero
   sitting permanently invisible whenever the animation had not progressed:
   a browser that pauses animations in a backgrounded tab leaves the element
   parked on the from-state, and "the headline is blank" is a far worse outcome
   than "the headline did not slide". Sliding degrades to a plain, visible
   heading; fading degrades to nothing at all. For the most important block on
   the site that trade is not close. */
.sa-hero-enter > * {
  animation: sa-hero-rise .82s cubic-bezier(.16, 1, .3, 1) backwards;
}
.sa-hero-enter > *:nth-child(1) { animation-delay: .06s; }
.sa-hero-enter > *:nth-child(2) { animation-delay: .17s; }
.sa-hero-enter > *:nth-child(3) { animation-delay: .28s; }
.sa-hero-enter > *:nth-child(4) { animation-delay: .39s; }
.sa-hero-enter > *:nth-child(5) { animation-delay: .50s; }

.sa-hero-enter-visual {
  animation: sa-hero-rise-visual 1.05s cubic-bezier(.16, 1, .3, 1) .34s backwards;
}

@keyframes sa-hero-rise {
  from { transform: translateY(24px); }
  to   { transform: none; }
}
@keyframes sa-hero-rise-visual {
  from { transform: translateY(32px) scale(.972); }
  to   { transform: none; }
}

/* Motion is decoration here, so none of it should survive a reduced-motion
   preference - including the entrance, which must land on its final state
   rather than never running and leaving the hero blank. */
@media (prefers-reduced-motion: reduce) {
  .sa-hero::before,
  .sa-hero::after,
  .sa-hero-gradient-text { animation: none; }
  .sa-hero-enter > *,
  .sa-hero-enter-visual { animation: none; }
  .sa-hero-cta::after { display: none; }
}

/* =============================================================================
   FEATURE CARDS — colour, depth, motion
   =============================================================================
   Eight identical white rectangles with an identical pale-blue icon gave the eye
   nothing to land on: the grid read as a table of contents rather than as eight
   distinct capabilities. Each card now carries its own accent (set inline as
   --fc), which drives the icon tile, the hover glow and a rule that draws across
   the top on hover. The card itself stays white, so the page keeps its calm.
   ============================================================================= */

.sa-features-grid { gap: 22px; }

.sa-feature-card {
  --fc: var(--sa-primary);                 /* fallback if a card sets no accent */
  position: relative;
  overflow: hidden;
  padding: 26px 24px 28px;
  border: 1px solid var(--sa-border);
  border-radius: 16px;
  background: #fff;
  transition:
    transform .34s cubic-bezier(.16, 1, .3, 1),
    box-shadow .34s cubic-bezier(.16, 1, .3, 1),
    border-color .34s ease;
}

/* Accent rule across the top, drawn on hover from left to right. scaleX on a
   pseudo-element rather than a border-width change, so it cannot reflow. */
.sa-feature-card::before {
  content: '';
  position: absolute;
  inset: 0 0 auto 0;
  height: 3px;
  background: linear-gradient(90deg, var(--fc), color-mix(in srgb, var(--fc) 45%, #06D6D1));
  transform: scaleX(0);
  transform-origin: left;
  transition: transform .42s cubic-bezier(.16, 1, .3, 1);
}

/* A wash of the accent, bottom-right, so the colour is present on hover without
   tinting the text behind it. */
.sa-feature-card::after {
  content: '';
  position: absolute;
  right: -70px;
  bottom: -70px;
  width: 190px;
  height: 190px;
  border-radius: 50%;
  background: radial-gradient(circle, color-mix(in srgb, var(--fc) 20%, transparent), transparent 70%);
  opacity: 0;
  transition: opacity .42s ease;
  pointer-events: none;
}

.sa-feature-card:hover {
  transform: translateY(-6px);
  border-color: color-mix(in srgb, var(--fc) 34%, var(--sa-border));
  box-shadow:
    0 18px 42px -12px color-mix(in srgb, var(--fc) 30%, transparent),
    0 6px 18px rgba(15, 23, 42, 0.05);
}
.sa-feature-card:hover::before { transform: scaleX(1); }
.sa-feature-card:hover::after  { opacity: 1; }

/* --- Icon tile ------------------------------------------------------------
   Bigger, tinted with the card's own accent, and it lifts with the card. */
.sa-feature-icon {
  position: relative;
  width: 46px;
  height: 46px;
  margin-bottom: 17px;
  border-radius: 12px;
  background: color-mix(in srgb, var(--fc) 12%, #fff);
  color: var(--fc);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--fc) 16%, transparent);
  transition: transform .34s cubic-bezier(.16, 1, .3, 1), background .34s ease, box-shadow .34s ease;
}
.sa-feature-card:hover .sa-feature-icon {
  transform: translateY(-2px) scale(1.06);
  background: linear-gradient(135deg, var(--fc), color-mix(in srgb, var(--fc) 55%, #06D6D1));
  color: #fff;
  box-shadow: 0 10px 22px -6px color-mix(in srgb, var(--fc) 55%, transparent);
}
.sa-feature-icon .mud-icon-root { font-size: 22px; }

.sa-feature-card h3 { position: relative; font-size: 1.09rem; margin: 0 0 9px; letter-spacing: -0.012em; }
.sa-feature-card p  { position: relative; font-size: 13.8px; line-height: 1.66; }

/* Older engines without color-mix() get a plain tint rather than a transparent
   icon tile - the accent is decoration, and losing it must not lose the shape. */
@supports not (background: color-mix(in srgb, red 10%, white)) {
  .sa-feature-icon { background: var(--sa-primary-light); }
  .sa-feature-card:hover .sa-feature-icon { background: var(--fc); color: #fff; }
  .sa-feature-card::after { display: none; }
}

/* --- Stagger ---------------------------------------------------------------
   The shared utility defined delays for six children only, so in an eight-card
   grid the last two fired at 0s - arriving before the cards above them and
   breaking the very sequence the stagger exists to create. Written as a formula
   so the grid can grow without anyone remembering to extend this. */
.sa-stagger-children.sa-visible > *:nth-child(1)  { transition-delay: .00s; }
.sa-stagger-children.sa-visible > *:nth-child(2)  { transition-delay: .06s; }
.sa-stagger-children.sa-visible > *:nth-child(3)  { transition-delay: .12s; }
.sa-stagger-children.sa-visible > *:nth-child(4)  { transition-delay: .18s; }
.sa-stagger-children.sa-visible > *:nth-child(5)  { transition-delay: .24s; }
.sa-stagger-children.sa-visible > *:nth-child(6)  { transition-delay: .30s; }
.sa-stagger-children.sa-visible > *:nth-child(7)  { transition-delay: .36s; }
.sa-stagger-children.sa-visible > *:nth-child(8)  { transition-delay: .42s; }
.sa-stagger-children.sa-visible > *:nth-child(9)  { transition-delay: .48s; }
.sa-stagger-children.sa-visible > *:nth-child(10) { transition-delay: .54s; }
.sa-stagger-children.sa-visible > *:nth-child(11) { transition-delay: .60s; }
.sa-stagger-children.sa-visible > *:nth-child(n+12) { transition-delay: .66s; }

/* A little more travel than the shared 20px, and the same spring the rest of
   the page now uses. */
.sa-features-grid.sa-stagger-children > * {
  transform: translateY(26px) scale(.985);
  transition:
    opacity .62s cubic-bezier(.16, 1, .3, 1),
    transform .62s cubic-bezier(.16, 1, .3, 1),
    box-shadow .34s cubic-bezier(.16, 1, .3, 1),
    border-color .34s ease;
}
.sa-features-grid.sa-stagger-children.sa-visible > * { transform: none; }

@media (prefers-reduced-motion: reduce) {
  .sa-feature-card,
  .sa-feature-card::before,
  .sa-feature-card::after,
  .sa-feature-icon { transition: none; }
  .sa-feature-card:hover { transform: none; }
}

/* =============================================================================
   BOOK A DEMO — dark band, live product panel, dialog
   =============================================================================
   Supersedes the earlier inline-form version of this section. Everything below
   the "band" heading replaces those rules; the field, submit and confirmation
   styles from that block are still used, now inside the dialog.
   ============================================================================= */

.sa-bd { padding: clamp(48px, 3.4vw + 30px, 84px) 24px; background: #fff; }

/* The band is a dark slab inset from the page rather than a full-bleed section:
   it reads as a distinct object, which is what stops it blending into the
   run of white sections above it. */
.sa-bd-band {
  position: relative;
  overflow: hidden;
  display: grid;
  grid-template-columns: minmax(0, 0.92fr) minmax(0, 1.08fr);
  align-items: center;
  gap: 44px;
  max-width: 1200px;
  margin: 0 auto;
  padding: clamp(38px, 3vw + 22px, 66px) clamp(28px, 2.6vw + 18px, 60px);
  border-radius: 20px;
  /* The logo's own two colours - #2563FF and #06D6D1 - over the dark #1C4CC4,
     rather than the near-black it was. The cyan is weighted to the right, behind
     the product panel: white on #2563FF clears 8:1, but white on full #06D6D1 is
     about 2:1, so the cyan has to stay away from the headline to remain readable
     rather than merely bright. */
  background:
    radial-gradient(760px 440px at 92% 8%, rgba(6, 214, 209, 0.40), transparent 62%),
    radial-gradient(640px 420px at 4% 94%, rgba(37, 99, 255, 0.55), transparent 64%),
    linear-gradient(150deg, #081f4d 0%, #1C4CC4 40%, #2563FF 74%, #0e4d84 100%);
}
/* Vertical light rake along the bottom edge - the detail that keeps a large
   dark rectangle from reading as flat. */
.sa-bd-band::after {
  content: '';
  position: absolute;
  inset: auto 0 0 0;
  height: 92px;
  background: repeating-linear-gradient(90deg,
    rgba(6, 214, 209, 0.16) 0 2px, transparent 2px 9px);
  mask-image: linear-gradient(to top, #000, transparent);
  -webkit-mask-image: linear-gradient(to top, #000, transparent);
  pointer-events: none;
}

.sa-bd-copy { position: relative; z-index: 1; }
.sa-bd-title {
  margin: 0 0 18px;
  font-size: clamp(1.9rem, 1.15rem + 2.6vw, 3.4rem);
  font-weight: 800;
  line-height: 1.06;
  letter-spacing: -0.035em;
  color: #fff;
}
.sa-bd-lede {
  margin: 0 0 30px;
  max-width: 430px;
  font-size: clamp(.98rem, .93rem + .22vw, 1.1rem);
  line-height: 1.62;
  color: rgba(219, 234, 254, 0.82);
}

/* Pill button, outlined on the dark ground, inverting on hover. */
.sa-bd-open {
  position: relative;
  overflow: hidden;
  padding: 15px 34px;
  border: 1.5px solid rgba(255, 255, 255, 0.9);
  border-radius: 999px;
  background: transparent;
  color: #fff;
  font-family: inherit;
  font-size: 15px;
  font-weight: 700;
  cursor: pointer;
  transition: background .26s ease, color .26s ease, transform .26s cubic-bezier(.16, 1, .3, 1), box-shadow .26s ease;
}
.sa-bd-open:hover {
  background: #fff;
  color: #05091c;
  transform: translateY(-2px);
  box-shadow: 0 14px 34px rgba(6, 214, 209, 0.28);
}
.sa-bd-open:focus-visible { outline: 3px solid #7fe6f4; outline-offset: 3px; }

/* --- The live product panel ----------------------------------------------- */
.sa-bd-visual { position: relative; z-index: 1; }
.sa-bd-screen {
  position: relative;
  overflow: hidden;
  padding: 14px;
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 16px;
  background: rgba(255, 255, 255, 0.05);
  box-shadow: 0 30px 70px rgba(2, 8, 24, 0.55);
}
/* Sweep that crosses the panel every 12s - the single cue that most says
   "this is playing" rather than "this is a screenshot". */
.sa-bd-scan {
  position: absolute;
  top: 0;
  left: -40%;
  width: 34%;
  height: 100%;
  background: linear-gradient(100deg, transparent, rgba(127, 230, 244, 0.13), transparent);
  animation: sa-bd-scan 12s cubic-bezier(.5, 0, .5, 1) infinite;
  pointer-events: none;
  z-index: 2;
}
@keyframes sa-bd-scan {
  0%, 8%   { left: -40%; }
  46%      { left: 108%; }
  100%     { left: 108%; }
}

.sa-bd-card-live { background: #fff; border-radius: 12px; }

/* --- Crawl progress -------------------------------------------------------- */
.sa-bd-progress { margin-bottom: 14px; }
.sa-bd-progress-top {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 7px;
  font-size: 11.5px;
  font-weight: 600;
}
.sa-bd-phase { color: var(--sa-primary); }
.sa-bd-count { color: var(--sa-text-placeholder); font-variant-numeric: tabular-nums; }
.sa-bd-bar { height: 6px; border-radius: 999px; background: #eef2f7; overflow: hidden; }
.sa-bd-bar-fill {
  display: block;
  height: 100%;
  width: 0;
  border-radius: 999px;
  background: linear-gradient(90deg, #0e7490, #06D6D1);
  animation: sa-bd-fill 12s cubic-bezier(.32, .72, .3, 1) infinite;
}
@keyframes sa-bd-fill {
  0%       { width: 0; }
  34%      { width: 100%; }
  92%      { width: 100%; }
  100%     { width: 0; }
}

/* --- Score ring ------------------------------------------------------------ */
.sa-bd-score { display: flex; align-items: center; gap: 16px; margin-bottom: 14px; }
.sa-bd-ring { flex-shrink: 0; }
.sa-bd-ring-arc {
  stroke-dasharray: 226;                  /* 2 * pi * 36, rounded */
  stroke-dashoffset: 226;
  animation: sa-bd-draw 12s cubic-bezier(.32, .72, .3, 1) infinite;
}
@keyframes sa-bd-draw {
  0%, 30%  { stroke-dashoffset: 226; }
  56%      { stroke-dashoffset: 16; }     /* 93 of 100 */
  92%      { stroke-dashoffset: 16; }
  100%     { stroke-dashoffset: 226; }
}
.sa-bd-score-meta { display: flex; flex-direction: column; gap: 2px; }
.sa-bd-score-val {
  font-size: 30px;
  font-weight: 800;
  line-height: 1;
  color: var(--sa-text-primary);
  font-variant-numeric: tabular-nums;
  animation: sa-bd-appear 12s ease infinite;
}
.sa-bd-score-lbl { font-size: 12px; font-weight: 600; color: var(--sa-text-muted); }
.sa-bd-score-delta { font-size: 11.5px; font-weight: 600; color: var(--sa-success); }

/* --- Issue rows ------------------------------------------------------------ */
.sa-bd-list .sa-deck-li {
  opacity: 0;
  animation: sa-bd-row 12s cubic-bezier(.16, 1, .3, 1) infinite;
}
.sa-bd-list .sa-deck-li:nth-child(1) { animation-delay: -0.0s; }
.sa-bd-list .sa-deck-li:nth-child(2) { animation-delay: 0.35s; }
.sa-bd-list .sa-deck-li:nth-child(3) { animation-delay: 0.70s; }
.sa-bd-list .sa-deck-li:nth-child(4) { animation-delay: 1.05s; }
@keyframes sa-bd-row {
  0%, 38%  { opacity: 0; transform: translateY(7px); }
  48%      { opacity: 1; transform: none; }
  92%      { opacity: 1; transform: none; }
  100%     { opacity: 0; transform: translateY(7px); }
}
@keyframes sa-bd-appear {
  0%, 36%  { opacity: 0; }
  50%, 92% { opacity: 1; }
  100%     { opacity: 0; }
}

.sa-bd-pulse { animation: sa-bd-pulse 2.2s ease-in-out infinite; }
@keyframes sa-bd-pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: .5; }
}

/* --- Dialog ---------------------------------------------------------------- */
.sa-modal-backdrop {
  position: fixed;
  inset: 0;
  z-index: 1400;
  display: grid;
  place-items: center;
  padding: 20px;
  background: rgba(4, 11, 36, 0.62);
  backdrop-filter: blur(5px);
  animation: sa-modal-in .22s ease;
  overflow-y: auto;
}
.sa-modal {
  position: relative;
  width: 100%;
  max-width: 480px;
  max-height: calc(100vh - 40px);
  overflow-y: auto;
  padding: 30px;
  border-radius: 20px;
  background: #fff;
  box-shadow: 0 40px 90px rgba(2, 8, 24, 0.4);
  animation: sa-modal-rise .3s cubic-bezier(.16, 1, .3, 1);
}
.sa-modal:focus { outline: none; }        /* focused programmatically, not by the user */
.sa-modal-title { margin: 0 0 6px; font-size: 21px; font-weight: 800; color: var(--sa-text-primary); }
.sa-modal-sub { margin: 0 0 22px; font-size: 13.5px; line-height: 1.55; color: var(--sa-text-muted); }

.sa-modal-x {
  position: absolute;
  top: 14px;
  right: 14px;
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--sa-text-muted);
  cursor: pointer;
  transition: background .16s ease, color .16s ease;
}
.sa-modal-x:hover { background: #f1f5f9; color: var(--sa-text-primary); }
.sa-modal-x svg { width: 18px; height: 18px; }

@keyframes sa-modal-in   { from { opacity: 0; } to { opacity: 1; } }
@keyframes sa-modal-rise { from { opacity: 0; transform: translateY(16px) scale(.98); } to { opacity: 1; transform: none; } }

/* Set on <body> while the dialog is open so a scroll gesture moves the form,
   not the page behind it. */
body.sa-modal-open { overflow: hidden; }

.sa-bd-row-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 13px; }

@media (max-width: 940px) {
  .sa-bd-band { grid-template-columns: 1fr; gap: 34px; }
  .sa-bd-lede { max-width: none; }
}
@media (max-width: 520px) {
  .sa-bd-row-2 { grid-template-columns: 1fr; gap: 0; }
  .sa-modal { padding: 24px 20px; }
  .sa-bd-band { padding: 32px 22px; border-radius: 16px; }
}

@media (prefers-reduced-motion: reduce) {
  .sa-bd-scan,
  .sa-bd-bar-fill,
  .sa-bd-ring-arc,
  .sa-bd-score-val,
  .sa-bd-pulse,
  .sa-bd-list .sa-deck-li { animation: none; }
  /* The loop's resting frame is mid-cycle, so the pieces it would have revealed
     have to be shown outright - otherwise switching off motion empties the panel. */
  .sa-bd-list .sa-deck-li { opacity: 1; }
  .sa-bd-bar-fill { width: 100%; }
  .sa-bd-ring-arc { stroke-dashoffset: 16; }
  .sa-modal, .sa-modal-backdrop { animation: none; }
}

/* Explains a disabled submit while the captcha resolves - a button that cannot
   be pressed and says nothing reads as a broken form. */
.sa-bd-waiting { margin: 0 0 12px; text-align: left; color: var(--sa-primary); font-weight: 600; }

/* -----------------------------------------------------------------------------
   Book-a-demo panel: undo the carousel's slide state
   -----------------------------------------------------------------------------
   .sa-deck-card is authored for the hero carousel, where a slide rests at
   opacity .34 / scale(.88) until it becomes .active, and is pinned to 396px with
   overflow:hidden so every slide is the same size. Reusing the component outside
   that carousel inherited all three: the panel rendered washed out, shrunk, and
   with its last row cut off. It is a standalone panel here, so it opts out.
   -------------------------------------------------------------------------- */
.sa-bd-screen .sa-deck-card {
  flex: initial;
  width: 100%;
  height: auto;                 /* content decides the height - nothing to clip */
  opacity: 1;
  transform: none;
  transition: none;
  border-radius: 16px;
  box-shadow: 0 16px 40px rgba(4, 12, 34, 0.26);
}

/* Retimed loop. The first version spent its opening 4.5s on an empty card while
   the crawl bar filled, which is a long time to show a prospect nothing. The
   crawl now resolves early and the populated state - the part worth looking at -
   holds for roughly two thirds of the cycle. */
.sa-bd-bar-fill { animation-name: sa-bd-fill-2; }
@keyframes sa-bd-fill-2 {
  0%   { width: 0; }
  18%  { width: 100%; }
  94%  { width: 100%; }
  100% { width: 0; }
}

.sa-bd-ring-arc { animation-name: sa-bd-draw-2; }
@keyframes sa-bd-draw-2 {
  0%, 14% { stroke-dashoffset: 226; }
  34%     { stroke-dashoffset: 16; }
  94%     { stroke-dashoffset: 16; }
  100%    { stroke-dashoffset: 226; }
}

.sa-bd-score-val { animation-name: sa-bd-appear-2; }
@keyframes sa-bd-appear-2 {
  0%, 16%  { opacity: 0; }
  28%, 95% { opacity: 1; }
  100%     { opacity: 0; }
}

/* Rows land quickly and then hold. The fade-out is compressed into the last 4%
   so the reset reads as a cut rather than a slow dissolve. */
.sa-bd-list .sa-deck-li { animation-name: sa-bd-row-2; }
@keyframes sa-bd-row-2 {
  0%, 20% { opacity: 0; transform: translateY(7px); }
  30%     { opacity: 1; transform: none; }
  96%     { opacity: 1; transform: none; }
  100%    { opacity: 0; transform: translateY(7px); }
}

/* Compacted for the band. Freed from the carousel's fixed 396px the panel grew
   to ~640px, which left it towering over the copy column beside it; these bring
   it back to a height that balances the headline without clipping anything. */
.sa-bd-screen .sa-deck-card { padding: 18px 20px 14px; gap: 12px; }
.sa-bd-screen .sa-deck-body { gap: 12px; justify-content: flex-start; }
.sa-bd-screen .sa-deck-list { gap: 6px; }
.sa-bd-screen .sa-deck-li { padding: 7px 10px; font-size: 12px; }
.sa-bd-screen .sa-deck-foot { padding-top: 10px; font-size: 11px; }
.sa-bd-screen .sa-bd-score { gap: 14px; margin-bottom: 10px; }
.sa-bd-screen .sa-bd-ring { width: 70px; height: 70px; }
.sa-bd-screen .sa-bd-score-val { font-size: 26px; }
.sa-bd-screen .sa-bd-progress { margin-bottom: 10px; }

/* =============================================================================
   STATS BAR
   =============================================================================
   Was four numbers floating on a flat panel with 48px between them and nothing
   holding them together. They now sit in a single card, each stat in its own
   cell with a hairline rule between, an icon, and a line of supporting copy -
   so each figure explains itself instead of relying on a two-word label.
   ============================================================================= */

.sa-stats-bar {
  padding: clamp(30px, 2.4vw + 18px, 52px) 24px clamp(38px, 3vw + 22px, 64px);
  background: linear-gradient(180deg, #eef3fd 0%, #f7f9fe 62%, #fff 100%);
  border-bottom: 0;
}

.sa-stats-inner {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0;
  max-width: 1120px;
  margin: 0 auto;
  padding: 8px;
  border: 1px solid rgba(37, 99, 255, 0.10);
  border-radius: 20px;
  background: rgba(255, 255, 255, 0.72);
  backdrop-filter: blur(6px);
  box-shadow: 0 18px 46px -20px rgba(13, 53, 128, 0.32);
}

.sa-stat {
  position: relative;
  padding: 22px 20px 20px;
  border-radius: 16px;
  text-align: center;
  transition: background .28s ease, transform .28s cubic-bezier(.16, 1, .3, 1);
}
/* Hairline between cells, drawn on the cell rather than as a border so the
   first one can be suppressed without changing the box model. */
.sa-stat + .sa-stat::before {
  content: '';
  position: absolute;
  left: 0;
  top: 24px;
  bottom: 24px;
  width: 1px;
  background: linear-gradient(180deg, transparent, rgba(37, 99, 255, 0.16), transparent);
}
.sa-stat:hover { background: rgba(37, 99, 255, 0.04); transform: translateY(-3px); }

.sa-stat-ico {
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  margin: 0 auto 12px;
  border-radius: 12px;
  background: linear-gradient(135deg, rgba(37, 99, 255, 0.12), rgba(6, 214, 209, 0.16));
  color: var(--sa-primary);
  transition: transform .28s cubic-bezier(.16, 1, .3, 1);
}
.sa-stat-ico svg { width: 19px; height: 19px; }
.sa-stat:hover .sa-stat-ico { transform: scale(1.08) rotate(-3deg); }

.sa-stat-number {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 1px;
  font-size: clamp(2rem, 1.4rem + 1.9vw, 3.1rem);
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.035em;
  /* The logo's two colours, so the figures read as brand rather than as plain
     dark text on a pale panel. */
  background: linear-gradient(135deg, #2563FF 0%, #1C4CC4 42%, #0e7fa8 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  font-variant-numeric: tabular-nums;   /* stops the width jittering while counting */
}
.sa-stat-number em {
  font-style: normal;
  font-size: .46em;
  font-weight: 700;
  letter-spacing: -0.01em;
}
.sa-stat-pre { margin-right: 1px; }

.sa-stat-label {
  margin-top: 9px;
  font-size: 13.5px;
  font-weight: 700;
  color: var(--sa-text-primary);
}
.sa-stat-sub {
  margin-top: 4px;
  font-size: 11.5px;
  line-height: 1.5;
  color: var(--sa-text-muted);
}

@media (max-width: 900px) {
  .sa-stats-inner { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* On two columns the hairline belongs between the pair, not before every cell
     after the first - otherwise it lands at the start of a row. */
  .sa-stat + .sa-stat::before { display: none; }
  .sa-stat:nth-child(even)::before { display: block; }
}
@media (max-width: 520px) {
  .sa-stats-inner { grid-template-columns: minmax(0, 1fr); }
  .sa-stat::before { display: none !important; }
  .sa-stat { padding: 18px 14px; }
  .sa-stat-sub { font-size: 12px; }
}

@media (prefers-reduced-motion: reduce) {
  .sa-stat, .sa-stat-ico { transition: none; }
  .sa-stat:hover { transform: none; }
}

/* =============================================================================
   FEATURES — horizontal rail
   =============================================================================
   Replaces the 4x2 grid. A rail suits eight peers better than a grid does: a
   grid asks the eye to scan two full rows before it knows what is on offer,
   whereas a rail shows four and makes the rest obviously reachable. The card cut
   off at the right edge is the affordance - it says "there is more" far more
   plainly than a row of dots.
   ============================================================================= */

.sa-fs { overflow: hidden; }          /* the rail bleeds past the inner width */

.sa-fs-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 28px;
  margin-bottom: 34px;
}

.sa-fs-kicker {
  display: inline-block;
  margin-bottom: 12px;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--sa-primary);
}
.sa-fs-kicker em { font-style: normal; color: var(--sa-text-placeholder); }

.sa-fs-title { margin: 0 0 12px; }
.sa-fs-title::before { content: none; }   /* the shared gradient bar fights a left-aligned block heading */
.sa-fs-sub { margin: 0; max-width: 540px; }

/* --- Arrows ---------------------------------------------------------------- */
.sa-fs-nav { display: flex; gap: 10px; flex-shrink: 0; padding-bottom: 4px; }
.sa-fs-arrow {
  display: grid;
  place-items: center;
  width: 48px;
  height: 48px;
  border: 1.5px solid rgba(37, 99, 255, 0.22);
  border-radius: 50%;
  background: #fff;
  color: var(--sa-primary);
  cursor: pointer;
  transition: background .2s ease, color .2s ease, border-color .2s ease, transform .2s cubic-bezier(.16, 1, .3, 1), opacity .2s ease;
}
.sa-fs-arrow svg { width: 19px; height: 19px; }
.sa-fs-arrow:hover:not(:disabled) {
  background: var(--sa-primary);
  border-color: var(--sa-primary);
  color: #fff;
  transform: translateY(-2px);
}
.sa-fs-arrow:disabled { opacity: .3; cursor: default; }
.sa-fs-arrow:focus-visible { outline: 3px solid rgba(6, 214, 209, .55); outline-offset: 3px; }

/* --- The rail --------------------------------------------------------------
   Native scrolling, snap points, and padding on the right so the last card can
   reach the left edge instead of stopping short. */
.sa-fs-rail {
  display: flex;
  gap: 20px;
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: none;                /* the progress bar below is the indicator */
  padding: 4px 4px 26px;
  margin: 0 -4px;
}
.sa-fs-rail::-webkit-scrollbar { display: none; }
.sa-fs-rail:focus-visible { outline: 3px solid rgba(6, 214, 209, .5); outline-offset: 6px; border-radius: 20px; }

/* --- Cards -----------------------------------------------------------------
   Cool tints only: each card mixes its accent into a pale cyan-white ground, so
   the eight read as one cool family rather than eight unrelated colours. */
.sa-fs-card {
  --fc: var(--sa-primary);
  position: relative;
  overflow: hidden;
  flex: 0 0 clamp(250px, 24vw, 306px);
  scroll-snap-align: start;
  display: flex;
  flex-direction: column;
  padding: 26px 24px 22px;
  border: 1px solid color-mix(in srgb, var(--fc) 16%, rgba(37, 99, 255, 0.08));
  border-radius: 20px;
  background:
    linear-gradient(168deg,
      color-mix(in srgb, var(--fc) 9%, #f3fbfd) 0%,
      color-mix(in srgb, var(--fc) 4%, #f7fbff) 58%,
      #ffffff 100%);
  transition: transform .34s cubic-bezier(.16, 1, .3, 1), box-shadow .34s ease, border-color .34s ease;
}
/* Diagonal hatch in the corner, echoing the reference. Decoration only, and it
   fades out before it reaches any text. */
.sa-fs-card::after {
  content: '';
  position: absolute;
  right: -30px;
  bottom: -30px;
  width: 170px;
  height: 170px;
  background: repeating-linear-gradient(-45deg,
    color-mix(in srgb, var(--fc) 24%, transparent) 0 1px, transparent 1px 8px);
  mask-image: radial-gradient(circle at 100% 100%, #000, transparent 72%);
  -webkit-mask-image: radial-gradient(circle at 100% 100%, #000, transparent 72%);
  pointer-events: none;
}
.sa-fs-card:hover {
  transform: translateY(-6px);
  border-color: color-mix(in srgb, var(--fc) 38%, transparent);
  box-shadow: 0 20px 44px -16px color-mix(in srgb, var(--fc) 40%, transparent);
}

.sa-fs-eyebrow {
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: color-mix(in srgb, var(--fc) 78%, #334155);
}

.sa-fs-ico {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  margin: 16px 0 15px;
  border-radius: 12px;
  background: #fff;
  color: var(--fc);
  box-shadow: 0 4px 14px -4px color-mix(in srgb, var(--fc) 46%, transparent),
              inset 0 0 0 1px color-mix(in srgb, var(--fc) 14%, transparent);
  transition: transform .34s cubic-bezier(.16, 1, .3, 1), background .34s ease, color .34s ease;
}
.sa-fs-ico .mud-icon-root { font-size: 21px; }
.sa-fs-card:hover .sa-fs-ico {
  transform: translateY(-2px) scale(1.07);
  background: linear-gradient(135deg, var(--fc), color-mix(in srgb, var(--fc) 52%, #06D6D1));
  color: #fff;
}

.sa-fs-card h3 {
  position: relative;
  margin: 0 0 9px;
  font-size: 1.08rem;
  font-weight: 700;
  letter-spacing: -0.014em;
  color: var(--sa-text-primary);
}
.sa-fs-card p {
  position: relative;
  flex: 1;
  margin: 0 0 16px;
  font-size: 13.4px;
  line-height: 1.64;
  color: var(--sa-text-muted);
}

.sa-fs-chips { position: relative; display: flex; flex-wrap: wrap; gap: 6px; }
.sa-fs-chips span {
  padding: 4px 10px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--fc) 13%, #fff);
  color: color-mix(in srgb, var(--fc) 82%, #1e293b);
  font-size: 11px;
  font-weight: 700;
}

/* --- Progress indicator ---------------------------------------------------- */

/* color-mix() is what carries the tint; without it the cards would be white on
   white, so fall back to the flat surface colour and a plain accent. */
@supports not (background: color-mix(in srgb, red 10%, white)) {
  .sa-fs-card { background: var(--sa-surface-light); border-color: var(--sa-border); }
  .sa-fs-card::after { display: none; }
  .sa-fs-eyebrow, .sa-fs-chips span { color: var(--sa-primary); }
  .sa-fs-chips span { background: var(--sa-primary-light); }
  .sa-fs-ico { color: var(--sa-primary); }
}

@media (max-width: 720px) {
  .sa-fs-head { flex-direction: column; align-items: flex-start; gap: 20px; }
  .sa-fs-nav { align-self: flex-end; margin-top: -8px; }
  .sa-fs-card { flex-basis: min(78vw, 300px); }
}

@media (prefers-reduced-motion: reduce) {
  .sa-fs-rail { scroll-behavior: auto; }
  .sa-fs-card, .sa-fs-ico, .sa-fs-arrow { transition: none; }
  .sa-fs-card:hover { transform: none; }
}

/* =============================================================================
   FEATURE CARDS — product UI inside each card
   =============================================================================
   The cards were text plus a couple of chips, which is not what the reference
   does: every card there carries a picture of the product. These do too, drawn
   in markup rather than screenshotted so they stay sharp, weigh nothing, and
   cannot go stale the day the real UI moves. Each mock shows the surface that
   feature actually produces.
   ============================================================================= */

.sa-fs-card { flex-basis: clamp(268px, 25vw, 322px); padding: 24px 22px 22px; }
.sa-fs-card h3 { margin: 14px 0 8px; }
.sa-fs-card p { flex: 0 0 auto; margin: 0 0 16px; font-size: 13px; line-height: 1.6; }

/* Caption under the feature grid. The .sa-fs-shot panels are drawn UI with
   invented hostnames, so the grid says so out loud rather than letting a
   prospect read them as a customer list. Muted ink, centred, small. */
.sa-fs-illustrative {
  margin: 22px 0 0;
  text-align: center;
  font-size: 12px;
  line-height: 1.5;
  color: #5b6b83;
}

/* --- Shot frame ------------------------------------------------------------ */
.sa-fs-shot {
  position: relative;
  margin-top: auto;
  border: 1px solid color-mix(in srgb, var(--fc) 18%, rgba(15, 23, 42, 0.08));
  border-radius: 12px;
  background: #fff;
  box-shadow: 0 8px 22px -10px color-mix(in srgb, var(--fc) 42%, transparent);
  overflow: hidden;
  transition: transform .34s cubic-bezier(.16, 1, .3, 1), box-shadow .34s ease;
}
.sa-fs-card:hover .sa-fs-shot {
  transform: translateY(-3px);
  box-shadow: 0 14px 30px -12px color-mix(in srgb, var(--fc) 55%, transparent);
}

.sa-fs-shot-bar {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 7px 10px;
  border-bottom: 1px solid rgba(15, 23, 42, 0.06);
  background: color-mix(in srgb, var(--fc) 5%, #f8fafc);
}
.sa-fs-shot-bar i { width: 6px; height: 6px; border-radius: 50%; background: rgba(15, 23, 42, 0.16); }
.sa-fs-shot-bar b {
  margin-left: 6px;
  font-family: 'Cascadia Code', 'Consolas', monospace;
  font-size: 9.5px;
  font-weight: 500;
  color: var(--sa-text-placeholder);
}

.sa-fs-shot-body { padding: 11px; }
.sa-fs-shot-ready { display: flex; align-items: center; gap: 12px; }

/* --- Gauge ----------------------------------------------------------------- */
.sa-fs-gauge { position: relative; flex-shrink: 0; width: 58px; height: 58px; }
.sa-fs-gauge svg { width: 58px; height: 58px; }
.sa-fs-gauge-bg  { fill: none; stroke: #eef2f7; stroke-width: 7; }
.sa-fs-gauge-arc {
  fill: none;
  stroke: var(--fc);
  stroke-width: 7;
  stroke-linecap: round;
  stroke-dasharray: 163;                 /* 2 * pi * 26 */
  stroke-dashoffset: 30;
}
.sa-fs-gauge-val {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-size: 16px;
  font-weight: 800;
  color: var(--sa-text-primary);
}

/* --- Mini rows ------------------------------------------------------------- */
.sa-fs-mini-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 4px; min-width: 0; flex: 1; }
.sa-fs-mini-list li {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 4px 7px;
  border-radius: 8px;
  background: #f6f8fb;
  font-size: 10px;
  font-weight: 600;
  color: var(--sa-text-secondary);
  white-space: nowrap;
  overflow: hidden;
}
.sa-fs-mini-list li b { margin-left: auto; font-size: 9.5px; color: var(--sa-text-placeholder); }
.sa-fs-urls li { font-family: 'Cascadia Code', 'Consolas', monospace; font-weight: 500; }

.sa-fs-tick {
  flex-shrink: 0;
  width: 11px;
  height: 11px;
  border-radius: 50%;
  background: rgba(4, 120, 87, 0.16);
  position: relative;
}
.sa-fs-tick::after {
  content: '';
  position: absolute;
  left: 3px; top: 3.4px;
  width: 4.4px; height: 2.2px;
  border-left: 1.4px solid var(--sa-success);
  border-bottom: 1.4px solid var(--sa-success);
  transform: rotate(-45deg);
}
.sa-fs-tick.sa-warn { background: rgba(180, 83, 9, 0.16); }
.sa-fs-tick.sa-warn::after { border-color: var(--sa-warning); }

.sa-fs-dot { flex-shrink: 0; width: 7px; height: 7px; border-radius: 50%; background: #94a3b8; }
.sa-fs-dot.sa-now   { background: #d4183d; }
.sa-fs-dot.sa-later { background: #f59e0b; }
.sa-fs-dot.sa-good  { background: #0d9488; }

/* --- Code block ------------------------------------------------------------ */
.sa-fs-code {
  margin: 0 0 8px;
  padding: 8px 9px;
  border-radius: 8px;
  background: #0f1b3d;
  color: #cbd5e1;
  font-family: 'Cascadia Code', 'Consolas', monospace;
  font-size: 9px;
  line-height: 1.55;
  white-space: pre;
  overflow: hidden;
}
.sa-fs-code .c-p { color: #7fe6f4; }
.sa-fs-code .c-s { color: #a5f3a0; }

.sa-fs-filerow { display: flex; gap: 5px; flex-wrap: wrap; }
.sa-fs-filerow-lg { margin-bottom: 8px; }
.sa-fs-file {
  padding: 3px 8px;
  border: 1px solid color-mix(in srgb, var(--fc) 22%, transparent);
  border-radius: 4px;
  font-size: 9.5px;
  font-weight: 700;
  color: color-mix(in srgb, var(--fc) 80%, #1e293b);
  background: #fff;
}
.sa-fs-file.is-on { background: var(--fc); border-color: var(--fc); color: #fff; }

/* --- Crawl / bars ---------------------------------------------------------- */
.sa-fs-crawlhead {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 6px;
  font-size: 9.5px;
  font-weight: 700;
  color: var(--fc);
}
.sa-fs-crawlhead b { color: var(--sa-text-placeholder); font-weight: 600; }
.sa-fs-track { height: 4px; border-radius: 999px; background: #eef2f7; overflow: hidden; margin-bottom: 8px; }
.sa-fs-track-fill {
  display: block;
  height: 100%;
  width: 72%;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--fc), color-mix(in srgb, var(--fc) 45%, #06D6D1));
}

.sa-fs-bars { flex: 1; display: grid; gap: 5px; min-width: 0; }
.sa-fs-bars span {
  position: relative;
  display: block;
  padding-left: 0;
  font-size: 9px;
  font-weight: 600;
  color: var(--sa-text-muted);
}
.sa-fs-bars i {
  display: block;
  height: 4px;
  margin-bottom: 2px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--fc) 62%, #cbd5e1);
}

.sa-fs-quote {
  margin-bottom: 8px;
  padding: 8px 9px;
  border-left: 2px solid var(--fc);
  border-radius: 0 6px 6px 0;
  background: color-mix(in srgb, var(--fc) 7%, #f8fafc);
  font-size: 10px;
  line-height: 1.5;
  color: var(--sa-text-secondary);
}

.sa-fs-link {
  display: flex;
  align-items: center;
  gap: 5px;
  margin-bottom: 7px;
  padding: 5px 8px;
  border-radius: 8px;
  background: #f6f8fb;
  font-family: 'Cascadia Code', 'Consolas', monospace;
  font-size: 9px;
  color: var(--sa-text-secondary);
  overflow: hidden;
  white-space: nowrap;
}
.sa-fs-link b { color: var(--fc); }
.sa-fs-lock { width: 7px; height: 8px; border-radius: 1.5px; background: var(--fc); flex-shrink: 0; }

.sa-fs-scores { display: grid; grid-template-columns: repeat(4, 1fr); gap: 5px; margin-bottom: 8px; }
.sa-fs-scores span {
  display: grid;
  gap: 1px;
  padding: 6px 2px;
  border-radius: 8px;
  background: #f6f8fb;
  text-align: center;
  font-size: 8.5px;
  font-weight: 600;
  color: var(--sa-text-placeholder);
}
.sa-fs-scores b { font-size: 14px; font-weight: 800; }

.sa-fs-av {
  flex-shrink: 0;
  display: grid;
  place-items: center;
  width: 14px;
  height: 14px;
  border-radius: 4px;
  background: color-mix(in srgb, var(--fc) 18%, #fff);
  color: color-mix(in srgb, var(--fc) 85%, #1e293b);
  font-size: 8px;
  font-weight: 800;
}
.sa-fs-projects li { font-size: 9.5px; }

/* --- Drag to scroll --------------------------------------------------------
   Grab cursor advertises it; the snap has to be switched off mid-drag or the
   rail fights the pointer and jumps back to the nearest card on every move. */
.sa-fs-rail { cursor: grab; }
.sa-fs-rail.is-dragging {
  cursor: grabbing;
  scroll-snap-type: none;
  scroll-behavior: auto;
  user-select: none;
}
.sa-fs-rail.is-dragging .sa-fs-card { pointer-events: none; }

@supports not (background: color-mix(in srgb, red 10%, white)) {
  .sa-fs-shot { border-color: var(--sa-border); box-shadow: 0 8px 20px -12px rgba(15, 23, 42, .35); }
  .sa-fs-shot-bar { background: #f8fafc; }
  .sa-fs-file { border-color: var(--sa-border); color: var(--sa-primary); }
  .sa-fs-av { background: var(--sa-primary-light); color: var(--sa-primary); }
  .sa-fs-quote { background: #f8fafc; }
  .sa-fs-bars i { background: var(--sa-primary); }
}

/* =============================================================================
   FEATURE RAIL — single cool palette, quieter surfaces
   =============================================================================
   Supersedes the per-card accents. Eight different colours made the rail read as
   a sticker sheet rather than one product; everything now sits on one pale
   cyan-blue drawn from the logo, with the brand blue as the only accent. The
   diagonal hatch and the dark code block are gone for the same reason - both
   were adding noise to a section whose job is to look calm and expensive.
   ============================================================================= */

.sa-fs-card {
  --fc: #2563FF;                        /* the logo blue, for every card */
  --tint: #eef6fc;                      /* pale cyan-blue ground */
  flex-basis: clamp(272px, 25vw, 328px);
  padding: 26px 24px 24px;
  border: 1px solid rgba(37, 99, 255, 0.09);
  border-radius: 20px;
  background: linear-gradient(170deg, var(--tint) 0%, #f7fbfe 46%, #ffffff 100%);
  box-shadow: 0 1px 2px rgba(13, 53, 128, 0.04);
}
/* The hatch read as texture-for-its-own-sake at this size. A single soft cyan
   bloom in the corner does the same job without the busywork. */
.sa-fs-card::after {
  right: -60px;
  bottom: -60px;
  width: 210px;
  height: 210px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(6, 214, 209, 0.13), transparent 68%);
  mask-image: none;
  -webkit-mask-image: none;
}
.sa-fs-card:hover {
  transform: translateY(-6px);
  border-color: rgba(37, 99, 255, 0.20);
  box-shadow: 0 22px 48px -20px rgba(13, 53, 128, 0.30);
}

.sa-fs-eyebrow { color: #4a6fa8; letter-spacing: 0.15em; font-size: 10px; }

.sa-fs-ico {
  width: 42px;
  height: 42px;
  margin: 15px 0 0;
  border-radius: 12px;
  background: #fff;
  color: var(--fc);
  box-shadow: 0 2px 10px -3px rgba(37, 99, 255, 0.28), inset 0 0 0 1px rgba(37, 99, 255, 0.09);
}
.sa-fs-card:hover .sa-fs-ico {
  background: linear-gradient(135deg, #2563FF, #0e8fb4);
  color: #fff;
}

.sa-fs-card h3 { margin: 15px 0 8px; font-size: 1.07rem; }
.sa-fs-card p { color: #5b6b83; }

/* --- Mock surfaces --------------------------------------------------------- */
.sa-fs-shot {
  border: 1px solid rgba(37, 99, 255, 0.10);
  border-radius: 12px;
  box-shadow: 0 6px 18px -10px rgba(13, 53, 128, 0.34);
}
.sa-fs-card:hover .sa-fs-shot { box-shadow: 0 12px 26px -12px rgba(13, 53, 128, 0.42); }
.sa-fs-shot-bar { background: #f6fafd; border-bottom-color: rgba(37, 99, 255, 0.07); }
.sa-fs-shot-bar i { background: rgba(37, 99, 255, 0.15); }

.sa-fs-gauge-arc { stroke: #2563FF; }
.sa-fs-mini-list li { background: #f5f9fd; color: #33455f; }
.sa-fs-crawlhead { color: var(--fc); }
.sa-fs-track-fill { background: linear-gradient(90deg, #2563FF, #06D6D1); }
.sa-fs-bars i { background: linear-gradient(90deg, #2563FF, #45c3d8); }
.sa-fs-quote { background: #f2f8fd; border-left-color: #2563FF; }
.sa-fs-link { background: #f5f9fd; }
.sa-fs-link b, .sa-fs-lock { color: var(--fc); }
.sa-fs-lock { background: var(--fc); }
.sa-fs-scores span { background: #f5f9fd; }
.sa-fs-av { background: rgba(37, 99, 255, 0.11); color: var(--fc); }
.sa-fs-file { border-color: rgba(37, 99, 255, 0.20); color: #23477f; }
.sa-fs-file.is-on { background: var(--fc); border-color: var(--fc); color: #fff; }

/* Schema chips - what replaced the dark JSON block. Same visual family as every
   other mock instead of a terminal dropped into a pastel card. */
.sa-fs-schema { display: flex; flex-wrap: wrap; gap: 5px; margin-bottom: 8px; }
.sa-fs-schema span {
  padding: 4px 9px;
  border-radius: 8px;
  background: linear-gradient(135deg, rgba(37, 99, 255, 0.10), rgba(6, 214, 209, 0.12));
  color: #23477f;
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.01em;
}

/* --- Arrows --------------------------------------------------------------- */
.sa-fs-arrow { border-color: rgba(37, 99, 255, 0.18); }
.sa-fs-arrow:hover:not(:disabled) { background: #2563FF; border-color: #2563FF; }

/* --- Rail: no visible indicator ------------------------------------------- */
.sa-fs-rail { padding-bottom: 8px; }

/* =============================================================================
   FINAL CTA — report belt
   =============================================================================
   Was a centred headline, a button and three ticks on a blue gradient: generic
   enough to sit at the bottom of any SaaS site. It now shows the deliverable,
   because the report is the artefact a customer actually hands to their own
   client, and a picture of it argues better than another "sign up today".

   The report pages are drawn in markup. A screenshot of a real PDF would carry
   a real client's data, would go soft on a retina screen, and would need
   retaking every time the report template changes.
   ============================================================================= */

.sa-cta {
  padding: clamp(52px, 3.6vw + 32px, 92px) 24px;
  background: #fff;
}

.sa-cta-belt {
  position: relative;
  overflow: hidden;
  display: grid;
  grid-template-columns: minmax(0, 1.02fr) minmax(0, 0.98fr);
  align-items: center;
  gap: 40px;
  max-width: 1200px;
  margin: 0 auto;
  padding: clamp(36px, 2.6vw + 22px, 58px) clamp(28px, 2.4vw + 18px, 56px);
  border-radius: 20px;
  background:
    radial-gradient(680px 380px at 96% 4%, rgba(6, 214, 209, 0.30), transparent 62%),
    linear-gradient(122deg, #1C4CC4 0%, #2563FF 52%, #0f5fa8 100%);
}

/* --- Report pages ---------------------------------------------------------- */
.sa-cta-art {
  position: relative;
  height: 320px;
  perspective: 1200px;
}
.sa-cta-page {
  position: absolute;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 16px 15px;
  border-radius: 12px;
  background: #fff;
  box-shadow: 0 20px 44px rgba(3, 12, 40, 0.34);
}
/* Stacked back-to-front with decreasing tilt, so the front page reads clearly
   and the two behind it only suggest depth. */
.sa-cta-page-1 { left: 2%;  top: 6%;  width: 46%; height: 84%; transform: rotate(-4deg); z-index: 3; }
.sa-cta-page-2 { left: 36%; top: 16%; width: 40%; height: 66%; transform: rotate(2.5deg); z-index: 2; }
.sa-cta-page-3 { left: 62%; top: 10%; width: 38%; height: 72%; transform: rotate(6deg);  z-index: 1; }

/* Placeholder text lines - a report at this size is texture, not reading matter,
   and lorem ipsum at 5px would only look like a mistake. */
.sa-cta-ph { display: block; height: 4px; border-radius: 999px; background: #e3e9f2; }
.sa-w50 { width: 50%; } .sa-w60 { width: 60%; } .sa-w70 { width: 70%; }
.sa-w80 { width: 80%; } .sa-w90 { width: 90%; }

.sa-cta-head { display: flex; align-items: center; gap: 6px; }
.sa-cta-brandmark { width: 16px; height: 16px; border-radius: 4px; background: linear-gradient(135deg, #2563FF, #06D6D1); }
.sa-cta-brandlines { display: grid; gap: 3px; flex: 1; }
.sa-cta-brandlines i { display: block; height: 3px; border-radius: 999px; background: #e3e9f2; }
.sa-cta-brandlines i:first-child { width: 44%; }
.sa-cta-brandlines i:last-child { width: 28%; }

.sa-cta-title-ph { display: block; height: 7px; width: 66%; border-radius: 999px; background: #2563FF; margin-top: 4px; }
.sa-cta-foot-ph { display: block; height: 3px; width: 40%; border-radius: 999px; background: #eef2f8; margin-top: auto; }

.sa-cta-scorewrap { display: flex; align-items: center; gap: 10px; margin: 4px 0; }
.sa-cta-ring { position: relative; width: 54px; height: 54px; flex-shrink: 0; }
.sa-cta-ring svg { width: 54px; height: 54px; }
.sa-cta-ring-bg  { fill: none; stroke: #eef2f8; stroke-width: 7; }
.sa-cta-ring-arc { fill: none; stroke: #2563FF; stroke-width: 7; stroke-linecap: round; stroke-dasharray: 182; stroke-dashoffset: 22; }
.sa-cta-ring span {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-size: 15px;
  font-weight: 800;
  color: #0f172a;
}
.sa-cta-scoremeta { display: grid; gap: 5px; flex: 1; min-width: 0; }

.sa-cta-rows { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.sa-cta-rows li {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 5px 7px;
  border-radius: 4px;
  background: #f6f8fc;
}
.sa-cta-rows li b { margin-left: auto; font-size: 8px; color: #94a3b8; }
.sa-cta-rows .sa-cta-ph { flex: 1; }
.sa-cta-dot { width: 5px; height: 5px; border-radius: 50%; flex-shrink: 0; background: #94a3b8; }
.sa-cta-dot.sa-now { background: #d4183d; }
.sa-cta-dot.sa-later { background: #f59e0b; }
.sa-cta-dot.sa-good { background: #0d9488; }

.sa-cta-chart { display: flex; align-items: flex-end; gap: 4px; height: 54px; margin: 2px 0 4px; }
.sa-cta-chart i {
  flex: 1;
  border-radius: 2px 2px 0 0;
  background: linear-gradient(180deg, #2563FF, #45c3d8);
}

/* --- Copy ------------------------------------------------------------------ */
.sa-cta-copy { position: relative; z-index: 1; }
.sa-cta-copy h2 {
  margin: 0 0 16px;
  font-size: clamp(1.6rem, 1.05rem + 1.9vw, 2.5rem);
  font-weight: 800;
  line-height: 1.12;
  letter-spacing: -0.03em;
  color: #fff;
}
.sa-cta-copy p {
  margin: 0 0 26px;
  max-width: 480px;
  font-size: clamp(.95rem, .9rem + .22vw, 1.05rem);
  line-height: 1.66;
  color: rgba(219, 234, 254, 0.86);
}

.sa-cta-actions { display: flex; align-items: center; flex-wrap: wrap; gap: 18px; margin-bottom: 22px; }
.sa-cta-btn {
  display: inline-block;
  padding: 14px 30px;
  border-radius: 12px;
  background: #fff;
  color: #1C4CC4;
  font-size: 15px;
  font-weight: 700;
  text-decoration: none;
  box-shadow: 0 12px 30px rgba(3, 12, 40, 0.28);
  transition: transform .22s cubic-bezier(.16, 1, .3, 1), box-shadow .22s ease;
}
.sa-cta-btn:hover { transform: translateY(-3px); box-shadow: 0 18px 40px rgba(3, 12, 40, 0.36); }
.sa-cta-link {
  color: #9ceefa;
  font-size: 14px;
  font-weight: 600;
  text-decoration: none;
  border-bottom: 1px solid rgba(156, 238, 250, 0.35);
  padding-bottom: 2px;
  transition: color .2s ease, border-color .2s ease;
}
.sa-cta-link:hover { color: #fff; border-color: rgba(255, 255, 255, .7); }

.sa-cta-perks {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 8px 20px;
  margin: 0;
  padding: 0;
}
.sa-cta-perks li {
  position: relative;
  padding-left: 18px;
  font-size: 13px;
  color: rgba(191, 219, 254, 0.82);
}
.sa-cta-perks li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 5px;
  width: 5px;
  height: 9px;
  border-right: 2px solid #4ade80;
  border-bottom: 2px solid #4ade80;
  transform: rotate(42deg);
}

@media (max-width: 980px) {
  .sa-cta-belt { grid-template-columns: 1fr; gap: 30px; }
  .sa-cta-art { height: 260px; order: 2; }
  .sa-cta-copy { order: 1; }
}
@media (max-width: 560px) {
  .sa-cta-belt { padding: 30px 22px; border-radius: 16px; }
  .sa-cta-art { height: 210px; }
  .sa-cta-actions { gap: 14px; }
}
@media (prefers-reduced-motion: reduce) {
  .sa-cta-btn, .sa-cta-link { transition: none; }
  .sa-cta-btn:hover { transform: none; }
}

/* =============================================================================
   POLISH — white CTA belt, tighter radii, tighter rhythm, scroll-in art
   =============================================================================
   Four problems, one pass:

   1. Everything was blue. The hero, the demo band, the book-demo band and the
      closing belt were all the same deep navy-to-cyan, so by the fourth one the
      page had stopped saying anything with colour. The closing belt is now
      white-based, which both breaks that run and lets the report art - white
      pages - finally have something to sit against.
   2. Radii were 20-24px everywhere, which reads soft rather than precise.
      Pulled back to 12-16px across the new sections.
   3. The gap between the book-demo band and the belt was two full section
      paddings stacked. Halved where they meet.
   4. The report art now assembles itself as the belt scrolls into view.
   ============================================================================= */

/* --- 1. White closing belt ------------------------------------------------- */
.sa-cta { padding: clamp(30px, 2vw + 18px, 54px) 24px clamp(52px, 3.4vw + 30px, 86px); }

.sa-cta-belt {
  gap: 52px;
  padding: clamp(38px, 2.8vw + 24px, 62px) clamp(30px, 2.6vw + 20px, 58px);
  border: 1px solid rgba(37, 99, 255, 0.13);
  border-radius: 16px;
  background:
    radial-gradient(700px 400px at 97% 2%, rgba(6, 214, 209, 0.12), transparent 60%),
    linear-gradient(118deg, #ffffff 0%, #f6fafe 46%, #eef5fc 100%);
  box-shadow: 0 22px 54px -30px rgba(13, 53, 128, 0.34);
}
/* A thin brand rule along the top edge - enough colour to tie the belt to the
   theme without another slab of blue. */
.sa-cta-belt::before {
  content: '';
  position: absolute;
  inset: 0 0 auto 0;
  height: 3px;
  background: linear-gradient(90deg, #2563FF, #06D6D1 60%, transparent);
}

.sa-cta-copy h2 { color: #0d1b3d; }
.sa-cta-copy p { color: #52627c; }

/* On white, the primary action has to carry the brand rather than borrow
   contrast from the background. */
.sa-cta-btn {
  background: linear-gradient(135deg, #2563FF, #1C4CC4);
  color: #fff;
  border-radius: 12px;
  box-shadow: 0 12px 26px -10px rgba(37, 99, 255, 0.55);
}
.sa-cta-btn:hover { box-shadow: 0 18px 34px -12px rgba(37, 99, 255, 0.62); }
.sa-cta-link { color: #2563FF; border-bottom-color: rgba(37, 99, 255, 0.30); }
.sa-cta-link:hover { color: #1C4CC4; border-bottom-color: rgba(13, 53, 128, .7); }
.sa-cta-perks li { color: #64748b; }
.sa-cta-perks li::before { border-color: #0d9488; }

/* White pages on a white belt need an edge of their own. */
.sa-cta-page {
  border: 1px solid rgba(37, 99, 255, 0.10);
  border-radius: 8px;
  box-shadow: 0 16px 34px -14px rgba(13, 53, 128, 0.30);
}
.sa-cta-art { height: 360px; }          /* the belt read as short - more room for the art */

/* --- 2. Tighter radii ------------------------------------------------------ */
.sa-fs-card { border-radius: 16px; }
.sa-fs-shot { border-radius: 8px; }
.sa-fs-ico  { border-radius: 12px; }
.sa-bd-band { border-radius: 16px; }
.sa-bd-screen { border-radius: 12px; }
.sa-bd-card-live, .sa-bd-screen .sa-deck-card { border-radius: 12px; }
.sa-stats-inner { border-radius: 16px; }
.sa-stat { border-radius: 12px; }
.sa-demo-frame { border-radius: 12px; }
.sa-modal { border-radius: 16px; }

/* --- 3. Rhythm ------------------------------------------------------------- */
/* Where two dark/tinted bands meet, one section's padding is enough. */
.sa-bd { padding-bottom: clamp(34px, 2.2vw + 20px, 58px); }

/* --- 4. The art assembles on scroll ---------------------------------------
   Transform only, no opacity. If the reveal class never arrives the pages are
   simply stacked square instead of fanned - which still looks deliberate,
   whereas a fade that never runs would leave the belt half empty. */
.sa-cta-page {
  transform: rotate(0deg) translateY(14px) scale(.97);
  transition: transform .85s cubic-bezier(.16, 1, .3, 1);
}
.sa-cta-belt.sa-visible .sa-cta-page-1 { transform: rotate(-4deg)  translateY(0) scale(1); transition-delay: .06s; }
.sa-cta-belt.sa-visible .sa-cta-page-2 { transform: rotate(2.5deg) translateY(0) scale(1); transition-delay: .18s; }
.sa-cta-belt.sa-visible .sa-cta-page-3 { transform: rotate(6deg)   translateY(0) scale(1); transition-delay: .30s; }

/* The bars grow once the belt is in view, so there is movement inside the art
   and not only on its arrival. */
.sa-cta-chart i { transform: scaleY(.25); transform-origin: bottom; transition: transform .8s cubic-bezier(.16, 1, .3, 1); }
.sa-cta-belt.sa-visible .sa-cta-chart i { transform: scaleY(1); }
.sa-cta-belt.sa-visible .sa-cta-chart i:nth-child(1) { transition-delay: .40s; }
.sa-cta-belt.sa-visible .sa-cta-chart i:nth-child(2) { transition-delay: .46s; }
.sa-cta-belt.sa-visible .sa-cta-chart i:nth-child(3) { transition-delay: .52s; }
.sa-cta-belt.sa-visible .sa-cta-chart i:nth-child(4) { transition-delay: .58s; }
.sa-cta-belt.sa-visible .sa-cta-chart i:nth-child(5) { transition-delay: .64s; }
.sa-cta-belt.sa-visible .sa-cta-chart i:nth-child(6) { transition-delay: .70s; }

.sa-cta-ring-arc { stroke-dashoffset: 182; transition: stroke-dashoffset 1.1s cubic-bezier(.16, 1, .3, 1) .34s; }
.sa-cta-belt.sa-visible .sa-cta-ring-arc { stroke-dashoffset: 22; }

@media (prefers-reduced-motion: reduce) {
  .sa-cta-page, .sa-cta-chart i, .sa-cta-ring-arc { transition: none; }
  .sa-cta-page-1 { transform: rotate(-4deg); }
  .sa-cta-page-2 { transform: rotate(2.5deg); }
  .sa-cta-page-3 { transform: rotate(6deg); }
  .sa-cta-chart i { transform: scaleY(1); }
  .sa-cta-ring-arc { stroke-dashoffset: 22; }
}

/* =============================================================================
   HERO — lighter, brighter
   =============================================================================
   The previous base ran #040b24 → #0b2568: technically a navy, visually almost
   black, and heavy enough that the product card looked like it was floating in
   a void. This lifts the whole ramp into the logo's actual blue and lets the
   cyan end of the brand actually appear.

   The ramp is arranged so the light end stays on the RIGHT, behind the product
   card, and the text sits over the darker left. That is not a stylistic
   preference: white clears 7:1 on the left stops and drops to about 2.8:1 on the
   cyan, so anywhere the copy could reach has to stay in the deeper half.
   ============================================================================= */

.sa-hero {
  background:
    radial-gradient(1100px 560px at 84% 6%,  rgba(89, 224, 244, 0.34), transparent 62%),
    radial-gradient(900px 520px at 10% 88%, rgba(37, 99, 235, 0.34), transparent 64%),
    linear-gradient(147deg,
      #0e3a95 0%,
      #1450b8 34%,
      #1a6bc6 62%,
      #1e88c4 86%,
      #22a3c9 100%);
  padding-bottom: clamp(48px, 2.6vw + 30px, 78px);   /* was leaving dead space below the fold */
}

/* Brighter, larger light sources - on the darker base they were barely doing
   anything, which is why the hero read flat as well as heavy. */
.sa-hero::before {
  width: 700px;
  height: 700px;
  top: -220px;
  right: -150px;
  background: radial-gradient(circle, rgba(125, 236, 250, 0.42), transparent 66%);
}
.sa-hero::after {
  width: 760px;
  height: 760px;
  bottom: -320px;
  left: -200px;
  background: radial-gradient(circle, rgba(96, 165, 250, 0.34), transparent 68%);
}

/* A little more grid, since it has more light to read against now. */
.sa-hero-inner::before {
  background-image:
    linear-gradient(rgba(255, 255, 255, 0.07) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.07) 1px, transparent 1px);
  background-size: 60px 60px;
}

/* Soft hand-off into the stats bar instead of a hard horizontal seam between a
   saturated blue and a near-white panel. */
.sa-hero::after { z-index: -1; }
.sa-hero {
  position: relative;
  isolation: isolate;
}
.sa-hero-fade {
  position: absolute;
  inset: auto 0 0 0;
  height: 90px;
  z-index: -1;
  background: linear-gradient(to bottom, transparent, rgba(238, 243, 253, 0.55));
  pointer-events: none;
}

/* Badge and small print need a touch more weight on the lighter ground. */
.sa-hero-badge {
  border-color: rgba(255, 255, 255, 0.34);
  background: rgba(255, 255, 255, 0.14);
  color: #eafcff;
}
.sa-hero-subtitle { color: rgba(233, 243, 255, 0.94); }
.sa-hero-note { color: rgba(226, 240, 255, 0.82); }

/* The white CTA now sits on mid-blue rather than near-black, so it needs its own
   shadow to stay separated from the background. */
.sa-hero-cta {
  box-shadow: 0 14px 38px rgba(6, 30, 78, 0.34);
}
.sa-hero-cta:hover { box-shadow: 0 20px 50px rgba(6, 30, 78, 0.44); }

/* The accent half of the headline was tuned for a near-black ground; on the
   lighter one it needs to stay bright at every point of its sweep. */
.sa-hero-gradient-text {
  background: linear-gradient(100deg, #ffffff 0%, #b8f4ff 30%, #7fe6f4 52%, #b8f4ff 74%, #ffffff 100%);
  background-size: 220% 100%;
  /* The `background` shorthand above resets background-clip to border-box. With
     -webkit-text-fill-color:transparent still inherited from the earlier rule,
     that paints the gradient across the whole box behind invisible glyphs - the
     words vanish and leave a solid rectangle. Any rule that restates the
     shorthand has to restate the clip with it. */
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}

/* Below 1024px the hero stacks and the copy spans the full width - measured at
   96% across and 95% down. On the desktop ramp that puts white body text over
   #1e88c4 (3.91:1) and #22a3c9 (2.94:1), both under AA. The two-column layout is
   what made the bright end safe, so when that layout goes, the bright end goes
   with it: this ramp stops at #1a6bc6, which holds 5.30:1 anywhere the text can
   reach. */
@media (max-width: 1024px) {
  .sa-hero {
    background:
      radial-gradient(620px 420px at 88% 4%, rgba(125, 236, 250, 0.26), transparent 62%),
      radial-gradient(560px 400px at 6% 92%, rgba(37, 99, 235, 0.30), transparent 64%),
      linear-gradient(158deg, #0e3a95 0%, #1450b8 52%, #1a6bc6 100%);
  }
  .sa-hero::before { width: 420px; height: 420px; top: -140px; right: -110px; }
  .sa-hero::after  { width: 460px; height: 460px; bottom: -200px; left: -140px; }
}

/* =============================================================================
   PAGE WASH — the two logo colours, carried to the bottom
   =============================================================================
   The page went saturated blue for the hero and then flat white for everything
   under it, so the brand stopped at the fold. This lays a very light wash of the
   same two logo colours - #2563FF and #06D6D1 - over the whole page and lets it
   fade all the way down, with the individual sections turned transparent so the
   wash reads as one continuous surface rather than a stack of panels.

   Everything here is between 2% and 7% saturation. Body text is dark on light
   throughout, so the wash cannot pull any pairing below AA - the palest stop
   still leaves #52627c body copy at better than 7:1.
   ============================================================================= */

#sa-main-content {
  position: relative;
  isolation: isolate;
  background:
    /* Brand blooms placed down the page so the colour keeps reappearing rather
       than draining out after the hero. */
    radial-gradient(1000px 620px at 92% 16%, rgba(6, 214, 209, 0.10), transparent 62%),
    radial-gradient(900px 580px at 4% 40%,  rgba(37, 99, 255, 0.09), transparent 64%),
    radial-gradient(1100px 700px at 88% 68%, rgba(6, 214, 209, 0.09), transparent 62%),
    radial-gradient(900px 620px at 8% 90%,  rgba(37, 99, 255, 0.08), transparent 64%),
    linear-gradient(180deg,
      #ffffff 0%,
      #f5fafe 14%,
      #eef6fc 38%,
      #eaf4fb 60%,
      #eef7fc 80%,
      #f6fbfe 100%);
}

/* The sections stop painting their own grounds so the wash shows through. Each
   was a slightly different white or grey, which is what made the page read as
   panels stacked on panels. */
.sa-section,
.sa-section-alt,
.sa-stats-bar,
.sa-bd,
.sa-cta,
.sa-fs { background: transparent; }

/* Surfaces that sit ON the wash keep their own white, or they would dissolve
   into it. */
.sa-stats-inner { background: rgba(255, 255, 255, 0.80); }
.sa-fs-card {
  background: linear-gradient(170deg, rgba(255, 255, 255, 0.94) 0%, rgba(247, 251, 254, 0.88) 46%, rgba(255, 255, 255, 0.92) 100%);
}
.sa-cta-belt {
  background:
    radial-gradient(700px 400px at 97% 2%, rgba(6, 214, 209, 0.10), transparent 60%),
    linear-gradient(118deg, #ffffff 0%, #fbfdff 48%, #f4fafe 100%);
}
.sa-fs-shot, .sa-cta-page, .sa-bd-card { background: #fff; }

/* The demo band and the book-demo band are the two deliberately dark moments
   left on the page; they keep their own backgrounds and now sit on the wash
   like objects rather than bands butting into white. */

/* Hero, one step DARKER, and handing off into the page wash rather than into
   plain white. Stops chosen against measured contrast, not by eye - every one
   recomputed for this ramp rather than carried over:

     #113e8f  9.96:1     #12469a  8.87:1     #1651a7  7.58:1
     #1c67ab  5.87:1     #207eaa  4.54:1

   The far stop is the one that mattered. At the old #2694c8 it measured 3.41:1
   and had to be pushed past 88% so no copy ever reached it; at #207eaa it clears
   AA on its own, so the ramp no longer has a corner the text must avoid.

   The two light sources are pulled back as well (0.36 -> 0.28, 0.30 -> 0.26).
   Leaving them where they were would have added back most of the brightness the
   darker stops removed, since they sit over the top. */
.sa-hero {
  background:
    radial-gradient(1100px 560px at 84% 6%,  rgba(150, 240, 252, 0.28), transparent 62%),
    radial-gradient(900px 520px at 10% 88%, rgba(59, 130, 246, 0.26), transparent 64%),
    linear-gradient(147deg,
      #113e8f 0%,
      #12469a 32%,
      #1651a7 58%,
      #1c67ab 82%,
      #207eaa 100%);
}

/* Fades into the wash's own top tone now, so the seam disappears entirely. */
.sa-hero-fade {
  height: 110px;
  background: linear-gradient(to bottom, transparent, rgba(245, 250, 254, 0.72));
}

@media (max-width: 1024px) {
  /* Stacked: the copy spans the full width, so the ramp must stop where white
     text still clears AA. Darkened to match the desktop ramp - #1651a7 is
     7.58:1, comfortably past the 6.04:1 the old end stop gave. */
  .sa-hero {
    background:
      radial-gradient(620px 420px at 88% 4%, rgba(150, 240, 252, 0.20), transparent 62%),
      radial-gradient(560px 400px at 6% 92%, rgba(59, 130, 246, 0.24), transparent 64%),
      linear-gradient(158deg, #113e8f 0%, #12469a 54%, #1651a7 100%);
  }
}

/* -----------------------------------------------------------------------------
   Features rail: full-bleed
   -----------------------------------------------------------------------------
   The rail was boxed inside the 1200px container, so it ended in mid-air with
   whitespace either side and the "there is more" cue was weakened. It now spans
   the viewport and runs off both edges, while its left padding keeps the first
   card aligned to the heading above it - the header stays in the grid, the cards
   escape it.

   100vw is safe here only because .sa-fs clips overflow: on a page with a
   vertical scrollbar 100vw is wider than the content box, and without that clip
   this would add a horizontal scrollbar to the whole document.
   -------------------------------------------------------------------------- */
.sa-fs-rail {
  width: 100vw;
  margin-left: calc(50% - 50vw);
  margin-right: calc(50% - 50vw);
  /* Aligns the first card with the container edge at any width, and falls back
     to the page gutter once the viewport is narrower than the container. */
  padding-left: max(24px, calc(50vw - 600px));
  padding-right: max(24px, calc(50vw - 600px));
  /* Snap points have to respect that padding or the first card lands under it. */
  scroll-padding-left: max(24px, calc(50vw - 600px));
}

/* -----------------------------------------------------------------------------
   Feature cards: separated from the wash
   -----------------------------------------------------------------------------
   The cards were near-white on a pale blue wash, so they floated with no clear
   edge. They now carry a deeper tint than the page behind them, which also sets
   up a proper three-step hierarchy: wash (palest) → card (mid) → the mock inside
   it (white), so the product surface is the brightest thing on the card.

   Darkening the ground pushed the old body colour (#5b6b83) to 4.40:1, just
   under AA, and the eyebrow to 4.13:1. Both moved down with it rather than being
   left behind - a tint change that quietly breaks contrast is the usual way
   these regressions get shipped.
   -------------------------------------------------------------------------- */
.sa-fs-card {
  background: linear-gradient(170deg, #e4eefa 0%, #dde9f6 52%, #e7f1fb 100%);
  border-color: rgba(37, 99, 255, 0.16);
  box-shadow: 0 2px 6px -2px rgba(13, 53, 128, 0.10);
}
.sa-fs-card:hover {
  border-color: rgba(37, 99, 255, 0.30);
  box-shadow: 0 22px 48px -20px rgba(13, 53, 128, 0.34);
}

.sa-fs-card p { color: #475569; }        /* 6.16:1 on the tint */
.sa-fs-eyebrow { color: #365a92; }       /* 5.62:1 on the tint */

/* The mock is now the brightest surface on the card, so it needs a touch more
   edge to stay crisp against the deeper ground. */
.sa-fs-shot {
  background: #fff;
  border-color: rgba(37, 99, 255, 0.14);
  box-shadow: 0 6px 16px -8px rgba(13, 53, 128, 0.30);
}
.sa-fs-ico { box-shadow: 0 2px 10px -3px rgba(37, 99, 255, 0.32), inset 0 0 0 1px rgba(37, 99, 255, 0.12); }

/* Square corners on the feature cards. The mock frame squares with them - a
   rounded panel inside a sharp card reads as a mismatch rather than a detail.
   The micro-elements inside the mock keep their radii on purpose: they are
   standing in for the real product UI, which is rounded, and squaring those
   would make the mock stop looking like the app. */
.sa-fs-card { border-radius: 0; }
.sa-fs-shot { border-radius: 0; }
.sa-fs-ico  { border-radius: 4px; }


/* =============================================================================
   AI CAPABILITIES — twelve equal cards
   =============================================================================
   Supersedes the bento. Mixed spans made the block busy and implied a ranking
   these twelve peers do not have; equal cards state them as the set they are.

   What carries the design instead of size variation:
     * three columns, not four - the descriptions had been wrapping to four
       cramped lines in a narrow slot;
     * a numeral per card, which turns twelve tiles into a legible sequence;
     * a brand rule that draws across the top on hover, so the interaction is
       precise rather than a card wobbling upward.
   ============================================================================= */

.sa-cap-sec .sa-section-header { text-align: center; margin-bottom: 40px; }
.sa-cap-sec .sa-section-title { justify-content: center; }
.sa-cap-sec .sa-section-subtitle { margin-inline: auto; }

/* Brand, not the violet this section used to carry - it was the only purple
   left on a page unified around #2563FF / #06D6D1. */
.sa-ai-section-badge {
  background: linear-gradient(135deg, #2563FF, #0e7fa8);
  color: #fff;
}


/* Top rule drawn on hover. scaleX on a pseudo-element, so it cannot reflow the
   card the way a border-width change would. */

/* The numeral sits in the corner as a quiet index rather than a decoration -
   it gives twelve equal cards a reading order without changing their weight. */


@media (max-width: 980px) {
  .sa-caps { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 600px) {
  .sa-caps { grid-template-columns: minmax(0, 1fr); }
  .sa-cap { padding: 20px 18px 18px; }
}

@media (prefers-reduced-motion: reduce) {
  .sa-cap, .sa-cap::before, .sa-cap-ico, .sa-cap-num { transition: none; }
}

/* =============================================================================
   FEATURE DEEP DIVES — animation
   =============================================================================
   Everything here keys off .sa-visible, which the reveal observer adds when the
   block scrolls into view. The parent already fades in, so the bars, list and
   card only need to say how they arrive.

   Every animation uses fill-mode `backwards` over a resting state that is the
   FINISHED state. That ordering is the whole safety argument: if an animation
   never runs - reduced motion, a browser that skips it, a reveal class that
   never lands - the bars are drawn, the numbers are readable and the card is
   in place. Animating from a hidden resting state would leave an empty panel.
   ============================================================================= */

/* --- Bars grow -------------------------------------------------------------
   scaleX on the fill rather than animating `width`: the inline width stays as
   the true target (no need to duplicate 85%/80%/35%/12% in CSS), and a
   transform animates on the compositor instead of laying out every frame. */
.sa-visual-bar-fill {
  transform-origin: left center;
  transform: scaleX(1);
}
.sa-animate-on-scroll.sa-visible .sa-visual-bar-fill {
  animation: sa-dd-grow .95s cubic-bezier(.16, 1, .3, 1) backwards;
}
@keyframes sa-dd-grow {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}
/* Staggered so the four bars read as a sequence rather than one block move. */
.sa-visible .sa-visual-bar-row:nth-child(2) .sa-visual-bar-fill { animation-delay: .10s; }
.sa-visible .sa-visual-bar-row:nth-child(3) .sa-visual-bar-fill { animation-delay: .22s; }
.sa-visible .sa-visual-bar-row:nth-child(4) .sa-visual-bar-fill { animation-delay: .34s; }
.sa-visible .sa-visual-bar-row:nth-child(5) .sa-visual-bar-fill { animation-delay: .46s; }

/* The figure fades in just behind its own bar, so the number lands as the bar
   settles rather than sitting there while the bar is still empty. */
.sa-animate-on-scroll.sa-visible .sa-visual-bar-value {
  animation: sa-dd-fade .5s ease backwards;
}
@keyframes sa-dd-fade {
  from { opacity: 0; transform: translateX(-6px); }
  to   { opacity: 1; transform: none; }
}
.sa-visible .sa-visual-bar-row:nth-child(2) .sa-visual-bar-value { animation-delay: .34s; }
.sa-visible .sa-visual-bar-row:nth-child(3) .sa-visual-bar-value { animation-delay: .46s; }
.sa-visible .sa-visual-bar-row:nth-child(4) .sa-visual-bar-value { animation-delay: .58s; }
.sa-visible .sa-visual-bar-row:nth-child(5) .sa-visual-bar-value { animation-delay: .70s; }

/* --- Checklist ticks in ----------------------------------------------------- */
.sa-animate-on-scroll.sa-visible .sa-deep-dive-content ul li {
  animation: sa-dd-item .55s cubic-bezier(.16, 1, .3, 1) backwards;
}
@keyframes sa-dd-item {
  from { opacity: 0; transform: translateX(-12px); }
  to   { opacity: 1; transform: none; }
}
.sa-visible .sa-deep-dive-content ul li:nth-child(1) { animation-delay: .14s; }
.sa-visible .sa-deep-dive-content ul li:nth-child(2) { animation-delay: .24s; }
.sa-visible .sa-deep-dive-content ul li:nth-child(3) { animation-delay: .34s; }
.sa-visible .sa-deep-dive-content ul li:nth-child(4) { animation-delay: .44s; }

/* --- Card arrives ----------------------------------------------------------
   From the side the block is laid out on, so it reads as sliding in from the
   page edge rather than drifting in from nowhere. */
.sa-animate-on-scroll.sa-visible .sa-deep-dive-visual-card {
  animation: sa-dd-card .8s cubic-bezier(.16, 1, .3, 1) backwards;
}
@keyframes sa-dd-card {
  from { opacity: 0; transform: translateX(26px) scale(.985); }
  to   { opacity: 1; transform: none; }
}
.sa-reversed.sa-visible .sa-deep-dive-visual-card { animation-name: sa-dd-card-rev; }
@keyframes sa-dd-card-rev {
  from { opacity: 0; transform: translateX(-26px) scale(.985); }
  to   { opacity: 1; transform: none; }
}

/* The label reads as a small kicker, so it arrives first and on its own. */
.sa-animate-on-scroll.sa-visible .sa-deep-dive-label {
  animation: sa-dd-fade .5s ease backwards;
}

@media (prefers-reduced-motion: reduce) {
  .sa-animate-on-scroll.sa-visible .sa-visual-bar-fill,
  .sa-animate-on-scroll.sa-visible .sa-visual-bar-value,
  .sa-animate-on-scroll.sa-visible .sa-deep-dive-content ul li,
  .sa-animate-on-scroll.sa-visible .sa-deep-dive-visual-card,
  .sa-animate-on-scroll.sa-visible .sa-deep-dive-label { animation: none; }
}

/* =============================================================================
   HERO — the audit field
   =============================================================================
   The single element that makes this hero this product's rather than any SaaS
   product's. It is styled as one object - prefix, field and button share a
   surface - so it reads as an instrument rather than three controls that happen
   to sit next to each other.
   ============================================================================= */

.sa-hero-check {
  position: relative;
  overflow: hidden;
  display: flex;
  align-items: stretch;
  width: 100%;
  max-width: 520px;
  margin-bottom: 14px;
  border: 1.5px solid rgba(255, 255, 255, 0.34);
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.13);
  backdrop-filter: blur(10px);
  box-shadow: 0 14px 40px rgba(4, 20, 60, 0.28);
  transition: border-color .24s ease, background .24s ease, box-shadow .24s ease;
}
.sa-hero-check:focus-within {
  border-color: rgba(150, 240, 252, 0.86);
  background: rgba(255, 255, 255, 0.19);
  box-shadow: 0 18px 48px rgba(4, 20, 60, 0.36), 0 0 0 4px rgba(6, 214, 209, 0.20);
}
.sa-hero-check.is-invalid { border-color: rgba(255, 176, 176, 0.85); }

/* A slow sweep across the field - the one piece of motion that says "this thing
   scans your site" without a word of copy. It stops on focus: movement behind a
   caret is a distraction, not a delight. */
.sa-hero-check-scan {
  position: absolute;
  top: 0;
  left: -45%;
  width: 38%;
  height: 100%;
  background: linear-gradient(100deg, transparent, rgba(150, 240, 252, 0.20), transparent);
  animation: sa-hero-scan 4.6s cubic-bezier(.5, 0, .5, 1) infinite;
  pointer-events: none;
}
.sa-hero-check:focus-within .sa-hero-check-scan { animation-play-state: paused; opacity: 0; }
@keyframes sa-hero-scan {
  0%, 12%  { left: -45%; }
  62%      { left: 108%; }
  100%     { left: 108%; }
}

.sa-hero-check-prefix {
  display: flex;
  align-items: center;
  padding: 0 2px 0 18px;
  color: rgba(226, 240, 255, 0.62);
  font-size: 15px;
  font-weight: 500;
  cursor: text;          /* clicking the prefix focuses the field - one object */
  user-select: none;
}

.sa-hero-check-input {
  flex: 1;
  min-width: 0;
  padding: 17px 12px 17px 2px;
  border: 0;
  background: transparent;
  color: #fff;
  font-family: inherit;
  font-size: 15.5px;
  font-weight: 500;
  outline: none;
}
.sa-hero-check-input::placeholder { color: rgba(226, 240, 255, 0.52); font-weight: 400; }

.sa-hero-check-btn {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
  margin: 5px;
  padding: 0 20px;
  border: 0;
  border-radius: 8px;
  background: #fff;
  color: #1C4CC4;
  font-family: inherit;
  font-size: 14.5px;
  font-weight: 700;
  white-space: nowrap;
  cursor: pointer;
  transition: background .2s ease, transform .2s cubic-bezier(.16, 1, .3, 1), box-shadow .2s ease;
}
.sa-hero-check-btn svg { width: 16px; height: 16px; transition: transform .24s cubic-bezier(.16, 1, .3, 1); }
.sa-hero-check-btn:hover { transform: translateY(-1px); box-shadow: 0 10px 24px rgba(4, 20, 60, 0.34); }
.sa-hero-check-btn:hover svg { transform: translateX(3px); }
.sa-hero-check-btn:focus-visible { outline: 3px solid #9ceefa; outline-offset: 3px; }

.sa-hero-hint { color: #ffd7d7; font-weight: 600; }

@media (max-width: 560px) {
  /* The button wraps under the field rather than squeezing the input down to a
     few characters - a domain has to stay readable while it is being typed. */
  .sa-hero-check { flex-wrap: wrap; }
  .sa-hero-check-input { flex: 1 0 60%; }
  .sa-hero-check-btn { flex: 1 0 100%; margin: 0 5px 5px; padding: 13px 20px; justify-content: center; }
}

@media (prefers-reduced-motion: reduce) {
  .sa-hero-check-scan { animation: none; opacity: 0; }
  .sa-hero-check-btn, .sa-hero-check-btn svg, .sa-hero-check { transition: none; }
  .sa-hero-check-btn:hover { transform: none; }
}

/* =============================================================================
   HERO → PAGE: no seam
   =============================================================================
   The blue simply stopped where the wash began, leaving a hard horizontal edge.
   The old fade could not close it for two reasons, both fixed here:

     1. It ended at rgba(245,250,254,0.72) - never fully opaque - so however soft
        the ramp looked, the last pixel was still blue meeting near-white.
     2. It sat at z-index:-1, the same layer as the hero's two blurred blooms,
        and ::after paints after a child at equal z-index. The bottom-left bloom
        was punching straight through the fade it was supposed to be behind.

   The end colour is not eyeballed. The page wash is
   `linear-gradient(180deg, #ffffff 0%, #f5fafe 14%, ...)` and the hero's bottom
   edge measures 2.60% down that gradient, which resolves to #fdfeff. Ending the
   fade on exactly that value means the two surfaces meet at the same colour and
   there is no edge left to see.
   ============================================================================= */

.sa-hero-fade {
  height: 200px;
  z-index: 0;                /* above the blooms, below the content */
  background: linear-gradient(
    to bottom,
    rgba(253, 254, 255, 0) 0%,
    rgba(253, 254, 255, 0.42) 46%,
    rgba(253, 254, 255, 0.82) 76%,
    #fdfeff 100%
  );
}

/* Content has to clear the fade now that the fade is no longer behind
   everything. */
.sa-hero-inner { z-index: 2; }

/* The bottom-left bloom is pulled up and softened so it finishes well before the
   blend starts - otherwise it fights the fade for the same 200px. */
.sa-hero::after {
  bottom: -380px;
  background: radial-gradient(circle, rgba(59, 130, 246, 0.26), transparent 70%);
}

/* Same treatment under 1024px, where the hero is shorter and the fade would
   otherwise eat into the copy. */
@media (max-width: 1024px) {
  .sa-hero-fade { height: 140px; }
}

/* The blend needs a band of hero to work in, and that band has to be empty.
   Measured before this rule: the "Free plan, no credit card" note sat 83% into
   the fade, where the whitening is already 87% - light text on near-white, which
   is a worse defect than the seam the fade was added to remove. The hero's
   bottom padding now reserves the fade's height plus a little, so the copy ends
   above the blend rather than inside it. */
.sa-hero { padding-bottom: 186px; }
.sa-hero-fade { height: 150px; }

@media (max-width: 1024px) {
  .sa-hero { padding-bottom: 156px; }
  .sa-hero-fade { height: 116px; }
}

/* =============================================================================
   HERO → PAGE: one long ramp, no onset
   =============================================================================
   The 116px fade still read as a line because a short blend cannot hide where it
   starts: the alpha has to climb ~1% per pixel, and the eye finds that onset.
   The blend is now 288px with seven eased stops, so the change per pixel is
   small enough that there is no point to see.

   That space has to be empty, which is why the hero's bottom padding grew to
   match it. The hero is taller as a result - the deliberate trade for a page
   that reads as one continuous surface instead of two stacked colours.
   ============================================================================= */

.sa-hero { padding-bottom: 326px; }
.sa-hero-fade {
  height: 300px;
  /* Linear, deliberately. For a 0 -> 1 blend over a fixed distance, a straight
     ramp is the flattest possible: it spreads the change evenly, so the steepest
     rate is simply 1/height. Any easing has to make some segment steeper to make
     another shallower - measured, the eased version peaked at 0.868% alpha per
     pixel, exactly as bad as the short fade it replaced. Linear over 300px is
     0.33%/px, which is below the threshold where an onset is visible. */
  background: linear-gradient(to bottom, rgba(253, 254, 255, 0) 0%, rgba(253, 254, 255, 1) 100%);
}

/* Both blooms finish above the ramp so neither reappears through it. */
.sa-hero::before { top: -260px; }
.sa-hero::after  { bottom: -520px; }

/* The grid is masked to fade out before the ramp begins - its lines were the
   sharpest thing crossing the blend, and a straight line through a soft gradient
   is exactly what the eye reads as an edge. */
.sa-hero-inner::before {
  mask-image: radial-gradient(circle at 50% 34%, #000 0%, transparent 62%);
  -webkit-mask-image: radial-gradient(circle at 50% 34%, #000 0%, transparent 62%);
}

@media (max-width: 1024px) {
  .sa-hero { padding-bottom: 272px; }
  .sa-hero-fade { height: 248px; }
}

/* =============================================================================
   RHYTHM — reclaim the gap the ramp created
   =============================================================================
   The blend needs length to stay invisible, but that length does not have to be
   empty page. Previously the hero reserved ~300px of nothing AND the stats bar
   added its own top padding on top of it, so the fold ended with a third of a
   screen of dead space.

   The fix is overlap, not compression: the ramp's lower half is more than half
   white, and the section below is white, so the stats card can sit ON the ramp's
   tail instead of waiting for it to finish. The blend keeps its full length; the
   page loses the emptiness.
   ============================================================================= */

.sa-hero { padding-bottom: 262px; }
.sa-hero-fade { height: 248px; }        /* 0.40% alpha per px - still below the visible threshold */

/* Pulled up into the pale end of the ramp. The card is white with dark text, so
   a background that is already 60%+ white behind it costs nothing in contrast. */
.sa-stats-bar {
  position: relative;
  z-index: 1;
  margin-top: -140px;
  padding-top: 0;
}

@media (max-width: 1024px) {
  .sa-hero { padding-bottom: 214px; }
  .sa-hero-fade { height: 200px; }
  .sa-stats-bar { margin-top: -112px; }
}

/* --- Global rhythm ---------------------------------------------------------
   Sections were on a 64-116px scale, which reads as generous on one section and
   as drift by the fifth. Tightened roughly 25% across the page. */
.sa-section { padding: clamp(48px, 3.2vw + 28px, 86px) 24px; }
.sa-bento-sec,
.sa-bd {
  padding-top: clamp(48px, 3.2vw + 28px, 84px);
  padding-bottom: clamp(28px, 1.8vw + 16px, 46px);
}
.sa-cta { padding: clamp(26px, 1.8vw + 14px, 44px) 24px clamp(44px, 2.8vw + 26px, 72px); }

/* =============================================================================
   HERO — centred copy, product charts as atmosphere
   =============================================================================
   The product deck is gone from the right column and the copy is centred. In its
   place, the shapes the app actually draws after login - the health-score donut,
   the category columns, the score trend and the crawl bar - are laid into the
   hero as background texture.

   The rule that shapes all of this: no card, no frame, no fill. Every piece is a
   stroke or a bar sitting directly on the gradient, so nothing reads as a
   rectangle floating on the hero. They are aria-hidden and never carry a number,
   because at this opacity they are texture, not information.
   ============================================================================= */

.sa-hero-inner {
  display: block;                    /* was a two-column layout */
  max-width: 860px;
  margin-inline: auto;
  text-align: center;
}
/* The content column kept a 560px max-width from the two-column layout, with no
   auto margins - so inside the centred 860px wrapper it sat flush left, exactly
   half the 300px difference off centre. */
.sa-hero-content {
  align-items: center;
  max-width: 640px;
  margin-inline: auto;
}
.sa-hero h1 { margin-inline: auto; }
.sa-hero-subtitle { margin-inline: auto; }

/* The audit field keeps its own width but centres in the column. */
.sa-hero-check { margin-inline: auto; }
.sa-hero-buttons { justify-content: center; }

/* --- The chart layer -------------------------------------------------------
   Behind the copy, above the gradient and its blooms. Nothing here may catch a
   pointer or reach the accessibility tree. */
.sa-hero-inner { position: relative; z-index: 2; }


/* Shared stroke language - the app's ring weight, no fills anywhere. */

/* --- Health-score donut, upper right --------------------------------------- */

/* --- Category columns, lower left ------------------------------------------
   scaleY from the baseline, so the bars grow the way the report's do. No track
   behind them - a track would be the rectangle this whole treatment avoids. */

/* --- Score trend ------------------------------------------------------------ */

/* --- Severity ring, upper left ---------------------------------------------- */

/* --- Crawl bar, a bare rule ------------------------------------------------- */

/* Below the two-column breakpoint the charts crowd the centred copy, so the
   pair nearest the text step back and the rest shrink. */


/* =============================================================================
   HERO — balanced chart clusters, bigger headline, rotating second line
   =============================================================================
   Supersedes the scattered-shape version. Everything below replaces its
   equivalent above.

   Three changes:
     1. The charts are two mirrored clusters, left and right, instead of five
        shapes dotted around - the sides were empty and the arrangement read as
        accidental. The copy now sits in a channel between two balanced groups.
     2. The headline is larger and holds a fixed first line.
     3. The second line cycles through what the product actually does.
   ============================================================================= */

/* --- Headline --------------------------------------------------------------- */
.sa-hero h1 {
  /* Two lines by design - "AI-Powered SEO" / "Audits in Minutes" - which
     `text-wrap: balance` splits evenly. At the 4.9rem ceiling the longer line
     measures ~663px against the 860px wrapper, so the size can grow this far
     before a third line appears. That headroom is the constraint to check if
     this is ever raised again: keep the balanced line under 860px. */
  /* Floor is 2.1rem, not 2.4: the lines are now split in markup, so
     `text-wrap: balance` can no longer rescue a line that does not fit. At
     320px the column is 272px and "AI-Powered SEO" needs 294px at 2.4rem - it
     broke at the hyphen into a third line. 2.1rem needs 257px. That is the
     binding constraint at the small end; the 860px wrapper is the one at the
     large end. */
  /* Ceiling 6.5rem = 104px, which is where the 860px wrapper runs out: line one
     measures 790px there, and overflows past ~112px. The ramp is re-solved so
     the ceiling lands at ~1405px rather than 1920 - most desktops are 1440, and
     that is the width this headline is being judged at.

     The slope is steep (6.9vw) on purpose. A gentler ramp with a high base
     would hold 104px down into phone widths, where the column is 342px and line
     one needs ~790px - three lines and an overflow. Base low, slope steep, is
     what keeps 320px and 1440px both correct off one expression. */
  font-size: clamp(2.1rem, 0.44rem + 6.9vw, 6.5rem);
  line-height: 1.06;
  letter-spacing: -0.036em;
  max-width: none;
  width: 100%;
}
/* The headline alone escapes the 640px copy column - the rest of the block stays
   at a comfortable reading measure. */
.sa-hero-content > h1 { width: min(860px, 92vw); margin-inline: auto; }

/* The rotating line. Stacked spans, swapped in CSS - a timer would re-render the
   whole page on every phrase. The box reserves one line of height so the
   headline never reflows as the phrases change length. */
.sa-hero-rot {
  position: relative;
  display: block;
  height: 1.06em;                  /* == h1 line-height */
}
.sa-hero-rot > span {
  position: absolute;
  left: 50%;
  top: 0;
  white-space: nowrap;
  opacity: 0;
  transform: translate(-50%, 0);
  animation: sa-hero-rot 17.5s cubic-bezier(.16, 1, .3, 1) infinite;
  /* Inherit the gradient fill from the parent rather than re-declaring it -
     restating the `background` shorthand here would reset background-clip and
     paint a solid block over invisible glyphs. */
  background: inherit;
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}
/* Fail-safe: the first phrase is visible on its own merits. If the animation
   never runs, the headline still reads as a finished sentence rather than
   losing its second line entirely. */
.sa-hero-rot > span:first-child { opacity: 1; }

.sa-hero-rot > span:nth-child(1) { animation-delay: 0s; }
.sa-hero-rot > span:nth-child(2) { animation-delay: 3.5s; }
.sa-hero-rot > span:nth-child(3) { animation-delay: 7s; }
.sa-hero-rot > span:nth-child(4) { animation-delay: 10.5s; }
.sa-hero-rot > span:nth-child(5) { animation-delay: 14s; }

/* 5 phrases over 17.5s = 20% each: rise in, hold, lift out. */
@keyframes sa-hero-rot {
  0%              { opacity: 0; transform: translate(-50%, 34%); }
  3%, 17%         { opacity: 1; transform: translate(-50%, 0); }
  20%             { opacity: 0; transform: translate(-50%, -34%); }
  100%            { opacity: 0; transform: translate(-50%, -34%); }
}


/* Columns — under the ring */

/* Trend — across the bottom of the cluster */


@media (prefers-reduced-motion: reduce) {
  .sa-hero-rot > span { animation: none; opacity: 0; }
  .sa-hero-rot > span:first-child { opacity: 1; }   /* one phrase, held */
}

/* =============================================================================
   HERO — charts out of the copy, static headline
   =============================================================================
   Two corrections to the previous pass.

   1. The clusters were positioned by eye and ended up UNDER the text - measured,
      the left ring crossed the headline and its columns crossed the subtitle.
      Low-opacity shapes behind type do not read as atmosphere, they read as a
      dirty background. Each cluster is now sized to the free channel beside the
      copy: width = (viewport - copy width) / 2, so it can never reach the text.
      Below the width where that channel stops being wide enough, they are gone
      rather than squeezed.

   2. The rotating second line is removed. It rendered all five phrases stacked
      on top of one another on the reporter's machine, and this environment
      cannot run the animation to verify a fix. An effect that cannot be tested
      does not belong on the most important line of the page.
   ============================================================================= */

.sa-hero-rot { display: none; }        /* markup gone too; belt and braces */

/* --- Clusters confined to the channel beside the copy --------------------- */

/* Sized to the cluster, not the viewport, so nothing spills into the channel's
   neighbour. */

/* Under ~1200px the channel is narrower than the smallest useful cluster, so the
   charts would have to sit under the copy to exist at all. They don't. */
@media (max-width: 1200px) {
  .sa-hero-charts { display: none; }
}

/* The headline was 860px wide inside a 640px copy column. `margin-inline: auto`
   cannot centre a child that is wider than its parent - it overflows to one side
   instead, which pushed the headline 110px right and straight into the right-hand
   cluster. Widen the column and constrain the elements that actually want a
   narrow measure, rather than making one child fight its container. */
.sa-hero-content { max-width: 860px; }
.sa-hero-content > h1 { width: 100%; }
.sa-hero-subtitle { max-width: 640px; margin-inline: auto; }

/* =============================================================================
   HERO BACKDROP — the audit run, not abstract charts
   =============================================================================
   Replaces the rings/columns/trend arrangement. Those were generic dataviz
   shapes: they could have belonged to any dashboard, which is exactly the
   objection. What is here now is the run screen this product actually shows -
   the completion ring, and the Crawl → Analyze → Recommendations → Done rail
   with each step lighting as it is reached.

   Both sides share one 11s cycle so the ring and the pipeline agree with each
   other: the ring is filling while the steps advance, and both reset together.
   ============================================================================= */

/* The old shapes are gone from the markup; these clear their rules. */


/* --- Completion ring -------------------------------------------------------- */
/* Paced like a real audit: quick through the crawl, a pause while analysis
   runs, then the last stretch. A constant sweep reads as a spinner. */

/* --- Pipeline rail ---------------------------------------------------------- */

/* Each step: hollow while pending, filled once reached - the same read as the
   run screen, where a completed stage goes solid. */
/* Stagger which step is "current" by delaying the fill on each. */


/* -----------------------------------------------------------------------------
   Features rail: continuous glide
   -----------------------------------------------------------------------------
   Two properties had to go for the drift to work:

     * scroll-snap-type. Snap and continuous motion are contradictory - the
       browser re-snaps to the nearest card the moment scrolling settles, which
       fights a rail moving a fraction of a pixel per frame and shows up as
       jitter. The arrows still land on card boundaries because they scroll by an
       exact card width.
     * scroll-behavior: smooth. It applies to direct scrollLeft assignment too, so
       every 0.35px step would have been animated in its own right. The arrows
       pass behavior:'smooth' per call, so they keep their easing.
   -------------------------------------------------------------------------- */
.sa-fs-rail {
  scroll-snap-type: none;
  scroll-behavior: auto;
}
.sa-fs-card { scroll-snap-align: none; }

/* Clones exist only to make the wrap seamless - they must never be announced or
   focusable, and they carry no semantics of their own. */
.sa-fs-card[data-clone] { pointer-events: none; }

/* =============================================================================
   HERO BACKDROP — the run screen, in 3D
   =============================================================================
   Supersedes the stripped-back rings and blank bars. This is the progress screen
   as the app draws it: percentage, phase caption, and the four named stages.

   The 3D is what keeps it readable as *background* despite now carrying words.
   Each side is rotated away from the viewer on its own axis, so the panels read
   as receding into the page rather than as text competing with the headline.
   ============================================================================= */


/* Turned away from the centre, lifted slightly, and pushed back in Z. The far
   edge of each panel ends up smaller and dimmer than the near edge - depth the
   eye reads without any of it being explained. */

/* --- Completion dial -------------------------------------------------------- */


/* --- Stage rail ------------------------------------------------------------- */
/* The rail between the nodes, drawn from each row to the next. */


/* Reached, and currently running. */

@media (max-width: 1200px) { .sa-hero-charts { display: none; } }


/* Rotating around the centre swings each panel's near edge INWARD - measured,
   the stage rail projected 90px left of its cluster and cut 40px into the
   headline. Pivoting from the outer edge sends that swing away from the copy
   instead, which is the difference between depth and collision. */

/* Each panel was centred in its cluster, so half the spare width sat on the
   inner side - where the copy is. Aligning each to its OUTER edge spends that
   slack away from the text instead. "Recommendations" is the longest label on
   the page's backdrop and was the one still clipping the headline. */

/* The rail was as wide as its cluster, so there was no slack for the previous
   alignment fix to spend - "Recommendations" simply needs less width. Narrower
   list, slightly smaller label, and a shallower turn on the right so the 3D
   projection widens it less. Measured target: clear the headline, which ends at
   1145px on a 1440 viewport. */

/* -----------------------------------------------------------------------------
   Feature rail: focus the hovered card
   -----------------------------------------------------------------------------
   Hovering a card lifts and enlarges it while its neighbours fade back, so the
   one being read is the only one competing for attention. The rail already
   pauses its glide on hover, so the enlarged card holds still to be read rather
   than sliding out from under the cursor.
   -------------------------------------------------------------------------- */
.sa-fs-card {
  transition:
    transform .34s cubic-bezier(.16, 1, .3, 1),
    opacity .34s ease,
    box-shadow .34s ease,
    border-color .34s ease;
}

/* Only the hovered card responds - the others stay at full strength. Dimming
   them made the rail feel like it was switching off around the cursor. */
.sa-fs-rail .sa-fs-card:hover {
  transform: translateY(-8px) scale(1.055);
  z-index: 3;                     /* above its neighbours once it overlaps them */
  border-color: rgba(37, 99, 255, 0.34);
  box-shadow: 0 28px 56px -22px rgba(13, 53, 128, 0.42);
}

/* The rail clips vertically (overflow-y is hidden once overflow-x scrolls), so a
   card scaled past its box would have its top and bottom cropped. This reserves
   the growth: 454px * 0.055 ~= 25px, split either side, plus the 8px lift. */
.sa-fs-rail { padding-top: 22px; padding-bottom: 22px; }

@media (prefers-reduced-motion: reduce) {
  .sa-fs-rail .sa-fs-card:hover { transform: none; }
}

/* Touch has no hover: without this the first tap would dim every card and leave
   them that way until the pointer moved somewhere else. */
/* Touch has no hover, so the lift would stick on whatever was tapped last. */
@media (hover: none) {
  .sa-fs-rail .sa-fs-card:hover { transform: none; }
}

/* =============================================================================
   HERO — the final treatment
   =============================================================================
   Every previous version put OBJECTS behind the copy: charts, panels, a labelled
   pipeline. Each one competed with the headline, and each fix for one collision
   created the next. The lesson is structural, not stylistic - type and diagrams
   cannot share the same space at the same size.

   So the backdrop is light, not drawing. Colour and depth can sit behind words
   without arguing with them, which is why every serious tool site does exactly
   this. The product gets to prove itself below the fold, where it has room.

   With the decoration gone, the effort goes where it earns something: the URL
   field. It is the one thing on this screen a visitor can act on, so it is
   built to be the unmistakable focal point.
   ============================================================================= */

/* --- Depth without objects -------------------------------------------------
   Three slow, very large lights on mismatched loops. Large and soft enough that
   no edge is ever legible as a shape - the eye reads "lit", not "circle". */
.sa-hero::before {
  width: 900px;
  height: 900px;
  top: -340px;
  right: -220px;
  background: radial-gradient(circle, rgba(150, 240, 252, 0.34), transparent 66%);
  filter: blur(130px);
  animation: sa-hero-drift-a 26s ease-in-out infinite;
}
.sa-hero::after {
  width: 980px;
  height: 980px;
  bottom: -560px;
  left: -280px;
  background: radial-gradient(circle, rgba(59, 130, 246, 0.30), transparent 68%);
  filter: blur(140px);
  animation: sa-hero-drift-b 34s ease-in-out infinite;
}
/* A third, centred behind the copy, so the middle is not the darkest part of
   the composition - which is what made earlier versions feel hollow. */
.sa-hero-inner::after {
  content: '';
  position: absolute;
  z-index: -1;
  left: 50%;
  top: 44%;
  width: min(1100px, 96vw);
  height: 620px;
  transform: translate(-50%, -50%);
  background: radial-gradient(ellipse at center, rgba(129, 214, 255, 0.16), transparent 68%);
  filter: blur(60px);
  pointer-events: none;
}

/* The grid reads as engineering rather than ornament, so it stays - but pulled
   back and masked tighter, as a texture rather than a pattern. */
.sa-hero-inner::before {
  background-size: 72px 72px;
  background-image:
    linear-gradient(rgba(255, 255, 255, 0.055) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.055) 1px, transparent 1px);
  mask-image: radial-gradient(ellipse 76% 62% at 50% 42%, #000 8%, transparent 72%);
  -webkit-mask-image: radial-gradient(ellipse 76% 62% at 50% 42%, #000 8%, transparent 72%);
}

/* --- Type ------------------------------------------------------------------ */
/* max() against the nav height, not a bare clamp. The nav is FIXED, so it is
   painted over this padding - a clamp tuned independently of it can (and did)
   resolve to less than the bar is tall, leaving the badge flush against it. The
   first term guarantees clearance; the second still drives the spacing whenever
   it is the larger, so the desktop look is unchanged. */
.sa-hero { padding-top: max(calc(var(--sa-nav-height) + 36px), clamp(84px, 5vw + 52px, 136px)); }
.sa-hero-badge { margin-bottom: 26px; }
.sa-hero h1 { margin-bottom: 22px; }
.sa-hero-subtitle {
  max-width: 600px;
  font-size: clamp(1rem, .94rem + .34vw, 1.18rem);
  margin-bottom: 38px;
}

/* --- The field: the point of the whole screen ------------------------------
   Bigger, lifted on its own light, and holding a resting glow so the eye lands
   here before anywhere else. This is the only interactive thing above the fold
   and it should look like it. */
.sa-hero-check {
  max-width: 580px;
  border-radius: 16px;
  border-width: 1px;
  border-color: rgba(255, 255, 255, 0.26);
  background: rgba(255, 255, 255, 0.11);
  backdrop-filter: blur(14px);
  box-shadow:
    0 22px 60px -18px rgba(3, 16, 48, 0.55),
    0 0 0 1px rgba(255, 255, 255, 0.05) inset,
    0 0 70px -12px rgba(126, 228, 250, 0.30);
}
.sa-hero-check:focus-within {
  border-color: rgba(160, 244, 255, 0.95);
  background: rgba(255, 255, 255, 0.17);
  box-shadow:
    0 26px 70px -18px rgba(3, 16, 48, 0.6),
    0 0 0 4px rgba(6, 214, 209, 0.22),
    0 0 90px -10px rgba(126, 228, 250, 0.45);
}
.sa-hero-check-prefix { padding-left: 22px; font-size: 15.5px; }
.sa-hero-check-input { padding: 20px 12px 20px 2px; font-size: 16px; }
.sa-hero-check-btn { margin: 6px; padding: 0 24px; font-size: 15px; border-radius: 12px; }
.sa-hero-note { margin-top: 16px; font-size: 13.5px; }

/* --- Scroll cue -------------------------------------------------------------
   One quiet mark that the page continues. Costs nothing and answers the only
   question a tall hero leaves open. */
.sa-hero-scroll {
  position: absolute;
  left: 50%;
  bottom: clamp(26px, 3vw, 44px);
  transform: translateX(-50%);
  z-index: 2;
  display: grid;
  place-items: center;
  width: 26px;
  height: 42px;
  border: 1.5px solid rgba(255, 255, 255, 0.28);
  border-radius: 999px;
  pointer-events: none;
}
.sa-hero-scroll i {
  display: block;
  width: 3px;
  height: 8px;
  border-radius: 999px;
  background: rgba(190, 240, 255, 0.85);
  animation: sa-hero-scroll 2.4s cubic-bezier(.4, 0, .2, 1) infinite;
}
@keyframes sa-hero-scroll {
  0%      { transform: translateY(-7px); opacity: 0; }
  22%, 55%{ opacity: 1; }
  80%,100%{ transform: translateY(7px); opacity: 0; }
}

/* The blend and the cue share the hero's foot, so the ramp shortens to make
   room rather than swallowing it. */
.sa-hero { padding-bottom: 232px; }
.sa-hero-fade { height: 210px; }

@media (max-width: 1024px) {
  /* Same guard as above. This clamp resolved to 66-81px across the range while
     the bar is 66-76px tall, so clearance was 0-5px at every width in it. */
  .sa-hero { padding-bottom: 196px; padding-top: max(calc(var(--sa-nav-height) + 28px), clamp(66px, 4vw + 40px, 100px)); }
  .sa-hero-fade { height: 176px; }
  .sa-hero-scroll { display: none; }
  .sa-hero-inner::after { width: 96vw; height: 460px; }
}

@media (prefers-reduced-motion: reduce) {
  .sa-hero::before, .sa-hero::after, .sa-hero-scroll i { animation: none; }
  .sa-hero-scroll i { opacity: 1; transform: none; }
}

/* =============================================================================
   PRODUCT DEMO — smaller frame, playing preview
   =============================================================================
   The placeholder was full-width 16:9 - taller than the viewport, and empty,
   which read as a hole in the page rather than a video. It is now the size of a
   real embedded player, and the frame plays a four-beat reconstruction of an
   audit on a 16s loop.

   That loop is doing a second job: it is the storyboard. Each beat is one shot
   the finished recording needs, in product order - domain in, crawl running,
   score resolving, report handed over - so the video can be shot against
   something concrete instead of a blank brief.
   ============================================================================= */

.sa-demo .sa-section-header { margin-bottom: 26px; }

/* A real player, not a billboard: 720px caps it at roughly 405px tall. */
.sa-demo-frame {
  max-width: 720px;
  margin-inline: auto;
  border-radius: 12px;
}
.sa-demo-chrome { height: 34px; padding: 0 13px; }
.sa-demo-addr { font-size: 10.5px; }

/* Play affordance stays, but subordinate to the content now playing beneath it:
   a badge in the corner rather than a target in the middle of an empty box. */
.sa-demo-play {
  left: auto;
  top: auto;
  right: 14px;
  bottom: 14px;
  transform: none;
  width: 44px;
  height: 44px;
  padding-left: 3px;
  box-shadow: 0 8px 22px rgba(0, 0, 0, 0.34);
}
.sa-demo-poster:hover .sa-demo-play { transform: scale(1.08); }
.sa-demo-glow { display: none; }              /* the reel is the focus now */

/* --- The reel --------------------------------------------------------------
   Four beats stacked in the same box, cross-fading. Absolute so the frame never
   resizes between beats - a player that changes height is not a player. */
/* 4 beats x 4s. Each holds for most of its slot and hands over quickly, so the
   loop reads as cuts between shots rather than a slow dissolve. */

/* Beat 1 — the domain going in */

/* Beat 2 — crawling */

/* Beat 3 — the score */

/* Beat 4 — the report */

@media (max-width: 620px) {
  .sa-demo-beat { padding: 16px 18px; gap: 9px; }
  .sa-demo-b3 { flex-direction: column; align-items: flex-start; gap: 12px; }
  .sa-demo-ring { width: 74px; height: 74px; }
  .sa-demo-score { font-size: 26px; }
  .sa-demo-bars { width: 100%; }
}

@media (prefers-reduced-motion: reduce) {
  /* No cuts, no typing, no draw - hold the last beat, fully rendered. */
  .sa-demo-beat, .sa-demo-url-typed::after, .sa-demo-caret,
  .sa-demo-track i, .sa-demo-ring-arc, .sa-demo-bars i { animation: none; }
  .sa-demo-b1, .sa-demo-b2, .sa-demo-b3 { opacity: 0; }
  .sa-demo-b4 { opacity: 1; transform: none; }
}

/* =============================================================================
   WHAT WE CHECK — four groups, not twelve cards
   =============================================================================
   Replaces the twelve-card grid. Two problems it fixes at once:

     * Accuracy. The old block was badged "Powered by AI" over twelve items, two
       of which used a model. The claim is now coverage, which is true, and the
       AI claim is confined to the two things that earn it.
     * Rhythm. Twelve cards immediately after eight cards is twenty identical
       rectangles in a row. Four grouped lists read as thorough where twelve
       cards read as padding, and the section is roughly half the height.

   The groups are the analyser's own IssueCategory values, so the layout mirrors
   the four scores the report produces rather than inventing a taxonomy.
   ============================================================================= */

.sa-checks-sec { padding-top: clamp(38px, 2.4vw + 22px, 62px); }
.sa-checks-sec .sa-section-header { text-align: center; margin-bottom: 38px; }
.sa-checks-sec .sa-section-title { justify-content: center; }
.sa-checks-sec .sa-section-subtitle { margin-inline: auto; max-width: 640px; }
.sa-checks-title::before { content: none; }

.sa-checks-kicker {
  display: inline-block;
  margin-bottom: 12px;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--sa-primary);
}


/* Panels, not cards: a hairline and a tint, no lift, no shadow. They are here to
   be read down, not clicked. */
.sa-check-group {
  padding: 22px 20px 20px;
  border: 1px solid rgba(37, 99, 255, 0.13);
  background: linear-gradient(170deg, rgba(233, 242, 251, 0.9), rgba(240, 247, 253, 0.72));
}

.sa-check-head {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 14px;
  padding-bottom: 12px;
  border-bottom: 1px solid rgba(37, 99, 255, 0.12);
}
.sa-check-ico {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border-radius: 4px;
  background: #fff;
  color: #2563FF;
  box-shadow: 0 2px 8px -3px rgba(37, 99, 255, 0.3), inset 0 0 0 1px rgba(37, 99, 255, 0.1);
}
.sa-check-ico .mud-icon-root { font-size: 17px; }
.sa-check-head h3 {
  margin: 0;
  font-size: .98rem;
  font-weight: 700;
  letter-spacing: -0.012em;
  color: #0d1b3d;
}
/* The count is the point of the section, so it is set as a figure rather than
   as a label. */
.sa-check-count {
  margin-left: auto;
  font-size: 1.15rem;
  font-weight: 800;
  color: #2563FF;
  font-variant-numeric: tabular-nums;
}

/* A tick rather than a bullet - these are things the product does, not items in
   a list. Drawn in CSS so twenty-two of them cost nothing. */

/* --- The honest AI strip ---------------------------------------------------- */
.sa-checks-ai {
  display: flex;
  align-items: center;
  gap: 18px;
  margin-top: 16px;
  padding: 18px 22px;
  border: 1px solid rgba(37, 99, 255, 0.14);
  background: linear-gradient(100deg, rgba(37, 99, 255, 0.06), rgba(6, 214, 209, 0.05));
}
.sa-checks-ai-badge {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  flex: none;
  padding: 7px 14px;
  border-radius: 999px;
  background: linear-gradient(135deg, #2563FF, #0e7fa8);
  color: #fff;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.02em;
  white-space: nowrap;
}
.sa-checks-ai p { margin: 0; font-size: 13.2px; line-height: 1.6; color: #475569; }

@media (max-width: 1080px) {
  .sa-checks { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 620px) {
  .sa-checks { grid-template-columns: minmax(0, 1fr); }
  .sa-checks-ai { flex-direction: column; align-items: flex-start; gap: 12px; }
}

/* =============================================================================
   WHAT WE CHECK — the split bar, and keywords instead of prose
   =============================================================================
   The grouped version was accurate and unreadable: twenty-two full sentences
   arranged in four columns. Nobody reads a spec list as prose - they scan it for
   the one thing they came to check.

   Two changes:
     * A proportional bar carries the distribution. On-page work is more than
       half of everything here, which is the actual insight in this data and was
       invisible in four columns of text.
     * The specifics are keywords. A reader wondering "does it check my schema?"
       finds it in one pass instead of reading a column to find out.
   ============================================================================= */

/* --- The split ------------------------------------------------------------- */
.sa-checks-split {
  display: flex;
  gap: 3px;
  height: 10px;
  margin-bottom: 22px;
}
.sa-split-seg {
  width: var(--w);
  border-radius: 2px;
  /* No entrance animation. Twice now a scaleX(0) start has left this bar at zero
     width - `backwards` fill applies the from-state whenever the animation has
     not progressed, which is any moment it is paused or throttled. The bar is
     the one graphic carrying this section; it is not worth risking for a 0.9s
     flourish. The section's own scroll fade already brings it in. */
}

/* Four steps of one brand ramp rather than four unrelated hues - they are parts
   of a single total, and the colour should say so. */
.sa-seg-1 { background: #2563FF; }
.sa-seg-2 { background: #2f6fc4; }
.sa-seg-3 { background: #3f9cc9; }
.sa-seg-4 { background: #45c3d8; }

/* --- Groups ---------------------------------------------------------------- */
.sa-checks-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 14px;
  /* stretch, not start: four panels of different heights read as four unrelated
     boxes. Equal height makes them one set of four, which is what they are - the
     count in each header already carries the difference in size. */
  align-items: stretch;
}

.sa-check-group {
  display: flex;
  flex-direction: column;
  padding: 20px 18px 18px;
  border: 1px solid rgba(37, 99, 255, 0.13);
  background: linear-gradient(170deg, rgba(233, 242, 251, 0.86), rgba(241, 247, 253, 0.7));
}
/* Each panel is tipped with its own segment colour, so the bar above and the
   groups below read as the same four things. */
.sa-check-group { border-top: 3px solid; }
.sa-g1 { border-top-color: #2563FF; }
.sa-g2 { border-top-color: #2f6fc4; }
.sa-g3 { border-top-color: #3f9cc9; }
.sa-g4 { border-top-color: #45c3d8; }

.sa-check-head {
  display: flex;
  align-items: center;
  gap: 9px;
  margin-bottom: 13px;
  padding-bottom: 0;
  border-bottom: 0;
}
.sa-check-ico { width: 28px; height: 28px; }
.sa-check-ico .mud-icon-root { font-size: 15px; }
.sa-check-head h3 { font-size: 1rem; }
.sa-check-count { font-size: 1.3rem; }

/* --- Keywords -------------------------------------------------------------- */
.sa-check-tags { display: flex; flex-wrap: wrap; gap: 6px; align-content: flex-start; }
.sa-check-tags span {
  padding: 6px 12px;
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.86);
  box-shadow: inset 0 0 0 1px rgba(37, 99, 255, 0.12);
  /* 11.5px was below comfortable reading size for the only specifics in the
     section - these are the words a visitor actually scans for. */
  font-size: 13px;
  font-weight: 600;
  line-height: 1.4;
  color: #35506e;
  white-space: nowrap;
}

@media (max-width: 1080px) {
  .sa-checks-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 620px) {
  .sa-checks-grid { grid-template-columns: minmax(0, 1fr); }
  .sa-checks-split { height: 8px; }
  .sa-check-tags span { white-space: normal; }
}


/* =============================================================================
   DEEP DIVE 1 — the run panel
   =============================================================================
   Replaces a generic four-bar chart with the screen the product actually shows
   while an audit runs. The bars said "some numbers went up"; this says what the
   crawler is doing, in the order it does it, with the stage names a customer
   will see ten minutes later inside the app.

   Everything ships in the finished state and the script rewinds it - so a failed
   or blocked script leaves a completed audit on screen, not an empty ring.
   ============================================================================= */

.sa-run { padding: 20px 22px; }

.sa-run-head {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 18px;
}
.sa-run-title { font-size: 15px; font-weight: 700; color: #0d1b3d; }
.sa-run-pill {
  margin-left: auto;
  flex: none;
  padding: 5px 11px;
  border-radius: 999px;
  background: rgba(37, 99, 255, 0.08);
  font-size: 11px;
  font-weight: 600;
  color: #3c5a86;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.sa-run-pill b { color: #2563FF; }

.sa-run-body { display: flex; align-items: center; gap: 22px; }

/* --- Dial ------------------------------------------------------------------ */
.sa-run-dial { position: relative; flex: none; width: 132px; height: 132px; }
.sa-run-dial svg { width: 132px; height: 132px; display: block; }
.sa-run-track { fill: none; stroke: #e6edf7; stroke-width: 11; }
.sa-run-arc {
  fill: none;
  stroke: #0e9bbd;
  stroke-width: 11;
  stroke-linecap: round;
  stroke-dasharray: 314;                  /* 2·pi·50 */
  stroke-dashoffset: 0;                   /* complete; the script rewinds it */
}
.sa-run-readout {
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  text-align: center;
  line-height: 1;
}
.sa-run-readout b {
  font-size: 28px;
  font-weight: 800;
  color: #0d1b3d;
  font-variant-numeric: tabular-nums;
}
.sa-run-readout b i { font-style: normal; font-size: .5em; font-weight: 700; color: #5b7086; }
.sa-run-readout em {
  display: block;
  margin-top: 5px;
  font-style: normal;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: #64748b;
}

/* --- Stage rail ------------------------------------------------------------ */
.sa-run-side { flex: 1; min-width: 0; }
.sa-run-status { margin: 0 0 12px; font-size: 12.5px; color: #64748b; }

.sa-run-steps { list-style: none; margin: 0 0 12px; padding: 0; display: grid; gap: 11px; }
.sa-run-steps li {
  position: relative;
  display: flex;
  align-items: center;
  gap: 11px;
  font-size: 12.5px;
  font-weight: 600;
  color: #94a3b8;
  transition: color .45s ease;
}
.sa-run-steps li::before {
  content: '';
  position: absolute;
  left: 10px;
  top: 22px;
  width: 2px;
  height: 11px;
  background: #e2e8f0;
}
.sa-run-steps li:last-child::before { display: none; }

.sa-run-node {
  position: relative;
  z-index: 1;
  flex: none;
  width: 22px;
  height: 22px;
  border-radius: 8px;
  background: #eef2f7;
  box-shadow: inset 0 0 0 1.5px #dbe3ee;
  transition: background .45s ease, box-shadow .45s ease;
}
/* The tick is drawn, not a glyph - it can then fade in with the node rather than
   popping in at full weight. */
.sa-run-node::after {
  content: '';
  position: absolute;
  left: 7px;
  top: 6px;
  width: 5px;
  height: 9px;
  border-right: 2px solid #fff;
  border-bottom: 2px solid #fff;
  transform: rotate(42deg);
  opacity: 0;
  transition: opacity .45s ease;
}
.sa-run-steps li.is-done { color: #334155; }
.sa-run-steps li.is-done .sa-run-node { background: #2f6fc4; box-shadow: none; }
.sa-run-steps li.is-done .sa-run-node::after { opacity: 1; }
.sa-run-steps li.is-active { color: #0e7fa8; }
.sa-run-steps li.is-active .sa-run-node {
  background: #0e9bbd;
  box-shadow: 0 0 0 4px rgba(14, 155, 189, 0.16);
}

.sa-run-timer {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 11.5px;
  font-weight: 600;
  color: #94a3b8;
  font-variant-numeric: tabular-nums;
}
.sa-run-timer svg { width: 13px; height: 13px; }

@media (max-width: 620px) {
  .sa-run-body { flex-direction: column; align-items: flex-start; gap: 16px; }
  .sa-run-dial { width: 108px; height: 108px; }
  .sa-run-dial svg { width: 108px; height: 108px; }
  .sa-run-head { flex-wrap: wrap; }
  .sa-run-pill { margin-left: 0; }
}

/* -----------------------------------------------------------------------------
   Run panel: the app's own stage colours
   -----------------------------------------------------------------------------
   The rail was one blue for every stage. The real stepper in AuditProgress.razor
   gives each phase its own fill, and that colour is meaningful - it is what the
   ring, the counter pills and the stage icon all share while that phase runs. A
   customer who has seen one audit recognises the sequence by colour before they
   read the labels, so the landing page should use the same four.

       Crawl #2563FF   Analyze #7c3aed   AI Summary #05A8A4   Done #0d9488
   -------------------------------------------------------------------------- */
.sa-run-steps li:nth-child(1) { --stage: #2563FF; --stage-lt: #3b82f6; }
.sa-run-steps li:nth-child(2) { --stage: #7c3aed; --stage-lt: #8b5cf6; }
.sa-run-steps li:nth-child(3) { --stage: #05A8A4; --stage-lt: #06D6D1; }
.sa-run-steps li:nth-child(4) { --stage: #0d9488; --stage-lt: #14b8a6; }

.sa-run-steps li.is-done .sa-run-node { background: var(--stage); box-shadow: none; }
.sa-run-steps li.is-done { color: #334155; }

/* Flat fill plus a zero-blur halo on the running stage - the same device the app
   uses, and the thing that separates "running now" from "already done" at a
   glance. A blurred shadow reads as elevation instead. */
.sa-run-steps li.is-active { color: var(--stage); }
.sa-run-steps li.is-active .sa-run-node {
  background: var(--stage-lt);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--stage-lt) 22%, transparent);
}

/* The connector inherits the colour of the stage it leaves, so the rail reads as
   a coloured path rather than a grey spine with dots on it. */
.sa-run-steps li.is-done::before { background: var(--stage); opacity: .45; }

@supports not (background: color-mix(in srgb, red 10%, white)) {
  .sa-run-steps li.is-active .sa-run-node { box-shadow: 0 0 0 4px rgba(59, 130, 246, 0.22); }
}

/* =============================================================================
   DEEP DIVE 2 — Score composition
   =============================================================================
   Replaces four generic score bars with the panel the report actually shows.
   The bars gave four numbers; this gives the thing those numbers hide: a
   category can hold almost every issue on the site and still be a minor part of
   the score. On-Page carries 1,183 of 1,375 issues at 30% weight, Technical
   carries 5 at 35%. That is the argument for weighting, and it is only visible
   when issue count and weight sit next to each other.

   Weights, colours and order come from ScoreParts in AuditDetail.razor.
   ============================================================================= */

.sa-comp { padding: 20px 22px; }
.sa-comp-head { margin-bottom: 18px; }
.sa-comp-head h4 { margin: 0 0 3px; font-size: 15px; font-weight: 700; color: #0d1b3d; }
.sa-comp-head p { margin: 0; font-size: 12px; color: #7c8ba1; }

.sa-comp-body { display: flex; align-items: center; gap: 20px; }

/* --- Donut ------------------------------------------------------------------ */
.sa-comp-donut { position: relative; flex: none; width: 148px; height: 148px; }
.sa-comp-donut svg { width: 148px; height: 148px; display: block; }
.sa-comp-seg {
  fill: none;
  stroke-width: 15;
  /* No draw animation. Three times on this page a scaleX/dash entrance has left
     the graphic at zero because the animation had not progressed; the donut is
     the whole point of this panel and is not worth that risk. The section's own
     scroll fade brings it in. */
}
.sa-comp-centre {
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  text-align: center;
  line-height: 1;
}
.sa-comp-centre b {
  font-size: 26px;
  font-weight: 800;
  color: #0d1b3d;
  font-variant-numeric: tabular-nums;
}
.sa-comp-centre em {
  display: block;
  margin-top: 5px;
  font-style: normal;
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: #94a3b8;
}

/* --- Rows ------------------------------------------------------------------- */
.sa-comp-list { list-style: none; margin: 0; padding: 0; flex: 1; min-width: 0; display: grid; gap: 7px; }
.sa-comp-list li {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 12px;
  border-radius: 8px;
  background: #f4f7fb;
}
.sa-comp-dot { flex: none; width: 9px; height: 9px; border-radius: 50%; background: var(--c); }
.sa-comp-info { flex: 1; min-width: 0; }
.sa-comp-top { display: flex; align-items: center; gap: 8px; }
.sa-comp-top b { font-size: 12.5px; font-weight: 700; color: #1e293b; }
/* The impact band, styled as the report styles it - a chip, not a colour on the
   label, so it stays legible against four different dot colours. */
.sa-comp-band {
  font-style: normal;
  padding: 1px 7px;
  border-radius: 4px;
  background: rgba(13, 148, 136, 0.12);
  font-size: 9px;
  font-weight: 800;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: #0d9488;
}
.sa-comp-meta {
  display: block;
  margin-top: 3px;
  font-size: 11px;
  color: #8494a8;
  font-variant-numeric: tabular-nums;
}
.sa-comp-score { flex: none; text-align: right; }
.sa-comp-score b {
  display: block;
  font-size: 19px;
  font-weight: 800;
  color: #0d1b3d;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
.sa-comp-score em {
  display: block;
  margin-top: 3px;
  font-style: normal;
  font-size: 8.5px;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: #a3b1c2;
}

/* Rows arrive in sequence. Transform only - the row is readable whether or not
   the animation ever runs. */
.sa-animate-on-scroll.sa-visible .sa-comp-list li {
  animation: sa-comp-row .55s cubic-bezier(.16, 1, .3, 1) backwards;
}
@keyframes sa-comp-row { from { transform: translateX(14px); } to { transform: none; } }
.sa-visible .sa-comp-list li:nth-child(1) { animation-delay: .10s; }
.sa-visible .sa-comp-list li:nth-child(2) { animation-delay: .20s; }
.sa-visible .sa-comp-list li:nth-child(3) { animation-delay: .30s; }
.sa-visible .sa-comp-list li:nth-child(4) { animation-delay: .40s; }

@media (max-width: 620px) {
  .sa-comp-body { flex-direction: column; }
  .sa-comp-list { width: 100%; }
}
@media (prefers-reduced-motion: reduce) {
  .sa-animate-on-scroll.sa-visible .sa-comp-list li { animation: none; }
}

/* =============================================================================
   HOW IT WORKS — a connected sequence
   =============================================================================
   Three numbered circles in a row, with nothing joining them, read as three
   unrelated things. The whole point of the section is that it is an order, so a
   rule now runs through the markers and the numbers sit on it.

   Each step also carries the artefact it produces - a domain, the checks, the
   file formats - so the section describes this product rather than describing a
   generic process that any tool could claim.
   ============================================================================= */

.sa-steps {
  position: relative;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 30px;
  max-width: 940px;
  margin-inline: auto;
  text-align: center;
}
/* One connector per gap, anchored to the markers rather than to the container.
   The first version placed a single rule at 16.67%/83.33%, assuming each column
   is exactly a third - but the 30px grid gaps make that false at every width, so
   the line stopped short of the numbers it was meant to join.

   Each segment starts at its own marker's edge (50% + radius) and runs to the
   next marker's edge: the centres are one column plus one gap apart, so the span
   is 100% + 30px - both radii = 100% - 24px. Exact at any width. */
.sa-step:not(:last-child)::after {
  content: '';
  position: absolute;
  top: 26px;                       /* marker centre, less half the rule */
  left: calc(50% + 27px);
  width: calc(100% - 24px);
  height: 2px;
  background: linear-gradient(90deg, #2563FF, #06D6D1);
  opacity: .28;
}

.sa-step { position: relative; }

.sa-step-num {
  position: relative;
  z-index: 1;                      /* sits ON the rule, not under it */
  display: grid;
  place-items: center;
  width: 54px;
  height: 54px;
  margin: 0 auto 18px;
  border-radius: 50%;
  background: linear-gradient(140deg, #2563FF, #0e7fa8);
  box-shadow: 0 10px 22px -10px rgba(37, 99, 255, 0.6);
  color: #fff;
  font-size: 19px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
}

.sa-step h3 {
  margin: 0 0 8px;
  font-size: 1.06rem;
  font-weight: 700;
  letter-spacing: -0.014em;
  color: #0d1b3d;
}
.sa-step p {
  margin: 0 auto 14px;
  max-width: 270px;
  font-size: 13.2px;
  line-height: 1.6;
  color: #5b6b83;
}

.sa-step-detail {
  display: inline-block;
  padding: 5px 12px;
  border-radius: 8px;
  background: rgba(37, 99, 255, 0.07);
  box-shadow: inset 0 0 0 1px rgba(37, 99, 255, 0.10);
  font-size: 11.5px;
  font-weight: 700;
  color: #23477f;
}
.sa-step-mono { font-family: 'Cascadia Code', 'Consolas', monospace; font-weight: 600; }

/* Markers arrive along the rule, left to right, so the eye is walked through the
   order. Transform only - every step is readable whether or not it runs. */
.sa-steps.sa-visible .sa-step-num { animation: sa-step-pop .6s cubic-bezier(.16, 1, .3, 1) backwards; }
@keyframes sa-step-pop { from { transform: scale(.8); } to { transform: none; } }
.sa-steps.sa-visible .sa-step:nth-child(1) .sa-step-num { animation-delay: .08s; }
.sa-steps.sa-visible .sa-step:nth-child(2) .sa-step-num { animation-delay: .22s; }
.sa-steps.sa-visible .sa-step:nth-child(3) .sa-step-num { animation-delay: .36s; }

@media (max-width: 780px) {
  .sa-steps { grid-template-columns: minmax(0, 1fr); gap: 34px; max-width: 420px; }
  /* Stacked: each connector turns and runs down the centre to the next marker. */
  .sa-step:not(:last-child)::after {
    top: calc(50% + 0px);
    left: 50%;
    width: 2px;
    height: auto;
    transform: translateX(-1px);
    background: linear-gradient(180deg, #2563FF, #06D6D1);
  }
  .sa-steps { position: relative; }
  .sa-step:not(:last-child)::after { top: 54px; bottom: -34px; height: auto; }
}
@media (prefers-reduced-motion: reduce) {
  .sa-steps.sa-visible .sa-step-num { animation: none; }
}

/* =============================================================================
   DISPLAY TYPE — Inter, properly weighted
   =============================================================================
   Plus Jakarta Sans is reverted; Inter carries the headings again.

   What is kept from that pass is the part that was doing the work: real 800s
   with tight tracking. The font request stopped at 700, so every heading set at
   800 was being faux-bolded by the browser - a synthetic smear that reads as
   slightly blurred rather than heavy. Loading the true 800 is why the headings
   look sharper now than they did before either change.
   ============================================================================= */

/* The hero keeps 800 - at 67px it is the one place a heavy cut reads as
   confident rather than shouty. Everything else drops to 700. */
.sa-hero h1 {
  font-family: 'Inter', system-ui, -apple-system, sans-serif;
  font-weight: 800;
  letter-spacing: -0.028em;
  word-spacing: 0.04em;
}

/* The two headline lines, weighted against each other rather than both shouting.
   Line one lightens to 600 so the eye starts somewhere calm; line two keeps the
   800 cut but drops to 0.86em, which lands it near the old 4.2rem size while the
   block overall reads bigger.

   0.86em, not a px value - em resolves against the h1's own clamp(), so line two
   tracks the responsive scale instead of going out of proportion on small
   screens. Both are set on the SPANS, so they beat the h1's inherited values
   without any specificity contest. */
.sa-hero-line-1,
.sa-hero-line-2 { display: block; }
.sa-hero-line-1 { font-weight: 600; }
.sa-hero-line-2 { font-size: 0.72em; }

/* --- The rotating second line ----------------------------------------------
   Complete phrases stacked in ONE grid cell. The cell is as wide as the longest
   ("Audits You Can Act On", 788px against the 860px wrapper) and each phrase
   centres inside it, so nothing shifts as they swap and every phrase sits
   centred under line one. */
.sa-hero-line-2 { display: grid; }
.sa-hero-line-2 > .sa-hero-word { grid-area: 1 / 1; }

/* Rest state is the FIRST phrase, alone and fully opaque. This is the rule that
   matters: stacked items all default to visible, so without it a page where the
   animation never runs - reduced motion, a paused compositor, an old engine -
   prints four phrases on top of each other. Rest on something readable and let
   the animation be decoration, not the thing holding the headline up. */
.sa-hero-word { opacity: 0; }
.sa-hero-word:first-child { opacity: 1; }

@keyframes sa-hero-word {
  0%        { opacity: 0; transform: translateY(0.34em); }
  4%, 21%   { opacity: 1; transform: translateY(0); }
  25%, 100% { opacity: 0; transform: translateY(-0.34em); }
}

/* Four phrases over 17.6s - each holds ~3.7s, long enough to read without the
   headline turning into a slot machine. `backwards` makes each hold the hidden
   0% state through its delay instead of flashing in at full opacity. */
.sa-hero-word {
  animation: sa-hero-word 17.6s cubic-bezier(.16, 1, .3, 1) infinite backwards;
  animation-delay: calc(var(--i) * 4.4s);
}

@media (prefers-reduced-motion: reduce) {
  /* Falls back to the rest state above: "in Minutes", no movement. */
  .sa-hero-word { animation: none; }
}
}

/* Section headings were 800 at -0.034em: too heavy at ~2.8rem, and the negative
   tracking pulls the WORD spaces in along with the letters, so "Trusted by SEO
   Professionals" ran together. 700 with gentler tracking, plus a positive
   word-spacing to give the spaces back without loosening the letters. */
/* Written as `.sa-section .sa-section-title` to match the earlier rule's
   specificity (0,2,0). A plain `.sa-section-title` loses to it however late it
   appears - which is why the first attempt at this left every heading at 800. */
.sa-section .sa-section-title,
.sa-section-title,
.sa-bd-title,
.sa-cta-copy h2,
.sa-demo-title,
.sa-checks-title {
  font-family: 'Inter', system-ui, -apple-system, sans-serif;
  font-weight: 700;
  letter-spacing: -0.018em;
  word-spacing: 0.06em;
}

.sa-step h3,
.sa-fs-card h3,
.sa-deep-dive-content h3 {
  font-family: 'Inter', system-ui, -apple-system, sans-serif;
  font-weight: 700;
  letter-spacing: -0.012em;
  word-spacing: 0.03em;
}

/* =============================================================================
   PRODUCT DEMO — a light video slot
   =============================================================================
   Was a dark navy band with an animated four-beat reconstruction inside it. Two
   problems: it was a great deal of production for a placeholder, and a dark band
   between two light sections drew far more attention than an unshot video
   deserves.

   Now it sits on the page's own ground, with one poster frame and one play
   control. The poster is a muted still of the report - enough that the frame is
   not an empty rectangle, held back enough that the play button stays the
   brightest thing in it. When the recording lands this becomes a plain embed and
   nothing else changes.
   ============================================================================= */

.sa-demo { padding: clamp(40px, 2.8vw + 24px, 70px) 24px; background: transparent; }
.sa-demo-inner { max-width: 780px; margin-inline: auto; }
.sa-demo .sa-section-header { text-align: center; margin-bottom: 24px; }
.sa-demo .sa-section-title { justify-content: center; }
.sa-demo-title::before { content: none; }
.sa-demo-subtitle { margin-inline: auto; max-width: 520px; }

.sa-demo-eyebrow {
  display: inline-block;
  margin-bottom: 11px;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .15em;
  text-transform: uppercase;
  color: var(--sa-primary);
}

/* --- The frame -------------------------------------------------------------- */
.sa-demo-frame {
  position: relative;
  display: block;
  width: 100%;
  max-width: 720px;
  margin-inline: auto;
  aspect-ratio: 16 / 9;
  padding: 0;
  overflow: hidden;
  border: 1px solid rgba(37, 99, 255, 0.14);
  border-radius: 12px;
  background: #fff;
  box-shadow: 0 18px 44px -24px rgba(13, 53, 128, 0.34);
}
.sa-demo-frame iframe { width: 100%; height: 100%; border: 0; display: block; }

.sa-demo-poster { cursor: pointer; transition: box-shadow .3s ease, transform .3s cubic-bezier(.16, 1, .3, 1); }
.sa-demo-poster:hover { transform: translateY(-2px); box-shadow: 0 24px 54px -24px rgba(13, 53, 128, 0.42); }
.sa-demo-poster:focus-visible { outline: 3px solid rgba(6, 214, 209, .6); outline-offset: 3px; }

/* --- The still -------------------------------------------------------------- */
.sa-demo-still {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  background: linear-gradient(170deg, #f7fafd, #eef4fa);
  /* Held back so it reads as a paused frame rather than as content asking to be
     read. The play control sits at full strength on top. */
  opacity: .55;
}
.sa-demo-still-bar {
  display: flex;
  align-items: center;
  gap: 5px;
  height: 30px;
  padding: 0 12px;
  border-bottom: 1px solid rgba(37, 99, 255, 0.08);
  background: rgba(255, 255, 255, 0.7);
}
.sa-demo-still-bar i { width: 7px; height: 7px; border-radius: 50%; background: rgba(37, 99, 255, 0.16); }
.sa-demo-still-bar em {
  margin-left: 8px;
  font-style: normal;
  font-family: 'Cascadia Code', 'Consolas', monospace;
  font-size: 10px;
  color: #8ea3bd;
}

.sa-demo-still-body {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 18px;
  padding: 0 34px;
}
.sa-demo-still-ring { width: 96px; height: 96px; flex: none; }
.sa-demo-still-meta b {
  display: block;
  font-size: 30px;
  font-weight: 800;
  line-height: 1;
  color: #0d1b3d;
}
.sa-demo-still-meta em {
  display: block;
  margin-top: 5px;
  font-style: normal;
  font-size: 11px;
  font-weight: 600;
  color: #7c8ba1;
}
.sa-demo-still-rows { flex: 1; display: grid; gap: 8px; }
.sa-demo-still-rows i {
  display: block;
  height: 7px;
  width: var(--w);
  border-radius: 999px;
  background: linear-gradient(90deg, #2563FF, #45c3d8);
  opacity: .5;
}

/* --- Play control ----------------------------------------------------------- */
.sa-demo-play {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  display: grid;
  place-items: center;
  width: 62px;
  height: 62px;
  padding-left: 4px;                 /* optical centring: a triangle is not a square */
  border-radius: 50%;
  background: #fff;
  color: var(--sa-primary);
  box-shadow: 0 10px 28px -8px rgba(13, 53, 128, 0.45), 0 0 0 1px rgba(37, 99, 255, 0.08);
  transition: transform .28s cubic-bezier(.16, 1, .3, 1);
}
.sa-demo-poster:hover .sa-demo-play { transform: translate(-50%, -50%) scale(1.07); }

.sa-demo-cap {
  margin: 14px 0 0;
  text-align: center;
  font-size: 12.5px;
  color: #7c8ba1;
}

@media (max-width: 620px) {
  .sa-demo-still-body { padding: 0 18px; gap: 12px; }
  .sa-demo-still-ring { width: 66px; height: 66px; }
  .sa-demo-still-meta b { font-size: 22px; }
  .sa-demo-play { width: 50px; height: 50px; }
}
@media (prefers-reduced-motion: reduce) {
  .sa-demo-poster, .sa-demo-play { transition: none; }
  .sa-demo-poster:hover { transform: none; }
  .sa-demo-poster:hover .sa-demo-play { transform: translate(-50%, -50%); }
}


/* =============================================================================
   NAV BAR — scaled up
   =============================================================================
   The bar read as small next to a 104px headline: 64px tall, 14px links at
   weight 500, and buttons sharing the generic .sa-btn-sm used all over the app.
   Everything here is scoped to .sa-landing-nav so the shared button and logo
   sizes elsewhere are untouched.

   Height moves through --sa-nav-height rather than a literal, because the mobile
   menu's offset, the legal-page hero padding and three scroll-margin rules are
   all derived from it - setting it here keeps them in step.
   ========================================================================== */

/* 46px made the lockup 61% of the 76px nav and taller than the Free Trial button
   (37px), rendering the wordmark at ~32px against 15.5px nav links. The height was
   tuned for the old lockup, whose wordmark was ~58% of the box; in the Elvisto one
   it is 69%, so the same box height sets the text ~19% larger. 36px puts the
   wordmark near 25px - still the largest thing in the bar, no longer shouting. */
.sa-nav-logo { height: 36px; display: block; }

.sa-landing-nav {
  padding: 0 32px;
  background: rgba(255, 255, 255, 0.92);
  /* A hairline alone left the bar floating once it got taller; the shadow gives
     it a base without turning into a visible band. */
  box-shadow: 0 1px 0 rgba(16, 42, 90, 0.06), 0 8px 28px rgba(16, 42, 90, 0.05);
}

.sa-landing-nav .sa-nav-links { gap: 6px; }

.sa-landing-nav .sa-nav-link {
  padding: 10px 18px;
  font-size: 15.5px;
  font-weight: 600;
}

.sa-nav-divider { height: 28px; margin: 0 14px; }

/* Scoped: .sa-btn-sm is shared with tables and cards across the app, so the nav
   gets its own sizing rather than everything growing with it. */
.sa-landing-nav .sa-btn-sm {
  padding: 11px 22px;
  font-size: 15px;
  border-radius: 12px;
}

.sa-nav-mobile-btn { width: 44px; height: 44px; }   /* was under the 44px touch target */
.sa-nav-mobile-btn .mud-icon-root { font-size: 26px; }

@media (max-width: 640px) {
  /* The landing hero's top padding bottoms out at 104px on small screens, so a
     76px bar would leave only 28px of clearance. */
  :root { --sa-nav-height: 66px; }
  .sa-landing-nav { padding: 0 16px; }
  .sa-nav-logo { height: 30px; }   /* 58% of the 66px mobile nav -> 45% */
}

/* =============================================================================
   FEATURE CARDS — legible type
   =============================================================================
   The card chrome was 10-13px and the mock product UIs inside them ran 8-11px,
   which is below what anyone should be asked to read on a marketing page. The
   mocks are decoration, but they are decoration made of words, and at 8.5px they
   were noise rather than a preview.

   Set here as one block rather than in place: .sa-fs-card p, .sa-fs-eyebrow and
   .sa-fs-card h3 each already had TWO competing declarations earlier in this
   file. Editing one of each would have changed nothing visible, because the
   later duplicate wins. Appending keeps the winning value in one place.
   ========================================================================== */

/* --- Card chrome --- */
.sa-fs-kicker  { font-size: 13px; }
.sa-fs-eyebrow { font-size: 12px; letter-spacing: 0.13em; }
.sa-fs-card h3 { font-size: 1.28rem; line-height: 1.3; }
.sa-fs-card p  { font-size: 15.2px; line-height: 1.62; }
.sa-fs-chips span { font-size: 12.5px; }

/* --- The mock product UIs --- */
.sa-fs-shot-bar b   { font-size: 11.5px; }
.sa-fs-gauge-val    { font-size: 19px; }
.sa-fs-mini-list li { font-size: 12.5px; }
.sa-fs-mini-list li b { font-size: 11.5px; }
.sa-fs-code         { font-size: 11px; }
.sa-fs-file         { font-size: 11.5px; }
.sa-fs-crawlhead    { font-size: 11.5px; }
.sa-fs-bars span    { font-size: 11px; }
.sa-fs-quote        { font-size: 12.5px; }
.sa-fs-link         { font-size: 11px; }
.sa-fs-scores span  { font-size: 11px; }
.sa-fs-scores b     { font-size: 16px; }
.sa-fs-av           { font-size: 10px; }
.sa-fs-projects li  { font-size: 11.5px; }
.sa-fs-schema span  { font-size: 11.5px; }

/* =============================================================================
   FEATURE CARDS — pale panel treatment (the reference card, in our colours)
   =============================================================================
   The structure was already right: pale card, eyebrow, heading, one white
   product mock. What was missing was the treatment. Four moves:

     * Ground derived from the logo, not borrowed. #E9F2F9 -> #DEF0F6 is our
       own cyan at ~1/20th chroma - the same pale field as the reference, in
       this brand's hue rather than a competitor's mint.
     * Ink-dark type. Eyebrow and heading go to #0A1B33 (14.7:1 on the darkest
       stop); body to #3A536E (6.8:1). The old blue-grey eyebrow read as UI
       chrome; dark ink reads as editorial.
     * ONE object floats. The white mock gets the deep shadow and a 14px radius;
       everything else on the card stays flat so the mock is the moment.
     * Texture, not decoration. The radial cyan glow becomes a 135deg hairline
       field masked to the bottom-right corner - felt, not read (~1.04:1).

   Appended rather than edited in place: .sa-fs-card alone has nine earlier
   declarations, and the winning radius (0) and background sit 1,000+ lines
   apart. One block, last, is the only version that is certain to win.
   ========================================================================== */

.sa-fs-card {
  border-radius: 20px;
  border: 1px solid rgba(13, 53, 128, 0.08);
  background: linear-gradient(160deg, #E9F2F9 0%, #E1EDF5 52%, #DEF0F6 100%);
  box-shadow: 0 1px 2px rgba(9, 38, 84, 0.04);
  color: #0A1B33;
}
/* Children sit above the texture layer. */
.sa-fs-card > * { position: relative; z-index: 1; }

.sa-fs-card::after {
  content: '';
  position: absolute;
  inset: 0;
  right: 0; bottom: 0;              /* undo the earlier -60px offsets */
  width: auto; height: auto;
  border-radius: 0;
  z-index: 0;
  pointer-events: none;
  background: repeating-linear-gradient(135deg, rgba(13, 53, 128, 0.07) 0 1px, transparent 1px 10px);
  -webkit-mask-image: radial-gradient(110% 100% at 100% 100%, #000 0%, rgba(0, 0, 0, 0.5) 40%, transparent 68%);
          mask-image: radial-gradient(110% 100% at 100% 100%, #000 0%, rgba(0, 0, 0, 0.5) 40%, transparent 68%);
}
@media (prefers-contrast: more) { .sa-fs-card::after { opacity: 0; } }

.sa-fs-card:hover {
  border-color: rgba(13, 53, 128, 0.16);
  box-shadow: 0 24px 50px -24px rgba(9, 38, 84, 0.32);
}

/* --- Type --- */
.sa-fs-eyebrow {
  color: #0A1B33;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.14em;
}
.sa-fs-card h3 {
  color: #0A1B33;
  font-size: 1.36rem;
  line-height: 1.12;
  letter-spacing: -0.02em;
  margin: 14px 0 9px;
}
.sa-fs-card p { color: #3A536E; }

/* --- Icon tile: kept, but quiet - the reference has no tile, and a loud one
       competes with the mock for "the one white object". --- */
.sa-fs-ico {
  border-radius: 12px;
  background: #fff;
  color: #2563FF;
  box-shadow: inset 0 0 0 1px rgba(13, 53, 128, 0.10);
}
.sa-fs-card:hover .sa-fs-ico { background: #2563FF; color: #fff; }

/* --- The floating mock --- */
.sa-fs-shot {
  border: 0;
  border-radius: 16px;
  background: #fff;
  box-shadow:
    0 18px 40px -22px rgba(9, 38, 84, 0.30),
    0 2px 6px -3px rgba(9, 38, 84, 0.12),
    inset 0 0 0 1px rgba(13, 53, 128, 0.06);
}
.sa-fs-card:hover .sa-fs-shot {
  transform: translateY(-3px);
  box-shadow:
    0 26px 52px -24px rgba(9, 38, 84, 0.38),
    0 2px 6px -3px rgba(9, 38, 84, 0.12),
    inset 0 0 0 1px rgba(13, 53, 128, 0.06);
}
.sa-fs-shot-bar { background: #F6FAFD; border-bottom: 1px solid rgba(13, 53, 128, 0.07); border-radius: 16px 14px 0 0; }

/* =============================================================================
   BOOK-A-DEMO BAND — light, in the logo's cyan; shorter
   =============================================================================
   This was the last dark slab on an otherwise light page. It now sits on a tint
   of the logo's second colour, #06D6D1, at 6-16% over white (#EAFAFC ->
   #D6F5F8): the same family as the pale grounds elsewhere, but leaning cyan
   rather than blue so it reads as its own moment instead of another card.

   Every colour below was chosen for the LIGHT ground, not inherited: the
   headline/lede were white and rgba-white, the button was a white outline, the
   mock's frame was white-at-5% with a near-black shadow - all invisible or
   wrong on a pale tint. Ink #0A1B33 is 15-16:1 on every stop; the filled
   #2563FF button carries white text at 8.8:1.

   Height: there was no min-height, so the band's height is its padding plus
   the mock. Vertical padding drops from 38-66px to 24-38px, the mock's inner
   frame from 14px to 10px, and the section's own top/bottom padding is
   trimmed to match.
   ========================================================================== */

.sa-bd { padding-top: clamp(36px, 2.4vw + 20px, 60px); padding-bottom: clamp(24px, 1.6vw + 12px, 40px); }

.sa-bd-band {
  padding: clamp(24px, 1.8vw + 14px, 38px) clamp(26px, 2.4vw + 16px, 52px);
  gap: 36px;
  border-radius: 20px;
  border: 1px solid rgba(6, 214, 209, 0.22);
  background: linear-gradient(160deg, #EAFAFC 0%, #E0F7FA 52%, #D6F5F8 100%);
  box-shadow: 0 1px 2px rgba(9, 38, 84, 0.04);
  color: #0A1B33;
}
/* The bottom stripe was cyan-on-navy; on the tint it becomes navy hairlines,
   still masked upward so it fades out under the copy. */
.sa-bd-band::after {
  height: 76px;
  background: repeating-linear-gradient(90deg, rgba(13, 53, 128, 0.10) 0 2px, transparent 2px 9px);
}

.sa-bd-title { color: #0A1B33; margin-bottom: 14px; }
.sa-bd-lede  { color: #3A536E; margin-bottom: 22px; }

/* A white outline on a pale tint is invisible - the CTA becomes the filled
   brand button, which is also what the nav and hero already use. */
.sa-bd-open {
  padding: 13px 30px;
  border: 1.5px solid #2563FF;
  background: #2563FF;
  color: #fff;
  box-shadow: 0 10px 24px -12px rgba(37, 99, 255, 0.55);
}
.sa-bd-open:hover { background: #1C4CC4; border-color: #1C4CC4; color: #fff; transform: translateY(-2px); }

/* The mock's frame: was a 5%-white glass on dark with a 70px near-black
   shadow. On the tint it becomes the one floating white object. */
.sa-bd-screen {
  padding: 10px;
  border: 1px solid rgba(13, 53, 128, 0.08);
  border-radius: 16px;
  background: rgba(255, 255, 255, 0.72);
  box-shadow:
    0 22px 48px -24px rgba(9, 38, 84, 0.32),
    0 2px 6px -3px rgba(9, 38, 84, 0.12);
}

@media (max-width: 900px) {
  .sa-bd-band { padding: 24px 20px; border-radius: 16px; gap: 26px; }
}

/* =============================================================================
   PRICING — the logo's palette, and the reason to choose a tier
   =============================================================================
   Four things, in order of how much they matter to whether anyone buys:

     * (A limits line under each price was tried and removed at the owner's
       request - limits are not shown on the landing page.)
     * One badge per card. Professional was rendering "Most Popular" and
       "Coming Soon" on top of each other.
     * Logo palette throughout: ink #0A1B33, blue #2563FF, navy #1C4CC4, cyan
       #06D6D1. Ticks are navy on a cyan disc (9.9:1) instead of green - the
       page has no green anywhere else. Cyan is never used as text on white
       (2.2:1); "Save 20%" is blue (8.8:1).
     * The featured card is the one saturated object: navy-to-blue, a cyan top
       rule, and a cyan CTA with navy text (5.1:1). White-on-cyan would be
       2.2:1, which is why the button text is navy and not white.
   ========================================================================== */

/* --- Toggle --- */
.sa-pricing-toggle { display: flex; align-items: center; justify-content: center; gap: 14px; margin-bottom: 34px; }
.sa-toggle-lbl { display: inline-flex; align-items: center; gap: 8px; font-size: 14.5px; font-weight: 600; color: #5A6E86; }
.sa-toggle-lbl.is-on { color: #0A1B33; }
.sa-toggle-save { font-style: normal; font-size: 11.5px; font-weight: 700; color: #2563FF;
                  background: rgba(37, 99, 255, 0.08); padding: 3px 8px; border-radius: 999px; }
.sa-toggle-switch { position: relative; display: inline-block; width: 50px; height: 28px; cursor: pointer; }
.sa-toggle-switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.sa-toggle-track { position: absolute; inset: 0; border-radius: 999px; background: #C9D6E8; transition: background .25s ease; }
.sa-toggle-knob  { position: absolute; top: 3px; left: 3px; width: 22px; height: 22px; border-radius: 50%; background: #fff;
                   box-shadow: 0 1px 3px rgba(9, 38, 84, 0.3); transition: transform .25s cubic-bezier(.16, 1, .3, 1); }
.sa-toggle-switch input:checked + .sa-toggle-track { background: #2563FF; }
.sa-toggle-switch input:checked + .sa-toggle-track .sa-toggle-knob { transform: translateX(22px); }
.sa-toggle-switch input:focus-visible + .sa-toggle-track { outline: 2px solid #2563FF; outline-offset: 3px; }

/* --- Cards --- */
.sa-pricing-grid { gap: 18px; }
.sa-pricing-card {
  border-radius: 20px;
  border: 1px solid rgba(13, 53, 128, 0.10);
  padding: 30px 24px 26px;
  box-shadow: 0 1px 2px rgba(9, 38, 84, 0.04);
}
.sa-pricing-card:hover { border-color: rgba(6, 214, 209, 0.55); box-shadow: 0 22px 48px -20px rgba(9, 38, 84, 0.22); }
.sa-pricing-name   { color: #0A1B33; font-size: 12.5px; letter-spacing: 0.12em; }
.sa-pricing-price  { color: #0A1B33; font-size: 2.8rem; }
.sa-pricing-period { color: #5A6E86; }


.sa-pricing-features li { color: #3A536E; font-size: 13.5px; }
.sa-plan-tick { color: #1C4CC4; background: rgba(6, 214, 209, 0.18); }
.sa-pricing-badge { background: linear-gradient(92deg, #2563FF, #06D6D1); box-shadow: 0 8px 18px -8px rgba(37, 99, 255, 0.6); }

/* --- Featured --- */
.sa-pricing-card.sa-featured {
  background: linear-gradient(165deg, #2563FF 0%, #1C4CC4 60%, #0a2a67 100%);
  border-color: rgba(6, 214, 209, 0.35);
  box-shadow: 0 30px 64px -24px rgba(13, 53, 128, 0.55), inset 0 1px 0 rgba(255, 255, 255, 0.14);
}
.sa-pricing-card.sa-featured::before {
  content: ''; position: absolute; inset: 0 0 auto 0; height: 4px;
  background: linear-gradient(90deg, #06D6D1, #7fe6f4);
  border-radius: 20px 22px 0 0;
}
.sa-pricing-card.sa-featured .sa-pricing-name { color: #7fe6f4; }
.sa-pricing-card.sa-featured .sa-plan-tick { color: #1C4CC4; background: #06D6D1; }
.sa-pricing-card.sa-featured .sa-btn-primary,
.sa-pricing-card.sa-featured .sa-btn-soft {
  background: #06D6D1; color: #1C4CC4; font-weight: 700;
  box-shadow: 0 12px 26px -10px rgba(6, 214, 209, 0.7);
}
.sa-pricing-card.sa-featured .sa-btn-primary:hover,
.sa-pricing-card.sa-featured .sa-btn-soft:hover { background: #7fe6f4; color: #1C4CC4; }

/* --- Free + coming soon --- */
.sa-btn-free { background: #2563FF; box-shadow: 0 10px 24px -12px rgba(37, 99, 255, 0.6); }
.sa-btn-free:hover { background: #1C4CC4; filter: none; }
.sa-btn-soon { opacity: 1; cursor: not-allowed; color: #5A6E86; border-color: rgba(13, 53, 128, 0.18); background: rgba(13, 53, 128, 0.03); }
.sa-pricing-card.sa-featured .sa-btn-soon { color: rgba(255, 255, 255, 0.72); border-color: rgba(255, 255, 255, 0.28); background: rgba(255, 255, 255, 0.06); }

/* --- Featured card, light ----------------------------------------------------
   The navy version read as heavy next to four white cards. The featured card
   is now the pale cyan ground the rest of the page uses (the logo's #06D6D1 at
   6-16% over white), with a cyan border and the cyan top rule kept, so it is
   still the one card that is a different colour - just a cool one, not a dark
   one. Every inner colour is re-derived for the light surface: ink text
   (15:1), a filled blue CTA with white text (8.8:1), navy ticks on cyan discs. */
.sa-pricing-card.sa-featured {
  background: linear-gradient(165deg, #EAFAFC 0%, #E0F7FA 55%, #DCEFF9 100%);
  border-color: rgba(6, 214, 209, 0.55);
  box-shadow: 0 26px 56px -26px rgba(6, 214, 209, 0.45), 0 2px 6px -3px rgba(9, 38, 84, 0.10);
}
.sa-pricing-card.sa-featured:hover {
  box-shadow: 0 32px 64px -26px rgba(6, 214, 209, 0.55), 0 2px 6px -3px rgba(9, 38, 84, 0.10);
}
.sa-pricing-card.sa-featured .sa-pricing-name   { color: #2563FF; }
.sa-pricing-card.sa-featured .sa-pricing-price  { color: #0A1B33; }
.sa-pricing-card.sa-featured .sa-pricing-period { color: #5A6E86; }
.sa-pricing-card.sa-featured .sa-pricing-features li { color: #3A536E; }
.sa-pricing-card.sa-featured .sa-plan-tick { color: #1C4CC4; background: rgba(6, 214, 209, 0.28); }
.sa-pricing-card.sa-featured .sa-btn-primary,
.sa-pricing-card.sa-featured .sa-btn-soft {
  background: #2563FF; color: #fff; font-weight: 700;
  box-shadow: 0 12px 26px -12px rgba(37, 99, 255, 0.6);
}
.sa-pricing-card.sa-featured .sa-btn-primary:hover,
.sa-pricing-card.sa-featured .sa-btn-soft:hover { background: #1C4CC4; color: #fff; }
.sa-pricing-card.sa-featured .sa-btn-soon {
  color: #2563FF; border-color: rgba(37, 99, 255, 0.35); background: rgba(255, 255, 255, 0.7);
}

/* --- Plan limits -------------------------------------------------------------
   The four numbers a buyer actually chooses on - audits/month, pages/crawl,
   projects, seats - read straight off /api/plans. They sit above the feature
   chips because volume is the decision and features are the tie-breaker; the
   card previously showed only chips, so comparing volume meant registering.

   A 2x2 grid rather than a list: four short number/label pairs read as a spec
   block that way, and it stays legible when a plan's figures run to five digits.
   Colours are the light-card inks, which the featured card also ends on after
   the "Featured card, light" pass above, so it needs no override. */
.sa-pricing-limits {
  list-style: none;
  margin: 0 0 4px;
  padding: 18px 0 0;
  border-top: 1px solid rgba(15, 23, 42, 0.08);
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px 10px;
}
.sa-pricing-limits li {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
}
.sa-pricing-limits b {
  font-size: 17px;
  font-weight: 700;
  line-height: 1.15;
  color: #0A1B33;
  font-variant-numeric: tabular-nums;
}
.sa-pricing-limits span {
  font-size: 11.5px;
  line-height: 1.3;
  color: #5b6b83;
}
.sa-pricing-card.sa-featured .sa-pricing-limits { border-color: rgba(6, 214, 209, 0.35); }

/* --- Pricing, pass three: three public plans ---------------------------------
   * Featured card: the flat cyan tint gets depth - a blue-leaning gradient, a
     soft bloom top-right, and the same hairline "lining" the demo band wears
     along its foot. Children are lifted above the lining so text never sits on
     the stripes.
   * Badges: one pill language for both. "Most Popular" is solid blue, not a
     gradient that fought the top rule; "Current Plan" moves to the same
     centred position and loses the green - the page has no green anywhere
     else, and the logo palette is what everything here is built from.
   -------------------------------------------------------------------------- */
.sa-pricing-card.sa-featured {
  background:
    radial-gradient(520px 300px at 88% 0%, rgba(6, 214, 209, 0.22), transparent 62%),
    radial-gradient(420px 260px at 8% 100%, rgba(37, 99, 255, 0.10), transparent 64%),
    linear-gradient(160deg, #EEF6FD 0%, #E3F1FB 46%, #D9F1F7 100%);
  border-color: rgba(37, 99, 255, 0.28);
  box-shadow: 0 28px 60px -26px rgba(37, 99, 255, 0.40), 0 2px 6px -3px rgba(9, 38, 84, 0.10);
}
.sa-pricing-card.sa-featured > * { position: relative; z-index: 1; }
.sa-pricing-card.sa-featured::before {
  z-index: 2;
  background: linear-gradient(90deg, #2563FF, #06D6D1);
}
/* The lining: vertical hairlines along the foot, fading out upward. */
.sa-pricing-card.sa-featured::after {
  content: '';
  position: absolute;
  inset: auto 0 0 0;
  height: 96px;
  z-index: 0;
  border-radius: 0 0 22px 22px;
  background: repeating-linear-gradient(90deg, rgba(37, 99, 255, 0.11) 0 2px, transparent 2px 9px);
  -webkit-mask-image: linear-gradient(to top, #000, transparent);
          mask-image: linear-gradient(to top, #000, transparent);
  pointer-events: none;
}

/* --- Badges: one language --- */
.sa-pricing-badge {
  top: -13px;
  left: 50%;
  right: auto;
  transform: translateX(-50%);
  background: #2563FF;
  color: #fff;
  font-size: 11px;
  letter-spacing: 0.08em;
  padding: 6px 14px;
  box-shadow: 0 8px 18px -8px rgba(37, 99, 255, 0.7);
}
.sa-pricing-badge-current {
  left: 50%;
  right: auto;
  transform: translateX(-50%);
  background: #1C4CC4;
  box-shadow: 0 8px 18px -8px rgba(13, 53, 128, 0.7);
}

/* --- Current plan: blue, not green --- */
.sa-pricing-card.sa-current {
  border-color: rgba(37, 99, 255, 0.45);
  box-shadow: 0 12px 34px -18px rgba(37, 99, 255, 0.35);
}
.sa-btn-current,
.sa-pricing-card.sa-current .sa-btn-current {
  color: #2563FF;
  border-color: rgba(37, 99, 255, 0.45);
  background: rgba(37, 99, 255, 0.04);
  opacity: 1;
}

/* The child-lift above (`.sa-featured > *` -> position: relative) also caught
   the badge, which relies on position: absolute to sit on the card's top edge.
   With relative it dropped into flow 18px down and slid right. Re-asserted at
   higher specificity; z-index 3 keeps it above the top rule (2). */
.sa-pricing-card.sa-featured > .sa-pricing-badge { position: absolute; z-index: 3; }

/* Feature-card lining, one step darker and reaching further across the card.
   .07 -> .11 on the hairlines, and the mask now holds half strength to 58% of
   the corner radius and only fades out by 90% (was 40% / 68%), so the texture
   fills the card's lower half instead of reading as a corner stamp. Still
   ~1.06:1 against the ground - felt, not read. */
.sa-fs-card::after {
  background: repeating-linear-gradient(135deg, rgba(13, 53, 128, 0.11) 0 1px, transparent 1px 10px);
  -webkit-mask-image: radial-gradient(118% 108% at 100% 100%, #000 0%, rgba(0, 0, 0, 0.5) 58%, transparent 90%);
          mask-image: radial-gradient(118% 108% at 100% 100%, #000 0%, rgba(0, 0, 0, 0.5) 58%, transparent 90%);
}

/* =============================================================================
   WHAT WE CHECK — rounded panels, plain labels, per-object reveal
   =============================================================================
   * The split bar and the "Written by AI" strip are gone from the markup.
   * Panels are rounded (18px) with a hairline border; the 3px coloured top rule
     is dropped because it fought the radius - the category colour now lives in
     the icon tile and the list dots instead.
   * Keyword chips become a two-column list: chips read as a tag cloud of
     jargon; a list with a dot reads as "here is what is covered".
   * Reveal: every object animates on its own beat. Header rises; each panel
     scales up in turn (--i); inside each panel the heading, the count and every
     list item follow in sequence (--n). All transform + opacity, one easing, and
     the existing initScrollReveal adds .sa-visible - no new observer.
   ========================================================================== */

.sa-check-group {
  border-top: 1px solid rgba(13, 53, 128, 0.12);
  border-radius: 16px;
  padding: 20px 20px 18px;
  background: linear-gradient(170deg, #FFFFFF 0%, #F6FAFE 100%);
  box-shadow: 0 1px 2px rgba(9, 38, 84, 0.04);
}
.sa-g1, .sa-g2, .sa-g3, .sa-g4 { border-top-color: rgba(13, 53, 128, 0.12); }
.sa-check-group { --gc: #2563FF; }
.sa-g2 { --gc: #0B72BB; }
.sa-g3 { --gc: #059AC8; }
.sa-g4 { --gc: #06D6D1; }
.sa-check-ico { background: color-mix(in srgb, var(--gc) 14%, #fff); color: var(--gc); border-radius: 8px; }
@supports not (color: color-mix(in srgb, #000, #fff)) { .sa-check-ico { background: #E6F1FB; } }
.sa-check-head h3 { font-size: 1.05rem; color: #0A1B33; }
.sa-check-count { color: var(--gc); }

/* --- The list --- */
.sa-check-list {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 7px 14px;
}
.sa-check-list li {
  display: flex; align-items: flex-start; gap: 8px;
  font-size: 13.5px; font-weight: 500; line-height: 1.4; color: #35506E;
}
.sa-check-list li i {
  flex: none; width: 7px; height: 7px; margin-top: 6px; border-radius: 50%;
  background: var(--gc);
}
.sa-g4 .sa-check-list li i { box-shadow: inset 0 0 0 1px rgba(13, 53, 128, 0.25); } /* cyan alone is faint on white */
@media (max-width: 1080px) { .sa-checks-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 620px)  { .sa-checks-grid { grid-template-columns: minmax(0, 1fr); } .sa-check-list { grid-template-columns: 1fr; } }

/* --- Reveal variants (driven by .sa-visible from initScrollReveal) --- */
.sa-checks-sec [data-rv] {
  opacity: 0;
  transition: opacity .7s cubic-bezier(.16, 1, .3, 1), transform .7s cubic-bezier(.16, 1, .3, 1);
}
.sa-checks-sec [data-rv="rise"]  { transform: translateY(28px); }
.sa-checks-sec [data-rv="scale"] { transform: translateY(22px) scale(.94); transition-delay: calc(var(--i, 0) * .12s); }
.sa-checks-sec [data-rv].sa-visible { opacity: 1; transform: none; }

/* Inside a panel: heading, count, then the items, each on its own beat. */
.sa-check-group h3, .sa-check-group .sa-check-count, .sa-check-group .sa-check-ico,
.sa-check-group .sa-check-list li {
  opacity: 0;
  transition: opacity .55s cubic-bezier(.16, 1, .3, 1), transform .55s cubic-bezier(.16, 1, .3, 1);
}
.sa-check-group .sa-check-ico   { transform: scale(.7); }
.sa-check-group h3              { transform: translateX(-10px); }
.sa-check-group .sa-check-count { transform: translateY(8px) scale(.85); }
.sa-check-group .sa-check-list li { transform: translateX(-8px); }
.sa-check-group.sa-visible .sa-check-ico   { opacity: 1; transform: none; transition-delay: calc(var(--i, 0) * .12s + .10s); }
.sa-check-group.sa-visible h3              { opacity: 1; transform: none; transition-delay: calc(var(--i, 0) * .12s + .16s); }
.sa-check-group.sa-visible .sa-check-count { opacity: 1; transform: none; transition-delay: calc(var(--i, 0) * .12s + .24s); }
.sa-check-group.sa-visible .sa-check-list li { opacity: 1; transform: none; transition-delay: calc(var(--i, 0) * .12s + .28s + var(--n, 0) * .045s); }

@media (prefers-reduced-motion: reduce) {
  .sa-checks-sec [data-rv], .sa-check-group h3, .sa-check-group .sa-check-count,
  .sa-check-group .sa-check-ico, .sa-check-group .sa-check-list li {
    opacity: 1; transform: none; transition: none;
  }
}

/* =============================================================================
   WHAT WE CHECK — premium pass
   =============================================================================
   Brief: number + outcome as the focus, fewer borders and more whitespace,
   floating cards with one coloured accent each, a real product visual, a proof
   strip instead of a benefits row, micro-interactions on hover, and a CTA that
   drives signup rather than "more information".

   Four category colours as in the mockup: On-Page = logo blue, Mobile = logo
   cyan, Technical = green, Structure = purple. Each card owns exactly one
   accent (--c) used for the icon tile, the number and the dots - nothing else.
   ========================================================================== */

.sa-checks-sec .sa-section-title { max-width: 16em; margin-inline: auto; }

/* --- Proof strip --- */
.sa-ck-strip {
  list-style: none; margin: 0 auto 30px; padding: 0;
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  max-width: 900px; gap: 10px;
}
.sa-ck-strip li {
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  padding: 12px 10px; text-align: center;
  border-left: 1px solid rgba(13, 53, 128, 0.10);
}
.sa-ck-strip li:first-child { border-left: 0; }
.sa-ck-strip b { font-size: 1.5rem; font-weight: 800; letter-spacing: -0.02em; color: #0A1B33; line-height: 1; }
.sa-ck-strip span { font-size: 12.5px; font-weight: 600; color: #5A6E86; letter-spacing: 0.02em; }

/* --- Product visual: the executive summary card --- */
.sa-ck-visual { max-width: 860px; margin: 0 auto 34px; }
.sa-ck-exec {
  position: relative;
  display: grid; grid-template-columns: 168px 1fr; gap: 26px; align-items: center;
  padding: 26px 28px;
  border-radius: 20px;
  background: linear-gradient(160deg, #F1FBF4 0%, #FFFFFF 70%);
  box-shadow: 0 26px 60px -30px rgba(9, 38, 84, 0.28), 0 2px 6px -3px rgba(9, 38, 84, 0.10),
              inset 0 0 0 1px rgba(13, 53, 128, 0.06);
}
.sa-ck-ring { position: relative; width: 150px; height: 150px; margin: 0 auto; }
.sa-ck-ring svg { width: 100%; height: 100%; display: block; }
.sa-ck-ring-val { position: absolute; inset: 0; display: grid; place-content: center; text-align: center; }
.sa-ck-ring-val b { font-size: 2.6rem; font-weight: 800; letter-spacing: -0.04em; color: #0A1B33; line-height: 1; }
.sa-ck-ring-val em { font-style: normal; font-size: 12px; font-weight: 600; color: #5A6E86; }
.sa-ck-grade {
  position: absolute; left: 50%; bottom: -14px; transform: translateX(-50%);
  display: inline-flex; align-items: center; gap: 6px; white-space: nowrap;
  padding: 4px 10px 4px 4px; border-radius: 999px; background: #fff;
  box-shadow: 0 6px 16px -8px rgba(9, 38, 84, 0.3), inset 0 0 0 1px rgba(13, 53, 128, 0.08);
  font-size: 12px; font-weight: 700; color: #15803d;
}
.sa-ck-grade i { display: grid; place-items: center; width: 22px; height: 22px; border-radius: 50%; background: #16a34a; color: #fff; font-style: normal; font-size: 12px; font-weight: 800; }
.sa-ck-exec-kicker { display: block; font-size: 11px; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase; color: #2563FF; margin-bottom: 6px; }
.sa-ck-exec h3 { margin: 0 0 8px; font-size: 1.25rem; font-weight: 700; letter-spacing: -0.015em; color: #0A1B33; }
.sa-ck-exec p { margin: 0 0 14px; font-size: 14px; line-height: 1.55; color: #3A536E; max-width: 54ch; }
.sa-ck-exec-facts { display: flex; gap: 28px; margin: 0; }
.sa-ck-exec-facts div { display: flex; flex-direction: column; gap: 2px; }
.sa-ck-exec-facts dt { font-size: 10.5px; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; color: #5A6E86; }
.sa-ck-exec-facts dd { margin: 0; font-size: 15px; font-weight: 700; color: #0A1B33; font-variant-numeric: tabular-nums; }
.sa-ck-exec-pill {
  position: absolute; top: 18px; right: 20px;
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 10px; border-radius: 999px; font-size: 11.5px; font-weight: 700;
  color: #15803d; background: rgba(22, 163, 74, 0.10);
}
.sa-ck-exec-pill i { width: 7px; height: 7px; border-radius: 50%; background: #16a34a; }

/* --- Cards --- */
.sa-ck-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 18px; align-items: start; }
.sa-ck {
  --c: #2563FF;
  position: relative;
  display: flex; flex-direction: column;
  padding: 24px 22px 20px;
  border-radius: 20px;
  background: #fff;
  box-shadow: 0 1px 2px rgba(9, 38, 84, 0.05), 0 14px 34px -26px rgba(9, 38, 84, 0.25);
  transition: transform .34s cubic-bezier(.16, 1, .3, 1), box-shadow .34s ease;
}
.sa-c-blue   { --c: #2563FF; }
.sa-c-green  { --c: #16a34a; }
.sa-c-purple { --c: #7c3aed; }
.sa-c-cyan   { --c: #05A8A4; }   /* cyan as a colour for text/ink needs the deeper stop: #06D6D1 is 2.2:1 on white */
.sa-c-cyan .sa-ck-ico { background: color-mix(in srgb, #06D6D1 18%, #fff); color: #05A8A4; }

.sa-ck-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 18px; }
.sa-ck-no { font-size: 11px; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase; color: #5A6E86; }
.sa-ck-ico {
  display: grid; place-items: center; width: 48px; height: 48px; border-radius: 16px;
  background: color-mix(in srgb, var(--c) 12%, #fff); color: var(--c);
  box-shadow: 0 10px 22px -12px color-mix(in srgb, var(--c) 60%, transparent);
  transition: transform .34s cubic-bezier(.16, 1, .3, 1), box-shadow .34s ease;
}
.sa-ck-ico .mud-icon-root { font-size: 26px; }
@supports not (color: color-mix(in srgb, #000, #fff)) {
  .sa-ck-ico { background: #EEF3FB; }
}

/* Number + outcome is the focus. */
.sa-ck-num { display: flex; flex-direction: column; gap: 2px; margin-bottom: 10px; }
.sa-ck-num b { font-size: 2.75rem; font-weight: 800; line-height: 1; letter-spacing: -0.04em; color: var(--c); transition: transform .34s cubic-bezier(.16, 1, .3, 1); transform-origin: left bottom; }
.sa-ck-num span { font-size: 15px; font-weight: 700; color: #0A1B33; }
.sa-ck-blurb { margin: 0 0 14px; font-size: 13.5px; line-height: 1.55; color: #3A536E; }

.sa-ck-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 7px; }
.sa-ck-list li { display: flex; align-items: flex-start; gap: 9px; font-size: 13.5px; font-weight: 500; line-height: 1.4; color: #35506E; }
.sa-ck-list li i { flex: none; width: 16px; height: 16px; margin-top: 1px; border-radius: 50%; background: color-mix(in srgb, var(--c) 14%, #fff); position: relative; }
.sa-ck-list li i::after { content: ''; position: absolute; left: 5px; top: 2.5px; width: 4px; height: 8px; border: solid var(--c); border-width: 0 2px 2px 0; transform: rotate(45deg); }
.sa-ck-more { margin-top: 8px; padding-top: 10px; border-top: 1px dashed rgba(13, 53, 128, 0.12); }
.sa-ck-more[hidden] { display: none; }

.sa-ck-cta {
  display: inline-flex; align-items: center; gap: 7px; align-self: flex-start;
  margin-top: 16px; padding: 0; border: 0; background: none; cursor: pointer;
  font: 700 14px/1 'Inter', system-ui, sans-serif; color: var(--c);
}
.sa-ck-cta svg { width: 16px; height: 16px; transition: transform .28s cubic-bezier(.16, 1, .3, 1); }
.sa-ck-cta:hover svg, .sa-ck:hover .sa-ck-cta svg { transform: translateX(4px); }
.sa-ck-cta:focus-visible { outline: 2px solid var(--c); outline-offset: 4px; border-radius: 4px; }

/* --- Micro-interactions: subtle, not flashy --- */
.sa-ck:hover { transform: translateY(-5px); box-shadow: 0 2px 4px rgba(9, 38, 84, 0.05), 0 28px 48px -26px rgba(9, 38, 84, 0.34); }
.sa-ck:hover .sa-ck-ico { transform: translateY(-2px) scale(1.06); box-shadow: 0 14px 26px -12px color-mix(in srgb, var(--c) 75%, transparent); }
.sa-ck:hover .sa-ck-num b { transform: scale(1.04); }

/* --- Section CTA --- */
.sa-ck-foot { display: flex; flex-direction: column; align-items: center; gap: 10px; margin-top: 34px; }
.sa-ck-run {
  display: inline-flex; align-items: center; gap: 10px;
  padding: 15px 28px; border-radius: 999px;
  background: #2563FF; color: #fff; font-size: 15.5px; font-weight: 700; text-decoration: none;
  box-shadow: 0 14px 30px -12px rgba(37, 99, 255, 0.6);
  transition: transform .26s cubic-bezier(.16, 1, .3, 1), box-shadow .26s ease, background .26s ease;
}
.sa-ck-run svg { width: 18px; height: 18px; transition: transform .26s cubic-bezier(.16, 1, .3, 1); }
.sa-ck-run:hover { background: #1C4CC4; transform: translateY(-2px); box-shadow: 0 18px 36px -12px rgba(37, 99, 255, 0.7); color: #fff; }
.sa-ck-run:hover svg { transform: translateX(4px); }
.sa-ck-foot-note { font-size: 13px; color: #5A6E86; }

/* --- Reveal (rides the existing observer; [data-rv] rules above already
       handle header/rise + card/scale; inner beats for the new card) --- */
.sa-ck .sa-ck-ico, .sa-ck .sa-ck-num b, .sa-ck .sa-ck-list > li {
  opacity: 0; transition: opacity .55s cubic-bezier(.16, 1, .3, 1), transform .55s cubic-bezier(.16, 1, .3, 1);
}
.sa-ck .sa-ck-ico { transform: scale(.7); }
.sa-ck .sa-ck-num b { transform: translateY(8px) scale(.85); }
.sa-ck .sa-ck-list > li { transform: translateX(-8px); }
.sa-ck.sa-visible .sa-ck-ico   { opacity: 1; transform: none; transition-delay: calc(var(--i, 0) * .12s + .10s); }
.sa-ck.sa-visible .sa-ck-num b { opacity: 1; transform: none; transition-delay: calc(var(--i, 0) * .12s + .20s); }
.sa-ck.sa-visible .sa-ck-list > li { opacity: 1; transform: none; transition-delay: calc(var(--i, 0) * .12s + .26s + var(--n, 0) * .05s); }
/* hover must still win once revealed */
.sa-ck.sa-visible:hover .sa-ck-ico { transform: translateY(-2px) scale(1.06); transition-delay: 0s; }
.sa-ck.sa-visible:hover .sa-ck-num b { transform: scale(1.04); transition-delay: 0s; }

/* Ring draws once when the visual reveals; rests FINISHED if it never runs. */
.sa-ck-visual.sa-visible .sa-ck-ring-arc { animation: sa-ck-ring 1.3s cubic-bezier(.16, 1, .3, 1) both; }
@keyframes sa-ck-ring { from { stroke-dashoffset: 314.16; } to { stroke-dashoffset: 25.13; } }

@media (max-width: 1080px) {
  .sa-ck-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .sa-ck-strip { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .sa-ck-strip li:nth-child(3) { border-left: 0; }
}
@media (max-width: 700px) {
  .sa-ck-exec { grid-template-columns: 1fr; text-align: center; padding: 26px 20px 30px; }
  .sa-ck-exec p { margin-inline: auto; }
  .sa-ck-exec-facts { justify-content: center; }
  .sa-ck-exec-pill { position: static; margin: 0 auto; }
  .sa-ck-grade { bottom: -10px; }
}
@media (max-width: 560px) {
  .sa-ck-grid { grid-template-columns: minmax(0, 1fr); }
  .sa-ck-strip { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px; }
}
@media (prefers-reduced-motion: reduce) {
  .sa-ck, .sa-ck .sa-ck-ico, .sa-ck .sa-ck-num b, .sa-ck .sa-ck-list > li { opacity: 1; transform: none; transition: none; }
  .sa-ck-visual.sa-visible .sa-ck-ring-arc { animation: none; }
}

/* --- Review fixes ------------------------------------------------------------
   * The green card's "Explore 18 checks" button was #16a34a on white = 3.30:1.
     At 14px bold that is below the 4.5:1 minimum, so only the CTA text moves to
     green-700 (5.02:1). The 44px number, the icon tint and the tick marks stay
     #16a34a - large text and non-text, where 3.30:1 passes.
   * Reduced motion missed the two HOVER micro-animations: the CTA arrow slide
     and the pill lift. Neither section block covered them.
   -------------------------------------------------------------------------- */
.sa-c-green .sa-ck-cta { color: #15803d; }

@media (prefers-reduced-motion: reduce) {
  .sa-ck-cta svg,
  .sa-ck:hover .sa-ck-cta svg,
  .sa-ck-cta:hover svg { transform: none; transition: none; }
  .sa-ck-run, .sa-ck-run:hover { transform: none; transition: background .01s linear; }
  .sa-ck-run svg, .sa-ck-run:hover svg { transform: none; transition: none; }
  .sa-ck:hover { transform: none; }
  .sa-ck:hover .sa-ck-ico, .sa-ck.sa-visible:hover .sa-ck-ico { transform: none; }
  .sa-ck:hover .sa-ck-num b, .sa-ck.sa-visible:hover .sa-ck-num b { transform: none; }
}

/* --- Review fixes, second pass ------------------------------------------------
   * HOVER LIFT WAS DEAD. `.sa-ck:hover` is (0,2,0); the reveal rules
     `.sa-checks-sec [data-rv]` and `.sa-checks-sec [data-rv].sa-visible` are
     (0,3,0) and set the transform in both states, so they won and the card
     never moved. Verified by probe: a (0,2,0) rule loses, (0,4,0) wins.
   * HOVER-OUT LAG. The icon and number carried the reveal's staggered
     transition-delay on their base rule, so leaving the card replayed that
     delay. The reveal is now a run-once ANIMATION, freeing `transition` for
     hover in both directions.
   * color-mix fallback existed for the icon tile but not the list tick.
   -------------------------------------------------------------------------- */
.sa-checks-sec .sa-ck[data-rv]:hover {
  transform: translateY(-5px);
  box-shadow: 0 2px 4px rgba(9, 38, 84, 0.05), 0 28px 48px -26px rgba(9, 38, 84, 0.34);
}

/* Reveal as animation, not a delayed transition. Rests at the FINISHED state so
   a browser that never runs it still shows a complete card. */
.sa-ck .sa-ck-ico,
.sa-ck .sa-ck-num b { opacity: 1; transform: none; transition: transform .34s cubic-bezier(.16, 1, .3, 1); }
.sa-ck[data-rv]:not(.sa-visible) .sa-ck-ico,
.sa-ck[data-rv]:not(.sa-visible) .sa-ck-num b { opacity: 0; }
/* sa-ck-pop / sa-ck-rise removed: superseded by the opacity-only sa-ck-fade
   entrance, which is what lets hover own `transform` without a conflict. */
/* Superseded: these once carried `animation: none`, which cancelled the entrance
   on hover and let it restart on hover-out - that was the number's blink. The
   entrance is opacity-only now and hover is transform-only, so they never touch
   the same property and nothing needs cancelling. */

.sa-ck-list li i { background: #EEF3FB; }                    /* fallback first */
@supports (background: color-mix(in srgb, red 10%, white)) {
  .sa-ck-list li i { background: color-mix(in srgb, var(--c) 14%, #fff); }
}

@media (prefers-reduced-motion: reduce) {
  .sa-checks-sec .sa-ck[data-rv]:hover { transform: none; }
  .sa-ck.sa-visible .sa-ck-ico, .sa-ck.sa-visible .sa-ck-num b { animation: none; opacity: 1; transform: none; }
  .sa-checks-sec .sa-ck[data-rv]:hover .sa-ck-ico,
  .sa-checks-sec .sa-ck[data-rv]:hover .sa-ck-num b { transform: none; }
}

/* Featured pricing card: no top rule, no shadow.
   The 4px blue->cyan ::before and the card's drop shadow are both removed; the
   cyan-leaning tint plus the 1px border are what separate it from its
   neighbours now. `content: none` (not display/height) so the pseudo-element is
   never generated, and the ::after lining along the foot is untouched. */
.sa-pricing-card.sa-featured::before { content: none; }
.sa-pricing-card.sa-featured,
.sa-pricing-card.sa-featured:hover { box-shadow: none; }

/* =============================================================================
   CHECK CARDS — no disclosure, and a hover that cannot blink
   =============================================================================
   THE BLINK: the entrance used keyframes that animated opacity AND transform on
   the same elements the hover scales. To let hover win, the hover rule set
   `animation: none` - so on hover-OUT the animation was re-applied, complete
   with its stagger delay, and replayed from opacity 0. That is the flash.

   THE FIX is to stop the two effects sharing a property. The entrance now
   animates OPACITY ONLY, on the wrapper (.sa-ck-num, .sa-ck-ico); hover owns
   TRANSFORM, on the child (b, .mud-icon-root). Nothing is ever cancelled, so
   there is nothing to restart.
   ========================================================================== */

/* Entrance: opacity only, and it rests visible if it never runs. */
.sa-ck .sa-ck-ico,
.sa-ck .sa-ck-num b { opacity: 1; transform: none; animation: none; }
.sa-ck[data-rv]:not(.sa-visible) .sa-ck-ico,
.sa-ck[data-rv]:not(.sa-visible) .sa-ck-num b { opacity: 0; }
.sa-ck.sa-visible .sa-ck-ico {
  animation: sa-ck-fade .5s ease both;
  animation-delay: calc(var(--i, 0) * .12s + .10s);
}
.sa-ck.sa-visible .sa-ck-num b {
  animation: sa-ck-fade .5s ease both;
  animation-delay: calc(var(--i, 0) * .12s + .20s);
}
@keyframes sa-ck-fade { from { opacity: 0; } to { opacity: 1; } }

/* Hover: transform only, and never on the animated property. The icon tile
   moves; the number scales via its own element. No `animation: none` anywhere,
   so hovering in and out cannot restart the entrance. */
.sa-ck .sa-ck-ico,
.sa-ck .sa-ck-num b {
  transition: transform .3s cubic-bezier(.16, 1, .3, 1), box-shadow .3s ease;
  transform-origin: left center;
  will-change: transform;
}
.sa-checks-sec .sa-ck[data-rv]:hover .sa-ck-ico   { transform: translateY(-2px) scale(1.06); }
.sa-checks-sec .sa-ck[data-rv]:hover .sa-ck-num b { transform: scale(1.04); }

@media (prefers-reduced-motion: reduce) {
  .sa-ck.sa-visible .sa-ck-ico,
  .sa-ck.sa-visible .sa-ck-num b { animation: none; opacity: 1; }
  .sa-checks-sec .sa-ck[data-rv]:hover .sa-ck-ico,
  .sa-checks-sec .sa-ck[data-rv]:hover .sa-ck-num b { transform: none; }
}

/* =============================================================================
   PLAIN WHITE PAGE — exploratory
   =============================================================================
   Neutralises every tint on the page GROUND so the landing page renders on flat
   white. Component surfaces are deliberately left alone: the hero band, the
   feature cards, the pale check cards, the demo band, the featured pricing card
   and the footer wordmark all keep their own colour, because without them a
   white ground has nothing to separate.

   This whole block is self-contained — delete from the header above down to the
   end of the file to go back to the washed version. Nothing else was edited.
   ========================================================================== */

/* The page wash: four brand blooms plus a vertical ramp, all removed. */
#sa-main-content { background: #ffffff; }

/* Alternating sections carried their own light-grey fill. */
.sa-section-alt { background: #ffffff; }

/* The footer ramp (light blue -> white) flattens to white too.
   `footer.sa-footer` (0,1,1), not `.sa-footer` (0,1,0): SharedFooter.razor ships
   its own <style> block, which the component injects AFTER this stylesheet, so a
   same-specificity rule here loses to it. */
footer.sa-footer { background: #ffffff; }

/* The stats bar and the check cards sat on translucent white over the wash;
   on flat white they need their hairline back or they vanish. */
.sa-stats-inner { background: #ffffff; box-shadow: inset 0 0 0 1px rgba(13, 53, 128, 0.08), 0 1px 2px rgba(9, 38, 84, 0.04); }

/* Banner: no separation lines.
   -----------------------------
   TWO causes, both measured rather than guessed:

   1. THE BLOOM EDGES. Three radial pseudo-elements sat over the ramp, and a
      circle stops contributing colour at its own boundary - over a smooth
      gradient that boundary reads as a horizontal line. Their edges fell
      exactly where the lines were marked:
        .sa-hero::after   980px, bottom:-560px  -> top edge at y=405 (left)
        .sa-hero::before  900px, top:-340px     -> bottom edge at y=560 (right)
      Being off-centre, they were also why the two sides never matched.
      .sa-hero-inner::after is the same story. All removed; the ramp underneath
      is a plain vertical gradient, which cannot produce an edge.
      .sa-hero-inner::before (the faint grid) stays - it is centred and already
      masked to fade out before the blend.

   2. THE FADE'S ONSET. .sa-hero-fade ran a LINEAR alpha from 0. Above its top
      edge the rate of change is zero; below it the rate is constant. The value
      is continuous but its slope is not, and that step in slope is itself a
      visible line. Smoothstep starts and ends at zero slope, so the onset
      disappears. It also now resolves to pure #ffffff - it was ending on
      rgb(253,254,255) against a pure-white page, which is a second faint edge
      at the hero's foot. */
.sa-hero::before,
.sa-hero::after,
.sa-hero-inner::after { content: none; }

.sa-hero-fade {
  background: linear-gradient(to bottom,
    rgba(255, 255, 255, 0)     0%,
    rgba(255, 255, 255, 0.028) 10%,
    rgba(255, 255, 255, 0.104) 20%,
    rgba(255, 255, 255, 0.216) 30%,
    rgba(255, 255, 255, 0.352) 40%,
    rgba(255, 255, 255, 0.5)   50%,
    rgba(255, 255, 255, 0.648) 60%,
    rgba(255, 255, 255, 0.784) 70%,
    rgba(255, 255, 255, 0.896) 80%,
    rgba(255, 255, 255, 0.972) 90%,
    rgba(255, 255, 255, 1)     100%);
}

/* Fade lengthened - the smoothstep was the problem, not the ramp.
   -------------------------------------------------------------
   Smoothstep removed the onset line but has 1.5x the slope of a linear ramp
   through its middle, so the visible transition got compressed into the centre
   of the 210px band and read as a SHORTER fade. The curve is right; it needed
   room.

   At the old hero height there was none: the note ends at 593px and the fade
   already started at 615px, so only ~212px was available. The banner grows
   120px purely to give the fade somewhere to happen - 210px -> 330px, which
   drops the peak slope to 64% of what it was. The fade still starts at 615px,
   clearing the note by the same 22px, so no text contrast changes.

   The stats card's offset is recomputed from the new height so the gap under
   the form is exactly what it was: -140 - 120 = -260. */
.sa-hero { padding-bottom: 352px; }
.sa-hero-fade { height: 330px; }
.sa-stats-bar { margin-top: -260px; }

@media (max-width: 1024px) {
  .sa-hero { padding-bottom: 300px; }
  .sa-hero-fade { height: 280px; }
  .sa-stats-bar { margin-top: -220px; }
}

/* =============================================================================
   FAQ - "THE ANSWER SPREAD"
   =============================================================================
   A ruled editorial spread replacing the MudExpansionPanels accordion.

   WHY NOT ANOTHER CARD. This section sits between the white pricing grid and the
   pale-cyan demo band. A fourth tint would be invisible and a fifth row of
   shadowed cards would be the twentieth rounded rectangle on the page. Hairlines,
   hanging numerals and type are the one visual language the page has not spent.
   Hence: no radius (except the plus disc and the focus ring), no shadow, no tint.

   WHY THE DECK LINE. The old section's weakness was never the border radius - it
   was that eight collapsed rows answer nothing. Every entry now shows a bolded
   one-sentence answer before any click; the disclosure carries only the detail.

   STATE IS IN data-open, NOT IN A CLASS. scrollReveal.js adds .sa-visible via
   classList.add, which Blazor's renderer cannot see. A bound state class in the
   same class attribute as sa-animate-on-scroll would make Blazor rewrite class on
   every toggle, wiping .sa-visible and dropping the row to opacity 0 until the
   next observer tick - and Index.razor re-runs initScrollReveal on every render,
   so it would re-reveal WITH its stagger delay. Every selector below keys off the
   data- attribute so the class attribute is a static literal Blazor never touches.

   NOTE the [data-rv] rules earlier in this file are scoped to .sa-checks-sec, so
   they do not reach here; this section declares its own reveal contract.
   ========================================================================== */

.sa-faq-sec { background: transparent; }

/* --- The spread ---------------------------------------------------------- */
.sa-faq-sec .sa-fq-spread {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 300px) minmax(0, 1fr);
  column-gap: 64px;
  align-items: start;
  padding-top: 46px;
  --fq-gutter: 40px;   /* one number; the open-state bar derives from it */
}
/* Brand rule across the top, echoing .sa-cta-belt::before so it reads as house
   language. Cyan appears exactly twice in this section and never as ink. */
.sa-faq-sec .sa-fq-spread::before {
  content: "";
  position: absolute; top: 0; left: 0; right: 0; height: 2px;
  background: linear-gradient(90deg, #2563FF, #06D6D1 55%, rgba(6, 214, 209, 0));
}

/* --- Left masthead ------------------------------------------------------- */
.sa-faq-sec .sa-fq-rail {
  position: sticky;
  top: calc(var(--sa-nav-height, 76px) + 28px);
  /* Belt and braces alongside moving the foot strip out of the grid: a sticky
     item is confined by its containing block, so keeping the rail's own bottom
     margin at zero and the grid ending at the list means it can never print
     over the block that follows. */
  align-self: start;
  margin-bottom: 0;
}
.sa-faq-sec .sa-fq-title {
  margin: 0 0 14px;
  font-size: clamp(1.6rem, 1.1rem + 1.6vw, 2.5rem);
  font-weight: 700;
  letter-spacing: -0.018em;
  line-height: 1.12;
  color: #0A1B33;
  text-align: left;
}
.sa-faq-sec .sa-fq-standfirst {
  margin: 0;
  max-width: 34ch;
  font-size: 15px;
  line-height: 1.65;
  color: #3A536E;
}

/* --- The ruled column ---------------------------------------------------- */
.sa-faq-sec .sa-fq-list {
  counter-reset: fq;
  border-left: 1px solid rgba(13, 53, 128, .10);
  padding-left: var(--fq-gutter);
}

.sa-faq-sec .sa-fq {
  position: relative;
  display: grid;
  grid-template-columns: 68px minmax(0, 1fr);
  counter-increment: fq;
  border-top: 1px solid rgba(13, 53, 128, .10);
  padding: 22px 0 20px;
}
.sa-faq-sec .sa-fq:first-child { border-top: 0; padding-top: 4px; }

/* Open marker: the gutter hairline becomes a live "you are here" bar. Its offset
   is derived from --fq-gutter, so a padding change at any breakpoint moves both. */
.sa-faq-sec .sa-fq::before {
  content: "";
  position: absolute; top: 0; bottom: 0;
  left: calc((var(--fq-gutter) + 1px) * -1);
  width: 2px;
  background: linear-gradient(180deg, #2563FF, #06D6D1);
  transform: scaleY(0);
  transform-origin: top;
  transition: transform .36s cubic-bezier(.16, 1, .3, 1);
}
.sa-faq-sec .sa-fq[data-open="true"]::before { transform: scaleY(1); }

/* Hover wash. Deliberately a BACKGROUND, not a lift: transform is owned by the
   reveal on this same element, and a hover translate would lose to it exactly as
   .sa-ck's did at line 9022. Choosing a different property sidesteps the
   collision by construction rather than by specificity arm-wrestling.
   :focus-within gives keyboard users the identical cue. */
.sa-faq-sec .sa-fq::after {
  content: "";
  position: absolute; inset: 0 -16px;
  background: linear-gradient(90deg, rgba(37, 99, 255, .045), transparent 62%);
  opacity: 0;
  transition: opacity .3s ease;
  pointer-events: none;
}
.sa-faq-sec .sa-fq:hover::after,
.sa-faq-sec .sa-fq:focus-within::after { opacity: 1; }

/* --- Hanging numeral (a CSS counter, so it can never go stale) ------------ */
.sa-faq-sec .sa-fq-no { grid-column: 1; grid-row: 1; }
.sa-faq-sec .sa-fq-no::before {
  content: counter(fq, decimal-leading-zero);
  font-size: clamp(1.5rem, 1.05rem + 1vw, 2.2rem);
  font-weight: 800;
  letter-spacing: -0.04em;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
  color: rgba(37, 99, 255, .18);
  transition: color .28s ease;
}
.sa-faq-sec .sa-fq:hover .sa-fq-no::before,
.sa-faq-sec .sa-fq[data-open="true"] .sa-fq-no::before { color: #2563FF; }

/* --- Question row -------------------------------------------------------- */
.sa-faq-sec .sa-fq-h { grid-column: 2; grid-row: 1; margin: 0; }
.sa-faq-sec .sa-fq-btn {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: 14px;
  width: 100%;
  padding: 0;
  background: none;
  border: 0;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
}
.sa-faq-sec .sa-fq-q {
  flex: 1 1 auto;
  font-size: clamp(1.02rem, .96rem + .28vw, 1.2rem);
  font-weight: 700;
  letter-spacing: -0.015em;
  line-height: 1.34;
  color: #0A1B33;
}

/* Plan-gate chip. Four of these questions are really "is this on my plan?", so
   the answer is given before the deck is read. It sits INSIDE the button and is
   not aria-hidden, so it joins the accessible name. The app's severity palette is
   deliberately not reused - red or amber on an FAQ row reads as "broken". */
.sa-faq-sec .sa-fq-chip {
  flex: 0 0 auto;
  margin-top: 3px;
  padding: 3px 9px;
  border-radius: 999px;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  white-space: nowrap;
  color: #5A6E86;
  background: #F2F5FA;
  box-shadow: inset 0 0 0 1px rgba(13, 53, 128, .09);
}
.sa-faq-sec .sa-fq-chip-paid {
  color: #1C4CC4;
  background: rgba(37, 99, 255, .10);
  box-shadow: inset 0 0 0 1px rgba(37, 99, 255, .22);
}

/* Plus becomes a minus: the vertical bar rotates flat and fades, so the two
   superimpose rather than one swapping for the other. */
.sa-faq-sec .sa-fq-plus {
  position: relative;
  flex: 0 0 auto;
  width: 26px; height: 26px;
  border-radius: 50%;
  box-shadow: inset 0 0 0 1px rgba(13, 53, 128, .16);
  transition: background .28s ease, box-shadow .28s ease;
}
.sa-faq-sec .sa-fq-plus::before,
.sa-faq-sec .sa-fq-plus::after {
  content: "";
  position: absolute; top: 50%; left: 50%;
  width: 10px; height: 1.5px;
  margin: -0.75px 0 0 -5px;
  border-radius: 1px;
  background: #2563FF;
  transition: transform .34s cubic-bezier(.16, 1, .3, 1), opacity .34s ease;
}
.sa-faq-sec .sa-fq-plus::after { transform: rotate(90deg); }
.sa-faq-sec .sa-fq[data-open="true"] .sa-fq-plus::after { transform: rotate(0deg); opacity: 0; }
.sa-faq-sec .sa-fq:hover .sa-fq-plus {
  background: rgba(37, 99, 255, .06);
  box-shadow: inset 0 0 0 1px rgba(37, 99, 255, .30);
}

/* --- The deck: the answer you get without clicking ----------------------- */
.sa-faq-sec .sa-fq-deck {
  position: relative;
  grid-column: 2; grid-row: 2;
  margin: 8px 0 0;
  max-width: 60ch;
  font-size: 14.5px;
  font-weight: 700;
  line-height: 1.55;
  color: #2563FF;          /* 8.0:1 - a ladder of blue verdict lines down the column */
}

/* --- Disclosure panel ---------------------------------------------------- */
/* grid-template-rows 0fr->1fr needs overflow:hidden + min-height:0 on the INNER
   wrapper only; putting them on the content is what breaks this technique.
   visibility rides along (delayed on close) so closed text leaves the tab order
   and the a11y tree even where `inert` is unsupported. */
.sa-faq-sec .sa-fq-panel {
  position: relative;
  grid-column: 2; grid-row: 3;
  display: grid;
  grid-template-rows: 0fr;
  visibility: hidden;
  transition: grid-template-rows .36s cubic-bezier(.16, 1, .3, 1), visibility 0s linear .36s;
}
.sa-faq-sec .sa-fq[data-open="true"] .sa-fq-panel {
  grid-template-rows: 1fr;
  visibility: visible;
  transition: grid-template-rows .36s cubic-bezier(.16, 1, .3, 1), visibility 0s;
}
.sa-faq-sec .sa-fq-panel-in { overflow: hidden; min-height: 0; }
.sa-faq-sec .sa-fq-a {
  margin: 12px 0 0;
  max-width: 64ch;
  font-size: 15px;
  line-height: 1.72;
  color: #3A536E;
}

/* Tabular facts. Only the four answers that carry numbers get these - the eye
   grabs 60+ / 59 / 8 far faster than it parses the sentence around them. */
.sa-faq-sec .sa-fq-facts {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 14px 0 2px;
}
.sa-faq-sec .sa-fq-facts > div {
  padding: 8px 14px;
  border-radius: 8px;
  background: #F7FAFE;
  box-shadow: inset 0 0 0 1px rgba(13, 53, 128, .07);
}
.sa-faq-sec .sa-fq-facts dt {
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: #5A6E86;
}
.sa-faq-sec .sa-fq-facts dd {
  margin: 2px 0 0;
  font-size: 17px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  color: #0A1B33;
}

/* --- Foot strip: the old question 8, promoted to the section's only CTA --- */
/* No longer a grid child: it sits after .sa-fq-spread so the sticky rail cannot
   travel over it. .sa-section-inner on the element supplies the 1200px cap and
   centring the grid used to give it. */
.sa-faq-sec .sa-fq-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 18px 32px;
  margin-top: 46px;
  padding-top: 26px;
  border-top: 1px solid rgba(13, 53, 128, .10);
}
.sa-faq-sec .sa-fq-foot-h {
  margin: 0 0 5px;
  font-size: 1.05rem;
  font-weight: 700;
  color: #0A1B33;
}
.sa-faq-sec .sa-fq-foot-p {
  margin: 0;
  max-width: 62ch;
  font-size: 14.5px;
  line-height: 1.6;
  color: #3A536E;
}
.sa-faq-sec .sa-fq-foot-a {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px 16px;
}
.sa-faq-sec .sa-fq-mail {
  display: inline-flex;
  align-items: center;
  padding: 10px 18px;
  border-radius: 999px;
  background: #2563FF;
  color: #ffffff;
  font-size: 14px;
  font-weight: 700;
  text-decoration: none;
  transition: background .25s ease;
}
.sa-faq-sec .sa-fq-mail:hover { background: #1C4CC4; }
.sa-faq-sec .sa-fq-link {
  font-size: 14px;
  font-weight: 600;
  color: #2563FF;
  text-decoration: none;
}
.sa-faq-sec .sa-fq-link:hover { text-decoration: underline; }

/* --- Focus ring: 8.0:1, never removed ------------------------------------ */
.sa-faq-sec .sa-fq-btn:focus-visible,
.sa-faq-sec .sa-fq-mail:focus-visible,
.sa-faq-sec .sa-fq-link:focus-visible {
  outline: 2px solid #2563FF;
  outline-offset: 4px;
  border-radius: 4px;
}

/* --- Reveal -------------------------------------------------------------- */
/* Rests in the FINISHED state and is hidden only while pending, so if the
   observer never runs the reader still gets a complete, readable spread. Each
   entry carries the class separately - one wrapper around all seven would exceed
   the viewport and never trip threshold 0.15 on a laptop. */
.sa-faq-sec [data-rv] {
  opacity: 1;
  transition: opacity .7s cubic-bezier(.16, 1, .3, 1),
              transform .7s cubic-bezier(.16, 1, .3, 1);
  transition-delay: calc(var(--i, 0) * .04s);
}
.sa-faq-sec [data-rv]:not(.sa-visible) { opacity: 0; }
.sa-faq-sec [data-rv="line"]:not(.sa-visible) { transform: translateY(18px); }
.sa-faq-sec [data-rv="rise"]:not(.sa-visible) { transform: translateY(24px); }
.sa-faq-sec [data-rv].sa-visible { transform: none; }

/* --- Responsive ---------------------------------------------------------- */
@media (max-width: 1180px) {
  .sa-faq-sec .sa-fq-spread {
    grid-template-columns: minmax(0, 258px) minmax(0, 1fr);
    column-gap: 44px;
    --fq-gutter: 30px;
  }
  .sa-faq-sec .sa-fq { grid-template-columns: 58px minmax(0, 1fr); }
}

/* Single column: the rail unsticks and becomes a normal masthead. The gutter
   rule survives at a narrower offset so the open-state bar keeps its anchor. */
@media (max-width: 900px) {
  .sa-faq-sec .sa-fq-spread {
    grid-template-columns: minmax(0, 1fr);
    row-gap: 26px;
    padding-top: 34px;
    --fq-gutter: 16px;
  }
  .sa-faq-sec .sa-fq-rail { position: static; }
  .sa-faq-sec .sa-fq-standfirst { max-width: 62ch; }
  .sa-faq-sec .sa-fq-foot { margin-top: 34px; }
}

/* Entry collapses to one column; the numeral demotes to a tracked eyebrow and
   the chip drops to its own line. DOM order is already the visual order. */
@media (max-width: 560px) {
  .sa-faq-sec .sa-fq {
    grid-template-columns: minmax(0, 1fr);
    padding: 18px 0 16px;
  }
  .sa-faq-sec .sa-fq-no,
  .sa-faq-sec .sa-fq-h,
  .sa-faq-sec .sa-fq-deck,
  .sa-faq-sec .sa-fq-panel { grid-column: 1; grid-row: auto; }
  .sa-faq-sec .sa-fq-no::before {
    font-size: 11.5px;
    font-weight: 700;
    letter-spacing: .14em;
    color: #5A6E86;
  }
  .sa-faq-sec .sa-fq-h { margin-top: 5px; }
  .sa-faq-sec .sa-fq-btn { flex-wrap: wrap; gap: 10px; }
  .sa-faq-sec .sa-fq-chip { order: 3; flex-basis: 100%; margin-top: 6px; }
  .sa-faq-sec .sa-fq-plus { order: 2; }
  .sa-faq-sec .sa-fq-facts > div { padding: 7px 12px; }
  .sa-faq-sec .sa-fq-foot-a { width: 100%; }
}

/* --- Reduced motion ------------------------------------------------------ */
/* The global rule at animations.css 141 already neutralises .sa-animate-on-scroll;
   this block covers what it does not - the panel slide, the gutter bar, the
   plus rotation, the numeral fade and the hover wash. Opening still works,
   instantly. */
@media (prefers-reduced-motion: reduce) {
  .sa-faq-sec [data-rv],
  .sa-faq-sec [data-rv]:not(.sa-visible) {
    opacity: 1;
    transform: none;
    transition: none;
  }
  .sa-faq-sec .sa-fq-panel { transition: visibility 0s linear .01s; }
  .sa-faq-sec .sa-fq[data-open="true"] .sa-fq-panel { transition: visibility 0s; }
  .sa-faq-sec .sa-fq::before,
  .sa-faq-sec .sa-fq::after,
  .sa-faq-sec .sa-fq-no::before,
  .sa-faq-sec .sa-fq-plus,
  .sa-faq-sec .sa-fq-plus::before,
  .sa-faq-sec .sa-fq-plus::after,
  .sa-faq-sec .sa-fq-mail { transition: none; }
}

/* =============================================================================
   DEMO VIDEO BELT
   =============================================================================
   Occupies the exact box the closing CTA belt used to: it reuses .sa-cta-belt so
   the 1200px cap, 16px radius, hairline border, brand top rule and drop shadow
   all still apply, then strips the padding and the two-column grid so the video
   can reach every edge.

   SIZE. aspect-ratio pins the box to 1200/504 - the proportion it already had -
   so it can never grow taller than the belt it replaced, at any width. Below
   900px that would leave a letterbox slot barely 200px tall, so the ratio opens
   to 16:9 there; the box is narrower by then, so it is still shorter in absolute
   terms than the desktop belt.

   FIT. data-fit="cover" (default) fills the box, cropping ~12% off the top and
   bottom of a 16:9 source. data-fit="contain" shows the whole frame on the belt
   ground instead. Only the <video> path covers: a cropped YouTube iframe would
   lose its own control bar, so the embed always fits inside the box.
   ========================================================================== */

.sa-vid-belt {
  display: block;
  padding: 0;
  overflow: hidden;
  aspect-ratio: 1200 / 504;
  /* the belt's own gradient shows through wherever the video does not reach */
  background:
    radial-gradient(700px 400px at 97% 2%, rgba(6, 214, 209, 0.10), transparent 60%),
    linear-gradient(118deg, #ffffff 0%, #fbfdff 48%, #f4fafe 100%);
}

/* The brand top rule sits above the video rather than under it. */
.sa-vid-belt::before { z-index: 2; }

/* --- Self-hosted video --------------------------------------------------- */
/* object-fit crops only the picture; the native control bar still renders
   across the element's full width, which is why filling the box is free here. */
/* ---- Drawn demo panel -------------------------------------------------------
   Fills the belt in place of a video. Replaced a 909KB GIF that had the previous
   brand, domain and check count baked into its pixels - drawn, it restyles with
   the site and the numbers come from AuditCheckCounts. Scales with cqw so one
   rule holds from 1200px down to a phone. */
.sa-vid-mock {
  container-type: inline-size;
  position: absolute; inset: 0;
  display: flex; flex-direction: column;
  background: var(--sa-surface, #fff);
}
.sa-vid-mock-bar {
  display: flex; align-items: center; gap: 8px;
  padding: 1.6cqw 2.8cqw;
  border-bottom: 1px solid var(--sa-border, #e6eaf0);
  background: var(--sa-surface-2, #f6f8fb);
}
.sa-vid-mock-bar i {
  width: 1cqw; height: 1cqw; min-width: 7px; min-height: 7px;
  border-radius: 50%; background: #d7dee8; flex: none;
}
.sa-vid-mock-bar i:first-child { background: #e8837c; }
.sa-vid-mock-bar i:nth-child(2) { background: #e8c07c; }
.sa-vid-mock-bar i:nth-child(3) { background: #8ccf9a; }
.sa-vid-mock-bar b {
  flex: 1; margin-left: 1.2cqw;
  font: 500 1.35cqw/1 var(--sa-brand-font, Inter, system-ui, sans-serif);
  color: #6b7f99; letter-spacing: .01em;
  background: #fff; border: 1px solid var(--sa-border, #e6eaf0);
  border-radius: 999px; padding: .7cqw 1.6cqw;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.sa-vid-mock-bar img { height: 2.2cqw; width: auto; flex: none; }
.sa-vid-mock-body {
  flex: 1; display: grid; grid-template-columns: 1fr 1.25fr;
  gap: 3cqw; padding: 2.2cqw 3.4cqw; align-content: start;
}
.sa-vid-mock-lead h3 {
  margin: 0; font: 700 3.2cqw/1.15 var(--sa-heading-font, Poppins, sans-serif);
  letter-spacing: -.02em; color: var(--sa-text-primary, #0B1F3B);
}
.sa-vid-mock-lead p {
  margin: .9cqw 0 0; font: 400 1.5cqw/1.5 var(--sa-brand-font, Inter, sans-serif);
  color: var(--sa-text-secondary, #536784);
}
.sa-vid-mock-count { display: flex; align-items: baseline; gap: 1.4cqw; margin-top: 2.4cqw; }
.sa-vid-mock-count strong {
  font: 700 5.2cqw/1 var(--sa-heading-font, Poppins, sans-serif);
  color: var(--mud-palette-primary, #2563FF); letter-spacing: -.03em;
  font-variant-numeric: tabular-nums;
}
.sa-vid-mock-count span {
  font: 400 1.5cqw/1 var(--sa-brand-font, Inter, sans-serif);
  color: var(--sa-text-secondary, #536784);
}
.sa-vid-mock-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: .5cqw; }
.sa-vid-mock-list li {
  display: flex; align-items: center; gap: 1.2cqw;
  padding: .75cqw 1.6cqw;
  border: 1px solid var(--sa-border, #e6eaf0); border-radius: .7cqw;
  background: var(--sa-surface-2, #f8fafc);
}
.sa-vid-mock-list svg { width: 1.7cqw; height: 1.7cqw; flex: none; }
.sa-vid-mock-list svg circle { fill: #2e9e63; }
.sa-vid-mock-list span {
  flex: 1; font: 500 1.45cqw/1 var(--sa-brand-font, Inter, sans-serif);
  color: var(--sa-text-primary, #0B1F3B);
}
.sa-vid-mock-list em {
  font: 500 1.2cqw/1 var(--sa-brand-font, Inter, sans-serif);
  font-style: normal; color: var(--sa-text-tertiary, #6b7f99); white-space: nowrap;
}
/* Phone: the two columns cannot both hold their type, so the list leads. */
@container (max-width: 640px) {
  .sa-vid-mock-body { grid-template-columns: 1fr; gap: 4cqw; padding: 5cqw; }
  .sa-vid-mock-lead h3 { font-size: 6cqw; }
  .sa-vid-mock-lead p, .sa-vid-mock-count span { font-size: 3.1cqw; }
  .sa-vid-mock-count strong { font-size: 10cqw; }
  .sa-vid-mock-bar b { font-size: 2.8cqw; }
  .sa-vid-mock-bar img { height: 4.4cqw; }
  .sa-vid-mock-list li { padding: 2.2cqw 3cqw; gap: 2.4cqw; }
  .sa-vid-mock-list span { font-size: 3cqw; }
  .sa-vid-mock-list em { font-size: 2.5cqw; }
  .sa-vid-mock-list svg { width: 3.4cqw; height: 3.4cqw; }
}

.sa-vid-el {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  background: #0b1a33;   /* letterbox ground while metadata loads */
}
.sa-vid-belt[data-fit="contain"] .sa-vid-el {
  object-fit: contain;
  background: transparent;
}

/* --- YouTube embed ------------------------------------------------------- */
/* Deliberately contained, not covered: cropping the iframe would cut off
   YouTube's own controls. Centred on the belt ground. */
/* position:absolute, not height:100%. As a grid whose single row was auto-sized,
   this box took its height FROM the iframe, so the iframe's own height:100%
   resolved against an indefinite height, fell back to its 16:9 ratio, and
   computed 1198x674 inside a 504px box. inset:0 gives the frame a definite
   height for the percentage to resolve against. */
.sa-vid-frame {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}
/* HEIGHT drives, width follows the ratio. Setting both width and height to 100%
   makes aspect-ratio inert - both dimensions become definite - and the iframe
   computed to 1198x674 inside a 504px box, so the belt's overflow:hidden cropped
   YouTube's control bar off. Constraining the height and letting width resolve
   from the ratio keeps the whole player inside the box, pillarboxed. */
.sa-vid-frame iframe {
  height: 100%;
  width: auto;
  max-width: 100%;
  aspect-ratio: 16 / 9;
  border: 0;
  display: block;
}

/* --- Poster -------------------------------------------------------------- */
.sa-vid-poster {
  position: relative;
  width: 100%;
  height: 100%;
  display: grid;
  place-items: center;
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
}
/* Scrim only when there is a poster image to darken; on the empty state the
   belt's own light ground should stay light. */
.sa-vid-poster[style]::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(6, 18, 40, .18), rgba(6, 18, 40, .42));
}

.sa-vid-play {
  position: relative;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  gap: 14px;
  padding: 14px 26px 14px 18px;
  border: 0;
  border-radius: 999px;
  background: #2563FF;
  color: #ffffff;
  font: inherit;
  font-size: 15px;
  font-weight: 700;
  cursor: pointer;
  box-shadow: 0 18px 40px -14px rgba(13, 53, 128, .70);
  transition: background .25s ease, transform .25s cubic-bezier(.16, 1, .3, 1),
              box-shadow .25s ease;
}
.sa-vid-play svg { width: 26px; height: 26px; flex: 0 0 auto; }
.sa-vid-play:hover {
  background: #1C4CC4;
  transform: translateY(-2px);
  box-shadow: 0 22px 46px -14px rgba(13, 53, 128, .78);
}
.sa-vid-play:focus-visible {
  outline: 2px solid #ffffff;
  outline-offset: 4px;
}

/* Empty state: no dead play triangle, just a plain note. */
.sa-vid-empty {
  position: relative;
  z-index: 1;
  margin: 0;
  max-width: 46ch;
  padding: 0 24px;
  text-align: center;
  font-size: 14.5px;
  line-height: 1.65;
  color: #5A6E86;
}
.sa-vid-empty span {
  display: block;
  margin-bottom: 6px;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .15em;
  text-transform: uppercase;
  color: #2563FF;
}
.sa-vid-empty code {
  padding: 1px 5px;
  border-radius: 4px;
  background: rgba(37, 99, 255, .08);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 12.5px;
  color: #1C4CC4;
}

/* --- Responsive ---------------------------------------------------------- */
/* 2.38:1 becomes an unwatchable slot on a phone; 16:9 there is still shorter in
   absolute pixels than the desktop belt. */
@media (max-width: 900px) {
  .sa-vid-belt { aspect-ratio: 16 / 9; }
}
@media (max-width: 560px) {
  .sa-vid-play { padding: 12px 20px 12px 14px; font-size: 14px; gap: 10px; }
  .sa-vid-play svg { width: 22px; height: 22px; }
  .sa-vid-empty { font-size: 13.5px; }
}

@media (prefers-reduced-motion: reduce) {
  .sa-vid-play, .sa-vid-play:hover { transform: none; transition: background .01s linear; }
}

/* =============================================================================
   HERO BANNER — FLAT, NO GRADIENT
   =============================================================================
   CEO call: the banner should not be a gradient.

   WHAT WAS THERE. Six .sa-hero background rules had accumulated in this file,
   all at specificity (0,1,0), so the winner was pure source order:
     - above 1024px, line 6328: two radial blooms over
       linear-gradient(147deg, #113e8f, #12469a 32%, #1651a7 58%, #1c67ab 82%,
       #207eaa 100%) — a five-stop navy-to-teal ramp
     - at/below 1024px, line 6350: the same idea truncated at #1651a7
   The ::before/::after blooms were already dead (content:none, line 9179).

   WHY #113e8f. It is the ramp's OWN 0% stop, so this is the existing banner's
   top-left corner extended across the whole box — no new blue enters the
   palette. It is also strictly safer than what it replaces: the copy column
   currently sits mid-ramp around #1651a7, so every ratio goes UP. The binding
   one is .sa-hero-note at 13.5px, which moves from ~4.97:1 to 6.34:1. White h1
   9.96:1, subtitle 8.04:1, badge text 9.42:1.

   The ramp's own documented purpose is obsolete anyway: the comment at line
   6146 says the light end "stays on the RIGHT, behind the product card", and
   that product card was deleted when the hero went single-column and centred
   (.sa-hero-visual appears zero times in Index.razor).

   NOT background-color. The shorthand is required: background-color alone
   leaves background-image intact and both radial blooms keep painting.

   The variable --sa-gradient-hero (line 149) is deliberately NOT touched —
   .sa-legal-hero at line 3864 still consumes it.
   ========================================================================== */

.sa-hero { background: #113e8f; }

/* Restated, not relied upon: the bloom pseudos are already off at line 9179.
   Kept here so flattening survives if that block is ever edited. */
.sa-hero::before,
.sa-hero::after,
.sa-hero-inner::after { content: none; }

/* Blurring a uniform colour returns that same colour, so these three are now
   no-ops that still force a compositing layer each — on the page whose whole
   pitch is site speed. The nav's own blur (line 217) is deliberately kept: it
   travels over the rest of the page, where it still does real work. */
.sa-hero-badge,
.sa-hero-check,
.sa-stats-inner {
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}

/* =============================================================================
   HERO — HARD BOTTOM EDGE, STATS CARD CENTRED ON IT
   =============================================================================
   Second half of the CEO's "no gradient on the banner" call: the long white
   fade at the foot of the hero was the last gradient on it. With the banner
   flat, the fade was the only thing still shading, so it went too. The banner
   now ends on a crisp horizontal line, and the stats card straddles that line.

   GEOMETRY. .sa-stats-bar's natural top sits exactly on the hero's bottom edge
   (verified: bar natural top - hero bottom = 0 at every width), and the card is
   the bar's only child with no top padding or margin. So a negative margin-top
   of exactly HALF the card's height puts the card's mid-line on the hero's
   edge - half in blue, half in white.

   The half-heights are measured, not guessed:
     1440px  card 226  -> 113      1200px  card 222 -> 111
     1024px  card 219  -> 110       640px  card 387 -> 194
      380px  card 691  -> 346
   Desktop is stable at 222-226, so -113px is centred to within a pixel across
   the whole range.

   Below 1024 the card stops being a horizontal row and stacks, growing to 691px
   at phone width. Centring THAT would bury 346px of it in blue and blow the
   hero out. So the small-screen rule keeps a fixed 110px overlap instead: exact
   centring at 1024 where the card is still 219 tall, easing to a straddle as it
   grows. It crosses the line at every width; it is only *centred* on it where
   the card is the wide bar the design is about.

   padding-bottom is re-cut to suit: it was 352px to make room for a 330px fade
   that no longer exists. 200px leaves an 87px gap between the hero copy and the
   card's top edge, matching the ~92px that was there before.
   ========================================================================== */

/* The fade element stays in the markup, switched off - a CEO decision is the
   kind that gets revisited, and this is one line to undo. */
.sa-hero-fade { display: none; }

.sa-hero { padding-bottom: 200px; }
.sa-stats-bar { margin-top: -113px; }

@media (max-width: 1024px) {
  .sa-hero { padding-bottom: 190px; }
  .sa-stats-bar { margin-top: -110px; }
}

/* =============================================================================
   FEATURES — static grid (append at the very end of premium.css, after line 9924)
   =============================================================================
   The rail is gone. Not hidden - gone: the arrows, the drag handler, the clone
   loop and window.initFeatureSlider are removed from the markup and the JS (see
   the notes with this change). All eight cards render at once, smaller.

   WHY EVERY LINE BELOW IS A BARE CLASS AND STILL WINS
   ---------------------------------------------------
   This file is append-only, so later beats earlier AT EQUAL SPECIFICITY. Before
   assuming that, each property was traced to its live winner:

     .sa-fs-rail        highest-specificity selector in the file is
                        `.sa-fs-rail.is-dragging` (0,2,0) - a class the deleted
                        JS added, so nothing beats a plain `.sa-fs-rail` now.
     .sa-fs-card        every declaration is (0,1,0): :5350 :5478 :5736 :6088
                        :6300 :6396 :6423 :7129 :8407. Order decides. We are last.
     .sa-fs-card h3/p   (0,1,1), winners at :8444 / :8365 and the shared
                        `.sa-step h3, .sa-fs-card h3, ...` at :8132. Order decides.
     .sa-fs-card:hover  NOT touched here. The live winner is
                        `.sa-fs-rail .sa-fs-card:hover` at :7139 (0,3,0), which
                        outranks every plain :hover regardless of order. The rail
                        DIV stays in the markup (it is the grid container), so
                        that selector still matches and the lift/scale is
                        preserved untouched. Re-anchoring it was unnecessary -
                        deleting the div would have been the mistake.

   The 1.055 hover scale is safe in the grid: a 285px card grows 15.7px, 7.8px
   per side, against a 20px gap. It cannot touch its neighbour.
   ============================================================================= */

/* --- Section ---------------------------------------------------------------
   `.sa-fs { overflow: hidden }` (:5281) existed only to clip the 100vw bleed at
   :6371. With the bleed gone the clip is what would crop the hover shadow at the
   section edge, so it is released. */
.sa-fs { overflow: visible; }

/* --- Header ----------------------------------------------------------------
   Was a two-column flex whose second child was the arrow nav. One child left. */
.sa-fs-head { display: block; margin-bottom: 30px; }
.sa-fs-nav  { display: none; }        /* belt + braces if the markup ships un-stripped */
.sa-fs-sub  { max-width: 560px; }

/* --- The grid --------------------------------------------------------------
   Each group below undoes one rail rule: the scroller (:5333-:5344, :5708), the
   full-bleed (:6371-:6381), and the growth padding (:7149, :5825). */
.sa-fs-rail {
  display: grid;                       /* was flex, :5334 - the only display decl */
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 20px;                           /* was 20px, :5335 */
  align-items: stretch;                /* explicit: this is what equalises rows */

  /* stop being a scroll container */
  overflow: visible;                   /* was overflow-x:auto / overflow-y:hidden */
  cursor: auto;                        /* :5708 put `grab` on the whole section */
  scroll-snap-type: none;
  scroll-padding-left: 0;

  /* stop being full-bleed */
  width: auto;                         /* was 100vw */
  max-width: none;
  margin: 0;                           /* was calc(50% - 50vw) left/right */
  padding: 0;                          /* was 22px vert + max(24px, 50vw-600px) horiz */
}

/* minmax(0,1fr) above, and min-width:0 here, are both load-bearing:
   `.sa-fs-mini-list li` is white-space:nowrap, and a bare 1fr track (or a grid
   item's default min-width:auto) floors at min-content and blows the row out. */
.sa-fs-card { min-width: 0; }

/* The card's OWN column layout - not slider machinery. `.sa-fs-shot`'s
   `margin-top:auto` (:5485) is what pins the mock to the card's bottom edge, and
   it needs these two. Re-asserted because they sit next to the flex-basis at
   :5356-5357 and read like leftovers. */
.sa-fs-card { display: flex; flex-direction: column; }

/* initFeatureSlider appended eight aria-hidden clones to the rail. If a browser
   is still running a cached copy of scrollReveal.js this keeps the grid at 8
   instead of 16. Same specificity as :7075, later, so it wins. */
.sa-fs-card[data-clone] { display: none; }

/* --- Card box, smaller ----------------------------------------------------- */
.sa-fs-card {
  padding: 20px 18px 18px;             /* was 26px 24px 24px, :5740 */
  border-radius: 16px;                 /* was 24px, :8408 */
}

/* --- Card type, smaller ---------------------------------------------------- */
.sa-fs-eyebrow { font-size: 10.5px; letter-spacing: 0.12em; }   /* was 11.5px/.14em, :8440 */

.sa-fs-ico {
  width: 34px; height: 34px;           /* was 42px, :5768 */
  margin: 15px 0 0;
  margin-top: 12px;
  border-radius: 12px;                 /* was 12px, :8455 */
}
.sa-fs-ico .mud-icon-root { font-size: 17px; }                  /* was 21px, :5410 */

.sa-fs-card h3 {
  font-size: 1.06rem;                  /* was 1.36rem, :8444 */
  line-height: 1.25;
  margin: 10px 0 6px;                  /* was 14px 0 9px, :8449 */
}
.sa-fs-card p {
  font-size: 13px;                     /* was 15.2px, :8365 */
  line-height: 1.55;
  margin: 0 0 14px;
  min-height: 4.65em;                  /* exactly 3 lines - keeps the block uniform */
}

/* =============================================================================
   THE MOCK PANEL — one fixed band, 154px, at every breakpoint
   =============================================================================
   The shot had no height: it ran 128px to 185px depending on which mock was in
   it, so eight bottom-pinned panels showed eight different top edges. Now it is
   a fixed band, and because `margin-top:auto` already flushes it to the card's
   bottom, tops AND bottoms align across the row.

   154px is measured, not chosen: with the sizes below the two tallest mocks land
   at 150.6px (card 2: schema + three rows) and 150.3px (card 5: quote + two
   rows). box-sizing:border-box is global (MudBlazor's `*` reset), so min-height
   includes padding.
   ========================================================================== */
.sa-fs-shot {
  display: flex;
  flex-direction: column;
  min-height: 154px;
  border-radius: 12px;                 /* was 14px, :8465 */
}
.sa-fs-shot-bar {
  flex: 0 0 auto;
  gap: 3px;
  padding: 5px 8px;                    /* was 7px 10px */
  border-radius: 12px 12px 0 0;        /* was 14px 14px 0 0, :8480 */
}
.sa-fs-shot-bar i { width: 5px; height: 5px; }
.sa-fs-shot-bar b { margin-left: 5px; font-size: 10px; line-height: 1.2; }

.sa-fs-shot-body { flex: 1 1 auto; padding: 9px; }              /* was 11px */

/* The slack in a short mock is centred rather than left hanging at the bottom.
   The :not() is required: `.sa-fs-shot-ready` IS this element on cards 1 and 4
   and is a flex ROW (:5516) - column here would stack the gauge onto its list. */
.sa-fs-shot-body:not(.sa-fs-shot-ready) {
  display: flex;
  flex-direction: column;
  justify-content: center;
}
/* Stops `.sa-fs-mini-list { flex: 1 }` (:5541) growing in the new column and
   stretching its rows. (0,2,0) beats it outright; the :not() leaves the
   horizontal cards' flex:1 alone, where it is genuinely needed. */
.sa-fs-shot-body:not(.sa-fs-shot-ready) > * { flex: 0 0 auto; }
.sa-fs-shot-body.sa-fs-shot-ready { gap: 10px; }                /* was 12px */

/* --- Mock internals -------------------------------------------------------- */
.sa-fs-gauge, .sa-fs-gauge svg { width: 46px; height: 46px; }   /* was 58px */
/* viewBox stays 0 0 64 64, so dasharray 163 / dashoffset 30 remain correct.
   Stroke goes up in viewBox units to hold its weight at the smaller render
   size; r26 + 4 = 30 < 32, so nothing clips. */
.sa-fs-gauge-bg, .sa-fs-gauge-arc { stroke-width: 8; }
.sa-fs-gauge-val { font-size: 15px; }                           /* was 19px */

.sa-fs-mini-list { gap: 3px; }
.sa-fs-mini-list li {
  gap: 5px;
  padding: 3px 6px;
  border-radius: 4px;
  font-size: 11px;                     /* was 12.5px, :8369 */
  line-height: 1.2;                    /* pinned: the 154px band is derived from it */
}
.sa-fs-mini-list li b { font-size: 10px; }
.sa-fs-urls li, .sa-fs-projects li { font-size: 10.2px; }       /* widest rows */

/* Small print: #6b7280 measures 4.57:1 on the mock's #f5f9fd - it passes, with
   almost no margin, at 10px. #5b6675 is 5.5:1. */
.sa-fs-mini-list li b,
.sa-fs-shot-bar b,
.sa-fs-scores span,
.sa-fs-crawlhead b { color: #5b6675; }

.sa-fs-tick { width: 9.5px; height: 9.5px; }                    /* was 11px */
/* The check is absolutely positioned in px, so it has to be re-derived, not
   left behind. x0.909 on every value. Width-only so the shorthand's colour at
   :5563 and the `.sa-warn` override at :5576 both survive. */
.sa-fs-tick::after {
  left: 2.6px; top: 2.9px;
  width: 3.8px; height: 1.9px;
  border-left-width: 1.3px;
  border-bottom-width: 1.3px;
}
.sa-fs-dot { width: 6px; height: 6px; }

/* Three chips on a two-column grid = ALWAYS two rows. As a wrapping flex row it
   was one row at 2-col and two at 4-col: a 20px swing driven by breakpoint,
   which is exactly what a fixed band cannot have. */
.sa-fs-schema {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 4px;
  margin-bottom: 6px;
}
.sa-fs-schema span {
  padding: 3px 6px;
  font-size: 10px;
  line-height: 1.2;
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.sa-fs-crawlhead { font-size: 10px; line-height: 1.2; margin-bottom: 5px; }
.sa-fs-shot-body > .sa-fs-crawlhead:last-child { margin-bottom: 0; }  /* card 8 */
.sa-fs-track { height: 3.5px; margin-bottom: 7px; }

.sa-fs-bars { gap: 4px; }
.sa-fs-bars span { font-size: 10px; line-height: 1.2; }
.sa-fs-bars i { height: 3.5px; margin-bottom: 2px; }

/* A floor and a ceiling, so the summary is a 3-line block at every width. The
   copy needs 3 lines at the narrowest card, so nothing truncates in practice;
   the clamp is insurance against a font fallback, and the block is inside
   aria-hidden="true" so no content is lost to assistive tech either way. */
.sa-fs-quote {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
          line-clamp: 3;
  overflow: hidden;
  min-height: calc(3 * 1.45em + 14px);
  margin-bottom: 6px;
  padding: 7px 8px;
  border-radius: 0 5px 5px 0;
  font-size: 11px;                     /* was 12.5px */
  line-height: 1.45;
}

.sa-fs-filerow { gap: 4px; }
.sa-fs-filerow-lg { margin-bottom: 6px; }
.sa-fs-file { padding: 2.5px 6px; border-radius: 4px; font-size: 10px; line-height: 1.2; }

.sa-fs-link { gap: 4px; margin-bottom: 6px; padding: 4px 7px; border-radius: 4px; font-size: 9.8px; line-height: 1.2; }
.sa-fs-lock { width: 6px; height: 7px; }

.sa-fs-scores { gap: 4px; margin-bottom: 6px; }
.sa-fs-scores span { padding: 5px 2px; border-radius: 8px; font-size: 9.8px; line-height: 1.2; }
.sa-fs-scores b { font-size: 14px; line-height: 1.2; }

.sa-fs-av { width: 13px; height: 13px; border-radius: 3px; font-size: 9px; }

/* =============================================================================
   BREAKPOINTS — 4 / 3 / 2 / 1
   =============================================================================
   Section padding is 24px at every width (:6818 wins), so the inner box is
   always min(1200px, 100vw - 48px).

   Every capped tier is margin-left:0, NOT margin:auto. `.sa-fs-head` is
   left-aligned, so a centred grid under a left-aligned H2 reads as a mistake.
   ========================================================================== */

/* --- 820-1059: three columns, on six tracks ---------------------------------
   Eight cards over three columns leaves a hole in the last row. Laying the grid
   on six tracks and spanning two lets the final pair be centred at the SAME
   width as the other six. This is coupled to there being exactly eight cards -
   the heading says "What you get (8)", so the count is already load-bearing in
   the markup. Add a ninth card and delete the two nth-child rules.

   The 940px cap is what stops 3-up being LARGER than 4-up: uncapped at 1059 the
   cards would be 359px, wider than the 328px we are replacing. */
@media (min-width: 820px) and (max-width: 1059px) {
  .sa-fs-rail {
    grid-template-columns: repeat(6, minmax(0, 1fr));
    gap: 16px;
    max-width: 940px;
    margin-inline: auto;
  }
  .sa-fs-card { grid-column: span 2; }
  .sa-fs-card:nth-child(7) { grid-column: 2 / span 2; }
  .sa-fs-card:nth-child(8) { grid-column: 4 / span 2; }
  .sa-fs-card { padding: 18px 16px 16px; }
}

/* --- 620-859: two columns, four clean rows, no orphan --------------------- */
@media (min-width: 620px) and (max-width: 819px) {
  .sa-fs-rail {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 14px;
    max-width: 700px;
    margin-inline: auto;
  }
  /* explicit: the six-track placement above must not leak into this tier */
  .sa-fs-card { grid-column: auto; }
}

/* --- under 620: one column ------------------------------------------------
   Two columns below this leaves ~160px cards, at which the mock's longest row
   ("loanquantum.com  81") starts clipping. One column instead. */
@media (max-width: 619px) {
  .sa-fs-rail {
    grid-template-columns: minmax(0, 1fr);
    gap: 14px;
    max-width: 420px;
    margin-inline: auto;
  }
  /* explicit: the six-track placement above must not leak into this tier */
  .sa-fs-card { grid-column: auto; }
  .sa-fs-head { margin-bottom: 24px; }
}

/* --- 4-col, narrow end of the tier --------------------------------------- */
@media (min-width: 1060px) and (max-width: 1247px) {
  .sa-fs-rail { gap: 16px; }
  .sa-fs-card { padding: 16px 14px 14px; }
}

/* --- Motion ----------------------------------------------------------------
   Fixes a live bug on the way past: `.sa-fs-card`'s transition at :7129 is TOP
   LEVEL and lands after the reduced-motion block at :5462, so the card has been
   ignoring prefers-reduced-motion for transitions. This block is later than
   both. The `.sa-fs-rail .sa-fs-card:hover` form is kept alongside the plain one
   because :7139 (0,3,0) is the live winner and only an equally specific
   selector can cancel its transform. */
@media (prefers-reduced-motion: reduce) {
  .sa-fs-card, .sa-fs-ico, .sa-fs-shot { transition: none; }
  .sa-fs-rail .sa-fs-card:hover,
  .sa-fs-card:hover { transform: none; }
  .sa-fs-card:hover .sa-fs-ico,
  .sa-fs-card:hover .sa-fs-shot { transform: none; }
}
@media (hover: none) {
  .sa-fs-rail .sa-fs-card:hover,
  .sa-fs-card:hover { transform: none; }
}

/* =============================================================================
   LANDING — MOBILE PASS
   =============================================================================
   Found by walking the page at 320 / 375px. Each fix names the rule it corrects;
   every selector below is at least as specific as the one it beats, and sits
   later, so order decides. */

/* --- Hero field ---------------------------------------------------------------
   The <=560px rule at :6709 wraps the button under the input, but the top-level
   restyle at :7307 lands later and resets it to `padding: 0 24px; margin: 6px`.
   Result: a 21px-tall button, and `flex: 1 0 100%` plus 12px of margin could not
   shrink, so it ran 5px past the field's right edge. */
@media (max-width: 560px) {
  .sa-hero-check-prefix { padding-left: 16px; }
  .sa-hero-check-input { padding: 16px 12px 14px 2px; }
  .sa-hero-check-btn {
    flex: 1 1 100%;
    margin: 0 6px 6px;
    padding: 14px 20px;
    justify-content: center;
  }
}

/* --- Mobile menu CTAs -----------------------------------------------------------
   `.sa-mobile-menu a` (0,1,1) at :279 outranks `.sa-btn-primary` (0,1,0), so
   Sign In and Free Trial rendered as plain grey text. */
.sa-mobile-menu a.sa-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 13px 16px;
  font-weight: 600;
  text-align: center;
}
.sa-mobile-menu a.sa-btn-primary { background: var(--sa-primary); color: #fff; }
.sa-mobile-menu a.sa-btn-primary:hover { background: var(--sa-primary); opacity: .9; }
.sa-mobile-menu a.sa-btn-outline-brand {
  background: transparent;
  color: var(--sa-primary);
  border: 1px solid var(--sa-border);
}
.sa-mobile-menu a.sa-btn-outline-brand:hover {
  background: rgba(37, 99, 235, 0.06);
  border-color: var(--sa-primary);
}

/* --- Stats card: 2x2 on phones --------------------------------------------------
   One column (:5299) made four figures a ~690px card - a full screen of scrolling
   straight after the hero. Two columns halves that and still fits "<1min" and
   "250+" at 320px. */
@media (max-width: 520px) {
  .sa-stats-inner { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .sa-stat { padding: 18px 8px 16px; }
  .sa-stat-ico { width: 34px; height: 34px; margin-bottom: 10px; }
  .sa-stat-label { font-size: 13px; }
}

/* --- Checks section footnote ----------------------------------------------------
   Centred as a flex item, but once it wraps the lines fell back to left-aligned
   under a centred button. */
.sa-ck-foot-note { text-align: center; }

/* --- How it works: a left rail when stacked -------------------------------------
   The stacked connector at :8066 runs down the centre of the column - straight
   through each step's paragraph and chip. Markers move to a left rail instead,
   text beside them, and the connector joins marker to marker in the gutter. */
@media (max-width: 780px) {
  .sa-steps { gap: 28px; text-align: left; }
  .sa-step {
    display: grid;
    grid-template-columns: 54px minmax(0, 1fr);
    column-gap: 18px;
    align-items: start;
  }
  .sa-step-num { grid-row: 1 / span 3; margin: 0; }
  .sa-step h3,
  .sa-step p,
  .sa-step-detail { grid-column: 2; }
  .sa-step h3 { margin-top: 14px; }   /* title centred on the 54px marker */
  .sa-step p { margin: 0 0 12px; max-width: none; }
  .sa-step-detail { justify-self: start; }
  .sa-step:not(:last-child)::after { left: 27px; top: 54px; bottom: -28px; }
}

/* --- Use cases --------------------------------------------------------------------
   minmax(300px, 1fr) at :1611 cannot go below 300px, so under ~350px the cards
   ran off-screen (html/body overflow-x: clip hid the scrollbar, not the cut). */
.sa-usecases-grid { grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr)); }
@media (max-width: 560px) {
  .sa-usecase-card { padding: 24px; }
}

/* --- Demo belt: never crop an image on a phone -----------------------------------
   Below 900px :9857 turns the belt 16:9 and the media is object-fit: cover. For a
   video that trades a little top/bottom; for the 1200x504 GIF it cut ~25% off
   BOTH sides, so the mock UI read as clipped text. An image keeps its own
   proportion instead - the belt just wraps it. */
@media (max-width: 900px) {
  .sa-vid-belt:has(> img.sa-vid-el) { aspect-ratio: auto; }
  /* Same reason as the image above. The drawn panel stacks to one column here, so
     a fixed 16/9 belt clips the check list (383px of content in a 182px box at
     375w). Let the belt take the panel's height, and let the panel flow rather
     than sit absolutely inside it. */
  .sa-vid-belt:has(> .sa-vid-mock) { aspect-ratio: auto; }
  .sa-vid-belt > .sa-vid-mock { position: static; }
  .sa-vid-belt img.sa-vid-el { height: auto; }
}

/* --- FAQ plan chip ---------------------------------------------------------------
   At <=560px :9665 drops the chip to its own line with flex-basis: 100%, which also
   stretches the pill across the whole column. A two-track grid puts it on its own
   line at its own width, with the +/- still beside the question. */
@media (max-width: 560px) {
  .sa-faq-sec .sa-fq-btn {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    column-gap: 12px;
    row-gap: 8px;
  }
  .sa-faq-sec .sa-fq-q { grid-column: 1; grid-row: 1; }
  .sa-faq-sec .sa-fq-plus { grid-column: 2; grid-row: 1; }
  .sa-faq-sec .sa-fq-chip { grid-column: 1; grid-row: 2; justify-self: start; margin-top: 0; }
}

/* =============================================================================
   HERO — static "Audits", rotating tail
   =============================================================================
   Replaces the whole-phrase rotation at :8116. "Audits" is identical in all four
   phrases, so it sits still and only the tail ("in Minutes", "at Scale", ...)
   cycles, stacked in one grid cell.

   The cell's WIDTH is the design decision. Sized to the longest tail, shorter
   ones leave a gap and the line drifts up to ~3.6em left of centre; sized to fit
   each phrase, "Audits" would slide sideways every swap. So it is the midpoint
   of the shortest and longest tail, and longer tails simply overflow it to the
   right (overflow stays visible). Measured at the line's own font size, so they
   hold at every breakpoint:
     at Scale 3.66em   in Minutes 4.86em   in Plain English 6.93em
     You Can Act On 7.26em                 -> (3.66 + 7.26) / 2 = 5.46em
   Worst case the line is 1.8em off centre, and "Audits" never moves.
   If a tail is added or reworded, re-measure and move the midpoint. */
.sa-hero-line-2 {
  display: flex;
  justify-content: center;
  align-items: baseline;
}
/* `pre` keeps the trailing space: in a flex row the gap between items is not
   rendered, and this space is also the word break in the h1's accessible name. */
.sa-hero-static { white-space: pre; }
/* NOT `.sa-hero-rot`: that name belongs to a retired rotator (:6973) whose rules
   are still in this file and would absolutely-position and re-animate the tails. */
.sa-hero-tails {
  display: grid;
  width: 5.46em;
  justify-items: start;
}
.sa-hero-tails > .sa-hero-word {
  grid-area: 1 / 1;
  white-space: nowrap;
}

/* =============================================================================
   LEGAL PAGES (Privacy / Terms) — landing theme
   =============================================================================
   Brings the block at :3898 in line with the landing, About and Contact pages:
   - hero: the landing's flat #113e8f, centred, with the same badge as the
     About/Contact heroes. It was the navy -> cyan --sa-gradient-hero ramp the
     landing dropped, left-aligned, with an uppercase tracked badge no other
     public page uses;
   - body: white ground, not the #f6f9ff blue-grey, with hairline-bordered cards
     and no drop shadow - the landing's card language;
   - type: the landing's heading ink (#0d1b3d), body ink (#3A536E) and muted
     ink (#5b6b83); section numbers use the gradient marker from How It Works.
   Same specificity as the rules it replaces, later in the file. */
.sa-legal-hero {
  background: #113e8f;
  padding: 140px 24px 64px;
  text-align: center;
}
.sa-legal-hero-inner { max-width: 680px; }
.sa-legal-badge {
  gap: 6px;
  margin-bottom: 20px;
  padding: 6px 16px;
  border-color: rgba(255, 255, 255, 0.2);
  border-radius: 20px;
  background: rgba(255, 255, 255, 0.12);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: normal;
  text-transform: none;
  color: rgba(255, 255, 255, 0.9);
}
.sa-legal-badge svg { width: 14px; height: 14px; }
.sa-legal-hero h1 {
  margin: 0 0 12px;
  font-size: 2.5rem;
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1.15;
}
.sa-legal-hero-sub {
  max-width: 560px;
  margin: 0 auto 18px;
  font-size: 1.1rem;
  line-height: 1.6;
}
.sa-legal-updated { color: rgba(255, 255, 255, 0.72); }

.sa-legal-body {
  background: #ffffff;
  padding: 64px 24px 96px;
}

.sa-legal-toc,
.sa-legal-content {
  border: 1px solid rgba(13, 53, 128, 0.10);
  border-radius: 16px;
  box-shadow: none;
}
.sa-legal-toc-title { color: #5A6E86; }
.sa-legal-toc a { color: #5b6b83; }
.sa-legal-toc a:hover { color: #2563FF; background: rgba(37, 99, 255, 0.06); }

.sa-legal-section + .sa-legal-section { border-top-color: rgba(13, 53, 128, 0.08); }
.sa-legal-section h2 {
  gap: 14px;
  font-size: 1.15rem;
  letter-spacing: -0.012em;
  color: #0d1b3d;
}
.sa-legal-num {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: linear-gradient(140deg, #2563FF, #0e7fa8);
  box-shadow: 0 8px 18px -10px rgba(37, 99, 255, 0.6);
  color: #ffffff;
  font-size: 13px;
  font-variant-numeric: tabular-nums;
}
.sa-legal-section p {
  padding-left: 44px;   /* aligned with the heading text, past the 30px marker */
  font-size: 15px;
  line-height: 1.75;
  color: #3A536E;
}

.sa-legal-section a { color: #2563FF; }

.sa-legal-cta {
  border: 1px solid rgba(37, 99, 255, 0.14);
  border-radius: 16px;
  background: #f4f8fe;
}
.sa-legal-cta-text strong { color: #0d1b3d; }
.sa-legal-cta-text span { color: #5b6b83; }

@media (max-width: 900px) {
  .sa-legal-body { padding: 40px 16px 64px; }
}
@media (max-width: 640px) {
  .sa-legal-hero { padding: 110px 16px 48px; }
  .sa-legal-hero h1 { font-size: 1.75rem; }
  .sa-legal-hero-sub { font-size: 0.95rem; }
  .sa-legal-section p { padding-left: 0; }   /* no room to indent on a phone */
}

/* --- "On this page" rail (Components/Public/LegalToc.razor) ------------------
   Numbered markers only - deliberately no connecting rule between them. The
   section being read is filled with the landing's step gradient, the ones
   already passed are tinted, and a reading-progress bar sits under the heading.
   State comes from scrollHelper.js as data-state="done|active|next" on each
   link and --p (0..1) on the rail; the base look is the "next" state, so the
   rail reads correctly before the script has run. */
.sa-legal-toc { padding: 20px 14px 14px; --p: 0; }
.sa-legal-toc-toggle { display: none; }   /* phones and tablets only, below */

.sa-legal-toc-head { padding: 0 8px 14px; }
.sa-legal-toc-title {
  display: block;
  margin: 0 0 10px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: #5A6E86;
}
.sa-legal-toc-bar {
  display: block;
  height: 3px;
  overflow: hidden;
  border-radius: 999px;
  background: rgba(13, 53, 128, 0.08);
}
.sa-legal-toc-bar i {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: inherit;
  background: linear-gradient(90deg, #2563FF, #06D6D1);
  transform: scaleX(var(--p));
  transform-origin: left;
  transition: transform .15s linear;
}

.sa-legal-toc-list { margin: 0; padding: 0; list-style: none; }
.sa-legal-toc-list a {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 8px 10px;
  border-radius: 12px;
  font-size: 13.5px;
  font-weight: 500;
  line-height: 1.45;
  color: #5b6b83;
  text-decoration: none;
  transition: background .18s ease, color .18s ease;
}
.sa-legal-toc-num {
  display: grid;
  flex: 0 0 22px;
  place-items: center;
  height: 22px;
  border-radius: 50%;
  background: #ffffff;
  box-shadow: inset 0 0 0 1.5px rgba(13, 53, 128, 0.16);
  font-size: 11px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: #5A6E86;
  transition: background .25s ease, box-shadow .25s ease, color .25s ease;
}
.sa-legal-toc-text { padding-top: 1px; }

.sa-legal-toc-list a:hover { background: rgba(37, 99, 255, 0.05); color: #2563FF; }
.sa-legal-toc-list a:hover .sa-legal-toc-num { box-shadow: inset 0 0 0 1.5px rgba(37, 99, 255, 0.4); color: #2563FF; }
.sa-legal-toc-list a:focus-visible { outline: 2px solid #2563FF; outline-offset: 2px; }

/* Passed: tinted marker. */
.sa-legal-toc-list a[data-state="done"] { color: #3A536E; }
.sa-legal-toc-list a[data-state="done"] .sa-legal-toc-num {
  background: rgba(37, 99, 255, 0.10);
  box-shadow: none;
  color: #2563FF;
}

/* Being read: filled marker, the landing's step gradient. */
.sa-legal-toc-list a[data-state="active"] {
  background: rgba(37, 99, 255, 0.07);
  color: #0d1b3d;
  font-weight: 600;
}
.sa-legal-toc-list a[data-state="active"] .sa-legal-toc-num {
  background: linear-gradient(140deg, #2563FF, #0e7fa8);
  box-shadow: 0 6px 14px -8px rgba(37, 99, 255, 0.8);
  color: #ffffff;
}

.sa-legal-toc-top {
  display: flex;
  align-items: center;
  justify-content: flex-start;   /* a global button rule centres by default */
  gap: 8px;
  width: calc(100% - 16px);
  margin: 10px 8px 0;
  padding: 12px 2px 2px;
  border: 0;
  border-top: 1px solid rgba(13, 53, 128, 0.08);
  background: none;
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  color: #2563FF;
  cursor: pointer;
}
.sa-legal-toc-top svg { width: 14px; height: 14px; transition: transform .2s ease; }
.sa-legal-toc-top:hover { color: #1C4CC4; }
.sa-legal-toc-top:hover svg { transform: translateY(-2px); }
.sa-legal-toc-top:focus-visible { outline: 2px solid #2563FF; outline-offset: 3px; border-radius: 4px; }

/* Phones and tablets: :4077 hid the rail entirely, leaving no way to jump
   between sections. It comes back as a collapsible card above the text. */
@media (max-width: 900px) {
  .sa-legal-inner { gap: 16px; }
  .sa-legal-toc { display: block; position: static; padding: 0; }
  .sa-legal-toc-head,
  .sa-legal-toc-top { display: none; }
  .sa-legal-toc-toggle {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    padding: 14px 16px;
    border: 0;
    background: none;
    font: inherit;
    font-size: 14px;
    font-weight: 700;
    color: #0d1b3d;
    text-align: left;
    cursor: pointer;
  }
  .sa-legal-toc-toggle em {
    margin-left: 6px;
    font-style: normal;
    font-size: 12.5px;
    font-weight: 500;
    color: #5b6b83;
  }
  .sa-legal-toc-toggle svg { width: 18px; height: 18px; color: #5A6E86; transition: transform .2s ease; }
  .sa-legal-toc[data-open="true"] .sa-legal-toc-toggle svg { transform: rotate(180deg); }
  .sa-legal-toc-toggle:focus-visible { outline: 2px solid #2563FF; outline-offset: -2px; border-radius: 16px; }
  .sa-legal-toc nav { padding: 0 8px 10px; }
  .sa-legal-toc[data-open="false"] nav { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .sa-legal-toc-bar i,
  .sa-legal-toc-list a,
  .sa-legal-toc-num,
  .sa-legal-toc-top svg,
  .sa-legal-toc-toggle svg { transition: none; }
}

/* =============================================================================
   BRAND SCOPE — MudBlazor components in the landing's palette
   =============================================================================
   The app-wide MudTheme (AppTheme.cs) is deliberately left at MudBlazor's
   defaults so the signed-in app's component colours do not shift: primary is
   purple #594AE2, secondary pink #FF4081, type Roboto. Public pages built from
   MudBlazor components (the Contact form) inherited that, so they read as a
   different product next to the landing page.

   MudBlazor's classes resolve colour and type through these custom properties,
   so redefining them on a wrapper re-themes everything inside it, and nothing
   outside. */
.sa-brand-scope {
  --mud-palette-primary: #2563FF;
  --mud-palette-primary-rgb: 37, 99, 255;
  --mud-palette-primary-text: #ffffff;
  --mud-palette-primary-darken: #1C4CC4;
  --mud-palette-primary-lighten: #4380FF;
  --mud-palette-primary-hover: rgba(37, 99, 255, 0.06);
  --sa-brand-font: 'Inter', system-ui, -apple-system, sans-serif;
  /* Brand spec: Poppins for headings, Inter for product UI/body. */
  --sa-heading-font: 'Poppins', 'Inter', system-ui, -apple-system, sans-serif;
  --mud-typography-default-family: var(--sa-brand-font);
  --mud-typography-h1-family: var(--sa-heading-font);
  --mud-typography-h2-family: var(--sa-heading-font);
  --mud-typography-h3-family: var(--sa-heading-font);
  --mud-typography-h4-family: var(--sa-heading-font);
  --mud-typography-h5-family: var(--sa-heading-font);
  --mud-typography-h6-family: var(--sa-heading-font);
  --mud-typography-subtitle1-family: var(--sa-brand-font);   /* text-field input */
  --mud-typography-subtitle2-family: var(--sa-brand-font);
  --mud-typography-body1-family: var(--sa-brand-font);
  --mud-typography-body2-family: var(--sa-brand-font);
  --mud-typography-button-family: var(--sa-brand-font);
  --mud-typography-caption-family: var(--sa-brand-font);    /* helper / error text */
  --mud-typography-overline-family: var(--sa-brand-font);
}

/* =============================================================================
   BOOK-A-DEMO DIALOG — above the nav and footer, and sized for phones
   =============================================================================
   The dialog is rendered inside <main>, and #sa-main-content is `isolation:
   isolate` (:6309) so the page wash stays under its sections. That makes <main>
   a stacking context at z-index auto: the backdrop's 1400 only counted INSIDE it.
   The fixed nav (1100) painted over the dialog's top - title and close button
   hidden - and the footer, a positioned sibling after <main>, painted over its
   bottom, taking the submit button with it.

   While the dialog is open, <main> itself is lifted above both. Two rules, not
   one selector list: a browser without :has() would drop the whole list, and
   the body class (set by BookDemo.razor) is the path every browser supports. */
body.sa-modal-open #sa-main-content { z-index: 1400; }
#sa-main-content:has(> .sa-modal-backdrop) { z-index: 1400; }

/* 100vh on a phone includes the area under the browser's toolbar, so the card
   could end below the visible screen. dvh is the visible height; vh stays as the
   fallback for browsers without it. */
.sa-modal { max-height: calc(100dvh - 40px); }

@media (max-width: 520px) {
  /* Wider card: 20px + 20px padding left 295px at 375 for a 300px Turnstile
     widget, and its wrapper clips overflow. */
  .sa-modal-backdrop { padding: 12px; }
  .sa-modal { max-height: calc(100vh - 24px); max-height: calc(100dvh - 24px); padding: 24px 18px 20px; }
  .sa-modal-title { padding-right: 36px; }   /* clear of the close button */
  /* Under 16px, iOS Safari zooms the page when a field takes focus. */
  .sa-bd-field input,
  .sa-bd-field textarea { font-size: 16px; }
  /* Below 360px turnstile.js renders the compact widget (150x140), which the
     90px reveal cap at :4478 would cut in half. */
  .sa-bd-turnstile.is-armed { max-height: 150px; }
}
/* ============================================================================
   LIGHT HERO
   ----------------------------------------------------------------------------
   The hero was white-on-dark-navy. This flips it to the same language as the
   book-a-demo band (.sa-bd-band, above): a pale cyan ground, navy type, a cyan
   hairline and a barely-there shadow - which is the treatment that reads as
   current rather than 2019-SaaS.

   Written as one override block rather than edited into the ~147 .sa-hero rules
   above, for the same reason the band's own light treatment is an override of
   its dark original: the earlier rules carry the reasoning for how they were
   tuned, and losing that to make a colour change is a bad trade. Delete this
   block and the dark hero returns intact.

   Contrast, measured on #E4F8FB: navy #0A1B33 ~15:1, muted #4A5F7A ~6.4:1,
   white on the #2563FF button ~5.8:1. All clear AA for their sizes.
   ========================================================================== */
.sa-hero {
  background:
    radial-gradient(1100px 560px at 82% 6%, rgba(6, 214, 209, 0.20), transparent 60%),
    radial-gradient(900px 520px at 8% 88%, rgba(37, 99, 255, 0.12), transparent 62%),
    linear-gradient(162deg, #F2FCFD 0%, #E7F8FB 46%, #DDF4F8 100%);
  color: #0A1B33;
}
/* The two drifting blobs were light sources on a dark ground; on a pale one the
   same opacity reads as smudges. Kept, at a third of the strength. */
.sa-hero::before { background: radial-gradient(circle, rgba(6, 214, 209, 0.16), transparent 66%); }
.sa-hero::after  { background: radial-gradient(circle, rgba(37, 99, 255, 0.10), transparent 66%); }
.sa-hero-inner::after { background: radial-gradient(ellipse at center, rgba(6, 214, 209, 0.10), transparent 68%); }
.sa-hero-orb-1, .sa-hero-orb-2, .sa-hero-orb-3 { opacity: .10; }

.sa-hero h1 { color: #0A1B33; }
/* Was white -> pale cyan. Inverted: the light end now has to be the dark one,
   or the rotating tail vanishes into the ground. */
.sa-hero-gradient-text {
  background: linear-gradient(100deg, #1C4CC4 0%, #2563FF 42%, #0E9AA0 100%);
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.sa-hero-subtitle { color: #33496B; }
.sa-hero-note     { color: #4A5F7A; }
.sa-hero-hint     { color: #B42318; }   /* was #ffd7d7 - unreadable on a pale ground */

.sa-hero-badge {
  background: rgba(255, 255, 255, 0.72);
  border: 1px solid rgba(6, 214, 209, 0.30);
  color: #14507A;
}

/* The URL field: a translucent-white-on-dark input is invisible here, so it
   becomes a solid white field with a cyan hairline - the one white object in
   the hero, which is also what makes it read as the thing to type into. */
.sa-hero-check {
  background: #FFFFFF;
  border: 1.5px solid rgba(6, 214, 209, 0.38);
  box-shadow: 0 1px 2px rgba(9, 38, 84, 0.05);
}
.sa-hero-check:focus-within {
  border-color: #2563FF;
  background: #FFFFFF;
  box-shadow: 0 0 0 4px rgba(37, 99, 255, 0.14);
}
.sa-hero-check-input { color: #0A1B33; background: transparent; }
.sa-hero-check-input::placeholder { color: #8196AE; }
.sa-hero-check-prefix { color: #566B87; }   /* #6B7F99 measured 4.1:1 - under the 4.5 AA floor at 15.5px */
.sa-hero-check-btn { background: #2563FF; color: #FFFFFF; }
.sa-hero-check-btn:hover { background: #1C4CC4; }
/* The sheen swept white across a dark field; on white it has to sweep blue. */
.sa-hero-check-scan { background: linear-gradient(100deg, transparent, rgba(37, 99, 255, 0.14), transparent); }
.sa-hero-cta::after { background: linear-gradient(100deg, transparent, rgba(255, 255, 255, 0.34), transparent); }

.sa-hero-scroll   { border: 1.5px solid rgba(10, 27, 51, 0.24); }
.sa-hero-scroll i { background: rgba(10, 27, 51, 0.55); }
/* Fades into the white section below instead of out of a dark band. */
.sa-hero-fade { background: linear-gradient(to bottom, rgba(255, 255, 255, 0), #FFFFFF 92%); }

/* ============================================================================
   PANEL LANGUAGE — one hue, one edge
   ----------------------------------------------------------------------------
   The page already had this language; it was just tuned two ways. .sa-fs-card
   used a blue-grey tint (#E9F2F9) while .sa-bd-band - the panel this restyle is
   modelled on - uses cyan (#EAFAFC), and the radii ran 10/12/14/16/18/24. Same
   recipe, two hues, six radii, so the page read as assembled rather than
   designed.

   This settles on the band's cyan and its edge: 1px rgba(6,214,209,.22) and
   0 1px 2px rgba(9,38,84,.04).

   What deliberately does NOT get tinted: the cards sitting ON a tinted panel,
   and the stats strip. Tinting every block would flatten the hierarchy - the
   band reads as special partly because it is one of the few tinted objects.
   They take the hairline and the shadow so they belong, and stay white so they
   still separate from what is behind them. */
.sa-fs-card {
  background: linear-gradient(160deg, #EAFAFC 0%, #E0F7FA 52%, #D6F5F8 100%);
  border: 1px solid rgba(6, 214, 209, 0.22);
  border-radius: 20px;
  box-shadow: 0 1px 2px rgba(9, 38, 84, 0.04);
}
/* White on the tint, so the screenshot panel still lifts off the card. */
.sa-fs-shot { border-radius: 16px; }

.sa-stats-inner {
  border: 1px solid rgba(6, 214, 209, 0.22);
  border-radius: 20px;
  box-shadow: 0 1px 2px rgba(9, 38, 84, 0.04);
}
.sa-feature-card {
  border: 1px solid rgba(6, 214, 209, 0.20);
  border-radius: 20px;
  box-shadow: 0 1px 2px rgba(9, 38, 84, 0.04);
}
.sa-feature-card:hover {
  border-color: rgba(6, 214, 209, 0.42);
  box-shadow: 0 10px 28px -16px rgba(9, 38, 84, 0.22);
}

/* ============================================================================
   CONTRAST — captions and legends on the homepage illustrations
   ----------------------------------------------------------------------------
   Pre-existing, not from the light restyle: verified by measuring the page with
   these changes stashed. Every one of these is text a sighted visitor reads -
   an explanatory caption, a legend row, a category weight - so aria-hidden is
   the wrong tool. Hiding readable copy from assistive tech while leaving it on
   screen is a regression, not a fix; the donut arcs beside them are genuinely
   decorative and already carry aria-hidden.

   Ratios below are measured with the semi-transparent grounds COMPOSITED over
   their parents. Comparing text against a raw rgba() value - which is what an
   uncomposited check does - reports a pill at 1.5:1 that is actually near 9:1,
   and sends you off darkening colours that were never wrong.
   ========================================================================== */
.sa-comp-head p { color: #5A6B80; }        /* #7c8ba1 -> 3.32:1 at 12px */
.sa-comp-meta   { color: #5E6E82; }        /* #8494a8 -> 2.88:1 at 11px */
.sa-comp-band   { color: #0B6B62; }        /* #0d9488 on its own 12% teal -> 3.04:1 */
.sa-comp-score em { color: #5A6B80; }      /* #a3b1c2 -> 2.03:1 at 9px */
.sa-run-timer   { color: #5E6E82; }        /* #94a3b8 -> 2.46:1 at 12px */
.sa-run-pill b  { color: #1B4FD8; }        /* #2563FF on its own 8% blue -> 4.19:1 */
/* The "12 Critical / 28 Warning" chips are INLINE styles in Index.razor, so no
   rule here can reach them without !important; they are darkened in the markup. */

/* ============================================================================
   LIGHT HERO — the other public pages
   ----------------------------------------------------------------------------
   Pricing, About, Contact, Privacy and Terms all opened on the same #113e8f
   navy with a white h1 that the home hero used to. With the home page light,
   they were the only dark bands left, so the site changed temperature as you
   moved through it.

   Same palette as the LIGHT HERO block above, deliberately: one ground, one
   navy, one badge treatment across every public page. Contact is the odd one -
   its own background is transparent and it paints through .sa-contact-hero-bg,
   so that layer is what gets the ground there.
   ========================================================================== */
.sa-pricing-hero,
.sa-about-hero,
.sa-contact-hero,
.sa-legal-hero {
  background:
    radial-gradient(900px 420px at 84% 4%, rgba(6, 214, 209, 0.18), transparent 62%),
    radial-gradient(760px 400px at 6% 92%, rgba(37, 99, 255, 0.10), transparent 64%),
    linear-gradient(162deg, #F2FCFD 0%, #E7F8FB 46%, #DDF4F8 100%);
  color: #33496B;
}
/* Contact paints its ground through an inner layer, so neutralise that one and
   let the section's own gradient show. */
.sa-contact-hero-bg { background: transparent; }

.sa-pricing-hero h1,
.sa-about-hero h1,
.sa-contact-hero h1,
.sa-legal-hero h1 { color: #0A1B33; }

.sa-pricing-hero p,
.sa-about-hero p,
.sa-contact-hero p,
.sa-legal-hero-sub { color: #33496B; }

/* One badge treatment, matching .sa-hero-badge. */
.sa-about-badge,
.sa-contact-hero-badge,
.sa-legal-badge {
  background: rgba(255, 255, 255, 0.72);
  border: 1px solid rgba(6, 214, 209, 0.30);
  color: #14507A;
}

/* The legal heroes' "Last updated" caption was white-on-navy; on the pale ground
   it has to carry its own ink. Muted, but still 5.9:1 at 13px. */
.sa-legal-updated { color: #45608A; }


/* =============================================================================
   CONTRAST - WCAG AA on the landing page
   =============================================================================
   Long-standing failures, measured with each label composited over the ground it
   actually sits on rather than against its declared colour - which is why the
   near-misses (4.1-4.49:1) never showed up before. Most sit inside the drawn
   product mock; that text is readable copy, not decoration, so it is darkened
   rather than hidden from assistive tech. Ratios below are the measured "after".
   ========================================================================== */

/* Avatar initials on the 11% blue wash: 3.98 -> 6.25. */
.sa-fs-av { color: #1C4CC4; }

/* White grade letter on green: 3.30 -> 5.02. Ground darkens, ink stays white. */
.sa-ck-grade i { background: #15803d; }

/* Green pills on their own tinted ground: 4.49 -> 6.34 and 4.39 -> 6.18. */
.sa-ck-exec-pill,
.sa-deck-badge.sa-good { color: #116634; }

/* The amber sibling measured 4.50 - passing, but only just, and the same rounding
   that hid the others could put it under. Given margin: -> 6.44. */
.sa-deck-badge.sa-warn { color: #8F4008; }

/* Mock captions and the URL bar: 2.46 -> 4.97 and 4.10 -> 5.19. */
.sa-comp-centre em,
.sa-vid-mock-bar b { color: #5A6E86; }

/* Legal TOC, "already read" markers: #2563FF on its own 10% blue wash was
   4.25:1. Only visible once the reader has scrolled past a section, which is
   why it hid behind the marker's colour transition until that was pinned. */
.sa-legal-toc-list a[data-state="done"] .sa-legal-toc-num { color: #1C4CC4; }

/* --- Auth pages -------------------------------------------------------------
   The signed-out auth screens keep their dark split panel (the light restyle was
   scoped to the blog), but two labels on it failed regardless of that choice. */

/* Stat captions were 60% white on the panel gradient: 3.39:1 at the teal end and
   2.69:1 at the blue midpoint. Opacity cannot reach 4.5 here - even 95% white
   only just clears it - so the caption goes solid and leans on size and letter-
   spacing for hierarchy instead of transparency. Worst case now 4.83:1. */
.sa-auth-brand-stat-label { color: #ffffff; }

/* The active step's numeral was white on a 20% white disc over the blue pill -
   a lighter ground under white text, so 3.5:1. Inverted to the usual stepper
   treatment: solid disc, dark numeral. 7.28:1. */
.sa-auth-step-pill.active span { background: #ffffff; color: #1C4CC4; }


/* =============================================================================
   LEGAL PAGES - lists and sub-headings
   =============================================================================
   The legal pages only ever styled h2, p and a, because both policies were a
   single paragraph per section. A readable privacy policy needs lists and
   sub-headings, so they get the same 44px indent that aligns body copy past the
   numbered marker, and the same type scale as .sa-legal-section p.
   ========================================================================== */
.sa-legal-section h3 {
  margin: 26px 0 8px;
  padding-left: 44px;
  font-size: 0.95rem;
  font-weight: 700;
  letter-spacing: -0.006em;
  color: #0d1b3d;
}
.sa-legal-section ul,
.sa-legal-section ol {
  margin: 10px 0 0;
  padding-left: 62px;        /* 44px indent + 18px for the marker */
  font-size: 15px;
  line-height: 1.75;
  color: #3A536E;
}
.sa-legal-section li { margin-bottom: 7px; }
.sa-legal-section li:last-child { margin-bottom: 0; }
.sa-legal-section li::marker { color: #8FA3BD; }
.sa-legal-section p + ul,
.sa-legal-section p + ol { margin-top: 12px; }
.sa-legal-section ul + p,
.sa-legal-section ol + p { margin-top: 14px; }
.sa-legal-section strong { font-weight: 650; color: #24405f; }

@media (max-width: 640px) {
  .sa-legal-section h3 { padding-left: 0; }
  .sa-legal-section ul,
  .sa-legal-section ol { padding-left: 20px; }
}


/* =============================================================================
   CONTRAST - the pricing plan cards
   =============================================================================
   Missed by every earlier sweep for a structural reason worth recording: the
   plan cards are fetched from the API, and with no API running locally the page
   renders "Plans are loading..." and nothing else. Local audits saw 34 nodes;
   the deployed page has 120. These three only appear once real plans render, on
   the featured card's cyan ground and the billing toggle.
   ========================================================================== */

/* Featured plan name on the cyan card: 4.15 -> 6.19. */
.sa-pricing-card.sa-featured .sa-pricing-name { color: #1C4CC4; }

/* Featured plan billing period: 4.46 -> 5.51. */
.sa-pricing-card.sa-featured .sa-pricing-period { color: #45608A; }

/* "Save 20%" on its own 8% blue wash: 4.37 -> 6.55. */
.sa-toggle-save { color: #1C4CC4; }
