/* base.css — tokens, reset, typography.
 *
 * The :root block between the markers is GENERATED by tools/palette.mjs and
 * written here by tools/build.mjs. Editing a hex in place is caught: the
 * validator recomputes the whole block and diffs it.
 */

/* PALETTE:BEGIN */
:root {
  --paper: #E7F8F3;
  --ground: #D2E2DE;
  --sink: #C0D0CC;
  --deep: #1D332E;
  --on-deep: #AEBFBA;
  --ink: #05110F;
  --ink2: #303E3A;
  --faint: #4B5A57;
  --rule: #6B7472;
  --open-lift: #D17C99;
  --gas-lift: #A189D4;
  --seal-lift: #CB864E;
  --open: #8B3D5B;
  --gas: #634A90;
  --seal: #864700;
  --d0: #B8EBDE;
  --d1: #95C7BA;
  --d2: #73A498;
  --d3: #538277;
  --d4: #336258;
  --d5: #12443A;
  --d6: #00261F;
}
/* PALETTE:END */

:root {
  /* Newsreader is the DISPLAY face, not the body face. A serif at reading
     size makes a document; a serif at headline size with an italic accent
     clause makes a product. The reference site is the second thing and so
     is this one. */
  --font-display: 'Newsreader', ui-serif, Georgia, 'Times New Roman', serif;
  --font-body: 'Instrument Sans', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font-mono: 'IBM Plex Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace;

  /* One ratio, applied. 1.5 at the base, and the scale is powers of it
     rounded to the nearest 0.5px at 16px root so nothing lands on a
     half-pixel that a hairline has to share. */
  --s0: 0.25rem; --s1: 0.5rem; --s2: 0.75rem; --s3: 1rem;
  --s4: 1.5rem; --s5: 2.25rem; --s6: 3.375rem; --s7: 5rem; --s8: 7.5rem;

  --shell: 76rem;
  --measure: 40rem;          /* body text never gets wider than this */
  --hair: 1px;
  --radius: 14px;
  --radius-sm: 10px;
  --pill: 999px;

  --lift-1: 0 1px 2px rgba(5, 17, 15, 0.04);
  --lift-2: 0 2px 4px rgba(5, 17, 15, 0.05), 0 18px 40px -22px rgba(5, 17, 15, 0.30);
  --lift-3: 0 2px 6px rgba(5, 17, 15, 0.06), 0 30px 70px -30px rgba(5, 17, 15, 0.38);
}

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 5rem;
}
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important; animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

body {
  background: var(--ground);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 1.0313rem;
  line-height: 1.6;
  letter-spacing: -0.003em;
  font-optical-sizing: auto;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img, svg, canvas { display: block; max-width: 100%; }
svg { fill: currentColor; }

h1, h2, h3 {
  font-family: var(--font-display);
  font-weight: 500;
  line-height: 1.04;
  letter-spacing: -0.02em;
  text-wrap: balance;
  font-optical-sizing: auto;
}
/* The accent clause. Italic, in the complement, and it is the one place the
   display face is allowed to raise its voice. */
h1 em, h2 em, h3 em { font-style: italic; color: var(--open); }
h1 { font-size: clamp(2.85rem, 1.6rem + 4.6vw, 5rem); letter-spacing: -0.028em; }
h2 { font-size: clamp(2.05rem, 1.3rem + 2.6vw, 3.05rem); letter-spacing: -0.024em; }
h3 { font-size: 1.35rem; letter-spacing: -0.014em; line-height: 1.18; }
h4 {
  font-family: var(--font-body); font-size: 0.94rem; font-weight: 600;
  letter-spacing: -0.004em; line-height: 1.3;
}

p, li { text-wrap: pretty; }
p + p { margin-top: var(--s3); }

a { color: inherit; text-decoration-color: color-mix(in oklab, currentColor 32%, transparent); text-underline-offset: 0.2em; text-decoration-thickness: 1px; }
a:hover { text-decoration-color: currentColor; }

b, strong { font-weight: 600; }
em { font-style: italic; }

code, kbd, samp, .num {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'zero' 1;
}
code {
  font-size: 0.85em;
  background: color-mix(in oklab, var(--sink) 70%, transparent);
  padding: 0.1em 0.34em;
  border-radius: var(--radius);
}

hr { border: 0; border-top: var(--hair) solid var(--rule); margin: var(--s5) 0; }

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

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--ink); color: var(--paper); padding: var(--s2) var(--s3);
  font-family: var(--font-display); font-size: 0.9rem;
}
.skip:focus { left: var(--s3); top: var(--s3); }

.shell { width: min(100% - 3rem, var(--shell)); margin-inline: auto; }
@media (max-width: 40rem) { .shell { width: min(100% - 1.75rem, var(--shell)); } }

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

/* Reveal-on-scroll is scoped to .js and set by an inline script in <head>.
   Unscoped, this rule hides the entire document from anyone without
   JavaScript — which is exactly what happened to a sibling. */
.js [data-reveal] { opacity: 0; transform: translateY(9px); }
.js [data-reveal].seen {
  opacity: 1; transform: none;
  transition: opacity 0.5s cubic-bezier(0.2, 0.7, 0.3, 1), transform 0.5s cubic-bezier(0.2, 0.7, 0.3, 1);
}
@media (prefers-reduced-motion: reduce) {
  .js [data-reveal] { opacity: 1; transform: none; }
}
