/* Hand-written, no dependencies. Dark only, by request: one accent, system fonts, no decoration. */

:root {
  --bg: #0c1014;
  --bg-soft: #121820;
  --ink: #e7edf3;
  --ink-soft: #98a5b2;
  --ink-dim: #6b7885;
  --line: #1e2731;
  --accent: #71b7ff;
  --warn: #e3b341;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
  --sans: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
}

* { box-sizing: border-box; }

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

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 17px;
  line-height: 1.7;
  -webkit-font-smoothing: antialiased;
}

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

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

/* ---------- nav ---------- */

.topnav { border-bottom: 1px solid var(--line); background: var(--bg-soft); }

.topnav ul {
  list-style: none;
  margin: 0 auto;
  padding: 0.9rem 1.5rem;
  max-width: 54rem;
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1.1rem;
  font-size: 0.85rem;
}

.topnav a { color: var(--ink-soft); text-decoration: none; }
.topnav a:hover { color: var(--ink); }
.topnav a[aria-current="page"] { color: var(--accent); }

/* ---------- layout ---------- */

.wrap, main, .page-head { max-width: 54rem; margin: 0 auto; }

main { padding: 3rem 1.5rem 4rem; }
.page-head { padding: 3.5rem 1.5rem 0; }

section { margin: 0 0 3.5rem; }

blockquote {
  margin: 0 0 1.8rem;
  padding: 0.2rem 0 0.2rem 1.1rem;
  border-left: 2px solid var(--line);
}
blockquote p { margin: 0; color: var(--ink-soft); }
blockquote footer { margin-top: 0.7rem; font-size: 0.85rem; color: var(--ink-dim); font-style: normal; }

/* ---------- type ---------- */

h1 {
  font-size: clamp(1.6rem, 4.5vw, 2.1rem);
  line-height: 1.2;
  letter-spacing: -0.02em;
  font-weight: 650;
  margin: 0 0 1rem;
}

h2 { font-size: 1.2rem; line-height: 1.3; font-weight: 650; margin: 0 0 1rem; }

h3 { font-size: 1rem; font-weight: 650; margin: 1.6rem 0 0.5rem; }

p { margin: 0 0 1.2rem; }

.eyebrow {
  margin: 0 0 0.9rem;
  font-size: 0.72rem;
  font-weight: 650;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-dim);
}

.lede { font-size: 1.12rem; line-height: 1.6; color: var(--ink-soft); margin: 0 0 1.3rem; }

.small, .meta { font-size: 0.86rem; line-height: 1.6; color: var(--ink-dim); }

ul, ol { padding-left: 1.2rem; }
li { margin: 0 0 0.55rem; }
li:last-child { margin-bottom: 0; }

strong { font-weight: 650; }

/* ---------- code ---------- */

code { font-family: var(--mono); font-size: 0.88em; }

pre {
  margin: 0 0 1.4rem;
  padding: 1rem 1.1rem;
  background: var(--bg-soft);
  border: 1px solid var(--line);
  border-radius: 8px;
  overflow-x: auto;
  font-size: 0.8rem;
  line-height: 1.6;
  color: var(--ink-soft);
}

pre code { font-size: 1em; }

/* ---------- figures ---------- */

/* Figures sit inside the 54rem measure, capped so a tall one cannot fill the viewport. A click
   opens the full-resolution file over the page (lightbox below), so inline size only has to read. */
figure.shot { margin: 2rem 0; }

figure.shot img,
figure.shot svg {
  display: block;
  max-width: 100%;
  /* A portrait diagram at the full column width renders thousands of pixels tall. max-height with
     width:auto scales the width down with the ratio instead of squashing the box. */
  max-height: 30rem;
  width: auto;
  height: auto;
  margin: 0 auto;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--bg-soft);
}

/* The phone screenshot keeps a smaller measure than the diagrams: even capped, a 1008x2008
   portrait shot is the tallest thing on any page. Sized on the figure so the caption matches it. */
figure.shot.narrow {
  width: 18rem;
  max-width: 100%;
  margin-inline: auto;
}

/* Block, because the image inside it is block-level and an inline box around a block splits into
   two fragments. zoom-in because it is a click target, which is the whole affordance here. */
a.zoom {
  display: block;
  cursor: zoom-in;
}

figcaption {
  margin: 0.7rem 0 0;
  font-size: 0.84rem;
  line-height: 1.55;
  color: var(--ink-dim);
}

figcaption strong { color: var(--ink-soft); }

/* A placeholder for a screenshot nobody has captured yet. Deliberately loud: it should be
   obvious at a glance which figures are still outstanding, so the page cannot quietly ship with
   three empty boxes that read as design. */
.shot-pending {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  min-height: 9rem;
  padding: 2rem 1.5rem;
  border: 1px dashed var(--warn);
  border-radius: 8px;
  background: var(--bg-soft);
  text-align: center;
}

.shot-pending .todo {
  font-size: 0.72rem;
  font-weight: 650;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--warn);
}

.shot-pending .path { font-size: 0.82rem; color: var(--ink-dim); }
.shot-pending .hint { font-size: 0.86rem; color: var(--ink-soft); max-width: 34rem; }

/* ---------- lightbox ---------- */

/* Click a zoomable figure to open it full size over the page; click away, or press Escape, to
   close. Native dialog rather than a div and a keydown handler: showModal brings the top layer, a
   focus trap and Escape handling with it, which is most of the accessibility work for a dozen
   lines, and ::backdrop needs no positioning to sit under the page. The box is the full viewport
   rather than a panel, so a click anywhere that is not the image closes it - a backdrop click
   reports the dialog itself as its target, which is what the handler in lightbox.js tests for.
   The dvh lines are the same declaration with the mobile URL bar accounted for, which vh is not;
   a browser that has never heard of dvh keeps the vh line and scrolls instead of clipping. */
.lightbox {
  width: 100vw;
  max-width: 100vw;
  height: 100vh;
  height: 100dvh;
  max-height: 100vh;
  max-height: 100dvh;
  margin: 0;
  padding: 2rem;
  border: 0;
  background: transparent;
  overflow: auto;
}

.lightbox[open] {
  display: grid;
  place-items: center;
}

.lightbox::backdrop { background: rgba(4, 7, 10, 0.92); }

.lightbox img {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  border-radius: 8px;
  box-shadow: 0 1.5rem 4rem rgba(0, 0, 0, 0.6);
}

.lightbox-close {
  position: fixed;
  top: 0.9rem;
  right: 0.9rem;
  padding: 0.4rem 0.7rem;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--bg-soft);
  color: var(--ink-soft);
  font: inherit;
  font-size: 0.78rem;
  cursor: pointer;
}

.lightbox-close:hover { color: var(--ink); }

/* ---------- callout ---------- */

.note { margin: 1.8rem 0; padding: 0 0 0 1.1rem; border-left: 2px solid var(--accent); }
.note p:last-child { margin-bottom: 0; }

.note .label {
  display: block;
  margin: 0 0 0.45rem;
  font-size: 0.72rem;
  font-weight: 650;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent);
}

/* ---------- cards ---------- */

.cards { display: grid; gap: 1.6rem; margin: 1.8rem 0 0; }
.card h3 { margin: 0 0 0.35rem; }
.card p { margin: 0; color: var(--ink-soft); font-size: 0.94rem; }

/* ---------- table ---------- */

table { width: 100%; margin: 0 0 1.4rem; border-collapse: collapse; font-size: 0.9rem; }

th, td {
  text-align: left;
  padding: 0.65rem 1rem 0.65rem 0;
  border-bottom: 1px solid var(--line);
  vertical-align: top;
}

th {
  font-size: 0.72rem;
  font-weight: 650;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-dim);
}

/* ---------- footer ---------- */

footer { border-top: 1px solid var(--line); padding: 1.8rem 0 3.5rem; font-size: 0.86rem; color: var(--ink-dim); }
footer .wrap { padding: 0 1.5rem; }
footer p { margin: 0; }

@media (min-width: 700px) {
  .cards { grid-template-columns: 1fr 1fr; }
  .page-head { padding-top: 4.5rem; }
}

@media (min-width: 76rem) {
  /* Fixed measure at desktop width; figures no longer break out of it. */
  main { width: 54rem; }
}

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
}
