/*
 * Shared stylesheet for the three custom landing templates: template-hub.php,
 * template-corporate.php, template-weddings.php. Consolidated from the three
 * validated mockups (rc-studio-hub-v3.html, rc-studio-corporate-landing.html,
 * rc-studio-weddings-landing.html) — corporate and weddings' CSS is byte-
 * identical in the source mockups (verified via diff), so their sections
 * live here once. The hub differs enough (simpler centered hero, split
 * cards instead of stat-bar/services/morph, different stats layout) that
 * its unique sections are also consolidated here rather than duplicated,
 * scoped with body classes only where a genuine name collision exists
 * (both mockups use the class name `.hero`, kept as-is for markup fidelity
 * rather than renamed) — see rc_child_landing_body_class() in functions.php
 * for the `rc-tpl-hub` / `rc-tpl-landing` body classes this relies on.
 *
 * No visual values were changed from the source mockups — this is a
 * consolidation, not a redesign.
 */

/* =========================================================================
   1. UNIVERSAL — identical across all three mockups
   ========================================================================= */

:root {
  --charcoal: #1b1815; --charcoal-2: #23201b; --champagne: #e9dfc7;
  --gold: #a8813f; --gold-bright: #c79a52; --bone: #f7f4ec; --ink: #2a241d;
  --line: rgba(233, 223, 199, 0.18); --line-dark: rgba(42, 36, 29, 0.12);
}
body.rc-tpl-hub, body.rc-tpl-landing { margin: 0; background: var(--bone); color: var(--ink); font-family: 'Work Sans', sans-serif; -webkit-font-smoothing: antialiased; }
body.rc-tpl-hub *, body.rc-tpl-landing * { box-sizing: border-box; }
.serif { font-family: 'Fraunces', serif; }
.mono { font-family: 'IBM Plex Mono', monospace; letter-spacing: 0.06em; text-transform: uppercase; }
.accent { color: var(--gold-bright); }
body.rc-tpl-hub a, body.rc-tpl-landing a { color: inherit; }
:focus-visible { outline: 2px solid var(--gold-bright); outline-offset: 3px; }
@media (prefers-reduced-motion: reduce) {
  body.rc-tpl-hub *, body.rc-tpl-landing * { animation: none !important; scroll-behavior: auto !important; }
  .pop, .pop-stagger > * { opacity: 1 !important; transform: none !important; }
  .hero-content { opacity: 1 !important; transform: none !important; }
  .morph-wrapper { height: auto !important; }
  .morph-sticky { position: static !important; height: auto !important; }
}

/* ---------- POP-IN REVEAL (one-time trigger, bounce easing, mobile-cheap) ---------- */
.js .pop, .js .pop-stagger > * { opacity: 0; }
.js .pop { transform: scale(0.86) translateY(26px); transition: opacity .65s cubic-bezier(.34,1.56,.64,1), transform .65s cubic-bezier(.34,1.56,.64,1); }
.js .pop.is-visible { opacity: 1; transform: scale(1) translateY(0); }
.js .pop-stagger > * { transform: scale(0.86) translateY(22px); transition: opacity .6s cubic-bezier(.34,1.56,.64,1), transform .6s cubic-bezier(.34,1.56,.64,1); }
.js .pop-stagger.is-visible > * { opacity: 1; transform: scale(1) translateY(0); }
.js .pop-stagger.is-visible > *:nth-child(1) { transition-delay: 0s; }
.js .pop-stagger.is-visible > *:nth-child(2) { transition-delay: .08s; }
.js .pop-stagger.is-visible > *:nth-child(3) { transition-delay: .16s; }
.js .pop-stagger.is-visible > *:nth-child(4) { transition-delay: .24s; }

/* ---------- NAV ---------- */
.nav { position: sticky; top: 0; z-index: 50; display: flex; align-items: center; justify-content: space-between; padding: 20px clamp(20px, 5vw, 56px); background: rgba(27, 24, 21, 0.9); backdrop-filter: blur(10px); border-bottom: 1px solid var(--line); transition: padding .3s ease, background .3s ease; }
.nav.scrolled { padding-top: 13px; padding-bottom: 13px; background: rgba(27, 24, 21, 0.97); }
.nav-logo { color: var(--champagne) !important; font-size: 18px; letter-spacing: 0.14em; font-weight: 500; text-decoration: none; text-shadow: 0 1px 3px rgba(0,0,0,0.6); }
.nav-logo span { color: var(--gold-bright); text-shadow: 0 1px 3px rgba(0,0,0,0.6); }
.nav-crumb { color: var(--champagne); opacity: 0.55; font-size: 12px; text-shadow: 0 1px 3px rgba(0,0,0,0.6); }
.nav-links { display: flex; gap: 28px; list-style: none; margin: 0; padding: 0; }
/* color: !important beats the higher-specificity `body.rc-tpl-hub a,
   body.rc-tpl-landing a { color: inherit }` reset above (that selector's
   two element types + one class outweighs this rule's one element + one
   class, so without !important these links were inheriting the body's
   --ink text color instead of champagne — confirmed via computed styles,
   not assumed). Full opacity + text-shadow so it also stays legible over
   the brighter/high-contrast regions of a real photographic hero, not
   just a flat dark background. */
.nav-links a { position: relative; color: var(--champagne) !important; text-decoration: none; font-size: 13px; letter-spacing: 0.08em; text-transform: uppercase; opacity: 1; padding-bottom: 3px; transition: opacity .2s; text-shadow: 0 1px 3px rgba(0,0,0,0.6); }
.nav-links a::after { content: ""; position: absolute; left: 0; right: 100%; bottom: 0; height: 1px; background: var(--gold-bright); transition: right .25s ease; }
.nav-links a:hover { opacity: 1; }
.nav-links a:hover::after { right: 0; }

/* ---------- MARQUEE ---------- */
.marquee-section { background: var(--bone); overflow: hidden; }
.marquee-section:hover .marquee-track { animation-play-state: paused; }
.marquee-label { text-align: center; font-size: 11px; opacity: 0.45; margin: 0 0 20px; }
.marquee-track { display: flex; width: max-content; animation: marquee 26s linear infinite; }
@keyframes marquee { from { transform: translateX(0); } to { transform: translateX(-50%); } }
/* The 26s duration was tuned for a 6-item list. The corporate/hub marquee now
   carries 46 real client names, making the track 5.5x longer — at a fixed 26s
   that scrolled at 264px/s instead of the wedding marquee's 48px/s, fast
   enough that the names were unreadable. Duration scaled to match so both
   marquees move at the same ~47px/s. Scoped, so /weddings/ keeps its 26s.
   If the client list changes materially, rescale this proportionally. */
body.rc-tpl-hub .marquee-track,
body.rc-tpl-corporate .marquee-track { animation-duration: 145s; }
.marquee-item { font-family: 'IBM Plex Mono', monospace; font-size: 14px; letter-spacing: 0.08em; opacity: 0.38; white-space: nowrap; }
/* Separator between marquee entries. .marquee-track is a flex container, and
   flex containers discard the whitespace text nodes between children — so the
   newlines in the template produced no gap at all and adjacent names ran
   together ("...MANSIONLONE PINE PENANG"). A ::after on every item (rather
   than :not(:last-child)) is deliberate: the list is rendered twice back to
   back for the seamless loop, so the final item needs a trailing separator
   before the sequence repeats. Middle dot matches the " · " already used in
   the hero eyebrow. */
.marquee-item::after { content: "\00B7"; margin: 0 clamp(14px, 1.6vw, 26px); }
@media (prefers-reduced-motion: reduce) { .marquee-track { animation: none; overflow-x: auto; padding: 0 24px; } }

footer { background: var(--charcoal); color: var(--champagne); padding: 36px clamp(20px, 5vw, 56px); display: flex; justify-content: space-between; flex-wrap: wrap; gap: 16px; font-size: 12px; opacity: 0.55; border-top: 1px solid var(--line); }
.footer-social { display: flex; gap: 16px; flex-wrap: wrap; }
.footer-social a { text-decoration: underline; text-underline-offset: 2px; }
.footer-social a:hover { opacity: 0.8; }

@media (max-width: 760px) { body.rc-tpl-hub .nav-links { display: none; } }
@media (max-width: 720px) { body.rc-tpl-landing .nav-links, body.rc-tpl-landing .nav-crumb { display: none; } }


/* =========================================================================
   2. HERO — genuine collision: hub's simpler centered hero vs the
      corporate/weddings directional-entrance hero both use `.hero` in the
      source markup. Scoped by body class rather than renamed, to keep
      each template's markup an exact match of its mockup.
   ========================================================================= */

/* ---- Hub hero ---- */
body.rc-tpl-hub .hero { position: relative; overflow: hidden; background: var(--charcoal); padding: clamp(56px, 10vw, 96px) clamp(20px, 5vw, 56px) clamp(70px, 11vw, 110px); text-align: center; }
body.rc-tpl-hub .hero-glow {
  position: absolute; inset: -15% -15%; pointer-events: none; will-change: transform;
  background:
    radial-gradient(ellipse 50% 40% at 20% 90%, rgba(168,129,63,0.34), transparent 65%),
    radial-gradient(ellipse 45% 35% at 82% 10%, rgba(233,223,199,0.10), transparent 60%);
}
body.rc-tpl-hub .hero-inner { position: relative; }
body.rc-tpl-hub .hero-eyebrow { color: var(--gold-bright); font-size: 12px; margin: 0 0 18px; }
body.rc-tpl-hub .hero h1 { color: var(--champagne); font-weight: 400; font-size: clamp(28px, 4.6vw, 48px); line-height: 1.2; margin: 0 auto 20px; max-width: 780px; }
body.rc-tpl-hub .hero p { color: var(--champagne); opacity: 0.7; font-size: clamp(14px, 1.5vw, 16px); line-height: 1.7; max-width: 560px; margin: 0 auto; }
/* Reveal rules below use COMPOUND selectors (body.rc-tpl-X.loaded), not
   descendants. landing-pages.js adds 'loaded' to <body> itself, and an
   element cannot be its own descendant — written as `body.rc-tpl-X .loaded`
   these never matched, so the h1 and CTAs stayed at opacity:0 forever on
   /corporate/ and /weddings/. Likewise the `.js` guard is prefixed, not
   nested: `.js` is on <html>, an ANCESTOR of body. */
.js body.rc-tpl-hub .hero-eyebrow, .js body.rc-tpl-hub .hero h1, .js body.rc-tpl-hub .hero > .hero-inner > p { opacity: 0; transform: translateY(16px); transition: opacity .7s ease, transform .7s ease; }
body.rc-tpl-hub.loaded .hero-eyebrow { opacity: 1; transform: none; transition-delay: .05s; }
body.rc-tpl-hub.loaded .hero h1 { opacity: 1; transform: none; transition-delay: .18s; }
body.rc-tpl-hub.loaded .hero > .hero-inner > p { opacity: 1; transform: none; transition-delay: .34s; }
body.rc-tpl-hub .scroll-cue { position: absolute; bottom: 22px; left: 50%; transform: translateX(-50%); width: 22px; height: 34px; border: 1.5px solid rgba(233,223,199,0.35); border-radius: 12px; display: flex; justify-content: center; padding-top: 6px; z-index: 2; }
body.rc-tpl-hub .scroll-cue::before { content: ""; width: 3px; height: 7px; background: var(--gold-bright); border-radius: 2px; animation: scrollcue 1.8s ease infinite; }
@keyframes scrollcue { 0% { opacity: 1; transform: translateY(0); } 70% { opacity: 0; transform: translateY(10px); } 100% { opacity: 0; } }

/* ---- Corporate / Weddings hero (Delex-style directional entrance + scroll exit) ---- */
/* --hero-bg is unset unless the PAGE has a featured image, so var() falls
   through to the original flat charcoal and the hero looks exactly as it
   did before. When set, the template supplies gradient-over-photo inline
   (see rc_page_hero_bg_style()) — same mechanism as --split-bg. */
body.rc-tpl-landing .hero { position: relative; overflow: hidden; min-height: 74vh; display: flex; flex-direction: column; justify-content: center; background: var(--hero-bg, var(--charcoal)); background-size: cover; background-position: center; padding: clamp(90px, 12vw, 130px) clamp(20px, 5vw, 56px) clamp(90px, 12vw, 120px); }
body.rc-tpl-landing .hero-glow { position: absolute; inset: -15% -15%; pointer-events: none; will-change: transform; background: radial-gradient(ellipse 55% 45% at 18% 30%, rgba(168,129,63,0.32), transparent 70%); }
body.rc-tpl-landing .hero-content { position: relative; max-width: 760px; will-change: opacity, transform; }
body.rc-tpl-landing .hero-eyebrow { color: var(--gold-bright); font-size: 12px; margin: 0 0 18px; }
body.rc-tpl-corporate .hero-eyebrow::before { content: "CORPORATE & BRANDS · "; color: var(--champagne); opacity: 0.5; }
body.rc-tpl-weddings .hero-eyebrow::before { content: "WEDDINGS · "; color: var(--champagne); opacity: 0.5; }
body.rc-tpl-landing .hero h1 { color: var(--champagne); font-weight: 400; font-size: clamp(30px, 5vw, 54px); line-height: 1.12; margin: 0 0 22px; }
body.rc-tpl-landing .hero p { color: var(--champagne); opacity: 0.75; font-size: clamp(14px, 1.6vw, 17px); line-height: 1.6; max-width: 520px; margin: 0 0 34px; }
body.rc-tpl-landing .hero-ctas { display: flex; gap: 14px; flex-wrap: wrap; }

/* Entrance state, JS only — mirrors the hub's `.js body.rc-tpl-hub ...` rule.
   Without JS nothing ever adds `loaded`, so hiding here would be permanent;
   guarding on `.js` means a no-JS visitor simply gets the finished state.
   Only the animated declarations live here — colour, type, margins and the
   CTA row's display:flex stay unguarded above so they survive either way.
   `.hero p` is never hidden (its 0.75 is a design value, not an entrance
   state), so it only needs the transform. */
.js body.rc-tpl-landing .hero-eyebrow { opacity: 0; transform: translateX(-24px); transition: opacity .6s ease, transform .6s ease; }
.js body.rc-tpl-landing .hero h1 { opacity: 0; transform: translateY(28px); transition: opacity .7s ease, transform .7s ease; }
.js body.rc-tpl-landing .hero p { transform: translateY(20px); transition: opacity .7s ease, transform .7s ease; }
.js body.rc-tpl-landing .hero-ctas { opacity: 0; transform: translateY(20px); transition: opacity .7s ease, transform .7s ease; }
body.rc-tpl-landing.loaded .hero-eyebrow { opacity: 1; transform: none; transition-delay: .05s; }
body.rc-tpl-landing.loaded .hero h1 { opacity: 1; transform: none; transition-delay: .18s; }
body.rc-tpl-landing.loaded .hero p { opacity: 0.75; transform: none; transition-delay: .32s; }
body.rc-tpl-landing.loaded .hero-ctas { opacity: 1; transform: none; transition-delay: .46s; }

.btn { display: inline-flex; align-items: center; gap: 8px; padding: 14px 26px; font-size: 13px; letter-spacing: 0.06em; text-transform: uppercase; text-decoration: none; border-radius: 2px; transition: transform 0.2s, background 0.2s, border-color 0.2s; cursor: pointer; border: 1px solid transparent; }
.btn:hover { transform: translateY(-1px); }
.btn .arrow { display: inline-block; transition: transform .25s ease; }
.btn:hover .arrow { transform: translateX(4px); }
.btn-fill { background: var(--gold-bright); color: var(--charcoal); font-weight: 500; }
.btn-fill:hover { background: var(--champagne); }
/* Same specificity trap as .nav-links a and .split-card above:
   `body.rc-tpl-hub a, body.rc-tpl-landing a { color: inherit }` is (0,2,1)
   and beats this single class, so the button inherited the body's dark
   --ink over its dark hero — 1.15:1 contrast, effectively invisible.
   Safe to force site-wide: .btn-outline is used in exactly two places
   (template-corporate.php, template-weddings.php), both on dark heroes,
   and nowhere in post content — checked before applying. */
.btn-outline { border-color: var(--line); color: var(--champagne) !important; }
.btn-outline:hover { border-color: var(--gold-bright); color: var(--gold-bright); }


/* =========================================================================
   3. HUB-ONLY sections — split cards, hub stats. No collision with
      corporate/weddings (those classes don't exist there).
   ========================================================================= */

.split { display: grid; grid-template-columns: 1fr 1fr; position: relative; min-height: 62vh; }
/* Same specificity trap as the nav above (see the note at .nav-links a):
   `body.rc-tpl-hub a, body.rc-tpl-landing a { color: inherit }` is (0,2,1)
   and outweighs this rule's single class, so without !important the card
   inherited the body's dark --ink instead of champagne — dark text on the
   dark tile gradient, effectively invisible. Confirmed via computed styles.
   .split-title needs its own rule rather than relying on inheritance:
   Kadence's content.min.css sets `h2 { color: var(--global-palette3) }`,
   and a direct colour rule on the element always beats an inherited value
   no matter the specificity, so the heading never receives the card's
   colour. .split-label and .split-cta are deliberately left alone — they
   set their own gold and were already rendering correctly. */
.split-card { position: relative; display: flex; align-items: flex-end; padding: clamp(28px, 4vw, 56px); overflow: hidden; text-decoration: none; color: var(--champagne) !important; }
.split-card .split-title { color: var(--champagne) !important; }
.split-card::before { content: ""; position: absolute; inset: 0; transition: transform 0.6s ease; z-index: 0; }
.split-card:hover::before { transform: scale(1.05); }
/* --split-bg is unset by default, so var() falls through to the exact
   gradient the mockup specifies. When a real rc_portfolio item exists for
   this category, the template sets --split-bg inline on the .split-card
   element itself (custom properties cascade to that element's own
   pseudo-elements), swapping in a real cover photo with zero CSS changes
   needed and zero visual change today, while 0 real items exist. */
.split-card.corporate::before { background: var(--split-bg, linear-gradient(160deg, #2c2620, #100e0b 75%)); background-size: cover; background-position: center; }
.split-card.corporate::after { content: ""; position: absolute; inset: 0; z-index: 0; background: radial-gradient(ellipse 60% 50% at 25% 15%, rgba(168,129,63,0.4), transparent 65%); }
.split-card.wedding::before { background: var(--split-bg, linear-gradient(160deg, #3a3226, #17140f 75%)); background-size: cover; background-position: center; }
.split-card.wedding::after { content: ""; position: absolute; inset: 0; z-index: 0; background: radial-gradient(ellipse 60% 50% at 75% 15%, rgba(233,223,199,0.18), transparent 65%); }
.split-content { position: relative; z-index: 1; }
.split-label { color: var(--gold-bright); font-size: 13px; margin: 0 0 14px; display: block; transition: letter-spacing .3s ease; }
.split-card:hover .split-label { letter-spacing: 0.1em; }
.split-title { font-size: clamp(28px, 4vw, 44px); font-weight: 400; margin: 0 0 14px; }
.split-desc { font-size: 14px; line-height: 1.65; opacity: 0.75; max-width: 380px; margin: 0 0 22px; }
.split-cta { font-size: 14px; letter-spacing: 0.06em; text-transform: uppercase; display: inline-flex; align-items: center; gap: 8px; color: var(--gold-bright); }
.split-cta .arrow { display: inline-block; transition: transform .25s ease; }
.split-card:hover .split-cta { color: var(--champagne); }
.split-card:hover .split-cta .arrow { transform: translateX(5px); }
.split-divider {
  position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); z-index: 2;
  width: 52px; height: 52px; border-radius: 50%; background: var(--bone);
  display: flex; align-items: center; justify-content: center;
  font-family: 'IBM Plex Mono', monospace; font-size: 11px; letter-spacing: 0.05em; color: var(--ink);
  box-shadow: 0 0 0 6px var(--charcoal);
}

body.rc-tpl-hub .marquee-section { padding: 36px 0 40px; border-bottom: 1px solid var(--line-dark); }

.stats { background: var(--charcoal); padding: 56px clamp(20px, 5vw, 56px); }
.stats-grid { max-width: 1000px; margin: 0 auto; display: grid; grid-template-columns: repeat(4, 1fr); gap: 24px; text-align: center; }
.stat-num { font-family: 'Fraunces', serif; font-size: clamp(30px, 4vw, 46px); color: var(--gold-bright); font-weight: 500; }
.stat-label { font-family: 'IBM Plex Mono', monospace; font-size: 10.5px; letter-spacing: 0.06em; text-transform: uppercase; color: var(--champagne); opacity: 0.6; margin-top: 8px; }

@media (max-width: 760px) {
  .split { grid-template-columns: 1fr; }
  .split-card { min-height: 46vh; }
  .split-divider { display: none; }
  .stats-grid { grid-template-columns: repeat(2, 1fr); row-gap: 28px; }
}


/* =========================================================================
   4. CORPORATE / WEDDINGS-ONLY sections — stat bar, services grid, morph,
      selected work, story, contact CTA. No collision with hub.
   ========================================================================= */

body.rc-tpl-landing .marquee-section { padding: 60px 0 38px; }

.stat-bar { position: relative; z-index: 3; margin: -46px clamp(20px, 5vw, 56px) 0; display: grid; grid-template-columns: repeat(3, 1fr); box-shadow: 0 12px 34px rgba(0,0,0,0.28); }
.stat-block { display: flex; align-items: center; gap: 14px; padding: 22px clamp(16px, 2.4vw, 28px); }
.stat-block:nth-child(odd) { background: var(--gold-bright); color: var(--charcoal); }
.stat-block:nth-child(even) { background: var(--charcoal-2); color: var(--champagne); }
.stat-icon { flex: none; width: 38px; height: 38px; }
.stat-icon svg { width: 100%; height: 100%; }
.stat-block-num { font-family: 'Fraunces', serif; font-size: clamp(20px, 2.6vw, 30px); font-weight: 500; line-height: 1; }
.stat-block-label { font-family: 'IBM Plex Mono', monospace; font-size: 10px; letter-spacing: 0.05em; text-transform: uppercase; opacity: 0.8; margin-top: 4px; }
@media (max-width: 640px) { .stat-bar { grid-template-columns: 1fr; margin-top: -30px; } }

.services { padding: clamp(56px, 9vw, 96px) clamp(20px, 5vw, 56px); max-width: 1200px; margin: 0 auto; }
.section-head { margin-bottom: 40px; max-width: 620px; }
.section-head .mono { color: var(--gold); font-size: 12px; margin-bottom: 14px; display: block; }
.section-head h2 { font-weight: 400; font-size: clamp(26px, 3.6vw, 38px); margin: 0; line-height: 1.15; }
.services-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1px; background: var(--line-dark); border: 1px solid var(--line-dark); }
/* Tighter padding and a subtle tint so the card reads as a filled panel
   rather than a small amount of text floating in whitespace. */
.service-card { background: linear-gradient(180deg, rgba(168,129,63,0.05), rgba(168,129,63,0) 55%), var(--bone); padding: 22px 20px 24px; position: relative; transition: transform .3s ease, background .3s ease; display: flex; flex-direction: column; }
.service-card:hover { background: linear-gradient(180deg, rgba(168,129,63,0.11), rgba(168,129,63,0) 60%), var(--bone); }
.service-icon { display: block; color: var(--gold); margin: 0 0 14px; }
.service-icon svg { width: 26px; height: 26px; display: block; }
.service-card:hover .service-icon { color: var(--gold-bright); }
.service-card:hover { transform: translateY(-4px); }
.service-card::before { content: ""; position: absolute; top: 10px; left: 10px; right: 10px; bottom: 10px; border: 1px solid var(--line-dark); pointer-events: none; transition: border-color .3s ease; }
.service-card:hover::before { border-color: var(--gold-bright); }
.service-settings { display: block; margin-bottom: 12px; opacity: 0.62; font-size: 11px; letter-spacing: 0.08em; color: var(--gold); }
.service-card h3 { font-weight: 500; font-size: 18px; margin: 0 0 10px; }
.service-card p { font-size: 13.5px; line-height: 1.6; opacity: 0.75; margin: 0; }
@media (max-width: 900px) { .services-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 720px) { .services-grid { grid-template-columns: 1fr; } }

/* ---------- MORPH: hero image travels into becoming a grid tile ---------- */
.morph-wrapper { position: relative; height: 160vh; background: var(--charcoal-2); }
.morph-sticky { position: sticky; top: 0; height: 100vh; overflow: hidden; }
/* Clears the sticky nav. The label sits inside .morph-sticky, and
   `position: sticky` establishes a stacking context — so the label's z-index:6
   is scoped INSIDE that context and can never rise above the nav's z-index:50
   no matter how high it is set. The only fix is to move it down past the nav.
   Nav height is not constant: it wraps as the crumb and links run out of room,
   measured at 56px >=1100, 85px around 900-1024 (corporate wraps first, its
   crumb is longer), and 109px at 800. Each step below leaves ~20px clearance
   over the tallest nav in that range. Under 780px the morph is inert and the
   label goes static, so these offsets stop applying. */
.morph-label { position: absolute; top: 76px; left: 20px; z-index: 6; color: var(--champagne); font-size: 14px; opacity: 0.72; background: rgba(27,24,21,0.6); padding: 7px 12px; }
@media (max-width: 1099px) { .morph-label { top: 105px; } }
@media (max-width: 899px)  { .morph-label { top: 129px; } }
.morph-grid { position: absolute; inset: 0; display: grid; grid-template-columns: 1fr 1fr 1fr; grid-template-rows: 1fr 1fr; gap: 4px; padding: 0; }
#morph-center-slot { grid-column: 2; grid-row: 1 / 3; visibility: hidden; }
/* display/text-decoration are explicit here (not just relying on div's
   default block display) because a real portfolio-backed tile now renders
   as <a> instead of <div> — see rc_portfolio_tile_tag() in functions.php.
   Placeholder tiles stay plain <div>s, for which these are no-ops. */
.morph-tile { position: relative; overflow: hidden; opacity: 0; display: block; text-decoration: none; }
.morph-tile-fill { position: absolute; inset: 0; }
/* Caption sizes raised for legibility (was 10px/12px — too small to read
   comfortably over imagery). All-caps + letter-spaced mono style kept. */
/* 14px -> 17px: against full-bleed photographs the smaller size was still
   hard to read. All-caps, letter-spacing and the text-shadow are kept —
   the shadow is what carries legibility over a bright frame. */
/* Scrim behind the captions. Enlarging the type alone did not make these
   readable: measured against the real photographs the champagne text sat at
   1.18:1 over bright frames (a text-shadow reads better than it measures, and
   WCAG gives it no credit at all). A bottom gradient fixes the contrast for
   real while leaving the top ~58% of every photo untouched.
   Explicit z-index is required, not decorative: a ::after pseudo-element is
   generated as the last child and would otherwise paint OVER the caption. */
.morph-tile::after, #morph-hero-img::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 42%;
  background: linear-gradient(to top, rgba(10,8,6,0.88), rgba(10,8,6,0.5) 45%, transparent);
  pointer-events: none; z-index: 1;
}
.morph-tile-fill { z-index: 0; }
.morph-tile-caption { position: absolute; left: 14px; right: 14px; bottom: 12px; z-index: 2; display: flex; justify-content: space-between; gap: 12px; color: var(--champagne); font-size: 17px; letter-spacing: 0.06em; text-shadow: 0 1px 4px rgba(0,0,0,0.7); }
.morph-tile-caption .num { color: var(--gold-bright); }
/* The hero's box (left/top/width/height) is animated by landing-pages.js;
   inset:0 here is its pre-JS resting state. Deliberately no
   will-change: transform — the element is never transformed now, and
   promoting it to its own compositor layer would only reintroduce the
   parent/child frame-timing gap that broke the previous approach. */
#morph-hero-img { position: absolute; inset: 0; margin: 0; z-index: 2; overflow: hidden; display: block; text-decoration: none; }
#morph-hero-img .morph-tile-fill { border: 2px solid var(--charcoal-2); }
@media (max-width: 780px) {
  .morph-wrapper { height: auto; padding: 50px 0; }
  .morph-sticky { position: static; height: auto; display: flex; flex-direction: column; }
  .morph-label { position: static; order: -2; padding-bottom: 20px; }
  .morph-grid { position: static; order: 0; display: grid; grid-template-columns: repeat(2, 1fr); grid-auto-rows: auto; gap: 8px; padding: 0 clamp(20px, 5vw, 56px); }
  .morph-tile { aspect-ratio: 4 / 5; }
  #morph-center-slot { display: none; }
  #morph-hero-img { position: static; order: -1; aspect-ratio: 4 / 5; height: auto; margin: 0 clamp(20px, 5vw, 56px) 14px; width: calc(100% - clamp(40px, 10vw, 112px)); }

  /* Mobile-only pop-in bounce (scoped entirely to this breakpoint — no effect on the
     desktop scroll-scrubbed version, which keeps setting these inline via JS instead) */
  .js #morph-hero-img, .js .morph-tile { opacity: 0; transform: scale(0.88) translateY(20px); transition: opacity .6s cubic-bezier(.34,1.56,.64,1), transform .6s cubic-bezier(.34,1.56,.64,1); }
  .js #morph-hero-img.is-visible, .js .morph-tile.is-visible { opacity: 1; transform: scale(1) translateY(0); }
}

/* ---------- SELECTED WORK: staggered two-column gallery ---------- */
.selected-work { background: var(--bone); padding: clamp(70px, 10vw, 110px) clamp(20px, 5vw, 56px); }
.selected-work-head { text-align: center; max-width: 620px; margin: 0 auto clamp(50px, 8vw, 80px); }
.selected-work-head .mono { color: var(--gold); font-size: 12px; display: block; margin-bottom: 14px; }
.selected-work-head h2 { font-weight: 400; font-size: clamp(30px, 4.4vw, 46px); margin: 0 0 16px; }
.selected-work-head p { font-size: 14px; line-height: 1.7; opacity: 0.65; margin: 0; }
/* max-width 1200 -> 1560 and a tighter column gap. At 1920 this cuts the
   dead margin either side from 360px to 180px and grows each photo from
   486px to ~730px wide; below ~1670 the section padding is the binding
   constraint, so narrower screens are unaffected. Staggered two-column
   structure is unchanged. */
.work-grid { max-width: 1560px; margin: 0 auto; display: grid; grid-template-columns: 1fr 1fr; gap: clamp(24px, 3.4vw, 48px) clamp(20px, 3.2vw, 48px); }
.work-item:nth-child(2), .work-item:nth-child(4) { margin-top: clamp(50px, 8vw, 120px); }
.work-photo { aspect-ratio: 4/3; position: relative; overflow: hidden; }
.work-photo-fill { position: absolute; inset: 0; transition: transform .6s ease; }
.work-item:hover .work-photo-fill { transform: scale(1.05); }
/* .work-item is an <a> now (each tile links to its service page); these two
   lines keep it looking exactly as it did as a <div>. */
a.work-item { text-decoration: none; color: inherit; display: block; }
.work-caption { margin-top: 18px; font-size: 17px; letter-spacing: 0.09em; opacity: 0.82; }
@media (max-width: 720px) {
  .work-grid { grid-template-columns: 1fr; }
  .work-item:nth-child(2), .work-item:nth-child(4) { margin-top: 0; }
}

/* ---------- FEATURE WORK (film-strip) ----------
 * Native horizontal overflow with scroll-snap. No wheel listener by design:
 * landing-pages.js already captures wheel for the morph section, and a second
 * wheel-hijacking region on the same page invites exactly the kind of
 * conflict that took several rounds to unpick there. Touch, trackpad and
 * keyboard scrolling all come free; the arrows are pure enhancement. */
.feature-work { background: var(--charcoal); padding: clamp(56px, 9vw, 90px) 0; }
.fw-head { max-width: 1200px; margin: 0 auto clamp(26px, 4vw, 40px); padding: 0 clamp(20px, 5vw, 56px); }
.fw-head .mono { color: var(--gold-bright); font-size: 12px; display: block; margin-bottom: 14px; }
.fw-head h2 { color: var(--champagne); font-weight: 400; font-size: clamp(24px, 3.4vw, 34px); line-height: 1.25; margin: 0; }
.fw-head p { color: var(--champagne); opacity: 0.62; font-size: 14px; line-height: 1.7; margin: 12px 0 0; max-width: 560px; }

.fw-strip { position: relative; }
.fw-track {
  display: flex;
  gap: 4px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-padding-left: clamp(20px, 5vw, 56px);
  padding: 4px clamp(20px, 5vw, 56px);
  scrollbar-width: thin;
  scrollbar-color: rgba(233,223,199,0.28) transparent;
}
.fw-track::-webkit-scrollbar { height: 6px; }
.fw-track::-webkit-scrollbar-thumb { background: rgba(233,223,199,0.28); }
.fw-track:focus-visible { outline: 2px solid var(--gold-bright); outline-offset: 3px; }

.fw-item { flex: 0 0 clamp(260px, 28vw, 380px); scroll-snap-align: start; display: block; text-decoration: none; background: var(--charcoal-2, #23201c); }
.fw-photo { aspect-ratio: 4/3; background: linear-gradient(160deg, #2c2620, #17140f 70%); background-size: cover; background-position: center; }
.fw-meta { padding: 16px 18px 22px; }
.fw-date { display: block; color: var(--gold-bright); font-size: 11px; margin-bottom: 8px; }
.fw-meta h3 { color: var(--champagne); font-weight: 400; font-size: 18px; line-height: 1.3; margin: 0 0 8px; }
.fw-meta p { color: var(--champagne); opacity: 0.6; font-size: 13px; line-height: 1.6; margin: 0; }
.fw-item:hover .fw-meta h3, .fw-item:focus-visible .fw-meta h3 { color: var(--gold-bright); }

.fw-nav {
  position: absolute; top: 38%; z-index: 3;
  width: 42px; height: 42px; border-radius: 50%;
  border: 1px solid rgba(233,223,199,0.35); background: rgba(27,24,21,0.82);
  color: var(--champagne); font-size: 17px; line-height: 1; cursor: pointer;
  transition: border-color .2s ease, background .2s ease, opacity .2s ease;
}
.fw-nav:hover { border-color: var(--gold-bright); background: rgba(27,24,21,0.97); }
.fw-nav[hidden] { display: none; }
.fw-prev { left: clamp(6px, 2vw, 16px); }
.fw-next { right: clamp(6px, 2vw, 16px); }

.fw-empty { max-width: 1200px; margin: 0 auto; padding: 0 clamp(20px, 5vw, 56px); }
.fw-empty p { color: var(--champagne); opacity: 0.5; font-size: 14px; margin: 0; }

@media (max-width: 780px) { .fw-nav { display: none; } }

/* ---------- FEATURE WORK INDEX (the two audience-specific pages) ---------- */
.fw-index-hero { background: var(--charcoal); padding: clamp(56px, 9vw, 96px) clamp(20px, 5vw, 56px) clamp(34px, 5vw, 52px); }
.fw-index-hero .mono { color: var(--gold-bright); font-size: 12px; display: block; margin-bottom: 14px; }
html body .fw-index-hero h1 { font-family: 'Fraunces', serif; color: var(--champagne); font-weight: 400; font-size: clamp(26px, 4vw, 42px); line-height: 1.18; margin: 0; max-width: 900px; }
.fw-index-hero p { color: var(--champagne); opacity: 0.62; font-size: 15px; line-height: 1.7; margin: 14px 0 0; max-width: 620px; }

.fw-index-grid { background: var(--charcoal); display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 4px; padding: 0 clamp(20px, 5vw, 56px) clamp(56px, 9vw, 90px); }
.fw-index-card { display: block; text-decoration: none; background: var(--charcoal-2, #23201c); }
.fw-index-photo { aspect-ratio: 16/9; background: linear-gradient(160deg, #2c2620, #17140f 70%); background-size: cover; background-position: center; }
.fw-index-meta { padding: 18px 20px 24px; }
.fw-index-chip { display: inline-block; color: var(--gold-bright); font-size: 11px; margin-bottom: 10px; }
html body .fw-index-meta h2 { font-family: 'Fraunces', serif; color: var(--champagne); font-weight: 400; font-size: 19px; line-height: 1.3; margin: 0 0 10px; }
.fw-index-meta p { color: var(--champagne); opacity: 0.6; font-size: 13.5px; line-height: 1.65; margin: 0; }
.fw-index-card:hover .fw-index-meta h2, .fw-index-card:focus-visible .fw-index-meta h2 { color: var(--gold-bright); }

.fw-index-empty { background: var(--charcoal); padding: 0 clamp(20px, 5vw, 56px) clamp(56px, 9vw, 90px); }
.fw-index-empty p { color: var(--champagne); opacity: 0.5; font-size: 14px; margin: 0; }

/* ---------- PULL QUOTE (relocated client testimonial, text only) ---------- */
.pull-quote { background: var(--charcoal); padding: clamp(34px, 5vw, 52px) clamp(20px, 5vw, 56px); border-top: 1px solid var(--line-dark, rgba(233,223,199,0.12)); text-align: center; }
.pull-quote blockquote { max-width: 720px; margin: 0 auto; padding: 0; border: 0; }
.pull-quote blockquote p { font-family: 'Fraunces', serif; font-style: italic; font-weight: 300; color: var(--champagne); font-size: clamp(16px, 2.1vw, 21px); line-height: 1.55; margin: 0; }
.pull-quote cite { display: block; margin-top: 14px; color: var(--champagne); opacity: 0.5; font-size: 12px; font-style: normal; letter-spacing: 0.04em; }

/* =========================================================================
   Testimonials strip (weddings). Piggybacks the Feature Work film-strip
   classes for the arrow/scroll behaviour — see template-weddings.php — so
   the .tm-* rules below are styling only, no new interaction model.

   Quote body is Work Sans, not the Fraunces italic the old single
   .pull-quote used: these reviews run to ~1,700 characters and extended
   italic serif at that length is genuinely hard to read. Fraunces stays on
   the section heading via .serif.
   ========================================================================= */

.testimonials { background: var(--charcoal); padding: clamp(56px, 9vw, 90px) 0; border-top: 1px solid rgba(233,223,199,0.10); }

.tm-card {
  flex: 0 0 clamp(290px, 30vw, 400px);
  scroll-snap-align: start;
  background: var(--charcoal-2, #23201c);
  margin: 0;
  padding: clamp(24px, 2.4vw, 32px);
  display: flex;
  flex-direction: column;
  border: 1px solid rgba(233,223,199,0.08);
}

.tm-quote { margin: 0; padding: 0; border: 0; }

/* Decorative opening quote. In normal flow (not absolutely positioned and not
   a ::before) for two reasons: it can never collide with the review text or
   the toggle at any width, and as a real element it carries aria-hidden so
   screen readers don't announce a stray '"' inside the blockquote.
   line-height 0.72 + the negative margin claw back most of the glyph's very
   generous serif leading, so it reads as a mark rather than a blank band. */
.tm-mark {
  display: block;
  font-family: 'Fraunces', serif;
  font-size: clamp(52px, 5.4vw, 72px);
  line-height: 0.72;
  color: var(--champagne);
  opacity: 0.16;
  margin: -6px 0 6px -2px;
  user-select: none;
}

/* Clamped by default so cards keep a common height regardless of the 195 -> 1685
   character spread. The full text is always present in the DOM, so screen
   readers and search engines get the complete review either way. */
.tm-text {
  color: var(--champagne);
  font-size: 14.5px;
  line-height: 1.72;
  margin: 0;
  opacity: 0.88;
  display: -webkit-box;
  -webkit-line-clamp: 10;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.tm-card.is-expanded .tm-text { -webkit-line-clamp: unset; overflow: visible; }

/* CJK falls outside Work Sans' coverage, so name real CJK families before the
   generic fallback — otherwise the browser picks whatever it likes and the
   Chinese reviews render in a face that doesn't match the rest of the card. */
.tm-text:lang(zh) { font-family: 'Work Sans', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'Noto Sans CJK SC', 'WenQuanYi Zen Hei', sans-serif; line-height: 1.8; -webkit-line-clamp: 6; }
/* CJK packs far more meaning per line than Latin, and these cards carry a
   second block underneath. Clamping the original to 6 lines and the
   translation to 4 keeps a translated card the same height as a plain
   English one — otherwise the four Chinese cards drag every card in the
   flex row taller (measured: 435px -> 580px before this). */

/* Translation is secondary: smaller, dimmer, and explicitly labelled so it is
   never mistaken for the reviewer's own words. Clamped separately from the
   original; the shared toggle releases both. */
.tm-trans {
  color: var(--champagne);
  opacity: 0.62;
  font-size: 13px;
  line-height: 1.65;
  margin: 12px 0 0;
  padding-top: 12px;
  border-top: 1px solid rgba(233,223,199,0.10);
  display: -webkit-box;
  -webkit-line-clamp: 4;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.tm-card.is-expanded .tm-trans { -webkit-line-clamp: unset; overflow: visible; }
.tm-trans-label {
  display: block;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--gold-bright);
  opacity: 0.75;
  margin-bottom: 6px;
}

.tm-toggle {
  align-self: flex-start;
  margin-top: 12px;
  padding: 0;
  background: none;
  border: 0;
  color: var(--gold-bright);
  font-family: 'IBM Plex Mono', monospace;
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  cursor: pointer;
  border-bottom: 1px solid transparent;
}
.tm-toggle:hover { border-bottom-color: var(--gold-bright); }
.tm-toggle:focus-visible { outline: 2px solid var(--gold-bright); outline-offset: 3px; }
.tm-toggle[hidden] { display: none; }

.tm-cite {
  margin-top: auto;
  padding-top: 18px;
  color: var(--gold-bright);
  font-size: 12px;
  letter-spacing: 0.04em;
}

@media (max-width: 599px) {
  .tm-card { flex-basis: 82vw; padding: 22px; }
  .tm-text { font-size: 14px; -webkit-line-clamp: 8; }
}

.contact-cta { background: var(--gold-bright); color: var(--charcoal); text-align: center; padding: clamp(48px, 8vw, 72px) 24px; }
.contact-cta h2 { font-weight: 400; font-size: clamp(24px, 3.6vw, 36px); margin: 0 0 12px; }
.contact-cta p { font-size: 14px; opacity: 0.75; margin: 0 0 26px; }
.contact-cta .btn-fill { background: var(--charcoal); color: var(--champagne); }
.contact-cta .btn-fill:hover { background: var(--charcoal-2); }
