/* ============================================================================
   GrowthAdmins — site styles.

   The copy on these pages is written in website/build.mjs; the record of what
   the site says and why is spec/growthadmins-positioning.md. Read that before
   changing copy or layout here.

   From 2026-08-10 to 2026-08-22 this was a dark one-page "door" (#224). The
   palette below is the LIGHT one the site shipped with on 2026-08-09: the
   tokens are lifted from the app so the site and the product render the same,
   and the contrast figures in the comments were measured then (D-13 and D-14
   in website/docs/PROJECT-BRIEF.md). Restored, not invented.

   Fonts are SELF-HOSTED, deliberately. No visitor's browser contacts a third
   party before they have agreed to anything — the published Privacy Notice was
   revised on 2026-08-04 to drop that disclosure, and a font CDN here would
   quietly make it necessary again.

   NO INLINE STYLES ANYWHERE. The CloudFront CSP sends style-src 'self', which
   blocks style="…" attributes silently in production and not at all on a
   file:// preview; check.mjs fails on any it finds so the difference is never
   discovered live.
   ========================================================================= */

@font-face {
  font-family: "Sora";
  src: url("fonts/sora-latin.woff2") format("woff2");
  font-weight: 100 800; /* variable — one file covers every weight used */
  font-display: swap;
  font-style: normal;
}
@font-face {
  font-family: "Public Sans";
  src: url("fonts/public-sans-latin.woff2") format("woff2");
  font-weight: 100 900;
  font-display: swap;
  font-style: normal;
}
@font-face {
  font-family: "JetBrains Mono";
  src: url("fonts/jetbrains-mono-latin.woff2") format("woff2");
  font-weight: 100 800;
  font-display: swap;
  font-style: normal;
}

:root {
  --display: "Sora", ui-sans-serif, system-ui, sans-serif;
  --ui: "Public Sans", ui-sans-serif, system-ui, -apple-system, sans-serif;
  --mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

  --bg: oklch(97% 0.005 250);
  --surface: oklch(100% 0 0);
  --surface-2: oklch(98.5% 0.004 250);
  --text: oklch(25% 0.02 250);
  --muted: oklch(50% 0.02 250);
  /* 53% clears 4.5:1 on --bg (4.74), --surface (5.26) and --primary-wash
     (4.74). 62% did not (3.34:1) — measured 2026-08-09 through a canvas, since
     Chrome returns computed colours in oklch and string-parsing them silently
     yields nonsense. Every use of this token is small text. */
  --faint: oklch(53% 0.018 250);
  --border: oklch(90% 0.008 250);
  --border-soft: oklch(93% 0.008 250);
  --primary: oklch(52% 0.16 258);
  --primary-deep: oklch(40% 0.13 258);
  --primary-wash: oklch(96.5% 0.02 258);
  /* Text ON a --primary fill. A token rather than `white` because --primary
     inverts between the palettes: dark blue by day, LIGHT blue in the dark
     override, where white lettering would sit at 2.5:1. */
  --on-primary: oklch(100% 0 0);

  /* The card covers. One hue per card, all inside the blue the rest of the
     palette uses; hue 300 is reserved for entitlement and never appears here.
     The letter is white at low alpha so it reads as light falling on the
     cover rather than as a glyph competing with the title below it. */
  --cover-ink: oklch(100% 0 0 / 0.62);

  --measure: 66ch;
  --radius: 12px;
  --shell: 1120px;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: oklch(17% 0.015 258);
    --surface: oklch(21% 0.018 258);
    --surface-2: oklch(24% 0.018 258);
    --text: oklch(94% 0.006 250);
    --muted: oklch(72% 0.015 250);
    /* 65% clears 4.5:1 against --bg, --surface, --surface-2 and --primary-wash
       (4.82 / 4.71 / 4.55 measured 2026-08-09). The two palettes hold
       different values because they solve different problems. */
    --faint: oklch(65% 0.018 250);
    --border: oklch(30% 0.02 258);
    --border-soft: oklch(27% 0.02 258);
    --primary: oklch(72% 0.14 258);
    --primary-deep: oklch(80% 0.12 258);
    --primary-wash: oklch(26% 0.04 258);
    /* Dark ink on the light-blue fill: 8.6:1 against --primary, 10.4:1 against
       the --primary-deep hover. */
    --on-primary: oklch(18% 0.02 258);
    --cover-ink: oklch(100% 0 0 / 0.16);
  }
}

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

html {
  background: var(--bg);
  scroll-behavior: smooth;
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  * {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

body {
  margin: 0;
  min-height: 100vh;
  background: var(--bg);
  color: var(--text);
  font-family: var(--ui);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  display: flex;
  flex-direction: column;
}

main {
  flex: 1 0 auto;
}

.shell {
  max-width: var(--shell);
  width: 100%;
  margin: 0 auto;
  padding: 0 28px;
}

a {
  color: var(--primary);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}
a:hover {
  color: var(--primary-deep);
}

/* Present for a screen reader and a search engine, absent for an eye. Clipped
   rather than display:none, which VoiceOver and NVDA both skip. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--primary);
  color: var(--on-primary);
  padding: 10px 16px;
  border-radius: 0 0 8px 0;
  z-index: 100;
  font-weight: 700;
}
.skip:focus {
  left: 0;
}

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

/* Anything reached by a fragment must clear the sticky header. The form's
   outcome panels are the case that matters: a visitor bounced back to
   /#too-many has to SEE the explanation, and one scrolled under the header
   reads as a page that did nothing. */
:target {
  scroll-margin-top: 96px;
}

/* ── Header — a mark, the menus, a way in, and the one conversion ────────── */
header.site {
  position: sticky;
  top: 0;
  z-index: 50;
  background: color-mix(in oklab, var(--bg) 88%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--border-soft);
}
.bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  height: 64px;
}
.wordmark {
  font-family: var(--display);
  font-weight: 800;
  font-size: 21px;
  letter-spacing: -0.015em;
  color: var(--text);
  text-decoration: none;
}
.wordmark:hover {
  color: var(--text);
}
/* The bar holds a mark, the menus, the way in, and the one conversion.
   `.nav-items` is the row on a desktop and the drop-down panel on a phone. */
nav.links {
  display: flex;
  align-items: center;
  gap: 22px;
}
.nav-items {
  display: flex;
  align-items: center;
  gap: 22px;
}
nav.links a,
.menu summary {
  color: var(--muted);
  text-decoration: none;
  font-size: 14px;
  font-weight: 600;
}
nav.links a:hover,
nav.links a[aria-current="page"],
.menu summary:hover,
.menu[open] summary {
  color: var(--text);
}

/* A menu is a <details>, so it opens on tap, click, Enter and Space with no
   script and announces its own state. The summary is as tall as the bar so the
   panel hangs from the bar's edge, not from the word. */
.menu {
  position: relative;
}
.menu summary {
  display: flex;
  align-items: center;
  gap: 7px;
  height: 64px;
  cursor: pointer;
  list-style: none;
  user-select: none;
}
.menu summary::-webkit-details-marker {
  display: none;
}
.menu summary::after {
  content: "";
  width: 6px;
  height: 6px;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: translateY(-2px) rotate(45deg);
  transition: transform 160ms ease;
}
.menu[open] summary::after {
  transform: translateY(1px) rotate(-135deg);
}
.drop {
  position: absolute;
  top: 58px;
  left: -14px;
  min-width: 300px;
  display: grid;
  padding: 8px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 18px 40px -18px oklch(20% 0.03 258 / 0.35);
}
nav.links .drop a {
  display: grid;
  gap: 2px;
  padding: 10px 12px;
  border-radius: 8px;
}
nav.links .drop a:hover {
  background: var(--surface-2);
}
.drop strong {
  color: var(--text);
  font-weight: 700;
}
.drop span {
  font-size: 12.5px;
  font-weight: 500;
  color: var(--faint);
}

/* The phone menu's control. The checkbox is the control and stays focusable —
   it is moved out of sight, never display:none, or the keyboard loses it. The
   label is what a finger hits. */
.nav-t {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}
.nav-burger {
  display: none;
}
@media (max-width: 940px) {
  .nav-burger {
    display: inline-flex;
    align-items: center;
    gap: 9px;
    padding: 9px 12px;
    border: 1px solid var(--border);
    border-radius: 9px;
    font-size: 14px;
    font-weight: 700;
    color: var(--text);
    cursor: pointer;
    user-select: none;
  }
  .nav-t:focus-visible + .nav-burger {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
  }
  /* Three bars that become a cross: one element, two shadows' worth of pseudo. */
  .bars,
  .bars::before,
  .bars::after {
    display: block;
    width: 16px;
    height: 2px;
    border-radius: 2px;
    background: currentColor;
    transition: transform 160ms ease, background-color 160ms ease;
  }
  .bars {
    position: relative;
  }
  .bars::before,
  .bars::after {
    content: "";
    position: absolute;
    left: 0;
  }
  .bars::before {
    top: -5px;
  }
  .bars::after {
    top: 5px;
  }
  .nav-t:checked + .nav-burger .bars {
    background: transparent;
  }
  .nav-t:checked + .nav-burger .bars::before {
    transform: translateY(5px) rotate(45deg);
  }
  .nav-t:checked + .nav-burger .bars::after {
    transform: translateY(-5px) rotate(-45deg);
  }

  /* The panel hangs from the sticky header and scrolls inside itself, so a long
     menu never pushes the page. */
  .nav-items {
    display: none;
    position: absolute;
    top: 64px;
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: 6px 20px 22px;
    max-height: calc(100dvh - 64px);
    overflow-y: auto;
    background: var(--bg);
    border-bottom: 1px solid var(--border);
    box-shadow: 0 24px 40px -24px oklch(20% 0.03 258 / 0.35);
  }
  .nav-t:checked ~ .nav-items {
    display: flex;
  }
  .nav-items > a,
  .menu summary {
    height: auto;
    padding: 15px 4px;
    font-size: 16px;
    border-bottom: 1px solid var(--border-soft);
  }
  .menu summary {
    justify-content: space-between;
  }
  .drop {
    position: static;
    min-width: 0;
    padding: 4px 0 10px 6px;
    background: transparent;
    border: none;
    border-bottom: 1px solid var(--border-soft);
    border-radius: 0;
    box-shadow: none;
  }
}

/* On a narrow phone the bar holds a wordmark, the menu control and the button,
   and at 375px the three did not fit: the row ran 51px past the screen and the
   whole page scrolled sideways (measured 2026-09-19). The control keeps its
   bars and drops its word — the checkbox still carries the name "Menu". */
@media (max-width: 480px) {
  .bar {
    gap: 12px;
  }
  .wordmark {
    font-size: 19px;
  }
  nav.links {
    gap: 10px;
  }
  .nav-burger {
    gap: 0;
    padding: 12px 11px;
    font-size: 0;
  }
  nav.links .btn {
    padding: 10px 14px;
  }
}
@media (max-width: 360px) {
  .wordmark {
    font-size: 17px;
  }
  .nav-burger {
    padding: 11px 9px;
  }
  nav.links .btn {
    padding: 9px 11px;
    font-size: 13px;
  }
}

.btn {
  display: inline-block;
  background: var(--primary);
  color: var(--on-primary) !important;
  border: none;
  padding: 10px 18px;
  border-radius: 9px;
  font-size: 14px;
  font-weight: 700;
  text-decoration: none;
  font-family: var(--ui);
  cursor: pointer;
  white-space: nowrap;
  transition: background-color 160ms ease;
}
.btn:hover {
  background: var(--primary-deep);
  color: var(--on-primary) !important;
}
.btn.ghost {
  background: transparent;
  color: var(--text) !important;
  border: 1px solid var(--border);
}
.btn.ghost:hover {
  background: var(--surface);
  color: var(--text) !important;
}
.btn.lg {
  padding: 14px 26px;
  font-size: 15.5px;
  border-radius: 10px;
}

/* ── Sections and the type scale ─────────────────────────────────────────── */
section {
  padding: 84px 0;
  border-bottom: 1px solid var(--border-soft);
}
section:last-of-type {
  border-bottom: none;
}

.eyebrow {
  font-size: 11.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--primary);
  margin: 0 0 12px;
}

h1 {
  font-family: var(--display);
  font-size: clamp(38px, 5.6vw, 60px);
  line-height: 1.04;
  letter-spacing: -0.03em;
  font-weight: 800;
  margin: 0 0 22px;
  max-width: 16ch;
  /* No orphaned last word. Balanced wrapping is a hint browsers that lack it
     ignore, so the fallback is the old ragged wrap, never a broken one. */
  text-wrap: balance;
}
h2 {
  font-family: var(--display);
  font-size: clamp(27px, 3.6vw, 38px);
  line-height: 1.14;
  letter-spacing: -0.022em;
  font-weight: 700;
  margin: 0 0 16px;
  max-width: 24ch;
  text-wrap: balance;
}
h3 {
  font-family: var(--display);
  font-size: 17px;
  line-height: 1.3;
  letter-spacing: -0.01em;
  font-weight: 700;
  margin: 0 0 7px;
}
.lede {
  font-size: clamp(17px, 2vw, 19px);
  line-height: 1.55;
  color: var(--muted);
  max-width: var(--measure);
  margin: 0 0 30px;
}
p {
  max-width: var(--measure);
}
.sub {
  color: var(--muted);
  max-width: var(--measure);
  margin: 0 0 34px;
}

/* ── Hero: the copy on the left, the system on the right ─────────────────── */
.hero {
  padding: 84px 0 76px;
}
.hero-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
  gap: 52px;
  align-items: center;
}
@media (max-width: 860px) {
  .hero-grid {
    grid-template-columns: 1fr;
    gap: 36px;
  }
}

/* The category pill: one short label above the
   headline. Mono and tracked so it reads as a label and not as a sentence. */
.pill {
  display: inline-block;
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--primary-deep);
  background: var(--primary-wash);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 6px 12px;
  margin: 0 0 22px;
}

.cta-row {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
  align-items: center;
}
.cta-note {
  font-size: 13.5px;
  color: var(--faint);
  margin: 16px 0 0;
}

/* Numbered tiles — numbered because they ARE a sequence. Stacked in a narrow
   column by default; `.wide` runs them across the shell. The site has no
   photography: nothing is fetched from anywhere, and a stock image is a claim. */
.steps {
  display: grid;
  grid-template-columns: 1fr;
  gap: 12px;
  list-style: none;
  margin: 0;
  padding: 0;
}
.steps li {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 18px 20px 18px 64px;
  position: relative;
  display: grid;
  gap: 5px;
}
.steps .n {
  position: absolute;
  left: 20px;
  top: 18px;
  font-family: var(--display);
  font-weight: 800;
  font-size: 26px;
  line-height: 1;
  letter-spacing: -0.03em;
  color: var(--primary);
}
.steps strong {
  font-family: var(--display);
  font-size: 15.5px;
  font-weight: 700;
  letter-spacing: -0.01em;
}
.steps span:not(.n) {
  font-size: 13.5px;
  color: var(--muted);
  line-height: 1.5;
}
.steps.wide {
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  margin-top: 30px;
}

/* An inner page's hero: the same pill, headline, lede and buttons as the front
   page, without the right-hand column. */
.page-hero {
  padding: 72px 0 60px;
}
.page-hero h1 {
  font-size: clamp(34px, 4.8vw, 52px);
  max-width: 20ch;
}
.chips {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 26px 0 0;
  padding: 0;
}
.chips li {
  font-size: 13px;
  font-weight: 600;
  color: var(--muted);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 6px 12px;
}

/* The front page's right-hand panel: the three parts of the company, each a link. */
.sys {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 16px;
  padding: 24px;
  display: grid;
  gap: 10px;
}
.sys .eyebrow {
  margin: 0;
}
.sys-h {
  font-family: var(--display);
  font-weight: 700;
  font-size: 19px;
  letter-spacing: -0.015em;
  margin: 0 0 8px;
}
.sys-row {
  display: grid;
  gap: 4px;
  padding: 16px 18px;
  border: 1px solid var(--border-soft);
  border-radius: var(--radius);
  background: var(--surface-2);
  text-decoration: none;
  color: var(--muted);
  font-size: 14px;
  line-height: 1.5;
}
.sys-row:hover {
  border-color: var(--primary);
  color: var(--muted);
}
.sys-row strong {
  font-family: var(--display);
  font-size: 16px;
  color: var(--text);
}

/* ── Cards ───────────────────────────────────────────────────────────────
   A cover with a category tag and a faint word, a title, a description, a label
   on the left and an arrow on the right. The grid fills the shell with as many
   as fit; `.three` fixes it at three. */
.grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(238px, 1fr));
  gap: 16px;
  margin-top: 36px;
}
.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
.cover {
  position: relative;
  aspect-ratio: 16 / 9;
  background: linear-gradient(135deg, oklch(95% 0.03 var(--h)), oklch(80% 0.1 var(--h)));
  border-bottom: 1px solid var(--border-soft);
  overflow: hidden;
}
@media (prefers-color-scheme: dark) {
  .cover {
    background: linear-gradient(135deg, oklch(27% 0.05 var(--h)), oklch(42% 0.1 var(--h)));
  }
}
/* A WORD on the cover where the 2026-08-22 page had a letter: the line's own
   short noun, set large and faint, so the card says what it is before the
   title does. Same ink, same placement. */
.cover .word {
  position: absolute;
  right: 14px;
  bottom: 10px;
  font-family: var(--display);
  font-weight: 800;
  font-size: 40px;
  line-height: 1;
  letter-spacing: -0.04em;
  color: var(--cover-ink);
  white-space: nowrap;
}
.cover .tag {
  position: absolute;
  top: 12px;
  left: 12px;
  background: var(--surface);
  color: var(--text);
  font-family: var(--mono);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 5px 10px;
  border-radius: 999px;
  border: 1px solid var(--border-soft);
}
.card-body {
  padding: 20px 22px 22px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  flex: 1;
}
.card-body h3 {
  margin: 0;
  font-size: 19px;
}
.card-body p {
  margin: 0;
  font-size: 14px;
  color: var(--muted);
  line-height: 1.55;
}
.card-foot {
  margin-top: auto;
  padding-top: 14px;
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 8px 14px;
  flex-wrap: wrap;
}
.price {
  font-size: 13.5px;
  font-weight: 700;
  color: var(--text);
}
.more {
  font-size: 14px;
  font-weight: 700;
  text-decoration: none;
  white-space: nowrap;
}
.more:hover {
  text-decoration: underline;
}
/* Five hues between cyan-blue and the palette's own 258. Nothing past 258: at
   270 a cover read lavender on screen, and violet is the entitlement hue this
   site must never touch. */
.c1 {
  --h: 208;
}
.c2 {
  --h: 224;
}
.c3 {
  --h: 240;
}
.c4 {
  --h: 250;
}
.c5 {
  --h: 258;
}
/* Three across, so six industries sit three by two and never four and a pair. */
.grid.three {
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
}

/* ONE link per card. The title is the link and its ::after covers the whole
   card, so the card is one large target and a screen reader hears one link, not
   a title and an arrow that go to the same place. The arrow is decoration and
   is aria-hidden in the markup. */
.card {
  position: relative;
  transition: border-color 160ms ease;
}
.card-body h3 a {
  color: inherit;
  text-decoration: none;
}
.card-body h3 a::after {
  content: "";
  position: absolute;
  inset: 0;
}
.card-body h3 a:focus-visible {
  outline: none;
}
.card:has(h3 a:focus-visible) {
  outline: 2px solid var(--primary);
  outline-offset: 3px;
}
.card:hover {
  border-color: var(--primary);
}
.card:hover .more {
  text-decoration: underline;
}
span.more {
  color: var(--primary);
}

/* ── Panels ──────────────────────────────────────────────────────────────── */
.panel {
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 3px solid var(--primary);
  border-radius: var(--radius);
  padding: 26px 28px;
}
.panel h3 {
  font-size: 19px;
  margin: 0 0 12px;
}
.panel p {
  margin: 0 0 12px;
  font-size: 15px;
  color: var(--muted);
  line-height: 1.6;
}
.panel p:last-child {
  margin-bottom: 0;
}
.panels {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 16px;
  margin-top: 30px;
}
.panels.three {
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
}
.ticks {
  margin: 4px 0 0;
  padding: 0 0 0 1.15em;
  display: grid;
  gap: 7px;
  font-size: 14px;
  color: var(--muted);
  line-height: 1.5;
}
.ticks li::marker {
  color: var(--primary);
}
.panel .ticks {
  margin: 0 0 14px;
  font-size: 15px;
}
.aside {
  margin: 22px 0 0;
  font-size: 14.5px;
  color: var(--muted);
  max-width: 84ch;
}
.aside strong {
  color: var(--text);
}

/* Small labels: a panel's kicker, and the "live now" marker. Same voice as the pill. */
.tier-name,
.live {
  font-family: var(--mono);
  font-weight: 600;
  text-transform: uppercase;
  color: var(--primary-deep);
}
.tier-name {
  font-size: 11px;
  letter-spacing: 0.12em;
  margin: 0 0 10px;
}
.live {
  margin-left: 8px;
  font-size: 10px;
  letter-spacing: 0.1em;
  background: var(--primary-wash);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 3px 8px;
  vertical-align: 2px;
}

/* ── Tables ───────────────────────────────────────────────────────────────
   Packages, terms, partner tiers. The table scrolls inside its own box on a
   phone, so the page never scrolls sideways. */
.tbl-wrap {
  overflow-x: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
}
.tbl {
  width: 100%;
  min-width: 640px;
  border-collapse: collapse;
  font-size: 14px;
  line-height: 1.5;
}
.tbl th,
.tbl td {
  text-align: left;
  vertical-align: top;
  padding: 14px 16px;
  border-bottom: 1px solid var(--border-soft);
}
.tbl tbody tr:last-child th,
.tbl tbody tr:last-child td {
  border-bottom: none;
}
.tbl thead th {
  font-size: 11.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--faint);
  background: var(--surface-2);
}
.tbl tbody th {
  font-family: var(--display);
  font-weight: 700;
  white-space: nowrap;
}
.tbl td {
  color: var(--muted);
}

/* ── Questions ────────────────────────────────────────────────────────────
   <details>: they open and close with no script. */
.faq {
  margin-top: 8px;
  max-width: 820px;
  border-top: 1px solid var(--border);
}
.qa {
  border-bottom: 1px solid var(--border);
}
.qa summary {
  cursor: pointer;
  padding: 18px 28px 18px 0;
  font-family: var(--display);
  font-weight: 700;
  font-size: 16.5px;
  letter-spacing: -0.01em;
}
.qa summary:hover {
  color: var(--primary);
}
.qa p {
  margin: 0 0 20px;
  color: var(--muted);
}

/* ── The problem, then the reality ────────────────────────────────────────── */
.pains {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 10px;
  max-width: 820px;
}
.pains li {
  position: relative;
  padding: 14px 18px 14px 46px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: var(--muted);
}
.pains li::before {
  content: "\2715";
  position: absolute;
  left: 18px;
  top: 14px;
  font-weight: 700;
  color: var(--faint);
}
.reality {
  margin: 22px 0 0;
  padding: 16px 20px;
  max-width: 820px;
  border-left: 3px solid var(--primary);
  background: var(--primary-wash);
  border-radius: 0 var(--radius) var(--radius) 0;
  color: var(--text);
}

/* ── Contact: the intake form ─────────────────────────────────────────────
   Posts across origins to the application, so the CloudFront CSP names that
   host in `form-action`. Unchanged in what it sends; restyled for the light
   palette. */
.gate {
  max-width: 620px;
}
.rows {
  display: grid;
  gap: 18px;
}
.pair {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 18px;
}
.field label {
  display: block;
  font-size: 14px;
  font-weight: 700;
  margin: 0 0 6px;
}

/* BY EXCLUSION, NOT BY NAME. An earlier version of this rule listed
   [type="text"] and [type="email"], so a [type="tel"] added later inherited
   nothing and rendered as a stunted browser default beside its neighbour. A
   selector you have to remember to extend is a selector that will be wrong.
   Hidden inputs are the only ones that must not be styled; the honeypot is
   already off-screen. */
.gate input:not([type="hidden"]),
.gate textarea {
  width: 100%;
  font-family: var(--ui);
  font-size: 15px;
  line-height: 1.5;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 9px;
  padding: 11px 13px;
  transition: border-color 160ms ease;
}
.gate textarea {
  resize: vertical;
  min-height: 120px;
}
.gate input:not([type="hidden"]):hover,
.gate textarea:hover {
  border-color: var(--muted);
}
.gate input:not([type="hidden"]):focus-visible,
.gate textarea:focus-visible {
  border-color: var(--primary);
  outline: none;
}

.submit {
  margin-top: 4px;
}
.gate button {
  padding: 13px 28px;
  font-size: 15px;
}

.note {
  font-size: 13.5px;
  color: var(--faint);
  margin: 18px 0 0;
}

/* Honeypot. Off-screen rather than display:none — some bots skip anything that
   is display:none, which would defeat the point — and out of the tab order and
   the accessibility tree, so no person ever meets it. */
.hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* ── Outcome panels ──────────────────────────────────────────────────────
   Revealed by the URL fragment alone. The intake route redirects to /#received,
   /#failed, /#too-many or /#bad-email, and `:target` shows the matching one —
   no JavaScript, no server render, and it survives the back button. */
.formnote {
  display: none;
  margin: 0 0 30px;
  padding: 18px 22px;
  border-radius: var(--radius);
  border: 1px solid var(--primary);
  background: var(--primary-wash);
  max-width: 620px;
}
.formnote:target {
  display: block;
}
.formnote p {
  margin: 0;
  font-size: 14.5px;
  line-height: 1.6;
}
.formnote strong {
  font-weight: 700;
}

/* ── 404 ─────────────────────────────────────────────────────────────────── */
.lost {
  max-width: 560px;
  padding: 84px 0;
}
.lost h2 {
  max-width: none;
}
.lost p {
  color: var(--muted);
  margin: 0 0 30px;
  max-width: 46ch;
}

/* ── Footer ──────────────────────────────────────────────────────────────── */
footer.site {
  flex: 0 0 auto;
  padding: 40px 0 52px;
  border-top: 1px solid var(--border-soft);
  font-size: 13.5px;
  color: var(--faint);
}
.foot-mark {
  font-size: 18px;
  display: block;
  margin-bottom: 8px;
}
/* Four columns. The footer is the site map: every page is reachable from it. */
.foot-cols {
  display: grid;
  grid-template-columns: minmax(0, 1.3fr) repeat(3, minmax(0, 1fr));
  gap: 32px;
}
@media (max-width: 760px) {
  .foot-cols {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
.foot-col a {
  display: block;
  margin: 0 0 9px;
}
.foot-h {
  margin: 0 0 12px;
  font-size: 11.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--text);
}
.foot-blurb {
  margin: 0;
  max-width: 30ch;
  line-height: 1.5;
}
footer.site a {
  color: var(--faint);
  text-decoration: none;
}
footer.site a:hover {
  color: var(--text);
}
footer.site .foot-mark {
  color: var(--text);
}
.copyright {
  margin: 14px 0 0;
  font-size: 12.5px;
}

@media (max-width: 560px) {
  .shell {
    padding: 0 20px;
  }
  section {
    padding: 60px 0;
  }
  .hero {
    padding: 52px 0 48px;
  }
  .lost {
    padding: 52px 0;
  }
}
