.wrap { max-width: var(--content); margin-inline: auto; }
.wrap--narrow { max-width: var(--content-narrow); margin-inline: auto; }

.section { padding: 0 var(--gutter) var(--section-y); }
.section--top { padding-top: var(--section-y); }

/* Sticky header is ~75px; keep anchor targets clear of it. */
[id] { scroll-margin-top: 78px; }
.section--band { padding-block: var(--section-y); } /* was its own smaller clamp -- unified with every plain .section's gap */
.section--deep { background: var(--bg-deep); border-block: 1px solid var(--line-soft); }
.section--navy { background: var(--navy); }
.section--accent { background: var(--accent); color: var(--ink-on-accent); }

/* Header */
.header {
  position: sticky;
  top: 0;
  z-index: 60;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding: 15px var(--gutter);
  background: rgba(22, 22, 22, 0.82);
  backdrop-filter: blur(16px);
  border-bottom: 1px solid var(--line-soft);
}

.wordmark {
  display: flex;
  align-items: center;
  min-height: 26px;
  color: var(--fg);
  font-size: 19px;
  font-weight: 800;
  letter-spacing: -0.025em;
}
.wordmark:hover { color: var(--fg); }
.wordmark em { color: var(--accent); font-style: normal; }

.nav { display: flex; align-items: center; gap: clamp(12px, 2.4vw, 30px); }
/* Two qualifiers, both load-bearing:
   `:not(.btn)` — buttons carry their own colour/weight and must not be
   overridden by this more specific selector.
   `>` — the language switcher's link is nested inside span.lang, and this
   selector (0,2,1) outranks `.lang a` (0,1,1). Without the child combinator
   it leaks 14px/500/--fg-body onto that link, which made the *inactive*
   language render larger and brighter than the active one. */
.nav > a:not(.btn) { display: flex; align-items: center; min-height: 44px; color: var(--fg-body); font-size: 14px; font-weight: 500; }
.nav > a:not(.btn):hover { color: var(--accent); }

/* Language switcher: the current language is the emphasised one. Both items
   share a size — mismatched sizes in a two-item toggle read as a rendering
   fault rather than as emphasis — so the hierarchy comes from weight and
   colour. min-height keeps the link a ≥24px target (WCAG 2.2 2.5.8); it is
   not an inline-in-a-sentence link, so that exemption does not apply. */
.lang { display: flex; align-items: center; gap: 7px; font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.06em; }
.lang span[aria-current] { color: var(--fg); font-weight: 700; }
.lang a { display: inline-flex; align-items: center; min-height: 24px; padding-inline: 2px; color: var(--fg-muted); font-weight: 400; }
.lang a:hover { color: var(--accent); }
.lang .sep { color: var(--fg-faint); }

/* Hero */
.hero { padding: clamp(40px, 6vw, 80px) var(--gutter) 0; }
.hero h1 {
  margin-top: clamp(20px, 3vw, 36px);
  font-size: var(--step-hero);
  line-height: 0.88;
  font-weight: 800;
  letter-spacing: -0.035em;
  text-transform: uppercase;
}
/* Direct children only. The nested .dim / .accent spans colour a word inside a
   line — making them blocks too would break each line in half. */
.hero h1 > span { display: block; }
.hero h1 .dim { color: var(--fg-quiet); }
.hero h1 .accent { color: var(--accent); }
.hero__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: clamp(22px, 4vw, 64px);
  margin-top: clamp(32px, 4.5vw, 54px);
}
.hero__foot .lead { max-width: 72ch; font-size: clamp(15px, 1.15vw, 17px); }

.status { display: flex; align-items: center; gap: 10px; }
.status__dot { width: 7px; height: 7px; border-radius: 50%; background: var(--accent); animation: pulse 2.8s ease-in-out infinite; }

/* Story */
/* Base rules — a plain stacked list. This is the whole story with no JS and
   the whole story under reduced motion; the pinned wave sequence below only
   ever adds to it, never replaces its content. */
.story { display: flex; flex-direction: column; gap: clamp(24px, 4.5vh, 50px); padding-top: clamp(14px, 2.5vh, 36px); padding-bottom: var(--section-y); } /* was its own larger clamp -- unified with every other section's gap */
.story p { font-size: var(--step-story); line-height: 1.12; font-weight: 600; letter-spacing: -0.025em; color: var(--fg); }
.story p.turn { margin-top: clamp(14px, 3vh, 30px); font-weight: 700; color: var(--fg); }
.story p.punch { font-size: clamp(30px, 5.4vw, 72px); line-height: 1.04; font-weight: 800; letter-spacing: -0.03em; text-transform: uppercase; color: var(--fg); }
.story p.punch em { color: var(--accent); font-style: normal; }

/* Pinned wave sequence (js/main.js drives opacity + transform per frame).
   One phrase fades in, holds, fades out, then the next — except the last
   two, which hold together as a pair (top line, bottom line) once shown.
   --pin-wave is the scroll distance one wave takes; retune it (and the
   ratio math is 1/phrase-count in JS) if a phrase is ever added or removed.
   Gated to JS + no-reduced-motion so the base rules above are always the
   fallback. */
@media (prefers-reduced-motion: no-preference) {
  .js .pin-story {
    --pin-wave: 130vh;
    position: relative;
    height: calc(var(--pin-wave) * 5);
    padding-bottom: 0;
  }
  .js .pin-story__view {
    position: sticky;
    top: 78px; /* clears the ~75px sticky header, see [id] scroll-margin-top above */
    height: calc(100vh - 78px);
    overflow: hidden;
    display: flex;
    align-items: center;
  }
  .js .pin-story__view .story {
    position: relative;
    width: 100%;
    height: 100%;
    padding: 0;
    gap: 0;
  }
  .js .pin-story__view .story p {
    position: absolute;
    left: 0;
    right: 0;
    top: 50%;
    opacity: 0;
  }
  .js .pin-story__view .story p[data-phrase-top] { top: 42%; }
  .js .pin-story__view .story p[data-phrase-bottom] { top: 58%; }
}

/* Section heads */
.head { display: flex; align-items: center; gap: 14px; }
.head__rule { flex: 1; height: 1px; background: var(--line); }

/* Grids */
.grid { display: grid; gap: clamp(14px, 1.6vw, 22px); margin-top: clamp(26px, 4vw, 44px); }
.grid--split { grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr)); }
.grid--quad { grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr)); }
.grid--seam {
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: 18px;
  overflow: hidden;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 270px), 1fr));
}

/* About */
/* The head label sits directly in .wrap.about, full width, same as every
   other section's header row. Below it, .about__grid is photo-first, text
   second: the photo column is only as wide as the photo itself (auto),
   the text column takes the rest (1fr) and reads left-aligned right next
   to it -- no more equal-width columns leaving a big dead gap between a
   narrow photo and the text beside it. Stacks to one column below 640px. */
.about { display: flex; flex-direction: column; gap: clamp(24px, 4vw, 40px); }
.about .label { color: var(--on-navy); }
.about__grid {
  /* Same value feeds the gap between photo/text AND the indent before the
     photo, so there's no flush-left photo sitting right at the edge while
     text gets breathing room on its side. */
  --about-gap: clamp(30px, 5vw, 72px);
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--about-gap);
  padding-left: var(--about-gap);
}
@media (min-width: 640px) {
  .about__grid { grid-template-columns: auto 1fr; }
}
.about__text { display: flex; flex-direction: column; }
/* Hardcoded, not margin-top: auto -- auto pushes flush to the very bottom
   of the stretched column (matching the photo's height), leaving no gap
   below the button. 78px centers it in the leftover space instead: photo
   ~400px tall, heading+paragraphs ~200px, so ~200px left over; minus the
   button's own ~44px, split evenly above/below is (200-44)/2 =~ 78px. */
.about__text .about__cta { margin-top: 78px; }
.about h2 { font-size: clamp(30px, 3.8vw, 52px); line-height: 1.06; font-weight: 800; letter-spacing: -0.03em; } /* matches .project__body h2 (SortedSam) */
/* :not(.label) matters -- without it this also matches the "04 · Who
   you'd work with" line (a <p class="head label"> too) and, being more
   specific than the bare .label rule, silently overrides its font-size.
   Same trap as .nav a:not(.btn). */
.about p:not(.label) { font-size: 14.5px; line-height: 1.6; color: var(--on-navy); max-width: 62ch; } /* matches .facts li */
/* Fixed-ish width, not a percentage: its grid column is auto (sized to
   content), so this is what that column actually measures. */
/* align-self: start opts out of the grid's default row-stretch (needed so
   .about__text stretches to the same height instead, which is what the
   hardcoded centering above is measured against) and keeps this at its
   own aspect-ratio height rather than being pulled taller. */
.about__photo { border-radius: var(--r-lg); overflow: hidden; width: min(300px, 45vw); aspect-ratio: 3 / 4; align-self: start; }
.about__photo img { display: block; width: 100%; height: 100%; object-fit: cover; }

/* CTA */
.cta { display: flex; flex-direction: column; align-items: flex-start; gap: 26px; }
.cta h2 { max-width: 18ch; font-size: var(--step-h2-lg); line-height: 0.94; font-weight: 800; letter-spacing: -0.035em; text-transform: uppercase; }
.cta p { font-size: clamp(16px, 1.6vw, 22px); line-height: 1.55; color: var(--fg-muted); }
/* The muted ink only reads on the yellow band. On a dark ground it is nearly
   invisible, so scope it instead of applying it to every .cta. */
.section--accent .cta p { color: var(--ink-on-accent-muted); }
/* An eyebrow label inside a CTA keeps label sizing, not body sizing. */
.cta p.label { font-size: var(--step-label); line-height: 1.4; color: var(--fg-faint); }
.section--accent .cta p.label { color: var(--ink-on-accent-muted); }
.cta__row { display: flex; flex-wrap: wrap; align-items: center; gap: 16px; }

/* Footer */
.footer { padding: clamp(46px, 7vw, 72px) var(--gutter) 34px; background: var(--bg-deep); border-top: 1px solid var(--line-soft); }
.footer__grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 190px), 1fr)); gap: clamp(28px, 4vw, 56px); }
.footer__col { display: flex; flex-direction: column; gap: 4px; align-items: flex-start; }
.footer__col .label { color: var(--fg-faint); margin-bottom: 6px; }
/* min-height keeps these above the 24px WCAG 2.2 target-size floor. */
.footer__col a {
  display: inline-flex;
  align-items: center;
  min-height: 26px;
  color: var(--fg-body);
  font-size: 14.5px;
}
.footer__col a:hover { color: var(--accent); }
.footer address { font-size: 14px; line-height: 1.7; color: var(--fg-faint); font-style: normal; }
.footer__base {
  max-width: var(--content);
  margin: clamp(34px, 5vw, 52px) auto 0;
  padding-top: 22px;
  border-top: 1px solid var(--line-soft);
  font-family: var(--font-mono);
  font-size: 11.5px;
  color: var(--fg-faint);
}
