/* ═══════════════════════════════════════════════════════════════
   chrome.css — the CSS EVERY surface gets
   ═══════════════════════════════════════════════════════════════

   Split out of the historical styles.css on 2026-09-03 (TWIN 5,
   docs/superpowers/plans/2026-09-02-delete-v1-twins.md §7). The split was a
   ONE-SHOT: the generator script that performed it was removed with the rest
   of the v1 tooling and no longer exists. THIS FILE IS THE SOURCE — edit it
   directly; there is nothing to re-run and nothing to regenerate from.

   What lives here: design tokens, reset/base, the skip link, nav + dropdowns +
   hamburger, footer, .reveal* + stagger scroll animation, the AI-section wrapper
   and surface machinery, the section-shell placeholders, the app-shell region
   layout, and the iframe sandbox rules.

   What does NOT live here: the tenant marketing template's component classes
   as BARE rules (.hero-*, .stat-*, .container, .section-eyebrow, .btn-glow,
   .plat-*, …). Those live in legacy.css and load only on the surfaces that emit
   them — see the loader list in that file's header. A bare rule on one of those
   generic names would paint any AI section that reused the name, which is the
   2026-08-18 card-blindness bug.

   ONE EXCEPTION, added 2026-09-03 when the AI page shell came off the legacy.css
   allowlist: the rules the five surviving legacy SECTION TEMPLATES + the "From
   the Blog" block need, ported here SCOPED to the section classes their
   emitters stamp (`.content-block-section` & co.). See the "LEGACY SECTION
   TEMPLATES" block below — the scope is why they cannot bleed.

   .reveal / .reveal-left / .reveal-right / .reveal-scale / .reveal-blur and
   their .visible pairs MUST stay in this file. site/public/js/main.js flips
   .visible and src/rendering/pages.js appends a per-section
   `#<id> .reveal.visible` override; a surface without these rules freezes
   every scroll reveal at opacity 0.
   ═══════════════════════════════════════════════════════════════ */

/* ═══════════════════════════════════════════════════════════════
   CMS — Shared Design System
   ═══════════════════════════════════════════════════════════════ */

/* ─── CUSTOM PROPERTIES ─── */
:root {
  /* ─── Existing color tokens (keep for backwards compat) ─── */
  --red: #ff0a0a;
  --red-glow: rgba(255, 10, 10, 0.4);
  --red-soft: rgba(255, 10, 10, 0.08);
  --red-border: rgba(255, 10, 10, 0.12);
  --orange: #ff6b35;
  --amber: #ffb020;
  --green: #22c55e;
  --blue: #3b82f6;
  --purple: #a855f7;
  --cyan: #06b6d4;
  --pink: #ec4899;
  --font-body: 'Outfit', sans-serif;
  --font-mono: 'JetBrains Mono', monospace;
  --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
  --nav-height: 80px;
  --nav-height-scrolled: 60px;
  --anim-speed: 0.8s;

  /* ─── Semantic theme tokens (dark mode default) ─── */
  --bg: #0a0a0a;
  --bg-elevated: #0d0d12;
  --bg-card: #111118;
  --text: #ffffff;
  --text-secondary: rgba(255, 255, 255, 0.7);
  --text-muted: rgba(255, 255, 255, 0.4);
  --text-dim: rgba(255, 255, 255, 0.55);
  --border-subtle: rgba(255, 255, 255, 0.04);
  --border-light: rgba(255, 255, 255, 0.06);
  --border-medium: rgba(255, 255, 255, 0.1);

  /* ─── Brand tokens (overridden per-tenant via design tokens) ─── */
  --brand-primary: var(--red);
  --brand-primary-glow: var(--red-glow);
  --brand-primary-soft: var(--red-soft);
  --brand-primary-border: var(--red-border);

  /* Legacy aliases (mapped to semantic tokens) */
  --dark: var(--bg);
  --darker: #050505;
  --dark-card: var(--bg-card);
  --white: var(--text);
  --gray-100: #f0f0f0;
  --gray-200: #e0e0e0;
  --gray-400: #888;
  --gray-600: #555;
  --gray-800: #222;

  /* ─── P1.4 Concept-driven rhythm tokens ─── */
  /* hero-full intentionally uses MODEST padding — the .ai-section-wrapper[data-density="hero-full"]
     selector below applies min-height: 100vh + center alignment. Treating hero-full as a 100vh
     padding-block value would add 200vh of empty space (top + bottom). */
  --pad-compact:   24px;
  --pad-short:     48px;
  --pad-medium:    80px;
  --pad-tall:      120px;
  --pad-xl:        160px;
  --pad-hero-full: 0;

  /* ─── P1.4 Concept-driven surface tokens ─── */
  --surface-base:          var(--brand-bg, #ffffff);
  --surface-inset-light:   color-mix(in srgb, var(--brand-bg, #ffffff) 95%, #000);
  --surface-inset-dark:    color-mix(in srgb, var(--brand-bg, #ffffff) 85%, #000);
  --surface-brand-accent:  var(--brand-primary, #1a7a4f);
  --surface-image-bleed:   transparent;
  --surface-high-contrast: #000;
}

/* ─── Light mode ─── */
[data-theme="light"] {
  --bg: #ffffff;
  --bg-elevated: #f8f8fa;
  --bg-card: #f0f0f4;
  --text: #1a1a1a;
  --text-secondary: rgba(0, 0, 0, 0.7);
  --text-muted: rgba(0, 0, 0, 0.55); /* 0.45 read at ~3.3:1 on --bg-card (card meta failed AA) */
  --text-dim: rgba(0, 0, 0, 0.62);
  --border-subtle: rgba(0, 0, 0, 0.04);
  --border-light: rgba(0, 0, 0, 0.06);
  --border-medium: rgba(0, 0, 0, 0.1);

  /* Legacy aliases for light mode */
  --dark: var(--bg);
  --darker: #f0f0f0;
  --dark-card: var(--bg-card);
  --white: var(--text);
  --gray-100: #222;
  --gray-200: #333;
  --gray-400: #666;
  --gray-600: #999;
  --gray-800: #ddd;
}

/* ─── SKIP LINK (a11y) ─── */
.skip-link {
  position: absolute;
  left: -9999px;
  top: 10px;
  z-index: 9999;
  background: var(--red);
  color: var(--white);
  padding: 12px 24px;
  border-radius: 8px;
  font-weight: 600;
  font-size: 14px;
  text-decoration: none;
  white-space: nowrap;
}

.skip-link:focus {
  left: 50%;
  transform: translateX(-50%);
}

/* ─── RESET & BASE ─── */
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

/* scroll-behavior:smooth removed from html — it fights iframe height mutations
   and causes scroll-snap. Per-call el.scrollIntoView({behavior:'smooth'}) in JS still works. */
body {
  font-family: var(--font-body);
  color: var(--white);
  background: var(--dark);
  overflow-x: hidden;
}

/* ─── SCROLL REVEAL ─── */
/* Animation speed controlled per-section via --anim-speed custom property */
.reveal {
  opacity: 0;
  transform: translateY(60px);
  transition: opacity var(--anim-speed, 0.8s) var(--ease-out-expo), transform var(--anim-speed, 0.8s) var(--ease-out-expo);
}

.reveal.visible {
  opacity: 1;
  transform: translateY(0);
}

.reveal-left {
  opacity: 0;
  transform: translateX(-80px);
  transition: opacity var(--anim-speed, 0.8s) var(--ease-out-expo), transform var(--anim-speed, 0.8s) var(--ease-out-expo);
}

.reveal-left.visible {
  opacity: 1;
  transform: translateX(0);
}

.reveal-right {
  opacity: 0;
  transform: translateX(80px);
  transition: opacity var(--anim-speed, 0.8s) var(--ease-out-expo), transform var(--anim-speed, 0.8s) var(--ease-out-expo);
}

.reveal-right.visible {
  opacity: 1;
  transform: translateX(0);
}

.reveal-scale {
  opacity: 0;
  transform: scale(0.85);
  transition: opacity var(--anim-speed, 0.8s) var(--ease-out-expo), transform var(--anim-speed, 0.8s) var(--ease-out-expo);
}

.reveal-scale.visible {
  opacity: 1;
  transform: scale(1);
}

.reveal-blur {
  opacity: 0;
  filter: blur(10px);
  transition: opacity var(--anim-speed, 0.8s) var(--ease-out-expo), filter var(--anim-speed, 0.8s) var(--ease-out-expo);
}

.reveal-blur.visible {
  opacity: 1;
  filter: blur(0);
}

/* ─── STAGGER DELAYS ─── */
.stagger-1 {
  transition-delay: 0.1s;
}

.stagger-2 {
  transition-delay: 0.2s;
}

.stagger-3 {
  transition-delay: 0.3s;
}

.stagger-4 {
  transition-delay: 0.4s;
}

.stagger-5 {
  transition-delay: 0.5s;
}

.stagger-6 {
  transition-delay: 0.6s;
}

/* ─── NAV ─── */
/* Nav colours are ABSOLUTE, not theme tokens (2026-09-03): the nav floats over
   arbitrary sections and flips itself via the `nav-light` sampler in main.js.
   `--white`/`--dark` are remapped by `[data-theme="light"]` (a whole-page flip for
   the footer/static template), which inverted the nav on every light-theme page:
   dark logo over a dark hero, white logo over light sections. */
nav {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 20px 48px;
  background: transparent;
  border-bottom: 1px solid transparent;
  backdrop-filter: none;
  transition: padding 0.4s var(--ease-out-expo), background 0.4s var(--ease-out-expo), border-bottom 0.4s var(--ease-out-expo), backdrop-filter 0.4s var(--ease-out-expo);
}

nav.scrolled {
  padding: 14px 48px;
  background: rgba(10, 10, 10, 0.92);
  backdrop-filter: blur(20px) saturate(180%);
  border-bottom: 1px solid rgba(255, 255, 255, 0.05);
}

/* Auto-detected light background behind nav */
nav.nav-light:not(.scrolled) {
  border-bottom-color: rgba(0, 0, 0, 0.06);
}

nav.nav-light:not(.scrolled) .logo {
  color: #0a0a0a;
}

nav.nav-light:not(.scrolled) .nav-links a {
  color: rgba(10, 10, 10, 0.6);
}

nav.nav-light:not(.scrolled) .nav-links a:hover,
nav.nav-light:not(.scrolled) .nav-links a.active {
  color: #0a0a0a;
}

nav.nav-light:not(.scrolled) .hamburger span {
  background: #0a0a0a;
}

nav.nav-light.scrolled {
  background: rgba(255, 255, 255, 0.95);
  border-bottom: 1px solid rgba(0, 0, 0, 0.08);
}

nav.nav-light.scrolled .logo {
  color: #0a0a0a;
}

nav.nav-light.scrolled .nav-links a {
  color: rgba(10, 10, 10, 0.6);
}

nav.nav-light.scrolled .nav-links a:hover,
nav.nav-light.scrolled .nav-links a.active {
  color: #0a0a0a;
}

nav.nav-light.scrolled .hamburger span {
  background: #0a0a0a;
}

.logo {
  /* position:relative anchors the absolutely-positioned .logo-img-light
     overlay used by the dual-image dark/light theme swap. */
  position: relative;
  display: flex;
  align-items: center;
  gap: 12px;
  text-decoration: none;
  color: var(--text);
  transition: color 0.4s var(--ease-out-expo);
}

/* The NAV logo is absolute white (it floats over arbitrary sections and the
   nav-light sampler flips it); the footer logo follows the theme token. */
nav .logo {
  color: #ffffff;
}

.logo-icon {
  width: 38px;
  height: 38px;
  background: var(--red);
  border-radius: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 900;
  font-size: 20px;
  color: white;
  box-shadow: 0 0 20px var(--red-glow);
  transition: box-shadow 0.3s;
}

.logo:hover .logo-icon {
  box-shadow: 0 0 30px var(--red-glow), 0 0 60px rgba(255, 10, 10, 0.2);
}

.logo-text {
  font-weight: 700;
  font-size: 22px;
  letter-spacing: -0.5px;
}

.logo img {
  /* T0506-followup: bump default nav logo height from 32px (felt tiny on
     wide layouts) and drop mix-blend-mode: screen — the chroma-key in
     toolGenerateLogo (cac0555) plus the quality gate (2af12a2) now
     guarantee transparent PNGs, so the screen-blend hack is actively
     harmful (a dark logo on a dark nav becomes invisible). */
  height: 56px;
  max-width: 280px;
  width: auto;
  object-fit: contain;
  transition: opacity 0.3s var(--ease-out-expo);
}

/* Dual-image dark/light theme swap. Renderer emits both <img> elements when
   a tenant has distinct dark + light logo variants; main.js toggles
   `nav.nav-light` based on the luminance of the section currently behind
   the nav. The light variant overlays the dark one absolutely so the
   layout doesn't shift between states. Replaces the old
   `nav.nav-light .logo img { filter: brightness(0) }` hack which flattened
   no-alpha logos to solid black squares (the "walker symptom").

   Naming: `logo-img-dark` = the dark-colored logo (use on light bg);
   `logo-img-light` = the light-colored logo (use on dark bg). Default
   (no `nav-light` class) = dark background, so show the LIGHT-colored
   variant. When `nav-light` is set, background is light, show the
   DARK-colored variant. */
.logo .logo-img-dark {
  position: absolute;
  top: 50%;
  left: 0;
  transform: translateY(-50%);
  opacity: 0;
}

nav.nav-light .logo .logo-img-light {
  opacity: 0;
}

nav.nav-light .logo .logo-img-dark {
  opacity: 1;
}

.logo-light .logo-icon {
  filter: none;
}

.nav-links {
  display: flex;
  gap: 32px;
  align-items: center;
  flex-shrink: 0;
}

.nav-links a {
  font-weight: 500;
  font-size: 14px;
  text-decoration: none;
  color: rgba(255, 255, 255, 0.6);
  letter-spacing: 0.3px;
  transition: color 0.3s;
  position: relative;
}

.nav-links a::after {
  content: '';
  position: absolute;
  bottom: -4px;
  left: 0;
  width: 0;
  height: 2px;
  background: var(--red);
  transition: width var(--anim-speed, 0.3s) var(--ease-out-expo);
}

.nav-links a:hover {
  color: #ffffff;
}

.nav-links a:hover::after {
  width: 100%;
}

.nav-links a.active {
  color: #ffffff;
}

.nav-links a.active::after {
  width: 100%;
}

.nav-cta {
  background: var(--red) !important;
  color: #ffffff !important;
  padding: 10px 24px !important;
  border-radius: 8px;
  font-weight: 600 !important;
  font-size: 13px !important;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  box-shadow: 0 0 20px var(--red-glow);
  transition: all 0.3s !important;
}

.nav-cta::after {
  display: none !important;
}

.nav-cta:hover {
  box-shadow: 0 0 40px var(--red-glow), 0 4px 20px rgba(0, 0, 0, 0.3) !important;
  transform: translateY(-1px);
}

/* ─── NAV DROPDOWNS ─── */
.nav-dropdown {
  position: relative;
}

.nav-dropdown-trigger {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  background: none;
  border: none;
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 14px;
  color: rgba(255, 255, 255, 0.6);
  letter-spacing: 0.3px;
  cursor: pointer;
  padding: 0;
  transition: color 0.3s;
}

.nav-dropdown-trigger:hover {
  color: #ffffff;
}

.nav-dropdown-chevron {
  transition: transform var(--anim-speed, 0.3s) var(--ease-out-expo);
}

.nav-dropdown:hover .nav-dropdown-chevron,
.nav-dropdown.open .nav-dropdown-chevron {
  transform: rotate(180deg);
}

.nav-dropdown-menu {
  position: absolute;
  top: calc(100% + 12px);
  left: 50%;
  transform: translateX(-50%) translateY(8px);
  min-width: 200px;
  background: rgba(13, 13, 18, 0.95);
  backdrop-filter: blur(20px) saturate(180%);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 12px;
  padding: 8px;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity 0.25s var(--ease-out-expo), transform 0.25s var(--ease-out-expo), visibility 0.25s;
  z-index: 1002;
  box-shadow: 0 16px 48px rgba(0, 0, 0, 0.4);
}

.nav-dropdown:hover .nav-dropdown-menu {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transform: translateX(-50%) translateY(0);
}

.nav-dropdown-menu a {
  display: block !important;
  padding: 10px 16px !important;
  border-radius: 8px;
  font-size: 14px !important;
  color: rgba(255, 255, 255, 0.6) !important;
  white-space: nowrap;
  transition: background 0.2s, color 0.2s !important;
}

.nav-dropdown-menu a::after {
  display: none !important;
}

.nav-dropdown-menu a:hover {
  background: rgba(255, 255, 255, 0.06) !important;
  color: #ffffff !important;
}

/* ─── MOBILE HAMBURGER ─── */
.hamburger {
  display: none;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  width: 44px;
  height: 44px;
  background: none;
  border: none;
  cursor: pointer;
  z-index: 1001;
  padding: 0;
  -webkit-tap-highlight-color: transparent;
}

.hamburger span {
  display: block;
  width: 24px;
  height: 2px;
  background: #ffffff;
  border-radius: 2px;
  transition: all var(--anim-speed, 0.3s) var(--ease-out-expo);
}

.hamburger span:nth-child(1) {
  margin-bottom: 6px;
}

.hamburger span:nth-child(3) {
  margin-top: 6px;
}

.nav-open .hamburger span:nth-child(1) {
  transform: rotate(45deg) translate(5px, 6px);
}

.nav-open .hamburger span:nth-child(2) {
  opacity: 0;
  transform: translateX(-10px);
}

.nav-open .hamburger span:nth-child(3) {
  transform: rotate(-45deg) translate(5px, -6px);
}

.nav-open .nav-links {
  display: flex;
  flex-direction: column;
  position: fixed;
  top: 0;
  right: 0;
  width: 280px;
  height: 100vh;
  background: rgba(10, 10, 10, 0.97);
  backdrop-filter: blur(24px) saturate(180%);
  padding: 100px 36px 48px;
  gap: 28px;
  border-left: 1px solid rgba(255, 255, 255, 0.06);
  animation: slideInRight var(--anim-speed, 0.35s) var(--ease-out-expo) forwards;
  z-index: 999;
}

.nav-open .nav-links a {
  font-size: 18px;
  color: rgba(255, 255, 255, 0.6);
}

.nav-open .nav-links a:hover {
  color: #ffffff;
}

/* Mobile dropdown accordion */
.nav-open .nav-dropdown {
  width: 100%;
}

.nav-open .nav-dropdown-trigger {
  font-size: 18px;
  width: 100%;
  justify-content: space-between;
}

.nav-open .nav-dropdown-menu {
  position: static;
  transform: none;
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  background: none;
  backdrop-filter: none;
  border: none;
  border-radius: 0;
  box-shadow: none;
  padding: 0 0 0 16px;
  max-height: 0;
  overflow: hidden;
  transition: max-height var(--anim-speed, 0.35s) var(--ease-out-expo);
}

.nav-open .nav-dropdown.open .nav-dropdown-menu {
  max-height: 300px;
}

.nav-open .nav-dropdown-menu a {
  padding: 8px 0 !important;
  font-size: 16px !important;
  border-radius: 0 !important;
}

.nav-open .nav-dropdown-menu a:hover {
  background: none !important;
}

.nav-open::before {
  content: '';
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.5);
  z-index: 998;
  animation: fadeIn var(--anim-speed, 0.3s) ease forwards;
}

@keyframes slideInRight {
  from {
    transform: translateX(100%);
    opacity: 0;
  }

  to {
    transform: translateX(0);
    opacity: 1;
  }
}

@keyframes fadeIn {
  from {
    opacity: 0;
  }

  to {
    opacity: 1;
  }
}

#hero-canvas {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
}

@keyframes float1 {

  0%,
  100% {
    transform: translate(0, 0);
  }

  50% {
    transform: translate(40px, 30px);
  }
}

@keyframes float2 {

  0%,
  100% {
    transform: translate(0, 0);
  }

  50% {
    transform: translate(-30px, -40px);
  }
}

@keyframes pulse {

  0%,
  100% {
    opacity: 0.08;
    transform: translate(-50%, -50%) scale(1);
  }

  50% {
    opacity: 0.15;
    transform: translate(-50%, -50%) scale(1.1);
  }
}

@keyframes blink {

  0%,
  100% {
    opacity: 1;
  }

  50% {
    opacity: 0.3;
  }
}

.hero-buttons {
  display: flex;
  gap: 16px;
  justify-content: center;
  flex-wrap: wrap;
  animation: fadeUp var(--anim-speed, 1s) 0.8s both;
}

@keyframes fadeUp {
  from {
    opacity: 0;
    transform: translateY(40px);
  }

  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes fadeDown {
  from {
    opacity: 0;
    transform: translateY(-20px);
  }

  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.hero-word-reveal .word {
  display: inline-block;
  opacity: 0;
  transform: translateY(20px);
  animation: wordFadeUp var(--anim-speed, 0.6s) forwards;
}

@keyframes wordFadeUp {
  from {
    opacity: 0;
    transform: translateY(20px);
  }

  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes bounce {

  0%,
  100% {
    transform: translateX(-50%) translateY(0);
  }

  50% {
    transform: translateX(-50%) translateY(10px);
  }
}

/* ─── SECTIONS ─── */
section:not(.ai-section-wrapper) {
  padding: 120px 48px;
  position: relative;
  overflow: hidden;
}
/* (2026-09-16) The model's OWN root <section> inside an AI section wrapper owns
   its rhythm (its CSS pads itself); the legacy 120px/48px band above stacked on
   top of it and produced ~220px of dead space at every section edge on every
   AI-built page (live: Critical Carry, all seven pages). The :not() above names
   the concept wrapper, not the model root, so it never excluded it. Specificity
   0,2,1 beats both the rule above and its mobile override. position/overflow
   stay as the rule above sets them. */
[data-section-id] section:not(.ai-section-wrapper) {
  padding: 0;
}

/* ─── Concept-driven wrapper ─── */
/* The wrapper carries surface bg only; the iframe content owns all padding
   and vertical rhythm. Density, boundary, and role survive as data attributes
   for JS hooks (hero-full iframe sizing in main.js, analytics, etc.) and as
   signals already passed to the LLM via the section prompt (prompts.js:374-379).
   No hardcoded wrapper padding ladder — each LLM-generated section emits its
   own internal padding per the density signal it receives. */
.ai-section-wrapper {
  display: block;
  width: 100%;
}

/* First-section nav clearance (2026-05-16):
   The page nav is position:fixed at top:0 with height var(--nav-height).
   Without this rule, the first dynamic section starts at y=0 and the nav
   floats over its top portion — fine for hero-full (intentional 100vh bleed)
   but visually broken for every other density. We apply a single, structural,
   top-only padding to the first wrapper that isn't hero-full. This is NOT
   the c6bd3e2 per-density wrapper-padding pattern that was removed for
   gap-stacking: it's a one-time, single-direction, page-level offset for
   the one fixed nav. The model bakes NO nav awareness into its own CSS —
   data-position="first" is re-evaluated at render time, so reordering
   sections automatically moves the clearance to whichever wrapper is now
   first. */
.ai-section-wrapper[data-position="first"]:not([data-density="hero-full"]) {
  padding-top: var(--nav-height);
}

/* Ring 0 Task 6 (2026-05-19): top-gap fix.
   The first-section wrapper inherits surface bg (white in untheme'd tenants).
   When the first section's iframe contents have a dark hero (and the
   iframe body is transparent + has 50px baseline padding from b09046d),
   the wrapper's white bg shows through that 50px strip + the nav-clearance
   padding — visible as a white band above dark content.
   Fix: transparent wrapper for first position. Page bg shows through.
   Hero-full sections already exempt from nav-clearance; this rule is
   additive — does not change padding behavior. */
.ai-section-wrapper[data-position="first"] {
  background: transparent;
}

/* ─── LOGO SIZING ─── */
/* T0506-followup: bump default heights for visibility on wide/dark nav.
   Operators wanting smaller can override per-tenant via design tokens. */
.logo-nav img {
  height: 56px;
  max-width: 280px;
  width: auto;
  object-fit: contain;
}

.logo-footer img {
  height: 40px;
  max-width: 220px;
  width: auto;
  object-fit: contain;
}

@keyframes dividerShimmer {

  0%,
  100% {
    opacity: 0.6;
    background-position: 0% 50%;
  }

  50% {
    opacity: 1;
    background-position: 100% 50%;
  }
}

.org-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 2px;
}

.connexions-tiers-inline {
  margin-top: 24px;
}

.connexions-layout {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 60px;
  align-items: start;
}

.tiers-heading {
  font-size: 22px;
  font-weight: 700;
  margin-bottom: 8px;
}

.platform-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 2px;
}

/* ─── INTELLIGENCE PIPELINE ─── */
.pipeline-container {
  width: 100%;
  max-width: 1100px;
  position: relative;
  margin: 0 auto;
}

.pipeline-stages {
  display: flex;
  align-items: center;
  gap: 0;
  position: relative;
}

.pipe-metrics {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 16px;
  margin-top: 48px;
}

.pipe-metric-value {
  font-family: var(--font-mono);
  font-size: 28px;
  font-weight: 700;
  margin-bottom: 4px;
}

.analytics-layout {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 60px;
  align-items: center;
}

.analytics-features {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.af {
  display: flex;
  gap: 16px;
  align-items: flex-start;
}

.af h4 {
  font-size: 15px;
  font-weight: 700;
  margin-bottom: 4px;
}

.af p {
  font-size: 13px;
  font-weight: 300;
  color: var(--text-muted);
  line-height: 1.6;
}

/* ─── CONVERGENCE CONTAINER ─── */
.convergence-container {
  width: 100%;
  max-width: 500px;
  height: 500px;
  position: relative;
}

.convergence-container canvas {
  width: 100%;
  height: 100%;
  border-radius: 20px;
}

.integration-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 16px;
  max-width: 800px;
}

.integration-icon {
  font-size: 28px;
}

/* ─── ENRICHMENT ENGINE ─── */
.enrich-wrap {
  display: flex;
  gap: 32px;
  width: 100%;
  max-width: 1100px;
  align-items: stretch;
  margin: 0 auto;
}

.enrich-canvas-wrap {
  flex: 1;
  min-width: 0;
}

.enrich-canvas-wrap canvas {
  height: 580px;
}

.enrich-sidebar {
  width: 300px;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.es-icon {
  width: 36px;
  height: 36px;
  border-radius: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 16px;
  flex-shrink: 0;
}

.es-info h5 {
  font-size: 13px;
  font-weight: 600;
  margin-bottom: 2px;
}

.es-info p {
  font-size: 11px;
  font-weight: 300;
  color: rgba(255, 255, 255, 0.35);
}

/* ─── CONVERSATIONAL INTELLIGENCE ─── */
.convo-wrap {
  display: grid;
  grid-template-columns: 1fr 380px;
  gap: 32px;
  width: 100%;
  max-width: 1100px;
  margin: 0 auto;
}

.convo-canvas-wrap canvas {
  height: 520px;
}

.convo-panel {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.cc-header {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 10px;
}

.cc-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex-shrink: 0;
}

.cc-label {
  font-size: 12px;
  font-weight: 600;
}

.cc-tags {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  margin-top: 10px;
}

.cc-tag {
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 600;
  padding: 3px 8px;
  border-radius: 4px;
  text-transform: uppercase;
  letter-spacing: 0.8px;
}

/* ─── DECISION ENGINE ─── */
.decision-container {
  width: 100%;
  max-width: 1100px;
  position: relative;
  margin: 0 auto;
}

.decision-grid {
  display: grid;
  grid-template-columns: 340px 1fr;
  gap: 32px;
  align-items: start;
}

@keyframes signalIn {
  from {
    opacity: 0;
    transform: translateX(-30px);
  }

  to {
    opacity: 1;
    transform: translateX(0);
  }
}

.signal-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex-shrink: 0;
}

.signal-text {
  font-size: 13px;
  font-weight: 400;
  flex: 1;
}

.decision-panels {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.dc-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 14px;
}

.dc-header h4 {
  font-size: 16px;
  font-weight: 700;
}

/* ─── ROI CHART ─── */
.roi-container {
  width: 100%;
  max-width: 1000px;
  height: 520px;
  position: relative;
  margin: 0 auto;
}

.roi-container canvas {
  width: 100%;
  height: 100%;
  border-radius: 20px;
  background: var(--dark-card);
  border: 1px solid var(--border-light);
}

.cta-buttons {
  display: flex;
  gap: 16px;
  justify-content: center;
  flex-wrap: wrap;
}

/* ─── LATEST BLOG POSTS SECTION ─── */
.blog-latest-section {
  padding: 100px 24px;
  position: relative;
  overflow: hidden;
}

.blog-latest-card-body {
  padding: 20px;
  flex: 1;
  display: flex;
  flex-direction: column;
}

.blog-latest-card-body h4 {
  font-family: var(--font-body);
  font-size: 1.05rem;
  font-weight: 700;
  color: #fff;
  margin: 0 0 8px;
  line-height: 1.3;
}

.blog-latest-card-body p {
  font-size: 0.85rem;
  color: var(--text-dim);
  line-height: 1.6;
  margin: 0;
  flex: 1;
}

@media (max-width: 768px) {
.blog-latest-section {
    padding: 60px 16px;
  }
}

/* ─── DYNAMIC SECTIONS ─── */
.dynamic-section {
  position: relative;
}

/* ─── LEGACY SECTION TEMPLATES — the v1 component rules, SCOPED ────────────
   src/rendering/pages.js still renders five pre-AI section templates out of
   live KV rows (renderLegacyTemplateSection: content-block / feature-grid /
   cta-banner / testimonial / catalog-grid-widget) plus the injected "From the
   Blog" block (injectLatestBlogPosts). Those six markups were the ONLY reason
   the AI page shell loaded legacy.css, so the rules they use are ported here,
   scoped to the section classes those two emitters stamp, and the shell now
   links chrome.css alone (src/rendering/stylesheet-links.js).

   WHY THE SCOPE IS THE TEMPLATE CLASS AND NOT `.dynamic-section`:
   renderInlineSection stamps `dynamic-section` on AI sections too (it leads
   the `ai-custom-section-wrapper` shell class list), so scoping on that would
   re-create the 2026-08-18 card-blindness bleed — a bare-name rule painting an
   AI section that merely reused a generic class name. `.content-block-section`
   & co. are emitted ONLY by renderLegacyTemplateSection / injectLatestBlogPosts,
   so an AI section can never match them. Pinned by
   tests/unit/rendering/legacy-template-wrapper-scope.test.js.

   WHAT WAS PORTED: exactly what these classes RESOLVED TO on the shell before
   this change — not the raw legacy.css rule. Every legacy template section
   (and the blog block) carries `data-section-id`, so the
   `[data-section-id] .<class>` neutraliser at the foot of legacy.css was
   already stripping color / background / opacity off them and killing the
   `.section-eyebrow::before` / `.btn-glow::before` pseudo-elements. Those
   declarations are absent here on purpose: `.btn-glow` keeps its layout,
   radius and glow shadow but not its red fill; `.section-eyebrow` keeps its
   mono/uppercase treatment but inherits its ink; `.blog-latest-card-placeholder`
   had nothing but a background, so it is gone entirely. `.section-title` and
   the `-center` / `-mb40` utilities were never in the neutraliser vocabulary,
   so they port verbatim. `.container` has never had a platform rule at all —
   the legacy templates carry inline max-width/margin.

   The unscoped originals stay in legacy.css for the surfaces that still load
   it (the blog listing/post, the storefront pages, site/public/*.html); none
   of those render `[data-section-id]` markup, which is why the neutraliser
   could be deleted outright rather than moved. */
:is(.content-block-section, .feature-grid-section, .cta-banner-section, .testimonial-section, .catalog-grid-section, .blog-latest-section) .section-eyebrow {
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 3px;
  margin-bottom: 16px;
  display: flex;
  align-items: center;
  gap: 12px;
}

:is(.content-block-section, .feature-grid-section, .cta-banner-section, .testimonial-section, .catalog-grid-section, .blog-latest-section) .section-eyebrow-center {
  justify-content: center;
}

:is(.content-block-section, .feature-grid-section, .cta-banner-section, .testimonial-section, .catalog-grid-section, .blog-latest-section) .section-title {
  font-size: clamp(36px, 4.5vw, 56px);
  font-weight: 800;
  line-height: 1.08;
  letter-spacing: -1.5px;
  margin-bottom: 20px;
  max-width: 700px;
}

:is(.content-block-section, .feature-grid-section, .cta-banner-section, .testimonial-section, .catalog-grid-section, .blog-latest-section) .section-title-center {
  text-align: center;
  max-width: 800px;
  margin: 0 auto 20px;
}

:is(.content-block-section, .feature-grid-section, .cta-banner-section, .testimonial-section, .catalog-grid-section, .blog-latest-section) .section-desc {
  font-size: 18px;
  font-weight: 300;
  line-height: 1.75;
  max-width: 580px;
  margin-bottom: 64px;
}

:is(.content-block-section, .feature-grid-section, .cta-banner-section, .testimonial-section, .catalog-grid-section, .blog-latest-section) .section-desc-center {
  text-align: center;
  max-width: 600px;
  margin-left: auto;
  margin-right: auto;
  margin-top: 0;
  margin-bottom: 48px;
}

:is(.content-block-section, .feature-grid-section, .cta-banner-section, .testimonial-section, .catalog-grid-section, .blog-latest-section) .section-desc-mb40 {
  margin-bottom: 40px;
}

:is(.content-block-section, .feature-grid-section, .cta-banner-section, .testimonial-section, .catalog-grid-section, .blog-latest-section) .btn-glow {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 18px 40px;
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 15px;
  text-decoration: none;
  border-radius: 12px;
  letter-spacing: 0.3px;
  box-shadow: 0 0 30px var(--red-glow), 0 8px 32px rgba(0, 0, 0, 0.3);
  transition: all var(--anim-speed, 0.3s) var(--ease-out-expo);
  border: none;
  cursor: pointer;
  position: relative;
  overflow: hidden;
}

:is(.content-block-section, .feature-grid-section, .cta-banner-section, .testimonial-section, .catalog-grid-section, .blog-latest-section) .btn-glow:hover {
  box-shadow: 0 0 50px var(--red-glow), 0 12px 40px rgba(0, 0, 0, 0.4);
  transform: translateY(-2px);
}

:is(.content-block-section, .feature-grid-section, .cta-banner-section, .testimonial-section, .catalog-grid-section, .blog-latest-section) .btn-ghost {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 18px 40px;
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 15px;
  text-decoration: none;
  border-radius: 12px;
  border: 1px solid rgba(255, 255, 255, 0.12);
  transition: all 0.3s;
}

/* The neutraliser's `background:none` outranked `.btn-ghost:hover`'s own
   background (same specificity, later in the file), so only the border moved
   on hover. */
:is(.content-block-section, .feature-grid-section, .cta-banner-section, .testimonial-section, .catalog-grid-section, .blog-latest-section) .btn-ghost:hover {
  border-color: rgba(255, 255, 255, 0.25);
}

/* feature-grid template only. The grid itself is inline-styled by the emitter
   (display:grid + a computed column count); only the mobile collapse is CSS. */
.feature-grid-section .dynamic-feature-card {
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: 16px;
  padding: 32px;
  transition: border-color 0.3s, transform 0.3s;
}

.feature-grid-section .dynamic-feature-card:hover {
  border-color: rgba(255, 10, 10, 0.2);
  transform: translateY(-4px);
}

.feature-grid-section .dynamic-feature-icon {
  width: 48px;
  height: 48px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 12px;
  font-size: 1.4rem;
  margin-bottom: 16px;
}

/* h3 / p are DESCENDANT rules — the neutraliser only ever hit the card
   itself, so these two keep their colours. */
.feature-grid-section .dynamic-feature-card h3 {
  font-size: 1.1rem;
  font-weight: 600;
  margin-bottom: 8px;
  color: var(--white);
}

.feature-grid-section .dynamic-feature-card p {
  font-size: 0.9rem;
  color: rgba(255, 255, 255, 0.5);
  line-height: 1.6;
}

@media (max-width: 768px) {
.feature-grid-section .dynamic-feature-grid {
    grid-template-columns: 1fr !important;
  }
}

/* "From the Blog" (injectLatestBlogPosts) only. `.blog-latest-section`,
   `.blog-latest-card-body` and its h4/p already live above. */
.blog-latest-section .blog-latest-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 24px;
  max-width: 1200px;
  margin: 0 auto;
}

/* `color: inherit` is load-bearing, not decoration — the card is an <a>, and
   without it the UA link colour paints every card title blue. */
.blog-latest-section .blog-latest-card {
  border: 1px solid var(--border-light);
  border-radius: 16px;
  overflow: hidden;
  text-decoration: none;
  color: inherit;
  transition: border-color 0.3s var(--ease-out-expo), transform 0.3s var(--ease-out-expo), box-shadow 0.3s;
  display: flex;
  flex-direction: column;
}

.blog-latest-section .blog-latest-card:hover {
  border-color: rgba(255, 10, 10, 0.25);
  transform: translateY(-6px);
  box-shadow: 0 16px 48px rgba(255, 10, 10, 0.08);
}

.blog-latest-section .blog-latest-card-img {
  width: 100%;
  height: 180px;
  object-fit: cover;
}

.blog-latest-section .blog-latest-card-date {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  margin-bottom: 8px;
  letter-spacing: 0.02em;
}

.blog-latest-section .blog-latest-card-cat {
  font-family: var(--font-mono);
  font-size: 0.65rem;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  margin-bottom: 6px;
}

@media (max-width: 1024px) {
.blog-latest-section .blog-latest-grid {
    grid-template-columns: 1fr 1fr;
  }
}

@media (max-width: 768px) {
.blog-latest-section .blog-latest-grid {
    grid-template-columns: none;
    display: flex;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    gap: 16px;
    padding-bottom: 12px;
    scrollbar-width: none;
  }
.blog-latest-section .blog-latest-grid::-webkit-scrollbar {
    display: none;
  }
.blog-latest-section .blog-latest-card {
    min-width: 280px;
    scroll-snap-align: start;
    flex-shrink: 0;
  }
}

/* ─── FOOTER ─── */
footer {
  background: var(--darker);
  padding: 60px 48px 40px;
  text-align: center;
  border-top: 1px solid var(--border-subtle);
}

.footer-logo {
  display: flex;
  align-items: center;
  gap: 12px;
  justify-content: center;
  margin-bottom: 32px;
  font-weight: 700;
  font-size: 20px;
}

.footer-logo .logo-icon {
  width: 32px;
  height: 32px;
  font-size: 16px;
}

.footer-links {
  display: flex;
  gap: 32px;
  justify-content: center;
  margin-bottom: 40px;
  flex-wrap: wrap;
}

.footer-links a {
  font-size: 14px;
  /* theme token, not an absolute white: footer{background:var(--darker)} flips
     to #f0f0f0 under [data-theme="light"], where white links vanished. */
  color: var(--text-muted);
  text-decoration: none;
  transition: color 0.3s;
}

.footer-links a:hover {
  color: var(--brand-primary);
}

.footer-divider {
  height: 1px;
  background: var(--border-subtle);
  margin-bottom: 28px;
}

.footer-contact {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 2px;
}

/* ─── FOOTER LOGO FOLLOWS THE BAND (2026-09-13) ───
   The nav swaps its logo from a JS luminance sample because it floats over
   arbitrary sections. The footer paints its OWN band: the page theme token by
   default (footer{background:var(--darker)} flips to #f0f0f0 under
   [data-theme="light"]) or an explicit footer.theme override (.footer-dark /
   .footer-light). The lockup emits both variants; the band decides which one
   is visible. Before this, the footer hard-coded the light-on-dark variant and
   the wordmark vanished on every light-theme site.
   `:where()` zeroes the theme rule's specificity so a band override written
   later always wins, on light AND dark pages. */
:where([data-theme="light"]) footer .logo .logo-img-light { opacity: 0; }
:where([data-theme="light"]) footer .logo .logo-img-dark { opacity: 1; }
footer.footer-dark .logo .logo-img-light { opacity: 1; }
footer.footer-dark .logo .logo-img-dark { opacity: 0; }
footer.footer-light .logo .logo-img-light { opacity: 0; }
footer.footer-light .logo .logo-img-dark { opacity: 1; }
footer.footer-dark {
  background: #0b0b0d;
  color: #f5f5f7;
  --text: #f5f5f7;
  --text-secondary: rgba(255, 255, 255, 0.78);
  --text-muted: rgba(255, 255, 255, 0.62);
  --border-subtle: rgba(255, 255, 255, 0.1);
  --border-medium: rgba(255, 255, 255, 0.2);
}
footer.footer-light {
  background: #f5f5f7;
  color: #1d1d1f;
  --text: #1d1d1f;
  --text-secondary: rgba(0, 0, 0, 0.72);
  --text-muted: rgba(0, 0, 0, 0.56);
  --border-subtle: rgba(0, 0, 0, 0.08);
  --border-medium: rgba(0, 0, 0, 0.16);
}

/* ─── FOOTER v2 (globals.footer: tagline / columns / social / form / live) ─── */
footer.footer-v2 { text-align: left; padding: 64px 48px 40px; }
.footer-v2 .footer-inner { max-width: 1180px; margin: 0 auto; }
.footer-v2 .footer-top { display: grid; grid-template-columns: 1.2fr 1fr; gap: 48px; align-items: start; padding-bottom: 40px; border-bottom: 1px solid var(--border-subtle); }
.footer-v2 .footer-logo { justify-content: flex-start; margin-bottom: 20px; }
.footer-v2 .footer-tagline { font-size: clamp(24px, 3vw, 34px); font-weight: 600; letter-spacing: -0.02em; line-height: 1.15; color: var(--text); max-width: 18em; margin: 0 0 20px; }
.footer-v2 .footer-social { display: flex; gap: 12px; }
.footer-v2 .footer-social a { width: 36px; height: 36px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; color: var(--text-muted); border: 1px solid var(--border-medium); transition: color 0.2s, border-color 0.2s; }
.footer-v2 .footer-social a:hover { color: var(--brand-primary); border-color: var(--brand-primary); }
.footer-v2 .footer-social svg { width: 18px; height: 18px; fill: currentColor; }
.footer-v2 .footer-form { width: 100%; max-width: 460px; justify-self: end; }
.footer-v2 .footer-form-title { font-size: 17px; font-weight: 600; margin: 0 0 12px; color: var(--text); }
.footer-v2 .footer-live { padding: 36px 0; border-bottom: 1px solid var(--border-subtle); }
.footer-v2 .footer-live-title { font-size: 13px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-muted); margin: 0 0 16px; }
.footer-v2 .footer-live-cards { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; }
.footer-v2 .footer-live-card { display: flex; flex-direction: column; gap: 4px; padding: 18px 20px; border-radius: 14px; background: rgba(127, 127, 127, 0.1); color: var(--text); text-decoration: none; transition: transform 0.2s, background 0.2s; }
.footer-v2 a.footer-live-card:hover { transform: translateY(-2px); background: rgba(127, 127, 127, 0.16); }
.footer-v2 .footer-live-meta { font-size: 13px; font-weight: 600; color: var(--brand-primary); }
.footer-v2 .footer-live-name { font-size: 16px; font-weight: 600; line-height: 1.3; }
.footer-v2 .footer-live-sub { font-size: 13px; color: var(--text-muted); }
.footer-v2 .footer-columns { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 32px; padding: 36px 0; border-bottom: 1px solid var(--border-subtle); }
.footer-v2 .footer-col-title { font-size: 13px; font-weight: 600; margin: 0 0 10px; color: var(--text); }
.footer-v2 .footer-col a { display: block; font-size: 14px; color: var(--text-muted); text-decoration: none; padding: 4px 0; transition: color 0.2s; }
.footer-v2 .footer-col a:hover { color: var(--brand-primary); }
.footer-v2 .footer-bottom { display: flex; justify-content: space-between; align-items: center; gap: 24px; flex-wrap: wrap; padding-top: 24px; }
.footer-v2 .footer-links { margin: 0; justify-content: flex-start; gap: 20px; }
.footer-v2 .footer-contact { font-family: inherit; font-size: 12px; text-transform: none; letter-spacing: 0; max-width: 64ch; line-height: 1.5; }
@media (max-width: 900px) {
  footer.footer-v2 { padding: 48px 24px 32px; }
  .footer-v2 .footer-top { grid-template-columns: 1fr; gap: 32px; }
  .footer-v2 .footer-form { justify-self: start; }
  .footer-v2 .footer-live-cards, .footer-v2 .footer-columns { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 560px) {
  .footer-v2 .footer-live-cards, .footer-v2 .footer-columns { grid-template-columns: 1fr; }
}

/* ─── RESPONSIVE — 1024px ─── */
@media (max-width: 1024px) {
.org-grid {
    grid-template-columns: repeat(2, 1fr);
  }
.connexions-layout {
    grid-template-columns: 1fr;
    gap: 40px;
  }
.platform-grid {
    grid-template-columns: repeat(2, 1fr);
  }
.pipeline-stages {
    flex-direction: column;
    gap: 12px;
  }
.pipe-metrics {
    grid-template-columns: repeat(2, 1fr);
  }
.analytics-layout {
    grid-template-columns: 1fr;
    gap: 40px;
  }
.convergence-container {
    max-width: 100%;
    height: 400px;
    margin: 0 auto;
  }
.integration-grid {
    grid-template-columns: repeat(2, 1fr);
  }
.decision-grid {
    grid-template-columns: 1fr;
  }
.enrich-wrap {
    flex-direction: column;
  }
.enrich-sidebar {
    width: 100%;
    flex-direction: row;
    flex-wrap: wrap;
  }
.convo-wrap {
    grid-template-columns: 1fr;
  }
.convo-panel {
    order: -1;
  }
.roi-container {
    height: 380px;
  }
}

/* ─── RESPONSIVE — 768px ─── */
@media (max-width: 768px) {
nav {
    padding: 14px 20px;
  }
.nav-links {
    display: none;
  }
.hamburger {
    display: flex;
  }
section:not(.ai-section-wrapper) {
    padding: 80px 20px;
  }
/* P1.4 Concept rhythm mobile overrides */
:root {
    --pad-medium:    48px;
    --pad-tall:      72px;
    --pad-xl:        96px;
  }
.org-grid {
    grid-template-columns: 1fr;
  }
.hero-buttons {
    flex-direction: column;
    align-items: center;
  }
footer {
    padding: 48px 20px 32px;
  }
.platform-grid {
    grid-template-columns: 1fr;
  }
.pipe-metrics {
    grid-template-columns: 1fr;
  }
.integration-grid {
    grid-template-columns: repeat(2, 1fr);
  }
.convergence-container {
    height: 320px;
  }
.enrich-canvas-wrap canvas {
    height: 400px;
  }
.convo-canvas-wrap canvas {
    height: 360px;
  }
}

/* ─── PREFERS REDUCED MOTION ─── */
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
.reveal,
.reveal-left,
.reveal-right,
.reveal-scale,
.reveal-blur {
    opacity: 1;
    transform: none;
    filter: none;
    transition: none;
  }
.hero-buttons {
    animation: none;
    opacity: 1;
    transform: none;
  }
.hero-word-reveal .word {
    animation: none;
    opacity: 1;
    transform: none;
  }
}

/* ─── AI Custom Section Iframe Sandbox ─────────────────────────────── */
/* No line-height:0 here: the sandbox iframe is display:block (pages.js
   frameStyle) so there is no inline gap to kill, while the wrapper also
   wraps INLINE text sections — inheriting 0 clipped/garbled any section
   that didn't set its own line-height (live repro 2026-08-31). */
.ai-custom-section-wrapper { position: relative; width: 100%; overflow: hidden; margin: 0; padding: 0; }

/* App-flow sections (data-flow="app") — Slice 1. Sticky rails + internal
   scroll panes need overflow-y visible; overflow-x:clip keeps the
   horizontal-blowout protection WITHOUT creating a scroll container or a
   sticky containing block (unlike overflow:hidden). Applied in BOTH draft
   (.section-shell--app) and live (.ai-custom-section-wrapper--app) so
   preview and published behavior match. */
.ai-custom-section-wrapper--app,
.section-shell--app { overflow: visible; overflow-x: clip; line-height: normal; }

/* Coexistence with the FULL top chrome (Slice 1.1): an app-shell FIRST
   section must clear the fixed nav or the page links/cart float over the
   dashboard header (live repro). Only under full chrome — 'minimal' is an
   in-flow sticky bar (takes its own space) and 'none' has nothing to clear. */
body:not(.nrl-chrome-minimal):not(.nrl-chrome-none) .ai-custom-section-wrapper--app[data-position="first"],
body:not(.nrl-chrome-minimal):not(.nrl-chrome-none) .section-shell--app[data-position="first"] {
  padding-top: var(--nav-height);
}

/* Section-internal <nav> (app-flow side rails / tab bars) must NOT inherit
   the fixed page-chrome nav geometry (the global `nav{position:fixed;...}`
   above targets the element selector and used to be masked by the live
   path's nav-strip, which app-flow sections are exempt from). Placed late
   in the file so it wins same-specificity ties; the section's own ID-scoped
   CSS (1,x,x) still restyles its nav freely. */
[data-section-id] nav {
  position: static;
  top: auto;
  left: auto;
  right: auto;
  z-index: auto;
  display: block;
  padding: 0;
  background: none;
  border-bottom: none;
  backdrop-filter: none;
  transition: none;
}

/* App-rail switch-view buttons — defensive layout anchored to the stable
   [data-action="switch-view"] contract (the model's class names vary).
   The model sometimes emits `.nav-label{width:0;overflow:hidden;text-overflow:ellipsis}`
   which collapses labels to nothing. width:auto!important defeats any
   ID-scoped or inline width:0 rule; min-width:0!important prevents flex
   children from refusing to shrink below their intrinsic width. The button
   itself is forced to width:100% and flex so the icon+label sit side-by-side.
   Live repro: leaderboard rail showed "Play…"/"Tour…" (truncated to ~2 chars). */
/* The model wraps the switch-view buttons in arbitrary nested containers
   (live repro: section.esports-nav-rail > div.rail[133px] > nav.navigation-links[85px])
   that shrink-wrap NARROWER than the 16rem rail column — so the label
   ellipsised to "L…"/"P…"/"T…" even though the DOM text is full. Force every
   container element inside the rail to fill the column and stretch its flex
   children, at ANY nesting depth. :where() keeps specificity 0 so the
   section's own inner rules still win where they don't fight the column width;
   the !important defeats model ID-scoped widths. Scoped to the rail, which is
   ALWAYS a vertical column, so width:100% is always the correct answer. */
[data-section-region="rail"] :where(nav,
ul,
ol,
div,
section,
header,
footer) {
  width: 100% !important;
  max-width: 100% !important;
  align-items: stretch !important;
  box-sizing: border-box;
}

[data-section-region="rail"] nav { width: 100% !important; }

[data-section-region="rail"] [data-action="switch-view"] {
  display: flex !important;
  align-items: center !important;
  gap: 0.6rem;
  width: 100% !important;
  min-width: 0;
  text-align: left;
}

/* Make every direct child min-width:0 (prevents flex overflow) and
   width:auto (defeats the model's width:0 trick). We intentionally do NOT
   force flex:1 on individual children — the button's width:100% provides
   the room; children size to their own content so the icon/indicator/badge
   stay compact while the label grows to fill the rest naturally. */
[data-section-region="rail"] [data-action="switch-view"] > * {
  min-width: 0;
  width: auto !important;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Leading SVG icon must never shrink or be hidden by the ellipsis rule. */
[data-section-region="rail"] [data-action="switch-view"] > svg {
  flex: 0 0 auto;
  overflow: visible;
}

/* View panels — display-gated by the switch-view dispatcher. The [hidden]
   attribute is the no-JS/boot fallback; .is-active is the runtime truth.
   !important is REQUIRED: section CSS is ID-scoped (#s_… .panel = 1,x,x
   specificity) and beats both an unmarked platform rule and the UA's
   [hidden] style — live repro: all views rendered stacked at once. Only
   NON-active panels are hidden; the active panel keeps the section's own
   display value (grid/flex/…), which a forced display:block would clobber. */
[data-view-group] [data-view]:not(.is-active) { display: none !important; }

/* …and the ACTIVE panel is force-revealed (models author their own
   display:none defaults with private "active" conventions — live repro:
   zero panels visible after a switch). revert = UA default (block), so a
   panel keeps layout via its inner wrapper; the prompt directive tells the
   model to put grid/flex there, never on [data-view] itself. */
[data-view-group] [data-view].is-active { display: revert !important; }

/* Modal reveal gate — same platform-owned bidirectional gate as view panels
   (section CSS is #id-scoped and beats any unmarked rule). Non-open modals
   are hidden; an open modal reveals with its own layout via revert. */
[data-modal-id]:not(.is-open) { display: none !important; }

[data-modal-id].is-open { display: revert !important; }

/* Section-view gate — page-level multi-view for app-flow pages (data-flow="app").
   switch-view dispatcher sets/clears .nrl-view-active on [data-section-view] shells.
   DISTINCT from the in-section panel gate above ([data-view-group]/[data-view]/.is-active)
   — different attribute names and different toggle class, zero selector overlap.
   !important is REQUIRED: section CSS is #id-scoped (specificity 1,x,x) and beats both
   any unmarked platform rule AND the UA [hidden] attribute rule.
   revert (not block) preserves the section's own display value (grid/flex/…). */
[data-section-view]:not(.nrl-view-active) { display: none !important; }

[data-section-view].nrl-view-active { display: revert !important; }

/* Rail region — fixed left sidebar column without touching <main> structure.
   body.nrl-has-rail is stamped by the renderer when any section has data-section-region="rail".
   [data-section-id]:not([data-section-region]) targets top-level section wrappers that
   carry no region assignment — safe because data-section-id and data-section-region are
   always on the SAME outermost shell element (never nested). Collapses to static below 900px. */
body.nrl-has-rail [data-section-region="rail"] {
  position: fixed; left: 0; top: var(--nrl-top-inset, 0px); bottom: var(--nrl-bottom-inset, 0px);
  width: var(--nrl-rail-w, 16rem); z-index: 50; overflow-y: auto;
}

/* OFFSET **AND** SHRINK (live fix, member-bookings 2026-09-03).
   margin-left alone was not enough: .ai-custom-section-wrapper below sets
   width:100% — 100% of <main>, i.e. the FULL viewport — so the used width
   stayed at the viewport width and the margin pushed the whole content column
   a rail-width PAST the right edge (measured: rail 0→256, content 256→1536 at
   a 1280px viewport). The wrapper's own overflow:hidden then clipped the
   overhang, so a composed app's last table column (the Edit / Cancel row
   actions) simply disappeared instead of producing a usable scrollbar.
   width:auto lets the block resolve to the space that is actually left;
   max-width holds the line for any descendant that re-asserts a percentage
   width. No !important needed — this selector already outranks the wrapper's
   single class. */
body.nrl-has-rail [data-section-id]:not([data-section-region]) {
  margin-left: var(--nrl-rail-w, 16rem);
  width: auto;
  max-width: calc(100% - var(--nrl-rail-w, 16rem));
  box-sizing: border-box;
}

@media (max-width: 900px) {
body.nrl-has-rail [data-section-region="rail"] { position: static; width: auto; bottom: auto; }
/* Rail is back in flow — release the offset AND the clamp together. */
body.nrl-has-rail [data-section-id]:not([data-section-region]) { margin-left: 0; width: auto; max-width: 100%; }
}

/* Header region — pinned top bar (data-section-region="header").
   body.nrl-has-header is stamped by the renderer when any section has that region value.
   FIXED, not sticky (A3 live-catch): sticky is DOM-order-dependent — a header
   section appended at the end of <main> would sit at the bottom of the document
   and never pin. Fixed + platform-pinned height makes it order-independent and
   enforces the slim-bar contract (tall model content is clipped), exactly like
   the bottom bar. Sits right of the rail via --nrl-left-inset. */
body.nrl-has-header [data-section-region="header"] {
  position: fixed;
  top: var(--nrl-top-inset, 0px);
  left: var(--nrl-left-inset, 0px);
  right: 0;
  height: var(--nrl-header-h, 4rem);
  overflow: hidden;
  z-index: 50;
}

/* Content offset below ALL pinned top chrome (site nav + header bar).
   --nrl-content-top defaults to the chrome inset; header pages add the bar. */
body.nrl-has-header { --nrl-content-top: calc(var(--nrl-top-inset, 0px) + var(--nrl-header-h, 4rem)); }

/* ═══════════════════════════════════════════════════════════════
   A3 — Chrome ↔ Regions Cooperation (Task 1)
   Inset model, bottom region, app-window clamp, footer/footer.
   ALL rules are gated on nrl-has-* body classes stamped only by
   the renderer when region sections exist. Pages WITHOUT these
   classes are byte-identical in behavior: --nrl-top-inset and
   --nrl-bottom-inset have 0px fallbacks, so every var() resolves
   to 0 = no layout change.
   Z-INDEX NOTE: full nav = 1000 (styles.css:226); mobile menu/hamburger
   = 999/1001; pres-nav (minimal chrome) = 100 INLINE (buildLogoOnlyNav:566).
   Regions must paint UNDER both navs → rail/header = 50, bottom = 40.
   ═══════════════════════════════════════════════════════════════ */

/* ── Inset variables ───────────────────────────────────────────
   Full chrome: fixed nav is var(--nav-height) = 80px.
   Minimal chrome: logo-only sticky bar pinned to --nrl-minimal-nav-h.
   Bottom region: --nrl-bottom-h = 4rem by default.
   Grouped selectors cover all three region-bearing page types. */
body.nrl-has-rail:not(.nrl-chrome-minimal):not(.nrl-chrome-none),
body.nrl-has-header:not(.nrl-chrome-minimal):not(.nrl-chrome-none),
body.nrl-has-bottom:not(.nrl-chrome-minimal):not(.nrl-chrome-none) {
  --nrl-top-inset: var(--nav-height);
}

body.nrl-has-rail.nrl-chrome-minimal,
body.nrl-has-header.nrl-chrome-minimal,
body.nrl-has-bottom.nrl-chrome-minimal {
  --nrl-top-inset: var(--nrl-minimal-nav-h, 4.5rem);
}

body.nrl-has-bottom { --nrl-bottom-inset: var(--nrl-bottom-h, 4rem); }

/* ── Logo-only nav height pin (region pages only) ───────────────
   buildLogoOnlyNav inline styles (pages.js:566):
     position:sticky; top:0; z-index:100; padding:16px 24px; background:transparent.
   height/box-sizing/flex here do NOT fight those properties.
   Pinning height to --nrl-minimal-nav-h makes the variable match the
   actual rendered bar so downstream inset math is always correct. */
body.nrl-has-rail nav.pres-nav,
body.nrl-has-header nav.pres-nav,
body.nrl-has-bottom nav.pres-nav {
  height: var(--nrl-minimal-nav-h, 4.5rem);
  box-sizing: border-box;
  display: flex;
  align-items: center;
  /* A3.1: on region pages the minimal bar becomes FIXED (it is sticky/in-flow
     elsewhere) so ALL visible chrome overlays uniformly and content offsets
     via the SAME inset math as the full nav — otherwise main's margin-top
     would double-count the in-flow bar. Inline style sets position:sticky;
     override needs !important (inline wins otherwise). */
  position: fixed !important;
  top: 0;
  left: 0;
  right: 0;
}

/* ── Left inset variable (rail offset for bottom bar + footer) ──
   Resets to 0 at 900px so bottom bar and footer go full-width on
   mobile (tab-bar pattern); rail's static collapse is unchanged. */
body.nrl-has-rail { --nrl-left-inset: var(--nrl-rail-w, 16rem); }

@media (max-width: 900px) {
body.nrl-has-rail { --nrl-left-inset: 0px; }
}

/* ── Bottom region: fixed tab bar / status bar ──────────────────
   Stays fixed at bottom viewport edge on all screen sizes (tab-bar
   pattern). Respects rail left offset on desktop via --nrl-left-inset
   (which resets to 0 at 900px, so mobile = full-width).
   z-index 40: below rail/header (50) and well below site chrome (100+). */
body.nrl-has-bottom [data-section-region="bottom"] {
  position: fixed;
  left: var(--nrl-left-inset, 0px);
  right: 0;
  bottom: 0;
  height: var(--nrl-bottom-h, 4rem);
  overflow: hidden;
  z-index: 40;
}

/* ── Content clearances (main = single insertion point) ─────────
   padding-top on <main> offsets ALL content sections below visible
   chrome without inserting gaps between stacked sections.
   Scoped to non-none chrome so chrome:'none' pages (--nrl-top-inset
   unset → 0px) are untouched. */
body.nrl-has-rail:not(.nrl-chrome-none) main,
body.nrl-has-header main {
  margin-top: var(--nrl-content-top, var(--nrl-top-inset, 0px));
}

/* A3.1 — app-window scroll model. Rail pages lock PAGE scroll: the window
   never scrolls (so the footer can never slide over the app and the fixed
   nav never shrink-jumps); <main> becomes the scroll container sized to the
   space between top chrome and the bottom bar. The renderer relocates the
   site footer INSIDE <main> on these pages so it sits at the true end of
   the scrollable content column. margin-top (not padding) above keeps the
   scrollport itself below the chrome. */
body.nrl-has-rail {
  height: 100dvh;
  overflow: hidden;
}

body.nrl-has-rail main {
  height: calc(100dvh - var(--nrl-content-top, var(--nrl-top-inset, 0px)) - var(--nrl-bottom-inset, 0px));
  box-sizing: border-box;
  overflow-y: auto;
}

/* Suppress the per-shell first-section clearance on region pages
   to avoid double-stacking with the main padding-top above.
   !important is required: the app-shell clearance rule above
   (body:not():not() .ai-custom-section-wrapper--app[data-position="first"],
   specificity 0,4,1) BEATS these body.nrl-has-* selectors (0,3,1) —
   without it the RAIL's own shell (position "first") gets 80px of
   clearance padding inside the fixed rail on full-chrome pages. */
body.nrl-has-rail .section-shell--app[data-position="first"],
body.nrl-has-rail .ai-custom-section-wrapper--app[data-position="first"],
body.nrl-has-rail .ai-section-wrapper[data-position="first"],
body.nrl-has-header .section-shell--app[data-position="first"],
body.nrl-has-header .ai-custom-section-wrapper--app[data-position="first"],
body.nrl-has-header .ai-section-wrapper[data-position="first"] { padding-top: 0 !important; }

/* Clearance for content above the pinned bottom bar. */
body.nrl-has-bottom main { padding-bottom: var(--nrl-bottom-inset, 0px); }

/* ── App-window panel height clamp ─────────────────────────────
   [data-section-view] panels sized to height:100dvh function as app
   windows. Under visible chrome they extend behind the fixed nav and/or
   bottom bar. max-height (NOT height) shrinks windows that overflow;
   panels with height:auto / intrinsic size are unaffected.
   !important is required: section CSS is #id-scoped (specificity 1,x,x)
   and beats unmarked platform rules. */
/* ONE scroll container (A3.1 owner-catch: "content is still cut off").
   Model view-panels bake height:100dvh + overflow:auto (the pre-regions
   app-WINDOW contract) — inside the scrolling <main> that made a second,
   nested scroll region whose content looked amputated at the footer line.
   Force panels to NATURAL height: main is the only scroller, the full view
   content flows, and the footer sits after it. min-height keeps sparse
   views filling one window so the footer never rides up mid-screen.
   (overflow:auto baked in section CSS is inert once height is auto.) */
body.nrl-has-rail [data-section-view] > *,
body.nrl-has-header [data-section-view] > * {
  height: auto !important;
  max-height: none !important;
  min-height: calc(100dvh - var(--nrl-content-top, var(--nrl-top-inset, 0px)) - var(--nrl-bottom-inset, 0px)) !important;
}

/* Pinned region shells: inner roots fill the SHELL exactly (rail inner bakes
   height:100dvh which would overflow the inset shell and push the pinned
   user chip below the fold; bars likewise). */
body.nrl-has-rail [data-section-region="rail"] > * {
  height: 100% !important;
  min-height: 0 !important;
}

body.nrl-has-header [data-section-region="header"] > *,
body.nrl-has-bottom [data-section-region="bottom"] > * {
  height: 100% !important;
  min-height: 0 !important;
}

/* ── Footer cooperation ─────────────────────────────────────────
   Rail pages: footer clears the fixed rail column.
   --nrl-left-inset resets to 0px at 900px (declared above) so the
   footer is full-width on mobile without an extra media query. */
body.nrl-has-rail footer[role="contentinfo"] {
  margin-left: var(--nrl-left-inset, 0px);
}

/* ── Mobile rail dead-space fix ─────────────────────────────────
   Rail archetypes write height:100dvh on their inner root element.
   When the rail collapses to position:static at 900px that
   viewport-tall height persists as dead whitespace in the layout.
   Force height:auto so the collapsed rail shell is only as tall as
   its content. */
@media (max-width: 900px) {
body.nrl-has-rail [data-section-region="rail"] { height: auto; }
body.nrl-has-rail [data-section-region="rail"] > * { height: auto !important; min-height: 0 !important; }
}

/* Presentation mode transparent nav */
.pres-nav {
  background: transparent !important;
  border-bottom: none !important;
  backdrop-filter: none !important;
}

.ai-section-iframe { width: 100%; border: none; display: block; }

/* ─── AI-section isolation: legacy component classes must not reach inside ───
   This file is the legacy tenant marketing template. Its component rules are
   bare single classes (specificity 0,1,0) on GENERIC names — `.stat-label`,
   `.card-*`, `.hero-*`, `.section-desc`… — authored for a dark page. An
   AI-generated section that happens to reuse one of those names inherits the
   legacy paint, and because a DIRECT rule always beats INHERITANCE regardless
   of specificity, it wins even when the section's own CSS colours an ancestor.

   Live defect (tenant storek, `storek-pitch-deck` slide 3, 2026-08-18): the
   section put `.stat-label` spans inside a LIGHT card and coloured the parent
   `.stat-row{color:#1f2937}`. Nothing in the section CSS set the label's
   colour, so `.stat-label{color:rgba(255,255,255,0.35)}` (line 1031) applied —
   live computed rgba(255,255,255,0.35) — ghost-white text on a white card. The
   static contrast validator/healer cannot see this: it only parses the
   section's own CSS.

   `section:not(.ai-section-wrapper)` (line 1040) already scopes the SECTION
   rules out of AI sections; the component rules never got the same treatment.
   Anchored on `[data-section-id]` (not `.ai-section-wrapper`) so it covers BOTH
   render paths — the live wrapper chain and the draft/inline `.section-shell`,
   which has no outer wrapper. Same anchor + late placement as the
   `[data-section-id] nav` precedent above.

   Specificity is (0,2,0) — beats every bare-class legacy rule, and loses to the
   section's own CSS, which the renderer scopes to `#<section-id>` (1,x,y). So
   authored section styling still wins; only the accidental legacy bleed is cut.

   DELIBERATELY EXCLUDED — `.reveal` / `.reveal-left` / `.reveal-right` /
   `.reveal-scale` / `.reveal-blur` (+ their `.visible` pairs). Those are a
   SUPPORTED AI-section contract: main.js flips `.visible` and the renderer
   appends a per-section `#<id> .reveal.visible{opacity:1}` override
   (src/rendering/pages.js ~line 928). Neutralising their opacity would break
   scroll reveals. */
[data-section-id] .skip-link,
[data-section-id] .logo,
[data-section-id] .logo-icon,
[data-section-id] .nav-dropdown-trigger,
[data-section-id] .nav-dropdown-menu,
[data-section-id] .hamburger,
[data-section-id] .footer-divider,
[data-section-id] .footer-contact,
[data-section-id] footer {
  color: inherit;
  background: none;
  opacity: 1;
  /* `.highlight` and `.plat-num` are gradient-clipped text
     (-webkit-text-fill-color:transparent + background-clip:text). Resetting
     only `background` there would leave the fill transparent with no gradient
     behind it — invisible text. Both must be reset together. */
  -webkit-text-fill-color: currentColor;
  background-clip: border-box;
}

/* Decorative pseudo-elements attached to the same legacy component classes —
   `content:none` removes them outright rather than trying to un-paint them. */
[data-section-id] .nav-open::before {
  content: none;
}

/* `.nav-cta` paints with !important (line 413), so only !important can undo it
   inside a section. Kept in its own block — adding !important to the list above
   would let it beat the section's own ID-scoped CSS, which must stay in charge. */
[data-section-id] .nav-cta {
  background: none !important;
  color: inherit !important;
}
