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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* The header is fixed and 66px tall, so an anchor jump that puts the target at
     y=0 puts it behind the bar. The browser subtracts this before landing.
     82 is the bar plus a little air, so /#coverage arrives with its eyebrow
     clear of the header rather than eleven pixels under it. */
  scroll-padding-top: 82px;
}

html.reduced-motion {
  scroll-behavior: auto;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-sans);
  font-size: var(--text-base);
  line-height: var(--leading-normal);
  letter-spacing: var(--tracking-default);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

h1,
h2,
h3,
h4 {
  margin: 0;
  font-weight: 400;
  letter-spacing: var(--tracking-tight);
  line-height: var(--leading-tight);
  text-wrap: balance;
}

p {
  margin: 0;
  text-wrap: pretty;
}

a {
  color: inherit;
  text-decoration: none;
}

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

button {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  cursor: pointer;
}

input,
textarea,
select {
  font: inherit;
  color: inherit;
}

::selection {
  background: var(--brand);
  color: #04070c;
}

:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 3px;
  border-radius: 1px;
}

/* Off-screen until focused, so the first Tab on any page can jump the six nav
   stops instead of walking them again on every route. Positioned, not
   display:none — a hidden element cannot be tabbed to. */
.skip-link {
  position: fixed;
  top: 10px;
  left: 10px;
  z-index: 200;
  transform: translateY(-200%);
  padding: 10px 16px;
  border-radius: var(--radius);
  background: var(--fg);
  color: var(--bg);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-mono);
  text-transform: uppercase;
  text-decoration: none;
}

.skip-link:focus-visible {
  transform: none;
}

/* The skip target takes focus programmatically, so it must not also draw a
   ring around the entire page body. */
main:focus {
  outline: none;
}

/* Layout ------------------------------------------------------------------ */

.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.container-narrow {
  max-width: var(--container-narrow);
}

.section {
  padding-block: var(--section-y);
  position: relative;
}

.section--tight {
  padding-block: calc(var(--section-y) * 0.6);
}

.rule {
  height: 1px;
  background: var(--border);
  border: 0;
  margin: 0;
}

/* Type helpers ------------------------------------------------------------ */

.mono {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-mono);
  text-transform: uppercase;
}

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: var(--tracking-mono);
  text-transform: uppercase;
  color: var(--fg-muted);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  padding: 7px 13px 6px;
  line-height: 1;
}

.eyebrow::before {
  content: '';
  width: 5px;
  height: 5px;
  background: var(--brand);
  flex: none;
}

.section-title {
  font-size: var(--text-4xl);
  max-width: 22ch;
}

.section-lede {
  margin-top: 20px;
  font-size: var(--text-md);
  color: var(--fg-muted);
  max-width: 56ch;
}

.section-head {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 26px;
  margin-bottom: 64px;
}

.text-muted {
  color: var(--fg-muted);
}
.text-dim {
  color: var(--fg-dim);
}
.text-brand {
  color: var(--brand);
}

/* Reveal ------------------------------------------------------------------ */
/* Opacity + transform only — both composite on the GPU, so a reveal never
   triggers layout. Reduced motion keeps the fade and drops the travel.
   Every rule that hides something pending JavaScript is gated on html.js,
   which boot.js sets before first paint. No boot.js, no hiding — see the
   comment in that file. */

html.js [data-reveal] {
  opacity: 0;
  transform: translate3d(0, 18px, 0);
  transition:
    opacity 0.75s var(--ease-out),
    transform 0.75s var(--ease-out);
  transition-delay: var(--reveal-delay, 0ms);
}

html.js [data-reveal].is-revealed {
  opacity: 1;
  transform: none;
}

html.reduced-motion [data-reveal] {
  transform: none;
  transition-duration: 0.3s;
}

.split-word {
  display: inline-block;
  white-space: nowrap;
}

.split-char {
  display: inline-block;
  will-change: transform, opacity;
}

/* A split headline animates its characters, not itself — so it opts out of the
   element-level reveal it also carries. */
html.js [data-split-lines][data-reveal] {
  opacity: 1;
  transform: none;
}

html.js [data-split-lines] .split-char {
  opacity: 0;
  transform: translate3d(0, 0.6em, 0);
  transition:
    opacity 0.85s var(--ease-out),
    transform 0.85s var(--ease-out);
}

html.js [data-split-lines].is-revealed .split-char {
  opacity: 1;
  transform: none;
}

html.reduced-motion [data-split-lines] .split-char {
  transform: none;
  transition-delay: 0ms !important;
  transition-duration: 0.3s;
}
