*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; scroll-padding-top: calc(var(--topbar-h) + 12px); }
body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-display);
  font-size: var(--step-0);
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}
h1, h2, h3, p { margin: 0; }
a { color: inherit; }
img { max-width: 100%; display: block; }
::selection { background: var(--accent); color: var(--accent-ink); }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

.wrap { max-width: var(--max); margin-inline: auto; padding-inline: var(--gutter); }
.mono { font-family: var(--font-mono); font-size: var(--step--1); letter-spacing: 0.06em; text-transform: uppercase; }
.dim { color: var(--ink-dim); }
.boot { padding: 30vh var(--gutter); font-family: var(--font-mono); color: var(--ink-dim); }

/* Scroll-reveal: main.js adds .reveal to content blocks, then .is-in once
   they cross into view. Everything is visible-by-default so JS failing
   never hides content. */
.reveal { opacity: 0; transform: translateY(22px); transition: opacity var(--dur) var(--ease-flow), transform var(--dur) var(--ease-flow); transition-delay: var(--rd, 0ms); }
.reveal.is-in { opacity: 1; transform: translateY(0); }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .reveal { opacity: 1; transform: none; transition: none; }
  * { animation: none !important; }
}
