/* ShackOS marketing site — style.css
 *
 * Brand guide v2.0 (docs/brand/shackos-brand-guide-v2.0.html). The palette is
 * the app's Shack Dark — the guide is explicit that the rename does not touch
 * it (S04) — so the tokens below match frontend/src/styles/themes.css
 * [data-theme="shack-dark"], except --text-muted (see where it is set). The
 * layout is this site's own: it leads with consolidation and proves it with
 * the inventory of tools (S02).
 */

/* ── Typefaces ────────────────────────────────────────────────────────── */
/* Served from this site (fonts/), never Google Fonts: a visitor's browser
   asks no one else for a font. Exactly the faces the pages use, in the
   Latin subset, the only one their text needs (checked in a browser on
   every page): Playfair Display 700, Source Sans 3 400/600/700, Source Code
   Pro 400/600. A weight not listed is drawn from the nearest one, as it was
   under Google Fonts. Every page preloads the two that fill the first screen
   (Source Sans 3 400, Playfair Display 700); a preload must name the same URL
   as the src below, or the font downloads twice. Measured 2026-10-09
   (Chromium, empty cache, home and privacy pages): with both preloads the
   first paint was already in these fonts in 19 of 20 runs and nothing
   shifted; without them, in none, and the text swapped and moved after it.
   The cost: first paint 30-40 ms later on a 4G-like link, 140-180 ms on a
   slow one. Preloading only the body font bought nothing. Files, versions and
   licences: fonts/SOURCES.json and the OFL files beside it. */
@font-face {
  font-family: 'Playfair Display'; font-style: normal; font-weight: 700; font-display: swap;
  src: url('../fonts/playfair-display-latin-700-normal.woff2') format('woff2');
}
@font-face {
  font-family: 'Source Sans 3'; font-style: normal; font-weight: 400; font-display: swap;
  src: url('../fonts/source-sans-3-latin-400-normal.woff2') format('woff2');
}
@font-face {
  font-family: 'Source Sans 3'; font-style: normal; font-weight: 600; font-display: swap;
  src: url('../fonts/source-sans-3-latin-600-normal.woff2') format('woff2');
}
@font-face {
  font-family: 'Source Sans 3'; font-style: normal; font-weight: 700; font-display: swap;
  src: url('../fonts/source-sans-3-latin-700-normal.woff2') format('woff2');
}
@font-face {
  font-family: 'Source Code Pro'; font-style: normal; font-weight: 400; font-display: swap;
  src: url('../fonts/source-code-pro-latin-400-normal.woff2') format('woff2');
}
@font-face {
  font-family: 'Source Code Pro'; font-style: normal; font-weight: 600; font-display: swap;
  src: url('../fonts/source-code-pro-latin-600-normal.woff2') format('woff2');
}

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

:root {
  --bg:         #0D1B2A;   /* Navy Deep   · page background */
  --bg-surface: #162435;   /* Navy Card   · card surface */
  --bg-raised:  #1D2F44;   /* Navy Raised · elevated surface */
  --accent:     #EF9F27;   /* Amber       · INTERACTIVE ONLY (see S04) */
  --accent-deep:#BA7517;
  --accent-lt:  #FAC775;
  --text:       #F0EBE0;   /* Warm White  · primary text on dark */
  --text-sec:   #B8B0A2;
  /* Label/eyebrow grey. Set when the app's muted was #7A7268, 3.67:1 on --bg
     and 3.0:1 on --bg-raised — below AA for the 11px eyebrows this site uses.
     This value clears 4.5:1 on ALL THREE surfaces (6.24 / 5.63 / 4.89), which
     the guide's S05 readability rule requires of every piece of body text. The
     app has since moved to #A29886, within a shade of it. */
  --text-muted: #A29A8C;
  --border:     rgba(239,159,39,0.18);
  /* Semantic — these MEAN things and are never decorative (S04). Amber is
     reserved for interaction, so a band condition is never amber. */
  --good:       #4CAF50;
  --marginal:   #D9A15C;
  --poor:       #E24B4A;
  --font-display: 'Playfair Display', Georgia, serif;
  --font-body:    'Source Sans 3', 'Segoe UI', sans-serif;
  --font-mono:    'Source Code Pro', 'Courier New', monospace;
  --radius:     12px;      /* S08: cards use 12px */
  --max-w:      1080px;
}

/* scroll-padding: anchors, the skip link and keyboard focus land below the
   sticky 64px nav instead of under it. */
html { font-size: 16px; scroll-behavior: smooth; scroll-padding-top: 80px; }
/* S05 readability rule: body text is 16px at 1.7, and never shrinks to make a
   layout fit. */
body {
  background: var(--bg); color: var(--text);
  font-family: var(--font-body); font-size: 16px; line-height: 1.7;
  -webkit-font-smoothing: antialiased;
}
/* Inline links are underlined AT REST, not only on hover. Colour alone is not
   a distinguishable link inside a text block (WCAG 1.4.1) — axe flagged all
   four pages for it. Structural links that are already obviously interactive
   by shape — the nav, buttons, the logo, the footer link row — opt out below. */
a { color: var(--accent); text-decoration: underline; text-underline-offset: 2px; }
a:hover { text-decoration-thickness: 2px; }
.nav-links a, .nav-logo, .btn, .footer-links a, .skip-link { text-decoration: none; }
.nav-links a:hover, .footer-links a:hover { text-decoration: underline; }
/* S08: focus is always visible, never outline:none. */
a:focus-visible, button:focus-visible, summary:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 4px;
}
.container { max-width: var(--max-w); margin: 0 auto; padding: 0 24px; }
.skip-link {
  position: absolute; left: -9999px; top: 0;
  background: var(--accent); color: var(--bg); padding: 10px 18px; font-weight: 700;
}
.skip-link:focus { left: 8px; top: 8px; z-index: 200; }

/* ── Type ─────────────────────────────────────────────────────────────── */
h1, h2, h3 { font-family: var(--font-display); font-weight: 700; line-height: 1.2; }
/* S05: the eyebrow/label is mono, 11px, wide tracking. Mono is for data and
   labels — a sentence set in Source Code Pro is a bug. */
.eyebrow {
  font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.2em;
  text-transform: uppercase; color: var(--text-muted);
}
.lead { font-size: 19px; color: var(--text-sec); }

/* ── Wordmark ─────────────────────────────────────────────────────────── */
/* S12: "Shack" is always serif, "OS" always mono, and the pairing IS the
   wordmark. The name is never split, never all-caps and never lower-cased. */
.wordmark { display: inline-flex; align-items: baseline; }
.wordmark-lead { font-family: var(--font-display); font-weight: 700; color: var(--text); letter-spacing: -0.5px; }
.wordmark-trail { font-family: var(--font-mono); font-weight: 600; color: var(--accent); letter-spacing: 0.1em; margin-left: 3px; }

/* ── Nav ──────────────────────────────────────────────────────────────── */
.nav {
  position: sticky; top: 0; z-index: 100;
  background: rgba(13,27,42,0.94); backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--border);
}
.nav-inner {
  max-width: var(--max-w); margin: 0 auto; padding: 0 24px;
  display: flex; align-items: center; justify-content: space-between;
  height: 64px; gap: 24px;
}
.nav-logo { display: flex; align-items: center; gap: 10px; }
.nav-logo:hover { text-decoration: none; }
.nav-logo .wordmark-lead { font-size: 21px; }
.nav-logo .wordmark-trail { font-size: 14px; }
.nav-links { display: flex; align-items: center; gap: 26px; }
/* :not(.btn) is load-bearing. Without it `.nav-links a` (specificity 0,2,1)
   beats `.btn-primary` (0,1,0) and the Sign-up button renders muted grey on
   amber — a 1.7:1 contrast that looks like a disabled control. Caught in a
   real browser, not by reading the file. */
.nav-links a:not(.btn) { color: var(--text-sec); font-size: 14px; }
.nav-links a:not(.btn):hover,
.nav-links a[aria-current="page"] { color: var(--text); text-decoration: none; }
.nav-links a[aria-current="page"] { border-bottom: 2px solid var(--accent); padding-bottom: 2px; }

/* ── Buttons ──────────────────────────────────────────────────────────── */
/* S08: one primary per view; 44px minimum hit target on touch. */
.btn {
  display: inline-block; border-radius: 8px; font-weight: 700;
  border: 1px solid transparent; cursor: pointer; font-size: 15px;
  padding: 12px 26px; min-height: 44px; line-height: 1.4;
}
.btn:hover { text-decoration: none; filter: brightness(1.08); }
.btn-primary { background: var(--accent); color: var(--bg); }
.btn-ghost { background: transparent; color: var(--text-sec); border-color: rgba(255,255,255,0.16); }
.btn-ghost:hover { border-color: var(--accent); color: var(--accent); filter: none; }
.btn-sm { font-size: 13px; padding: 8px 16px; min-height: 36px; }

/* ── Sections ─────────────────────────────────────────────────────────── */
.section { padding: 72px 0; border-top: 1px solid rgba(239,159,39,0.08); }
.section:first-of-type { border-top: 0; }
.section-head { max-width: 660px; margin-bottom: 36px; }
.section-head h2, .split h2 { font-size: 28px; margin: 8px 0 12px; }

/* ── Hero ─────────────────────────────────────────────────────────────── */
.hero { padding: 88px 0 64px; }
.hero h1 { font-size: clamp(34px, 6vw, 52px); margin: 14px 0 20px; }
.hero h1 em { font-style: italic; color: var(--accent); }
.hero .lead { max-width: 640px; }
.hero-actions { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 32px; }

/* ── Cards ────────────────────────────────────────────────────────────── */
.cards { display: grid; gap: 20px; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }
.card { background: var(--bg-surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 24px; }
.card h3 { font-size: 18px; margin: 8px 0 10px; }
.card p { color: var(--text-sec); font-size: 15px; }

/* ── Band readout (S08 data card) ─────────────────────────────────────── */
.readout { display: flex; flex-direction: column; gap: 10px; margin-top: 18px; }
.readout-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; font-family: var(--font-mono); font-size: 14px; }
.readout-band { color: var(--text-sec); }
/* S04 "never colour alone": every state carries a label AND a dot AND a
   position, because red-green is the most common colour vision deficiency and
   band conditions are exactly where it matters.
   The WORD is full-contrast text and the DOT carries the semantic colour —
   which is the guide's own rule made literal ("a green dot is not a status;
   'Open' next to a green dot is"), and the only way to keep the semantics
   exact: --poor is 3.99:1 on a card, so setting the label to it would put the
   one state that means trouble below AA. */
.state { display: inline-flex; align-items: center; gap: 8px; color: var(--text); }
.state::before {
  content: ''; width: 9px; height: 9px; border-radius: 50%; flex: none;
  background: var(--state-dot, currentColor);
}
.state-good     { --state-dot: var(--good); }
.state-marginal { --state-dot: var(--marginal); }
.state-poor     { --state-dot: var(--poor); }

/* ── FAQ ──────────────────────────────────────────────────────────────── */
.faq-group { margin-bottom: 40px; }
.faq-group h2 { font-size: 22px; font-family: var(--font-body); font-weight: 600; margin-bottom: 6px; }
details.qa { border-bottom: 1px solid rgba(239,159,39,0.12); padding: 4px 0; }
details.qa summary { cursor: pointer; padding: 14px 0; font-weight: 600; list-style: none; display: flex; justify-content: space-between; gap: 16px; }
details.qa summary::-webkit-details-marker { display: none; }
/* The +/− is drawn, not said. The summary already reports expanded or
   collapsed, and generated content joins its accessible name, so every
   question used to be read out with a trailing "plus". The second `content`
   gives the glyph empty alt text; a browser too old for that syntax drops it
   and keeps the first. Same for the tick bullets and the error badge below. */
details.qa summary::after { content: '+'; content: '+' / ''; color: var(--accent); font-family: var(--font-mono); flex: none; }
details.qa[open] summary::after { content: '−'; content: '−' / ''; }
details.qa .qa-body { padding: 0 0 18px; color: var(--text-sec); max-width: 72ch; }
details.qa .qa-body p + p { margin-top: 12px; }

/* ── Footer ───────────────────────────────────────────────────────────── */
.footer { border-top: 1px solid var(--border); padding: 40px 0 56px; margin-top: 32px; }
.footer-inner { display: flex; flex-wrap: wrap; gap: 24px; justify-content: space-between; align-items: flex-start; }
.footer-links { display: flex; flex-wrap: wrap; gap: 20px; }
.footer-links a { color: var(--text-sec); font-size: 14px; }
.footer-note { color: var(--text-muted); font-size: 13px; margin-top: 14px; width: 100%; }

/* ── Band conditions explainer (band-conditions.html, 2026-09-13) ─────── */
/* Ported from the retired www/ site's copy, which drew its diagrams, step
   numbers and one pill in amber. Here amber means "you can click this" (S04),
   so structure is drawn in the warm neutrals and band states use .state
   (label + dot, never colour alone). */
.visually-hidden {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.bc-lead { color: var(--text-sec); max-width: 760px; margin: 0 0 24px; }
.bc-h3 { font-size: 18px; margin: 0 0 10px; }
.bc-svg {
  width: 100%; height: auto; display: block;
  background: var(--bg-raised); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 14px;
}
.bc-table {
  width: 100%; border-collapse: collapse; margin: 0 0 24px;
  background: var(--bg-surface); border-radius: var(--radius); overflow: hidden;
  font-size: 15px;
}
.bc-table th, .bc-table td {
  padding: 11px 14px; text-align: left; vertical-align: top;
  border-bottom: 1px solid var(--border);
}
.bc-table thead th {
  background: var(--bg-raised); color: var(--text-muted);
  font-family: var(--font-mono); font-size: 11px; font-weight: 600;
  letter-spacing: 0.2em; text-transform: uppercase;
}
.bc-table tbody tr:last-child > * { border-bottom: none; }
/* Each row's first cell is a row header (th scope="row"), so a screen reader
   names the row while moving down a column. It keeps the look of a cell. */
.bc-table td, .bc-table tbody th { color: var(--text-sec); }
.bc-table tbody th { font-weight: inherit; }
.bc-table strong { color: var(--text); }
.bc-cap { caption-side: top; text-align: left; padding: 0 0 8px; color: var(--text-muted); font-size: 14px; }
.bc-sub { color: var(--text-muted); font-size: 14px; }
.bc-row-hl > * { background: var(--bg-raised); color: var(--text); }
.bc-compare { display: grid; grid-template-columns: 1fr 1fr; gap: 22px; }
.bc-compare-col {
  border: 1px solid var(--border); border-radius: var(--radius);
  padding: 22px; background: var(--bg-surface);
}
.bc-compare-col .bc-table { background: var(--bg-raised); }
/* An h3 (the two columns are sections a heading key should reach), set as a label. */
.bc-compare-head {
  font-family: var(--font-mono); font-size: 11px; font-weight: 400; line-height: inherit;
  letter-spacing: 0.2em; text-transform: uppercase; color: var(--text-muted); margin-bottom: 14px;
}
.bc-flaws { padding-left: 20px; color: var(--text-sec); font-size: 15px; }
.bc-flaws li { margin-bottom: 6px; }
.bc-ours-text { color: var(--text-sec); margin: 0 0 14px; }
.bc-three { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; margin-top: 24px; }
.bc-three-item { background: var(--bg-surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 22px; }
.bc-three-item h3 { font-size: 17px; margin: 6px 0 8px; }
.bc-three-item p { color: var(--text-sec); font-size: 15px; }
.bc-three-item p.eyebrow { color: var(--text-muted); font-size: 11px; }
.bc-fan-wrap { display: grid; grid-template-columns: 300px 1fr; gap: 28px; align-items: center; }
.bc-fan {
  width: 100%; height: auto;
  background: var(--bg-raised); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 10px;
}
.bc-fan-text p { color: var(--text-sec); margin: 0 0 14px; }
.bc-two { display: grid; grid-template-columns: 1fr 1fr; gap: 26px; margin-bottom: 26px; }
.bc-two p { color: var(--text-sec); }
.bc-note {
  border: 1px solid var(--border); background: var(--bg-surface);
  padding: 18px 22px; border-radius: var(--radius); color: var(--text-sec); font-size: 15px;
}
.bc-note strong { color: var(--text); }
.bc-honest-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; }
.bc-honest-item { background: var(--bg-surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 20px 22px; }
.bc-honest-item h3 { font-size: 17px; margin: 0 0 8px; }
.bc-honest-item p { color: var(--text-sec); font-size: 15px; }
.bc-scorecard td.yes { color: var(--text); font-weight: 600; }
.bc-scorecard td.no { color: var(--text-muted); }
.bc-closing { font-size: 17px; }
@media (max-width: 860px) {
  .bc-compare, .bc-two, .bc-honest-grid, .bc-three, .bc-fan-wrap { grid-template-columns: 1fr; }
  /* Tables are the densest thing on the page — they scroll inside
     themselves rather than pushing the page sideways on a phone. */
  .bc-table-wide { display: block; overflow-x: auto; }
  .bc-table-wide td, .bc-table-wide th { min-width: 130px; }
}

/* ── Responsive ───────────────────────────────────────────────────────── */
@media (max-width: 720px) {
  /* The nav wraps to a second row rather than collapsing behind a hamburger.
     Four links and two buttons do not fit beside the logo at 390px — measured,
     they overflowed the viewport by 87px — and a drawer would mean shipping JS
     to a site that otherwise needs none. The <details> FAQ is the same choice.
     Verified at 390px in a real browser: no horizontal scroll on any page. */
  /* Not sticky here. Wrapped onto rows of links under the logo, a sticky nav
     would cover a large part of a phone screen (far more at 200% zoom) and
     whatever has keyboard focus under it. */
  .nav { position: static; }
  html { scroll-padding-top: 0; }
  .nav-inner { height: auto; flex-wrap: wrap; padding: 10px 16px 12px; gap: 10px; }
  .nav-links {
    width: 100%; gap: 10px 16px; justify-content: flex-start; flex-wrap: wrap; font-size: 13px;
  }
  .nav-links a { font-size: 13px; white-space: nowrap; }
  .nav-links .btn-sm { padding: 6px 12px; }
  .nav-links .nav-hide-sm { display: none; }
  .container { padding: 0 16px; }
  .hero { padding: 48px 0 36px; }
  .section { padding: 48px 0; }
}

/* S06: dark is the default and this site is deliberately single-theme — every
   screenshot, tutorial and marketing asset uses Shack Dark. The colours above
   are therefore stated unconditionally rather than behind a media query. */

/* ══ 2026-10-05 overhaul ════════════════════════════════════════════════
   Home, features, Elmer, accessibility, contact and the legal pages. Same
   tokens and rules as above: amber is interactive only, states carry a word,
   body text never drops below 16px except labels and fine print. */

/* ── Split: text beside a screenshot. If the screenshot is missing (see
   js/site.js) the figure is removed and the text takes the full width. ── */
.split { display: grid; gap: 40px; grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr); align-items: center; }
.split.flip > :first-child { order: 2; }
.split > :only-child { grid-column: 1 / -1; }
/* list-style: none makes Safari drop the list semantics, so VoiceOver stops
   saying "list, 5 items"; every ul.ticks carries role="list" to keep them. */
.ticks { list-style: none; display: flex; flex-direction: column; gap: 10px; margin-top: 18px; }
.ticks li { display: flex; gap: 10px; align-items: flex-start; color: var(--text-sec); }
.ticks li::before { content: '\25B8'; content: '\25B8' / ''; color: var(--accent); flex: none; }
.ticks li strong { color: var(--text); }

/* ── Screenshots ─────────────────────────────────────────────────────── */
.shot { margin: 0; }
.shot img {
  display: block; width: 100%; height: auto;
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--bg-raised);
}
.shot-wide { margin-top: 40px; }
/* Preview mode only (?shots=1): a labelled box where a screenshot will go. */
.shot-ph {
  border: 2px dashed var(--accent-deep); border-radius: var(--radius);
  background: var(--bg-raised); padding: 28px; min-height: 220px;
  display: flex; flex-direction: column; justify-content: center; gap: 8px;
}
.shot-ph strong { font-family: var(--font-mono); font-size: 13px; letter-spacing: 0.1em; color: var(--accent-lt); }
.shot-ph span { color: var(--text-sec); font-size: 15px; }

/* ── Integration grid ────────────────────────────────────────────────── */
.tools { display: grid; gap: 16px; grid-template-columns: repeat(auto-fit, minmax(290px, 1fr)); }
.tool { background: var(--bg-surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 20px; }
.tool h3 { font-family: var(--font-body); font-size: 17px; font-weight: 700; margin-bottom: 6px; }
.tool p { color: var(--text-sec); font-size: 15px; }
.tag {
  display: inline-block; font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--text); border: 1px solid rgba(255,255,255,0.22);
  border-radius: 999px; padding: 1px 9px; margin-left: 6px; vertical-align: 2px;
}
.fineprint { color: var(--text-muted); font-size: 14px; margin-top: 18px; max-width: 80ch; }

/* ── Audience cards ──────────────────────────────────────────────────── */
.card ul.ticks li { font-size: 15px; }
.card .more { display: inline-block; margin-top: 14px; font-weight: 600; }

/* ── Callout / CTA band ──────────────────────────────────────────────── */
.callout {
  background: var(--bg-surface); border: 1px solid var(--border); border-radius: var(--radius);
  padding: 32px; display: flex; flex-wrap: wrap; gap: 24px; align-items: center; justify-content: space-between;
}
.callout h2 { font-size: 26px; margin-bottom: 6px; }
.callout p { color: var(--text-sec); }

/* ── Long-form prose (Elmer, accessibility, legal) ───────────────────── */
.prose { max-width: 76ch; }
.prose h2 { font-size: 24px; margin: 44px 0 12px; }
.prose .eyebrow + h2 { margin-top: 8px; }
.prose h3 { font-family: var(--font-body); font-size: 18px; font-weight: 700; margin: 26px 0 8px; }
.prose p, .prose li { color: var(--text-sec); }
.prose p + p { margin-top: 12px; }
.prose ul, .prose ol { padding-left: 22px; margin: 10px 0 14px; display: flex; flex-direction: column; gap: 6px; }
.prose strong { color: var(--text); }
.prose .caps { text-transform: uppercase; font-size: 15px; }
.legal-meta { color: var(--text-muted); font-size: 14px; margin-top: 8px; }
.summary-box {
  background: var(--bg-surface); border: 1px solid var(--border); border-radius: var(--radius);
  padding: 22px 26px; margin: 28px 0;
}
.summary-box h2 { margin-top: 0; font-size: 20px; }
.toc { columns: 2; column-gap: 32px; padding-left: 20px; }
.toc li { break-inside: avoid; margin-bottom: 4px; }
.table-wrap { overflow-x: auto; margin: 14px 0 20px; }
.data-table { width: 100%; border-collapse: collapse; font-size: 15px; background: var(--bg-surface); }
.data-table caption { caption-side: top; text-align: left; color: var(--text-muted); font-size: 14px; padding-bottom: 8px; }
.data-table th, .data-table td { text-align: left; vertical-align: top; padding: 10px 12px; border-bottom: 1px solid var(--border); }
.data-table thead th {
  background: var(--bg-raised); color: var(--text-muted); font-family: var(--font-mono);
  font-size: 11px; letter-spacing: 0.16em; text-transform: uppercase; font-weight: 600;
}
.data-table td { color: var(--text-sec); }
.data-table td:first-child { color: var(--text); }

/* ── Contact form ────────────────────────────────────────────────────── */
.form { display: flex; flex-direction: column; gap: 18px; max-width: 560px; }
.field label { display: block; font-weight: 600; margin-bottom: 6px; }
.field .hint { display: block; color: var(--text-muted); font-size: 14px; margin-top: 4px; }
/* The border is what shows where a field is: its fill is one navy step off the
   page. At 0.22 white it was 2.6:1 against the page; 0.35 is 3.9:1 against the
   page and 3.0:1 against the fill (WCAG 1.4.11 asks 3:1). */
.field input, .field select, .field textarea {
  width: 100%; font: inherit; color: var(--text); background: var(--bg-raised);
  border: 1px solid rgba(255,255,255,0.35); border-radius: 8px; padding: 11px 13px; min-height: 44px;
}
.field textarea { min-height: 160px; resize: vertical; }
.field input:focus-visible, .field select:focus-visible, .field textarea:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 2px;
}
.field [aria-invalid="true"] { border-color: var(--poor); }
.field .error { color: var(--text); font-size: 14px; margin-top: 6px; display: flex; gap: 8px; }
.field .error::before { content: '!'; content: '!' / ''; flex: none; width: 18px; height: 18px; border-radius: 50%; background: var(--poor); color: #fff; font-weight: 700; font-size: 12px; display: inline-flex; align-items: center; justify-content: center; }
.field .error:empty { display: none; }
/* The honeypot: off-screen, out of the tab order and hidden from assistive
   technology, so only a bot that fills every field fills it. */
.hp { position: absolute; left: -10000px; width: 1px; height: 1px; overflow: hidden; }
.form-status { padding: 14px 16px; border-radius: 8px; border: 1px solid var(--border); background: var(--bg-surface); }
.form-status:empty { display: none; }
.form-status.ok { border-color: var(--good); }
.form-status.err { border-color: var(--poor); }
.btn[disabled], .btn[aria-disabled="true"] { opacity: 0.6; cursor: wait; }

@media (max-width: 860px) {
  .split { grid-template-columns: 1fr; gap: 28px; }
  .split.flip > :first-child { order: 0; }
  .toc { columns: 1; }
  .callout { padding: 24px; }
}
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }
