/* ==========================================================================
   base.css — reset, document defaults, typography, layout primitives.
   ========================================================================== */

/* --- Fonts ----------------------------------------------------------------
   Fetched by fetch-assets.py. font-display:swap means text paints in the
   Helvetica fallback immediately rather than blocking, and the files are
   optional — the site is fully styled without them.                        */
/* --- Reset --------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* Anchor targets clear the sticky header instead of hiding under it. */
  scroll-padding-top: calc(var(--header-h) + var(--space-4));
}

body {
  margin: 0;
  background: var(--surface);
  color: var(--text);
  font-family: var(--font-text);
  font-size: var(--step-0);
  font-weight: var(--weight-light);
  line-height: var(--leading-normal);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  /* Belt-and-braces against the horizontal scroll the old site had on
     narrow viewports. */
  overflow-x: hidden;
}

h1, h2, h3, h4, h5, h6, p, figure, blockquote, dl, dd { margin: 0; }
ul[role="list"], ol[role="list"] { list-style: none; margin: 0; padding: 0; }

img, picture, video, canvas, svg {
  display: block;
  max-width: 100%;
  height: auto;
}

input, button, textarea, select { font: inherit; color: inherit; }
button { background: none; border: 0; padding: 0; cursor: pointer; }

/* --- Typography ---------------------------------------------------------- */
h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: var(--weight-thin);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
  text-wrap: balance;   /* avoids orphan words in big statement type */
}

.t-hero      { font-size: var(--step-6); }
.t-display   { font-size: var(--step-5); }
.t-statement { font-size: var(--step-4); font-weight: var(--weight-thin);
               line-height: var(--leading-snug); }
.t-title     { font-size: var(--step-3); }
.t-subtitle  { font-size: var(--step-2); }
.t-lede      { font-size: var(--step-1); font-weight: var(--weight-light);
               line-height: var(--leading-relaxed); color: var(--text-muted);
               max-width: var(--measure-prose); text-wrap: pretty; }
.t-body      { font-size: var(--step-0); max-width: var(--measure-prose);
               text-wrap: pretty; }
.t-meta      { font-size: var(--step--1); letter-spacing: var(--tracking-wider);
               text-transform: uppercase; font-weight: var(--weight-normal);
               color: var(--text-subtle); }
.t-mono      { font-family: var(--font-mono); font-size: var(--step--1);
               letter-spacing: var(--tracking-normal); }

/* --- Links --------------------------------------------------------------- */
a { color: inherit; text-decoration: none; }

/* Underline grows from the left on hover rather than simply appearing —
   cheap to render (transform only) and reads as deliberate. */
.link {
  position: relative;
  color: var(--text);
  padding-bottom: 2px;
}
.link::after {
  content: "";
  position: absolute; inset-inline: 0; bottom: 0;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--dur) var(--ease-out);
}
.link:hover::after, .link:focus-visible::after { transform: scaleX(1); }
.link--accent:hover { color: var(--accent); }

/* --- Focus --------------------------------------------------------------- */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: var(--radius-sm);
}
.on-inverse :focus-visible { outline-color: var(--accent-on-inverse); }

.skip-link {
  position: absolute; top: 0; left: 0;
  transform: translateY(-120%);
  z-index: calc(var(--z-header) + 1);
  padding: var(--space-3) var(--space-5);
  background: var(--surface-inverse);
  color: var(--text-on-inverse);
  font-size: var(--step--1);
  transition: transform var(--dur-fast) var(--ease-out);
}
.skip-link:focus { transform: translateY(0); }

.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap; border: 0;
}

/* --- Layout primitives --------------------------------------------------- */
.wrap {
  width: 100%;
  max-width: var(--measure-content);
  margin-inline: auto;
  padding-inline: var(--space-gutter);
}
.wrap--wide  { max-width: var(--measure-wide); }
.wrap--prose { max-width: 76ch; }
.wrap--flush { max-width: none; padding-inline: 0; }

.section { padding-block: var(--space-section); }
.section--tight { padding-block: clamp(2.5rem, 1.5rem + 4vw, 5rem); }
.section--flush-top { padding-block-start: 0; }

.stack > * + * { margin-block-start: var(--space-4); }
.stack-lg > * + * { margin-block-start: var(--space-6); }

/* --- The backdrop grid ---------------------------------------------------
   Two 1px gradients on one square cell. Because the cell is a single length
   and the pattern starts at the element's own origin, it tiles perfectly at
   any viewport width — which is precisely what the hand-placed bitmaps in
   the original could not do.                                              */
.grid-backdrop { position: relative; isolation: isolate; }
.grid-backdrop::before {
  content: "";
  position: absolute; inset: 0;
  z-index: -1;
  pointer-events: none;
  background-image:
    linear-gradient(to right,  var(--grid-line) 1px, transparent 1px),
    linear-gradient(to bottom, var(--grid-line) 1px, transparent 1px);
  background-size: var(--grid-cell) var(--grid-cell);
  /* Fades the grid out at the edges so it reads as texture, not a table. */
  -webkit-mask-image: radial-gradient(ellipse 85% 75% at 50% 40%, #000 45%, transparent 100%);
          mask-image: radial-gradient(ellipse 85% 75% at 50% 40%, #000 45%, transparent 100%);
}

/* Checkerboard variant: set data-backdrop="checks" on the section. */
.grid-backdrop[data-backdrop="checks"]::before {
  background-image:
    conic-gradient(var(--grid-line) 0 25%, transparent 0 50%,
                   var(--grid-line) 0 75%, transparent 0);
  background-size: calc(var(--grid-cell) * 2) calc(var(--grid-cell) * 2);
}

.on-inverse {
  --grid-line: rgba(255, 255, 255, 0.07);
  --rule: var(--rule-on-inverse);
  background: var(--surface-inverse);
  color: var(--text-on-inverse);
}

/* --- Scroll reveal -------------------------------------------------------
   Opt-in: JS adds .reveal-ready to <html> only when IntersectionObserver
   exists, so with JS off or unsupported everything is simply visible. */
.reveal-ready [data-reveal] {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity var(--dur-slow) var(--ease-out),
              transform var(--dur-slow) var(--ease-out);
  transition-delay: var(--reveal-delay, 0ms);
}
.reveal-ready [data-reveal].is-revealed { opacity: 1; transform: none; }

/* --- Motion preference ---------------------------------------------------
   One global override. Anything animated anywhere in the site is covered
   here, so no component has to remember to opt out.                       */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
  .reveal-ready [data-reveal] { opacity: 1; transform: none; }
}

/* --- Print --------------------------------------------------------------- */
@media print {
  .site-header, .site-footer__nav, .lightbox, .to-top { display: none !important; }
  .grid-backdrop::before { display: none; }
  body { color: #000; background: #fff; }
  a[href^="http"]::after { content: " (" attr(href) ")"; font-size: 0.8em; }
}

/* --- Accent: selection --------------------------------------------------- */
::selection { background: var(--accent-graphic); color: var(--ink-900); }
.on-inverse ::selection { background: var(--accent-graphic); color: var(--ink-900); }

/* --- Inverted band -------------------------------------------------------
   Full-bleed black. The brand mint is a 1.5:1 contrast on white but ~13:1 on
   #171717, so these bands are where the accent actually gets to be itself.
   Used sparingly — two on the homepage — they also break up what would
   otherwise be fifteen consecutive white sections.                        */
.band {
  background: var(--surface-inverse);
  color: var(--text-on-inverse);
  padding-block: clamp(4.5rem, 3rem + 9vw, 10rem);
  position: relative;
  overflow: hidden;
}
.band--flush-footer { padding-block-end: clamp(3rem, 2rem + 5vw, 6rem); }
