/* ==========================================================================
   yahai.app — site.css
   One stylesheet for every page. No build step, no external requests.

   Everything derives from the one brand artifact the app has: the icon
   (AppIcons/Icon-1024.png) — a torn-paper tile, teal at top-left to deep
   purple at bottom-right, cream hand-lettered "Yah" on a white ground.
   Every color below was measured from that file or derived from it, and
   every text/background pair used for words meets WCAG AA (see notes).

   Rules of the house:
   - Brand teal (#48BEBC) is decorative only in light mode: it is 2.24:1 on
     white and must never carry text or a state indicator there. --teal-text
     (#1A6E6B, 6.02:1 on white, 5.63:1 on paper-warm, 5.39:1 on code-bg)
     carries the rare teal label and the selected-tab / current-nav rule;
     --plum carries links and buttons. Ratios in the comments are measured
     (WCAG 2.x relative luminance), not rounded.
   - Every control boundary (inputs, secondary buttons, copy buttons, device
     chips) uses --control-border, which clears the 3:1 non-text minimum in
     both schemes; --line and --line-strong are for decorative rules only.
   - No glass on glass. Cards are solid; the hairline is the app's
     0.5px-at-8% rule.
   - Headings are sentence case. No all-caps.
   - Motion is limited to the hero halo and is removed under
     prefers-reduced-motion.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Tokens
   -------------------------------------------------------------------------- */
:root {
  color-scheme: light dark;

  /* Light palette (default) */
  --paper: #FFFFFF;          /* the icon's own ground */
  --paper-warm: #FAF7F1;     /* cream #E3D5B9 at ~8% over white */
  --ink: #1B1420;            /* purple-black, derived from #49224F (17.99:1 on white) */
  --ink-dim: #5C5364;        /* secondary text (7.30:1 on white, 6.83:1 on paper-warm) */
  --line: #E6E1DA;           /* decorative rules only (1.3:1) */
  --line-strong: #CFC7BC;    /* decorative rules only (1.67:1 — never a control boundary) */
  --control-border: #857B8C; /* control boundaries: 4.03:1 on white, 3.77:1 on paper-warm (≥ 3:1, WCAG 1.4.11) */
  --code-bg: #F5F2ED;
  --plum: #55295A;           /* links, primary buttons (11.34:1 on white) */
  --plum-deep: #69205B;      /* hover / pressed */
  --teal: #48BEBC;           /* decorative only in light mode (2.24:1 on white) */
  --teal-text: #1A6E6B;      /* the one teal that may carry text or a state rule on white (6.02:1; 5.63:1 on paper-warm; 5.39:1 on code-bg) */
  --cream: #E3D5B9;          /* button text on plum (7.82:1), badges */

  /* Semantic */
  --bg: var(--paper);
  --bg-alt: var(--paper-warm);
  --fg: var(--ink);
  --fg-dim: var(--ink-dim);
  --link: var(--plum);
  --link-hover: var(--plum-deep);
  --focus: var(--teal-text);
  --btn-bg: var(--plum);
  --btn-bg-hover: var(--plum-deep);
  --btn-fg: var(--cream);
  --halo: var(--teal);
  --rule: var(--teal);             /* decorative: halo, hairlines, diagram strokes, quote bars */
  --rule-strong: var(--teal-text); /* state indicators: the selected tab, the current nav link (≥ 3:1) */
  --chip-bg: var(--paper-warm);
  --chip-fg: var(--ink-dim);
  --card-bg: var(--paper);
  --hairline: rgba(27, 20, 32, 0.08);
  --shadow: 0 1px 2px rgba(27, 20, 32, 0.06), 0 8px 24px rgba(27, 20, 32, 0.06);
  --ok: #1A6E6B;             /* 6.02:1 on white */
  --err: #8A2B3B;            /* 8.44:1 on white */

  /* Type */
  --font-head: 'Iowan Old Style', 'Palatino Linotype', Palatino, 'Book Antiqua', Georgia, serif;
  --font-body: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
  --font-mono: ui-monospace, 'SF Mono', Menlo, Consolas, 'Liberation Mono', monospace;

  /* Space — the app's DS tokens (xs 6, s 10, m 12, l 16, xl 20) plus larger rhythm */
  --sp-xs: 0.375rem;   /* 6 */
  --sp-s: 0.625rem;    /* 10 */
  --sp-m: 0.75rem;     /* 12 */
  --sp-l: 1rem;        /* 16 */
  --sp-xl: 1.25rem;    /* 20 */
  --sp-2xl: 2rem;
  --sp-3xl: 3rem;
  --sp-section: clamp(3rem, 8vw, 7rem);

  /* Radius — the app's card 14 / inner 12, button 12 */
  --r-card: 14px;
  --r-inner: 12px;
  --r-btn: 12px;
  --r-chip: 999px;

  /* Measure */
  --measure: 46rem;
  --wide: 72rem;
}

@media (prefers-color-scheme: dark) {
  :root {
    --paper: #15101A;
    --paper-warm: #1C1522;
    --ink: #EEE6DA;          /* cream-tinted, not pure white */
    --ink-dim: #A79DAA;      /* 7.18:1 on #15101A */
    --line: #2C2333;
    --line-strong: #3E3347;  /* decorative only (1.58:1) */
    --control-border: #8C8195; /* 5.08:1 on #15101A, 4.82:1 on #1C1522 */
    --code-bg: #1E1826;
    --teal: #5FC9C4;         /* 9.49:1 on #15101A — carries links, buttons and state rules here */
    --teal-text: #5FC9C4;
    --plum: #B57ABC;         /* lightened, secondary accent: 5.78:1 on #15101A, 5.49:1 on chip-bg #1C1522 */
    --plum-deep: #C089C6;
    --cream: #E3D5B9;

    --link: var(--teal);
    --link-hover: #8AE0DB;
    --focus: var(--teal);
    --rule-strong: var(--teal);
    --btn-bg: var(--teal);
    --btn-bg-hover: #8AE0DB;
    --btn-fg: #15101A;       /* dark text on the teal fill (9.5:1) */
    --hairline: rgba(238, 230, 218, 0.10);
    --shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 8px 24px rgba(0, 0, 0, 0.35);
    --ok: #5FC9C4;
    --err: #F2A2AE;

    /* Cards lift off the ground in dark mode: paper-warm on a plain section,
       paper inside a warm section, so a card is never the same color as the
       band behind it. (Light mode keeps white cards; the hairline carries them.) */
    --card-bg: var(--paper-warm);
  }
  .section--warm { --card-bg: var(--paper); }
}

/* --------------------------------------------------------------------------
   2. Reset and base
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 1rem; /* the header is in normal flow, not sticky: a larger value lands every #jump above its target */
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-body);
  font-size: 1.0625rem;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

main { flex: 1 0 auto; overflow-x: clip; } /* belt and braces: nothing inside main may scroll the page sideways */
main:focus { outline: none; }               /* the skip-link target needs no ring around the whole page */

img, svg, video { max-width: 100%; height: auto; display: block; }

h1, h2, h3, h4 {
  font-family: var(--font-head);
  font-weight: 600;
  line-height: 1.15;
  letter-spacing: -0.015em;
  margin: 0 0 var(--sp-l);
  color: var(--fg);
  text-wrap: balance;
}
h1 { font-size: clamp(2.25rem, 5vw, 4.25rem); letter-spacing: -0.025em; line-height: 1.05; }
h2 { font-size: clamp(1.75rem, 3vw, 2.125rem); margin-top: 0; }
h3 { font-size: 1.375rem; }
h4 { font-size: 1.125rem; font-family: var(--font-body); font-weight: 600; letter-spacing: 0; }

p, ul, ol, dl, table, blockquote, pre, figure { margin: 0 0 var(--sp-l); }
p:last-child, ul:last-child, ol:last-child { margin-bottom: 0; }

ul, ol { padding-left: 1.25rem; }
li { margin: 0.35rem 0; }
li::marker { color: var(--fg-dim); }

a {
  color: var(--link);
  text-decoration: underline;
  text-decoration-thickness: 1.5px;
  text-underline-offset: 0.16em;
  text-decoration-color: color-mix(in srgb, var(--link) 75%, transparent);
  transition: color 120ms ease, text-decoration-color 120ms ease;
}
a:hover { color: var(--link-hover); text-decoration-color: currentColor; }

hr {
  border: 0;
  border-top: 1px solid var(--line);
  margin: var(--sp-2xl) 0;
}

strong { font-weight: 600; }
small, .small { font-size: 0.9rem; }
.muted { color: var(--fg-dim); }

blockquote {
  margin: var(--sp-xl) 0;
  padding: var(--sp-m) var(--sp-xl);
  border-left: 3px solid var(--rule);
  color: var(--fg);
  font-family: var(--font-head);
  font-size: 1.15em;
  line-height: 1.45;
}
blockquote cite { display: block; font-family: var(--font-body); font-size: 0.85rem; color: var(--fg-dim); font-style: normal; margin-top: var(--sp-s); }

code, kbd, samp {
  font-family: var(--font-mono);
  font-size: 0.875em;
}
:not(pre) > code {
  background: var(--code-bg);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 0.08em 0.38em;
  /* Inline code wraps: a 40-character PowerShell path at 360px would otherwise
     push main wider than the viewport and scroll the whole page sideways. */
  white-space: normal;
  overflow-wrap: anywhere;
}
.nowrap { white-space: nowrap; } /* opt-in for a short token that must never break */

/* Focus: teal ring, always visible. The :not(:focus-visible) form means an
   engine without :focus-visible keeps its own default ring instead of none. */
:focus:not(:focus-visible) { outline: none; }
:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 3px;
  border-radius: 4px;
}

::selection { background: color-mix(in srgb, var(--teal) 35%, transparent); }

/* --------------------------------------------------------------------------
   3. Layout primitives
   -------------------------------------------------------------------------- */
.container {
  width: 100%;
  max-width: var(--wide);
  margin-inline: auto;
  padding-inline: clamp(1rem, 4vw, 2rem);
}
.prose {
  max-width: var(--measure);
}

.section {
  padding-block: var(--sp-section);
}
.section--tight { padding-block: clamp(2rem, 5vw, 4rem); }
.section--warm { background: var(--bg-alt); }
.section > .container > h2:first-child,
.section-head { margin-bottom: var(--sp-2xl); }
.section-head p { max-width: var(--measure); color: var(--fg-dim); font-size: 1.125rem; }

.eyebrow {
  display: block;
  font-family: var(--font-body);
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--teal-text);
  margin-bottom: var(--sp-s);
}

.grid {
  display: grid;
  gap: var(--sp-xl);
  grid-template-columns: minmax(0, 1fr); /* minmax(0,…) so a <pre> inside an item scrolls instead of widening the page on phones */
}
.grid > * { min-width: 0; } /* the item, too: min-width:auto would size a card to its widest <pre> line and overflow the track */
@media (min-width: 640px) {
  .grid--2, .grid--3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (min-width: 960px) {
  .grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

.cluster { display: flex; flex-wrap: wrap; gap: var(--sp-s) var(--sp-m); align-items: center; }

.visually-hidden, .hp {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* --------------------------------------------------------------------------
   4. Header, nav, footer
   -------------------------------------------------------------------------- */
.skip-link {
  position: absolute;
  left: var(--sp-l);
  top: -4rem;
  z-index: 100;
  background: var(--btn-bg);
  color: var(--btn-fg);
  padding: var(--sp-s) var(--sp-l);
  border-radius: var(--r-btn);
  text-decoration: none;
  font-weight: 600;
  transition: top 120ms ease;
}
.skip-link:focus { top: var(--sp-l); color: var(--btn-fg); }

.site-header {
  border-bottom: 1px solid var(--line);
  background: var(--bg);
}
.site-header .container {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-l);
  min-height: 4rem;
  flex-wrap: wrap;
  padding-block: var(--sp-s);
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-s);
  text-decoration: none;
  color: var(--fg);
  font-family: var(--font-head);
  font-weight: 600;
  font-size: 1.25rem;
  letter-spacing: -0.01em;
}
.brand:hover { color: var(--fg); }
.brand img, .brand svg {
  width: 1.75rem; height: 1.75rem;
  border-radius: 7px;
  background: #FFFFFF;      /* the icon PNG has a baked white margin; keep it on white */
}
/* The header uses /icon-96.png (28 px at up to 3×); the 512 px file is only the home hero and the touch icon. */

.site-nav ul {
  list-style: none;
  margin: 0; padding: 0;
  display: flex;
  gap: clamp(0.5rem, 2vw, 1.5rem);
  flex-wrap: wrap;
}
.site-nav a {
  display: inline-block;
  min-width: 44px;            /* "Pro" is the narrow one; the box, not the word, is the target */
  text-align: center;
  padding: 0.6rem 0.45rem;    /* ≥ 44 px tall */
  margin: -0.25rem -0.35rem;  /* keeps the visual rhythm while the hit area grows */
  color: var(--fg-dim);
  text-decoration: none;
  font-weight: 500;
  font-size: 0.975rem;
  border-bottom: 2px solid transparent;
}
.site-nav a:hover { color: var(--fg); }
.site-nav a[aria-current="page"] { color: var(--fg); border-bottom-color: var(--rule-strong); }
@media (max-width: 420px) {
  /* Six items in 328 px: tighter type and gaps, the 44 px hit area kept by the padding. */
  .site-nav ul { gap: 0.15rem; }
  .site-nav a { font-size: 0.9rem; padding: 0.6rem 0.3rem; margin: -0.25rem -0.15rem; }
}

.site-footer {
  border-top: 1px solid var(--line);
  background: var(--bg-alt);
  color: var(--fg-dim);
  font-size: 0.9rem;
  margin-top: var(--sp-section);
}
.site-footer .container {
  padding-block: var(--sp-2xl);
  display: grid;
  gap: var(--sp-xl);
}
@media (min-width: 800px) {
  .site-footer .container { grid-template-columns: 2fr 1fr; }
}
.site-footer a { color: var(--fg); }
.site-footer nav ul { list-style: none; padding: 0; margin: 0; display: flex; flex-wrap: wrap; gap: var(--sp-xs) var(--sp-m); }
.site-footer nav a { display: inline-block; padding: 0.6rem 0.4rem; margin: -0.3rem -0.2rem; } /* ≥ 44 px targets */
.site-footer .statement { max-width: var(--measure); }
.site-footer .fineprint { font-size: 0.8125rem; margin-top: var(--sp-l); }
.site-footer .copyright { margin: 0; }

/* --------------------------------------------------------------------------
   5. Hero, halo, torn edge
   -------------------------------------------------------------------------- */
.hero {
  padding-block: clamp(3rem, 9vw, 7rem) clamp(3rem, 8vw, 6rem);
}
.hero .container {
  display: grid;
  gap: var(--sp-3xl);
  align-items: center;
}
@media (min-width: 880px) {
  .hero .container { grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr); }
}
.hero h1 { margin-bottom: var(--sp-xl); }
.hero .lede {
  font-size: clamp(1.125rem, 1.6vw, 1.3125rem);
  line-height: 1.55;
  color: var(--fg-dim);
  max-width: 36rem;
  margin-bottom: var(--sp-2xl);
}
.hero .actions { display: flex; flex-wrap: wrap; gap: var(--sp-m); }
.hero__note { margin-top: var(--sp-l); font-size: 0.95rem; color: var(--fg-dim); max-width: 36rem; }

/* The app's "calm breathing halo": an accent circle at 18%→30% opacity,
   blurred, breathing over 2.4 s. Removed under reduced motion. */
.halo {
  position: relative;
  display: grid;
  place-items: center;
  padding: clamp(1.5rem, 5vw, 3rem);
  isolation: isolate;
  justify-self: center;
}
.halo::before {
  content: "";
  position: absolute;
  inset: 4%;
  border-radius: 50%;
  background: radial-gradient(circle, var(--halo) 0%, color-mix(in srgb, var(--halo) 60%, transparent) 45%, transparent 72%);
  filter: blur(22px);
  opacity: 0.24;
  z-index: -1;
  will-change: opacity, transform;  /* one compositor layer, made once */
  animation: breathe 2.4s ease-in-out infinite alternate;
}
/* site.js adds .is-offscreen when the hero has scrolled out of view, so the
   blur layer stops animating while nobody can see it. */
.halo.is-offscreen::before { animation-play-state: paused; }
@keyframes breathe {
  from { opacity: 0.18; transform: scale(0.96); }
  to   { opacity: 0.30; transform: scale(1.04); }
}

/* The icon always sits on white: the PNG has a baked white margin and no alpha. */
.icon-card {
  width: clamp(9rem, 26vw, 15rem);
  aspect-ratio: 1;
  background: #FFFFFF;
  border-radius: 22.5%;
  overflow: hidden;
  box-shadow: var(--shadow), 0 0 0 0.5px var(--hairline);
}
.icon-card img { width: 100%; height: 100%; object-fit: cover; }

/* Hero transcript — the product shown as text. Real HTML styled as the app's
   chat bubbles (user bubble = accent fill, assistant bubble = secondary
   background), labeled illustrative until a device capture exists. It is
   selectable, indexable and cannot be mistaken for a screenshot. */
.transcript {
  width: min(100%, 24rem);
  margin: 0;
  background: var(--card-bg);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  box-shadow: var(--shadow), 0 0 0 0.5px var(--hairline);
  overflow: hidden;
  font-size: 0.95rem;
  text-align: left;
}
.transcript__bar {
  display: flex;
  align-items: center;
  gap: var(--sp-s);
  padding: var(--sp-s) var(--sp-l);
  background: var(--bg-alt);
  border-bottom: 1px solid var(--line);
}
.transcript__bar .icon-card { width: 1.75rem; flex: none; box-shadow: 0 0 0 0.5px var(--hairline); }
.transcript__title { font-weight: 600; }
.transcript__status {
  margin-left: auto;
  font-family: var(--font-mono);
  font-size: 0.75rem;
  color: var(--fg-dim);
  white-space: nowrap;
}
.transcript__body { display: flex; flex-direction: column; gap: var(--sp-s); padding: var(--sp-l); }
.bubble {
  margin: 0;
  max-width: 88%;
  padding: var(--sp-s) var(--sp-m);
  border-radius: var(--r-inner);
  line-height: 1.45;
}
.bubble--you { align-self: flex-end; background: var(--btn-bg); color: var(--btn-fg); border-bottom-right-radius: 4px; }
.bubble--agent { align-self: flex-start; background: var(--bg-alt); border-bottom-left-radius: 4px; }
.bubble__meta { margin: 0; align-self: flex-start; font-family: var(--font-mono); font-size: 0.75rem; color: var(--fg-dim); }
.transcript figcaption {
  padding: var(--sp-s) var(--sp-l);
  font-size: 0.8125rem;
  color: var(--fg-dim);
  border-top: 1px solid var(--line);
}
@media (max-width: 400px) {
  .transcript__status { display: none; } /* 360 px: the bar keeps the icon and the name */
}

/* Torn-paper divider — the icon's edge as the one recurring motif.
   Sits between the hero (paper) and the first warm section. Uses the next
   section's background and tears its top edge. No image asset needed. */
.torn-divider {
  position: relative;
  height: 26px;
  overflow: hidden;
  --torn-edge: polygon(
    0 60%, 3% 30%, 6% 75%, 9% 20%, 12% 55%, 15% 90%, 18% 35%, 21% 70%, 24% 15%,
    27% 60%, 30% 85%, 33% 40%, 36% 10%, 39% 65%, 42% 95%, 45% 30%, 48% 55%,
    51% 20%, 54% 80%, 57% 45%, 60% 10%, 63% 70%, 66% 35%, 69% 90%, 72% 50%,
    75% 15%, 78% 65%, 81% 40%, 84% 85%, 87% 25%, 90% 60%, 93% 10%, 96% 75%,
    100% 45%, 100% 100%, 0 100%
  );
}
.torn-divider::before, .torn-divider::after {
  content: "";
  position: absolute;
  left: 0; right: 0; top: 0;
  height: 26px;
  clip-path: var(--torn-edge);
}
.torn-divider::before { background: var(--line-strong); }        /* the 1 px edge */
.torn-divider::after { top: 1px; background: var(--bg-alt); }    /* the paper, 1 px lower */

/* --------------------------------------------------------------------------
   6. Buttons, chips
   -------------------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-xs);
  min-height: 44px;
  padding: 0.6rem 1.15rem;
  border-radius: var(--r-btn);
  font: inherit;
  font-weight: 600;
  line-height: 1.2;
  text-decoration: none;
  cursor: pointer;
  border: 1px solid transparent;
  transition: background-color 120ms ease, color 120ms ease, border-color 120ms ease, transform 80ms ease;
  -webkit-tap-highlight-color: transparent;
}
.btn:active { transform: translateY(1px); }
.btn--primary {
  background: var(--btn-bg);
  color: var(--btn-fg);
}
.btn--primary:hover { background: var(--btn-bg-hover); color: var(--btn-fg); }
.btn--secondary {
  background: transparent;
  color: var(--fg);
  border-color: var(--control-border);
}
.btn--secondary:hover { border-color: var(--fg); color: var(--fg); }
.btn[disabled], .btn[aria-disabled="true"] { opacity: 0.6; cursor: default; transform: none; }

.chip {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.2rem 0.7rem;
  border-radius: var(--r-chip);
  background: var(--chip-bg);
  color: var(--chip-fg);
  border: 1px solid var(--line);
  font-size: 0.8125rem;
  font-weight: 600;
  line-height: 1.5;
  white-space: nowrap;
}
.chip--free { color: var(--teal-text); border-color: color-mix(in srgb, var(--teal) 50%, transparent); }
.chip--pro { color: var(--plum); border-color: color-mix(in srgb, var(--plum) 40%, transparent); }
.chip--status::before {
  content: "";
  width: 0.5rem; height: 0.5rem;
  border-radius: 50%;
  background: currentColor;
  opacity: 0.7;
}

/* --------------------------------------------------------------------------
   7. Cards, lists of features, tables
   -------------------------------------------------------------------------- */
.card {
  background: var(--card-bg);
  border: 0.5px solid var(--hairline);
  border-radius: var(--r-card);
  padding: var(--sp-xl);
  box-shadow: 0 0 0 0.5px var(--hairline);
}
.card--warm { background: var(--bg-alt); }
.card--outline { background: transparent; border: 1px solid var(--line); box-shadow: none; }
.card h3, .card h2 { font-size: 1.2rem; margin-bottom: var(--sp-s); }
.card > :last-child { margin-bottom: 0; }
.card .chip { margin-bottom: var(--sp-m); }
a.card { display: block; text-decoration: none; color: inherit; transition: border-color 120ms ease, box-shadow 120ms ease; }
a.card:hover { border-color: var(--line-strong); box-shadow: var(--shadow); color: inherit; }
a.card h3 { color: var(--link); }

/* Three truths / feature rows */
.truths { counter-reset: truth; }
.truth { position: relative; padding-left: 3.25rem; }
.truth::before {
  counter-increment: truth;
  content: counter(truth);
  position: absolute; left: 0; top: 0.1rem;
  width: 2.25rem; height: 2.25rem;
  display: grid; place-items: center;
  border-radius: 50%;
  border: 1.5px solid var(--rule);
  font-family: var(--font-head);
  font-weight: 600;
  color: var(--fg);
}
.truth h3 { margin-bottom: var(--sp-xs); }

/* Home page "What runs where": three stacked groups, each a heading and a list */
.where-groups { margin-bottom: var(--sp-xl); }
.where-groups h3 { font-size: 1.2rem; margin-bottom: var(--sp-s); }
.where-groups ul { margin: 0; }

/* Definition-style feature lists */
.features { list-style: none; padding: 0; margin: 0; display: grid; gap: var(--sp-l); }
.features li { margin: 0; padding-left: 0; }
.features strong { display: block; }

.table-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  margin-bottom: var(--sp-l);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
}
table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.95rem;
  min-width: 36rem;
}
.table-scroll table { margin: 0; }
/* Sideways scrollers are keyboard stops (WCAG 2.1.1): every .table-scroll and
   .diagram__scroll ships tabindex="0" + role="region" + a name in the HTML, the
   bare <pre> and .pair-box blocks ship tabindex="0", and site.js adds
   tabindex="0" to a .cmd <pre> only while it actually overflows. Safari never
   makes a scroller focusable on its own. The ring keeps the box's own radius. */
.table-scroll:focus-visible { border-radius: var(--r-card); }
.diagram__scroll:focus-visible, pre:focus-visible { border-radius: var(--r-inner); }
th, td {
  text-align: left;
  vertical-align: top;
  padding: 0.7rem 0.9rem;
  border-bottom: 1px solid var(--line);
}
thead th {
  background: var(--bg-alt);
  font-weight: 600;
  font-size: 0.875rem;
  color: var(--fg-dim);
}
tbody tr:last-child td { border-bottom: 0; }
td strong { font-weight: 600; }

.pricing td:first-child, .pricing th:first-child { white-space: nowrap; }
.price { font-family: var(--font-head); font-size: 1.5rem; font-weight: 600; letter-spacing: -0.01em; }
.price small { font-family: var(--font-body); font-size: 0.85rem; color: var(--fg-dim); font-weight: 400; }

/* --------------------------------------------------------------------------
   8. Commands: pre/code with a copy button and a one-line "why"
   -------------------------------------------------------------------------- */
pre {
  background: var(--code-bg);
  border: 1px solid var(--line);
  border-radius: var(--r-inner);
  padding: 0.85rem 1rem;
  overflow-x: auto;
  font-size: 0.8125rem;
  line-height: 1.55;
  tab-size: 2;
}
pre code {
  font-family: var(--font-mono);
  font-size: 0.8125rem;
  white-space: pre;
  background: none;
  border: 0;
  padding: 0;
}

.cmd { position: relative; margin: var(--sp-l) 0; }
.cmd pre { margin: 0; padding-right: 5.25rem; }
.cmd .why {
  margin: var(--sp-xs) 0 0;
  font-size: 0.875rem;
  color: var(--fg-dim);
}
.cmd .why::before { content: "— " / ""; } /* the dash is visual only; the alt text keeps screen readers from announcing it */
.cmd + .cmd { margin-top: var(--sp-m); }
.cmd-label {
  display: block;
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--fg-dim);
  margin-bottom: var(--sp-xs);
}
.copy {
  position: absolute;
  top: 0.5rem; right: 0.5rem;
  min-height: 36px;
  min-width: 44px;
  padding: 0.2rem 0.6rem;
  border-radius: 8px;
  border: 1px solid var(--control-border);
  background: var(--bg);
  color: var(--fg-dim);
  font: inherit;
  font-size: 0.8rem;
  font-weight: 600;
  cursor: pointer;
  transition: color 120ms ease, border-color 120ms ease;
}
.copy:hover { color: var(--link); border-color: var(--link); }
.copy.is-copied { color: var(--ok); border-color: var(--ok); }

/* Pair-code box — what the installer prints */
.pair-box {
  font-family: var(--font-mono);
  font-size: 0.8125rem;
  line-height: 1.6;
  background: var(--code-bg);
  border: 1px solid var(--line);
  border-radius: var(--r-inner);
  padding: var(--sp-l) var(--sp-xl);
  white-space: pre;
  overflow-x: auto;
}
.pair-box strong { color: var(--fg); font-weight: 700; letter-spacing: 0.06em; }

/* --------------------------------------------------------------------------
   9. Tabs (platform switcher). Markup contract in templates/layout.html.
   -------------------------------------------------------------------------- */
.tabs { margin: var(--sp-l) 0 var(--sp-2xl); }
.tabs__list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-xs);
  border-bottom: 1px solid var(--line);
  margin-bottom: var(--sp-l);
}
.tabs__list [role="tab"] {
  appearance: none;
  background: none;
  border: 0;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  padding: 0.55rem 0.9rem;
  font: inherit;
  font-weight: 500;
  color: var(--fg-dim);
  cursor: pointer;
  border-radius: 6px 6px 0 0;
}
.tabs__list [role="tab"]:hover { color: var(--fg); }
.tabs__list [role="tab"][aria-selected="true"] { color: var(--fg); border-bottom-color: var(--rule-strong); font-weight: 600; }
.tabs__list [role="tab"] .detected {
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--teal-text);
  margin-left: 0.35rem;
}
.tabs__panel[hidden] { display: none; }
/* Progressive: the HTML ships every panel visible and no tab list state.
   site.js adds .js to <html>, hides the unselected panels and takes over the
   list. Without it, every OS's command is on the page under its own label. */
.tabs__label { font-weight: 600; margin: var(--sp-l) 0 var(--sp-xs); }
html.js .tabs__label { display: none; }
html:not(.js) .tabs__list { display: none; }

/* --------------------------------------------------------------------------
   10. Forms (waitlist)
   -------------------------------------------------------------------------- */
.field { display: grid; gap: var(--sp-xs); margin-bottom: var(--sp-l); }
label { font-weight: 600; font-size: 0.95rem; }
.field .hint { font-weight: 400; color: var(--fg-dim); font-size: 0.875rem; }

input[type="email"], input[type="text"], input[type="url"], textarea, select {
  font: inherit;
  color: var(--fg);
  background: var(--bg);
  border: 1px solid var(--control-border);
  border-radius: var(--r-inner);
  padding: 0.65rem 0.85rem;
  min-height: 44px;
  width: 100%;
  max-width: 28rem;
}
input:focus-visible, textarea:focus-visible, select:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 1px;
  border-color: var(--focus);
}
input[aria-invalid="true"] { border-color: var(--err); }

fieldset { border: 0; padding: 0; margin: 0 0 var(--sp-l); min-width: 0; }
legend { font-weight: 600; font-size: 0.95rem; padding: 0; margin-bottom: var(--sp-xs); }

/* Device chips: <label><input type="radio"><span>iPhone</span></label>. The
   border, the checked state and the focus ring all live on the <span> via the
   adjacent-sibling combinator, so no :has() is needed anywhere. */
.chips { display: flex; flex-wrap: wrap; gap: var(--sp-xs); }
.chips label { position: relative; display: inline-flex; cursor: pointer; font-weight: 500; }
.chips input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.chips input + span {
  display: inline-flex;
  align-items: center;
  min-height: 36px;
  padding: 0.25rem 0.85rem;
  border: 1px solid var(--control-border);
  border-radius: var(--r-chip);
  background: var(--bg);
}
.chips input:checked + span { border-color: var(--link); color: var(--link); }
.chips input:focus-visible + span { outline: 2px solid var(--focus); outline-offset: 2px; }

.check { display: flex; gap: var(--sp-s); align-items: flex-start; font-weight: 400; margin-bottom: var(--sp-l); max-width: 28rem; }
.check input { width: 1.1rem; height: 1.1rem; margin-top: 0.25rem; accent-color: var(--link); flex: none; }

.form-status { min-height: 1.5rem; font-size: 0.95rem; margin: var(--sp-m) 0 0; }
.form-status.is-ok { color: var(--ok); }
.form-status.is-err { color: var(--err); }
/* The no-JS answer: the server 303s back to /download?…#joined, #err-email,
   #err-consent, #err-rate or #err-storage, and the matching notice shows via :target. With
   JS on, site.js renders the same message in the live status line instead. */
.form-notice { display: none; font-size: 0.95rem; margin: var(--sp-m) 0 0; }
.form-notice:target { display: block; }
.form-notice--ok { color: var(--ok); }
.form-notice--err { color: var(--err); }
html.js .form-notice { display: none; }
.form-note { font-size: 0.875rem; color: var(--fg-dim); max-width: 28rem; margin-top: var(--sp-s); }

/* --------------------------------------------------------------------------
   11. Diagrams, status lines, callouts
   -------------------------------------------------------------------------- */
.diagram { margin: var(--sp-xl) 0; }
/* The message diagram is 680 units wide with 12–13 px labels. On a phone it
   scrolls sideways inside its own box at a legible size rather than shrinking
   to 6 px type. */
.diagram__scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.diagram svg { width: 100%; height: auto; }
@media (max-width: 639.98px) { .diagram svg { min-width: 560px; } }
.diagram .stroke { stroke: var(--rule-strong); fill: none; stroke-width: 1.5; } /* arrows, connectors, the dashed nearby line: ≥ 3:1 in both schemes */
.diagram .ink { stroke: var(--fg); fill: none; stroke-width: 1.5; }
.diagram .fill { fill: var(--bg-alt); stroke: var(--control-border); stroke-width: 1; } /* box outlines are boundaries, so --control-border */
.diagram text { font-family: var(--font-body); font-size: 0.8125rem; fill: var(--fg); }
.diagram .dim { fill: var(--fg-dim); font-size: 0.75rem; }
.diagram figcaption { font-size: 0.875rem; color: var(--fg-dim); margin-top: var(--sp-s); }

.status-line { font-family: var(--font-mono); font-size: 0.8125rem; color: var(--fg-dim); }
.status-line[hidden] { display: none; }

/* Callouts */
.note, .warn {
  border-left: 3px solid var(--rule);
  background: var(--bg-alt);
  padding: var(--sp-m) var(--sp-l);
  border-radius: 0 var(--r-inner) var(--r-inner) 0;
  margin: var(--sp-l) 0;
  font-size: 0.95rem;
}
.warn { border-left-color: var(--err); }
.note > :last-child, .warn > :last-child { margin-bottom: 0; }

/* Docs layout: an optional in-page contents list */
.toc { font-size: 0.9rem; margin-bottom: var(--sp-2xl); }
.toc ul { list-style: none; padding: 0; margin: 0; display: flex; flex-wrap: wrap; gap: var(--sp-xs) var(--sp-l); }
.toc a { display: inline-block; padding: 0.55rem 0.25rem; margin: -0.3rem 0; color: var(--fg-dim); text-decoration: none; } /* ≥ 44 px targets */
.toc a:hover { color: var(--link); text-decoration: underline; }

.breadcrumb { font-size: 0.875rem; color: var(--fg-dim); margin-bottom: var(--sp-l); }
.breadcrumb ol { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; }
.breadcrumb li { margin: 0; }
.breadcrumb a { color: var(--fg-dim); }
.breadcrumb li + li::before { content: " / " / ""; white-space: pre; } /* the slash is visual only; the empty alt keeps it out of the name */

/* Draft banner (terms page until counsel signs off) */
.banner {
  background: var(--bg-alt);
  border-bottom: 1px solid var(--line);
  font-size: 0.9rem;
  color: var(--fg-dim);
  text-align: center;
  padding: var(--sp-s) var(--sp-l);
}

/* --------------------------------------------------------------------------
   12. Motion and print
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation: none !important; transition: none !important; }
  .halo::before { opacity: 0.24; transform: none; }
}

@media print {
  .site-header, .site-footer, .skip-link, .copy, .halo::before { display: none !important; }
  body { background: #fff; color: #000; }
  a { color: #000; }
  pre { border: 1px solid #999; }
}

/* --------------------------------------------------------------------------
   13. Docs layout: a left nav beside the prose from 960px, a chip row above
       it below. Every docs page uses it — /docs with plain prose inside
       .docs-main, and the sub-pages with their <section> blocks nested in it
       (the sections lose their full-bleed warm bands and read as one document
       separated by rules).
   Markup:
     <div class="container docs-layout">
       <aside class="docs-nav"><nav aria-label="Docs"><p class="docs-nav__title">Docs</p><ul>…</ul></nav></aside>
       <div class="docs-main">…</div>
     </div>
   Mark the current guide's link with aria-current="page".
   -------------------------------------------------------------------------- */
.docs-layout { display: grid; gap: var(--sp-2xl); align-items: start; }
.docs-main { min-width: 0; max-width: var(--measure); }
.docs-main h1 { font-size: clamp(2rem, 4vw, 3rem); margin-bottom: var(--sp-l); }
.docs-main h2 { margin-top: var(--sp-3xl); }
.docs-main h3 { margin-top: var(--sp-2xl); }
.docs-main h4 { margin-top: var(--sp-xl); }
.docs-main .lede { font-size: 1.125rem; color: var(--fg-dim); margin-bottom: var(--sp-2xl); }
.docs-main > hr { margin: var(--sp-3xl) 0; }
/* Sub-pages: sections nested inside .docs-main flow as one column. */
.docs-main > .section { padding-block: var(--sp-2xl); background: transparent; }
.docs-main > .section:first-child { padding-top: 0; }
.docs-main > .section + .section { border-top: 1px solid var(--line); }
.docs-main > .section > .container { padding-inline: 0; max-width: none; }
.docs-main > .section h2:first-child, .docs-main .section-head h1 { margin-top: 0; }

.docs-nav { font-size: 0.925rem; }
.docs-nav__title { font-family: var(--font-head); font-weight: 600; font-size: 1.05rem; margin: 0 0 var(--sp-s); color: var(--fg); }
.docs-nav ul { list-style: none; margin: 0; padding: 0; }
.docs-nav li { margin: 0; }
.docs-nav a {
  display: block;
  padding: 0.3rem 0.75rem;
  color: var(--fg-dim);
  text-decoration: none;
  border-left: 2px solid var(--line);
}
.docs-nav a:hover { color: var(--fg); border-left-color: var(--line-strong); }
.docs-nav a[aria-current="page"] { color: var(--fg); border-left-color: var(--rule-strong); font-weight: 600; }

@media (max-width: 959.98px) {
  .docs-nav__title { margin-bottom: var(--sp-xs); }
  .docs-nav ul { display: flex; flex-wrap: wrap; gap: var(--sp-xs); }
  .docs-nav a { border: 1px solid var(--line); border-radius: var(--r-chip); padding: 0.45rem 0.8rem; } /* ≈ 38 px */
  .docs-nav a[aria-current="page"] { border-color: var(--rule-strong); }
}

/* Coarse pointers (touch): every small control grows to 44 px. */
@media (pointer: coarse) {
  .copy { min-height: 44px; }
  .chips input + span { min-height: 44px; }
  .site-footer nav a, .toc a { min-height: 44px; display: inline-flex; align-items: center; }
}
/* The docs-nav chip row exists only below 960 px; above it the sidebar links are
   block-level and full-width, and an inline-flex override there would shrink them. */
@media (pointer: coarse) and (max-width: 959.98px) {
  .docs-nav a { min-height: 44px; display: inline-flex; align-items: center; }
}
@media (min-width: 960px) {
  .docs-layout { grid-template-columns: 15rem minmax(0, 1fr); gap: var(--sp-3xl); }
  .docs-nav { position: sticky; top: var(--sp-xl); max-height: calc(100vh - 2.5rem); overflow-y: auto; }
}

/* ── Feature tour (home) ──────────────────────────────────────────────
   The hero's chip row links into the tour; cards in the tour carry a
   small door label (the app's own grouping) above the title. */
.hero__doors { list-style: none; padding: 0; margin: var(--sp-m) 0 0; }
.hero__doors li { margin: 0; padding: 0; }
a.chip { text-decoration: none; }
a.chip:hover, a.chip:focus-visible { text-decoration: underline; text-underline-offset: 0.15em; }
.feature .eyebrow { margin-bottom: var(--sp-xs); }
