/* ============================================================
   base.css — resets, background, shared chrome (header / nav /
   footer / switcher), grade + background. Page templates layer on top.
   Values from docs/reference/index-v5.dc.html (canvas px × --u).
   ============================================================ */

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

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

/* flat INK on the root as the safety floor; the real background
   material is the fixed .bgroot stack below (z:-1) */
html {
  background-color: var(--ink);
}

body {
  min-height: 100vh;
  color: var(--paper);
  font-family: var(--font-grotesque);
  font-size: 16px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  display: flex;
  flex-direction: column;
}

/* ============================================================
   Living background v2 "field and matter" (BRIEF §4b) — one fixed
   root at z:-1 below ALL content. Rebuilt checkpoint by checkpoint
   (18.07 incident). Stack, bottom→top:

     base → grad → chroma → material → vignette → dither

   The dither is the LAST layer inside .bgroot: every gradient
   beneath it — the duotone field, the chroma pools AND the
   vignette's edge fall-off and top strip — is dithered. An
   undithered gradient above the dither is a contour no value of
   --bg-dither-op can break. Imagery and video never receive any
   of it (three noise registers: background < stills < hover).
   ============================================================ */

.bgroot {
  position: fixed;
  inset: -24px; /* margin under the weave so edges never bare */
  z-index: -1;
  pointer-events: none;
  overflow: hidden;   /* clip the oversized chroma pools */
  isolation: isolate; /* blend layers stay inside the stack */
  animation: weave 13s ease-in-out infinite alternate;
  animation-play-state: var(--bg-weave);
}

@keyframes weave {
  0%   { transform: translate(0, 0) rotate(0); }
  28%  { transform: translate(1.6px, -1px) rotate(0.035deg); }
  55%  { transform: translate(-1.2px, 0.8px) rotate(-0.025deg); }
  100% { transform: translate(1px, 1.4px) rotate(0.03deg); }
}

.bg-base,
.bg-grad,
.bg-chroma,
.bg-material,
.bg-vignette,
.bg-dither {
  position: absolute;
  inset: 0;
}

/* static grain-matter: sparse soft grains, brightness capped in
   the tile itself — screen blend can never spark white. Never
   animated; composites inside the isolated bgroot stack. */
.bg-material {
  mix-blend-mode: screen;
  image-rendering: pixelated;
  background-image: var(--bg-material-image);
  background-repeat: repeat;
  background-size: calc(240px * var(--bg-material-scale)) calc(240px * var(--bg-material-scale));
  opacity: var(--bg-material-op);
}

/* the field breathes: two oversized soft pools in counter-phase,
   90 s alternate cycles — transform/opacity only (compositor,
   no repaint), clipped by the root */
.bg-chroma .cool,
.bg-chroma .warm {
  position: absolute;
  width: 120%;
  height: 120%;
}

.bg-chroma .cool {
  left: 25%;
  top: -50%;
  background: radial-gradient(closest-side, rgba(46, 66, 92, 0.5), rgba(46, 66, 92, 0) 70%);
  animation: coolDrift 90s ease-in-out infinite alternate;
  animation-play-state: var(--bg-chroma);
}

.bg-chroma .warm {
  left: -50%;
  top: 40%;
  background: radial-gradient(closest-side, rgba(74, 40, 32, 0.4), rgba(74, 40, 32, 0) 70%);
  animation: warmDrift 90s ease-in-out infinite alternate;
  animation-play-state: var(--bg-chroma);
}

@keyframes coolDrift {
  0%   { transform: translate(0, 0) scale(1);       opacity: 0.6; }
  50%  { transform: translate(-6%, 6%) scale(1.08); opacity: 1; }
  100% { transform: translate(3%, -3%) scale(0.97); opacity: 0.65; }
}

@keyframes warmDrift {
  0%   { transform: translate(0, 0) scale(1);       opacity: 0.5; }
  50%  { transform: translate(6%, -5%) scale(1.1);  opacity: 0.9; }
  100% { transform: translate(-3%, 4%) scale(1);    opacity: 0.55; }
}

.bg-base {
  background: var(--ink);
}

.bg-grad {
  background: var(--bg-field);
  opacity: var(--bg-grad);
}

/* darkroom depth over the field: radial edge fall-off + a shallow
   top strip. Sits UNDER the dither so both of its gradients are
   dithered like every other gradient in the stack. */
.bg-vignette {
  opacity: var(--bg-vignette-op);
  background:
    radial-gradient(135% 105% at 50% 42%, rgba(0, 0, 0, 0) 52%, rgba(0, 0, 0, 0.38) 100%),
    linear-gradient(rgba(0, 0, 0, 0.12), rgba(0, 0, 0, 0) 18%);
}

/* engineering dither against banding: full-range noise at 1:1,
   soft-light, static — the topmost layer, compositing against the
   whole stack below it inside the isolated bgroot */
.bg-dither {
  mix-blend-mode: soft-light;
  background-image: var(--bg-dither-image);
  background-repeat: repeat;
  background-size: 240px 240px;
  opacity: var(--bg-dither-op);
}

/* dev tuning behind ?bg= (BRIEF §4b, head.html sets data-bg; no
   visible switchers): off = no background stack at all; flat =
   base + grad only, to check banding without the dither */
html[data-bg="off"] .bgroot {
  display: none;
}

html[data-bg="flat"] .bg-chroma,
html[data-bg="flat"] .bg-material,
html[data-bg="flat"] .bg-vignette,
html[data-bg="flat"] .bg-dither {
  display: none;
}

/* reduced motion: weave and chroma stop; field, matter, dither and
   vignette are static by nature — the material stays */
@media (prefers-reduced-motion: reduce) {
  :root {
    --bg-weave: paused;
    --bg-chroma: paused;
  }
}

main {
  flex: 1;
  position: relative;
  z-index: 2;
  padding: 0 var(--page-pad);
}

/* An overlay that lives INSIDE main is trapped in main's stacking
   context (the z-index: 2 above), so its own z-index is scoped there
   and cannot beat anything outside it. The header chrome is outside:
   .lang-switcher and the mobile .menu-trigger both sit at z-index 6
   against main's 2, so they painted straight through the player's
   scrim — the switcher landing on the ESC control, top right
   (03.09.2026, author). Raising .player itself does nothing about
   that; the context holding it has to outrank the header, and only
   while an overlay is open, so nothing else re-layers.
   Stays BELOW .menu-overlay (60), which is a sibling of main and
   keeps its own rule — the switcher is meant to stay readable there.
   overlay-player.js sets the class; the Film frames viewer has the
   same trapped-overlay shape and can join by setting it too. */
body.is-overlay-open main {
  z-index: 40;
}

a {
  color: inherit;
  text-decoration: none;
}

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

/* ============================================================
   Header: name / tagline / nav / language switcher
   ============================================================ */

.site-header {
  position: relative;
  z-index: 2;
  padding-top: var(--header-top);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--header-gap);
  text-align: center;
}

/* SLAVA … GRYSHANIN spread across a fixed comp width;
   the tagline row shares that width so it can end under the N.
   The name is a link to the index — but a logo, not a nav item:
   no hover underline or color shift. content-box + negative
   margins add a generous hit area without moving the comp. */
.site-header__name {
  display: flex;
  justify-content: space-between;
  width: var(--name-comp-width);
  box-sizing: content-box;
  padding: 10px 14px;
  margin: -10px -14px;
  font-family: var(--font-grotesque);
  font-weight: 500;
  font-size: var(--name-size);
  letter-spacing: var(--name-tracking);
  text-transform: uppercase;
  line-height: 1;
  color: var(--paper);
}

.site-header__tagline-row {
  width: var(--name-comp-width);
  display: flex;
  justify-content: flex-end; /* right-edge: ends under the final N (BRIEF §4) */
}

.site-header__tagline {
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 400;
  font-size: var(--tagline-size);
  letter-spacing: var(--tagline-tracking);
  line-height: 1;
  white-space: nowrap;
  color: var(--tagline-color);
  /* letter-spacing leaves a trailing gap after the final N inside the
     name row; pull the tagline back so it ends under the N itself */
  padding-right: calc(var(--name-size) * 0.24);
}

/* ---- nav row ---- */
.site-nav {
  margin-top: calc(3 * var(--u));
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.4em var(--nav-gap);
  font-family: var(--font-grotesque);
  font-size: var(--nav-size);
  letter-spacing: var(--nav-tracking);
  text-transform: uppercase;
}

/* hover: underline grows from center */
.site-nav a {
  position: relative;
  color: var(--secondary);
  padding-bottom: 3px;
  transition: color 0.35s ease;
}

.site-nav a::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: 0;
  width: 100%;
  height: 1px;
  background: var(--paper);
  transform: translateX(-50%) scaleX(0);
  transform-origin: center;
  transition: transform 0.45s var(--ease-slide);
}

.site-nav a:hover,
.site-nav a:focus-visible {
  color: var(--paper);
}

.site-nav a:hover::after,
.site-nav a:focus-visible::after {
  transform: translateX(-50%) scaleX(1);
}

/* current page: paper text over a static gray rule */
.site-nav a[aria-current="page"] {
  color: var(--paper);
}

.site-nav a[aria-current="page"]::after {
  background: var(--rule);
  transform: translateX(-50%) scaleX(1);
}

/* ---- language switcher, top right ---- */
.lang-switcher {
  position: absolute;
  top: var(--edge-x);
  right: var(--edge-x);
  z-index: 6;
  display: flex;
  gap: calc(14 * var(--u));
  font-family: var(--font-mono);
  font-size: max(calc(8.5 * var(--u)), 8px);
  letter-spacing: var(--meta-tracking);
}

.lang-switcher a {
  color: var(--secondary);
  border-bottom: 1px solid transparent;
  padding-bottom: 2px;
}

.lang-switcher a[aria-current="true"] {
  color: var(--paper);
  border-bottom-color: var(--rule-lang);
}

.lang-switcher a:hover {
  color: var(--paper);
}

/* ---- section header: oversized numeral + title + bracket ----
   shared by category grids, filmography, case pages */
.section-head {
  position: relative;
  z-index: 2;
  max-width: calc(1280 * var(--u));
  margin: calc(74 * var(--u)) auto 0;
  padding: 0 calc(64 * var(--u));
  display: flex;
  align-items: flex-end;
  gap: calc(36 * var(--u));
}

.section-head .numeral {
  font-size: calc(150 * var(--u));
  line-height: 0.78;
}

.section-head__text {
  display: flex;
  flex-direction: column;
  gap: calc(14 * var(--u));
  padding-bottom: calc(5 * var(--u));
}

.section-head__title {
  font-family: var(--font-grotesque);
  font-size: calc(30 * var(--u));
  font-weight: 400;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  line-height: 1;
  color: var(--paper);
}

.section-head__genre {
  font-family: var(--font-mono);
  font-size: max(calc(10.5 * var(--u)), 9px);
  letter-spacing: var(--meta-tracking);
  color: var(--secondary);
}

/* ---- roman numeral section anchors ---- */
.numeral {
  font-family: var(--font-serif);
  font-weight: 400;
  font-size: var(--numeral-size);
  line-height: 1;
  color: var(--numerals);
  opacity: var(--numeral-opacity);
  user-select: none;
}

/* ---- hover loops (BRIEF §8b): shared by Index strips and category
   work tiles. hover-loop.js creates the <video> lazily and only on
   fine-pointer, motion-ok devices; it fills its media container
   (.tile__media / .work__frame, both positioned) and crossfades in
   once frames actually play — no flash of unstyled video. Grade is
   locked to lift, so the loop keeps its original color (no filter).
   Vertical sources crop like the stills (cover, centered). ---- */
/* The loop layer's whole stylesheet sits inside the pointer guard:
   off a fine pointer the JS creates no <video> at all, so there is
   nothing here to style — and if one ever appeared it would be
   unstyled rather than shown, which is the safe direction. This
   replaces the `@media (hover: none) { .hover-loop { display: none } }`
   undo that used to stand here. */
/* ============================================================
   HOVER CHOREOGRAPHY IS POINTER-ONLY (14.09.2026)
   ------------------------------------------------------------
   On a touch device NO hover treatment exists — not a neutralised
   one, none: no zoom, no grade lift, no sibling dim, no preview
   loop. The passport says as much (§4: "the rest/hover pairing does
   not exist on touch"), and it used to be honoured rule by rule,
   each hover rule shipping a matching `@media (hover: none)` undo
   somewhere further down its stylesheet. That is one undo per rule
   to remember, it only ever covered the rules somebody remembered,
   and a rule and its undo drifted apart the moment either moved.

   So the branch is guarded ONCE, positively, in the same terms
   hover-loop.js already uses to decide whether to create a video —
   `(hover: hover) and (pointer: fine)` — and the undos are gone.
   What is not in this block does not exist off a fine pointer.

   KEYBOARD FOCUS IS NOT HOVER and stays outside the guard: a
   :focus-visible / :focus-within pairing is how a keyboard user sees
   what a pointer user sees, and it belongs on every device. Where a
   rule used to name both, the two are written apart — the shared
   declarations are two lines, which is cheaper than a guard that
   quietly takes accessibility with it.
   ============================================================ */
@media (hover: hover) and (pointer: fine) {
  .hover-loop {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    opacity: 0;
    transition: opacity 0.18s ease;
    pointer-events: none;
  }

  .is-looping .hover-loop {
    opacity: 1;
  }
}

/* ---- YouTube facade (shared): poster + our own mono play
   affordance — nothing YouTube-hosted loads until the click swaps in
   the nocookie iframe. Dry, in the ✕ ESC glyph language — no
   platform styling. Used by the overlay player (built in
   overlay-player.js) and the MV project pages (static markup +
   yt-facade.js). Fills a positioned media container; a missing
   poster leaves PLAY centered on the dark frame (layout intact). */
.facade {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  padding: 0;
  background: none;
  border: 0;
  cursor: pointer;
}

.facade img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: var(--grade-filter);
}

.facade__play {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  font-family: var(--font-mono);
  font-size: max(calc(11 * var(--u)), 10px);
  letter-spacing: 0.2em;
  color: var(--paper);
  text-shadow: 0 1px 18px rgba(14, 17, 22, 0.85);
  opacity: 0.85;
  transition: opacity 0.3s ease;
}

.facade__play::before {
  content: "";
  width: 0;
  height: 0;
  border-left: 9px solid currentColor;
  border-top: 6px solid transparent;
  border-bottom: 6px solid transparent;
  filter: drop-shadow(0 1px 10px rgba(14, 17, 22, 0.85));
}

.facade:hover .facade__play,
.facade:focus-visible .facade__play {
  opacity: 1;
}

/* ---- hero-header pages: chrome rides over a full-bleed hero ---- */
.has-hero-header {
  position: relative;
}

.has-hero-header main {
  padding: 0;
}

.has-hero-header .site-header {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: 5;
}

/* ---- prev / next rail: film details and case pages ---- */
.film-nav {
  position: relative;
  z-index: 2;
  max-width: calc(1280 * var(--u));
  margin: calc(110 * var(--u)) auto 0;
  padding: 0 calc(64 * var(--u));
}

.film-nav__inner {
  border-top: 1px solid rgba(94, 98, 104, 0.25);
  padding-top: calc(26 * var(--u));
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
}

.film-nav__col {
  display: flex;
  flex-direction: column;
  gap: calc(9 * var(--u));
  align-items: flex-start;
}

.film-nav__col--next {
  align-items: flex-end;
  text-align: right;
}

.film-nav__label {
  font-family: var(--font-mono);
  font-size: max(calc(9 * var(--u)), 8px);
  letter-spacing: 0.26em;
  color: var(--numerals);
}

.film-nav__link {
  font-family: var(--font-mono);
  font-size: max(calc(10.5 * var(--u)), 9px);
  letter-spacing: var(--meta-tracking);
  text-transform: uppercase;
  color: var(--secondary);
  transition: color 0.35s ease;
}

.film-nav__link:hover,
.film-nav__link:focus-visible {
  color: var(--paper);
}

/* ============================================================
   404 — the page Cloudflare Pages serves for a path it cannot
   match. Standard chrome, INK, no imagery: one mono line and the
   way back, centred on the space the header and footer leave.
   English in every locale, like all metadata (§1).
   ============================================================ */

.notfound {
  position: relative;
  z-index: 2;
  min-height: 46vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: calc(26 * var(--u));
  text-align: center;
}

.notfound__line {
  font-family: var(--font-mono);
  font-size: max(calc(13 * var(--u)), 11px);
  letter-spacing: 0.26em;
  color: var(--paper);
}

.notfound__link {
  font-family: var(--font-mono);
  font-size: var(--meta-size);
  letter-spacing: var(--meta-tracking);
  color: var(--secondary);
  transition: color 0.35s ease;
}

.notfound__link:hover,
.notfound__link:focus-visible {
  color: var(--paper);
}

/* ============================================================
   Footer
   ============================================================ */

.site-footer {
  position: relative;
  z-index: 2;
  padding: calc(var(--page-pad) * 0.75) var(--edge-x) var(--footer-bottom);
  text-align: right;
  font-family: var(--font-mono);
  font-size: var(--meta-size);
  letter-spacing: var(--meta-tracking);
  color: var(--numerals);
}

/* ============================================================
   Mobile menu (shared, every page) — base state. The MENU
   trigger and the overlay are desktop-hidden here; the mobile
   media block below turns them on. Keep these rules BEFORE the
   media block so the display:block override wins by source order.
   ============================================================ */
.menu-trigger {
  display: none; /* desktop shows the full nav row instead */
  font-family: var(--font-mono);
  font-size: max(calc(9.5 * var(--u)), 9px);
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--secondary);
  background: none;
  border: 0;
  padding: 2px 0;
  cursor: pointer;
  transition: color 0.3s ease;
}

.menu-trigger:hover,
.menu-trigger:focus-visible {
  color: var(--paper);
}

.menu-overlay {
  display: none; /* desktop: never shown, never tabbable */
}

/* body scroll lock while the overlay is open */
.menu-open {
  overflow: hidden;
}

/* ============================================================
   Mobile chrome (≤768px) — reference index-mobile.html frame A.
   The nav row is replaced by a MENU trigger top-left (mirroring
   the switcher top-right); the name collapses to one centered
   line with the tagline right-aligned beneath it.
   ============================================================ */
@media (max-width: 768px) {
  /* ------------------------------------------------------------
     TAP TARGETS (≤768px, 14.09.2026). MENU and the three switcher
     links were 8–9px of monospace with 2px of padding: a hit area
     about 13px tall, which a finger cannot reliably land on, and
     three of them 13px apart, so a near miss took you to another
     language rather than to nothing.

     Every one of the four is now a ≥44×44 box. The padding is on
     the LINK — the thing that receives the tap — never on a margin
     around it, and each container is pulled back by exactly that
     padding so the label stays in the corner it has always sat in.
     The glyph goes up one step with it (switcher 8 → 10px, MENU
     9 → 11px); the tracking is untouched, both being metadata.

     line-height drops to 1 so the box height is padding + glyph and
     nothing else, which is what makes the pull-back exact. Desktop
     is untouched — this block is the mobile chrome.
     ------------------------------------------------------------ */
  .lang-switcher {
    /* pulled back by the link padding: 18 − 17 and 20 − 14, so the
       glyphs still start at y 18 and end on the 20px page inset */
    top: 1px;
    right: calc(var(--edge-x) - 14px);
    /* clear space BETWEEN two 44px hit boxes — a near miss lands on
       nothing rather than on the next language */
    gap: 14px;
    font-size: 10px;
  }

  .lang-switcher a {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    min-width: 44px;
    min-height: 44px;
    padding: 17px 14px;
    line-height: 1;
    /* the active underline cannot ride the link's own border here —
       it would hang 17px under the word. It is drawn against the
       glyph instead (below), so the border comes off. */
    border-bottom: 0;
  }

  .lang-switcher a[aria-current="true"]::after {
    content: "";
    position: absolute;
    left: 14px;
    right: 14px;
    top: calc(17px + 1em + 2px);
    height: 1px;
    background: var(--rule-lang);
  }

  .menu-trigger {
    display: flex;
    align-items: center;
    justify-content: center;
    position: absolute;
    /* same pull-back: 18 − 17 vertically, 20 − 8 horizontally */
    top: 1px;
    left: calc(var(--edge-x) - 8px);
    z-index: 6;
    min-width: 44px;
    min-height: 44px;
    padding: 17px 8px;
    font-size: 11px;
    line-height: 1;
  }

  .site-nav {
    display: none; /* navigation lives in the overlay */
  }

  .site-header {
    align-items: stretch;
    padding: var(--header-top) var(--edge-x) 0;
    gap: var(--header-gap);
  }

  /* single centered name line; letter-spacing tightened to 0.185em
     to fit 390px. width:auto + align-self keep the padded link's
     hit area snug around the text instead of full-bleed */
  .site-header__name {
    width: auto;
    align-self: center;
    justify-content: center;
    gap: 0.34em;
    letter-spacing: 0.185em;
  }

  .site-header__tagline-row {
    width: 100%;
    justify-content: flex-end;
  }

  .site-header__tagline {
    padding-right: 0;
  }

  .section-head {
    margin-top: 44px;
    padding: 0 var(--edge-x);
    gap: 20px;
  }

  .section-head .numeral {
    font-size: 92px;
  }

  .section-head__title {
    font-size: 20px;
    letter-spacing: 0.26em;
  }

  .film-nav {
    margin-top: 72px;
    padding: 0 var(--edge-x);
  }

  /* ---- full-screen INK menu overlay ---- */
  .menu-overlay {
    display: flex;
    flex-direction: column;
    position: fixed;
    inset: 0;
    z-index: 60;
    background: rgba(14, 17, 22, 0.96);
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: opacity 0.3s ease, visibility 0s linear 0.3s;
  }

  .menu-overlay.is-open {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
    transition: opacity 0.3s ease;
  }

  /* material + dither over the ink — the overlay reads as the same
     medium as the page background, statically (a separate plane:
     no chroma, no weave); z:-1 = below the menu content */
  .menu-overlay::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    mix-blend-mode: screen;
    image-rendering: pixelated;
    background-image: var(--bg-material-image);
    background-repeat: repeat;
    background-size: calc(240px * var(--bg-material-scale)) calc(240px * var(--bg-material-scale));
    opacity: var(--bg-material-op);
  }

  .menu-overlay::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    mix-blend-mode: soft-light;
    background-image: var(--bg-dither-image);
    background-repeat: repeat;
    background-size: 240px 240px;
    opacity: var(--bg-dither-op);
  }

  .menu-overlay__close {
    align-self: flex-end;
    margin: 18px var(--edge-x) 0;
    z-index: 2;
    font-family: var(--font-mono);
    font-size: 11px;
    letter-spacing: 0.22em;
    color: var(--paper);
    background: none;
    border: 0;
    padding: 4px;
    cursor: pointer;
  }

  .menu-nav {
    position: relative;
    z-index: 2;
    flex: 1;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: flex-start;
    gap: 26px;
    padding: 0 var(--edge-x) 40px;
  }

  .menu-nav__group {
    display: flex;
    flex-direction: column;
    gap: 8px;
  }

  .menu-nav a {
    font-family: var(--font-grotesque);
    font-size: 20px;
    font-weight: 500;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    line-height: 1;
    color: var(--paper);
  }

  .menu-nav a[aria-current="page"] {
    border-bottom: 1px solid var(--rule);
    padding-bottom: 3px;
  }

  .menu-nav__bracket {
    font-family: var(--font-mono);
    font-size: 9px;
    letter-spacing: 0.14em;
    color: var(--secondary);
  }
}

/* (The touch undo that used to close this file is gone: the hover
   rule it neutralised now lives inside the pointer guard above.) */

/* Keyboard-only bypass; absolute placement leaves the resting layout intact. */
.skip-link {
  position: fixed;
  top: 8px;
  left: 8px;
  z-index: 1000;
  transform: translateY(calc(-100% - 16px));
  padding: 10px 14px;
  background: var(--ink);
  color: var(--paper);
  font: 12px/1.5 var(--font-mono);
}

.skip-link:focus-visible {
  transform: none;
  outline: 1px solid var(--paper);
  outline-offset: 2px;
}

/* The tagline's existing class already resets h1; preserve the About lead
   and the following paragraph's spacing when its first p becomes h1. */
h1.statement__lead {
  margin: 0;
  padding: 0;
  font: 400 clamp(28px, 3.2vw, 32px)/1.2 var(--font-serif);
  color: var(--paper);
}

h1.statement__lead + p {
  margin-top: 1.6em;
}
