/* =============================================================
   DoveBoard — doveboard.com
   Shared chrome and the eight inner pages. No build step, no
   framework. The home page's seven-section sequence is in home.css.

   COLOUR COMES FROM tokens.css AND NOWHERE ELSE. There is not one hex
   value in this file, on purpose: tokens.css is the supplied brand file
   and every colour here is a var() into it. tools/verify.py fails the
   build if a hex literal appears in this file, which is also how
   "no leftover teal or gold" stays true without anyone remembering to
   check.

   Sections: 0 fonts · 1 site tokens · 2 base · 3 type · 4 layout
             5 nav · 6 buttons · 7 forms · 8 hero · 9 cards
             10 spine · 11 tour · 12 pricing · 13 details · 14 prose
             15 terminal · 16 footer · 17 the mark · 18 motion
             19 responsive
   ============================================================= */

/* ---------- 0. Fonts ----------
   Self-hosted, deliberately. A privacy-first product whose marketing
   site phones a font CDN on every page load is a broken promise, so
   these files are the only fonts and they come from this origin.

   Each family is ONE variable file per subset covering every weight the
   site uses. Bricolage ships without its optical-size axis: pinning it
   drops the latin file from 75 KB to 41 KB and renders identically at
   every size this site actually sets. The latin-ext faces are declared
   but only fetched if a visitor's text needs a character in that range.
   -------------------------------------------------------------- */
@font-face {
  font-family: "Bricolage Grotesque";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("../fonts/bricolage-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Bricolage Grotesque";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("../fonts/bricolage-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Instrument Sans";
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url("../fonts/instrument-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Instrument Sans";
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url("../fonts/instrument-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 400 500;
  font-display: swap;
  src: url("../fonts/jetbrains-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 400 500;
  font-display: swap;
  src: url("../fonts/jetbrains-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ---------- 1. Site tokens ----------
   Structure, type and motion only. Colours are tokens.css's job.

   THE SIGNATURE GRADIENT is assembled here from the four anchors by
   reference. BRAND.md fixes the stops at 0 / 38 / 72 / 100 and the
   sequence indigo -> plum -> rose -> coral; only the angle varies, so
   the angle is the argument and the stops never get retyped.
   -------------------------------------------------------------- */
:root {
  --font-display: "Bricolage Grotesque", "Segoe UI", system-ui, sans-serif;
  --font-body:    "Instrument Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-mono:    "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;

  --shell: 1180px;
  --pad: clamp(20px, 5vw, 40px);
  --band: clamp(76px, 9vw, 132px);
  --r-sm: 8px;
  --r: 14px;
  --r-lg: 20px;

  --ease: cubic-bezier(.22,.61,.36,1);
  --ease-in-out: cubic-bezier(.45,.05,.55,.95);

  /* Translucent surfaces. tokens.css has no alpha tokens — reported as a
     Wave 0 finding — so these are the palette's own bone and ink mixed
     with transparent rather than new colours invented to sit on top. */
  --hair: var(--db-border);
  --hair-soft: color-mix(in srgb, var(--db-border) 55%, transparent);
  --glass: color-mix(in srgb, var(--db-bone) 4%, transparent);
  --glass-2: color-mix(in srgb, var(--db-bone) 7%, transparent);
  --veil: color-mix(in srgb, var(--db-ink) 72%, transparent);

  --signature: linear-gradient(160deg,
    var(--db-indigo) 0%, var(--db-plum) 38%,
    var(--db-rose) 72%, var(--db-coral) 100%);
  --signature-x: linear-gradient(90deg,
    var(--db-indigo) 0%, var(--db-plum) 38%,
    var(--db-rose) 72%, var(--db-coral) 100%);
  --signature-y: linear-gradient(180deg,
    var(--db-indigo) 0%, var(--db-plum) 38%,
    var(--db-rose) 72%, var(--db-coral) 100%);
}

/* ---------- 2. Base ---------- */
*, *::before, *::after { box-sizing: border-box; }

html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
  background: var(--db-surface);
}

body {
  margin: 0;
  background: var(--db-surface);
  color: var(--db-text);
  font-family: var(--font-body);
  font-size: 17px;
  line-height: 1.62;
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
}

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

/* The UA's [hidden] rule loses to any class that sets display, and the
   pathway trail is display:flex — so it stayed on screen while hidden.
   One !important here beats scattering :not([hidden]) through the file. */
[hidden] { display: none !important; }

/* Focus: one visible ring everywhere, on a colour that is not the
   danger hue. Interactive UI is indigo regardless of lens (BRAND.md). */
:focus-visible {
  outline: 2px solid var(--db-primary);
  outline-offset: 3px;
  border-radius: 3px;
}
:focus:not(:focus-visible) { outline: none; }

::selection {
  background: color-mix(in srgb, var(--db-primary) 40%, transparent);
  color: var(--db-text);
}

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

.skip {
  position: absolute; left: 12px; top: -60px; z-index: 100;
  background: var(--db-primary-fill); color: var(--db-on-primary);
  padding: 10px 16px; border-radius: var(--r-sm);
  font: 500 14px/1 var(--font-mono); text-decoration: none;
  transition: top .18s var(--ease);
}
.skip:focus { top: 12px; }

/* The honeypot. Off screen rather than display:none, so a bot that
   filters on display still fills it in. */
.hp {
  position: absolute; left: -9999px; top: auto;
  width: 1px; height: 1px; overflow: hidden;
}

/* ---------- 3. Type ---------- */
h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 600;
  line-height: 1.08;
  letter-spacing: -.02em;
  margin: 0 0 .5em;
  text-wrap: balance;
}
h1 { font-size: clamp(38px, 6.4vw, 68px); letter-spacing: -.03em; }
h2 { font-size: clamp(28px, 4.2vw, 44px); }
h3 { font-size: clamp(19px, 2vw, 23px); letter-spacing: -.015em; }

p { margin: 0 0 1em; }
p:last-child { margin-bottom: 0; }

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

strong, b { font-weight: 600; color: var(--db-text); }

.eyebrow {
  font: 500 12px/1.4 var(--font-mono);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--db-text-muted);
  margin: 0 0 14px;
}

.lede {
  font-size: clamp(17px, 1.7vw, 20px);
  line-height: 1.58;
  color: var(--db-text-muted);
  max-width: 68ch;
}

.mono { font-family: var(--font-mono); font-size: .92em; }

/* Small labels that carry the business tone. Text-safe indigo, never an
   anchor value — BRAND.md's anchors fail AA under 24px. */
.tone-biz { color: var(--db-primary); }

.split-note {
  margin-top: 26px;
  font-size: 15px;
  color: var(--db-text-muted);
}

/* ---------- 4. Layout ---------- */
.shell {
  width: 100%;
  max-width: var(--shell);
  margin-inline: auto;
  padding-inline: var(--pad);
}

.band { padding-block: var(--band); position: relative; }
.band--tint { background: var(--db-surface-raised); }

/* A hairline between bands, in the signature sequence. Display use, no
   text over it — BRAND.md's rule for the gradient. */
.band--tint::before,
.band--tint::after {
  content: ""; position: absolute; inset-inline: 0; height: 1px;
  background: var(--signature-x);
  opacity: .5;
}
.band--tint::before { top: 0; }
.band--tint::after { bottom: 0; }

.section-head { max-width: 76ch; margin-bottom: clamp(34px, 4vw, 56px); }
.section-head--mid { margin-inline: auto; text-align: center; }
.section-head--mid .lede { margin-inline: auto; }

.grid-2, .grid-3, .grid-4 { display: grid; gap: clamp(14px, 1.6vw, 20px); }
.grid-2 { grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
.grid-3 { grid-template-columns: repeat(auto-fit, minmax(268px, 1fr)); }
.grid-4 { grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); }

.stack { display: grid; gap: 18px; }
.spacer { flex: 1 1 auto; }

/* ---------- 5. Nav ---------- */
.nav {
  position: sticky; top: 0; z-index: 40;
  background: color-mix(in srgb, var(--db-surface) 96%, transparent);
  border-bottom: 1px solid var(--hair-soft);
}
.nav-inner {
  display: flex; align-items: center; gap: 18px;
  min-height: 62px;
}

.brand {
  display: inline-flex; align-items: center; gap: 10px;
  text-decoration: none; color: var(--db-text);
  margin-right: auto;
}
.brand-name {
  font-family: var(--font-display);
  font-weight: 600; font-size: 19px; letter-spacing: -.02em;
}

.nav-links {
  display: flex; align-items: center; gap: clamp(10px, 1.6vw, 26px);
  list-style: none; margin: 0; padding: 0;
}
.nav-links a:not(.btn) {
  color: var(--db-text-muted); text-decoration: none;
  font-size: 15px;
}
.nav-links a:not(.btn):hover,
.nav-links a[aria-current="page"] { color: var(--db-text); }
.nav-links a[aria-current="page"] {
  text-decoration: underline;
  text-decoration-color: var(--db-primary);
  text-decoration-thickness: 2px;
  text-underline-offset: 5px;
}

.nav-toggle {
  display: none;
  width: 40px; height: 40px; padding: 0;
  background: none; border: 1px solid var(--hair); border-radius: var(--r-sm);
  cursor: pointer;
}
.nav-toggle span,
.nav-toggle span::before,
.nav-toggle span::after {
  display: block; width: 17px; height: 1.5px;
  background: var(--db-text); margin-inline: auto;
  position: relative;
}
.nav-toggle span::before,
.nav-toggle span::after {
  content: ""; position: absolute; left: 0;
}
.nav-toggle span::before { top: -5px; }
.nav-toggle span::after { top: 5px; }

/* ---------- 6. Buttons ----------
   Every control is indigo primary or plum secondary, in both lenses.
   Rose and coral never reach a button: both sit within ~25 degrees of
   the danger hue and would read as an error state. -------------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  gap: 8px;
  padding: 13px 22px;
  border: 1px solid transparent; border-radius: var(--r-sm);
  font: 500 15px/1 var(--font-body);
  text-decoration: none; cursor: pointer;
  transition: background-color .16s var(--ease), border-color .16s var(--ease),
              color .16s var(--ease), transform .16s var(--ease);
}
.btn:active { transform: translateY(1px); }

.btn--primary {
  background: var(--db-primary-fill); color: var(--db-on-primary);
  font-weight: 600;
}
.btn--primary:hover {
  background: color-mix(in srgb, var(--db-primary-fill) 84%, var(--db-bone));
  color: var(--db-on-primary);
}

.btn--secondary {
  background: var(--db-secondary-fill); color: var(--db-on-primary);
  font-weight: 600;
}
.btn--secondary:hover {
  background: color-mix(in srgb, var(--db-secondary-fill) 84%, var(--db-bone));
  color: var(--db-on-primary);
}

.btn--ghost {
  background: transparent; color: var(--db-text);
  border-color: var(--hair);
}
.btn--ghost:hover {
  border-color: var(--db-primary); color: var(--db-text);
  background: var(--glass);
}

.btn--sm { padding: 9px 15px; font-size: 14px; }
.btn--lg { padding: 15px 26px; font-size: 16px; width: 100%; }

/* ---------- 7. Forms ---------- */
.waitlist {
  display: flex; flex-wrap: wrap; gap: 10px;
  margin-top: 26px; max-width: 520px;
}
.waitlist input[type="email"] { flex: 1 1 240px; }

input[type="email"], input[type="text"], select, textarea {
  width: 100%;
  padding: 13px 15px;
  background: var(--db-surface-sunken);
  color: var(--db-text);
  border: 1px solid var(--hair);
  border-radius: var(--r-sm);
  font: 400 15px/1.4 var(--font-body);
}
input::placeholder, textarea::placeholder { color: var(--db-text-muted); }
input:focus, select:focus, textarea:focus {
  border-color: var(--db-primary);
}
textarea { min-height: 160px; resize: vertical; }
select {
  appearance: none;
  padding-right: 34px;
  cursor: pointer;
}

.field { display: grid; gap: 7px; }
.field > label {
  font: 500 12px/1.4 var(--font-mono);
  letter-spacing: .1em; text-transform: uppercase;
  color: var(--db-text-muted);
}

.form-msg {
  margin: 12px 0 0; min-height: 1.4em;
  font-size: 14px; color: var(--db-text-muted);
}
.form-msg[data-state="ok"] { color: var(--db-success); }
.form-msg[data-state="err"] { color: var(--db-danger); }

.hero-note {
  margin-top: 16px;
  font-size: 14px; color: var(--db-text-muted);
  max-width: 56ch;
}

/* ---------- 8. Hero (inner pages) ---------- */
.hero { padding-block: clamp(52px, 8vw, 108px) clamp(40px, 5vw, 72px); }
.hero-head { max-width: 78ch; }

/* ---------- 9. Cards, strips ---------- */
.card {
  padding: clamp(18px, 2vw, 26px);
  background: var(--glass);
  border: 1px solid var(--hair-soft);
  border-radius: var(--r);
}
.card h3 { margin-bottom: .45em; }
.card p { color: var(--db-text-muted); font-size: 15.5px; margin-bottom: 0; }
.card-k {
  font: 500 11px/1.4 var(--font-mono);
  letter-spacing: .13em; text-transform: uppercase;
  color: var(--db-text-muted);
  margin: 0 0 10px;
}

.strip {
  display: grid; gap: 1px;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  background: var(--hair-soft);
  border: 1px solid var(--hair-soft);
  border-radius: var(--r);
  overflow: hidden;
}
.strip > div { background: var(--db-surface); padding: 22px; }
.strip .k {
  font-family: var(--font-display); font-weight: 600; font-size: 18px;
  margin-bottom: 6px;
}
.strip .t { font-size: 14.5px; color: var(--db-text-muted); }

.hl {
  /* A highlighted string inside a terminal block, at 13px. Coral would
     be small text in a display colour and would read as an error into
     the bargain, so this is the text-safe secondary. */
  color: var(--db-secondary);
  font-weight: inherit;
}

/* ---------- 10. The spine ----------
   A drawn line down the page in the signature sequence. Three
   implementations, in this order: CSS scroll-driven animation where the
   browser has it, one custom property from JS where it does not, and a
   fully drawn path where neither happens. The default is DRAWN, so no
   path is ever left half-finished. ------------------------------ */
.spine-host { position: relative; }
.spine {
  position: absolute; inset: 0;
  pointer-events: none;
  z-index: 0;
  overflow: hidden;
}
.spine svg { width: 100%; height: 100%; display: block; }
.spine-line, .spine-glow {
  fill: none;
  stroke: url(#spine-grad);
  stroke-linecap: round;
}
.spine-line { stroke-width: 2; }
.spine-glow { stroke-width: 7; opacity: .16; }
.spine-node {
  fill: var(--db-plum);
  stroke: var(--db-surface);
  stroke-width: 3;
}
.spine-node--biz { fill: var(--db-indigo); }

.spine-host > *:not(.spine) { position: relative; z-index: 1; }

/* The draw. --draw defaults to 1: complete. The paths carry
   pathLength="1" in the markup, so dash units are fractions of the
   path and this arithmetic needs no measurement. */
.spine { --draw: 1; }
.spine-line, .spine-glow {
  stroke-dasharray: 1;
  stroke-dashoffset: calc(1 - var(--draw));
}
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .spine { animation: spine-draw linear both; animation-timeline: view();
             animation-range: cover 0% cover 96%; }
    @keyframes spine-draw { from { --draw: 0 } to { --draw: 1 } }
  }
}
@property --draw { syntax: "<number>"; inherits: true; initial-value: 1; }

/* ---------- 11. Tour rows (features) ---------- */
.tour {
  display: grid;
  grid-template-columns: minmax(0, 210px) minmax(0, 1fr);
  gap: clamp(16px, 3vw, 44px);
  padding-block: clamp(26px, 3vw, 40px);
  border-top: 1px solid var(--hair-soft);
}
.tour:first-child { border-top: 0; padding-top: 0; }
.tour-label {
  font: 500 12px/1.5 var(--font-mono);
  letter-spacing: .1em; text-transform: uppercase;
  color: var(--db-text-muted);
  padding-left: 14px;
  border-left: 2px solid var(--db-secondary);
  align-self: start;
}
.tour[data-lens="business"] .tour-label { border-left-color: var(--db-indigo); }
.tour p { color: var(--db-text-muted); }
.tour ul {
  list-style: none; margin: 18px 0 0; padding: 0;
  display: grid; gap: 7px;
  grid-template-columns: repeat(auto-fit, minmax(232px, 1fr));
}
.tour li {
  font: 400 13.5px/1.5 var(--font-mono);
  color: var(--db-text-muted);
  padding-left: 15px; position: relative;
}
.tour li::before {
  content: ""; position: absolute; left: 0; top: .62em;
  width: 5px; height: 5px; border-radius: 50%;
  background: var(--db-secondary);
}

/* ---------- 12. Pricing ---------- */
.price-toggle {
  display: inline-flex; gap: 2px; padding: 3px;
  background: var(--db-surface-sunken);
  border: 1px solid var(--hair); border-radius: 10px;
  margin-bottom: clamp(26px, 3vw, 40px);
}
.price-toggle label {
  padding: 9px 18px; border-radius: 7px; cursor: pointer;
  font: 500 14px/1 var(--font-body);
  color: var(--db-text-muted);
}
.price-toggle input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.price-toggle input:checked + label,
.price-toggle label:has(input:checked) {
  background: var(--db-primary-fill); color: var(--db-on-primary);
}
.price-toggle label:has(input:focus-visible) {
  outline: 2px solid var(--db-primary); outline-offset: 2px;
}

.price-grid {
  display: grid; gap: clamp(16px, 2vw, 24px);
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  align-items: start;
}
.plan {
  padding: clamp(22px, 2.4vw, 32px);
  background: var(--glass);
  border: 1px solid var(--hair);
  border-radius: var(--r-lg);
  position: relative;
}
.plan[data-best] { border-color: color-mix(in srgb, var(--db-primary) 55%, transparent); }
.plan-flag {
  position: absolute; top: -11px; left: clamp(22px, 2.4vw, 32px);
  padding: 4px 11px; border-radius: 20px;
  background: var(--db-primary-fill); color: var(--db-on-primary);
  font: 500 11px/1.5 var(--font-mono);
  letter-spacing: .1em; text-transform: uppercase;
}
.plan-name {
  font-family: var(--font-display); font-weight: 600;
  font-size: 22px; margin: 0 0 4px;
}
.plan-kind {
  font: 400 13px/1.5 var(--font-mono);
  color: var(--db-text-muted); margin: 0 0 18px;
}
.plan-price { display: flex; align-items: baseline; gap: 9px; margin: 0 0 14px; }
.plan-price > span:first-child {
  font-family: var(--font-display); font-weight: 600;
  font-size: clamp(34px, 4vw, 46px); letter-spacing: -.03em;
}
.plan-price .per { font-size: 14px; color: var(--db-text-muted); }
.plan-sub { font-size: 15px; color: var(--db-text-muted); }
.plan-feats {
  list-style: none; margin: 20px 0; padding: 0;
  display: grid; gap: 9px;
}
.plan-feats li {
  font-size: 15px; padding-left: 24px; position: relative;
  color: var(--db-text-muted);
}
.plan-feats li::before {
  content: ""; position: absolute; left: 4px; top: .52em;
  width: 9px; height: 5px;
  border-left: 1.5px solid var(--db-primary);
  border-bottom: 1.5px solid var(--db-primary);
  transform: rotate(-45deg);
}
.plan-feats li.off { color: var(--db-text-muted); opacity: .72; }
.plan-feats li.off::before {
  content: "—"; border: 0; transform: none;
  top: 0; left: 4px; width: auto; height: auto;
  color: var(--db-text-muted);
}
.plan-note { margin: 14px 0 0; font-size: 13px; color: var(--db-text-muted); }
.plan-note:empty { display: none; }

/* One billing mode on screen, driven by the radio. Where :has() is
   missing BOTH are shown, so a price is never hidden with no way to
   reveal it. */
.term-month { display: none; }
.term-once { display: block; }
@supports selector(:has(*)) {
  body:has(#term-month:checked) .term-once { display: none; }
  body:has(#term-month:checked) .term-month { display: block; }
}

.compare {
  width: 100%; border-collapse: collapse;
  font-size: 15px;
}
.compare th, .compare td {
  text-align: left; padding: 12px 14px;
  border-bottom: 1px solid var(--hair-soft);
}
.compare th { font: 500 12px/1.4 var(--font-mono); letter-spacing: .1em;
              text-transform: uppercase; color: var(--db-text-muted); }
.compare td { color: var(--db-text-muted); }
.compare .y { color: var(--db-success); }
.compare .n { color: var(--db-text-muted); }

/* ---------- 13. Details: FAQ and the space list ---------- */
.faq { display: grid; gap: 1px; background: var(--hair-soft);
       border: 1px solid var(--hair-soft); border-radius: var(--r);
       overflow: hidden; }
.faq details { background: var(--db-surface); }
.faq summary,
.spacelist summary {
  padding: 17px 20px; cursor: pointer;
  font-family: var(--font-display); font-weight: 600;
  font-size: 17px; letter-spacing: -.01em;
  list-style: none;
  display: flex; align-items: center; gap: 12px;
}
.faq summary::-webkit-details-marker,
.spacelist summary::-webkit-details-marker { display: none; }
.faq summary::after,
.spacelist summary::after {
  content: "+"; margin-left: auto;
  font: 400 20px/1 var(--font-mono); color: var(--db-primary);
}
.faq details[open] summary::after,
.spacelist[open] summary::after { content: "\2013"; }
.faq details > div { padding: 0 20px 20px; }
.faq details p { color: var(--db-text-muted); font-size: 15.5px; }

.spacelist {
  margin-top: 26px;
  border: 1px solid var(--hair-soft); border-radius: var(--r);
  background: var(--glass);
}
.spacelist-body {
  padding: 0 20px 20px;
  display: grid; gap: 12px;
  grid-template-columns: repeat(auto-fit, minmax(290px, 1fr));
}
.spacelist-body > div { font-size: 14.5px; color: var(--db-text-muted); }
.spacelist-body b {
  display: block; color: var(--db-text);
  font-family: var(--font-display); font-size: 15px; margin-bottom: 2px;
}

/* ---------- 14. Prose (about, privacy, terms) ---------- */
.prose { max-width: 74ch; }
.prose h2 { margin-top: 1.9em; font-size: clamp(23px, 2.6vw, 30px); }
.prose h2:first-child { margin-top: 0; }
.prose h3 { margin-top: 1.6em; }
.prose p, .prose li { color: var(--db-text-muted); }
.prose ul, .prose ol { padding-left: 22px; display: grid; gap: 8px; margin: 0 0 1em; }
.prose li::marker { color: var(--db-secondary); }

/* ---------- 15. Terminal blocks ---------- */
.term {
  background: var(--db-surface-sunken);
  border: 1px solid var(--hair);
  border-radius: var(--r);
  overflow: hidden;
}
.term-bar, .qm-head {
  display: flex; align-items: center; gap: 8px;
  padding: 11px 15px;
  border-bottom: 1px solid var(--hair-soft);
  font: 400 12.5px/1 var(--font-mono);
  color: var(--db-text-muted);
}
.term-bar .right, .qm-head .right { margin-left: auto; }
.dot {
  width: 9px; height: 9px; border-radius: 50%;
  background: var(--hair);
}
.dot:first-child { background: color-mix(in srgb, var(--db-plum) 70%, transparent); }

.term pre, .own-manifest {
  margin: 0; padding: 18px 15px;
  overflow-x: auto;
  font: 400 13px/1.75 var(--font-mono);
  color: var(--db-text);
  tab-size: 2;
}
.term pre .c, .own-manifest .c { color: var(--db-text-muted); }
.term pre .p { color: var(--db-secondary); }
.term pre .o { color: var(--db-primary); }
.term pre .n, .own-manifest .n { color: var(--db-text); }
.term pre .k, .own-manifest .k { color: var(--db-primary); }

/* ---------- 16. Footer ---------- */
.foot {
  border-top: 1px solid var(--hair-soft);
  padding-block: clamp(40px, 5vw, 66px) 30px;
  background: var(--db-surface-sunken);
}
.foot-top {
  display: grid; gap: clamp(24px, 3vw, 44px);
  grid-template-columns: minmax(260px, 1.6fr) repeat(auto-fit, minmax(130px, 1fr));
  margin-bottom: 34px;
}
.foot .brand { margin-right: 0; }
.foot-blurb, .foot-parent {
  font-size: 14.5px; color: var(--db-text-muted); max-width: 44ch;
}
.foot-parent { font-size: 13.5px; }
.foot-h {
  font: 500 11px/1.4 var(--font-mono);
  letter-spacing: .13em; text-transform: uppercase;
  color: var(--db-text-muted); margin: 0 0 14px;
}
.foot nav ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 9px; }
.foot nav a { color: var(--db-text-muted); text-decoration: none; font-size: 15px; }
.foot nav a:hover { color: var(--db-text); }
.foot-base {
  display: flex; flex-wrap: wrap; align-items: center; gap: 14px;
  padding-top: 22px; border-top: 1px solid var(--hair-soft);
  font: 400 13px/1.5 var(--font-mono); color: var(--db-text-muted);
}

/* ---------- 17. The mark ----------
   THE HELPER. BRAND.md: below 32px the standard mark's neck narrows
   until the tail visually detaches, so mark-compact.svg exists for
   small sizes. tools/mark.py measures that neck at 3.16 units either
   side of the axis, which is under half a device pixel at 26px.

   Rather than leave that to whoever writes the next page, .mark--auto
   carries both files and a container query picks: the container's own
   inline size is the size the mark is drawn at, so the swap happens on
   the real rendered width and needs no script. Both files are 358
   bytes and cached for a year, so carrying the pair costs nothing that
   matters.

   The other files are picked by context at author time:
     mark.svg           inherits currentColor — the default
     mark-ink.svg       on light
     mark-bone.svg      on dark
     mark-indigo.svg    when the mark carries brand colour
     mark-gradient.svg  large display only
   Clear space is 25% of mark height, which is what --mark-clear is.
   -------------------------------------------------------------- */
.mark {
  display: block;
  aspect-ratio: 296 / 302;   /* never distorted */
  height: auto;
}

/* WHY A MASK AND NOT <img>. mark.svg and mark-compact.svg are filled
   with `currentColor`, which is the whole point of them — BRAND.md calls
   mark.svg "the default choice" because it inherits text colour. An
   <img> cannot do that: the SVG loads as its own document, inherits
   nothing, and currentColor resolves to black. On this near-black page
   that is an invisible logo, and it is exactly what happened first.

   Used as a mask the supplied file is untouched — only its alpha is
   read — and the colour comes from currentColor after all, so the mark
   in the nav and the footer is the same bone as the wordmark beside it
   and would follow a theme change without another file. */
.mark--auto {
  container-type: inline-size;
  display: inline-block;
  line-height: 0;
  width: 26px;
}
.mark-swap {
  display: block;
  aspect-ratio: 296 / 302;
  background: currentColor;
  mask: url("../img/mark.svg") center / contain no-repeat;
  -webkit-mask: url("../img/mark.svg") center / contain no-repeat;
}
/* Below 32px the standard mark's neck narrows to about 3.2 units either
   side of the axis — under half a device pixel at this size — and the
   tail visually detaches. tools/mark.py measures it. */
@container (max-width: 31.98px) {
  .mark-swap {
    mask-image: url("../img/mark-compact.svg");
    -webkit-mask-image: url("../img/mark-compact.svg");
  }
}

.mark--clear { padding: 25%; }   /* the clear-space rule, as a box */

/* ---------- 18. Motion ----------
   Reveals are an enhancement over a document that is already complete.
   The stylesheet has NO hidden state until site.js removes `no-js`,
   and it does that only after marking what is already on screen — so
   the page never flashes its own content away. There is no timer
   anywhere in the path: a reveal is either observed in, or it was
   never hidden. ------------------------------------------------- */
@media (prefers-reduced-motion: no-preference) {
  html:not(.no-js) .reveal {
    opacity: 0;
    transform: translateY(14px);
    transition: opacity .6s var(--ease), transform .6s var(--ease);
  }
  html:not(.no-js) .reveal.is-in {
    opacity: 1;
    transform: none;
  }
  html:not(.no-js) .stagger.is-in > * {
    animation: rise .55s var(--ease) both;
    animation-delay: calc(var(--i, 0) * 60ms);
  }
  @keyframes rise {
    from { opacity: 0; transform: translateY(12px); }
    to   { opacity: 1; transform: none; }
  }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
}

/* ---------- 19. Responsive ---------- */
@media (max-width: 820px) {
  .nav-toggle { display: block; order: 3; }
  .nav-links {
    display: none;
    order: 4; flex-basis: 100%;
    flex-direction: column; align-items: stretch;
    gap: 4px; padding-bottom: 14px;
  }
  .nav-links.is-open { display: flex; }
  .nav-links a:not(.btn) { display: block; padding: 11px 2px; }
  .nav-links .btn { margin-top: 8px; }

  .tour { grid-template-columns: 1fr; gap: 14px; }
  .tour-label { border-left: 0; border-top: 2px solid var(--db-secondary);
                padding: 12px 0 0; }
  .tour[data-lens="business"] .tour-label { border-top-color: var(--db-indigo); }
}

@media (max-width: 560px) {
  body { font-size: 16.5px; }
  .foot-top { grid-template-columns: 1fr 1fr; }
  .foot-top > div:first-child { grid-column: 1 / -1; }
}
