/* =============================================================================
   Foldnine — reset, typography, layout primitives
   Everything here is used by more than one section. Section-specific
   composition lives in sections.css.
   ========================================================================== */

@font-face {
  font-family: "Newsreader";
  src: url("../fonts/newsreader.woff2") format("woff2");
  font-weight: 300 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "JetBrains Mono";
  src: url("../fonts/jetbrains-mono.woff2") format("woff2");
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
}

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; scroll-padding-block-start: 5rem; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--bg);
  color: var(--prose);
  font-family: var(--serif);
  font-size: var(--step-0);
  font-weight: 380;            /* light-on-dark optically bolds; weigh less */
  line-height: 1.6;
  font-optical-sizing: auto;
  font-feature-settings: "kern", "liga", "clig";
  overflow-x: hidden;
}

h1, h2, h3, h4 { color: var(--ink); font-weight: 400; margin: 0; text-wrap: balance; }
p { margin: 0; text-wrap: pretty; }
ul, ol { margin: 0; padding: 0; list-style: none; }

/* Trims half-leading so mixed sizes align on cap height rather than line box.
   No Firefox yet; costs a pixel or two there and nothing else. */
@supports (text-box: trim-both cap alphabetic) {
  h1, h2, h3, .display, .stat-value { text-box: trim-both cap alphabetic; }
}

::selection { background: var(--accent); color: var(--bg); }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: .18em;
  border-radius: 3px;
}

/* --- skip link ------------------------------------------------------------ */
.skip {
  position: fixed; left: var(--gutter); top: -5rem; z-index: 100;
  background: var(--accent); color: var(--bg);
  font-family: var(--mono); font-size: var(--step--1);
  letter-spacing: var(--track-mono); text-transform: uppercase;
  padding: .7rem 1rem; border-radius: 3px; text-decoration: none;
  transition: top var(--t-state) var(--ease);
}
.skip:focus { top: .75rem; }

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

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

/* The rail: a label column beside its content. Sidebar primitive, so it
   reflows on the container it is in rather than on a viewport breakpoint.
   min() is load-bearing - a bare floor overflows a narrower container. */
.rail {
  display: flex; flex-wrap: wrap;
  column-gap: clamp(1.5rem, 4vw, 3.5rem);
  row-gap: 1.5rem;
}
.rail > .rail-label { flex-basis: var(--rail); flex-grow: 1; }
.rail > .rail-body  { flex-basis: 0; flex-grow: 999; min-inline-size: min(30rem, 100%); }

/* --- typographic roles ---------------------------------------------------- */

.label {
  font-family: var(--mono);
  font-size: var(--step--1);
  font-weight: 500;
  letter-spacing: var(--track-mono);
  text-transform: uppercase;
  color: var(--muted);
  margin: 0;
}
.label-accent { color: var(--accent); }

.meta {
  font-family: var(--mono);
  font-size: var(--step--2);
  letter-spacing: .08em;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.display  { font-size: var(--step-4); line-height: 1.02; letter-spacing: var(--track-disp); }
.head     { font-size: var(--step-3); line-height: 1.08; letter-spacing: var(--track-head); }
.subhead  { font-size: var(--step-2); line-height: 1.2;  letter-spacing: var(--track-sub); }
.lede     { font-size: var(--step-1); line-height: 1.5;  color: var(--prose); max-width: 40rem; }
.prose    { max-width: var(--measure); }

.num { font-family: var(--mono); font-variant-numeric: tabular-nums; }

/* --- status dot ----------------------------------------------------------- */

.dot {
  display: inline-block; inline-size: .45rem; block-size: .45rem;
  border-radius: 50%; background: var(--accent); flex: none;
  vertical-align: baseline;
}
.dot-pending { background: var(--pending); }
@media (prefers-reduced-motion: no-preference) {
  .dot-live { animation: pulse 2.6s var(--ease) infinite; }
  @keyframes pulse {
    0%, 100% { opacity: 1;   box-shadow: 0 0 0 0 rgb(111 224 184 / .45); }
    50%      { opacity: .75; box-shadow: 0 0 0 .35rem rgb(111 224 184 / 0); }
  }
}

/* --- links ---------------------------------------------------------------- */

a { color: inherit; text-decoration-color: var(--rule-firm); text-decoration-thickness: .05em; text-underline-offset: .2em; transition: color var(--t-state) var(--ease), text-decoration-color var(--t-state) var(--ease); }
a:hover { color: var(--accent); text-decoration-color: currentColor; }

/* --- buttons -------------------------------------------------------------- */

.btn {
  display: inline-flex; align-items: center; gap: .6rem;
  font-family: var(--mono); font-size: var(--step--1);
  letter-spacing: var(--track-mono); text-transform: uppercase;
  padding: .95rem 1.4rem; border-radius: 3px; text-decoration: none;
  border: 1px solid var(--rule-firm); color: var(--ink);
  background: transparent;
  transition: background var(--t-state) var(--ease), border-color var(--t-state) var(--ease), color var(--t-state) var(--ease);
}
.btn:hover { border-color: var(--accent); color: var(--accent); background: var(--accent-wash); }
.btn-primary { background: var(--accent); border-color: var(--accent); color: var(--bg); font-weight: 600; }
.btn-primary:hover { background: var(--ink); border-color: var(--ink); color: var(--bg); }

/* --- section frame -------------------------------------------------------- */

section { padding-block: clamp(4.5rem, 10vw, 9rem); border-block-start: 1px solid var(--rule); }

/* =============================================================================
   Reveal on scroll.

   Content is visible by default and stays visible if JavaScript never runs,
   if it fails, or if the browser cannot observe intersections. Motion is only
   ever added on top of a page that already reads. An earlier build of this
   site animated from opacity 0 and left whole sections blank whenever nothing
   could scroll; that is not a trade worth making for a fade.
   ========================================================================== */
@media (prefers-reduced-motion: no-preference) {
  .js-motion [data-reveal] {
    opacity: 0;
    transform: translateY(14px);
    transition: opacity var(--t-move) var(--ease), transform var(--t-move) var(--ease);
  }
  .js-motion [data-reveal].is-in {
    opacity: 1;
    transform: none;
  }
}
