/* design_intelligence · foundation.css — direction-AGNOSTIC premium layer.
 * Import this once, then ONE direction-*.css for the colour/type identity.
 * Everything here is grounded in award-tier references (Vercel Web Interface
 * Guidelines, Emil Kowalski / animations.dev, Stripe·Linear·Vercel teardown).
 * These values are the "material" the website-design-team pipeline was missing:
 * premium motion + interaction + a11y that an LLM otherwise reinvents as slop.
 * ------------------------------------------------------------------------- */

:root {
  /* — SPACING — 4px base grid; use these, never arbitrary px (AI-sprawl tell). */
  --space-1: 4px;   --space-2: 8px;   --space-3: 12px;  --space-4: 16px;
  --space-6: 24px;  --space-8: 32px;  --space-12: 48px; --space-16: 64px;
  --space-24: 96px; --space-32: 128px;
  /* Section rhythm: TIGHT inside a group, GENEROUS between groups.
     Premium sections breathe — vary density, don't py-20 everything. */
  --section-y: clamp(64px, 10vw, 128px);
  --section-sm: clamp(48px, 7vw, 96px);
  --container: 1120px;        /* content max-width (Linear/Stripe ~1100-1200) */
  --page-pad: clamp(20px, 5vw, 64px); /* side gutter; NEVER 0 on mobile */
  --measure: 68ch;            /* body line-length cap; never let prose run wide */

  /* — RADII — pick a consistent scale; over-rounding small cards is a tell. */
  --radius-xs: 6px;   --radius-sm: 8px;   --radius-md: 12px;
  --radius-lg: 16px;  --radius-pill: 999px;

  /* — MOTION durations — premium is FAST. Keep all UI motion < 300ms. */
  --dur-fast: 120ms;    /* hover / color / active press */
  --dur-base: 200ms;    /* dropdown / tooltip / small reveal */
  --dur-slow: 280ms;    /* modal / sheet entrance (ceiling for UI) */

  /* — EASING — ease-OUT for user-initiated enter/exit; never ease-in on UI,
       never linear except loops. out-quint is the go-to UI curve. */
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);        /* out-quint */
  --ease-out-soft: cubic-bezier(0.19, 1, 0.22, 1);   /* out-expo, gentler */
  --ease-inout: cubic-bezier(0.645, 0.045, 0.355, 1);/* on-screen movement */

  /* — FOCUS ring — real, visible, keyboard-only (see :focus-visible below). */
  --focus-w: 2px;
  --focus-offset: 2px;
}

/* — BASE reset (minimal, premium defaults) — */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
body { margin: 0; -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility; }
img, svg, video { display: block; max-width: 100%; height: auto; }
button, input, textarea, select { font: inherit; color: inherit; }

/* — INTERACTION primitives — six states, subtle deltas (NOT scale-1.05+glow). */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2);
  padding: 12px 20px; border-radius: var(--radius-sm);
  font-weight: 600; line-height: 1.15; cursor: pointer; border: 1px solid transparent;
  transition: background-color var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out),
              transform var(--dur-fast) var(--ease-out),
              box-shadow var(--dur-fast) var(--ease-out);
}
.btn:active { transform: scale(0.97); }        /* tactile "it responded" */
.btn:disabled { opacity: 0.5; cursor: not-allowed; }
.btn[aria-busy="true"] { cursor: progress; }

/* Hover only where a real pointer exists — avoids stuck hover on touch. */
@media (hover: hover) and (pointer: fine) {
  .link-underline { background-size: 0 1px; transition: background-size var(--dur-base) var(--ease-out); }
  .card--interactive { transition: transform var(--dur-base) var(--ease-out),
                                   border-color var(--dur-base) var(--ease-out),
                                   box-shadow var(--dur-base) var(--ease-out); }
  .card--interactive:hover { transform: translateY(-2px); }  /* -1 to -2px, never -8 */
}

/* Keyboard-visible focus ring (not on mouse click). */
:focus-visible {
  outline: var(--focus-w) solid var(--focus, currentColor);
  outline-offset: var(--focus-offset);
}
:focus:not(:focus-visible) { outline: none; }

/* Adequate touch targets, no double-tap zoom, no iOS input auto-zoom. */
.btn, a[role="button"], [data-touch] { touch-action: manipulation; min-height: 44px; }
input, textarea, select { font-size: 16px; }

/* — REVEAL — happens ONCE, only for key blocks; opacity + small translateY, no bounce. */
.reveal { opacity: 0; transform: translateY(12px);
          transition: opacity var(--dur-slow) var(--ease-out),
                      transform var(--dur-slow) var(--ease-out); }
.reveal.is-in { opacity: 1; transform: none; }
/* no-JS safety net: .reveal hides content and relies on JS (.is-in) to reveal it.
   If scripting is off, everything below the fold stays opacity:0 = invisible.
   Restore visibility when the UA won't run scripts (does NOT fire in a JS browser
   whose observer failed — that's a code bug, not a default a11y hole).
   NOTE for builders: the (scripting:none) feature only exists in Chrome/Edge 120+,
   FF 113+, Safari 17+. On OLDER no-JS UAs (iOS 16, old Android WebViews, in-app
   browsers) it is unknown -> evaluates false -> below-fold .reveal stays invisible.
   If you use .reveal below the fold, ALSO add the universally-supported no-JS belt
   in the document head (a noscript style block that resets .reveal to opacity:1) —
   the exact pasteable snippet is in DECISION_RULES.md section 4 (Motion). Never write
   a closing style tag inside any CSS file: once inlined it would terminate the enclosing
   style element in a real browser and blank the page (self-test guards this). */
@media (scripting: none) { .reveal { opacity: 1; transform: none; } }

/* — reduced-motion: drop translate/scale, keep gentle fades; no !important. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms; animation-iteration-count: 1;
    transition-duration: 0.01ms; scroll-behavior: auto;
  }
  .reveal { transform: none; }
}

/* — TYPE-SETTING classes — the four levers that separate pro from amateur:
     line-height tightens as size grows · tracking negative on display, positive
     on eyebrows · body capped to a measure · weight 400 body / 500 UI / 600 head.
     A direction-*.css supplies the --fs-* sizes and --font-* families; these
     classes apply the craft. (grounded: Linear/Stripe/Vercel type teardown.) */
body { font-family: var(--font-body, system-ui, sans-serif);
       font-size: var(--fs-body, 1rem); line-height: 1.6;
       letter-spacing: -0.006em; }
.display { font-family: var(--font-display, var(--font-body));
           font-size: var(--fs-display); font-weight: 600;
           line-height: 1.04; letter-spacing: -0.035em;
           text-wrap: balance; max-width: 18ch; }
.h1 { font-family: var(--font-display, var(--font-body));
      font-size: var(--fs-h1); font-weight: 600;
      line-height: 1.08; letter-spacing: -0.03em; text-wrap: balance; }
.h2 { font-family: var(--font-display, var(--font-body));
      font-size: var(--fs-h2); font-weight: 600;
      line-height: 1.15; letter-spacing: -0.02em; text-wrap: balance; }
.h3 { font-size: var(--fs-h3); font-weight: 600;
      line-height: 1.25; letter-spacing: -0.015em; }
.lead { font-size: var(--fs-lead); font-weight: 400;
        line-height: 1.5; letter-spacing: -0.01em; max-width: 46ch; }
.body { font-size: var(--fs-body); font-weight: 400;
        line-height: 1.6; max-width: var(--measure); text-wrap: pretty; }
.ui { font-weight: 500; letter-spacing: -0.01em; }        /* nav / buttons: 500 not 400 */
.eyebrow { font-size: var(--fs-caption, 0.8125rem); font-weight: 500;
           letter-spacing: 0.08em; text-transform: uppercase; }
.tabular { font-variant-numeric: tabular-nums; }          /* aligned stats/pricing */
/* Heading rhythm: more space ABOVE than below binds a heading to its paragraph. */
.prose h2 { margin: 2.5em 0 0.75em; }
.prose h3 { margin: 2em 0 0.5em; }
.prose p  { margin: 0 0 1.25em; }
/* DIRECTION: "Graphite" — Technical / cool-precise (Linear-class). DARK-FIRST.
 * Mood: engineered, timeless, dark-first. Grounded in verified Linear tokens.
 * Refuses: purple→blue gradient hero, saturated accents, drop shadows —
 * elevation comes from the surface ladder + hairline borders, not shadow.
 * Accent = desaturated indigo (chroma 0.137), NOT #6366f1. Type: minor-third
 * (1.2) product-UI scale, body 16px. Pair with foundation.css. Fonts: Inter + Geist Mono. */
:root { /* dark IS the primary theme */
  --bg:         #08090a;
  --surface:    #0f1011;   /* Linear surface-1 */
  --surface-2:  #141516;
  --border:     #23252a;   /* solid hairline */
  --border-strong: #34343a;
  --muted:      #8a8f98;   /* Linear ink-subtle (~5:1 on bg) */
  --text:       #d0d6e0;   /* body (~12:1) */
  --ink:        #f7f8f8;   /* heading (~17:1) */
  --primary:    #5e6ad2;   /* Linear indigo: white text on it = 4.7:1 (AA); on bg = 4.24:1 */
  --primary-hover: #6c78e0;
  --on-primary: #ffffff;
  --accent:     #7a8bff;   /* lighter indigo for eyebrow/inline accent text on dark */
  --accent-soft: rgba(94,106,210,0.14);   /* faint indigo wash for photo-slot fill (matches --grad-glow) */
  --focus:      #7c88e6;

  --grad-glow:    radial-gradient(600px circle at 50% 0%, rgba(94,106,210,0.15), transparent 70%);
  --grad-surface: linear-gradient(180deg, #0f1011, #010102);
  --shadow-1: none;  --shadow-2: none;   /* no shadows: depth = surface ladder */
  --radius-card: 8px;
  --sep-shadow: none; --sep-border: 1px solid var(--border);   /* ONE separation primitive: hairline (components.css .cta .box) */

  --font-display: "Geist", "Inter", ui-sans-serif, system-ui, sans-serif; /* distinct display face (not Inter-only) */
  --font-body:    "Inter", system-ui, sans-serif;
  --font-mono:    "Geist Mono", ui-monospace, "SF Mono", Menlo, monospace;

  /* Type — minor third 1.2, product UI · base 16px, body 16px */
  --fs-caption: 0.75rem;    /* 12 */
  --fs-small:   0.875rem;   /* 14 */
  --fs-body:    1rem;       /* 16 */
  --fs-lead:    1.1875rem;  /* 19 */
  --fs-h4:      1.25rem;    /* 20 */
  --fs-h3:      1.5rem;     /* 24 */
  --fs-h2:      1.875rem;   /* 30 */
  --fs-h1:      2.375rem;   /* 38 */
  --fs-display: clamp(2.75rem, 1.9rem + 4.2vw, 4rem);  /* 44 → 64 (restrained) */
}
.light {
  --bg:        #fcfcfd;   /* Radix slate 1 */
  --surface:   #ffffff;
  --border:    #e6e7eb;
  --border-strong: #cdced6;
  --muted:     #60646c;   /* Radix slate 11 (~5.6:1) */
  --text:      #1c2024;   /* Radix slate 12 */
  --ink:       #0d0e10;
  --primary:   #4d58bd;  /* darkened indigo for >=4.5 as text on white if used inline */
  --primary-solid: #5e6ad2;
  --on-primary:#ffffff;
  --accent:    #4d58bd;
  --accent-soft: rgba(77,88,189,0.10);   /* faint indigo wash for photo-slot fill on light */
  --focus:     #5e6ad2;
  --grad-surface: linear-gradient(180deg, #ffffff, #f5f6f8);
}
/* ===== design_intelligence — components.css (SHARED, floor-safe primitives) =====
 *
 * The reusable component layer that sits BETWEEN foundation.css (direction-agnostic
 * base) and a direction-*.css token file. A builder pastes, in order:
 *     foundation.css  →  direction-<x>.css  →  components.css  →  page-specific styles
 * so that nav / buttons (colour-bound) / .photo-slot / .lead-index / .trust-row /
 * .proof / .cta / footer are all real, paste-able CSS — NOT trapped in a Python
 * generator. (Before this file existed, every fresh build reinvented these slightly
 * differently or reverse-engineered them from a proof HTML — the "skin-not-bones each
 * builder hand-rolls the same component" hazard.)
 *
 * Separation primitive: ONE per direction (never border AND shadow together). Each
 * direction-*.css sets --sep-shadow / --sep-border; the defaults below match the
 * hairline register, so a direction that sets neither still renders correctly.
 *
 * This file is the SINGLE SOURCE OF TRUTH: build_proof.py reads it verbatim (no inline
 * duplicate to drift). Keep it token-only — never hardcode a colour/size a token owns. */

/* ===== proof/page layout ===== */
body { background: var(--bg); color: var(--text); }
.wrap { max-width: var(--container); margin-inline: auto; padding-inline: var(--page-pad); }
a { color: inherit; text-decoration: none; }
.muted { color: var(--muted); }
.accent { color: var(--accent); }

/* margins: kill UA heading/paragraph defaults so spacing is controlled by the
   layout (flex gap / explicit rules), never by uneven browser em-margins. */
h1, h2, h3, p, figure, blockquote { margin: 0; }
.hero .eyebrow, .bcell--hero .eyebrow, .brutal-main .eyebrow { margin-bottom: var(--space-4); }
.hero .lead { margin-top: var(--space-6); }
h3 + .body { margin-top: var(--space-2); }

/* nav base + link scoping. :not(.btn) keeps the muted link colour OFF the CTA
   (an unscoped `.nav .links a{color:--muted}` outranks .btn-primary and paints
   the button label muted-on-accent = illegible). */
.nav { display:flex; align-items:center; justify-content:space-between;
       height:64px; border-bottom:1px solid var(--border); }
.nav .brand { font-weight:600; letter-spacing:-0.02em; font-size:1.0625rem; }
.nav .links { display:flex; gap:var(--space-8); align-items:center; }
.nav .links a { font-size:var(--fs-small); }
.nav .links a:not(.btn) { color:var(--muted); }
@media (hover:hover){ .nav .links a:not(.btn):hover { color:var(--text); } }

/* buttons wired to the accent/ink of the active direction. .btn base lives in
   foundation.css (shape/padding/press); these bind the colour + the quiet variant
   the hero anatomy (§3: "one filled CTA + one quiet text link") asks for. */
.btn-primary { background:var(--primary,#111); color:var(--on-primary,#fff); }
@media (hover:hover){ .btn-primary:hover { filter:brightness(1.08); } }
.btn-quiet { color:var(--muted); }
@media (hover:hover){ .btn-quiet:hover { color:var(--text); } }
.actions { display:flex; align-items:center; gap:var(--space-6); }

/* .lead-index — SHARED content component: the concrete specifics that fill any
   tall region with intentional content so it never reads as a void/missing-image
   placeholder (slop tell 33 that no token/contrast gate can see). Content-led;
   a short accent dash marks each item (NOT a 01/02/03 counter — these unordered
   specifics have no sequence: §1 tell 6). */
.lead-index { list-style:none; margin:0; padding:0; }
.lead-index li { display:flex; align-items:center; gap:var(--space-3);
                 padding:var(--space-3) 0; border-bottom:1px solid var(--border);
                 font-size:var(--fs-small); color:var(--muted); letter-spacing:-0.01em; }
.lead-index li:first-child { padding-top:0; }
.lead-index li:last-child { border-bottom:0; }
.lead-index li::before { content:""; flex:none; width:14px; height:2px;
                         border-radius:2px; background:var(--accent); }

/* quiet proof strip — inline, tabular, no giant gradient numbers */
.proof { display:flex; gap:var(--space-12); flex-wrap:wrap;
         padding-block:var(--space-12); border-top:1px solid var(--border);
         border-bottom:1px solid var(--border); }
.proof .stat .n { font-size:var(--fs-h3); font-weight:600; letter-spacing:-0.02em; }
.proof .stat .l { font-size:var(--fs-small); color:var(--muted); }

/* CTA band — surface with the direction's ONE separation primitive, one CTA.
   --sep-shadow / --sep-border are set per direction; both default to none. */
.cta { text-align:left; padding-block:clamp(64px,10vw,140px); }
.cta .box { box-shadow: var(--sep-shadow, none);
            border: var(--sep-border, none);   /* both default none: a token that sets ONLY
              --sep-shadow must NOT inherit a hairline too (= the banned border+shadow tell) */
            border-radius:var(--radius-card); background:var(--surface);
            padding:clamp(32px,5vw,64px); display:flex; align-items:center;
            justify-content:space-between; gap:var(--space-8); flex-wrap:wrap; }
.cta h2 { margin:0; }

footer { border-top:1px solid var(--border); padding-block:var(--space-8);
         color:var(--muted); font-size:var(--fs-small);
         display:flex; justify-content:space-between; flex-wrap:wrap; gap:var(--space-4); }

/* .photo-slot — SHARED stage-② image component. A warm/consumer site LIVES on real
   photography; a text-only layout there reads as unfinished. This is the honest,
   intentional placeholder the imagery stage emits BEFORE the real shot arrives: a
   correctly-proportioned figure with a warm fill, a camera glyph and an explicit
   "real photo goes here" caption. It is NOT tell 33 (void card: an empty tall panel
   reading as broken) — it announces itself as a photo slot; NOT tell 36 (a flat
   vector pretending to BE the product) — it never masquerades as the real thing.
   Swap the inner .ps-frame for an <img>/<picture> and the layout is unchanged. */
.photo-slot { position:relative; margin:0; }
.photo-slot .ps-frame { position:relative; width:100%; height:100%; min-height:inherit;
    border-radius:var(--radius-card); overflow:hidden;
    background:
      radial-gradient(120% 90% at 78% 0%, var(--accent-soft, rgba(128,128,128,0.08)), transparent 60%),
      linear-gradient(180deg, var(--surface), var(--bg));
    box-shadow: inset 0 0 0 1px var(--border);
    display:flex; flex-direction:column; align-items:center; justify-content:center;
    gap:var(--space-3); text-align:center; padding:var(--space-8); }
/* When an overlaid .ps-chip is present, reserve bottom room so the centred caption
   never collides with the chip in a short frame (the chip is absolute bottom-left; a
   ~240px frame at the caption's centre overlapped the chip — real, render-only bug).
   :has() targets only chip-bearing slots so no space is wasted otherwise; browsers
   without :has() fall back to the pre-fix behaviour (never worse). */
.photo-slot:has(.ps-chip) .ps-frame { padding-bottom: var(--space-16); }
.photo-slot .ps-icon { width:34px; height:34px; color:var(--accent); opacity:0.85; }
.photo-slot .ps-cap { font-size:var(--fs-small); color:var(--muted); max-width:24ch;
    letter-spacing:-0.005em; }
/* floating info chip — a real, useful status label overlaid on the photo */
.photo-slot .ps-chip { position:absolute; left:var(--space-4); bottom:var(--space-4);
    background:var(--surface); box-shadow:var(--shadow-2); border-radius:var(--radius-pill);
    padding:var(--space-2) var(--space-4); display:flex; align-items:center; gap:var(--space-2);
    font-size:var(--fs-small); }
.photo-slot .ps-chip .dot { flex:none; width:8px; height:8px; border-radius:50%;
    background:var(--primary); }
.photo-slot .ps-chip b { font-weight:600; color:var(--text); letter-spacing:-0.01em; }
.photo-slot .ps-chip span { color:var(--muted); }

/* .trust-row — reassurance specifics for warm/consumer directions (a caring,
   content-led list, NOT a 01/02/03 sequence: these are unordered promises). */
.trust-row { list-style:none; margin:0; padding:0; display:flex; flex-direction:column;
    gap:var(--space-3); }
.trust-row li { display:flex; align-items:center; gap:var(--space-3);
    font-size:var(--fs-body); color:var(--text); letter-spacing:-0.01em; }
.trust-row li svg { flex:none; width:20px; height:20px; color:var(--primary); }
/* ARCHETYPE: terminal — index-gutter hero + horizontal manifest + numbered rows */
.hero--terminal { display:grid; grid-template-columns:auto 1fr; gap:var(--space-6) var(--space-12);
                  padding-block:clamp(56px,9vw,120px); align-items:start; }
.hero--terminal .idx { display:flex; flex-direction:column; gap:var(--space-2);
                       border-left:2px solid var(--accent); padding-left:var(--space-4); }
.hero--terminal .idxn { font-family:var(--font-mono,var(--font-body)); font-size:var(--fs-h3);
                        color:var(--accent); font-weight:600; line-height:1; }
.hero--terminal .idxl { font-family:var(--font-mono,var(--font-body)); font-size:var(--fs-small);
                        color:var(--muted); text-transform:uppercase; letter-spacing:0.08em; }
.hero--terminal .heromain { grid-column:2; }
.hero--terminal .heromain .actions { margin-top:var(--space-8); }
.hero--terminal .manifest { grid-column:2; display:grid; grid-template-columns:repeat(4,1fr);
                            margin-top:var(--space-4); border:1px solid var(--border);
                            border-radius:var(--radius-card); overflow:hidden; }
.hero--terminal .mcell { padding:var(--space-4) var(--space-6); border-right:1px solid var(--border);
                         display:flex; flex-direction:column; gap:var(--space-2); background:var(--surface); }
.hero--terminal .mcell:last-child { border-right:0; }
.hero--terminal .mk { font-size:var(--fs-small); color:var(--muted); font-family:var(--font-mono,var(--font-body)); }
.hero--terminal .mv { font-family:var(--font-mono,var(--font-body)); font-weight:500; letter-spacing:-0.01em; }
.hero--terminal .mv.up { color:var(--accent); }
.features--rows { display:flex; flex-direction:column; padding-block:var(--section-sm); }
.frow { display:grid; grid-template-columns:auto 1fr; gap:var(--space-8);
        padding:var(--space-8) 0; border-top:1px solid var(--border); align-items:start; }
.frow:last-child { border-bottom:1px solid var(--border); }
.frow .fnum { font-family:var(--font-mono,var(--font-body)); font-size:var(--fs-h2);
              color:var(--muted); font-weight:600; line-height:1; }
.frow--lead .fnum { color:var(--accent); }
.frow .fbody .lead-index { margin-top:var(--space-6); max-width:34ch; }

/* ===== responsive collapses (mobile-first floor) ===== */
@media (max-width:820px) {
  .hero--terminal { grid-template-columns:1fr; }
  .hero--terminal .idx { flex-direction:row; align-items:baseline; border-left:0;
                         border-bottom:2px solid var(--accent); padding:0 0 var(--space-3); }
  .hero--terminal .heromain, .hero--terminal .manifest { grid-column:1; }
  .hero--terminal .manifest { grid-template-columns:1fr 1fr; }
  .hero--terminal .mcell:nth-child(2n){ border-right:0; }
  .hero--editorial .ed-cols { grid-template-columns:1fr; gap:var(--space-8); }
  .features--editorial .ed-flow { grid-template-columns:1fr; gap:var(--space-8); }
  .hero--brutal { grid-template-columns:1fr; }
  .features--slab { grid-template-columns:1fr; }
  .features--slab .slab:nth-child(2){ transform:none; }
  .bento { grid-template-columns:repeat(2,1fr); }
  .bcell--hero, .bcell--index, .bcell--f2 { grid-column:span 2; }
  .hero--portrait { grid-template-columns:1fr; gap:var(--space-8); }
  .hero--portrait .pt-photo { min-height:clamp(300px,60vw,420px); order:-1; }
  .features--reassure .reassure-grid { grid-template-columns:1fr; }
  .features--shelf .shelf { grid-template-columns:1fr; }
  .hero--showcase .sh-copy { margin-inline:var(--space-4); }
}
@media (max-width:640px) {
  /* nav has no room for text links on a phone — keep brand + CTA, drop the rest */
  .nav .links a:not(.btn) { display:none; }
  .nav--masthead .mast-links { display:none; }
  .bento { grid-template-columns:1fr; }
  .bcell--hero, .bcell--index, .bcell--f1, .bcell--f2, .bcell--stat { grid-column:span 1; }
}
