/* ==========================================================================
   db5ive — global.css
   Tokens, reset, type scale, layout, nav, footer, buttons, motion.
   Governed by build-spec §5 (design system) and §6 (components).

   RULE: every spacing value is a multiple of 8px. Every font size is a token.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. FONTS — self-hosted, no CDN

   Jost is the display face. It was originally loaded as a stand-in for
   Brockmann (Atipo Foundry); that plan was dropped on 19 Aug 2026 — David
   chose to stay on Jost for now and revisit the face later if he wants to.
   There is nothing pending here and nothing to grep for.

   Both families are variable and ROMAN ONLY. Neither ships an italic, so
   italic anywhere will be synthesised by the browser. Do not set italic.
   -------------------------------------------------------------------------- */

@font-face {
  font-family: "Jost";
  src: url("../assets/fonts/jost-var.woff2") format("woff2-variations"),
       url("../assets/fonts/jost-var.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Newsreader";
  src: url("../assets/fonts/newsreader-var.woff2") format("woff2-variations"),
       url("../assets/fonts/newsreader-var.woff2") format("woff2");
  font-weight: 200 800;
  font-style: normal;
  font-display: swap;
}

/* --------------------------------------------------------------------------
   2. TOKENS
   -------------------------------------------------------------------------- */

:root {
  /* --- Families (build-spec §5.1) --- */
  --font-display: "Jost", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --font-reading: "Newsreader", Georgia, "Times New Roman", serif;

  /* --- Type scale (build-spec §5.1) — seven sizes, no ad-hoc values ---
     Fluid between 375px and 1440px viewports. */
  --fs-hero:     clamp(2.75rem,   1.9577rem + 3.3804vw, 5rem);
  --fs-h1:       clamp(2.125rem,  1.6409rem + 2.0657vw, 3.5rem);
  --fs-h2:       clamp(1.5rem,    1.2359rem + 1.1268vw, 2.25rem);
  --fs-quote:    clamp(1.625rem,  1.2289rem + 1.6902vw, 2.75rem);
  --fs-body-lg:  clamp(1.125rem,  1.0590rem + 0.2817vw, 1.3125rem);
  --fs-body:     clamp(1.0625rem, 1.0185rem + 0.1878vw, 1.1875rem);
  --fs-small:    clamp(0.8125rem, 0.7905rem + 0.0939vw, 0.875rem);

  /* --- Line heights (build-spec §5.1) --- */
  --lh-display: 1.1;
  --lh-quote:   1.2;
  --lh-body-lg: 1.5;
  --lh-body:    1.65;

  /* --- Tracking (build-spec §5.1) — geometric faces need pulling in at scale --- */
  --track-hero:  -0.03em;
  --track-head:  -0.02em;
  --track-label:  0.12em;

  /* --- Neutrals (build-spec §5.2) ---
     Cool, per the spec's stated intent — "built cool and clean rather than
     warm and printed". Held one step harder than the spec's literal values at
     David's request for more contrast: the hue is unchanged, the ends of the
     range are pushed apart. Spec values in the right-hand comments.        */
  --paper:     #FFFFFF;  /* §5.2 #FFFFFF — unchanged */
  --paper-alt: #EEF2F6;  /* §5.2 #F5F7F9 — deeper, so the bands read apart */
  --ink:       #0E131A;  /* §5.2 #12171F — darker */
  --ink-muted: #4A5563;  /* §5.2 #5B6573 — darker: 5.9:1 -> 7.6:1 */
  --rule:      #D5DDE5;  /* §5.2 #E4E9EE — crisper hairline */

  /* --- Accent — cobalt. Final. (build-spec §5.2) --- */
  --blue:       #0047AB;
  --blue-hover: #003A8C;
  --blue-wash:  #EAF0FB;
  /* Lifted from #5B8DEF as --deep got lighter. The binding pair is the close
     CTA — a --blue-light panel with --deep text — which had fallen to 4.66:1.
     At #6D9BF1 it is 5.4:1. ONLY on --deep. Never on white. */
  --blue-light: #6D9BF1;

  /* --- Inverted (build-spec §5.2) ---
     --deep started at #0A0E14 (effectively black), which slammed against the
     white footer beneath it. Lifted twice, now a slate charcoal — still an
     unmistakable dark band, far softer at the boundary.

     This is about as light as it can go: the CTA on this section is a
     --blue-light panel with --deep text, and that pair is the binding
     constraint, not the body text. At #1F2733 it holds ~4.7:1; much lighter
     and the button label drops below AA. */
  --deep:      #1F2733;  /* §5.2 #0D121A */
  --deep-text: #F4F7FA;  /* §5.2 #F2F5F8 */
  --deep-muted: #9AA6B4;
  --deep-rule: rgba(244, 247, 250, 0.16);

  /* --- Spacing — 8px base unit, no exceptions (build-spec §5.4) --- */
  --sp-1:  0.5rem;   /*   8px */
  --sp-2:  1rem;     /*  16px */
  --sp-3:  1.5rem;   /*  24px */
  --sp-4:  2rem;     /*  32px */
  --sp-5:  2.5rem;   /*  40px */
  --sp-6:  3rem;     /*  48px */
  --sp-7:  3.5rem;   /*  56px */
  --sp-8:  4rem;     /*  64px */
  --sp-10: 5rem;     /*  80px */
  --sp-12: 6rem;     /*  96px */
  --sp-14: 7rem;     /* 112px */
  --sp-16: 8rem;     /* 128px */

  /* Section rhythm (build-spec §5.4) — err generous */
  --section-y: clamp(6rem, 13vh, 10rem);

  /* --- Layout (build-spec §5.4) --- */
  --container:  74rem;   /* 1184px */
  --measure:    36rem;   /* 576px — 62–68 characters */
  --gutter:     var(--sp-3);
  --grid-gap:   var(--sp-3);

  /* --- Motion — one curve, one duration, everywhere (build-spec §5.6) --- */
  --ease:        cubic-bezier(0.16, 1, 0.3, 1);
  --dur-entrance: 500ms;
  --dur-hover:    200ms;
  /* Gap between staggered siblings in a revealed group. One curve and one
     duration still apply — only the start time differs. */
  --stagger:      80ms;
}

/* --------------------------------------------------------------------------
   3. RESET
   -------------------------------------------------------------------------- */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body,
h1, h2, h3, h4, p, figure, blockquote, dl, dd, ul, ol {
  margin: 0;
  padding: 0;
}

ul, ol { list-style: none; }

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

button,
input,
textarea {
  font: inherit;
  color: inherit;
}

/* --------------------------------------------------------------------------
   4. BASE
   -------------------------------------------------------------------------- */

body {
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-reading);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

/* Headings — display family, weight ≤ 500, tight tracking (build-spec §5.1) */
h1, h2, h3 {
  font-family: var(--font-display);
  font-weight: 500;
  line-height: var(--lh-display);
  letter-spacing: var(--track-head);
  text-wrap: balance;
}

h1 { font-size: var(--fs-h1); }
h2 { font-size: var(--fs-h2); }
h3 { font-size: var(--fs-h2); }

p { text-wrap: pretty; }

p + p { margin-top: var(--sp-3); }

strong { font-weight: 600; }

/* Links — underline offset transition, no color flash (build-spec §5.6) */
a {
  color: var(--blue);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
  transition: text-decoration-thickness var(--dur-hover) var(--ease),
              text-underline-offset var(--dur-hover) var(--ease);
}

a:hover {
  text-decoration-thickness: 2px;
  text-underline-offset: 0.22em;
}

/* Visible focus everywhere (build-spec §9) */
:focus-visible {
  outline: 2px solid var(--blue);
  outline-offset: 3px;
  border-radius: 1px;
}

.section-dark :focus-visible { outline-color: var(--blue-light); }

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

/* --------------------------------------------------------------------------
   5. LAYOUT
   -------------------------------------------------------------------------- */

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

@media (min-width: 48em) {
  :root { --gutter: var(--sp-5); }
}

/* 12-column grid — place things on it (build-spec §5.4) */
.grid-12 {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: var(--grid-gap);
}

/* Prose measure — 62–68 characters (build-spec §5.1) */
.measure { max-width: var(--measure); }

.measure-wide { max-width: 48rem; }

.section {
  padding-block: var(--section-y);
}

.section-alt { background: var(--paper-alt); }

/* Dark sections — used sparingly; currently [HOME-02] only (build-spec §5.5) */
.section-dark {
  background: var(--deep);
  color: var(--deep-text);
}

.section-dark h1,
.section-dark h2,
.section-dark h3 { color: var(--deep-text); }

.section-dark a { color: var(--blue-light); }
.section-dark a:hover { color: var(--blue-light); }

.hairline-top { border-top: 1px solid var(--rule); }

/* --------------------------------------------------------------------------
   6. TYPE UTILITIES
   -------------------------------------------------------------------------- */

/* Eyebrows and small labels (build-spec §5.1) */
.eyebrow {
  font-family: var(--font-display);
  font-size: var(--fs-small);
  font-weight: 500;
  line-height: 1.4;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink-muted);
}

.section-dark .eyebrow { color: var(--deep-muted); }

.standfirst {
  font-family: var(--font-reading);
  font-size: var(--fs-body-lg);
  line-height: var(--lh-body-lg);
  color: var(--ink-muted);
}

.lede {
  font-size: var(--fs-body-lg);
  line-height: var(--lh-body-lg);
}

.caption {
  font-family: var(--font-display);
  font-size: var(--fs-small);
  line-height: 1.5;
  color: var(--ink-muted);
}

/* Pull quotes — space and scale do the work.
   No quote glyphs, no italic, no border bar, no blue (build-spec §7).
   NOTE: this is .pullquote, currently unused. The [HOME-02] blockquote is a
   separate component (.statement-quote in pages.css) and deliberately does use
   generated quote marks in --blue-light. */
.pullquote {
  font-family: var(--font-display);
  font-size: var(--fs-quote);
  font-weight: 400;
  line-height: var(--lh-quote);
  letter-spacing: var(--track-head);
  color: var(--ink);
  max-width: 28ch;               /* deliberately breaks the prose measure */
  margin-block: var(--sp-8);
  text-wrap: balance;
}

.section-dark .pullquote { color: var(--deep-text); }

/* --------------------------------------------------------------------------
   7. BUTTONS — one primary, one secondary. Nothing else. (build-spec §7)
   -------------------------------------------------------------------------- */

.btn {
  display: inline-block;
  font-family: var(--font-display);
  font-size: var(--fs-small);
  font-weight: 500;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  text-decoration: none;
  border: 1px solid transparent;
  cursor: pointer;
}

/* The one solid blue element on the page */
.btn-primary {
  background: var(--blue);
  color: var(--paper);
  padding: var(--sp-2) var(--sp-3);
  border-radius: 2px;
  transition: background var(--dur-hover) var(--ease);
}

.btn-primary:hover { background: var(--blue-hover); }

.section-dark .btn-primary {
  background: var(--blue-light);
  color: var(--deep);
}

.section-dark .btn-primary:hover { background: #7BA5F3; }

.btn-secondary {
  background: none;
  color: var(--blue);
  padding: var(--sp-2) 0;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.35em;
  transition: text-decoration-thickness var(--dur-hover) var(--ease),
              text-underline-offset var(--dur-hover) var(--ease);
}

.btn-secondary:hover {
  text-decoration-thickness: 2px;
  text-underline-offset: 0.4em;
}

.section-dark .btn-secondary { color: var(--blue-light); }

.btn-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-4);
}

/* Standalone forward link, e.g. "How I work →" */
.link-forward {
  font-family: var(--font-display);
  font-size: var(--fs-small);
  font-weight: 500;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--blue);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.35em;
}

.section-dark .link-forward { color: var(--blue-light); }

/* --------------------------------------------------------------------------
   8. SKIP LINK
   -------------------------------------------------------------------------- */

.skip-link {
  position: absolute;
  top: var(--sp-1);
  left: var(--sp-1);
  z-index: 100;
  padding: var(--sp-2);
  background: var(--ink);
  color: var(--paper);
  font-family: var(--font-display);
  font-size: var(--fs-small);
  text-decoration: none;
  transform: translateY(-200%);
}

.skip-link:focus { transform: translateY(0); }

/* --------------------------------------------------------------------------
   9. NAV (build-spec §6, §7)
   Sticky, paper background, hairline rule that fades in only after scroll.
   -------------------------------------------------------------------------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--paper);
  border-bottom: 1px solid transparent;
  transition: border-color var(--dur-hover) var(--ease);
}

.site-header.is-scrolled { border-bottom-color: var(--rule); }

.site-header > .container {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  min-height: var(--sp-5);
  padding-block: var(--sp-1);
}

/* Primary lockup: db5 mark | DB5IVE wordmark (build-spec §6) */
.lockup {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  text-decoration: none;
  color: var(--ink);
  /* Clear space ≥ height of the d (build-spec §6) */
  padding-right: var(--sp-2);
}

.lockup:hover { text-decoration: none; }

/* Optically sized, not mathematically — geometric marks sit visually
   larger than their bounding box suggests (build-spec §6). */
.lockup-mark {
  width: auto;
  height: 22px;
  flex: none;
}

.lockup-rule {
  width: 1px;
  height: 16px;
  background: var(--rule);
  flex: none;
}

.lockup-word {
  font-family: var(--font-display);
  font-size: var(--fs-small);
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  line-height: 1;
  /* optical: uppercase sits high, nudge to the mark's visual centre */
  padding-top: 1px;
}

/* The "5" is set in --blue wherever DB5IVE appears in text form (build-spec §6) */
.lockup-word .five { color: var(--blue); }

.nav-links {
  display: none;
  align-items: center;
  gap: var(--sp-4);
}

/* Was 64em. The inline nav measures ~731px plus a 138px lockup and 80px of
   gutter, so it fits comfortably from 60em — and below 64em a desktop window
   was falling back to the hamburger and showing no labels at all. The gap
   tightens to --sp-3 in the range where space is tight and returns to --sp-4
   above 75em. */
@media (min-width: 60em) {
  .nav-links { display: flex; gap: var(--sp-3); }
}

@media (min-width: 75em) {
  .nav-links { gap: var(--sp-4); }
}

.nav-links a {
  font-family: var(--font-display);
  font-size: var(--fs-small);
  font-weight: 400;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink);
  text-decoration: none;
  white-space: nowrap;
  padding-block: var(--sp-1);
  border-bottom: 1px solid transparent;
  transition: border-color var(--dur-hover) var(--ease);
}

.nav-links a:hover { border-bottom-color: var(--ink); }

/* Current page. At rest this is the ONLY underlined item in the nav, which is
   what makes it read as "you are here"; hover underlines the others only while
   the pointer is on them.

   [aria-current] with no value matches both forms: "page" on an exact match, and
   "true" on a story page, where The Work is the section containing the current
   page rather than the page itself.

   Before this existed nothing set aria-current at all, so the only coloured item
   in the nav was the CTA — which read as a selection state rather than as the
   action it is. */
.nav-links a[aria-current] {
  color: var(--ink);
  border-bottom-color: var(--ink);
}

.mobile-nav a[aria-current] {
  color: var(--ink);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.35em;
}

/* Nav CTA is a blue-underlined link, NOT a solid button — the solid blue
   button is reserved for the one primary CTA in the page body (build-spec §5.2). */
.nav-links a.nav-cta,
.nav-cta {
  font-family: var(--font-display);
  font-size: var(--fs-small);
  font-weight: 500;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--blue);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.35em;
  white-space: nowrap;
  border-bottom: 0;
}

.nav-links a.nav-cta:hover { border-bottom-color: transparent; }

/* Mobile: full-screen overlay, generous type (build-spec §7) */
.nav-toggle {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  min-height: var(--sp-6);
  padding: var(--sp-1) 0;
  background: none;
  border: 0;
  font-family: var(--font-display);
  font-size: var(--fs-small);
  font-weight: 500;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink);
  cursor: pointer;
}

@media (min-width: 60em) {
  .nav-toggle { display: none; }
}

.mobile-nav {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: none;
  flex-direction: column;
  justify-content: center;
  background: var(--paper);
  padding: var(--sp-8) var(--gutter);
}

.mobile-nav.is-open { display: flex; }

/* Must track the .nav-toggle breakpoint above, or between 60em and 64em the
   overlay could stay open with no visible control to close it. */
@media (min-width: 60em) {
  .mobile-nav.is-open { display: none; }
}

.mobile-nav-close {
  position: absolute;
  top: var(--sp-3);
  right: var(--gutter);
  min-height: var(--sp-6);
  padding: var(--sp-1) 0;
  background: none;
  border: 0;
  font-family: var(--font-display);
  font-size: var(--fs-small);
  font-weight: 500;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink);
  cursor: pointer;
}

.mobile-nav ul {
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
  max-width: var(--container);
  margin-inline: auto;
  width: 100%;
}

.mobile-nav ul a {
  font-family: var(--font-display);
  font-size: var(--fs-h2);
  font-weight: 400;
  letter-spacing: var(--track-head);
  text-transform: none;
  color: var(--ink);
  text-decoration: none;
}

.mobile-nav .nav-cta {
  display: inline-block;
  margin-top: var(--sp-6);
  font-size: var(--fs-small);
}

/* --------------------------------------------------------------------------
   10. FOOTER (build-spec §7)
   Stacked lockup, tagline, contact, legal. Hairline top rule.
   -------------------------------------------------------------------------- */

.site-footer {
  border-top: 1px solid var(--rule);
  padding-block: var(--sp-5) var(--sp-4);
}

.footer-grid {
  display: grid;
  gap: var(--sp-6);
  grid-template-columns: 1fr;
}

/* Lockup, tagline, email on one line — the tagline centred between the two.
   Outer columns are sized to content so the centre column is genuinely the
   middle of the row. */
@media (min-width: 48em) {
  .footer-grid {
    grid-template-columns: auto 1fr auto;
    align-items: center;
    column-gap: var(--sp-8);
    row-gap: var(--sp-3);
  }
}

/* Stacked lockup: mark over rule over DB5IVE (build-spec §6) */
.footer-lockup {
  display: inline-flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--sp-1);
  text-decoration: none;
  color: var(--ink);
}

.footer-lockup:hover { text-decoration: none; }

.footer-lockup img {
  height: 24px;
  width: auto;
}

/* Stacked lockup: mark over rule over DB5IVE (build-spec §6). The rule is sized to
   the wordmark beneath it, not to the column — a rule that runs wider than
   the lockup stops reading as part of the mark. */
.footer-lockup .footer-rule {
  width: 72px;
  height: 1px;
  background: var(--rule);
  margin-block: var(--sp-1);
}

.footer-lockup .lockup-word { font-size: var(--fs-small); }

/* Copy v2 replaced the tagline with the four-part operating proposition, which
   is roughly twice as long. The nowrap that kept the old one on a single line
   would now push the footer past the container, so it wraps — held to a
   measure so it breaks in a controlled place rather than running the full
   column width. */
/* Quieter than it was. At --fs-body-lg it competed with the lockup and read
   as a statement floating in the middle of the row rather than as a line of
   footer furniture sitting level with the email. */
/* The footer's children are adjacent <p>s, so the base `p + p` rule was giving
   the email a 24px top margin. Centring a margin box drops the border box by
   half of it — which is exactly why the email sat 12px below the tagline. */
.footer-grid > p { margin-top: 0; }

.footer-tagline {
  font-family: var(--font-reading);
  font-size: var(--fs-body);
  line-height: var(--lh-body-lg);
  color: var(--ink);
}

@media (min-width: 48em) {
  .footer-tagline { text-align: center; }
}

/* Contact is one inline pair separated by the middot the copy doc uses.
   Stacked and flush right, two links of different lengths left a ragged left
   edge and read as an afterthought. */
.footer-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--sp-1) var(--sp-2);
  font-family: var(--font-display);
  font-size: var(--fs-small);
  color: var(--ink-muted);
}

@media (min-width: 48em) {
  .footer-meta { justify-content: flex-end; }
}

/* LinkedIn removed at David's request, so the middot separator is unused. */

/* Visible but quiet — --rule is near-invisible on white */
.footer-sep { color: var(--ink-muted); opacity: 0.55; }

.footer-meta a { color: var(--ink-muted); }
.footer-meta a:hover { color: var(--blue); }

/* Legal sits below a hairline that spans the full footer width */
.footer-legal {
  grid-column: 1 / -1;
  padding-top: var(--sp-2);
  border-top: 1px solid var(--rule);
  font-family: var(--font-display);
  font-size: var(--fs-small);
  color: var(--ink-muted);
}

/* --------------------------------------------------------------------------
   11. MOTION (build-spec §5.6)
   Fade-and-rise on entry, 20px, once per element, never repeating.
   Guarded by .js so content is visible with JavaScript disabled (build-spec §9).
   -------------------------------------------------------------------------- */

.js [data-reveal] {
  opacity: 0;
  transform: translateY(20px);
  transition: opacity var(--dur-entrance) var(--ease),
              transform var(--dur-entrance) var(--ease);
}

.js [data-reveal].is-visible {
  opacity: 1;
  transform: none;
}

/* Staggered groups: the CONTAINER is observed, and its children come in one
   after another from that single trigger. This is why the children are not
   individually observed — six separate observers firing at six different
   scroll positions reads as noise; one trigger with a cascade reads as a
   deliberate sequence. */
.js [data-reveal-group] > * {
  opacity: 0;
  transform: translateY(20px);
  transition: opacity var(--dur-entrance) var(--ease),
              transform var(--dur-entrance) var(--ease);
}

.js [data-reveal-group].is-visible > * {
  opacity: 1;
  transform: none;
}

.js [data-reveal-group] > *:nth-child(2) { transition-delay: calc(var(--stagger) * 1); }
.js [data-reveal-group] > *:nth-child(3) { transition-delay: calc(var(--stagger) * 2); }
.js [data-reveal-group] > *:nth-child(4) { transition-delay: calc(var(--stagger) * 3); }
.js [data-reveal-group] > *:nth-child(5) { transition-delay: calc(var(--stagger) * 4); }
/* Held at five steps — past ~400ms the tail of a long list feels slow */
.js [data-reveal-group] > *:nth-child(n + 6) { transition-delay: calc(var(--stagger) * 5); }

/* --------------------------------------------------------------------------
   12. TOUCH TARGETS

   On coarse pointers every interactive element needs a 44×44 minimum hit
   area. These rules extend the hit area with a pseudo-element rather than
   with padding, so the visual layout and the 8px spacing rhythm are
   untouched — the editorial density on desktop is the point of the design.
   -------------------------------------------------------------------------- */

@media (pointer: coarse) {
  .lockup,
  .link-forward,
  .nav-cta {
    position: relative;
  }

  .lockup::after,
  .link-forward::after,
  .nav-cta::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    top: 50%;
    height: 44px;
    transform: translateY(-50%);
  }

  .nav-toggle { padding-inline: var(--sp-1); }

  /* Inline pair wraps rather than stacking; the vertical padding gives each
     link its 44px without the two hit areas colliding. */
  .footer-meta { gap: var(--sp-1) var(--sp-3); }

  .footer-meta a { padding-block: var(--sp-2); }
}

@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;
    scroll-behavior: auto !important;
  }

  .js [data-reveal],
  .js [data-reveal-group] > * {
    opacity: 1;
    transform: none;
    transition-delay: 0ms;
  }
}
