/* ==========================================================================
   base.css — tokens, reset, type.

   THE COLOURS BETWEEN THE MARKERS ARE GENERATED. tools/palette.mjs solves
   every one of them and tools/build.mjs pastes them in; validate.mjs
   recomputes the palette and fails the build if a single hex here has been
   edited by hand.

   THREE SURFACES AND NO MORE. The page ground sits at the lightness where
   the best contrast available going up equals the best going down, which is
   4.6:1 in either direction — under AAA, so BODY TEXT NEVER SITS ON IT. Text
   lives on a plate: `--sheet` (light) or `--night` (dark). The ink on the
   sheet IS the night colour and the lume on the night IS the sheet colour,
   the same two hexes, which is why there are three surfaces rather than six.
   ========================================================================== */

/* PALETTE:BEGIN */
:root {
  --page: #C1D9C7;
  --sheet: #E3F1E7;
  --sheet-hi: #F5FCF7;
  --night: #223227;
  --night-lo: #142418;
  --ink: #425347;
  --ink-2: #516356;
  --ink-3: #5E7063;
  --lume: #B5BDB7;
  --lume-2: #A0A8A2;
  --lume-3: #8F9791;
  --on-page: #555D57;
  --rule: #B6C4BA;
  --rule-night: #48544B;
  --rule-page: #A3B0A6;
  --acc: #007C40;
  --acc-2: #505FB3;
  --acc-3: #A64531;
  --acc-n: #28B767;
  --acc-n-2: #7A90FF;
  --acc-n-3: #EE6E54;
}
/* PALETTE:END */

:root {
  --shell: 76rem;
  --gutter: clamp(1.15rem, 4vw, 2.5rem);
  --radius: 14px;
  --radius-sm: 8px;
  /* Generous rounding is most of the difference between a product page and
     a paper. */
  --radius-lg: 22px;
  --radius-xl: 30px;
  --hair: 1px;

  --display: 'Fraunces', 'Iowan Old Style', Georgia, serif;
  --body: 'Archivo', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;
  --mono: 'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, monospace;

  --step--1: clamp(0.78rem, 0.76rem + 0.1vw, 0.84rem);
  --step-0: clamp(0.98rem, 0.95rem + 0.16vw, 1.08rem);
  --step-1: clamp(1.16rem, 1.09rem + 0.34vw, 1.36rem);
  --step-2: clamp(1.4rem, 1.26rem + 0.66vw, 1.8rem);
  --step-3: clamp(1.75rem, 1.48rem + 1.3vw, 2.6rem);
  --step-4: clamp(2.2rem, 1.6rem + 2.9vw, 4.2rem);

  --lede: 1.62;
  --tight: 1.18;
}

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

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--page);
  color: var(--on-page);
  font-family: var(--body);
  font-size: var(--step-0);
  line-height: var(--lede);
  font-variant-numeric: tabular-nums;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 {
  font-family: var(--display);
  font-weight: 460;
  line-height: var(--tight);
  letter-spacing: -0.012em;
  margin: 0 0 0.55em;
  text-wrap: balance;
}
h1 { font-size: var(--step-4); font-weight: 420; }
h2 { font-size: var(--step-3); }
h3 { font-size: var(--step-1); font-family: var(--body); font-weight: 620; letter-spacing: 0; }
h4 { font-size: var(--step-0); font-family: var(--body); font-weight: 640; letter-spacing: 0; }
p { margin: 0 0 1em; text-wrap: pretty; }
em { font-style: italic; }
b, strong { font-weight: 640; }
code, kbd, samp { font-family: var(--mono); font-size: 0.9em; }
a { color: inherit; }
img, svg, canvas { max-width: 100%; }
hr { border: 0; border-top: var(--hair) solid var(--rule); margin: 2.4rem 0; }

.shell { width: 100%; max-width: var(--shell); margin-inline: auto; padding-inline: var(--gutter); }
.narrow { max-width: 46rem; }

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--sheet); color: var(--ink);
  padding: 0.7rem 1rem; border-radius: 0 0 var(--radius-sm) 0;
}
.skip:focus { left: 0; }

:where(a, button, summary, input, [tabindex]):focus-visible {
  outline: 2px solid var(--acc-2);
  outline-offset: 3px;
  border-radius: 3px;
}

/* Everything that animates in on scroll is scoped to .js, set by an inline
   script before any stylesheet. A sibling shipped the opposite and its pages
   were 37 invisible elements without script. */
.js [data-reveal] { opacity: 0; transform: translateY(10px); }
.js [data-reveal].seen { opacity: 1; transform: none; transition: opacity 620ms ease, transform 620ms cubic-bezier(.2,.7,.3,1); }
@media (prefers-reduced-motion: reduce) {
  .js [data-reveal] { opacity: 1; transform: none; transition: none; }
}
