/* Cairnward · "Honest Routing" design system (SPEC §3 as floor)
   Type: Fraunces (display, variable opsz) · Public Sans (body) · IBM Plex Mono (system voice)
   Amber appears ONLY as CTA fills and cloud-state fills, always with ink text. */

/* ---------- fonts ---------- */

@font-face {
  font-family: Fraunces;
  src: url("fonts/fraunces-var.woff2") format("woff2");
  font-weight: 400 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Public Sans";
  src: url("fonts/public-sans-var.woff2") format("woff2");
  font-weight: 400 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Public Sans";
  src: url("fonts/public-sans-italic.woff2") format("woff2");
  font-weight: 400;
  font-style: italic;
  font-display: swap;
}
@font-face {
  font-family: "IBM Plex Mono";
  src: url("fonts/plex-mono-400.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "IBM Plex Mono";
  src: url("fonts/plex-mono-500.woff2") format("woff2");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}

/* Metric-compatible local fallbacks (generated by scripts/gen_fallback_metrics.py);
   font-display:swap repaints without layout shift. */
@font-face {
  font-family: "Fraunces-fb";
  src: local("Georgia");
  size-adjust: 107.98%;
  ascent-override: 90.57%;
  descent-override: 23.62%;
  line-gap-override: 0.00%;
}
@font-face {
  font-family: "PublicSans-fb";
  src: local("Arial");
  size-adjust: 105.29%;
  ascent-override: 90.23%;
  descent-override: 21.37%;
  line-gap-override: 0.00%;
}
@font-face {
  font-family: "PlexMono-fb";
  src: local("Consolas");
  size-adjust: 109.13%;
  ascent-override: 93.92%;
  descent-override: 25.20%;
  line-gap-override: 0.00%;
}

/* ---------- tokens ---------- */

:root {
  --ink: #14212b;
  --paper: #fafbfc;
  --local-blue: #1a4e96;
  --cloud-amber: #c9861b;
  --slate: #5a6b7a;
  --hairline: #e3e8ed;

  /* Design-constitution §2 mapping (compliance, not restyle): field.light is
     exactly this surface's paper, aliased below. The remaining Honest-Routing
     values are this surface's deliberate expression; the constitution defers to
     the site for state.local blue and body faces. accent.bronze #B08D57 appears
     only in brand assets (og image, favicon glyph), never in page chrome. */
  --field-light: var(--paper);

  --font-display: Fraunces, "Fraunces-fb", Georgia, serif;
  --font-body: "Public Sans", "PublicSans-fb", Arial, system-ui, sans-serif;
  --font-mono: "IBM Plex Mono", "PlexMono-fb", Consolas, ui-monospace, monospace;

  /* Fluid modular scale: ~1.2 at 360px → ~1.25 at 1440px; the H1 step is
     stretched past the ratio on purpose (the one loud thing on the page). */
  --fs--2: clamp(0.75rem, 0.7292rem + 0.0926vw, 0.8125rem);   /* 12 → 13  eyebrows */
  --fs--1: clamp(0.8125rem, 0.7917rem + 0.0926vw, 0.875rem);  /* 13 → 14  micro/mono */
  --fs-0: clamp(1.0625rem, 1.0417rem + 0.0926vw, 1.125rem);   /* 17 → 18  body */
  --fs-1: clamp(1.28125rem, 1.2396rem + 0.1852vw, 1.40625rem);/* 20.5 → 22.5 lead */
  --fs-2: clamp(1.5rem, 1.4167rem + 0.3704vw, 1.75rem);       /* 24 → 28  h3 */
  --fs-3: clamp(1.8125rem, 1.6875rem + 0.5556vw, 2.1875rem);  /* 29 → 35  h2 */
  --fs-4: clamp(2.125rem, 1.9167rem + 0.9259vw, 2.75rem);     /* 34 → 44  final h2 */
  --fs-5: clamp(2.25rem, 1.75rem + 2.2222vw, 3.75rem);        /* 36 → 60  h1 (mobile floor keeps the triad to three lines) */
  --fs-badge: clamp(0.8125rem, 0.7708rem + 0.1852vw, 0.9375rem); /* 13 → 15 */

  /* 8px rhythm */
  --sp-1: 0.5rem;
  --sp-2: 1rem;
  --sp-3: 1.5rem;
  --sp-4: 2rem;
  --sp-5: 3rem;
  --sp-6: 4rem;
  --sp-7: 6rem;

  --wash: color-mix(in srgb, var(--ink) 3%, var(--paper));
  --radius: 10px;
}

/* ---------- base ---------- */

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

html {
  color-scheme: light;
  background: var(--paper);
  scroll-behavior: smooth;
}

body {
  margin: 0;
  font: 400 var(--fs-0) / 1.65 var(--font-body);
  color: var(--ink);
  font-synthesis: style; /* never fake weights; oblique allowed where no italic face ships */
  font-kerning: normal;
}

h1,
h2,
h3,
p,
ul,
ol,
figure,
blockquote {
  margin: 0;
}

::selection {
  background: var(--local-blue);
  color: var(--paper);
}

:focus-visible {
  outline: 2px solid var(--local-blue);
  outline-offset: 3px;
  border-radius: 2px;
}

a {
  color: var(--local-blue);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.2em;
}

b,
strong {
  font-weight: 600;
}

[hidden] {
  display: none !important;
}

.skip-link {
  position: absolute;
  left: -999px;
  top: 0;
  background: var(--ink);
  color: var(--paper);
  padding: 0.6em 1em;
  z-index: 10;
}

.skip-link:focus-visible {
  left: 0.5rem;
  top: 0.5rem;
}

.shell {
  max-width: 42rem;
  margin-inline: auto;
  padding-inline: clamp(1.25rem, 5vw, 2rem);
}

/* ---------- type detail ---------- */

h1 {
  font-family: var(--font-display);
  font-size: var(--fs-5);
  font-weight: 570;
  line-height: 1.06;
  letter-spacing: -0.015em;
  font-optical-sizing: auto;
  font-variation-settings: "opsz" 144; /* the full display cut, H1 only */
}

.h1-line {
  display: block;
}

h2 {
  font-family: var(--font-display);
  font-size: var(--fs-3);
  font-weight: 540;
  line-height: 1.14;
  letter-spacing: -0.008em;
  font-optical-sizing: auto; /* opsz rides rendered size: sturdier cut than H1 */
  text-wrap: balance;
}

h3 {
  font-family: var(--font-body);
  font-size: var(--fs-1);
  font-weight: 600;
  line-height: 1.35;
  letter-spacing: -0.005em;
  text-wrap: balance;
}

.eyebrow {
  font: 500 var(--fs--2) / 1 var(--font-mono);
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--slate);
  margin-bottom: var(--sp-2);
}

.prose p {
  max-width: 68ch;
}

.prose > * + * {
  margin-top: 1.15em;
}

.arrow {
  font-family: var(--font-mono); /* Public Sans has no ↓; the mono carries it */
}

/* ---------- badge pill ---------- */

.badge {
  --badge-n: 34; /* chars in "LOCAL · 0 bytes leave this machine"; asserted by verify_copy.py */
  display: inline-flex;
  align-items: center;
  gap: 0.55em;
  padding: 0.5em 0.95em;
  border-radius: 999px;
  font: 500 var(--fs-badge) / 1.2 var(--font-mono);
  /* no letter-spacing: the type-on reveal is calc(n × 1ch); tracking would
     widen the real string past the reveal box and clip the last character */
}

.badge--local {
  background: var(--local-blue);
  color: var(--paper);
}

.badge--cloud {
  background: var(--cloud-amber);
  color: var(--ink);
}

.badge__dot {
  inline-size: 0.5em;
  block-size: 0.5em;
  border-radius: 50%;
  background: currentColor;
  flex: none;
}

.badge__text {
  display: inline-block;
  white-space: nowrap;
  border-right: 2px solid transparent;
  box-sizing: content-box; /* the reveal box is exactly n×1ch of text; the caret border must ride outside it */
}

/* Signature moment 1: the badge types on once. Pure CSS: full text always in the
   DOM and accessibility tree; a steps() reveal clips it visually, one character
   per step. The pill reserves its final width, so nothing on the page moves. */
.badge--typeon {
  min-inline-size: calc(var(--badge-n) * 1ch + 0.5em + 0.55em + 1.9em + 2px);
}

@media (prefers-reduced-motion: no-preference) {
  .badge--typeon .badge__text {
    overflow: hidden;
    border-right-color: currentColor;
    animation:
      badge-type 1190ms steps(var(--badge-n), end) 520ms both,
      badge-caret-off 1ms linear 1710ms forwards;
  }

  @keyframes badge-type {
    from {
      inline-size: 0;
    }
    to {
      inline-size: calc(var(--badge-n) * 1ch);
    }
  }

  @keyframes badge-caret-off {
    to {
      border-right-color: transparent;
    }
  }
}

/* ---------- hero ---------- */

.hero {
  padding-block: clamp(5rem, 6vw + 3rem, 8.5rem) clamp(4rem, 5vw + 2rem, 6.5rem);
}

.hero h1 {
  margin-top: var(--sp-4);
}

.hero__sub {
  margin-top: var(--sp-4);
  font-size: var(--fs-1);
  line-height: 1.55;
  max-width: 56ch;
}

.hero__cta {
  margin-top: var(--sp-5);
}

.microcopy {
  margin-top: var(--sp-2);
  font: 400 var(--fs--1) / 1.6 var(--font-mono);
  font-variant-numeric: tabular-nums;
  color: var(--slate);
  max-width: 52ch;
}

.hero__demo-link {
  margin-top: var(--sp-3);
}

.demo-link {
  font-weight: 500;
  text-decoration-color: color-mix(in srgb, var(--local-blue) 45%, transparent);
  transition: text-decoration-color 140ms ease;
}

.demo-link:hover {
  text-decoration-color: var(--local-blue);
}

.trustline {
  margin-top: var(--sp-6);
  font-size: var(--fs--1);
  color: var(--slate);
}

@media (prefers-reduced-motion: no-preference) {
  /* The H1 never animates: it must paint at first render (it is the LCP
     element) and the promise reads strongest as the fixed point everything
     else settles around. */
  .hero .shell > :not(h1) {
    animation: rise 460ms cubic-bezier(0.2, 0.7, 0.3, 1) both;
  }
  .hero .shell > :nth-child(3) { animation-delay: 120ms; }
  .hero .shell > :nth-child(4) { animation-delay: 200ms; }
  .hero .shell > :nth-child(5) { animation-delay: 280ms; }

  @keyframes rise {
    from {
      opacity: 0;
      translate: 0 10px;
    }
  }
}

/* ---------- buttons ---------- */

.btn {
  display: inline-block;
  font: 600 var(--fs-0) / 1 var(--font-body);
  background: var(--cloud-amber); /* amber: CTA fill, ink text, per spec */
  color: var(--ink);
  padding: 0.95em 1.6em;
  border-radius: 8px;
  text-decoration: none;
  transition: filter 140ms ease, translate 140ms ease;
}

.btn:hover {
  filter: brightness(0.955);
  translate: 0 -1px;
}

.btn:active {
  translate: 0 0;
  filter: brightness(0.92);
}

/* ---------- sections & rhythm ---------- */

.section {
  padding-block: clamp(4rem, 3rem + 4vw, 6.75rem);
  border-top: 1px solid var(--hairline);
}

.section__head {
  margin-bottom: clamp(2rem, 1.5rem + 2vw, 3rem);
}

.section__lead {
  margin-top: var(--sp-3);
  font-size: var(--fs-1);
  line-height: 1.5;
  max-width: 58ch;
}

/* acts breathe differently: the relief and the door get more air */
#security,
.section--offer {
  padding-block: clamp(4.5rem, 3.5rem + 4.5vw, 7.5rem);
}

section[id] {
  scroll-margin-top: 1rem;
}

/* ---------- §4 method ---------- */

.method {
  list-style: none;
  padding: 0;
  display: grid;
  gap: var(--sp-4);
}

.method li {
  border-left: 2px solid var(--hairline);
  padding-left: clamp(1rem, 3vw, 1.5rem);
}

.method li p {
  max-width: 66ch;
}

.roi {
  margin-top: var(--sp-6);
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  background: var(--wash);
  padding: clamp(1.25rem, 4vw, 2rem);
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
}

.roi__label {
  font: 500 var(--fs--2) / 1 var(--font-mono);
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--slate);
  margin-bottom: var(--sp-2);
}

.roi p:not(.roi__label) {
  font-size: var(--fs--1);
  line-height: 1.75;
  max-width: 68ch;
}

/* ---------- §5 demo video (self-hosted; no third party involved) ---------- */

.video {
  margin-bottom: clamp(2rem, 1.5rem + 2vw, 3rem);
}

.video__player {
  display: block;
  inline-size: 100%;
  block-size: auto;
  aspect-ratio: 16 / 9;
  background: var(--ink);
  border-radius: 12px;
}

.video__player:focus-visible {
  outline: 2px solid var(--local-blue);
  outline-offset: 3px;
}

.video__noscript {
  margin-top: var(--sp-2);
}

/* the accessible transcript, under the player */
.transcript {
  margin-top: var(--sp-3);
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  background: var(--wash);
}

.transcript summary {
  display: flex;
  align-items: center;
  gap: 0.6em;
  padding: 0.85rem 1.1rem;
  cursor: pointer;
  font: 500 var(--fs--1) / 1 var(--font-mono);
  letter-spacing: 0.04em;
  color: var(--slate);
  list-style: none;
}

.transcript summary::-webkit-details-marker {
  display: none;
}

.transcript summary::before {
  content: "";
  flex: none;
  inline-size: 0.45rem;
  block-size: 0.45rem;
  border-right: 1.5px solid var(--slate);
  border-bottom: 1.5px solid var(--slate);
  transform: rotate(-45deg); /* points right when closed */
  transition: transform 180ms ease;
}

.transcript[open] summary::before {
  transform: rotate(45deg); /* points down when open */
}

.transcript summary:hover {
  color: var(--ink);
}

.transcript__body {
  padding: 0.25rem 1.1rem 1.25rem;
}

.transcript__body p {
  max-width: 66ch;
  margin-top: var(--sp-2);
  font-size: var(--fs--1);
  line-height: 1.6;
}

.transcript__ch {
  font: 500 var(--fs--2) / 1 var(--font-mono);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--slate);
  margin-top: var(--sp-3);
}

.transcript__dl {
  margin-top: var(--sp-3);
}

/* ---------- lists (§5 what-you'll-see, §6 security, §7 offer) ---------- */

.checks,
.plain-list {
  list-style: none;
  padding: 0;
  display: grid;
  gap: var(--sp-2);
}

.checks li,
.plain-list li {
  position: relative;
  padding-left: 1.6rem;
  max-width: 68ch;
}

.checks li::before,
.plain-list li::before {
  content: "";
  position: absolute;
  left: 0.35rem;
  top: 0.65em;
  inline-size: 6px;
  block-size: 6px;
  border-radius: 50%;
  background: var(--local-blue);
}

.checks {
  margin-top: var(--sp-3);
}

/* Signature moment 3: the delete-moment beat. */
.gone {
  font-family: var(--font-display);
  font-weight: 560;
  font-size: 1.22em;
  line-height: 1;
  letter-spacing: -0.01em;
  font-variation-settings: "opsz" 40;
}

.no-terminal {
  margin-top: var(--sp-4);
  font-weight: 500;
}

/* ---------- §6 route toggle (signature moment 2) ---------- */

.route {
  border: 1px solid var(--hairline);
  border-radius: 12px;
  background: var(--wash);
  padding: clamp(1.5rem, 4vw, 2.5rem);
  margin-bottom: clamp(2rem, 1.5rem + 2vw, 3rem);
}

.route__static {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sp-4);
}

@media (max-width: 560px) {
  .route__static {
    grid-template-columns: 1fr;
  }
}

.route__card {
  display: grid;
  justify-items: start;
  align-content: start;
  gap: 0.8rem;
}

.route__caption {
  font: 400 var(--fs--1) / 1.6 var(--font-mono);
  color: var(--slate);
  max-width: 34ch;
}

/* interactive variant exists only once JS has actually wired it */
.route__interactive {
  display: none;
}

.js .route__interactive {
  display: grid;
  justify-items: center;
  text-align: center;
  gap: var(--sp-3);
}

.js .route__static {
  display: none;
}

.js .route__interactive .route__caption {
  min-block-size: 3lh; /* reserve the taller caption; the swap moves nothing */
  max-width: 38ch;
}

.route__seg {
  display: inline-flex;
  gap: 3px;
  padding: 3px;
  border: 1px solid var(--hairline);
  border-radius: 999px;
  background: var(--paper);
}

.route__seg button {
  font: 500 var(--fs--1) / 1 var(--font-mono);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  border: 0;
  background: transparent;
  color: var(--slate);
  padding: 0.55em 1.2em;
  border-radius: 999px;
  cursor: pointer;
  transition: background-color 160ms ease, color 160ms ease;
}

.route__seg button[data-route-btn="local"][aria-pressed="true"] {
  background: var(--local-blue);
  color: var(--paper);
}

.route__seg button[data-route-btn="cloud"][aria-pressed="true"] {
  background: var(--cloud-amber); /* amber: cloud state selected */
  color: var(--ink);
}

.route__state-badge {
  transition: background-color 160ms ease, color 160ms ease;
}

.route[data-route="local"] .route__state-badge {
  background: var(--local-blue);
  color: var(--paper);
}

.route[data-route="cloud"] .route__state-badge {
  background: var(--cloud-amber); /* amber: cloud state badge */
  color: var(--ink);
}

/* ---------- §7 offer ---------- */

.offer {
  border: 1px solid var(--hairline);
  border-radius: 12px;
  padding: clamp(1.5rem, 5vw, 2.75rem);
}

.offer h3 {
  margin-bottom: var(--sp-3);
}

.offer h3 + .plain-list {
  margin-bottom: var(--sp-5);
}

.offer__excluded {
  max-width: 68ch;
}

.offer__terms {
  margin-top: var(--sp-4);
  border-top: 1px solid var(--hairline);
  padding-top: var(--sp-4);
  display: grid;
  gap: var(--sp-2);
  font-variant-numeric: tabular-nums;
}

.offer__terms p {
  max-width: 68ch;
}

.offer__cta {
  margin-top: var(--sp-5);
}

/* ---------- §8 founder ---------- */

.portrait {
  margin-bottom: var(--sp-5);
}

/* The portrait ships flattened onto the section field (--paper), so it sits
   borderless on the page; the baked-in soft shadow carries the depth. */
.portrait__img {
  display: block;
  inline-size: min(230px, 58%);
  block-size: auto;
}

/* ---------- §9 FAQ ---------- */

.faq-list {
  border-top: 1px solid var(--hairline);
}

.faq {
  border-bottom: 1px solid var(--hairline);
}

.faq summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  padding: 1.15rem 0.25rem 1.15rem 0;
  cursor: pointer;
  list-style: none;
}

.faq summary::-webkit-details-marker {
  display: none;
}

.faq summary h3 {
  font-size: calc(var(--fs-0) * 1.02);
  line-height: 1.45;
  font-weight: 600;
  flex: 1;
}

.faq summary:hover h3 {
  color: var(--local-blue);
}

.faq__chev {
  flex: none;
  inline-size: 0.55rem;
  block-size: 0.55rem;
  border-right: 1.5px solid var(--slate);
  border-bottom: 1.5px solid var(--slate);
  transform: rotate(45deg);
  transition: transform 180ms ease;
  margin-top: -0.25em;
}

.faq[open] .faq__chev {
  transform: rotate(225deg);
  margin-top: 0.25em;
}

.faq__a {
  padding: 0.25rem 0 1.5rem;
}

.faq__a p {
  max-width: 66ch;
}

/* ---------- §10 final + footer ---------- */

.section--final {
  text-align: center;
  padding-block: clamp(5rem, 4rem + 5vw, 8.5rem);
}

.section--final h2 {
  font-size: var(--fs-4);
  margin-inline: auto;
  max-width: 22ch;
}

.final__sub {
  margin-top: var(--sp-3);
  font-size: var(--fs-1);
  line-height: 1.5;
  max-width: 44ch;
  margin-inline: auto;
}

.final__cta {
  margin-top: var(--sp-5);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  column-gap: var(--sp-2);
  row-gap: var(--sp-2);
}

.final__intro {
  margin-top: var(--sp-3);
}

.final__door {
  margin-top: var(--sp-2);
  font-size: var(--fs--1);
  color: var(--slate);
  max-width: 52ch;
  margin-inline: auto;
}

.final__demo {
  margin-top: var(--sp-4);
  font-size: var(--fs--1);
  color: var(--slate);
}

.footer {
  border-top: 1px solid var(--hairline);
  padding-block: var(--sp-5);
  text-align: center;
}

.footer p {
  font-size: var(--fs--1);
  color: var(--slate);
  max-width: 68ch;
  margin-inline: auto;
}

/* ---------- staged fade-ups (the scroll is the story) ----------
   .rv marks candidates; main.js adds .rv-h only to below-fold elements once the
   revealer is alive, so no failure mode can hide content. */

.rv-h {
  opacity: 0;
  translate: 0 12px;
}

.rv-h.on {
  opacity: 1;
  translate: 0 0;
  transition: opacity 190ms ease-out, translate 190ms ease-out;
  transition-delay: var(--rvd, 0ms);
}

/* the "Gone." beat lands just after its sentence settles */
.rv-h .gone {
  opacity: 0;
}

.rv-h.on .gone {
  opacity: 1;
  transition: opacity 280ms ease-out;
  transition-delay: calc(var(--rvd, 0ms) + 430ms);
}

/* print: reveals must not hide content on paper */
@media print {
  .rv-h,
  .rv-h .gone {
    opacity: 1 !important;
    translate: none !important;
  }
}

/* ---------- reduced motion: everything off, everything visible ---------- */

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation: none !important;
    transition: none !important;
  }

  html {
    scroll-behavior: auto;
  }

  .rv-h,
  .rv-h .gone {
    opacity: 1 !important;
    translate: none !important;
  }

  .badge--typeon .badge__text {
    inline-size: auto !important;
    border-right-color: transparent !important;
  }
}
