/* Normwerk, Rev. B: reset, fonts, grid, type, a11y. Shared by every page. */

/* Fonts: self-hosted latin subsets. Archivo axes pinned wght 380-660, wdth 100-125. */
@font-face {
  font-family: "Archivo";
  font-style: normal;
  font-weight: 380 660;
  font-stretch: 100% 125%;
  font-display: swap;
  src: url("../assets/fonts/archivo-var.woff2") format("woff2");
}
@font-face {
  font-family: "Fragment Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../assets/fonts/fragment-mono.woff2") format("woff2");
}
/* Metric-matched fallbacks so the display headline cannot shift layout */
@font-face {
  font-family: "Archivo-fallback";
  src: local("Arial");
  size-adjust: 99%;
  ascent-override: 88%;
  descent-override: 22%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "FragmentMono-fallback";
  src: local("Courier New");
  size-adjust: 103%;
  ascent-override: 96%;
  descent-override: 25%;
  line-gap-override: 0%;
}

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

html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
}
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
}

body {
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-display);
  font-size: var(--fs-16);
  line-height: 1.55;
  font-variation-settings: "wdth" 100;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

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

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

a {
  color: inherit;
}

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

input,
textarea {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  border-radius: 0;
}

::placeholder {
  color: var(--graphite);
  opacity: 1;
}

[hidden] {
  display: none !important;
}

:focus-visible {
  outline: var(--focus-ring);
  outline-offset: 3px;
}

/* The sheet: page frame with printed margin rules */
.wrap {
  max-width: var(--max-w);
  margin-inline: auto;
  padding-inline: var(--margin);
}

.page-rules {
  position: fixed;
  inset: 0;
  margin-inline: auto;
  max-width: var(--max-w);
  pointer-events: none;
  z-index: 0;
}
.page-rules::before,
.page-rules::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  width: var(--rule-w);
  background: var(--hairline);
}
.page-rules::before {
  left: calc(var(--margin) - var(--rule-inset));
}
.page-rules::after {
  right: calc(var(--margin) - var(--rule-inset));
}

main {
  position: relative;
  z-index: 1;
}

section[id] {
  scroll-margin-top: 84px; /* clears the sticky header on anchor jumps */
}

/* 12-column grid (4 on mobile) */
.grid {
  display: grid;
  grid-template-columns: repeat(var(--cols), minmax(0, 1fr));
  column-gap: var(--gutter);
}

/* Type voices */
.mono {
  font-family: var(--font-mono);
  font-size: var(--fs-13);
  line-height: 1.5;
}
.label {
  font-family: var(--font-mono);
  font-size: var(--fs-13);
  text-transform: uppercase;
  letter-spacing: var(--track-label);
}
.display {
  font-weight: 620;
  font-variation-settings: "wdth" 105;
  letter-spacing: -0.015em;
  line-height: 0.96;
}
.numeral {
  font-weight: 620;
  font-variation-settings: "wdth" 125;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
  line-height: 1;
}
.body-l {
  font-size: var(--fs-18);
  color: var(--graphite);
}

/* Links */
.tlink {
  color: var(--orange-ink);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  transition: color var(--t-micro) var(--ease-micro);
}
.tlink:hover {
  color: var(--orange-ink); /* stays AA; the heat moves to the underline (non-text, 3:1) */
  text-decoration-thickness: 2px;
  text-decoration-color: var(--werk-orange);
}

/* A11y */
/* Extends the hit area to 44px without moving layout */
.tap {
  padding-block: 14px;
  margin-block: -14px;
  display: inline-block;
}

.skip-link {
  position: absolute;
  left: var(--s-2);
  top: -100px;
  z-index: 100;
  background: var(--ink);
  color: var(--paper);
  font-family: var(--font-mono);
  font-size: var(--fs-13);
  padding: 12px 16px;
}
.skip-link:focus {
  top: var(--s-2);
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* Pre-hide for motion: the inline head script adds .nw-motion only when the user allows motion.
   motion.js removes it again if GSAP never arrives, so no network state can strand hidden content. */
.nw-motion [data-rise],
.nw-motion [data-stamp] {
  opacity: 0;
}
.nw-motion .reg-line,
.nw-motion .sweep-line {
  transform: scaleX(0);
}

/* =====================================================================
   THE LIVING GRID  ·  Rev. C
   A faint drafting grid under the whole sheet. The cursor warms a small
   area of it, which is the only ambient motion on the site. Fixed, behind
   main, pointer-events none. Inversion bands are opaque, so the grid
   simply stops there: solid ink is still solid ink.
   ===================================================================== */
.bg-grid {
  position: fixed;
  inset: 0;
  z-index: 0;
  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);
  /* Rev. D: a sub-pixel blur. A hairline grid rendered dead sharp reads as a
     screen artefact; blurred a fraction it reads as drafting paper, which is
     the thing being imitated. */
  filter: blur(var(--grid-blur));
}
/* The warm patch, revealed only near the cursor. --mx / --my are set by
   js/grid.js; the fallback keeps it off screen so a no-JS visitor sees the
   plain grid and nothing else.

   Rev. F: THREE layers, not one, and the order matters. Until now this drew the
   same two line gradients as the base layer, in a hotter ink, directly on top of
   them. Measured, that changed 2.98 percent of the pixels in the patch and moved
   its mean luminance by 0.14 percent, because grid lines are only about 3
   percent of the surface: the effect was capped by construction, not by its
   values. It ran correctly for three revisions and Max reported it as never
   built, which for a decorative interaction is the same thing.
   The radial wash is FIRST in the stack and is what makes it perceptible: it
   tints the PAPER between the lines, giving the eye an area to lock onto rather
   than a scattering of hairlines. The two line layers supply the character of a
   drafting grid warming up. Measured together against the quieter base: 14x the
   mean signal, 32x the changed-pixel area. Removing the wash returns this to the
   invisible version, so do not "simplify" it back to lines. */
.bg-grid::after {
  content: "";
  position: absolute;
  inset: 0;
  /* Rev. G: FOUR layers. The sub-grid is the new one and it is the reason this
     revision is perceptible where three previous ones were not. The other three
     only made the lines and paper that are already there warmer, which is a
     change of degree; the quarter-cell grid is a change of kind, because those
     lines do not exist anywhere else on the page and the eye is far better at
     noticing structure appear than at noticing a wash intensify. */
  /* Rev. H.1: an ELLIPSE, not a circle. Max asked for "some more motion WITHIN
     it... rather than just having a round shaped element, but something that
     changes shape too as we move the cursor." js/grid.js writes --gr-x and
     --gr-y from pointer velocity, so a horizontal sweep draws a wide patch, a
     vertical one draws a tall patch, and stopping eases it back to round.
     Ellipse radii are axis aligned in CSS and cannot be rotated, which is why
     the shape is driven by the two velocity COMPONENTS rather than by an angle:
     the axis-aligned version is what CSS can actually express, it covers the
     way people move a pointer while reading, and it needs one gradient rather
     than a mask-composite stack that Safari and Firefox spell differently. */
  background-image:
    radial-gradient(
      ellipse var(--gr-x, var(--grid-radius)) var(--gr-y, var(--grid-radius))
      at var(--mx, -999px) var(--my, -999px),
      var(--grid-halo) 0%, var(--grid-halo-soft) 45%, transparent 72%),
    linear-gradient(to right, var(--grid-sub) 1px, transparent 1px),
    linear-gradient(to bottom, var(--grid-sub) 1px, transparent 1px),
    linear-gradient(to right, var(--grid-line-hot) 1px, transparent 1px),
    linear-gradient(to bottom, var(--grid-line-hot) 1px, transparent 1px);
  background-size:
    auto,
    var(--grid-cell-sub) var(--grid-cell-sub),
    var(--grid-cell-sub) var(--grid-cell-sub),
    var(--grid-cell) var(--grid-cell),
    var(--grid-cell) var(--grid-cell);
  /* The motion WITHIN. The quarter-cell sub-grid parallaxes against the coarse
     grid, so the fine lines flow through the patch as it travels instead of
     the patch being a rigid window sliding over a static field. One sub-cell is
     24px and the factor is 0.06, so 400px of pointer travel slides it exactly
     one cell: enough to read as movement, not enough to read as a glitch. */
  background-position:
    0 0,
    var(--gp-x, 0px) var(--gp-y, 0px),
    var(--gp-x, 0px) var(--gp-y, 0px),
    0 0,
    0 0;
  opacity: 0;
  transition: opacity 500ms var(--ease-micro);
  /* Wider and softer than the old hard-coded 200px, whose stops left a usable
     core of only about 160px with the outer 28 percent of the radius doing
     nothing at all. Rev. G holds the core solid further out: the sub-grid needs
     a region where it is unambiguously drawn, or it reads as a rendering fault
     rather than as a finer grid. */
  -webkit-mask-image: radial-gradient(
    ellipse var(--gr-x, var(--grid-radius)) var(--gr-y, var(--grid-radius))
    at var(--mx, -999px) var(--my, -999px),
    #000 0%, #000 34%, rgba(0, 0, 0, 0.66) 58%, transparent 82%);
  mask-image: radial-gradient(
    ellipse var(--gr-x, var(--grid-radius)) var(--gr-y, var(--grid-radius))
    at var(--mx, -999px) var(--my, -999px),
    #000 0%, #000 34%, rgba(0, 0, 0, 0.66) 58%, transparent 82%);
}
.bg-grid.is-live::after {
  opacity: 1;
}
/* Touch and reduced-motion visitors get the static grid, never the tracker. */
@media (prefers-reduced-motion: reduce) {
  .bg-grid::after {
    display: none;
  }
}
@media (hover: none) {
  .bg-grid::after {
    display: none;
  }
}
