/* ==========================================================================
   BASE — reset, substrates, typography primitives, layout scaffolding.
   ========================================================================== */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--nav-h) + var(--s4));
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--fg);
  font-family: var(--f-text);
  font-size: var(--t-body);
  line-height: var(--lh-text);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

img, video, svg { display: block; max-width: 100%; }
button, input, textarea, select { font: inherit; color: inherit; }
a { color: inherit; text-decoration: none; }

h1, h2, h3, h4, p, figure, blockquote { margin: 0; }
ul, ol { margin: 0; padding: 0; list-style: none; }

/* Square, visible, never removed (§8). */
:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 3px;
}

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

/* --------------------------------------------------------------- SUBSTRATES */
/* The graph grid is the page floor, not a decoration (§4.1). Pure gradients —
   no image request. Cell size is shared with the spacing scale, which is why
   the layout snaps to it. */

.substrate {
  position: relative;
  background-color: var(--paper);
  background-image:
    linear-gradient(var(--rule) 1px, transparent 1px),
    linear-gradient(90deg, var(--rule) 1px, transparent 1px),
    linear-gradient(var(--rule-major) 1px, transparent 1px),
    linear-gradient(90deg, var(--rule-major) 1px, transparent 1px);
  background-size:
    var(--cell) var(--cell),
    var(--cell) var(--cell),
    var(--cell-major) var(--cell-major),
    var(--cell-major) var(--cell-major);
}

.substrate--dark {
  background-color: var(--ink);
  color: var(--fg-invert);
  background-image:
    linear-gradient(var(--rule-dark) 1px, transparent 1px),
    linear-gradient(90deg, var(--rule-dark) 1px, transparent 1px),
    linear-gradient(var(--rule-dark-mj) 1px, transparent 1px),
    linear-gradient(90deg, var(--rule-dark-mj) 1px, transparent 1px);
}

/* Flat dark panel with no ruling, for dense sections like the marquee. */
.substrate--solid {
  background-color: var(--ink);
  background-image: none;
  color: var(--fg-invert);
}

.substrate--dark  { --line: var(--line-invert); }
.substrate--solid { --line: var(--line-invert); }

/* Paper grain (§4.2). Noticeable by its absence, not its presence. */
.substrate::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0.035;
  mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='3'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");
}
.substrate--dark::after,
.substrate--solid::after { mix-blend-mode: screen; opacity: 0.05; }

/* ------------------------------------------------------------------ LAYOUT */

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

/* Asymmetric 12-col (§5.3). Never centre a full-width block. */
.grid12 {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: var(--s3);
}

.section {
  position: relative;
  padding-block: var(--s16);
  overflow: clip;
}

@media (max-width: 768px) {
  .section { padding-block: var(--s8); }
  .grid12  { grid-template-columns: repeat(6, 1fr); gap: var(--s2); }
}

/* -------------------------------------------------------------- TYPOGRAPHY */

.display {
  font-family: var(--f-display);
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: var(--tr-xl);
  line-height: var(--lh-disp);
  text-wrap: balance;
}

.t-mega { font-size: var(--t-mega); letter-spacing: var(--tr-mega); line-height: var(--lh-mega); }
.t-xl   { font-size: var(--t-xl);   letter-spacing: var(--tr-xl); }
.t-lg   { font-size: var(--t-lg);   letter-spacing: var(--tr-lg); }
.t-md   { font-size: var(--t-md);   letter-spacing: var(--tr-lg); }

/* Wide-tracked tiny mono against tight-tracked giant display — the signature
   contrast of the whole system (§3.3). */
.micro {
  font-family: var(--f-micro);
  font-size: var(--t-micro);
  text-transform: uppercase;
  letter-spacing: var(--tr-micro);
  color: var(--fg-mute);
  line-height: 1.4;
}
.substrate--dark .micro,
.substrate--solid .micro { color: var(--fg-mute-dark); }

.hand {
  font-family: var(--f-hand);
  font-size: 1.35rem;
  line-height: 1.25;
  transform: rotate(-2.5deg);
  color: var(--accent);
}

.lead   { font-size: var(--t-lead); max-width: 46ch; }
.prose  { max-width: 62ch; }
.accent { color: var(--accent); }

/* ------------------------------------------------------------ MEDIA BASICS */
/* Aspect-ratio comes from the manifest via the inline --ratio custom property,
   so every tile reserves its exact box before a single byte of media loads.
   This is the whole CLS story. */

.media-img,
.media-video {
  width: 100%;
  height: 100%;
  aspect-ratio: var(--ratio, 4 / 3);
  object-fit: cover;
  background-color: var(--paper-2);
}
.substrate--dark .media-img,
.substrate--dark .media-video { background-color: var(--ink-2); }

/* Stand-in for a referenced upload that is not on disk. */
.media-missing {
  width: 100%;
  aspect-ratio: var(--ratio, 4 / 3);
  display: grid;
  place-items: center;
  padding: var(--s2);
  text-align: center;
  background: repeating-linear-gradient(
    45deg,
    var(--paper-2) 0 10px,
    var(--paper) 10px 20px
  );
  border: 1px dashed var(--line);
}
.substrate--dark .media-missing {
  background: repeating-linear-gradient(
    45deg, var(--ink-2) 0 10px, var(--ink) 10px 20px
  );
}

/* ---------------------------------------------------------------- REVEALS */

[data-reveal] {
  opacity: 0;
  transform: translateY(28px);
  transition:
    opacity var(--d-slow) var(--ease-out),
    transform var(--d-slow) var(--ease-out);
  transition-delay: var(--reveal-delay, 0ms);
}
[data-reveal].is-visible { opacity: 1; transform: none; }

/* Mask reveal for display lines (§7.2).
   nowrap enforces the manual line breaks — without it an inline glyph or a long
   word reflows and silently adds a phantom line to the headline.
   The padding/margin pair gives glyphs headroom inside a sub-1.0 line-height box
   without breaking the mask: the slide distance is a % of the box, so it still
   starts fully hidden. */
.line-mask {
  display: block;
  overflow: hidden;
  white-space: nowrap;
  padding-block: 0.08em;
  margin-block: -0.08em;
}
.line-mask > span {
  display: block;
  transform: translateY(110%);
  transition: transform var(--d-slow) var(--ease-out);
  transition-delay: var(--reveal-delay, 0ms);
}
.is-visible .line-mask > span,
.line-mask.is-visible > span { transform: none; }

/* -------------------------------------------------------------- UTILITIES */

.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.skip-link {
  position: absolute; top: -100px; left: var(--s2); z-index: 999;
  background: var(--ink); color: var(--fg-invert);
  padding: var(--s2) var(--s3); font-family: var(--f-micro);
  font-size: var(--t-micro); text-transform: uppercase; letter-spacing: var(--tr-micro);
}
.skip-link:focus { top: var(--s2); }

.hairline { border: 0; border-top: 1px solid var(--line); margin: 0; }

/* ------------------------------------------------------- REDUCED MOTION (§7.4) */

@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;
  }
  /* Nothing may end up stuck invisible. */
  [data-reveal] { opacity: 1 !important; transform: none !important; }
  .line-mask > span { transform: none !important; }
}
