/* ==========================================================================
   NUVORM — base.css (Phase 1b fresh build, index-next.html)
   Fonts · tokens · reset · a11y primitives. §29 directive set + §2.2/§2.3.
   Self-contained: relative asset paths only, no CDN, no external fonts.
   ========================================================================== */

/* --------------------------------------------------------------------------
   §29.1 TYPE CONTRACT — Inter (display/structure) + Figtree (body).
   Self-hosted variable woff2, two faces per family (latin-ext + latin),
   Google unicode-range subsets (same ranges the 1a build used, lines 33/34).
   font-stretch is FORBIDDEN (Inter has no wdth axis; §29.1 retires Anybody's
   stretch signature). Anybody/Syne files stay vendored but are NOT loaded.
   Role map: giant words, headings, labels/chips/captions/menu → Inter;
   body paragraphs, addresses, notes → Figtree.
   -------------------------------------------------------------------------- */
@font-face {
  font-family: "Inter";
  src: url("../fonts/inter-latin-ext.woff2") format("woff2");
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Inter";
  src: url("../fonts/inter-latin.woff2") format("woff2");
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Figtree";
  src: url("../fonts/figtree-latin-ext.woff2") format("woff2");
  font-style: normal;
  font-weight: 300 900;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Figtree";
  src: url("../fonts/figtree-latin.woff2") format("woff2");
  font-style: normal;
  font-weight: 300 900;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* --------------------------------------------------------------------------
   §2.3 TOKENS (carried forward; grids themselves are NEW §29.13 designs).
   Monochrome absolute: colour exists only inside photography (§2.2).
   Tints: black/white dilutions for NON-LOAD-BEARING fields only (A5).
   -------------------------------------------------------------------------- */
:root {
  --black: #000;
  --white: #fff;

  --font-display: "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-body: "Figtree", system-ui, -apple-system, "Segoe UI", sans-serif;

  /* A5 tint allowance — background FIELDS only, never text (repealed grey text) */
  --tint: rgba(0, 0, 0, 0.06);          /* black dilution on white fields */
  --tint-inverse: rgba(255, 255, 255, 0.06); /* white dilution on black fields (map panels) */
  --tint-ring: rgba(0, 0, 0, 0.3);      /* §25 grey ring register (black-diluted) */
  --tint-ring-inverse: rgba(255, 255, 255, 0.3);

  --ease: cubic-bezier(0.22, 1, 0.36, 1);

  /* §34.8 NO ROUNDED CORNERS — the §21 soft-corner scale is RETIRED (client:
     "no rounded corners on tiles or elements"): all three tokens collapse to
     0. Named circle exemptions ONLY (set per-component, not here): the hero
     slide dots, the lightbox dot navigation (§35.11) and the favicon mark.
     (§35.12: the lightbox o-exit button is RETIRED — the close control is a
     square X, radius 0 again.) */
  --radius-sm: 0;
  --radius-md: 0;
  --radius-lg: 0;

  /* §34.11 uniform gutter — THE single gap of the quad grid (rows AND
     columns, both sections) and the lightbox track; declared once here.
     §35.8/§35.10: the gutter itself is viewport-derived and GROWS
     8–16px → 12–24px (mid-point 1.2vw → 1.5vw). */
  --band-gap: clamp(12px, 1.5vw, 24px);

  /* §35.8/§35.10 VIEWPORT-DERIVED SECTION PADDING — the one-viewport
     sections' own air (top/bottom inside the 100svh box), growing with the
     viewport height. --vw-pad-m = the ≤700px mobile register. */
  --vw-pad: clamp(40px, 6vh, 72px);
  --vw-pad-m: clamp(28px, 5svh, 44px);

  /* §2.3 spacing rhythm: 8px base unit; page margins 20px mobile / 80px desktop */
  --unit: 8px;
  --edge: 80px;            /* general page margin (desktop; 20px mobile below) */
  --edge-left: 120px;      /* deep step of the §2.3 margin scale (20 → 80 → 120):
                              the reserved wide left gutter — held unwired for
                              asymmetric compositions (no current grid uses it) */

  --hairline: 1px solid var(--black);

  /* footer wordmark slot width — the static footer mark and the loader's
     letterform master (index-next.html .footer-mark) both key off this.
     §35.1: the HEADER wordmark now uses this same slot (footer-scale parity). */
  --mark-w: 180px;
  /* §35.1 mobile: the footer mark's mobile slot (≤700px) — the header
     wordmark matches it exactly (found in layout.css: 150px). */
  --mark-w-m: 150px;

  /* §30.7 GLYPH/CAP-H BASELINE GEOMETRY — both values measured against the
     SHIPPED woff2 (fontTools: OS/2.sCapHeight + glyph ink bounds, weight-
     stable at wght 800), not remembered metrics:
     · --cap-h: Inter's cap-height ratio = 1490/2048 = 0.72754em. H ink is
       0→1490 units (descent 0) at default AND wght 800. Every brand glyph
       standing in a heading composition (the ∩/U NEWS cells, the WORK W
       glyph, the contact companion nu) sizes its svg to this height so its
       ink body equals the heading's cap height exactly. (Round letters O/S
       overshoot to 0.7373em top / 0.747em ink — that overshoot is Inter's
       optical correction, NOT the cap; an earlier 0.735em constant here was
       a mis-measure and made glyphs run ~1% over the cap line. §30.7 says
       cap-height EXACTLY.)
     · --baseline-gap: the text baseline sits 0.8638em from a line-height:1
       box top = 0.136em above its bottom (typo/hhea 1984/−494 @upm 2048,
       USE_TYPO_METRICS set — half-leading −0.105em + ascent 0.9688em) — the
       seat where glyph ink bottoms meet the text baseline. */
  --cap-h: 0.72754em;
  --baseline-gap: 0.136em;
}

/* --------------------------------------------------------------------------
   Reset + document defaults
   -------------------------------------------------------------------------- */
*,
*::before,
*::after { box-sizing: border-box; }

html {
  scroll-behavior: smooth;
  /* Giant words intentionally bleed past viewport edges (special ruling:
     decorative display devices) — never a horizontal scrollbar. `clip` keeps
     position:fixed children (header, loader) un-scrolled. */
  overflow-x: hidden;
  overflow-x: clip;
}
body {
  margin: 0;
  color: var(--black);
  background: var(--white);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

img { display: block; max-width: 100%; height: auto; }
a { color: inherit; }
button { font: inherit; color: inherit; }

/* A5/§2.10 focus: pure black on white; white on black sections (see
   components.css section overrides). Visible, thick, offset. */
:focus-visible { outline: 3px solid var(--black); outline-offset: 5px; }

/* --------------------------------------------------------------------------
   A11y primitives
   -------------------------------------------------------------------------- */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: normal;
  border: 0;
}

/* First focusable: "Skip to content" → focuses #main-content (§31 fix2 hook contract) */
.skip-link {
  position: fixed;
  top: 12px;
  left: 12px;
  z-index: 300;
  padding: 10px 16px;
  background: var(--white);
  color: var(--black);
  border: 1px solid var(--black);
  border-radius: var(--radius-sm);
  font-family: var(--font-display);
  font-size: 13px;
  font-weight: 600;
  text-decoration: none;
  /* hidden until focused */
  transform: translateY(-200%);
  transition: transform 160ms ease;
}
.skip-link:focus-visible { transform: translateY(0); }

/* Anchored section jumps. §35.8: #work/#news are EXACTLY one viewport tall —
   an anchor jump must land them FLUSH (scroll-margin 0), or 104px of the
   section's bottom row would be stranded below the fold. The header never
   hides now (§35.2) and overlays the section's own --vw-pad top air
   harmlessly. #about takes NO offset: §34.9 — an anchor jump must land the
   intro flush at the viewport top so the white screen fills it (the hero
   must never peek). §36 rev: #contact's §34 104px offset register is
   RETIRED — it stranded 104px of the News tail ABOVE the dark field at the
   menu-click landing and left the scroll-driven header-on-dark state
   unengaged (the dark field's top sat at 104px, past the 72px band scan).
   The header instead overlays #contact's own top air — clamp(120px, 14vh,
   176px) desktop / 88px mobile = the 88px header exactly — and the landing
   sits flush like the other sections. */
#work, #news, #about, #contact { scroll-margin-top: 0; }

/* --------------------------------------------------------------------------
   Global reduced-motion kill-switch (parity law: nothing gated, content
   instant). Component-specific reduce overrides live at the end of
   components.css.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *,
  *::before,
  *::after {
    scroll-behavior: auto !important;
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
  }
  .skip-link { transition: none; }
}