/* ============================================================================
   Docket — the promo page.
   ============================================================================

   ⚠️ THE PALETTE IS LIFTED VALUE-FOR-VALUE FROM THE APP, AND THAT IS THE POINT.
   Every hex below is copied from `web/src/app/globals.css`, where each one
   carries a measured contrast ratio in a comment and `npm run contrast` (79
   checks) re-measures all of it. Re-picking colours here would mean a second
   palette nobody has measured, on the page whose whole job is to look like the
   thing it is selling. If a token changes in the app, change it here; do not
   invent one.

   ⚠️ LIGHT ONLY, AND THAT IS A COMMITMENT RATHER THAN AN OMISSION.
   Decided 2026-09-08, on OB1's recorded rule — "one committed look beats two
   mediocre ones" (`OB1/landing/art/brain-spine-handoff.html` §03). It now has a
   second reason: **the screenshots are shot in the app's light theme**, so a
   dark ground would put five stone-coloured rectangles on a charcoal page.
   A theme switch here is no longer a stylesheet change, it is a re-shoot.

   ⚠️ NO SCRIPT, AND THE CSP SAYS SO. `vercel.json` sends
   `default-src 'none'; style-src 'self'; img-src 'self' data:`, which means no
   inline <style>, no inline style attribute, and no JavaScript at all. A rule
   written inline is silently dropped in production and works perfectly in local
   preview, where the dev server sends no CSP — so it fails in the one place
   nobody looks. ⚠️ It also means **there is no lightbox**. Carrel's page had one
   and it needed JavaScript; the screenshots here are shot zoomed so they are
   legible at the size they are actually drawn.

   ⚠️ NO WEBFONT FILES, SO NO `font-src` USE. The app self-hosts Archivo and IBM
   Plex Mono through `next/font`. Shipping those here would mean adding binary
   files to a directory whose selling point is that it has none. Archivo is named
   first in case a visitor has it; the rest is a system grotesque of similar
   width.

   ⚠️ THE PROSE MEASURE IS THE NUMBER TO TURN, AND IT HAS BEEN TURNED TWICE.
   The first version ran one column at ~1000px and read as a memo. The second
   capped it at 34rem beside a drawn mark. This one is 26rem, because the thing
   beside it is now a screenshot rather than a diagram and a screenshot needs the
   room more. Carrel's cards were 29rem — the same argument, reached separately.
   ========================================================================= */

:root {
  color-scheme: light;

  --bg: #f3f1ec;          /* stone — the ground under every surface */
  --card: #fbfaf7;        /* a zone lifted off it */
  --line: #e1ddd4;

  --ink: #23211d;         /* 14.24:1 on stone */
  --ink-dim: #5a554d;     /*  6.55:1 */
  --ink-faint: #6f6959;   /*  4.84:1 on stone · 5.24:1 on card */

  --accent: #1f3a5f;      /* 10.17:1 — links. Never a verdict */
  --good: #2f7a4a;        /*  4.65:1 */
  --bad: #87281a;         /*  7.92:1 */

  --good-wash: #2f7a4a1a;
  --bad-wash: #87281a1a;
  --flat-wash: #6f695914;

  --load-3: #8896ac;      /* the navy ramp — used here only for the § numbers */

  --measure: 26rem;
  --wrap: clamp(58rem, 92vw, 80rem);

  --font-sans: Archivo, "Helvetica Neue", Inter, ui-sans-serif, system-ui, "Segoe UI", sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, "Cascadia Mono", Menlo, monospace;
}

/* --------------------------------------------------------------------------
   Base
   -------------------------------------------------------------------------- */

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

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: clamp(1rem, 0.95rem + 0.25vw, 1.09rem);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 2px; }
a:hover { text-decoration-thickness: 2px; }

h1, h2 { line-height: 1.14; letter-spacing: -0.02em; font-weight: 600; margin: 0; }
h1 { font-size: clamp(2.3rem, 1.2rem + 4.4vw, 4.1rem); letter-spacing: -0.033em; }
h2 { font-size: clamp(1.45rem, 1.2rem + 1.1vw, 1.95rem); margin-bottom: 0.9rem; }

p { margin: 0 0 1rem; }
p:last-child { margin-bottom: 0; }
strong { font-weight: 600; color: var(--ink); }

.wrap {
  width: var(--wrap);
  max-width: calc(100% - 3rem);
  margin-inline: auto;
}

/* --------------------------------------------------------------------------
   Chrome
   -------------------------------------------------------------------------- */

.site-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  padding: 1.6rem 0 0;
}

/* ⚠️ THE NAME IS IN FIVE PLACES IN index.html. See landing/README.md. */
.wordmark { font-weight: 600; font-size: 1.06rem; letter-spacing: -0.02em; }

/* ⚠️ THE HEADER CARRIES NO CALL TO ACTION, AND THAT IS DELIBERATE AS OF
   2026-09-08. It used to hold a "Talk to us" link, which put two of them on
   the first screen — the header link and the hero button, ~450px apart, saying
   the same words and going to the same mailto. Two CTAs in one view do not
   double the asking; they make the reader work out whether they differ. The
   hero button is the one that survived, because it sits under the sentence
   that earns it. The footer's address is a third mention and is fine: it is a
   different act, at the end, for somebody who scrolled past the button. */

/* --------------------------------------------------------------------------
   Hero — words, no picture. Both OB1 pages opened this way with the first
   visual well below a 900px fold, and that position was measured.
   -------------------------------------------------------------------------- */

.hero { padding: clamp(4rem, 12vh, 8rem) 0 clamp(3.5rem, 9vh, 6rem); }
.hero h1 { max-width: 15ch; text-wrap: balance; }

.lede {
  margin-top: 1.5rem;
  max-width: 44ch;
  font-size: clamp(1.08rem, 1rem + 0.45vw, 1.28rem);
  line-height: 1.5;
  color: var(--ink-dim);
}

.hero-foot {
  margin-top: 2.2rem;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem 1.4rem;
}

.btn {
  display: inline-block;
  padding: 0.62rem 1.4rem;
  background: var(--ink);
  color: var(--bg);
  font-size: 0.95rem;
  font-weight: 500;
  text-decoration: none;
  border-radius: 2px;
}
.btn:hover { background: var(--accent); }
.btn-note { font-size: 0.86rem; color: var(--ink-faint); }

/* --------------------------------------------------------------------------
   The section grid — a short prose card, a big screenshot.

   ⚠️ THIS RATIO IS THE ONE THING CARRIED OVER FROM CARREL'S PAGE. Ten sections
   there, each a small block of prose beside a visual, prose capped near 29rem.
   The failure it fixes is a page where every section is the same rectangle of
   text — which is what this page was before, twice.
   -------------------------------------------------------------------------- */

.band {
  border-top: 1px solid var(--line);
  padding: clamp(3rem, 7vh, 5rem) 0;
}

.band-grid {
  display: grid;
  grid-template-columns: minmax(0, var(--measure)) minmax(0, 1fr);
  gap: clamp(2rem, 5vw, 4.5rem);
  align-items: start;
}

/* ⚠️ STICKY, WHICH IS THE ONLY MOTION ON A PAGE WITH NO JAVASCRIPT. The shot
   holds while its two sentences scroll past, and it costs two declarations. */
.art { position: sticky; top: 5rem; }

/* ⚠️ THE BORDER IS NOT DECORATION. The app's ground is --bg and so is this
   page's, so an unbordered screenshot bleeds into the page and the reader
   cannot tell where the product stops. */
.art img {
  width: 100%;
  height: auto;
  display: block;
  border: 1px solid var(--line);
  border-radius: 3px;
}

/* Numbered, in mono. The page argues in order; the number says where you are. */
.eyebrow {
  margin: 0 0 0.9rem;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.eyebrow .n { color: var(--load-3); margin-right: 0.75em; }

.fig-note {
  margin-top: 0.9rem;
  font-size: 0.85rem;
  line-height: 1.5;
  color: var(--ink-faint);
  max-width: 68ch;
}

/* --------------------------------------------------------------------------
   ⚠️ THE TWO PATTERN BREAKS, WHICH EXIST BECAUSE SIX IDENTICAL SECTIONS IS
   ITSELF A KIND OF BLANDNESS.

   Prose-left / picture-right is the right shape for a section that argues
   something. Repeated without exception it becomes a template the reader stops
   reading — the eye learns "text block, screenshot, text block, screenshot"
   and starts skipping. So the rhythm is broken twice on purpose:

     .band-center   no picture at all, centred — used by §01 (what this IS)
                    and by the three closing sections, which are claims and
                    admissions rather than features and have nothing to show.
     .pair          TWO screenshots side by side under one heading — used once,
                    mid-page, for the one argument that genuinely has two
                    halves (a thing goes in; the same thing comes back out).

   Neither is decoration. A third variant would be a fourth pattern, which is
   how a page stops having a pattern at all.
   -------------------------------------------------------------------------- */

.band-wide .head { max-width: 44rem; }
.band-wide .wide { margin-top: 1.8rem; }

/* ⚠️ THE CENTRED SECTIONS SPAN THE WRAP, AND THE CLOSING ONE DOES NOT.
   These were capped at 46rem, which left about 480px of empty ground on each
   side at a wide viewport — a narrow ribbon of text down the middle of a page
   whose picture sections run nearly edge to edge. They now take the full wrap,
   so the margin either side is just the wrap's own and the centred bands read
   as the same page as the ones above them.

   ⚠️ §10 IS THE DELIBERATE EXCEPTION and keeps the tight measure. It is the
   ask, it is four lines long, and a closing call to action that spans 1280px
   stops looking like an invitation and starts looking like a banner. Every
   other centred band is prose or a list that benefits from the room. */
.band-center { text-align: center; }
.band-center .head { max-width: none; margin-inline: auto; }

/* The list bands carry their own reading caps for the ranged-left case; inside
   a full-width centred band those caps are what would keep the ribbon. */
.band-center .facts li,
.band-center .status-row p { max-width: none; }

.band-center.cta .head { max-width: 46rem; }

/* Centred text shows its orphans. "...lands on a / page." is the failure —
   one word alone on the last line, dead centre, where ranged-left copy would
   have hidden it at the end of a rag. */
.band-center h2,
.band-center .head p { text-wrap: balance; }
.band-center h2 { margin-inline: auto; }

/* ⚠️ THE LEDE DROPS ITS OWN CAP HERE. `.lede` is 44ch, which is right in the
   hero where it sits under a 15ch headline and nothing follows it. Centred,
   with ordinary paragraphs beneath it at the head's full 46rem, a 44ch lede
   wraps two lines shorter than everything under it and the block reads as
   three different column widths stacked up. */
.band-center .lede { margin-inline: auto; max-width: none; }
.band-center .hero-foot { justify-content: center; }

/* ⚠️ THE BLOCK IS CENTRED; THE LIST ITEMS ARE NOT. Centring a five-item list
   of two-line facts gives every row a different left edge, so the eye has to
   find the start of each one — which is exactly the work a list exists to save.
   The column is centred on the page and the text inside it stays ranged left. */
.band-center .wide { max-width: none; margin-inline: auto; text-align: left; }

/* ⚠️ `stretch`, NOT `start`, AND THE CAPTIONS ARE WHY. The two captures are
   1476×812 and 1512×789 — near-identical framing, slightly different aspect
   ratios, because the browser window moved between shots. At equal widths that
   is a ~16px height difference, which is invisible on the images themselves and
   glaring on the two caption lines beneath them. Stretching the figures to the
   row height and pushing the captions down with `margin-top: auto` puts the two
   captions on one baseline whatever the pictures do. Re-shooting to identical
   dimensions would also fix it, and would break again the next time. */
.pair {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1.4rem;
  align-items: stretch;
  margin-top: 2rem;
}

.pair figure {
  margin: 0;
  display: flex;
  flex-direction: column;
  height: 100%;
}

.pair img {
  width: 100%;
  height: auto;
  display: block;
  border: 1px solid var(--line);
  border-radius: 3px;
}

.pair figcaption {
  margin-top: auto;      /* see the note above .pair — this is the alignment */
  padding-top: 0.7rem;
  font-size: 0.85rem;
  line-height: 1.5;
  color: var(--ink-faint);
}

.facts { margin: 0; padding: 0; list-style: none; }
.facts li {
  padding: 0.8rem 0;
  border-top: 1px solid var(--line);
  font-size: 0.95rem;
  line-height: 1.5;
  color: var(--ink-dim);
  max-width: 78ch;
}

.status-row {
  display: grid;
  grid-template-columns: 6.5rem minmax(0, 1fr);
  gap: 1.4rem;
  align-items: start;
  padding: 0.8rem 0;
  border-top: 1px solid var(--line);
}
.status-row p { font-size: 0.95rem; line-height: 1.5; color: var(--ink-dim); max-width: 72ch; }

.tag {
  justify-self: start;
  font-family: var(--font-mono);
  font-size: 0.68rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 0.24rem 0.5rem;
  border-radius: 2px;
}
.tag-built { color: var(--good); background: var(--good-wash); }
.tag-not   { color: var(--ink-faint); background: var(--flat-wash); }
.tag-no    { color: var(--bad); background: var(--bad-wash); }

/* --------------------------------------------------------------------------
   Close
   -------------------------------------------------------------------------- */

.cta { padding-bottom: clamp(3.5rem, 9vh, 6rem); }
.cta h2 { max-width: 16ch; font-size: clamp(1.8rem, 1.3rem + 2vw, 2.6rem); }

.site-foot {
  border-top: 1px solid var(--line);
  padding: 1.8rem 0 3rem;
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.5rem 1.5rem;
  font-size: 0.86rem;
  color: var(--ink-faint);
}
.site-foot p { margin: 0; }

/* --------------------------------------------------------------------------
   ⚠️ NARROW. The screenshot moves BELOW its prose rather than shrinking beside
   it. These are dense product screens; at 30% of a phone they are grey noise.
   Sticky is released too — a picture that follows you down a phone is in the way.
   -------------------------------------------------------------------------- */

@media (max-width: 62rem) {
  .band-grid { grid-template-columns: minmax(0, 1fr); gap: 1.8rem; }
  .art { position: static; }
  /* ⚠️ THE PAIR STACKS RATHER THAN HALVING. Two dense product screens at ~45%
     of a phone are two smudges; the pattern break is worth less than the
     pictures being readable, so on a narrow screen it simply becomes two. */
  .pair { grid-template-columns: minmax(0, 1fr); gap: 1.8rem; }
}

@media (max-width: 34rem) {
  .status-row { grid-template-columns: minmax(0, 1fr); gap: 0.4rem; }
  .site-head { padding-top: 1.1rem; }
}

@media (prefers-reduced-motion: reduce) {
  .art { position: static; }
}
