/* jevmod.dev: one stylesheet for every page. Light only. No frameworks. */

@font-face {
  font-family: "Geist";
  src: url("/fonts/Geist-Variable.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Geist Mono";
  src: url("/fonts/GeistMono-Variable.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

:root {
  /* "light dark" tells the UA both are supported; the two selectors below pin it explicitly the moment
     a theme is chosen or the OS asks, so form controls and scrollbars never fall out of sync with ours. */
  color-scheme: light dark;
  /* >>> tokens from brand/tokens.css, do not edit by hand >>> */
/* The design system, and the only place these values are written down.
 *
 * Two things render jevmod: the marketing site, which nginx serves as plain CSS, and the web app, which
 * Tailwind compiles. They used to each carry their own copy of the palette and their own idea of how long
 * a hover takes, which is how two pages on one domain end up looking like two products.
 *
 * `scripts/site/sync_tokens.py` copies this block into both, between markers, and CI fails when they drift.
 * Edit here, run the script, commit all three.
 *
 * Colours are jevmod's own. The geometry and the motion come from what Omar picked looking at
 * portal.nousresearch.com: monospace uppercase on every control, square corners on anything you click,
 * half-pixel hairlines, shadows tinted with the ink rather than neutral black.
 */

/* --- palette. Two themes now. Omar asked for light only in the first pass and for dark in the second, so
       the light set stays exactly what shipped and the dark one is derived rather than invented: the same
       relationships, inverted, with the flag and the ok colours lifted because a saturated red on near
       black reads as a warning about the page rather than about a message. ---------------------------- */
--bg: #FAFAFA;
--surface: #FFFFFF;
--ink: #111113;
--body: #3F3F46;
--muted: #71717A;
--line: #E4E4E7;
/* A divider can be faint; the edge of something you type into cannot. WCAG 1.4.11 asks 3:1 of any control
   boundary against what is behind it, and the divider colour measured 1.27:1, which is a field whose edge
   you cannot see until you tab into it. Measured, not chosen by eye: #8E8E93 is 3.26:1 on the surface and
   3.12:1 on the page. */
--control-line: #8E8E93;
--flag: #DC2626;
--ok: #15803D;

/* --- dark. Applied under [data-theme="dark"] and under the system preference, so a person who never
       touches the toggle still gets the one their machine asked for. --------------------------------- */
--dark-bg: #0B0B0C;
--dark-surface: #141416;
--dark-ink: #F4F4F5;
--dark-body: #C4C4CC;
--dark-muted: #8A8A94;
--dark-line: #26262A;
--dark-control-line: #6B6B75;   /* 3.49:1 on the dark surface, 3.73:1 on the dark page */
--dark-flag: #F87171;
--dark-ok: #4ADE80;
--dark-sh-hair: inset 0 0 0 0.5px rgba(244, 244, 245, 0.16);
--dark-sh-control: inset 0 0 0 1px var(--control-line);
--dark-sh-lift: 0 2px 8px 0 rgba(0, 0, 0, 0.45);
--dark-sh-lift-strong: 0 2px 8px 0 rgba(0, 0, 0, 0.60);
--dark-sh-press: inset 0 1px 4px 0 rgba(0, 0, 0, 0.45);
--dark-sh-menu: 0 4px 2px 0 rgba(0, 0, 0, 0.35);
--dark-sh-popout: 0 4px 40px 0 rgba(0, 0, 0, 0.65);

/* --- type. One variable family for text, one monospace for every control, one with a width axis for
       display. Archivo stands in for the licensed condensed face the reference uses. ------------------- */
--sans: "Geist", system-ui, -apple-system, "Segoe UI", sans-serif;
--mono: "Geist Mono", ui-monospace, "Cascadia Mono", Consolas, monospace;
--display: "Archivo", "Geist", system-ui, sans-serif;
--display-stretch: 72%;

--fs-legend: 9px;
--fs-meta: 12px;
--fs-small: 13px;
--fs-label: 14px;

/* --- shape. Square is the default; roundness is the exception. ---------------------------------------- */
--r-control: 0;
--r-card: 2px;
--r-pill: 999px;

/* --- depth. Every shadow is tinted with the ink, never neutral black. A half-pixel border is unreliable
       across browsers; a half-pixel inset shadow is not, and it stays out of layout. ------------------- */
--sh-hair: inset 0 0 0 0.5px rgba(17, 17, 19, 0.20);
--sh-control: inset 0 0 0 1px var(--control-line);   /* the visible edge of something you operate */
--sh-lift: 0 2px 8px 0 rgba(17, 17, 19, 0.08);
--sh-lift-strong: 0 2px 8px 0 rgba(17, 17, 19, 0.14);
--sh-press: inset 0 1px 4px 0 rgba(17, 17, 19, 0.08);
--sh-menu: 0 4px 2px 0 rgba(17, 17, 19, 0.05);
--sh-popout: 0 4px 40px 0 rgba(17, 17, 19, 0.18);

/* --- motion. Four durations and two curves, and nothing is allowed a fifth.
       `--ease` is the expo-out already shipped on the marketing site: things arrive fast and settle.
       Colour is quicker than movement because a colour that takes as long as a slide reads as lag. ----- */
--ease: cubic-bezier(0.22, 1, 0.36, 1);
--ease-out: cubic-bezier(0, 0, 0.2, 1);
--dur-press: 90ms;
--dur-color: 120ms;
--dur-move: 180ms;
--dur-draw: 380ms;

/* --- rhythm ------------------------------------------------------------------------------------------- */
--side: max(24px, env(safe-area-inset-left), env(safe-area-inset-right));
--nav-h: 56px;
--tap: 44px;
--control-h: 48px;
--prose: 680px;
/* <<< tokens from brand/tokens.css, do not edit by hand <<< */
  --r: 6px;
  /* --side/--nav-h/--tap/--control-h/--prose above are brand/tokens.css's app-chrome rhythm (sidebar,
     dialogs); the marketing site keeps its own responsive --side/--section/--block below instead, since
     long-form pages and app chrome do not share a spacing scale. They are harmless here: nothing on this
     site reads --nav-h/--tap/--control-h/--prose, and the --side below simply wins in the cascade. */
  /* type scale, 390 */
  --fs-display: 36px;
  --fs-num: 56px;
  --fs-h2: 28px;
  --fs-h3: 20px;
  --fs-lead: 18px;
  --fs-body: 16px;
  /* spacing, 390 */
  --side: max(20px, env(safe-area-inset-left), env(safe-area-inset-right));
  --section: 80px;
  --block: 24px;
}
@media (min-width: 768px) {
  :root {
    --fs-display: 52px; --fs-num: 80px; --fs-h2: 36px; --fs-h3: 22px; --fs-lead: 20px; --fs-body: 17px;
    --side: 40px; --section: 112px; --block: 32px;
  }
}
@media (min-width: 1440px) {
  :root {
    --fs-display: 72px; --fs-num: 112px; --fs-h2: 48px; --fs-h3: 24px; --fs-lead: 22px;
    --side: 64px; --section: 160px; --block: 48px;
  }
}

/* --- dark theme. `data-theme="dark"` is an explicit choice made through a toggle; the media query is
       what a person who never touches one gets from their OS, guarded with `:not([data-theme="light"])`
       so it never overrides an explicit light choice. Both branches just repoint the light names at the
       `--dark-*` values brand/tokens.css already derived, so nothing below here has to know a colour
       changed. -------------------------------------------------------------------------------------- */
:root[data-theme="dark"] {
  color-scheme: dark;
  --bg: var(--dark-bg);
  --surface: var(--dark-surface);
  --ink: var(--dark-ink);
  --body: var(--dark-body);
  --muted: var(--dark-muted);
  --line: var(--dark-line);
  --control-line: var(--dark-control-line);
  --flag: var(--dark-flag);
  --ok: var(--dark-ok);
  --sh-hair: var(--dark-sh-hair);
  --sh-lift: var(--dark-sh-lift);
  --sh-lift-strong: var(--dark-sh-lift-strong);
  --sh-press: var(--dark-sh-press);
  --sh-menu: var(--dark-sh-menu);
  --sh-popout: var(--dark-sh-popout);
}
:root[data-theme="light"] { color-scheme: light; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --bg: var(--dark-bg);
    --surface: var(--dark-surface);
    --ink: var(--dark-ink);
    --body: var(--dark-body);
    --muted: var(--dark-muted);
    --line: var(--dark-line);
    --control-line: var(--dark-control-line);
    --flag: var(--dark-flag);
    --ok: var(--dark-ok);
    --sh-hair: var(--dark-sh-hair);
    --sh-lift: var(--dark-sh-lift);
    --sh-lift-strong: var(--dark-sh-lift-strong);
    --sh-press: var(--dark-sh-press);
    --sh-menu: var(--dark-sh-menu);
    --sh-popout: var(--dark-sh-popout);
  }
}

/* base */
*, *::before, *::after { box-sizing: border-box; }
html { background: var(--bg); -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
body {
  margin: 0;
  color: var(--body);
  background: var(--bg);
  font: 400 var(--fs-body)/1.6 var(--sans);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
h1, h2, h3, p, figure, ul, ol, dl, table { margin: 0; }
img, svg { display: block; max-width: 100%; height: auto; }
a { color: inherit; text-decoration: none; }
code, kbd, pre { font-family: var(--mono); }
code {
  font-size: 0.875em;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: 1px 6px;
  white-space: nowrap;
}
strong, b { font-weight: 600; color: var(--ink); }
:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
::selection { background: var(--ink); color: var(--bg); }

/* layout */
.wrap { max-width: 1120px; margin: 0 auto; padding-left: var(--side); padding-right: var(--side); }
.section { padding-top: var(--section); padding-bottom: var(--section); }
.section + .section { border-top: 1px solid var(--line); }
.stack > * + * { margin-top: var(--block); }
.stack-s > * + * { margin-top: 16px; }
.grid-7-5, .grid-5-7 { display: grid; grid-template-columns: 1fr; gap: var(--block); align-items: start; }
@media (min-width: 768px) {
  .grid-7-5, .grid-5-7 { grid-template-columns: repeat(12, 1fr); column-gap: 32px; }
  .grid-7-5 > :first-child { grid-column: 1 / span 7; }
  .grid-7-5 > :last-child { grid-column: 8 / span 5; }
  .grid-5-7 > :first-child { grid-column: 1 / span 5; }
  .grid-5-7 > :last-child { grid-column: 6 / span 7; }
}
@media (min-width: 1440px) {
  .grid-7-5, .grid-5-7 { column-gap: 48px; }
}
.grid-7-5 > *, .grid-5-7 > * { min-width: 0; }

/* type */
h1.display {
  font-size: var(--fs-display);
  font-weight: 600;
  line-height: 1.05;
  letter-spacing: -0.02em;
  color: var(--ink);
  max-width: 22ch;
  text-wrap: balance;
}
h2 {
  font-size: var(--fs-h2);
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: var(--ink);
  max-width: 24ch;
  text-wrap: balance;
}
h3 { font-size: var(--fs-h3); font-weight: 500; line-height: 1.25; letter-spacing: -0.01em; color: var(--ink); }
.lead { font-size: var(--fs-lead); line-height: 1.45; max-width: 52ch; }
.prose { max-width: 62ch; }
.prose > * + * { margin-top: 16px; }
/* rhythm for running text, including content nested in .section blocks */
.prose p + p,
.prose > .section > * + *,
.prose ul, .prose ol, .prose figure, .prose table, .prose .code { margin-top: 16px; }
.prose ul, .prose ol { padding-left: 22px; }
.prose li + li { margin-top: 8px; }

/* text pages (privacy, terms): a document column, not a landing section.
   `.textpage` is the shape agent C uses; `main.prose` is supported for the same job. */
main.textpage, main.prose { max-width: 62ch; font-size: 17px; line-height: 1.65; }
.textpage .section, main.prose .section { padding-top: 40px; padding-bottom: 40px; }
@media (min-width: 768px) { .textpage .section, main.prose .section { padding-top: 48px; padding-bottom: 48px; } }
.textpage h1, main.prose h1 {
  font-size: 32px;
  font-weight: 600;
  line-height: 1.15;
  letter-spacing: -0.02em;
  color: var(--ink);
  max-width: none;
}
.textpage h2, main.prose h2 { font-size: 26px; line-height: 1.25; max-width: none; }
.textpage h3, main.prose h3 { font-size: 19px; }
@media (min-width: 768px) {
  .textpage h1, main.prose h1 { font-size: 40px; }
  .textpage h2, main.prose h2 { font-size: 30px; }
  .textpage h3, main.prose h3 { font-size: 20px; }
}
.textpage p, .textpage li { font-size: 17px; line-height: 1.65; color: var(--body); }
/* rhythm: space under every heading, between every pair of paragraphs */
.textpage .section > * + *, .textpage p + p, .textpage p + ul, .textpage ul + p { margin-top: 16px; }
.textpage h1 + *, .textpage h2 + *, .textpage h3 + * { margin-top: 12px; }
.textpage ul, .textpage ol { margin-top: 16px; padding-left: 22px; }
.textpage li + li { margin-top: 8px; }
.textpage .lead { max-width: none; }
.textpage .small { font-size: 15px; }
/* links in running text: visible, with a 44px hit area */
.textpage p a, .textpage li a, .textpage dd a, .textpage td a {
  color: var(--ink);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-color: var(--line);
  padding-top: 13px;
  padding-bottom: 13px;
}
.textpage p a:hover, .textpage li a:hover, .textpage dd a:hover, .textpage td a:hover { text-decoration-color: var(--ink); }
.small { font-size: 14px; line-height: 1.55; }
.muted { color: var(--muted); }
.num {
  font-size: 1em;
  font-weight: 600;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}
.link { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; text-decoration-color: var(--line); text-decoration-thickness: 1px; }
.link:hover { text-decoration-color: var(--ink); }
.prose a, .small a, .lead a, td a, dd a { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; text-decoration-color: var(--line); }
/* Inline links keep their own line box. A 44px padded box on a 22px line makes neighbouring links overlap and
   steal each other's taps (measured with elementFromPoint), so the hit area is a pseudo-element that only
   reaches half the leading and never covers a sibling. */
.link, .prose a, .small a, .lead a, td a, dd a { position: relative; }
.link::after, .prose a::after, .small a::after, .lead a::after, td a::after, dd a::after {
  content: "";
  position: absolute;
  inset: -6px -2px;
}
.prose a:hover, .small a:hover, .lead a:hover, td a:hover, dd a:hover { text-decoration-color: var(--ink); }

/* stat */
.stats { display: grid; grid-template-columns: 1fr 1fr; gap: var(--block) 24px; }
@media (min-width: 768px) { .stats { grid-template-columns: repeat(4, 1fr); } }
.stat-n {
  display: block;
  font-size: var(--fs-num);
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.03em;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.stat-l { display: block; margin-top: 12px; color: var(--ink); font-weight: 500; }
.stat-d { display: block; margin-top: 4px; font-size: 14px; line-height: 1.5; color: var(--muted); }

/* figure */
figure.shot img {
  width: 100%;
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--surface);
}
figure.shot figcaption { margin-top: 12px; font-size: 14px; line-height: 1.55; color: var(--muted); max-width: 62ch; }

/* definitions */
.defs { display: grid; grid-template-columns: 1fr; gap: 24px 48px; }
@media (min-width: 768px) { .defs { grid-template-columns: 1fr 1fr; gap: 32px 48px; } }
.def { padding-top: 16px; border-top: 1px solid var(--line); }
.def dt { font-size: var(--fs-h3); font-weight: 500; line-height: 1.25; color: var(--ink); }
.def dd { margin: 6px 0 0; max-width: 46ch; }

/* plans table */
table.plans { width: 100%; border-collapse: collapse; font-variant-numeric: tabular-nums; }
table.plans th, table.plans td { text-align: left; vertical-align: top; padding: 14px 16px 14px 0; border-bottom: 1px solid var(--line); }
table.plans th { font-weight: 500; color: var(--ink); font-size: var(--fs-h3); padding-bottom: 20px; }
table.plans thead th:first-child { font-size: 14px; font-weight: 400; color: var(--muted); }
table.plans tbody th { font-size: 14px; font-weight: 400; color: var(--muted); }
table.plans td { color: var(--body); }
table.plans td strong { font-weight: 500; }
table.plans caption { text-align: left; padding-bottom: 12px; }
table.plans td small, table.plans th small { display: block; font-size: 13px; font-weight: 400; color: var(--muted); }
@media (max-width: 767px) {
  table.plans thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
  table.plans, table.plans tbody, table.plans tr { display: block; width: 100%; }
  table.plans tbody th { display: block; padding: 16px 0 6px; border: 0; }
  table.plans tr { border-bottom: 1px solid var(--line); padding-bottom: 8px; }
  /* A hanging indent, not a grid. As a grid every child of the cell became its own row, so a value written
     as <b>0.977</b> / <b>0.519</b> broke into three stacked lines with the slash orphaned on one of them.
     This keeps the value as ordinary inline text that wraps under itself, clear of the label. */
  table.plans td {
    display: block;
    padding: 4px 0 4px 8.5em;
    text-indent: -8.5em;
    border: 0;
  }
  table.plans td::before {
    content: attr(data-plan);
    display: inline-block;
    width: 8.5em;
    text-indent: 0;
    padding-right: 12px;
    box-sizing: border-box;
    vertical-align: top;
    color: var(--ink);
    font-weight: 500;
  }
  /* a block child would break the hanging indent, so keep the ones that appear in these cells inline */
  table.plans td > code, table.plans td > b, table.plans td > strong, table.plans td > span { text-indent: 0; }
  table.plans td > small { display: block; margin-left: 0; text-indent: 0; }
}

/* pricing: three cards, not a table read six labels deep before you can compare them. One column at 390 so
   each plan reads top to bottom on its own; three side by side once there is room to actually compare. */
.pricing { display: grid; grid-template-columns: 1fr; gap: 16px; }
@media (min-width: 768px) { .pricing { grid-template-columns: repeat(3, 1fr); align-items: start; } }
.plan-card { border: 1px solid var(--line); border-radius: var(--r-card); padding: 24px; }
.plan-card--pro { border-color: var(--ink); }
.plan-card h3 { font-size: var(--fs-h3); font-weight: 500; color: var(--ink); }
.plan-price { margin-top: 8px; font-size: var(--fs-h2); font-weight: 600; letter-spacing: -0.02em; color: var(--ink); }
.plan-card dl { margin-top: 20px; }
.plan-card dl > div { padding-top: 12px; margin-top: 12px; border-top: 1px solid var(--line); }
.plan-card dl > div:first-child { padding-top: 0; margin-top: 0; border-top: 0; }
.plan-card dt { font-family: var(--mono); font-size: var(--fs-meta); font-weight: 500; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.plan-card dd { margin: 4px 0 0; color: var(--body); }

/* buttons and links */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 48px;
  padding: 0 24px;
  font: 500 16px/1 var(--sans);
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--ink);
  border-radius: var(--r);
  white-space: nowrap;
  cursor: pointer;
  text-decoration: none;
  transition: background-color 120ms ease, color 120ms ease, transform 80ms ease;
}
.btn:hover { background: var(--ink); color: var(--bg); }
.btn:active { transform: translateY(1px); }
.btn.primary { background: var(--ink); color: var(--bg); }
.btn.primary:hover { background: #2A2A2E; border-color: #2A2A2E; }
.btn[aria-disabled="true"], .btn[disabled] {
  background: transparent;
  color: var(--muted);
  border-color: var(--line);
  cursor: not-allowed;
  pointer-events: none;
  transform: none;
}
.btn[disabled] { pointer-events: auto; }
.cta { display: flex; flex-wrap: wrap; gap: 12px 24px; align-items: center; }

/* inline link inside a button row keeps a 44px hit area without the text padding */
.cta .link { display: inline-flex; align-items: center; justify-content: center; min-height: 44px; min-width: 44px; padding-top: 0; padding-bottom: 0; }

/* labelled snippets (developers) */
.snippet > .code-label { margin: 0 0 8px; }
.snippet + .snippet { margin-top: var(--block); }

/* form fields (developers calculator) */
.field { display: grid; gap: 8px; }
.field + .field { margin-top: 24px; }
.field label { font-weight: 500; color: var(--ink); }
.field input[type="number"], .field input[type="text"] {
  width: 100%;
  max-width: 320px;
  height: 48px;
  padding: 0 14px;
  font: 400 16px/1 var(--sans);
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  appearance: none;
}
.field input:focus { border-color: var(--ink); outline: 0; box-shadow: inset 0 0 0 1px var(--ink); }
.field input[type="range"] { width: 100%; max-width: 320px; height: 44px; margin: 0; accent-color: var(--ink); }
.field p { margin-top: 4px; max-width: 46ch; }
#o-jev, #o-llm, #o-lg { color: var(--ink); font-weight: 600; }

/* code blocks with copy */
.code { display: flex; flex-direction: column; align-items: flex-end; gap: 8px; }
.code > pre { width: 100%; }
.code pre {
  margin: 0;
  padding: 20px;
  font-size: 13px;
  line-height: 1.6;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  overflow-x: auto;
}
.code pre code { font: inherit; color: inherit; background: none; border: 0; padding: 0; white-space: pre; }
.code pre.wrap-text, .code pre.wrap-text code { white-space: pre-wrap; overflow-wrap: anywhere; }
.code .copy {
  order: -1;
  height: 44px;
  padding: 0 12px;
  font: 500 13px/1 var(--sans);
  color: var(--muted);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  cursor: pointer;
}
.code .copy:hover { color: var(--ink); border-color: var(--ink); }
.code .copy:active { transform: translateY(1px); }

/* nav: works whether the row is the nav itself (nav.site-nav.wrap) or an inner .wrap,
   and whether the links sit in a .links box or are bare anchors next to the brand */
nav.site-nav { min-height: 56px; display: flex; align-items: center; gap: 8px; }
nav.site-nav > .wrap { flex: 1 1 auto; min-height: 56px; display: flex; align-items: center; gap: 8px; }
nav.site-nav a.brand { display: inline-flex; align-items: center; height: 44px; margin-right: auto; font-weight: 600; color: var(--ink); letter-spacing: -0.01em; }
nav.site-nav .links { display: flex; align-items: center; gap: 8px; }
nav.site-nav .links a,
nav.site-nav > a:not(.brand),
nav.site-nav > .wrap > a:not(.brand) {
  display: inline-flex;
  align-items: center;
  height: 44px;
  padding: 0 12px;
  font-size: 15px;
  color: var(--body);
  border-radius: var(--r);
  white-space: nowrap;
}
nav.site-nav .links a:hover,
nav.site-nav > a:not(.brand):hover,
nav.site-nav > .wrap > a:not(.brand):hover { color: var(--ink); background: var(--surface); }
/* the last nav link lines up with the content edge */
nav.site-nav .links { margin-right: -12px; }
nav.site-nav > .wrap > a:last-child { margin-right: -12px; }

/* footer: grouped under headings rather than one flat run of twelve links, so a reader can tell "the legal
   ones" from "the product ones" at a glance instead of parsing every label. One column at 390, because four
   columns of wrapped labels at that width is smaller print than the links themselves; the grid earns its
   columns back at 480 and again at 768. */
footer.site-footer { border-top: 1px solid var(--line); padding: 40px 0 calc(40px + env(safe-area-inset-bottom)); font-size: 14px; color: var(--muted); }
footer.site-footer .wrap { display: flex; flex-direction: column; gap: 28px; align-items: flex-start; }
footer.site-footer .foot-groups {
  display: grid;
  grid-template-columns: 1fr;
  gap: 24px 32px;
  width: 100%;
}
@media (min-width: 480px) { footer.site-footer .foot-groups { grid-template-columns: 1fr 1fr; } }
@media (min-width: 768px) { footer.site-footer .foot-groups { grid-template-columns: repeat(4, auto); gap: 32px 48px; } }
footer.site-footer .foot-group h4 {
  margin: 0 0 4px;
  font-family: var(--mono);
  font-size: var(--fs-meta);
  font-weight: 500;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--muted);
}
footer.site-footer .foot-group .links { display: flex; flex-direction: column; gap: 0; margin-left: -12px; }
footer.site-footer .links a { display: inline-flex; align-items: center; min-height: 44px; padding: 0 12px; color: var(--ink); border-radius: var(--r); }
footer.site-footer .links a:hover { background: var(--surface); }
@media (min-width: 768px) { footer.site-footer .wrap { flex-direction: row; flex-wrap: wrap; justify-content: space-between; align-items: flex-start; } }
@media (min-width: 768px) { footer.site-footer .seg { order: 2; } footer.site-footer .foot-groups { order: 1; flex: 1 1 auto; } footer.site-footer p { order: 3; width: 100%; } }

/* hero demo */
#demo { min-width: 0; }
#liveForm .row { display: grid; grid-template-columns: 1fr; gap: 12px; }
@media (min-width: 480px) { #liveForm .row { grid-template-columns: 1fr auto; } }
/* a textarea, because the thing being tested is a chat message and those run to several lines. It grows to
   the text up to a point and scrolls after that, so the layout under it never jumps around while typing. */
#liveText {
  width: 100%;
  min-width: 0;
  height: 48px;
  min-height: 48px;
  max-height: 168px;
  padding: 13px 14px;
  resize: none;
  overflow-y: auto;
  font: 400 16px/1.45 var(--sans);
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  appearance: none;
}
#liveText::placeholder { color: var(--muted); }
#liveText:hover { border-color: #A1A1AA; }
#liveText:focus { border-color: var(--ink); outline: 0; box-shadow: inset 0 0 0 1px var(--ink); }
#liveBtn { min-width: 112px; align-self: start; }
.chips { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.chip {
  display: inline-flex;
  align-items: center;
  height: 44px;
  padding: 0 14px;
  font: 400 14px/1 var(--sans);
  color: var(--body);
  background: transparent;
  border: 1px solid var(--line);
  border-radius: var(--r);
  cursor: pointer;
  transition: background-color 120ms ease, color 120ms ease, border-color 120ms ease;
}
.chip:hover { color: var(--ink); border-color: #A1A1AA; background: var(--surface); }
.chip:active { transform: translateY(1px); }
.chip.on { color: var(--bg); background: var(--ink); border-color: var(--ink); }
.result {
  margin-top: 20px;
  min-height: 1.3em;
  font-size: var(--fs-h3);
  font-weight: 500;
  line-height: 1.3;
  letter-spacing: -0.01em;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
/* the mark strokes itself once, the length of its own path, so the tick and the cross both feel drawn */
.mark { display: inline-block; width: 1em; height: 1em; vertical-align: -0.12em; margin-right: 8px; }
.mark path { stroke-dasharray: var(--len, 40); stroke-dashoffset: var(--len, 40); }
.mark.draw path { animation: draw 380ms cubic-bezier(.22,1,.36,1) forwards; }
@keyframes draw { to { stroke-dashoffset: 0; } }

.result.hit { color: var(--flag); }
.result.ok { color: var(--ok); }
.result:not(.shown) { display: none; }
#liveMsg { display: block; margin-top: 6px; }
#liveMsg:empty { display: none; }
#liveClosed { margin-top: 12px; max-width: 52ch; }
#liveNote { margin-top: 12px; max-width: 52ch; }
details#cats { margin-top: 12px; }
details#cats summary {
  display: inline-flex;
  align-items: center;
  height: 44px;
  font-size: 14px;
  color: var(--ink);
  cursor: pointer;
  list-style: none;
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-color: var(--line);
}
details#cats summary::-webkit-details-marker { display: none; }
details#cats summary:hover { text-decoration-color: var(--ink); }
details#cats[open] summary { text-decoration: none; color: var(--muted); }
#bars { display: grid; grid-template-columns: 6.5em 1fr 3em; gap: 8px 12px; align-items: center; margin-top: 8px; font: 400 13px/1 var(--mono); }
#bars .n { color: var(--body); }
#bars .v { text-align: right; color: var(--muted); font-variant-numeric: tabular-nums; }
#bars .v.hit { color: var(--flag); font-weight: 500; }
#bars .b { position: relative; height: 6px; background: var(--line); border-radius: 3px; overflow: visible; }
#bars .b i { position: absolute; left: 0; top: 0; bottom: 0; width: 0; background: var(--ink); border-radius: 3px; transition: width 200ms ease; }
#bars .b i.hit { background: var(--flag); }
#bars .b s { position: absolute; top: -4px; bottom: -4px; width: 1px; background: var(--muted); text-decoration: none; }

/* hero */
.hero { padding-top: 48px; padding-bottom: var(--section); }
@media (min-width: 768px) { .hero { padding-top: 72px; } }
@media (min-width: 1440px) { .hero { padding-top: 88px; } }
.hero .grid-5-7 { margin-top: var(--block); }
/* the developers hero stacks its own children instead of using .stack */
#dev-page .hero .lead { margin-top: 20px; }
#dev-page .hero .cta { margin-top: 28px; }

/* the two fine-print lines used to sit under the CTA, ahead of the live demo, so the interactive proof was
   the fifth thing on the page rather than the second. Moved below the whole grid: reachable either way,
   no longer the reason a phone has to scroll past four blocks of text before the demo appears. */
.hero-fine { margin-top: var(--block); max-width: 46ch; }

/* billing pages */
main.plain { padding-top: 64px; padding-bottom: var(--section); min-height: calc(100vh - 56px - 130px); }
@media (min-width: 768px) { main.plain { padding-top: 112px; } }

/* micro-interactions: they fire on a real interaction, never on their own, and all of them are switched off
   by prefers-reduced-motion at the end of this file. Nothing here animates while the reader is just reading. */

/* the verdict: rises into place once, so a new answer reads as new rather than as text that silently swapped */
#result { transition: opacity 180ms ease, transform 180ms cubic-bezier(.22,1,.36,1); }
#result.settling { opacity: 0; transform: translateY(6px); }

/* the bars fill left to right with a short stagger, so the eye follows the one that crossed its line */
#bars .b i { transition: width 420ms cubic-bezier(.22,1,.36,1); }
#bars .b i.hit { transition-duration: 560ms; }

/* the button takes the press, and says it is working instead of going dead */
.btn { transition: background-color 120ms ease, color 120ms ease, transform 90ms cubic-bezier(.22,1,.36,1), opacity 120ms ease; }
.btn:active:not([aria-disabled="true"]):not(:disabled) { transform: translateY(1px) scale(.985); }
.btn[data-busy="true"] { position: relative; overflow: hidden; color: transparent; }
.btn[data-busy="true"]::after {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 40%;
  background: linear-gradient(90deg, transparent, rgba(250, 250, 250, .55), transparent);
  animation: sweep 1100ms ease-in-out infinite;
}
@keyframes sweep { from { transform: translateX(-100%); } to { transform: translateX(350%); } }

/* the chips answer the tap before the network does */
.chip { transition: background-color 120ms ease, border-color 120ms ease, transform 90ms cubic-bezier(.22,1,.36,1); }
.chip:active { transform: translateY(1px) scale(.98); }
.chip.on { border-color: var(--ink); }

/* copy buttons: the label already swaps to copied, this gives the press a body */
.copy { transition: color 120ms ease, border-color 120ms ease, transform 90ms cubic-bezier(.22,1,.36,1); }
.copy:active { transform: translateY(1px); }
.copy[data-done="true"] { color: var(--ok); border-color: var(--ok); }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { transition: none !important; animation: none !important; }
  #result.settling { opacity: 1; transform: none; }
  .mark path { stroke-dashoffset: 0; }
  .btn[data-busy="true"] { color: inherit; }
  .btn[data-busy="true"]::after { content: none; }
}

/* jump-to-section list on the long legal pages. Closed by default, the same native <details> pattern as
   the live demo's "Show all categories": the failure mode on these pages was never overflow, it was a wall
   of text nobody on a phone was going to read start to finish. This gets a reader to the one section they
   came for without scrolling past nineteen headings to find it. */
details.toc {
  margin-top: 24px;
  padding: 4px 20px;
  border: 1px solid var(--line);
  border-radius: var(--r);
}
details.toc summary {
  display: flex;
  align-items: center;
  min-height: 44px;
  font-size: 14px;
  font-weight: 500;
  color: var(--ink);
  cursor: pointer;
  list-style: none;
}
details.toc summary::-webkit-details-marker { display: none; }
details.toc summary::before {
  content: "+";
  display: inline-block;
  width: 1em;
  margin-right: 8px;
  font-family: var(--mono);
  color: var(--muted);
}
details.toc[open] summary::before { content: "\2212"; }
details.toc ul {
  margin: 4px 0 12px;
  padding: 0;
  list-style: none;
  border-top: 1px solid var(--line);
}
details.toc li { border-bottom: 1px solid var(--line); }
details.toc li:last-child { border-bottom: 0; }
details.toc a {
  display: flex;
  align-items: center;
  min-height: 44px;
  color: var(--body);
  text-decoration: none;
}
details.toc a:hover { color: var(--ink); }
@media (min-width: 768px) {
  details.toc ul { display: grid; grid-template-columns: 1fr 1fr; column-gap: 24px; }
}

/* text page rules live in one place, further up: search "text pages (privacy, terms)" */

/* the colour theme control: three states, because "follow the machine" is one of them */
.seg { display: inline-flex; box-shadow: var(--sh-hair); }
.seg-item {
  appearance: none; border: 0; background: transparent;
  min-height: 44px; padding: 0 12px;
  color: var(--muted); font-family: var(--mono); font-size: 12px;
  letter-spacing: .06em; text-transform: uppercase; cursor: pointer;
  transition: color 120ms ease, background-color 120ms ease;
}
.seg-item:hover { color: var(--ink); }
.seg-item[aria-pressed="true"] { background: var(--ink); color: var(--bg); }
.seg-item:focus-visible { outline: 2px solid var(--ink); outline-offset: -2px; }

/* The edge of a control has to be visible before you touch it: WCAG 1.4.11 asks 3:1, and the divider
   colour these used to borrow measured 1.27:1. */
textarea, input, select { box-shadow: var(--sh-control); }

/* Out of the way until it is focused, which is the only time it is for anybody. */
.skip {
  position: absolute; left: 8px; top: -60px; z-index: 10;
  display: inline-flex; align-items: center; min-height: 44px; padding: 0 16px;
  background: var(--ink); color: var(--bg); text-decoration: none;
  font-family: var(--mono); font-size: 12px; letter-spacing: .06em; text-transform: uppercase;
  transition: top 120ms ease;
}
.skip:focus { top: 8px; }

/* The log flag, built rather than drawn. A 1600px drawing squeezed into a phone is text at 22%; this is
   the page's own type, so it reflows, translates, and can be read aloud. */
.shot-embed { margin: 0; }
.embed { background: var(--surface); border-radius: var(--r); box-shadow: var(--sh-hair); padding: 16px; }
.embed-chan { margin: 0 0 12px; font-family: var(--mono); font-size: 13px; color: var(--muted); }
.embed-card { border-left: 3px solid var(--flag); padding-left: 12px; }
.embed-title { margin: 0; font-weight: 600; color: var(--ink); font-size: 15px; }
.embed-body { margin: 6px 0 12px; color: var(--body); font-size: 15px; overflow-wrap: anywhere; }
.embed-fields { display: flex; flex-wrap: wrap; gap: 24px; margin: 0 0 12px; }
.embed-fields div { margin: 0; }
.embed-fields dt { font-family: var(--mono); font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: .06em; }
.embed-fields dd { margin: 2px 0 0; color: var(--ink); font-size: 14px; }
.embed-link { margin: 0 0 12px; color: var(--ink); font-size: 14px; text-decoration: underline; text-underline-offset: 3px; }
.embed-foot { margin: 0; font-size: 13px; color: var(--muted); }
.embed-btns { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px; }
.embed-btn {
  display: inline-flex; align-items: center; min-height: 36px; padding: 0 12px;
  background: var(--bg); box-shadow: var(--sh-control); border-radius: var(--r);
  font-size: 13px; color: var(--body);
}

/* Code is told apart by weight and by the muted-to-ink ramp. There is no accent colour in this design, and
   borrowing one for syntax would put somebody else's palette in the middle of the page. */
.code i { font-style: normal; }
.code i.c { color: var(--muted); }           /* a comment is the one thing that should recede */
.code i.k { color: var(--ink); font-weight: 600; }
.code i.s { color: var(--body); }
.code i.n { color: var(--ink); font-variant-numeric: tabular-nums; }
.code i.f { color: var(--muted); font-weight: 500; }

/* Invisible until the heading is hovered or the link itself is focused, so it is there for the person who
   wants it and nowhere for everybody else. */
.anchor {
  margin-left: .4em;
  color: var(--muted);
  text-decoration: none;
  opacity: 0;
  transition: opacity 120ms ease;
  /* A hash character is about fifteen pixels wide, which is not something a thumb can hit. The target is
     grown with padding and pulled back with a negative margin, so it is reachable without moving the
     heading it sits beside. On a touch screen it is always visible, because there is no hover there to
     reveal it with and an invisible control is not one. */
  display: inline-block;
  min-width: var(--tap);
  min-height: var(--tap);
  padding: 0 .5em;
  margin-right: -.5em;
  line-height: var(--tap);
  vertical-align: middle;
}
h2:hover .anchor, .anchor:focus-visible { opacity: 1; }

@media (hover: none) {
  .anchor { opacity: .45; }
}
