/* ============================================================
   United Charitable — v4 HOMEPAGE MOCKUP LAYER
   Loaded only by index.php (head.php gates on $mockup_home) and
   double-scoped: no rule here matches without body.mockup-home,
   so internal pages render the v3 grayscale wireframe unchanged.

   Palette: burgundy #6b2146 · gold #a48560 · teal #75b9be
            navy #0a2a49 · cream #f6f1e7 (locked collateral value)
   Type: reverted to the wireframe, matching v1b — Source Serif 4 (headings +
   body), Poppins (UI/labels), system monospace (fine print). No Fraunces.
   Gold discipline: #a48560 is decorative-only against light grounds
   (3.4:1) — text-gold is --uc-gold-light on dark, --uc-gold-dark on light.
   ============================================================ */

/* ---------- 1 · Brand tokens (override the :root grayscale set) ---------- */
body.mockup-home {
  --uc-burgundy: #6b2146;
  --uc-burgundy-dark: #541a38;
  --uc-gold: #a48560;
  --uc-gold-light: #d9c29f; /* gold as text on dark bands */
  --uc-gold-dark: #7c6344;  /* gold as text on light grounds (reserved) */
  --uc-teal: #75b9be;
  --uc-teal-ink: #33717a;  /* teal darkened to pass AA as small text on cream/white */
  --uc-silver: #8b8d8f;     /* non-text uses only */
  --uc-navy: #0a2a49;
  --uc-offwhite: #f6f1e7;   /* snapped to the locked newsletter/collateral cream */
  --uc-mute: #63666a;       /* brand silver darkened to pass AA as text */
  /* Typography from v1b (John, 2026-07-29): reverted to the wireframe system.
     --serif, --sans and --mono are inherited unchanged from style.css: Source
     Serif 4 for headings + body, Poppins for UI/labels, system mono for fine
     print. --display aliases --serif so any legacy reference keeps resolving. */
  --display: var(--serif);

  /* (v1b's --uc-path-curve stripe graphic removed per John, 2026-07-29.) */

  /* Grain tiles, tokenized so mobile can swap the whole set at once.
     Strengths: standard 46 · white sections 44 · Find-Your-Path 37 ·
     fabric sections 24 · trust strip 34 (navy-tinted). */
  /* v2 (John, 2026-07-28): ALL GRAIN REMOVED. Every grain layer in this sheet
     flows through these five tokens, so nulling them here strips the texture
     site-wide. RESTORE: put the url() values back (noise*.png are still in
     assets/img/) and the layers, blend modes and positions all still work. */
  /* Globe line-art, carried over with direction B's impact band. Inline SVG,
     no asset file needed. */
  --uc-globe: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 200' fill='none' stroke='%23a48560' stroke-width='1.2' stroke-opacity='0.5'%3E%3Ccircle cx='100' cy='100' r='94'/%3E%3Cellipse cx='100' cy='100' rx='94' ry='34'/%3E%3Cellipse cx='100' cy='100' rx='94' ry='66'/%3E%3Cellipse cx='100' cy='100' rx='34' ry='94'/%3E%3Cellipse cx='100' cy='100' rx='66' ry='94'/%3E%3Cline x1='6' y1='100' x2='194' y2='100'/%3E%3Cline x1='100' y1='6' x2='100' y2='194'/%3E%3C/svg%3E");
  --grain: none;
  --grain-white: none;
  --grain-soft: none;
  --grain-faint: none;
  --grain-navy: none;
}

/* Teal's quiet utility role: text selection (with focus rings, below). */
body.mockup-home ::selection { background: rgba(117, 185, 190, 0.4); }

/* ---------- 2 · Display typography ----------
   Reverted to the wireframe, matching v1b: Source Serif 4 carries the whole
   heading scale and the body, exactly as internal pages render it.
   font-optical-sizing lets Source Serif 4 shift to its display cut at large
   sizes; sizes, weights and tracking all stay on the wireframe scale from
   style.css (no letter-spacing override here anymore). */
body.mockup-home h1,
body.mockup-home h2,
body.mockup-home h3,
body.mockup-home h4,
body.mockup-home h5,
body.mockup-home h6,
body.mockup-home .display,
body.mockup-home .jumbo__num,
body.mockup-home .pullquote__quote {
  font-family: var(--serif);
  font-optical-sizing: auto;
}

/* ---------- 2.5 · Line-break quality (orphans & widows) ----------
   `balance` evens the rag on short display text; `pretty` keeps body copy
   from stranding a lone word on the last line. Both degrade to normal
   wrapping in engines that lack them. */
body.mockup-home h1,
body.mockup-home h2,
body.mockup-home h3,
body.mockup-home h4,
body.mockup-home .display,
body.mockup-home .eyebrow { text-wrap: balance; }

body.mockup-home p,
body.mockup-home .lead,
body.mockup-home .small,
body.mockup-home li,
body.mockup-home .hero__intro p,
body.mockup-home .jumbo__label,
body.mockup-home .pullquote__quote,
body.mockup-home .pullquote__attr,
body.mockup-home .footer-nap,
body.mockup-home .tax-disclaimer { text-wrap: pretty; }

/* The closing quote mark must never be pushed to a line of its own. */
body.mockup-home .pullquote__mark { white-space: nowrap; }

/* "For Program Managers" is the only card title that wraps to two lines,
   which also pushed that card's body copy out of line with its neighbours.
   Reserving two lines on every card title aligns all four. */
body.mockup-home .portrait-card h3 { min-height: 2.4em; }
@media (max-width: 899px) {
  body.mockup-home .portrait-card h3 { min-height: 2.5em; }
}

/* Solid-color sections carry the brand-silver fractal noise (John's SVG,
   recolored from the generator's purple): multiply on light surfaces,
   soft-light on burgundy. Image-backed sections (satin band, bridge hero)
   are left alone — their texture is the photo. */
body.mockup-home .section {
  /* White sections run 5% lighter grain than the shared tile (John). */
  background: var(--grain-white) repeat, var(--uc-bg);
  background-blend-mode: multiply, normal;
}
/* "01 · Two paths" (Give/Do): the fabric continues up through this section
   over its white ground, so Two Paths and What-We-Do read as one cloth. */
/* Seal watermark, top-right of Two Paths (John, 2026-07-21). */
body.mockup-home .section:not(.band--dark):has(> .wrapper > .grid-2) { position: relative; overflow: hidden; }
body.mockup-home .section:not(.band--dark):has(> .wrapper > .grid-2) > .wrapper { position: relative; z-index: 1; }
body.mockup-home .section:not(.band--dark):has(> .wrapper > .grid-2)::after {
  content: "";
  position: absolute;
  /* Sized and anchored deliberately (John, 2026-07-24): smaller than the old
     oversized crop so the whole peak-and-road silhouette reads as the brand
     mark, with a modest, consistent bleed off the right edge. */
  top: clamp(-380px, -26vw, -180px);
  right: clamp(-760px, -48vw, -370px); /* +20vw = 20% of the mark's own width, John 2026-07-28 (orig -300/-20vw/-140) */
  width: clamp(1020px, 100vw, 1930px);
  aspect-ratio: 1;
  background-color: var(--uc-burgundy);
  /* Two masks composited: the mark itself, intersected with a vertical fade so
     the road dissolves before this section's overflow clip instead of ending on a
     hard horizontal cut (John, 2026-07-24). Unclipping isn't an option — 02 sits
     after this section with an opaque ground and would cover the overflow. */
  -webkit-mask:
    url("../img/line-uc.svg") center / contain no-repeat,
    linear-gradient(to bottom, #000 56%, transparent 86%);
  -webkit-mask-composite: source-in;
  mask:
    url("../img/line-uc.svg") center / contain no-repeat,
    linear-gradient(to bottom, #000 56%, transparent 86%);
  mask-composite: intersect;
  opacity: 0.06;
  pointer-events: none;
  transform: translate3d(0, var(--sym-y, 0px), 0); /* GSAP scrubs --sym-y */
  will-change: transform;
}

/* Fabric removed (John, 2026-07-23): Two Paths rides on white with faint grain.
   Merged with the trust band above (John, 2026-07-24): it picks up that band's
   exact end tone (#f7f2e7) and finishes the fade to white over the first ~340px,
   so the gradient carries across the seam instead of stopping at it. */
body.mockup-home .section:not(.band--dark):has(> .wrapper > .grid-2) {
  /* Fabric stays hidden here (John, 2026-07-24) — it lives on the 04 · Impact
     band. Re-add the fabric-texture.jpg layer + a matching multiply blend to
     bring it back to this section. */
  background:
    var(--grain-faint) repeat,
    linear-gradient(180deg, #f7f2e7 0px, #fbf8f1 150px, #ffffff 340px),
    #ffffff;
  background-blend-mode: multiply, normal, normal;
}

/* Cream sections ("What does United Charitable do?"): the fabric scan spans
   the whole section as ONE sheet (multiply, behind both columns), white-to-
   cream gradient kept beneath, light white veil holding the eyebrow at AA. */
/* Mountain accent bleeding off the bottom-left of What-We-Do (mirrors the
   top-right one on Two Paths, so the pair brackets the section pair). */
body.mockup-home .section--warm { position: relative; overflow: hidden; }
body.mockup-home .section--warm > .wrapper { position: relative; z-index: 1; }
/* ---------- Ambient road overlays (John, 2026-07-24) ----------
   The same line mark, scaled way up and dropped to a whisper, so each section
   carries a DIFFERENT piece of the road rather than a repeated logo. Scale and
   opacity move inversely — big + faint reads as texture, not as an object. */

/* 02 · Plain language — the lower-left sweep of the road. */
body.mockup-home .section--warm { position: relative; overflow: hidden; }
body.mockup-home .section--warm > .wrapper { position: relative; z-index: 1; }
body.mockup-home .section--warm::after {
  content: "";
  position: absolute;
  /* Anchored bottom-left and mirrored like the footer (John, 2026-07-24), with
     the same composited fade so it dissolves before this section's clip. */
  left: -30%;
  bottom: -44%;
  width: clamp(1020px, 128vw, 2200px);
  aspect-ratio: 1;
  transform: scaleX(-1);
  background-color: var(--uc-burgundy);
  /* Radial vignette rather than a one-way fade (John, 2026-07-24): the artwork
     runs past its own 0 0 500 500 viewBox, so the SVG self-clips into straight
     cut edges at this scale. Fading from the centre outward dissolves every
     edge — top, sides and bottom — so nothing reads as a hard line. */
  -webkit-mask:
    url("../img/line-uc.svg") center / contain no-repeat,
    radial-gradient(ellipse 72% 72% at 50% 50%, #000 38%, transparent 80%);
  -webkit-mask-composite: source-in;
  mask:
    url("../img/line-uc.svg") center / contain no-repeat,
    radial-gradient(ellipse 72% 72% at 50% 50%, #000 38%, transparent 80%);
  mask-composite: intersect;
  opacity: 0.05;
  pointer-events: none;
}

/* Testimonial — the upper-right ridge and the road's far bend. */
body.mockup-home .section:has(> .wrapper > .pullquote) { position: relative; overflow: hidden; }
body.mockup-home .section:has(> .wrapper > .pullquote) > .wrapper { position: relative; z-index: 1; }
body.mockup-home .section:has(> .wrapper > .pullquote)::after {
  content: "";
  position: absolute;
  right: -28%;
  bottom: -44%;
  width: clamp(1020px, 118vw, 2050px);
  aspect-ratio: 1;
  background-color: var(--uc-burgundy);
  -webkit-mask: url("../img/line-uc.svg") center / contain no-repeat;
  mask: url("../img/line-uc.svg") center / contain no-repeat;
  opacity: 0.05;
  pointer-events: none;
}
/* Fabric removed (John, 2026-07-23): the cream ground and grain remain; the
   white veil still lifts the top toward AA for the eyebrow. */
body.mockup-home .section--warm {
  background:
    var(--grain-faint) repeat,
    linear-gradient(rgb(255 255 255), rgb(255 255 255 / 50%)),
    linear-gradient(180deg, #ffffff 0%, #f6f1e7 55%, #f1e9d8 100%);
  background-position: 0 0, 50% 50%, 50% 50%;
  background-blend-mode: multiply, normal, normal;
}

/* (The 2026-07-28 deeper gold-cream floor on "What does United Charitable do?"
   is retired in v2a — it existed to feed the road photo below, which is gone.
   The section falls back to the standard .section--warm ramp above, whose
   light-cream base is exactly what Find Your Path's gradient starts on (v1b's
   one-for-one seam). v2b keeps the gold floor + road. */

/* ---------- 3 · Headings: navy on light sections, white on dark ---------- */
body.mockup-home .section h2,
body.mockup-home .section h3,
body.mockup-home .section h4 { color: var(--uc-navy); }
body.mockup-home .section--dark h2,
body.mockup-home .section--dark h3,
body.mockup-home .section--dark h4,
body.mockup-home .section--navy h2,
body.mockup-home .section--navy h3,
body.mockup-home .section--navy h4 { color: #fff; }

/* ---------- 4 · Eyebrows ---------- */
body.mockup-home .eyebrow { color: var(--uc-burgundy); }
/* Muted eyebrows carry the brand teal (darkened for AA) — its one visible
   text role on the page, used sparingly per the palette hierarchy. */
body.mockup-home .eyebrow--mute { color: var(--uc-teal-ink); }
body.mockup-home .eyebrow--dark { color: var(--uc-gold-light); }

/* ---------- 5 · Buttons ---------- */
/* Filled/outline/ghost pick the brand up from the tokens. On-dark variants
   get burgundy text instead of the wireframe's neutral ink. */
body.mockup-home .btn--ghost:hover { text-underline-offset: 3px; }
body.mockup-home .btn--dark { background: #fff; border-color: #fff; color: var(--uc-burgundy); }
body.mockup-home .btn--dark:hover { background: var(--uc-offwhite); border-color: var(--uc-offwhite); color: var(--uc-burgundy-dark); }
body.mockup-home .btn--dark.btn--outline { background: transparent; border-color: #fff; color: #fff; }
body.mockup-home .btn--dark.btn--outline:hover { background: #fff; border-color: #fff; color: var(--uc-burgundy); }
/* Rounded buttons across the system (John, 2026-07-21). Ghost buttons have
   no box, so the radius is a no-op there. */
body.mockup-home .btn,
body.mockup-home .floating-cta,
body.mockup-home .program-cta { border-radius: 999px; }
/* Primary buttons: champagne gold (John, 2026-07-28), replacing the burgundy
   gradient. Same fill the floating CTA already carries, with ink text to match
   it. Contrast on ink: 8.8:1 at the lightest stop, 7.3:1 at the darkest.
   Outline/ghost/on-dark excluded, so the hero's white header buttons are
   untouched. REVERT: burgundy was #7b2a52 / #6b2146 55% / #5e1c3d with white
   text, hover #6b2146 / #541a38 60% / #451530. */
body.mockup-home .btn:not(.btn--outline):not(.btn--ghost):not(.btn--dark) {
  background: linear-gradient(180deg, #e3cfa9, #d9c29f 60%, #cbb083);
  border-color: var(--uc-gold-light);
  color: var(--uc-ink);
}
/* Hover deepens the champagne. The floating CTA's own hover bottoms out at
   #a48560, which puts ink at 4.4:1 and just misses AA, so this stops a little
   lighter at #b1946b (5.3:1) rather than inherit that. */
body.mockup-home .btn:not(.btn--outline):not(.btn--ghost):not(.btn--dark):hover {
  background: linear-gradient(180deg, #d9c29f, #c4a87e 70%, #b1946b);
  border-color: var(--uc-gold);
  color: var(--uc-ink);
}

/* ---------- 6 · Header: transparent over the hero → glass pill on scroll ---------- */
/* The header leaves the flow so the burgundy hero runs to the top of the
   viewport behind it. Only the inner container is interactive. */
body.mockup-home .site-header {
  position: fixed;
  top: 0; left: 0; right: 0;
  background: transparent;
  border-bottom: 0;
  pointer-events: none;
}
body.mockup-home .site-header__inner {
  pointer-events: auto;
  border: 1px solid transparent;
  border-radius: 999px;
  transition: margin .25s ease, max-width .25s ease, padding .25s ease,
              background .25s ease, border-color .25s ease, box-shadow .25s ease;
}
/* Logo scale by header state (John, 2026-07-28): larger while the page is at
   the top, easing down to the standard 43px once the nav lifts into its
   floating pill. 43px is the tagline-free lockup at its current size. */
body.mockup-home .brand__img { transition: filter .25s ease, height .25s ease; }
body.mockup-home .site-header:not(.is-scrolled) .brand__img { height: 60px; }
body.mockup-home .site-header.is-scrolled .brand__img { height: 43px; }
@media (prefers-reduced-motion: reduce) {
  body.mockup-home .brand__img { transition: none; }
}
body.mockup-home .nav-item__btn { transition: color .25s ease; }
body.mockup-home .hamburger span { transition: background .25s ease; }
/* Top-of-page state — #225. The hero used to be a dark burgundy panel, so the
   header reversed to a white logo and white nav. With the scrim gone and the
   photo running bright, reversed type no longer holds, so the header wears the
   same glass pill it uses when scrolled and keeps its normal dark logo and
   navy nav. Only the logo size still distinguishes the two states. */
body.mockup-home .site-header:not(.is-scrolled) .site-header__inner {
  margin: 10px auto 0;
  max-width: min(1180px, calc(100% - 28px));
  padding: 8px 20px;
  background: rgba(255, 255, 255, 0.52);
  -webkit-backdrop-filter: blur(22px) saturate(1.6);
  backdrop-filter: url(#uc-liquid-glass) blur(5px) saturate(1.6);
  border-color: rgba(255, 255, 255, 0.62);
  box-shadow: 0 12px 32px rgba(10, 42, 73, 0.14), inset 0 1px 0 rgba(255, 255, 255, 0.7);
}
@supports (-webkit-touch-callout: none) {
  body.mockup-home .site-header:not(.is-scrolled) .site-header__inner {
    backdrop-filter: blur(22px) saturate(1.6);
    background: rgba(255, 255, 255, 0.64);
  }
}
/* Scrolled state: floating glass pill (backdrop blur over the page). */
body.mockup-home .site-header.is-scrolled .site-header__inner {
  margin: 10px auto 0;
  max-width: min(1180px, calc(100% - 28px));
  padding: 8px 20px;
  background: rgba(255, 255, 255, 0.58);
  -webkit-backdrop-filter: blur(22px) saturate(1.6);
  backdrop-filter: url(#uc-liquid-glass) blur(5px) saturate(1.6);
  border-color: rgba(255, 255, 255, 0.65);
  box-shadow: 0 12px 32px rgba(10, 42, 73, 0.14), inset 0 1px 0 rgba(255, 255, 255, 0.7);
}
body.mockup-home .nav-dropdown {
  border-radius: 16px;
  overflow: hidden;
  background: rgba(255, 255, 255, 0.8);
  -webkit-backdrop-filter: blur(18px) saturate(1.4);
  backdrop-filter: blur(18px) saturate(1.4);
  border-color: rgba(255, 255, 255, 0.6);
  box-shadow: 0 12px 32px rgba(10, 42, 73, 0.12), inset 0 1px 0 rgba(255, 255, 255, 0.7);
}
body.mockup-home .nav-dropdown a:hover { background: rgba(246, 241, 231, 0.75); }
/* Glass outline CTA on dark heroes (secondary button only — primary stays solid). */
body.mockup-home .btn--dark.btn--outline {
  background: rgba(255, 255, 255, 0.12);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  border-color: rgba(255, 255, 255, 0.55);
}
/* Mobile drawer joins the glass system. */
body.mockup-home .drawer {
  background: rgba(255, 255, 255, 0.86);
  -webkit-backdrop-filter: blur(24px) saturate(1.4);
  backdrop-filter: blur(24px) saturate(1.4);
}
body.mockup-home .drawer-sub { background: rgba(246, 241, 231, 0.7); }
/* Bottom-right floating CTA: champagne with a soft metallic gradient
   (ink text: 8.9:1 vs the deepest stop); richer gold on hover. */
body.mockup-home .floating-cta {
  background: linear-gradient(180deg, #e3cfa9, #d9c29f 60%, #cbb083);
  border-color: var(--uc-gold-light);
  color: var(--uc-ink);
  box-shadow: 0 8px 24px rgba(43, 10, 26, 0.35);
}
body.mockup-home .floating-cta:hover {
  background: linear-gradient(180deg, #d9c29f, #b89a72 70%, #a48560);
  border-color: var(--uc-gold);
  color: var(--uc-ink);
}

/* ---------- 7 · Hero: clear photo, content on glass ---------- */
/* #225 (John, 2026-08-05) — "brighten this image so it's clearer, with no
   overlays (gradient). I'm thinking we can extend the glass look here as well."
   The burgundy duotone panel and both radial washes are gone; the road photo
   now runs clean and is lifted with a filter rather than tinted. Legibility
   moves off the scrim and onto the glass frame around the hero copy below. */
body.mockup-home .hero .photo--fill {
  background:
    url("../img/path-road.jpg") center 52% / cover no-repeat,
    #e9e2d6;
  filter: brightness(1.16) contrast(0.98) saturate(1.06);
}
/* Taller opening hero: +20% over the last bump — near full viewport on
   desktop (closing hero keeps its --short height). */
body.mockup-home .hero:not(.hero--short) { min-height: clamp(576px, 94vh, 960px); }
/* Parallax overscan: the fill runs 20% tall inside the clipped hero bg so
   GSAP can drift it up to ±8% without exposing edges. */
body.mockup-home .hero__bg { overflow: hidden; }
body.mockup-home .hero .photo--fill { position: relative; height: 120%; top: -10%; }
/* #225 / #223 — scrims removed from both heroes. Only the faintest lift stays,
   to stop the photo blowing out where it meets the page above and below. */
body.mockup-home .hero__overlay {
  background: linear-gradient(to top, rgba(30, 7, 19, 0.16) 0%, rgba(30, 7, 19, 0) 42%);
}
/* Closing hero ("Start your charitable journey."): the bridge-at-dusk brand
   photo. #223 — "Extend the glass frame and brighten the image": same
   treatment as the top hero, no navy scrim, copy carried on the glass frame. */
body.mockup-home .hero--short .photo--fill {
  background:
    url("../img/hero-bridge.jpg") center 45% / cover no-repeat,
    #dfe6ee;
  filter: brightness(1.2) contrast(0.97) saturate(1.04);
}
body.mockup-home .hero--short .hero__overlay {
  background: linear-gradient(to top, rgba(6, 16, 30, 0.16) 0%, rgba(6, 16, 30, 0) 42%);
}

/* ---------- 7b · Hero glass frame (#225 / #223) ----------
   With the scrims gone, white type on a bright photo would not hold, so the
   hero copy moves onto the same liquid-glass panel the Two Paths stats and
   Find Your Path tiles use: real refraction in Chromium via #uc-liquid-glass,
   plain frost everywhere else. Text flips to navy to sit on the light frost. */
body.mockup-home .hero .hero__inner {
  padding: clamp(28px, 4vw, 52px) clamp(24px, 4vw, 56px);
  border-radius: 26px;
  /* 0.58, not the 0.46 the stat panels use: hero copy sits over asphalt and
     shadow, and at 0.46 navy body text fell to ~3.2:1 on the darkest regions.
     At 0.58 the worst case clears AA while the panel still reads as glass. */
  background: rgba(255, 255, 255, 0.58);
  border: 1px solid rgba(255, 255, 255, 0.68);
  -webkit-backdrop-filter: blur(20px) saturate(1.4);
  backdrop-filter: url(#uc-liquid-glass) blur(8px) saturate(1.4);
  box-shadow: 0 18px 54px rgba(10, 42, 73, 0.18), inset 0 1px 0 rgba(255, 255, 255, 0.72);
  color: var(--uc-navy);
}
body.mockup-home .hero .hero__inner h1,
body.mockup-home .hero .hero__inner h2 { color: var(--uc-navy); }
body.mockup-home .hero .hero__inner .lead,
body.mockup-home .hero .hero__inner .hero__intro p { color: rgba(10, 42, 73, 0.86); }
/* Burgundy-dark, not the standard burgundy: the eyebrow is small uppercase text,
   so it needs the full 4.5:1 and #6b2146 only reached 3.6:1 over the darkest
   backdrop the panel can sit on. */
body.mockup-home .hero .hero__inner .eyebrow { color: var(--uc-burgundy-dark); }
/* The hero CTAs still render with .btn--dark (the on-dark variant). On the light
   glass frame they need the normal light-ground treatment: solid burgundy
   primary, navy-outlined secondary. */
body.mockup-home .hero .hero__inner .btn--dark {
  background: var(--uc-burgundy);
  border-color: var(--uc-burgundy);
  color: #fff;
}
body.mockup-home .hero .hero__inner .btn--dark:hover {
  background: var(--uc-burgundy-dark);
  border-color: var(--uc-burgundy-dark);
  color: #fff;
}
body.mockup-home .hero .hero__inner .btn--dark.btn--outline {
  background: rgba(255, 255, 255, 0.4);
  border-color: rgba(10, 42, 73, 0.45);
  color: var(--uc-navy);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
}
body.mockup-home .hero .hero__inner .btn--dark.btn--outline:hover {
  background: var(--uc-navy);
  border-color: var(--uc-navy);
  color: #fff;
}

/* iOS/Safari can't run SVG filters in backdrop-filter; keep the frost. */
@supports (-webkit-touch-callout: none) {
  body.mockup-home .hero .hero__inner {
    backdrop-filter: blur(20px) saturate(1.4);
    background: rgba(255, 255, 255, 0.66);
  }
}
@media (max-width: 599px) {
  body.mockup-home .hero .hero__inner {
    padding: clamp(22px, 6vw, 30px) clamp(18px, 5vw, 26px);
    border-radius: 20px;
  }
}

/* ---------- 8 · Trust strip: white ground, seal stands alone ---------- */
/* White (not cream) because the Candid badge ships with a baked-in opaque
   background; on white it stops reading as a pasted box. Official
   transparent SVG is on the asset-request list. */
/* Trust strip (John, 2026-07-23): reworked from an orphan teal band into a
   warm cream shelf that carries the hero down into the white of Two Paths —
   no hard rules, a short label giving the credentials a voice, and all three
   marks in ONE matched card set (which also swallows Candid's baked-in box). */
/* Tip of the line mark carried up into the trust band (John, 2026-07-24) so the
   swoosh reads as one continuous line across the seam. Geometry mirrors the Two
   Paths mark exactly (same right/width, and a bottom offset of T − W), overflow
   keeps it clipped to this band, and .wrapper sits above it so the credential
   cards stay clean. Its drift is synced to Two Paths in mockup-home.js. */
body.mockup-home .trust-strip { position: relative; overflow: hidden; }
body.mockup-home .trust-strip > .wrapper { position: relative; z-index: 1; }
body.mockup-home .trust-strip::after {
  content: "";
  position: absolute;
  /* Geometry mirrors the Two Paths mark exactly — keep these in sync. */
  right: clamp(-760px, -48vw, -370px); /* +20vw = 20% of the mark's own width, John 2026-07-28 (orig -300/-20vw/-140) */
  bottom: calc(clamp(180px, 26vw, 380px) - clamp(1020px, 100vw, 1930px));
  width: clamp(1020px, 100vw, 1930px);
  aspect-ratio: 1;
  background-color: var(--uc-burgundy);
  -webkit-mask: url("../img/line-uc.svg") center / contain no-repeat;
  mask: url("../img/line-uc.svg") center / contain no-repeat;
  opacity: 0.06;
  pointer-events: none;
  transform: translate3d(0, var(--sym-y, 0px), 0);
  will-change: transform;
}
body.mockup-home .trust-strip {
  /* Hands off to Two Paths mid-ramp (John, 2026-07-24): this band no longer
     resolves to white inside itself — it ends on #f7f2e7 and Two Paths picks up
     that exact tone, so the two read as one continuous gradient. */
  background:
    var(--grain-faint) repeat,
    linear-gradient(180deg, #f4eee1 0%, #f7f2e7 100%);
  background-blend-mode: multiply, normal;
  border: 0;
  padding-block: clamp(40px, 6vw, 64px);
}
/* Two columns: the voice on the left, the matched card set on the right. */
body.mockup-home .trust-strip__inner {
  display: grid;
  grid-template-columns: minmax(200px, 0.85fr) minmax(0, 1.7fr);
  gap: clamp(28px, 5vw, 60px);
  align-items: center;
}
body.mockup-home .trust-strip__lead .eyebrow { margin: 0 0 10px; }
body.mockup-home .trust-strip__note {
  color: var(--uc-navy);
  opacity: 0.82;
  line-height: 1.5;
  margin: 0;
  max-width: 34ch;
}
/* Marks: three equal cards, one visual language. */
body.mockup-home .trust-strip__marks {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(12px, 1.6vw, 20px);
}
body.mockup-home .trust-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  min-height: 132px;
  padding: 20px 16px;
  text-align: center;
  background: #fff;
  border: 1px solid rgba(51, 113, 122, 0.18);
  border-radius: 16px;
  box-shadow: 0 6px 20px rgba(51, 113, 122, 0.10);
}
/* Logo art rides bare inside the card (no per-badge shadow now). */
body.mockup-home .trust-badge {
  height: clamp(58px, 6.5vw, 76px);
  width: auto;
  filter: none;
}
body.mockup-home .trust-item--seal .trust-item__seal {
  height: clamp(44px, 5vw, 54px);
  width: auto;
}
body.mockup-home .trust-item__label {
  color: var(--uc-teal-ink);
  font-size: 0.78rem;
  letter-spacing: 0.04em;
}

/* ---------- 8.5 · Universal image parallax layer ----------
   Any slot that sets --img renders it on ::after at 124% height, so GSAP can
   drift --pary vertically for real parallax without exposing edges.
   --tint layers a color wash above the photo; --px/--py set the crop. */
body.mockup-home .photo { position: relative; overflow: hidden; }
/* Two Paths runs a wider parallax (+/-11% vs 7%), and translateY percentages
   resolve against THIS layer's own height, not the card's. At 124% tall, 11%
   travels 13.6% of the card and overshoots the 12% overhang, exposing a strip
   at the top and bottom (John spotted it, 2026-07-28). 140% tall gives a 20%
   margin each side, so 11% x 1.40 = 15.4% leaves ~4.6% of slack.
   RULE OF THUMB: margin must exceed amp x (height/100). */
body.mockup-home .grid-2 .photo::after { top: -20%; height: 140%; }
body.mockup-home .photo::after {
  content: "";
  position: absolute;
  left: 0; right: 0; top: -12%; height: 124%;
  /* Grain rides over every photo too, so images share the page's texture. */
  background-image:
    var(--grain),
    var(--tint, linear-gradient(transparent, transparent)),
    var(--img);
  background-size: 300px auto, cover, cover;
  background-position: 0 0, var(--px, 50%) var(--py, 50%), var(--px, 50%) var(--py, 50%);
  background-repeat: repeat, no-repeat, no-repeat;
  background-blend-mode: soft-light, normal, normal;
  transform: translateY(var(--pary, 0%));
  pointer-events: none;
}

/* ---------- 9 · Photo slots: linen panels with the seal watermark ---------- */
/* No fabricated photography in the mockup round. aria-labels on the figures
   remain the shot list for the real photo pass. */
body.mockup-home .photo {
  background: linear-gradient(150deg, #f2ecdf, #e6ddcc);
}
body.mockup-home .photo::before {
  content: ""; position: absolute; inset: 0;
  background: url("../img/uc-seal-mark.png") center / clamp(64px, 38%, 120px) no-repeat;
  opacity: 0.09;
}
/* One tone deeper inside cream sections, with a white inset edge. */
body.mockup-home .section--warm .photo {
  background: linear-gradient(150deg, #efe8da, #e2d8c4);
  box-shadow: inset 0 0 0 1px #fff;
}
/* What-We-Do media slot: real brand photo (Athletes gala, dignity-framed),
   rounded + lifted to match the elevated card language. */
body.mockup-home .section--warm .alt-row__media .photo {
  --img: url("../img/what-we-do.jpg?v=3"); --px: 50%; --py: 20%;
  border-radius: 20px;
  border-color: rgba(51, 34, 20, 0.08);
  box-shadow: 0 16px 40px rgba(10, 42, 73, 0.12);
}
body.mockup-home .section--warm .alt-row__media .photo::before { content: none; }
/* Give/Do slots (Two Paths): real brand photos, rounded + lifted. */
body.mockup-home .section:not(.band--dark):has(> .wrapper > .grid-2) .grid-2 > div:nth-child(1) .photo {
  --img: url("../img/give-road.jpg"); --py: 62%;
}
body.mockup-home .section:not(.band--dark):has(> .wrapper > .grid-2) .grid-2 > div:nth-child(2) .photo {
  --img: url("../img/do-steps.jpg"); --py: 55%;
}
body.mockup-home .section:not(.band--dark):has(> .wrapper > .grid-2) .grid-2 .photo {
  /* Landscape crop instead of the wireframe's square (!important beats the
     inline aspect-ratio uc_photo() writes). */
  aspect-ratio: 3 / 2 !important;
  border-radius: 20px;
  border-color: rgba(51, 34, 20, 0.08);
  box-shadow: 0 16px 40px rgba(10, 42, 73, 0.12);
}
body.mockup-home .section:not(.band--dark):has(> .wrapper > .grid-2) .grid-2 .photo::before { content: none; }

/* Find Your Path tiles: real photos with each path's color tint over them
   (keeps the four-color wayfinding), watermark off. */
body.mockup-home .portrait-card:nth-child(1) .photo {
  --img: url("../img/tile-donors.jpg?v=2"); --px: 42%; --py: 42%;
  --tint: linear-gradient(rgba(107, 33, 70, 0.16), rgba(107, 33, 70, 0.04));
}
body.mockup-home .portrait-card:nth-child(2) .photo {
  --img: url("../img/tile-advisors.jpg"); --px: 46%; --py: 45%;
  --tint: linear-gradient(rgba(10, 42, 73, 0.16), rgba(10, 42, 73, 0.04));
}
body.mockup-home .portrait-card:nth-child(3) .photo {
  /* Wayfinding palette (John, 2026-07-24): Donors burgundy, Advisors navy,
     Program Managers teal, Athletes gold. */
  --img: url("../img/tile-managers.jpg?v=2"); --px: 50%; --py: 38%;
  --tint: linear-gradient(rgba(51, 113, 122, 0.16), rgba(51, 113, 122, 0.04));
}
body.mockup-home .portrait-card:nth-child(4) .photo {
  --img: url("../img/tile-athletes.jpg"); --px: 55%; --py: 48%;
  --tint: linear-gradient(rgba(164, 133, 96, 0.18), rgba(164, 133, 96, 0.05));
}
body.mockup-home .portrait-card .photo::before { content: none; }

/* Testimonial media slot: real brand photo beside the Watchlist quote. */
/* Wider photo column + taller crop so the image fills the quote's height
   (!important beats uc_photo()'s inline 1/1). */
@media (min-width: 900px) {
  body.mockup-home .pullquote { grid-template-columns: 1.25fr 1.4fr; align-items: start; }
  body.mockup-home .pullquote__media .photo { aspect-ratio: 4 / 5 !important; }
}
body.mockup-home .pullquote__media .photo {
  --img: url("../img/quote-photo.jpg?v=2"); --px: 52%; --py: 40%;
  border-radius: 20px;
  border-color: rgba(51, 34, 20, 0.08);
  box-shadow: 0 16px 40px rgba(10, 42, 73, 0.12);
}
body.mockup-home .pullquote__media .photo::before { content: none; }
/* Dark slots (impact band) follow the band onto navy, with the gold wash. */
body.mockup-home .photo--dark {
  background:
    radial-gradient(ellipse at 30% 20%, rgba(164, 133, 96, 0.14), transparent 62%),
    linear-gradient(150deg, #14355a, #081f37);
  border-color: rgba(255, 255, 255, 0.12);
}
body.mockup-home .photo--dark::before { content: none; }
/* Hero backgrounds are full designed panels — no watermark. */
body.mockup-home .hero .photo--fill::before { content: none; }

/* ---------- 10 · Cards ---------- */
body.mockup-home .card { transition: border-color .18s ease, box-shadow .18s ease, transform .18s ease; }
body.mockup-home .card:hover {
  border-color: rgba(164, 133, 96, 0.55);
  box-shadow: 0 10px 30px rgba(10, 42, 73, 0.08);
  transform: translateY(-2px);
}

/* ---------- 10.5 · Find Your Path: liquid-glass tiles ---------- */
/* v2a (John, 2026-07-29): background + gradient transition ported one-for-one
   from v1b — white-ish ground with the oversized gold curved path as the ONE
   decorative system. The four tiles carry the color and the wayfinding, so
   the background never competes with them. v2b keeps the alpine-road photo. */
body.mockup-home .section:has(> .wrapper > .grid-4) {
  position: relative;
  overflow: hidden;
  /* Smooth handoff from 02 (v1b): 02's ground renders as a light cream at its
     base (white veil over the sand gradient), so 03 starts on that same tone
     and resolves down into the warm sand — no step at the seam. */
  background:
    var(--grain-soft) repeat,
    linear-gradient(180deg, #f8f4ec 0px, #f4edde 200px, #f1e9d8 400px),
    #f1e9d8;
  background-blend-mode: multiply, normal, normal;
}
/* (v1b's gold curved-path stripe removed per John, 2026-07-29 — the gradient
   ground above is the whole background here.) */
/* Cards: liquid glass over the road (kube.io displacement recipe — Chromium
   refracts via the SVG filter; Safari/Firefox keep the plain frost). */
body.mockup-home .portrait-card {
  border-radius: 20px;
  overflow: hidden;
  background: rgba(255, 255, 255, 0.52);
  border-color: rgba(255, 255, 255, 0.7);
  -webkit-backdrop-filter: blur(18px) saturate(1.35);
  backdrop-filter: url(#uc-liquid-glass) blur(7px) saturate(1.35);
  box-shadow: 0 10px 34px rgba(10, 42, 73, 0.16), inset 0 1px 0 rgba(255, 255, 255, 0.75);
}
/* ---------- iOS glass ----------
   iOS/Safari can't run SVG filters in backdrop-filter, and because the
   unprefixed declaration above wins over the -webkit- one it would otherwise
   get NO glass at all. -webkit-touch-callout is iOS-only, so Chromium is
   untouched by anything in this block.
   Beyond restoring the blur, we fake the refracting bezel: a masked rim with
   its OWN backdrop-filter (brighter, more saturated, less blurred than the
   centre) reads as light bending at the edge of a lens. */
@supports (-webkit-touch-callout: none) {
  body.mockup-home .portrait-card { backdrop-filter: blur(18px) saturate(1.35); }
  body.mockup-home .site-header.is-scrolled .site-header__inner { backdrop-filter: blur(22px) saturate(1.6); }

  /* Desktop Safari: frost a little heavier to compensate for the missing
     refraction. (The masked rim experiment was removed — on iOS it read as a
     hard border ring, not a bezel.) */
  body.mockup-home .portrait-card {
    background: rgba(255, 255, 255, 0.6);
    box-shadow:
      0 10px 34px rgba(10, 42, 73, 0.16),
      inset 0 1px 0 rgba(255, 255, 255, 0.9);
  }
}
body.mockup-home .portrait-card:hover {
  transform: translateY(-4px);
  box-shadow: 0 16px 40px rgba(10, 42, 73, 0.11);
}
body.mockup-home .portrait-card .btn--ghost { transition: transform .18s ease, background .18s ease, color .18s ease; }
body.mockup-home .portrait-card:hover .btn--ghost { transform: translateX(3px); }
/* Each path carries one brand color — whisper tint on the linen panel,
   matching pill chip on the eyebrow. Order: Donors (burgundy), Advisors
   (navy), Program Managers (teal), Athletes (gold). Copy untouched. */
body.mockup-home .portrait-card .eyebrow--mute {
  display: inline-block;
  padding: 5px 12px;
  border-radius: 999px;
  align-self: flex-start;
}
/* (Tile photo backgrounds live in §9 with the other photo-slot rules;
   linen fallbacks retired when the real photos landed.) */
body.mockup-home .portrait-card:nth-child(1) .eyebrow--mute { background: rgba(107, 33, 70, 0.09); color: var(--uc-burgundy); }
body.mockup-home .portrait-card:nth-child(2) .eyebrow--mute { background: rgba(10, 42, 73, 0.08); color: var(--uc-navy); }
body.mockup-home .portrait-card:nth-child(3) .eyebrow--mute { background: rgba(51, 113, 122, 0.10); color: var(--uc-teal-ink); }
body.mockup-home .portrait-card:nth-child(4) .eyebrow--mute { background: rgba(164, 133, 96, 0.14); color: var(--uc-gold-dark); }

/* Mobile: Find Your Path runs two-up with compacted type (John, 2026-07-21).
   The h3 !important is needed to beat the tile's inline clamp() size. */
@media (max-width: 899px) {
  body.mockup-home .section .grid-4 {
    grid-template-columns: 1fr 1fr;
    gap: 12px;
  }
  body.mockup-home .portrait-card { border-radius: 14px; }
  body.mockup-home .portrait-card .card__body { padding: 12px; }
  body.mockup-home .portrait-card .card__body > * + * { margin-top: 8px; }
  body.mockup-home .portrait-card h3 { font-size: 1.02rem !important; }
  body.mockup-home .portrait-card .small { font-size: 0.78rem; line-height: 1.45; }
  body.mockup-home .portrait-card .eyebrow--mute {
    font-size: 0.58rem;
    letter-spacing: 0.12em;
    padding: 4px 9px;
  }
  body.mockup-home .portrait-card .btn--ghost { font-size: 0.78rem; }

  /* All grain runs 20% lighter on mobile (John) — one token swap covers
     every surface that uses it. */
  body.mockup-home {
    /* v2: grain removed here too (see the :root note). */
    --grain: none;
    --grain-white: none;
    --grain-soft: none;
    --grain-faint: none;
    --grain-navy: none;
  }

  /* Glass on mobile: keep the frosted surfaces (Safari/iOS uses the
     -webkit- blur fallback; the SVG displacement is Chromium-only), and
     round the drawer's leading edge so it reads as a glass panel. */
  /* Mobile glass = pure frost. No SVG refraction (Safari can't run it, and at
     phone size the bezel reads as an artefact rather than an effect) and no
     rim layer — that was showing as a hard border ring on iOS. Desktop keeps
     the refraction. */
  body.mockup-home .site-header.is-scrolled .site-header__inner {
    -webkit-backdrop-filter: blur(26px) saturate(1.5);
    backdrop-filter: blur(26px) saturate(1.5);
    background: rgba(255, 255, 255, 0.76);
    border-color: rgba(255, 255, 255, 0.5);
    box-shadow: 0 10px 26px rgba(10, 42, 73, 0.12);
  }
  body.mockup-home .portrait-card {
    -webkit-backdrop-filter: blur(24px) saturate(1.45);
    backdrop-filter: blur(24px) saturate(1.45);
    background: rgba(255, 255, 255, 0.72);
    border-color: rgba(255, 255, 255, 0.45);
    box-shadow: 0 8px 24px rgba(10, 42, 73, 0.14);
  }
  /* kill the bezel-rim layer on phones */
  body.mockup-home .portrait-card::after,
  body.mockup-home .site-header.is-scrolled .site-header__inner::after { content: none; }

  /* Two Paths columns go side by side at the same breakpoint as the path
     cards (John) — the base stylesheet only splits .grid-2 at 900px. */
  body.mockup-home .section:not(.band--dark) .grid-2 {
    grid-template-columns: 1fr 1fr;
  }
  body.mockup-home .drawer {
    border-top-left-radius: 22px;
    border-bottom-left-radius: 22px;
  }

  /* The header is fixed + transparent, so hero copy must clear it on mobile
     (tall stacked content used to run up under the logo). */
  body.mockup-home .hero__overlay { padding-top: 104px; }
  body.mockup-home .hero:not(.hero--short) { min-height: clamp(600px, 92vh, 820px); }

  /* Smaller CTAs on mobile, side by side (they share the row, so keep the
     labels from wrapping oddly and let each take half the width). */
  body.mockup-home .hero .btn-row {
    flex-wrap: nowrap;
    gap: 10px;
  }
  body.mockup-home .hero .btn {
    flex: 1 1 0;
    min-width: 0;
    padding: 10px 10px;
    min-height: 44px;
    font-size: 0.74rem;
    line-height: 1.25;
    letter-spacing: 0;
    text-align: center;
  }
  body.mockup-home .hero .btn .ext-mark { display: none; }

  /* Trust strip stacks: the voice sits above its matched card set, and the
     three credential cards stay in one row across the full width. */
  body.mockup-home .trust-strip__inner {
    grid-template-columns: 1fr;
    gap: 26px;
  }
  body.mockup-home .trust-strip__lead {
    text-align: center;
    justify-items: center;
  }
  body.mockup-home .trust-strip__note { max-width: 46ch; margin-inline: auto; }
  body.mockup-home .trust-item {
    min-height: 108px;
    padding: 16px 10px;
    gap: 9px;
  }
  body.mockup-home .trust-badge { height: clamp(46px, 12vw, 68px); }

  /* "01 · Two paths" (Give/Do) also runs side-by-side here, compacted.
     The band--dark exclusion keeps the impact band's heading rows stacked. */
  body.mockup-home .section:not(.band--dark) .grid-2 {
    grid-template-columns: 1fr 1fr;
    gap: 12px;
  }
  body.mockup-home .section:not(.band--dark) .grid-2 h3 { font-size: 1.02rem; }
  body.mockup-home .section:not(.band--dark) .grid-2 p { font-size: 0.78rem; line-height: 1.5; }
  body.mockup-home .section:not(.band--dark) .grid-2 .btn {
    padding: 9px 14px;
    min-height: 36px;
    font-size: 0.72rem;
  }

  /* Footer runs fully left-aligned on mobile — the tax disclaimer and
     copyright sit right/opposite on desktop, which reads as ragged once the
     columns stack. */
  body.mockup-home .site-footer,
  body.mockup-home .footer-newsletter-band,
  body.mockup-home .footer-bottom,
  body.mockup-home .footer-identity,
  body.mockup-home .site-footer__grid > div { text-align: left; }
  body.mockup-home .footer-legal {
    text-align: left;
    max-width: none;
  }
  body.mockup-home .footer-bottom { justify-content: flex-start; }
  body.mockup-home .footer-newsletter-band { justify-content: flex-start; }
  body.mockup-home .footer-social { justify-content: flex-start; }
}
@media (max-width: 500px) {
  /* Phones from 500px down: trim every button a notch. */
  body.mockup-home .btn {
    padding: 10px 16px;
    min-height: 40px;
    font-size: 0.78rem;
  }
  body.mockup-home .btn--ghost { padding: 0; min-height: 0; }
  body.mockup-home .floating-cta {
    padding: 9px 14px;
    min-height: 36px;
    font-size: 0.72rem;
  }
  body.mockup-home .header__actions .btn { padding: 7px 12px; font-size: 0.68rem; }
  body.mockup-home .footer-newsletter button { padding: 9px 13px; font-size: 0.64rem; }
  body.mockup-home .hero .btn { font-size: 0.72rem; padding: 10px 10px; min-height: 42px; }
}
@media (max-width: 380px) {
  /* Smallest phones: hero labels need one more step down to stay two-up. */
  body.mockup-home .hero .btn { font-size: 0.68rem; padding: 10px 8px; }
  body.mockup-home .floating-cta {
    padding: 10px 16px;
    min-height: 38px;
    font-size: 0.75rem;
  }
  body.mockup-home .header__actions .btn { font-size: 0.72rem; }
}

/* ---------- 11 · Impact band ---------- */
/* Navy satin (gold-dust) image replaces the flat burgundy (John, 2026-07-21).
   Veil: solid brand navy at the top fading to 55% alpha at the bottom, so
   the band opens anchored-solid behind the heading and the satin + gold
   dust emerge behind the stats. #0c1f38 = no-image fallback base. */
/* John's veil, verbatim: solid brand navy at top fading to 55% — brand navy
   is lighter than the satin's deepest folds, so this evens and lifts the
   band. No noise here; the satin is the texture. */
body.mockup-home .band--dark {
  /* v2 (John, 2026-07-28): impact band taken from direction B — flat pure black.
     Direction A's magenta satin is preserved intact in v1a if it needs to come back. */
  background: #000;
}
/* Stat hairlines: gold fading to brand silver left-to-right — silver's one
   deliberate on-page appearance. */
body.mockup-home .section--dark .jumbo,
body.mockup-home .band--dark .jumbo {
  border-top-color: rgba(164, 133, 96, 0.45);
  border-image-source: linear-gradient(90deg, rgba(164, 133, 96, 0.6), rgba(139, 141, 143, 0.12));
  border-image-slice: 1;
}
/* Gold unit letters on the jumbo stats — champagne text-gold, matching the
   "All Accounts" sub-line (6.3:1 on burgundy). */
body.mockup-home .jumbo__unit { color: var(--uc-gold-light); }
/* Gold sub-line under the 189 numeral. Small type, so it uses the
   text-gold (--uc-gold-light, 6.3:1 on burgundy), not raw #a48560. */
body.mockup-home .jumbo__sub {
  font-family: var(--sans);
  font-size: 0.9375rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--uc-gold-light);
  margin-top: 12px;
}
/* Stat labels: keep date ranges unbroken and wrap multi-line labels evenly. */
body.mockup-home .nowrap { white-space: nowrap; }
body.mockup-home .jumbo__label { text-wrap: balance; }
/* Reach row, from direction B (John, 2026-07-28): the pill chrome, network photo
   and line mark are gone. The paragraph sits flat on the black band with the
   globe line-art at the far right, inside the container. */
body.mockup-home .uc-reach-pill {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: clamp(28px, 5vw, 72px);
  margin-top: clamp(32px, 5vw, 56px);
  background: none;
  border: 0;
  padding: 0;
  box-shadow: none;
}
body.mockup-home .uc-reach-pill p { margin: 0; max-width: 60ch; }
body.mockup-home .uc-reach-globe {
  flex: 0 0 auto;
  width: clamp(140px, 17vw, 250px);
  aspect-ratio: 1;
  background: var(--uc-globe) center / contain no-repeat;
  opacity: 0.9;
}
/* Narrow screens: globe hidden, text spans the full row. */
@media (max-width: 760px) {
  body.mockup-home .uc-reach-globe { display: none; }
}
body.mockup-home .uc-reach-pill p { max-width: 62ch; }

/* "What our community says": direction B's white-to-cream gradient (John,
   2026-07-28) — the same stack B uses on its .section--warm bands. */
body.mockup-home .section:has(> .wrapper > .pullquote) {
  background:
    linear-gradient(rgb(255 255 255), rgb(255 255 255 / 50%)),
    linear-gradient(180deg, #ffffff 0%, #f6f1e7 55%, #f1e9d8 100%);
  background-position: 50% 50%, 50% 50%;
  background-blend-mode: normal, normal;
}

/* ---------- 12 · Pull quote ---------- */
body.mockup-home .section .pullquote__quote { color: var(--uc-navy); }
body.mockup-home .pullquote__mark { color: var(--uc-gold); }

/* ---------- 13 · Footer: burgundy variant (navy floor = restore
   `background: var(--uc-navy)` on .site-footer and swap the button
   text color back to navy) ---------- */
/* Base style.css already paints .site-footer with --uc-burgundy; the gold
   hairline keeps it reading as its own band under the burgundy closing hero. */
body.mockup-home .site-footer {
  position: relative;
  overflow: hidden;
  background:
    var(--grain) repeat,
    linear-gradient(180deg, #6b2146 0%, #541a38 45%, #331023 100%);
  background-blend-mode: soft-light, normal;
}
body.mockup-home .site-footer > .wrapper { position: relative; z-index: 1; }
/* Footer marks removed per John, 2026-07-24 — restore by setting content back
   to "" on this rule and the ::after below. */
body.mockup-home .site-footer::before {
  content: none;
  position: absolute;
  left: -34%;
  top: -48%;
  width: clamp(1120px, 112vw, 2150px);
  aspect-ratio: 1;
  background-color: var(--uc-gold-light);
  -webkit-mask: url("../img/line-uc.svg") center / contain no-repeat;
  mask: url("../img/line-uc.svg") center / contain no-repeat;
  opacity: 0.05;
  pointer-events: none;
}
/* Footer mark removed per John, 2026-07-24 — see the ::before note above. */
body.mockup-home .site-footer::after {
  content: none;
  position: absolute;
  /* Bottom-right, un-mirrored back to the logo's natural direction and dropped
     lower in the band (John, 2026-07-24). */
  right: -22%;
  bottom: -32%;
  width: clamp(1020px, 100vw, 1930px);
  aspect-ratio: 1;
  background-color: var(--uc-gold-light);
  -webkit-mask: url("../img/line-uc.svg") center / contain no-repeat;
  mask: url("../img/line-uc.svg") center / contain no-repeat;
  opacity: 0.05;
  pointer-events: none;
}
body.mockup-home .footer-col__head { color: var(--uc-gold-light); }
body.mockup-home .footer-newsletter button { color: var(--uc-burgundy); }
body.mockup-home .footer-newsletter button:hover { background: var(--uc-offwhite); }
body.mockup-home .footer-newsletter { border-radius: 999px; overflow: hidden; }

/* ---------- 14 · Find-path modal ---------- */
body.mockup-home .uc-modal__overlay { background: rgba(10, 42, 73, 0.55); }
body.mockup-home .uc-modal__close { border-radius: 50%; }
body.mockup-home .uc-modal__close:hover { background: var(--uc-offwhite); }
body.mockup-home .uc-modal h3,
body.mockup-home .uc-modal h4 { color: var(--uc-navy); }

/* ---------- 15 · Focus-visible: navy on light, teal on dark ---------- */
body.mockup-home :focus-visible { outline: 2px solid var(--uc-navy); outline-offset: 2px; }
body.mockup-home .hero :focus-visible,
body.mockup-home .section--dark :focus-visible,
body.mockup-home .section--navy :focus-visible,
body.mockup-home .site-footer :focus-visible { outline-color: var(--uc-teal); }

/* ---------- 16 · Token-driven system pieces (no homepage render today) ---------- */
body.mockup-home .step-num { color: var(--uc-gold-dark); }

/* ---------- 16.4 · SVG icon system ----------
   Replaces the wireframe's text glyphs (→ ↗ ▾ ×) with stroked SVGs drawn
   as masks, so they inherit currentColor and scale with the type. Icons
   are decorative; the link text carries the meaning. */
body.mockup-home .i-arrow,
body.mockup-home .i-ext,
body.mockup-home .nav-item__caret,
body.mockup-home .drawer-group__caret,
body.mockup-home .ext-mark {
  display: inline-block;
  width: 1em;
  height: 1em;
  background-color: currentColor;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
  vertical-align: -0.13em;
  /* the original glyph is masked out of view */
  font-size: 1em;
  color: inherit;
  text-indent: -9999px;
  overflow: hidden;
  opacity: 1;
}
body.mockup-home .i-arrow {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 12h14M13 6l6 6-6 6'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 12h14M13 6l6 6-6 6'/%3E%3C/svg%3E");
  width: 1.15em;
}
body.mockup-home .i-ext,
body.mockup-home .ext-mark {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M7 17 17 7M9 7h8v8'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M7 17 17 7M9 7h8v8'/%3E%3C/svg%3E");
  width: 0.85em;
  height: 0.85em;
}
body.mockup-home .nav-item__caret,
body.mockup-home .drawer-group__caret {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  width: 0.7em;
  height: 0.7em;
  opacity: 0.75;
}
/* Modal close: the × glyph swapped for a stroked cross. */
body.mockup-home .uc-modal__close {
  font-size: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}
body.mockup-home .uc-modal__close::before {
  content: "";
  width: 18px;
  height: 18px;
  background-color: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='M6 6l12 12M18 6 6 18'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='M6 6l12 12M18 6 6 18'/%3E%3C/svg%3E") center / contain no-repeat;
}
/* Card eyebrows drop the external mark — the link below already carries it. */
body.mockup-home .portrait-card .eyebrow .ext-mark,
body.mockup-home .uc-modal .eyebrow .ext-mark { display: none; }

/* ---------- 16.5 · Floating CTA clearance ----------
   The CTA is fixed bottom-right. On phones and tablets it sat over the
   footer copy, so reserve room beneath the last line (and give the CTA a
   safe-area inset on notched devices). It also fades out once the footer
   is in view — see mockup-home.js. */
@media (max-width: 1080px) {
  body.mockup-home .site-footer { padding-bottom: 150px; }
  body.mockup-home .footer-bottom { gap: var(--space-3); }
  body.mockup-home .floating-cta {
    bottom: calc(16px + env(safe-area-inset-bottom, 0px));
    right: 16px;
  }
}
body.mockup-home .floating-cta { transition: opacity .25s ease, transform .25s ease, background .18s ease, border-color .18s ease; }
body.mockup-home .floating-cta.is-hidden {
  opacity: 0;
  transform: translateY(12px);
  pointer-events: none;
}

/* ---------- 17 · Reduced motion ---------- */
@media (prefers-reduced-motion: reduce) {
  /* This file is homepage-gated, so the html-level override cannot leak. */
  html { scroll-behavior: auto; }
  body.mockup-home *,
  body.mockup-home *::before,
  body.mockup-home *::after { transition-duration: 0.01ms !important; animation-duration: 0.01ms !important; }
  body.mockup-home .card:hover { transform: none; }
}

/* ---------- 18 · Fabric texture overlay (fixed, full-viewport) ---------- */
/* One full-bleed fabric scan (no tiling) riding above every layer — the
   2000px export covers any viewport as a single sheet. brightness/contrast
   pull the light scan toward mid-gray so soft-light adds weave to BOTH the
   light and burgundy bands without milking them; pointer-events: none lets
   every click pass through. Tune strength via opacity. */
body.mockup-home::after {
  display: none; /* texture hidden for now (John, 2026-07-21) — delete this line to restore */
  content: "";
  position: fixed;
  inset: 0;
  z-index: 9999;
  pointer-events: none;
  background: url("../img/fabric-texture.jpg?v=2") center / cover no-repeat;
  /* multiply wants the scan's natural light values — no mid-gray pull-down
     (that filter was a soft-light compensator and would murk the page here). */
  mix-blend-mode: multiply;
  opacity: 0.15;
}


/* ---------- Two Paths: frosted glass stat over each photo ----------
   (John, 2026-07-28) Replaces the black stat cards. Same liquid-glass recipe
   the portrait cards and scrolled header use: real backdrop refraction in
   Chromium via #uc-liquid-glass, plain frost everywhere else. */
body.mockup-home .uc-photo-stat { position: relative; }
body.mockup-home .uc-stat-glass {
  position: absolute;
  left: clamp(14px, 4%, 28px);
  right: clamp(14px, 4%, 28px);
  bottom: clamp(14px, 4%, 28px);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: clamp(16px, 3.2%, 26px) clamp(14px, 4%, 24px);
  border-radius: 18px;
  text-align: center;
  background: rgba(255, 255, 255, 0.52);
  border: 1px solid rgba(255, 255, 255, 0.7);
  -webkit-backdrop-filter: blur(18px) saturate(1.35);
  backdrop-filter: url(#uc-liquid-glass) blur(7px) saturate(1.35);
  box-shadow: 0 10px 34px rgba(10, 42, 73, 0.16), inset 0 1px 0 rgba(255, 255, 255, 0.75);
}
body.mockup-home .uc-stat-glass__num {
  font-family: var(--serif);
  font-weight: 600;
  font-size: clamp(2.4rem, 5.4vw, 3.9rem);
  line-height: 1;
  letter-spacing: -0.015em;
  color: var(--uc-navy);
}
body.mockup-home .uc-stat-glass__label {
  font-family: var(--sans);
  font-size: clamp(0.66rem, 1.05vw, 0.78rem);
  font-weight: 700;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  line-height: 1.45;
  color: var(--uc-navy);
  max-width: 24ch;
}
/* iOS/Safari can't run SVG filters in backdrop-filter; keep the frost. */
@supports (-webkit-touch-callout: none) {
  body.mockup-home .uc-stat-glass {
    backdrop-filter: blur(18px) saturate(1.35);
    background: rgba(255, 255, 255, 0.62);
  }
}


/* ---------- Find Your Path: whole tile is the click target ----------
   (John, 2026-07-28) The ghost link in .card__footer stays the ONLY anchor and
   keeps the visible label, so screen readers still get real link text — its
   ::after just stretches to cover the card. No empty anchors, no nested links.
   Remove by dropping card--linked from the <article> in index.php. */
body.mockup-home .card--linked { position: relative; }
body.mockup-home .card--linked .card__footer a::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  border-radius: inherit;
}
/* NOTE: do NOT give .card__body or .photo position:relative here. The stretched
   ::after resolves inset:0 against its nearest POSITIONED ancestor, so making a
   child positioned shrinks the hit area to that child instead of the card. */
/* Interactive affordance. NOTE: do NOT use transform here — GSAP writes an
   inline transform on these cards for the reveal stagger, and inline beats the
   stylesheet, so a :hover translate is silently dead. These three properties
   are ones GSAP does not touch, so they actually fire. */
body.mockup-home .card--linked {
  transition: box-shadow .2s ease, border-color .2s ease, background-color .2s ease;
}
body.mockup-home .card--linked:hover {
  border-color: var(--uc-gold-light);
  box-shadow: 0 20px 46px rgba(10, 42, 73, 0.22);
  background-color: rgba(255, 255, 255, 0.72);
}
body.mockup-home .card--linked .card__footer a { transition: color .2s ease; }
body.mockup-home .card--linked:hover .card__footer a { color: var(--uc-burgundy-dark); }
/* Keyboard: outline the whole card when the inner link is focused. */
body.mockup-home .card--linked:has(a:focus-visible) {
  outline: 2px solid var(--uc-gold);
  outline-offset: 3px;
}
body.mockup-home .card--linked .card__footer a:focus-visible { outline: none; }
@media (prefers-reduced-motion: reduce) {
  body.mockup-home .card--linked,
  body.mockup-home .card--linked .card__footer a { transition: none; }
}
