
      :root {
        --ink: #1e1e1e;
        --paper: #fdfdfd;
        --font: "Archivo", system-ui, -apple-system, "Segoe UI", sans-serif;
      }
      * { box-sizing: border-box; }
      html, body { margin: 0; padding: 0; }
      body {
        font-family: var(--font);
        background: var(--ink);
        color: #fff;
        -webkit-font-smoothing: antialiased;
      }

      /* ----- Proportional frame scaling -----
         Mash (2026-10-21): "jokhon screen choto hocche tokhon
         content beshi boro lagteche" — on smaller screens the
         content looks too big. The design is a fixed 1600px
         Figma frame; between 1200px and 1599px viewport width
         the whole page scales DOWN proportionally (factor ≈
         viewport / 1600, in steps — the same bands as the
         cleaned project's body zoom) so type, cards, photos
         and spacing all shrink TOGETHER and the proportions
         stay exactly the design's. At ≥1600px the page renders
         at native size (never scaled up). Below 1200px scaling
         is OFF: the stacked responsive layouts rule there,
         including the Section 5 rule that the team text must
         NOT shrink (headline stays 44px at 800/400px widths).
         The pointer-driven scripts that mix client coordinates
         with layout pixels (Section 8 image trail, Section 5
         carousel drag) divide by the same factor — see
         pageZoom() in those scripts. */
      @media (min-width: 1440px) and (max-width: 1599.98px) {
        body { zoom: 0.92; }
      }
      @media (min-width: 1280px) and (max-width: 1439.98px) {
        body { zoom: 0.84; }
      }
      @media (min-width: 1200px) and (max-width: 1279.98px) {
        body { zoom: 0.78; }
      }
      /* Header-logo exemption (Mash, 2026-10-21: "header bar er
         logo ta choto lagteche oita ager size e rakho" — the
         header logo looks small, keep it at the previous size).
         The HEADER BAR logo only (the homepage header and the
         Sell view header — the same 95×48 logo) counter-zooms by
         the inverse of each band's factor, so it renders at its
         native 95×48 in every band while everything else keeps
         scaling. Mirrors the cleaned project's .header-logo
         rules. The loader logo and the footer logo are NOT
         exempt — Mash named the header bar only. */
      @media (min-width: 1440px) and (max-width: 1599.98px) {
        .header-logo { zoom: 1.087; }
      }
      @media (min-width: 1280px) and (max-width: 1439.98px) {
        .header-logo { zoom: 1.19; }
      }
      @media (min-width: 1200px) and (max-width: 1279.98px) {
        .header-logo { zoom: 1.282; }
      }
      a { color: inherit; text-decoration: none; }
      img { display: block; }

      /* ---------- Section 1 — Hero ---------- */
      .hero {
        position: relative;
        display: flex;
        flex-direction: column;
        min-height: 100vh;
        min-height: 100svh;
        overflow: hidden;
        background: var(--ink);
      }
      .hero-bg {
        position: absolute;
        inset: 0;
        width: 100%;
        height: 100%;
        object-fit: cover;
        object-position: center;
      }
      .hero-shade {
        position: absolute;
        inset: 0;
        background: linear-gradient(
          180deg,
          rgba(1, 17, 22, 0.68) 0.12%,
          rgba(3, 17, 21, 0.19) 21.54%,
          rgba(5, 17, 21, 0) 44.52%,
          #1e1e1e 101.85%
        );
      }

      /* ----- Header ----- */
      .site-header {
        position: relative;
        z-index: 10;
        margin: 0 auto;
        width: 100%;
        max-width: 1600px;
        display: flex;
        flex-wrap: wrap;
        align-items: center;
        gap: 16px 24px;
        padding: 32px 24px 0;
      }
      .header-left {
        display: flex;
        align-items: center;
        gap: 40px;
      }
      .logo { flex-shrink: 0; line-height: 0; }
      .logo img {
        width: 95px;
        height: 48px;
        object-fit: contain;
      }
      .main-nav { display: none; align-items: center; gap: 19px; }
      .nav-pill {
        position: relative;
        overflow: hidden;
        border: 1px solid var(--paper);
        border-radius: 999px;
        padding: 8px 16px;
        font-size: 18px;
        white-space: nowrap;
        color: #fff;
      }
      .header-rule {
        display: none;
        height: 1px;
        min-width: 32px;
        flex: 1;
        margin: 0 8px;
        background: rgba(255, 255, 255, 0.8);
      }

      /* ----- Pill CTA + arrow circle (shared) ----- */
      .cta { display: inline-flex; align-items: center; flex-shrink: 0; }
      .cta-pill {
        position: relative;
        overflow: hidden;
        display: flex;
        align-items: center;
        height: 48px;
        border-radius: 999px;
        padding: 10px 20px;
        font-size: 16px;
        font-weight: 500;
        line-height: 1.2;
        white-space: nowrap;
      }
      .cta-arrow {
        position: relative;
        overflow: hidden;
        display: grid;
        place-items: center;
        width: 48px;
        height: 48px;
        flex-shrink: 0;
        border-radius: 50%;
        background: #fff;
      }
      .cta-arrow svg { display: block; }
      .cta-reserve { margin-left: auto; }
      .cta-reserve .cta-pill {
        background: #fff;
        border: 1px solid #fff;
        color: #000;
        line-height: 1.4;
      }
      .cta-submit .cta-pill { background: #fff; color: var(--ink); }

      /* ----- ONE shared hover effect for every button -----
         Mash's rule (2026-10-20): ALL buttons, ONE effect. Every
         CTA — header Reserve a call, hero Submit your Property,
         Services Sell a Property, both Get Started buttons and
         the service-card pills — uses the exact same hover: the
         pill lifts up with a soft shadow, a shine sweep crosses
         it, the label ROLLS (shared .roll-label, see Section 3)
         and the arrow circle nudges diagonally while its arrow
         RELOADS (shared .cta-arrow-track below). Colours adapt
         to each button's own scheme; the motion never differs. */
      .nav-pill,
      .cta-pill,
      .cta-arrow {
        transition:
          background 0.35s ease,
          color 0.35s ease,
          transform 0.35s cubic-bezier(0.22, 1, 0.36, 1),
          box-shadow 0.35s ease;
      }
      .nav-pill::after,
      .cta-pill::after {
        content: "";
        position: absolute;
        top: 0;
        bottom: 0;
        left: -70%;
        width: 45%;
        background: linear-gradient(100deg, transparent, rgba(30, 30, 30, 0.16), transparent);
        transform: skewX(-20deg);
        transition: left 0.6s ease;
        pointer-events: none;
      }
      .nav-pill:hover, .nav-pill:focus-visible {
        background: #fff;
        color: var(--ink);
        transform: translateY(-3px);
        box-shadow: 0 14px 34px rgba(0, 0, 0, 0.35);
      }
      .cta:hover .cta-pill, .cta:focus-visible .cta-pill {
        background: transparent;
        color: #fff;
        transform: translateY(-3px);
        box-shadow: 0 14px 34px rgba(0, 0, 0, 0.35), inset 0 0 0 1px #fff;
      }
      .cta:hover .cta-arrow, .cta:focus-visible .cta-arrow {
        transform: translate(3px, -3px);
        box-shadow: 0 14px 34px rgba(0, 0, 0, 0.35);
      }
      .nav-pill:hover::after, .nav-pill:focus-visible::after,
      .cta:hover .cta-pill::after, .cta:focus-visible .cta-pill::after { left: 130%; }

      /* ----- Arrow "reload" on hover (both CTA arrow circles) -----
         Transition-driven, not a keyframe animation: the circle
         holds a track with two arrows. On hover the track slides
         diagonally — the first arrow exits toward the top-right
         (clipped by the circle) while the second rolls in from the
         bottom-left. On mouse leave the same transition runs in
         reverse, so the arrow always glides back to its resting
         position, even if the pointer leaves mid-flight. */
      .cta-arrow-track {
        position: relative;
        width: 48px;
        height: 48px;
        transition: transform 0.45s cubic-bezier(0.22, 1, 0.36, 1);
      }
      .cta-arrow-track svg { position: absolute; inset: 0; }
      .cta-arrow-track svg:last-child { transform: translate(-32px, 32px); }
      .cta:hover .cta-arrow-track, .cta:focus-visible .cta-arrow-track {
        transform: translate(32px, -32px);
      }

      /* ----- Bottom block ----- */
      .hero-bottom {
        position: relative;
        z-index: 10;
        margin: 0 auto;
        width: 100%;
        max-width: 1600px;
        perspective: 900px;
        flex: 1;
        display: flex;
        flex-direction: column;
        justify-content: flex-end;
        gap: 40px;
        padding: 96px 24px 40px;
      }
      .hero-copy {
        display: flex;
        flex-direction: column;
        align-items: flex-start;
        gap: 16px;
        max-width: 994px;
      }
      .hero-copy h1 {
        margin: 0;
        font-size: 36px;
        line-height: 1.08;
        font-weight: 600;
        color: #fff;
      }
      /* Line 2 serif segment: "we help with the" is Playfair
         Display italic medium in the design (Mash, 2026-10-21) —
         same split-serif pattern as the Section 8 banner headline.
         "Next chapter." stays Archivo semibold. */
      .hero-copy h1 .serif-it {
        font-family: "Playfair Display", Georgia, "Times New Roman", serif;
        font-style: italic;
        font-weight: 500;
      }
      /* A small left pad on line 2's mask (cancelled by margin)
         keeps the italic entry glyph from clipping against the
         mask edge; the settled layout is unchanged. */
      .rv-line-serif {
        padding-left: 0.08em;
        margin-left: -0.08em;
      }
      .hero-sub {
        display: flex;
        flex-direction: column;
        gap: 24px;
      }
      .hero-sub p {
        margin: 0;
        max-width: 716px;
        font-size: 16px;
        font-weight: 300;
        line-height: 1.5;
        color: #fff;
      }

      /* ----- 197K+ card ----- */
      .trust-card {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        gap: 16px;
        width: 100%;
        max-width: 292px;
        flex-shrink: 0;
        border: 1px solid rgba(255, 255, 255, 0.2);
        border-radius: 36px;
        background: var(--ink);
        padding: 8px 8px 16px;
      }
      .trust-card > img {
        width: 100%;
        height: 168px;
        border-radius: 28px;
        object-fit: cover;
      }
      .trust-row { display: flex; align-items: center; gap: 12px; }
      .avatar-stack { display: flex; align-items: center; }
      .avatar-photo {
        width: 48px;
        height: 48px;
        border-radius: 50%;
        border: 2px solid #fff;
        object-fit: cover;
        background: #15161b;
      }
      .avatar-photo + .avatar-photo { margin-left: -16px; }
      .trust-row p {
        margin: 0;
        width: 168px;
        font-size: 16px;
        font-weight: 500;
        line-height: 1.4;
        color: #fff;
      }

      /* ---------- Loader ----------
         Mash's Figma prototype (2026-10-20): a PLAIN BLACK screen
         with the SR Property logo centred — nothing else. No
         progress bar, no cycling words, no percentage.
         EXIT (Mash, 2026-10-20, correcting "the whole screen left
         at once"): the black screen is SIX equal vertical panels.
         They leave ONE BY ONE, leftmost first, with increasing
         delays — panel 1 starts at 0.6s, panel 2 at 0.8s, then
         +0.2s each (1.0 / 1.2 / 1.4 / 1.6s) — each panel sliding
         UP out of the screen over ~0.5s, so the exit cascades
         left -> right like a staircase (the stepped black blocks
         at the top of his prototype recording) and the hero is
         revealed beneath. The logo sits on its own layer above
         the panels and fades out as the first panels start
         moving. The hero entrance begins as the panels clear. */
      body.is-loading { overflow: hidden; }
      .loader {
        position: fixed;
        inset: 0;
        z-index: 100;
        display: flex;
        align-items: center;
        justify-content: center;
      }
      body.is-exiting .loader { pointer-events: none; }
      .loader-panel {
        position: absolute;
        top: 0;
        bottom: 0;
        width: 16.67%;
        background: #000;
        transition: transform 0.5s cubic-bezier(0.76, 0, 0.24, 1);
      }
      .loader-panel:nth-child(1) { left: 0;        transition-delay: 0.6s; }
      .loader-panel:nth-child(2) { left: 16.667%;  transition-delay: 0.8s; }
      .loader-panel:nth-child(3) { left: 33.333%;  transition-delay: 1s; }
      .loader-panel:nth-child(4) { left: 50%;      transition-delay: 1.2s; }
      .loader-panel:nth-child(5) { left: 66.667%;  transition-delay: 1.4s; }
      .loader-panel:nth-child(6) { left: 83.333%;  transition-delay: 1.6s; }
      body.is-exiting .loader-panel { transform: translateY(-101%); }
      .loader-logo {
        position: relative;
        z-index: 1;
        width: 150px;
        height: auto;
        animation: loaderIn 0.7s cubic-bezier(0.22, 1, 0.36, 1) backwards;
        transition: opacity 0.45s ease 0.55s;
      }
      body.is-exiting .loader-logo { opacity: 0; }
      @keyframes loaderIn {
        from { opacity: 0; transform: scale(0.94) translateY(8px); }
        to { opacity: 1; transform: scale(1) translateY(0); }
      }

      /* ---------- Entrance choreography ----------
         Mash's rules (2026-10-20, from his Figma prototype video):
         elements do NOT all come in at once — they enter ONE BY
         ONE (staggered). They do NOT all come from the same
         position/direction — each element slides in from the
         OUTSIDE direction nearest its final position:
           - logo (top-left)        -> from the top-left
           - nav pills (top centre) -> drop in from the top
           - header divider         -> draws in with the header
           - Reserve a call (right) -> from the right
           - headline (left column) -> line by line (text in pieces)
           - paragraph              -> from the left
           - Submit CTA             -> from the left
           - 197K+ card (bottom-right) -> from the bottom-right
         TEXT animates in pieces too: headline line 1 rises out of
         its mask, then line 2, then the paragraph — never all the
         text at once. Everything is snappy (settled ~2.9s after the
         entrance starts, as the loader panels clear), clean
         single-element slides only — no Figma
         prototype crossfade/ghosting artifacts. Once settled, JS
         adds body.rv-done so the buttons get back their fast hover
         timing, and the card starts its float + cursor tilt. */
      body.is-loaded .hero-bg { animation: bgSettle 1.8s cubic-bezier(0.22, 1, 0.36, 1) both; }
      @keyframes bgSettle {
        from { transform: scale(1.18); filter: brightness(0.5); }
        to { transform: scale(1); filter: brightness(1); }
      }
      .fx {
        opacity: 0;
        transition:
          opacity var(--dur, 0.8s) ease,
          transform var(--dur, 0.8s) var(--ease, cubic-bezier(0.16, 1, 0.3, 1));
        transition-delay: var(--d, 0s);
        will-change: transform, opacity;
      }
      .fx-left { transform: translateX(-44px); }
      .fx-topleft { transform: translate(-40px, -28px); }
      .fx-right { transform: translateX(44px); }
      .fx-drop { transform: translateY(-30px); --ease: cubic-bezier(0.34, 1.25, 0.64, 1); }
      .fx-corner { transform: translate(64px, 48px); --dur: 0.85s; }
      body.is-loaded .fx { opacity: 1; transform: translate(0, 0) scale(1); }
      /* Once the entrance is done, hand the buttons back their fast
         hover timing (no stagger delay, no slow entrance curve). */
      body.rv-done .fx {
        transition:
          background 0.35s ease,
          color 0.35s ease,
          transform 0.35s cubic-bezier(0.22, 1, 0.36, 1),
          box-shadow 0.35s ease,
          opacity 0.35s ease;
        transition-delay: 0s;
      }
      .rv-line {
        display: block;
        overflow: hidden;
        padding-bottom: 0.12em;
        margin-bottom: -0.12em;
      }
      .rv-line > span {
        display: block;
        transform: translateY(115%);
        transition: transform var(--dur, 0.9s) var(--ease, cubic-bezier(0.16, 1, 0.3, 1));
        transition-delay: var(--d, 0s);
        will-change: transform;
      }
      body.is-loaded .rv-line > span { transform: translateY(0); }
      .header-rule {
        transform: scaleX(0);
        transform-origin: left center;
        transition: transform 1s cubic-bezier(0.22, 1, 0.36, 1) 0.7s;
      }
      body.is-loaded .header-rule { transform: scaleX(1); }
      /* 197K+ card: gentle up-down float loop after it lands, with a
         slight turn toward the cursor folded in through --tilt-x /
         --tilt-y (JS eases those once the card has landed). Kept
         deliberately small — a hint of movement, not a swing. */
      .trust-card.is-floating { animation: cardFloat 5s ease-in-out infinite; }
      @keyframes cardFloat {
        0%, 100% { transform: translateY(0) rotateX(var(--tilt-x, 0deg)) rotateY(var(--tilt-y, 0deg)); }
        50% { transform: translateY(-9px) rotateX(var(--tilt-x, 0deg)) rotateY(var(--tilt-y, 0deg)); }
      }

      @media (prefers-reduced-motion: reduce) {
        .loader { display: none; }
        .loader-logo,
        body.is-loaded .hero-bg, .trust-card.is-floating { animation: none; }
        .cta-arrow-track { transition: none; }
        .cta:hover .cta-arrow-track, .cta:focus-visible .cta-arrow-track,
        .svc-card:hover .cta-arrow-track, .svc-card:focus-visible .cta-arrow-track { transform: none; }
        .fx, .rv-line > span, .header-rule {
          opacity: 1;
          transform: none;
          transition: none;
        }
        body.rv-done .fx { transition: none; }
      }

      @media (min-width: 768px) {
        .site-header { padding: 32px 40px 0; }
        .main-nav { display: flex; }
        .hero-bottom { padding: 96px 40px 40px; }
        .hero-copy h1 { font-size: 48px; }
        .hero-sub { flex-direction: row; align-items: center; justify-content: space-between; }
      }
      @media (min-width: 1024px) {
        .site-header { padding: 43px 72px 0; flex-wrap: nowrap; }
        .header-left { gap: 82px; }
        .header-rule { display: block; }
        .cta-reserve { margin-left: 0; }
        .hero-bottom {
          flex-direction: row;
          align-items: flex-end;
          justify-content: space-between;
          padding: 96px 72px 56px;
        }
      }
      @media (min-width: 1280px) {
        .hero-copy h1 { font-size: 64px; }
      }

      /* ---------- Section 2 — About us + Services ----------
         Same system as the hero: 1600px container, 24/40/72px side
         padding, Archivo, white on --ink. The "Sell a Property" CTA
         reuses the hero's .cta / .cta-pill / .cta-arrow /
         .cta-arrow-track classes, so the shared hover and arrow
         reload apply unchanged. The service cards use their own
         single-node morphing CTA (see .svc-top-cta below). */
      .about-services { background: var(--ink); }
      .s2-wrap {
        margin: 0 auto;
        width: 100%;
        max-width: 1600px;
        padding-left: 24px;
        padding-right: 24px;
      }
      .sec-label {
        margin: 0;
        font-size: 24px;
        font-weight: 700;
        color: #fff;
      }
      .body-text {
        margin: 0;
        font-size: 16px;
        font-weight: 300;
        line-height: 1.5;
        color: #fff;
      }

      /* ----- About us ----- */
      .about { padding-top: 96px; }
      .about-grid {
        display: flex;
        flex-direction: column;
        gap: 48px;
      }
      .about-left {
        display: flex;
        flex-direction: column;
        gap: 40px;
        width: 100%;
        max-width: 520px;
      }
      .about-right {
        display: flex;
        flex-direction: column;
        align-items: flex-start;
        gap: 24px;
        width: 100%;
        max-width: 742px;
      }
      .about-headline {
        margin: 0;
        font-size: 30px;
        font-weight: 500;
        line-height: 1.15;
        color: #fff;
      }
      .social-row { display: flex; align-items: center; gap: 12px; }
      .social-circle {
        display: grid;
        place-items: center;
        width: 36px;
        height: 36px;
        flex-shrink: 0;
        border: 1px solid #fff;
        border-radius: 50%;
        color: #fff;
        transition: background 0.35s ease, color 0.35s ease;
      }
      .social-circle:hover, .social-circle:focus-visible {
        background: #fff;
        color: var(--ink);
      }

      /* ----- Services / Choose your path ----- */
      .services { padding-top: 96px; padding-bottom: 96px; }
      .svc-head {
        display: flex;
        flex-direction: column;
        gap: 40px;
      }
      .svc-head-left {
        display: flex;
        flex-direction: column;
        align-items: flex-start;
        gap: 24px;
      }
      .svc-headline {
        margin: 0;
        max-width: 373px;
        font-size: 30px;
        font-weight: 500;
        line-height: 1.15;
        color: #fff;
      }
      .svc-head-right {
        display: flex;
        flex-direction: column;
        align-items: flex-start;
        gap: 24px;
      }
      .svc-head-right .body-text { max-width: 414px; }
      .svc-grid {
        /* FRAME MODEL (Mash, 2026-10-20, from his Figma screenshots):
           the cards live in an auto-layout row frame that keeps
           EXTRA SPACE AT THE TOP — 64px of reserved padding-top — so
           a lifting card never clashes with the header text above.
           The reserved padding is TRANSPARENT (no fill) — the section
           background shows through. UPDATED (Mash, 2026-10-20,
           annotated screenshot): the gap between the heading block
           and the cards needed MORE space (124–132px total), so the
           row now has a 64px margin-top — the net heading-to-card
           gap is 128px (64 reserve + 64 margin) while the lift
           reserve stays 64px. Card gaps widened for breathing room
           on smaller screens: 32px base, 40px at lg, 48px at xl. */
        margin-top: 64px;
        padding-top: 64px;
        display: grid;
        align-items: end;
        gap: 32px;
      }
      .svc-card {
        position: relative;
        display: block;
        height: 380px;
        border-radius: 32px;
        overflow: hidden;
        background: #111010;
        transition: transform 0.3s ease;
      }
      /* The photo fills the WHOLE card. The card's height never
         changes (always 430px on desktop), so the photo can never
         stretch or leave an empty strip — the lift is a pure
         translate into the grid's reserved top space. */
      .svc-card > img {
        position: absolute;
        left: 0;
        right: 0;
        top: 0;
        width: 100%;
        height: 100%;
        object-fit: cover;
      }
      /* Default overlay: bottom gradient (transparent -> #111010),
         191px tall. On hover it is swapped for the flat overlay. */
      .svc-shade {
        position: absolute;
        left: 0;
        right: 0;
        bottom: 0;
        height: 191px;
        background: linear-gradient(180deg, rgba(17, 16, 16, 0) 3.31%, #111010 100%);
        transition: opacity 0.3s ease;
      }
      .svc-card:hover .svc-shade, .svc-card:focus-visible .svc-shade { opacity: 0; }
      /* Hover overlay: black/55 starting at top 239px (desktop)
         and running ALL the way to the card's bottom edge — the
         shade must not stop mid-card and the bottom must never look
         empty/bright on hover. Since the card is always 430px tall,
         239px + 191px lands exactly on the bottom edge; mobile
         keeps the same bottom-anchored placement. UPDATED (Mash,
         2026-10-20, annotated screenshot): the top edge must FADE
         in, never a sharp line — transparent at the top edge,
         reaching full strength after 64px, then solid to the
         bottom edge so the text zone stays fully dark. UPDATED
         (Mash, 2026-10-20): full strength raised from black/40 to
         black/55 — the white text was not always readable over
         bright photo areas; the 64px top fade is unchanged. */
      .svc-flat {
        position: absolute;
        left: 0;
        right: 0;
        bottom: 0;
        height: 191px;
        background: linear-gradient(180deg, rgba(0, 0, 0, 0) 0px, rgba(0, 0, 0, 0.55) 64px, rgba(0, 0, 0, 0.55) 100%);
        opacity: 0;
        transition: opacity 0.3s ease;
      }
      .svc-card:hover .svc-flat, .svc-card:focus-visible .svc-flat { opacity: 1; }
      /* Card top-right CTA — per Mash's hover-state export code
         (2026-10-20), which supersedes the earlier screenshot-based
         glass reading. Default: ONE white circle, dark ↗ arrow, and
         ONE pill clipped away behind it. Hover: the pill GROWS OUT
         from the circle — a clip-path reveal anchored at the right
         edge expands it leftward to full width while it fades in.
         The pill is SOLID WHITE, 48px tall, dark #1E1E1E 16px
         medium text (Sell pill = 182px wide in the export; the
         others size by content with px-5). The circle keeps its
         white bg + dark arrow in both states — but on hover the
         arrow now RELOADS exactly like the main buttons' arrows,
         and the pill label ROLLS like the main buttons' text
         effect (Mash, 2026-10-20). Its
         text sits in a fixed-width inner span so the words never
         squish or double. Single nodes only, so nothing crossfades
         or ghosts. Keyboard focus shows the same state;
         mouse-leave / blur mirrors the motion in reverse. */
      .svc-top-cta {
        position: absolute;
        top: 24px;
        right: 24px;
        display: flex;
        align-items: center;
      }
      .svc-pill {
        position: relative;
        overflow: hidden;
        display: flex;
        align-items: center;
        height: 48px;
        padding: 0 20px;
        border-radius: 999px;
        background: #fff;
        font-size: 16px;
        font-weight: 500;
        line-height: 1.2;
        white-space: nowrap;
        color: var(--ink);
        visibility: hidden;
        opacity: 0;
        clip-path: inset(0 0 0 100% round 999px);
        transition:
          clip-path 0.3s ease,
          opacity 0.3s ease,
          visibility 0.3s ease,
          transform 0.35s cubic-bezier(0.22, 1, 0.36, 1),
          box-shadow 0.35s ease;
      }
      /* SAME button effect as the main CTAs (Mash, 2026-10-20 —
         all buttons, one effect): once the pill has grown out it
         also LIFTS with the shared shadow, and a SHINE SWEEPS
         across it — the same ::after sweep as .cta-pill, delayed
         0.2s so the sweep crosses the fully revealed pill. On
         mouse-leave everything glides back with the reveal. */
      .svc-pill::after {
        content: "";
        position: absolute;
        top: 0;
        bottom: 0;
        left: -70%;
        width: 45%;
        background: linear-gradient(100deg, transparent, rgba(30, 30, 30, 0.16), transparent);
        transform: skewX(-20deg);
        transition: left 0.6s ease 0.2s;
        pointer-events: none;
      }
      .svc-card:hover .svc-pill, .svc-card:focus-visible .svc-pill {
        visibility: visible;
        opacity: 1;
        clip-path: inset(0 0 0 0% round 999px);
        transform: translateY(-3px);
        box-shadow: 0 14px 34px rgba(0, 0, 0, 0.35);
      }
      .svc-card:hover .svc-pill::after, .svc-card:focus-visible .svc-pill::after { left: 130%; }
      /* Fixed-width text carrier: the clip reveal passes over it,
         so the label itself never stretches, squishes or doubles.
         UPDATED (Mash, 2026-10-20): the label also performs the
         main buttons' text effect — a ROLL. The carrier clips to
         exactly one line; on card hover the visible copy rolls UP
         out of the clip while a duplicate copy parked directly
         below it rolls IN to take its place; on mouse-leave both
         glide back. Two stacked copies of the same label moved by
         one transform — nothing crossfades or ghosts. */
      .svc-pill-text {
        position: relative;
        display: block;
        overflow: hidden;
        flex-shrink: 0;
        white-space: nowrap;
      }
      .svc-pill-roll {
        display: block;
        transition: transform 0.3s ease;
      }
      .svc-pill-roll-dup {
        position: absolute;
        left: 0;
        right: 0;
        top: 100%;
      }
      .svc-card:hover .svc-pill-roll, .svc-card:focus-visible .svc-pill-roll {
        transform: translateY(-100%);
      }
      /* Sell pill is exactly 182px wide in the export. */
      .svc-pill-sell { width: 182px; justify-content: center; }
      .svc-morph-arrow {
        position: relative;
        z-index: 1;
        display: grid;
        place-items: center;
        width: 48px;
        height: 48px;
        flex-shrink: 0;
        border-radius: 50%;
        overflow: hidden;
        background: #fff;
        color: var(--ink);
        transition: transform 0.35s cubic-bezier(0.22, 1, 0.36, 1), box-shadow 0.35s ease;
      }
      /* Same arrow-circle nudge + shadow as the main buttons'
         .cta-arrow (Mash, 2026-10-20 — all buttons, one effect),
         fired by the card hover like the pill's reveal. */
      .svc-card:hover .svc-morph-arrow, .svc-card:focus-visible .svc-morph-arrow {
        transform: translate(3px, -3px);
        box-shadow: 0 14px 34px rgba(0, 0, 0, 0.35);
      }
      .svc-morph-arrow svg { display: block; }
      /* Arrow RELOAD inside the card circle — the exact main-button
         implementation (Mash, 2026-10-20: the card button's arrow
         reloads like the main buttons' arrows). The circle hosts
         the same .cta-arrow-track as the hero/header CTAs (two
         arrows on one track, 0.45s cubic-bezier(0.22, 1, 0.36, 1));
         on card hover/focus the track slides (32px, -32px): the
         first arrow exits toward the top-right, clipped by the
         circle, while the second rolls in from the bottom-left.
         On mouse-leave the same transition glides it back to
         centre — no snap. */
      .svc-card:hover .cta-arrow-track, .svc-card:focus-visible .cta-arrow-track {
        transform: translate(32px, -32px);
      }
      /* Text block — anchored by its BOTTOM, never by top. As the
         description slides in under the title on hover, the block
         GROWS UPWARD from its fixed bottom line — the bottom edge
         never moves, and the shade behind it always reaches the
         card's bottom edge. UPDATED (Mash, 2026-10-20, annotated
         screenshot + "in card text content reduce bottom padding
         more"): this supersedes his earlier 64px hover rule — the
         anchor drops from 64px to 32px and the inner bottom padding
         is removed (16px top kept, 0 bottom), so the text's last
         line sits 32px above the card's bottom edge in BOTH default
         and hover states (it was ~80px: 64 anchor + 16 inner pad).
         Same 32px bottom offset on mobile (380px cards). */
      .svc-text {
        position: absolute;
        left: 0;
        right: 0;
        bottom: 32px;
        display: flex;
        flex-direction: column;
        align-items: flex-start;
        gap: 12px;
        padding: 16px 32px 0;
      }
      .svc-title {
        font-size: 36px;
        font-weight: 500;
        line-height: 1.15;
        color: #fff;
      }
      /* Description — exactly ONE node inside a grid-rows wrapper
         (0fr -> 1fr, overflow hidden): as the wrapper expands over
         0.3s the text fades in under the title AND slides up into
         place (translateY 14px -> 0, per Mash 2026-10-20: the body
         slides upward from beneath the heading; the wrapper's clip
         keeps it emerging from under the title). Per export: 16px
         Archivo LIGHT (300), white, full width of the px-8 block. */
      .svc-desc-wrap {
        display: grid;
        grid-template-rows: 0fr;
        transition: grid-template-rows 0.3s ease;
      }
      .svc-card:hover .svc-desc-wrap, .svc-card:focus-visible .svc-desc-wrap {
        grid-template-rows: 1fr;
      }
      .svc-desc {
        display: block;
        min-height: 0;
        overflow: hidden;
        font-size: 16px;
        font-weight: 300;
        line-height: 1.5;
        color: #fff;
        opacity: 0;
        transform: translateY(14px);
        transition: opacity 0.3s ease, transform 0.3s ease;
      }
      .svc-card:hover .svc-desc, .svc-card:focus-visible .svc-desc {
        opacity: 1;
        transform: translateY(0);
      }

      /* ----- Scroll animation for Section 2 -----
         Mash's entrance language, applied on scroll (2026-10-20):
         blocks do NOT appear all at once — their pieces come in
         ONE BY ONE (staggered via --sd), each sliding in from the
         OUTSIDE direction nearest its final position, and text in
         pieces rather than all at once:
           - About: left-column pieces from the LEFT (label, then
             paragraph); the right headline from the RIGHT; then
             the social icons tick in one by one.
           - Services header: left pieces from the LEFT (label,
             then headline); right pieces from the RIGHT (intro
             paragraph, then the Sell a Property pill).
           - Service cards: rise from BELOW, left to right.
         Triggered per block by IntersectionObserver (script at the
         end of the body) adding .in — each sequence runs ONCE;
         scrolling back up never hides anything again. Pieces are
         CSS animations with backwards fill: during a piece's delay
         it holds its hidden from-state, and once its animation
         ends it rests on its natural styles, so hover behaviour
         (card lift, pills, social circles) is never fought by a
         leftover reveal transform. Distances are modest (36px
         from the sides, 40px rise) with a fade, same ease and
         snappy feel as the hero entrance. */
      .sp { opacity: 0; }
      .srev.in .sp { opacity: 1; }
      .srev.in .sp-l { animation: spFromLeft 0.75s cubic-bezier(0.16, 1, 0.3, 1) var(--sd, 0s) backwards; }
      .srev.in .sp-r { animation: spFromRight 0.75s cubic-bezier(0.16, 1, 0.3, 1) var(--sd, 0s) backwards; }
      @keyframes spFromLeft {
        from { opacity: 0; transform: translateX(-36px); }
        to { opacity: 1; transform: translateX(0); }
      }
      @keyframes spFromRight {
        from { opacity: 0; transform: translateX(36px); }
        to { opacity: 1; transform: translateX(0); }
      }
      /* Service cards are their own blocks and rise from below;
         once the rise animation ends, the card's base transform
         transition owns the hover lift again — no fight. */
      .svc-card.srev { opacity: 0; }
      .svc-card.srev.in {
        opacity: 1;
        animation: spFromBelow 0.8s cubic-bezier(0.16, 1, 0.3, 1) var(--sd, 0s) backwards;
      }
      @keyframes spFromBelow {
        from { opacity: 0; transform: translateY(40px); }
        to { opacity: 1; transform: translateY(0); }
      }

      @media (prefers-reduced-motion: reduce) {
        .sp, .svc-card.srev { opacity: 1; }
        .srev.in .sp-l, .srev.in .sp-r, .svc-card.srev.in { animation: none; }
        .svc-card, .svc-shade, .svc-flat, .svc-text, .svc-pill, .svc-pill-roll, .svc-desc-wrap, .svc-desc { transition: none; }
        .svc-card.in:hover, .svc-card.in:focus-visible { transform: none; }
        .svc-desc { transform: none; }
        .svc-card:hover .svc-pill-roll, .svc-card:focus-visible .svc-pill-roll { transform: none; }
        .svc-card:hover .svc-pill, .svc-card:focus-visible .svc-pill,
        .svc-card:hover .svc-morph-arrow, .svc-card:focus-visible .svc-morph-arrow { transform: none; }
      }

      @media (min-width: 640px) {
        .svc-head-right { flex-direction: row; align-items: center; }
      }
      @media (min-width: 768px) {
        .s2-wrap { padding-left: 40px; padding-right: 40px; }
        .about-headline, .svc-headline { font-size: 44px; }
        .svc-grid { grid-template-columns: repeat(2, 1fr); }
      }
      @media (min-width: 1024px) {
        .s2-wrap { padding-left: 72px; padding-right: 72px; }
        .about { padding-top: 140px; }
        .about-grid {
          flex-direction: row;
          align-items: center;
          justify-content: space-between;
        }
        .about-left { gap: 100px; }
        .services { padding-top: 216px; padding-bottom: 120px; }
        .svc-head {
          flex-direction: row;
          align-items: flex-end;
          justify-content: space-between;
        }
        .svc-grid { gap: 40px; }
        .svc-card { height: 430px; }
        /* Desktop LIFT (frame model): the visible card is ALWAYS
           430px tall — no height growth. On hover/focus it
           translates UP exactly 64px into the grid's reserved top
           padding (the same 64px as the hover frame's bottom
           padding in Figma). Its vacated bottom zone shows the dark
           section background; the card settles back cleanly on
           mouse-leave. The flat hover shade runs from top 239px to
           the card's bottom edge; the default gradient stays in the
           same 239px/191px area. The text block is bottom-anchored
           (bottom: 32px, the base rule) in both states — on hover it
           grows upward as the description appears; no top rules. */
        @media (prefers-reduced-motion: no-preference) {
          .svc-card.in:hover, .svc-card.in:focus-visible {
            transform: translateY(-64px);
          }
        }
        .svc-flat { top: 239px; bottom: 0; height: auto; }
        .svc-shade { top: 239px; bottom: auto; }
      }
      @media (min-width: 1280px) {
        .svc-grid { grid-template-columns: repeat(3, 1fr); gap: 48px; }
      }

      /* ---------- Section 3 — How we work ----------
         Same shell as Sections 1–2 (1600px container via .s2-wrap,
         Archivo, white on --ink), mirroring the cleaned HowWeWork
         component. Header row: label + paragraph + Get Started CTA
         on the left, 44px headline on the right. Below: 4 step
         rows beside a single-photo stack. FIX vs the raw export:
         step 1 is the HIGHLIGHTED row — white background with
         DARK #1E1E1E text (the export had white text on the white
         bg = invisible). The photo area uses percentage geometry
         inside an aspect-ratio box so it scales on mobile, and
         holds ONE photo (the active row's) at the front offset;
         on a step change the new photo pops from scale 0 to 100%.
         overflow-x: clip
         keeps the photos' intentional overhang from ever
         scrolling the page sideways. */
      .how {
        background: var(--ink);
        overflow-x: clip;
        padding-top: 96px;
        padding-bottom: 96px;
      }
      .how-head { display: flex; flex-direction: column; gap: 40px; }
      .how-head-left {
        display: flex;
        flex-direction: column;
        align-items: flex-start;
        gap: 40px;
        width: 100%;
      }
      .how-para-row {
        display: flex;
        flex-direction: column;
        align-items: flex-start;
        gap: 24px;
        width: 100%;
      }
      .how-para-row .body-text { max-width: 414px; }
      .how-headline {
        margin: 0;
        font-size: 30px;
        font-weight: 500;
        line-height: 1.15;
        color: #fff;
      }
      .how-content {
        margin-top: 64px;
        display: flex;
        flex-direction: column;
        gap: 56px;
      }
      .how-steps { display: flex; flex-direction: column; width: 100%; }
      .how-step {
        display: flex;
        flex-direction: column;
        gap: 12px;
        padding: 32px 16px;
      }
      .how-step h3 {
        margin: 0;
        font-size: 32px;
        font-weight: 500;
        line-height: 1.2;
        color: #fff;
      }
      /* BODY TEXT (Mash, 2026-10-20): hidden by DEFAULT — every
         row shows ONLY its title, row 1 included (highlight +
         photo show, but no description until the pointer is
         actually on the row). The text appears only while its
         row is engaged (.how-step-show, toggled by the script):
         the .how-body wrapper grows (grid-template-rows 0fr→1fr)
         while the text slides UP from under the title
         (translateY 14px→0 + fade), clipped inside the wrapper —
         the same text animation as the service cards'
         description. Leaving the row/list animates it back out.
         Colour follows the row state: dark on the white
         highlighted row, white otherwise. */
      .how-body {
        display: grid;
        grid-template-rows: 0fr;
        width: 100%;
        max-width: 435px;
        opacity: 0;
        transition: grid-template-rows 0.3s ease, opacity 0.3s ease;
      }
      .how-step-show .how-body { grid-template-rows: 1fr; opacity: 1; }
      .how-body-clip { display: block; overflow: hidden; min-height: 0; }
      .how-step p {
        margin: 0;
        font-size: 16px;
        font-weight: 300;
        line-height: 1.5;
        color: #fff;
        transform: translateY(14px);
        transition: transform 0.3s ease, color 0.3s ease;
      }
      .how-step-show p { transform: translateY(0); }
      /* HOVER STATE (Mash, 2026-10-20): the white highlight is no
         longer fixed on row 1 — it sits on the ACTIVE row and MOVES.
         Default active = row 1; hovering, focusing or tapping any
         row makes it active (JS toggles .how-step-active, see the
         script at the end of the body). The highlight and the text
         colour crossfade over ~300ms. The row's BODY TEXT is a
         separate state again (.how-step-show): it shows only while
         the pointer/focus is genuinely on the row, so the default
         row-1 state shows highlight + photo but NO description. */
      .how-step {
        transition: background 0.3s ease;
      }
      .how-step h3 {
        transition: color 0.3s ease;
      }
      .how-step-active { background: #fff; }
      .how-step-active h3, .how-step-active p { color: var(--ink); }
      .how-photos {
        position: relative;
        width: 100%;
        max-width: 436px;
        margin: 0 auto;
        aspect-ratio: 436 / 537;
        flex-shrink: 0;
      }
      .how-backing { position: absolute; inset: 0; background: #d9d9d9; }
      /* ONE photo at a time (Mash, 2026-10-20, correcting the
         first build): the ACTIVE row's photo only, straight, at
         the front offset over the grey backing. The tilted
         back/next-photo layer and its crossfade are REMOVED —
         never two photos visible together. When the active row
         changes, JS swaps the img src and re-triggers the pop on
         the wrapper (img-pop keyframes, mirrored from the cleaned
         component's .img-pop in app/globals.css): the incoming
         photo grows from scale 0 to 100% over ~0.45s with a pop
         easing; the outgoing photo is simply gone — no fade. */
      .how-photo {
        position: absolute;
        top: -5%;
        left: -3.4%;
        display: block;
        overflow: hidden;
        width: 106.9%;
        height: 106.5%;
      }
      .how-photo img { width: 100%; height: 100%; object-fit: cover; }
      @keyframes img-pop {
        from { transform: scale(0); }
        to { transform: scale(1); }
      }
      .how-photo-pop {
        animation: img-pop 0.45s cubic-bezier(0.34, 1.4, 0.64, 1) both;
        transform-origin: center;
      }
      /* Step rows reveal from below-left, one by one — Section 2's
         reveal language, new direction variant. */
      .srev.in .sp-b { animation: spFromBelowLeft 0.75s cubic-bezier(0.16, 1, 0.3, 1) var(--sd, 0s) backwards; }
      @keyframes spFromBelowLeft {
        from { opacity: 0; transform: translate(-24px, 32px); }
        to { opacity: 1; transform: translate(0, 0); }
      }
      /* Label roll — THE shared text effect for every CTA pill
         (Mash, 2026-10-20: all buttons, same effect). The visible
         copy rolls up out of the pill's clip while a duplicate
         rolls in beneath it; mouse-leave glides back. Any .cta
         whose pill carries .roll-label gets it — header Reserve
         a call, hero Submit, Services Sell a Property, and both
         Get Started buttons all share this one implementation. */
      .roll-label { position: relative; display: block; overflow: hidden; white-space: nowrap; }
      .roll-label > span { display: block; transition: transform 0.35s cubic-bezier(0.22, 1, 0.36, 1); }
      .roll-label > .roll-dup { position: absolute; left: 0; top: 100%; }
      .cta:hover .roll-label > span, .cta:focus-visible .roll-label > span { transform: translateY(-100%); }

      @media (min-width: 640px) {
        .how-para-row { flex-direction: row; align-items: center; }
        .how-step { padding-top: 44px; padding-bottom: 44px; }
      }
      @media (min-width: 768px) {
        .how-headline { font-size: 44px; }
      }
      @media (min-width: 1024px) {
        .how { padding-top: 120px; padding-bottom: 120px; }
        .how-head {
          flex-direction: row;
          align-items: flex-start;
          justify-content: space-between;
        }
        .how-head-left { max-width: 631px; gap: 81px; }
        .how-headline { max-width: 721px; }
        .how-content {
          margin-top: 120px;
          flex-direction: row;
          align-items: center;
          justify-content: space-between;
        }
        .how-steps { max-width: 914px; }
        .how-step {
          flex-direction: row;
          align-items: center;
          justify-content: space-between;
        }
        .how-photos { margin: 0; }
      }
      @media (prefers-reduced-motion: reduce) {
        .srev.in .sp-b { animation: none; }
        .roll-label > span { transition: none; }
        .cta:hover .roll-label > span, .cta:focus-visible .roll-label > span { transform: none; }
        /* Hover swaps become instant — the highlight colour
           change is immediate and the photo pop is disabled. */
        .how-step, .how-step h3, .how-step p, .how-body { transition: none; }
        .how-photo-pop { animation: none; }
      }

      /* ---------- Section 4 — Light CTA band ----------
         Mirrors the cleaned CtaBand component. CORRECTED
         (Mash, 2026-10-20): the band's background is ONE gradient
         image he designed and supplied (../images/img-01.webp,
         3200×1287 — pale yellow top-left → white centre →
         mint/teal bottom → lavender/purple right), used as-is as
         a full-bleed cover. The earlier build's flat #F2F2F2 fill
         + four separate colour circles were a bad read of that
         gradient and are REMOVED entirely (the export's empty 51%
         overlay div was also a Figma leftover, excluded).
         Content: max-w 1146px centred — a scattered 3-row cloud
         of decorative white tag pills (all STRAIGHT/upright —
         Mash, 2026-10-20, superseding the tilted look in his
         earlier screenshot), then the headline + DARK main
         CTA. The headline repeats Section 3's headline
         word-for-word in the export — kept as exported
         (flagged to Mash). */
      .cta-band {
        position: relative;
        overflow: hidden;
        background: #fff;
        color: var(--ink);
      }
      .cta-bg {
        position: absolute;
        inset: 0;
        width: 100%;
        height: 100%;
        object-fit: cover;
      }
      .cta-inner {
        position: relative;
        margin: 0 auto;
        width: 100%;
        max-width: 1146px;
        display: flex;
        flex-direction: column;
        align-items: center;
        gap: 56px;
        padding: 80px 24px;
      }
      /* Tag cloud — pills are decorative spans, not links.
         UPDATED (Mash's idea, 2026-10-20: "those pills are moving
         like trail in loop"): each row is now a seamless infinite
         MARQUEE. The row clips to the content width (overflow
         hidden); inside it a w-max flex TRACK holds the row's
         pill set TWICE (two identical .tag-group halves) and
         slides translateX to -50% linearly — when the first half
         has scrolled exactly out, the identical second half sits
         where it started, so the loop has no seam and no jump.
         Directions alternate: rows 1 and 3 move LEFT, row 2 moves
         RIGHT (its track runs -50% -> 0). Per-row durations are
         inline (38s / 44s / 42s) — slow and smooth, always moving.
         Hovering a row pauses ONLY that row (see the pause rule
         below); the other rows keep moving.
         Pills keep their vertical scattered offsets while moving
         (the offset is margin-top --ty) and stay STRAIGHT —
         no rotation anywhere (Mash, 2026-10-20). The cloud also
         carries the .trail-fade mask (below) so pills fade into
         the background at both ends instead of being hard-cut.
         The one-time scroll reveal sits on the ROW wrappers
         (.sp-u rise on each .tag-row), the marquee on the inner
         tracks — different nodes, no transform conflict.
         UPDATED (Mash, 2026-10-20, annotated screenshot): the
         per-pill vertical offsets (--ty) are REMOVED — the rows
         must be PERFECTLY LINED, every pill in a row on ONE
         straight line, vertically centred in its row band. The
         track is height:100% + align-items:center and the groups
         centre their pills, exactly like the cleaned CtaBand
         component. */
      .tag-rows {
        display: flex;
        flex-direction: column;
        gap: 12px;
        width: 100%;
      }
      /* Edge fade (Mash, 2026-10-20): pills must not be hard-cut
         at the cloud's left/right ends — the whole cloud carries
         a horizontal fade mask so pills FADE OUT / FADE IN over
         ~80px at each side and blend into the gradient
         background (mirrors .trail-fade in the cleaned code). */
      .trail-fade {
        -webkit-mask-image: linear-gradient(
          to right,
          transparent 0,
          #000 80px,
          #000 calc(100% - 80px),
          transparent 100%
        );
        mask-image: linear-gradient(
          to right,
          transparent 0,
          #000 80px,
          #000 calc(100% - 80px),
          transparent 100%
        );
      }
      .tag-row {
        position: relative;
        overflow: hidden;
        width: 100%;
      }
      .tag-track {
        display: flex;
        width: max-content;
        height: 100%;
        align-items: center;
      }
      .tag-group {
        display: flex;
        align-items: center;
        gap: 0 20px;
        padding-right: 20px;
        flex-shrink: 0;
      }
      @keyframes trail-left {
        to { transform: translateX(-50%); }
      }
      @keyframes trail-right {
        from { transform: translateX(-50%); }
        to { transform: translateX(0); }
      }
      .marquee-l { animation: trail-left 40s linear infinite; }
      .marquee-r { animation: trail-right 46s linear infinite; }
      /* Pause scope (Mash, 2026-10-20): hovering pauses ONLY the
         line under the mouse — the other two rows keep moving.
         (Was: hovering the cloud paused every row.) Moving the
         pointer to another row hands the pause over: the newly
         hovered row stops, the previous one resumes. */
      .tag-row:hover .marquee-l,
      .tag-row:hover .marquee-r { animation-play-state: paused; }
      /* JS-driven scroll-linked marquee (v2.0.2): the driver owns the
         transform, so the CSS loop must stand down when it runs. */
      .js-marquee .tag-track { animation: none; }
      .tag-pill {
        display: inline-flex;
        align-items: center;
        height: 48px;
        padding: 0 20px;
        border: 1px solid var(--ink);
        border-radius: 999px;
        background: #fff;
        font-size: 18px;
        font-weight: 500;
        line-height: 1.2;
        white-space: nowrap;
        color: var(--ink);
      }
      /* Headline + CTA row */
      .cta-band-row {
        display: flex;
        flex-direction: column;
        align-items: center;
        gap: 32px;
        width: 100%;
      }
      .cta-band-headline {
        margin: 0;
        max-width: 721px;
        font-size: 30px;
        font-weight: 500;
        line-height: 1.15;
        text-align: center;
        color: var(--ink);
      }
      /* DARK main CTA — the shared .cta system inverted for the
         light background: solid #1E1E1E pill (200×48, white text)
         and a dark arrow circle with a white arrow. The arrow
         reload (.cta-arrow-track) and label roll (.roll-label)
         behave exactly like the main buttons; only the colours
         and the hover fill/shine are flipped. */
      .cta-dark .cta-pill {
        background: var(--ink);
        color: #fff;
        width: 200px;
        justify-content: center;
      }
      .cta-dark .cta-pill::after {
        background: linear-gradient(100deg, transparent, rgba(255, 255, 255, 0.28), transparent);
      }
      .cta-dark .cta-arrow { background: var(--ink); }
      .cta.cta-dark:hover .cta-pill, .cta.cta-dark:focus-visible .cta-pill {
        background: rgba(30, 30, 30, 0.85);
        color: #fff;
        transform: translateY(-3px);
        box-shadow: 0 14px 34px rgba(0, 0, 0, 0.25);
      }
      /* Scroll reveal — Section 2/3 language, once, via the
         shared .srev observer. TRIGGER FIX (Mash, 2026-10-20:
         "i dont see that scroll animation, when i scroll"): the
         reveal used to sit on the WHOLE .cta-inner (~650px tall),
         so the observer's 15% threshold fired the moment the
         band's top sliver entered the viewport — every piece's
         timer started at once, and on a normal continuous scroll
         the lower pieces (row 3, headline, CTA) finished their
         animations while still below the fold; by the time they
         scrolled into view everything had already settled, so
         the animation was never SEEN. Sections 2–3 never had
         this problem because each block is its own .srev. The
         band now follows the same model — TWO separate .srev
         blocks: the tag cloud (.tag-rows) and the headline+CTA
         row (.cta-band-row), each triggering only when IT
         genuinely enters the viewport. Inside the cloud the
         three tag ROWS rise + fade in one by one (stagger via
         --sd; the reveal sits on the row wrappers while the
         marquee keeps running on the inner tracks — different
         nodes, no transform conflict, and the cloud's
         .trail-fade mask is untouched). Inside the row block the
         headline's TEXT animates in pieces (line by line,
         below), then the CTA from the right. Nothing appears
         all at once. The rise is also made clearly readable
         against the moving marquee + page scroll: 44px over
         0.85s (was a barely visible 18px over 0.6s), same ease
         and language as Sections 2–3 (36–40px, 0.75–0.8s). */
      .srev.in .sp-u { animation: spRise 0.85s cubic-bezier(0.16, 1, 0.3, 1) var(--sd, 0s) backwards; }
      @keyframes spRise {
        from { opacity: 0; transform: translateY(44px); }
        to { opacity: 1; transform: translateY(0); }
      }
      /* Headline TEXT animation — the hero's masked line rise
         (.rv-line), retargeted from the hero's body.is-loaded
         trigger to the band's own .srev.in: each line sits in an
         overflow-hidden mask and its inner span rises from 115%
         when the band reveals, the three lines staggered via
         --ld — the text comes in PIECES, never as one block. The
         lines are the headline's natural desktop breaks (721px
         box at 44px, as in Mash's design screenshot); on narrow
         screens a line wraps inside its mask and still rises as
         one piece. The 0.12em bottom pad, cancelled by the
         negative margin, keeps descenders (p, g, y) from
         clipping in the mask — same construction as the hero. */
      .band-line {
        display: block;
        overflow: hidden;
        padding-bottom: 0.12em;
        margin-bottom: -0.12em;
      }
      .band-line > span {
        display: block;
        transform: translateY(115%);
        transition: transform 0.9s cubic-bezier(0.16, 1, 0.3, 1);
        transition-delay: var(--ld, 0s);
        will-change: transform;
      }
      .srev.in .band-line > span { transform: translateY(0); }

      @media (min-width: 768px) {
        .cta-band-headline { font-size: 44px; }
      }
      @media (min-width: 1024px) {
        .cta-inner { gap: 69px; padding: 107px 24px 110px; }
        .tag-rows { gap: 0; }
        .tag-row-1 { height: 80px; }
        .tag-row-2 { height: 83px; }
        .tag-row-3 { height: 74px; }
        .cta-band-row {
          flex-direction: row;
          justify-content: center;
          gap: 72px;
        }
        .cta-band-headline { text-align: left; }
      }
      @media (prefers-reduced-motion: reduce) {
        .srev.in .sp-u { animation: none; }
        /* Headline lines simply present — no masked rise. */
        .band-line > span { transform: none; transition: none; }
        /* No looping under reduced motion — the cloud rests
           static on the first pill set. */
        .marquee-l, .marquee-r { animation: none; }
      }

      /* ---------- Section 5 — Meet Our team ----------
         Mirrors the cleaned Team component, in the same shell as
         Sections 2–3 (.s2-wrap: 1600px container, 24/40/72px side
         padding), white on the dark --ink page background. LEFT
         column: bold label + 44px headline on top, light
         paragraph at the bottom (380px tall on desktop,
         space-between). RIGHT column (807px on desktop): a
         WORKING carousel — 380px clipped viewport, 280×380 cards
         (radius 27px). CARD SYSTEM ported verbatim from Mash's
         own reference HTML (Meet_Our_Team, 2026-10-20), which
         supersedes every earlier hover model:
         DEFAULT = the photo alone fills the card (object-fit
         cover, centre top), rendered GREYSCALE via CSS filter,
         on the card's #15161B background; no text at all.
         HOVER / focus / tap = the card background turns white
         (.45s), the photo box SHRINKS in height to 62% of the
         card (.5s), the image returns to full COLOUR, a white
         gradient fade (bottom 45% of the photo box) dissolves
         the photo's bottom into the white card, and the
         member's name (24px medium) + role (16px light) appear
         in black at the bottom-left — the info block's bottom
         edge sits 48px above the card bottom, left inset 12px —
         rising/fading in, with a 100×1px divider under the role.
         Mouse-leave reverses everything. Prev/next
         48px circle buttons sit
         right-aligned ~51px below. TWO ways to slide
         (Mash, 2026-10-20): the buttons move one full PAGE (the
         viewport's width) per click over .55s, clamped to the
         max offset so the last card ends flush with the
         viewport's right edge — with 4 cards, ONE Next click
         fully shows the 4th card; and the track can be DRAGGED
         left/right (mouse or touch), following the pointer 1:1
         and snapping on release to the nearest card step
         (304px = 280 + 24 gap) or the clamped end. Button
         disabled states follow the actual offset: prev disabled
         iff offset 0 (40% opacity, as exported), next disabled
         iff offset = max. The
         arrow buttons are plain icon buttons (hover fills them
         rgba(255,255,255,.12)) — NOT the unified CTA effect.
         Names/photos are as
         exported (cards 1 & 3 share one photo, three cards share
         a name — flagged to Mash as placeholders). */
      .team { background: var(--ink); padding: 96px 0; }
      .team-grid {
        display: flex;
        flex-direction: column;
        gap: 48px;
      }
      .team-left {
        display: flex;
        flex-direction: column;
        justify-content: space-between;
        gap: 40px;
      }
      .team-left-top {
        display: flex;
        flex-direction: column;
        align-items: flex-start;
        gap: 24px;
      }
      .team-headline {
        margin: 0;
        max-width: 519px;
        /* NO text shrink on narrow frames (Mash, 2026-10-20): the
           headline stays 44px at EVERY width — when the section
           stacks, the text sits above the cards at full size and
           wraps naturally instead of scaling down. (Label stays
           24px via .sec-label, paragraph 16px via .body-text.) */
        font-size: 44px;
        font-weight: 500;
        line-height: 1.15;
        color: #fff;
      }
      .team-left .body-text { max-width: 414px; }
      /* Headline TEXT animation — the same masked line rise as
         the hero and the Section 4 band headline: each line's
         inner span rises from 115% inside its overflow-hidden
         mask when the left column's .srev fires, staggered via
         --ld. The 0.12em bottom pad, cancelled by the negative
         margin, keeps descenders from clipping in the mask. */
      .team-line {
        display: block;
        overflow: hidden;
        padding-bottom: 0.12em;
        margin-bottom: -0.12em;
      }
      .team-line > span {
        display: block;
        transform: translateY(115%);
        transition: transform 0.9s cubic-bezier(0.16, 1, 0.3, 1);
        transition-delay: var(--ld, 0s);
        will-change: transform;
      }
      .srev.in .team-line > span { transform: translateY(0); }
      .team-right {
        display: flex;
        flex-direction: column;
        align-items: flex-end;
        gap: 51px;
        width: 100%;
      }
      .team-viewport {
        width: 100%;
        height: 380px;
        overflow: hidden;
        /* Drag sliding (Mash, 2026-10-20): the track can be dragged
           left/right with mouse or touch. touch-action: pan-y keeps
           vertical page scroll working while horizontal drags reach
           the pointer handlers; user-select off so a mouse drag
           never selects text. */
        touch-action: pan-y;
        user-select: none;
        -webkit-user-select: none;
        cursor: grab;
      }
      .team-viewport.team-dragging { cursor: grabbing; }
      .team-track {
        display: flex;
        width: max-content;
        align-items: center;
        gap: 24px;
        transition: transform 0.55s cubic-bezier(0.2, 0.7, 0.2, 1);
      }
      /* While dragging, the track follows the pointer 1:1 — the
         .55s transition is disabled; it comes back for the snap
         on release. */
      .team-track.drag-live { transition: none; }
      .team-photo img { -webkit-user-drag: none; }
      .team-card {
        position: relative;
        width: 280px;
        height: 380px;
        flex: 0 0 280px;
        overflow: hidden;
        border-radius: 27px;
        background: #15161b;
        cursor: pointer;
        outline: none;
        transition: background-color 0.45s ease;
      }
      .team-card:hover,
      .team-card:focus-visible,
      .team-card.team-show { background: #fff; }
      /* The photo box (Mash's .pic): full-card by default; on
         hover/focus/tap its HEIGHT animates to 62% of the card
         while the img inside keeps object-fit: cover anchored
         centre-top, so the photo appears to shrink upward and
         its lower part is clipped away. The img renders
         greyscale by default and returns to colour in the
         active state — team-4's photo is a colour photo, so
         this filter is what makes the default state B&W. */
      .team-photo {
        position: absolute;
        left: 0;
        top: 0;
        width: 100%;
        height: 100%;
        overflow: hidden;
        transition: height 0.5s cubic-bezier(0.2, 0.7, 0.2, 1);
      }
      .team-card:hover .team-photo,
      .team-card:focus-visible .team-photo,
      .team-card.team-show .team-photo { height: 62%; }
      .team-photo img {
        display: block;
        width: 100%;
        height: 100%;
        object-fit: cover;
        object-position: center top;
        filter: grayscale(1);
        transition: filter 0.45s ease;
      }
      .team-card:hover .team-photo img,
      .team-card:focus-visible .team-photo img,
      .team-card.team-show .team-photo img { filter: none; }
      /* White dissolve at the bottom of the photo box (Mash's
         .fade): transparent at its top, solid white at the
         photo box's bottom edge, so the shrinking photo melts
         into the white card below it. */
      .team-photo-fade {
        position: absolute;
        left: 0;
        right: 0;
        bottom: 0;
        height: 45%;
        background: linear-gradient(to bottom, rgba(255, 255, 255, 0), #fff);
        opacity: 0;
        transition: opacity 0.45s ease;
      }
      .team-card:hover .team-photo-fade,
      .team-card:focus-visible .team-photo-fade,
      .team-card.team-show .team-photo-fade { opacity: 1; }
      /* Info block (Mash's .info): black text, its bottom edge
         48px above the card bottom, 12px left inset; hidden and
         nudged 14px down by default, rising/fading in on
         hover/focus/tap. Name, role, then a 100×1px divider. */
      .team-info {
        position: absolute;
        left: 12px;
        right: 8px;
        bottom: 48px;
        color: #000;
        opacity: 0;
        transform: translateY(14px);
        transition: opacity 0.4s ease 0.05s, transform 0.5s cubic-bezier(0.2, 0.7, 0.2, 1);
      }
      .team-card:hover .team-info,
      .team-card:focus-visible .team-info,
      .team-card.team-show .team-info {
        opacity: 1;
        transform: none;
      }
      .team-info b {
        display: block;
        font-size: 24px;
        font-weight: 500;
        line-height: 1.15;
      }
      .team-info span {
        display: block;
        font-size: 16px;
        font-weight: 300;
        line-height: 1.2;
        margin-top: 4px;
      }
      .team-info i {
        display: block;
        width: 100px;
        height: 1px;
        background: rgba(0, 0, 0, 0.45);
        margin-top: 4px;
      }
      .team-controls {
        display: flex;
        align-items: center;
        gap: 12px;
      }
      .team-btn {
        width: 48px;
        height: 48px;
        border-radius: 50%;
        background: none;
        border: none;
        padding: 0;
        cursor: pointer;
        line-height: 0;
        display: grid;
        place-items: center;
        transition: opacity 0.2s ease, background-color 0.2s ease;
      }
      .team-btn svg { display: block; }
      /* Prev starts disabled at 40% (as exported); next joins it
         at the end of the track. Equal specificity with the
         reveal's .srev.in .sp opacity, later in the file, so the
         disabled state wins once revealed. */
      .team-controls > .team-btn:disabled {
        opacity: 0.4;
        cursor: default;
      }
      .team-controls > .team-btn:not(:disabled):hover { background: rgba(255, 255, 255, 0.12); }
      .team-controls > .team-btn:focus-visible {
        outline: 2px solid #fff;
        outline-offset: 3px;
      }

      @media (min-width: 1024px) {
        .team { padding: 120px 0; }
        .team-grid {
          flex-direction: row;
          align-items: flex-start;
          justify-content: space-between;
        }
        .team-left { height: 380px; gap: 0; }
        .team-right { width: 807px; flex-shrink: 0; }
      }
      @media (prefers-reduced-motion: reduce) {
        /* Everything present; the carousel still slides, just
           without the transition. */
        .team-line > span { transform: none; transition: none; }
        .team-track, .team-card, .team-btn, .team-photo, .team-photo img, .team-photo-fade, .team-info { transition: none; }
      }

      /* ---------- Section 6 — FAQ ----------
         Mirrors the cleaned Faq component, in the same shell as
         Sections 2–5 (.s2-wrap: 1600px container, 24/40/72px side
         padding), white on the dark --ink background. HEADER:
         left column (631px on desktop) — bold 24px label, the
         light paragraph ~81px below it; right — 44px medium
         headline (max-w 533px), vertically centred against the
         left column; ~100px gap down to the content row.
         CONTENT: bottom-aligned on desktop — LEFT an accordion
         (max-w 725px, items 24px apart), RIGHT a 533px block
         whose 44px headline carries the "Talk to us" CTA at the
         export's position (left 202px, top 104px on desktop, so
         it sits beside the headline's last line; static below
         the headline on mobile). The CTA is the site's shared
         .cta system (white pill + arrow circle, roll label,
         arrow reload, unified hover) with the pill fixed at the
         export's 170px width. ACCORDION: item 1 open by default
         (as exported); ONE item open at a time; clicking the
         question row toggles it; the answer expands/collapses
         via grid-template-rows (0fr -> 1fr) over ~0.3s and the
         48px plus/minus icon's vertical bar scales away when
         open (plus -> minus). ⚠️ Items 2–5 have NO answer copy
         in Mash's export — nothing was invented; they toggle
         with an empty answer area until he supplies the texts. */
      .faq { background: var(--ink); padding: 96px 0; }
      .faq-head {
        display: flex;
        flex-direction: column;
        gap: 40px;
      }
      .faq-head-left {
        display: flex;
        flex-direction: column;
        align-items: flex-start;
        gap: 40px;
        width: 100%;
      }
      .faq-head-left .body-text { max-width: 414px; }
      .faq-headline {
        margin: 0;
        max-width: 533px;
        font-size: 44px;
        font-weight: 500;
        line-height: 1.1;
        color: #fff;
      }
      .faq-content {
        margin-top: 64px;
        display: flex;
        flex-direction: column;
        gap: 56px;
      }
      .faq-list {
        display: flex;
        flex-direction: column;
        gap: 24px;
        width: 100%;
        max-width: 725px;
      }
      .faq-item {
        display: flex;
        align-items: flex-start;
        gap: 10px;
      }
      .faq-main { flex: 1; min-width: 0; padding: 16px 0; }
      .faq-q {
        display: block;
        width: 100%;
        margin: 0;
        padding: 0;
        border: none;
        background: none;
        cursor: pointer;
        text-align: left;
        font-family: inherit;
        font-size: 32px;
        font-weight: 500;
        line-height: 1.15;
        color: #fff;
      }
      .faq-q:focus-visible {
        outline: 2px solid #fff;
        outline-offset: 4px;
      }
      /* Answer — ONE node inside a grid-rows wrapper (0fr -> 1fr,
         overflow hidden), the same construction as the service
         cards' description and Section 3's step bodies, so the
         height animates smoothly over ~0.3s. */
      .faq-answer {
        display: grid;
        grid-template-rows: 0fr;
        transition: grid-template-rows 0.3s ease-out;
      }
      .faq-item.faq-open .faq-answer { grid-template-rows: 1fr; }
      .faq-answer-clip { overflow: hidden; min-height: 0; }
      .faq-answer p {
        margin: 0;
        padding-top: 16px;
        font-size: 16px;
        font-weight: 300;
        line-height: 1.5;
        color: #fff;
      }
      /* Plus/minus icon: 48×48 box, two centred white bars (20px,
         2px, rounded). Closed = plus; open = the vertical bar
         scales away, leaving the minus. Pure CSS — the state
         follows the item's .faq-open class, so it can never
         disagree with the answer area. */
      .faq-icon {
        position: relative;
        flex-shrink: 0;
        width: 48px;
        height: 48px;
        cursor: pointer;
      }
      .faq-icon::before,
      .faq-icon::after {
        content: "";
        position: absolute;
        top: 50%;
        left: 50%;
        background: #fff;
        border-radius: 2px;
      }
      .faq-icon::before {
        width: 20px;
        height: 2px;
        transform: translate(-50%, -50%);
      }
      .faq-icon::after {
        width: 2px;
        height: 20px;
        transform: translate(-50%, -50%);
        transition: transform 0.3s ease;
      }
      .faq-item.faq-open .faq-icon::after {
        transform: translate(-50%, -50%) scaleY(0);
      }
      /* Right block — "Still have questions?" */
      .faq-side { width: 100%; }
      .faq-side-headline {
        margin: 0;
        font-size: 44px;
        font-weight: 500;
        line-height: 1.1;
        color: #fff;
      }
      /* The CTA flows INLINE inside the headline, right after the
         word "situation." on its last line (Mash's design
         screenshot, 2026-10-21) — inline flow, not absolute
         coordinates, so it stays glued to the word whatever the
         font rendering: same line, a small gap, vertically
         centred on that line, the arrow circle touching the
         pill's right edge. On mobile it simply wraps with the
         text. */
      .faq-side .cta {
        margin-left: 12px;
        vertical-align: middle;
        white-space: nowrap;
      }
      /* The pill is exactly 170×48 with centred text. */
      .cta-talk .cta-pill { width: 170px; justify-content: center; }
      /* The FAQ "Talk to us" CTAs are <button>s now (they open
         the on-site Tawk live chat — lazy-loaded by the script
         at the end of the body — instead of linking away);
         strip the native button chrome so they render exactly
         like the anchors they replaced. */
      button.cta-talk {
        margin: 0;
        padding: 0;
        border: none;
        background: none;
        font-family: inherit;
        cursor: pointer;
      }

      @media (min-width: 1024px) {
        .faq { padding: 120px 0; }
        .faq-head {
          flex-direction: row;
          align-items: center;
          justify-content: space-between;
        }
        .faq-head-left { width: 631px; flex-shrink: 0; gap: 81px; }
        .faq-content {
          margin-top: 100px;
          flex-direction: row;
          align-items: flex-end;
          justify-content: space-between;
        }
        .faq-side { width: 533px; flex-shrink: 0; }
      }
      @media (prefers-reduced-motion: reduce) {
        .faq-answer, .faq-icon::after { transition: none; }
      }

      /* ---------- Section 7 — Contact form ("Get in touch") ----------
         Mirrors the cleaned ContactForm component, in the same
         shell as Sections 2–6 (.s2-wrap), white on --ink, with
         id="contact" (the target of the site's #contact links).
         HEADER: bold 24px label, 52px below it the 44px medium
         headline at full width. CONTENT (~120px below the header
         on desktop, bottom-aligned): LEFT a 520px column at the
         row's full height — the light paragraph at the top and
         the Section 2 social row (same uniform 36px stroke
         circles, same hrefs; the export's empty 4th icon is
         Instagram, confirmed by Mash for Section 2) pinned to
         the bottom. RIGHT a real working FORM (763px): labels
         16px medium with a 16px gap, inputs 56px tall, rounded
         12px, 1px #B2B2B2 border, transparent background, 20px
         side padding, placeholders and typed text 18px regular
         (400) — placeholders #B2B2B2, typed text white. Two paired rows (348px fields), one
         full-width select with a #B2B2B2 chevron (the discuss
         select carries his three services) and a custom
         availability picker (Mash, 2026-10-21, his "Schedule
         send" reference: a date field opening a white calendar
         popover + a time field opening a white dropdown list),
         then the 218px message box with a LIVE "n/500" counter
         bottom-right (maxLength 500). Placeholders kept
         word-for-word from the export, including "Jhon" and
         "setuation". Required fields use native validation; the
         form has NO backend — submit prevents default. The
         "Request a Call" submit reuses the shared .cta system,
         so the unified hover (lift, shine, roll label, arrow
         reload) applies unchanged. Scroll animation in the
         established per-block reveal-once language: header label
         then headline lines from the left, left-column pieces
         from the left, form rows one by one from the right. */
      .contact { background: var(--ink); padding: 96px 0; }
      .contact-head {
        display: flex;
        flex-direction: column;
        align-items: flex-start;
        gap: 52px;
      }
      .contact-headline {
        margin: 0;
        width: 100%;
        font-size: 44px;
        font-weight: 500;
        line-height: 1.1;
        color: #fff;
      }
      .contact-headline .ch-line { display: block; }
      .contact-content {
        margin-top: 64px;
        display: flex;
        flex-direction: column;
        gap: 56px;
      }
      .contact-left {
        display: flex;
        flex-direction: column;
        justify-content: space-between;
        gap: 40px;
        width: 100%;
      }
      .contact-form {
        display: flex;
        flex-direction: column;
        align-items: flex-start;
        gap: 48px;
        width: 100%;
        max-width: 763px;
      }
      .cf-fields {
        display: flex;
        flex-direction: column;
        gap: 24px;
        width: 100%;
      }
      .cf-row {
        display: flex;
        flex-direction: column;
        gap: 24px;
        width: 100%;
      }
      .cf-cell { width: 100%; min-width: 0; }
      .cf-field {
        display: flex;
        flex-direction: column;
        align-items: flex-start;
        gap: 16px;
        width: 100%;
      }
      .cf-label {
        font-size: 16px;
        font-weight: 500;
        line-height: 1.2;
        color: #fff;
      }
      .cf-input {
        width: 100%;
        height: 56px;
        border-radius: 12px;
        border: 1px solid #b2b2b2;
        background: transparent;
        padding: 16px 20px;
        font-family: inherit;
        font-size: 18px;
        font-weight: 400;
        line-height: 1.2;
        color: #fff;
        outline: none;
      }
      .cf-input::placeholder { color: #b2b2b2; opacity: 1; font-weight: 400; transition: opacity 0.18s ease; }
      .cf-input::-webkit-input-placeholder { transition: opacity 0.18s ease; }
      /* Mash (2026-10-21): when a field is clicked for typing,
         its placeholder VANISHES; it returns on blur while the
         field is still empty. Only the real ::placeholder fields
         (the text inputs + the message textarea) — the discuss
         select and the date/time picker buttons carry no
         placeholder and are untouched. */
      .cf-input:focus::placeholder { opacity: 0; }
      .cf-input:focus::-webkit-input-placeholder { opacity: 0; }
      .cf-input:focus { border-color: #fff; }
      /* Availability picker (Mash, 2026-10-21, his "Schedule
         send" reference): a CUSTOM pair replacing the native
         datetime-local input shipped before it — a DATE field
         opening a WHITE calendar popover (centred month title,
         ‹ › arrows, Su–Sa header, the selected day a BLACK
         rounded square with white text, past days disabled) and
         a TIME field opening a white dropdown of 12-hour times
         in 30-minute steps. Both fields are .cf-input buttons,
         56px tall, flex-1 side by side in the 763px row,
         stacked on mobile; unchosen labels read #B2B2B2, chosen
         values white. A hidden required input carries the
         combined value so native validation still applies.
         Mirrors AvailabilityPicker in the cleaned ContactForm
         component. */
      .cf-avail { position: relative; width: 100%; }
      .cf-avail-row { display: flex; flex-direction: column; gap: 16px; }
      .cf-picker-btn {
        display: flex;
        align-items: center;
        gap: 12px;
        margin: 0;
        text-align: left;
        cursor: pointer;
      }
      .cf-picker-btn > svg { flex-shrink: 0; }
      .cf-picker-text { color: #b2b2b2; }
      .cf-picker-text.has-value { color: #fff; }
      .cf-picker-chev { margin-left: auto; flex-shrink: 0; }
      .cf-avail-hidden {
        position: absolute;
        left: 0;
        right: 0;
        top: 0;
        height: 56px;
        opacity: 0;
        pointer-events: none;
      }
      .cf-cal {
        position: absolute;
        top: calc(100% + 8px);
        left: 0;
        z-index: 30;
        width: 320px;
        max-width: calc(100vw - 48px);
        border-radius: 24px;
        background: #fff;
        padding: 20px;
        color: var(--ink);
        box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.45);
      }
      .cf-cal-head {
        display: flex;
        align-items: center;
        justify-content: space-between;
        margin-bottom: 12px;
      }
      .cf-cal-title { margin: 0; font-size: 18px; font-weight: 600; }
      .cf-cal-nav {
        display: grid;
        place-items: center;
        width: 36px;
        height: 36px;
        border: none;
        border-radius: 50%;
        background: none;
        font-family: inherit;
        font-size: 20px;
        line-height: 1;
        color: inherit;
        cursor: pointer;
      }
      .cf-cal-nav:hover { background: rgba(0, 0, 0, 0.05); }
      .cf-cal-nav:disabled { opacity: 0.3; cursor: default; }
      .cf-cal-nav:disabled:hover { background: none; }
      .cf-cal-grid {
        display: grid;
        grid-template-columns: repeat(7, 1fr);
        justify-items: center;
      }
      .cf-cal-dow {
        padding: 4px 0;
        font-size: 14px;
        font-weight: 500;
        color: #8a97a5;
      }
      .cf-cal-day {
        width: 40px;
        height: 40px;
        border: none;
        border-radius: 12px;
        background: none;
        font-family: inherit;
        font-size: 15px;
        color: inherit;
        cursor: pointer;
      }
      .cf-cal-day:hover { background: rgba(0, 0, 0, 0.05); }
      .cf-cal-day.is-selected {
        background: #1e1e1e;
        color: #fff;
        font-weight: 600;
      }
      .cf-cal-day.is-selected:hover { background: #1e1e1e; }
      .cf-cal-day:disabled { opacity: 0.3; cursor: default; }
      .cf-cal-day:disabled:hover { background: none; }
      .cf-times {
        position: absolute;
        top: calc(100% + 8px);
        right: 0;
        z-index: 30;
        width: 220px;
        max-height: 256px;
        overflow-y: auto;
        border-radius: 24px;
        background: #fff;
        padding: 8px;
        color: var(--ink);
        box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.45);
      }
      .cf-time-opt {
        display: block;
        width: 100%;
        border: none;
        border-radius: 12px;
        background: none;
        padding: 10px 16px;
        font-family: inherit;
        font-size: 16px;
        text-align: left;
        color: inherit;
        cursor: pointer;
      }
      .cf-time-opt:hover { background: rgba(0, 0, 0, 0.05); }
      .cf-time-opt.is-selected { background: #1e1e1e; color: #fff; }
      .cf-time-opt.is-selected:hover { background: #1e1e1e; }
      .cf-select-wrap { position: relative; display: block; width: 100%; }
      .cf-select {
        appearance: none;
        -webkit-appearance: none;
        padding-right: 52px;
        cursor: pointer;
      }
      /* Unchosen (the disabled placeholder option is selected):
         the closed select reads in the placeholder grey; once a
         real option is picked it turns white like typed text. */
      .cf-select:invalid { color: #b2b2b2; }
      .cf-select option { color: var(--ink); }
      .cf-chevron {
        position: absolute;
        right: 20px;
        top: 50%;
        transform: translateY(-50%);
        pointer-events: none;
      }
      .cf-msg-wrap { position: relative; display: block; width: 100%; }
      .cf-msg {
        display: block;
        height: 218px;
        resize: none;
      }
      .cf-count {
        position: absolute;
        right: 20px;
        bottom: 16px;
        font-size: 16px;
        font-weight: 500;
        line-height: 1.2;
        color: #b2b2b2;
        pointer-events: none;
      }
      /* The submit is a real <button> wearing the shared .cta
         clothes — strip the native button chrome so it renders
         exactly like the anchor CTAs. */
      .cf-submit {
        border: none;
        background: none;
        padding: 0;
        margin: 0;
        cursor: pointer;
        font-family: inherit;
      }
      .cf-submit:focus-visible { outline: 2px solid #fff; outline-offset: 4px; }

      @media (min-width: 640px) {
        .cf-row { flex-direction: row; justify-content: space-between; }
        .cf-cell { flex: 0 1 348px; }
        .cf-avail-row { flex-direction: row; gap: 20px; }
        .cf-picker-btn { flex: 1; }
      }
      @media (min-width: 1024px) {
        .contact { padding: 120px 0; }
        .contact-content {
          margin-top: 120px;
          flex-direction: row;
          align-items: flex-end;
          justify-content: space-between;
          /* No row gap on desktop: space-between alone places
             the 520px column and the 763px form, so the form
             keeps its full export width (a leftover column gap
             would shrink it below 763px). */
          gap: 0;
        }
        .contact-left {
          width: 520px;
          flex-shrink: 0;
          align-self: stretch;
        }
      }

      /* ---------- Section 8 — Final CTA banner ----------
         Mirrors the cleaned CtaBanner component. Background
         (Mash, 2026-10-21: "section 4 er oi image ta e eikhane
         use koro"): the SAME designed gradient image Section 4
         already uses (../images/img-01.webp, 3200×1287), as
         cover — not a per-section bake. Headline type is Archivo
         semibold; line 2 "Let's figure it out" in Playfair
         Display ITALIC medium + " together." back in Archivo
         semibold. TEXT COLOUR + BLEND (Mash, 2026-10-21, from
         his Figma Appearance panel: opacity 100%, blend mode
         Difference): the headline and the paragraph are #FFFFFF
         with mix-blend-mode: difference, so over the light
         gradient they render inverted (near-black over the white
         centre, tinted over the coloured corners) and invert
         against any trail photo passing behind them — the cool
         effect he asked for. The Get Started CTA stays SOLID
         #1E1E1E, never blended. For the blend to see the whole
         banner backdrop (gradient + trail cards), nothing
         between the text and the section may isolate: the trail
         cards live in .cta-trail-layer and the content wrapper
         carries NO z-index / transform / opacity of its own —
         paint order comes from DOM order alone (bg → trail →
         content), and the reveal animations end on natural
         styles so they never leave an isolating context behind.
         Scroll reveal in the established
         per-block language: the headline is its own .srev (its
         two lines rise in pieces via .band-line), the row below
         is its own .srev (paragraph from the LEFT, CTA from the
         RIGHT). The photos are a CURSOR-FOLLOWING IMAGE TRAIL
         (Mash's own words, 2026-10-21: "those images are
         following my cursor — cursor following image trail
         effect"): idle, the band is PLAIN like Section 4 — no
         photos at all. As the mouse moves over the banner, a
         photo card spawns at the cursor every ~80px of travel,
         cycling through his 18 tile images in order; each card
         pops in tilted, lingers, fades out (~1.5s total life)
         and is removed from the DOM. Two earlier reads — fixed
         floating scatter, then hover-fade-in — were both wrong
         and were replaced. Mouse-only; prefers-reduced-motion
         disables the trail entirely. */
      .cta-banner {
        position: relative;
        overflow: hidden;
        background: #f2f2f2;
        color: var(--ink);
      }
      .cta-banner-bg {
        position: absolute;
        inset: 0;
        width: 100%;
        height: 100%;
        object-fit: cover;
      }
      /* Cursor-following image trail: cards are spawned by the
         pointermove script at the cursor position (centred on
         it via translate(-50%, -50%)) and live one trail-life
         cycle — pop in (scale 0.7→1 + fade in by 12%), linger,
         then fade out shrinking slightly — after which the
         script removes them. They live inside .cta-trail-layer
         (below), painted behind the content purely by DOM
         order — NO z-index anywhere in this section, so the
         headline's difference blend sees them — and never take
         pointer events. Size is FIXED at 200×266px (Mash,
         2026-10-21) — the script sets width: 200px inline and
         the aspect ratio gives the 266px height. Mirrors
         .trail-img / @keyframes trail-life
         in the cleaned project's globals.css. */
      .cta-trail-layer {
        position: absolute;
        inset: 0;
      }
      .trail-img {
        position: absolute;
        aspect-ratio: 200 / 266;
        overflow: hidden;
        /* Square corners (Mash, 2026-10-21: "no need any rounded
           corner here"); the soft shadow stays. */
        box-shadow: 0 18px 36px rgba(30, 30, 30, 0.22);
        pointer-events: none;
        animation: trail-life 1.5s ease-out both;
      }
      .trail-img img {
        width: 100%;
        height: 100%;
        object-fit: cover;
        display: block;
      }
      @keyframes trail-life {
        0% {
          opacity: 0;
          transform: translate(-50%, -50%) scale(0.7) rotate(var(--rot, 0deg));
        }
        12% {
          opacity: 1;
          transform: translate(-50%, -50%) scale(1) rotate(var(--rot, 0deg));
        }
        70% { opacity: 1; }
        100% {
          opacity: 0;
          transform: translate(-50%, -50%) scale(0.94) rotate(var(--rot, 0deg));
        }
      }
      /* NO z-index here on purpose (Mash's difference blend,
         2026-10-21): a z-index — or a transform / opacity left
         by an animation — would make this wrapper its own
         stacking context and the headline would blend only
         against the wrapper's empty inside, rendering plain
         white and invisible over the light gradient. Positioned
         with z-index auto it creates no stacking context, so
         the text blends against the section backdrop (gradient
         image + trail photos), and it still paints after them
         because it comes later in DOM order. */
      .cta-banner-inner {
        position: relative;
        margin: 0 auto;
        width: 100%;
        max-width: 868px;
        min-height: 560px;
        display: flex;
        flex-direction: column;
        justify-content: center;
        padding: 96px 24px;
      }
      .cta-banner-headline {
        margin: 0;
        font-size: 40px;
        font-weight: 600;
        line-height: 1.08;
        /* #FFFFFF + difference (Mash, 2026-10-21): renders
           inverted against the gradient and the trail photos. */
        color: #ffffff;
        mix-blend-mode: difference;
      }
      /* The serif segment: Playfair Display italic medium. A
         small left pad on the line mask (cancelled by margin)
         keeps the italic L's entry swash from clipping. */
      .cta-banner-headline .band-line {
        padding-left: 0.08em;
        margin-left: -0.08em;
      }
      .cta-banner-headline .serif-it {
        font-family: "Playfair Display", Georgia, "Times New Roman", serif;
        font-style: italic;
        font-weight: 500;
      }
      .cta-banner-row {
        margin-top: 40px;
        display: flex;
        flex-direction: column;
        align-items: flex-start;
        gap: 24px;
      }
      .cta-banner-sub {
        margin: 0;
        max-width: 418px;
        font-size: 16px;
        font-weight: 300;
        line-height: 1.5;
        /* Same treatment as the headline: #FFFFFF + difference. */
        color: #ffffff;
        mix-blend-mode: difference;
      }
      @media (min-width: 640px) {
        .cta-banner-headline { font-size: 52px; }
        /* LEFT-ALIGNED GROUP (Mash, 2026-10-21, annotated
           screenshot): the CTA sits right after the paragraph
           with a ~72px gap — NOT spread to the block's right
           edge. No justify-content: space-between; the row just
           flows paragraph → 72px gap → CTA from the left. */
        .cta-banner-row {
          flex-direction: row;
          align-items: center;
          gap: 72px;
        }
      }
      @media (min-width: 1024px) {
        .cta-banner-inner { min-height: 720px; }
        .cta-banner-headline { font-size: 64px; }
      }
      /* SELL PAGE banner variant (Mash, 2026-10-21, his design
         screenshot: "only change text and btn" — cleaned
         reference: SellBanner.tsx). The banner SYSTEM is the
         homepage's, untouched: same gradient backdrop, trail,
         difference-blend text and dark CTA. Only the copy
         changes, and with it the measures that copy needs:
         the content block widens to ~1232px so headline
         line 1 holds on one line (the homepage keeps its
         ~820px block), the paragraph widens to ~540px, and
         the dark pill grows from its fixed 200px to fit the
         longer label — same padding family, auto width. */
      #ctaBannerSell .cta-banner-inner { max-width: 1232px; }
      #ctaBannerSell .cta-banner-sub { max-width: 540px; }
      #ctaBannerSell .cta-dark .cta-pill { width: auto; }
      /* BUYERS PAGE banner variant (Mash, 2026-10-21, his design
         screenshot; cleaned reference: BuyersBanner.tsx): the
         same system once more — only the copy changes. The
         content block widens to ~1280px so headline line 1
         ("Every opportunity starts with a possibility.") holds
         on one line, the paragraph widens to ~540px, and the
         dark pill is auto width to fit "Explore
         Opportunities". */
      #ctaBannerBuyers .cta-banner-inner { max-width: 1280px; }
      #ctaBannerBuyers .cta-banner-sub { max-width: 540px; }
      #ctaBannerBuyers .cta-dark .cta-pill { width: auto; }
      /* SURPLUS PAGE banner variant (Mash, 2026-10-21, his design
         screenshot; cleaned reference: SurplusBanner.tsx): the
         same system once more — only the copy changes. The
         content block is ~1232px (as the Sell banner's) so
         headline line 1 ("You don't have to figure it all out
         alone.") holds on one line, the paragraph widens to
         ~540px, and the dark pill is auto width to fit "Explore
         Opportunities". */
      #ctaBannerSurplus .cta-banner-inner { max-width: 1232px; }
      #ctaBannerSurplus .cta-banner-sub { max-width: 540px; }
      #ctaBannerSurplus .cta-dark .cta-pill { width: auto; }
      @media (prefers-reduced-motion: reduce) {
        /* No trail at all under reduced motion (the script also
           checks the media query before spawning). */
        .trail-img { animation: none; opacity: 0; }
      }

      /* ---------- Section 9 — Footer ----------
         Mirrors the cleaned Footer component, in the same shell
         as Sections 2–7 (.s2-wrap: 1600px container, 24/40/72px
         side padding). BACKGROUND: his Unsplash villa photo
         (../images/img-02.webp, 1597×1205) covering, anchored to
         the TOP, under the hero-family gradient with his
         export's exact stops (0.68 / 0.49 / 0.55 -> #1E1E1E) —
         the photo fades to near-black at the bottom, where the
         giant wordmark sits. CONTENT (top padding 90px): a
         justify-between row — LEFT the white logo at 200×101
         (same asset as the hero), the 18px MEDIUM tagline
         (max-w 441px) and the uniform 36px social circles with
         his real links (4th icon = Instagram, confirmed by
         Mash); RIGHT a 680px block — four link columns on top
         (20px semibold headings, 16px links, 12px gaps) and the
         legal row pinned to its bottom by space-between.
         BOTTOM WORDMARK: his supplied image
         (../images/img-03.webp, 1402×142 — giant white
         "SR PROPERTY" + script "solution llc"), centred (left
         99px in the 1600 frame = centred), its bottom ~14px
         CLIPPED by the footer's bottom edge, as exported.
         Desktop height 591px as exported; on mobile the footer
         stacks naturally (logo/tagline/socials, columns 2-up,
         legal row) with bottom padding so the content never
         collides with the wordmark, which scales to ~94vw and
         stays clipped at the bottom. Scroll reveal in the
         established per-block language: left column from the
         LEFT, columns one by one from the RIGHT, the wordmark
         rising LAST — reveal-once via the shared .srev observer
         (the footer itself is the .srev block). */
      .footer {
        position: relative;
        overflow: hidden;
        background: var(--ink);
      }
      .footer-bg {
        position: absolute;
        inset: 0;
        width: 100%;
        height: 100%;
        object-fit: cover;
        object-position: top;
      }
      .footer-shade {
        position: absolute;
        inset: 0;
        background: linear-gradient(
          180deg,
          rgba(1, 17, 22, 0.68) 0.12%,
          rgba(3, 17, 21, 0.49) 21.54%,
          rgba(5, 17, 21, 0.55) 44.52%,
          #1e1e1e 101.85%
        );
      }
      .footer-content {
        position: relative;
        display: flex;
        flex-direction: column;
        gap: 48px;
        padding-top: 90px;
        /* Mobile clearance: the wordmark (94vw wide, ~9.5vw
           tall) sits clipped at the bottom — keep the content
           well clear of it. Desktop resets this to 0. */
        padding-bottom: 24vw;
      }
      .footer-left {
        display: flex;
        flex-direction: column;
        align-items: flex-start;
        gap: 29px;
      }
      .footer-logo { line-height: 0; }
      .footer-logo img {
        width: 200px;
        height: 101px;
        object-fit: contain;
        object-position: left;
      }
      .footer-tag {
        margin: 0;
        max-width: 441px;
        font-size: 18px;
        font-weight: 500;
        line-height: 1.4;
        color: #fff;
      }
      .footer-right {
        display: flex;
        flex-direction: column;
        justify-content: space-between;
        gap: 48px;
        width: 100%;
      }
      .footer-cols {
        display: grid;
        grid-template-columns: repeat(2, 1fr);
        gap: 40px 32px;
      }
      .footer-col {
        display: flex;
        flex-direction: column;
        align-items: flex-start;
        gap: 12px;
      }
      .footer-col h3 {
        margin: 0;
        font-size: 20px;
        font-weight: 600;
        line-height: 1.2;
        color: #fff;
      }
      .footer-col a {
        font-size: 16px;
        line-height: 1.4;
        color: #fff;
        overflow-wrap: anywhere;
      }
      .footer-col a:hover, .footer-col a:focus-visible { text-decoration: underline; }
      .footer-legal {
        display: flex;
        flex-wrap: wrap;
        align-items: center;
        gap: 12px;
        font-size: 16px;
        line-height: 1.4;
        color: #fff;
      }
      .footer-legal p { margin: 0; }
      .footer-legal a:hover, .footer-legal a:focus-visible { text-decoration: underline; }
      /* Centred by a full-width flex row so the rising reveal
         (transform on the img) never fights the centring. */
      .footer-wordmark {
        position: absolute;
        left: 0;
        right: 0;
        bottom: -14px;
        display: flex;
        justify-content: center;
        pointer-events: none;
      }
      .footer-wordmark img {
        width: min(1402px, 94vw);
        height: auto;
      }

      @media (min-width: 1024px) {
        .footer { height: 591px; }
        .footer-content {
          flex-direction: row;
          align-items: stretch;
          justify-content: space-between;
          padding-bottom: 0;
        }
        .footer-right { width: 680px; flex-shrink: 0; gap: 0; }
        .footer-cols {
          display: flex;
          justify-content: space-between;
          align-items: flex-start;
        }
        .footer-col a { white-space: nowrap; overflow-wrap: normal; }
      }

      /* ---------- Legal views — Privacy Policy / Terms of Use ----------
         Full-page views keyed to the URL hash (#privacy / #terms),
         ported from the cleaned project's LegalLayout: dark #1E1E1E,
         Archivo, top bar (logo-hero.svg 95×48 left, "← Back to home"
         right), content column max-w 820px — bold "Legal" label, 44px
         medium title, light effective-date line, then sections (24px
         semibold headings, 16px light body, relaxed leading, disc
         lists), closing with the divider + © / contact block. When a
         legal view is active, body.legal-active hides everything else
         on the page (loader included) and restores scrolling. */
      .legal-view[hidden] { display: none; }
      body.legal-active { overflow: visible; }
      body.legal-active > :not(.legal-view) { display: none !important; }
      .legal-view {
        min-height: 100vh;
        min-height: 100svh;
        background: var(--ink);
      }
      .legal-header {
        margin: 0 auto;
        width: 100%;
        max-width: 1600px;
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 16px;
        padding: 32px 24px 0;
      }
      .legal-logo { flex-shrink: 0; line-height: 0; }
      .legal-logo img {
        width: 95px;
        height: 48px;
        object-fit: contain;
      }
      .legal-back {
        font-size: 16px;
        font-weight: 500;
        white-space: nowrap;
        color: #fff;
      }
      .legal-back:hover, .legal-back:focus-visible { text-decoration: underline; }
      .legal-body {
        margin: 0 auto;
        width: 100%;
        max-width: 820px;
        display: flex;
        flex-direction: column;
        gap: 40px;
        padding: 64px 24px 96px;
      }
      .legal-intro { display: flex; flex-direction: column; gap: 16px; }
      .legal-label {
        margin: 0;
        font-size: 24px;
        font-weight: 700;
        color: #fff;
      }
      .legal-title {
        margin: 0;
        font-size: 36px;
        font-weight: 500;
        line-height: 1.1;
        color: #fff;
      }
      .legal-meta {
        margin: 0;
        font-size: 16px;
        font-weight: 300;
        line-height: 1.5;
        color: rgba(255, 255, 255, 0.7);
      }
      .legal-sec { display: flex; flex-direction: column; gap: 12px; }
      .legal-sec h2 {
        margin: 0;
        font-size: 24px;
        font-weight: 600;
        line-height: 1.25;
        color: #fff;
      }
      .legal-sec-body {
        display: flex;
        flex-direction: column;
        gap: 12px;
        font-size: 16px;
        font-weight: 300;
        line-height: 1.65;
        color: rgba(255, 255, 255, 0.85);
      }
      .legal-sec-body p { margin: 0; }
      .legal-sec-body strong { font-weight: 500; color: #fff; }
      .legal-sec-body ul {
        margin: 0;
        padding-left: 24px;
        list-style: disc;
      }
      .legal-sec-body a { color: #fff; }
      .legal-sec-body a:hover, .legal-sec-body a:focus-visible { text-decoration: underline; }
      .legal-foot {
        display: flex;
        flex-direction: column;
        gap: 12px;
        border-top: 1px solid rgba(255, 255, 255, 0.15);
        padding-top: 32px;
        font-size: 16px;
        font-weight: 300;
        line-height: 1.5;
        color: rgba(255, 255, 255, 0.7);
      }
      .legal-foot p { margin: 0; }
      .legal-foot a { color: #fff; }
      .legal-foot a:hover, .legal-foot a:focus-visible { text-decoration: underline; }

      @media (min-width: 768px) {
        .legal-header { padding-left: 40px; padding-right: 40px; }
        .legal-title { font-size: 44px; }
      }
      @media (min-width: 1024px) {
        .legal-header { padding: 43px 72px 0; }
        .legal-body { padding-top: 96px; padding-bottom: 96px; }
      }

      /* ---------- Sell page view — Sell Your Property (#sell) ----------
         Full-page view keyed to the URL hash, on the same router as
         the legal views (body.sell-active hides the main page,
         loader included; no loader runs on this view). The view
         carries the Sell page hero, ported from the cleaned
         project's SellHero, and Section 2 — the main form —
         below it (see .sell-form-section further down). The
         homepage hero's markup and classes are reused wholesale
         (header, shared CTA system, 197K+ trust card), so the
         settled state matches the design exactly. This page's
         own pieces: the background photo (sell-hero-bg.jpg)
         under ITS gradient stops, the split-style headline
         (Archivo semibold, "Your next move" in Playfair italic),
         the seller paragraph and the 198px "Start a
         Conversation" pill — which anchors to THIS page's own
         form (#sell-form), not the homepage contact section.
         Header links point back at the main page's sections;
         the router scrolls to them once the main page is
         visible again. */
      .sell-view[hidden] { display: none; }
      body.sell-active { overflow: visible; }
      body.sell-active > :not(.sell-view) { display: none !important; }
      .sell-shade {
        position: absolute;
        inset: 0;
        background: linear-gradient(
          180deg,
          rgba(1, 17, 22, 0.68) 1.99%,
          rgba(3, 17, 21, 0.19) 23.32%,
          rgba(5, 17, 21, 0) 36.47%,
          #1e1e1e 98.74%
        );
      }
      .sell-copy {
        display: flex;
        flex-direction: column;
        align-items: flex-start;
        gap: 16px;
        max-width: 1024px;
      }
      .sell-title {
        margin: 0;
        font-size: 36px;
        font-weight: 600;
        line-height: 1.08;
        color: #fff;
      }
      /* Serif segment: "Your next move" is Playfair Display
         italic medium — the landing hero's split text style
         (Mash, 2026-10-21: "same text style on poroperty sale
         page hero"). The rest of the headline stays Archivo
         semibold, same size. Same .serif-it treatment as the
         landing hero's "we help with the" span. */
      .sell-title .serif-it {
        font-family: "Playfair Display", Georgia, "Times New Roman", serif;
        font-style: italic;
        font-weight: 500;
      }
      .sell-sub {
        display: flex;
        flex-direction: column;
        gap: 24px;
        width: 100%;
      }
      .sell-sub p {
        margin: 0;
        max-width: 716px;
        font-size: 16px;
        font-weight: 300;
        line-height: 1.5;
        color: #fff;
      }
      .cta-convo .cta-pill { width: 198px; justify-content: center; }

      @media (min-width: 768px) {
        .sell-title { font-size: 48px; }
        .sell-sub { flex-direction: row; align-items: center; justify-content: space-between; }
      }
      @media (min-width: 1024px) {
        .sell-sub { width: 992px; max-width: 100%; }
      }
      @media (min-width: 1280px) {
        .sell-title { font-size: 64px; }
      }

      /* ---------- Buyers page view — Cash Buyers & Investors
         (#buyers) ---------- Full-page view on the same router
         (body.buyers-active hides the main page, loader included;
         no loader runs on this view). Twin of the Sell hero: the
         header, the shared CTA system, the 197K+ trust card and
         the hero copy styles (.sell-copy / .sell-title /
         .sell-sub) are reused wholesale, so only this page's own
         pieces live here — the background photo
         (buyers-hero-bg.png) under the SAME gradient stops as
         the Sell hero. Below the hero sits Section 2 — this
         page's main form (#buyers-form, see the section markup);
         it reuses the Sell form section's layout and field system
         wholesale (.sell-form-section / .sf-*), so only this
         page's fields and copy differ. The hero's "Discuss an
         Opportunity" CTA anchors to that form, exactly as the
         Sell hero's CTA anchors to #sell-form. */
      .buyers-view[hidden] { display: none; }
      body.buyers-active { overflow: visible; }
      body.buyers-active > :not(.buyers-view) { display: none !important; }
      .buyers-shade {
        position: absolute;
        inset: 0;
        background: linear-gradient(
          180deg,
          rgba(1, 17, 22, 0.68) 1.99%,
          rgba(3, 17, 21, 0.19) 23.32%,
          rgba(5, 17, 21, 0) 36.47%,
          #1e1e1e 98.74%
        );
      }

      /* ---------- Surplus page view — Surplus Funds Assistance
         (#surplus) ---------- Full-page view on the same router
         (body.surplus-active hides the main page, loader included;
         no loader runs on this view). Twin of the Sell and Buyers
         heroes: the header, the shared CTA system, the 197K+
         trust card and the hero copy styles (.sell-copy /
         .sell-title / .sell-sub) are reused wholesale, so only
         this page's own pieces live here — the background photo
         (surplus-hero-bg.png, the mailbox with the SURPLUS FUNDS
         envelope) under the SAME gradient stops as the other
         service heroes, and the copy column at the standard
         1024px measure (the Sell/Buyers column is also 1024px).
         Below the hero, Section 2 — this page's main
         form — reuses the shared form-section system wholesale
         (.sell-form-section / .sf-*), so no surplus-specific
         form CSS lives here. The hero's "Explore Your Claim
         Options" CTA anchors to that form (#surplus-form),
         exactly as the other heroes' CTAs anchor to their own
         pages' forms. */
      .surplus-view[hidden] { display: none; }
      body.surplus-active { overflow: visible; }
      body.surplus-active > :not(.surplus-view) { display: none !important; }
      .surplus-shade {
        position: absolute;
        inset: 0;
        background: linear-gradient(
          180deg,
          rgba(1, 17, 22, 0.68) 1.99%,
          rgba(3, 17, 21, 0.19) 23.32%,
          rgba(5, 17, 21, 0) 36.47%,
          #1e1e1e 98.74%
        );
      }
      .surplus-view .sell-copy { max-width: 1024px; }

      /* ---------- Sell page — Section 2: the main form ----------
         Mirrors the cleaned SellForm component on the same shell
         and form system as the homepage's Section 7 (.s2-wrap,
         .sec-label, .body-text, the uniform .social-circle set
         and the .cf-* field styles are reused as-is). This
         section's own layout: it starts ~60px below the hero,
         the header-to-content gap is 120px on desktop, the left
         column is 520px at full row height (paragraph top,
         socials pinned to the bottom) and the form is 763px.
         THE DIFFERENCE from Section 7: the paired fields are
         FLEXIBLE halves 16px apart (.sf-row / .sf-cell flex: 1)
         — NOT the homepage form's fixed 348px cells. Rows sit
         24px apart; fields stack on mobile. The three selects
         carry NO options beyond the disabled placeholder (none
         in Mash's export — none invented); an unchosen select
         reads in the placeholder grey until a real value is
         picked (.sf-select.has-value, toggled by the section's
         script). The Additional Details box reuses .cf-msg's
         218px height but has NO character counter (none in this
         export). Scroll reveal in the established per-block
         language: header pieces from the left, the left column
         from the left, the form rows one by one from the
         right. */
      .sell-form-section { background: var(--ink); padding: 64px 0 96px; }
      .sf-head {
        display: flex;
        flex-direction: column;
        align-items: flex-start;
        gap: 52px;
      }
      .sf-headline {
        margin: 0;
        width: 100%;
        font-size: 44px;
        font-weight: 500;
        line-height: 1.1;
        color: #fff;
      }
      .sf-headline .sf-line { display: block; }
      .sf-content {
        margin-top: 64px;
        display: flex;
        flex-direction: column;
        gap: 56px;
      }
      .sf-left {
        display: flex;
        flex-direction: column;
        justify-content: space-between;
        gap: 40px;
        width: 100%;
      }
      .sf-form {
        display: flex;
        flex-direction: column;
        align-items: flex-start;
        gap: 48px;
        width: 100%;
        max-width: 763px;
      }
      .sf-fields {
        display: flex;
        flex-direction: column;
        gap: 24px;
        width: 100%;
      }
      .sf-row {
        display: flex;
        flex-direction: column;
        gap: 16px;
        width: 100%;
      }
      .sf-cell { width: 100%; min-width: 0; }
      .sf-form .sf-select { color: #b2b2b2; }
      .sf-form .sf-select.has-value { color: #fff; }

      @media (min-width: 640px) {
        .sf-row { flex-direction: row; }
        .sf-cell { flex: 1 1 0; width: auto; }
      }
      @media (min-width: 1024px) {
        .sell-form-section { padding: 60px 0 120px; }
        .sf-content {
          margin-top: 120px;
          flex-direction: row;
          align-items: flex-end;
          justify-content: space-between;
          /* No row gap on desktop (same rule as Section 7):
             space-between alone places the 520px column and the
             763px form at their full export widths. */
          gap: 0;
        }
        .sf-left {
          width: 520px;
          flex-shrink: 0;
          align-self: stretch;
        }
      }
    
/* Country-code selector — unified phone field with flag dropdown (v1.4.6) */
.cf-phone-row { display: flex; align-items: center; gap: 10px; height: 56px; border: 1px solid #b2b2b2; border-radius: 12px; padding: 0 20px 0 14px; background: transparent; }
.cf-phone-row:focus-within { border-color: #ffffff; }
.cf-phone-row input[type="tel"] { order: 2; flex: 1; min-width: 0; height: 100%; border: none; padding: 0; background: transparent; }
.cf-phone-row .cc-select[hidden] { display: none; }
.cc-wrap { position: relative; order: 1; flex: none; }
.cc-btn { display: flex; align-items: center; gap: 7px; background: none; border: none; cursor: pointer; padding: 6px 2px; color: #fff; font: inherit; }
.cc-flag { width: 24px; height: 24px; border-radius: 50%; object-fit: cover; display: block; }
.cc-chev { flex: none; opacity: 0.8; }
.cc-code { font-size: 18px; font-weight: 500; line-height: 1; }
.cc-list { position: absolute; top: calc(100% + 18px); left: -16px; width: 290px; max-height: 256px; overflow-y: auto; background: #fff; border-radius: 12px; box-shadow: 0 18px 50px rgba(0,0,0,0.45); padding: 6px; z-index: 80; }
.cc-list[hidden] { display: none; }
.cc-opt { display: flex; align-items: center; gap: 10px; width: 100%; padding: 9px 10px; border: none; background: none; border-radius: 8px; cursor: pointer; font: inherit; font-size: 15px; color: #141414; text-align: left; }
.cc-opt:hover { background: #f0f4fa; }
.cc-opt.sel { background: #dce9fd; }
.cc-opt .cc-flag { width: 22px; height: 22px; }

/* Other -> specify (v2.0.3): a hidden specify wrapper must stay hidden
   even though .cf-field / .field set their own display. */
.cf-other-wrap[hidden] { display: none !important; }
