/* Winch Labs — winchlabs.io
   Brand: Winch blue, one theme family across marketing site and app. Minimal,
   dense, animated by reveals. Voice is mono-forward for
   product surfaces (code, findings, chips, evidence) paired with a plain
   sans for prose — system stacks only, zero-dependency.

   ---------------------------------------------------------------------
   THEME MECHANICS (dark is canonical today; light is new — read before
   touching any color below):

   - Dark values live on the bare `:root` — that's the "dark-first" choice:
     visitors with no OS preference and no stored choice get the canonical
     dark look, same as before this redesign.
   - `@media (prefers-color-scheme: light)` swaps in the light palette, but
     only when `:root` does NOT carry `data-theme="light"` — sorry,
     `data-theme="dark"` — see the guard below. (Read: the media query is
     skipped whenever an explicit theme is set, so it only ever supplies
     the *system* light preference.)
   - `:root[data-theme="light"]` and `:root[data-theme="dark"]` restate
     their full palettes so an explicit toggle click always wins, in
     *either* direction, regardless of what the OS prefers.
   - The toggle itself lives in script.js (search "theme toggle"): reads
     localStorage, defaults to system, persists on click, wrapped in
     try/catch. `body`'s background always resolves from `--bg` — never a
     bare color — so an unthemed shell never shows through.
   - Every token below must resolve in BOTH palettes. When adding a new
     token, add it to all three blocks (bare :root, the light media
     override, and `[data-theme="light"]`) plus `[data-theme="dark"]` if it
     isn't identical to the bare root.
   --------------------------------------------------------------------- */

:root {
  /* ---- dark palette (bare :root = the canonical default) ---- */
  --bg: oklch(0.165 0.012 265);
  --bg-sunk: oklch(0.135 0.012 265);
  --card: oklch(0.199 0.013 265);
  --ink: oklch(0.965 0.005 265);
  --muted-ink: oklch(0.66 0.012 265);
  --border: oklch(0.255 0.014 265);
  --brand: oklch(0.658 0.187 282);        /* accent text, links, icons */
  --brand-solid: oklch(0.52 0.24 275);    /* CTA / filled-button background */
  --success: oklch(0.74 0.15 152);
  --warning: oklch(0.8 0.15 75);
  --destructive: oklch(0.66 0.2 27);
  /* .accent text shimmer highlight (see the .accent gradient near the end of
     this file) — near-white on the dark canvas; redefined for light below so
     the sweep never washes accent text out to invisible-on-white */
  --accent-shimmer: #cac7ff;

  /* Garboard logo-mark amber. Reserved for EXACTLY one thing: the Garboard
     mark itself (the bot avatar chip that carries the mark image). Never a
     button, link, accent, heading, or "warning" color — that's --warning,
     a different token, above. If you reach for --garboard anywhere else,
     you've reached for the wrong token. */
  --garboard: oklch(0.77 0.141 75);

  /* constant white for text set on a --brand-solid fill: both themes' fill
     is a mid-lightness saturated blue, so one constant clears AA in both
     rather than a token that would just resolve to the same value twice */
  --on-brand: #fff;

  /* derived — computed from the tokens above, so they never need
     restating inside the theme blocks below */
  --border-strong: color-mix(in oklab, var(--border) 45%, var(--ink) 30%);
  --brand-glow: color-mix(in oklab, var(--brand-solid) 35%, transparent);
  /* Atmosphere (WIN light-immersion pass): each theme designs its own air.
     Dark = glowing nebula on a void; light = morning sky on paper. Every
     layer reads these, so neither theme is a faded copy of the other. */
  --atmo-1: color-mix(in oklab, var(--brand-solid) 35%, transparent);
  --atmo-2: color-mix(in oklab, oklch(0.6 0.2 250) 20%, transparent);
  --atmo-opacity: 0.55;
  --page-wash: none;
  --grain-dot: color-mix(in oklab, var(--ink) 4%, transparent);
  --field-dot: 190,187,255;
  --field-link: 131,125,255;

  /* type */
  --sans: ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --mono: ui-monospace, "SF Mono", "Cascadia Code", Menlo, monospace;
  --text-2xs: 10.5px;
  --text-xs: 11.5px;
  --text-sm: 13px;
  --text-md: 14.5px;

  /* spacing + shape, for shared chrome and new components (chips, findings,
     badges, nav, footer) — legacy section-specific rules keep their own
     hand-tuned values and are not forced onto this scale retroactively */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-8: 48px;
  --radius-sm: 6px;
  --radius: 10px;
  --radius-lg: 14px;
  --radius-full: 999px;

  --max: 1120px;
}

/* ---- light palette: system preference, only when no explicit choice ---- */
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) {
    /* Light air: saturated sky layers on paper, ink constellation, tinted
       grain, and elevation as soft blue shadow instead of glow. */
    --atmo-1: color-mix(in oklab, var(--brand-solid) 26%, transparent);
    --atmo-2: color-mix(in oklab, oklch(0.72 0.16 250) 32%, transparent);
    --atmo-opacity: 0.85;
    --page-wash: radial-gradient(ellipse 95% 60% at 50% -12%, color-mix(in oklab, oklch(0.463 0.287 269) 8%, transparent), transparent 62%);
    --grain-dot: color-mix(in oklab, oklch(0.463 0.287 269) 10%, transparent);
    --field-dot: 82,55,238;
    --field-link: 108,84,246;
    --brand-glow: color-mix(in oklab, oklch(0.463 0.287 269) 22%, transparent);
    --bg: oklch(0.985 0.003 265);
    --bg-sunk: oklch(0.965 0.004 265);
    --card: #fff;
    --ink: oklch(0.205 0.015 265);
    --muted-ink: oklch(0.535 0.012 265);
    --border: oklch(0.905 0.008 265);
    --brand: oklch(0.463 0.287 269);
    --brand-solid: oklch(0.463 0.287 269);
    --success: oklch(0.47 0.12 152);
    --warning: oklch(0.53 0.13 70);
    --destructive: oklch(0.52 0.2 27);
    /* darker/richer, not lighter — mixing toward white here would sweep
       .accent text to near-invisible against the light --bg */
    --accent-shimmer: color-mix(in oklab, var(--brand) 55%, white 45%);
  }
}

/* ---- explicit toggle always wins, either direction ---- */
:root[data-theme="light"] {
    /* Light air: saturated sky layers on paper, ink constellation, tinted
       grain, and elevation as soft blue shadow instead of glow. */
    --atmo-1: color-mix(in oklab, var(--brand-solid) 26%, transparent);
    --atmo-2: color-mix(in oklab, oklch(0.72 0.16 250) 32%, transparent);
    --atmo-opacity: 0.85;
    --page-wash: radial-gradient(ellipse 95% 60% at 50% -12%, color-mix(in oklab, oklch(0.463 0.287 269) 8%, transparent), transparent 62%);
    --grain-dot: color-mix(in oklab, oklch(0.463 0.287 269) 10%, transparent);
    --field-dot: 82,55,238;
    --field-link: 108,84,246;
    --brand-glow: color-mix(in oklab, oklch(0.463 0.287 269) 22%, transparent);
  --bg: oklch(0.985 0.003 265);
  --bg-sunk: oklch(0.965 0.004 265);
  --card: #fff;
  --ink: oklch(0.205 0.015 265);
  --muted-ink: oklch(0.535 0.012 265);
  --border: oklch(0.905 0.008 265);
  --brand: oklch(0.463 0.287 269);
  --brand-solid: oklch(0.463 0.287 269);
  --success: oklch(0.47 0.12 152);
  --warning: oklch(0.53 0.13 70);
  --destructive: oklch(0.52 0.2 27);
  --accent-shimmer: color-mix(in oklab, var(--brand) 55%, white 45%);
}
:root[data-theme="dark"] {
  --atmo-1: color-mix(in oklab, var(--brand-solid) 35%, transparent);
  --atmo-2: color-mix(in oklab, oklch(0.6 0.2 250) 20%, transparent);
  --atmo-opacity: 0.55;
  --page-wash: none;
  --grain-dot: color-mix(in oklab, var(--ink) 4%, transparent);
  --field-dot: 190,187,255;
  --field-link: 131,125,255;
  --bg: oklch(0.165 0.012 265);
  --bg-sunk: oklch(0.135 0.012 265);
  --card: oklch(0.199 0.013 265);
  --ink: oklch(0.965 0.005 265);
  --muted-ink: oklch(0.66 0.012 265);
  --border: oklch(0.255 0.014 265);
  --brand: oklch(0.658 0.187 282);
  --brand-solid: oklch(0.52 0.24 275);
  --success: oklch(0.74 0.15 152);
  --warning: oklch(0.8 0.15 75);
  --destructive: oklch(0.66 0.2 27);
  --accent-shimmer: #cac7ff;
}

* { margin: 0; padding: 0; box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
  background-image: var(--page-wash);
  background-attachment: fixed;
  background-repeat: no-repeat;
}

/* faint drifting dot-field + a blue aurora behind the hero */
.grain {
  position: fixed; inset: -50%;
  pointer-events: none;
  background-image: radial-gradient(var(--grain-dot) 1px, transparent 1px);
  background-size: 26px 26px;
  animation: drift 90s linear infinite;
  mask-image: radial-gradient(ellipse 70% 55% at 50% 32%, black 0%, transparent 72%);
  z-index: 0;
}
@keyframes drift {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-26px, -26px, 0); }
}
.aurora {
  position: absolute; top: -280px; left: 50%;
  width: 1100px; height: 700px;
  transform: translateX(-50%);
  background:
    radial-gradient(ellipse 50% 50% at 50% 40%, var(--atmo-1), transparent 70%),
    radial-gradient(ellipse 42% 46% at 63% 26%, var(--atmo-2), transparent 72%);
  filter: blur(60px);
  opacity: var(--atmo-opacity);
  pointer-events: none;
  z-index: 0;
}

/* interactive constellation field (drawn by JS; empty canvas without it) */
.field {
  position: fixed; inset: 0;
  width: 100vw; height: 100vh;
  pointer-events: none;
  z-index: 0;
  mask-image: radial-gradient(ellipse 85% 70% at 50% 30%, black 0%, transparent 78%);
}

main, header, footer { position: relative; z-index: 1; }

/* thin scroll progress line (element injected by JS) */
.scroll-progress {
  position: fixed; top: 0; left: 0; right: 0;
  height: 2px;
  background: linear-gradient(90deg, var(--brand-solid), var(--brand));
  box-shadow: 0 0 12px var(--brand-glow);
  transform: scaleX(0);
  transform-origin: left;
  z-index: 30;
  pointer-events: none;
}

a { color: inherit; text-decoration: none; }

/* ---------------- top bar ---------------- */
.top {
  position: fixed; top: 0; left: 0; right: 0;
  display: flex; justify-content: space-between; align-items: center;
  padding: 16px clamp(20px, 5vw, 56px);
  z-index: 10;
  background: color-mix(in oklab, var(--bg) 78%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid color-mix(in oklab, var(--border) 60%, transparent);
}
.brand-lockup { display: inline-flex; align-items: center; }
/* the real brand lockup image — actual mark + typography */
.brand-lockup img.lockup { height: 30px; width: auto; }
footer .brand-lockup img.lockup { height: 26px; }
/* both the lockup and the small inline Garboard mark are monochrome-white
   PNGs designed for a dark canvas — invisible on a light one. Shipping the
   light palette makes that reachable on every page immediately (it's a
   media-query default, not gated behind the toggle button existing on the
   page), so invert them in light theme as a stopgap until real light-theme
   art exists. img[src*=] matches the icon wherever it's referenced, with
   no class needed on pages this phase didn't touch. */
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) .brand-lockup img.lockup,
  :root:not([data-theme="dark"]) img[src*="garboard-mark"] { filter: invert(1); }
}
:root[data-theme="light"] .brand-lockup img.lockup,
:root[data-theme="light"] img[src*="garboard-mark"] { filter: invert(1); }

/* faint W watermark behind the hero */
.hero-mark {
  position: absolute;
  top: 6%; left: 50%;
  width: min(760px, 80vw);
  transform: translateX(-50%);
  opacity: 0.05;
  pointer-events: none;
  z-index: 0;
}
.hero > *:not(.aurora):not(.hero-mark) { position: relative; z-index: 1; }

/* small mark above the closing headline */
.closing-mark { width: 64px; height: auto; margin-bottom: 26px; }
.top nav { display: flex; align-items: center; gap: 24px; }
.top nav a {
  font: 500 13px/1 var(--sans);
  color: var(--muted-ink);
  transition: color 0.15s ease-in-out;
}
.top nav a:hover { color: var(--ink); }
.top nav a.nav-cta {
  color: var(--on-brand);
  background: var(--brand-solid);
  padding: 9px 16px;
  border-radius: 8px;
  font-weight: 600;
  transform: translate3d(var(--tx, 0px), var(--ty, 0px), 0);
  transition: filter 0.15s ease-in-out, transform 0.2s ease-out;
}
.top nav a.nav-cta:hover { filter: brightness(1.2); }
/* current page in the nav — set aria-current="page" on the matching link */
.top nav a[aria-current="page"] { color: var(--ink); }

/* theme toggle: sun/moon button, hidden without JS since it does nothing
   inert (progressive enhancement, same gate as .reveal via html.js) */
.theme-toggle {
  display: none;
  align-items: center; justify-content: center;
  width: 34px; height: 34px;
  flex: 0 0 auto;
  border-radius: var(--radius-full);
  border: 1px solid var(--border-strong);
  background: var(--card);
  color: var(--muted-ink);
  cursor: pointer;
  transition: color 0.15s ease-in-out, border-color 0.15s ease-in-out;
}
.js .theme-toggle { display: inline-flex; }
.theme-toggle:hover { color: var(--ink); border-color: var(--brand); }
.theme-toggle svg { width: 16px; height: 16px; display: block; }
.theme-toggle .i-sun { display: none; }
.theme-toggle .i-moon { display: block; }
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) .theme-toggle .i-sun { display: block; }
  :root:not([data-theme="dark"]) .theme-toggle .i-moon { display: none; }
}
:root[data-theme="light"] .theme-toggle .i-sun { display: block; }
:root[data-theme="light"] .theme-toggle .i-moon { display: none; }
:root[data-theme="dark"] .theme-toggle .i-sun { display: none; }
:root[data-theme="dark"] .theme-toggle .i-moon { display: block; }

/* ---------------- hero ---------------- */
.hero {
  min-height: 92svh;
  display: flex; flex-direction: column; justify-content: center; align-items: center;
  text-align: center;
  max-width: var(--max);
  margin: 0 auto;
  padding: 140px clamp(20px, 5vw, 56px) 40px;
  position: relative;
  /* --exit (0→1, set by JS as the hero scrolls away) sinks and dims the
     whole section, so the page underneath feels like it slides over it */
  opacity: calc(1 - var(--exit, 0) * 0.9);
  transform: translateY(calc(var(--exit, 0) * 46px));
}
.eyebrow {
  font: 600 12px/1 var(--mono);
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--brand);
  display: inline-flex; align-items: center; gap: 8px;
  margin-bottom: 22px;
}
.eyebrow img, .eyebrow svg { border-radius: 4px; }
h1 {
  font-size: clamp(2.7rem, 6.5vw, 5rem);
  line-height: 1.05;
  font-weight: 700;
  letter-spacing: -0.035em;
  max-width: 17ch;
}
.accent { color: var(--brand); }
.lede {
  margin-top: 24px;
  max-width: 54ch;
  font-size: clamp(1.05rem, 1.6vw, 1.2rem);
  color: var(--muted-ink);
}
.cta-row { display: flex; gap: 14px; margin-top: 36px; flex-wrap: wrap; }
.hero .cta-row { justify-content: center; }
.cta {
  display: inline-flex; align-items: center; gap: 10px;
  font: 600 14.5px/1 var(--sans);
  padding: 14px 24px;
  border-radius: 9px;
  background: var(--brand-solid);
  color: var(--on-brand);
  box-shadow: 0 8px 30px -10px var(--brand-glow);
  transform: translate3d(var(--tx, 0px), var(--ty, 0px), 0);
  transition: transform 0.2s ease-out, filter 0.15s ease-in-out;
}
.cta:hover { filter: brightness(1.18); }
.cta .arr { transition: transform 0.15s ease-in-out; }
.cta:hover .arr { transform: translateX(3px); }
.cta.ghost {
  background: transparent;
  color: var(--ink);
  border: 1px solid var(--border-strong);
  box-shadow: none;
}
.cta.ghost:hover { background: var(--card); border-color: var(--ink); filter: none; }

/* works-with strip */
.stacks {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap; justify-content: center;
  margin-top: 46px;
}
.stacks .lbl { font: 500 11px/1 var(--mono); letter-spacing: 0.18em; color: var(--muted-ink); }
.stack-chip {
  font: 600 12px/1 var(--mono);
  letter-spacing: 0.08em;
  color: var(--ink);
  border: 1px solid var(--border-strong);
  background: var(--card);
  padding: 8px 14px;
  border-radius: 999px;
}
.stack-chip.soon { color: var(--muted-ink); border-style: dashed; }

/* ---------------- closing ---------------- */
.closing {
  max-width: var(--max);
  margin: 0 auto;
  padding: clamp(80px, 14vh, 150px) clamp(20px, 5vw, 56px);
  text-align: center;
}
.closing h2 {
  font-size: clamp(2rem, 5vw, 3.4rem);
  line-height: 1.1;
  letter-spacing: -0.03em;
  font-weight: 700;
}
.closing .cta-row { justify-content: center; }

/* ---------------- pricing ---------------- */
.pricing-head {
  max-width: var(--max);
  margin: 0 auto;
  text-align: center;
  padding: 150px clamp(20px, 5vw, 56px) 30px;
}
.pricing-head h1 { margin: 0 auto; }
.pricing-head .lede { margin-left: auto; margin-right: auto; }
.pricing-head .cta-row { justify-content: center; }
.plans {
  max-width: 1300px;
  margin: 0 auto;
  padding: 40px clamp(20px, 5vw, 56px) 30px;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 16px;
  align-items: stretch;
}
@media (max-width: 1140px) {
  .plans { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.plan {
  border: 1px solid var(--border-strong);
  border-radius: 14px;
  background: var(--card);
  padding: 28px 26px;
  display: flex; flex-direction: column;
}
.plan.featured {
  border-color: color-mix(in oklab, var(--brand-solid) 60%, var(--border-strong));
  box-shadow: 0 0 0 1px color-mix(in oklab, var(--brand-solid) 35%, transparent),
              0 30px 90px -50px var(--brand-glow);
  position: relative;
}
.plan .tier {
  font: 600 11.5px/1 var(--mono);
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--brand);
}
.plan .price {
  margin-top: 16px;
  font-size: 2.4rem; font-weight: 700; letter-spacing: -0.03em;
}
.plan .price small { font-size: 0.95rem; font-weight: 500; color: var(--muted-ink); letter-spacing: 0; }
.plan .for { margin-top: 4px; font-size: 13.5px; color: var(--muted-ink); min-height: 3.1em; }
.plan ul { list-style: none; margin: 20px 0 26px; display: grid; gap: 10px; flex: 1; }
.plan li { display: flex; gap: 10px; align-items: baseline; font-size: 14px; color: var(--muted-ink); }
.plan li .tick { color: var(--success); font-family: var(--mono); }
.plan li strong { color: var(--ink); font-weight: 600; }
.plan .cta { justify-content: center; }
.badge {
  position: absolute; top: -11px; left: 50%; transform: translateX(-50%);
  font: 600 10.5px/1 var(--mono);
  letter-spacing: 0.14em;
  background: var(--brand-solid);
  color: var(--on-brand);
  padding: 6px 12px;
  border-radius: 999px;
  white-space: nowrap;
  max-width: calc(100% - 28px);
  overflow: hidden;
  text-overflow: ellipsis;
}
.pricing-note {
  max-width: var(--max);
  margin: 0 auto;
  padding: 0 clamp(20px, 5vw, 56px) 30px;
  text-align: center;
  font: 400 12.5px/1.6 var(--mono);
  color: var(--muted-ink);
}
.faq {
  max-width: 760px;
  margin: 0 auto;
  padding: clamp(40px, 8vh, 90px) clamp(20px, 5vw, 56px);
  border-top: 1px solid var(--border);
}
.faq h2 { font-size: 1.5rem; font-weight: 700; letter-spacing: -0.02em; margin-bottom: 26px; }
.faq details {
  border-bottom: 1px solid var(--border);
  padding: 16px 0;
}
.faq summary {
  cursor: pointer;
  font-weight: 600;
  font-size: 15px;
  list-style: none;
  display: flex; justify-content: space-between; align-items: center;
}
.faq summary::after { content: "+"; color: var(--brand); font-family: var(--mono); }
.faq details[open] summary::after { content: "–"; }
.faq details p { margin-top: 10px; font-size: 14px; color: var(--muted-ink); }

/* ---------------- footer ---------------- */
footer {
  border-top: 1px solid var(--border);
  margin-top: 20px;
}
.foot-grid {
  max-width: var(--max);
  margin: 0 auto;
  padding: 44px clamp(20px, 5vw, 56px) 20px;
  display: grid;
  grid-template-columns: 2fr 1fr 1fr;
  gap: 30px;
}
.foot-brand p { margin-top: 12px; font-size: 13px; color: var(--muted-ink); max-width: 34ch; }
.foot-col h4 {
  font: 600 11px/1 var(--mono);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--muted-ink);
  margin-bottom: 14px;
}
.foot-col a {
  display: block;
  font-size: 13.5px;
  color: var(--muted-ink);
  padding: 4px 0;
  transition: color 0.15s ease-in-out;
}
.foot-col a:hover { color: var(--ink); }
.foot-base {
  max-width: var(--max);
  margin: 0 auto;
  padding: 18px clamp(20px, 5vw, 56px) 34px;
  display: flex; justify-content: space-between; gap: 12px; flex-wrap: wrap;
  font: 400 12px/1.5 var(--mono);
  color: var(--muted-ink);
}

/* ---------------- components: cards, section rhythm ----------------
   Shared vocabulary for pages built or rebuilt after this redesign. Existing
   bespoke blocks below (.plan, .pr-mock) keep their own hand-tuned rules for
   now rather than being force-migrated; converge them to `.card` / `.section`
   only when a page is next rewritten. */
.card {
  background: var(--card);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-lg);
  padding: var(--space-5);
}
.section {
  max-width: var(--max);
  margin: 0 auto;
  padding: clamp(60px, 10vh, 110px) clamp(20px, 5vw, 56px);
  border-top: 1px solid var(--border);
}

/* ---------------- components: chips ----------------
   Category tags for a finding: convention · secops · cost. Neutral pill,
   colored only by a left accent + text color so a page of them still reads
   calm; severity lives in .tag, not here. */
.chip {
  display: inline-flex; align-items: center; gap: var(--space-2);
  font: 600 var(--text-xs)/1 var(--mono);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 0.45em 0.75em;
  border-radius: var(--radius-full);
  border: 1px solid var(--border);
  background: var(--card);
  color: var(--chip-color, var(--muted-ink));
}
.chip::before {
  content: "";
  width: 6px; height: 6px;
  border-radius: 50%;
  background: currentColor;
  flex: 0 0 auto;
}
.chip-convention { --chip-color: var(--brand); }
.chip-secops { --chip-color: var(--destructive); }
.chip-cost { --chip-color: var(--warning); }

/* ---------------- components: findings ----------------
   The unit of the product's PR comment: a severity tag, an evidence
   file:line link, and the claim. Pairs with .chip above for category. */
.finding {
  display: flex; gap: var(--space-3); align-items: flex-start;
  padding: var(--space-3);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--card);
}
.finding .tag {
  flex: 0 0 auto;
  font: 700 var(--text-2xs)/1.4 var(--mono);
  letter-spacing: 0.05em;
  text-transform: uppercase;
  padding: 0.25em 0.55em;
  border-radius: var(--radius-sm);
  margin-top: 0.1em;
}
.tag-critical { color: var(--destructive); background: color-mix(in oklab, var(--destructive) 14%, transparent); }
.tag-warn { color: var(--warning); background: color-mix(in oklab, var(--warning) 16%, transparent); }
.finding-body { flex: 1; min-width: 0; font-size: var(--text-sm); }
.finding-body b { font: 600 var(--text-sm)/1.5 var(--mono); }
.finding-body p { margin-top: 2px; color: var(--muted-ink); }
/* file:line evidence — always a link (or looks like one) to the exact source */
.evidence {
  font: 500 var(--text-xs)/1.6 var(--mono);
  color: var(--brand);
  border-bottom: 1px dotted color-mix(in oklab, var(--brand) 50%, transparent);
}
.evidence:hover { color: var(--ink); }

/* ---------------- components: badges ----------------
   The enforced/documented split: a rule that gates the merge vs. one that's
   only recorded. Never interchange these two — the distinction is real. */
.badge-enforced, .badge-documented {
  display: inline-flex; align-items: center;
  font: 700 var(--text-2xs)/1 var(--mono);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 0.4em 0.65em;
  border-radius: var(--radius-full);
}
.badge-enforced { background: var(--brand-solid); color: var(--on-brand); }
.badge-documented { background: transparent; border: 1px dashed var(--border-strong); color: var(--muted-ink); }

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

/* ---------------- reveal-on-scroll ----------------
   Hidden-for-animation ONLY when JS is live (html.js set inline in <head>).
   No JS — crawlers, previews — means no hiding. */
.js .reveal {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 0.7s cubic-bezier(0.2, 0.6, 0.2, 1) var(--d, 0s),
              transform 0.7s cubic-bezier(0.2, 0.6, 0.2, 1) var(--d, 0s);
}
.js .reveal.in { opacity: 1; transform: none; }

/* ---------------- responsive ---------------- */
@media (max-width: 880px) {
  .plans { grid-template-columns: 1fr; }
  .plan .for { min-height: 0; }
  .foot-grid { grid-template-columns: 1fr; gap: 22px; }
  .top nav { gap: 14px; }
  .top nav a { font-size: 12px; }
}
@media (max-width: 480px) {
  .top nav a:not(.nav-cta) { display: none; }
  .brand-lockup .name { font-size: 15px; }
}

/* ---------------- reduced motion ---------------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .grain { animation: none; }
  .js .reveal { opacity: 1; transform: none; transition: none; }
}

/* li text flows as one run beside the tick */
.plan li .txt { flex: 1; min-width: 0; }

/* billing period toggle */
.bill-toggle {
  display: inline-flex;
  margin-top: 28px;
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  padding: 4px;
  background: var(--card);
  gap: 4px;
}
.bill-opt {
  font: 600 13px/1 var(--sans);
  color: var(--muted-ink);
  background: transparent;
  border: 0;
  border-radius: 999px;
  padding: 9px 18px;
  cursor: pointer;
  transition: color 0.15s ease-in-out, background 0.15s ease-in-out;
}
.bill-opt:hover { color: var(--ink); }
.bill-opt.on { background: var(--brand-solid); color: var(--on-brand); }
.bill-opt .save {
  font-size: 10.5px;
  font-family: var(--mono);
  letter-spacing: 0.04em;
  opacity: 0.85;
  margin-left: 4px;
}
.amount { transition: opacity 0.15s ease-in-out; }
.amount.swap { opacity: 0; }

/* ---------------- pricing: at-a-glance tier strip ----------------
   Infracost-style compact restatement of what the full .plan cards below
   already spell out — same repo/review numbers, faster to scan before
   committing to four bullet lists. Shares .amount's monthly/annual swap
   (generic [data-monthly][data-annual] wiring in script.js), so it stays in
   sync with the billing toggle for free. */
.tier-glance {
  max-width: 1300px;
  margin: 0 auto;
  padding: 0 clamp(20px, 5vw, 56px);
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 12px;
}
.tier-glance .tg { text-align: center; padding: var(--space-4); }
.tier-glance .tg .name {
  font: 600 11px/1 var(--mono);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--brand);
}
.tier-glance .tg .amt {
  margin-top: 8px;
  font: 700 1.4rem/1 var(--sans);
  letter-spacing: -0.02em;
}
.tier-glance .tg .amt small { font-size: 0.6em; font-weight: 500; color: var(--muted-ink); }
.tier-glance .tg .fits { margin-top: 6px; font-size: 12.5px; color: var(--muted-ink); }
@media (max-width: 1140px) {
  .tier-glance { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ---------------- ambient motion & pointer interactivity ---------------- */
/* the aurora breathes — and leans toward the cursor inside the hero (--ax/--ay) */
@keyframes aurora-breathe {
  /* Breathes RELATIVE to the theme's own air (--atmo-opacity): hardcoded
     opacity here silently overrode the light theme's stronger aurora. */
  0%, 100% { transform: translateX(calc(-50% + var(--ax, 0px))) translateY(var(--ay, 0px)) scale(1); opacity: var(--atmo-opacity); }
  50%      { transform: translateX(calc(-50% + var(--ax, 0px))) translateY(var(--ay, 0px)) scale(1.07); opacity: calc(var(--atmo-opacity) + 0.12); }
}
.aurora { animation: aurora-breathe 12s ease-in-out infinite; }

/* the hero watermark drifts gently against the cursor, and swells toward
   the viewer while the hero exits — cheap depth-of-field */
.hero-mark {
  transform: translateX(calc(-50% - var(--ax, 0px) * 0.6))
             translateY(calc(var(--ay, 0px) * -0.6 + var(--exit, 0) * -60px))
             scale(calc(1 + var(--exit, 0) * 0.22));
  transition: transform 0.35s cubic-bezier(0.22, 1, 0.36, 1);
}

/* closing section echoes the hero's aurora */
.closing { position: relative; overflow: hidden; }
.closing > *:not(.aurora) { position: relative; z-index: 1; }
.closing .aurora { position: absolute; z-index: 0; top: auto; bottom: -420px; opacity: 0.4; }

/* pointer spotlight on plan cards */
.plan { position: relative; }
.plan::after {
  content: "";
  position: absolute; inset: 0;
  border-radius: inherit;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.35s ease-in-out;
  background: radial-gradient(240px circle at var(--mx, 50%) var(--my, 50%),
              color-mix(in oklab, var(--brand) 9%, transparent), transparent 70%);
}
.plan:hover::after { opacity: 1; }

/* CTA sheen sweep */
.cta { position: relative; overflow: hidden; }
.cta::before {
  content: "";
  position: absolute; top: 0; bottom: 0; left: -75%; width: 45%;
  background: linear-gradient(105deg, transparent, rgb(255 255 255 / 0.22), transparent);
  transform: skewX(-20deg);
  pointer-events: none;
}
.cta:hover::before { animation: sheen 0.7s ease; }
@keyframes sheen { to { left: 130%; } }

/* stack chips come alive */
.stack-chip { transition: transform 0.2s ease, border-color 0.2s ease, color 0.2s ease, box-shadow 0.2s ease; }
.stack-chip:hover {
  transform: translateY(-2px);
  border-color: var(--brand);
  color: var(--ink);
  box-shadow: 0 6px 24px -12px var(--brand-glow);
}

@media (prefers-reduced-motion: reduce) {
  .aurora { animation: none; }
  .cta:hover::before { animation: none; }
  .hero-mark { transition: none; }
}

/* small email fallback under booking CTAs */
.alt-contact { margin-top: 16px; font: 400 12.5px/1 var(--mono); color: var(--muted-ink); }
.alt-contact a { color: var(--brand); border-bottom: 1px dotted color-mix(in oklab, var(--brand) 50%, transparent); }
.alt-contact a:hover { color: var(--ink); }

/* the PR comment mock — the artifact engineers actually see */
.pr-mock { max-width: 780px; margin: 0 auto; border: 1px solid var(--border-strong); border-radius: 12px; background: var(--card); overflow: hidden; }
.pr-head { display: flex; align-items: center; gap: 8px; padding: 12px 16px; border-bottom: 1px solid var(--border); font-size: 13px; }
/* the one sanctioned non-logo use of --garboard: the bot avatar chip that
   carries the mark image itself, tinted to match it */
.pr-avatar { display: inline-flex; width: 26px; height: 26px; border-radius: 50%; background: color-mix(in oklab, var(--garboard) 18%, var(--bg)); align-items: center; justify-content: center; }
.pr-head b { font-weight: 600; }
.pr-head .bot { font: 500 10px/1 var(--mono); color: var(--muted-ink); border: 1px solid var(--border-strong); border-radius: 999px; padding: 3px 7px; }
.pr-when { color: var(--muted-ink); font-size: 12.5px; }
.pr-body { padding: 16px; }
.pr-sum { font-size: 13.5px; margin-bottom: 14px; }
.pr-sum .blocked { color: var(--destructive); font-weight: 650; }
.pr-btn { flex: 0 0 auto; font: 600 11.5px/1 var(--sans); color: var(--on-brand); background: var(--brand-solid); border-radius: 7px; padding: 8px 12px; white-space: nowrap; }

/* ---------------- subscribe form ---------------- */
.sub-form { display: flex; gap: 10px; justify-content: center; margin-top: 40px; flex-wrap: wrap; }
.sub-form input[type="email"] {
  font: 400 14px/1 var(--sans); color: var(--ink);
  background: var(--card); border: 1px solid var(--border-strong);
  border-radius: 10px; padding: 13px 16px; width: min(300px, 80vw); outline: none;
  transition: border-color 0.2s ease;
}
.sub-form input[type="email"]:focus { border-color: var(--brand); }
.sub-form .hp { position: absolute; left: -9999px; width: 1px; height: 1px; opacity: 0; }
.sub-note { margin-top: 12px; font: 400 12px/1.5 var(--mono); color: var(--muted-ink); }
.sub-note.ok { color: var(--success); }

/* ---------------- doc pages (security / legal) ---------------- */
.doc { max-width: 720px; margin: 0 auto; padding: 150px clamp(20px, 5vw, 56px) 90px; }
.doc h1 { font-size: clamp(1.9rem, 4.5vw, 2.8rem); letter-spacing: -0.03em; line-height: 1.12; margin-bottom: 34px; }
.doc h1 .accent { color: var(--brand); }
.doc h2 { font-size: 1.15rem; font-weight: 650; letter-spacing: -0.01em; margin: 34px 0 10px; }
.doc p { font-size: 14.5px; color: var(--muted-ink); line-height: 1.7; margin-bottom: 12px; }
.doc p strong, .doc p em { color: var(--ink); font-style: normal; }
.doc code { font: 500 12.5px/1 var(--mono); color: var(--brand); }
.doc a { color: var(--brand); border-bottom: 1px dotted color-mix(in oklab, var(--brand) 50%, transparent); }
.foot-base a { color: inherit; border-bottom: 1px dotted color-mix(in oklab, var(--muted-ink) 50%, transparent); }

/* ---------------- immersion layer ---------------- */
/* hero headline enters word by word (spans injected by JS; no-JS unaffected) */
.js .hero h1 .w {
  display: inline-block;
  opacity: 0;
  transform: translateY(0.55em) rotate(1.5deg);
  filter: blur(8px);
  transition: opacity 0.6s ease var(--wd, 0s),
              transform 0.85s cubic-bezier(0.22, 1, 0.36, 1) var(--wd, 0s),
              filter 0.6s ease var(--wd, 0s);
}
.js .hero h1.in .w { opacity: 1; transform: none; filter: none; }

/* accent text carries a slow light-sweep */
@supports (-webkit-background-clip: text) {
  /* .accent .w too: the split hero headline wraps accent words in inline-block
     spans, and a parent's clipped gradient doesn't reliably paint through them */
  .accent, .accent .w {
    background: linear-gradient(100deg,
                var(--brand) 0%, var(--accent-shimmer) 46%, var(--brand) 62%);
    background-size: 220% 100%;
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    animation: shimmer 7s ease-in-out infinite;
  }
}
@keyframes shimmer {
  0%, 100% { background-position: 0% 0; }
  50%      { background-position: 100% 0; }
}

/* JS tags the PR-comment mock .tilt — perspective lean + a glare that tracks the cursor */
.tilt { position: relative; }
.tilt::after {
  content: "";
  position: absolute; inset: 0;
  border-radius: inherit;
  pointer-events: none;
  opacity: 0;
  z-index: 2;
  transition: opacity 0.3s ease;
  background: radial-gradient(340px circle at var(--gx, 50%) var(--gy, 50%),
              rgb(255 255 255 / 0.07), transparent 70%);
}
.tilt:hover::after { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  .hero { opacity: 1; transform: none; }
  .hero-mark { transform: translateX(-50%); }
  .accent { animation: none; }
  .js .hero h1 .w { opacity: 1; transform: none; filter: none; transition: none; }
  .tilt::after { display: none; }
}
