/*
 * Front page (splash chooser) — ported verbatim from the static index.html on
 * 2026-08-12 when the theme became the single dev target.
 *
 * Everything here is scoped to `body.home-alt`, which front-page.php adds via
 * body_class(). That scoping came from the static site and is worth keeping:
 * it means this file cannot leak onto an inner page even if it's enqueued by
 * mistake.
 *
 * Loaded only on the front page — see refinery_enqueue_assets().
 */

/* Cursor stays chartreuse on the chooser. The site-wide rule swaps the mark
       to lavender over anything clickable, which reads well on inner pages where
       links are a small part of the page — but here the two halves ARE the page,
       so the "hover" state was on essentially all the time and the mark never
       looked chartreuse. Pinning the fill is page-scoped; the lavender swap is
       untouched everywhere else. */
    .cursor-dot svg,
    .cursor-dot.is-grown svg { fill: var(--chartreuse); }

    /* Homepage hero must fill the whole viewport — the shared stylesheet caps
       .hero-split at max-height:1000px, which leaves white space (and throws off
       the bottom-anchored roundel) on taller screens. */
    body.home-alt .hero-split {
      height: 100vh;
      height: 100dvh;   /* account for mobile browser chrome */
      max-height: none;

      /* The roundel's rendered width, promoted to a custom property (2026-09-01)
         because two other things now have to know it: the headline centres
         itself in the band ABOVE the mark (SP-8), and the halves' copy has to
         stop before it reaches the mark's edge now that it sits at mid-height
         (SP-3). Both were hard-coding 32vw before this. Change it HERE only. */
      --rn-size: clamp(150px, 32vw, 640px);

      /* Half the MARK, not half the box: .roundel-inner's svg is 78% of the
         roundel, centred — so the drawing's half-height is 0.78 / 2 = 0.39 of
         the box. This is the number that puts the headline's band and the
         copy's clearance against the visible circle rather than its padding. */
      --rn-half: calc(var(--rn-size) * 0.39);
    }

    /* Centred brand roundel. The outer element is just a positioning anchor;
       the inner element carries the visual and does all the intro motion so we
       never have to fight the translate(-50%,-50%) centering transform. */
    .hero-roundel {
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      z-index: 6;
      pointer-events: none;
      width: var(--rn-size);
      aspect-ratio: 1;
    }

    .roundel-inner {
      width: 100%;
      height: 100%;
      display: flex;
      align-items: center;
      justify-content: center;
      /* Pre-JS start state = off-screen below + invisible, so the rise has
         nothing to flash past. The JS timeline animates from here. */
      transform: translateY(62vh) scale(0.9);
      opacity: 0;
      will-change: transform, opacity;
    }

    .roundel-inner svg {
      width: 78%;
      height: 78%;
      overflow: visible;
    }

    /* Pupils — animated (glance, squash-blink, then fade) by the intro timeline */
    .roundel-mark .glint {
      transform-box: fill-box;
      transform-origin: center;
    }

    @media (prefers-reduced-motion: reduce) {
      /* Skip the choreography — settle the clean logo (no pupils) immediately */
      .roundel-inner { transform: none; opacity: 1; }
      .roundel-mark .glint { opacity: 0; }
    }

    /* Key art sample grid behind the Entertainment side */
    /* gap was 6px until 2026-09-08 — Kay: "no black edge/gap between cards".
       front-page.js measures one set's advance from the DOM
       (kids[tiles].offsetLeft - kids[0].offsetLeft), gap included, so zeroing
       it here needs no matching change there. */
    body.home-alt .keyart-bg-grid {
      position: absolute;
      inset: 0;
      z-index: 0;
      display: flex;
      flex-direction: column;
      gap: 0;
      overflow: hidden;
      pointer-events: none;
    }

    body.home-alt .keyart-bg-row {
      flex: 1;
      min-height: 0;
      display: flex;
      gap: 0;
      width: max-content;

      /* How far the track travels before it repeats — ONE full copy of the
         row's tile set, gap included.

         50% is the no-JS fallback and it is an approximation: it is only the
         right distance when the track holds exactly two copies, and even then
         it lands half a flex gap short of a seamless loop. front-page.js
         measures the real advance after layout and overwrites this with a
         pixel value, which is exact at any number of copies — and it has to be,
         because the same script clones extra copies on wide screens where one
         copy of the set is narrower than the row. */
      --rfn-shift: 50%;
    }

    /* Scroll animations for the key art rows */
    @keyframes scrollRight {
      from { transform: translateX(calc(-1 * var(--rfn-shift))); }
      to   { transform: translateX(0); }
    }

    @keyframes scrollLeft {
      from { transform: translateX(0); }
      to   { transform: translateX(calc(-1 * var(--rfn-shift))); }
    }

    /* Sped up 2026-08-18 (was 70/85/75s): the rows should read as VOLUME of
       work at a glance. Each row runs a clearly different speed so the three
       never sync into one sliding wall — different enough to read as depth,
       close enough not to read as chaos. front-page.js adds a random per-image
       fade on top of this.

       ⚠️ These durations are the NO-JS fallback and the ratio of record —
       nothing more. A duration only describes a speed if the distance is fixed,
       and the distance is now measured (--rfn-shift) and varies with the
       viewport, so front-page.js recomputes each duration from a px/sec figure
       carrying these same relative speeds. Change the feel HERE and in SPEED[]
       there, or the two disagree and the JS wins. */
    body.home-alt .keyart-bg-row:nth-child(1) { animation: scrollRight 34s linear infinite; }
    body.home-alt .keyart-bg-row:nth-child(2) { animation: scrollLeft 48s linear infinite; }
    body.home-alt .keyart-bg-row:nth-child(3) { animation: scrollRight 40s linear infinite; }

    /* ══ MOTION ON INTENT (2026-09-08, Kay) ═══════════════════════════════
       The rows no longer drift on their own. At rest the wall is STILL and
       the only change is front-page.js swapping one tile's art at a time —
       "no row movement, just card flips". Scrolling starts when a pointer
       enters a half and stops when it leaves.

       ⚠️ SPECIFICITY, NOT ORDER, IS WHAT MAKES THIS WORK. The three rules
       above are `…keyart-bg-row:nth-child(N)` (0,3,1). Anything that wants to
       override their `animation` shorthand must reach (0,3,1) too — and a
       @media wrapper contributes NOTHING. Going through .hero-half is what
       buys the third class here rather than a bare `.keyart-bg-row`, which
       would silently lose.

       That is not hypothetical: the reduced-motion rule below WAS
       `body.home-alt .keyart-bg-row { animation: none }` (0,2,1) and never
       applied — Reduce Motion left all three rows scrolling. Found and fixed
       2026-09-08. */
    body.home-alt .hero-half .keyart-bg-row {
      animation-play-state: paused;
    }

    @media (hover: hover) and (pointer: fine) {
      body.home-alt .hero-half:hover .keyart-bg-row {
        animation-play-state: running;
      }
    }

    /* Touch has no hover, so a phone would get a permanently frozen wall.
       There the tile swaps ARE the motion, which is the point of the change —
       but let the rows run so the wall is not visibly identical to a
       screenshot. */
    @media (hover: none) {
      body.home-alt .hero-half .keyart-bg-row {
        animation-play-state: running;
      }
    }

    @media (prefers-reduced-motion: reduce) {
      body.home-alt .hero-half .keyart-bg-row { animation: none; }
    }

    /* 🔴 KEY ART IS NEVER CROPPED. Standing rule (Kay, 2026-09-02): match the
       height, let the width follow the art, show the whole piece. Pieces do not
       share a ratio and that is fine — a row of mixed widths is the design.

       height:100% + width:auto already does that, so `contain` is a no-op for a
       tile the browser sized itself. It is here as the backstop for a tile whose
       width has been pinned in JS mid-swap: `cover` in that same position is
       what cut the posters Kay screenshotted, and it did it invisibly, because
       the frozen ratio came from whatever art the slot happened to start with.
       If a swap ever mismatches a slot again the worst case is now a letterbox,
       not a crop. Do not put `cover` back. */
    body.home-alt .keyart-bg-row img {
      height: 100%;
      width: auto;          /* same height, natural (varying) width */
      flex: 0 0 auto;
      object-fit: contain;
      display: block;
      filter: brightness(0.92);
    }

    /* Drive cutover 2026-08-11: the 12 posters that filled these rows moved to
       the archive and each tile is now an .rfn-slot (rfnEntSplash). The <img>
       rule above sized tiles from their natural width; a placeholder has no
       intrinsic size, so it needs an explicit one. 2:3 is the portrait ratio
       the splash requires — TAGGING-SCHEMA.md §1 destination 1 is portrait-only.
       Delete this block when Drive feeds the rows. */
    body.home-alt .keyart-bg-row .rfn-slot {
      height: 100%;
      aspect-ratio: 2 / 3;
      flex: 0 0 auto;
      width: auto;
    }

    /* Lift the black gradient above the images so the headline stays readable */
    body.home-alt .hero-half--entertainment .hero-bg {
      z-index: 2;

      /* ── SP-7: "the vignetting to the bottom feels really intense, so the
         artwork is just really getting lost" ────────────────────────────────
         The shared sheet runs 0.9 → 0.3 → 0.1 bottom-to-top. That density at
         the bottom existed to carry bottom-anchored copy; SP-3 has just moved
         the copy to mid-height, so the darkest band is now covering artwork and
         supporting nothing. Bottom drops to 0.55, mid comes up a little to 0.34
         where the copy now sits, and the top is left alone (0.1 → 0.14) because
         the headline already carries its own text-shadow.

         Overridden HERE, not in assets/styles.css — that file is a synced copy
         of the root stylesheet and bin/sync-theme-assets overwrites it. It is
         also correct scoping: the splash is the only page with these rows.

         `background` is shorthand, so the 45° hatch has to be restated or it
         is dropped. Same trap as the ≤768px block at the end of this file. */
      background:
        linear-gradient(to top, rgba(0, 0, 0, 0.55) 0%, rgba(0, 0, 0, 0.34) 45%, rgba(0, 0, 0, 0.14) 100%),
        repeating-linear-gradient(
          45deg,
          rgba(255, 255, 255, 0.015) 0px,
          rgba(255, 255, 255, 0.015) 1px,
          transparent 1px,
          transparent 8px
        );
    }

    /* With the copy at mid-height it sits on the LIGHTEST part of the gradient
       above, over moving key art rather than a settled dark band. The gradient
       cannot be made to do both jobs — darken there and the SP-7 complaint comes
       straight back — so the copy carries its own contrast instead, the same way
       the headline always has. */
    body.home-alt .hero-eyebrow,
    body.home-alt .hero-title,
    body.home-alt .hero-title-right {
      text-shadow: 0 2px 24px rgba(0, 0, 0, 0.55);
    }

    /* Right-align the Brands side so it clears the centred logo */
    body.home-alt .hero-half--brands {
      align-items: flex-end;
    }

    body.home-alt .hero-half--brands .hero-content {
      display: flex;
      flex-direction: column;
      align-items: flex-end;
      text-align: right;
    }

    body.home-alt .hero-half--brands .hero-eyebrow {
      flex-direction: row-reverse;
    }

    @media (max-width: 600px) {
      body.home-alt .hero-split { --rn-size: clamp(120px, 38vw, 200px); }
    }

    /* ── Main title over the chooser (2026-08-18; dialed in 2026-08-19) ──────
       "NEXT LEVEL ADVERTISING FOR ENTERTAINMENT AND BRANDS", centred above
       both halves. Values from leadership's pass on splash-preview.html:
       58px at a ~1660px window → 3.5vw, and the title dropped to ~11vh so it
       sits evenly between the top edge and the roundel rather than hugging
       the ceiling. Uppercase via text-transform — markup stays sentence case,
       per the standing display-heading rule.

       Mixed weights: the base line is Poppins LIGHT white; the two division
       names (<strong>) are BLACK chartreuse. This is deliberately NOT the
       .accent-brush pattern (light word inside a heavy heading) — here the
       heavy words are the point: they name the two doors in the doors' own
       colour. */
    body.home-alt .hero-headline {
      position: absolute;

      /* ── SP-8: "the copy is not centering above the disc" ─────────────────
         HORIZONTAL centring was measured exact and is unchanged: on the live
         build the headline's line boxes and the roundel share a centre to the
         pixel at 1699px (849.5 / 849.5) and at 1120px two-line (560 / 560).
         There was nothing to fix on that axis.

         VERTICAL was the real fault. `top: 11vh` was dialled at one window and
         does not hold at others, because the mark's position is a function of
         WIDTH (it is 32vw wide, centred) while the headline's was a function of
         HEIGHT. On a 1120x757 window that put the headline 83px from the top
         edge and 65px from the mark — visibly low in its own band, which is
         what reads as "not centred above the disc".

         Now the headline centres itself in the band between the top edge and
         the top of the mark, so the two gaps stay equal at every size. translateY
         (-50%) means it self-centres whether the line wraps or not. The clamp
         keeps it off the ceiling on very short windows and stops it drifting
         down on very tall ones. */
      top: clamp(3.75rem, calc((50% - var(--rn-half)) / 2), 11rem);
      left: 50%;
      transform: translate(-50%, -50%);
      z-index: 5;                /* over both halves, under the roundel (6) */
      width: min(92%, 1080px);
      margin: 0;
      text-align: center;
      pointer-events: none;      /* the halves stay clickable straight through */
      color: var(--white);
      font-weight: 300;
      font-size: clamp(1.6rem, 3.5vw, 4.2rem);
      line-height: 1.15;
      letter-spacing: 0.01em;
      text-transform: uppercase;
      text-shadow: 0 2px 24px rgba(0, 0, 0, 0.55);
      transition: opacity 0.45s ease;
    }

    body.home-alt .hero-headline strong {
      font-weight: 900;
      color: var(--chartreuse);
    }

    /* ── SP-1: "built FOR the best" → "built BY the best" ────────────────────
       The two words share ONE grid cell, so they can cross-fade in place. A
       grid and not two absolutely-positioned spans: absolute positioning would
       collapse the slot to zero width and the line would close up around it.

       THE SLOT'S WIDTH IS ANIMATED, not fixed to the wider word. Fixed, the
       cell sizes to "FOR" and the narrower "BY" then sits in a visibly loose
       pocket for the rest of the page's life — about a character of air either
       side at this type size. front-page.js measures both words and writes
       --w-out / --w-in, and the width transitions between them alongside the
       fade, so the line closes up as the word changes. Both custom properties
       have an `auto` fallback, so before JS runs (or if it never does) the slot
       is simply max-content and the line still reads correctly.

       inline-grid, and vertical-align set explicitly — a grid box's default
       baseline alignment would drop the slot relative to the words beside it. */
    body.home-alt .hero-headline .word-swap {
      display: inline-grid;
      vertical-align: baseline;
      font-weight: 900;
      color: var(--chartreuse);
      width: var(--w-out, auto);
      transition: width 0.5s cubic-bezier(0.22, 1, 0.36, 1);

      /* LOAD-BEARING. Without it the single column is `auto`, which resolves to
         the max-content of the two words — the width of "for" — and a column is
         free to overflow a container that has been made narrower than it. So
         once the width animated down to "by", the column stayed at "for"'s
         width, `justify-self: center` centred "by" 15px right of the slot, and
         it printed straight over the "t" of "the best". Pinning the track to the
         container's own width is what makes the animated width actually govern
         where the word sits. */
      grid-template-columns: minmax(0, 1fr);
    }

    body.home-alt .hero-headline.is-swapped .word-swap {
      width: var(--w-in, auto);
    }

    /* `center`, not the grid default of `stretch`. Two reasons: each span then
       sizes to its own text, which is what makes it measurable in JS at all,
       and the outgoing word stays centred in a slot that is shrinking under it
       rather than sitting left-aligned in it. */
    body.home-alt .hero-headline .word-swap > span {
      grid-area: 1 / 1;
      justify-self: center;
      white-space: nowrap;
      transition: opacity 0.5s ease, transform 0.5s cubic-bezier(0.22, 1, 0.36, 1);
    }

    /* Start state: "for" showing, "by" waiting one line-height below. */
    body.home-alt .hero-headline .word-swap__out { opacity: 1; transform: none; }
    body.home-alt .hero-headline .word-swap__in  { opacity: 0; transform: translateY(0.85em); }

    /* front-page.js adds .is-swapped once the intro has settled. */
    body.home-alt .hero-headline.is-swapped .word-swap__out { opacity: 0; transform: translateY(-0.85em); }
    body.home-alt .hero-headline.is-swapped .word-swap__in  { opacity: 1; transform: none; }

    /* Reduced motion: no swap to watch, so the line simply IS the resolved
       sentence — which is also what the element's aria-label says. */
    @media (prefers-reduced-motion: reduce) {
      body.home-alt .hero-headline .word-swap > span { transition: none; }
      body.home-alt .hero-headline .word-swap__out { opacity: 0; transform: none; }
      body.home-alt .hero-headline .word-swap__in  { opacity: 1; transform: none; }
    }

    /* ── Hover crossfade: title out, the hovered half's copy in ──────────────
       Pointer devices only. Touch has no hover, so there the title and both
       halves' copy simply coexist — hiding the copy behind a hover that can
       never happen would leave a phone with two unlabeled doors. front-page.js
       toggles is-exploring on .hero-split and is-hovered on the half; CSS-only
       :hover would flicker when the cursor crosses the centre seam. */
    @media (hover: hover) and (pointer: fine) {
      body.home-alt .hero-content {
        opacity: 0;
        transform: translateY(8px);
        transition: opacity 0.45s ease, transform 0.45s ease;
      }

      body.home-alt .hero-half.is-hovered .hero-content {
        opacity: 1;
        transform: none;
      }

      body.home-alt .hero-split.is-exploring .hero-headline {
        opacity: 0;
      }
    }

    @media (prefers-reduced-motion: reduce) {
      body.home-alt .hero-headline,
      body.home-alt .hero-content {
        transition: none;
      }

      /* `transform: none` used to be in the rule above, and it was a real bug:
         the headline's transform is not motion, it is the centring itself. On
         a machine with Reduce Motion switched on, killing it left the headline
         starting AT the centre line and running off the right edge. Only the
         content's 8px reveal offset is motion, so only that is reset. */
      body.home-alt .hero-content { transform: none; }
    }

    /* Stacked layout: the Entertainment copy is TOP-anchored on mobile (see
       the ≤768px block below) — exactly where the headline sits. Two headlines
       fighting for the same band helps nobody; the halves' own copy carries
       the message there. */
    /* ── MOBILE: the headline is back, and the labels straddle the mark ─────
       (2026-09-08, Kay: "Entertainment label above the R, Brands below the R;
       add headline back at the top".)

       This block used to be `display: none` on the headline, and the reason
       was real at the time: the Entertainment copy was TOP-anchored on mobile,
       which is exactly where the headline sits, and two things fought for one
       band. Moving the labels onto the seam frees that band, so the headline
       comes back rather than the rule staying out of habit.

       The mark sits at the seam between the stacked halves. So the label of
       the TOP half goes to its BOTTOM edge, and the label of the BOTTOM half
       goes to its TOP edge — both then sit against the mark, one above and one
       below, which is what was asked for. It is the exact inverse of what the
       ≤768px block below still sets, so that rule is overridden here rather
       than edited: it is the last word for widths this block does not own. */
    @media (max-width: 768px) {
      body.home-alt .hero-headline {
        display: block;
        /* Anchored near the top rather than centred in the band above the
           mark — on a phone that band is the whole upper half. */
        top: 2.5rem;
        width: min(88%, 30rem);
        font-size: clamp(1.35rem, 6.2vw, 2.1rem);
      }

      /* The two halves' copy is anchored onto the seam in the ≤768px block
         further down — it owns that, because the gradient under the copy has
         to flip with it. Doing it here as well would just be a duplicate that
         loses to the later rule anyway. */

      /* Both labels now sit against the mark, so they need to clear it. The
         roundel is 32vw wide and centred on the seam, so half of it plus a
         little air is the clearance each side needs. */
      body.home-alt .hero-half--entertainment .hero-content {
        padding-bottom: calc(16vw + 1rem);
      }

      body.home-alt .hero-half--brands .hero-content {
        padding-top: calc(16vw + 1rem);
      }
    }

    /* ── SP-9: the headline breaks on purpose ───────────────────────────────
       "A creative agency / built by the best" (Kay, 2026-09-08). The break is
       a <br class="hero-headline__break"> in the mark-up rather than a width
       cap, because where the line breaks is a typographic decision and a cap
       moves it every time the viewport does.

       The headline is display:none at ≤768px (block above), so there is no
       phone case to solve. The band that does need care is 769-1100px: the
       line is now two lines in a fixed band between the top edge and the
       roundel, and at 3.5vw it started to crowd the mark. Easing the clamp's
       middle term buys the second line back without touching either endpoint.

       The break element is NOT display:none anywhere — it is inside an
       aria-hidden span-free text run whose accessible name is supplied by
       aria-label on the <p>, so a <br> changes nothing for a screen reader
       and everything for the rendered line. */
    @media (min-width: 769px) and (max-width: 1100px) {
      body.home-alt .hero-headline {
        font-size: clamp(1.5rem, 2.9vw, 2.6rem);
      }
    }

    /* ── SP-10: hover blacks out the half you are NOT on ────────────────────
       Kay, 2026-09-08: "it's too crazy-busy right now … on hover I want to
       black-out the non-focused area."

       PURE CSS — front-page.js already puts .is-hovered on the half under the
       pointer and .is-exploring on the container (it has done since the title
       cross-fade landed), so the state needed here already exists and no JS
       changes. If the blackout ever stops working, check those two classes
       before anything else.

       The overlay is a ::after on the half rather than a filter or an opacity
       on the half itself: both of those would dim the half's OWN copy — the
       ENTERTAINMENT / BRANDS label and its arrow — which is the one thing on
       that side that should stay legible. A ::after paints over the artwork
       and sits under the copy via z-index instead.

       It is scoped to (hover: hover) so a touch device, where :hover latches
       after a tap and never clears, never blacks out half the screen. */
    @media (hover: hover) and (min-width: 769px) {
      body.home-alt .hero-half::after {
        content: '';
        position: absolute;
        inset: 0;
        background: #000;
        opacity: 0;
        pointer-events: none;
        transition: opacity 0.45s ease;
        z-index: 2;
      }

      body.home-alt .hero-split.is-exploring .hero-half:not(.is-hovered)::after {
        opacity: 0.82;
      }

      /* Belt and braces. Today the non-hovered half's copy is already
         invisible — the block above sets .hero-content { opacity: 0 } and only
         .is-hovered brings it back — so nothing is currently painting under
         this overlay. The z-index is here so that if that rule is ever
         relaxed (a touch build, or someone deciding both labels should always
         show), the blackout dims the ARTWORK and not the label. */
      body.home-alt .hero-half .hero-content {
        position: relative;
        z-index: 3;
      }
    }

    @media (prefers-reduced-motion: reduce) {
      body.home-alt .hero-half::after { transition: none; }
    }

    /* ── SP-3: ENTERTAINMENT / BRANDS move up beside the roundel ─────────────
       The mark-up puts both labels at mid-height, tight to the mark's edge,
       instead of down on the bottom edge. The shared sheet bottom-anchors the
       halves (.hero-half { justify-content: flex-end }), so this is the only
       override needed — and it is scoped ≥769px because the ≤768px block below
       stacks the halves and anchors the top one's copy to the TOP. Centring on
       mobile would put ENTERTAINMENT straight under the mark's final centred
       pose.

       ⚠️ That block's original reason — clearing the roundel where it rested at
       the seam — expired on 2026-09-02: the mark rests peeking over the BOTTOM
       edge on every width now, the same as desktop (Kay; see the long note in
       front-page.js). Top-anchoring the Entertainment copy still earns its keep
       for the reason above, but do not treat it as protecting the mark's resting
       pose. The mark now deliberately crosses the Brands copy at the bottom of
       the screen for a couple of seconds, and that is the accepted cost of the
       eyes reading as eyes. */
    @media (min-width: 769px) {
      body.home-alt .hero-half {
        justify-content: center;
      }
    }

    /* ── Hero text resizing (homepage) ── */

    /* Eyebrow: much larger, bolder — becomes the visual anchor.

       Max size came down from 4vw to 3.4vw with SP-3, and it is not a taste
       change — it is the geometry. The mark is 32vw wide and centred, so its
       left edge sits at (50vw - 16vw) = 34vw. At mid-height that edge is the
       circle's widest point, and "ENTERTAINMENT" set at 4vw from a 3rem left
       padding measured PAST it at every width from 769px up (~20px of overlap
       at 1024px, ~7px at 1440px). At the bottom of the half, where this copy
       used to live, the circle has curved away and none of that applied.

       At 3.4vw the word clears the mark at every width — 9px of air at 769px,
       78px at 1699px. "BRANDS" is six characters and was never close. */
    body.home-alt .hero-eyebrow {
      font-size: clamp(2.5rem, 3.4vw, 4.2rem);
      font-weight: 800;
      letter-spacing: -0.02em;
      line-height: 1;
      margin-bottom: 0.75rem;
    }

    /* Belt and braces on the same geometry: even if the eyebrow copy changes to
       a longer word, the copy block cannot grow into the mark. Half the viewport
       minus the mark's half-width, minus the half's own 3rem padding, minus a
       1.5rem gutter so the two never actually touch. */
    @media (min-width: 769px) {
      body.home-alt .hero-content {
        max-width: calc(50vw - var(--rn-size) / 2 - 4.5rem);
      }
    }

    body.home-alt .hero-eyebrow::before {
      display: none;
    }

    /* Title (byline): secondary supporting line, kept tight to the CTA below */
    body.home-alt .hero-title,
    body.home-alt .hero-title-right {
      font-size: clamp(0.85rem, 1.2vw, 1.2rem);
      font-weight: 600;
      letter-spacing: 0.01em;
      margin-bottom: 0.6rem;
    }

    /* The .hero-subtitle expand-on-hover panel that used to live here is gone
       (2026-08-07): both halves' paragraphs were cut, so the byline now sits
       straight above the CTA with nothing to reveal. The shared .hero-subtitle
       rules in styles.css are still used by index-base/index-video.
       Pre-removal copy of this page is in Backups/2026-08-07-pre-copy-sweep/. */

    /* ── Brands half: video background ── */
    body.home-alt .hero-half--brands {
      background: var(--black);  /* fallback while video loads */
    }

    /* Kill the 40px grid the shared sheet draws over this half (2026-09-02).
       `.hero-half--brands::before` in assets/styles.css lays 1px lines of
       rgba(0,0,0,0.06) every 40px, at z-index 1 — above the video (z 0) and
       below the gradient (z 2). It is static-build furniture: back then this
       half was a flat chartreuse panel and the grid was the only texture on it.
       With a sizzle reel underneath it is just a mesh of dark lines over the
       footage, which is what Kay saw on the live splash.

       An override rather than a deletion, because assets/styles.css is a synced
       copy of the root sheet and bin/sync-theme-assets would put the rule back;
       `content: none` removes the pseudo-element outright rather than making an
       invisible one. The static build's own pages still use it. */
    body.home-alt .hero-half--brands::before {
      content: none;
    }

    /* Drive cutover 2026-08-11: the playlist is empty (rfnBrandSplash), so the
       inline script hides the <video> and sets .brands-splash-empty. Without
       this the half is a flat black rectangle that reads as a broken asset
       rather than a slot waiting to be filled. Matches the .rfn-slot hatch in
       styles.css. Delete both when Drive feeds this. */
    body.brands-splash-empty .hero-half--brands {
      background:
        repeating-linear-gradient(
          -45deg,
          rgba(219, 225, 32, 0.045) 0 6px,
          transparent 6px 16px
        ),
        var(--black);
    }

    body.brands-splash-empty .hero-half--brands::after {
      content: 'rfnBrandSplash';
      position: absolute;
      top: 1.25rem;
      left: 1.25rem;
      z-index: 3;
      padding: 0.3rem 0.55rem;
      border: 1px dashed rgba(219, 225, 32, 0.45);
      font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
      font-size: 0.625rem;
      font-weight: 700;
      color: var(--chartreuse);
      pointer-events: none;
    }

    .brands-video-bg {
      position: absolute;
      inset: 0;
      z-index: 0;
      width: 100%;
      height: 100%;
      object-fit: cover;
      /* Centred (2026-09-02, Kay). This was `75% center` — a crop biased toward
         the right, chosen when the clip on this half was a fragment framed
         around the copy. It is the full brand sizzle now, composed to be seen
         whole, and biasing the window pushed its subject off to the left. Centre
         is the right default for a piece that was framed by someone; it holds
         for the narrow desktop half and the short, wide box the half becomes
         when the two stack on a phone.

         The Brands page's own reel (.brand-reel-video) sets no object-position
         at all, so it is already centred — the two now agree. */
      object-position: center;
    }

    /* Dark gradient overlay so text stays readable over video */
    body.home-alt .hero-half--brands .hero-bg {
      z-index: 2;
      background: linear-gradient(to top, rgba(0,0,0,0.88) 0%, rgba(0,0,0,0.5) 55%, rgba(0,0,0,0.2) 100%);
    }

    /* Switch brands-side text to white */
    body.home-alt .hero-half--brands .hero-eyebrow   { color: rgba(255,255,255,0.65); }
    body.home-alt .hero-half--brands .hero-title-right { color: #ffffff; }

    /* ── Statement + inline arrow (2026-08-07) ──────────────────────────────
       The separate "View Key Art" / "View Brand Work" CTA line was removed and
       its chartreuse disc moved up beside the statement. inline-flex (not flex)
       so the h2 hugs its text — the brands half is right-aligned via
       .hero-content's align-items:flex-end, and a full-width block would leave
       the arrow stranded away from the words on that side. */
    body.home-alt .hero-title,
    body.home-alt .hero-title-right {
      display: inline-flex;
      align-items: center;
      gap: 0.7rem;
    }

    body.home-alt .hero-arrow {
      flex: 0 0 auto;
      width: 32px;
      height: 32px;
      border-radius: 50%;
      display: flex;
      align-items: center;
      justify-content: center;
      font-size: 1.1rem;
      background: var(--chartreuse);
      color: var(--dark);
      transition: transform var(--transition-fast);
    }

    /* Nudge on hover — the only motion the CTA has left now that it's an icon. */
    body.home-alt .hero-half:hover .hero-arrow { transform: translateX(4px); }

    @media (prefers-reduced-motion: reduce) {
      body.home-alt .hero-arrow { transition: none; }
    }

    /* ── Mobile: close the gap under the stacked halves ──────────────────────
       The shared stylesheet stacks the split at <=768px with
       .hero-split { min-height: 100svh } and .hero-half { min-height: 50svh },
       which tiles exactly. At <=480px it drops the halves to 45svh but leaves
       the container at 100svh — so two halves fill 90svh and the remaining
       10svh shows the body's #1a1a1a as a grey bar under the fold.

       It also moved the seam. The roundel is anchored at top:50% of
       .hero-split, so with 45svh halves the join sat at 45% and the mark
       floated below it. Restoring 50svh puts the seam and the roundel back on
       the same line, which is the whole idea of the composition.

       INVARIANT: the two halves must sum to .hero-split's min-height. If either
       value changes, change the other. */
    @media (max-width: 480px) {
      body.home-alt .hero-half {
        min-height: 50svh;
      }
    }

    /* ── Mobile: clear the centre for the roundel ────────────────────────────
       Stacked, both halves bottom-align their text — so the Entertainment
       copy lands right on the seam, which is exactly where the roundel settles.
       The mark covered the "Entertainment" line every time it landed.

       Fix: on mobile the top half anchors its copy to the TOP, leaving the
       middle band empty for the roundel. Brands keeps its copy at the bottom,
       so the two sit either side of the mark rather than under it.

       ⚠️ REVERSED 2026-09-08 (Kay: "Entertainment label above the R, Brands
       below the R"). The Entertainment copy was TOP-anchored here, and this
       gradient was flipped `to bottom` to put the dark end under it. Both go
       back: the copy now sits at the BOTTOM of the top half so it lands just
       above the mark on the seam, so the densest black belongs at the bottom
       again — which is what the shared sheet does, hence `to top`.

       Brands is anchored to the top of its half for the mirror reason, so its
       copy sits just below the mark. The repeating 45deg hatch is unchanged
       and has to be restated because `background` is shorthand. */
    @media (max-width: 768px) {
      body.home-alt .hero-half--entertainment {
        justify-content: flex-end;
      }

      body.home-alt .hero-half--brands {
        justify-content: flex-start;
      }

      body.home-alt .hero-half--entertainment .hero-bg {
        background:
          linear-gradient(to top, rgba(0, 0, 0, 0.9) 0%, rgba(0, 0, 0, 0.3) 60%, rgba(0, 0, 0, 0.1) 100%),
          repeating-linear-gradient(
            45deg,
            rgba(255, 255, 255, 0.015) 0px,
            rgba(255, 255, 255, 0.015) 1px,
            transparent 1px,
            transparent 8px
          );
      }
    }
