/* =============================================================
   V3 — audience-first, visual-led
   Reads brand tokens from v2 styles.css. New components prefixed .v3-
   to avoid any v2 collision. All custom properties scoped under :root
   here use --v3- prefix.
   ============================================================= */

:root {
  --v3-pad-y: clamp(80px, 9vw, 128px);
  --v3-pad-x: clamp(24px, 3vw, 56px);
  --v3-content-max: 1760px;
  --v3-rule: rgba(0, 0, 0, 0.08);
  --v3-mint-white: #F4FAF7;
  --v3-bg-card: #FAFBF9;
  --v3-forest: var(--accent-deep);
  --v3-mint:   var(--mint);
  --v3-sage:   #6FB89C;
  /* Reusable safe-zone clearance for the sticky desktop nav pill so
     content at the top of any major section (especially split 2-col
     layouts where eyebrows top-anchor) never sits behind the pill.
     Pill = 16px top-offset + 10px pad + 40px logo + 10px pad ≈ 76px
     of visual occupied at the top of the viewport; this clamp adds
     comfortable breathing room beyond that.
     Bumped from clamp(96px, 11vh, 128px) → clamp(112px, 12vh, 144px)
     because the centered pill horizontally overlaps the inner edge
     of the right column on 2-col split frames (e.g. /sell/'s
     Valuation column) — at slightly past-fully-scrolled positions
     the prior 20px-of-clearance margin (96px content top vs 76px
     pill bottom) wasn't enough to keep the right-column eyebrow
     visible below the pill. New clamp gives 36–64px of clearance
     across common desktop heights. The grid's `1fr` card-region
     row absorbs the extra padding-top automatically (cards have
     `min-height: 0` so they shrink ~5px per card without overflow). */
  --v3-desktop-nav-offset: clamp(112px, 12vh, 144px);
  /* Mobile counterpart for the burger-only pill (16px top-offset +
     4px pad + 44px button ≈ 64px occupied). Applied surgically to
     only the sections where burger overlap was reported, not to
     every mobile section globally — the existing
     `--v3-mobile-frame-pad-y` floor already clears the pill on most
     sections; this variable is for the few where it doesn't. */
  --v3-mobile-nav-offset: clamp(72px, 14vw, 96px);
}

/* root route additions */
.v2-contact-card {
  color: inherit;
  text-decoration: none;
}
.v2-contact-split {
  display: grid;
  grid-template-columns: minmax(280px, 0.8fr) minmax(420px, 1.2fr);
  gap: 24px;
  align-items: stretch;
}
.v2-contact-office {
  justify-content: center;
}
.v2-contact-map {
  min-height: 420px;
  border-radius: 24px;
  overflow: hidden;
}
.v2-contact-map iframe {
  width: 100%;
  height: 100%;
  min-height: 420px;
  border: 0;
}
@media (max-width: 768px) {
  .v2-contact-split {
    grid-template-columns: 1fr;
  }
  .v2-contact-map,
  .v2-contact-map iframe {
    min-height: 320px;
  }
}

/* Reusable desktop/mobile copy-variant toggle. Markup pattern is two
   sibling elements (typically `<p>`s) with the same parent-styling
   class — one tagged `.copy-desktop` (long-form copy, visible ≥769px)
   and one tagged `.copy-mobile` (short-form copy, visible ≤768px).
   Lets desktop hero copy stay unchanged while mobile gets sharper,
   conversion-focused supporting text without a JS swap. */
.copy-mobile { display: none; }
@media (max-width: 768px) {
  .copy-desktop { display: none; }
  .copy-mobile { display: block; }
}

/* v2 capitalize override */
.v3-section h1, .v3-section h2, .v3-section h3, .v3-section h4,
.v3-h1, .v3-h2, .v3-h3,
.v3-router__card h3, .v3-feature h3, .v3-usp h3,
.v3-process__step h3, .v3-stat h3, .v3-faq__q,
.v3-plot h3, .v3-deal h3, .v3-model h3, .v3-fee h3, .v3-cred h3,
.v3-principle h3, .v3-partner h3, .v3-keyfact dt, .v3-trust__cell h3,
.v3-rep__copy h3, .v3-twocol__h, .v3-features__cell h3,
.v3-buy-showcase__title { text-transform: none; }

/* / home — RAK investment case section. Replaces the prior
   .bento "fastest-growing investment corridor" grid. Layout: top
   eyebrow + headline + lede; below, a 2-col grid with a large
   image-feature card on the left and a 2×2 grid of standard
   non-image cards on the right. Built with v3 brand tokens and
   v3 typography — no new fonts, no new colors. The image asset
   reuses the original home hero image (Wynn Al Marjan
   masterplan render that was previously the bento hero cell). */
/* Tighten the vertical padding around the .v3-case section on
   desktop so the "RAK INVESTMENT CASE" eyebrow sits closer to the
   hero/marquee above and the section's bottom edge doesn't leave
   excessive empty space before the next section. The base .section
   rule applies 180px top + 180px bottom at ≥1024px, which produced
   a ~188px gap between the marquee bottom and the eyebrow. Trimmed
   to ~65–80px each side on desktop — still premium breathing room,
   no longer a chasm. Scoped via @media so mobile/tablet keep the
   base 120px so the section isn't cramped on small screens. */
@media (min-width: 1024px) {
  .v3-case {
    padding-top: clamp(56px, 6vh, 80px);
    padding-bottom: clamp(56px, 6vh, 80px);
  }
}

/* ── v3 audit: tighten too-small / over-padded closing sections ──
   Audit at 1440×1080 found three closing sections on the v3 hub
   pages that read as tiny islands with >50% padding share:
   • /buy/ "Don't see it? / Brief us" closing CTA (504px tall,
     51% padding) — the .v3-section that immediately follows the
     #inventory grid.
   • /broker/ "Register your client now" closing CTA (310px tall,
     56% padding) — the .v3-section--cta that follows the
     .v3-deck-walk section.
   The /sell/ "Ready for a free valuation?" + /invest/ "See
   what's open this quarter." closing CTAs were already tightened in
   prior passes via :has(.v3-rep) and :has(.v3-usps) scoping; they
   are not re-touched here. The home cta-final (657px / 61% vp) is
   substantial enough to remain as-is. */
@media (min-width: 1024px) {
  /* /buy/ "Don't see it? / Brief us" — the .v3-section that
     immediately follows #inventory (Current Pool grid). Tighten its
     padding so the small brief-CTA groups visually with the
     inventory section above instead of floating in 128/128 padding. */
  .v3-section--alt#inventory + .v3-section {
    padding-block: clamp(40px, 5vh, 72px);
  }
  /* /broker/ "Register your client now" — the .v3-section--cta
     that immediately follows the deck-walkthrough section. Trim
     padding on both sides of the boundary so the closing CTA reads
     as part of the deck-walk story rather than a 310px island.
     Scoped via :has(.v3-deck-walk) so the home / sell / invest
     closing CTAs are unaffected. */
  .v3-section:has(.v3-deck-walk) {
    padding-bottom: clamp(40px, 5vw, 72px);
  }
  .v3-section:has(.v3-deck-walk) + .v3-section--cta {
    padding-block: clamp(28px, 3.5vw, 48px);
  }
}
.v3-case__eyebrow {
  font-family: "DM Sans", -apple-system, sans-serif;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent);
  margin: 0 0 16px;
  text-align: left;
}
.v3-case__title {
  font-family: "DM Sans", -apple-system, sans-serif;
  font-weight: 500;
  font-size: clamp(2rem, 3.8vw, 3.5rem);
  line-height: 1.08;
  letter-spacing: -0.03em;
  color: var(--ink);
  margin: 0 0 16px;
  max-width: none;
  text-transform: none;
  text-align: left;
}
/* Each title sentence on its own line — explicit display:block plus
   a desktop-only nowrap so "Dubai is mature." and "RAK still has
   room to grow." each stay on a single line at desktop widths
   instead of wrapping mid-sentence into a third line. */
.v3-case__title-line { display: block; }
@media (min-width: 1024px) {
  .v3-case__title-line { white-space: nowrap; }
}
.v3-case__title .serif {
  font-family: "Instrument Serif", serif;
  font-style: italic;
  font-weight: 400;
}
.v3-case__lede {
  font-family: "DM Sans", -apple-system, sans-serif;
  font-size: clamp(1rem, 1.2vw, 1.25rem);
  line-height: 1.6;
  color: var(--ink-muted);
  margin: 0 0 48px;
  max-width: 56ch;
  text-align: left;
}
.v3-case__grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 24px;
  align-items: stretch;
}
/* Large feature card — image background with dark gradient overlay.
   Content sits at the bottom-left over the gradient so the image
   imagery reads through the upper portion of the card. */
.v3-case__feature {
  position: relative;
  display: flex;
  align-items: stretch;
  min-height: 480px;
  padding: 0;
  border-radius: 24px;
  overflow: hidden;
  background-size: cover;
  background-position: center;
  text-decoration: none;
  color: inherit;
  transition: transform 0.6s var(--ease), box-shadow 0.4s ease;
}
.v3-case__feature::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(0, 41, 30, 0) 0%, rgba(0, 41, 30, 0.35) 50%, rgba(0, 41, 30, 0.85) 100%);
  pointer-events: none;
}
.v3-case__feature:hover {
  transform: translateY(-4px);
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.18);
}
.v3-case__feature-body {
  position: relative;
  padding: clamp(28px, 3vw, 40px);
  color: #fff;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-between;
  text-align: center;
  gap: 16px;
  width: 100%;
  max-width: none;
}
.v3-case__feature-title {
  font-family: "DM Sans", -apple-system, sans-serif;
  font-weight: 500;
  font-size: clamp(1.5rem, 2vw, 2rem);
  line-height: 1.15;
  letter-spacing: -0.02em;
  margin: 0;
  color: #fff;
  text-transform: none;
}
.v3-case__feature-text {
  font-family: "DM Sans", -apple-system, sans-serif;
  font-size: clamp(1.0625rem, 1.25vw, 1.25rem);
  font-weight: 600;
  line-height: 1.5;
  color: rgba(255, 255, 255, 0.95);
  margin: 0;
  max-width: 56ch;
}
.v3-case__feature-cta {
  display: inline-flex;
  align-items: center;
  align-self: center;
  gap: 10px;
  margin-top: 8px;
  padding: 14px 26px;
  border-radius: 999px;
  background: var(--accent, #00B380);
  color: var(--accent-deep, #003D2E);
  font-family: "DM Sans", -apple-system, sans-serif;
  font-weight: 500;
  font-size: 0.9375rem;
  transition: transform 200ms var(--ease), background 200ms var(--ease);
}
.v3-case__feature-cta svg {
  width: 16px;
  height: 16px;
  transition: transform 200ms var(--ease);
}
.v3-case__feature:hover .v3-case__feature-cta svg {
  transform: translateX(2px);
}
/* 2×2 small-card grid — standard v3 non-image card surface
   (mint-white bg, rule border, generous padding, no icon). */
.v3-case__cards {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr 1fr;
  gap: 24px;
}
.v3-case__card {
  background: var(--v3-mint-white);
  border: 1px solid var(--v3-rule);
  border-radius: 24px;
  padding: clamp(24px, 2.4vw, 36px);
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 12px;
  transition: transform 0.6s var(--ease), border-color 0.4s ease;
}
.v3-case__card:hover {
  transform: translateY(-4px);
  border-color: var(--accent);
}
/* Material Symbols icon, mint-accent — matches the existing v3
   non-image card icon language (.v3-card__icon, .v3-feature__icon). */
.v3-case__card-icon {
  font-size: 32px;
  color: var(--accent);
  margin-bottom: 4px;
}
.v3-case__card-title {
  font-family: "DM Sans", -apple-system, sans-serif;
  font-weight: 500;
  font-size: clamp(1.25rem, 1.5vw, 1.625rem);
  line-height: 1.2;
  letter-spacing: -0.015em;
  color: var(--ink);
  margin: 0;
  text-transform: none;
}
.v3-case__card-body {
  font-family: "DM Sans", -apple-system, sans-serif;
  font-size: clamp(0.9375rem, 1vw, 1.0625rem);
  line-height: 1.55;
  color: var(--ink-muted);
  margin: 0;
}
/* Tablet: stack feature above 2×2 cards; cards stay 2-col */
@media (max-width: 1023px) {
  .v3-case__grid { grid-template-columns: 1fr; }
  .v3-case__feature { min-height: 360px; }
}
/* Mobile: cards stack 1-col */
@media (max-width: 600px) {
  .v3-case__cards {
    grid-template-columns: 1fr;
    grid-template-rows: auto;
  }
}

/* /buy/ — tighten the gap between the dark .call-showcase process
   section and the Current Pool inventory section that follows. The
   base .call-showcase rule (in css/styles.css, inherited from the
   v2 base) has margin-bottom: 80px which — combined with the already-
   tightened #inventory padding-top — leaves a large empty band above
   the "CURRENT POOL" eyebrow. Drop the margin so the inventory section
   sits closer beneath the showcase and the Current Pool starts higher
   in the viewport. site.css loads only on site pages, and .call-showcase
   only appears on /buy/, so this override is scoped to the buy hub
   and does not affect /featured-property/. */
.call-showcase { margin-bottom: 0; }

/* /buy/ — fit the .call-showcase ("Your specialist walks you
   through the deck, plot by plot.") section inside one full desktop
   viewport. The base v2-derived rules give the section a 1063px
   natural height (fits 1080 but overflows 900 and 768). Tightened
   section padding-block, capped each .call-frame max-width so the
   stacked screenshots stay short enough to fit, and pulled the
   inter-frame gap in. Images keep their natural 1.6 / 2.027 aspect
   ratios — no crop, no distortion — via the existing width: 100%;
   height: auto. The CTA's existing margin-top: auto continues to
   pin it to the column bottom so it visually aligns with the bottom
   screenshot's bottom edge. Slightly larger margins on the left
   text elements give the column more vertical breathing room without
   changing the column's overall height (auto-margin on CTA absorbs
   the difference). */
.call-showcase { padding: clamp(40px, 4vw, 64px) var(--v3-pad-x); }
.call-showcase .call-showcase__frames {
  gap: 20px;
  /* space-between pushes the last cap to the column bottom so it
     aligns with the left column's CTA bottom (which is anchored
     there via the existing margin-top: auto). */
  justify-content: space-between;
}
.call-showcase .call-frame { max-width: 380px; align-self: center; }
.call-showcase .call-frame__cap { margin-top: 10px; }
/* Single-frame variant of .call-showcase__frames — used when the
   right column shows just ONE device mockup (currently the RAK
   overview deck page). Lifts the 380 px per-frame cap (which was
   sized for the previous two-frame stack so both could fit one
   viewport) so the lone frame scales up to the parent's existing
   720 px max width, making the snapshot materially larger and
   readable. The frame stays centred via the base align-self:
   center on .call-frame. */
.call-showcase .call-showcase__frames--single { justify-content: center; }
.call-showcase .call-showcase__frames--single .call-frame { max-width: 100%; }
.call-showcase .call-showcase__copy h2 {
  /* Trim h2 from the v2 base clamp(2.75rem, 5vw, 4.5rem) so the
     section fits within shorter desktop viewports (1366×768) too.
     Title still reads as the section's primary visual anchor. */
  font-size: clamp(2.25rem, 4vw, 3.75rem);
  margin-bottom: 40px;
}
.call-showcase .call-showcase__copy p { margin-bottom: 48px; }
.call-showcase .call-showcase__list { margin: 0 0 56px; }
.call-showcase .call-showcase__list li { margin-bottom: 22px; }

/* /buy/ — mobile fit fix for the dark `.call-showcase` section
   ("Your specialist walks you through the deck, plot by plot."). The
   v2-base mobile rule (`@media (max-width: 900px)` in css/styles.css)
   only tightens section padding+gap; it leaves the v2-base h2 at
   `clamp(2.75rem, 5vw, 4.5rem)` (≈44px on a 390px-wide phone), the
   body p at 17px / line-height 1.7, the list at 56px bottom margin
   per the v3 desktop override above, and the device mockup at the
   parent's full ≈720px max-width. Together that overflows the phone
   viewport (~844px tall) and clips the device frame at the bottom of
   the mobile screen.

   Tightened the mobile vertical budget here. Every element scales
   down via `clamp()` so the section fits in one ~844px focused
   viewport on 390/393/402-px-wide phones while staying comfortable
   at 430 / 768 (tablet). Desktop is untouched — every selector lives
   inside `@media (max-width: 768px)`, scoped to `.call-showcase`. */
@media (max-width: 768px) {
  .call-showcase {
    /* Top padding bumped further from clamp(96px, 22vw, 120px) →
       clamp(120px, 28vw, 160px) so the heading sits 52–92 px below
       the 68-px-tall pills (was 28 px on a 390-px phone — felt too
       tight). At 390 px width: 120 px (clamp min). At 430 px width:
       120 px. At 768 tablet: 160 px. */
    padding: clamp(120px, 28vw, 160px) clamp(20px, 5vw, 32px) clamp(28px, 7vw, 48px);
    /* Drop the `min-height: 100svh` mobile-major-section floor for
       `.call-showcase` (set further down in this file at line ~5263)
       so the section is content-height instead of forced to 100svh.
       Forced-100svh + content < 100svh produced a big empty band
       below the snapshot, which the user perceived as "the snapshot
       is too far below the CTA." With content-height, the snapshot
       sits directly below the CTA with only the explicit `gap`
       between the two wrapped flex rows; the next section starts
       immediately after the snapshot's bottom padding. */
    min-height: 0;
    /* Cluster the wrapped flex rows at the top of the section
       instead of stretching them — defensive in case any other
       rule reintroduces extra height on the section. */
    align-content: flex-start;
    /* Tighter inter-block gap between copy column and frames column
       so the CTA sits visually close to the deck snapshot. Was
       clamp(20px, 5vw, 32px); now clamp(12px, 3vw, 20px) so the
       section reads as one continuous composition rather than two
       disconnected stacks separated by a dark band. */
    gap: clamp(12px, 3vw, 20px);
  }
  .call-showcase .call-showcase__copy h2 {
    /* Was clamp(2.75rem, 5vw, 4.5rem) at v2 base, then
       clamp(2.25rem, 4vw, 3.75rem) at v3 desktop override which still
       resolves to 36px on a 390px-wide phone (because of the 2.25rem
       floor). At 36px × ~3 wrap lines × line-height 1.05, the h2 alone
       was ~115px tall before margins. Mobile-only floor lowered to
       1.625rem (26px) so the heading fits in ~85px including line
       wraps. */
    font-size: clamp(1.625rem, 6.4vw, 2rem);
    line-height: 1.1;
    margin-bottom: clamp(12px, 3.5vw, 18px);
  }
  .call-showcase .call-showcase__copy p {
    /* Body line-height tightened from 1.7 → 1.55 saves ~15% vertical;
       margin-bottom dropped 48 → ~20 saves ~28px directly. */
    font-size: clamp(15px, 4vw, 16px);
    line-height: 1.55;
    margin-bottom: clamp(16px, 4vw, 22px);
  }
  .call-showcase .call-showcase__list {
    margin: 0 0 clamp(20px, 5vw, 28px);
  }
  .call-showcase .call-showcase__list li {
    font-size: clamp(14px, 3.8vw, 15px);
    margin-bottom: clamp(8px, 2.5vw, 12px);
    gap: 12px;
  }
  .call-showcase .call-showcase__list li .material-symbols-outlined {
    font-size: clamp(20px, 5vw, 22px);
  }
  .call-showcase .call-showcase__cta {
    /* Was 20px 36px; tightened so the button still reads as a
       comfortable tap target (>44px tall) but takes ~14px less
       vertical room. */
    padding: 14px 24px;
    font-size: 15px;
    /* Neutralise the base `margin-top: auto` (which was tuned for the
       desktop's stretched flex column where the copy column matches
       the frames column height — auto pinned the CTA to the bottom
       of the stretched column). On mobile, copy + frames each sit on
       their own row so there's no stretched empty space, but `auto`
       can still introduce phantom whitespace above the CTA when the
       column has any extra height from rounding or nested flex
       behaviour. Setting margin-top: 0 keeps the CTA flush under the
       bullet list. */
    margin-top: 0;
  }
  .call-showcase .call-showcase__frames,
  .call-showcase .call-showcase__frames--single {
    /* Pull the inter-element gap on the frames container (caption
       sits below the frame) so the caption stays tight under the
       device. */
    gap: 12px;
  }
  .call-showcase .call-showcase__frames--single .call-frame {
    /* Cap the device mockup max-width on mobile so it scales down to
       ~280–320 px (was up to the parent's ≈720px max-width via the
       single-frame variant rule above). The image's natural 1.6
       aspect renders ≈175–200 px tall after the 14px frame padding.
       Total frame + caption ≈ 215–240 px on a 390px-wide phone. */
    max-width: clamp(260px, 78vw, 320px);
  }
  .call-showcase .call-frame {
    padding: 10px;
  }
  .call-showcase .call-frame__cap {
    margin-top: 8px;
    font-size: 12px;
  }
}

/* / home - wide First Call composition. The v2-derived base uses
   a constrained equal two-column grid, which makes the ROI simulator
   case tall/narrow and crops the dashboard. On desktop, convert the
   section to one wide row: text stays left, the media expands across
   the remaining viewport width, and the screenshot renders in its
   natural wide ratio. Mobile/tablet (<1024px) keeps the stacked base
   layout. */
@media (min-width: 1024px) {
  .reveal {
    padding: clamp(40px, 5vh, 64px) var(--v3-pad-x);
  }
  .reveal__inner {
    width: min(96vw, var(--v3-content-max));
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: clamp(32px, 4vw, 72px);
  }
  .reveal__left {
    flex: 0 0 clamp(340px, 27vw, 520px);
    max-width: 540px;
    gap: clamp(32px, 5vh, 56px);
    align-self: stretch;
  }
  .reveal__title {
    font-size: clamp(3rem, 5.2vw, 5rem);
    line-height: 1.04;
  }
  .reveal__lede {
    font-size: clamp(1.125rem, 1.5vw, 1.5rem);
    line-height: 1.6;
  }
  .reveal__cta {
    font-size: clamp(17px, 1.2vw, 20px);
    padding: 22px 40px;
  }
  .reveal__showcase {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    align-items: stretch;
    justify-content: center;
    height: auto;
    transform: none;
  }
  .reveal__showcase .call-frame {
    width: 100%;
    max-width: none;
    flex: 0 0 auto;
  }
  .reveal__showcase .call-frame__screen {
    aspect-ratio: 1909 / 942;
  }
  .reveal__showcase .call-frame__screen img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    object-position: center;
  }
}

/* ── / home — full-frame desktop sections ─────────────
   `.reveal` ("Your first call with Namou is where the numbers get real.")
   and `.section--lanes` ("Built for every side of the deal.") each take
   one full desktop viewport height with their existing content
   vertically centered inside, so they read as their own self-contained
   frame instead of sharing a frame with the next section. Mobile and
   tablet (<1024px) keep their natural stacked height — no forced
   viewport rules on short screens. These two class names are only used
   on the v3 home page (other site pages use the `.v3-section` family),
   and `css/site.css` is only loaded by /* pages, so the overrides
   do not leak into root, /, or any v3 child page.

   Note: an earlier override here pointed `.section--lanes background-image`
   at `the previous legacy background image`, which silently overrode the
   `Audience-Path-bg.png` value set in styles.css (same specificity, later
   in cascade order). That single-property rule has been removed so the
   styles.css value is the single source of truth. The viewport-frame
   layout rules below are separate concerns and remain. */

@media (min-width: 1024px) {
  .reveal,
  .section--lanes {
    min-height: 100dvh;
    display: flex;
    flex-direction: column;
    justify-content: center;
    box-sizing: border-box;
  }
  /* Lanes section refinement: scale up the title + cards so the
     content cluster fills ~80% of the section's vertical height,
     anchor it slightly above center so the title sits high, and
     increase the title→cards gap. The base styles.css keeps the
     content in cols 2–3 of a 3-col grid, so the left third stays
     visually empty (the section background image reads
     through). */
  .section--lanes {
    justify-content: flex-start;
    /* padding-top clears the sticky nav (~80px) and keeps the title
       stable; tighter bottom padding gives room back to the lower
       card position without increasing the frame height. */
    padding-top: clamp(96px, 11vh, 144px);
    padding-bottom: clamp(32px, 4vh, 56px);
  }
  /* Drop the base 3-col grid (which pushed title + lanes into cols
     2–4 and left col 1 visually empty). Center title + cards in the
     full section width instead. */
  .section--lanes .section__inner {
    display: block;
    row-gap: clamp(80px, 10vh, 144px);
  }
  .section--lanes .section__title {
    grid-column: 1 / -1;
    /* Bumped from the base clamp(1.5rem, 2.4vw, 2.5rem) — large enough
       to read as a substantial counterweight to the cards. Centered
       in the full section width via text-align + auto margins. */
    font-size: clamp(2.25rem, 3.8vw, 3.75rem);
    /* Bottom margin = title-to-cards gap on desktop. Increased so the
       four-card row clears the upper-middle script/artwork baked into
       Audience-Path-bg.png. Mobile/tablet keeps the base
       `.section--lanes .lanes { margin-top: 80px }` rule in
       styles.css; that path is unaffected. */
    margin: 0 auto clamp(128px, 13vh, 176px);
    max-width: none;
    text-align: center;
    white-space: normal;
  }
  /* The base @media (min-width: 768px) rule pins .lanes to grid-column
     2 / 4 (right two-thirds). Override here to span the full section
     width with a reasonable max-width so the four cards (Buyers /
     Landowners / Investors / Brokers) stay visually balanced rather
     than stretched edge-to-edge on wide viewports. Bumped from
     repeat(3, 1fr) → repeat(4, 1fr) when the Brokers card was added —
     the previous 3-col grid was forcing the 4th card to wrap into a
     second row. Max-width nudged up + gap tightened to give four cards
     room to breathe without feeling cramped. */
  .section--lanes .lanes {
    grid-column: 1 / -1;
    grid-template-columns: repeat(4, 1fr);
    max-width: 1320px;
    margin: 0 auto;
    gap: 20px;
  }
  .section--lanes .lane {
    /* Padding/gap/min-height proportionally reduced from the prior
       3-card values (padding 14%, min-height clamp(480px, 64vh, 720px))
       so four narrower cards still read premium without the body or
       CTA breaking out of the card. */
    padding: 10%;
    gap: 20px;
    min-height: clamp(380px, 52vh, 600px);
    justify-content: flex-start;
  }
  /* Distribute card content into three vertical zones: eyebrow +
     heading at the top, body in the middle, CTA pinned to the
     bottom. Achieved by giving the body and the CTA each margin-
     top: auto — the two auto margins split the remaining column
     space equally so body lands at ~50% of card height (middle)
     while the CTA absorbs the second half and lands at the bottom.
     Replaces the prior justify-content: center cluster (which
     stacked everything together in the middle and made the cards
     feel "floating"). */
  .section--lanes .lane .lane__body {
    margin-top: auto;
  }
  .section--lanes .lane .btn--ghost {
    margin-top: auto;
  }
  /* Type scale tuned down from the prior 3-card values so the longest
     eyebrow ("For Landowners", `white-space: nowrap`) still fits inside
     a 4-col card at 1280–1440px viewports. Headings/body/CTA scaled
     proportionally to keep the visual hierarchy consistent. */
  .section--lanes .lane__eyebrow {
    font-size: clamp(1.5rem, 2.1vw, 2.125rem);
  }
  .section--lanes .lane__heading {
    font-size: clamp(1.05rem, 1.2vw, 1.375rem);
    line-height: 1.3;
  }
  .section--lanes .lane__body {
    font-size: clamp(13px, 1vw, 15px);
    line-height: 1.55;
  }
  .section--lanes .lane .btn--ghost {
    font-size: clamp(13px, 0.9vw, 15px);
    padding: 13px 22px;
  }
}

/* Tablet — keep four-card audience row two-up rather than letting the
   base `.lanes { grid-template-columns: repeat(4, 1fr); }` force four
   cramped cards in the 901–1023px range. Below 768px the base
   `@media (max-width: 900px) { .lanes { grid-template-columns: 1fr; } }`
   already collapses the row to a single column. Scoped to
   `.section--lanes` so other lane usages (none today) wouldn't be
   affected. */
@media (min-width: 768px) and (max-width: 1023px) {
  .section--lanes .lanes {
    grid-template-columns: repeat(2, 1fr);
  }
}

/* ── Section + typography primitives ─────────────────── */
.v3-section { padding: var(--v3-pad-y) 32px; position: relative; }
.v3-section:not(.v3-hero) { padding-inline: var(--v3-pad-x); }
.v3-section__inner { width: min(100%, var(--v3-content-max)); max-width: none; margin: 0 auto; }
.v3-section--narrow .v3-section__inner { max-width: 760px; margin: 0 auto; }
.v3-section--alt { background: var(--v3-mint-white); }
.v3-section--strip { padding: 32px var(--v3-pad-x); border-top: 1px solid var(--v3-rule); border-bottom: 1px solid var(--v3-rule); }
.v3-section--cta { padding: clamp(56px, 8vh, 96px) var(--v3-pad-x); text-align: center; }
/* Home carries a few v2-derived non-hero shells. Normalize only their
   horizontal rhythm to the v3 section width; keep their vertical pacing
   and layouts intact. */
.section:not(.hero) { padding-inline: var(--v3-pad-x); }
.section:not(.hero) > .section__inner {
  width: min(100%, var(--v3-content-max));
  max-width: none;
}
.cta-final { padding-inline: var(--v3-pad-x); }

/* Footer uses the same horizontal rhythm as v3 content sections. V3
   pages theme the footer from the containing final frame instead of
   inheriting the forced forest-green override from styles.css. */
.footer {
  padding-inline: var(--v3-pad-x);
  background: var(--bg);
  color: var(--ink);
  border-top-color: var(--line);
}

.footer,
.footer a,
.footer span,
.footer p,
.footer h4,
.footer__brand p,
.footer__col a,
.footer__col span,
.footer__col h4,
.footer__bottom,
.footer__bottom span,
.footer__bottom a {
  opacity: 1;
}

.footer__brand p,
.footer__col h4,
.footer__bottom,
.footer__bottom span {
  color: var(--ink-muted);
}

.footer__col a,
.footer__col span,
.footer__bottom a {
  color: var(--ink);
}

.footer a:hover {
  color: var(--accent);
  opacity: 1;
}

.footer__inner,
.footer__bottom {
  width: min(100%, var(--v3-content-max));
  max-width: none;
}

.footer__inner {
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(24px, 3vw, 48px);
  align-items: start;
}

.footer__map {
  min-width: 0;
}

.footer__map iframe {
  display: block;
  width: 100%;
  height: 120px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--bg-alt);
  filter: saturate(0.85) contrast(0.95);
}

.footer__map a {
  display: inline-flex;
  margin-top: 10px;
  font-size: 14px;
  font-weight: 500;
  color: var(--ink);
}

@media (max-width: 1100px) {
  .footer__inner {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .footer__map {
    max-width: 420px;
  }
}

@media (max-width: 600px) {
  .footer__inner {
    grid-template-columns: 1fr;
  }

  .footer__map iframe {
    height: 180px;
  }
}

/* Soft green ambient glow on every V3 final major section. Applied
   via the shared `.v3-frame-group--final` modifier — the homepage,
   buy, sell, invest, and broker hubs all carry this class on their
   final frame already, so the treatment lands on all five places
   from one rule. The effect is a layered combination:
   • Outer drop shadow rising 16px above the frame, soft accent-green
     at low opacity, gives the section a subtle premium "lift" off
     the previous content above without intruding on it.
   • Inset top glow — a wider/softer accent-green band painted INSIDE
     the frame's top edge, fading downward, so the brand colour
     reads as ambient light against either a white frame surface
     (sell-final) or a black frame surface (buy/invest/broker-final),
     and reads at the top of the home-final cluster as a halo
     above the news + CTA columns.
   `inset` shadows render above the frame's background-colour but
   below child content, so the glow tints the surface without
   dimming text, cards, or CTAs. Reusable token-style — no
   per-page override needed. Applied at all viewports (outside the
   desktop frame media query) so mobile/tablet finals also pick up
   the ambient brand glow. */
.v3-frame-group--final {
  box-shadow:
    0 -16px 40px -12px rgba(0, 176, 115, 0.16),
    inset 0 80px 120px -60px rgba(0, 176, 115, 0.18),
    inset 0 -40px 80px -60px rgba(63, 230, 168, 0.06);
}

/* Major viewport frame system. Desktop gets complete presentation
   frames; tablet/mobile keep natural document flow. Use .v3-frame for
   one substantial section and .v3-frame-group when adjacent short
   sections should read as one combined frame. */
@media (min-width: 1024px) {
  .v3-frame,
  .v3-frame-group {
    min-height: 100svh;
    min-height: 100dvh;
    box-sizing: border-box;
  }

  .v3-frame {
    display: flex;
    flex-direction: column;
    justify-content: center;
  }

  .v3-section.v3-frame {
    padding-block: clamp(56px, 6vh, 80px);
  }

  .section.v3-frame {
    display: flex;
    flex-direction: column;
    justify-content: center;
  }

  .call-showcase.v3-frame {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: stretch;
    justify-content: space-evenly;
    align-content: center;
  }

  .v3-frame-group {
    display: flex;
    flex-direction: column;
    justify-content: center;
  }

  .v3-frame-group > .v3-section {
    padding-block: clamp(28px, 3.5vh, 52px);
  }

  .v3-frame-group--final {
    justify-content: flex-end;
  }

  .v3-frame-group--final > .v3-section {
    padding-block: clamp(28px, 3.5vh, 48px);
  }

  .v3-frame-group--final > .footer {
    flex: 0 0 auto;
    width: 100%;
  }

  /* / home-final frame carries 2 children — a centred News & Updates
     carousel section + the footer pinned full-width below. The previous
     two-column cluster (news left, "Twenty minutes" CTA right) was
     replaced by a single centred carousel after the CTA block was
     removed. Override the inherited `justify-content: flex-end` so the
     news + footer stack from the top; let the news section absorb the
     viewport-frame slack so the carousel centres vertically and the
     footer stays at its natural height at the bottom of the 100dvh
     frame. */
  .v3-frame-group--home-final {
    justify-content: flex-start;
  }
  .v3-frame-group--home-final > .home-news {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    justify-content: center;
    width: 100%;
    /* Reserve sticky-nav clearance at the top of the news section
       so the `News & Updates` title doesn't sit under the floating
       nav pill when the home-final frame is fully displayed. The
       base `.home-news { padding: clamp(32px, 4.5vh, 64px) ... }`
       only gave ~48 px on a 1080 px-tall desktop — at fully-
       displayed scroll positions the centred cluster could land
       within ~30 px of the pill bottom. Override the top side to
       `--v3-desktop-nav-offset` (clamp 112–144 px) so the title
       and the rest of the cluster (cards + dots + arrows) are
       guaranteed below the pill. The cluster still centres via
       the existing `justify-content: center` on this same flex
       container, just within a slightly smaller content box. */
    padding-top: var(--v3-desktop-nav-offset);
  }
  .v3-frame-group--home-final > .footer {
    flex: 0 0 auto;
  }

  .v3-frame-group--sell-method > .v3-sell-valuation {
    padding-block: clamp(12px, 1.8vh, 26px) clamp(28px, 4vh, 60px);
  }

  .v3-frame-group--sell-method > .v3-sell-process {
    padding-block: clamp(28px, 4vh, 60px) clamp(12px, 1.8vh, 26px);
  }

  .v3-frame-group--sell-method .v3-h2 {
    font-size: clamp(1.5rem, 2.4vw, 2.125rem);
    line-height: 1.1;
    /* Bumped from clamp(6px, 0.8vw, 12px) — that tight margin was
       tuned for the prior stacked layout where two h2s appeared close
       together. With the 2-col layout, each column wants its own
       generous title→content rhythm. */
    margin-bottom: clamp(14px, 1.6vh, 24px);
    /* Force the h2 to occupy 2 lines' worth of vertical space across
       BOTH columns regardless of actual word count, so the card
       regions in Process and Valuation start at the same y-baseline.
       Without this, Process's h2 ("Five steps from first call to
       signed deal." — 42 chars) wraps to 2 lines on desktop while
       Valuation's h2 ("How we price your land." — 22 chars) fits on
       1, leaving Valuation's card region starting ~30–40 px higher
       than Process's and breaking the top-edge alignment between
       `Reach out` and `Recent comparables`. The trailing empty
       half-line below Valuation's single-line h2 reads as
       deliberate column rhythm. */
    min-height: calc(2 * 1.1em);
  }

  .v3-frame-group--sell-method .v3-eyebrow {
    margin-bottom: clamp(10px, 1.2vh, 16px);
  }

  .v3-frame-group--broker-pair > .v3-section,
  .v3-frame-group--invest-intro > .v3-section {
    padding-block: clamp(28px, 3.5vh, 48px);
  }

  .v3-frame-group--broker-deck > .v3-section {
    padding-block: clamp(24px, 3vh, 40px);
  }

  .v3-frame-group--broker-deck .v3-deck-walk {
    grid-template-columns: repeat(3, 1fr);
    gap: 18px;
  }

  .v3-frame-group--broker-deck .v3-deck-walk__step p {
    font-size: 0.875rem;
    line-height: 1.45;
    margin-top: 8px;
  }

  .section.v3-frame .faq__item summary {
    padding-block: clamp(20px, 2.5vh, 28px);
    font-size: clamp(1.125rem, 1.6vw, 1.45rem);
  }

  .section.v3-frame .faq__item summary::after {
    width: 36px;
    height: 36px;
  }

  #inventory.v3-frame {
    padding-block: clamp(20px, 2.5vh, 32px);
    justify-content: flex-start;
  }

  #inventory.v3-frame .v3-plot__media {
    aspect-ratio: 16 / 5;
  }

  #inventory.v3-frame .v3-plot__body {
    padding: 6px 12px 8px;
  }

  #inventory.v3-frame .v3-plot__title {
    font-size: 0.875rem;
    line-height: 1.15;
  }

  .v3-frame-group--invest-intro .v3-feature,
  .v3-frame-group--broker-pair .v3-feature {
    padding: 22px 20px;
  }

  .v3-frame-group--invest-intro .v3-feature-row,
  .v3-frame-group--broker-pair .v3-feature-row {
    margin-top: 24px;
  }

  .v3-frame-group--invest-intro .v3-stats {
    margin-top: 24px;
  }

  .v3-frame-group--invest-intro .v3-stat {
    padding: 26px 22px;
  }

  /* /invest/ intro frame — desktop two-column split (mirrors the
     `/broker/` `.v3-frame-group--broker-pair-2` pattern). Above
     1024px the major frame stops stacking `How our JV works` +
     `Active pipeline` vertically and sits them side-by-side at 50/50
     under one viewport-frame floor. Inside `How our JV works` (left),
     the three feature cards stack vertically; inside `Active
     pipeline` (right), the four stats become a 2×2 quadrant grid.
     Card backgrounds are transparent with a subtle hairline
     perimeter — same treatment used on the Sell process rows / Broker
     2×2 quadrant. Mobile/tablet (<1024px) is unaffected: the entire
     block lives inside `@media (min-width: 1024px)` so smaller
     viewports keep their natural stacked flow + horizontal swipe
     rows from the mobile-frame block far below. */

  /* Single-section variant: the right-hand "What's open this
     quarter" stat panel was removed, so the frame group is now a
     simple vertical stack — centred title block at the top with
     the 3 feature cards filling the remaining viewport height in a
     full-width 3-column row underneath. */
  .v3-frame-group--invest-intro {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    padding: var(--v3-desktop-nav-offset) var(--v3-pad-x) clamp(48px, 7vh, 96px);
  }
  .v3-frame-group--invest-intro > .v3-section {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-width: 0;
    padding: 0;
    background: transparent;
  }
  .v3-frame-group--invest-intro .v3-section__inner {
    display: flex;
    flex-direction: column;
    flex: 1;
    width: 100%;
    max-width: none;
    min-width: 0;
  }

  /* Centre the section title across the full frame width. */
  .v3-frame-group--invest-intro .v3-eyebrow,
  .v3-frame-group--invest-intro .v3-h2 {
    text-align: center;
    margin-inline: auto;
  }

  /* Three feature cards span the full frame width side-by-side and
     stretch to fill the remaining major-section viewport height
     below the title. */
  .v3-frame-group--invest-intro .v3-feature-row {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    grid-template-rows: 1fr;
    gap: clamp(14px, 1.6vw, 24px);
    margin-top: clamp(24px, 3vh, 40px);
    flex: 1;
    min-height: 0;
    align-self: stretch;
  }
  /* Transparent card surface + hairline perimeter (matches Sell
     process rows + Broker quadrant cards). Card content centred on
     one horizontal axis: icon on top, h3, then body — so the icon /
     title / supporting text all sit on the column's centre line. */
  .v3-frame-group--invest-intro .v3-feature {
    background: transparent;
    border: 1px solid rgba(0, 61, 46, 0.12);
    border-radius: 18px;
    padding: clamp(16px, 1.8vh, 24px) clamp(20px, 2.4vw, 32px);
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    transition: border-color 0.3s ease;
  }
  .v3-frame-group--invest-intro .v3-feature:hover {
    background: transparent;
    border-color: var(--accent);
  }

  /* Right column: 4 stat cards form a 2×2 quadrant + fill row 4.
     Both grid columns equal width, both rows equal height, content
     centred inside each card. */
  .v3-frame-group--invest-intro .v3-stats.v3-stats--4 {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    grid-template-rows: repeat(2, 1fr);
    gap: clamp(10px, 1.2vh, 16px);
    margin-top: clamp(18px, 2vh, 28px);
    min-height: 0;
    align-self: stretch;
    border: 0;
  }
  .v3-frame-group--invest-intro .v3-stat {
    background: transparent;
    border: 1px solid rgba(0, 61, 46, 0.12);
    border-radius: 18px;
    padding: clamp(20px, 2.4vh, 32px) clamp(20px, 2.4vw, 32px);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    transition: border-color 0.3s ease;
  }
  .v3-frame-group--invest-intro .v3-stat:hover {
    background: transparent;
    border-color: var(--accent);
  }

  .v3-frame-group--sell-method .v3-split {
    grid-template-columns: minmax(0, 1.35fr) minmax(260px, 0.65fr);
    gap: 32px;
  }

  .v3-frame-group--sell-method .v3-split__visual img {
    max-height: 280px;
    object-fit: contain;
  }

  /* Valuation card internals tightened so all 3 cards fit comfortably
     inside the shared card region (the prior values overflowed —
     3rd card was being cut at the bottom). Card surface, border,
     border-radius, brand accents are unchanged; only inside metrics
     (padding, icon size + margin, h3 + divider margin, body line
     height) shrink. Each cut is ~3–10px; cumulative ~30–40px per
     card × 3 cards ≈ 90–120px reclaimed across the stack — plenty
     to clear the prior overflow on a 1080dvh viewport with
     `--v3-desktop-nav-offset` top padding. */
  .v3-frame-group--sell-method .v3-feature.v3-feature--method {
    padding: clamp(12px, 1.5vh, 18px) clamp(14px, 1.4vw, 20px);
  }

  .v3-frame-group--sell-method .v3-feature--method .v3-feature__icon-wrap {
    width: clamp(36px, 2.6vw, 42px);
    height: clamp(36px, 2.6vw, 42px);
    margin-bottom: clamp(8px, 0.8vh, 12px);
  }

  .v3-frame-group--sell-method .v3-feature--method .v3-feature__icon {
    font-size: clamp(18px, 1.4vw, 22px);
  }

  .v3-frame-group--sell-method .v3-feature--method h3 {
    margin-bottom: 4px;
  }

  .v3-frame-group--sell-method .v3-feature--method .v3-feature__divider {
    margin-bottom: 6px;
  }

  .v3-frame-group--sell-method .v3-feature--method p {
    font-size: clamp(0.8125rem, 0.9vw, 0.9375rem);
    line-height: 1.45;
  }

  .v3-frame-group--sell-method .v3-feature-row.v3-feature-row--method {
    gap: clamp(12px, 1.2vw, 18px);
    margin-top: clamp(14px, 1.4vw, 22px);
  }

  .v3-frame-group--sell-method .v3-process.v3-process--timeline {
    margin-top: clamp(14px, 1.4vw, 22px);
    gap: clamp(10px, 1vw, 16px);
  }

  .v3-frame-group--sell-method .v3-process.v3-process--timeline .v3-process__step {
    padding: clamp(14px, 1.4vw, 20px) clamp(10px, 1vw, 16px);
  }

  .v3-frame-group--sell-method .v3-process--timeline .v3-process__icon-wrap {
    width: clamp(36px, 2.8vw, 44px);
    height: clamp(36px, 2.8vw, 44px);
    margin-bottom: clamp(8px, 0.8vw, 12px);
  }

  .v3-frame-group--sell-method .v3-process.v3-process--timeline .v3-process__step h3 {
    margin-bottom: 6px;
  }

  .v3-frame-group--sell-method .v3-process--timeline .v3-process__divider {
    margin-bottom: 8px;
  }

  /* /sell/ — 2-column DESKTOP-ONLY layout for the sell-method frame.
     The HTML markup is unchanged from the prior stacked layout (mobile
     and tablet keep their existing rendering exactly: process in a
     horizontal swipe row with body text via the existing mobile-frame
     rules in site.css). On desktop only, this block transforms the same
     markup into a 2-column split: Process LEFT (vertical 5-step
     timeline, icons + titles only) and Valuation RIGHT (3 cards
     stacked vertically). DOM order is valuation → process, so `order`
     pushes valuation to the right column visually while leaving the
     reading/source order intact for screen readers and mobile. */
  .v3-frame-group--sell-method {
    /* STRUCTURAL ALIGNMENT FIX (was flex-row + flex-start). Previous
       flex layout failed because each column laid out independently:
       LEFT h2 ("Five steps from first call to signed deal.") wrapped
       to 2 lines, RIGHT h2 ("How we price your land.") fit on 1 line,
       so the headers consumed different heights and the card regions
       started/ended at different y-coordinates per column. `justify-
       content: space-between` then distributed strips within each
       column's INDEPENDENT card-region height, so first/last
       valuation card never aligned with first/last process strip.
       The fix: 2-col x 3-row CSS grid where row 1 = eyebrow,
       row 2 = h2, row 3 = the shared card region (1fr, fills the
       remaining viewport height). Both child sections subgrid these
       3 row tracks (rules below), so row 2 auto-sizes to the TALLER
       h2 across both columns and BOTH columns get that same row
       track height. The card region (row 3) is therefore guaranteed
       to start and end at the same y on left and right. */
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-template-rows: auto auto 1fr;
    align-items: stretch;
    column-gap: clamp(48px, 5vw, 96px);
    row-gap: 0;
    /* Top padding uses the shared `--v3-desktop-nav-offset` so the
       first row of content (eyebrow) clears the sticky nav pill at
       the top of the viewport. Bottom padding stays at the existing
       major-frame rhythm. */
    padding: var(--v3-desktop-nav-offset) var(--v3-pad-x) clamp(48px, 7vh, 96px);
  }
  /* Both column sections subgrid the parent's 3 row tracks, spanning
     rows 1–3, so eyebrow / h2 / card-region positions are tied across
     columns instead of being independent flex-column stacks. */
  .v3-frame-group--sell-method > .v3-sell-process,
  .v3-frame-group--sell-method > .v3-sell-valuation {
    display: grid;
    grid-template-rows: subgrid;
    grid-row: 1 / 4;
    padding: 0;
    min-width: 0;
  }
  /* DOM order is valuation → process; explicit `grid-column` puts
     Process on the left and Valuation on the right without changing
     the source-order reading flow used by mobile + screen readers. */
  .v3-frame-group--sell-method > .v3-sell-process { grid-column: 1; }
  .v3-frame-group--sell-method > .v3-sell-valuation { grid-column: 2; }
  /* `.v3-section__inner` subgrids the same 3 row tracks so the
     eyebrow / h2 / card-region children inside it land in the
     parent's row tracks — without this, the inner would auto-size
     its own rows independently and the alignment chain would
     break here. */
  .v3-frame-group--sell-method .v3-section__inner {
    display: grid;
    grid-template-rows: subgrid;
    grid-row: 1 / 4;
    width: 100%;
    max-width: none;
    min-width: 0;
  }

  /* Valuation cards land in the shared card-region row (row 3 of the
     grid). `repeat(3, 1fr)` enforces all three cards at the same
     height regardless of body-copy line count — required so the cards
     read as one stacked composition rather than three different-sized
     panels. The first card's top edge sits at the card-region top
     (= 0% of row 3), the third card's bottom edge sits at the
     card-region bottom (= 100% of row 3). With the Process column's
     5-strip space-between distribution sharing that exact card-region
     range, `Reach out` top aligns with `Recent comparables` top, and
     `Negotiate & close` bottom aligns with `Area-specific knowledge`
     bottom. Card vertical padding reduced from clamp(16px, 2vh, 22px)
     → clamp(10px, 1.2vh, 16px) so the cards feel less compact at the
     enforced equal height — the section breathes without the cards
     going cramped. */
  .v3-frame-group--sell-method .v3-feature-row.v3-feature-row--method {
    display: grid;
    /* `grid-template-columns: 1fr` is REQUIRED here — the base
       `.v3-feature-row.v3-feature-row--method` rule sets
       `grid-template-columns: repeat(3, 1fr)`. Without resetting it,
       this desktop override's `grid-template-rows: repeat(3, 1fr)`
       would create a 3×3 grid and the 3 cards would fill row 1
       horizontally instead of stacking vertically. */
    grid-template-columns: 1fr;
    grid-template-rows: repeat(3, 1fr);
    gap: clamp(10px, 1.2vh, 18px);
    margin-top: clamp(18px, 2vh, 28px);
    min-height: 0;
    align-self: stretch;
  }
  .v3-frame-group--sell-method .v3-feature.v3-feature--method {
    width: 100%;
    padding: clamp(10px, 1.2vh, 16px) clamp(18px, 2vw, 24px);
    min-height: 0;
    display: flex;
    flex-direction: column;
    justify-content: flex-start;
  }

  /* Process timeline transforms from horizontal cards-row to vertical
     numbered list on desktop. The original `.v3-process__nav-row`
     (the horizontal `01–05` strip above the cards) is hidden because
     each step now carries its own number via a CSS counter. The
     `.v3-process__cards-row` becomes a vertical flex column.
     Each step renders as a 3-column grid: number circle | icon tile |
     title; the body `<p>` and decorative `.v3-process__divider` are
     hidden so each row stays compact. */
  /* Process timeline wrapper fills the parent grid's row 3 (the
     shared card-region track that the valuation column also occupies
     with `grid-template-rows: repeat(3, 1fr)`). `align-self: stretch`
     anchors the wrapper top + bottom to row 3 top + bottom; `min-
     height: 0` lets nested flex children participate in shrinking on
     shorter desktop heights so `space-between` below has space to
     distribute. Same `margin-top` clamp as the valuation row so
     both columns' card-regions start at the same y. */
  .v3-frame-group--sell-method .v3-process.v3-process--timeline {
    counter-reset: sell-process-step;
    display: flex;
    flex-direction: column;
    margin-top: clamp(18px, 2vh, 28px);
    align-self: stretch;
    min-height: 0;
  }
  .v3-frame-group--sell-method .v3-process.v3-process--timeline .v3-process__nav-row {
    display: none;
  }
  /* Cards-row fills the timeline wrapper height and distributes the
     5 compact step rows top-to-bottom. CHANGED from a flex-column
     `justify-content: space-between` container to a CSS GRID with
     5 explicit column tracks + `align-content: space-between` so
     each step (below) can subgrid those columns. The previous
     per-step grid had `1fr 1fr` left/right spacer columns whose
     widths were computed PER ROW from each row's own title width,
     which meant wider titles shrunk the spacers and pulled the icon
     left while shorter titles pushed the icon right. With the column
     tracks defined ONCE here at the cards-row level and subgridded
     by every step, all 5 icons land in the same x-position (col 3),
     and the title column auto-sizes to the widest title across all
     rows ("Negotiate & close") — which is exactly the row 05 title
     width that produced its existing icon position, so row 05's
     icon doesn't move and rows 01–04 align to it. The vertical
     distribution (top of step 01 ↔ top of valuation card 1, bottom
     of step 05 ↔ bottom of valuation card 3, steps 02–04 evenly
     distributed) carries through unchanged via `align-content:
     space-between` (grid equivalent of the prior flex
     `justify-content: space-between`). */
  .v3-frame-group--sell-method .v3-process.v3-process--timeline .v3-process__cards-row {
    display: grid;
    flex: 1 1 auto;
    grid-template-rows: repeat(5, auto);
    grid-template-columns: clamp(60px, 5vw, 76px) minmax(0, 1fr) clamp(60px, 5vw, 76px) auto minmax(0, 1fr);
    align-content: space-between;
    column-gap: 0;
    row-gap: 0;
    min-height: 0;
  }
  /* Step row height is driven by the larger of the two circles
     (number-circle / icon-circle) since the row is `align-items:
     center` over a single grid track. Bumped circle tracks from
     `clamp(44px, 4vw, 56px)` → `clamp(60px, 5vw, 76px)` so each row is
     visibly taller (~+20px). Because the cards-row uses
     `justify-content: space-between` over a fixed shared card-region
     height, taller rows automatically REDUCE the leftover gap between
     them — the alignment of step 01's top with valuation card 1's top
     and step 05's bottom with valuation card 3's bottom is preserved
     (those endpoints are anchored by space-between, not by row size).
     Column gap nudged up to match the larger circles. */
  /* Step row layout: number circle pinned far-left; icon + title pair
     centered inside the area to the right of the number circle. The
     5-column grid encodes that explicitly:
       col 1 = number circle (fixed-width clamp)
       col 2 = 1fr left spacer (empty)
       col 3 = icon-wrap (auto width, fixed clamp)
       col 4 = title (auto width, content-driven)
       col 5 = 1fr right spacer (empty)
     The two 1fr spacer columns are equal-width, so the icon+title
     cluster horizontally centers between the number's right edge and
     the row's right edge. `column-gap: 0` so spacer columns do their
     job cleanly; the explicit icon→title gap is set as `margin-left`
     on the h3 (below). Row height is still driven by the number /
     icon circle clamps (60–76 px) — unchanged from before. The row
     has no background and no border, so the previous "filled rounded
     card" appearance is gone. */
  .v3-frame-group--sell-method .v3-process.v3-process--timeline .v3-process__step {
    counter-increment: sell-process-step;
    position: relative;
    display: grid;
    /* SUBGRID — every step shares the column tracks defined once on
       `.v3-process__cards-row` above. This is what guarantees the icon
       column lands at the same x across all 5 rows: title column at
       cards-row level resolves ONCE to the widest title's width
       ("Negotiate & close") instead of each row computing its own
       cluster centring from its own title width. Step spans all 5
       parent columns; ::before / icon-wrap / h3 below place into
       cols 1 / 3 / 4 respectively (cols 2 + 5 are the empty 1fr
       spacers). `column-gap: 0` is inherited from parent. */
    grid-template-columns: subgrid;
    grid-column: 1 / -1;
    align-items: center;
    /* Transparent fill (no gray/dark card background) but keep a
       subtle perimeter so each row still reads as a contained
       element on the dark sell-method frame. Border tone matches
       the translucent-white-on-dark hairline used elsewhere in this
       frame (icon-wrap border etc.). Padding gives a small breathing
       gap between content and the perimeter without changing the
       grid track sizes (number circle + icon circle stay at the
       clamp(60–76px) sizes from below). */
    background: transparent;
    border: 1px solid rgba(255, 255, 255, 0.10);
    border-radius: 18px;
    padding: clamp(6px, 0.8vh, 12px) clamp(14px, 1.6vw, 22px);
    margin: 0;
    text-align: left;
    transition: border-color 0.3s ease;
  }
  /* Centre the Process and Valuation column heading blocks (eyebrow
     + h2) over their respective card regions. The card region itself
     stays left-aligned per its own internal layout — only the heading
     pair is centred. The base `.v3-h2` rule sets `max-width: 26ch;
     margin: 0 0 24px` (line ~1990 of this file) which constrains the
     h2 box width and left-anchors it inside its grid cell — so
     `text-align: center` alone only centred the TEXT inside a narrow
     left-anchored BOX. Adding `margin-inline: auto` centres the box
     itself within the column so the h2 actually shares the same
     horizontal centre axis as its eyebrow. */
  .v3-frame-group--sell-method .v3-sell-process .v3-eyebrow,
  .v3-frame-group--sell-method .v3-sell-process .v3-h2,
  .v3-frame-group--sell-method .v3-sell-valuation .v3-eyebrow,
  .v3-frame-group--sell-method .v3-sell-valuation .v3-h2 {
    text-align: center;
    margin-inline: auto;
  }
  /* Suppress the base `.v3-process--timeline .v3-process__step:hover`
     translateY card-lift, but keep a subtle hover response: brighten
     the perimeter to mint instead of bringing back the filled gray
     background. The icon+title shift treatment further down still
     applies on hover. */
  .v3-frame-group--sell-method .v3-process.v3-process--timeline .v3-process__step:hover {
    transform: none;
    background: transparent;
    border-color: rgba(63, 230, 168, 0.32);
  }
  /* Subtle hover: nudge the icon+title group right by 4 px and shift
     the title colour to mint. Number circle stays put (no transform
     applied to ::before), so the hover reads as "lean toward the
     content" rather than a card lift. */
  .v3-frame-group--sell-method .v3-process.v3-process--timeline .v3-process__step:hover .v3-process__icon-wrap,
  .v3-frame-group--sell-method .v3-process.v3-process--timeline .v3-process__step:hover h3 {
    transform: translateX(4px);
  }
  .v3-frame-group--sell-method .v3-process.v3-process--timeline .v3-process__step:hover h3 {
    color: var(--mint);
  }
  /* Numbered circle rendered via ::before with a CSS counter so the
     mobile markup (no inline number per step) stays untouched. */
  .v3-frame-group--sell-method .v3-process.v3-process--timeline .v3-process__step::before {
    /* Pin the number circle to col 1 of the step's 5-col grid. */
    grid-column: 1;
    content: counter(sell-process-step, decimal-leading-zero);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: clamp(60px, 5vw, 76px);
    height: clamp(60px, 5vw, 76px);
    border-radius: 50%;
    border: 1px solid var(--mint);
    background: rgba(63, 230, 168, 0.06);
    color: var(--mint);
    font-family: "DM Sans", -apple-system, sans-serif;
    font-size: clamp(0.9375rem, 1.05vw, 1.0625rem);
    font-weight: 500;
    letter-spacing: 0.04em;
  }
  .v3-frame-group--sell-method .v3-process.v3-process--timeline .v3-process__step .v3-process__icon-wrap {
    /* Pin the icon-wrap to col 3 (col 2 is the 1fr left spacer). */
    grid-column: 3;
    width: clamp(60px, 5vw, 76px);
    height: clamp(60px, 5vw, 76px);
    margin: 0;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid rgba(255, 255, 255, 0.12);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: transform 0.3s var(--ease);
  }
  .v3-frame-group--sell-method .v3-process.v3-process--timeline .v3-process__step .v3-process__icon {
    color: var(--mint);
    font-size: clamp(26px, 2.5vw, 34px);
  }
  .v3-frame-group--sell-method .v3-process.v3-process--timeline .v3-process__step h3 {
    /* Pin the title to col 4 (col 5 is the 1fr right spacer). The
       icon→title gap is supplied here as `margin-left` rather than
       parent `column-gap` so the two 1fr spacer columns can do their
       job without inheriting a fixed gap on every column boundary. */
    grid-column: 4;
    margin: 0 0 0 clamp(18px, 2vw, 28px);
    font-family: "DM Sans", -apple-system, sans-serif;
    font-weight: 500;
    font-size: clamp(1.125rem, 1.5vw, 1.5rem);
    line-height: 1.25;
    letter-spacing: -0.01em;
    color: #fff;
    transition: transform 0.3s var(--ease), color 0.3s var(--ease);
  }
  /* Hide body text + decorative divider on desktop only — preserved
     in markup so mobile renders them. */
  .v3-frame-group--sell-method .v3-process.v3-process--timeline .v3-process__step > p,
  .v3-frame-group--sell-method .v3-process.v3-process--timeline .v3-process__step .v3-process__divider {
    display: none;
  }
  /* Connector line between consecutive number circles previously
     drawn here. Removed because the cards-row now uses
     `justify-content: space-between` to spread 5 steps evenly across
     the column height — the actual gap between consecutive number
     circles becomes a function of the column height, not a fixed
     clamp value, so a fixed-height connector either falls short or
     overshoots. The numbered circles + content rhythm communicate
     the sequence on their own. */

  /* /broker/ second major frame (`.v3-frame-group--broker-pair-2`,
     "Commission" + "Process"). The frame stacks two `.v3-section`s
     under one `.v3-frame-group` viewport-frame floor (min-height:
     100dvh). With the four-step process timeline added below the three
     commission cards, the combined content was over-running the
     viewport floor on 1080p / 1440×900 desktops — the fourth row of
     process cards was clipping below the next-section boundary. Pattern
     mirrors the existing `.v3-frame-group--sell-method` tightening
     above (per-section padding, h2/lede/eyebrow margin shrink, feature
     and process card padding shrink, timeline gap + margin-top shrink).
     Specificity-wise, every rule below is scoped via the
     `.v3-frame-group--broker-pair-2` ancestor — the more specific
     `--broker-pair-2` selector beats the looser `--broker-pair` rule
     above (line ~685) on source order at equal specificity, and the
     class-prefixed selector beats the bare `.v3-h2` / `.v3-eyebrow` /
     `.v3-lede` / `.v3-feature` / `.v3-process--timeline` base rules.
     `.v3-frame-group--broker-pair-1` is not affected — it's a
     separate dark "Three reasons" major higher up the page. */
  .v3-frame-group--broker-pair-2 > .v3-section {
    padding-block: clamp(16px, 2vh, 32px);
  }

  .v3-frame-group--broker-pair-2 .v3-h2 {
    font-size: clamp(1.5rem, 2.4vw, 2.125rem);
    line-height: 1.1;
    margin-bottom: clamp(8px, 1vh, 14px);
  }

  .v3-frame-group--broker-pair-2 .v3-eyebrow {
    margin-bottom: clamp(6px, 0.8vw, 12px);
  }

  .v3-frame-group--broker-pair-2 .v3-lede {
    font-size: clamp(0.95rem, 1.2vw, 1.125rem);
    margin-bottom: clamp(14px, 1.6vh, 22px);
  }

  .v3-frame-group--broker-pair-2 .v3-feature-row {
    margin-top: clamp(10px, 1.2vh, 18px);
    gap: clamp(12px, 1.4vw, 20px);
  }

  .v3-frame-group--broker-pair-2 .v3-feature {
    padding: clamp(14px, 1.6vw, 20px) clamp(14px, 1.4vw, 18px);
  }

  .v3-frame-group--broker-pair-2 .v3-process.v3-process--timeline {
    margin-top: clamp(14px, 1.6vh, 24px);
    gap: clamp(10px, 1.2vh, 18px);
  }

  .v3-frame-group--broker-pair-2 .v3-process.v3-process--timeline .v3-process__step {
    padding: clamp(18px, 2vw, 28px) clamp(14px, 1.4vw, 22px);
  }

  /* Scale up the Broker Process card internal content so each large
     2×2 card no longer feels empty. Step number, icon circle, icon
     glyph, and title are bumped together so the proportions stay
     balanced. Sizes are scoped to .v3-frame-group--broker-pair-2 so
     no other process timeline (Sell, broker-pair-1, plot-detail
     pages, etc.) is affected. */
  .v3-frame-group--broker-pair-2 .v3-process--timeline .v3-process__icon-wrap {
    width: clamp(56px, 4.6vw, 72px);
    height: clamp(56px, 4.6vw, 72px);
    margin-bottom: clamp(12px, 1.2vw, 18px);
  }
  .v3-frame-group--broker-pair-2 .v3-process--timeline .v3-process__icon {
    font-size: clamp(28px, 2.4vw, 36px);
  }
  .v3-frame-group--broker-pair-2 .v3-process--timeline .v3-process__step h3 {
    font-size: clamp(1.125rem, 1.4vw, 1.375rem);
    line-height: 1.25;
    margin-bottom: 6px;
  }

  .v3-frame-group--broker-pair-2 .v3-process--timeline .v3-process__divider {
    margin-bottom: 8px;
  }

  /* Centre the Process column heading block (eyebrow + h2 + lede)
     above the 2×2 card grid. Scoped to the Process side only via
     `:not(.v3-section--alt)` — the Commission side keeps its
     existing left-aligned headings per the task's "Process-side
     only" constraint. `margin-inline: auto` is required because
     the base `.v3-h2` rule sets `max-width: 26ch; margin: 0`
     (left-anchors the box) and the base `.v3-lede` sets
     `max-width: 60ch; margin: 0 0 32px` (also left-anchors).
     Without auto inline margins, `text-align: center` would only
     centre the text inside a left-anchored box. */
  .v3-frame-group--broker-pair-2 > .v3-section:not(.v3-section--alt) .v3-eyebrow,
  .v3-frame-group--broker-pair-2 > .v3-section:not(.v3-section--alt) .v3-h2,
  .v3-frame-group--broker-pair-2 > .v3-section:not(.v3-section--alt) .v3-lede {
    text-align: center;
    margin-inline: auto;
  }

  /* /broker/ second major (`--broker-pair-2`) — desktop two-column
     split. Above 1024px the major frame stops stacking Commission +
     Process vertically and sits them side-by-side at 50/50, one
     viewport-frame tall. Inside Commission, the three cards stack in a
     vertical column instead of the horizontal row. Inside Process, the
     horizontal numbered timeline collapses to a 2x2 quadrant grid of
     compact step cards (number + icon + title; body paragraph and
     accent divider hidden). The numbered nav row is hidden — step
     numbers are rendered via a CSS counter ::before on each card so
     01-04 are still surfaced without an HTML change. Mobile/tablet
     (<1024px) is unaffected: this entire block lives inside
     `@media (min-width: 1024px)`, so smaller viewports continue to
     render the original stacked layout with the horizontal timeline.
     The earlier broker-pair-2 tightening block above (heading sizes,
     padding shrink, etc.) still applies. */
  /* STRUCTURAL ALIGNMENT (subgrid pattern, mirrors the /sell/
     sell-method fix). Previous flex layout had each column laying
     out independently — Commission's `flex: 1 1 auto` card stack
     and Process's `flex: 1 1 auto` 2×2 grid each grew inside their
     own flex column, but unequal header heights (eyebrow / h2 /
     lede line counts) and intermediate flex-shrink behaviour meant
     the card-region top + bottom didn't reliably land at the same
     y on both sides. Replaced with a 2-col × 4-row CSS grid where
     row 4 = the shared card-region track (`1fr`, fills the
     remaining viewport height). Both child sections subgrid all 4
     row tracks, so eyebrow / h2 / lede / cards positions are tied
     across columns and the Process 2×2 grid's top + bottom edges
     align exactly with the Commission stack's top + bottom edges.
     Subgrid: Firefox 71+, Safari 16+, Chrome/Edge 117+ (Sep 2023). */
  .v3-frame-group--broker-pair-2 {
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-template-rows: auto auto auto 1fr;
    align-items: stretch;
    column-gap: clamp(32px, 4vw, 64px);
    row-gap: 0;
    /* Top padding clears the sticky nav pill so the Commission and
       Process eyebrows aren't masked when the frame sits at the top
       of the viewport. */
    padding: var(--v3-desktop-nav-offset) var(--v3-pad-x) clamp(48px, 7vh, 96px);
  }
  /* Both column sections subgrid the parent's 4 row tracks (eyebrow
     / h2 / lede / card-region), spanning rows 1–4, so each row's
     height is equalised across columns. */
  .v3-frame-group--broker-pair-2 > .v3-section {
    display: grid;
    grid-template-rows: subgrid;
    grid-row: 1 / 5;
    min-width: 0;
    padding: 0;
  }
  /* `.v3-section__inner` subgrids the same 4 row tracks so the
     inner's eyebrow/h2/lede/cards children land in the parent's
     row tracks — without this, the inner would auto-size its own
     rows and the alignment chain would break here. */
  .v3-frame-group--broker-pair-2 .v3-section__inner {
    display: grid;
    grid-template-rows: subgrid;
    grid-row: 1 / 5;
    width: 100%;
    max-width: none;
    min-width: 0;
  }

  /* Commission feature row lands in the shared card-region row
     (row 4). `repeat(3, 1fr)` enforces 3 equal-height stacked
     cards filling the row top-to-bottom. */
  .v3-frame-group--broker-pair-2 .v3-feature-row.v3-feature-row--3 {
    display: grid;
    grid-template-columns: 1fr;
    grid-template-rows: repeat(3, 1fr);
    gap: clamp(10px, 1.2vh, 16px);
    margin-top: clamp(18px, 2vh, 28px);
    min-height: 0;
    align-self: stretch;
  }

  /* Process timeline + cards-row also land in row 4. The timeline
     wrapper just stretches to fill row 4; the cards-row is the
     actual 2×2 grid that fills the wrapper. */
  .v3-frame-group--broker-pair-2 .v3-process.v3-process--timeline {
    display: block;
    margin-top: clamp(18px, 2vh, 28px);
    align-self: stretch;
    min-height: 0;
  }
  .v3-frame-group--broker-pair-2 .v3-process.v3-process--timeline .v3-process__nav-row {
    display: none;
  }
  .v3-frame-group--broker-pair-2 .v3-process.v3-process--timeline.v3-process--4 .v3-process__cards-row {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    grid-template-rows: repeat(2, 1fr);
    gap: clamp(10px, 1.2vh, 16px);
    counter-reset: broker-step;
    /* Inherit row 4's full height by stretching to fill the
       timeline wrapper. With the wrapper anchored to row 4 top +
       bottom (via subgrid stretch), this 2×2 grid fills the same
       vertical range — top + bottom edges land at exactly the same
       y-coordinates as the Commission stack's first + third card
       edges across the column. */
    height: 100%;
    min-height: 0;
  }

  /* Compact step card: number (counter) + icon + title. Body p and
     divider hidden so the quadrant stays compact. */
  .v3-frame-group--broker-pair-2 .v3-process.v3-process--timeline .v3-process__step {
    counter-increment: broker-step;
  }

  .v3-frame-group--broker-pair-2 .v3-process.v3-process--timeline .v3-process__step::before {
    content: "0" counter(broker-step);
    font-family: "DM Sans", -apple-system, sans-serif;
    /* Bumped from 0.8125rem so the step number reads as a proper
       editorial label sized to the larger icon + title below it,
       not a tiny tag. */
    font-size: clamp(1rem, 1.2vw, 1.25rem);
    font-weight: 500;
    letter-spacing: 0.06em;
    color: var(--accent);
    margin: 0 0 clamp(10px, 1.2vh, 16px);
  }

  .v3-frame-group--broker-pair-2 .v3-process.v3-process--timeline .v3-process__step .v3-process__divider,
  .v3-frame-group--broker-pair-2 .v3-process.v3-process--timeline .v3-process__step p {
    display: none;
  }

  /* Commission column refinements (desktop only). Scoped to
     `.v3-frame-group--broker-pair-2 > .v3-section--alt` (the Commission
     section) so the Process column on the right is unaffected and no
     other page's `.v3-feature` cards leak into. (1) Header centring —
     eyebrow / h2 / lede centred on a shared horizontal axis using
     `text-align: center` + `margin-inline: auto` (margin-inline needed
     because the base `.v3-h2` carries a `max-width: 26ch` and the base
     `.v3-lede` carries `max-width: 56ch`; without auto-margins those
     constrained blocks would still sit at the column's left edge).
     (2) Card surface transparent — the base `.v3-feature` rule paints
     `background: var(--bg)` (a pale page surface). On the dark broker-
     pair-2 frame, that read as a "filled card" backdrop. Stripped to
     transparent on both the resting state and `:hover` so the cards
     show their border + content only. The base hover still applies
     `transform: translateY(-3px); border-color: var(--v3-mint)` —
     subtle motion + accent border kept; just no fill comes back.
     (3) Card content centred — flex-column with `align-items: center`
     and `text-align: center` so the icon glyph, h3, and p sit on the
     same horizontal centre axis inside each card. */
  .v3-frame-group--broker-pair-2 > .v3-section--alt .v3-eyebrow,
  .v3-frame-group--broker-pair-2 > .v3-section--alt .v3-h2,
  .v3-frame-group--broker-pair-2 > .v3-section--alt .v3-lede {
    text-align: center;
    margin-inline: auto;
  }

  .v3-frame-group--broker-pair-2 > .v3-section--alt .v3-feature {
    background: transparent;
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
  }
  .v3-frame-group--broker-pair-2 > .v3-section--alt .v3-feature:hover {
    background: transparent;
  }

  /* Removed legacy /sell/ final-frame rules that targeted the
     pre-restructure markup (separate .v3-rep section + .v3-section--cta
     sibling). The new structure uses a single .v3-sell-final-section
     with .v3-rep--final and .v3-cta-panel--sell-final inside, so the
     old `.v3-frame-group--sell-final > .v3-section` /
     `> .v3-section--cta` / `.v3-rep` overrides are dead or conflicting
     (the .v3-rep override silently overrode .v3-rep--final's flex
     gap/padding via higher specificity). New rules live further down
     in this file under the same media query. */

  .v3-frame-group--sell-final .footer {
    padding-top: 20px;
    padding-bottom: 18px;
  }

  .v3-frame-group--sell-final .footer__inner {
    gap: 28px;
  }

  .v3-frame-group--sell-final .footer__col a,
  .v3-frame-group--sell-final .footer__col span {
    margin-bottom: 6px;
  }

  .v3-frame-group--sell-final .footer__bottom {
    margin-top: 20px;
    padding-top: 14px;
  }
}
/* /sell/ rep → valuation-CTA pairing: tighten the gap between the
   representative section's bottom and the closing valuation CTA's top
   so the rep card doesn't get pushed off the top of the final-scroll
   frame on shorter viewports (1440×900, 1366×768). Scoped via :has()
   so only the /sell/ rep section + its immediate CTA sibling are
   affected — the home `/` `.v3-section--cta` (which doesn't sit
   after a `.v3-rep`) keeps its default padding. */
.v3-section:has(.v3-rep) { padding-bottom: clamp(32px, 4vw, 56px); }
/* (The companion `.v3-section:has(.v3-rep) + .v3-section--cta` rule
    that previously tightened the sibling CTA was removed — after the
    /sell/ final-frame restructure there is no sibling .v3-section--cta;
    the rep card and the valuation CTA now share a single section.) */

/* /sell/ Valuation + Process pairing — the two sections are
   visually grouped (rather than wrapped into one <section>, which
   would lose their independent eyebrow/h2 structure) by tightening
   the padding on both sides of their shared boundary. The two read
   as one combined "how we price your land / what happens next" story
   and fit closer to a single desktop frame.
   • Valuation: padding-top ~128 → ~72 (eyebrow starts higher),
     padding-bottom ~128 → ~32 (closes the gap to Process).
   • Process:   padding-top ~128 → ~32 (mirrors Valuation bottom),
     padding-bottom kept at default (--v3-pad-y) since the next
     boundary is the rep card section which already has its own
     padding-top to manage that gap.
   • Both:      h2 margin-bottom 24 → 16 so the eyebrow/h2 cluster
     reads tight against the cards/visual below. */
.v3-sell-valuation { padding-block: clamp(40px, 5vw, 72px) clamp(20px, 2.5vw, 32px); }
.v3-sell-process   { padding-block: clamp(20px, 2.5vw, 32px) var(--v3-pad-y); }
.v3-sell-valuation .v3-h2,
.v3-sell-process   .v3-h2 { margin-bottom: 16px; }

/* /invest/ "Why JV with us" → final CTA pairing: tighten the gap
   between the .v3-usps reasons section bottom and the closing
   .v3-section--cta top so the reasons section, "See what's open this
   quarter" CTA, and footer all fit together at maximum bottom scroll.
   Scoped via :has(.v3-usps) so only the Invest hub's reasons → CTA
   pairing is affected — the home `/` and sell `.v3-section--cta`
   (which don't sit after a `.v3-usps`) keep their respective padding. */
.v3-section:has(.v3-usps) { padding-bottom: clamp(32px, 4vw, 56px); }
.v3-section:has(.v3-usps) + .v3-section--cta { padding: clamp(32px, 4vw, 56px) var(--v3-pad-x); }

/* /buy/ and /invest/ frame refinements after the major-frame
   pass. Keep the full-frame structure, but remove the empty-feeling
   space that appeared around the final conversion moments. */
@media (min-width: 1024px) {
  .v3-frame-group--buy-final {
    justify-content: flex-start;
  }

  .v3-frame-group--buy-final > .v3-section {
    flex: 1 1 auto;
    display: flex;
    align-items: center;
    padding-block: clamp(32px, 5vh, 64px);
  }

  /* Desktop CTA layout for /buy/'s "Don't see it?" final
     section — content centred and capped, but with NO card
     surface. The previous mint-white card box was removed; the
     CTA copy now sits directly on the dark-green final-frame
     background. */
  .v3-frame-group--buy-final .v3-section__inner {
    max-width: 760px;
    padding: clamp(32px, 4vw, 48px);
    text-align: center;
  }

  .v3-frame-group--buy-final .v3-h2,
  .v3-frame-group--buy-final .v3-body {
    margin-left: auto;
    margin-right: auto;
  }

  .v3-frame-group--buy-final .v3-cta-row {
    justify-content: center;
  }

  /* Final-frame distribution — three children (reasons section,
     CTA section, footer). The previous `flex-end` packed everything
     to the bottom and left all viewport slack as empty space above
     the reasons block; the page felt compressed in the
     upper/middle. `space-between` flushes the reasons section to
     the top of the 100dvh frame and the footer to the bottom, with
     the CTA carrying the slack as evenly-distributed breathing room
     on either side — so the CTA reads as a hinge between the
     reasons and the footer, and the frame fills top to bottom. */
  .v3-frame-group--invest-final {
    justify-content: space-between;
  }

  .v3-frame-group--invest-final > .v3-section:first-child {
    padding-block: clamp(20px, 2.5vh, 28px) clamp(8px, 1.2vh, 14px);
  }

  .v3-frame-group--invest-final > .v3-section.v3-section--alt.v3-section--cta {
    padding-block: clamp(24px, 3vh, 40px);
  }

  .v3-frame-group--invest-final .v3-usps {
    grid-template-columns: repeat(4, 1fr);
    gap: 24px;
    margin: 24px 0 0;
  }

  .v3-frame-group--invest-final .v3-usp h3 {
    font-size: 1.125rem;
  }

  .v3-frame-group--invest-final .v3-usp p {
    line-height: 1.45;
  }

  .v3-frame-group--invest-final .v3-section--cta .v3-h2 {
    font-size: clamp(2.5rem, 4.4vw, 4rem);
    margin-bottom: 28px;
  }

  .v3-frame-group--invest-final .v3-section--cta .btn--primary {
    font-size: clamp(1rem, 1.2vw, 1.125rem);
    padding: 18px 34px;
  }

  .v3-frame-group--invest-final .footer {
    padding-top: 28px;
    padding-bottom: 20px;
  }

  .v3-frame-group--invest-final .footer__bottom {
    margin-top: 24px;
    padding-top: 16px;
  }

  /* /broker/ final major (`.v3-frame-group--broker-final`) — closing
     CTA frame ("Bring your client onto a Namou-led call.") + footer.
     The base `.v3-frame-group--final` rule pins both children to the
     bottom (`justify-content: flex-end`), which collapses the CTA
     against the top of the footer and leaves a large empty band at
     the top of the viewport frame. Make the CTA section grow to fill
     the available space and vertically + horizontally center its
     inner content cluster, while the footer keeps its natural size
     pinned to the bottom (preserved by the existing
     `.v3-frame-group--final > .footer { flex: 0 0 auto }` rule). The
     headline + button are scaled up to feel like a substantial
     closing moment, mirroring the size pattern used by --invest-final
     just above. Horizontal centering already comes from
     `.v3-h2--center` + `.v3-cta-row--center` + the section's
     `text-align: center`; vertical centering is what was missing. */
  .v3-frame-group--broker-final > .v3-section.v3-section--cta {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    padding-block: clamp(48px, 7vh, 96px);
  }

  .v3-frame-group--broker-final .v3-section--cta .v3-section__inner {
    width: 100%;
    max-width: 720px;
  }

  .v3-frame-group--broker-final .v3-section--cta .v3-h2 {
    font-size: clamp(2.5rem, 4.4vw, 4rem);
    line-height: 1.05;
    max-width: 22ch;
    margin-left: auto;
    margin-right: auto;
    margin-bottom: clamp(28px, 3.5vh, 44px);
  }

  .v3-frame-group--broker-final .v3-section--cta .btn--primary {
    font-size: clamp(1rem, 1.2vw, 1.125rem);
    padding: 18px 34px;
  }
}

/* Swap-target class for the basic-for-now valuation visual. No
   styling override — keeps the existing .v3-split__visual layout.
   Search for ".v3-split__visual--placeholder" or the
   data-placeholder="valuation-visual" attribute when replacing the
   image with a better asset. */
.v3-split__visual--placeholder { /* intentionally empty — swap target only */ }

/* /sell/ Valuation + Process restyle: 3-column valuation row of
   centered text cards (each with a circular accent-subtle icon
   badge, title, accent divider, and description), and a Process
   block split into two rows — a top "nav" row of 5 outlined
   numbered circles connected by an accent line + arrowhead between
   adjacent circles, and below it a row of 5 cards with a circular
   icon badge, title, accent divider, and description. Scoped via
   modifier classes (.v3-feature--method, .v3-process--timeline) so
   other site pages using the base .v3-feature / .v3-process classes
   are unaffected. */
.v3-feature-row.v3-feature-row--method {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(16px, 1.6vw, 24px);
  margin-top: clamp(28px, 3vw, 48px);
}
.v3-feature.v3-feature--method {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: clamp(24px, 2.4vw, 36px) clamp(20px, 2vw, 28px);
  border-radius: 20px;
  background: var(--v3-mint-white);
  border: 1px solid var(--v3-rule);
  transition: transform 0.4s var(--ease), border-color 0.3s ease;
}
.v3-feature.v3-feature--method:hover {
  transform: translateY(-4px);
  border-color: var(--accent);
}
.v3-feature--method .v3-feature__icon-wrap {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: clamp(44px, 3.6vw, 56px);
  height: clamp(44px, 3.6vw, 56px);
  border-radius: 999px;
  background: var(--accent-subtle);
  margin-bottom: clamp(16px, 1.6vw, 24px);
}
.v3-feature--method .v3-feature__icon {
  font-size: clamp(22px, 1.8vw, 26px);
  color: var(--accent);
}
.v3-feature--method h3 {
  font-family: "DM Sans", -apple-system, sans-serif;
  font-weight: 500;
  font-size: clamp(1rem, 1.2vw, 1.25rem);
  line-height: 1.25;
  color: var(--ink);
  margin: 0 0 12px;
}
.v3-feature--method .v3-feature__divider {
  display: block;
  width: 32px;
  height: 1.5px;
  background: var(--accent);
  margin: 0 0 16px;
  border-radius: 2px;
}
.v3-feature--method p {
  font-family: "DM Sans", -apple-system, sans-serif;
  font-size: clamp(0.875rem, 0.95vw, 1rem);
  line-height: 1.55;
  color: var(--ink-muted);
  margin: 0;
  max-width: 36ch;
}

/* Process timeline — two-row layout: nav row + cards row.
   Both rows share an identical 5-column grid with the same
   column-gap so each numbered circle aligns horizontally with the
   center of the card directly below it. The `--proc-gap` CSS
   variable is read by the connector-line math (see below). */
.v3-process.v3-process--timeline {
  --proc-gap: clamp(20px, 2vw, 36px);
  --proc-num-radius: 28px;
  display: flex;
  flex-direction: column;
  gap: clamp(20px, 2vw, 32px);
  margin-top: clamp(40px, 4vw, 64px);
  border: none;
  grid-template-columns: none;
}
.v3-process__nav-row,
.v3-process__cards-row {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  column-gap: var(--proc-gap);
}
/* 4-step variant — used by /broker/ to render the same timeline
   pattern with four numbered cells instead of five. The connector-
   line / arrowhead math is per-cell so it works for any cell count. */
.v3-process.v3-process--timeline.v3-process--4 .v3-process__nav-row,
.v3-process.v3-process--timeline.v3-process--4 .v3-process__cards-row {
  grid-template-columns: repeat(4, 1fr);
}
.v3-process__nav-cell {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: calc(var(--proc-num-radius) * 2);
}
.v3-process--timeline .v3-process__num {
  width: calc(var(--proc-num-radius) * 2);
  height: calc(var(--proc-num-radius) * 2);
  border-radius: 999px;
  border: 1.5px solid var(--accent);
  background: transparent;
  color: var(--accent);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: "DM Sans", -apple-system, sans-serif;
  font-size: 0.8125rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  margin: 0;
  position: relative;
  z-index: 1;
}
/* Connector line between adjacent numbered circles. Math: in this
   cell's coordinate system (cell width = 100%), the next circle's
   center sits at 150% + column-gap, so its left edge is at
   150% + gap − radius. Translated to a CSS `right` offset (negative
   when the line extends past this cell's right boundary), that's
   `-50% − gap + radius`. Line starts at `50% + radius`, the right
   edge of the current circle. */
.v3-process__nav-cell:not(:last-child)::after {
  content: "";
  position: absolute;
  top: 50%;
  left: calc(50% + var(--proc-num-radius) + 2px);
  right: calc(-50% - var(--proc-gap) + var(--proc-num-radius) + 2px);
  height: 1.5px;
  background: var(--accent);
  transform: translateY(-50%);
  pointer-events: none;
  z-index: 0;
}
/* Arrowhead at the line's right end (just before the next circle).
   Drawn as a CSS triangle via borders: the box has 0 width and
   border-left renders as a 7×10 px chevron pointing right. The tip
   sits at the box's right edge, so we share the same `right` value
   as the connector line above to align tip with line-end. */
.v3-process__nav-cell:not(:last-child)::before {
  content: "";
  position: absolute;
  top: 50%;
  right: calc(-50% - var(--proc-gap) + var(--proc-num-radius) + 2px);
  width: 0;
  height: 0;
  border-left: 7px solid var(--accent);
  border-top: 5px solid transparent;
  border-bottom: 5px solid transparent;
  transform: translateY(-50%);
  pointer-events: none;
  z-index: 1;
}
.v3-process.v3-process--timeline .v3-process__step {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: clamp(22px, 2vw, 32px) clamp(16px, 1.6vw, 24px);
  border-radius: 20px;
  background: var(--v3-mint-white);
  border: 1px solid var(--v3-rule);
  border-right: 1px solid var(--v3-rule);
  position: relative;
  z-index: 1;
  transition: transform 0.4s var(--ease), border-color 0.3s ease;
}
.v3-process.v3-process--timeline .v3-process__step:hover {
  transform: translateY(-4px);
  border-color: var(--accent);
  background: var(--v3-mint-white);
}
.v3-process.v3-process--timeline .v3-process__step:last-child {
  border-right: 1px solid var(--v3-rule);
}
.v3-process--timeline .v3-process__icon-wrap {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: clamp(40px, 3.4vw, 52px);
  height: clamp(40px, 3.4vw, 52px);
  border-radius: 999px;
  background: var(--accent-subtle);
  margin-bottom: clamp(14px, 1.4vw, 20px);
}
.v3-process--timeline .v3-process__icon {
  font-size: clamp(20px, 1.7vw, 24px);
  color: var(--accent);
  margin: 0;
}
.v3-process--timeline .v3-process__step h3 {
  font-family: "DM Sans", -apple-system, sans-serif;
  font-weight: 500;
  font-size: clamp(0.9375rem, 1.05vw, 1.0625rem);
  line-height: 1.25;
  color: var(--ink);
  margin: 0 0 10px;
  text-transform: none;
}
.v3-process--timeline .v3-process__divider {
  display: block;
  width: 32px;
  height: 1.5px;
  background: var(--accent);
  margin: 0 0 12px;
  border-radius: 2px;
}
.v3-process--timeline .v3-process__step p {
  font-family: "DM Sans", -apple-system, sans-serif;
  font-size: clamp(0.8125rem, 0.9vw, 0.9375rem);
  line-height: 1.5;
  color: var(--ink-muted);
  margin: 0;
}
@media (max-width: 1023px) {
  .v3-feature-row.v3-feature-row--method { grid-template-columns: 1fr; }
  .v3-process.v3-process--timeline .v3-process__nav-row,
  .v3-process.v3-process--timeline .v3-process__cards-row { grid-template-columns: repeat(2, 1fr); }
  /* Hide the desktop horizontal connector line + arrowhead on
     2-col layout — the visual flow no longer reads as a single row,
     so the line/arrow would point sideways at random circles. */
  .v3-process.v3-process--timeline .v3-process__nav-cell:not(:last-child)::before,
  .v3-process.v3-process--timeline .v3-process__nav-cell:not(:last-child)::after { display: none; }
}
@media (min-width: 768px) and (max-width: 1023px) {
  .v3-feature-row.v3-feature-row--method { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 600px) {
  .v3-process.v3-process--timeline .v3-process__nav-row,
  .v3-process.v3-process--timeline .v3-process__cards-row { grid-template-columns: 1fr; }
}

/* Asymmetric padding: top-padding is wider so the trust strip sits
   lower beneath the preceding section (e.g. the home #audience grid),
   creating clearer separation between the audience image-card row and
   this 3-cell text-card row. Bottom-padding stays tight so the trust
   strip's bottom edge against the next section is unchanged. */
.v3-section--trust { padding: clamp(40px, 5vw, 72px) var(--v3-pad-x) clamp(16px, 2vw, 26px); }

/* Inflate fallback for sections that have no adjacent short neighbor to
   pair with. Targets ~85vh so content has breathing room without
   floating-in-void at full 100vh. Inner container expands to width: 100%
   so internal grids (.v3-aud-router__grid, .v3-stats, .v3-feature-row,
   etc.) keep their layout rules. Desktop only — mobile keeps default
   padding-driven height. */
@media (min-width: 1024px) {
  .v3-section--filled {
    min-height: 85vh;
    display: flex;
    flex-direction: column;
    justify-content: center;
  }
  .v3-section--filled > .v3-section__inner {
    width: 100%;
  }
  /* Home-only override: Wynn top-anchors its content against the
     padding-top instead of centering in the 85vh frame. Without this,
     the marquee → eyebrow gap stayed ~200px because flex-center
     distributed the leftover height symmetrically above the eyebrow. */
  .v3-section--filled.v3-wynn { justify-content: flex-start; }
}

.v3-eyebrow {
  font-family: "DM Sans", sans-serif;
  font-weight: 500;
  font-size: 12px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent);
  margin: 0 0 20px;
}

.v3-h1 {
  font-family: "DM Sans", sans-serif;
  font-weight: 500;
  font-size: clamp(2.5rem, 5.4vw, 5rem);
  line-height: 1.04;
  letter-spacing: -0.035em;
  color: var(--ink);
  margin: 0 0 24px;
  max-width: min(22ch, 100%);
  text-wrap: balance;
}
.v3-h2 {
  font-family: "DM Sans", sans-serif;
  font-weight: 500;
  font-size: clamp(2rem, 3.8vw, 3.25rem);
  line-height: 1.08;
  letter-spacing: -0.03em;
  color: var(--ink);
  margin: 0 0 24px;
  max-width: 26ch;
}
.v3-h2--center { margin-left: auto; margin-right: auto; max-width: 32ch; text-align: center; }
.v3-h3 { font-family: "DM Sans", sans-serif; font-weight: 500; font-size: 1.25rem; letter-spacing: -0.015em; margin: 32px 0 12px; color: var(--ink); }

.v3-serif {
  font-family: "Instrument Serif", serif;
  font-style: italic;
  font-weight: 400;
  letter-spacing: -0.02em;
  color: var(--v3-forest);
}

.v3-lede {
  font-family: "DM Sans", sans-serif;
  font-size: clamp(1.05rem, 1.5vw, 1.3rem);
  line-height: 1.5;
  color: var(--ink-muted);
  max-width: 56ch;
  margin: 0 0 32px;
}
.v3-body { font-size: 1.0625rem; line-height: 1.6; color: var(--ink-muted); max-width: 60ch; margin: 0 0 16px; }
.v3-body--center { max-width: 50ch; margin-left: auto; margin-right: auto; text-align: center; }
.v3-prose p { margin: 0 0 16px; }

/* ── CTA row ─────────────────────────────────────────── */
.v3-cta-row { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 24px; }
.v3-cta-row--center { justify-content: center; }
.v3-cta-row .btn--primary svg { transition: transform 200ms var(--ease); }
.v3-cta-row .btn--primary:hover svg { transform: translateX(2px); }
/* WhatsApp glyph variant for .btn buttons. The path is filled (currentColor),
   so the inherited `.btn--primary svg path { stroke: var(--accent-deep) }` rule
   would draw a deep-green outline around the glyph. Reset stroke and pin
   geometry so it sits like a logo cue, not a directional arrow (no hover slide).
   Hover-translate reset is class-scoped (not container-scoped) so it works
   anywhere a .btn__wa-icon appears — .v3-cta-row, .v3-cta-panel__actions, etc. */
.btn .btn__wa-icon path { stroke: none; }
.btn--primary:hover .btn__wa-icon { transform: none; }

/* ── Hero variants ────────────────────────────────────── */
.v3-hero { position: relative; overflow: clip; }
.v3-hero--full {
  --v3-hero-copy-offset: clamp(112px, 8vw, 148px);
  --v3-hero-copy-pad-x: clamp(24px, 5vw, 72px);
  --v3-hero-copy-pad-bottom: clamp(40px, 6vw, 80px);
  position: relative;
  min-height: clamp(560px, 78vh, 820px);
  padding: 0;
  display: grid;
  align-items: start;
  justify-items: center;
  isolation: isolate;
}
/* Desktop: hero + marquee fit exactly inside one viewport from the
   first screen view. Hero takes calc(100vh - marquee height); marquee
   sits at the bottom edge as a fixed 80px strip. */
@media (min-width: 1024px) {
  .v3-hero--full {
    min-height: 0;
    height: calc(100svh - 80px);
    height: calc(100dvh - 80px);
  }
}
/* Mobile.
   - Hub heroes (`.v3-hero--full.v3-hero--up`, used on /buy/,
     /sell/, /invest/, /broker/) carry a .v3-hub-marquee
     strip immediately below them. Reserve the marquee height in
     the hero so hero + marquee = exactly 100svh — same concept
     desktop already uses (`calc(100dvh - 80px)` + 80px marquee).
     `svh` (small viewport height) stays stable as iOS chrome
     shows/hides so the layout doesn't jitter when the URL bar
     collapses. Without this, the prior `min-height: 100svh` on
     hero alone pushed the marquee below the fold on phones —
     users saw only the hero in the first viewport.
   - Plot-detail heroes (`.v3-hero--full` without `--up`) don't
     have a marquee below, so they keep the simple `min-height:
     100svh` floor from the broader rule. */
@media (max-width: 768px) {
  :root {
    --v3-mobile-hub-marquee-h: 64px;
  }
  .v3-hero--full {
    min-height: 100svh;
  }
  .v3-hero--full.v3-hero--up {
    min-height: 0;
    height: calc(100svh - var(--v3-mobile-hub-marquee-h));
  }
  .v3-hub-marquee {
    height: var(--v3-mobile-hub-marquee-h);
  }
}
.v3-hero--full .v3-hero__media {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
}
.v3-hero--full .v3-hero__media .ph,
.v3-hero--full .v3-hero__media img {
  width: 100% !important;
  height: 100% !important;
  object-fit: cover;
  aspect-ratio: auto !important;
  border-radius: 0 !important;
  border: 0 !important;
}
/* Hide the placeholder's centered label inside hero (it'd compete with the headline) */
.v3-hero--full .v3-hero__media .ph .ph__inner { opacity: 0.18; }
/* Audience-hub heroes (.v3-hero--up: buy/sell/invest/broker) carry the
   *-hero-bg.png technical-illustration assets (~1915×821, aspect
   ≈2.33:1). The hero container is taller than the image (≈1.92:1 on a
   1080p viewport), so the previous `object-fit: contain` was leaving
   green letterbox bands at the top and bottom. Switched to `cover` so
   the image fills the hero vertically with no visible section
   background. The image is wider than the container, so the side
   edges crop slightly under cover; technical labels in the asset's
   centre band stay visible. The forest letterbox fill on
   `.v3-hero__media` is no longer needed and has been removed — `cover`
   never exposes the underlying surface. */
.v3-hero--full.v3-hero--up .v3-hero__media img {
  object-fit: cover;
  object-position: center center;
}
.v3-hero--full .v3-hero__copy {
  position: relative;
  z-index: 2;
  align-self: start;
  padding: 0 var(--v3-hero-copy-pad-x) var(--v3-hero-copy-pad-bottom);
  color: #fff;
  max-width: min(920px, 100%);
  margin: 0 auto;
  margin-top: var(--v3-hero-copy-offset);
  width: 100%;
  text-align: center;
  box-sizing: border-box;
}
@media (max-width: 768px) {
  .v3-hero--full {
    /* Floor lifted to 128px so the title clears the ~68px-tall
       mobile nav pill (16px top inset + ~52px pill height) with a
       comfortable ~60px breathing band. */
    --v3-hero-copy-offset: clamp(128px, 26vw, 168px);
    --v3-hero-copy-pad-x: clamp(20px, 6vw, 32px);
    --v3-hero-copy-pad-bottom: 32px;
  }
}
/* Hero variant that pulls the copy block higher up the frame —
   used on /sell/, /invest/, etc., where the hero photograph
   carries colour-heavy content in its lower half (buildings,
   coastline, parcel diagrams) that would otherwise sit underneath
   the title + lede and crush legibility. Tighter top offset
   parks the copy cluster firmly in the upper sky band. */
.v3-hero--full.v3-hero--up .v3-hero__copy {
  --v3-hero-copy-offset: clamp(56px, 4.5vw, 88px);
}
@media (max-width: 768px) {
  /* Hub-hero copy on mobile: same 128px floor as the base hero
     copy variant so the h1 sits clearly below the nav pill. */
  .v3-hero--full.v3-hero--up .v3-hero__copy {
    --v3-hero-copy-offset: clamp(128px, 26vw, 168px);
  }
}
.v3-hero--full .v3-h1, .v3-hero--full .v3-eyebrow, .v3-hero--full .v3-lede { color: #fff; }
.v3-hero--full .v3-eyebrow { color: var(--v3-mint); }
.v3-hero--full .v3-lede { color: rgba(255,255,255,0.85); }
.v3-hero--full .v3-serif { color: var(--accent-deep); }
/* Audience-hub heroes carry the new *-hero-bg.png illustrations whose
   surface is mostly white/light sketch — white H1 + lede text became
   unreadable on that surface. Flip both to ink for the four hub pages
   (buy/sell/invest/broker, all `.v3-hero--up`). The mint accent
   treatments (`.v3-eyebrow`, `.v3-serif`) keep their existing green
   colour via their own rules above and are not overridden here, so
   serif-italic words inside the H1 (e.g. "Ras Al Khaimah",
   "accountability", "managing the build", "your client") remain green.
   Plot-detail heroes (`.v3-hero--full` without `--up`) keep their
   white text — those sit on darkened real-estate photographs and the
   existing `.v3-hero__media--plot::after` dimming gradient was tuned
   for white-on-photo legibility. */
.v3-hero--full.v3-hero--up .v3-h1 { color: var(--ink); }
.v3-hero--full.v3-hero--up .v3-lede { color: #fff; }
.v3-hero--full.v3-hero--up .v3-lede.v3-lede--halo {
  position: relative;
  isolation: isolate;
  max-width: min(720px, 88vw);
  padding: clamp(2px, 0.4vw, 5px) clamp(8px, 1vw, 14px);
  color: rgba(0, 0, 0, 0.84);
  text-shadow:
    0 1px 10px rgba(255, 255, 255, 0.98),
    0 0 22px rgba(255, 255, 255, 0.92);
}
.v3-hero--full.v3-hero--up .v3-lede.v3-lede--halo::before {
  content: "";
  position: absolute;
  inset: clamp(-14px, -1.3vw, -8px) clamp(-48px, -4vw, -24px);
  z-index: -1;
  border-radius: 999px;
  background:
    radial-gradient(ellipse at 48% 44%, rgba(255, 255, 255, 0.9) 0%, rgba(255, 255, 255, 0.64) 36%, rgba(255, 255, 255, 0.22) 66%, rgba(255, 255, 255, 0) 100%),
    radial-gradient(ellipse at 22% 58%, rgba(255, 255, 255, 0.52) 0%, rgba(255, 255, 255, 0) 62%),
    radial-gradient(ellipse at 78% 52%, rgba(255, 255, 255, 0.48) 0%, rgba(255, 255, 255, 0) 64%);
  filter: blur(18px);
  opacity: 0.94;
  pointer-events: none;
}
.v3-hero--full.v3-hero--up .v3-lede.v3-lede--halo.copy-desktop {
  display: inline-block;
}
@media (max-width: 1180px), (max-height: 760px) {
  .v3-hero--full.v3-hero--up .v3-lede.v3-lede--halo::before {
    inset: clamp(-22px, -2vw, -14px) clamp(-64px, -5vw, -36px);
    filter: blur(22px);
    opacity: 1;
    background:
      radial-gradient(ellipse at 50% 48%, rgba(255, 255, 255, 0.96) 0%, rgba(255, 255, 255, 0.7) 42%, rgba(255, 255, 255, 0.28) 72%, rgba(255, 255, 255, 0) 100%),
      radial-gradient(ellipse at 18% 56%, rgba(255, 255, 255, 0.58) 0%, rgba(255, 255, 255, 0) 68%),
      radial-gradient(ellipse at 82% 54%, rgba(255, 255, 255, 0.54) 0%, rgba(255, 255, 255, 0) 68%);
  }
}
@media (max-width: 768px) {
  .v3-hero--full.v3-hero--up .v3-lede.v3-lede--halo.copy-desktop {
    display: none;
  }
  .v3-hero--full.v3-hero--up .v3-lede.v3-lede--halo.copy-mobile {
    display: inline-block;
  }
}
/* Plot-detail heroes (real-estate photography behind white H1 + price +
   status text) keep a soft self-contained dimming gradient for legibility.
   Self-contained because the broad .v3-hero--full .v3-hero__media::after
   rule that previously supplied content/position/inset/z-index has been
   removed (it was dimming the audience-hub illustrations as well). */
.v3-hero__media--plot::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(0,0,0,0.08) 0%, rgba(0,0,0,0.42) 100%);
  z-index: 1;
}

.v3-hero--text {
  padding-top: clamp(140px, 18vh, 200px);
  padding-bottom: clamp(48px, 6vh, 80px);
  text-align: center;
}
.v3-hero--text .v3-section__inner { max-width: 880px; margin: 0 auto; }

/* Desktop: text-only hero fills the full viewport. The fixed nav overlays
   the top 80px, but the hero's existing padding-top (clamp(140px, 18vh,
   200px)) already pushes copy well below the nav, so no content is occluded. */
@media (min-width: 1024px) {
  .v3-hero--text {
    min-height: 100svh;
    min-height: 100dvh;
  }
}

/* Top-center content inside every v3 hero (full + text variants) */
.v3-hero .v3-eyebrow,
.v3-hero .v3-h1,
.v3-hero .v3-h2,
.v3-hero .v3-h3,
.v3-hero .v3-lede,
.v3-hero .v3-body,
.v3-hero .v3-plot-detail__price,
.v3-hero .v3-plot-detail__cta-line,
.v3-hero .v3-plot-detail__status {
  text-align: center;
  margin-left: auto;
  margin-right: auto;
}
.v3-hero .v3-cta-row { justify-content: center; }

@media (min-width: 1024px) and (max-height: 760px) {
  .v3-hero--full {
    --v3-hero-copy-offset: 84px;
    --v3-hero-copy-pad-bottom: 32px;
  }
  .v3-hero--full.v3-hero--up .v3-hero__copy {
    --v3-hero-copy-offset: 78px;
  }
  .v3-hero--full .v3-h1 {
    font-size: clamp(2.35rem, 4.8vw, 4.35rem);
    margin-bottom: 18px;
  }
  .v3-hero--full .v3-lede {
    font-size: clamp(1rem, 1.25vw, 1.15rem);
    line-height: 1.45;
    margin-bottom: 22px;
  }
  .v3-hero--full .v3-cta-row {
    margin-top: 18px;
  }
}

/* ── Areas marquee ───────────────────────────────────── */
.v3-marquee-section {
  padding: 0;
  height: 80px;
  display: flex;
  align-items: center;
  border-top: 1px solid var(--v3-rule);
  border-bottom: 1px solid var(--v3-rule);
}
.v3-marquee {
  width: 100%;
  overflow: hidden;
  /* Soft fade on each edge so items enter/exit gracefully */
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 80px, #000 calc(100% - 80px), transparent 100%);
          mask-image: linear-gradient(90deg, transparent 0, #000 80px, #000 calc(100% - 80px), transparent 100%);
}
.v3-marquee__track {
  display: inline-flex;
  align-items: center;
  gap: clamp(16px, 3vw, 48px);
  white-space: nowrap;
  animation: v3-marquee-scroll 40s linear infinite;
  will-change: transform;
}
.v3-marquee__item {
  font-family: "DM Sans", sans-serif;
  font-weight: 500;
  font-size: clamp(1.1rem, 1.8vw, 1.5rem);
  color: var(--ink);
  letter-spacing: -0.01em;
}
.v3-marquee__sep { color: var(--ink-soft); font-size: 1.25rem; }
.v3-marquee:hover .v3-marquee__track { animation-play-state: paused; }

@keyframes v3-marquee-scroll {
  from { transform: translateX(0); }
  /* Track holds two copies of the list (one duplicate marked aria-hidden);
     -50% slides exactly one full copy off, then loops seamlessly. */
  to   { transform: translateX(-50%); }
}

@media (prefers-reduced-motion: reduce) {
  .v3-marquee__track { animation: none; }
}

.v3-areas__caption { font-size: 14px; color: var(--ink-soft); margin: 16px 0 0; padding: 0 32px; }

/* ── Hub marquee ─────────────────────────────────────────
   80px companion strip below .v3-hero--full on each of the 4 audience
   hub pages (Buy / Sell / Invest / Broker). Mirrors the home marquee's
   exact-80px band shape (overrides .v3-section--strip's 32px padding
   so the hub hero — calc(100dvh - 80px) — plus this strip lands on 1vp).
   Reuses .v3-marquee internals; differentiation from the home zones
   marquee is purely content-level (.v3-marquee__num numbered prefix). */
.v3-hub-marquee {
  padding: 0;
  height: 80px;
  display: flex;
  align-items: center;
  border-top: 1px solid var(--v3-rule);
  border-bottom: 1px solid var(--v3-rule);
}
.v3-marquee__num {
  color: var(--accent);
  font-size: 0.85em;
  margin-right: 0.4em;
  font-feature-settings: "tnum" 1; /* tabular numerals so 01/02/.../06 align cleanly */
}

/* =============================================================
   Audience Router Cards — premium editorial pattern
   Single rounded container; image full-bleed top with soft fade
   into a cream content panel; label-row + headline + arrow link.
   ============================================================= */
.v3-aud-router__grid {
  display: grid;
  /* Desktop: all 4 audience cards in one row. Tablet collapses to
     2 cols (≤1023px) and mobile to 1 col (≤720px), see breakpoints
     at the bottom of this file. */
  grid-template-columns: repeat(4, 1fr);
  column-gap: 20px;
  row-gap: 24px;
  margin-top: 24px;
}

/* Audience-router-only card compressions (scoped via descendant
   selector so .v3-aud-card placements outside the home audience grid —
   e.g. /buy/'s .v3-buy-value-card variant — keep their original
   spec). With the 4-col desktop layout cards are now ~320px wide, so
   16/9 reads as a proportioned thumbnail (was 16/7 when cards were
   ~676px wide in 2-col — that flatter ratio looked letterboxed at
   narrower widths). */
.v3-aud-router__grid .v3-aud-card__image-wrap { aspect-ratio: 16 / 9; }
.v3-aud-router__grid .v3-aud-card__body { padding: 18px; }
.v3-aud-router__grid .v3-aud-card__headline { margin-top: 8px; }
.v3-aud-router__grid .v3-aud-card__link { margin-top: 12px; }
.v3-aud-card {
  display: flex;
  flex-direction: column;
  text-decoration: none;
  color: inherit;
  background: var(--v3-bg-card);
  border: 1px solid rgba(0, 61, 46, 0.08);
  border-radius: 24px;
  overflow: hidden;
  cursor: pointer;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
  transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.v3-aud-card:hover {
  transform: translateY(-2px);
  box-shadow: 0 8px 24px rgba(0, 61, 46, 0.12);
}
.v3-aud-card:focus-visible {
  outline: 2px solid var(--accent-deep);
  outline-offset: 2px;
}
.v3-aud-card:active {
  transform: scale(0.99);
}

/* Image area — full-bleed, 16:10, with soft fade dissolving into the
   content panel via an ::after gradient overlay (Option A from the
   spec). Broader browser support than mask-image and easier to debug. */
.v3-aud-card__image-wrap {
  position: relative;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  background: var(--v3-bg-card);
}
.v3-aud-card__image-wrap::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    to bottom,
    transparent 0%,
    transparent 60%,
    var(--v3-bg-card) 100%
  );
  pointer-events: none;
}
.v3-aud-card__image {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  display: block;
}

/* Placeholder treatment scoped to this card pattern only — softer
   mint wash, mint dotted border (not Forest Green), label centered,
   slot tag in bottom-right at 11px / 0.06em. */
.v3-aud-card__placeholder {
  width: 100%;
  height: 100%;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  text-align: center;
  background: linear-gradient(135deg, rgba(63, 230, 168, 0.08) 0%, rgba(63, 230, 168, 0.16) 100%);
  border: 2px dashed var(--mint);
  border-bottom: none;
}
.v3-aud-card__placeholder-label {
  font-family: "DM Sans", sans-serif;
  font-size: 15px;
  font-weight: 500;
  letter-spacing: -0.01em;
  color: var(--accent-deep);
  max-width: 28ch;
}
.v3-aud-card__placeholder-tag {
  position: absolute;
  bottom: 16px;
  right: 16px;
  font-family: "DM Sans", sans-serif;
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--v3-sage);
}

/* Content panel — sits below image, padded, continuous bg with card */
.v3-aud-card__body {
  padding: 24px;
  display: flex;
  flex-direction: column;
  background: var(--v3-bg-card);
}
.v3-aud-card__label-row {
  display: flex;
  align-items: center;
  gap: 8px;
}
.v3-aud-card__label {
  font-family: "DM Sans", sans-serif;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.08em;
  color: var(--accent-deep);
}
.v3-aud-card__label-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--accent);
  display: inline-block;
  flex-shrink: 0;
}
.v3-aud-card__headline {
  font-family: "DM Sans", sans-serif;
  font-size: 18px;
  font-weight: 500;
  line-height: 1.35;
  letter-spacing: -0.01em;
  color: var(--ink);
  margin: 12px 0 0;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.v3-aud-card__link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: 16px;
  font-family: "DM Sans", sans-serif;
  font-size: 14px;
  font-weight: 500;
  color: var(--accent-deep);
}
.v3-aud-card__arrow {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  transition: transform 0.3s ease;
}
.v3-aud-card:hover .v3-aud-card__arrow {
  transform: translateX(4px);
}

/* Tablet: 4-col → 2-col (still 2 rows × 2 cards). */
@media (max-width: 1023px) {
  .v3-aud-router__grid { grid-template-columns: repeat(2, 1fr); }
}
/* Mobile: 1-col stack. */
@media (max-width: 720px) {
  .v3-aud-router__grid { grid-template-columns: 1fr; row-gap: 32px; }
  .v3-aud-card__headline { font-size: 17px; }
}

/* Buy value cards: image-card variant sized for the Buy page's 3-up grid. */
.v3-buy-value-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 24px;
  margin-top: 32px;
}

.v3-buy-value-card {
  cursor: default;
}

.v3-buy-value-card .v3-aud-card__headline {
  display: block;
  overflow: visible;
  font-size: clamp(1.25rem, 1.6vw, 1.5rem);
  line-height: 1.18;
}

.v3-aud-card__text {
  margin: 12px 0 0;
  font-size: 0.9375rem;
  line-height: 1.55;
  color: var(--ink-muted);
}

@media (max-width: 1000px) {
  .v3-buy-value-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 620px) {
  .v3-buy-value-grid { grid-template-columns: 1fr; }
}

/* ── Buy showcase ──────────────────────────────────────
   Used on /buy/. Port of v2's .call-showcase from
   /featured-property/: full-bleed dark band with a 2-col layout
   (copy + 3-item icon list + pill CTA on the left, two device-frame
   mockups on the right). v3-prefixed selectors; uses v3 tokens; no
   v2 CSS dependency. The .v3-buy-value-grid + .v3-buy-value-card
   rules above are now orphan after this section replaced the previous
   3-up image cards — left in place for now (cleanup belongs in a
   future §6 sweep). */
.v3-buy-showcase {
  background: var(--ink);
  color: var(--bg);
  padding: clamp(40px, 4vw, 64px) clamp(24px, 6vw, 88px);
  width: 100vw;
  margin-inline: calc(50% - 50vw);
  display: flex;
  flex-wrap: wrap;
  gap: clamp(32px, 4vw, 64px);
  align-items: stretch;
  justify-content: center;
  box-sizing: border-box;
}
/* Desktop: bind the section to exactly one full viewport height so
   when the user scrolls naturally and the section comes into view,
   the next section never peeks at the bottom edge. Content is
   vertically centered within each column (justify-content: center
   on .v3-buy-showcase__copy and .v3-buy-showcase__frames) so the
   title/CTA cluster on the left and the screenshot pair on the right
   sit in the middle of the viewport — well below the 96px sticky nav
   that floats over the top of the section. Tablet/mobile (<1024px)
   stays natural so content is never forced into an awkward squashed
   frame on short screens. */
@media (min-width: 1024px) {
  .v3-buy-showcase {
    min-height: 100dvh;
  }
}
.v3-buy-showcase__copy {
  flex: 1 1 480px;
  max-width: 720px;
  display: flex;
  flex-direction: column;
  /* Vertically center the title/lede/list/CTA cluster within the
     equal-height left column so the content reads as a balanced,
     intentional group regardless of viewport height. */
  justify-content: center;
  color: #fff;
}
.v3-buy-showcase__title {
  font-family: "DM Sans", sans-serif;
  font-weight: 500;
  font-size: clamp(1.5rem, 2.6vw, 2.25rem);
  line-height: 1.1;
  letter-spacing: -0.03em;
  margin: 0 0 16px;
  color: #fff;
}
.v3-buy-showcase__title .v3-serif { color: var(--v3-mint); }
.v3-buy-showcase__lede {
  font-size: clamp(0.9375rem, 1.1vw, 1.0625rem);
  line-height: 1.55;
  color: rgba(255, 255, 255, 0.72);
  margin: 0 0 16px;
  max-width: 56ch;
}
/* Container for the three .v3-card items — vertical flex stack that
   fills the available middle space between the lede paragraph above
   and the CTA button below. Each card takes flex: 1 so they grow to
   equal heights, distributing evenly from top to bottom of the copy
   column. The cards themselves still use the standard .v3-card
   primitive (pale mint-white bg, mint rule border, mint icon, centered
   title/body) — only the proportions and spacing changed for this
   placement. */
.v3-buy-showcase__list {
  list-style: none;
  padding: 0;
  /* The full copy column now uses justify-content: center to vertically
     center the title/lede/list/CTA cluster as one block — no auto
     margins needed on the list itself. Cards stay grouped at their
     natural compact heights with a small inter-card gap. */
  margin: 0;
  display: flex;
  flex-direction: column;
  flex: 0 0 auto;
  gap: 12px;
}
/* Compact natural-height cards — no flex: 1 fill, narrower max-width
   so the proportions match the short body sentence, tighter padding
   so the cards read as a unified group rather than 3 separate islands.
   Standard .v3-card primitive (mint-white bg, rule border, mint icon,
   centered icon/body) otherwise unchanged. */
.v3-buy-showcase__list .v3-card {
  padding: 14px 22px;
  gap: 10px;
  max-width: 420px;
  width: 100%;
  align-self: flex-start;
}
.v3-buy-showcase__list .v3-card__icon { font-size: 28px; }
.v3-buy-showcase__list .v3-card__body { font-size: 0.9375rem; line-height: 1.55; }
.v3-buy-showcase__cta {
  display: inline-flex;
  align-items: center;
  align-self: flex-start;
  /* Explicit margin-top instead of auto — the parent copy column now
     vertically centers the whole cluster, so the CTA just needs a
     small visible gap above it for breathing room from the cards. */
  margin-top: 16px;
  gap: 10px;
  padding: 16px 28px;
  border-radius: 999px;
  background: #fff;
  color: var(--ink);
  font-family: "DM Sans", sans-serif;
  font-weight: 500;
  font-size: 0.9375rem;
  text-decoration: none;
  transition: transform 200ms var(--ease), background 200ms var(--ease), color 200ms var(--ease);
}
.v3-buy-showcase__cta:hover {
  transform: translateY(-2px);
  background: var(--v3-mint);
  color: var(--accent-deep);
}
.v3-buy-showcase__cta svg {
  width: 18px; height: 18px;
  transition: transform 200ms var(--ease);
}
.v3-buy-showcase__cta:hover svg { transform: translateX(2px); }

.v3-buy-showcase__frames {
  flex: 1 1 480px;
  max-width: 720px;
  display: flex;
  flex-direction: column;
  /* Vertically center the two-screenshot stack within the equal-height
     right column so it visually mirrors the centered copy cluster on
     the left. Fixed 16px gap between frames — no auto distribution
     across the column (which previously created excessive empty space
     between the two screenshots when the column was tall). */
  justify-content: center;
  gap: 16px;
}
.v3-buy-showcase__frame {
  margin: 0;
  padding: 8px;
  background: linear-gradient(180deg, #2a2a2a 0%, #1a1a1a 100%);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 20px 20px 8px 8px;
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.45), inset 0 1px 0 rgba(255, 255, 255, 0.05);
  position: relative;
}
.v3-buy-showcase__frame::before {
  content: "";
  position: absolute;
  top: 5px;
  left: 50%;
  transform: translateX(-50%);
  width: 44px;
  height: 4px;
  border-radius: 2px;
  background: rgba(255, 255, 255, 0.08);
}
.v3-buy-showcase__screen {
  border-radius: 8px;
  overflow: hidden;
  background: #0a0a0a;
  /* aspect-ratio defines the screen's shape; max-height caps it so the
     two-frame stack stays compact enough for the section to fit in one
     desktop viewport (1366×768 / 1440×900 / 1440×1080). object-fit cover
     on the img preserves natural aspect — img scales to fill and crops
     overflow so neither frame is letterboxed. */
  aspect-ratio: 16 / 9;
  max-height: 220px;
}
.v3-buy-showcase__screen img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.v3-buy-showcase__frame figcaption {
  font-family: "DM Sans", sans-serif;
  font-size: 0.75rem;
  color: rgba(255, 255, 255, 0.55);
  text-align: center;
  margin-top: 6px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

/* Tablet / mobile: stack the two columns. */
@media (max-width: 900px) {
  .v3-buy-showcase {
    flex-direction: column;
    padding: 56px 32px;
    gap: 48px;
  }
  .v3-buy-showcase__copy,
  .v3-buy-showcase__frames {
    max-width: 100%;
    flex-basis: auto;
  }
}

/* ── Wynn catalyst (home) ────────────────────────────── */
/* Asymmetric vertical padding:
   - Top (5vw, 48–72px) → tighter so the marquee → eyebrow gap is small
     (companion override below top-anchors content within .v3-section--filled).
   - Bottom (4vw, 40–64px) → tighter so the Wynn → audience-router gap
     reads as a deliberate transition rather than a wide chasm. */
.v3-wynn { padding-block: clamp(48px, 5vw, 72px) clamp(40px, 4vw, 64px); }
.v3-wynn__grid {
  display: grid;
  grid-template-columns: 1.05fr 1fr;
  gap: clamp(48px, 6vw, 96px);
  /* `stretch` (grid default) so the right-side photo column matches the
     left content column's full height — top-aligned with the eyebrow,
     bottom-aligned with the last card row. Without this, the photo was
     vertically centered against the much taller cards column, leaving
     visible gaps top + bottom. */
  align-items: stretch;
}
.v3-wynn__copy .v3-h2 { margin-bottom: 16px; }
.v3-wynn__copy .v3-lede { margin-bottom: 32px; }
.v3-wynn__stats {
  display: grid;
  grid-template-columns: repeat(3, auto);
  gap: 32px clamp(24px, 4vw, 56px);
  padding: 24px 0;
  border-top: 1px solid var(--v3-rule);
  border-bottom: 1px solid var(--v3-rule);
  margin: 0 0 24px;
}
.v3-wynn__stats > div { display: flex; flex-direction: column; gap: 4px; }
.v3-wynn__stats dt { font-family: "DM Sans", sans-serif; font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-soft); margin: 0; }
.v3-wynn__stats dd { font-family: "DM Sans", sans-serif; font-size: clamp(1.0625rem, 1.4vw, 1.25rem); font-weight: 500; letter-spacing: -0.01em; color: var(--ink); margin: 0; }
.v3-wynn__map img { width: 100%; height: auto; display: block; max-width: 600px; margin-inline: auto; }

/* Wynn left column — sub-grid of 6 .v3-card items in a 2-col × 3-row
   layout. Stats fill column 1 (cards 1–3), USPs fill column 2 (cards 4–6).
   Row heights are auto = tallest card per row, with align-items: stretch
   (grid default) so paired cards in a row render at equal height — closer
   to root's bento card pattern than start-aligned cards would be. */
.v3-wynn__sub {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: repeat(3, auto);
  /* Cards arrive in source order (3 stats, then 3 USPs). With explicit
     grid-column placement and default sparse auto-flow, the placement
     cursor advances past the last stat row before USPs arrive — which
     would push USPs into implicit rows 4–6 instead of pairing with
     stats in rows 1–3. `dense` makes auto-placement backfill earlier
     empty cells, restoring the 1/2/3 row pairing. */
  grid-auto-flow: dense;
  column-gap: clamp(19px, 2.375vw, 30px);
  row-gap: clamp(19px, 2.375vw, 30px);
  margin-top: clamp(30px, 3.8vw, 46px);
  padding-top: clamp(23px, 2.85vw, 30px);
  border-top: 1px solid var(--v3-rule);
}
/* Place cards by source order: first 3 in column 1, last 3 in column 2.
   Row position is auto — with grid-template-rows: repeat(3, auto) and
   explicit grid-column on every child, items land in row 1, 2, 3 of their
   respective columns naturally (no auto-flow ambiguity since row + col
   are both unambiguous per source order). */
.v3-wynn__sub > .v3-card:nth-child(-n+3) { grid-column: 1; }
.v3-wynn__sub > .v3-card:nth-child(n+4)  { grid-column: 2; }

/* Card — port of root index.html's .bento__cell visual (light bg, mint
   rule border, rounded corners, centered icon + heading + body, hover
   lift). Token-substituted where v3 has equivalents (--v3-mint-white for
   root's --bg-alt, --v3-rule for root's --line); literal values otherwise.
   Used only inside the Wynn sub-grid. */
.v3-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 16px;
  padding: 32px;
  border-radius: 24px;
  border: 1px solid var(--v3-rule);
  background: var(--v3-mint-white);
  text-align: center;
  transition: transform 0.6s var(--ease), border-color 0.4s ease;
}
.v3-card:hover {
  transform: translateY(-4px);
  border-color: var(--accent);
}

.v3-card__icon {
  font-size: 32px;
  color: var(--accent);
}

.v3-card__title {
  font-family: "DM Sans", -apple-system, sans-serif;
  font-weight: 500;
  font-size: clamp(1.4rem, 2vw, 2rem);
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: var(--ink);
  margin: 0;
}

.v3-card__body {
  font-size: 14px;
  line-height: 1.6;
  color: var(--ink-muted);
  margin: 0;
}

/* Mobile: collapse to single column; all 6 cards flow in source order. */
@media (max-width: 700px) {
  .v3-wynn__sub {
    grid-template-columns: 1fr;
    grid-template-rows: auto;
  }
  .v3-wynn__sub > .v3-card:nth-child(n) {
    grid-column: 1;
  }
}

/* Wynn photo wrapper on desktop. With .v3-wynn__grid set to
   align-items: stretch, the wrapper takes the full row height (matching
   the left content/cards column). The previous max-height: 540px cap
   was removed — it was preventing the photo from aligning with the
   cards column bottom edge. The img inside fills the wrapper via
   height: 100% + object-fit: cover so the photo crops cleanly to
   whatever shape the row produces, without distortion. */
@media (min-width: 1024px) {
  .v3-wynn__map {
    overflow: hidden;
  }
  .v3-wynn__map img {
    width: 100%;
    height: 100%;
    max-width: none;
    object-fit: cover;
    margin-inline: 0;
  }
}
@media (max-width: 1000px) {
  .v3-wynn__grid { grid-template-columns: 1fr; }
  .v3-wynn__stats { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 540px) { .v3-wynn__stats { grid-template-columns: 1fr; gap: 16px; } }

/* ── Audience router ─────────────────────────────────── */
/* Section-level: tighter top + bottom padding so the title and the
   first row of cards land within one viewport from the marquee. The
   top is also tightened against Wynn's bottom (which is already
   clamp(40,4vw,64)) so the transition is compact, not a chasm. */
#audience {
  padding-top: clamp(28px, 3vw, 40px);
  padding-bottom: clamp(10px, 1.3vw, 20px);
}
#audience .v3-router__intro { margin-bottom: 32px; }
.v3-router {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  row-gap: 56px;
  column-gap: 24px;
  margin-top: 24px;
}
.v3-router__card {
  display: flex; flex-direction: column;
  text-decoration: none;
  border: 1px solid var(--v3-rule);
  border-radius: 16px;
  overflow: hidden;
  background: var(--bg);
  transition: transform 240ms var(--ease), border-color 240ms var(--ease), box-shadow 240ms var(--ease);
  box-shadow: 0 1px 2px rgba(0,0,0,0.03);
}
.v3-router__card:hover { transform: translateY(-4px); border-color: var(--v3-mint); box-shadow: 0 16px 36px rgba(0, 61, 46, 0.10); }
.v3-router__media { aspect-ratio: 16 / 10; overflow: hidden; }
.v3-router__media img, .v3-router__media .ph { width: 100%; height: 100%; object-fit: cover; aspect-ratio: auto; }
.v3-router__body { padding: 28px 28px 32px; flex: 1; display: flex; flex-direction: column; gap: 12px; color: var(--ink); }
.v3-router__eye { font-family: "DM Sans", sans-serif; font-size: 12px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--accent); margin: 0; }
.v3-router__card h3 { font-family: "DM Sans", sans-serif; font-size: clamp(1.3rem, 1.9vw, 1.6rem); font-weight: 500; letter-spacing: -0.02em; line-height: 1.2; margin: 0; }
.v3-router__arrow { display: inline-flex; align-items: center; gap: 6px; font-size: 14px; font-weight: 500; color: var(--v3-forest); margin-top: auto; }
.v3-router__arrow .material-symbols-outlined { font-size: 18px; transition: transform 240ms var(--ease); }
.v3-router__card:hover .v3-router__arrow .material-symbols-outlined { transform: translateX(4px); }
@media (max-width: 720px) { .v3-router { grid-template-columns: 1fr; } }

/* ── Stats ───────────────────────────────────────────── */
.v3-stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 0; border-top: 1px solid var(--v3-rule); margin-top: 32px; }
.v3-stats--3 { grid-template-columns: repeat(3, 1fr); }
.v3-stats--6 { grid-template-columns: repeat(6, 1fr); }
.v3-stats--4 { grid-template-columns: repeat(4, 1fr); }
.v3-stat { padding: 36px 28px; border-right: 1px solid var(--v3-rule); }
.v3-stat:last-child { border-right: none; }
.v3-stat__num { font-family: "DM Sans", sans-serif; font-size: clamp(2rem, 3.4vw, 3rem); font-weight: 500; letter-spacing: -0.03em; line-height: 1; color: var(--ink); margin: 0 0 12px; }
.v3-stat__label { font-size: 0.875rem; line-height: 1.45; color: var(--ink-muted); margin: 0; }
.v3-stats__caption { font-size: 13px; color: var(--ink-soft); margin: 16px 0 0; }
@media (max-width: 1100px) { .v3-stats--6 { grid-template-columns: repeat(3, 1fr); border-left: 1px solid var(--v3-rule); } .v3-stats--6 .v3-stat:nth-child(-n+3) { border-bottom: 1px solid var(--v3-rule); } }
@media (max-width: 900px) { .v3-stats, .v3-stats--4 { grid-template-columns: repeat(2, 1fr); border-left: 1px solid var(--v3-rule); } .v3-stats .v3-stat { border-bottom: 1px solid var(--v3-rule); } }
@media (max-width: 540px) { .v3-stats, .v3-stats--3, .v3-stats--4, .v3-stats--6 { grid-template-columns: 1fr; } .v3-stat { border-right: none; } }

/* ── Trust strip ─────────────────────────────────────── */
.v3-trust { display: grid; grid-template-columns: repeat(3, 1fr); gap: 32px; }
.v3-trust__cell { text-align: left; }
.v3-trust__cell .material-symbols-outlined { font-size: 36px; color: var(--accent); }
.v3-trust__cell h3 { font-family: "DM Sans", sans-serif; font-size: 1.25rem; font-weight: 500; letter-spacing: -0.015em; margin: 12px 0 8px; color: var(--ink); }
.v3-trust__cell p { font-size: 0.9375rem; line-height: 1.55; color: var(--ink-muted); margin: 0; max-width: 36ch; }
@media (max-width: 720px) { .v3-trust { grid-template-columns: 1fr; } }

/* ── Feature row (cards no tiles) ────────────────────── */
.v3-feature-row { display: grid; grid-template-columns: repeat(3, 1fr); gap: 24px; margin-top: 32px; }
.v3-feature-row--4 { grid-template-columns: repeat(4, 1fr); }
.v3-feature {
  padding: 28px 24px;
  border: 1px solid var(--v3-rule);
  border-radius: 14px;
  background: var(--bg);
  transition: transform 240ms var(--ease), border-color 240ms var(--ease);
}
.v3-feature:hover { transform: translateY(-3px); border-color: var(--v3-mint); }
.v3-feature__icon { font-size: 28px; color: var(--accent); margin-bottom: 12px; display: block; }
.v3-feature h3 { font-family: "DM Sans", sans-serif; font-size: 1.0625rem; font-weight: 500; letter-spacing: -0.01em; margin: 0 0 8px; color: var(--ink); }
.v3-feature p { font-size: 0.875rem; line-height: 1.55; color: var(--ink-muted); margin: 0; }
.v3-feature-row--off .v3-feature { background: transparent; border-style: dashed; opacity: 0.7; }
.v3-feature-row--off .v3-feature__icon { color: var(--ink-soft); }
@media (max-width: 1000px) { .v3-feature-row, .v3-feature-row--4 { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 600px) { .v3-feature-row, .v3-feature-row--4 { grid-template-columns: 1fr; } }

/* ── Numbered USPs ───────────────────────────────────── */
.v3-usps { display: grid; grid-template-columns: repeat(2, 1fr); gap: 36px 56px; margin: 32px 0; }
.v3-usp__num { display: block; font-family: "DM Sans", sans-serif; font-weight: 500; font-size: 14px; letter-spacing: 0.05em; color: var(--accent); margin-bottom: 12px; }
.v3-usp h3 { font-family: "DM Sans", sans-serif; font-size: 1.25rem; font-weight: 500; letter-spacing: -0.015em; margin: 0 0 8px; color: var(--ink); }
.v3-usp p { font-size: 0.9375rem; line-height: 1.55; color: var(--ink-muted); margin: 0; }
@media (max-width: 720px) { .v3-usps { grid-template-columns: 1fr; gap: 32px; } }

/* ── Process timeline ────────────────────────────────── */
.v3-process { display: grid; grid-template-columns: repeat(5, 1fr); gap: 0; border-top: 1px solid var(--v3-rule); margin-top: 32px; }
.v3-process--3 { grid-template-columns: repeat(3, 1fr); }
.v3-process--4 { grid-template-columns: repeat(4, 1fr); }
.v3-process--6 { grid-template-columns: repeat(6, 1fr); }
.v3-process__step { padding: 32px 24px; border-right: 1px solid var(--v3-rule); transition: background 240ms var(--ease); }
.v3-process__step:last-child { border-right: none; }
.v3-process__step:hover { background: var(--accent-subtle); }
.v3-process__num { display: block; font-family: "DM Sans", sans-serif; font-size: 13px; font-weight: 500; letter-spacing: 0.06em; color: var(--accent); margin-bottom: 16px; }
.v3-process__step h3 { font-family: "DM Sans", sans-serif; font-size: 1.0625rem; font-weight: 500; letter-spacing: -0.01em; line-height: 1.3; margin: 0 0 8px; color: var(--ink); }
.v3-process__step p { font-size: 0.875rem; line-height: 1.5; color: var(--ink-muted); margin: 0; }
@media (max-width: 1100px) { .v3-process { grid-template-columns: repeat(2, 1fr); border-left: 1px solid var(--v3-rule); } .v3-process--6 { grid-template-columns: repeat(3, 1fr); border-left: 1px solid var(--v3-rule); } .v3-process__step { border-bottom: 1px solid var(--v3-rule); } }
@media (max-width: 600px) { .v3-process, .v3-process--3, .v3-process--4, .v3-process--6 { grid-template-columns: 1fr; } }

/* ── FAQ ─────────────────────────────────────────────── */
.v3-faq { border-top: 1px solid var(--v3-rule); margin-top: 24px; max-width: 760px; }
.v3-faq__item { border-bottom: 1px solid var(--v3-rule); padding: 24px 0; }
.v3-faq__q { font-family: "DM Sans", sans-serif; font-size: 1.0625rem; font-weight: 500; letter-spacing: -0.01em; color: var(--ink); cursor: pointer; list-style: none; display: flex; justify-content: space-between; align-items: center; gap: 16px; }
.v3-faq__q::-webkit-details-marker { display: none; }
.v3-faq__q::marker { content: ""; }
.v3-faq__q::after { content: "+"; font-size: 22px; color: var(--accent); transition: transform 200ms var(--ease); }
.v3-faq__item[open] .v3-faq__q::after { content: "−"; }
.v3-faq__a { font-size: 0.9375rem; line-height: 1.6; color: var(--ink-muted); margin: 16px 0 0; max-width: 65ch; }

/* ── Tables ──────────────────────────────────────────── */
.v3-table { width: 100%; border-collapse: collapse; margin-top: 24px; font-size: 0.9375rem; }
.v3-table thead { background: var(--v3-mint-white); }
.v3-table th, .v3-table td { padding: 16px 18px; text-align: left; border-bottom: 1px solid var(--v3-rule); }
.v3-table th { font-family: "DM Sans", sans-serif; font-weight: 500; font-size: 12px; letter-spacing: 0.05em; text-transform: uppercase; color: var(--ink-soft); }
.v3-table td { color: var(--ink); }
.v3-table--compare td:first-child { font-weight: 500; color: var(--ink-soft); }
.v3-table__note { font-size: 13px; color: var(--ink-soft); margin-top: 12px; }

/* ── Pills + badges ──────────────────────────────────── */
.v3-pill { display: inline-flex; align-items: center; gap: 6px; padding: 6px 12px; border-radius: 999px; font-size: 13px; font-weight: 500; }
.v3-pill--ok { background: var(--accent-subtle); color: var(--v3-forest); }
.v3-pill--ghost { background: transparent; color: var(--ink); border: 1px solid var(--v3-rule); }
.v3-pill-list { display: flex; flex-wrap: wrap; gap: 8px; padding: 0; margin: 12px 0 0; list-style: none; }

/* ── Plot grid + filters ─────────────────────────────── */
/* Pill-shaped filter bar — port of /featured-property/'s .filters
   visual language (rounded outer container, segmented filter cells with
   icon + label-on-top + select-below, vertical rules between cells,
   custom dropdown caret via ::after). v3-prefixed selectors; uses v3
   tokens; sized for the v3 Buy inventory section, not the v2 default. */
.v3-fp-filters {
  display: flex;
  align-items: stretch;
  background: var(--v3-mint-white);
  border: 1px solid var(--v3-rule);
  border-radius: 999px;
  padding: 4px;
  margin: 12px 0 8px;
}
.v3-fp-filter {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 14px;
  border-right: 1px solid var(--v3-rule);
  position: relative;
  min-width: 0;
}
.v3-fp-filter:last-child { border-right: none; }
.v3-fp-filter .material-symbols-outlined {
  font-size: 20px;
  color: var(--ink-soft);
  flex-shrink: 0;
}
.v3-fp-filter__body {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-width: 0;
  position: relative;
}
.v3-fp-filter__label {
  font-family: "DM Sans", sans-serif;
  font-size: 11px;
  font-weight: 500;
  color: var(--ink);
  letter-spacing: 0.04em;
  text-transform: none;
}
.v3-fp-filter select {
  appearance: none;
  -webkit-appearance: none;
  background: transparent;
  border: none;
  padding: 2px 16px 0 0;
  font-family: "DM Sans", sans-serif;
  font-size: 13px;
  color: var(--ink-muted);
  cursor: pointer;
  width: 100%;
  outline: none;
  transition: color 200ms var(--ease);
}
.v3-fp-filter select:focus,
.v3-fp-filter select:hover { color: var(--ink); }
.v3-fp-filter__body::after {
  content: "";
  position: absolute;
  right: 0;
  bottom: 8px;
  border-left: 4px solid transparent;
  border-right: 4px solid transparent;
  border-top: 4px solid var(--ink-muted);
  pointer-events: none;
}
.v3-filters__count { font-size: 13px; color: var(--ink-soft); margin: 0 0 10px; }
@media (max-width: 1023px) {
  .v3-fp-filters {
    border-radius: 16px;
    flex-wrap: wrap;
    padding: 8px;
  }
  .v3-fp-filter {
    flex: 1 1 calc(50% - 1px);
    border-right: 1px solid var(--v3-rule);
    border-bottom: 1px solid var(--v3-rule);
  }
  .v3-fp-filter:nth-child(2n) { border-right: none; }
  .v3-fp-filter:nth-last-child(-n+2) { border-bottom: none; }
}
@media (max-width: 600px) {
  .v3-fp-filter {
    flex: 1 1 100%;
    border-right: none;
  }
  .v3-fp-filter:not(:last-child) { border-bottom: 1px solid var(--v3-rule); }
}

/* Inventory card grid — sized so the first 6 cards (3 cols × 2 rows)
   fit within a 1080px desktop viewport. Card height was compacted via
   flatter media aspect (16/9), tighter body padding, and tighter
   internal margins; grid gap and surrounding rhythm (filter margin,
   count margin, more-button margin) compressed in tandem. The
   "See more lands" expand still reveals the full 27-card pool. */
.v3-plots { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
/* Centered "See more lands" button container — appears below the plot
   grid, hidden by default until JS detects more matches than the
   initial 6-card cap. */
.v3-plots__more { display: flex; justify-content: center; margin-top: 24px; }
.v3-plot { border: 1px solid var(--v3-rule); border-radius: 14px; overflow: hidden; background: var(--bg); transition: transform 240ms var(--ease), border-color 240ms var(--ease), box-shadow 240ms var(--ease); box-shadow: 0 1px 2px rgba(0,0,0,0.03); }
.v3-plot:hover { transform: translateY(-4px); border-color: var(--v3-mint); box-shadow: 0 12px 28px rgba(0,0,0,0.08); }
.v3-plot__link { display: block; text-decoration: none; color: inherit; }
.v3-plot__media { aspect-ratio: 2 / 1; overflow: hidden; }
.v3-plot__media .ph, .v3-plot__media img { width: 100%; height: 100%; object-fit: cover; aspect-ratio: auto; }
/* Mobile-only object-position shift for /buy/ plot-card images.
   Source images are 2172×724 (≈3:1) but the mobile card frame is 2:1
   (the desktop `aspect-ratio: 16/5` override at line ~970 only applies
   ≥1024 px), so `object-fit: cover` with the default `50% 50%` position
   crops ~17% off each horizontal side — and the left-side text labels
   embedded in some plot illustrations live in that leftmost band, so
   they were getting cropped off-screen. Anchor the image's left edge
   to the frame's left edge on mobile so the leftmost 2/3 of the source
   is visible (the right ~33% of the source crops instead). Scoped to
   `.v3-plot__media` which only exists on /buy/ — no other page or
   selector is affected. Desktop is untouched. */
@media (max-width: 768px) {
  .v3-plot__media .ph,
  .v3-plot__media img {
    object-position: left center;
  }
}
/* Al Nakheel area photo: anchor the bottom of the source so the
   skyline + coastline stay in frame instead of the empty sky above. */
.v3-plot__media img[src*="Al Nakheel"] { object-position: center bottom; }
/* Seeh Al Bana area photo: anchor the top so the building tops
   stay in frame instead of the reflective water below. */
.v3-plot__media img[src*="Seeh Al Bana"] { object-position: center top; }
.v3-plot__body { padding: 10px 14px 12px; }
.v3-plot__row { display: flex; justify-content: space-between; align-items: center; gap: 12px; margin-bottom: 4px; }
.v3-plot__loc { font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--accent); margin: 0; font-family: "DM Sans", sans-serif; font-weight: 500; }
.v3-plot__title { font-family: "DM Sans", sans-serif; font-size: 0.9375rem; font-weight: 500; letter-spacing: -0.01em; line-height: 1.25; margin: 0 0 3px; color: var(--ink); }
.v3-plot__meta { font-size: 0.75rem; color: var(--ink-soft); margin: 0 0 3px; letter-spacing: 0.01em; }
.v3-plot__price { font-size: 0.875rem; color: var(--ink-muted); margin: 0 0 6px; }
.v3-plot__price strong { font-family: "DM Sans", sans-serif; font-weight: 500; color: var(--ink); font-size: 1rem; }
.v3-plot__cta { display: inline-flex; align-items: center; gap: 4px; font-size: 12px; font-weight: 500; color: var(--v3-forest); }
.v3-plot__cta .material-symbols-outlined { font-size: 16px; transition: transform 240ms var(--ease); }
.v3-plot:hover .v3-plot__cta .material-symbols-outlined { transform: translateX(3px); }
.v3-plot__status { padding: 4px 10px; border-radius: 999px; font-size: 11px; letter-spacing: 0.05em; font-weight: 500; text-transform: uppercase; }
.v3-plot__status--available { background: var(--accent-subtle); color: var(--v3-forest); }
.v3-plot__status--under-offer { background: rgba(214, 158, 46, 0.15); color: #855a06; }
.v3-plot__status--reserved { background: rgba(0,0,0,0.08); color: var(--ink-soft); }
.v3-plot__status--open { background: var(--accent-subtle); color: var(--v3-forest); }
.v3-plot__status--funded { background: rgba(0,0,0,0.08); color: var(--ink-soft); }
.v3-plot__status--closed { background: rgba(0,0,0,0.08); color: var(--ink-soft); }
@media (max-width: 1000px) { .v3-plots { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 600px) { .v3-plots { grid-template-columns: 1fr; } }

/* Inventory section padding override — tightened so the 6-card grid
   plus heading and filter fit within a desktop viewport without the
   bottom row of cards being clipped. Scoped to #inventory so other
   .v3-section--alt sections keep their default vertical rhythm. */
#inventory.v3-section { padding-block: clamp(20px, 2.5vh, 32px); }
#inventory .v3-eyebrow { margin-bottom: 10px; }
#inventory .v3-h2 { font-size: clamp(1.5rem, 2.6vw, 2.125rem); margin-bottom: 14px; }

/* Inventory: stable section height regardless of filter result count.
   The eyebrow/title/filters/count anchor to the top, plot grid sits
   beneath them, and the section bottom stays at the same Y position
   whether the filter yields 1 or 27 matches — so scroll position and
   the section below don't shift as filters change. */
#inventory.v3-frame {
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  min-height: 100svh;
  min-height: 100dvh;
  box-sizing: border-box;
}
#inventory.v3-frame > .v3-section__inner {
  flex: 0 0 auto;
  width: 100%;
}

.v3-empty { text-align: center; padding: 64px 24px; }
.v3-empty p { color: var(--ink-muted); margin-bottom: 24px; max-width: 40ch; margin-inline: auto; }

/* ── Plot detail ─────────────────────────────────────── */
.v3-plot-detail__cta-line { font-family: "DM Sans", sans-serif; font-size: 1rem; color: var(--v3-mint); margin: 0 0 12px; font-weight: 500; }
.v3-plot-detail__price { font-family: "DM Sans", sans-serif; font-size: 1.5rem; font-weight: 500; letter-spacing: -0.02em; color: rgba(255,255,255,0.95); margin: 16px 0 8px; }
.v3-plot-detail__price strong { font-size: 1.875rem; }
.v3-plot-detail__status { margin: 0 0 16px; }

.v3-keyfacts { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0; border-top: 1px solid var(--v3-rule); border-left: 1px solid var(--v3-rule); margin-top: 32px; }
.v3-keyfact { padding: 28px 24px; border-right: 1px solid var(--v3-rule); border-bottom: 1px solid var(--v3-rule); }
.v3-keyfact .material-symbols-outlined { font-size: 24px; color: var(--accent); margin-bottom: 12px; display: block; }
.v3-keyfact dt { font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-soft); margin-bottom: 4px; }
.v3-keyfact dd { font-family: "DM Sans", sans-serif; font-size: 1.125rem; font-weight: 500; color: var(--ink); margin: 0; }
@media (max-width: 720px) { .v3-keyfacts { grid-template-columns: 1fr; } }

.v3-distances { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 16px; }
/* Phase 3 G2: cap the 16:9 map container so a single section's
   Location block fits one viewport on desktop. At 1376px-wide inner
   uncapped, 16:9 → 774px tall (cropped the section). At 960px max-width,
   16:9 → 540px tall (fits). */
.v3-map { aspect-ratio: 16/9; overflow: hidden; border-radius: 12px; margin-top: 24px; max-width: 960px; margin-inline: auto; }
.v3-map .ph { width: 100%; height: 100%; aspect-ratio: auto; }

/* Phase 3 G2: cap the ROI screenshot container. At 1376px-wide inner
   uncapped + image aspect ~2.027, height was ~679px (cropped the section).
   At 960px max-width, height ≈ 474px (fits). */
.v3-roi-snap { margin-top: 24px; border-radius: 12px; overflow: hidden; border: 1px solid var(--v3-rule); max-width: 960px; margin-inline: auto; }
.v3-roi-snap img { width: 100%; height: auto; display: block; }

/* ── Models (invest) ─────────────────────────────────── */
.v3-models { display: grid; grid-template-columns: repeat(3, 1fr); gap: 24px; margin-top: 32px; align-items: stretch; }
.v3-model {
  display: grid;
  grid-template-rows: minmax(220px, 1fr) minmax(220px, 1fr);
  min-height: 520px;
  overflow: hidden;
  border: 1px solid var(--v3-rule);
  border-radius: 24px;
  text-decoration: none;
  color: inherit;
  background: var(--v3-mint-white);
  transition: transform 240ms var(--ease), border-color 240ms var(--ease), box-shadow 240ms var(--ease);
}
.v3-model:hover { transform: translateY(-4px); border-color: var(--v3-mint); box-shadow: 0 12px 28px rgba(0,0,0,0.06); }
.v3-model__illu {
  display: grid;
  place-items: center;
  min-height: 0;
  padding: clamp(28px, 4vw, 48px);
  border-bottom: 1px solid var(--v3-rule);
}
.v3-model__illu img { width: min(72%, 240px); height: min(72%, 240px); object-fit: contain; }
.v3-model__content {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: space-between;
  gap: 14px;
  padding: clamp(24px, 2.8vw, 34px);
  background: var(--bg);
}
.v3-model__label {
  font-family: "DM Sans", sans-serif;
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent);
}
.v3-model h3 { font-family: "DM Sans", sans-serif; font-size: clamp(1.35rem, 1.8vw, 1.75rem); font-weight: 500; line-height: 1.12; letter-spacing: -0.025em; margin: 0; color: var(--ink); }
.v3-model p { font-size: 0.9375rem; line-height: 1.55; color: var(--ink-muted); margin: 0; }
.v3-model__cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 44px;
  margin-top: auto;
  padding: 0 18px;
  border: 1px solid var(--v3-rule);
  border-radius: 999px;
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--v3-forest);
  background: var(--v3-mint-white);
}
.v3-model__cta .material-symbols-outlined { font-size: 18px; transition: transform 240ms var(--ease); }
/* Inline WhatsApp logo inside the model CTA — sized to match the
   material-symbols icon used elsewhere in this CTA pattern. */
.v3-model__cta-icon { width: 16px; height: 16px; flex-shrink: 0; }
.v3-model:hover .v3-model__cta { border-color: var(--v3-mint); }
.v3-model:hover .v3-model__cta .material-symbols-outlined { transform: translateX(3px); }
@media (max-width: 1000px) {
  .v3-models { grid-template-columns: 1fr; }
  .v3-model { grid-template-rows: minmax(180px, auto) auto; min-height: 0; }
}

/* ── Deals grid ──────────────────────────────────────── */
.v3-deal-filters { display: flex; gap: 16px; flex-wrap: wrap; margin: 24px 0; }
.v3-deal-filters .v3-filter { border: 1px solid var(--v3-rule); border-radius: 8px; }
.v3-deals { display: grid; grid-template-columns: repeat(3, 1fr); gap: 24px; margin-top: 24px; }
.v3-deal { border: 1px solid var(--v3-rule); border-radius: 14px; overflow: hidden; background: var(--bg); transition: transform 240ms var(--ease), border-color 240ms var(--ease), box-shadow 240ms var(--ease); }
.v3-deal:hover { transform: translateY(-4px); border-color: var(--v3-mint); box-shadow: 0 12px 28px rgba(0,0,0,0.08); }
.v3-deal__link { display: block; text-decoration: none; color: inherit; }
.v3-deal__media { aspect-ratio: 16 / 10; overflow: hidden; }
.v3-deal__media .ph { width: 100%; height: 100%; aspect-ratio: auto; }
.v3-deal__body { padding: 20px 22px 24px; }
.v3-deal__model { font-family: "DM Sans", sans-serif; font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--accent); font-weight: 500; }
.v3-deal__title { font-family: "DM Sans", sans-serif; font-size: 1.125rem; font-weight: 500; letter-spacing: -0.01em; margin: 8px 0 16px; color: var(--ink); }
.v3-deal__stats { display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px 16px; margin: 0 0 14px; }
.v3-deal__stats > div { display: flex; flex-direction: column; gap: 2px; margin: 0; }
.v3-deal__stats dt { font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-soft); margin: 0; }
.v3-deal__stats dd { font-size: 0.9375rem; font-weight: 500; color: var(--ink); margin: 0; }
@media (max-width: 1000px) { .v3-deals { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 600px) { .v3-deals { grid-template-columns: 1fr; } }

.v3-progress { width: 100%; height: 6px; background: var(--v3-mint-white); border-radius: 999px; margin: 24px 0 8px; overflow: hidden; }
.v3-progress__bar { height: 100%; background: var(--accent); border-radius: 999px; }

/* ── Credentials (about) ─────────────────────────────── */
.v3-credentials { display: grid; grid-template-columns: repeat(2, 1fr); gap: 16px; margin-top: 32px; }
.v3-cred { padding: 28px 24px; border: 1px solid var(--v3-rule); border-radius: 12px; background: var(--bg); }
.v3-cred .material-symbols-outlined { font-size: 28px; color: var(--accent); margin-bottom: 12px; display: block; }
.v3-cred h3 { font-family: "DM Sans", sans-serif; font-size: 1.125rem; font-weight: 500; margin: 0 0 6px; color: var(--ink); }
.v3-cred p { font-size: 0.9375rem; line-height: 1.55; color: var(--ink-muted); margin: 0; }
.v3-cred-visual { aspect-ratio: 16/9; margin-top: 32px; border-radius: 12px; overflow: hidden; }
.v3-cred-visual .ph { width: 100%; height: 100%; aspect-ratio: auto; }
@media (max-width: 720px) { .v3-credentials { grid-template-columns: 1fr; } }

/* ── Two-column do/don't (about) ─────────────────────── */
.v3-twocol { display: grid; grid-template-columns: repeat(2, 1fr); gap: 32px; margin-top: 32px; }
.v3-twocol__h { font-family: "DM Sans", sans-serif; font-size: 1.25rem; font-weight: 500; letter-spacing: -0.015em; margin: 0 0 16px; color: var(--ink); }
.v3-twocol__list { list-style: none; padding: 0; margin: 0; display: grid; gap: 12px; }
.v3-twocol__list li { display: flex; gap: 12px; align-items: center; font-size: 0.9375rem; color: var(--ink); }
.v3-twocol__list .material-symbols-outlined { font-size: 22px; color: var(--accent); flex-shrink: 0; }
.v3-twocol__col--off .v3-twocol__list .material-symbols-outlined { color: var(--ink-soft); }
@media (max-width: 720px) { .v3-twocol { grid-template-columns: 1fr; } }

/* ── Quotes (track-record) ───────────────────────────── */
.v3-quotes { display: grid; grid-template-columns: repeat(3, 1fr); gap: 24px; margin-top: 32px; }
.v3-quote { padding: 28px 24px; border-left: 3px solid var(--accent); background: var(--v3-mint-white); margin: 0; border-radius: 0 12px 12px 0; }
.v3-quote p { font-size: 1.0625rem; line-height: 1.55; color: var(--ink); margin: 0 0 16px; font-style: italic; }
.v3-quote footer { font-size: 14px; color: var(--ink-soft); }
.v3-quote footer strong { display: block; font-weight: 500; color: var(--ink); font-style: normal; }
@media (max-width: 1000px) { .v3-quotes { grid-template-columns: 1fr; } }

/* ── RAK map (insights) ──────────────────────────────── */
.v3-rakmap { aspect-ratio: 16/9; max-width: 1100px; margin: 32px auto 0; border-radius: 16px; overflow: hidden; }
.v3-rakmap img { width: 100%; height: 100%; object-fit: contain; display: block; }

/* ── Illustration containers ─────────────────────────── */
.v3-illu { max-width: 800px; margin: 24px auto; }
.v3-illu img { width: 100%; height: auto; display: block; }
/* Phase 3 G2: tighter cap for the JV-simulator screenshot variant.
   jv-simulator.png aspect ≈ 1.422; at .v3-illu's 800px parent cap, the
   screenshot rendered ~562px tall, overflowing the Returns-profile
   section. At 600px max-width → ~422px tall (fits). */
.v3-illu--simulator { border: 1px solid var(--v3-rule); border-radius: 12px; overflow: hidden; max-width: 600px; }

/* ── Split (sell valuation methodology) ──────────────── */
.v3-split { display: grid; grid-template-columns: 1fr 1fr; gap: 56px; align-items: center; margin-top: 32px; }
.v3-split__visual img { width: 100%; height: auto; }
@media (max-width: 1000px) { .v3-split { grid-template-columns: 1fr; gap: 40px; } }

/* ── Nadim representative card (sell only) ───────────── */
.v3-rep { display: grid; grid-template-columns: 280px 1fr; gap: 40px; align-items: center; margin-top: 32px; padding: 32px; border: 1px solid var(--v3-rule); border-radius: 16px; background: var(--v3-mint-white); }
.v3-rep__photo { width: 100%; aspect-ratio: 1; border-radius: 50%; overflow: hidden; }
.v3-rep__photo img { width: 100%; height: 100%; object-fit: cover; }
.v3-rep__copy h3 { font-family: "DM Sans", sans-serif; font-size: 1.5rem; font-weight: 500; letter-spacing: -0.02em; margin: 0 0 4px; color: var(--ink); }
.v3-rep__role { font-size: 0.9375rem; color: var(--accent); margin: 0 0 16px; font-weight: 500; }
.v3-rep__copy p { font-size: 1rem; line-height: 1.55; color: var(--ink-muted); margin: 0 0 20px; }
@media (max-width: 720px) { .v3-rep { grid-template-columns: 1fr; text-align: center; padding: 24px; } .v3-rep__photo { max-width: 200px; margin: 0 auto; } }

/* ── Fees ────────────────────────────────────────────── */
.v3-fees { display: grid; grid-template-columns: repeat(2, 1fr); gap: 24px; margin-top: 32px; }
.v3-fee { padding: 32px 28px; border: 1px solid var(--v3-rule); border-radius: 16px; background: var(--bg); }
.v3-fee h3 { font-family: "DM Sans", sans-serif; font-size: 1.25rem; font-weight: 500; margin: 0 0 8px; color: var(--ink); }
.v3-fee__rate { font-family: "DM Sans", sans-serif; font-size: 3rem; font-weight: 500; letter-spacing: -0.04em; color: var(--accent); margin: 0 0 24px; line-height: 1; }
.v3-fee ul { list-style: none; padding: 0; margin: 0; display: grid; gap: 8px; }
.v3-fee li { font-size: 0.9375rem; color: var(--ink); display: flex; gap: 8px; align-items: baseline; }
.v3-fee li::before { content: "·"; color: var(--accent); }
@media (max-width: 720px) { .v3-fees { grid-template-columns: 1fr; } }

/* ── Eval form ───────────────────────────────────────── */
.v3-eval { display: grid; grid-template-columns: repeat(2, 1fr); gap: 20px 24px; margin-top: 32px; }
.v3-eval__field { display: flex; flex-direction: column; gap: 6px; }
.v3-eval__field--full { grid-column: 1 / -1; }
.v3-eval__label { font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-soft); }
.v3-eval__field input, .v3-eval__field select, .v3-eval__field textarea {
  border: none; border-bottom: 1px solid var(--v3-rule); background: transparent;
  font-family: inherit; font-size: 1rem; color: var(--ink); padding: 8px 0; width: 100%;
}
.v3-eval__field textarea { min-height: 96px; resize: vertical; }
.v3-eval__field input:focus, .v3-eval__field select:focus, .v3-eval__field textarea:focus {
  outline: none; border-bottom-color: var(--accent);
}
.v3-eval__submit { grid-column: 1 / -1; margin-top: 16px; justify-self: start; }
/* Note rendered alongside the submit button on the broker scheduling
   form — clarifies what happens on submit (frontend-only handoff to
   WhatsApp; A2A signing + call confirmation are manual on the
   resulting WhatsApp thread, not auto-scheduled by the page). */
.v3-eval__note {
  grid-column: 1 / -1;
  margin: 12px 0 0;
  font-size: 0.875rem;
  line-height: 1.55;
  color: var(--ink-muted);
  max-width: 56ch;
}
@media (max-width: 700px) { .v3-eval { grid-template-columns: 1fr; } }

/* ── Partners (invest model) ─────────────────────────── */
.v3-partners { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; margin-top: 32px; }
.v3-partner { padding: 24px; border: 1px solid var(--v3-rule); border-radius: 12px; }
.v3-partner h3 { font-family: "DM Sans", sans-serif; font-size: 1.0625rem; font-weight: 500; margin: 0 0 8px; color: var(--ink); }
.v3-partner p { font-size: 0.9375rem; line-height: 1.55; color: var(--ink-muted); margin: 0; }
@media (max-width: 1000px) { .v3-partners { grid-template-columns: 1fr; } }

/* Standard non-image cards: mirror the home USP .v3-card treatment. */
.v3-stats,
.v3-process,
.v3-keyfacts {
  gap: 24px;
  border: 0;
}

.v3-card,
.v3-stat,
.v3-trust__cell,
.v3-feature,
.v3-usp,
.v3-process__step,
.v3-keyfact,
.v3-cred,
.v3-fee,
.v3-partner {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 16px;
  padding: 32px;
  border: 1px solid var(--v3-rule);
  border-radius: 24px;
  background: var(--v3-mint-white);
  text-align: center;
  transition: transform 0.6s var(--ease), border-color 0.4s ease;
}

.v3-card:hover,
.v3-stat:hover,
.v3-trust__cell:hover,
.v3-feature:hover,
.v3-usp:hover,
.v3-process__step:hover,
.v3-keyfact:hover,
.v3-cred:hover,
.v3-fee:hover,
.v3-partner:hover {
  transform: translateY(-4px);
  border-color: var(--accent);
  background: var(--v3-mint-white);
}

.v3-stat:last-child,
.v3-process__step:last-child,
.v3-feature-row--off .v3-feature {
  border: 1px solid var(--v3-rule);
}

.v3-feature-row--off .v3-feature {
  background: var(--v3-mint-white);
  border-style: solid;
  opacity: 1;
}

/* Home Wynn cards: scoped ~5% packing pass, preserving the shared card design. */
.v3-wynn .v3-card {
  gap: 15px;
  padding: 30px;
}

.v3-wynn .v3-card__icon {
  font-size: 30px;
}

.v3-feature-row--off .v3-feature__icon {
  color: var(--accent);
}

.v3-trust__cell .material-symbols-outlined,
.v3-feature__icon,
.v3-keyfact .material-symbols-outlined,
.v3-cred .material-symbols-outlined {
  display: block;
  margin: 0;
  font-size: 32px;
  color: var(--accent);
}

.v3-process__num,
.v3-usp__num {
  margin: 0;
  color: var(--accent);
}

.v3-feature h3,
.v3-usp h3,
.v3-process__step h3,
.v3-cred h3,
.v3-fee h3,
.v3-partner h3,
.v3-trust__cell h3 {
  font-family: "DM Sans", sans-serif;
  font-size: clamp(1.4rem, 2vw, 2rem);
  font-weight: 500;
  line-height: 1.1;
  letter-spacing: -0.02em;
  margin: 0;
  color: var(--ink);
}

.v3-feature p,
.v3-usp p,
.v3-process__step p,
.v3-cred p,
.v3-partner p,
.v3-trust__cell p,
.v3-stat__label {
  margin: 0;
  font-size: 0.9375rem;
  line-height: 1.6;
  color: var(--ink-muted);
}

/* Invest intro cards: distribute the icon, title, and supporting copy
   across the card height instead of grouping them tightly at center. */
.v3-frame-group--invest-intro .v3-feature {
  justify-content: space-evenly;
  gap: clamp(18px, 4vh, 44px);
}

.v3-frame-group--invest-intro .v3-feature h3,
.v3-frame-group--invest-intro .v3-feature p {
  max-width: 34ch;
}

.v3-trust__cell p {
  margin-inline: auto;
}

.v3-stat__num,
.v3-keyfact dd,
.v3-fee__rate {
  margin: 0;
}

.v3-keyfact dt {
  margin: 0;
}

.v3-fee ul {
  justify-items: center;
}

.v3-fee li {
  justify-content: center;
  text-align: center;
}

/* ── Terms list (broker agreement) ───────────────────── */
.v3-terms { padding: 0; margin: 32px 0; counter-reset: terms; max-width: 760px; }
.v3-terms li { list-style: none; padding: 28px 0 28px 56px; border-bottom: 1px solid var(--v3-rule); position: relative; counter-increment: terms; }
.v3-terms li::before { content: counter(terms, decimal-leading-zero); position: absolute; left: 0; top: 28px; font-family: "DM Sans", sans-serif; font-size: 14px; font-weight: 500; color: var(--accent); letter-spacing: 0.05em; }
.v3-terms h3 { font-family: "DM Sans", sans-serif; font-size: 1.125rem; font-weight: 500; letter-spacing: -0.01em; margin: 0 0 8px; color: var(--ink); }
.v3-terms p { font-size: 0.9375rem; line-height: 1.6; color: var(--ink-muted); margin: 0; max-width: 60ch; }

/* ── Doc mockup (broker agreement) ───────────────────── */
/* Phase 3 G2: tightened from 480px → 360px. doc-mockup.svg viewBox is
   240×320 (aspect 0.75 portrait); at 480px wide → 640px tall, which
   overflowed the Sample-A2A section. At 360px wide → 480px tall (fits). */
.v3-doc-mock { max-width: 360px; margin: 24px auto; }
.v3-doc-mock img { width: 100%; height: auto; }

/* ── Deck walkthrough (broker) ───────────────────────── */
.v3-deck-walk { display: grid; grid-template-columns: repeat(2, 1fr); gap: 32px; margin-top: 32px; }
.v3-deck-walk__step img { width: 100%; height: auto; border: 1px solid var(--v3-rule); border-radius: 12px; }
.v3-deck-walk__step p { font-size: 0.9375rem; line-height: 1.55; color: var(--ink-muted); margin: 12px 0 0; }
@media (max-width: 720px) { .v3-deck-walk { grid-template-columns: 1fr; } }

/* ── PlaceholderImage component ──────────────────────── */
.ph {
  width: 100%; height: auto;
  background: var(--v3-mint-white);
  border: 2px dashed var(--accent);
  border-radius: 8px;
  position: relative;
  display: flex; align-items: center; justify-content: center;
  color: var(--v3-forest);
}
.ph__inner { display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 24px; text-align: center; }
.ph__label { font-family: "DM Sans", sans-serif; font-size: 0.9375rem; font-weight: 500; letter-spacing: -0.01em; color: var(--v3-forest); }
.ph__dim { font-family: "DM Sans", sans-serif; font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--v3-sage); position: absolute; bottom: 12px; right: 12px; }
.ph--category[data-category="residential"]        { background: linear-gradient(135deg, #E8F4ED 0%, #D5EADE 100%); }
.ph--category[data-category="commercial"]         { background: linear-gradient(135deg, #EAF1F4 0%, #D5E2EA 100%); }
.ph--category[data-category="hospitality"]        { background: linear-gradient(135deg, #F0E8DC 0%, #E2D5C2 100%); }
.ph--category[data-category="mixed-use"]          { background: linear-gradient(135deg, #F0EDDC 0%, #E2DEC2 100%); }
.ph--category[data-category="industrial"]         { background: linear-gradient(135deg, #ECECEC 0%, #DADADA 100%); }
.ph--category[data-category="branded-residential"]{ background: linear-gradient(135deg, #F0DCE8 0%, #E2C2D5 100%); }

/* ── Placeholder flag ────────────────────────────────── */
.v3-flag { display: inline-block; padding: 2px 8px; margin-left: 4px; background: rgba(214, 158, 46, 0.18); color: #855a06; font-size: 11px; letter-spacing: 0.04em; border-radius: 4px; font-weight: 500; vertical-align: baseline; }

/* ── Anchor offset for fixed nav ─────────────────────── */
.v3-section[id], section[id] { scroll-margin-top: 96px; }

/* / home - FAQ + Latest News split. FAQ remains the left-column
   accordion; news cards sit to the right with compact image areas. */
.home-insights__inner {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(360px, 0.95fr);
  gap: clamp(40px, 5vw, 84px);
  align-items: center;
}

.home-insights__faq { min-width: 0; }

.home-insights__faq .section__title {
  max-width: 620px;
  margin-inline: auto;
  text-align: center;
}

.home-insights__faq .faq__list { max-width: 760px; }

.home-insights__news {
  min-width: 0;
  text-align: left;
}

.home-insights__news-title {
  margin: 0 0 20px;
  font-family: "DM Sans", -apple-system, sans-serif;
  font-size: clamp(1.5rem, 2vw, 2rem);
  font-weight: 500;
  line-height: 1.15;
  letter-spacing: -0.02em;
  color: var(--ink);
  text-transform: none;
}

.home-insights__cards {
  display: grid;
  gap: 14px;
}

.home-insights__card {
  display: grid;
  grid-template-columns: minmax(132px, 0.42fr) minmax(0, 1fr);
  overflow: hidden;
  min-height: 132px;
  border: 1px solid var(--v3-rule);
  border-radius: 24px;
  background: var(--v3-mint-white);
  /* Card is now an <a> element; reset link defaults so the card
     reads as a card and not as underlined blue text. */
  text-decoration: none;
  color: inherit;
  transition: transform 0.6s var(--ease), border-color 0.4s ease;
}

.home-insights__card:hover {
  transform: translateY(-4px);
  border-color: var(--accent);
}

/* Small uppercase source label inside each Latest News card body
   (e.g. "Wynn Al Marjan Island", "Wynn Resorts", "Colliers") so the
   reader can place the article's authority before reading the title. */
.home-insights__source {
  display: block;
  font-family: "DM Sans", -apple-system, sans-serif;
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent);
}

.home-insights__media {
  min-height: 100%;
  background: rgba(0, 61, 46, 0.06);
}

.home-insights__media img {
  display: block;
  width: 100%;
  height: 100%;
  min-height: 132px;
  object-fit: cover;
}

.home-insights__card-body {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 8px;
  padding: clamp(18px, 2vw, 24px);
}

.home-insights__card-body h3 {
  margin: 0;
  font-family: "DM Sans", -apple-system, sans-serif;
  font-size: clamp(1.0625rem, 1.3vw, 1.25rem);
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: -0.015em;
  color: var(--ink);
  text-transform: none;
}

.home-insights__card-body p {
  margin: 0;
  font-size: 0.9375rem;
  line-height: 1.55;
  color: var(--ink-muted);
}

/* (.home-insights__button rule removed — the "See latest news"
   button under the third article card was deleted from the markup.
   Each .home-insights__card is now itself a clickable <a>, so a
   separate section-CTA is no longer needed.) */

@media (min-width: 1101px) {
  .home-insights.section.v3-frame {
    padding-block: clamp(17px, 2.3vh, 27px);
  }

  .home-insights__inner {
    min-height: calc(100dvh - clamp(36px, 5vh, 56px));
    align-items: stretch;
  }

  .home-insights__faq,
  .home-insights__news {
    display: grid;
    grid-template-rows: minmax(88px, auto) minmax(0, 1fr) auto;
    gap: clamp(10px, 1.2vh, 14px);
  }

  /* Title alignment — both column headers share an identical
     font-size + line-height and bottom-align inside row 1
     (align-self: end) so the two titles sit on the same visual
     baseline. Font-size is sized so "Questions we often hear."
     fits on a single line at the smallest desktop viewport
     (~1101 px), keeping the two titles' heights equal so the
     bottom-align also produces matching top edges. Both center
     horizontally so the news title sits directly above the
     3-card stack. */
  .home-insights__faq .section__title,
  .home-insights__news-title {
    align-self: end;
    font-size: clamp(2rem, 2.4vw, 2.75rem);
    line-height: 1.02;
    text-align: center;
    margin: 0;
    max-width: none;
  }

  /* FAQ list — six equal-height rows that align with the three
     news cards so each card visually spans a pair of FAQ rows.
     Gap matches `.home-insights__cards { gap: 14px }` exactly so
     card-bottom-N lands precisely on FAQ-row-(2N)-bottom; with
     mismatched gaps the gap-arithmetic broke alignment by ~9 px
     per card. */
  .home-insights__faq .faq__list {
    display: grid;
    grid-row: 2;
    grid-template-rows: repeat(6, minmax(0, 1fr));
    gap: 14px;
    width: 100%;
    margin: 0 auto;
  }

  /* (FAQ row-3 spacer removed — it existed to match the height of
     the news-side "See latest news" button so the two columns'
     row 3 stayed equal. The button has been removed, so neither
     column needs a row-3 filler. Both columns now end at row 2.) */

  .home-insights .faq__list .faq__item {
    min-height: 0;
  }

  /* Specificity bump (`.faq__list` added to selector path) so this
     rule outranks `.section.v3-frame .faq__item summary` from line
     676, which otherwise wins on (0,3,1) > (0,2,1) and forces the
     wrong padding/font-size on this section's six FAQ rows. */
  .home-insights .faq__list .faq__item summary {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 44px;
    align-items: center;
    column-gap: 16px;
    min-height: 100%;
    padding: clamp(10px, 1.2vh, 16px) 0;
    font-size: clamp(1rem, 1.2vw, 1.125rem);
    line-height: 1.22;
  }

  /* Same specificity bump for the plus-icon. position: static moves
     it out of base absolute positioning into the summary's grid as
     a real grid cell (column 2, justify-self: end), so all icons
     align in one vertical column at the column-2 right edge
     regardless of how long the question text is. */
  .home-insights .faq__list .faq__item summary::after {
    position: static;
    grid-column: 2;
    justify-self: end;
    width: 32px;
    height: 32px;
    transform: none;
  }

  .home-insights .faq__list .faq__item[open] summary::after {
    transform: rotate(180deg);
  }

  .home-insights__cards {
    display: grid;
    grid-row: 2;
    grid-template-rows: repeat(3, minmax(0, 1fr));
    gap: 14px;
    min-height: 0;
    margin: 0;
  }

  .home-insights__card {
    height: auto;
    min-height: 0;
  }

  .home-insights__media img {
    min-height: 0;
  }

  .home-insights__card-body {
    gap: 6px;
    padding: clamp(14px, 1.4vw, 18px);
  }

  .home-insights__card-body h3 {
    font-size: clamp(1rem, 1.1vw, 1.125rem);
    line-height: 1.18;
  }

  .home-insights__card-body p {
    font-size: 0.875rem;
    line-height: 1.42;
  }

  /* (Desktop .home-insights__button rule removed — see comment by
     the base rule above; the button itself was deleted from markup.) */
}

@media (max-width: 1100px) {
  .home-insights__inner { grid-template-columns: 1fr; }

  .home-insights__news {
    max-width: 760px;
    width: 100%;
    margin-inline: auto;
  }
}

@media (max-width: 600px) {
  .home-insights__card { grid-template-columns: 1fr; }

  .home-insights__media { aspect-ratio: 16 / 9; }
}

/* / home — FAQ full-width section. Replaces the previous
   `.home-insights` two-column FAQ + Latest News layout (Latest News
   removed per CEO direction). The FAQ now owns the whole frame:
   centred title above a single-column accordion list. Compact row
   spacing; plus icons aligned via the same grid pattern as before
   so long question text never pushes them out of column. */
.home-faq__inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}
.home-faq__title {
  max-width: 760px;
  margin: 0 0 clamp(28px, 4vh, 48px);
}
.home-faq__list {
  width: 100%;
  max-width: 880px;
  margin: 0 auto;
}
/* Compact FAQ row spacing — overrides the larger
   `.section.v3-frame .faq__item summary` padding (line ~676) so
   each row reads as a tight, premium row rather than a tall slab.
   Selector specificity is bumped via `.home-faq` so this pair wins
   over the `.section.v3-frame .faq__item summary` rule (0,3,1) at
   tied (0,3,1) source-order. Text size also tightened slightly. */
.home-faq .faq__item summary {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 44px;
  align-items: center;
  column-gap: 16px;
  padding: clamp(14px, 1.6vh, 20px) 0;
  font-size: clamp(1rem, 1.2vw, 1.15rem);
  line-height: 1.28;
}
/* Plus icon — pulled out of base absolute positioning into the
   summary grid (column 2, justify-self end) so all icons line up
   on one vertical column at every row regardless of question
   length. Selector specificity again sized to outrank
   `.section.v3-frame .faq__item summary::after` (0,3,2). */
.home-faq .faq__item summary::after {
  position: static;
  grid-column: 2;
  justify-self: end;
  width: 32px;
  height: 32px;
  transform: none;
}
.home-faq .faq__item[open] summary::after {
  transform: rotate(180deg);
}

/* / home — News & Updates carousel. Replaces the prior 3-card
   static grid + decorative dots. Now a horizontal scroll-snap viewport
   showing 3 cards per page on desktop, 2 on tablet, 1 on mobile, with
   JS-rendered functional dots and prev/next arrows that step through
   pages. Cards are <a> elements opening real source articles (Colliers,
   CBRE, Wynn Resorts newsroom, Zawya, ValuStrat, Arabian Business) in
   a new tab. The carousel degrades to a horizontal scroll with no nav
   if JS fails. */
.home-news {
  padding: clamp(32px, 4.5vh, 64px) var(--v3-pad-x);
  background: var(--bg);
  color: var(--ink);
}
.home-news__inner {
  max-width: 1280px;
  margin: 0 auto;
}
.home-news__title {
  margin: 0 0 clamp(24px, 3vh, 40px);
  font-family: "DM Sans", -apple-system, sans-serif;
  font-weight: 500;
  font-size: clamp(1.75rem, 3vw, 2.5rem);
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: var(--ink);
  text-align: center;
}
.home-news__viewport {
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  -ms-overflow-style: none;
  scrollbar-width: none;
  margin-inline: calc(var(--v3-pad-x) * -0.25);
  padding-inline: calc(var(--v3-pad-x) * 0.25);
  padding-block: 4px;
}
.home-news__viewport::-webkit-scrollbar { display: none; }
.home-news__track {
  display: flex;
  gap: clamp(20px, 2.4vw, 32px);
  align-items: stretch;
}
.home-news__card {
  flex: 0 0 calc((100% - 2 * clamp(20px, 2.4vw, 32px)) / 3);
  scroll-snap-align: start;
  display: flex;
  flex-direction: column;
  gap: 12px;
  background: transparent;
  border: 0;
  padding: 0;
  text-decoration: none;
  color: inherit;
  transition: transform 0.4s var(--ease, ease);
}
.home-news__card:hover {
  transform: translateY(-3px);
}
.home-news__card:focus-visible {
  outline: 2px solid var(--accent, #00B073);
  outline-offset: 6px;
  border-radius: 18px;
}
.home-news__media {
  width: 100%;
  aspect-ratio: 16 / 7;
  overflow: hidden;
  border-radius: 18px;
  background: rgba(0, 61, 46, 0.06);
}
.home-news__media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.6s var(--ease, ease);
}
.home-news__card:hover .home-news__media img {
  transform: scale(1.04);
}
.home-news__card-meta {
  margin: 6px 0 0;
  font-family: "DM Sans", -apple-system, sans-serif;
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent, #00B073);
}
.home-news__card-title {
  margin: 4px 0 0;
  font-family: "DM Sans", -apple-system, sans-serif;
  font-weight: 600;
  font-size: clamp(1rem, 1.15vw, 1.125rem);
  line-height: 1.3;
  letter-spacing: -0.01em;
  color: var(--ink);
}
.home-news__card-body {
  margin: 0;
  font-family: "DM Sans", -apple-system, sans-serif;
  font-size: 0.9375rem;
  line-height: 1.55;
  color: rgba(18, 18, 18, 0.6);
}

.home-news__nav {
  margin-top: clamp(20px, 2.5vh, 32px);
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 16px;
}
.home-news__arrow {
  appearance: none;
  -webkit-appearance: none;
  background: transparent;
  border: 1px solid rgba(18, 18, 18, 0.18);
  width: 40px;
  height: 40px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--ink);
  cursor: pointer;
  padding: 0;
  transition: border-color 0.2s ease, background-color 0.2s ease, color 0.2s ease;
}
.home-news__arrow svg { width: 18px; height: 18px; display: block; }
.home-news__arrow:hover {
  border-color: var(--accent, #00B073);
  color: var(--accent, #00B073);
}
.home-news__arrow:focus-visible {
  outline: 2px solid var(--accent, #00B073);
  outline-offset: 3px;
}
.home-news__arrow[disabled] {
  opacity: 0.3;
  cursor: default;
  pointer-events: none;
}
.home-news__dots {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 10px;
  margin: 0;
}
.home-news__dot {
  appearance: none;
  -webkit-appearance: none;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: rgba(18, 18, 18, 0.18);
  border: 0;
  padding: 0;
  cursor: pointer;
  transition: background-color 0.3s ease, transform 0.3s ease;
}
.home-news__dot:hover { background: rgba(18, 18, 18, 0.4); }
.home-news__dot:focus-visible {
  outline: 2px solid var(--accent, #00B073);
  outline-offset: 3px;
}
.home-news__dot.is-active {
  background: var(--ink);
  transform: scale(1.25);
}

@media (max-width: 1023px) {
  .home-news__card { flex-basis: calc((100% - clamp(20px, 2.4vw, 32px)) / 2); }
}
@media (max-width: 768px) {
  .home-news__viewport {
    --home-news-mobile-card: clamp(320px, 82vw, 560px);
    --home-news-mobile-edge: calc((100vw - var(--home-news-mobile-card)) / 2);
    width: 100vw;
    margin-left: calc(50% - 50vw);
    margin-right: calc(50% - 50vw);
    padding-inline: 0;
    scroll-padding-inline: var(--home-news-mobile-edge);
  }
  .home-news__track {
    gap: clamp(16px, 4vw, 22px);
    padding-inline: var(--home-news-mobile-edge);
  }
  .home-news__track::after {
    content: "";
    flex: 0 0 var(--home-news-mobile-edge);
  }
  .home-news__card {
    flex-basis: var(--home-news-mobile-card);
    scroll-snap-align: center;
  }
  .home-news__nav { gap: 12px; }
}

/* /sell/ closing CTA — promotional panel.
   Replaces the centered single-line CTA with a substantial dark
   forest-green card. Two-column desktop layout (copy left, CTAs
   right), 24/28px corner radius matching .v3-card / .v3-case__feature,
   reuses --accent-deep + --mint + --accent tokens. Section wrapper
   keeps its existing class chain so the prior .v3-section--cta
   spacing rules (incl. :has(.v3-rep) override) still apply; the
   inner panel is the new visual element. */
/* / home final frame - black frame after the white FAQ section.
   News, CTA, and footer inherit this single final surface so the
   frame does not break into white/green bands. */
.v3-frame-group--home-final {
  background: var(--ink);
  color: #fff;
}
.v3-frame-group--home-final > .home-final-cluster,
.v3-frame-group--home-final .home-news,
.v3-frame-group--home-final .cta-final--compact {
  background: transparent;
}
.v3-frame-group--home-final .home-news {
  color: #fff;
}
.v3-frame-group--home-final .home-news__media {
  background: rgba(255, 255, 255, 0.08);
}
.v3-frame-group--home-final .home-news__title,
.v3-frame-group--home-final .home-news__card-title,
.v3-frame-group--home-final .cta-final__title,
.v3-frame-group--home-final .home-final-cluster .cta-final__title {
  color: #fff;
}
.v3-frame-group--home-final .home-news__card-body,
.v3-frame-group--home-final .cta-final__sub,
.v3-frame-group--home-final .home-final-cluster .cta-final__sub {
  color: rgba(255, 255, 255, 0.72);
}
.v3-frame-group--home-final .home-news__dot {
  background: rgba(255, 255, 255, 0.28);
}
.v3-frame-group--home-final .home-news__dot.is-active {
  background: var(--mint);
}
.v3-frame-group--home-final .cta-final--compact {
  color: #fff;
}
.v3-frame-group--home-final .cta-final .btn--primary,
.v3-frame-group--home-final .cta-final .btn--primary:hover,
.v3-frame-group--home-final .home-final-cluster .cta-final .btn--primary,
.v3-frame-group--home-final .home-final-cluster .cta-final .btn--primary:hover {
  background: var(--accent);
  color: var(--accent-deep);
}

/* Footer theme inheritance for final V3 frames. The footer is
   transparent inside each final wrapper, so its surface visually
   matches the preceding final section instead of forcing forest green. */
.v3-frame-group--home-final > .footer,
.v3-frame-group--buy-final > .footer,
.v3-frame-group--invest-final > .footer,
.v3-frame-group--broker-final > .footer {
  background: transparent;
  color: #fff;
  border-top-color: rgba(255, 255, 255, 0.12);
}
/* Footer logo on dark-frame pages: namou-logo-2.png is already a
   coloured mark (green on white), so the legacy brightness(0)
   invert(1) silhouette flip used for the old transparent logo no
   longer applies — it would turn the whole image into a solid
   white square. mix-blend-mode: multiply blends the white image
   background into the dark footer surface so only the green
   wordmark reads through. */
.v3-frame-group--home-final > .footer .footer__brand img,
.v3-frame-group--buy-final > .footer .footer__brand img,
.v3-frame-group--invest-final > .footer .footer__brand img,
.v3-frame-group--broker-final > .footer .footer__brand img {
  filter: none;
  mix-blend-mode: multiply;
}
.v3-frame-group--home-final > .footer .footer__brand p,
.v3-frame-group--buy-final > .footer .footer__brand p,
.v3-frame-group--invest-final > .footer .footer__brand p,
.v3-frame-group--broker-final > .footer .footer__brand p,
.v3-frame-group--home-final > .footer .footer__col h4,
.v3-frame-group--buy-final > .footer .footer__col h4,
.v3-frame-group--invest-final > .footer .footer__col h4,
.v3-frame-group--broker-final > .footer .footer__col h4,
.v3-frame-group--home-final > .footer .footer__col span,
.v3-frame-group--buy-final > .footer .footer__col span,
.v3-frame-group--invest-final > .footer .footer__col span,
.v3-frame-group--broker-final > .footer .footer__col span,
.v3-frame-group--home-final > .footer .footer__bottom,
.v3-frame-group--buy-final > .footer .footer__bottom,
.v3-frame-group--invest-final > .footer .footer__bottom,
.v3-frame-group--broker-final > .footer .footer__bottom,
.v3-frame-group--home-final > .footer .footer__bottom span,
.v3-frame-group--buy-final > .footer .footer__bottom span,
.v3-frame-group--invest-final > .footer .footer__bottom span,
.v3-frame-group--broker-final > .footer .footer__bottom span {
  color: rgba(255, 255, 255, 0.68);
}
.v3-frame-group--home-final > .footer .footer__col a,
.v3-frame-group--buy-final > .footer .footer__col a,
.v3-frame-group--invest-final > .footer .footer__col a,
.v3-frame-group--broker-final > .footer .footer__col a,
.v3-frame-group--home-final > .footer .footer__map a,
.v3-frame-group--buy-final > .footer .footer__map a,
.v3-frame-group--invest-final > .footer .footer__map a,
.v3-frame-group--broker-final > .footer .footer__map a {
  color: #fff;
}
.v3-frame-group--home-final > .footer a:hover,
.v3-frame-group--buy-final > .footer a:hover,
.v3-frame-group--invest-final > .footer a:hover,
.v3-frame-group--broker-final > .footer a:hover {
  color: var(--mint);
}
.v3-frame-group--home-final > .footer .footer__bottom,
.v3-frame-group--buy-final > .footer .footer__bottom,
.v3-frame-group--invest-final > .footer .footer__bottom,
.v3-frame-group--broker-final > .footer .footer__bottom {
  border-top-color: rgba(255, 255, 255, 0.12);
}
.v3-frame-group--home-final > .footer .footer__map iframe,
.v3-frame-group--buy-final > .footer .footer__map iframe,
.v3-frame-group--invest-final > .footer .footer__map iframe,
.v3-frame-group--broker-final > .footer .footer__map iframe {
  border-color: rgba(255, 255, 255, 0.18);
  background: rgba(255, 255, 255, 0.06);
}

.v3-frame-group--sell-final > .footer {
  background: transparent;
  color: var(--ink);
  border-top-color: var(--line);
}
.v3-frame-group--sell-final > .footer .footer__brand img {
  filter: none;
}

.v3-section--cta-panel { text-align: left; }

.v3-cta-panel {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1.35fr) minmax(280px, 0.65fr);
  align-items: center;
  gap: clamp(28px, 4vw, 64px);
  max-width: 1240px;
  margin: 0 auto;
  padding: clamp(36px, 4.5vw, 72px) clamp(28px, 4vw, 64px);
  border-radius: 28px;
  background: var(--accent-deep);
  color: #fff;
  overflow: hidden;
}
/* Soft mint glow anchored to the bottom-left for warmth and depth. */
.v3-cta-panel::before {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse 70% 60% at 0% 100%, rgba(0, 176, 115, 0.22), transparent 65%);
  pointer-events: none;
}

.v3-cta-panel__copy {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 14px;
  min-width: 0;
}

.v3-cta-panel__eyebrow {
  margin: 0;
  font-family: "DM Sans", -apple-system, sans-serif;
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--mint);
}

.v3-cta-panel__title {
  margin: 0;
  font-family: "DM Sans", -apple-system, sans-serif;
  font-weight: 500;
  font-size: clamp(1.875rem, 3.4vw, 3rem);
  line-height: 1.05;
  letter-spacing: -0.02em;
  color: #fff;
  text-transform: none;
}
.v3-cta-panel__title .v3-serif {
  font-family: "Instrument Serif", serif;
  font-style: italic;
  font-weight: 400;
}

.v3-cta-panel__sub {
  margin: 0;
  font-family: "DM Sans", -apple-system, sans-serif;
  font-size: clamp(0.9375rem, 1.05vw, 1.0625rem);
  line-height: 1.55;
  color: rgba(255, 255, 255, 0.78);
  max-width: 56ch;
}

.v3-cta-panel__reassure {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 24px;
  margin: 14px 0 0;
  padding: 0;
  list-style: none;
}
.v3-cta-panel__reassure li {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: "DM Sans", -apple-system, sans-serif;
  font-size: 0.875rem;
  color: rgba(255, 255, 255, 0.85);
}
.v3-cta-panel__reassure .material-symbols-outlined {
  font-size: 18px;
  color: var(--mint);
}

.v3-cta-panel__actions {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 12px;
  align-self: stretch;
  justify-content: center;
}
.v3-cta-panel__actions .btn {
  width: 100%;
  justify-content: center;
}
/* Ghost button adapted for the dark panel surface (mirrors
   .cta-final .btn--ghost on the home final CTA). */
.v3-cta-panel__actions .btn--ghost {
  background: transparent;
  color: #fff;
  border: 1px solid rgba(255, 255, 255, 0.32);
}
.v3-cta-panel__actions .btn--ghost:hover {
  border-color: #fff;
  background: rgba(255, 255, 255, 0.08);
  color: #fff;
}

/* Tablet/mobile: stack copy above CTAs; CTAs go full-width. */
@media (max-width: 1023px) {
  .v3-cta-panel {
    grid-template-columns: 1fr;
    gap: 28px;
    padding: clamp(28px, 4vw, 48px);
  }
}
@media (max-width: 600px) {
  .v3-cta-panel { padding: 26px 22px; border-radius: 22px; }
  .v3-cta-panel__title { font-size: clamp(1.625rem, 7vw, 2.25rem); }
  .v3-cta-panel__reassure { gap: 8px 16px; }
}

/* /sell/ final frame: representative card + valuation CTA share one
   desktop row, with the footer completing the bottom of the viewport.
   The frame is now WHITE (V3 alternation pass switched it away from
   forest-green); inner section stays transparent so it inherits the
   white frame. The Nadim rep card + the dark-green `.v3-cta-panel`
   sit on this white surface as two contained card components. */
.v3-sell-final-section {
  background: transparent;
}

.v3-sell-final-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(20px, 3vw, 32px);
  align-items: stretch;
}

.v3-rep--final {
  display: flex;
  flex-direction: column;
  gap: clamp(22px, 2.5vw, 32px);
  height: 100%;
  margin: 0;
}

.v3-rep__intro .v3-eyebrow {
  margin-bottom: 10px;
}

.v3-rep__intro .v3-h2 {
  margin-bottom: 0;
}

.v3-rep__body {
  display: grid;
  grid-template-columns: minmax(150px, 220px) minmax(0, 1fr);
  gap: clamp(24px, 3vw, 40px);
  align-items: center;
}

.v3-cta-panel--sell-final {
  height: 100%;
}

@media (min-width: 1024px) {
  /* Final-frame layout. The previous `space-between` on the frame
     group put all the viewport slack between the section and the
     footer; `flex-start` instead places the slack below the footer
     band, with `margin-block: auto` on the section centring the
     two cards inside the available space. Background colour is now
     WHITE (inherited from the page) — see the major-section background
     block at the bottom of this file. The footer below is transparent
     and inherits the same white surface. */
  .v3-frame-group--sell-final {
    justify-content: flex-start;
  }

  .v3-frame-group--sell-final > .v3-sell-final-section {
    margin-block: auto;
    padding-block: clamp(18px, 2.75vh, 36px);
  }

  .v3-sell-final-grid {
    grid-template-columns: minmax(0, 1fr) minmax(420px, 0.92fr);
  }

  .v3-sell-final-grid > .v3-rep--final,
  .v3-sell-final-grid > .v3-cta-panel--sell-final {
    min-height: clamp(420px, 47vh, 540px);
  }

  .v3-rep--final {
    padding: clamp(24px, 2.4vw, 34px);
  }

  .v3-rep--final .v3-h2,
  .v3-cta-panel--sell-final .v3-cta-panel__title {
    font-size: clamp(2rem, 3vw, 3rem);
    line-height: 1.04;
  }

  .v3-rep--final .v3-rep__photo {
    max-width: 190px;
  }

  .v3-cta-panel--sell-final {
    grid-template-columns: 1fr;
    /* Distribute the copy block + CTA evenly down the card so the
       breathing room above the eyebrow, between the bullets and the
       button, and below the button are all equal — no dead band. */
    align-content: space-evenly;
    row-gap: clamp(24px, 3.5vh, 44px);
    padding: clamp(28px, 3.2vw, 44px);
  }

  .v3-cta-panel--sell-final .v3-cta-panel__actions {
    align-self: stretch;
  }

  .v3-frame-group--sell-final .footer {
    padding-top: clamp(18px, 2vh, 24px);
  }
}

@media (max-width: 1023px) {
  .v3-rep__body {
    grid-template-columns: 1fr;
    text-align: center;
  }

  .v3-rep--final .v3-rep__photo {
    max-width: 220px;
    margin: 0 auto;
  }
}

/* Nadim representative card — mobile sizing trim. The base rep card
   at line 3106+ + base mobile rule at line 3112 already collapses
   the card to a centred single column with 24px padding and a 200px
   photo cap. On phones (390–430px) that still left the card too tall
   to read cleanly inside one mobile screen alongside the closing
   `.v3-cta-panel--sell-final` stacked above. Tighten further at
   ≤768px: smaller portrait, lighter padding/gaps, tighter body line-
   height, and a slightly shorter mobile-only paragraph variant
   (`.copy-mobile`) — same meaning, ~30 fewer characters. Desktop
   is byte-identical (these rules are gated by the mobile breakpoint
   and the `.v3-frame-group--sell-final` scope). */
@media (max-width: 768px) {
  .v3-frame-group--sell-final .v3-rep--final {
    padding: clamp(16px, 4vw, 22px);
    gap: clamp(14px, 3vw, 22px);
  }
  .v3-frame-group--sell-final .v3-rep--final .v3-rep__photo {
    max-width: 144px;
  }
  .v3-frame-group--sell-final .v3-rep--final .v3-rep__body {
    gap: clamp(12px, 2.6vw, 18px);
  }
  .v3-frame-group--sell-final .v3-rep--final .v3-rep__copy h3 {
    font-size: clamp(1.125rem, 4.4vw, 1.25rem);
    margin-bottom: 2px;
  }
  .v3-frame-group--sell-final .v3-rep--final .v3-rep__role {
    margin-bottom: 10px;
    line-height: 1.4;
  }
  .v3-frame-group--sell-final .v3-rep--final .v3-rep__copy p {
    font-size: 0.9375rem;
    line-height: 1.45;
    margin: 0 0 14px;
  }
  .v3-frame-group--sell-final .v3-rep--final .v3-cta-row {
    gap: 10px;
  }
}

/* ============================================================
   MAJOR-SECTION BACKGROUNDS — V3 page-by-page
   Each major-section wrapper paints the entire frame in one of:
     • Black           — `var(--ink)` (existing token #121212)
     • Footer green    — `var(--accent-deep)` (the same token .footer
                         already paints with, so the frame meets the
                         footer with no mismatched band)
     • White           — `#fff` literal
   Grouped child sections inherit by going transparent so the wrapper
   colour shows through unbroken. Card surfaces and text are adapted
   per scope so contrast holds without per-section background patches.
   ============================================================ */

/* Sell · first major (`.v3-frame-group--sell-method`) — black */
.v3-frame-group--sell-method { background: var(--ink); color: #fff; }
.v3-frame-group--sell-method > .v3-section { background: transparent; }
.v3-frame-group--sell-method .v3-eyebrow { color: var(--mint); }
.v3-frame-group--sell-method .v3-h2,
.v3-frame-group--sell-method h2,
.v3-frame-group--sell-method h3 { color: #fff; }
.v3-frame-group--sell-method p,
.v3-frame-group--sell-method li { color: rgba(255, 255, 255, 0.78); }
.v3-frame-group--sell-method .v3-feature {
  background: rgba(255, 255, 255, 0.04);
  border-color: rgba(255, 255, 255, 0.12);
}
.v3-frame-group--sell-method .v3-feature:hover {
  background: rgba(255, 255, 255, 0.07);
  border-color: rgba(255, 255, 255, 0.22);
}
/* Process step cards inside the timeline — selector path bumped to
   include `.v3-process.v3-process--timeline` so this rule reaches
   (0,4,0) and outranks the base timeline rule
   `.v3-process.v3-process--timeline .v3-process__step` (0,3,0) at
   line ~1112 which paints `background: var(--v3-mint-white)`. With
   the previous (0,2,0) override, the base rule's higher specificity
   was winning and the cards stayed light on the black frame.
   Scoped to MOBILE/TABLET only via `@media (max-width: 1023px)` —
   on desktop the timeline switches to a vertical numbered list with
   transparent rows + a hairline perimeter (rules around line 1151),
   so the translucent-white fill should NOT apply at ≥1024px or it
   re-introduces the gray/dark filled card look the desktop layout
   intentionally removed. */
@media (max-width: 1023px) {
  .v3-frame-group--sell-method .v3-process.v3-process--timeline .v3-process__step {
    background: rgba(255, 255, 255, 0.04);
    border-color: rgba(255, 255, 255, 0.12);
  }
  .v3-frame-group--sell-method .v3-process.v3-process--timeline .v3-process__step:hover {
    background: rgba(255, 255, 255, 0.07);
    border-color: rgba(255, 255, 255, 0.22);
  }
}
/* Same specificity-bump trick as the card background above: the base
   rule `.v3-process--timeline .v3-process__step h3` (0,2,1) was
   painting these titles with `var(--ink)` (black) on the dark frame.
   The frame-level `.v3-frame-group--sell-method h3` (0,1,1) lost that
   match, so titles rendered black-on-dark. Path bumped to (0,4,1) so
   the dark-theme white wins, scoped strictly to the timeline cards
   inside the sell-method black frame. */
.v3-frame-group--sell-method .v3-process.v3-process--timeline .v3-process__step h3 { color: #fff; }
.v3-frame-group--sell-method .v3-process { border-top-color: rgba(255, 255, 255, 0.12); }
.v3-frame-group--sell-method .v3-process__step { border-right-color: rgba(255, 255, 255, 0.12); }
/* Mint-tinted icon bubble — replaces a previous translucent-white
   bubble around white icons. Keeps the soft "icon on a halo" shape
   the section was designed with, but rebinds the colour family to
   the brand accent so the icons read as on-brand green markers,
   matching `.v3-frame-group--broker-pair-1 .v3-feature__icon`. */
.v3-frame-group--sell-method .v3-feature--method .v3-feature__icon-wrap,
.v3-frame-group--sell-method .v3-process--timeline .v3-process__icon-wrap {
  background: rgba(63, 230, 168, 0.12);
}
/* Mint icons on dark cards — was forced to #fff on the dark frame
   override, which stripped the brand accent the rest of the V3
   black-section system uses. */
.v3-frame-group--sell-method .v3-feature__icon,
.v3-frame-group--sell-method .v3-process__icon { color: var(--mint); }
/* Divider hairline + timeline numbered-circle border fall back to
   the base brand `var(--accent)` (mint). The previous overrides
   forced both to translucent-white, which dropped the green accent
   markers on this otherwise on-brand black frame. The base rules
   already paint these mint, so we just remove the white-tint
   overrides. `.v3-process__num` was already set to mint. */
.v3-frame-group--sell-method .v3-process__nav-cell { color: #fff; }

/* Sell · final major (`.v3-frame-group--sell-final`) — switched from
   forest-green to WHITE per the V3 alternation pass (no two adjacent
   major sections share a colour). The previous frame was dark green,
   which forced the Nadim rep card and the "Ready for a free valuation?"
   CTA panel to carry translucent-white-on-dark surfaces; that pattern
   no longer applies on a white frame. The frame now falls back to the
   page background, the rep card falls back to its base `.v3-rep`
   mint-white card with ink text + accent role, and the CTA panel falls
   back to its base `.v3-cta-panel` design (dark green panel with white
   text — a contained brand accent that pops on the white frame, not a
   major-section background). All previous dark-frame text/card/btn
   overrides are removed because their light-theme defaults are correct
   for a white surface. Sequence: hero W → sell-method B → sell-final W. */

/* Invest · second major (`#strategies`, the standalone "Three structures"
   section) — black. The model cards previously kept their light mint-white
   surfaces on the new black frame; that read as "cards designed for a
   white page sitting on a black page" rather than as cards intentionally
   adapted for dark. Re-skinned to the same translucent-white-on-dark
   pattern Broker uses on `.v3-frame-group--broker-pair-1 .v3-feature`:
   `rgba(255,255,255,0.04)` base / `0.07` hover surface, `0.12`/`0.22`
   borders, mint accents on label + hover, white headings, muted-white
   body. Both halves of the model card (the illustration tile + the
   content tile) carry the same translucent surface so the card reads
   as one unified dark-theme element with a hairline separator. */
#strategies.v3-section.v3-frame { background: var(--ink); }
#strategies.v3-section.v3-frame > .v3-section__inner > .v3-eyebrow { color: var(--mint); }
#strategies.v3-section.v3-frame > .v3-section__inner > .v3-h2 { color: #fff; }
#strategies.v3-section.v3-frame .v3-model {
  background: rgba(255, 255, 255, 0.04);
  border-color: rgba(255, 255, 255, 0.12);
  color: #fff;
}
#strategies.v3-section.v3-frame .v3-model:hover {
  background: rgba(255, 255, 255, 0.07);
  border-color: var(--mint);
  box-shadow: 0 12px 28px rgba(0, 0, 0, 0.32);
}
#strategies.v3-section.v3-frame .v3-model__illu {
  background: transparent;
  border-bottom-color: rgba(255, 255, 255, 0.12);
}
#strategies.v3-section.v3-frame .v3-model__content {
  background: transparent;
}
#strategies.v3-section.v3-frame .v3-model h3 { color: #fff; }
#strategies.v3-section.v3-frame .v3-model p { color: rgba(255, 255, 255, 0.78); }
#strategies.v3-section.v3-frame .v3-model__label { color: var(--mint); }
#strategies.v3-section.v3-frame .v3-model__cta {
  background: rgba(255, 255, 255, 0.06);
  border-color: rgba(255, 255, 255, 0.18);
  color: #fff;
}
#strategies.v3-section.v3-frame .v3-model:hover .v3-model__cta {
  background: rgba(255, 255, 255, 0.10);
  border-color: var(--mint);
}

/* Invest · final major (`.v3-frame-group--invest-final`) — switched
   from forest-green to BLACK per the V3 alternation pass. The four
   `Why JV` USP cards already use a translucent-white-on-dark surface
   pattern (`rgba(255,255,255,0.06)` base / `0.16` border, white text,
   mint accent counters), which works identically on `var(--ink)` and
   on the previous `var(--accent-deep)`; no inner text/card rules need
   to change. The nested `.v3-section--alt` cta strip continues to
   drop its mint-white tint so the frame paint flows unbroken through
   to the dark-green footer below. Sequence: hero W → invest-intro W
   → invest-final B (hero/intro W-W adjacency accepted — re-theming
   the JV intro to dark would require redesigning its feature/stat
   cards beyond the scope of a colour-only pass). */
.v3-frame-group--invest-final { background: var(--ink); }
.v3-frame-group--invest-final > .v3-section,
.v3-frame-group--invest-final > .v3-section--alt,
.v3-frame-group--invest-final > .v3-section--cta { background: transparent; }
.v3-frame-group--invest-final .v3-eyebrow { color: var(--mint); }
.v3-frame-group--invest-final .v3-h2,
.v3-frame-group--invest-final h2,
.v3-frame-group--invest-final h3 { color: #fff; }
.v3-frame-group--invest-final p { color: rgba(255, 255, 255, 0.82); }
.v3-frame-group--invest-final .v3-usp {
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: 14px;
  padding: clamp(20px, 1.8vw, 28px);
  transition: background 240ms var(--ease), border-color 240ms var(--ease);
}
.v3-frame-group--invest-final .v3-usp:hover {
  background: rgba(255, 255, 255, 0.09);
  border-color: rgba(255, 255, 255, 0.26);
}
.v3-frame-group--invest-final .v3-usp__num { color: var(--mint); }
/* The closing `Inquire about opportunities` primary button currently relies
   on `.btn--primary svg path { stroke: var(--accent-deep) }` — invisible on
   the dark green frame because the arrow is the same colour as the bg
   behind the button. Lift the arrow to white so it stays visible. */
.v3-frame-group--invest-final .v3-cta-row .btn--primary svg path { stroke: #fff; }

/* Broker · first major (`.v3-frame-group--broker-pair-1`, "Three
   protections" + "Video deck advantage") — black. Feature cards inside
   adapt to a translucent-white elevated surface so they read as cards
   on a dark frame, not punch-outs. */
.v3-frame-group--broker-pair-1 { background: var(--ink); color: #fff; }
.v3-frame-group--broker-pair-1 > .v3-section { background: transparent; }
.v3-frame-group--broker-pair-1 .v3-eyebrow { color: var(--mint); }
.v3-frame-group--broker-pair-1 .v3-h2,
.v3-frame-group--broker-pair-1 h2,
.v3-frame-group--broker-pair-1 h3 { color: #fff; }
.v3-frame-group--broker-pair-1 p { color: rgba(255, 255, 255, 0.78); }
.v3-frame-group--broker-pair-1 .v3-feature {
  background: rgba(255, 255, 255, 0.04);
  border-color: rgba(255, 255, 255, 0.12);
}
.v3-frame-group--broker-pair-1 .v3-feature:hover {
  background: rgba(255, 255, 255, 0.07);
  border-color: rgba(255, 255, 255, 0.22);
}
.v3-frame-group--broker-pair-1 .v3-feature__icon { color: var(--mint); }

/* Broker · second major (`.v3-frame-group--broker-pair-2`, "Commission"
   + "Process") — fully white. The nested Commission section carries a
   `v3-section--alt` modifier (mint-white) by default — drop that here
   so the whole frame is uniformly white per spec. Standard light-theme
   text/card colours still apply, no overrides needed. */
.v3-frame-group--broker-pair-2 { background: #fff; }
.v3-frame-group--broker-pair-2 > .v3-section,
.v3-frame-group--broker-pair-2 > .v3-section--alt { background: transparent; }

/* Broker flow replaces the previous Commission + Process pair with one
   direct sequence: reach out, agreement, commission, official partner. */
.v3-frame-group--broker-flow {
  background: #fff;
  display: flex;
  align-items: center;
  padding: var(--v3-desktop-nav-offset) var(--v3-pad-x) clamp(48px, 7vh, 96px);
}
.v3-frame-group--broker-flow > .v3-section {
  background: transparent;
  width: 100%;
  padding: 0;
}
.v3-frame-group--broker-flow .v3-section__inner {
  max-width: 1480px;
  text-align: center;
}
.v3-frame-group--broker-flow .v3-eyebrow,
.v3-frame-group--broker-flow .v3-h2,
.v3-frame-group--broker-flow .v3-lede {
  margin-inline: auto;
}
.v3-frame-group--broker-flow .v3-h2 { max-width: 30ch; }
.v3-frame-group--broker-flow .v3-lede { max-width: 64ch; }
.v3-broker-flow {
  --bf-gap: clamp(48px, 7vh, 72px);
  --bf-arrow-head: 10px;
  --bf-icon-size: clamp(54px, 5vw, 72px);
  --bf-num-col: clamp(34px, 3vw, 46px);
  --bf-col-gap: clamp(14px, 1.4vw, 22px);
  --bf-step-w: min(100%, 440px);
  display: flex;
  flex-direction: column;
  align-items: center;
  margin-top: clamp(30px, 5vh, 60px);
  width: var(--bf-step-w);
  margin-left: auto;
  margin-right: auto;
}
.v3-broker-flow__step {
  flex: 0 0 auto;
  display: grid;
  grid-template-columns: var(--bf-icon-size) var(--bf-num-col) minmax(0, 1fr);
  grid-template-rows: auto auto;
  column-gap: var(--bf-col-gap);
  row-gap: 4px;
  align-items: center;
  justify-items: start;
  text-align: left;
  padding: 0;
  border: 0;
  border-radius: 0;
  min-height: 0;
  width: 100%;
  max-width: none;
  transition: none;
}
.v3-broker-flow__step:hover {
  transform: none;
  border-color: transparent;
}
.v3-broker-flow__arrow {
  flex: 0 0 var(--bf-gap);
  position: relative;
  width: 1.5px;
  background: linear-gradient(to bottom, rgba(0, 184, 124, 0.55), rgba(0, 184, 124, 0.18));
  border-radius: 1px;
  min-height: 32px;
}
.v3-broker-flow__arrow::after {
  content: '';
  position: absolute;
  bottom: 0;
  left: 50%;
  width: var(--bf-arrow-head);
  height: var(--bf-arrow-head);
  border-right: 1.5px solid rgba(0, 184, 124, 0.85);
  border-bottom: 1.5px solid rgba(0, 184, 124, 0.85);
  transform: translate(-50%, 30%) rotate(45deg);
}
.v3-broker-flow__num {
  grid-column: 2;
  grid-row: 1;
  color: var(--accent);
  font-size: clamp(0.85rem, 0.9vw, 1rem);
  font-weight: 600;
  letter-spacing: 0.08em;
  margin: 0;
  align-self: end;
  justify-self: center;
}
.v3-broker-flow__icon {
  grid-column: 1;
  grid-row: 1 / span 2;
  width: var(--bf-icon-size);
  height: var(--bf-icon-size);
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 184, 124, 0.12);
  color: var(--accent);
  font-size: clamp(1.75rem, 2vw, 2.25rem);
  margin: 0;
  justify-self: center;
}
.v3-broker-flow__step h3 {
  grid-column: 3;
  grid-row: 2;
  margin: 0;
  font-size: clamp(1.2rem, 1.5vw, 1.55rem);
  line-height: 1.12;
  align-self: start;
  justify-self: start;
}
.v3-broker-flow__step p {
  display: none;
}

@media (max-width: 768px) {
  .v3-frame-group--broker-flow {
    padding: clamp(88px, 14vh, 118px) var(--v3-pad-x) clamp(36px, 7vh, 64px);
  }
  .v3-broker-flow {
    --bf-gap: 40px;
    --bf-icon-size: 56px;
    --bf-step-w: min(100%, 350px);
    --bf-num-col: 36px;
    --bf-col-gap: 14px;
    margin-top: 24px;
  }
  .v3-broker-flow__icon {
    font-size: 1.65rem;
  }
}

.v3-frame-group--broker-inventory-flow {
  background: #fff;
}

@media (min-width: 1024px) {
  .v3-frame-group--broker-inventory-flow {
    display: grid;
    grid-template-columns: minmax(360px, 0.9fr) minmax(0, 1.1fr);
    align-items: stretch;
    column-gap: clamp(32px, 4vw, 64px);
    height: 100svh;
    height: 100dvh;
    min-height: 0;
    overflow: clip;
    padding: clamp(96px, 10vh, 112px) var(--v3-pad-x) clamp(64px, 8vh, 96px);
  }

  .v3-frame-group--broker-inventory-flow > .v3-section {
    background: transparent;
    display: flex;
    min-width: 0;
    padding: 0;
  }

  .v3-frame-group--broker-inventory-flow .v3-section__inner {
    display: flex;
    flex-direction: column;
    height: 100%;
    max-width: none;
    min-height: 0;
    min-width: 0;
    width: 100%;
  }

  .v3-frame-group--broker-inventory-flow .v3-eyebrow,
  .v3-frame-group--broker-inventory-flow .v3-h2,
  .v3-frame-group--broker-inventory-flow .v3-lede {
    margin-inline: auto;
    text-align: center;
  }

  .v3-frame-group--broker-inventory-flow .v3-h2 {
    font-size: clamp(1.8rem, 2.45vw, 2.85rem);
    line-height: 1.06;
    margin-bottom: clamp(8px, 1.2vh, 14px);
    max-width: 30ch;
  }

  .v3-frame-group--broker-inventory-flow > .v3-section:nth-child(2) .v3-h2 {
    max-width: 36ch;
  }

  .v3-frame-group--broker-inventory-flow .v3-lede {
    font-size: clamp(0.95rem, 1.05vw, 1.12rem);
    line-height: 1.4;
    margin-bottom: clamp(10px, 1.4vh, 16px);
    max-width: 54ch;
  }

  .v3-frame-group--broker-inventory-flow .v3-eyebrow {
    margin-bottom: clamp(6px, 0.8vh, 10px);
  }

  .v3-frame-group--broker-inventory-flow > .v3-section:first-child .v3-feature-row {
    display: grid;
    flex: 1;
    grid-template-columns: 1fr;
    grid-template-rows: repeat(3, 1fr);
    gap: clamp(8px, 1vh, 12px);
    margin-top: clamp(10px, 1.2vh, 16px);
    min-height: 0;
  }

  .v3-frame-group--broker-inventory-flow > .v3-section:first-child .v3-feature {
    gap: clamp(6px, 0.9vh, 10px);
    min-height: 0;
    padding: clamp(14px, 1.8vh, 20px) clamp(18px, 1.8vw, 26px);
  }

  .v3-frame-group--broker-inventory-flow > .v3-section:first-child .v3-feature__icon {
    font-size: clamp(1.35rem, 1.7vw, 1.7rem);
    margin-bottom: 0;
  }

  .v3-frame-group--broker-inventory-flow > .v3-section:first-child .v3-feature h3 {
    font-size: clamp(1.2rem, 1.6vw, 1.55rem);
    line-height: 1.12;
    margin-bottom: 0;
  }

  .v3-frame-group--broker-inventory-flow > .v3-section:first-child .v3-feature p {
    font-size: clamp(0.84rem, 0.92vw, 0.98rem);
    line-height: 1.38;
  }

  .v3-frame-group--broker-inventory-flow .v3-broker-flow {
    --bf-icon-size: clamp(48px, 4vw, 60px);
    --bf-step-w: min(100%, 440px);
    flex: 1;
    margin-top: clamp(10px, 1.2vh, 16px);
    min-height: 0;
  }

  .v3-frame-group--broker-inventory-flow .v3-broker-flow__arrow {
    flex: 1 1 0;
    min-height: 32px;
  }

  .v3-frame-group--broker-inventory-flow .v3-broker-flow__num {
    margin-bottom: clamp(6px, 0.8vh, 10px);
  }

  .v3-frame-group--broker-inventory-flow .v3-broker-flow__icon {
    width: clamp(48px, 4vw, 60px);
    height: clamp(48px, 4vw, 60px);
    font-size: clamp(1.45rem, 1.7vw, 1.9rem);
    margin-bottom: clamp(8px, 1vh, 12px);
  }
}

@media (max-width: 1023px) {
  .v3-frame-group--broker-inventory-flow {
    padding-block: clamp(54px, 8vh, 84px);
  }

  .v3-frame-group--broker-inventory-flow > .v3-section {
    background: transparent;
  }
}

/* Broker · final major (`.v3-frame-group--broker-final`) — switched
   from forest-green to BLACK per the V3 alternation pass. Existing
   translucent-white-on-dark feature cards (`rgba(255,255,255,0.06)`
   base / `0.16` border, mint accents, white headings, muted-white
   body) work identically on `var(--ink)` as on the previous
   `var(--accent-deep)`; no inner text/card rules need to change. The
   nested Inventory + Register sections still drop their alt tint so
   the frame paint flows unbroken through to the forest-green footer
   below. Sequence: hero W → broker-pair-1 B → broker-pair-2 W →
   broker-final B. */
.v3-frame-group--broker-final { background: var(--ink); }
.v3-frame-group--broker-final > .v3-section,
.v3-frame-group--broker-final > .v3-section--alt,
.v3-frame-group--broker-final > .v3-section--cta { background: transparent; }
.v3-frame-group--broker-final .v3-eyebrow { color: var(--mint); }
.v3-frame-group--broker-final .v3-h2,
.v3-frame-group--broker-final h2,
.v3-frame-group--broker-final h3 { color: #fff; }
.v3-frame-group--broker-final p { color: rgba(255, 255, 255, 0.82); }
.v3-frame-group--broker-final .v3-feature {
  background: rgba(255, 255, 255, 0.06);
  border-color: rgba(255, 255, 255, 0.16);
}
.v3-frame-group--broker-final .v3-feature:hover {
  background: rgba(255, 255, 255, 0.09);
  border-color: rgba(255, 255, 255, 0.26);
}
.v3-frame-group--broker-final .v3-feature__icon { color: var(--mint); }
/* Closing `Register client` arrow-less WhatsApp button still inherits
   the global `.btn--primary svg path { stroke: var(--accent-deep) }`
   rule — but that arrow rule never matched here (the WhatsApp glyph
   uses fill, not stroke; `.btn .btn__wa-icon path { stroke: none }`
   already neutralises it). No additional override needed. */

/* Buy · final major (`.v3-frame-group--buy-final`, "Brief us. We source
   against your criteria.") — switched from forest-green to BLACK per
   the V3 alternation pass. CTA content still sits directly on the dark
   surface (no card, no border, no rounded panel) — the eyebrow +
   headline + body + WhatsApp CTA read as one premium direct-on-dark
   composition.
   • frame painted ink-black; child section transparent so the frame
     paint shows through
   • centring + max-width preserved so the CTA copy doesn't span the
     full viewport width
   • text colours unchanged from the previous dark-frame treatment
     (white headline, muted-white body, mint eyebrow) because they
     work identically on var(--ink) and var(--accent-deep)
   • the WhatsApp/forward-arrow SVG inside .btn--primary keeps the
     deep-green stroke that .btn--primary svg path defines — the
     button still has its own bright accent-green fill, so the arrow
     stays readable inside the button regardless of frame colour
   Sequence: hero W → call-showcase B → inventory W → buy-final B. */
.v3-frame-group--buy-final { background: var(--ink); }
.v3-frame-group--buy-final > .v3-section { background: transparent; }
.v3-frame-group--buy-final .v3-section__inner {
  padding: clamp(28px, 4vw, 48px);
  max-width: 760px;
  margin: 0 auto;
  text-align: center;
}
.v3-frame-group--buy-final .v3-eyebrow {
  color: var(--mint);
}
.v3-frame-group--buy-final .v3-h2 {
  color: #fff;
}
.v3-frame-group--buy-final .v3-body {
  color: rgba(255, 255, 255, 0.82);
}
.v3-frame-group--buy-final .v3-h2,
.v3-frame-group--buy-final .v3-body {
  margin-left: auto;
  margin-right: auto;
}
.v3-frame-group--buy-final .v3-cta-row {
  justify-content: center;
}

.mobile-swipe-indicator {
  display: none;
}

/* Mobile full-frame adaptation. Desktop keeps the strict viewport-frame
   rules above; below tablet width, major sections use focused screenfuls:
   tighter rhythm, natural height, and swipe rows for dense repeated cards. */
@media (max-width: 768px) {
  :root {
    --v3-mobile-frame-pad-y: clamp(52px, 13vw, 76px);
    --v3-mobile-group-pad-y: clamp(18px, 5vw, 34px);
    --v3-mobile-group-gap-y: clamp(10px, 3vw, 22px);
    --v3-mobile-card-span: min(82vw, 340px);
  }

  /* Each major section gets a `min-height: 100svh` floor on mobile so
     short content fills a focused viewport (compact sections feel
     one-screen complete) and long content (FAQ, audience cards, plot
     inventory, narrative copy) scrolls naturally past the floor
     without clipping. `svh` is used over `dvh`/`vh` to stay stable as
     iOS chrome shows/hides — `dvh` would cause layout jitter, `vh`
     would underflow on iOS Safari's collapsed-bar state. The padding
     tokens above continue to apply as natural top/bottom rhythm. No
     scroll-snap-type on the y-axis: forcing snap on long content
     (FAQ, inventory, multi-card carousels) would trap the user
     mid-read; the visible-floor approach removes the "always slicing
     two sections" issue without scroll-jacking. The hero is excluded
     (`:not(.v3-hero)`) because it has its own height treatment, and
     the marquee strip and #inventory plot grid are excluded so the
     marquee stays an 80-px companion strip and the inventory grid
     scrolls naturally past its filtered list. */
  /* Single-section frames get a 100svh floor so they read as one
     focused mobile screen. Sections that live INSIDE a
     `.v3-frame-group` (Invest's `Why JV`, sell-method's
     valuation/process pair, etc.) NO LONGER get an individual
     100svh floor — that previously made small grouped sections
     feel empty in isolation (Invest "Why JV with us" was reported
     as too sparse). Instead, frame-group children stack at their
     natural content height + the mobile padding rhythm, so the
     wrapper frame-group renders as one combined screen of related
     content rather than two stacked nearly-empty screens. */
  .section.v3-frame,
  .section--lanes,
  .home-faq,
  .home-news,
  .reveal {
    min-height: 100svh;
  }

  .v3-frame-group {
    min-height: 100svh;
    display: flex;
    flex-direction: column;
    justify-content: center;
  }

  .section.v3-frame,
  .section--lanes,
  .home-faq,
  .home-news,
  .reveal,
  .v3-section:not(.v3-hero):not(.v3-section--strip):not(#inventory),
  .v3-frame-group > .v3-section:not(.v3-section--strip):not(#inventory) {
    padding-top: var(--v3-mobile-frame-pad-y);
    padding-bottom: var(--v3-mobile-frame-pad-y);
  }

  .v3-frame-group > .v3-section:not(.v3-section--strip):not(#inventory) {
    padding-top: var(--v3-mobile-group-pad-y);
    padding-bottom: var(--v3-mobile-group-pad-y);
  }

  .v3-frame-group > .v3-section:first-child:not(.v3-section--strip):not(#inventory) {
    padding-top: var(--v3-mobile-nav-offset);
    padding-bottom: var(--v3-mobile-group-gap-y);
  }

  .v3-frame-group > .v3-section + .v3-section:not(.v3-section--strip):not(#inventory) {
    padding-top: var(--v3-mobile-group-gap-y);
  }

  .v3-frame-group > .v3-section:last-of-type:not(.v3-section--strip):not(#inventory) {
    padding-bottom: var(--v3-mobile-group-pad-y);
  }

  .v3-frame-group > .v3-section + .v3-section {
    border-top: 1px solid rgba(18, 18, 18, 0.08);
  }

  .v3-frame-group--sell-method > .v3-section + .v3-section,
  .v3-frame-group--broker-pair-1 > .v3-section + .v3-section,
  .v3-frame-group--invest-final > .v3-section + .v3-section,
  .v3-frame-group--broker-final > .v3-section + .v3-section {
    border-top-color: rgba(255, 255, 255, 0.12);
  }

  .v3-frame-group .v3-eyebrow {
    margin-bottom: clamp(8px, 2.2vw, 12px);
    font-size: 11px;
  }

  .v3-frame-group .v3-h2 {
    font-size: clamp(1.55rem, 7vw, 2.35rem);
    line-height: 1.08;
    margin-bottom: clamp(12px, 3vw, 18px);
  }

  .v3-frame-group .v3-lede,
  .v3-frame-group .v3-body {
    font-size: clamp(0.9375rem, 3.5vw, 1.05rem);
    line-height: 1.45;
    margin-bottom: clamp(12px, 3vw, 20px);
  }

  .v3-frame-group .v3-feature-row,
  .v3-frame-group .v3-stats,
  .v3-frame-group .v3-usps,
  .v3-frame-group .v3-process {
    margin-top: clamp(14px, 3.5vw, 22px);
  }

  .v3-frame-group .v3-feature,
  .v3-frame-group .v3-stat,
  .v3-frame-group .v3-usp,
  .v3-frame-group .v3-process__step {
    gap: clamp(8px, 2.4vw, 12px);
    padding: clamp(18px, 5vw, 24px);
    border-radius: 18px;
  }

  .v3-frame-group .v3-feature__icon,
  .v3-frame-group .v3-process__icon,
  .v3-frame-group .v3-feature__icon-wrap,
  .v3-frame-group .v3-process__icon-wrap {
    margin-bottom: 0;
  }

  .v3-frame-group .v3-feature h3,
  .v3-frame-group .v3-usp h3,
  .v3-frame-group .v3-process__step h3 {
    font-size: clamp(1.05rem, 4.5vw, 1.3rem);
    line-height: 1.15;
  }

  .v3-frame-group .v3-feature p,
  .v3-frame-group .v3-usp p,
  .v3-frame-group .v3-process__step p,
  .v3-frame-group .v3-stat__label {
    font-size: clamp(0.8125rem, 3.2vw, 0.9rem);
    line-height: 1.45;
  }

  .v3-frame-group .v3-stat__num {
    font-size: clamp(1.55rem, 7vw, 2.15rem);
    letter-spacing: -0.025em;
  }

  .v3-frame-group .mobile-swipe-indicator {
    margin-top: 0;
  }

  .v3-frame-group--invest-final .v3-section--cta .v3-section__inner,
  .v3-frame-group--broker-final .v3-section--cta .v3-section__inner,
  .v3-frame-group--buy-final .v3-section__inner {
    gap: clamp(14px, 3vw, 20px);
  }

  .v3-frame-group--invest-final .v3-section--cta .v3-h2,
  .v3-frame-group--broker-final .v3-section--cta .v3-h2 {
    max-width: 18ch;
    margin-bottom: 0;
  }
  /* Targeted burger-overlap fix for `.reveal` (homepage ROI/first-
     call section, "Your first call with Namou is where the numbers
     get real."), reported as having the burger menu cover the title
     on phones. The base mobile pad-y of clamp(52px, 13vw, 76px)
     gives 52–76px of top padding — the burger pill at 16px from top
     extends to ~68px, so 52–56px of pad-top isn't enough to clear
     it. Bumping just `.reveal` to the larger nav-offset clamp
     instead of overpadding every mobile section globally. */
  .reveal {
    padding-top: var(--v3-mobile-nav-offset);
  }

  .section.v3-frame,
  .section--lanes,
  .home-faq,
  .home-news,
  .reveal,
  .v3-section:not(.v3-hero):not(.v3-section--strip):not(#inventory),
  .v3-frame-group > .v3-section:not(.v3-section--strip):not(#inventory) {
    display: flex;
    flex-direction: column;
    justify-content: center;
  }

  .call-showcase {
    min-height: 100svh;
  }

  .v3-section__inner,
  .section__inner {
    width: 100%;
  }

  .v3-case__grid {
    gap: 22px;
  }

  .v3-case__feature {
    min-height: clamp(320px, 78vw, 420px);
  }

  .v3-case__cards,
  .section--lanes .lanes,
  .v3-frame-group--sell-method .v3-feature-row--method,
  .v3-frame-group--invest-intro .v3-feature-row,
  .v3-frame-group--invest-final .v3-usps,
  .v3-frame-group--broker-pair .v3-feature-row,
  .v3-frame-group--broker-pair-2 .v3-feature-row {
    display: flex;
    grid-template-columns: none;
    gap: 16px;
    overflow-x: auto;
    overflow-y: hidden;
    scroll-snap-type: x mandatory;
    scroll-padding-inline: var(--v3-pad-x);
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    margin-inline: calc(var(--v3-pad-x) * -1);
    padding-inline: var(--v3-pad-x);
    padding-bottom: 8px;
  }

  .v3-case__cards::-webkit-scrollbar,
  .section--lanes .lanes::-webkit-scrollbar,
  .v3-frame-group--sell-method .v3-feature-row--method::-webkit-scrollbar,
  .v3-frame-group--invest-intro .v3-feature-row::-webkit-scrollbar,
  .v3-frame-group--invest-final .v3-usps::-webkit-scrollbar,
  .v3-frame-group--broker-pair .v3-feature-row::-webkit-scrollbar,
  .v3-frame-group--broker-pair-2 .v3-feature-row::-webkit-scrollbar {
    display: none;
  }

  .v3-case__card,
  .section--lanes .lane,
  .v3-frame-group--sell-method .v3-feature-row--method > .v3-feature,
  .v3-frame-group--invest-intro .v3-feature-row > .v3-feature,
  .v3-frame-group--invest-final .v3-usps > .v3-usp,
  .v3-frame-group--broker-pair .v3-feature-row > .v3-feature,
  .v3-frame-group--broker-pair-2 .v3-feature-row > .v3-feature {
    flex: 0 0 var(--v3-mobile-card-span);
    scroll-snap-align: start;
  }

  /* Paired mobile frames should not stack two swipe carousels back to
     back. Keep the first/top section as cards, then render the
     companion section as compact rows in the same visual footprint. */
  .v3-frame-group--sell-method .v3-process__cards-row,
  .v3-frame-group--invest-intro .v3-stats,
  .v3-frame-group--broker-pair-1 > .v3-section:nth-child(2) .v3-feature-row,
  .v3-frame-group--broker-pair-2 .v3-process__cards-row {
    display: grid;
    grid-template-columns: 1fr;
    gap: clamp(8px, 2vh, 12px);
    overflow: visible;
    scroll-snap-type: none;
    margin-inline: 0;
    padding-inline: 0;
    padding-bottom: 0;
    border: 0;
  }

  .v3-frame-group--sell-method .v3-process__cards-row > .v3-process__step,
  .v3-frame-group--invest-intro .v3-stats > .v3-stat,
  .v3-frame-group--broker-pair-1 > .v3-section:nth-child(2) .v3-feature-row > .v3-feature,
  .v3-frame-group--broker-pair-2 .v3-process__cards-row > .v3-process__step {
    flex: none;
    width: 100%;
    min-height: clamp(58px, 8.5vh, 82px);
    scroll-snap-align: none;
    background: transparent;
    border: 0;
    border-bottom: 1px solid var(--v3-rule);
    border-radius: 0;
    box-shadow: none;
  }

  .v3-frame-group--sell-method .v3-process__cards-row > .v3-process__step {
    border-bottom-color: rgba(255, 255, 255, 0.14);
  }

  .v3-frame-group--sell-method .v3-process__cards-row > .v3-process__step:last-child,
  .v3-frame-group--invest-intro .v3-stats > .v3-stat:last-child,
  .v3-frame-group--broker-pair-1 > .v3-section:nth-child(2) .v3-feature-row > .v3-feature:last-child,
  .v3-frame-group--broker-pair-2 .v3-process__cards-row > .v3-process__step:last-child {
    border-bottom: 0;
  }

  .v3-frame-group--sell-method .v3-process__cards-row + .mobile-swipe-indicator,
  .v3-frame-group--invest-intro .v3-stats + .mobile-swipe-indicator,
  .v3-frame-group--broker-pair-1 > .v3-section:nth-child(2) .v3-feature-row + .mobile-swipe-indicator,
  .v3-frame-group--broker-pair-2 .v3-process__cards-row + .mobile-swipe-indicator {
    display: none;
  }

  .v3-frame-group--sell-method .v3-process__cards-row > .v3-process__step,
  .v3-frame-group--broker-pair-2 .v3-process__cards-row > .v3-process__step {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    align-items: center;
    column-gap: clamp(12px, 3.4vw, 18px);
    text-align: left;
    padding: clamp(12px, 3.4vw, 16px) clamp(14px, 4vw, 18px);
  }

  .v3-frame-group--sell-method .v3-process__cards-row .v3-process__icon-wrap,
  .v3-frame-group--broker-pair-2 .v3-process__cards-row .v3-process__icon-wrap {
    grid-row: 1 / span 3;
    margin: 0;
  }

  .v3-frame-group--sell-method .v3-process__cards-row .v3-process__step h3,
  .v3-frame-group--broker-pair-2 .v3-process__cards-row .v3-process__step h3 {
    margin: 0;
  }

  .v3-frame-group--sell-method .v3-process__cards-row .v3-process__divider,
  .v3-frame-group--broker-pair-2 .v3-process__cards-row .v3-process__divider {
    display: none;
  }

  .v3-frame-group--sell-method .v3-process__cards-row .v3-process__step p,
  .v3-frame-group--broker-pair-2 .v3-process__cards-row .v3-process__step p {
    margin-top: 3px;
    max-width: none;
  }

  .v3-frame-group--broker-pair-1 > .v3-section:nth-child(2) .v3-feature-row > .v3-feature {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    align-items: center;
    column-gap: clamp(12px, 3.4vw, 18px);
    text-align: left;
    padding: clamp(12px, 3.4vw, 16px) clamp(14px, 4vw, 18px);
  }

  .v3-frame-group--broker-pair-1 > .v3-section:nth-child(2) .v3-feature__icon {
    grid-row: 1 / span 2;
    margin: 0;
  }

  .v3-frame-group--broker-pair-1 > .v3-section:nth-child(2) .v3-feature h3,
  .v3-frame-group--broker-pair-1 > .v3-section:nth-child(2) .v3-feature p {
    margin: 0;
  }

  .v3-frame-group--broker-pair-1 > .v3-section:nth-child(2) .v3-feature p {
    margin-top: 3px;
  }

  .v3-frame-group--invest-intro .v3-stats > .v3-stat {
    display: grid;
    grid-template-columns: minmax(4.5ch, auto) minmax(0, 1fr);
    align-items: center;
    column-gap: clamp(12px, 3.4vw, 18px);
    text-align: left;
    padding: clamp(12px, 3.4vw, 16px) clamp(14px, 4vw, 18px);
  }

  .v3-frame-group--invest-intro .v3-stat__num,
  .v3-frame-group--invest-intro .v3-stat__label {
    margin: 0;
  }

  .mobile-swipe-indicator {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 2px;
    min-height: 44px;
    margin: 8px auto 0;
  }

  .mobile-swipe-dot {
    appearance: none;
    -webkit-appearance: none;
    display: grid;
    place-items: center;
    width: 44px;
    height: 44px;
    padding: 0;
    border: 0;
    border-radius: 999px;
    background: transparent;
    cursor: pointer;
  }

  .mobile-swipe-dot::before {
    content: "";
    width: 7px;
    height: 7px;
    border-radius: 999px;
    background: rgba(18, 18, 18, 0.24);
    transition: width 180ms var(--ease), background-color 180ms var(--ease), opacity 180ms var(--ease);
  }

  .mobile-swipe-dot.is-active::before {
    width: 22px;
    background: var(--accent);
  }

  .mobile-swipe-dot:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
  }

  .v3-frame-group--sell-method .mobile-swipe-dot::before,
  .v3-frame-group--invest-final .mobile-swipe-dot::before,
  .v3-frame-group--broker-pair-1 .mobile-swipe-dot::before {
    background: rgba(255, 255, 255, 0.32);
  }

  .v3-frame-group--sell-method .mobile-swipe-dot.is-active::before,
  .v3-frame-group--invest-final .mobile-swipe-dot.is-active::before,
  .v3-frame-group--broker-pair-1 .mobile-swipe-dot.is-active::before {
    background: var(--mint);
  }

  .v3-frame-group--sell-method .v3-process__nav-row,
  .v3-frame-group--broker-pair-2 .v3-process__nav-row {
    display: none;
  }

  .section--lanes .lane {
    min-height: clamp(360px, 72svh, 500px);
    padding: clamp(28px, 8vw, 40px);
  }

  .reveal__inner {
    width: min(100%, 640px);
    gap: 32px;
  }

  .reveal__left {
    gap: 28px;
  }

  .call-showcase {
    padding-block: 40px;
    gap: 34px;
  }

  .call-showcase__copy p,
  .call-showcase__list {
    margin-bottom: 26px;
  }

  .call-showcase__list li {
    margin-bottom: 14px;
  }

  .call-showcase .call-frame {
    max-width: min(100%, 300px);
  }

  .v3-sell-final-grid {
    gap: 18px;
  }

  .v3-cta-panel--sell-final {
    order: -1;
  }

  .v3-cta-panel {
    padding: clamp(24px, 7vw, 34px) clamp(20px, 6vw, 28px);
  }

  .home-faq .faq__item summary {
    padding-block: 14px;
  }

  .mobile-contact-bar {
    display: none !important;
  }

  body {
    padding-bottom: 0;
  }

  /* Floating WhatsApp button on mobile — push to the bottom-right
     corner so it doesn't float midway up over major-section content.
     The base `.wa-float { bottom: 96px }` was tuned for desktop where
     it cleared the hero marquee strip; on mobile the button reads as
     an obstruction over hero/section text. `env(safe-area-inset-
     bottom)` keeps a margin from the iOS home indicator and Android
     gesture bar; `right: clamp(16px, 4vw, 24px)` keeps a consistent
     thumb-zone-friendly inset. The mobile-contact-bar that the prior
     `bottom: 96px` was clearing has `display: none !important` on
     mobile via the existing rule above, so there's no conflict. */
  .wa-float {
    display: flex !important;
    bottom: calc(env(safe-area-inset-bottom, 0px) + 20px);
    right: clamp(16px, 4vw, 24px);
  }

  .nav__toggle,
  .home-news__arrow,
  .home-news__dot {
    min-width: 44px;
    min-height: 44px;
  }

  .home-news__arrow {
    width: 44px;
    height: 44px;
  }

  .home-news__dot {
    position: relative;
    display: grid;
    place-items: center;
    width: 44px;
    height: 44px;
    background: transparent;
  }

  .home-news__dot::before {
    content: "";
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: rgba(18, 18, 18, 0.18);
    transition: background-color 0.3s ease, transform 0.3s ease;
  }

  .home-news__dot:hover::before {
    background: rgba(18, 18, 18, 0.4);
  }

  .home-news__dot.is-active::before {
    background: var(--ink);
    transform: scale(1.25);
  }

  .v3-frame-group--home-final .home-news__dot::before {
    background: rgba(255, 255, 255, 0.28);
  }

  .v3-frame-group--home-final .home-news__dot.is-active::before {
    background: var(--mint);
  }

  /* === Mobile content distribution for V3 major sections ===
     The min-height: 100svh + symmetric padding rule above gives each
     major section a focused screenful, but with `justify-content:
     center` on the section, its single inner block sat as a centered
     cluster — leaving a large empty band above and below. This pass
     stretches the inner to fill the section, then pushes the section's
     "body" element (carousel, grid, process row, stats row, etc.) to
     the bottom of the inner. The head (eyebrow + title + lede) stays
     at the natural top, the body fills the lower half, swipe
     indicators stay close to their carousel, and the empty-bottom
     gap collapses. Single-child inners (e.g. `.v3-sell-final-section`)
     keep `justify-content: center` and stay centered as a whole. */
  .section.v3-frame > .section__inner,
  .section--lanes > .section__inner,
  .home-faq > .home-faq__inner,
  .home-news > .home-news__inner,
  .reveal > .reveal__inner,
  .v3-section:not(.v3-hero):not(.v3-section--strip):not(#inventory) > .v3-section__inner,
  .v3-frame-group > .v3-section:not(.v3-section--strip):not(#inventory) > .v3-section__inner {
    flex: 1 1 auto;
    width: 100%;
    display: flex;
    flex-direction: column;
    justify-content: center;
  }

  /* Sections with a clear "head + carousel/grid" pattern push the body
     element to the bottom of the inner — head at top, carousel near
     the bottom, swipe indicator (auto-inserted by JS as the next
     sibling) stays close to its carousel. Sections with a tighter
     label-to-content relationship (FAQ accordion, news carousel with
     dots-nav, CTA-only sections) intentionally fall through to the
     centered default above so the title + content read as one
     cluster rather than being split apart by an awkward middle gap. */
  .v3-section__inner > .v3-feature-row:not(:first-child),
  .v3-section__inner > .v3-process:not(:first-child),
  .v3-section__inner > .v3-stats:not(:first-child),
  .v3-section__inner > .v3-usps:not(:first-child),
  .section.v3-frame.v3-case > .section__inner > .v3-case__grid:not(:first-child),
  .section--lanes > .section__inner > .lanes:not(:first-child) {
    margin-top: auto;
  }
  /* `.reveal__showcase` previously had `margin-top: auto` (was in the
     selector list above) which pushed the ROI-simulator mockup hard
     to the bottom of the section. Combined with the inner's
     `justify-content: center` on the text cluster above, that produced
     a large empty band in the middle of the mobile frame — text near
     top, mockup near bottom. Switch the inner to `space-evenly` so the
     two children (`.reveal__left` text/CTA cluster + `.reveal__showcase`
     mockup) distribute evenly through the viewport: ~1/3 above, ~1/3
     between, ~1/3 below. Eliminates the empty-middle gap without
     redesigning the section. */
  .reveal > .reveal__inner {
    justify-content: space-evenly;
  }

  /* Buy-final ("Brief us. We source against your criteria.") — text +
     CTA only. Push the CTA row to the bottom so the head copy sits at
     the top and the action lands at the bottom of the visual frame. */
  .v3-frame-group--buy-final > .v3-section > .v3-section__inner > .v3-cta-row:not(:first-child) {
    margin-top: auto;
  }

  /* Invest-intro stats section: `.v3-stats` already pushes itself
     down via the body rule above; the trailing `.v3-cta-row` should
     sit close to the stats group, not absorb its own auto. The
     standard 16-28px gap reads as one bottom cluster (stats +
     indicator + CTA). */
  .v3-frame-group--invest-intro > .v3-section.v3-section--alt > .v3-section__inner > .v3-cta-row {
    margin-top: clamp(16px, 2.5vh, 28px);
  }

  /* Unify the `.v3-frame-group--invest-intro` mobile rendering as ONE
     continuous major section. Without these overrides the second
     child section carries `.v3-section--alt` (mint-white background
     from the global rule at line 694) while the first child section
     uses the page-default white — that background colour difference
     reads as a divider line on mobile, splitting the frame into
     "two stacked sections" instead of one unified Invest-intro.
     Forcing both children to a transparent background lets the
     frame-group's natural page background bleed through both,
     producing one continuous white surface. Padding-block on each
     child is also tightened so the two clusters sit closer
     together with no awkward empty band between them. */
  .v3-frame-group--invest-intro > .v3-section,
  .v3-frame-group--invest-intro > .v3-section.v3-section--alt {
    background: transparent;
  }
  .v3-frame-group--invest-intro > .v3-section {
    padding-block: clamp(20px, 3vh, 32px);
  }
  /* First section gets a slightly larger top pad so its eyebrow/h2
     clears the burger + logo pills at the top of the frame. */
  .v3-frame-group--invest-intro > .v3-section:first-child {
    padding-top: clamp(40px, 6vh, 64px);
  }

  /* Buy-page `.call-showcase` is its own flex container (no inner
     wrapper), so the inner-distribution rule above does not apply.
     Switch to a column flow on mobile and distribute the copy at the
     top with the deck frames at the bottom. */
  .call-showcase {
    flex-direction: column;
    flex-wrap: nowrap;
    align-items: stretch;
    justify-content: space-between;
    gap: clamp(28px, 5vh, 48px);
  }
  .call-showcase > .call-showcase__copy,
  .call-showcase > .call-showcase__frames {
    flex: 0 0 auto;
    max-width: 100%;
    width: 100%;
  }
}

@media (max-width: 430px) {
  :root {
    --v3-mobile-card-span: min(84vw, 326px);
  }

  .v3-case__feature {
    min-height: 300px;
  }

  .section--lanes .lane {
    min-height: 380px;
  }
}

/* V2 comparison contrast rules. Light surfaces use black supporting
   copy. Dark major sections use white copy, with eyebrow/accent text
   kept green. Scoped here so legacy route remains redirected. */
:root {
  --v2-text-on-light: #000000;
  --v2-text-on-dark: #ffffff;
  --v2-accent-on-dark: var(--mint);
}

.hero__subtitle,
.v3-lede,
.v3-body,
.v3-prose p,
.v3-case__lede,
.v3-case__card-body,
.reveal__lede,
.lane__body,
.bento__body,
.home-news__card-body,
.home-insights__card-body p,
.call-showcase__copy p,
.call-showcase__list li,
.call-frame__cap,
.v3-card__body,
.v3-router__body p,
.v3-stat__label,
.v3-stats__caption,
.v3-trust__cell p,
.v3-feature p,
.v3-usp p,
.v3-process__step p,
.v3-faq__a,
.faq__body,
.v3-table__note,
.v3-areas__caption,
.v3-plot__meta,
.v3-plot__price,
.v3-empty p,
.v3-model p,
.v3-deal__stats dt,
.v3-cred p,
.v3-rep__copy p,
.v3-partner p,
.v3-terms p,
.v3-deck-walk__step p,
.footer p,
.footer h4,
.footer__brand p,
.footer__col a,
.footer__col span,
.footer__col h4,
.footer__bottom,
.footer__bottom span,
.footer__bottom a,
.footer__map a,
figcaption {
  color: var(--v2-text-on-light) !important;
}

:is(
  .reveal,
  .section--lanes,
  .call-showcase,
  .cta-final,
  .v3-frame-group--home-final,
  .v3-frame-group--sell-method,
  #strategies.v3-section.v3-frame,
  .v3-frame-group--invest-final,
  .v3-frame-group--broker-pair-1,
  .v3-frame-group--broker-final,
  .v3-frame-group--buy-final,
  .v3-frame-group--home-final > .footer,
  .v3-frame-group--buy-final > .footer,
  .v3-frame-group--invest-final > .footer,
  .v3-frame-group--broker-final > .footer
) :is(
  h1,
  h2,
  h3,
  h4,
  p,
  li,
  figcaption,
  .hero__subtitle,
  .v3-lede,
  .v3-body,
  .v3-prose p,
  .v3-case__feature-text,
  .v3-case__card-body,
  .reveal__lede,
  .lane__body,
  .home-news__card-body,
  .call-showcase__copy p,
  .call-showcase__list li,
  .call-frame__cap,
  .v3-card__body,
  .v3-stat__label,
  .v3-trust__cell p,
  .v3-feature p,
  .v3-usp p,
  .v3-process__step p,
  .v3-model p,
  .v3-cred p,
  .v3-partner p,
  .v3-terms p,
  .v3-deck-walk__step p,
  .footer__brand p,
  .footer__col a,
  .footer__col span,
  .footer__bottom,
  .footer__bottom span,
  .footer__map a
) {
  color: var(--v2-text-on-dark) !important;
}

:is(
  .reveal,
  .section--lanes,
  .call-showcase,
  .cta-final,
  .v3-frame-group--home-final,
  .v3-frame-group--sell-method,
  #strategies.v3-section.v3-frame,
  .v3-frame-group--invest-final,
  .v3-frame-group--broker-pair-1,
  .v3-frame-group--broker-final,
  .v3-frame-group--buy-final,
  .v3-frame-group--home-final > .footer,
  .v3-frame-group--buy-final > .footer,
  .v3-frame-group--invest-final > .footer,
  .v3-frame-group--broker-final > .footer
) :is(
  .v3-eyebrow,
  .v3-case__eyebrow,
  .reveal__eyebrow,
  .lane__heading,
  .home-news__card-meta,
  .v3-feature__icon,
  .v3-process__icon,
  .v3-process__num,
  .v3-usp__num,
  .v3-model__label,
  .material-symbols-outlined
) {
  color: var(--v2-accent-on-dark) !important;
}

/* Lane card hover: invert the entire content of the hovered lane to
   dark text on the light card surface. Spells out every text node
   the lane carries by class so it beats both the global on-dark
   "text inside section--lanes" override AND the legacy .lane:hover
   .lane__body rule in styles.css that was forcing the body line
   back to translucent white on hover. */
.section--lanes .lane:hover,
.section--lanes .lane:hover *,
.section--lanes .lane:hover .lane__eyebrow,
.section--lanes .lane:hover .lane__body,
.section--lanes .lane:hover p,
.section--lanes .lane:hover h3,
.section--lanes .lane:hover span,
.section--lanes .lane:hover .btn--ghost {
  color: var(--v2-text-on-light) !important;
}
.section--lanes .lane:hover .lane__heading,
.section--lanes .lane:hover .lane__heading * {
  color: var(--accent-deep, var(--accent)) !important;
}
.section--lanes .lane:hover .btn--ghost {
  border-color: var(--rule, rgba(0, 0, 0, 0.18)) !important;
}
.section--lanes .lane:hover .btn--ghost:hover {
  background: var(--ink) !important;
  border-color: var(--ink) !important;
}
.section--lanes .lane:hover .btn--ghost:hover,
.section--lanes .lane:hover .btn--ghost:hover * {
  color: #ffffff !important;
}

/* Mobile broker process: render the steps as rows, not swipe columns. */
@media (max-width: 768px) {
  .v3-frame-group--broker-pair-2 .v3-process.v3-process--timeline .v3-process__nav-row,
  .v3-frame-group--broker-pair-2 .v3-process__cards-row + .mobile-swipe-indicator {
    display: none !important;
  }

  .v3-frame-group--broker-pair-2 .v3-process.v3-process--timeline .v3-process__cards-row,
  .v3-frame-group--broker-pair-2 .v3-process.v3-process--timeline.v3-process--4 .v3-process__cards-row {
    display: flex !important;
    flex-direction: column !important;
    gap: 0 !important;
    width: 100% !important;
    overflow: visible !important;
    scroll-snap-type: none !important;
    margin: clamp(16px, 3vh, 24px) 0 0 !important;
    padding: 0 !important;
    border: 0 !important;
  }

  .v3-frame-group--broker-pair-2 .v3-process.v3-process--timeline .v3-process__cards-row > .v3-process__step {
    display: grid !important;
    grid-template-columns: clamp(44px, 12vw, 56px) minmax(0, 1fr) !important;
    align-items: center !important;
    column-gap: clamp(12px, 4vw, 18px) !important;
    width: 100% !important;
    min-width: 0 !important;
    min-height: clamp(76px, 12vh, 104px) !important;
    flex: 0 0 auto !important;
    padding: clamp(14px, 3.8vw, 18px) 0 !important;
    text-align: left !important;
    scroll-snap-align: none !important;
    border: 0 !important;
    border-bottom: 1px solid var(--v3-rule) !important;
    border-radius: 0 !important;
    background: transparent !important;
    box-shadow: none !important;
  }

  .v3-frame-group--broker-pair-2 .v3-process.v3-process--timeline .v3-process__cards-row > .v3-process__step:last-child {
    border-bottom: 0 !important;
  }

  .v3-frame-group--broker-pair-2 .v3-process.v3-process--timeline .v3-process__cards-row > .v3-process__step::before {
    display: none !important;
  }

  .v3-frame-group--broker-pair-2 .v3-process__cards-row .v3-process__icon-wrap {
    grid-column: 1 !important;
    grid-row: 1 / span 3 !important;
    justify-self: center !important;
    margin: 0 !important;
  }

  .v3-frame-group--broker-pair-2 .v3-process__cards-row .v3-process__step h3 {
    grid-column: 2 !important;
    margin: 0 !important;
    text-align: left !important;
  }

  .v3-frame-group--broker-pair-2 .v3-process__cards-row .v3-process__step p {
    display: block !important;
    grid-column: 2 !important;
    max-width: none !important;
    margin: 4px 0 0 !important;
    text-align: left !important;
  }

  .v3-frame-group--broker-pair-2 .v3-process__cards-row .v3-process__divider {
    display: none !important;
  }
}

/* ============================================================
   RESPONSIVE SAFETY NET
   ------------------------------------------------------------
   Defensive rules to prevent overflow / overlap at sub-desktop
   widths regardless of the specific layout each section uses.
   These are intentionally low-specificity so any section-specific
   rule above can still override them when needed.
   ============================================================ */

/* Universal box-model + horizontal overflow guard. Body never
   scrolls horizontally even if a child briefly exceeds the
   viewport while a webfont swaps in. */
html, body { max-width: 100%; overflow-x: hidden; }
*, *::before, *::after { box-sizing: border-box; }

/* Images and embedded media never overflow their container, and
   their height auto-scales so the aspect ratio is preserved when
   only width is constrained (or vice versa). */
img, picture, svg, video, iframe {
  max-width: 100%;
  height: auto;
}

/* Long, unbreakable strings (URLs in copy, e-mail addresses,
   numeric IDs) shouldn't push their container wider than the
   viewport. `overflow-wrap: anywhere` lets the browser break
   mid-word as a last resort instead of overflowing. */
p, h1, h2, h3, h4, h5, h6, li, dd, dt, blockquote, figcaption,
.v3-h1, .v3-h2, .v3-lede, .v3-body,
.v3-case__feature-title, .v3-case__feature-text,
.v3-cta-panel__title, .v3-cta-panel__sub,
.lane__heading, .lane__body, .footer__col a, .footer__col span {
  overflow-wrap: anywhere;
  word-break: normal;
}

/* Tablet range (769-1023px) — fall back to a single column for
   the small handful of grids whose desktop track widths can
   exceed the available width once the column gap is added. */
@media (min-width: 769px) and (max-width: 1023px) {
  .v2-contact-split,
  .v3-frame-group--broker-inventory-flow,
  .v3-frame-group--invest-intro {
    grid-template-columns: 1fr !important;
    display: block !important;
  }
}

/* Hero copy block keeps a sane reading width at tablet widths
   even if the hero variant doesn't explicitly cap it. */
@media (max-width: 1023px) {
  .v3-hero--full .v3-hero__copy {
    max-width: min(720px, 92vw);
    padding-inline: clamp(16px, 4vw, 32px);
  }
}

/* Small-mobile (≤768px) — slightly shrink the largest display
   typography so the H1 doesn't run off the right edge or pile up
   into the nav pill. Line-height is tightened from the default
   1.05 so a 2-line H1 occupies a more compact vertical box and
   doesn't visually crowd the lede below it. */
@media (max-width: 768px) {
  .v3-h1 {
    font-size: clamp(1.875rem, 7.5vw, 2.5rem);
    line-height: 1.1;
  }
  .v3-h2 {
    font-size: clamp(1.5rem, 6vw, 2.125rem);
    line-height: 1.15;
  }
  .v3-hero--full .v3-hero__copy { padding-inline: 16px; }
}
@media (max-width: 480px) {
  .v3-h1 { font-size: clamp(1.625rem, 7.8vw, 2.125rem); }
  .v3-h2 { font-size: clamp(1.375rem, 6.5vw, 1.875rem); }
}

/* ========================================================
   Language toggle (i18n) + RTL support
   ======================================================== */

/* Desktop chip — sits at the right end of the .nav pill area.
   Pinned to the same row as the centred .nav__links pill. */
.lang-toggle {
  position: absolute;
  top: 8px;
  right: clamp(24px, 3vw, 56px);
  z-index: 1001;
  pointer-events: auto;
}
/* Toggle chip — mirrors the centre .nav__links pill exactly so the
   right-hand language control reads as a paired sibling of the
   audience menu: same min-height (48px), same padding (0 22px),
   same font-size (13px), same translucent-green pill. Carries the
   active language abbreviation only — no icon, no label word. */
.lang-toggle__btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 48px;
  padding: 0 22px;
  background: rgba(0, 61, 46, 0.62);
  -webkit-backdrop-filter: blur(14px) saturate(140%);
  backdrop-filter: blur(14px) saturate(140%);
  border: 1px solid rgba(0, 61, 46, 0.55);
  border-radius: 999px;
  box-shadow: 0 8px 32px rgba(0, 61, 46, 0.24);
  color: #fff;
  font: 500 13px "DM Sans", sans-serif;
  letter-spacing: 0.02em;
  cursor: pointer;
}
.lang-toggle__current {
  display: inline-block;
  min-width: 18px;
  text-align: center;
  font-weight: 500;
  letter-spacing: 0.02em;
}
.lang-toggle__menu {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  min-width: 160px;
  margin: 0;
  padding: 8px;
  list-style: none;
  background: rgba(0, 61, 46, 0.92);
  -webkit-backdrop-filter: blur(14px) saturate(140%);
  backdrop-filter: blur(14px) saturate(140%);
  border: 1px solid rgba(0, 61, 46, 0.55);
  border-radius: 18px;
  box-shadow: 0 12px 32px rgba(0, 61, 46, 0.28);
  opacity: 0;
  pointer-events: none;
  transform: translateY(-4px);
  transition: opacity 160ms ease, transform 160ms ease;
}
.lang-toggle.is-open .lang-toggle__menu {
  opacity: 1;
  pointer-events: auto;
  transform: translateY(0);
}
.lang-toggle__item {
  display: block;
  width: 100%;
  padding: 10px 12px;
  background: transparent;
  border: 0;
  border-radius: 12px;
  color: #fff;
  font: 500 14px "DM Sans", sans-serif;
  text-align: left;
  cursor: pointer;
  transition: background 140ms ease;
}
.lang-toggle__item:hover,
.lang-toggle__item[aria-current="true"] {
  background: rgba(255, 255, 255, 0.12);
}
.lang-toggle__item[aria-current="true"] {
  font-weight: 600;
}

/* Mobile chip is added inside the open mobile menu drawer */
.mobile-lang {
  margin-top: 24px;
  padding-top: 16px;
  border-top: 1px solid rgba(255, 255, 255, 0.18);
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.mobile-lang__label {
  margin: 0 0 4px;
  font: 500 12px "DM Sans", sans-serif;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  opacity: 0.72;
}
.mobile-lang__item {
  display: block;
  width: 100%;
  padding: 10px 0;
  background: transparent;
  border: 0;
  text-align: inherit;
  color: inherit;
  font: 500 16px "DM Sans", sans-serif;
  cursor: pointer;
}
.mobile-lang__item[aria-current="true"] { font-weight: 700; }

@media (max-width: 768px) {
  /* Mobile: language chip sits next to the burger button, sized
     visibly smaller than the burger so it occupies minimal space
     in the nav row. The drawer block (.mobile-lang) is removed in
     favour of this always-visible chip. */
  .lang-toggle {
    display: block;
    /* Vertically centred against the 54px burger: (54-40)/2 = 7px.
       Right offset clears the 54px burger + 16px nav inset + 10px
       gap = 80px from the right edge. */
    top: 7px;
    right: 80px;
  }
  .lang-toggle__btn {
    min-height: 40px;
    padding: 0 14px;
    font-size: 12px;
    letter-spacing: 0.04em;
    box-shadow: 0 6px 20px rgba(0, 61, 46, 0.22);
  }
  .lang-toggle__current { min-width: 16px; }
  .lang-toggle__menu {
    min-width: 130px;
    padding: 6px;
  }
  .lang-toggle__item {
    padding: 9px 10px;
    font-size: 13px;
  }
  .mobile-lang { display: none !important; }
  /* RTL on mobile: full mirror of the nav row. Logo flips to the
     right edge, burger flips to the left edge, language chip sits
     immediately to the right of the burger. Dropdown menu opens
     down-and-to-the-right of the chip. */
  html[dir="rtl"] .nav__logo {
    left: auto;
    right: 16px;
  }
  html[dir="rtl"] .nav__toggle {
    right: auto;
    left: 16px;
  }
  html[dir="rtl"] .lang-toggle {
    right: auto;
    left: 80px;
  }
  html[dir="rtl"] .lang-toggle__menu {
    right: auto;
    left: 0;
  }
  html[dir="rtl"] .lang-toggle__item { text-align: right; }
}

/* ---------- RTL (Arabic) overrides ---------- */
html[dir="rtl"] body { text-align: right; }
html[dir="rtl"] .nav__logo { left: auto; right: clamp(24px, 3vw, 56px); }
html[dir="rtl"] .lang-toggle { right: auto; left: clamp(24px, 3vw, 56px); }
html[dir="rtl"] .lang-toggle__menu { right: auto; left: 0; }
html[dir="rtl"] .lang-toggle__item { text-align: right; }
html[dir="rtl"] .v3-hero__copy,
html[dir="rtl"] .v3-section__inner { text-align: center; }
html[dir="rtl"] .v3-cta-row svg { transform: scaleX(-1); }
html[dir="rtl"] .footer__inner { direction: rtl; }
html[dir="rtl"] .footer__col,
html[dir="rtl"] .footer__map { text-align: right; }
/* Mobile-specific RTL flip for .nav__toggle and .nav__logo lives
   inside the @media (max-width: 768px) block above. The old
   top-level rule that set .nav__toggle to right: 16px on RTL
   used to be correct when the LTR burger was anchored left; with
   the LTR burger now on the right, the same flip makes the
   Arabic burger collide with the logo on the right edge. Keep
   only the mobile-home-pill flip which is mobile-only by markup. */
html[dir="rtl"] .mobile-home-pill { left: 16px; right: auto; }

/* ========================================================
   Per-language anti-overlap typography
   --------------------------------------------------------
   Arabic carries tashkeel/diacritics that sit above and
   below the baseline, Chinese characters are denser, and
   Russian words are longer than their English equivalents.
   Bump line-height a touch on non-English locales so
   adjacent lines never crowd into the next. Scoped via
   the [data-lang] attribute set on <html> by i18n.js.
   ======================================================== */
html[data-lang="ar"] body,
html[data-lang="hi"] body,
html[data-lang="zh"] body,
html[data-lang="ru"] body {
  line-height: 1.7;
}
html[data-lang="ar"] .v3-h1,
html[data-lang="ar"] .v3-h2,
html[data-lang="ar"] .v3-h3,
html[data-lang="ar"] .hero__title,
html[data-lang="ar"] .v3-case__title,
html[data-lang="ar"] .v3-case__feature-title,
html[data-lang="ar"] .lane__eyebrow,
html[data-lang="ar"] .lane__heading,
html[data-lang="hi"] .v3-h1,
html[data-lang="hi"] .v3-h2,
html[data-lang="hi"] .v3-h3,
html[data-lang="hi"] .hero__title,
html[data-lang="hi"] .v3-case__title,
html[data-lang="hi"] .v3-case__feature-title,
html[data-lang="hi"] .lane__eyebrow,
html[data-lang="hi"] .lane__heading,
html[data-lang="zh"] .v3-h1,
html[data-lang="zh"] .v3-h2,
html[data-lang="zh"] .v3-h3,
html[data-lang="zh"] .hero__title,
html[data-lang="zh"] .v3-case__title,
html[data-lang="zh"] .v3-case__feature-title,
html[data-lang="zh"] .lane__eyebrow,
html[data-lang="zh"] .lane__heading,
html[data-lang="ru"] .v3-h1,
html[data-lang="ru"] .v3-h2,
html[data-lang="ru"] .v3-h3,
html[data-lang="ru"] .hero__title,
html[data-lang="ru"] .v3-case__title,
html[data-lang="ru"] .v3-case__feature-title,
html[data-lang="ru"] .lane__eyebrow,
html[data-lang="ru"] .lane__heading {
  line-height: 1.25;
}
html[data-lang="ar"] .v3-lede,
html[data-lang="ar"] .v3-body,
html[data-lang="ar"] .hero__subtitle,
html[data-lang="ar"] .v3-case__lede,
html[data-lang="ar"] .v3-case__feature-text,
html[data-lang="ar"] .lane__body,
html[data-lang="ar"] .reveal__lede,
html[data-lang="ar"] .footer p,
html[data-lang="ar"] .footer span,
html[data-lang="ar"] .footer a,
html[data-lang="hi"] .v3-lede,
html[data-lang="hi"] .v3-body,
html[data-lang="hi"] .hero__subtitle,
html[data-lang="hi"] .v3-case__lede,
html[data-lang="hi"] .v3-case__feature-text,
html[data-lang="hi"] .lane__body,
html[data-lang="hi"] .reveal__lede,
html[data-lang="zh"] .v3-lede,
html[data-lang="zh"] .v3-body,
html[data-lang="zh"] .hero__subtitle,
html[data-lang="zh"] .v3-case__lede,
html[data-lang="zh"] .v3-case__feature-text,
html[data-lang="zh"] .lane__body,
html[data-lang="zh"] .reveal__lede,
html[data-lang="ru"] .v3-lede,
html[data-lang="ru"] .v3-body,
html[data-lang="ru"] .hero__subtitle,
html[data-lang="ru"] .v3-case__lede,
html[data-lang="ru"] .v3-case__feature-text,
html[data-lang="ru"] .lane__body,
html[data-lang="ru"] .reveal__lede {
  line-height: 1.7;
}
/* Arabic-only: cards and step blocks need extra breathing room
   because the diacritics can otherwise touch the card borders. */
html[data-lang="ar"] .v3-feature,
html[data-lang="ar"] .v3-card,
html[data-lang="ar"] .v3-process__step,
html[data-lang="ar"] .v3-cta-panel__copy,
html[data-lang="ar"] .v3-cta-panel__reassure li,
html[data-lang="ar"] .footer__col,
html[data-lang="ar"] .v3-cta-row .btn {
  letter-spacing: 0;
}
html[data-lang="ar"] .v3-cta-panel__reassure li {
  gap: 12px;
  line-height: 1.6;
}
html[data-lang="ar"] .marquee__item,
html[data-lang="ar"] .v3-marquee__item {
  letter-spacing: 0;
}
