/* ──────────────────────────────────────────────────────────────────────────
   tokens/index.css — single entry point for the three-axis token system.
   PostCSS resolves these @import directives at build time (postcss-import),
   so dist/tokens.css is a single concatenated file with NO runtime @import
   chain. See architecture.md §Token File Organization (lines 537–550).
   ────────────────────────────────────────────────────────────────────────── */

/* ──────────────────────────────────────────────────────────────────────────
   color-tokens.css — three-axis colour system, two-layer per Story 1.3 D1.

   Axes:        --color-{mode}-{aspect}-{surface}
                  mode    ∈ { light, dark }                        (data-theme on <html>)
                  aspect  ∈ { primary, secondary, accent, surface, text, border }
                  surface ∈ { base, enterprise, smb, developer, manifesto, dpp }
   Aliases:     semantic vocabulary consumed by component CSS
                (--surface-page, --ink-primary, --accent-eu-blue, …).

   Source-of-truth values: _bmad-output/implementation-artifacts/manifesto-preview.html
   (Tom-signed canonical visual reference — UX line 551).

   Mode resolution priority (architecture.md §Theme Detection 619–627):
     1. localStorage.theme  → :root[data-theme="dark"|"light"]
     2. prefers-color-scheme → @media block (only if user hasn't forced light)
     3. light (canonical fallback baked into :root)

   Story 1.3 declares ONLY the (aspect × surface) cells the manifesto-preview
   actually uses. Aspect drift (enterprise / smb / developer / dpp) lands in
   Stories 2.x / 3.x as those surfaces are built. Don't backfill.
   ────────────────────────────────────────────────────────────────────────── */

/* ┌────────────────────────────────────────────────────────────────────────┐
   │ Light mode — canonical fallback. Raw axis tokens.                      │
   └────────────────────────────────────────────────────────────────────────┘ */

:root {
  /* Native form controls / scrollbars match the active theme.
     Without this declaration browsers render scrollbars in their default
     light styling under data-theme="dark" — visible white slab on the page. */
  color-scheme: light dark;

  /* — surface aspect — */
  --color-light-surface-base:      #F6F6F5;  /* whitish-white substrate */
  --color-light-surface-card:      #FAFAFA;

  /* — text aspect — */
  --color-light-text-base:         #1C1C20;  /* anthracite, near-black */
  --color-light-text-secondary:    #4A4A52;
  --color-light-text-quiet:        #717178;

  /* — border aspect — */
  --color-light-border-quiet:      #E4E4E2;

  /* — accent aspect (structural-only — never on type fills) — */
  --color-light-accent-eu-blue:    #1B2D5C;  /* EU sovereign blue */
  --color-light-accent-eu-gold:    #A07C2C;  /* EU gold, AA-clean */
  --color-light-accent-eu-gold-foil: #C9A24A;  /* EU gold decorative */
  --color-light-accent-primary:    var(--color-light-accent-eu-blue);

  /* — secondary aspect (metallic finishes, structural-only) — */
  --color-light-secondary-platine: #B0B5BD;
  --color-light-secondary-steel:   #8A8E9A;

  /* — primary aspect — brand-mark channels, B&W mode-adaptive — */
  --color-light-primary-brand-bg:  #1C1C20;
  --color-light-primary-brand-fg:  #F6F6F5;

  /* — stigmergy texture (substrate dot-grid + waypoint marks + trails) — */
  --color-light-surface-grid-dot:  rgba(28, 28, 32, 0.07);

  /* ── Semantic aliases — manifesto-preview vocabulary ── */
  --surface-page:        var(--color-light-surface-base);
  --surface-card:        var(--color-light-surface-card);
  --rule-quiet:          var(--color-light-border-quiet);

  --ink-primary:         var(--color-light-text-base);
  --ink-secondary:       var(--color-light-text-secondary);
  --ink-quiet:           var(--color-light-text-quiet);

  --accent-eu-blue:      var(--color-light-accent-eu-blue);
  --accent-eu-gold:      var(--color-light-accent-eu-gold);
  --accent-eu-gold-foil: var(--color-light-accent-eu-gold-foil);
  --accent-primary:      var(--color-light-accent-primary);

  --metal-platine:       var(--color-light-secondary-platine);
  --metal-steel:         var(--color-light-secondary-steel);

  --brand-bg:            var(--color-light-primary-brand-bg);
  --brand-fg:            var(--color-light-primary-brand-fg);

  --grid-dot:            var(--color-light-surface-grid-dot);
  --trail-stroke:        var(--rule-quiet);
  --waypoint-fill:       var(--accent-primary);

  /* Text colour for content painted on --accent-primary fills (CTAs etc.).
     White on EU blue clears 8.6:1 (WCAG AAA). Decoupled from --surface-page
     because the surface alias may not always invert the accent. */
  --ink-on-accent:       #FFFFFF;
}

/* ┌────────────────────────────────────────────────────────────────────────┐
   │ Dark mode — explicit user toggle (data-theme="dark") wins outright.    │
   │ Redeclares both raw axis tokens AND the aliases that flip between      │
   │ EU-blue/EU-gold and brand-bg/brand-fg.                                 │
   └────────────────────────────────────────────────────────────────────────┘ */

:root[data-theme="dark"] {
  /* Pin native form controls / scrollbars to dark even when OS prefers light. */
  color-scheme: dark;

  --color-dark-surface-base:        #141414;  /* deep anthracite */
  --color-dark-surface-card:        #1C1C20;

  --color-dark-text-base:           #F0F0EE;  /* whitish-white, off-neutral */
  --color-dark-text-secondary:      #C4C4C6;
  --color-dark-text-quiet:          #888890;

  --color-dark-border-quiet:        #282828;

  --color-dark-accent-eu-blue:      #5D78B5;  /* lighter signal in dark */
  --color-dark-accent-eu-gold:      #D9B65C;
  --color-dark-accent-eu-gold-foil: #E0C77A;
  --color-dark-accent-primary:      var(--color-dark-accent-eu-gold);

  --color-dark-secondary-platine:   #5A5A62;
  --color-dark-secondary-steel:     #484850;

  --color-dark-primary-brand-bg:    #F0F0EE;
  --color-dark-primary-brand-fg:    #1C1C20;

  --color-dark-surface-grid-dot:    rgba(240, 240, 238, 0.05);

  /* Aliases re-bind to dark-side raw tokens. */
  --surface-page:        var(--color-dark-surface-base);
  --surface-card:        var(--color-dark-surface-card);
  --rule-quiet:          var(--color-dark-border-quiet);

  --ink-primary:         var(--color-dark-text-base);
  --ink-secondary:       var(--color-dark-text-secondary);
  --ink-quiet:           var(--color-dark-text-quiet);

  --accent-eu-blue:      var(--color-dark-accent-eu-blue);
  --accent-eu-gold:      var(--color-dark-accent-eu-gold);
  --accent-eu-gold-foil: var(--color-dark-accent-eu-gold-foil);
  --accent-primary:      var(--color-dark-accent-primary);

  --metal-platine:       var(--color-dark-secondary-platine);
  --metal-steel:         var(--color-dark-secondary-steel);

  --brand-bg:            var(--color-dark-primary-brand-bg);
  --brand-fg:            var(--color-dark-primary-brand-fg);

  --grid-dot:            var(--color-dark-surface-grid-dot);
  /* --trail-stroke and --waypoint-fill chain via their own aliases — no redeclare. */

  /* On dark, --accent-primary becomes EU gold; deep anthracite text on EU
     gold clears 8.5:1 (WCAG AAA). */
  --ink-on-accent:       #1C1C20;
}

/* ┌────────────────────────────────────────────────────────────────────────┐
   │ Dark mode — system preference, only when user hasn't forced light.    │
   │ Same raw axis tokens + aliases as the explicit branch above.          │
   └────────────────────────────────────────────────────────────────────────┘ */

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;

    --color-dark-surface-base:        #141414;
    --color-dark-surface-card:        #1C1C20;

    --color-dark-text-base:           #F0F0EE;
    --color-dark-text-secondary:      #C4C4C6;
    --color-dark-text-quiet:          #888890;

    --color-dark-border-quiet:        #282828;

    --color-dark-accent-eu-blue:      #5D78B5;
    --color-dark-accent-eu-gold:      #D9B65C;
    --color-dark-accent-eu-gold-foil: #E0C77A;
    --color-dark-accent-primary:      var(--color-dark-accent-eu-gold);

    --color-dark-secondary-platine:   #5A5A62;
    --color-dark-secondary-steel:     #484850;

    --color-dark-primary-brand-bg:    #F0F0EE;
    --color-dark-primary-brand-fg:    #1C1C20;

    --color-dark-surface-grid-dot:    rgba(240, 240, 238, 0.05);

    --surface-page:        var(--color-dark-surface-base);
    --surface-card:        var(--color-dark-surface-card);
    --rule-quiet:          var(--color-dark-border-quiet);

    --ink-primary:         var(--color-dark-text-base);
    --ink-secondary:       var(--color-dark-text-secondary);
    --ink-quiet:           var(--color-dark-text-quiet);

    --accent-eu-blue:      var(--color-dark-accent-eu-blue);
    --accent-eu-gold:      var(--color-dark-accent-eu-gold);
    --accent-eu-gold-foil: var(--color-dark-accent-eu-gold-foil);
    --accent-primary:      var(--color-dark-accent-primary);

    --metal-platine:       var(--color-dark-secondary-platine);
    --metal-steel:         var(--color-dark-secondary-steel);

    --brand-bg:            var(--color-dark-primary-brand-bg);
    --brand-fg:            var(--color-dark-primary-brand-fg);

    --grid-dot:            var(--color-dark-surface-grid-dot);

    --ink-on-accent:       #1C1C20;
  }
}

/* ──────────────────────────────────────────────────────────────────────────
   type-tokens.css — three-axis typography system, two-layer per Story 1.3 D1.

   Raw axis layer:  --type-{mode}-text-{surface}, --type-size-*, --type-weight-*,
                    --type-line-height-*. Mode axis here mostly tweaks weight/
                    tracking to compensate for substrate contrast; full mode
                    drift lands when actual surfaces consume it.
   Semantic aliases: font stacks (--font-serif, --font-sans, --font-mono) +
                     reading measure (--measure). Component CSS consumes these.

   Per-locale micro-adjustments (German tracking, French line-height) are
   placeholder-stubbed; Story 2.5 (locale switcher) wires lang-attribute
   selectors. NO live html[lang="…"] selectors at this story.

   Source-of-truth values: manifesto-preview.html lines 50–52, 282–303.
   ────────────────────────────────────────────────────────────────────────── */

:root {
  /* — raw axis layer: text aspect (mode dimension) — */
  --type-light-text-base:       400;   /* regular weight, light substrate */
  --type-dark-text-base:        400;   /* same — anthracite ink unchanged */

  /* — raw axis layer: typographic scale — */
  --type-size-h1-base:          clamp(2rem, 6vw, 3.25rem);
  --type-size-body-base:        1.0625rem;        /* 17px mobile */
  --type-size-body-comfortable: 1.125rem;         /* ≥768px */
  --type-size-eyebrow-base:     0.75rem;
  --type-size-meta-base:        0.8125rem;
  --type-size-small-base:       0.875rem;

  --type-weight-regular:        400;
  --type-weight-medium:         500;
  --type-weight-semibold:       600;

  --type-line-height-tight:     1.12;
  --type-line-height-base:      1.65;
  --type-line-height-loose:     1.7;

  /* — semantic alias layer: font stacks (system-font fallback chain
       backs the @font-face declarations below). — */
  --font-serif: Charter, "Iowan Old Style", "Source Serif Pro", "Source Serif", Cambria, Georgia, "Times New Roman", Times, serif;
  --font-sans:  system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-mono:  "Geist Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;

  /* — reading measure — */
  --measure: 60rem;
}

/* ──────────────────────────────────────────────────────────────────────────
   Self-hosted WOFF2 declarations — Story 1.4 D2 path (a). UX-DR8.

   • Charter (regular, italic, bold) — Bitstream Charter license, free
     redistribution; procured from practicaltypography.com 2026-05-02.
   • Geist Mono (regular)            — SIL OFL 1.1, Vercel/basement.studio.

   Operational notes:
   • font-display: swap — system-fallback renders immediately, WOFF2 swaps in
     when ready. Avoids invisible-text FOUT; CLS impact is minimal because
     Charter and Iowan Old Style have similar metrics.
   • License trail: public/fonts/LICENSE.md (notice preservation required by
     the Bitstream Charter license; OFL bundling clause for Geist Mono).
   • <link rel="preload" as="font" type="font/woff2" crossorigin> tags for
     each face are emitted by templates/layouts/base-layout.eta.
   ────────────────────────────────────────────────────────────────────────── */

@font-face {
  font-family: "Charter";
  src: url("/fonts/charter-regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Charter";
  src: url("/fonts/charter-italic.woff2") format("woff2");
  font-weight: 400;
  font-style: italic;
  font-display: swap;
}

@font-face {
  font-family: "Charter";
  src: url("/fonts/charter-bold.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Geist Mono";
  src: url("/fonts/geist-mono-regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

/* ┌────────────────────────────────────────────────────────────────────────┐
   │ Per-locale micro-adjustments — STUBS only. Story 2.5 wires these.     │
   ├────────────────────────────────────────────────────────────────────────┤
   │ TODO Story 2.5: html[lang="de"] { --type-tracking-tight: -0.01em; }   │
   │ TODO Story 2.5: html[lang="fr"] { --type-line-height-loose: 1.75;  }  │
   └────────────────────────────────────────────────────────────────────────┘ */

/* ──────────────────────────────────────────────────────────────────────────
   space-tokens.css — spacing scale. Mode axis irrelevant for spacing;
   single layer suffices.

   Raw axis layer:    --space-base-{1..7}  (canonical scale)
   Semantic aliases:  --space-{1..7}        (preserves manifesto-preview's
                                              component CSS unchanged)

   Source-of-truth values: manifesto-preview.html lines 55–61.
   ────────────────────────────────────────────────────────────────────────── */

:root {
  /* — raw axis layer — */
  --space-base-1: 0.5rem;
  --space-base-2: 1rem;
  --space-base-3: 1.5rem;
  --space-base-4: 2rem;
  --space-base-5: 3rem;
  --space-base-6: 4.5rem;
  --space-base-7: 6.5rem;

  /* — semantic alias layer (manifesto-preview vocabulary) — */
  --space-1: var(--space-base-1);
  --space-2: var(--space-base-2);
  --space-3: var(--space-base-3);
  --space-4: var(--space-base-4);
  --space-5: var(--space-base-5);
  --space-6: var(--space-base-6);
  --space-7: var(--space-base-7);
}

/* ──────────────────────────────────────────────────────────────────────────
   motion-tokens.css — motion durations + easings, with the AC4
   reduced-motion gate at the token layer (UX line 423).

   Raw axis layer:    --motion-duration-* + --motion-easing-*
   Semantic aliases:  --motion-quick, --motion-base, --easing
                       (preserves manifesto-preview's component CSS unchanged)

   Source-of-truth values: manifesto-preview.html lines 63–66, 146–152.

   Reduced-motion gate operates in two layers:
     1. Token-layer override (spec-mandated) — re-resolves duration tokens to
        0ms when prefers-reduced-motion: reduce. Aliases inherit via var().
     2. Global escape hatch — defends against any third-party / not-yet-
        tokenized CSS by zeroing every transition-duration / animation-duration.
   ────────────────────────────────────────────────────────────────────────── */

:root {
  /* — raw axis layer — */
  --motion-duration-quick: 120ms;
  --motion-duration-base:  200ms;
  --motion-easing-base:    cubic-bezier(0.2, 0, 0, 1);

  /* — semantic alias layer — */
  --motion-quick: var(--motion-duration-quick);
  --motion-base:  var(--motion-duration-base);
  --easing:       var(--motion-easing-base);
}

/* AC4 — reduced-motion at the token layer.
   Aliases above inherit via var(), so redeclaring the raw axis tokens here
   collapses every alias-consumer's transition to 0ms automatically. */

@media (prefers-reduced-motion: reduce) {
  :root {
    --motion-duration-quick: 0ms;
    --motion-duration-base:  0ms;
  }
}

/* Global escape hatch — defends against any rule that hardcodes durations
   (third-party CSS, or component CSS that hasn't yet been migrated to tokens).
   Belt-and-braces with the token-layer override above; both intentional.

   Zeroing duration alone is not enough: a 5s-delayed animation still fires
   visibly, and an `iteration-count: infinite` animation with duration 0 can
   wedge the rendering thread on some engines. Override delays + clamp
   iteration to 1 alongside duration. */

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    transition-duration: 0ms !important;
    transition-delay:    0ms !important;
    animation-duration:  0ms !important;
    animation-delay:     0ms !important;
    animation-iteration-count: 1 !important;
  }
}

/* ──────────────────────────────────────────────────────────────────────────
   layout-base.css — Story 1.4 (UX:468–531).

   Layout-level body styling. Lives outside tokens/{color,type,space,motion}-tokens.css
   because the stylelint regex `^(color|type|space|motion)-[a-z0-9-]+$` enforced
   on declarations in component CSS only allows declarations of those four
   prefixes — body styling, skip-link, brand-mark sizing, and the substrate
   dot-grid background-image are all consumers, not declarations, so they
   live here. The tokens/** stylelint exemption (Story 1.1) covers this file.

   Body substrate per UX §Stigmergy Texture System Primitive 1:
     • radial-gradient(circle, var(--grid-dot) 0.7px, transparent 1.4px)
     • size: var(--grid-cadence) (28px default)
     • Mode-aware via the cascade — --grid-dot redeclares per data-theme.
     • AA constraint: dot opacity is calibrated for ≥4.5:1 body-text contrast.

   Source-of-truth values: manifesto-preview.html lines 271–360 (Tom-signed,
   per UX line 551 — canonical visual reference).
   ────────────────────────────────────────────────────────────────────────── */

/* Layout-level constants. --grid-cadence pairs with --grid-dot (declared in
   color-tokens.css per the stigmergy pair) but is dimensional, not chromatic.
   Per UX:526–531 it adapts per data-aspect in Stories 2.x/3.x; at Story 1.4
   it stays consistent (28px) across surfaces. */

:root {
  --grid-cadence: 28px;
}

*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scroll-behavior: smooth;
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

body {
  margin: 0;
  /* Substrate: solid surface + radial dot-grid at --grid-cadence.
     The colony's substrate — barely perceptible, never competing with type. */
  background-color: var(--surface-page);
  background-image: radial-gradient(circle, var(--grid-dot) 0.7px, transparent 1.4px);
  background-size: var(--grid-cadence) var(--grid-cadence);
  background-position: 0 0;
  color: var(--ink-primary);
  font-family: var(--font-serif);
  font-size: var(--type-size-body-base);
  line-height: var(--type-line-height-base);
  font-feature-settings: "kern" 1, "liga" 1;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  transition: background-color var(--motion-base) var(--easing),
              color            var(--motion-base) var(--easing);
}

@media (min-width: 768px) {
  body {
    font-size:   var(--type-size-body-comfortable);
    line-height: var(--type-line-height-loose);
  }
}

::selection { background: var(--accent-eu-gold-foil); color: var(--ink-primary); }

/* Visually-hidden utility — Story 2.2 (D12=c). Renders content for assistive
   technology while removing it from visual layout. Bootstrap canonical form;
   used by Story 2.2 zone-name <h2> headings inside scroll sections. */

.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;
}

/* Skip-link — keyboard-only affordance for the WCAG 2.4.1 bypass-blocks rule. */

.skip-link {
  position: absolute;
  top: -100px;
  left: 1rem;
  padding: var(--space-1) 0.75rem;
  background: var(--surface-card);
  color: var(--ink-primary);
  font-family: var(--font-sans);
  font-size: var(--type-size-small-base);
  text-decoration: none;
  border: 1px solid var(--rule-quiet);
  border-radius: 4px;
  z-index: 100;
}

.skip-link:focus {
  top: 0.75rem;
  outline: 2px solid var(--accent-primary);
  outline-offset: 2px;
}

/* Header chrome — Story 1.3 minimum; Story 2.1 reskins. */

header.site {
  padding: var(--space-3) 0;
  border-bottom: 1px solid var(--rule-quiet);
}

.site-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  width: 100%;
  max-width: var(--measure);
  margin: 0 auto;
  padding: 0 var(--space-3);
}

@media (min-width: 768px) {
  .site-inner { padding: 0 var(--space-4); }
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.625rem;
  text-decoration: none;
  color: var(--ink-primary);
  font-family: var(--font-sans);
  font-size: 0.9375rem;
  font-weight: var(--type-weight-medium);
}

.brand-mark { width: 28px; height: 28px; flex: 0 0 28px; }

.brand-name { letter-spacing: 0.04em; }

.nav { display: flex; align-items: center; gap: var(--space-2); }

/* Lucie widget surface dot-grid suppression — UX:522.
   The widget is its own owned surface; the stigmergy texture frames her,
   never invades her. Scope to the canonical mount root. */

#lucie-root,
#lucie-root * {
  background-image: none;
}

/* Story 1.4 — body substrate + skip-link + header chrome (lifts manifesto-preview body block) */

/* ──────────────────────────────────────────────────────────────────────────
   hero.css — Story 2.1 hero-block consumer rules.

   Composition lock: A1 centred / cinematic per ux-design-specification.md
   §Design Direction Decision (Step 9). Element order rendered by
   templates/pages/landing-page.eta: logo → descriptor → H1 → Sub 1 →
   Sub 2 → brand-mark close → CTA. Hero is centred; per-slot rows are
   constrained to a prose measure (70ch).

   Token consumers use CURRENT (pre-migration) names. Step 8 visual-foundation
   lock enumerates the migration to Spectral + Switzer + new colour values +
   new type scale + touch-target tokens + --measure-{site,prose,narrow}.
   That migration lands separately as Story 1.3-update; see
   ux-design-specification.md §Token Deltas (lines 967–1103).

   Forward-compat sweep targets that Story 1.3-update will resolve:
     • --measure              → --measure-site (72rem)
     • --type-size-h1-base    → --type-size-h1
     • --type-size-body-base / -comfortable → --type-size-body (stepped)
     • --type-size-eyebrow-base → --type-size-eyebrow
     • Hardcoded 70ch         → var(--measure-prose)
     • Hardcoded 48px (CTA)   → var(--target-primary)

   Lives under tokens/** so the four-prefix stylelint regex exemption
   (Story 1.1) covers consumer rules using ad-hoc class names.
   ────────────────────────────────────────────────────────────────────────── */

.hero {
  padding: var(--space-4) 0;
  text-align: center;
}

.hero-inner {
  width: 100%;
  max-width: var(--measure);
  margin: 0 auto;
  padding: 0 var(--space-3);
}

@media (min-width: 768px) {
  .hero { padding: var(--space-6) 0 var(--space-5); }
  .hero-inner { padding: 0 var(--space-4); }
}

/* Logo size matches the SVG's HTML width/height attributes (64×64) at the
   smallest breakpoint so the browser reserves the right box for CLS before
   CSS parses; ≥768px we scale up to 96. */

.hero-mark {
  display: block;
  width: 64px;
  height: 64px;
  margin: 0 auto var(--space-3);
}

@media (min-width: 768px) {
  .hero-mark { width: 96px; height: 96px; }
}

.hero .eyebrow {
  font-family: var(--font-sans);
  font-size: var(--type-size-eyebrow-base);
  font-weight: var(--type-weight-medium);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-quiet);
  margin: 0 auto var(--space-2);
  max-width: 70ch;
}

.hero h1 {
  font-family: var(--font-serif);
  font-weight: var(--type-weight-regular);
  font-size: var(--type-size-h1-base);
  line-height: var(--type-line-height-tight);
  letter-spacing: -0.02em;
  margin: 0 auto var(--space-3);
  color: var(--ink-primary);
  max-width: 70ch;
}

.hero-sub {
  font-family: var(--font-serif);
  font-size: var(--type-size-body-base);
  line-height: var(--type-line-height-base);
  color: var(--ink-secondary);
  margin: 0 auto var(--space-2);
  max-width: 70ch;
}

@media (min-width: 768px) {
  .hero-sub { font-size: var(--type-size-body-comfortable); }
}

.hero-brand-mark {
  font-family: var(--font-serif);
  font-style: italic;
  font-size: var(--type-size-body-base);
  color: var(--ink-secondary);
  margin: var(--space-3) auto;
  max-width: 70ch;
}

.hero-cta {
  margin-top: var(--space-3);
}

.cta-lucie {
  display: inline-block;
  font-family: var(--font-sans);
  font-size: var(--type-size-body-base);
  font-weight: var(--type-weight-medium);
  background: var(--accent-primary);
  color: var(--ink-on-accent);
  border: 1px solid var(--accent-primary);
  border-radius: 6px;
  padding: 0.625rem 1.125rem;
  min-height: 48px;
  cursor: pointer;
  transition:
    border-color var(--motion-quick) var(--easing),
    color var(--motion-quick) var(--easing),
    background-color var(--motion-quick) var(--easing);
}

.cta-lucie:hover {
  background: transparent;
  color: var(--accent-primary);
}

/* Focus ring uses --ink-primary so it stays contrast-safe against any
   substrate the CTA might land on (today --surface-page; future hero
   variants may differ). Decoupled from --accent-primary on purpose. */

.cta-lucie:focus-visible {
  outline: 2px solid var(--ink-primary);
  outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
  .cta-lucie { transition: none; }
}

/* Story 2.1 — A1 centred/cinematic hero block (landing-page.eta consumer rules) */

/* ──────────────────────────────────────────────────────────────────────────
   aspect-tokens.css — Story 2.2 D8/D11.

   Aspect-axis cascade per UX:451 (`data-aspect` on section roots) and the
   accent-ratio rules in UX:519–534. The minimum-mechanism scalar at MVP-0:

     --accent-presence ∈ [0, 1]

   Components multiply chromatic accent emphasis (link underlines, divider
   trails, eyebrow tints, etc.) by this scalar so the SAME chromatic system
   carries register difference across zones — the substrate
   (--surface-page / --ink-primary) and accent palette stay constant; only
   the *presence ratio* changes per zone (UX:80 line: "no re-skinning per
   zone, only accent-ratio modulation").

   Story 2.2 materialises the first two non-`manifesto` aspect zones:
     • [data-aspect="enterprise"] — full presence
     • [data-aspect="smb"]        — quietened to 0.4

   Forward path (Story 1.3-update / UX:529–534): a richer aspect catalog may
   add --motif-density, --metallic-density, --cadence-density alongside
   --accent-presence. The single-scalar form here is forward-compatible —
   richer aliases extend, they don't displace.

   Lives under tokens/** so the four-prefix stylelint regex exemption
   (Story 1.1) covers the new --accent-presence alias.
   ────────────────────────────────────────────────────────────────────────── */

:root {
  --accent-presence: 1;
}

/* Enterprise zone — full presence (UX:519 + UX:1131 portfolio block). The
   :root form catches a future top-level html[data-aspect="enterprise"]
   declaration; the bare attribute selector catches the canonical Story 2.2
   usage where data-aspect lives on a <section>, with descendants picking
   up the override via custom-property inheritance. */

:root[data-aspect="enterprise"],
[data-aspect="enterprise"] {
  --accent-presence: 1;
}

/* SMB zone — quietened. UX:519 says SMB suppresses waypoints and runs at
   reduced motif density; the 0.4 scalar lands the rule of thumb that the
   accent presence in SMB is roughly 40% of the enterprise reading. */

:root[data-aspect="smb"],
[data-aspect="smb"] {
  --accent-presence: 0.4;
}

/* DPP zone — quietened to match SMB scalar. Without this rule the DPP zone
   inherited the :root default of 1, reading at full enterprise presence and
   defeating the "single understated line below the fold" framing locked at
   PRD §DPP CTA Voice Lock line 400 + UX:138. Story 5.1/5.2 may extend the
   DPP aspect into a richer composition (UX:556); the 0.4 scalar here is the
   minimum-mechanism pin keeping the landing-side DPP CTA register-honest
   (review patch DP-1, 2026-05-06). */

:root[data-aspect="dpp"],
[data-aspect="dpp"] {
  --accent-presence: 0.4;
}

/* Story 2.2 — --accent-presence per data-aspect (UX:451 + 519–534) */

/* ──────────────────────────────────────────────────────────────────────────
   scroll-sections.css — Story 2.2 consumer rules.

   Composition lock: B1 cards-grid 4-up portfolio + mid-page Manifesto CTA +
   below-the-fold DPP CTA + Enterprise / SMB / DPP `data-aspect` zones, per
   ux-design-specification.md §Step 9 lock (UX:1131, UX:1133, UX:1157) and
   §Stigmergy Application Rules (UX:519–534).

   Token consumers use CURRENT (pre-migration) names. Step 8 visual-
   foundation lock enumerates the migration to Spectral + Switzer + new
   colour values + new type scale + touch-target tokens +
   --measure-{site,prose,narrow}. That migration lands separately as
   Story 1.3-update (UX:967–1103); this file ships forward-compat consumers
   parallel to tokens/hero.css.

   Forward-compat sweep targets:
     • --measure              → --measure-site (72rem)
     • Hardcoded 70ch         → var(--measure-prose)
     • Inline clamp() for h3  → var(--type-size-h3) once defined
     • --type-size-body-base / -comfortable → var(--type-size-body) (stepped)

   No transitions on scroll-section paint per UX:251 (Composed > delightful);
   card hover is a quiet border-colour change with no transform, no parallax,
   no scroll-trigger affordance.

   Aspect-presence consumers (Story 2.2 D8): --accent-presence multiplies
   accent emphasis. Currently consumed by:
     • .stigmergy-divider path (stroke-opacity scaled below)
     • .card-explore         (border-bottom opacity)
     • .card-eyebrow         (colour mix)
   Story 1.3-update may extend the consumer list when it lands.

   Lives under tokens/** so the four-prefix stylelint regex exemption
   (Story 1.1) covers ad-hoc class-name consumer rules.
   ────────────────────────────────────────────────────────────────────────── */

/* ── Section frame ─────────────────────────────────────────────────────── */

.scroll-section {
  padding: var(--space-5) 0;
}

.scroll-section > * {
  width: 100%;
  max-width: var(--measure);
  margin-left: auto;
  margin-right: auto;
  padding-left: var(--space-3);
  padding-right: var(--space-3);
}

@media (min-width: 768px) {
  .scroll-section { padding: var(--space-6) 0; }
  .scroll-section > * {
    padding-left: var(--space-4);
    padding-right: var(--space-4);
  }
}

/* ── Stigmergy divider (Story 2.2 D9 — primitive 4 sprite reference) ───── */

.stigmergy-divider {
  display: block;
  width: 100%;
  max-width: 240px;
  height: auto;
  margin: var(--space-3) auto;
  /* viewBox is 240×36; let height resolve from intrinsic ratio. */
  aspect-ratio: 240 / 36;
}

.stigmergy-divider path {
  /* UX:506 — 0.55 baseline opacity; scaled by --accent-presence so SMB
     zones (--accent-presence=0.4) read at ~0.22 vs enterprise at 0.55. */
  stroke-opacity: calc(0.55 * var(--accent-presence));
}

/* ── Portfolio grid + cards (B1 4-up per UX:1131 + UX:1157) ─────────────── */

.portfolio-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-4);
  list-style: none;
  margin: 0 auto;
  padding-left: var(--space-3);
  padding-right: var(--space-3);
}

@media (min-width: 600px) {
  .portfolio-grid { grid-template-columns: repeat(2, 1fr); }
}

@media (min-width: 1024px) {
  .portfolio-grid { grid-template-columns: repeat(4, 1fr); }
}

@media (min-width: 768px) {
  .portfolio-grid {
    padding-left: var(--space-4);
    padding-right: var(--space-4);
  }
}

.portfolio-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-3);
  border: 1px solid var(--rule-quiet);
  border-radius: 6px;
  background: var(--surface-card);
}

.card-eyebrow {
  font-family: var(--font-mono);
  font-size: var(--type-size-eyebrow-base);
  font-weight: var(--type-weight-medium);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  /* Tint scaled by --accent-presence so eyebrows quieten in SMB zones. */
  color: color-mix(
    in srgb,
    var(--accent-primary) calc(100% * var(--accent-presence)),
    var(--ink-quiet)
  );
  margin: 0;
}

.card-name {
  font-family: var(--font-serif);
  font-weight: var(--type-weight-medium);
  /* Inline clamp until Story 1.3-update introduces --type-size-h3. */
  font-size: clamp(1.25rem, 2.5vw, 1.625rem);
  line-height: var(--type-line-height-tight);
  letter-spacing: -0.01em;
  color: var(--ink-primary);
  margin: 0;
}

.card-tagline {
  font-family: var(--font-serif);
  font-style: italic;
  font-size: var(--type-size-body-base);
  line-height: var(--type-line-height-base);
  color: var(--ink-secondary);
  margin: 0;
}

.card-descriptor {
  font-family: var(--font-serif);
  font-size: var(--type-size-body-base);
  line-height: var(--type-line-height-base);
  color: var(--ink-primary);
  margin: 0;
  /* Per-card copy stays under the column-width cap — no narrower bound. */
}

.card-explore {
  align-self: start;
  font-family: var(--font-sans);
  font-size: var(--type-size-small-base);
  font-weight: var(--type-weight-medium);
  text-decoration: none;
  color: var(--accent-primary);
  /* Dotted bottom-border per UX:1131 "explore link with dotted bottom-border".
     Opacity scaled by --accent-presence so the underline quietens with the
     zone. Border below the text rather than text-decoration so dot weight is
     consistent across browsers. */
  border-bottom: 1px dotted color-mix(
    in srgb,
    var(--accent-primary) calc(100% * var(--accent-presence)),
    transparent
  );
  margin-top: auto;
  padding-bottom: 1px;
}

.portfolio-card:hover {
  border-color: var(--accent-primary);
}

/* ── Manifesto CTA — mid-page inline anchor (UX-DR4 + AC4) ─────────────── */

.manifesto-cta-zone {
  text-align: center;
}

.manifesto-cta {
  font-family: var(--font-serif);
  font-style: italic;
  font-size: var(--type-size-body-comfortable);
  color: var(--ink-secondary);
  max-width: 70ch;
  margin: 0 auto;
}

.manifesto-cta a {
  color: var(--accent-primary);
  text-decoration: none;
  border-bottom: 1px dotted var(--accent-primary);
}

.manifesto-cta a:hover {
  border-bottom-style: solid;
}

/* ── SMB intro (D7=a — quiet bridging paragraph) ───────────────────────── */

.smb-intro {
  font-family: var(--font-serif);
  font-size: var(--type-size-body-base);
  line-height: var(--type-line-height-base);
  color: var(--ink-secondary);
  text-align: center;
  max-width: 70ch;
  margin: 0 auto;
}

/* ── DPP CTA — single understated line below the fold (AC5 + UX:138) ───── */

.dpp-zone {
  text-align: center;
}

.dpp-cta {
  font-family: var(--font-serif);
  font-style: italic;
  font-size: var(--type-size-body-base);
  color: var(--ink-secondary);
  max-width: 70ch;
  margin: 0 auto;
}

.dpp-cta a {
  color: var(--accent-primary);
  text-decoration: none;
  border-bottom: 1px dotted var(--accent-primary);
  margin-left: 0.4ch;
}

.dpp-cta a:hover {
  border-bottom-style: solid;
}

/* ── Focus-visible (review patch DP-5) ─────────────────────────────────────
   Keyboard users get an explicit ring on every scroll-section anchor; mouse
   hover is the dotted-border-thickening above. Pattern matches mode-toggle +
   skip-link (--accent-primary, 2px outline, 2px offset); hero CTA uses
   --ink-primary instead because it sits on a different substrate (see
   tokens/hero.css:127 — decoupled deliberately). */

.card-explore:focus-visible,
.manifesto-cta a:focus-visible,
.dpp-cta a:focus-visible {
  outline: 2px solid var(--accent-primary);
  outline-offset: 2px;
}

/* Story 2.2 — portfolio grid + manifesto CTA + DPP CTA + zone padding */
