/* Mel Custom Theme — site.css
   Cloned from lki-child/lki.css on August 7, 2026.

   Source of truth for all tokens: tokens.css, which is enqueued BEFORE this file.
   Never redefine a --qp-* value here, and never redefine anything tokens.css
   already owns (--font-sans, --font-display, --fw-*, --radius-*, --ease-std, --dur-*,
   --sp-*, --sz-*, --type-*, --ls-*). Doing so would silently override the brand system,
   because this file loads second.

   There is no alias layer. Every declaration below references a canonical --qp-* or
   --type-* token directly. An earlier version carried a "token bridge" remapping the
   --lki-* names inherited from lki-child; that was removed on August 8, 2026 so this
   theme reads as Mel's own and can serve as a clean donor for future sites.
   ============================================================= */

/* No @import here. Fonts (Newsreader + Inter) are loaded by tokens.css.
   Duplicating the import would fetch the same stylesheet twice. */

/* ============================================================
   Reset + Base
   ============================================================ */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { scroll-behavior: smooth; }
body {
  margin: 0; padding: 0;
  font-family: var(--font-sans);
  font-weight: var(--fw-light);
  background: var(--qp-white-solid);
  color: var(--qp-ink);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}
img { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
ul, ol { list-style: none; }
p { margin: 0; }
button { font-family: inherit; }

/* ============================================================
   Layout
   ============================================================ */
.container    { max-width: 1240px; margin: 0 auto; padding: 0 80px; }
.sec          { padding: 112px 0; }
.sec--tight   { padding: 44px 0; }
.sec--neutral { background: var(--qp-canvas); }
.sec--dark    { background: var(--qp-ink); }
.sec-rule     { border: none; border-top: 1px solid var(--qp-hairline); margin: 0; }

/* ============================================================
   Type
   ------------------------------------------------------------
   Mel's scale, from the design guidelines. LKI shouted at Inter 900; Mel is
   Newsreader 400 for display and editorial headings, Inter for everything
   structural. Sizes and leading come from the token file, not from LKI.
   ============================================================ */

/* Micro caps. Inter 700 tracked, per the guidelines' micro spec. */
.eyebrow {
  display: block;
  font-family: var(--font-sans);
  font-size: var(--type-micro); line-height: var(--type-micro-lh);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-wide-md); text-transform: uppercase;
  color: var(--qp-brand); margin-bottom: var(--sp-5);
}
.eyebrow--light  { color: var(--qp-brand-light); }
.eyebrow--muted  { color: var(--qp-muted-soft); }

/* The italic accent. Forest only, and ONE PER PAGE. Newsreader 300 italic. */
.accent {
  font-family: var(--font-display); font-style: italic;
  font-weight: var(--fw-light); color: var(--qp-brand);
}

/* Section headings. Newsreader 400, scaling between Mel's H2 and H1. */
h2.display-h2 {
  font-family: var(--font-display);
  font-size: var(--type-h2);   /* 32px -> 40px */
  line-height: 1.2; letter-spacing: var(--ls-tight-xs);
  font-weight: var(--fw-regular);
  color: var(--qp-ink); margin-bottom: var(--sp-5);
}

/* Structural headings. Inter 600, per the guidelines' H3 definition. */
h3.h3 {
  font-family: var(--font-sans);
  font-size: var(--type-body-lg); line-height: 1.4;
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-tight-xs);
  color: var(--qp-ink); margin-bottom: var(--sp-2_5);
}

/* Body. Inter 400 at 16/26, the default reading size. */
.body-copy {
  font-family: var(--font-sans);
  font-size: var(--type-body); line-height: var(--type-body-lh);
  font-weight: var(--fw-regular); color: var(--qp-body);
}
.body-copy p + p { margin-top: var(--sp-4); }
.body-copy--light { color: var(--qp-on-dark-muted); }

/* ============================================================
   Grids
   ============================================================ */
.grid-2      { display: grid; grid-template-columns: 5fr 7fr; gap: 80px; align-items: start; }
.grid-2-even { display: grid; grid-template-columns: 1fr 1fr; gap: 72px; align-items: center; }
.grid-3      { display: grid; grid-template-columns: repeat(3,1fr); gap: 24px; }
.grid-4      { display: grid; grid-template-columns: repeat(4,1fr); gap: 20px; }

/* ============================================================
   Scroll Reveal
   ============================================================ */
.reveal {
  opacity: 0; transform: translateY(18px);
  transition: opacity 520ms var(--ease-std), transform 520ms var(--ease-std);
}
.reveal.is-visible { opacity: 1; transform: none; }
.reveal.d1 { transition-delay: 80ms; }
.reveal.d2 { transition-delay: 160ms; }
.reveal.d3 { transition-delay: 240ms; }

/* ============================================================
   Navigation
   ============================================================ */
.nav {
  position: fixed; top: 0; left: 0; right: 0; z-index: 100;
  height: 84px; display: flex; align-items: center;
  transition: background var(--dur-std) var(--ease-std);
}
.nav.scrolled {
  background: var(--qp-bg-scrim);
  backdrop-filter: saturate(160%) blur(14px);
  -webkit-backdrop-filter: saturate(160%) blur(14px);
}
.nav__inner {
  width: 100%; max-width: 1240px; margin: 0 auto; padding: 0 80px;
  display: flex; align-items: center; justify-content: space-between; gap: 32px;
}
/* 48px in an 84px bar, leaving 18px clear above and below. The lockup is
   3.84:1, so this is ~184px wide. Went 56px (inherited from lki-child) -> 30px
   -> 48px on September 1, 2026; 30px was legible but the tagline under the
   wordmark had gone to noise at that size. */
.nav__logo         { height: 48px; width: auto; display: block; }
.nav__logo-light   { display: block; }
.nav__logo-dark    { display: none; }
.nav.scrolled .nav__logo-light { display: none; }
.nav.scrolled .nav__logo-dark  { display: block; }
.nav__links {
  display: flex; align-items: center; gap: 32px;
  font-size: var(--type-micro); font-weight: var(--fw-semibold);
  letter-spacing: .06em; text-transform: uppercase;
}
.nav__contacts {
  display: flex; align-items: center; gap: var(--sp-3);
  margin-left: var(--sp-2);
}
.nav__contact {
  display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; border-radius: var(--radius-circle);
  border: 1px solid var(--qp-on-dark-muted);
  background: var(--qp-bg-raised-on-dark-soft);
  overflow: hidden;
  transition: background var(--dur-fast) var(--ease-std), border-color var(--dur-fast) var(--ease-std);
}
.nav__contact img { width: 18px; height: 18px; display: block; filter: brightness(0) invert(1); }
.nav__contact:hover,
.nav.scrolled .nav__contact:hover,
body.nav-solid .nav .nav__contact:hover {
  background: var(--qp-cta); border-color: var(--qp-cta-dark);
}
.nav.scrolled .nav__contact,
body.nav-solid .nav .nav__contact {
  background: var(--qp-cta); border-color: var(--qp-cta-dark);
}
.nav.scrolled .nav__contact img { filter: brightness(0); }
body.nav-solid .nav .nav__contact img { filter: brightness(0); }
.nav__link { color: var(--qp-on-dark-muted); transition: color var(--dur-fast); }
.nav__link:hover { color: var(--qp-canvas); }
.nav.scrolled .nav__link       { color: var(--qp-muted); }
.nav.scrolled .nav__link:hover { color: var(--qp-ink); }
.nav .nav-pill {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 6px 6px 6px 16px; border-radius: var(--radius-pill);
  background: var(--qp-bg-raised-on-dark); border: 1px solid var(--qp-border-on-dark-strong);
  color: var(--qp-canvas);
  font-family: var(--font-sans); font-size: var(--type-micro); font-weight: var(--fw-semibold);
  letter-spacing: .04em; text-transform: uppercase;
  cursor: pointer; text-decoration: none;
  transition: background var(--dur-fast), border-color var(--dur-fast);
}
.nav .nav-pill:hover { background: var(--qp-bg-raised-on-dark-hover); border-color: var(--qp-on-dark-muted); }
.nav .nav-pill .arr {
  width: 28px; height: 28px; border-radius: 50%;
  background: var(--qp-cta); color: var(--qp-cta-dark);
  display: flex; align-items: center; justify-content: center; flex-shrink: 0;
  transition: transform var(--dur-std) var(--ease-std);
}
.nav .nav-pill:hover .arr { transform: rotate(45deg); }
.nav.scrolled .nav-pill { background: var(--qp-ink); color: var(--qp-canvas); border-color: transparent; }
.nav.scrolled .nav-pill:hover { background: var(--qp-ink-deep); color: var(--qp-cta); }

/* Hamburger */
.nav__hamburger {
  display: none; flex-direction: column; justify-content: space-between;
  width: 24px; height: 18px;
  background: none; border: none; cursor: pointer; padding: 0; flex-shrink: 0;
}
.nav__hamburger span {
  display: block; height: 2px; border-radius: 2px;
  background: var(--qp-on-dark-soft);
  transition: transform var(--dur-std) var(--ease-std), opacity var(--dur-fast), background var(--dur-std) var(--ease-std);
}
.nav.scrolled .nav__hamburger span,
body:not(.home) .nav .nav__hamburger span { background: var(--qp-ink); }
.nav__hamburger.is-open span:nth-child(1) { transform: translateY(8px) rotate(45deg); }
.nav__hamburger.is-open span:nth-child(2) { opacity: 0; }
.nav__hamburger.is-open span:nth-child(3) { transform: translateY(-8px) rotate(-45deg); }
.nav__drawer {
  position: fixed; top: 84px; left: 0; right: 0; z-index: 99;
  background: var(--qp-bg-scrim-solid);
  backdrop-filter: saturate(160%) blur(14px); -webkit-backdrop-filter: saturate(160%) blur(14px);
  display: flex; flex-direction: column;
  max-height: 0; overflow: hidden;
  transition: max-height var(--dur-std) var(--ease-std);
}
.nav__drawer.is-open { max-height: 400px; }
.nav__drawer-link {
  display: block; padding: 14px 28px;
  font-size: var(--type-small); font-weight: var(--fw-semibold); letter-spacing: .06em; text-transform: uppercase;
  color: var(--qp-muted); text-decoration: none;
  border-bottom: 1px solid var(--qp-hairline);
  transition: color var(--dur-fast), background var(--dur-fast);
}
.nav__drawer-link:hover { color: var(--qp-ink); background: var(--qp-bg-hover-tint); }
.nav__drawer-cta {
  display: block; margin: 16px 28px 20px; padding: 12px 20px;
  background: var(--qp-ink); color: var(--qp-canvas);
  border-radius: var(--radius-pill); text-align: center;
  font-size: var(--type-small); font-weight: var(--fw-semibold); letter-spacing: .04em; text-transform: uppercase;
  text-decoration: none; transition: background var(--dur-fast);
}
.nav__drawer-cta:hover { background: var(--qp-ink-deep); }

/* ============================================================
   Hero
   ============================================================ */
.hero {
  position: relative; min-height: 100vh;
  display: flex; flex-direction: column; justify-content: flex-end;
  padding-bottom: 100px; background: var(--qp-ink); overflow: hidden;
}
.hero__bg { position: absolute; inset: 0; z-index: 0; background: var(--qp-ink); }

/* ── Hero slideshow ──────────────────────────────────────────────
   Eleven photos from Lara's posts, crossfading. Replaced the single
   background-image on .hero__bg.

   The slides all sit in the same place, stacked, and only .is-active is opaque,
   so the crossfade is one opacity transition with nothing moving. The ink
   background underneath means the first paint is never a white flash.

   Ratios of the source photos run 1.33 to 1.78, so object-fit: cover is doing
   real cropping on the squarer ones. object-position is centred, which suits
   these particular images (landscape, subject near the middle). If one of them
   crops badly, give that slide its own object-position rather than changing
   this rule. */
.hero__field {
  position: absolute; inset: 0; z-index: 0;
  width: 100%; height: 100%; display: block;
  background: var(--qp-surface-dark);
  cursor: default;
}
.hero__field.is-hovering {
  cursor: pointer;
}
.hero__haze {
  position: absolute; inset: -10%; z-index: 1;
  background: rgba(12, 10, 9, 0.24);
  backdrop-filter: saturate(0.88);
  -webkit-backdrop-filter: saturate(0.88);
  pointer-events: none;
}

/* The scrim used to be baked into .hero__bg's background shorthand. It has to be
   its own layer now so it sits above whichever slide is showing, otherwise the
   headline loses contrast every time a bright photo comes up.

   ⚠️ Reweighted September 1, 2026. It ran to --scrim-hero-soft at the very top,
   so a 25% grey wash covered the whole photograph and every slide read flat and
   dull — the scrim was doing its job across an area with no text in it. The
   hero is bottom-aligned, so the gradient now clears completely by 70% and the
   top third of the image is untouched. The stops below the text are slightly
   deeper than before to make up the contrast in the part that matters.

   The --scrim-hero-* tokens themselves are unchanged: .hero--page and the
   pattern example on /design-guidelines/ still use the original full-height
   wash, which is correct for both. This is a different distribution of the same
   three colours, not a different colour. */
.hero__scrim {
  position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: linear-gradient(to top,
    var(--scrim-hero-strong) 0%,
    var(--scrim-hero-strong) 12%,
    var(--scrim-hero-mid)   34%,
    var(--scrim-hero-soft)  54%,
    transparent             70%);
}

/* ── Interior-page hero ──────────────────────────────────────────
   The front-page .hero is a 100vh slideshow. An interior page wants the same
   language at a fraction of the height: dark slab, eyebrow, headline, lead,
   with room for the fixed nav above it.

   Added August 16, 2026 alongside the Design Guidelines page. Named
   .hero--page to match the modifier lki-child uses for exactly this, so the
   two themes stay one system. Works with no photograph at all, which is the
   current state: the dark slab is the default, not a fallback.

   To give any interior hero a photograph, add .hero__bg--photo to the same
   element and pass the image in as --hero-image. Nothing else changes. */
.hero--page {
  min-height: 0;
  padding-top: var(--sp-13);
  padding-bottom: var(--sp-10);
}
@media (max-width: 760px) {
  .hero--page { padding-top: var(--sp-11); padding-bottom: var(--sp-8); }
}
.hero--page .mel-title { max-width: 22ch; color: var(--qp-canvas); }

/* Photographic hero. The scrim is what keeps a headline legible over an
   arbitrary image, so a template must not restate it: pass the picture in as
   --hero-image and nothing else. The `, none` fallback matters — without it an
   unset --hero-image makes the whole declaration invalid and takes the scrim
   with it, leaving unreadable text on a bare photo. */
.hero__bg--photo {
  background-image:
    linear-gradient(to top,
      var(--scrim-hero-strong) 0%,
      var(--scrim-hero-mid)   45%,
      var(--scrim-hero-soft) 100%),
    var(--hero-image, none);
  background-position: center center;
  background-size: cover;
  background-repeat: no-repeat;
}

/* Single-post hero: was clear except for a small blurred radial patch behind
   the text, which only held up over photos where that patch happened to land
   under the headline — anywhere else the title had nothing behind it and read
   as lost against the photo. Replaced with the same bottom-up gradient
   .hero--project uses, so contrast holds regardless of the photo, and the
   text now sits bottom-left over that gradient instead of floating centred.
   Taller as of September 13, 2026 — the dark area reached only 48% up the
   photo, so on some images the title's upper half still sat on bare
   photograph; it now clears past the halfway mark. */
.hero--post .hero__bg--photo {
  background-image:
    linear-gradient(to top,
      rgba(12, 10, 9, .88) 0%,
      rgba(12, 10, 9, .6) 30%,
      transparent 62%),
    var(--hero-image, none);
}
.hero--post .hero__body {
  text-align: left;
}
.hero--post .hero__body > * {
  margin-left: 0;
  max-width: 640px;
}
.hero--post .mel-title,
.hero--post .hero__lead { text-shadow: 0 2px 14px rgba(12, 10, 9, .6); }
/* .mel-title is the Title role (--type-h1, up to 77px) everywhere else
   it's used — project pages, page headers — and that's the right scale for
   a page's own heading. A blog post's title sitting over its own photo,
   directly above a lead paragraph, doesn't need to compete at that size;
   dialed back to H2 scale on Lara's request, September 13, 2026, and set
   tighter than H2's own default line-height — a short 2-3 word title stacked
   over an excerpt reads as one unit better with less air between its lines. */
.hero--post .mel-title { color: var(--qp-canvas); font-size: clamp(2.25rem, 4vw, 3.25rem); line-height: 1.05; }
.hero--post .hero__lead { line-height: 1.4; font-size: 1.25rem; }
/* Eyebrow was the site's plain 12px micro-label size, sized for a caption
   sitting on a white page — on a full-bleed photo it read as barely there.
   Bumped alongside the title and lead, September 14, 2026. */
.hero--post .eyebrow { font-size: 1rem; margin-bottom: var(--sp-4); }
/* Blog-post hero: half the viewport rather than the full 100vh the base
   .hero rule sets — a post shouldn't need a full scroll before the reading
   starts. .hero--post.hero (both classes on the same element) beats the
   later "Hero — Mel overrides" block's bare .hero on specificity.
   padding-bottom tightened from --sp-9 (64px) to --sp-5 (24px) September 14,
   2026 — the text block was floating well clear of the bottom edge instead
   of anchoring to it. */
.hero--post.hero { min-height: 50vh; justify-content: flex-end; padding-bottom: var(--sp-5); }

/* Featured-image posts keep the nav transparent over the photograph. */
body.single-post .nav {
  background: linear-gradient(to bottom, rgba(12, 10, 9, .42), transparent);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
body.single-post .nav.scrolled {
  background: rgba(12, 10, 9, .58);
  backdrop-filter: blur(5px);
  -webkit-backdrop-filter: blur(5px);
}
body.single-post .nav .nav__contact {
  background: transparent;
  border-color: var(--qp-on-dark-muted);
}
body.single-post .nav .nav__contact img { filter: brightness(0) invert(1); }
body.single-post .nav.scrolled .nav__contact,
body.single-post .nav.scrolled .nav__contact:hover {
  background: var(--qp-cta);
  border-color: var(--qp-cta-dark);
}
body.single-post .nav.scrolled .nav__contact img { filter: brightness(0); }

.hero__body {
  position: relative; z-index: 2;
  width: 100%; max-width: 1240px; margin: 0 auto; padding: 0 80px;
  text-align: center;
}
.hero__body > * { margin-left: auto; margin-right: auto; }
.hero__scroll {
  position: absolute; z-index: 2; left: 50%; bottom: var(--sp-6);
  transform: translateX(-50%); display: inline-flex; flex-direction: column;
  align-items: center; gap: 8px;
  font-family: var(--font-sans); font-size: var(--type-micro);
  line-height: 1; letter-spacing: var(--ls-wide-md); text-transform: uppercase;
  color: var(--qp-on-dark-subtle); text-decoration: none;
  transition: color var(--dur-fast) var(--ease-std);
  animation: hero-scroll-drift 2.8s var(--ease-std) infinite;
}
.hero__scroll span {
  font-size: 18px; line-height: .75; letter-spacing: 0;
}
.hero__scroll:hover { color: var(--qp-cta); }
.hero__scroll:focus-visible {
  outline: none; box-shadow: 0 0 0 3px var(--qp-focus-ring);
}
@keyframes hero-scroll-drift {
  0%, 100% { transform: translate(-50%, 0); opacity: .65; }
  50% { transform: translate(-50%, 6px); opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .hero__scroll { animation: none; }
}
/* .hero__h1, .hero__h1 .accent and .hero__lead were declared here as inherited
   LKI rules and then re-declared in full further down, in the Mel overrides
   block, which won on source order. Every property was overridden, so these
   were dead: the danger was that deleting the later block would silently drop
   the hero back to Inter 600. Removed August 16, 2026, one declaration each. */
.hero__ctas { display: flex; flex-wrap: wrap; gap: 16px; align-items: center; }

/* ============================================================
   Buttons
   ------------------------------------------------------------
   Mel's guidelines put button radii at 8px and reserve pill radii for tags
   and chips, so LKI's pill system is replaced rather than recoloured. The
   circular arrow that rotated 45 degrees on hover is gone too: rotation is
   outside Mel's motion contract.
   ============================================================ */
.btn {
  display: inline-flex; align-items: center; gap: 10px;
  padding: 13px 24px; border-radius: var(--radius-sm);   /* 8px */
  /* CTA, not Primary. September 1, 2026: the guidelines say CTA is buttons
     and links, so the buttons had to actually become it. The fill is pale,
     so the label is --qp-cta-dark rather than white — 5.1:1 on the fill. */
  background: var(--qp-cta); color: var(--qp-cta-dark);
  font-family: var(--font-sans); font-size: var(--type-small);
  font-weight: var(--fw-semibold); letter-spacing: var(--ls-wide-xs);
  cursor: pointer; border: 1px solid transparent; text-decoration: none;
  white-space: nowrap;
  transition: background var(--dur-fast) var(--ease-std),
              border-color var(--dur-fast) var(--ease-std),
              color var(--dur-fast) var(--ease-std);
}
.btn:hover { background: var(--qp-cta-dark); color: var(--qp-cta); }
.btn svg { flex-shrink: 0; }

/* Ghost: quiet secondary action on a light ground. */
.btn--ghost {
  background: transparent; color: var(--qp-ink);
  border-color: var(--qp-hairline-strong);
}
.btn--ghost:hover {
  background: var(--qp-surface-strong);
  border-color: var(--qp-muted-soft);
  color: var(--qp-ink);
}

/* On a dark or photographic ground: hero, dark bands. */
.btn--on-dark {
  background: var(--qp-bg-raised-on-dark); color: var(--qp-canvas);
  border-color: var(--qp-border-on-dark-strong);
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
}
.btn--on-dark:hover {
  background: var(--qp-bg-raised-on-dark-hover); border-color: var(--qp-on-dark-muted);
}

/* Text-only link action. */
.btn--text {
  padding: 0; background: none; border: none; border-radius: 0;
  color: var(--qp-cta-dark);
}
.btn--text:hover { background: none; color: var(--qp-cta-dark); text-decoration: underline; }
.btn--text-on-dark { padding: 0; background: none; border: none; color: var(--qp-on-dark-soft); }
.btn--text-on-dark:hover { background: none; color: var(--qp-canvas); }

/* Focus: visible for keyboard users, using the token ring. */
.btn:focus-visible {
  outline: none; box-shadow: 0 0 0 3px var(--qp-focus-ring);
}

/* ============================================================
   Proof Strip
   ============================================================ */
.proof {
  overflow: hidden; display: flex; padding: 8px 0 16px;
  -webkit-mask-image: linear-gradient(to right, transparent 0%, black 8%, black 92%, transparent 100%);
  mask-image: linear-gradient(to right, transparent 0%, black 8%, black 92%, transparent 100%);
}
.proof__track {
  display: flex; flex-shrink: 0; gap: 64px; align-items: center;
  height: 96px; padding-right: 64px; animation: marquee 32s linear infinite;
}
.proof:hover .proof__track { animation-play-state: paused; }
@keyframes marquee { from { transform: translateX(0); } to { transform: translateX(-100%); } }
.proof__item { flex: 0 0 auto; display: flex; align-items: center; justify-content: center; }
.proof__logo { height: 44px; width: auto; max-width: 220px; filter: brightness(0) opacity(0.45); display: block; }

/* ============================================================
   About
   ============================================================ */
.about-grid  { display: grid; grid-template-columns: 2fr 3fr; gap: 88px; align-items: start; }
.about-photo { aspect-ratio: 4/5; overflow: hidden; border-radius: 2px; }
.about-photo img { width: 100%; height: 100%; object-fit: cover; object-position: center top; display: block; }
.about-photo.no-img {
  background: var(--qp-canvas); border: 1px solid var(--qp-hairline);
  background-image:
    linear-gradient(to top right, transparent calc(50% - .5px), var(--qp-hairline) calc(50% - .5px), var(--qp-hairline) calc(50% + .5px), transparent calc(50% + .5px)),
    linear-gradient(to bottom right, transparent calc(50% - .5px), var(--qp-hairline) calc(50% - .5px), var(--qp-hairline) calc(50% + .5px), transparent calc(50% + .5px));
}
.about-note  { margin-top: 22px; font-size: var(--type-body); font-weight: var(--fw-semibold); color: var(--qp-ink); letter-spacing: -.005em; }
.about-btns  { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; margin-top: 28px; }

/* ============================================================
   CTA Section
   ============================================================ */
.cta-sec { text-align: center; padding: 128px 0; position: relative; overflow: hidden; background: var(--qp-ink); }
.cta-sec__flowers { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; pointer-events: none; }
.cta-sec__flowers img { width: min(900px, 120%); opacity: .06; filter: brightness(0) invert(1); }
.cta-sec .eyebrow { color: var(--qp-brand-light); }

/* ============================================================
   Footer
   ------------------------------------------------------------
   As of September 13, 2026 this is the same block on every page: no more
   separate .footer bar (it rendered nothing an interior page didn't already
   get from .mel-closing__col--identity below) and no more homepage-only
   version of the two-column layout (moved here from homepage.css, which
   doesn't load on interior pages). See footer.php.
   ============================================================ */
.footer__copy { font-size: var(--type-micro); color: var(--qp-on-dark-subtle); margin-top: 10px; }
.footer__colophon { color: var(--qp-on-dark-muted); text-decoration: underline;
  text-underline-offset: 3px; transition: color var(--dur-fast) var(--ease-std); }
.footer__colophon:hover { color: var(--qp-canvas); }
.footer__email { color: var(--qp-on-dark-muted); text-decoration: underline;
  text-underline-offset: 3px; transition: color var(--dur-fast) var(--ease-std); }
.footer__email:hover { color: var(--qp-canvas); }

/* Two columns sharing one bottom-aligned row: CTA heading + streaming
   buttons on the left, the footer identity (wordmark + copyright line) on
   the right.

   Grid, not flex-wrap: with flex-wrap, each column's natural (max-content)
   width counted toward the wrap decision, and the heading + three pill
   buttons on the left plus the copyright line on the right added up to just
   over the container width — enough to force the whole row onto two lines
   even though neither column needed that much space. Grid's 1fr/auto split
   gives the identity column exactly its content width and lets the CTA
   column take (and wrap within) whatever is left, so this reflows instead of
   stacking. */
.mel-closing__layout { display:grid; grid-template-columns:1fr auto; align-items:end; gap:clamp(1.5rem,3vw,2.25rem); }
.mel-closing__col--cta { display:flex; flex-direction:column; gap:clamp(1.25rem,2.5vw,1.75rem); min-width:0; text-align:left; }
#listen.mel-closing #cta-heading { font:300 clamp(2.75rem,5.3vw,4.8rem)/1.08 var(--font-display); letter-spacing:-.025em; margin:0; max-width:16ch; color:#fafafa; }
#listen.mel-closing #cta-heading em { font-weight:300; }
/* Interior pages get a smaller heading here — the big fluid homepage size
   (up to 4.8rem) was designed for the homepage's own dark-to-light
   progression and read as oversized reused verbatim as an interior page's
   closing CTA. body.nav-solid marks every page but the front page (see the
   nav-position rule below); higher specificity than the bare rule above, so
   this wins regardless of source order. */
body.nav-solid #listen.mel-closing #cta-heading { font-size: var(--type-h2); line-height: var(--type-h2-lh); }
/* Three small pill buttons instead of a stacked, full-width divided list. */
.mel-closing__links { display:flex; flex-wrap:wrap; gap:.75rem; }
.mel-closing__links a { display:inline-flex; align-items:center; gap:.5rem; padding:.65rem 1.15rem; border:1px solid #ffffff4d; border-radius:var(--radius-pill); color:#fafafa; text-decoration:none; background:transparent; font:400 .9rem/1.4 var(--font-sans); transition:border-color .2s ease, background .2s ease; }
.mel-closing__links a span:last-child { font-size:1rem; transition:transform .25s ease; }
.mel-closing__links a:hover { border-color:#fafafa; background:#ffffff1a; }
.mel-closing__links a:hover span:last-child { transform:translate(2px,-2px); }
.mel-closing__links a:focus-visible { outline:2px solid #fafafa; outline-offset:4px; }

/* Right column: the footer identity block. Text-align right so both columns
   read as mirrored blocks anchored to the same baseline. white-space:nowrap
   on the copy line keeps "© 2026 Mel·lif·lu·ous. <email> · Media Kit" on one
   line — it fits, and wrapping mid-line read as a mistake rather than a
   deliberate two-line block. No max-width on the column itself: that would
   just fight the nowrap line for space. */
.mel-closing__col--identity { text-align:right; }
.mel-closing__col--identity .footer__wordmark { color:#fafafa; }
.mel-closing__col--identity .footer__copy { color:#fafafa9c; margin-top:10px; white-space:nowrap; }
.mel-closing__col--identity .footer__email { color:inherit; text-decoration:underline; text-underline-offset:.25em; text-decoration-thickness:1px; transition:color .2s ease; }
.mel-closing__col--identity .footer__email:hover { color:#fafafa; }
.mel-closing__col--identity .footer__colophon { color:inherit; }

@media(max-width:800px) {
 #listen.mel-closing #cta-heading { max-width:18ch; }
 .mel-closing__layout { grid-template-columns:1fr; align-items:flex-start; }
 .mel-closing__col--identity { text-align:left; }
 .mel-closing__col--identity .footer__copy { white-space:normal; }
}
@media(prefers-reduced-motion:reduce) { .mel-closing__links a span:last-child { transition:none; } }

/* NOTE: the .footer__nav, .footer__socials and icon-circle .footer__social rules
   that used to live here were deleted in 1.7.1. They came from lki-child, where
   the socials were 34px circles holding <img> icons.
   The bug they caused: .footer__social was declared twice in this file — here as
   a 34px circle, and again further down as a plain text link. The later block won
   on colour and font but never reset width/height/border-radius, so the footer
   rendered small circles with the words "Instagram" and "Bandcamp" spilling out
   of them and overlapping each other. Do not reintroduce a second
   .footer__social block; the only one now is .footer__social--circle below. */

/* ============================================================
   Interior nav — solid on non-hero pages
   body.nav-solid is added via body_class filter in functions.php
   ============================================================ */
/* Not sticky on interior pages: scrolls away with the page instead of
   staying pinned like the homepage nav. Same body.nav-solid flag already
   marks "every page but the front page", so this needs no new hook. */
body.nav-solid .nav { position: absolute; }
body.nav-solid .nav {
  background: var(--qp-bg-scrim);
  backdrop-filter: saturate(160%) blur(14px);
  -webkit-backdrop-filter: saturate(160%) blur(14px);
}
body.nav-solid .nav .nav__logo-light { display: none; }
body.nav-solid .nav .nav__logo-dark  { display: block; }
body.nav-solid .nav .nav__link       { color: var(--qp-muted); }
body.nav-solid .nav .nav__link:hover { color: var(--qp-ink); }
body.nav-solid .nav .nav-pill        { background: var(--qp-ink); color: var(--qp-canvas); border-color: transparent; }
body.nav-solid .nav .nav-pill:hover  { background: var(--qp-ink-deep); color: var(--qp-cta); }
body.nav-solid .nav .nav__hamburger span { background: var(--qp-ink); }

/* Featured-image posts keep the image nav transparent until it scrolls. */
body.single-post.nav-solid .nav {
  background: linear-gradient(to bottom, rgba(12, 10, 9, .42), transparent);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
body.single-post.nav-solid .nav .nav__logo-light { display: block; }
body.single-post.nav-solid .nav .nav__logo-dark { display: none; }
body.single-post.nav-solid .nav.scrolled {
  background: var(--qp-white-solid);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
body.single-post.nav-solid .nav.scrolled .nav__logo-light { display: none; }
body.single-post.nav-solid .nav.scrolled .nav__logo-dark { display: block; }
body.single-post.nav-solid .nav .nav__contact {
  background: transparent;
  border-color: var(--qp-on-dark-muted);
}
body.single-post.nav-solid .nav .nav__contact img { filter: brightness(0) invert(1); }
body.single-post.nav-solid .nav.scrolled .nav__contact,
body.single-post.nav-solid .nav.scrolled .nav__contact:hover {
  background: var(--qp-cta);
  border-color: var(--qp-cta-dark);
}
body.single-post.nav-solid .nav.scrolled .nav__contact img { filter: brightness(0); }

/* ============================================================
   Generic Page (About, Guest Teaching, etc.)
   ============================================================ */
.page-main { padding-top: 84px; min-height: 60vh; }
/* A hero paints its own dark up under the fixed nav, so the top pad that
   keeps ordinary pages clear of it would show as a light band above. */
.page-main--hero { padding-top: 0; }
.page-header {
  padding: 72px 0 56px;
  margin-bottom: 72px;
}
/* Page titles use the same .mel-title Title role as the homepage and project
   pages (Newsreader, weight 400) rather than a second, sans-serif "page
   title" style that used to live only here — this container just adjusts
   spacing for its own layout. */
.page-header .mel-title { max-width: 22ch; margin: 0; }
.page-content {
  max-width: 760px;
  padding-bottom: 120px;
}
.page-content h2 {
  font-size: var(--type-h3); font-weight: var(--fw-semibold); line-height: 1.25; letter-spacing: -.015em;
  margin-top: 2.2em; margin-bottom: 0.5em;
}
.page-content h3 {
  font-size: var(--type-h4); font-weight: var(--fw-semibold); line-height: 1.3; letter-spacing: -.01em;
  margin-top: 1.8em; margin-bottom: 0.4em;
}
.page-content p { margin-bottom: 1.4em; }
.page-content ul, .page-content ol { padding-left: 1.5em; margin-bottom: 1.4em; }
.page-content li { margin-bottom: 0.5em; }
.page-content img { max-width: 100%; height: auto; border-radius: var(--radius-sm); margin: 2em 0; }
/* :not(.btn) matters. Found August 9, 2026: a plain `.btn` has specificity
   0-1-0, but this descendant selector is 0-1-1, so without the exclusion it
   always won regardless of source order and repainted every button dropped
   into prose (Contact's mailto link, here) in --qp-brand text on a
   --qp-brand background. Invisible, not just off-brand. */
.page-content a:not(.btn) { color: var(--qp-cta-dark); text-decoration: underline; text-decoration-thickness: 1px; }
.page-content blockquote {
  border-left: 3px solid var(--qp-brand);
  padding-left: 24px; margin: 2em 0;
  font-size: var(--type-body-lg); color: var(--qp-muted); font-style: italic;
}

/* ============================================================
   Blog Archive (home.php / archive.php)
   ============================================================ */
.blog-archive { padding-top: 84px; }
.blog-archive__header {
  padding: 72px 0 56px;
}
.blog-archive__header .mel-title { margin: 0; }
.blog-grid {
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: 56px 32px; padding-bottom: 80px;
}
.blog-card { display: block; }
.blog-card__link { display: block; text-decoration: none; }
.blog-card__img-wrap {
  position: relative;
  aspect-ratio: 3 / 4; border-radius: var(--radius-sm);
  overflow: hidden; background: var(--qp-ink);
}
.blog-card__img {
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover; display: block;
  transition: transform 480ms var(--ease-std);
}
.blog-card__link:hover .blog-card__img { transform: scale(1.04); }
/* Was a dark scrim under light text — reliable when the photo's bottom edge
   happened to be dark, unreliable when it wasn't (a bright sky, pale sand,
   a white wall) since the text's contrast then depended on the photo. A
   light card (dark text on --qp-canvas, near-opaque) reads at the same
   contrast no matter what's in the photo. Changed September 13, 2026. */
.blog-card__body {
  position: absolute; inset: 0;
  background: linear-gradient(to top, var(--qp-canvas) 0%, var(--qp-canvas) 42%, transparent 78%);
  display: flex; flex-direction: column; justify-content: flex-end;
  padding: 28px;
}
.blog-card__title {
  font-size: var(--type-h4);
  font-weight: var(--fw-semibold); letter-spacing: -.02em; line-height: 1.22;
  color: var(--qp-ink); margin: 0 0 10px;
}
.blog-card__excerpt {
  font-size: var(--type-small); line-height: 1.65; color: var(--qp-muted); margin: 0 0 12px;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.blog-card__meta {
  font-size: var(--type-micro); font-weight: var(--fw-semibold); letter-spacing: .06em;
  text-transform: uppercase; color: var(--qp-muted);
}
.blog-pagination { padding: 24px 0 80px; display: flex; justify-content: center; }
.blog-pagination .nav-links { display: flex; gap: 8px; align-items: center; }
.blog-pagination .page-numbers {
  display: flex; align-items: center; justify-content: center;
  width: 38px; height: 38px; border-radius: 50%;
  font-size: var(--type-small); font-weight: var(--fw-semibold); color: var(--qp-muted);
  border: 1px solid var(--qp-hairline); text-decoration: none;
  transition: background var(--dur-fast), color var(--dur-fast);
}
.blog-pagination .page-numbers:hover,
.blog-pagination .page-numbers.current { background: var(--qp-ink); color: var(--qp-canvas); border-color: transparent; }
.blog-pagination .page-numbers.dots { border: none; width: auto; }

/* ============================================================
   Blog Single Post (single.php)
   ============================================================ */
.post-title-header { padding-top: 84px; background: var(--qp-white-solid); }
.post-title-header .container { padding-top: 72px; padding-bottom: 56px; border-bottom: 1px solid var(--qp-hairline); }
.post-title-header .mel-title { margin: 12px 0 20px; max-width: 22ch; }
.post-meta-bar {
  font-size: var(--type-micro); font-weight: var(--fw-semibold); letter-spacing: .05em;
  text-transform: uppercase; color: var(--qp-muted);
}
.post-meta-bar .post-cat { color: var(--qp-brand); }
.post-main { padding: 72px 0 120px; }
.hero + .post-main { padding-top: 80px; }
.post-content { max-width: 760px; }
.post-content h2 {
  font-size: var(--type-h3); font-weight: var(--fw-semibold); line-height: 1.25; letter-spacing: -.015em;
  margin-top: 2.2em; margin-bottom: 0.5em;
}
.post-content h3 {
  font-size: var(--type-h4); font-weight: var(--fw-semibold); line-height: 1.3; letter-spacing: -.01em;
  margin-top: 1.8em; margin-bottom: 0.4em;
}
.post-content p { margin-bottom: 1.4em; }
.post-content ul, .post-content ol { padding-left: 1.5em; margin-bottom: 1.4em; }
.post-content li { margin-bottom: 0.5em; }
.post-content img { max-width: 100%; height: auto; border-radius: var(--radius-sm); margin: 2em 0; }
/* Same :not(.btn) exclusion as .page-content above, and for the same reason. */
.post-content a:not(.btn) { color: var(--qp-cta-dark); text-decoration: underline; text-decoration-thickness: 1px; }
.post-content blockquote {
  border-left: 3px solid var(--qp-brand);
  padding-left: 24px; margin: 2em 0;
  font-size: var(--type-body-lg); color: var(--qp-muted); font-style: italic;
}

/* ============================================================
   Hero — Mel overrides
   ------------------------------------------------------------
   Same structure as LKI (full-bleed photo, content bottom-left) but the
   headline is Newsreader 400 rather than Inter 900, and the scrim leans on
   Mel's ink rather than LKI's navy.
   ============================================================ */
.hero {
  background: var(--qp-surface-dark);
  padding-bottom: 0;
  justify-content: center;
}
.hero__bg:not(.hero__bg--photo) { background: var(--qp-surface-dark); }
.hero__h1 {
  font-family: var(--font-display);
  font-size: 7rem;
  line-height: 0.94; letter-spacing: var(--ls-tight-md);
  font-weight: var(--fw-regular);
  color: var(--qp-canvas);
  max-width: none; margin-bottom: var(--sp-6);
}
.hero__h1 span {
  display: inline-block;
  white-space: nowrap;
  opacity: 0;
  transform: translateY(0.35em);
  transition: opacity var(--dur-med) var(--ease-std), transform var(--dur-med) var(--ease-std);
}
.hero__body .hero__h1,
.hero__body .hero__lead { opacity: 1; transform: none; }
.hero__h1.is-visible { opacity: 1; transform: none; }
.hero__h1.is-visible span { opacity: 1; transform: none; }
.hero__h1.is-visible span:nth-child(2) { transition-delay: 120ms; }
.hero__h1 .accent { color: var(--qp-brand-light); }
.hero__lead {
  font-family: var(--font-sans);
  font-size: var(--type-body-lg); line-height: 1.65;
  font-weight: var(--fw-light);
  color: var(--qp-on-dark-soft);
  /* 54ch rather than 48: the lead is now a full bio sentence, and at 48 it wrapped
     to five lines in the hero. */
  max-width: 54ch; margin-bottom: var(--sp-7);
}
@media (prefers-reduced-motion: reduce) {
  .hero__h1 span { opacity: 1; transform: none; transition: none; }
}
@media (max-width: 760px) {
  .hero__h1 { font-size: 3.5rem; }
}

/* ============================================================
   Tags
   ------------------------------------------------------------
   The ONE place pill radii are allowed, per the guidelines.
   ============================================================ */
.tag {
  display: inline-flex; align-items: center;
  padding: var(--sp-1) var(--sp-3);
  border-radius: var(--radius-pill);
  background: var(--qp-annotate-bg); border: 1px solid var(--qp-annotate-border);
  font-family: var(--font-sans); font-size: var(--type-micro);
  font-weight: var(--fw-semibold); letter-spacing: var(--ls-wide-xs);
  text-transform: uppercase; color: var(--qp-annotate-fg);
}
.tag-row { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-bottom: var(--sp-4); }

/* ============================================================
   Album Section
   ------------------------------------------------------------
   One per album. Art and player on one side, editorial copy on the other,
   with the album's residency posts underneath. Categories map to albums:
   japan-2025 to Wildroot & Amber, iceland-2023 to Spákonufell.
   ============================================================ */
/* min-width: 0 on the columns is load-bearing, not tidying.
   Grid columns default to min-width: auto, so a column will refuse to shrink
   below its content's minimum size. The Bandcamp iframe is 350px wide, so the
   media column had a 350px floor: once the viewport got narrow enough, the album
   grid grew wider than its .container, the container's 80/48/28px gutters stopped
   lining up with the rest of the page, and the whole document scrolled sideways.
   That was the "margins are wrong" bug (August 9, 2026) — the gutters were never
   the problem, the overflow was. */
.album { display: grid; grid-template-columns: 5fr 6fr; gap: var(--sp-9); align-items: start; }
.album > * { min-width: 0; }
.album--reverse .album__media { order: 2; }
.album__media { position: sticky; top: var(--sp-11); }
.album__art {
  width: 100%; height: auto; display: block;
  border-radius: var(--radius-card);
  border: 1px solid var(--qp-hairline);
}

/* The About portrait is square, so at full column width it would stand a good
   deal taller than the copy next to it. Cap the height and let object-fit crop
   rather than letting the section grow to fit a photograph. */
.about__portrait {
  max-height: 560px;
  object-fit: cover;
  object-position: center top;
}
.album__title {
  font-family: var(--font-display);
  font-size: var(--type-h2); line-height: 1.15;
  letter-spacing: var(--ls-tight-xs); font-weight: var(--fw-regular);
  color: var(--qp-ink); margin-bottom: var(--sp-3);
}
/* One line under the album title, before the year. Lead-weight so it reads as
   part of the title block rather than the start of the body copy. */
.album__subtitle {
  font-family: var(--font-sans);
  font-size: var(--type-body-lg); line-height: 1.5;
  font-weight: var(--fw-light);
  color: var(--qp-body);
  max-width: 42ch;
  margin-bottom: var(--sp-3);
}
.album__meta {
  font-family: var(--font-sans); font-size: var(--type-small);
  color: var(--qp-muted); margin-bottom: var(--sp-5);
}
.album__body { margin-bottom: var(--sp-6); }
.album__actions { display: flex; flex-wrap: wrap; gap: var(--sp-3); margin-bottom: var(--sp-7); }

/* ============================================================
   Audio Embed
   ------------------------------------------------------------
   The real Bandcamp player, embedded directly (Lara's call, August 9, 2026).
   It replaced a click-to-load facade, so the tracklist and controls are visible
   on arrival rather than after a click.

   `loading="lazy"` on the iframe keeps the cost off first paint: the player is
   only fetched as it nears the viewport. That is the compromise that keeps the
   top of the page fast while still showing three real players.

   Height is set per album as an HTML attribute, never here. Bandcamp's large
   player does not reflow, and the right number is whatever its own embed code
   says for that album.
   ============================================================ */
.audio-embed { margin-bottom: var(--sp-5); }

.audio-embed__player {
  width: 100%; max-width: 350px; border: 0; display: block;
  /* Height is set per-album as an HTML attribute. Bandcamp's large player does
     not reflow, so it needs an exact pixel height. Do not set it here. */
}

/* ============================================================
   Residency Post List
   ------------------------------------------------------------
   The posts belonging to an album. Editorial list, not cards: these are
   writing, and a list reads faster than a grid of thumbnails.
   ============================================================ */
.post-list { border-top: 1px solid var(--qp-hairline); }
.post-list__item { border-bottom: 1px solid var(--qp-hairline); }
.post-list__link {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--sp-5); padding: var(--sp-4) 0; text-decoration: none;
  transition: color var(--dur-fast) var(--ease-std);
}

/* Rows carrying a featured image. Vertically centred rather than baseline
   aligned, because an 80px thumbnail next to baseline-aligned text sits wrong. */
.post-list--thumbs .post-list__link {
  align-items: center;
  gap: var(--sp-4);
  padding: var(--sp-3) 0;
}
.post-list__thumb {
  flex: 0 0 80px; width: 80px; height: 80px;
  border-radius: var(--radius-s);
  overflow: hidden; background: var(--qp-surface-strong);
  border: 1px solid var(--qp-hairline);
}
/* Forced square with cover. These images run from 0.71 to 1.79 in ratio inside
   one list, so honouring the real aspect would make the rows ragged. */
.post-list__thumb img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  transition: transform var(--dur-slow) var(--ease-std);
}
.post-list__link:hover .post-list__thumb img { transform: scale(1.04); }
/* The title takes the slack so the date stays hard right. */
.post-list--thumbs .post-list__title { flex: 1 1 auto; }
.post-list__link:hover .post-list__title { color: var(--qp-brand); }
.post-list__title {
  font-family: var(--font-sans); font-size: var(--type-body-lg);
  font-weight: var(--fw-medium); line-height: 1.4; color: var(--qp-ink);
  transition: color var(--dur-fast) var(--ease-std);
}
.post-list__date {
  font-family: var(--font-sans); font-size: var(--type-small);
  color: var(--qp-muted-soft); white-space: nowrap; flex-shrink: 0;
}
.post-list__more { margin-top: var(--sp-5); }

/* ============================================================
   Shell — Mel overrides
   ------------------------------------------------------------
   Wordmark is live text in Newsreader rather than an SVG. Nav CTA and footer
   drop LKI's pill shapes and icon boxes.
   ============================================================ */

/* Keyboard skip link. Off-screen until focused. */
.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 200;
  padding: var(--sp-3) var(--sp-4);
  background: var(--qp-ink); color: var(--qp-canvas);
  font-family: var(--font-sans); font-size: var(--type-small);
  border-radius: 0 0 var(--radius-sm) 0;
}
.skip-link:focus { left: 0; }

/* The typeset .nav__logo-text rules were removed on September 1, 2026 along
   with the <span> they styled — the nav carries the drawn lockup now. */
/* Nav links: Inter, sentence case rather than LKI's tracked uppercase. */
.nav__links {
  font-family: var(--font-sans);
  font-size: var(--type-small);
  font-weight: var(--fw-medium);
  letter-spacing: 0; text-transform: none;
  gap: var(--sp-6);
}

/* Small button, for the nav bar. */
.btn--sm {
  padding: var(--sp-2) var(--sp-4);
  font-size: var(--type-small);
}
.nav.scrolled .nav__cta,
body.nav-solid .nav__cta {
  background: var(--qp-cta); color: var(--qp-cta-dark);
  border-color: transparent; backdrop-filter: none; -webkit-backdrop-filter: none;
}
.nav.scrolled .nav__cta:hover,
body.nav-solid .nav__cta:hover { background: var(--qp-cta-dark); color: var(--qp-cta); }

/* Footer wordmark and links. */
.footer__wordmark {
  display: block;
  font-family: var(--font-display);
  font-size: var(--type-h4);
  font-weight: var(--fw-regular);
  letter-spacing: var(--ls-tight-xs);
  color: var(--qp-canvas);
  margin-bottom: var(--sp-3);
}
/* The footer's own social row is gone as of September 12, 2026 — it duplicated
   .social-float below, which is fixed on every page including this one. See
   the note in footer.php. .footer__social--icon is the one surviving rule;
   .social-float reuses it rather than styling its own icons from scratch. */

/* Icon socials, September 1, 2026, replacing the IG/BC/SP/AM initials.

   These are used as plain images and carry NO circle of their own from CSS.
   Each Social-*.svg is already a finished badge — a green disc with a white
   glyph knocked out of it — so wrapping one in .footer__social--circle would
   draw a bordered circle around a circle, and painting it as a mask (the first
   attempt here) flattened the whole badge into a featureless disc, because a
   mask keeps only the alpha and these files are opaque right to the rim. */
.footer__social--icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; border-radius: var(--radius-circle);
  border: 1px solid var(--qp-on-dark-muted);
  background: var(--qp-bg-raised-on-dark-soft);
  transition: opacity var(--dur-fast) var(--ease-std),
              transform var(--dur-fast) var(--ease-std);
  opacity: .88;
}
.footer__social--icon img { width: 18px; height: 18px; display: block; filter: brightness(0) invert(1); }
.footer__social--icon:hover { opacity: 1; transform: translateY(-1px); }
.footer__social--icon:hover { background: var(--qp-cta); border-color: var(--qp-cta-dark); }

/* Persistent social, replacing the header's nav__contacts icons (which used to
   scroll away with the no-longer-sticky interior nav). Reuses the exact
   footer__social--icon circle, just fixed in place so it's on screen
   everywhere, on every page. Backdrop-filter keeps the translucent dark
   circle readable over light sections too.

   Row, not stacked (changed September 12, 2026) — two icons read as a single
   badge in a row; stacked, they read as two separate, unrelated buttons.

   Hover is its own rule here rather than reusing .footer__social--icon:hover:
   that rule swaps straight to a solid cta-green disc with a black glyph,
   which on top of an already-translucent floating circle read as a hard flash
   rather than a hover. This version stays in the same dark-glass language —
   circle darkens and lifts slightly, glyph stays white — so it feels like the
   same object responding, not a different button appearing. */
.social-float {
  position: fixed; right: 20px; bottom: 20px; z-index: 90;
  display: flex; flex-direction: row; gap: var(--sp-3);
}
.social-float .footer__social--icon {
  background: rgba(12, 10, 9, 0.55);
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
  box-shadow: var(--shadow-sm);
}
.social-float .footer__social--icon:hover {
  background: rgba(12, 10, 9, 0.85);
  border-color: var(--qp-cta);
  opacity: 1;
  transform: translateY(-2px);
}
.social-float .footer__social--icon:hover img { filter: brightness(0) invert(1); }
@media (max-width: 600px) {
  .social-float { right: 14px; bottom: 14px; }
  .social-float .footer__social--icon { width: 36px; height: 36px; }
  .social-float .footer__social--icon img { width: 16px; height: 16px; }
}
.footer__social--icon:hover img { filter: brightness(0); }
.footer__social--icon:focus-visible {
  outline: none; box-shadow: 0 0 0 3px var(--qp-focus-ring);
}

/* ============================================================
   Accessibility Utilities
   ============================================================ */
.screen-reader-text {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}
.screen-reader-text:focus {
  position: static !important;
  width: auto; height: auto; margin: 0; overflow: visible;
  clip: auto; white-space: normal;
}

/* ============================================================
   Search Form
   ============================================================ */
.search-form { display: flex; gap: var(--sp-2); flex-wrap: wrap; max-width: 34rem; }
.search-form__field {
  flex: 1 1 16rem; min-width: 0;
  padding: var(--sp-3) var(--sp-4);
  font-family: var(--font-sans); font-size: var(--type-body);
  color: var(--qp-ink); background: var(--qp-surface-card);
  border: 1px solid var(--qp-hairline-strong); border-radius: var(--radius-sm);
  transition: border-color var(--dur-fast) var(--ease-std),
              box-shadow var(--dur-fast) var(--ease-std);
}
.search-form__field::placeholder { color: var(--qp-muted-soft); }
.search-form__field:focus {
  outline: none; border-color: var(--qp-brand);
  box-shadow: 0 0 0 3px var(--qp-focus-ring-soft);
}
.search-form__submit { flex: 0 0 auto; }

/* ============================================================
   404
   ============================================================ */
.error-404__body { max-width: 52ch; margin-bottom: var(--sp-6); }
.error-404__actions {
  display: flex; flex-wrap: wrap; gap: var(--sp-3);
  margin-bottom: var(--sp-8);
}
.error-404__search { margin-bottom: var(--sp-9); }

/* ============================================================
   Search Results Page
   ============================================================ */
.search-page__form  { margin-bottom: var(--sp-8); }
.search-page__empty { max-width: 52ch; padding: var(--sp-6) 0 var(--sp-10); }
.search-page__empty a { color: var(--qp-cta-dark); text-decoration: underline; }
.search-page__empty a:hover { color: var(--qp-primary-1); }

/* ============================================================
   Prose lists
   ------------------------------------------------------------
   The global reset kills list markers, which is correct for nav and for the
   card/post lists that are semantically lists but visually not. Inside actual
   writing, bullets and numbers carry meaning: a materials list without them
   reads as loose lines. Restore them for prose only.
   ============================================================ */
.post-content ul,
.body-copy ul,
.page-content ul { list-style: disc outside; padding-left: var(--sp-5); margin-bottom: var(--sp-5); }
.post-content ol,
.body-copy ol,
.page-content ol { list-style: decimal outside; padding-left: var(--sp-5); margin-bottom: var(--sp-5); }
.post-content li,
.body-copy li,
.page-content li { display: list-item; margin-bottom: var(--sp-2); }
.post-content ul ul, .body-copy ul ul { list-style: circle outside; margin-bottom: 0; }

/* But never inside the component lists, which are lists only semantically. */
.post-list, .post-list li,
.nav__links { list-style: none; padding-left: 0; }
.post-list li { display: block; margin-bottom: 0; }

/* ============================================================
   Intro
   ------------------------------------------------------------
   The block directly under the hero photo. Centred, mirroring the previous
   site's layout, but on Mel's canvas rather than that build's lime green.

   Note on the italic accent: the guidelines allow the 300-italic forest accent
   ONCE per page, and the hero headline already spends it. The example sentence
   below is therefore Newsreader italic in ink, not forest, so the rule holds.
   If the accent belongs here instead, move it off the hero rather than adding
   a second one.
   ============================================================ */
.intro { background: var(--qp-canvas); }
.intro__inner {
  max-width: 60ch;
  margin: 0 auto;
  text-align: center;
}
.intro__q {
  font-size: var(--type-h2);
  line-height: 1.12;
  margin-bottom: var(--sp-6);
}
.intro__example {
  font-family: var(--font-display);
  font-style: italic;
  font-weight: var(--fw-light);
  font-size: var(--type-italic);
  line-height: 1.35;
  color: var(--qp-ink);
  max-width: none;
  margin: 0 auto var(--sp-7);
}
.intro__bio {
  max-width: 56ch;
  margin: 0 auto;
}
.intro__streams {
  justify-content: center;
  align-items: center;
  gap: var(--sp-3);
  margin-top: var(--sp-6);
}
.intro__stream-link {
  color: var(--qp-ink); text-decoration: underline;
  text-decoration-thickness: 1px; text-underline-offset: 4px;
  font-family: var(--font-sans); font-size: var(--type-small);
  font-weight: var(--fw-medium);
  transition: color var(--dur-fast) var(--ease-std);
}
.intro__stream-link:hover { color: var(--qp-cta-dark); text-decoration-thickness: 2px; }
.intro__stream-link:focus-visible {
  outline: none; box-shadow: 0 0 0 3px var(--qp-focus-ring);
}
/* The hero's only call to action, replacing the old button pair. White pills
   read cleanly against the dark scrim over the photo, and the eyebrow uses the
   --light variant because brand forest is too dark on this ground. */
.hero__streams {
  gap: var(--sp-3) var(--sp-4);
  align-items: center;
}

/* ============================================================
   Social Graphic Component (.mel-social-card)
   ============================================================ */
.mel-social-card {
  position: relative;
  width: 100%;
  aspect-ratio: 1 / 1;
  background-color: var(--qp-surface-dark);
  background-image: url('assets-logo/mel-logo-in-use.jpg');
  background-size: cover;
  background-position: center;
  overflow: hidden;
  display: flex;
  box-sizing: border-box;
  font-family: var(--font-sans);
}

.mel-social-card__scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(to top,
    var(--scrim-hero-strong) 0%,
    var(--scrim-hero-mid) 50%,
    var(--scrim-hero-soft) 100%);
}

.mel-social-card__content {
  position: relative;
  z-index: 1;
  width: 100%;
  height: 100%;
  padding: var(--sp-8);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  box-sizing: border-box;
}

.mel-social-card .eyebrow {
  letter-spacing: var(--ls-wide-md);
  color: var(--qp-on-dark-muted);
  margin-bottom: 0;
}

.mel-social-card__body .mel-social-card__h1 {
  font-family: var(--font-display);
  font-size: clamp(1.75rem, 1.2rem + 2.5vw, 3.25rem);
  line-height: 1.1;
  font-weight: var(--fw-regular);
  color: var(--qp-canvas-soft);
  margin-bottom: var(--sp-4);
}

.mel-social-card__body .accent {
  font-family: var(--font-display);
  font-style: italic;
  font-weight: var(--fw-light);
  font-size: clamp(1.125rem, 0.9rem + 1vw, 1.85rem);
  line-height: 1.3;
  color: var(--qp-primary-2);
  margin: 0;
}

.mel-social-card__footer {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
}

.mel-social-card__attribution {
  font-size: var(--type-small);
  color: var(--qp-on-dark-subtle);
  display: flex;
  gap: var(--sp-2);
  align-items: center;
}

.mel-social-card__logo img {
  width: 44px;
  height: 44px;
}

/* ============================================================
   Responsive
   ============================================================ */
@media (max-width: 700px) {
  .intro__inner { text-align: left; }
}
@media (max-width: 1024px) {
  .container, .nav__inner, .hero__body { padding-left: 48px; padding-right: 48px; }
  .grid-2, .grid-2-even { grid-template-columns: 1fr; gap: 40px; }
  .grid-4 { grid-template-columns: repeat(2,1fr); }
  .caps   { grid-template-columns: repeat(2,1fr); gap: 28px; }
  .about-grid { grid-template-columns: 1fr 1.6fr; gap: 56px; }
  .blog-grid  { grid-template-columns: repeat(2,1fr); }
  .chapter-gallery   { grid-template-columns: repeat(2, 1fr); }
  .nav__links .nav__link { display: none; }
  .nav .nav-pill { display: none; }
  .nav__hamburger { display: flex; }
}
@media (max-width: 768px) {
  .container, .nav__inner, .hero__body { padding-left: 28px; padding-right: 28px; }
  .sec { padding: 80px 0; }
  .grid-3, .caps, .about-grid, .ai-items { grid-template-columns: 1fr; }
  .grid-4 { grid-template-columns: 1fr 1fr; }
  .nav__links .nav__link:not(.nav__link--cta) { display: none; }
  .footer__inner { grid-template-columns: 1fr; gap: 24px; }
  .t-masonry { grid-template-columns: repeat(2,1fr); }
  .t-col--3 { display: none; }
  .blog-grid { grid-template-columns: 1fr; gap: 40px; }
  .chapter-nav__inner { grid-template-columns: 1fr 1fr; }
  .chapter-nav__back { display: none; }
  .page-header, .blog-archive__header { padding: 48px 0 40px; margin-bottom: 48px; }
}
@media (max-width: 480px) {
  .grid-4 { grid-template-columns: 1fr; }
  .t-masonry { grid-template-columns: 1fr; max-height: 520px; }
  .t-col--2 { display: none; }
  .chapter-gallery   { grid-template-columns: 1fr 1fr; }
  .chapter-nav__inner { grid-template-columns: 1fr; }
  .chapter-nav__link--right { align-items: flex-start; }
}
