/* Routn — routn.xyz
   Ported from the "Routn Website v2" Claude Design project. The design's
   palette, type ramp and motion rules are preserved; the reactive prototype
   runtime is not (see README). */

:root {
  /* — Palette (from the design) — */
  --bg: #0b1620;
  --text: #f2f5f7;
  --dim: #b7c2cd;
  --muted: #7f8d9c;
  --accent: #8fb0ff;
  --line: rgba(255, 255, 255, 0.09);
  --card: rgba(255, 255, 255, 0.035);

  /* — Spacing scale. Every margin, padding and gap resolves to one of these;
       no bare pixel spacing below this line. — */
  --s-1: 4px;
  --s-2: 8px;
  --s-3: 12px;
  --s-4: 16px;
  --s-5: 24px;
  --s-6: 32px;
  --s-7: 40px;
  --s-8: 56px;
  --s-9: 80px;
  --s-10: 112px;

  /* Page gutter scales with the viewport so 320px never feels cramped and
     1920px never runs to the edge. */
  --gutter: clamp(var(--s-4), 4vw, var(--s-7));

  /* Minimum comfortable touch target (WCAG 2.5.8 / Apple HIG). */
  --tap: 44px;

  --maxw: 1080px;
  --readw: 720px;

  /* — Radii, duration and easing. The v4 pages design reuses these values
       throughout; they had no tokens before, only repeated literals. — */
  --r-pill: 999px;
  --r-lg: 24px;
  --r-md: 18px;
  --r-sm: 10px;
  --dur-1: 200ms;
  --dur-2: 300ms;

  /* — The floating nav pill. 1200px wide on purpose: the design makes the
       chrome wider than the 1080px content column. — */
  --nav-h: 60px;
  --nav-maxw: 1200px;
  --nav-bg: rgba(27, 44, 78, 0.24);
  --nav-bg-scrolled: rgba(19, 29, 52, 0.66);
  --nav-line: rgba(143, 176, 255, 0.12);
  --nav-line-scrolled: rgba(143, 176, 255, 0.22);
  --nav-shadow: rgba(2, 6, 14, 0.45);

  /* How far down the page the pill reaches: its 12px offset plus its height.
     Anchor jumps and the sticky sidebar are both derived from it, so moving
     the pill can't leave a heading tucked underneath. */
  --nav-clear: calc(var(--s-3) + var(--nav-h));
  --clear-lg: calc(var(--nav-clear) + var(--s-7));

  /* — Surfaces taken from the design — */
  --hi: rgba(255, 255, 255, 0.08);
  --pill: rgba(116, 140, 184, 0.14);
  --pill-hover: rgba(150, 170, 210, 0.12);
  --rail: rgba(143, 176, 255, 0.12);
  --cta: rgba(91, 140, 255, 0.3);
  --cta-hover: rgba(91, 140, 255, 0.45);

  --aside-w: 220px;

  /* The two-column legal and support layouts collapse here. One number, in
     one place: the old 700px TOC breakpoint was written twice, once in CSS and
     once in JS, free to drift apart. */
  --desk: 1024px;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

body {
  font-family: Geist, system-ui, -apple-system, sans-serif;
  font-size: 17px;
  line-height: 1.65;
  overflow-x: hidden; /* belt-and-braces: nothing may scroll sideways */

  /* The design washes the top 720px of every page with two radials — a blue
     one off to the right and a fainter violet at top-left. Painted as a body
     background rather than a pseudo-element so it can't land in front of
     content: a z-indexed ::before on a body that makes no stacking context
     either covers the text or disappears behind the html background. */
  background-color: var(--bg);
  background-image:
    radial-gradient(50% 60% at 70% 0%, rgba(143, 176, 255, 0.16), transparent 70%),
    radial-gradient(30% 40% at 10% 10%, rgba(170, 120, 230, 0.08), transparent 70%);
  background-repeat: no-repeat;
  background-size: 100% 720px;
  background-position: top center;
}

a {
  color: var(--text);
  text-decoration: underline;
  text-decoration-color: rgba(143, 176, 255, 0.7);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}
a:hover { color: var(--accent); text-decoration-color: var(--accent); }

:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 6px; }
::selection { background: rgba(143, 176, 255, 0.3); }
li::marker { color: var(--muted); }

img { max-width: 100%; display: block; }

/* — Skip link — */
.skip {
  position: absolute; left: var(--s-4); top: -80px; z-index: 50;
  background: var(--text); color: var(--bg);
  padding: var(--s-3) var(--s-5); border-radius: 999px;
  font-size: 14px; font-weight: 600; text-decoration: none;
}
.skip:focus { top: var(--s-4); }

/* — Shell — */
.wrap { width: 100%; max-width: var(--maxw); margin: 0 auto; padding: 0 var(--gutter); }
.read { max-width: var(--readw); }

/* — Header: the design's floating pill —
   Not a full-width bar. It hovers 12px off the top edge, runs to 1200px, and
   darkens on scroll. The gutter comes from .site-head's own padding, so the
   pill is NOT a .wrap — overriding .wrap's padding is what used to push text
   flush to the edge at 320px. */
.site-head {
  position: sticky; top: 0; z-index: 30;
  padding: var(--s-3) clamp(var(--s-3), 3vw, var(--s-6)) 0;
}
.nav-pill {
  max-width: var(--nav-maxw); margin: 0 auto;
  min-height: var(--nav-h);
  padding-left: clamp(var(--s-4), 3vw, 22px);
  padding-right: var(--s-2);
  border-radius: var(--r-pill);
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s-2);
  background: var(--nav-bg);
  backdrop-filter: blur(24px) saturate(1.6);
  -webkit-backdrop-filter: blur(24px) saturate(1.6);
  box-shadow:
    inset 0 1px 0 var(--hi),
    0 0 0 1px var(--nav-line),
    0 14px 40px rgba(2, 6, 14, 0);
  transition: background var(--dur-2) ease, box-shadow var(--dur-2) ease;
}
/* The design drove this off a `scrolled` flag. Set by JS past 8px; without JS
   the pill simply stays in its idle state, which is a complete look. */
.site-head.is-scrolled .nav-pill {
  background: var(--nav-bg-scrolled);
  box-shadow:
    inset 0 1px 0 var(--hi),
    0 0 0 1px var(--nav-line-scrolled),
    0 14px 40px var(--nav-shadow);
}
.brand {
  font-family: 'Instrument Serif', Georgia, serif;
  font-size: 30px; line-height: 1;
  display: flex; align-items: center;
  min-height: var(--tap);
  text-decoration: none; color: var(--text);
}
.brand:hover { color: var(--text); }
.site-head nav { display: flex; align-items: center; gap: var(--s-1); }
.site-head nav a {
  text-decoration: none; color: var(--text);
  font-size: 15px;
  /* The link text alone was a ~20px tap target; pad it out to 44px. */
  display: inline-flex; align-items: center; justify-content: center;
  min-height: var(--tap); min-width: var(--tap);
  padding: 0 var(--s-3);
  border-radius: var(--r-pill);
}
.site-head nav a:hover { background: var(--pill-hover); color: var(--text); }
.site-head nav a[aria-current='page'] { background: rgba(150, 170, 210, 0.14); }

/* — Type — */
h1 {
  font-size: clamp(34px, 5vw, 64px);
  line-height: 1.05; letter-spacing: -0.03em; font-weight: 600;
  margin: var(--s-4) 0; text-wrap: balance;
  overflow-wrap: break-word;
}
h2 {
  font-size: clamp(23px, 2.6vw, 34px);
  line-height: 1.15; letter-spacing: -0.02em; font-weight: 600;
  margin: var(--s-9) 0 var(--s-3); text-wrap: balance;
}
h3 { font-size: 18px; font-weight: 600; margin: var(--s-6) 0 var(--s-1); letter-spacing: -0.01em; }

/* An eyebrow labels the heading under it, so the heading keeps its section
   spacing above the eyebrow, not between the two. */
.eyebrow + h1, .eyebrow + h2 { margin-top: var(--s-3); }
/* `myaccount.google.com/permissions` runs 16px past a 320px list item on the
   privacy page: one unbreakable token, wider than the column it sits in. */
p, li { overflow-wrap: break-word; }
p { color: var(--dim); margin: 0 0 var(--s-4); }
ul { color: var(--dim); padding-left: var(--s-5); }
li { margin: var(--s-2) 0; }
strong { color: var(--text); font-weight: 600; }

.eyebrow {
  font-family: 'Geist Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11.5px; text-transform: uppercase; letter-spacing: 0.15em;
  color: var(--muted); margin: 0;
}
.lede { font-size: clamp(17px, 1.4vw, 19.5px); color: var(--dim); max-width: 34em; }
.small { font-size: 14px; color: var(--muted); }

/* — Hero — */
.hero { padding-top: var(--s-8); padding-bottom: var(--s-7); }
.hero h1 { font-size: clamp(36px, 6vw, 86px); line-height: 1.02; letter-spacing: -0.035em; }
.hero-grid { display: grid; gap: var(--s-7); align-items: center; }
@media (min-width: 900px) { .hero-grid { grid-template-columns: 1.05fr 0.95fr; gap: var(--s-8); } }

.glow { position: relative; }
.glow::before {
  content: ''; position: absolute; inset: -14% 0 8%;
  background: radial-gradient(52% 44% at 50% 42%, rgba(143, 176, 255, 0.30), transparent 70%);
  filter: blur(46px); pointer-events: none; z-index: 0;
}
.phone-wrap { position: relative; z-index: 1; display: flex; justify-content: center; }
.phone {
  width: min(258px, 66vw);
  max-height: 574px;
  border-radius: 42px; overflow: hidden;
  border: 1px solid rgba(255, 255, 255, 0.14);
  box-shadow: 0 40px 90px rgba(0, 0, 0, 0.55), 0 2px 0 rgba(255, 255, 255, 0.06) inset;
  background: #0d1a26;
}
.phone img { width: 100%; height: auto; display: block; }

.badge-row {
  display: flex; align-items: center; gap: var(--s-3);
  flex-wrap: wrap; margin-top: var(--s-6);
}
/* — The pre-launch pill —
   Two sizes, both the design's: 52px in the body, 44px in the nav. The lit dot
   is the design's too, and was missing from the shipped body badges. */
.badge-soon {
  display: inline-flex; align-items: center; gap: 10px;
  min-height: calc(var(--tap) + var(--s-2)); padding: 0 22px;
  border-radius: var(--r-pill);
  background: var(--pill);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.12), 0 0 0 1px rgba(143, 176, 255, 0.28);
  font-size: 16px; font-weight: 500; white-space: nowrap; color: var(--text);
}
.badge-soon::before {
  content: ''; flex: none;
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--accent); box-shadow: 0 0 10px var(--accent);
}

/* The design shows a pill in the nav too, from 420px — but that nav holds one
   link and this one keeps three. 820px is where all four fit: measured. */
.nav-badge { display: none; }
@media (min-width: 820px) { .nav-badge { display: flex; } }
.nav-badge .badge-soon {
  gap: var(--s-2); min-height: var(--tap); padding: 0 var(--s-4); font-size: 13px;
}

/* — App Store badge (rendered only when STORE_URL is set) —
   The design leaves this a placeholder reading "Apple badge"; the real mark is
   the one thing here deliberately ahead of the design. */
.badge-store {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s-2);
  min-height: calc(var(--tap) + var(--s-2)); padding: 0 var(--s-5);
  border-radius: var(--r-pill);
  background: var(--text); color: var(--bg); border: 1px solid var(--text);
  font-size: 15px; font-weight: 600; text-decoration: none; white-space: nowrap;
}
.badge-store:hover { color: var(--bg); }
.nav-badge .badge-store {
  min-height: var(--tap); padding: 0 var(--s-4); font-size: 13px;
}
.badge-apple { width: 20px; height: 20px; flex: none; }

/* — Steppers / tablists — */
.demo { padding-top: var(--s-7); padding-bottom: var(--s-5); }
.steps {
  display: flex; gap: var(--s-2); flex-wrap: wrap;
  margin: var(--s-5) 0 var(--s-6); padding: 0; list-style: none;
}
.step-btn {
  font-family: 'Geist Mono', ui-monospace, monospace;
  font-size: 12.5px; letter-spacing: 0.04em;
  /* Was ~34px tall — under the 44px minimum. */
  min-height: var(--tap); padding: 0 var(--s-4);
  border-radius: 999px; cursor: pointer;
  border: 1px solid var(--line); background: transparent; color: var(--muted);
  transition: background 160ms ease, color 160ms ease, border-color 160ms ease;
}
.step-btn[aria-selected='true'] {
  background: rgba(143, 176, 255, 0.14);
  border-color: rgba(143, 176, 255, 0.45);
  color: var(--text);
}
.demo-cap {
  min-height: 3.2em; color: var(--dim); max-width: 30em;
  font-size: clamp(16px, 1.3vw, 18px);
}
.demo-grid { display: grid; gap: var(--s-6); align-items: start; }
@media (min-width: 900px) { .demo-grid { grid-template-columns: 1.05fr 0.95fr; gap: var(--s-8); } }

/* — Feature cards — */
.features { display: grid; gap: var(--s-4); margin: var(--s-6) 0 var(--s-3); }
@media (min-width: 820px) { .features { grid-template-columns: 1fr 1fr; gap: var(--s-5); } }
.card {
  background: var(--card); border: 1px solid var(--line);
  border-radius: 22px; padding: var(--s-6) var(--s-5);
}
.card h3 { margin: 0 0 var(--s-1); font-size: 19px; }
.card p { margin: 0; font-size: 15.5px; }

.shots { display: grid; gap: var(--s-4); margin-top: var(--s-6); }
@media (min-width: 720px) { .shots { grid-template-columns: repeat(3, 1fr); } }
.shot {
  border: 1px solid var(--line); border-radius: 18px;
  overflow: hidden; background: #0d1a26; margin: 0;
}

/* — Legal pages: the design's two-column reading layout — */
.legal {
  padding-top: clamp(var(--s-7), 7vw, var(--s-10));
  padding-bottom: clamp(var(--s-9), 9vw, 128px);
}
.legal-grid { display: flex; gap: clamp(var(--s-7), 6vw, 88px); align-items: flex-start; }
.legal-body { flex: 1 1 auto; min-width: 0; max-width: 68ch; }

.legal-body h1 {
  font-size: clamp(34px, 5vw, 64px);
  line-height: 1.02; letter-spacing: -0.035em; margin: 0;
}
.legal-eff {
  font-family: 'Geist Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 13px; color: var(--dim); margin: var(--s-4) 0 0;
}
.legal-intro { margin-top: var(--s-7); }
.legal-body h2 {
  font-size: 24px; line-height: 1.25; letter-spacing: -0.015em;
  color: var(--text); margin: var(--s-8) 0 var(--s-4);
  /* Without this, every anchor jump landed with the heading tucked under the
     sticky pill. Derived from the pill's own height, so it can't go stale. */
  scroll-margin-top: var(--clear-lg);
}
.legal-body p, .legal-body li { font-size: 17px; line-height: 1.7; }
.legal-body p { margin: 0 0 var(--s-4); text-wrap: pretty; }
.legal-body ul {
  margin: 0 0 var(--s-4); padding-left: 1.2em;
  display: flex; flex-direction: column; gap: var(--s-2);
}
.legal-body li { margin: 0; text-wrap: pretty; }

/* "The short version" becomes the design's highlighted card. The id moves to
   the wrapper so an anchor jump lands on the card's edge, not mid-card. */
.short-card {
  scroll-margin-top: var(--clear-lg);
  margin-top: var(--s-7); padding: clamp(22px, 3vw, 30px);
  border-radius: var(--r-lg);
  background: rgba(143, 176, 255, 0.07);
  box-shadow: inset 0 1px 0 var(--hi), 0 0 0 1px rgba(143, 176, 255, 0.2);
}
.short-card h2 { font-size: 22px; letter-spacing: -0.015em; margin: 0 0 var(--s-3); }
.short-card ul { margin: 0; }
.short-card li { color: #dce3ea; }

/* — The sticky sidebar: section switcher over a scroll-spy rail — */
.legal-aside {
  display: none;
  position: sticky; top: var(--clear-lg);
  flex: 0 0 var(--aside-w);
  flex-direction: column; gap: var(--s-5);
}
@media (min-width: 1024px) { .legal-aside { display: flex; } }

.seg {
  display: flex; gap: 2px; padding: var(--s-1);
  border-radius: var(--r-pill);
  background: rgba(116, 140, 184, 0.1);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06), 0 0 0 1px var(--rail);
}
.seg a {
  flex: 1; min-height: 40px;
  display: flex; align-items: center; justify-content: center;
  border-radius: var(--r-pill); text-decoration: none;
  font-family: 'Geist Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 13px; font-weight: 500;
  color: var(--dim); background: transparent;
}
.seg a:hover { color: var(--text); }
.seg a[aria-current='page'] { background: var(--text); color: var(--bg); }
.seg a[aria-current='page']:hover { color: var(--bg); }

.toc-spy {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-direction: column;
  border-left: 1px solid var(--line);
}
.toc-spy li { margin: 0; }
.toc-spy a {
  display: flex; align-items: center; min-height: 36px;
  margin-left: -1px; padding-left: 14px;
  font-size: 14px; line-height: 1.35;
  text-decoration: none; color: var(--dim);
  box-shadow: inset 2px 0 0 transparent;
  transition: color var(--dur-1) ease, box-shadow var(--dur-1) ease;
}
.toc-spy a:hover { color: var(--text); }
.toc-spy a[aria-current='location'] {
  color: var(--text); box-shadow: inset 2px 0 0 var(--accent);
}

/* — The same contents, as a disclosure, below the sidebar's breakpoint —
   Terms' 14 entries otherwise push the agreement itself off two phone screens.
   Static markup, closed by default, no JS: the sidebar is the enhancement and
   this is the base. Hidden once the sidebar takes over. */
.toc {
  margin: var(--s-6) 0 0;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}
.toc > summary {
  cursor: pointer; list-style: none;
  display: flex; align-items: center; justify-content: space-between; gap: var(--s-4);
  min-height: 52px;
  font-size: 15px; font-weight: 500; color: var(--text);
}
.toc > summary::-webkit-details-marker { display: none; }
.toc > summary::after {
  content: '+'; font-size: 18px; line-height: 1; color: var(--dim);
  transition: transform var(--dur-2) ease;
}
.toc[open] > summary::after { transform: rotate(45deg); }
.toc ol { list-style: none; margin: 0; padding: 0 0 var(--s-2); }
.toc li { margin: 0; }
.toc a {
  display: flex; align-items: center; min-height: var(--tap);
  font-size: 15px; color: var(--dim); text-decoration: none;
}
.toc a:hover { color: var(--text); }
@media (min-width: 1024px) { .toc { display: none; } }

/* The design's note: a full rounded panel with an inset ring, not a left rule. */
.callout {
  margin: 0 0 var(--s-4); padding: var(--s-4) var(--s-5);
  border-radius: var(--r-md);
  background: rgba(116, 140, 184, 0.1);
  box-shadow: inset 0 0 0 1px rgba(143, 176, 255, 0.26);
}
.callout p { margin: 0; color: var(--text); font-weight: 600; line-height: 1.6; }

/* — Support: the design's email-first two-column layout — */
.support {
  padding-top: clamp(var(--s-7), 7vw, var(--s-10));
  padding-bottom: clamp(var(--s-9), 9vw, 128px);
}
.support-grid {
  display: grid; grid-template-columns: minmax(0, 1fr);
  gap: clamp(var(--s-8), 6vw, 88px); align-items: start;
}
@media (min-width: 1024px) {
  .support-grid { grid-template-columns: minmax(0, 5fr) minmax(0, 6fr); }
}
.support-ask { display: flex; flex-direction: column; gap: var(--s-4); min-width: 0; }
.support-ask h1 {
  font-size: clamp(34px, 5vw, 64px);
  line-height: 1.02; letter-spacing: -0.035em; margin: 0;
}
.support-ask p { margin: 0; }

/* The address itself is the headline. The design's 52px ceiling broke it
   mid-domain ("routnapp@gmail." / "com") in the 5fr column at every desktop
   width; 41px is the largest size that holds one line at 1024px, the narrowest
   the two-column layout ever gets. `anywhere` stays as the 320px safety net. */
.mailto-xl {
  margin-top: clamp(var(--s-5), 4vw, var(--s-7));
  font-size: clamp(27px, 4.4vw, 41px); line-height: 1.05;
  letter-spacing: -0.035em; font-weight: 600;
  color: var(--text); text-decoration: none;
  overflow-wrap: anywhere;
}
.mailto-xl:hover { color: var(--accent); }
.cta {
  align-self: flex-start;
  display: inline-flex; align-items: center;
  min-height: calc(var(--tap) + var(--s-2)); padding: 0 var(--s-5);
  border-radius: var(--r-pill);
  background: var(--cta); color: var(--text);
  font-size: 16px; font-weight: 600; text-decoration: none;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.16), 0 0 0 1px rgba(143, 176, 255, 0.45);
  transition: background var(--dur-1) ease;
}
.cta:hover { background: var(--cta-hover); color: var(--text); }
.support-hint { font-size: 15px; line-height: 1.6; text-wrap: pretty; }

/* — 404 — */
.notfound {
  padding-top: clamp(var(--s-9), 16vh, 200px);
  padding-bottom: clamp(var(--s-9), 16vh, 200px);
  min-height: 52vh;
  display: flex; flex-direction: column; justify-content: center; gap: var(--s-5);
}
.notfound > * { margin: 0; }
.notfound .eyebrow {
  font-size: 15px; letter-spacing: 0.14em;
  color: var(--accent); text-transform: none;
}
.notfound-h {
  font-size: clamp(38px, 6vw, 80px);
  line-height: 1.02; letter-spacing: -0.04em; max-width: 12em;
}
.notfound .lede { font-size: clamp(17px, 1.4vw, 20px); }

/* — FAQ —
   The design builds each row as <h2><button aria-expanded>; <details> gets the
   same behaviour with no JS, and <summary> is allowed to carry one heading, so
   the document outline survives. */
.faq { border-top: 1px solid var(--line); }
.faq details { border-bottom: 1px solid var(--line); }
.faq summary {
  cursor: pointer; list-style: none;
  display: flex; align-items: center; justify-content: space-between; gap: var(--s-5);
  min-height: 64px; padding: var(--s-4) 0;
  color: var(--text);
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary:hover { color: var(--accent); }
.faq summary h2 {
  margin: 0; font-size: 17px; font-weight: 500; line-height: 1.35;
  letter-spacing: normal;
}
.faq summary::after {
  content: '+'; flex: none;
  color: var(--dim); font-weight: 400; font-size: 20px; line-height: 1;
  transition: transform var(--dur-2) ease;
}
.faq details[open] summary::after { transform: rotate(45deg); }
.faq details > p {
  margin: 0; padding: 0 var(--s-6) var(--s-5) 0;
  font-size: 16px; line-height: 1.65; text-wrap: pretty;
}

/* — Footer —
   One variant, on all five pages. index.html and the other four had drifted
   into two different footers with two different copyright lines. */
.site-foot {
  border-top: 1px solid var(--line); margin-top: var(--s-9);
  padding: var(--s-5) 0 var(--s-6);
}
.site-foot .wrap {
  max-width: var(--nav-maxw);
  display: flex; flex-wrap: wrap; gap: var(--s-2) var(--s-6);
  align-items: center; justify-content: space-between;
  font-size: 14px; color: var(--dim);
}
.site-foot nav { display: flex; align-items: center; flex-wrap: wrap; gap: 0 var(--s-1); }
.foot-brand {
  font-family: 'Instrument Serif', Georgia, serif;
  font-size: 22px; color: var(--text); text-decoration: none;
  display: flex; align-items: center;
  min-height: var(--tap); padding-right: var(--s-3);
}
.foot-brand:hover { color: var(--text); }
.site-foot nav a {
  color: var(--dim); font-size: 14.5px; text-decoration: none;
  display: inline-flex; align-items: center;
  min-height: var(--tap); padding: 0 var(--s-3);
}
.site-foot nav a:hover { color: var(--text); }
.foot-mail {
  font-family: 'Geist Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 13px;
}
.foot-meta {
  margin: 0; display: flex; flex-wrap: wrap; align-items: center;
  gap: var(--s-1) var(--s-4); min-height: var(--tap);
}
.foot-meta .by { color: var(--text); }
.foot-legal {
  flex-basis: 100%; margin: 0;
  font-size: 12.5px; line-height: 1.5; color: var(--muted);
}

/* — Motion — */
.reveal { opacity: 0; transform: translateY(24px); transition: opacity 620ms ease, transform 620ms ease; }
.reveal.in { opacity: 1; transform: none; }

/* Hero entrance — the design brought the hero in on load (opacity + lift),
   with these durations and easing. */
@keyframes heroIn {
  from { opacity: 0; transform: translateY(28px); }
  to   { opacity: 1; transform: none; }
}
@keyframes glowIn { from { opacity: 0; } to { opacity: 1; } }

.hero-anim .hero-grid > div { animation: heroIn 1.1s cubic-bezier(.2, .7, .2, 1) both; }
.hero-anim .hero-grid > div:nth-child(2) { animation-duration: 1.4s; animation-delay: 80ms; }
.hero-anim .glow::before { animation: glowIn 2s ease both; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    transition: none !important;
    animation: none !important;
    scroll-behavior: auto !important;
  }
  .reveal { opacity: 1; transform: none; }
}

/* — Narrowest phones —
   The 30px serif wordmark plus three padded links overflows 320px. Tighten the
   horizontal rhythm and the wordmark only; every tap target keeps its 44px
   height, and each link stays wider than 44px on its text alone. */
@media (max-width: 400px) {
  .site-head { padding-left: var(--s-3); padding-right: var(--s-3); }
  .nav-pill { padding-left: var(--s-4); gap: 0; }
  .brand { font-size: 26px; }
  .site-head nav { gap: 0; }
  .site-head nav a { padding: 0 var(--s-2); font-size: 14px; min-width: 0; }
}
