@charset "UTF-8";
/* ============================================================================
   Babe: Elaboratio - album pre-order landing page (node 2901)

   THEME FILE. Loaded from template.php, conditionally, on node 2901 only.
   It is no longer pasted into CSS Injector - entry 2 is superseded by this
   file and should be emptied.

   Why conditional rather than a stylesheets[] line in the .info:
     1. An .info stylesheet loads on every page. These styles belong to one
        node, and include a 100vw full-bleed breakout plus a root
        `html { overflow-x: clip }` that has no business running elsewhere.
     2. The webfonts are a third-party connection; opening it on ~2,900 other
        nodes to serve one landing page costs something for nothing.

   Two guards agree: every rule below is also scoped under the
   `.page-node-2901` body class. The one deliberate exception is the root
   `html { overflow-x: clip }`, which cannot be scoped to a body class because
   html is body's ancestor - the other reason the load stays conditional.

   THIS FILE IS THE SOURCE. Edit it, then compile with CodeKit - that is the
   site's compiler and it runs Autoprefixer, which the compiled twin needs:
   `hyphens` and `clip-path` here both gain a -webkit- form that a hand copy
   does not produce. Never hand-edit css/babe-elaboratio.css.

   The other theme CSS carries `line N` comments that CodeKit does NOT emit -
   they are legacy output from an older compiler, not a provenance marker, and
   a recompile correctly strips them. (Corrected 2026-08-27: an earlier note
   here claimed the opposite and told you not to recompile. That was measured
   against dart-sass, which is not this site's toolchain.)

   Regression check after any change: .claude/verify/ - the header harness
   documents the six measurement traps that apply site-wide here.
   ============================================================================ */
@import url("https://fonts.googleapis.com/css2?family=Archivo+Narrow:wght@400;600&family=Cormorant+Garamond:ital,wght@0,400;0,600;0,700;1,400&family=Libre+Franklin:wght@300;400;500&display=swap");
/* ---- header social links ----------------------------------------- */
@media (max-width: 1230px) {
  .page-node-2901 .social-links {
    display: none;
  }
}
/* ---- page-level: this node only ----------------------------------------- */
.page-node-2901 #main-content-header {
  display: none;
}

/* The node body ends before #below-menu-wrapper does, and no ancestor paints
   a background, so white showed between the landing page and the mailing-list
   band. Carry the dark ground down the whole page instead. The fixed nav and
   the mailing-list band paint their own backgrounds and are unaffected. */
.page-node-2901 #page-wrapper,
.page-node-2901 #below-menu-wrapper {
  background-color: #14110f;
}

/* Close the 90px of slack above the mailing-list band so the colophon meets it
   on a clean seam. .region-tertiary-content computes to margin:70px 0 54px here
   (the theme's own `margin: 0 0 54px` is overridden by another rule), and
   article.node adds 20px below itself. Measured 90px -> 0px. */
.page-node-2901 .region-tertiary-content {
  margin-top: 0;
}

.page-node-2901 article.node {
  margin-bottom: 0;
}

/* Clips the 100vw bleed's overhang. Must be `clip`, NOT `hidden`:
   overflow-x:hidden makes the root a scroll container, which silently
   disables position:sticky on the story image below. */
html {
  overflow-x: clip;
}

/* ---- tokens -------------------------------------------------------------- */
.babe-lp {
  --ink: #14110f;
  --ink-deep: #0d0b0a;
  --gold: #9a8b60; /* theme $gold */
  --gold-lit: #c4b183;
  --parchment: #efe9dd;
  --muted: #a2937f;
  /* One step dimmer than --muted, for the caption sub-line and the colophon. This is the DIMMEST
     value that still clears WCAG AA (4.5:1) for normal-size text on both dark grounds:
     4.86:1 on --ink, 5.08:1 on --ink-deep. The two places using it were previously #6f6558
     (3.29:1) and #7d7263 (4.17:1) — both failing. Do not darken it. */
  --muted-dim: #8b8073;
  --hairline: rgba(154,139,96,.28);
  --gutter: clamp(1.25rem, 5vw, 4rem);
  --nav-h: 96px; /* theme's fixed #menu-bar-wrapper */
  --col-gap: 20px;
  --measure: 62ch;
  --f-display: "Cormorant Garamond", "Hoefler Text", Georgia, serif;
  --f-body: "Libre Franklin", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --f-util: "Tungsten", "tungstenmedium", "Archivo Narrow", "Arial Narrow", Arial, sans-serif;
  --s1: 1.125rem;
  --s2: clamp(1.35rem, 1.1rem + .9vw, 1.75rem);
  --s3: clamp(1.8rem, 1.3rem + 2vw, 2.9rem);
  --s4: clamp(2.4rem, 1.4rem + 4.2vw, 4.6rem);
  --s5: clamp(2.7rem, 1.1rem + 4.6vw, 4.8rem);
  font-family: var(--f-body);
  font-weight: 300;
  font-size: var(--s1);
  line-height: 1.7;
  color: var(--parchment);
  background: var(--ink);
}

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

/* the theme sets word-wrap:break-word globally; display type must not break */
.babe-lp h1, .babe-lp h2, .babe-lp blockquote,
.babe-lp .movement__place, .babe-lp .babe-lp__sub {
  overflow-wrap: normal;
  word-wrap: normal;
  word-break: normal;
  -webkit-hyphens: none;
          hyphens: none;
}

/* ---- grid: gutters + clearfix the theme's Bootstrap 3 omits -------------- */
.babe-lp .row {
  margin-left: calc(var(--col-gap) * -1);
  margin-right: calc(var(--col-gap) * -1);
}

.babe-lp .row::before,
.babe-lp .row::after {
  content: " ";
  display: table;
}

.babe-lp .row::after {
  clear: both;
}

.babe-lp .row > [class*=col-] {
  padding-left: var(--col-gap);
  padding-right: var(--col-gap);
}

/* the theme's .row-eq-height is flex at >=768px; make it wrap and let each
   band decide its own alignment */
@media (min-width: 768px) {
  .babe-lp .row-eq-height {
    flex-wrap: wrap;
  }
  .babe-lp .row-eq-height::before,
  .babe-lp .row-eq-height::after {
    display: none;
  }
}
/* ---- full-bleed breakout -------------------------------------------------
   The whole landing page breaks out of the 930px content column, so every
   band shares one unbroken dark ground. .babe-lp__bleed is kept as a no-op
   so the markup still reads correctly if the breakout is removed. */
.babe-lp {
  width: 100vw;
  margin-left: calc(50% - 50vw);
}

.babe-lp__bleed {
  width: auto;
  margin-left: 0;
}

.babe-lp__wrap {
  width: 100%;
  max-width: 1100px;
  margin-left: auto;
  margin-right: auto;
  padding-left: var(--gutter);
  padding-right: var(--gutter);
}

.babe-lp section {
  padding-top: clamp(3.5rem, 8vw, 7rem);
  padding-bottom: clamp(3.5rem, 8vw, 7rem);
}

/* ---- shared bits --------------------------------------------------------- */
.babe-lp .eyebrow {
  font-family: var(--f-util);
  font-size: 0.82rem;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--gold);
  margin: 0;
}

/* the stave: five hairlines, after the score in the jacket photograph */
.babe-lp .stave {
  height: 17px;
  width: 200px;
  max-width: 42vw;
  border: 0;
  margin: 0;
  opacity: 0.45;
  background-image: repeating-linear-gradient(to bottom, var(--gold) 0, var(--gold) 1px, transparent 1px, transparent 4px);
}

.babe-lp .stave--center {
  margin-left: auto;
  margin-right: auto;
}

.babe-lp .section-head {
  margin-bottom: clamp(2rem, 4vw, 3rem);
}

.babe-lp .section-head .eyebrow {
  margin-bottom: 1rem;
}

.babe-lp .section-head h2 {
  font-family: var(--f-display);
  font-weight: 600;
  font-size: var(--s3);
  line-height: 1.05;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  margin: 0;
  color: var(--parchment);
  text-wrap: balance;
}

/* ---- the call to action -------------------------------------------------- */
.babe-lp .cta {
  display: inline-block;
  padding: 1.05rem 2.5rem;
  background: var(--gold-lit);
  color: #17130d;
  font-family: var(--f-util);
  font-size: 1.05rem;
  font-weight: 600;
  letter-spacing: 0.17em;
  text-transform: uppercase;
  text-decoration: none;
  /* The page sets line-height 1.7 — a reading metric. Applied to a control it
     added ~9px of dead space inside the button and left the type floating in
     a tall box. A control sets its own. Measured: 66px -> 54px, no padding
     change; the reclaimed height went back into the hero's gaps. */
  line-height: 1.2;
  border: 0;
  border-radius: 1px;
  box-shadow: 0 10px 26px rgba(201, 177, 131, 0.22);
  /* Colour settles fast; the lift uses the same easing as the page-load rise
     so the button moves like the rest of the page rather than snapping. */
  transition: background-color 0.2s ease, transform 0.28s cubic-bezier(0.2, 0.6, 0.2, 1), box-shadow 0.28s cubic-bezier(0.2, 0.6, 0.2, 1);
}

.babe-lp .cta:hover, .babe-lp .cta:focus {
  background: #ddc79a;
  color: #17130d;
  text-decoration: none;
  transform: translateY(-2px);
  box-shadow: 0 16px 36px rgba(201, 177, 131, 0.36);
}

.babe-lp .cta:active {
  transform: translateY(0);
  box-shadow: 0 6px 16px rgba(201, 177, 131, 0.28);
  transition-duration: 0.08s; /* press reads instantly */
}

/* The arrow leads the way out. inline-block is required — transforms do
   nothing on a plain inline element. */
.babe-lp .cta .arrow {
  font-family: var(--f-body);
  font-weight: 400;
  display: inline-block;
  margin-left: 0.7rem;
  transition: transform 0.28s cubic-bezier(0.2, 0.6, 0.2, 1);
}

.babe-lp .cta:hover .arrow,
.babe-lp .cta:focus .arrow {
  transform: translateX(6px);
}

.babe-lp a:focus {
  outline: 2px solid var(--gold-lit);
  outline-offset: 3px;
}

/* Reduced motion keeps the colour and shadow response — which is what makes
   the control legible as a control — and drops only the movement. */
@media (prefers-reduced-motion: reduce) {
  .babe-lp .cta,
  .babe-lp .cta .arrow {
    transition: background-color 0.2s ease, box-shadow 0.2s ease;
  }
  .babe-lp .cta:hover, .babe-lp .cta:focus, .babe-lp .cta:active {
    transform: none;
  }
  .babe-lp .cta:hover .arrow, .babe-lp .cta:focus .arrow {
    transform: none;
  }
}
/* The slot directly under the button. Currently unused: the phonogram notice
   that occupied it was removed 2026-08-25 (it duplicated the colophon). Kept
   styled and ready for the release date — `Out <date>` — once the label
   supplies one. */
.babe-lp .cta-note {
  font-family: var(--f-util);
  font-size: 0.84rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0;
}

/* ---- art direction: where each image lives, per width -------------------
   Simplified 2026-08-25, when the desktop hero took her photograph and the
   album cover moved to the closing section at every width.

       >=768px   hero = photograph  ·  closing = cover
       <768px    hero = (no image)  ·  story = photograph  ·  closing = cover

   Each picture therefore appears EXACTLY ONCE at either width. The cover is
   in one place at all widths, so it needs no switching at all — only the
   photograph moves, and it does so by swapping which of its two instances is
   shown.

   Selectors stay container-scoped (0,3,0) rather than the bare class (0,1,0):
   `.babe-lp .print` is 0,2,0 and declares `display: block`, so a short-form
   selector LOSES to it on source order and the element never hides. That has
   bitten this file twice. Assert the value — don't trust the cascade. */
.babe-lp .print.babe-lp__story-art,
.babe-lp .babe-lp__story-cta {
  display: none;
}

@media (max-width: 767px) {
  /* The hero loses its image entirely — type and the button alone. */
  .babe-lp .babe-lp__hero-art {
    display: none;
  }
  .babe-lp .print.babe-lp__story-art {
    display: block;
  }
}
/* A photograph, not a sleeve: no gloss, no radius — just the drop shadow the
   story plate and the closing portrait already carry. Putting a sleeve gloss
   on a 1940s photograph of a real person would read as a mistake. */
.babe-lp .print {
  margin: 0;
  display: block;
  width: 100%;
}

.babe-lp .print img {
  width: 100%;
  height: auto;
  display: block;
  box-shadow: 0 18px 40px rgba(0, 0, 0, 0.55);
}

.babe-lp .print figcaption {
  margin-top: 1rem;
  font-family: var(--f-util);
  font-size: 0.8rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--muted);
  line-height: 1.6;
  text-align: left;
}

.babe-lp .print figcaption span {
  display: block;
  margin-top: 0.3rem;
  color: var(--muted-dim);
  letter-spacing: 0.16em;
}

/* ---- hero ---------------------------------------------------------------- */
.babe-lp__hero {
  background: radial-gradient(120% 90% at 78% 12%, rgba(111, 92, 70, 0.34) 0%, transparent 62%), linear-gradient(180deg, var(--ink-deep) 0%, var(--ink) 68%);
}

@media (min-width: 768px) {
  .babe-lp__hero .row-eq-height {
    align-items: center;
  }
}
/* the sleeve is a physical object; the artwork carries its own typography,
   so nothing is ever overlaid on it */
.babe-lp .sleeve {
  position: relative;
  display: block;
  width: 100%;
  border-radius: 2px;
  overflow: hidden;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.5), 0 22px 45px rgba(0, 0, 0, 0.62), 0 50px 90px rgba(0, 0, 0, 0.45);
}

.babe-lp .sleeve img {
  width: 100%;
  height: auto;
  display: block;
}

.babe-lp .sleeve::after {
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  pointer-events: none;
  background: linear-gradient(102deg, rgba(255, 255, 255, 0.11) 0%, transparent 34%, transparent 100%);
}

.babe-lp__hero-type {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1.4rem;
}

.babe-lp .babe-lp__hero-type > * {
  margin: 0;
}

.babe-lp__hero-type h1 {
  font-family: var(--f-display);
  font-weight: 600;
  font-size: var(--s5);
  line-height: 0.92;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  text-wrap: balance;
  margin: 0;
  padding: 0;
  border: 0;
  color: var(--parchment);
  max-width: 100%;
  overflow-wrap: normal;
}

.babe-lp__hero-type h1 .colon {
  color: var(--gold);
}

.babe-lp__sub {
  font-family: var(--f-display);
  font-style: italic;
  font-size: var(--s2);
  line-height: 1.25;
  color: var(--gold-lit);
  letter-spacing: 0.01em;
}

.babe-lp .babe-lp__hero-type > .babe-lp__sub {
  margin-top: -0.6rem;
}

.babe-lp__artist {
  font-family: var(--f-util);
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--muted);
}

.babe-lp__hook {
  max-width: 46ch;
  font-size: var(--s1);
  line-height: 1.66;
  color: rgba(239, 233, 221, 0.84);
}

.babe-lp__hook strong {
  color: var(--parchment);
  font-weight: 500;
}

/* ---- quote --------------------------------------------------------------- */
/* ---- the quote, revealed on the jacket panel -----------------------------
   The standalone quote band was removed 2026-08-25. The quote now lives on
   the jacket panel in the Story section and appears on hover (desktop) or tap
   (touch, via the checkbox in the markup — no JavaScript).

   Treatment: the artwork goes monochrome and pushes in very slightly while a
   vignette closes around the quote. The full-cover wash matters here because
   the jacket already has "BABE: ELABORATIO / A TRIBUTE TO MY MOTHER / HARRY
   CONNICK, JR." printed across its lower third — the quote has to sit over
   that type, not beside it. */
.babe-lp__jacket {
  position: relative;
}

.babe-lp__jacket-frame {
  position: relative;
  overflow: hidden;
  border-radius: 2px;
}

/* Timing. Two rules make the reveal read identically in and out:

   1. Every transition is declared on the RESTING state, never inside the
      :hover / :checked rule. A transition declared only on :hover animates in
      and then snaps out — on the way back there is no transition left.

   2. The easing is SYMMETRIC about its midpoint. Matching durations is not
      enough: the default `ease` is cubic-bezier(.25,.1,.25,1), which is
      front-loaded, so fading in reaches most of its opacity quickly and then
      creeps to full, while fading out drops quickly and then lingers near
      invisible. Same 1.5s, visibly different motion. cubic-bezier(.42,0,.58,1)
      — ease-in-out — is a mirror of itself, so both directions look the same.

   One curve, one duration, every property. */
.babe-lp__jacket-frame img {
  transition: filter 1.5s cubic-bezier(0.42, 0, 0.58, 1), transform 1.5s cubic-bezier(0.42, 0, 0.58, 1);
}

/* The scrim. z-index matters: ::after is generated as the LAST child, so
   without stacking it paints ON TOP of the quote and the text is unreadable
   behind a near-opaque wash. Scrim 1, quote 2. */
.babe-lp__jacket-frame::after {
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 1;
  pointer-events: none;
  opacity: 0;
  /* Solid, not a gradient — this is the same flat --ink-deep ground the
     removed quote band had, so the quote reads on exactly the surface it used
     to. It also has to be solid: the artwork has "BABE: ELABORATIO / A TRIBUTE
     TO MY MOTHER / HARRY CONNICK, JR." printed across its lower third, and at
     anything less that type ghosts through and collides with the quote's own
     attribution, which says the same name. */
  background: var(--ink-deep);
  transition: opacity 1.5s cubic-bezier(0.42, 0, 0.58, 1);
}

.babe-lp__q {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 0.9rem 0.75rem;
  pointer-events: none;
  opacity: 0;
  /* No delay: a lead-in delay makes the fade-out lag on the way back, which
     reads as the two halves running at different speeds. */
  transition: opacity 1.5s cubic-bezier(0.42, 0, 0.58, 1);
}

/* Type from the removed .babe-lp__quote band: same face, weight, line-height,
   colour, stave and attribution treatment. Set as large as the jacket frame
   can physically hold — see the note under .babe-lp__q about font-size. */
.babe-lp__q .stave {
  margin: 0 auto 0.75rem;
  width: 92px;
  height: 10px;
}

.babe-lp__q blockquote {
  margin: 0 auto;
  padding: 0;
  border: 0;
  max-width: none;
  font-family: var(--f-display);
  font-weight: 400;
  font-size: clamp(1.6rem, 0.95rem + 1.9vw, 2.35rem);
  line-height: 1.14;
  color: var(--parchment);
  text-wrap: balance;
}

.babe-lp__q cite {
  display: block;
  margin-top: 0.8rem;
  font-style: normal;
  font-family: var(--f-util);
  font-size: 0.86rem;
  font-weight: 600;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--gold);
}

/* The tap target: covers the artwork, label text visually hidden but still
   announced. Not display:none — that would remove it from the a11y tree. */
.babe-lp__q-hit {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  margin: 0;
  cursor: pointer;
  text-indent: -9999px;
  overflow: hidden;
  white-space: nowrap;
}

/* The checkbox itself is off-screen rather than hidden, so it stays
   focusable and operable by keyboard. */
.babe-lp .babe-lp__q-toggle {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: 0;
  padding: 0;
  border: 0;
  opacity: 0;
  clip: rect(0 0 0 0);
  -webkit-clip-path: inset(50%);
          clip-path: inset(50%);
  overflow: hidden;
}

/* Reveal — tap / click / keyboard, on every device. */
.babe-lp__q-toggle:checked ~ figure .babe-lp__jacket-frame img {
  filter: grayscale(1) contrast(1.05);
  transform: scale(1.03);
}

.babe-lp__q-toggle:checked ~ figure .babe-lp__jacket-frame::after {
  opacity: 1;
}

.babe-lp__q-toggle:checked ~ figure .babe-lp__q {
  opacity: 1;
}

/* Visible focus ring for keyboard users. */
.babe-lp__q-toggle:focus-visible ~ figure .babe-lp__jacket-frame {
  outline: 2px solid var(--gold-lit);
  outline-offset: 3px;
}

/* Reveal on hover — pointer devices only, so a tap on a phone can't leave a
   stuck half-hovered state fighting the checkbox. */
@media (hover: hover) and (pointer: fine) {
  .babe-lp__jacket-frame:hover img {
    filter: grayscale(1) contrast(1.05);
    transform: scale(1.03);
  }
  .babe-lp__jacket-frame:hover::after {
    opacity: 1;
  }
  .babe-lp__jacket-frame:hover .babe-lp__q {
    opacity: 1;
  }
}
@media (prefers-reduced-motion: reduce) {
  .babe-lp__jacket-frame img {
    transition: filter 0.2s ease;
  }
  .babe-lp__jacket-frame:hover img,
  .babe-lp__q-toggle:checked ~ figure .babe-lp__jacket-frame img {
    transform: none;
  }
}
/* The quote used to be the seam between the hero and the story. With it moved
   to the end, those two bands are both --ink with no divider — an unbroken
   2884px run on mobile. This restores the seam. Delete this one rule if you
   prefer the hero to bleed straight into the story. */
.babe-lp__story {
  border-top: 1px solid var(--hairline);
}

/* The .babe-lp__quote band's own rules were removed 2026-08-25 along with the
   section — dead selectors that would have outlived their markup. The quote's
   styling now lives with the jacket reveal above. */
/* ---- story --------------------------------------------------------------- */
.babe-lp .prose {
  max-width: var(--measure);
}

.babe-lp .prose p {
  margin: 0 0 1.5rem;
  color: rgba(239, 233, 221, 0.8);
}

.babe-lp .prose p:last-child {
  margin-bottom: 0;
}

/* The story's opening paragraph, set larger than the rest.
   This WAS `.babe-lp .prose p:first-child`. That rule had to go: the paragraph
   now lives outside .prose (it sits above the photograph on mobile), and
   leaving the old selector in place would have promoted "Her story unfolds…"
   to lede size instead — a silent regression, since the page would still look
   plausible. Styling follows the paragraph, not its position. */
.babe-lp .prose-lede {
  max-width: var(--measure);
  font-size: var(--s2);
  line-height: 1.5;
  color: var(--parchment);
  margin: 0 0 1.5rem;
}

.babe-lp .prose em {
  color: var(--gold-lit);
  font-style: italic;
}

/* The story image stays put while the prose scrolls past it. Needs the row
   to be .row-eq-height so this column stretches to the full row height and
   the image has somewhere to travel.

   The offset must clear the theme's pinned nav (#menu-bar-wrapper, fixed,
   96px, z-index 200) or the image parks underneath it. The extra 3rem is
   breathing room so it rests clear of the bar rather than tucked against it. */
@media (min-width: 992px) {
  .babe-lp__story .plate {
    position: -webkit-sticky;
    position: sticky;
    top: calc(var(--nav-h) + 3rem);
  }
}
.babe-lp .plate figure {
  margin: 0;
}

.babe-lp .plate img {
  width: 100%;
  height: auto;
  display: block;
  border-radius: 2px;
  box-shadow: 0 18px 40px rgba(0, 0, 0, 0.55);
}

.babe-lp .plate figcaption {
  margin-top: 1rem;
  font-family: var(--f-util);
  font-size: 0.84rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
}

/* ---- movements: a true sequence — her life ran New York -> Nouasseur ->
        New Orleans, so the numbering carries real information --------------- */
.babe-lp__movements {
  background: var(--ink-deep);
  border-top: 1px solid var(--hairline);
  border-bottom: 1px solid var(--hairline);
}

.babe-lp .movement-list {
  margin: 0;
  padding: 0;
  list-style: none;
}

.babe-lp .movement {
  list-style: none;
}

.babe-lp .movement-inner {
  height: 100%;
  padding: clamp(2rem, 3.4vw, 3rem) clamp(1.5rem, 2.6vw, 2.6rem);
  border-left: 1px solid var(--hairline);
}

.babe-lp .movement:last-child .movement-inner {
  border-right: 1px solid var(--hairline);
}

.babe-lp .movement__num {
  display: block;
  font-family: var(--f-util);
  font-size: 0.86rem;
  font-weight: 600;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--gold);
  margin-bottom: 0.9rem;
}

.babe-lp .movement__place {
  font-family: var(--f-display);
  font-weight: 600;
  font-size: clamp(1.5rem, 1rem + 1.35vw, 2.05rem);
  line-height: 1.02;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--parchment);
  margin: 0 0 0.9rem;
}

.babe-lp .movement__gloss {
  margin: 0;
  font-size: 1rem;
  line-height: 1.6;
  color: rgba(239, 233, 221, 0.72);
}

/* ---- credits: set like the back of a sleeve ------------------------------ */
.babe-lp .credits {
  margin: 0;
}

.babe-lp .credit {
  margin-bottom: clamp(1.75rem, 3vw, 2.75rem);
}

.babe-lp .credit dt {
  font-family: var(--f-util);
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--gold);
  margin-bottom: 0.4rem;
}

.babe-lp .credit dd {
  margin: 0;
  font-size: 1rem;
  line-height: 1.5;
  color: rgba(239, 233, 221, 0.84);
}

/* ---- closing CTA ---------------------------------------------------------
   Two-up from 768px: her photograph left, the closing line right. Left-aligned
   rather than centred — with a portrait beside it, centred type reads adrift. */
.babe-lp__close {
  text-align: left; /* pinned: the theme centres this section otherwise */
  border-top: 1px solid var(--hairline);
  background: radial-gradient(90% 120% at 50% 100%, rgba(111, 92, 70, 0.36) 0%, transparent 60%), var(--ink);
}

@media (min-width: 768px) {
  .babe-lp__close .row-eq-height {
    align-items: flex-end;
  }
}
/* The .babe-lp__portrait rules that lived here were removed 2026-08-25 along
   with their markup: the closing section now carries the album cover at every
   width, and her photograph moved to the hero / Story section, where the
   `.print` treatment above styles it. Dead selectors outliving their elements
   is how a stylesheet rots. */
.babe-lp__close-type {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1.6rem;
  padding-bottom: 1rem;
}

.babe-lp .babe-lp__close-type > * {
  margin: 0;
}

.babe-lp__close h2 {
  font-family: var(--f-display);
  font-weight: 600;
  font-size: var(--s4);
  line-height: 1.02;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  margin: 0;
  color: var(--parchment);
  text-wrap: balance;
  max-width: 14ch;
}

.babe-lp__close p {
  max-width: 48ch;
  color: rgba(239, 233, 221, 0.78);
}

/* Full width and left-aligned in its own band. (Earlier this was 62ch, but
   ch measured in condensed Tungsten is only ~4.3px, which collapsed it to
   ~270px and four cramped lines — ch is unreliable for condensed faces.) */
.babe-lp .colophon {
  max-width: none;
  text-align: left;
  margin: 0;
  font-family: var(--f-util);
  font-size: 0.76rem;
  line-height: 1.9;
  /* #8b8073, not #7d7263: measured 4.17:1 on the --ink-deep ground at 12.16px, just under the
     4.5:1 AA minimum. #8b8073 gives 5.08:1 here. */
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--muted-dim);
}

/* The colophon sits in its own band below the closing CTA, so the closing
   band keeps normal section padding. No sticky CTA of our own: #footer is
   position:fixed;bottom:0 site-wide (global.styles.scss:247) and a second
   fixed bar would cover it. */
.babe-lp__sticky {
  display: none !important;
}

/* ---- colophon band ------------------------------------------------------ */
.babe-lp__colophon-band {
  background: var(--ink-deep);
  border-top: 1px solid var(--hairline);
  padding-top: 2.25rem;
  padding-bottom: 2.5rem;
}

/* ---- motion: pure CSS, so nothing hides if scripts are stripped ---------- */
@media (prefers-reduced-motion: no-preference) {
  .babe-lp .rise {
    animation: babeRise 0.9s cubic-bezier(0.2, 0.6, 0.2, 1) both;
  }
  .babe-lp .rise:nth-child(2) {
    animation-delay: 0.06s;
  }
  .babe-lp .rise:nth-child(3) {
    animation-delay: 0.12s;
  }
  .babe-lp .rise:nth-child(4) {
    animation-delay: 0.18s;
  }
  .babe-lp .rise:nth-child(5) {
    animation-delay: 0.24s;
  }
  .babe-lp .rise:nth-child(6) {
    animation-delay: 0.3s;
  }
  .babe-lp .rise:nth-child(7) {
    animation-delay: 0.36s;
  }
}
@keyframes babeRise {
  from {
    opacity: 0;
    transform: translateY(18px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
/* ---- the hero image's reveal, which is a different problem at each width --
   >=768px  the image is beside the type, above the fold at load, so it
            reveals on load with everything else — just after the type.
   <768px   the type comes first, so the image starts BELOW the fold and a
            load animation would play where nobody can see it. It reveals on
            scroll instead, as it is reached.

   The scroll version is CSS-only (no JavaScript — the node body can have
   scripts stripped by the text filter) and double-guarded. Without
   @supports the image is simply visible and static. It is NEVER hidden by
   default: a hidden-by-default reveal would leave a hole where the cover
   should be in any browser that can't drive it. */
@keyframes babeFadeUp {
  from {
    opacity: 0;
    transform: translateY(48px) scale(0.985);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
@media (min-width: 768px) and (prefers-reduced-motion: no-preference) {
  .babe-lp__hero-art > * {
    animation: babeRise 0.9s cubic-bezier(0.2, 0.6, 0.2, 1) both;
    animation-delay: 0.42s;
  }
}
@supports (animation-timeline: view()) {
  @media (max-width: 767px) and (prefers-reduced-motion: no-preference) {
    /* On mobile the hero has no image; the one that fades up on scroll is
       her photograph, now down in the Story section. */
    .babe-lp .babe-lp__story-art {
      animation: babeFadeUp linear both;
      animation-timeline: view();
      animation-range: entry 5% entry 65%;
    }
  }
}
/* ---- The Work: each movement slides in from the right ---------------------
   Part I, II, III arrive one after another as the section is scrolled into
   view. Each has its own view() timeline, so on mobile — where they stack —
   they arrive naturally in turn as each one enters. On desktop they sit side
   by side and would otherwise arrive together, so the ranges are staggered to
   keep the succession.

   Same double guard as the other scroll animations: without @supports they
   are simply in place and visible, never mid-slide or blank. */
@keyframes babeSlideInRight {
  from {
    opacity: 0;
    transform: translateX(105%);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    /* The whole width of the item, not a nudge — it genuinely travels in from
       off its own right edge. Eased rather than linear so the motion decelerates
       into place, and the range is short so the travel is decisive instead of a
       slow drift across half a screen of scrolling. */
    /* Range placement is what decides whether you SEE this happen.
       `entry 0%` is the moment the block's top edge touches the bottom of the
       viewport; `entry 100%` is the moment it is fully on screen. Finishing
       early in that window means the slide completes while the block is still
       at the very bottom edge — it is over by the time you are looking at it.
       These run late and finish AT full visibility, so the travel happens in
       front of the reader. */
    /* Same easing curve as the jacket reveal — cubic-bezier(.42,0,.58,1),
       symmetric about its midpoint — so the motion has the same character
       going in and, when you scroll back up, coming out. Scroll-linked
       animation reverses along the identical curve, so in and out are mirrors
       by construction here. (See the note below about duration.) */
    .babe-lp .movement-list .movement {
      animation: babeSlideInRight cubic-bezier(0.42, 0, 0.58, 1) both;
      animation-timeline: view();
      animation-range: entry 22% entry 78%;
    }
    .babe-lp .movement-list .movement:nth-child(2) {
      animation-range: entry 33% entry 89%;
    }
    .babe-lp .movement-list .movement:nth-child(3) {
      animation-range: entry 44% entry 100%;
    }
    /* The travel is clipped rather than allowed to widen the page. */
    .babe-lp__movements {
      overflow-x: clip;
    }
  }
}
/* ---- below the theme's md breakpoint ------------------------------------- */
@media (max-width: 991px) {
  /* .row-eq-height goes flex at 768px but col-md-* widths only start at 992px.
     In that band these columns would be flex items with no defined width, so
     they'd size to content and wrap. Stack them instead. The hero is exempt:
     it uses col-sm-*, which does have widths here. */
  .babe-lp__story .row-eq-height,
  .babe-lp .movement-list.row-eq-height {
    display: block;
  }
  .babe-lp .plate {
    margin-top: 2.5rem;
  }
  .babe-lp .movement-inner {
    border-left: 0;
    border-top: 1px solid var(--hairline);
  }
  .babe-lp .movement:last-child .movement-inner {
    border-right: 0;
    border-bottom: 1px solid var(--hairline);
  }
}
@media (max-width: 767px) {
  .babe-lp .babe-lp__close-type {
    align-items: center;
    text-align: center;
  }
  .babe-lp .babe-lp__close {
    text-align: center;
  }
  .babe-lp__close h2 {
    margin-inline: auto;
  }
  .babe-lp__close p {
    margin-inline: auto;
  }
  .babe-lp .sleeve {
    max-width: 330px;
    margin-left: auto;
    margin-right: auto;
    margin-bottom: 2.5rem;
  }
  .babe-lp .print {
    max-width: 330px;
    margin-left: auto;
    margin-right: auto;
  }
  .babe-lp__hero-type .cta {
    display: block;
    width: 100%;
    text-align: center;
  }
  /* ---- THE MOBILE REORDER: type first, image second ---------------------
     The theme's .row-eq-height only goes flex at >=768px, so below that the
     two columns are plain blocks stacking in source order — image, then type.
     Making the row a flex column here lets `order` put the type first, so the
     visitor meets the title and the pre-order button before the image rather
     than after 510px of artwork. Measured at 390x844: the button moves from
     360px BELOW the fold to 88px above it.

     This is a two-child swap only because the phonogram line was removed from
     the hero; while it was there the note had to be re-ordered past the image
     as well, which needed `display: contents` on the copy column. */
  .babe-lp__hero .row-eq-height {
    display: flex;
    flex-direction: column;
    margin-left: 0;
    margin-right: 0;
  }
  .babe-lp__hero .row-eq-height > [class*=col-] {
    width: 100%;
    padding-left: 0;
    padding-right: 0;
  }
  .babe-lp__hero-copy {
    order: 1;
  }
  .babe-lp__hero-art {
    order: 2;
  }
  /* The gaps the shorter button paid for. */
  .babe-lp__hero-type {
    gap: 1.25rem;
  }
  .babe-lp__hook {
    font-size: 1rem;
    line-height: 1.55;
  }
  /* The Story section's own pre-order button, closing that section. Full
     width and centred, matching the hero button. */
  .babe-lp .babe-lp__story-cta {
    display: block;
    margin: 2.5rem 0 0;
  }
  .babe-lp .babe-lp__story-cta .cta {
    display: block;
    width: 100%;
    text-align: center;
  }
  /* Her photograph in the Story section: clear of the section title above it
     and the prose below, and capped to the same 330px the other mobile
     images use so the page keeps one image width throughout. */
  .babe-lp .babe-lp__story-art {
    max-width: 330px;
    margin-left: auto;
    margin-right: auto;
    margin-top: 2rem;
    margin-bottom: 2.5rem;
  }
}
