/* deal-detail.css - the blocks that loaded AFTER public-ui.css, in order.
   Extracted verbatim from deal-detail.html. LOAD ORDER IS LOAD-BEARING:
   deal-detail-base.css -> public-ui.css -> deal-detail.css. Merging these two
   files, or moving either across the public-ui.css link, reorders the cascade.
   Both are registered as SHELL ASSETS in scripts/build-admin.mjs so the service
   worker's CACHE_VERSION bumps when they change - without that, a returning
   visitor gets new markup paired with a stale stylesheet. */

        /* ── STANDARDIZE all primary RED CTAs to the canonical contactAboutDeal()
              red button exactly (Submit an Offer ×2, Join Cash Buyers, Call Austin,
              mobile Submit an Offer). Loaded after public-ui.css so it wins.
              Kills each button's bespoke glow-edge / shimmer / amber-hairline so
              they read as one flat crimson gradient.

              2026-08-17: the sticky bar's Submit Offer LEFT this list. It has
              since been converted to `.email-btn--red email-btn--sm`, so this
              block was no longer standardizing it — it was de-standardizing it,
              repainting the sampled 180deg artwork face as a 135deg crimson,
              adding a 1px pink rim nothing else has, and forcing 1.05rem radius
              onto a --sm button whose scale is 12px. It sat beside a canonical
              gold Walkthrough, and the two not matching is most of why the bar
              read as off. The five remaining selectors are still legacy
              non-.email-btn markup and still need this. ── */
        body.public-body .pricing-primary-cta,
        body.public-body .investor-summary-primary,
        body.public-body #dealCashBuyersCard a[href^="/join"],
        body.public-body .deal-interest-primary {
            background: linear-gradient(135deg, #b91c1c 0%, #dc2626 55%, #ef4444 100%) !important;
            border: 1px solid rgba(252, 165, 165, 0.45) !important;
            box-shadow: 0 12px 22px rgba(185, 28, 28, 0.28), inset 0 1px 0 rgba(255,255,255,0.16) !important;
            color: #ffffff !important;
            border-radius: 1.05rem !important;
            transition: transform 180ms ease, box-shadow 180ms ease !important;
            filter: none !important;
        }
        body.public-body .pricing-primary-cta i, body.public-body .pricing-primary-cta svg,
        body.public-body .investor-summary-primary i, body.public-body .investor-summary-primary svg,
        body.public-body #dealCashBuyersCard a[href^="/join"] i, body.public-body #dealCashBuyersCard a[href^="/join"] svg,
        body.public-body .deal-interest-primary i, body.public-body .deal-interest-primary svg {
            color: #ffffff !important;
            stroke: #ffffff !important;
        }
        /* remove the per-button glow edge (::before) and shimmer/flourish (::after) */
        body.public-body .pricing-primary-cta::before, body.public-body .pricing-primary-cta::after,
        body.public-body .investor-summary-primary::before, body.public-body .investor-summary-primary::after,
        body.public-body #dealCashBuyersCard a[href^="/join"]::before, body.public-body #dealCashBuyersCard a[href^="/join"]::after,
        body.public-body .deal-interest-primary::before, body.public-body .deal-interest-primary::after {
            content: none !important;
            display: none !important;
            background: none !important;
            box-shadow: none !important;
        }
        body.public-body .pricing-primary-cta:hover,
        body.public-body .investor-summary-primary:hover,
        body.public-body #dealCashBuyersCard a[href^="/join"]:hover,
        body.public-body .deal-interest-primary:hover {
            transform: translateY(-1px) !important;
            box-shadow: 0 18px 30px rgba(185, 28, 28, 0.40), inset 0 1px 0 rgba(255,255,255,0.22) !important;
            background: linear-gradient(135deg, #b91c1c 0%, #dc2626 55%, #ef4444 100%) !important;
            filter: none !important;
        }
    

        /* ── The sticky offer bar's chat-bubble gutter has ONE owner. ─────────
           Below the desktop pill the bar is full-bleed, so it runs underneath
           the GoHighLevel chat bubble — a third-party web component fixed
           bottom-right that we cannot move. The bar's own controls must clear
           it, and the only lever is a right reserve on the row.

           That number used to live in three places (an inline style at 5.5rem,
           a `@media (max-width: 480px)` override at 3.9rem, and the desktop
           reset at 1rem), and the narrowest one was the wrong one: 3.9rem is
           62px against a bubble that reaches ~80px in from the right, so on a
           375px and a 480px phone the red offer button rendered underneath it.
           It is now stated once. The desktop rule (min-width: 768px, later in
           this file) still resets it to 1rem, where the pill does not run under
           the bubble at all.

           5.75rem = 92px: a 60px bubble at a 20px inset reaches 80px, and the
           extra 12px keeps a 44px tap target off its edge rather than merely
           off its centre. ─────────────────────────────────────────────────── */
        body.public-body #mobileOfferBar > div {
            padding-right: 5.75rem !important;
        }

        /* ── 2026-07-15 MODERN REFRESH — hero header + pricing sidebar only.
              Appended after every earlier pass (and after public-ui.css) so it
              wins ties. Language: crisp 1px borders, soft layered UNDERGLOW
              (navy/gold on neutral surfaces, hue-matched on colored ones), and
              the pricing-sidebar-card as the most-rounded container on the page.
              The four in-card CTAs (Submit an Offer / View All Photos / Attend
              Walkthrough / Save PDF Flyer) are intentionally NOT touched. ── */

        /* The pricing card's radius / border / shadow used to be restated here as
           "biggest radius on the page". The premium pass at the foot of the file
           sets all three (and takes the radius the other way, down to the hero's
           1.5rem), so this pair of rules only ever lost. Deleted. */

        /* Spread highlight — GOLD rim + gold underglow, second-most rounded.
           It was emerald, which is the operator status ramp: a green figure means
           "this cleared", and a buyer has nothing to clear. It also read as a
           promise about the number inside it, which is the one thing a spread
           estimate must not do. Gold is the page's existing "this row matters"
           accent (the hero pin tile, the kind chip's icon, the section hairlines),
           so the card still leads the pricing stack without borrowing a meaning
           from a vocabulary this surface does not speak. */
        body.public-body #propertyContent .pricing-spread-card {
            border-radius: 1.75rem !important;
            border: 1px solid rgba(231, 194, 119, 0.6) !important;
            box-shadow:
                inset 0 1px 0 rgba(255, 255, 255, 0.9),
                0 18px 38px -18px rgba(180, 106, 6, 0.28),
                0 0 26px -6px rgba(231, 194, 119, 0.32) !important;
        }

        /* Starting / ARV / Spread micro tiles — clean chip look with a soft lift. */
        body.public-body #propertyContent .pricing-micro-card {
            border-radius: 1.15rem !important;
            border: 1px solid rgba(226, 232, 240, 1) !important;
            background: linear-gradient(180deg, #ffffff, #f8fafc) !important;
            box-shadow:
                inset 0 1px 0 rgba(255, 255, 255, 0.92),
                0 10px 22px -14px rgba(30, 58, 95, 0.30) !important;
        }
        body.public-body #propertyContent .pricing-micro-card:last-child {
            border-color: rgba(110, 231, 183, 0.9) !important;
            background: linear-gradient(180deg, #f0fdf4, #dcfce7) !important;
            box-shadow:
                inset 0 1px 0 rgba(255, 255, 255, 0.92),
                0 12px 24px -12px rgba(16, 185, 129, 0.38) !important;
        }

        /* Estimated ARV / Rehab / Potential Spread rows — matching bordered pills. */
        body.public-body #propertyContent .financial-metric-card {
            border-radius: 1.1rem !important;
            border: 1px solid rgba(226, 232, 240, 1) !important;
            box-shadow:
                inset 0 1px 0 rgba(255, 255, 255, 0.9),
                0 12px 26px -16px rgba(30, 58, 95, 0.26) !important;
        }
        body.public-body #propertyContent .financial-metric-card:hover {
            border-color: rgba(30, 58, 95, 0.35) !important;
            box-shadow:
                inset 0 1px 0 rgba(255, 255, 255, 0.92),
                0 16px 32px -16px rgba(30, 58, 95, 0.36) !important;
        }

        /* Hero header action buttons (Share / Save PDF / Save / Contact / View
           Full Address) — one shared shape: same radius, 1px border, soft
           underglow, gentle hover lift. */
        body.public-body #propertyContent > .flex.flex-col.md\:flex-row button {
            border-radius: 0.95rem !important;
            box-shadow:
                inset 0 1px 0 rgba(255, 255, 255, 0.9),
                0 10px 22px -14px rgba(30, 58, 95, 0.35) !important;
            transition: transform 180ms ease, box-shadow 180ms ease, background-color 180ms ease, border-color 180ms ease !important;
        }
        body.public-body #propertyContent > .flex.flex-col.md\:flex-row button:hover {
            transform: translateY(-1px);
            box-shadow:
                inset 0 1px 0 rgba(255, 255, 255, 0.92),
                0 16px 30px -14px rgba(30, 58, 95, 0.45) !important;
        }
        /* White header buttons get a navy-tinted border so they read as one set. */
        body.public-body #propertyContent > .flex.flex-col.md\:flex-row button.bg-white {
            border: 1px solid rgba(30, 58, 95, 0.16) !important;
            color: #1e3a5f !important;
        }
        body.public-body #propertyContent > .flex.flex-col.md\:flex-row button.bg-white:hover {
            border-color: rgba(30, 58, 95, 0.38) !important;
            background: linear-gradient(180deg, #ffffff, #f1f5f9) !important;
        }
        /* Contact — the canonical crimson CTA gradient + hue-matched underglow. */
        body.public-body #propertyContent > .flex.flex-col.md\:flex-row button.bg-secondary {
            background: linear-gradient(135deg, #b91c1c 0%, #dc2626 55%, #ef4444 100%) !important;
            border: 1px solid rgba(252, 165, 165, 0.45) !important;
            box-shadow:
                inset 0 1px 0 rgba(255, 255, 255, 0.16),
                0 12px 26px -12px rgba(185, 28, 28, 0.55) !important;
        }
        body.public-body #propertyContent > .flex.flex-col.md\:flex-row button.bg-secondary:hover {
            box-shadow:
                inset 0 1px 0 rgba(255, 255, 255, 0.22),
                0 18px 34px -12px rgba(185, 28, 28, 0.65) !important;
        }

        /* Status chip next to the title — soften into a bordered pill. */
        body.public-body #propertyContent #statusBadge {
            border-radius: 0.65rem;
            letter-spacing: 0.06em;
            box-shadow:
                inset 0 1px 0 rgba(255, 255, 255, 0.35),
                0 8px 18px -10px rgba(15, 23, 42, 0.35);
        }

        /* Main photo frame — rounder corners + soft navy/gold underglow. */
        body.public-body #propertyContent .deal-image-frame {
            border-radius: 1.4rem !important;
            border: 1px solid rgba(226, 232, 240, 0.9) !important;
            box-shadow: 0 18px 40px -28px rgba(15, 23, 42, 0.30) !important;
        }

        /* ── Property Details card — brought into the same brokerage language as
              the pricing sidebar (the earlier refresh left it as flat gray boxes).
              Scoped to the sidebar column so the left-column content cards are
              untouched. Bordered tiles + soft navy underglow, gentle hover lift,
              the four spec numbers reading as navy stats instead of plain text. ── */
        body.public-body #propertyContent .dd-col-sidebar .grid.grid-cols-2.gap-4 > .bg-gray-50 {
            background: linear-gradient(180deg, #ffffff, #f8fafc) !important;
            border: 1px solid rgba(226, 232, 240, 1) !important;
            border-radius: var(--radius-lg) !important;
            box-shadow:
                inset 0 1px 0 rgba(255, 255, 255, 0.92),
                0 10px 22px -14px rgba(30, 58, 95, 0.28) !important;
            transition: transform 180ms ease, box-shadow 180ms ease, border-color 180ms ease !important;
        }
        body.public-body #propertyContent .dd-col-sidebar .grid.grid-cols-2.gap-4 > .bg-gray-50:hover {
            transform: translateY(-2px);
            border-color: rgba(30, 58, 95, 0.32) !important;
            box-shadow:
                inset 0 1px 0 rgba(255, 255, 255, 0.94),
                0 16px 30px -16px rgba(30, 58, 95, 0.38) !important;
        }
        /* Spec value → navy, tighter and larger so the number is the hero of the tile. */
        body.public-body #propertyContent .dd-col-sidebar .grid.grid-cols-2.gap-4 > .bg-gray-50 > p:last-child {
            color: #1e3a5f !important;
            font-weight: 800 !important;
            letter-spacing: -0.01em;
        }
        /* Spec label → quiet uppercase micro-label, matching the pricing micro tiles. */
        body.public-body #propertyContent .dd-col-sidebar .grid.grid-cols-2.gap-4 > .bg-gray-50 > p:first-of-type {
            text-transform: uppercase;
            letter-spacing: 0.08em;
            font-weight: 600;
            color: #64748b !important;
        }
        /* Key/value rows below the tiles — firmer dividers + a touch more air. */
        body.public-body #propertyContent .dd-col-sidebar .grid.grid-cols-2.gap-4 ~ .mt-4 > .flex.justify-between {
            padding: 0.35rem 0;
            border-bottom: 1px solid rgba(226, 232, 240, 0.7);
        }
        body.public-body #propertyContent .dd-col-sidebar .grid.grid-cols-2.gap-4 ~ .mt-4 > .flex.justify-between:last-child {
            border-bottom: 0;
        }
    

        /* ── 2026-07-18 DEAL-PAGE REFRESH — top region + surfaces.
              Last style block in the head, so it wins every tie (public-ui.css
              and all earlier inline passes included). ── */

        /* 1) Ray effect behind the containers on the main background: the
              black brand ray sheet rises from the top of <main> and fades out
              before the footer; every container stacks above it. */
        body.public-body main.pt-8 {
            position: relative;
        }
        body.public-body main.pt-8::before {
            content: '';
            position: absolute;
            inset: 0;
            background: url('/branding/rayeffect-m-black.webp') 50% 0% / cover no-repeat;
            opacity: 0.09;
            mix-blend-mode: multiply;
            -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 52%, transparent 90%);
            mask-image: linear-gradient(to bottom, #000 0%, #000 52%, transparent 90%);
            pointer-events: none;
            z-index: 0;
        }
        body.public-body main.pt-8 > div {
            position: relative;
            z-index: 1;
        }

        /* 2) COHESIVE HERO — the whole top region rebuilt as ONE command card
              instead of the old title-left / buttons-right split: a
              section-border rail flush to the top edge, a faint ray wash in
              the corner (ties to the page's ray theme), a meta cluster where
              the kind chip + Active status sit together, a gold-tiled
              headline, then a hairline-divided action bar. */
        /* overflow is VISIBLE on purpose: the price chip's tooltip opens upward
           out of the card, and `overflow: hidden` sheared its top off — the
           silent-auction copy is long enough to be taller than the space above
           the action bar. The two decorative pseudos carry their own matching
           corner radii instead, which is all the clipping ever did here. */
        body.public-body #propertyContent .deal-hero {
            position: relative;
            overflow: visible;
            margin-bottom: 1.5rem;
            padding: 1.6rem 1.6rem 1.5rem;
            border-radius: 1.6rem;
            background:
                radial-gradient(120% 90% at 100% 0%, rgba(30, 58, 95, 0.06), transparent 42%),
                linear-gradient(180deg, #ffffff 0%, #f7fafd 100%);
            border: 1px solid rgba(226, 232, 240, 0.95);
            box-shadow:
                inset 0 1px 0 rgba(255, 255, 255, 0.9),
                0 26px 54px -26px rgba(15, 23, 42, 0.28);
        }
        @media (min-width: 768px) {
            body.public-body #propertyContent .deal-hero { padding: 1.9rem 2.1rem 1.7rem; }
        }
        /* Section-border rail flush to the card's top edge. */
        body.public-body #propertyContent .deal-hero::before {
            content: '';
            position: absolute;
            top: 0; left: 0; right: 0;
            height: 3px;
            background: linear-gradient(90deg, rgba(53, 95, 140, 0) 0%, #35608f 12%, #c0303d 50%, #35608f 88%, rgba(53, 95, 140, 0) 100%);
            border-radius: 1.6rem 1.6rem 0 0;
            z-index: 3;
        }
        /* Faint corner ray wash. */
        body.public-body #propertyContent .deal-hero::after {
            content: '';
            position: absolute;
            top: 0; right: 0;
            width: 46%;
            height: 100%;
            background: url('/branding/rayeffect-m-black.webp') 100% 0% / cover no-repeat;
            opacity: 0.05;
            mix-blend-mode: multiply;
            -webkit-mask-image: linear-gradient(to left, #000, transparent 85%);
            mask-image: linear-gradient(to left, #000, transparent 85%);
            border-radius: 0 1.6rem 1.6rem 0;
            pointer-events: none;
            z-index: 0;
        }
        body.public-body #propertyContent .deal-hero > * { position: relative; z-index: 1; }

        /* Meta row: kind chip + Active status pill, side by side. */
        body.public-body #propertyContent .deal-hero-meta {
            display: flex;
            align-items: center;
            flex-wrap: wrap;
            gap: 0.6rem;
            margin-bottom: 1rem;
        }
        body.public-body .deal-kind-chip {
            display: inline-flex;
            align-items: center;
            gap: 0.5rem;
            margin: 0;
            padding: 0.42rem 1rem;
            border-radius: 9999px;
            background: linear-gradient(135deg, #10243f 0%, #1e3a5f 100%);
            border: 1px solid rgba(255, 255, 255, 0.16);
            color: #ffffff;
            font-family: 'Outfit', sans-serif;
            font-size: 0.72rem;
            font-weight: 700;
            letter-spacing: 0.22em;
            text-transform: uppercase;
            box-shadow:
                inset 0 1px 0 rgba(255, 255, 255, 0.14),
                0 10px 20px -10px rgba(30, 58, 95, 0.55);
        }
        body.public-body .deal-kind-chip i,
        body.public-body .deal-kind-chip svg { color: #e7c277; }
        /* Status pill matches the chip's pill shape + type. renderDeal rewrites the
           badge's className wholesale, so the chrome lives on the ID and the COLOUR
           comes off `data-status`, which survives that rewrite. */
        body.public-body #propertyContent .deal-hero-meta #statusBadge {
            margin: 0;
            padding: 0.42rem 0.9rem !important;
            border-radius: 9999px !important;
            font-size: 0.72rem !important;
            letter-spacing: 0.16em;
            border: 1px solid rgba(255, 255, 255, 0.18);
            box-shadow:
                inset 0 1px 0 rgba(255, 255, 255, 0.2),
                0 10px 20px -12px rgba(15, 23, 42, 0.45);
        }
        /* ACTIVE: green, per explicit operator override on 2026-08-25 — this
           deliberately breaks the Status-Is-Not-Brand rule documented above
           (green was avoided site-wide because it borrows "this cleared" from
           a vocabulary only an operator has). White ink; green at this weight
           fails contrast with dark text. */
        body.public-body #propertyContent .deal-hero-meta #statusBadge[data-status="active"] {
            background: linear-gradient(180deg, #22c55e 0%, #16a34a 100%);
            color: #ffffff;
            border-color: rgba(255, 255, 255, 0.55);
        }
        /* Pending and sold are not invitations, so they step into the neutral ramp
           rather than taking amber-warning and red-danger off the operator shelf. */
        body.public-body #propertyContent .deal-hero-meta #statusBadge[data-status="pending"],
        body.public-body #propertyContent .deal-hero-meta #statusBadge[data-status="unknown"] {
            background: linear-gradient(180deg, #64748b 0%, #475569 100%);
            color: #ffffff;
        }
        body.public-body #propertyContent .deal-hero-meta #statusBadge[data-status="sold"] {
            background: linear-gradient(180deg, #475569 0%, #334155 100%);
            color: #ffffff;
        }

        /* The photo-overlay badge's gold state. A class rather than a Tailwind
           arbitrary value because the gold face needs dark ink AND a lit rim, and
           `bg-[#f5b301] text-[#422006]` only compiles if this file is inside the
           Tailwind content globs — a colour that silently compiles to nothing is
           worse than the orange it replaced. */
        body.public-body #propertyContent .dd-badge-gold {
            background: linear-gradient(180deg, #fbbf24 0%, #f59e0b 100%);
            color: #422006;
            box-shadow:
                inset 0 1px 0 rgba(255, 255, 255, 0.5),
                0 10px 20px -10px rgba(180, 106, 6, 0.6);
        }
        body.public-body #propertyContent .dd-badge-gold i,
        body.public-body #propertyContent .dd-badge-gold svg { color: #422006; }

        /* Headline: gold-tiled pin + title, address underneath. */
        body.public-body #propertyContent .deal-hero-headline {
            display: flex;
            align-items: flex-start;
            gap: 0.85rem;
        }
        body.public-body #propertyContent .deal-hero-headline .deal-header-map-icon {
            flex-shrink: 0;
            display: inline-flex;
            align-items: center;
            justify-content: center;
            width: 2.6rem;
            height: 2.6rem;
            margin-top: 0.15rem;
            border-radius: 0.9rem;
            background: linear-gradient(135deg, #10243f 0%, #1e3a5f 100%);
            border: 1px solid rgba(231, 194, 119, 0.4);
            box-shadow:
                inset 0 1px 0 rgba(255, 255, 255, 0.14),
                0 10px 20px -12px rgba(15, 23, 42, 0.5);
        }
        body.public-body #propertyContent .deal-hero-headline .deal-header-map-icon i,
        body.public-body #propertyContent .deal-hero-headline .deal-header-map-icon svg { color: #e7c277 !important; }
        body.public-body #propertyContent .deal-hero h1 { line-height: 1.1; }
        body.public-body #propertyContent .deal-hero #propertyAddress { margin-top: 0.35rem; }

        /* 3) Action bar: hairline-divided from the headline. Secondary cluster
              left (slim), Contact primary right. Wraps to full-width on mobile. */
        /* Hero stat chips — the landing-style quick-scan row (type · beds · baths ·
           sqft · starting price). Price chip is the emphasised navy pill. */
        body.public-body #propertyContent .deal-hero-stats {
            display: flex;
            flex-wrap: wrap;
            align-items: center;
            gap: 0.5rem;
            margin-top: 1.1rem;
        }
        body.public-body #propertyContent .deal-stat-chip {
            display: inline-flex;
            align-items: center;
            gap: 0.4rem;
            padding: 0.42rem 0.8rem;
            border-radius: 0.85rem;
            background: #f1f5f9;
            border: 1px solid rgba(226, 232, 240, 0.9);
            font-size: 0.86rem;
            font-weight: 600;
            color: #334155;
            white-space: nowrap;
        }
        body.public-body #propertyContent .deal-stat-chip b { color: #0f172a; font-weight: 800; }
        body.public-body #propertyContent .deal-stat-chip svg { color: #1e3a5f; }
        /* Light-green treatment, matching the spread card's emerald accent. */
        body.public-body #propertyContent .deal-stat-chip-type {
            background: rgba(16, 185, 129, 0.10);
            border-color: rgba(52, 211, 153, 0.55);
            color: #047857;
            text-transform: capitalize;
        }
        body.public-body #propertyContent .deal-stat-chip-type svg { color: #059669; }
        /* Matches the `.deal-kind-chip` ("Investment Property") treatment — same
           navy gradient, hairline highlight and lift — but a rounded RECTANGLE
           rather than that chip's full 9999px pill. */
        /* NOT position:relative. The price tip is a child of this chip, so a
           relative chip made the CHIP the tip's containing block — a 30rem
           bubble anchored `left:0` on a 233px pill, which ran ~100px past the
           right edge of a phone and cut the copy off mid-sentence. The tip now
           resolves against .deal-hero-actionbar (already relative, full row
           width), so it can never over-extend on either side. */
        body.public-body #propertyContent .deal-stat-chip-price {
            margin-left: auto;
            background: linear-gradient(135deg, #10243f 0%, #1e3a5f 100%);
            border: 1px solid rgba(255, 255, 255, 0.16);
            border-radius: 0.7rem;
            color: #fff;
            padding: 0.5rem 1rem;
            box-shadow:
                inset 0 1px 0 rgba(255, 255, 255, 0.14),
                0 10px 20px -10px rgba(30, 58, 95, 0.55);
        }
        body.public-body #propertyContent .deal-stat-chip-price b { color: #fff; font-size: 1.02rem; }
        body.public-body #propertyContent .deal-stat-chip-price .deal-stat-chip-label {
            font-family: 'Outfit', sans-serif;
            font-size: 0.68rem; font-weight: 700; letter-spacing: 0.22em; text-transform: uppercase; color: rgba(231, 194, 119, 0.95);
        }
        /* The tip on this chip had NO affordance — the label just happened to be
           hoverable, so the one explanation of the most misread number on the
           page was undiscoverable. Gold ring on the navy chip (the .deal-tip-mark
           idiom, recoloured for a dark ground). It LEADS the label for the same
           reason the pricing card's help link does. Its own letter-spacing is 0:
           the label's 0.22em would push it a third of a character off. */
        body.public-body #propertyContent .deal-stat-chip-price .deal-chip-tip-mark {
            display: inline-flex; align-items: center; justify-content: center;
            width: 0.95rem; height: 0.95rem; margin-right: 0.4rem;
            border-radius: 999px; border: 1px solid rgba(231, 194, 119, 0.6);
            color: rgba(231, 194, 119, 0.95);
            font-size: 0.62rem; font-weight: 800; line-height: 1; letter-spacing: 0;
            cursor: help; vertical-align: middle;
        }

        /* Hover/focus tooltip on the price chip. That label is the most misread
           thing on the page — buyers read it as a list price and assume an
           assignment fee is baked into it. Pure CSS, no JS; `tabindex` on the
           label plus the `:focus-within` twin keep it reachable by keyboard. */
        body.public-body #propertyContent .deal-price-tip {
            position: absolute;
            /* Anchored on the action bar, not the chip — see the note on
               .deal-stat-chip-price. left/right:0 pins it to the row's own
               measure, so it stays inside the card at every width. */
            bottom: calc(100% + 0.55rem);
            left: 0;
            right: 0;
            z-index: 40;
            width: auto;
            max-width: 30rem;
            padding: 0.8rem 0.9rem;
            border-radius: 0.75rem;
            background: #0f1f36;
            border: 1px solid rgba(231, 194, 119, 0.35);
            box-shadow: 0 18px 38px -18px rgba(8, 15, 28, 0.75);
            color: #e2e8f0;
            font-family: 'Outfit', sans-serif;
            font-size: 0.78rem;
            font-weight: 500;
            line-height: 1.45;
            letter-spacing: 0;
            text-transform: none;
            white-space: normal;
            opacity: 0;
            visibility: hidden;
            transform: translateY(4px);
            transition: opacity 0.16s ease, transform 0.16s ease, visibility 0.16s;
        }
        body.public-body #propertyContent .deal-price-tip b { color: #f7d99a; font-weight: 800; }
        body.public-body #propertyContent .deal-stat-chip-price:hover .deal-price-tip,
        body.public-body #propertyContent .deal-stat-chip-price:focus-within .deal-price-tip {
            opacity: 1;
            visibility: visible;
            transform: translateY(0);
        }
        @media (max-width: 640px) {
            body.public-body #propertyContent .deal-stat-chip-price { margin-left: 0; width: 100%; justify-content: space-between; }
        }

        /* Same tooltip mechanics as the price chip, on the status pill. "ACTIVE" is
           the one word on this page that reads as "no rush" when it means the
           opposite, so hovering it says how long these actually last.

           The wrapper carries the hover/reveal state, NOT #statusBadge: renderDeal
           REPLACES that element's whole className to swap the status colour, so any
           class parked on the badge itself is wiped on first paint. The wrapper also
           carries .is-active, so a SOLD or PENDING deal shows no "move fast" tip.

           The tip's own z-index is NOT enough to lift it over the headline.
           `.deal-hero > *` puts position:relative + z-index:1 on EVERY direct
           child, so the meta row and the headline row are sibling stacking
           CONTEXTS at the same level — the headline paints over the meta row on
           DOM order alone, and z-index:40 inside the meta row can never escape
           it (that is why the title and address showed THROUGH the bubble). The
           row that owns the tip has to outrank its siblings. */
        /* 30, not 5. This row opens its OWN stacking context (position:relative from
           `.deal-hero > *` plus a z-index), so the tip's z-index 40 is sealed inside it
           and the row's own number is the only thing that competes with the rest of the
           page. At 5 it lost to every 3px section rail that outranked it — the gallery
           frame's gold rail (6) and the sibling card rails — which is why a hairline
           painted straight ACROSS the open tooltip. 30 clears every decorative rail and
           the action bar (20) while staying under the site chrome (45+), so the nav and
           any modal still win. Same trap, same fix, as .deal-hero-actionbar below. */
        body.public-body #propertyContent .deal-hero-meta { z-index: 30; }
        body.public-body #propertyContent .deal-status-chip { position: relative; display: inline-flex; align-items: center; }
        /* The circled "?" that makes the status pill hoverable at all — previously the pill
           itself was the only affordance, so nothing told a buyer there was anything to
           reveal. Reuses the light-ground .deal-tip-mark idiom (defined below) rather than
           the price chip's gold-on-navy variant: this mark sits on the page's white ground
           next to a COLORED pill (gold when active), not on the navy chip. Hidden entirely
           on a non-active deal — there is no tip to show a sold or pending buyer. */
        /* The circled "?" lives INSIDE the pill, leading the word — not floating
           beside it. The badge's own className is rewritten wholesale on every
           render, so the mark stays a SIBLING absolutely positioned over the
           badge's left padding rather than a child that would be wiped. */
        body.public-body #propertyContent .deal-status-chip.is-active #statusBadge {
            padding-left: 2.1rem !important;
        }
        body.public-body #propertyContent .deal-status-mark {
            position: absolute;
            left: 0.55rem;
            top: 50%;
            transform: translateY(-50%);
            display: inline-flex;
            align-items: center;
            justify-content: center;
            width: 1.05rem;
            height: 1.05rem;
            margin: 0;
            border-radius: 999px;
            /* The mark only ever shows on an ACTIVE deal, and that pill is now gold
               rather than green. White-on-transparent read fine on green and lands at
               about 1.9:1 on gold, so it takes the same dark ink the label does. */
            border: 1.5px solid rgba(66, 32, 6, 0.55);
            background: transparent;
            color: #422006;
            font-size: 0.66rem;
            font-weight: 800;
            line-height: 1;
            cursor: help;
        }
        body.public-body #propertyContent .deal-status-mark:focus-visible {
            outline: 2px solid rgba(66, 32, 6, 0.75);
            outline-offset: 2px;
        }
        body.public-body #propertyContent .deal-status-chip:not(.is-active) .deal-status-mark { display: none; }
        body.public-body #propertyContent .deal-status-tip {
            position: absolute;
            top: calc(100% + 0.5rem);
            left: 0;
            z-index: 40;
            width: min(22rem, 78vw);
            padding: 0.8rem 0.9rem;
            border-radius: 0.75rem;
            background: #0f1f36;
            border: 1px solid rgba(231, 194, 119, 0.35);
            box-shadow: 0 18px 38px -18px rgba(8, 15, 28, 0.75);
            color: #e2e8f0;
            font-family: 'Outfit', sans-serif;
            font-size: 0.78rem;
            font-weight: 500;
            line-height: 1.45;
            letter-spacing: 0;
            text-transform: none;
            white-space: normal;
            opacity: 0;
            visibility: hidden;
            transform: translateY(-4px);
            transition: opacity 0.16s ease, transform 0.16s ease, visibility 0.16s;
        }
        body.public-body #propertyContent .deal-status-tip b { color: #f7d99a; font-weight: 800; }
        body.public-body #propertyContent .deal-status-chip.is-active:hover .deal-status-tip,
        body.public-body #propertyContent .deal-status-chip.is-active:focus-within .deal-status-tip {
            opacity: 1;
            visibility: visible;
            transform: translateY(0);
        }

        /* ── Reusable explainer tooltip ──────────────────────────────────────────
           The price chip and the status pill each grew their own copy of this. A
           THIRD copy for ARV/Spread/EMD/Deadline would guarantee the four drift, so
           these two classes are the generic version: put .deal-tip-host on whatever
           the buyer hovers, .deal-tip on the bubble inside it.

           Every place it is used is a number buyers read as a PROMISE — ARV as an
           appraisal, Spread as profit, the deadline as a queue position. The tip is
           where we say what the number actually is, next to the number itself,
           instead of in fine print further down the page nobody reaches. */
        body.public-body #propertyContent .deal-tip-host { position: relative; }
        body.public-body #propertyContent .deal-tip {
            position: absolute;
            top: calc(100% + 0.45rem);
            left: 50%;
            transform: translate(-50%, -4px);
            z-index: 45;
            width: min(20rem, 74vw);
            padding: 0.7rem 0.85rem;
            border-radius: 0.7rem;
            background: #0f1f36;
            border: 1px solid rgba(231, 194, 119, 0.35);
            box-shadow: 0 18px 38px -18px rgba(8, 15, 28, 0.75);
            color: #e2e8f0;
            font-family: 'Outfit', sans-serif;
            font-size: 0.75rem;
            font-weight: 500;
            line-height: 1.45;
            letter-spacing: 0;
            text-transform: none;
            text-align: left;
            white-space: normal;
            opacity: 0;
            visibility: hidden;
            transition: opacity 0.16s ease, transform 0.16s ease, visibility 0.16s;
        }
        body.public-body #propertyContent .deal-tip b { color: #f7d99a; font-weight: 800; }
        body.public-body #propertyContent .deal-tip-host:hover .deal-tip,
        body.public-body #propertyContent .deal-tip-host:focus-within .deal-tip {
            opacity: 1;
            visibility: visible;
            transform: translate(-50%, 0);
        }
        /* The rightmost tile is ~100px wide and the bubble is ~320px, so a centred
           tip on it hangs a third of its width past the card — off-screen entirely
           once the sidebar goes full-width on a phone. Anchor that one to its right
           edge instead; the middle tile has room either side and stays centred. */
        body.public-body #propertyContent .pricing-micro-card:last-child > .deal-tip {
            left: auto;
            right: 0;
            transform: translate(0, -4px);
        }
        body.public-body #propertyContent .pricing-micro-card:last-child:hover > .deal-tip,
        body.public-body #propertyContent .pricing-micro-card:last-child:focus-within > .deal-tip {
            transform: translate(0, 0);
        }
        /* The hint dot — without it nothing tells a buyer there is anything to hover,
           and a tooltip nobody discovers explains nothing.

           DESCENDANT, not `>`. On the deadline and EMD rows the mark is a direct
           child of the host; on the ARV and Spread tiles it sits inside the label
           paragraph, so the child combinator skipped both — those two rendered a
           bare inline "ARV?" / "SPREAD?" with no circle, no help cursor and no
           focus ring. The one pair of numbers buyers most often misread as an
           appraisal and as profit were the pair whose explainer looked like a
           typo. */
        body.public-body #propertyContent .deal-tip-host .deal-tip-mark {
            display: inline-flex; align-items: center; justify-content: center;
            width: 0.95rem; height: 0.95rem; margin-left: 0.3rem;
            border-radius: 999px; border: 1px solid rgba(30, 58, 95, 0.35);
            color: #1e3a5f; font-size: 0.62rem; font-weight: 800; line-height: 1;
            cursor: help; vertical-align: middle;
        }
        body.public-body #propertyContent .deal-tip-host .deal-tip-mark:focus-visible {
            outline: 2px solid rgba(30, 58, 95, 0.55); outline-offset: 2px;
        }

        /* Locked-address notice. Sits under the address line and only appears when a
           SIGNED-IN member is blocked from the full street — an anonymous visitor
           already has the "View Full Address" capture path and needs no explaining. */
        body.public-body #propertyContent #addressLockNotice {
            display: none;
            align-items: flex-start;
            gap: 0.5rem;
            margin-top: 0.5rem;
            padding: 0.6rem 0.8rem;
            border-radius: 0.7rem;
            border: 1px solid rgba(231, 194, 119, 0.45);
            background: rgba(231, 194, 119, 0.12);
            color: #4a3b1c;
            font-size: 0.82rem;
            line-height: 1.45;
        }
        body.public-body #propertyContent #addressLockNotice.is-shown { display: flex; }
        body.public-body #propertyContent #addressLockNotice a { font-weight: 800; color: #8f232e; text-decoration: underline; }

        /* `position: relative` is LOAD-BEARING: it is the containing block for
           .deal-price-tip (see the note above that rule). The z-index is too —
           this row already opened a stacking context at z-index 1, which
           trapped the tip's own z-index 40 inside it, so the "INVESTMENT
           PROPERTY" chip and the "ACTIVE" pill above (both positioned, z auto,
           in the hero's context) painted straight over the tooltip copy. 20
           puts the whole row, tooltip included, above them. */
        body.public-body #propertyContent .deal-hero-actionbar {
            position: relative;
            z-index: 20;
            display: flex;
            align-items: center;
            justify-content: space-between;
            flex-wrap: wrap;
            gap: 0.75rem;
            margin-top: 1.25rem;
            padding-top: 1.25rem;
            border-top: 1px solid rgba(226, 232, 240, 0.9);
        }
        /* The two hero rows each own a tooltip that opens INTO the other one:
           the price tip opens upward into the meta row, the status tip opens
           downward into the action bar. No pair of fixed numbers can satisfy
           both — at meta 30 / bar 20 the "Investment Property" chip and the
           "Active" pill painted straight over the open price tip. So the row
           BEING USED wins: hover/focus lifts it above its sibling (still under
           the 45+ site chrome, so nav and modals keep the top). */
        body.public-body #propertyContent .deal-hero-meta:hover,
        body.public-body #propertyContent .deal-hero-meta:focus-within,
        body.public-body #propertyContent .deal-hero-actionbar:hover,
        body.public-body #propertyContent .deal-hero-actionbar:focus-within { z-index: 35; }
        body.public-body .deal-top-actions {
            display: flex;
            flex-wrap: wrap;
            gap: 0.5rem;
            justify-content: flex-start;
        }
        body.public-body .deal-top-actions button {
            padding: 0.48rem 0.9rem !important;
            font-size: 0.85rem !important;
            border-radius: 0.85rem !important;
        }
        /* Contact = the emphasised primary: standardized crimson skin, larger,
           gold-glow lift on hover. Selector out-specifies the earlier
           contactAboutDeal() crimson rule so this exact skin lands. */
        body.public-body #propertyContent button.deal-contact-primary[onclick] {
            padding: 0.6rem 1.4rem !important;
            font-size: 0.9rem !important;
            border-radius: 0.95rem !important;
            background: linear-gradient(160deg, #d03a4a 0%, #c0303d 40%, #a52833 100%) !important;
            border: 1px solid rgba(255, 255, 255, 0.16) !important;
            box-shadow:
                inset 0 1px 0 rgba(255, 255, 255, 0.18),
                0 16px 28px -14px rgba(165, 40, 51, 0.55) !important;
            transition: transform 220ms cubic-bezier(0.22, 1, 0.36, 1), box-shadow 220ms ease, filter 220ms ease !important;
        }
        body.public-body #propertyContent button.deal-contact-primary[onclick]:hover {
            transform: translateY(-2px);
            filter: brightness(1.05);
            box-shadow:
                inset 0 1px 0 rgba(255, 255, 255, 0.22),
                0 24px 40px -18px rgba(165, 40, 51, 0.6),
                0 0 22px -4px rgba(231, 194, 119, 0.4) !important;
        }
        @media (max-width: 767px) {
            body.public-body #propertyContent .deal-hero-actionbar { justify-content: stretch; }
            body.public-body #propertyContent button.deal-contact-primary[onclick] { width: 100%; }
        }

        /* 4) Photos section — inward bordered, impressed/embossed. The recess
              overlay rides ABOVE the image (the frame clips it), the thumb
              strip becomes a pressed track, and the outer shadow pulls back so
              the card reads sunk-in rather than floating. */
        /* De-embossed photo frame: flat clean edge, one soft ambient shadow, no inset
           pressed-in look. Sits first under the hero as the lead visual. */
        body.public-body #propertyContent .deal-image-frame {
            position: relative;
            border: 1px solid rgba(226, 232, 240, 0.9) !important;
            box-shadow: 0 18px 40px -28px rgba(15, 23, 42, 0.30) !important;
        }
        body.public-body #propertyContent .deal-image-frame::after {
            content: none !important;
            box-shadow: none !important;
        }
        body.public-body #propertyContent #galleryThumbs {
            background: #ffffff;
            box-shadow: none;
            border-top: 1px solid rgba(226, 232, 240, 0.9);
        }
        body.public-body #propertyContent #galleryThumbs img,
        body.public-body #propertyContent #galleryThumbs > * {
            border-radius: 0.7rem;
        }

        /* 5) Sidebar CTAs join the premium button system — one shared frame
              (hairline border, inset highlight, 1.1rem radius, lift + glow
              hover), each in its standardized hue. */
        body.public-body .pricing-primary-cta,
        body.public-body #viewAllMediaBtn,
        body.public-body .pricing-secondary-cta,
        body.public-body .pricing-tertiary-cta {
            border-radius: 1.1rem !important;
            transition: transform 240ms cubic-bezier(0.22, 1, 0.36, 1), box-shadow 240ms ease, filter 240ms ease !important;
        }
        body.public-body .pricing-primary-cta {
            background: linear-gradient(160deg, #d03a4a 0%, #c0303d 40%, #a52833 100%) !important;
            border: 1px solid rgba(255, 255, 255, 0.16) !important;
            box-shadow:
                inset 0 1px 0 rgba(255, 255, 255, 0.18),
                0 18px 30px -14px rgba(165, 40, 51, 0.55) !important;
        }
        body.public-body .pricing-primary-cta:hover {
            transform: translateY(-2px);
            filter: brightness(1.05);
            background: linear-gradient(160deg, #d03a4a 0%, #c0303d 40%, #a52833 100%) !important;
            box-shadow:
                inset 0 1px 0 rgba(255, 255, 255, 0.22),
                0 26px 44px -18px rgba(165, 40, 51, 0.65),
                0 0 24px -4px rgba(231, 194, 119, 0.4) !important;
        }
        body.public-body #viewAllMediaBtn {
            background: linear-gradient(160deg, #2a5a8a 0%, #1e3a5f 45%, #10243f 100%) !important;
            border: 1px solid rgba(255, 255, 255, 0.16) !important;
            box-shadow:
                inset 0 1px 0 rgba(255, 255, 255, 0.14),
                0 18px 30px -14px rgba(8, 15, 28, 0.5) !important;
        }
        body.public-body #viewAllMediaBtn:hover {
            transform: translateY(-2px);
            filter: brightness(1.06);
            box-shadow:
                inset 0 1px 0 rgba(255, 255, 255, 0.18),
                0 26px 44px -18px rgba(8, 15, 28, 0.6),
                0 0 22px -4px rgba(125, 211, 252, 0.35) !important;
        }
        body.public-body .pricing-secondary-cta {
            background: linear-gradient(135deg, #f0d394 0%, #e7c277 40%, #c9a24f 100%) !important;
            border: 1px solid rgba(255, 246, 224, 0.55) !important;
            color: #10243f !important;
            box-shadow:
                inset 0 1px 0 rgba(255, 255, 255, 0.5),
                0 16px 28px -14px rgba(0, 0, 0, 0.4),
                0 0 22px -4px rgba(231, 194, 119, 0.45) !important;
        }
        body.public-body .pricing-secondary-cta:hover {
            transform: translateY(-2px);
            filter: brightness(1.04);
            background: linear-gradient(135deg, #f0d394 0%, #e7c277 40%, #c9a24f 100%) !important;
            box-shadow:
                inset 0 1px 0 rgba(255, 255, 255, 0.55),
                0 24px 40px -18px rgba(0, 0, 0, 0.45),
                0 0 32px 0 rgba(231, 194, 119, 0.6) !important;
        }
        body.public-body .pricing-secondary-cta i { color: #10243f !important; }
        body.public-body .pricing-tertiary-cta {
            background: linear-gradient(180deg, #ffffff 0%, #eef2f7 100%) !important;
            border: 1px solid rgba(30, 58, 95, 0.2) !important;
            color: #1e3a5f !important;
            box-shadow:
                inset 0 1px 0 rgba(255, 255, 255, 0.9),
                0 12px 24px -14px rgba(30, 58, 95, 0.35) !important;
        }
        body.public-body .pricing-tertiary-cta:hover {
            transform: translateY(-2px);
            background: linear-gradient(180deg, #ffffff 0%, #e2e8f0 100%) !important;
            border-color: rgba(30, 58, 95, 0.4) !important;
            box-shadow:
                inset 0 1px 0 rgba(255, 255, 255, 0.92),
                0 18px 34px -16px rgba(30, 58, 95, 0.45) !important;
        }
        body.public-body .pricing-tertiary-cta i { color: #1e3a5f !important; }

        /* 6) Sidebar CTA left accent bar — light navy premium edge
              (was the light-red edge, brand call 2026-07-19) and
              nudged slightly into the button instead of flush to the edge.
              Two IDs deep so it out-specifies the earlier per-button edge rules. */
        body.public-body #propertyContent .pricing-primary-cta::before,
        body.public-body #propertyContent #viewAllMediaBtn::before,
        body.public-body #propertyContent .pricing-secondary-cta::before,
        body.public-body #propertyContent #detailAddressActionBtn::before {
            left: 0.5rem !important;
            background: linear-gradient(180deg, #cfe0f5 0%, #7da3cf 100%) !important;
            box-shadow: 0 0 14px rgba(125, 163, 207, 0.6) !important;
        }
    
        /* =====================================================================
           MARKETPLACE LAYOUT PASS — appended LAST so it wins every earlier
           override in this file. Structural, not decorative: it lays out the
           new showcase band, builds the photo collage, and strips the surface
           effects that were making a data-dense page feel busy.
           ===================================================================== */

        /* --- 1) SHOWCASE: ONE 2:1 layout for the whole deal body. ------------
           Photos + write-up left, price + facts right. A single grid replaces
           the old full-width photo band, full-width value band and separate
           content grid, so nothing has to be re-aligned across three seams —
           and the left column can no longer end in a tall block of whitespace
           just because the right one ran longer. */
        body.public-body #propertyContent .deal-showcase {
            display: grid;
            grid-template-columns: minmax(0, 1fr);
            gap: 1.5rem;
            align-items: start;
        }
        @media (min-width: 1024px) {
            body.public-body #propertyContent .deal-showcase {
                grid-template-columns: minmax(0, 2fr) minmax(20rem, 1fr);
                gap: 2rem;
            }
        }
        /* Both columns carry their own vertical rhythm. The left one never had
           a spacing utility (it used to hold a single card); the right one lost
           its `space-y-6` wrapper in the merge. */
        body.public-body #propertyContent .deal-showcase-media,
        body.public-body #propertyContent .deal-showcase-rail {
            display: flex;
            flex-direction: column;
            gap: 1.5rem;
            min-width: 0;
        }
        /* Margin utilities carried over from when these cards were stacked in a
           different container would double up on the flex gap. `min-width: 0`
           is load-bearing, not tidiness: a flex item defaults to min-width:auto,
           so ONE wide child (the horizontally-scrolling thumb strip, a map embed)
           would otherwise stretch the whole column past the viewport and give
           the page a horizontal scrollbar on phones. */
        body.public-body #propertyContent .deal-showcase-media > *,
        body.public-body #propertyContent .deal-showcase-rail > * {
            margin-top: 0 !important;
            margin-bottom: 0 !important;
            min-width: 0;
            max-width: 100%;
        }
        /* The gated-location map embed is sized in px and overhangs a 375px
           viewport by ~40px, which is enough to make the whole page scroll
           sideways. */
        body.public-body #propertyContent .deal-location-lock-iframe { max-width: 100%; }

        /* --- 2) PHOTO COLLAGE: one large left, up to two stacked right. ------
           `data-cells` is written by renderCollage() from the number of photos
           the deal ACTUALLY has, so the grid never reserves a slot that will
           render as a grey box. One photo = one full-width cell. */
        body.public-body #propertyContent .deal-collage {
            display: grid;
            gap: 4px;
            grid-template-columns: 1fr;
            background: #e2e8f0;
            /* The "on fire" flourish (triggerDealFireFx) anchors HERE, not to the main
               cell alone — position:relative makes this the containing block for its
               inset:0 overlay, so the glow, badge and embers cover every visible photo
               cell (up to 4) instead of just the hero image. */
            position: relative;
        }
        body.public-body #propertyContent .deal-collage-cell {
            position: relative;
            overflow: hidden;
            min-width: 0;
            background: #e5e7eb;
        }
        /* ABSOLUTE, not in-flow. `height: 100%` against an AUTO grid row resolves
           back to auto, so each side cell contributed its photo's NATURAL height
           to the track. The main cell is pinned to 16/9 and spans both rows, so
           the two rows grew past it and left a bare #e2e8f0 rectangle under the
           main photo — grid background showing through a cell nobody filled.
           Out of flow, a side cell contributes NO height and simply stretches to
           whatever the row is, which is what makes the frames even. */
        body.public-body #propertyContent .deal-collage-cell > img {
            position: absolute;
            inset: 0;
            width: 100%;
            height: 100%;
            object-fit: cover;
            display: block;
        }
        /* The main cell keeps the 16:9 the hero always used, so the land-deal
           map overlay (#landMapHero, absolutely positioned) still fills it. */
        body.public-body #propertyContent .deal-collage-main { aspect-ratio: 16 / 9; }
        body.public-body #propertyContent .deal-collage[data-cells="2"],
        body.public-body #propertyContent .deal-collage[data-cells="3"] {
            grid-template-columns: 2.4fr 1fr;
        }
        body.public-body #propertyContent .deal-collage[data-cells="2"] .deal-collage-main,
        body.public-body #propertyContent .deal-collage[data-cells="3"] .deal-collage-main {
            grid-row: 1 / -1;
            /* 16/9, NOT auto. `auto` let this frame's height follow whichever photo
               happened to be loaded, and clicking a thumbnail or a side cell swaps
               exactly that — so selecting a portrait shot grew the cell (and the
               whole collage with it) by ~600px, shoving the page down under the
               cursor mid-click. The one-cell rule above and the phone rule below
               both pin 16/9 already; this was the only branch that did not, which
               is why the jump only appeared on desktop deals with 2+ photos.
               The frame is a fixed window; object-fit: cover crops into it. */
            aspect-ratio: 16 / 9;
        }
        body.public-body #propertyContent .deal-collage[data-cells="3"] { grid-template-rows: 1fr 1fr; }
        /* No aspect-ratio on the lone side cell: the row is already 280px tall
           (the main cell's 16/9), so pinning the side to its own 16/9 made it
           117px and left 163px of bare grid showing underneath. It stretches. */
        /* FOUR cells: a 2x2, wide column left, narrow column right. The right two
           keep the size they already had — the column split and the row heights
           are unchanged, so only the empty half of the left column is new.
           Row heights come from the two LEFT cells (both 16/9 against the same
           column width, so both rows are identical); the right cells carry no
           aspect-ratio and just stretch into whatever the row is. Nothing is a
           fixed pixel height, so the whole block still scales with the column. */
        body.public-body #propertyContent .deal-collage[data-cells="4"] {
            grid-template-columns: 2.4fr 1fr;
            grid-template-rows: auto auto;
        }
        body.public-body #propertyContent .deal-collage[data-cells="4"] .deal-collage-main {
            grid-area: 1 / 1;
            aspect-ratio: 16 / 9;
        }
        /* Placed explicitly rather than left to auto-flow: the "+N photos" overlay
           rides the LAST side cell, and it has to land bottom-right (where it has
           always been), not wherever the flow happened to drop cell 3. */
        body.public-body #propertyContent .deal-collage[data-cells="4"] .deal-collage-side:nth-of-type(1) {
            grid-area: 2 / 1;
            aspect-ratio: 16 / 9;
        }
        body.public-body #propertyContent .deal-collage[data-cells="4"] .deal-collage-side:nth-of-type(2) { grid-area: 1 / 2; }
        body.public-body #propertyContent .deal-collage[data-cells="4"] .deal-collage-side:nth-of-type(3) { grid-area: 2 / 2; }
        body.public-body #propertyContent .deal-collage-side {
            border: 0;
            padding: 0;
            cursor: pointer;
            transition: filter 0.16s ease;
        }
        body.public-body #propertyContent .deal-collage-side:hover { filter: brightness(1.06); }
        body.public-body #propertyContent .deal-collage-side:focus-visible {
            outline: 3px solid #7dd3fc;
            outline-offset: -3px;
        }
        /* "+N photos" rides on the last side cell. The count is real (total
           photos minus the three on show) — it never says "+more" on a deal
           that has none. */
        body.public-body #propertyContent .deal-collage-more {
            position: absolute;
            inset: 0;
            display: flex;
            align-items: center;
            justify-content: center;
            gap: 0.4rem;
            background: rgba(8, 15, 28, 0.52);
            color: #ffffff;
            font-family: 'Outfit', sans-serif;
            font-size: 0.82rem;
            font-weight: 700;
            letter-spacing: 0.01em;
            pointer-events: none;
        }
        body.public-body #propertyContent .deal-collage-more svg { color: #ffffff; }
        /* On phones the 2.4fr/1fr split makes the side cells postage stamps;
           stack to one photo and let the thumb strip carry the rest. */
        @media (max-width: 767px) {
            body.public-body #propertyContent .deal-collage[data-cells="2"],
            body.public-body #propertyContent .deal-collage[data-cells="3"] {
                grid-template-columns: 1fr 1fr;
                grid-template-rows: auto auto;
            }
            body.public-body #propertyContent .deal-collage[data-cells="2"] .deal-collage-main,
            body.public-body #propertyContent .deal-collage[data-cells="3"] .deal-collage-main {
                grid-row: 1;
                grid-column: 1 / -1;
                aspect-ratio: 16 / 9;
            }
            body.public-body #propertyContent .deal-collage-side { aspect-ratio: 4 / 3; }
            /* Four cells on a phone: the 2x2's left column would be ~190px, so the
               desktop placement is dropped entirely — full-width main, then the
               three side cells as one strip. `grid-area: auto` is required, not
               tidiness: the desktop nth-of-type rules out-specify the generic
               .deal-collage-side above and would otherwise survive down here. */
            body.public-body #propertyContent .deal-collage[data-cells="4"] {
                grid-template-columns: repeat(3, 1fr);
                grid-template-rows: auto auto;
            }
            body.public-body #propertyContent .deal-collage[data-cells="4"] .deal-collage-main {
                grid-area: 1 / 1 / 2 / -1;
                aspect-ratio: 16 / 9;
            }
            body.public-body #propertyContent .deal-collage[data-cells="4"] .deal-collage-side:nth-of-type(1),
            body.public-body #propertyContent .deal-collage[data-cells="4"] .deal-collage-side:nth-of-type(2),
            body.public-body #propertyContent .deal-collage[data-cells="4"] .deal-collage-side:nth-of-type(3) {
                grid-area: auto;
                aspect-ratio: 4 / 3;
            }
        }

        /* --- 3) PRICING CARD: the surface/rail/::after rules that lived here are
           gone — see the "no red dot glow" note, now folded into the premium pass
           at the foot of this file, which restates all of them. The ::after
           killer went with the ::after itself (the 12rem crimson radial that read
           as a smudge behind the price): both sides of that argument are deleted
           rather than one cancelling the other. --- */
        /* The metric rows carried their own gold radial wash. With the card
           flat, that wash is the last thing making it look textured. */
        body.public-body #propertyContent .financial-metric-card {
            background: #f8fafc !important;
            background-image: none !important;
            box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.9) !important;
        }

        /* --- 4) LAND INTEL: no ray on the panel or its tiles. ----------------
           Every white card on this page inherits a dark-ray wash from the
           email-match pass. On Land Intel that put a diagonal streak behind
           five small data tiles, which is exactly where texture costs the most
           legibility. The panel is plain white; the tiles are plain slate. */
        body.public-body #propertyContent #landIntelPanel,
        body.public-body #propertyContent #landIntelPanel > div,
        body.public-body #propertyContent #landIntelPanel > div > div {
            background-image: none !important;
            background-blend-mode: normal !important;
        }
        body.public-body #propertyContent #landIntelPanel {
            background-color: #ffffff !important;
            box-shadow: 0 18px 40px -28px rgba(15, 23, 42, 0.24) !important;
        }
        /* The tiles are built inline by renderLandIntel(), so they are targeted
           structurally rather than by class. */
        body.public-body #propertyContent #landIntelPanel > div > div {
            background-color: #f8fafc !important;
            box-shadow: none !important;
        }

        /* --- 5) CASH BUYERS CARD: light gray, not a navy ray band. -----------
           It was the darkest object on the page and pulled the eye away from
           the offer CTA. As a quiet gray panel it still reads as an invitation
           without competing with the thing we actually want clicked. */
        body.public-body #propertyContent #dealCashBuyersCard {
            background-color: #f1f5f9 !important;
            background-image: none !important;
            border: 1px solid rgba(203, 213, 225, 0.9) !important;
            box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.9) !important;
        }
        /* The light-on-navy text overrides have to come back to dark ink, or
           the copy turns white-on-light-gray and disappears. */
        body.public-body #dealCashBuyersCard h3.text-primary { color: #1e3a5f !important; }
        body.public-body #dealCashBuyersCard p.text-slate-600 { color: #475569 !important; }
        body.public-body #dealCashBuyersCard .text-slate-500 { color: #64748b !important; }
        body.public-body #dealCashBuyersCard .text-secondary,
        body.public-body #dealCashBuyersCard .text-secondary i,
        body.public-body #dealCashBuyersCard .text-secondary svg {
            color: #b62c38 !important;
            stroke: #b62c38 !important;
        }
        body.public-body #dealCashBuyersCard .text-emerald-600,
        body.public-body #dealCashBuyersCard .text-emerald-600 svg {
            color: #059669 !important;
            stroke: #059669 !important;
        }

        /* --- 6) HERO ACTION BAR: chips left, Contact right, one row. ---------
           The chips now live INSIDE the action bar, below the same hairline
           divider the Contact button already sat under. */
        body.public-body #propertyContent .deal-hero-actionbar {
            gap: 0.75rem 1rem;
        }
        body.public-body #propertyContent .deal-hero-actionbar .deal-hero-stats {
            flex: 1 1 auto;
            margin-top: 0;
            min-width: 0;
        }
        /* The price chip used to push itself to the far right with margin-left:
           auto. Inside a shared row that would strand it against the Contact
           button and break the "all the chips, then the CTA" reading order. */
        body.public-body #propertyContent .deal-hero-actionbar .deal-stat-chip-price {
            margin-left: 0;
        }
        body.public-body #propertyContent .deal-hero-contact-btn {
            flex: 0 0 auto;
            width: auto;
            margin-left: auto;
        }
        /* This is the one CTA inside #propertyContent that is genuinely
           auto-width, and the label rule this page carries
           (`#propertyContent .email-btn .email-btn-label`, flex:1 + a 16px right
           margin) is written for full-width buttons: on an auto-width one there
           is no remaining space to centre in, so the margin is just dead air and
           the label sits left of centre. public-ui.css fixes this for
           `.email-btn--inline` generally, but that selector cannot reach past
           the ID here, and the fix must NOT apply to the page's other --inline
           buttons — those are forced back to width:100% by the local
           `#propertyContent .email-btn` block, where flex:1 is correct. Below
           768px this button is full-width too, hence the query. */
        @media (min-width: 768px) {
            body.public-body #propertyContent .deal-hero-contact-btn .email-btn-label {
                flex: none;
                margin-right: 0;
            }
        }
        @media (max-width: 767px) {
            body.public-body #propertyContent .deal-hero-actionbar { justify-content: flex-start; }
            body.public-body #propertyContent .deal-hero-contact-btn {
                width: 100%;
                margin-left: 0;
                justify-content: flex-start;
            }
            body.public-body #propertyContent .deal-hero-actionbar .deal-stat-chip-price {
                width: auto;
                justify-content: flex-start;
            }
        }

        /* --- 7) The .email-btn accent bar owns the CTAs. ---------------------
           .pricing-primary-cta / .pricing-secondary-cta / #viewAllMediaBtn each
           painted their OWN 3px full-height left edge via ::before. On a button
           that is also an .email-btn, that edge overwrites the 4x20 brand bar —
           two accent marks specified for the same pixel, and the non-brand one
           was winning. Where both classes are present, the brand button wins. */
        body.public-body #propertyContent .email-btn.pricing-primary-cta::before,
        body.public-body #propertyContent .email-btn.pricing-secondary-cta::before,
        body.public-body #propertyContent .email-btn.deal-hero-contact-btn::before {
            position: static !important;
            left: auto !important;
            top: auto !important;
            bottom: auto !important;
            width: 4px !important;
            height: 20px !important;
            border-radius: 999px !important;
            background: linear-gradient(180deg, var(--eb-bar-top) 0%, var(--eb-bar) 50%, var(--eb-bar-bot) 100%) !important;
            box-shadow: 0 0 10px var(--eb-bar) !important;
        }
        body.public-body #propertyContent .email-btn.pricing-primary-cta,
        body.public-body #propertyContent .email-btn.pricing-secondary-cta {
            border-radius: 16px !important;
            overflow: visible !important;
        }

        /* --- 8) `.hidden` has to actually hide a stat chip. ------------------
           `.deal-stat-chip` is declared through `#propertyContent` (1-2-1), so it
           out-specifies Tailwind's `.hidden` (0-1-0). The JS that hides bed/bath
           on a LAND deal adds `.hidden` and nothing happened — every land listing
           rendered "- bd" and "- ba" chips next to its acreage. Restated here at
           matching weight. */
        body.public-body #propertyContent .deal-stat-chip.hidden,
        body.public-body #propertyContent .deal-hero-stats.hidden { display: none !important; }

        /* --- 9) "View Full Address" glow variant: RETIRED (see base sheet).
           The button is a plain quick-action tile like its three siblings. */

        /* --- 10) Mobile order. -----------------------------------------------
           `.dd-col-sidebar { order: -1 }` existed to lead mobile with the
           pricing card. The pricing card is now in the showcase rail — which on
           mobile already falls directly under the photos — so leaving the rule
           in place would hoist PROPERTY DETAILS above the write-up instead,
           which is not what it was for. */
        @media (max-width: 1023px) {
            body.public-body #propertyContent .dd-col-sidebar { order: 0; }
        }

        /* --- 11) deal-detail's LOCAL .email-btn had drifted off the artwork. --
           This page carries its own `#propertyContent .email-btn` block, which
           out-specifies the shared system in public-ui.css. It had been
           simplified to FLAT fills (#c81826 red, #1e3a5f navy, #35a06a green)
           and a single-colour accent bar, so the page that ORIGINATED the brand
           button was the one page not rendering it: no face gradient, no lit top
           rim, no three-stop bar, no brand-tinted shadow.

           Re-stated below with the values sampled 1:1 from
           brand-assets/brand-buttons.png — the same numbers `.email-btn` uses
           everywhere else. Nothing about the markup or the local layout rules
           changes; only the paint. */
        body.public-body #propertyContent .email-btn {
            background-image: linear-gradient(180deg, var(--eb-face-top) 0%, var(--eb-face-mid) 52%, var(--eb-face-bot) 100%) !important;
            box-shadow:
                inset 0 1px 0 rgba(255, 255, 255, 0.20),
                inset 0 -1px 0 rgba(0, 0, 0, 0.16),
                var(--eb-shadow) !important;
        }
        body.public-body #propertyContent .email-btn::before {
            background: linear-gradient(180deg, var(--eb-bar-top) 0%, var(--eb-bar) 50%, var(--eb-bar-bot) 100%) !important;
            box-shadow: 0 0 10px var(--eb-bar) !important;
        }
        body.public-body #propertyContent .email-btn--red {
            --eb-face-top: #df3238;
            --eb-face-mid: #dd3036;
            --eb-face-bot: #d72932;
            --eb-bar-top:  #fb9d9f;
            --eb-bar:      #fa8991;
            --eb-bar-bot:  #f87483;
            --eb-shadow:   0 10px 22px -6px rgba(176, 34, 44, 0.48), 0 2px 6px -1px rgba(176, 34, 44, 0.32);
        }
        body.public-body #propertyContent .email-btn--navy {
            --eb-face-top: #183153;
            --eb-face-mid: #162f4f;
            --eb-face-bot: #152c4b;
            --eb-bar-top:  #78d1fb;
            --eb-bar:      #5cc8fa;
            --eb-bar-bot:  #3ebff9;
            --eb-shadow:   0 10px 22px -6px rgba(19, 42, 74, 0.52), 0 2px 6px -1px rgba(19, 42, 74, 0.34);
        }
        body.public-body #propertyContent .email-btn--green {
            --eb-face-top: #21bb86;
            --eb-face-mid: #17b382;
            --eb-face-bot: #17ae7c;
            --eb-bar-top:  #c9f8e1;
            --eb-bar:      #a2f1cf;
            --eb-bar-bot:  #76e9bb;
            --eb-shadow:   0 10px 22px -6px rgba(17, 140, 100, 0.46), 0 2px 6px -1px rgba(17, 140, 100, 0.30);
        }
        /* Gold takes DARK ink and re-states its rim: a white top rim vanishes on
           gold and the dark bottom edge reads as dirt. */
        body.public-body #propertyContent .email-btn--gold {
            --eb-face-top: #fbbf24;
            --eb-face-mid: #f7ad14;
            --eb-face-bot: #f59e0b;
            --eb-bar-top:  #fffaf0;
            --eb-bar:      #fff3c4;
            --eb-bar-bot:  #ffe89a;
            --eb-shadow:   0 10px 22px -6px rgba(180, 106, 6, 0.42), 0 2px 6px -1px rgba(180, 106, 6, 0.28);
            color: #422006 !important;
            box-shadow:
                inset 0 1px 0 rgba(255, 255, 255, 0.55),
                inset 0 -1px 0 rgba(120, 70, 4, 0.22),
                var(--eb-shadow) !important;
        }
        /* Tailwind's .hidden is a single class and loses to `#propertyContent
           .email-btn { display: flex }` — the same trap that kept hidden stat
           chips on screen. #viewAllMediaBtn / #viewOnZillowBtn rely on it. */
        body.public-body #propertyContent .email-btn.hidden { display: none !important; }

        /* --- 12) Let .email-btn actually win where it is applied. ------------
           Three older selectors out-specify `#propertyContent .email-btn`:
             · `#propertyContent button[onclick="contactAboutDeal()"]:not(…)`
               — flattened the hero CTA to a solid #c0303d with no face gradient,
             · `#viewAllMediaBtn` / `#viewOnZillowBtn` ID rules — kept the old
               sky-blue and outline skins and a 3px full-height accent edge.
           Naming them explicitly (rather than piling on `[class][class]` hacks)
           keeps the intent readable: where BOTH the old hook and .email-btn are
           present, the brand button is the one that paints. */
        body.public-body #propertyContent button[onclick="contactAboutDeal()"].email-btn,
        body.public-body #propertyContent a#viewAllMediaBtn.email-btn,
        body.public-body #propertyContent a#viewOnZillowBtn.email-btn {
            background: none !important;
            background-image: linear-gradient(180deg, var(--eb-face-top) 0%, var(--eb-face-mid) 52%, var(--eb-face-bot) 100%) !important;
            border: 0 !important;
            border-radius: 16px !important;
            box-shadow:
                inset 0 1px 0 rgba(255, 255, 255, 0.20),
                inset 0 -1px 0 rgba(0, 0, 0, 0.16),
                var(--eb-shadow) !important;
        }
        body.public-body #propertyContent a#viewAllMediaBtn.email-btn::before,
        body.public-body #propertyContent a#viewOnZillowBtn.email-btn::before {
            position: static !important;
            left: auto !important;
            top: auto !important;
            bottom: auto !important;
            width: 4px !important;
            height: 20px !important;
            border-radius: 999px !important;
            background: linear-gradient(180deg, var(--eb-bar-top) 0%, var(--eb-bar) 50%, var(--eb-bar-bot) 100%) !important;
            box-shadow: 0 0 10px var(--eb-bar) !important;
        }
        /* The Google Drive mark is a multi-colour brand glyph with hard-coded
           fills, so the blanket `.email-btn > svg { color: #fff }` cannot reach
           it — `inherit` just keeps the button's ink off it. */
        body.public-body #propertyContent a#viewAllMediaBtn.email-btn > svg { color: inherit !important; }
        /* Zillow gets its OWN colour, not the button's. This used to `inherit`
           alongside Drive, back when the mark was a currentColor tile with a
           white house punched out of it — inheriting was how that tile picked up
           an ink at all. It is now Zillow's real single-colour glyph, so
           inheriting painted their logo in our navy. #006AFF is the brand blue,
           and it reads on this button's near-white outline face. */
        body.public-body #propertyContent a#viewOnZillowBtn.email-btn > svg.zillow-mark { color: #006AFF !important; }

        /* The OUTLINE variant is defined in public-ui.css but not in this page's
           local `#propertyContent .email-btn--*` block, so it needs restating
           here or the Zillow link renders with no face at all. */
        body.public-body #propertyContent .email-btn--outline:not(.email-btn--on-dark) {
            --eb-face-top: #ffffff;
            --eb-face-mid: #fdfefe;
            --eb-face-bot: #f4f7fb;
            --eb-bar-top:  #2a5078;
            --eb-bar:      #1e3a5f;
            --eb-bar-bot:  #142741;
            --eb-shadow:   0 10px 22px -6px rgba(15, 23, 42, 0.16), 0 2px 6px -1px rgba(15, 23, 42, 0.10);
            color: #14304f !important;
        }
        /* Every outline button, not just Zillow's: rule 11 above stamps the
           white rim + dark bottom edge on `.email-btn` with !important, and on
           a WHITE face the rim is invisible and the bottom edge reads as dirt
           (the same reason --gold restates its own). It is the variant that
           needs the navy ring, so state it on the variant. */
        body.public-body #propertyContent .email-btn--outline:not(.email-btn--on-dark) {
            box-shadow:
                inset 0 0 0 1px rgba(20, 48, 79, 0.16),
                var(--eb-shadow) !important;
        }

        /* Same story for the Cash Buyers "Join" link: its own
           `#dealCashBuyersCard a[href^="/join"]` rule (1-2-2) out-specified the
           brand button, so it kept the old 135deg crimson wash and a 3px
           full-height edge after adopting .email-btn. */
        body.public-body #propertyContent #dealCashBuyersCard a[href^="/join"].email-btn {
            background: none !important;
            background-image: linear-gradient(180deg, var(--eb-face-top) 0%, var(--eb-face-mid) 52%, var(--eb-face-bot) 100%) !important;
            border: 0 !important;
            border-radius: 16px !important;
            box-shadow:
                inset 0 1px 0 rgba(255, 255, 255, 0.20),
                inset 0 -1px 0 rgba(0, 0, 0, 0.16),
                var(--eb-shadow) !important;
        }
        body.public-body #propertyContent #dealCashBuyersCard a[href^="/join"].email-btn::before {
            position: static !important;
            left: auto !important;
            top: auto !important;
            bottom: auto !important;
            width: 4px !important;
            height: 20px !important;
            border-radius: 999px !important;
            background: linear-gradient(180deg, var(--eb-bar-top) 0%, var(--eb-bar) 50%, var(--eb-bar-bot) 100%) !important;
            box-shadow: 0 0 10px var(--eb-bar) !important;
        }

        /* --- 13) ONE authoritative accent bar for every .email-btn here. ------
           Rule 11 above only re-painted the bar; it left the GEOMETRY to whatever
           older rule matched, and this page has several that disagree:
             · `.investor-summary-primary::before` is killed outright
               (`content: none; display: none`) by the 2026-07 "remove the
               per-button glow edge" block — so that CTA had no mark at all;
             · `.investor-summary-secondary::before` / `#viewAllMediaBtn::before`
               keep the older 3px FULL-HEIGHT edge pinned to left:0.
           The result was three different accent treatments on one screen. This
           states the sampled 4x20 bar once, for every .email-btn in
           #propertyContent, and every property it can be overridden through. */
        body.public-body #propertyContent .email-btn::before {
            content: '' !important;
            display: block !important;
            position: static !important;
            left: auto !important;
            right: auto !important;
            top: auto !important;
            bottom: auto !important;
            flex: 0 0 auto !important;
            width: 4px !important;
            height: 20px !important;
            min-height: 20px !important;
            border-radius: 999px !important;
            opacity: 1 !important;
            transform: none !important;
            background: linear-gradient(180deg, var(--eb-bar-top) 0%, var(--eb-bar) 50%, var(--eb-bar-bot) 100%) !important;
            box-shadow: 0 0 10px var(--eb-bar) !important;
        }
        /* The same block also killed some ::after flourishes and left others; an
           .email-btn has no ::after of its own here, so keep them all off. */
        body.public-body #propertyContent .email-btn::after {
            content: none !important;
            display: none !important;
        }
        body.public-body #propertyContent .email-btn--sm::before { height: 15px !important; min-height: 15px !important; width: 3px !important; }
        body.public-body #propertyContent .email-btn--lg::before { height: 25px !important; min-height: 25px !important; }

        /* --- 14) The Contact Team card is NAVY, so its two actions invert. ----
           `Save Contact` had a dedicated white-on-navy skin at
           `#propertyContent .bg-primary… a[data-site-contact-card-link]` (1-7-2),
           which out-specifies anything reasonable — so adopting .email-btn--red
           left it rendering as the old white slab. Both are restated at that
           depth: brand RED for the action we want taken, and the on-dark outline
           for the quieter "browse everything else" link, so the card keeps its
           two-tier reading instead of two identical slabs. */
        body.public-body #propertyContent .bg-primary.rounded-2xl.shadow-lg.p-6.text-white a[data-site-contact-card-link].email-btn {
            background: none !important;
            background-image: linear-gradient(180deg, var(--eb-face-top) 0%, var(--eb-face-mid) 52%, var(--eb-face-bot) 100%) !important;
            border: 0 !important;
            border-radius: 16px !important;
            color: #ffffff !important;
            letter-spacing: 0.01em;
            box-shadow:
                inset 0 1px 0 rgba(255, 255, 255, 0.20),
                inset 0 -1px 0 rgba(0, 0, 0, 0.16),
                var(--eb-shadow) !important;
        }
        body.public-body #propertyContent .bg-primary.rounded-2xl.shadow-lg.p-6.text-white a[data-site-contact-card-link].email-btn i,
        body.public-body #propertyContent .bg-primary.rounded-2xl.shadow-lg.p-6.text-white a[data-site-contact-card-link].email-btn svg {
            color: #ffffff !important;
        }
        /* On-dark outline. My own `#propertyContent .email-btn--outline` reset
           above used to win here and drag the face back to WHITE, so the
           modifier that exists precisely for dark surfaces never took effect.
           It was fixed by restating the on-dark palette here -- which made this
           block a byte-for-byte copy of public-ui.css's canonical one, i.e. a
           second owner of six colours that would silently keep the old values
           the first time the canonical variant was retuned. The reset is now
           scoped `:not(.email-btn--on-dark)`, so the canonical rule applies
           untouched and the FACE is stated in exactly one place.

           What stays: rule 11 stamps every `.email-btn` with a white rim, a
           dark bottom edge and an ink, all `!important`, and specificity does
           not beat `!important` -- so the two declarations that have to answer
           it are still restated. Nothing else. */
        body.public-body #propertyContent .email-btn--outline.email-btn--on-dark {
            color: #eaf3fb !important;
            box-shadow:
                inset 0 0 0 1px rgba(255, 255, 255, 0.24),
                0 10px 22px -6px rgba(0, 0, 0, 0.45) !important;
        }
        body.public-body #propertyContent .email-btn--outline.email-btn--on-dark i,
        body.public-body #propertyContent .email-btn--outline.email-btn--on-dark svg { color: #eaf3fb !important; }

        /* The Cash Buyers "Join" link keeps its bar suppressed by
           `#dealCashBuyersCard a[href^="/join"]::before { content: none }`
           (1-2-2), which out-specifies the general rule above (1-2-1). It was
           the only brand button on the page still missing its accent mark. */
        body.public-body #propertyContent #dealCashBuyersCard a[href^="/join"].email-btn::before {
            content: '' !important;
            display: block !important;
            position: static !important;
            width: 4px !important;
            height: 20px !important;
            min-height: 20px !important;
            border-radius: 999px !important;
            opacity: 1 !important;
            background: linear-gradient(180deg, var(--eb-bar-top) 0%, var(--eb-bar) 50%, var(--eb-bar-bot) 100%) !important;
            box-shadow: 0 0 10px var(--eb-bar) !important;
        }

        /* --- 15) The FOOTER "Save Contact" on this page only. ----------------
           public-ui.css brings .site-footer-button onto the sampled 4x20 bar
           sitewide, and it lands everywhere — except here. This page carries its
           own `a[data-site-contact-card-link]` skin at (0-2-2) in an inline
           block that loads AFTER public-ui.css, so the footer button kept the
           old 3px full-height edge and a 16.8px corner while the identical
           button on every other page had already changed. Same element, same
           label, two different buttons depending on which page you were on. */
        body.public-body a.site-footer-button[data-site-contact-card-link] {
            border-radius: 16px !important;
        }
        body.public-body a.site-footer-button[data-site-contact-card-link]::before {
            left: 14px !important;
            top: 50% !important;
            bottom: auto !important;
            transform: translateY(-50%) !important;
            width: 4px !important;
            height: 20px !important;
            border-radius: 999px !important;
            background: linear-gradient(180deg, #fb9d9f 0%, #fa8991 50%, #f87483 100%) !important;
            box-shadow: 0 0 10px #fa8991 !important;
        }

        /* --- 16) The pricing card's 2x2 quick actions. ----------------------
           Share / Save PDF / Save / View Full Address wear the brand button
           itself now — `.email-btn--outline .email-btn--sm`, and `--navy --sm`
           for View Full Address, the action this card exists to drive once a
           buyer is interested. SMALL in the brand scale is what keeps a 2x2
           grid of them from competing with Submit an Offer above.

           This block used to CONTAIN that button: the --outline face stops, its
           `inset 0 0 0 1px rgba(20,48,79,.16)` rim, a 3x15 bar at left:11px and
           a 12px corner, every value identical to the real thing and restated
           here under !important because the markup carried no brand classes.
           It rendered correctly, which is exactly why it was worth deleting —
           a second copy of a button only announces itself once the two have
           already drifted. What is left is what is genuinely local. */

        /* Nothing about the tile's paint lives here any more. Everything this
           block used to declare — face, rim, radius, accent bar, hover — is
           either the brand button's now or belongs to the sidebar-card block
           further down, which is more specific and was silently winning the
           argument anyway. Height and type live there, with the tap-target
           reasoning that motivated them. */
        /* Saved state. It was emerald — DESIGN.md's status ramp is operator
           vocabulary and never decorates a buyer surface, and "I bookmarked
           this" is not a thing that cleared. It is now the navy variant's own
           tokens: a saved tile reads as SELECTED (filled, dark) against three
           unselected outline tiles, which is a stronger signal than a colour
           swap anyway. */
        body.public-body #propertyContent .pricing-quick-btn.is-saved {
            --eb-face-top: #183153;
            --eb-face-mid: #162f4f;
            --eb-face-bot: #152c4b;
            --eb-bar-top:  #78d1fb;
            --eb-bar:      #5cc8fa;
            --eb-bar-bot:  #3ebff9;
            --eb-glow:     rgba(124, 205, 250, 0.20);
            color: #ffffff !important;
        }
        body.public-body #propertyContent .pricing-quick-btn.is-saved > i,
        body.public-body #propertyContent .pricing-quick-btn.is-saved > svg { color: #ffffff !important; }

        /* --- 17) DEAL TIMELINE — the shared brand button, not a copy of it. --
           The four rows previously carried a hand-rolled restatement of the
           brand-button skin (face gradients, an absolutely-positioned accent
           bar, per-row ink) — a second implementation that drifted from
           `.email-btn` and, with `saturate(0.6)` on past stages, rendered the
           gold and crimson tiles as dusty pastels. The rows now wear
           `.email-btn--gold/--red/--navy/--outline` directly, so face, bar,
           rim and tinted shadow come from public-ui.css. Only what is
           genuinely local lives here: the two-line label/value stack, the
           add-to-calendar affordance, and the done / up-next states. */
        body.public-body #datesSection .deal-timeline {
            display: flex;
            flex-direction: column;
            gap: 0.6rem;
        }
        /* The rows are Tailwind-`hidden` until the deal supplies their date, and
           `.email-btn { display: flex }` beats a single class. */
        body.public-body #datesSection .email-btn.hidden { display: none !important; }
        /* The text block takes the space the label would centre in — these rows
           read as a stack, not a centred CTA caption. */
        body.public-body #datesSection .deal-timeline-row > div {
            flex: 1 1 auto;
            min-width: 0;
            text-align: left;
            white-space: normal;
        }
        body.public-body #datesSection .deal-timeline-label {
            font-size: 0.68rem;
            font-weight: 800;
            text-transform: uppercase;
            letter-spacing: 0.14em;
            color: currentColor;
            opacity: 0.72;
        }
        body.public-body #datesSection .deal-timeline-value {
            font-weight: 800;
            font-variant-numeric: tabular-nums;
            font-size: 0.95rem;
            line-height: 1.25;
            margin-top: 0.15rem;
            color: currentColor;
        }
        /* Listed is a <div>, so it must not offer a pointer it cannot honour. */
        body.public-body #datesSection #listedRow { cursor: default; }
        /* DONE — behind the buyer, but NOT dimmed: opacity on a colored
           .email-btn read as a washed-out blue/grey tile, the exact
           "highlighted"/dusty look this section keeps retiring. A past stage
           keeps its full brand color; "Up next" on the chip is the only
           state signal. */
        /* UP NEXT — a small chip on the label, not a glow on the tile. */
        body.public-body #datesSection .deal-timeline-row.is-next .deal-timeline-label::after {
            content: 'Up next';
            display: inline-block;
            margin-left: 0.5rem;
            padding: 0.1rem 0.45rem;
            border-radius: 999px;
            background: rgba(255, 255, 255, 0.22);
            border: 1px solid rgba(255, 255, 255, 0.45);
            font-size: 0.6rem;
            font-weight: 800;
            letter-spacing: 0.1em;
            vertical-align: middle;
        }
        /* Gold and outline take dark ink, so a white chip disappears on them. */
        body.public-body #datesSection #walkthroughRow.is-next .deal-timeline-label::after,
        body.public-body #datesSection #listedRow.is-next .deal-timeline-label::after {
            background: rgba(20, 48, 79, 0.10);
            border-color: rgba(20, 48, 79, 0.32);
        }
        /* Add-to-calendar affordance: quiet until hover on desktop, always on
           for touch; hidden on a row with no date to add. */
        body.public-body #datesSection .deal-timeline-add {
            flex: 0 0 auto;
            display: inline-flex;
            align-items: center;
            justify-content: center;
            width: 1.75rem;
            height: 1.75rem;
            border-radius: 0.5rem;
            background: rgba(255, 255, 255, 0.18);
            box-shadow: inset 0 0 0 1px currentColor;
            color: currentColor;
            opacity: 0;
            transition: opacity 140ms ease;
        }
        body.public-body #datesSection button.deal-timeline-row:hover .deal-timeline-add,
        body.public-body #datesSection button.deal-timeline-row:focus-visible .deal-timeline-add {
            opacity: 0.75;
        }
        body.public-body #datesSection button.deal-timeline-row:disabled { cursor: default; }
        body.public-body #datesSection button.deal-timeline-row:disabled .deal-timeline-add { display: none; }
        @media (hover: none) {
            body.public-body #datesSection .deal-timeline-add { opacity: 0.75; }
        }

        /* --- 18) Contact Team phone / email rows. ---------------------------
           These are <a href="tel:"> and <a href="mailto:"> — a contact LIST, not
           actions, so no accent bar (a bar here would make them compete with the
           Save Contact button directly below). Corner family only, so the navy
           card stops mixing an 8px radius with the 16px buttons inside it. */
        body.public-body #propertyContent .bg-primary.rounded-2xl.shadow-lg.p-6.text-white a[href^="tel:"],
        body.public-body #propertyContent .bg-primary.rounded-2xl.shadow-lg.p-6.text-white a[href^="mailto:"] {
            border-radius: 12px !important;
            transition: transform 0.16s ease, background-color 0.16s ease !important;
        }
        body.public-body #propertyContent .bg-primary.rounded-2xl.shadow-lg.p-6.text-white a[href^="tel:"]:hover,
        body.public-body #propertyContent .bg-primary.rounded-2xl.shadow-lg.p-6.text-white a[href^="mailto:"]:hover {
            transform: translateY(-1px);
        }

        /* --- 19) LAND INTEL: flat, and impossible to re-decorate. -----------
           The rays were removed once already, but the panel still inherited
           `backdrop-filter: blur(14px)` from the shared glass-card treatment in
           public-ui.css. On an opaque white card that blur buys nothing — it is
           pure compositing cost — and the moment any ancestor rule makes the
           card even slightly translucent it smears whatever is behind it across
           five small data tiles, which is exactly the streak this panel kept
           being reported for.

           So this states the surface EXHAUSTIVELY rather than just turning off
           the one property that was wrong last time: no image, no filter, no
           backdrop filter, no pseudo-element on the panel, its row, or the
           tiles. A future card-level effect cannot reach in here. Land Intel is
           five small numbers a buyer squints at — legibility beats texture. */
        body.public-body #propertyContent #landIntelPanel,
        body.public-body #propertyContent #landIntelPanel > div,
        body.public-body #propertyContent #landIntelPanel > div > div {
            background-image: none !important;
            background-blend-mode: normal !important;
            filter: none !important;
            -webkit-backdrop-filter: none !important;
            backdrop-filter: none !important;
            box-shadow: none !important;
            text-shadow: none !important;
        }
        body.public-body #propertyContent #landIntelPanel::before,
        body.public-body #propertyContent #landIntelPanel::after,
        body.public-body #propertyContent #landIntelPanel > div::before,
        body.public-body #propertyContent #landIntelPanel > div::after,
        body.public-body #propertyContent #landIntelPanel > div > div::before,
        body.public-body #propertyContent #landIntelPanel > div > div::after {
            content: none !important;
            display: none !important;
            background: none !important;
        }
        /* Re-state the two surfaces the tiles actually need. */
        body.public-body #propertyContent #landIntelPanel {
            background-color: #ffffff !important;
            box-shadow: 0 18px 40px -28px rgba(15, 23, 42, 0.24) !important;
        }
        body.public-body #propertyContent #landIntelPanel > div > div {
            background-color: #f8fafc !important;
            border: 1px solid #e2e8f0 !important;
        }

        /* ==== 20) The sticky mobile bar stands down when a real offer CTA is on screen.
               Measured at 390x844: three scroll bands showed the bar's "Submit an Offer"
               beside an in-page one — two identical controls for one action, in the
               tightest space on the site. Hidden via opacity/transform (never display)
               so nothing reflows mid-scroll, and pointer-events off so the invisible
               bar can't still be tapped. ==== */
        body.public-body #mobileOfferBar {
            transition: opacity 180ms ease, transform 180ms ease, visibility 180ms ease;
        }
        body.public-body #mobileOfferBar.is-stood-down {
            opacity: 0;
            transform: translateY(100%);
            visibility: hidden;
            pointer-events: none;
        }

        /* ==== 21) Contact Team → LIGHT surface. ==============================
           It was a navy ray band (blocks 1-1 and 1-9 above). Now a light-gray
           face inside a 2px off-white→white gradient rim, done with the
           padding-box/border-box double background: `border-image` would draw
           the same gradient but drops the 1.4rem corners.

           Everything inside the card was painted FOR navy, so this block
           restates each of those children instead of editing the rules above:
           several of them also describe the Cash Buyers navy band, which is
           deliberately unchanged. Later + equal specificity = this wins.
           ==================================================================== */
        body.public-body #propertyContent .bg-primary.rounded-2xl.shadow-lg.p-6.text-white {
            /* The face is WHITE→gray (not flat #f1f5f9) and the rim is a real,
               contrasting slate — the previous off-white→white gradient rim was
               invisible against the gray face, so the card had no edge at all
               and read as a hole in the page rather than a container. */
            background:
                linear-gradient(180deg, #ffffff 0%, #f8fafc 58%, #eef2f7 100%) padding-box,
                linear-gradient(135deg, #cbd5e1 0%, #94a3b8 52%, #cbd5e1 100%) border-box !important;
            border: 2px solid transparent !important;
            color: #0f172a !important;
            box-shadow:
                inset 0 1px 0 rgba(255, 255, 255, 0.9),
                0 18px 40px -24px rgba(15, 23, 42, 0.28) !important;
        }
        body.public-body #propertyContent .bg-primary.rounded-2xl.shadow-lg.p-6.text-white:hover {
            background:
                linear-gradient(180deg, #ffffff 0%, #f8fafc 58%, #eef2f7 100%) padding-box,
                linear-gradient(135deg, #b6c2d2 0%, #6f8098 52%, #b6c2d2 100%) border-box !important;
            box-shadow:
                inset 0 1px 0 rgba(255, 255, 255, 0.9),
                0 24px 48px -22px rgba(15, 23, 42, 0.34) !important;
        }
        /* Heading underline: the gold/sky pair was tuned against navy and all but
           vanishes on gray, so it flips to navy→gold. */
        body.public-body #propertyContent .bg-primary.rounded-2xl.shadow-lg.p-6.text-white > h3:first-child::after {
            background: linear-gradient(90deg, #1e3a5f, rgba(231, 194, 119, 0.9)) !important;
        }
        /* #agentName is set white by an ID rule, which no card-scoped selector
           can outrank — it has to be re-stated on the same ID. */
        body.public-body #agentName { color: #0f172a !important; }
        /* Brand JHB gold — the same #f5b301 as the review stars below. */
        body.public-body #propertyContent .bg-primary.rounded-2xl.shadow-lg.p-6.text-white p[data-site-contact-title] {
            color: #f5b301 !important;
        }
        body.public-body #propertyContent .bg-primary.rounded-2xl.shadow-lg.p-6.text-white img {
            box-shadow: 0 0 0 2px #cbd5e1, 0 4px 10px -4px rgba(15, 23, 42, 0.35) !important;
        }
        /* Phone / email rows: white-on-white-alpha reads as nothing on a light
           card, so they take a real white face with a slate rim. */
        body.public-body #propertyContent .bg-primary.rounded-2xl.shadow-lg.p-6.text-white a[href^="tel:"],
        body.public-body #propertyContent .bg-primary.rounded-2xl.shadow-lg.p-6.text-white a[href^="sms:"],
        body.public-body #propertyContent .bg-primary.rounded-2xl.shadow-lg.p-6.text-white a[href^="mailto:"] {
            background: #ffffff !important;
            border: 1px solid #e2e8f0 !important;
            color: #1e3a5f !important;
        }
        body.public-body #propertyContent .bg-primary.rounded-2xl.shadow-lg.p-6.text-white a[href^="tel:"]:hover,
        body.public-body #propertyContent .bg-primary.rounded-2xl.shadow-lg.p-6.text-white a[href^="sms:"]:hover,
        body.public-body #propertyContent .bg-primary.rounded-2xl.shadow-lg.p-6.text-white a[href^="mailto:"]:hover {
            background: #f8fafc !important;
            border-color: #cbd5e1 !important;
        }
        body.public-body #propertyContent .bg-primary.rounded-2xl.shadow-lg.p-6.text-white a[href^="tel:"] i,
        body.public-body #propertyContent .bg-primary.rounded-2xl.shadow-lg.p-6.text-white a[href^="sms:"] i,
        body.public-body #propertyContent .bg-primary.rounded-2xl.shadow-lg.p-6.text-white a[href^="mailto:"] i {
            color: #1e3a5f !important;
        }
        /* Every remaining `text-blue-200` in this card was picked for navy; on the
           light face it is barely a shade off white (the phone line under the
           Call/Text pair and the response-window note both read as blank). */
        body.public-body #propertyContent .bg-primary.rounded-2xl.shadow-lg.p-6.text-white .text-blue-200 {
            color: #64748b !important;
        }
        /* The number and the address live in a <span> painted #f1f5f9 by an ID
           rule (`#agentPhone span`, 1-0-2) written when the card was navy —
           same trap as #agentName above: no card-scoped selector outranks an
           ID, so on the light card both rows rendered white-on-white and could
           not be read at all. Re-state on the same IDs. */
        body.public-body #agentPhone span,
        body.public-body #agentEmail span {
            color: #1e3a5f !important;
        }
        /* The card is no longer dark, so the on-dark outline button drops its
           translucent-white face for the normal light one. */
        body.public-body #propertyContent .bg-primary.rounded-2xl.shadow-lg.p-6.text-white .email-btn--outline.email-btn--on-dark {
            --eb-face-top: #ffffff;
            --eb-face-mid: #fbfdff;
            --eb-face-bot: #f1f5f9;
            --eb-bar-top:  #2b6fb8;
            --eb-bar:      #1e3a5f;
            --eb-bar-bot:  #12294a;
            color: #1e3a5f !important;
            border: 1px solid #cbd5e1 !important;
            box-shadow: 0 8px 18px -10px rgba(15, 23, 42, 0.35) !important;
        }
        body.public-body #propertyContent .bg-primary.rounded-2xl.shadow-lg.p-6.text-white .email-btn--outline.email-btn--on-dark i,
        body.public-body #propertyContent .bg-primary.rounded-2xl.shadow-lg.p-6.text-white .email-btn--outline.email-btn--on-dark svg {
            color: #1e3a5f !important;
        }


        /* =====================================================================
           PRICING SIDEBAR CARD — premium pass, 2026-08-03.
           Appended after every earlier block AND after public-ui.css, so it
           wins ties at equal specificity. Scoped to .pricing-sidebar-card and
           its children only — nothing else on the page changes.

           TWO SOURCES, both named by the request:

           1) THE FLYER (branding/jhb-brand-render.js). Its signature move is a
              full-bleed PRICE BAND under the hero photo: a dark strip carrying a
              small uppercase grotesk label over one very large figure, a ray
              sheen, and a hairline highlight on its top edge. This card had the
              same information as loose centered text on white, so the single
              most important number on the page had no frame around it.

           2) THE TOP BAR (.deal-hero, directly above this card). It already
              solved "how does a price look here": #heroPriceChip is a NAVY
              gradient tile with a GOLD uppercase eyebrow. So the band is navy
              and gold, not crimson — crimson stays where it already means
              "act": the top rail and the Submit an Offer CTA. Two red things on
              one card is one too many, and a crimson band directly under the
              crimson hero rail would have read as a single bleeding block.
              The card also drops to the hero's 1.5rem radius and borrows its
              exact 3px rail gradient, so the two now read as one system.

           LESS ROUND. Outfit's bowls and figures are circles; at 3.8rem the
           price was the roundest object on the page. Archivo is a squared
           grotesk — flat-sided bowls, cut terminals, true tabular figures, so
           digits stop shifting when the price re-renders. Radii come down to
           match (2.25rem -> 1.5rem card, pills -> rounded rectangles).
           ===================================================================== */

        /* ---- The card itself -------------------------------------------------
           Padding is restated here at both breakpoints ON PURPOSE: the band is a
           full-bleed child that cancels the card's horizontal padding with a
           negative margin, so the two numbers must agree. Earlier passes set the
           padding from three different rules (p-6 / md:p-7 / a 1.35rem mobile
           override), and a band sized against the wrong one leaves a white seam
           down one edge. Top padding is 0 — the band supplies it. */
        body.public-body #propertyContent .pricing-sidebar-card {
            padding: 0 1.35rem 1.35rem !important;
            border-radius: 1.5rem !important;
            border: 1px solid rgba(226, 232, 240, 0.95) !important;
            background: #ffffff !important;
            background-image: none !important;
            overflow: hidden !important;
            box-shadow:
                inset 0 1px 0 rgba(255, 255, 255, 0.95),
                0 2px 6px -2px rgba(15, 23, 42, 0.06),
                0 30px 60px -28px rgba(15, 23, 42, 0.30) !important;
        }
        @media (min-width: 768px) {
            body.public-body #propertyContent .pricing-sidebar-card {
                padding: 0 1.75rem 1.75rem !important;
            }
        }
        /* Same 3px rail as .deal-hero::before, same stops. z-index 4 keeps it
           above the navy band, which is what it now sits on top of. */
        body.public-body #propertyContent .pricing-sidebar-card::before {
            content: '' !important;
            display: block !important;
            position: absolute !important;
            inset: 0 0 auto 0 !important;
            height: 3px !important;
            z-index: 4 !important;
            background: linear-gradient(90deg,
                rgba(53, 95, 140, 0) 0%,
                #35608f 12%,
                #c0303d 50%,
                #35608f 88%,
                rgba(53, 95, 140, 0) 100%) !important;
        }

        /* ---- The price band --------------------------------------------------
           Full-bleed navy strip carrying the BLACK brand ray sheet
           (brand-assets/black-ray-effect.png, mirrored to /branding and allowlisted
           in .assetsignore — branding/** is dropped from the upload by default, so
           an un-allowlisted sheet 404s and the rays silently never paint).

           Why the white `mw` cut had to go: at `68% auto` it was sized to a
           FRACTION of the band, so the sheet ended mid-surface and left a hard
           vertical seam — bright white diagonals stopping dead against flat navy.
           Rays that terminate in a straight line read as a rendering fault, not a
           sheen. `cover` removes the seam: the sheet always spans the band.

           No blend mode, deliberately. Sampling the asset shows it is pure black
           (luminance 0 at every point) with alpha ramping 0 -> 63/255 across the
           band's visible crop, i.e. a 25% black wash at its strongest and ~9% on
           average. Normal alpha compositing IS the effect — it
           sinks the navy into soft shadow rays. Stacking multiply or soft-light on
           top would only crush the same pixels twice.

           Anchored 100% 100% because the sheet's ink is densest toward ITS bottom
           edge (measured, not assumed). Anchoring to the top crops to the
           near-transparent end and paints almost nothing.

           The gradient is re-oriented so its LIGHTER navy sits where the rays land.
           Same brand navies, walked along the band the other way. This is the whole
           reason the earlier pass reached for the white cut: black on near-black is
           invisible. Give the sheet a lighter surface and the black rays read. */
        body.public-body #propertyContent .pricing-price-header {
            position: relative;
            margin: 0 -1.35rem 1.4rem !important;
            padding: 2rem 1.35rem 1.5rem !important;
            background:
                url('/branding/black-ray-effect.webp') 100% 100% / cover no-repeat,
                linear-gradient(118deg, #0a1424 0%, #0f2848 34%, #1a3459 68%, #24466f 100%);
            /* 2px translucent white closing edge, with a soft glow spilling out
               below it. The glow is NAVY, not white: it lands on the card's white
               face, where a white shadow paints nothing at all. Tinted with the
               band's own lightest stop (#24466f) so it reads as the band bleeding
               out rather than a grey drop-shadow. Border-box sizing is not in play
               here (the band is full-bleed via negative margins), so the border
               adds its 2px to the band's height and nothing shifts sideways. */
            border-bottom: 2px solid rgba(255, 255, 255, 0.30);
            box-shadow:
                inset 0 -14px 20px -16px rgba(255, 255, 255, 0.35),
                0 7px 16px -7px rgba(36, 70, 111, 0.32);
        }
        @media (min-width: 768px) {
            body.public-body #propertyContent .pricing-price-header {
                margin: 0 -1.75rem 1.6rem !important;
                padding: 2.15rem 1.75rem 1.6rem !important;
            }
        }
        /* Hairline highlight on the band's top edge — the flyer paints the same
           1.5px white line across the top of its price strip. */
        body.public-body #propertyContent .pricing-price-header::before {
            content: '';
            position: absolute;
            top: 3px; left: 0; right: 0;
            height: 1px;
            background: rgba(255, 255, 255, 0.16);
        }

        /* Eyebrow — gold, matching .deal-stat-chip-label in the top bar. */
        body.public-body #propertyContent .pricing-sidebar-card .pricing-kicker {
            font-family: 'Archivo', 'Segoe UI', sans-serif !important;
            font-size: 0.68rem !important;
            font-weight: 700 !important;
            letter-spacing: 0.26em !important;
            text-transform: uppercase;
            color: #e7c277 !important;
        }
        /* The figure — Archivo, white on navy, tabular so the digits hold their
           columns when JS swaps the value in. */
        body.public-body #propertyContent .pricing-sidebar-card .pricing-amount {
            font-family: 'Archivo', 'Segoe UI', sans-serif !important;
            font-weight: 700 !important;
            font-size: clamp(2.9rem, 5.2vw, 3.7rem) !important;
            letter-spacing: -0.035em !important;
            line-height: 1.02 !important;
            color: #ffffff !important;
            -webkit-text-fill-color: #ffffff !important;
            background: none !important;
            font-variant-numeric: tabular-nums !important;
            text-shadow: 0 2px 18px rgba(0, 0, 0, 0.35) !important;
        }
        /* The underscore was crimson-on-white; on navy it goes gold. */
        body.public-body #propertyContent .pricing-sidebar-card .pricing-amount::after {
            content: "" !important;
            display: block !important;
            width: 3.2rem !important;
            height: 2px !important;
            margin: 0.8rem auto 0 !important;
            border-radius: 0 !important;
            background: linear-gradient(90deg, rgba(231, 194, 119, 0), #e7c277 45%, rgba(231, 194, 119, 0)) !important;
            opacity: 1 !important;
        }
        /* FAQ affordance — a translucent white tile on the band, not the old
           navy-tinted one meant for a white surface (which vanished here). */
        body.public-body #propertyContent .pricing-sidebar-card .pricing-faq-link {
            border-radius: 0.5rem !important;
            border-color: rgba(231, 194, 119, 0.38) !important;
            background: rgba(255, 255, 255, 0.08) !important;
            color: #e7c277 !important;
            /* Carried over from the deleted premium-pass rule, which was otherwise
               fully superseded here — without it the hover is an instant snap. */
            transition: border-color 200ms ease, background 200ms ease, color 200ms ease, transform 200ms ease !important;
        }
        body.public-body #propertyContent .pricing-sidebar-card .pricing-faq-link:hover {
            border-color: rgba(231, 194, 119, 0.75) !important;
            background: rgba(231, 194, 119, 0.16) !important;
            color: #ffffff !important;
            transform: translateY(-1px) !important;
        }
        /* Zestimate line sits on the band now — Tailwind painted it slate-500,
           which is unreadable on navy. */
        body.public-body #propertyContent .pricing-price-header .zillow-zestimate {
            color: #aebfd8 !important;
            font-family: 'Archivo', 'Segoe UI', sans-serif !important;
            letter-spacing: 0.01em;
        }
        /* Reversed to white on the navy band. Zillow blue (#006AFF) on #0f2848 is
           near-invisible, and an invented lighter blue is not their colour either
           — white is the sanctioned dark-background treatment for the mark. */
        body.public-body #propertyContent .pricing-price-header .zillow-zestimate .zillow-mark {
            color: #ffffff !important;
        }

        /* ---- Spread block ----------------------------------------------------
           Kept emerald (it is the profit story), squared off, and the three
           figures now sit on flyer-light panels: #f2f6fb face, #e2e9f2 line. */
        body.public-body #propertyContent .pricing-sidebar-card .pricing-spread-card {
            border-radius: 1rem !important;
            padding: 1.05rem !important;
            background: linear-gradient(180deg, #f4fbf6 0%, #eefaf2 100%) !important;
            border: 1px solid rgba(22, 163, 74, 0.22) !important;
            box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.9) !important;
        }
        body.public-body #propertyContent .pricing-sidebar-card .pricing-micro-card {
            border-radius: 0.7rem !important;
            background: #ffffff !important;
            border: 1px solid #e2e9f2 !important;
            padding: 0.6rem 0.4rem !important;
            box-shadow: none !important;
        }
        /* nowrap: the label and its hint mark are one unit. "SPREAD" plus the 14px
           circle is 3px wider than the bare word, which was enough to drop the mark
           onto a second line and shove that tile's figure a row lower than the two
           beside it — a three-up row of numbers that no longer lines up. */
        body.public-body #propertyContent .pricing-sidebar-card .pricing-micro-label {
            white-space: nowrap !important;
            font-family: 'Archivo', 'Segoe UI', sans-serif !important;
            font-size: 0.6rem !important;
            font-weight: 700 !important;
            letter-spacing: 0.16em !important;
            text-transform: uppercase !important;
            color: #5b6b82 !important;
        }
        body.public-body #propertyContent .pricing-sidebar-card .pricing-micro-value {
            font-family: 'Archivo', 'Segoe UI', sans-serif !important;
            font-weight: 700 !important;
            font-variant-numeric: tabular-nums !important;
            letter-spacing: -0.015em !important;
        }
        body.public-body #propertyContent .pricing-sidebar-card .pricing-spread-title {
            font-family: 'Archivo', 'Segoe UI', sans-serif !important;
            font-size: 0.66rem !important;
            font-weight: 700 !important;
            letter-spacing: 0.2em !important;
            text-transform: uppercase !important;
            color: #15803d !important;
        }
        /* The footer was a centered COLUMN holding one label. It now carries the
           relocated Rehab level too, so it becomes a two-up row: spread label
           left, rehab right. */
        body.public-body #propertyContent .pricing-sidebar-card .pricing-spread-footer {
            flex-direction: row !important;
            justify-content: space-between !important;
            align-items: center !important;
            gap: 0.75rem !important;
            text-align: left !important;
        }
        body.public-body #propertyContent .pricing-sidebar-card .pricing-spread-rehab {
            display: inline-flex !important;
            align-items: baseline !important;
            gap: 0.4rem !important;
            white-space: nowrap !important;
        }
        body.public-body #propertyContent .pricing-sidebar-card .pricing-spread-rehab-label {
            font-family: 'Archivo', 'Segoe UI', sans-serif !important;
            font-size: 0.6rem !important;
            font-weight: 700 !important;
            letter-spacing: 0.16em !important;
            text-transform: uppercase !important;
            color: #5b6b82 !important;
        }
        body.public-body #propertyContent .pricing-sidebar-card #rehabDisplay {
            font-family: 'Archivo', 'Segoe UI', sans-serif !important;
            font-size: 0.86rem !important;
            font-weight: 700 !important;
        }
        /* Narrow cards: let the two halves stack rather than squeeze "Potential
           Spread" onto two lines beside a nowrap rehab chip. */
        @media (max-width: 420px) {
            body.public-body #propertyContent .pricing-sidebar-card .pricing-spread-footer {
                flex-direction: column !important;
                align-items: center !important;
                text-align: center !important;
                gap: 0.35rem !important;
            }
        }

        /* ---- Metric rows -----------------------------------------------------
           Label left in small caps, figure right in tabular Archivo. Squared to
           0.65rem so they read as a ledger, not as three more pills. */
        body.public-body #propertyContent .pricing-sidebar-card .financial-metric-card {
            border-radius: 0.65rem !important;
            padding: 0.7rem 0.9rem !important;
            background: #f2f6fb !important;
            background-image: none !important;
            border: 1px solid #e2e9f2 !important;
            box-shadow: none !important;
        }
        body.public-body #propertyContent .pricing-sidebar-card .financial-metric-label {
            font-family: 'Archivo', 'Segoe UI', sans-serif !important;
            font-size: 0.68rem !important;
            font-weight: 600 !important;
            letter-spacing: 0.1em !important;
            text-transform: uppercase !important;
            color: #5b6b82 !important;
        }
        body.public-body #propertyContent .pricing-sidebar-card .financial-metric-value,
        body.public-body #propertyContent .pricing-sidebar-card .financial-metric-value span {
            font-family: 'Archivo', 'Segoe UI', sans-serif !important;
            font-weight: 700 !important;
            font-variant-numeric: tabular-nums !important;
            letter-spacing: -0.01em !important;
        }

        /* ---- Quick actions ---------------------------------------------------
           The four tiles wear `.email-btn--outline .email-btn--sm` (and --navy for
           View Full Address). This block used to paint them itself — a flat
           #f8fafc face, an #e2e9f2 hairline, a 0.7rem corner and its own hover —
           which made THREE layers arguing over one control: the base sheet, the
           quick-actions block above, and this one. This was the specific one, so
           it won, and the other two were armed !important paint sitting behind it.

           The stated reason for the old numbers was to match .deal-stat-chip-price's
           0.7rem corner. The brand --sm corner is 12px against that 11.2px, so
           nothing about that intent is lost by deleting the paint; what is gained
           is that the tiles now carry the accent bar, the lit rim and the hover
           lift from the same place every other button on the site does.

           What stays is what is genuinely NOT the brand button: the smaller
           Archivo grotesk label these use to sit quietly under the CTAs, and the
           tap-target floor that label costs them. */
        body.public-body #propertyContent .pricing-sidebar-card .pricing-quick-btn {
            font-family: 'Archivo', 'Segoe UI', sans-serif !important;
            font-size: 0.74rem !important;
            font-weight: 700 !important;
            letter-spacing: 0.02em !important;
            /* The smaller grotesk label shrank these to 41px on a phone. The tap
               target is a floor, not a consequence of the type size. */
            min-height: 44px !important;
        }

        /* ---- Countdown + trust line ------------------------------------------ */
        body.public-body #propertyContent .pricing-sidebar-card .offer-countdown {
            border-radius: 0.7rem !important;
            font-family: 'Archivo', 'Segoe UI', sans-serif !important;
            letter-spacing: 0.04em !important;
        }
        body.public-body #propertyContent .pricing-sidebar-card .deal-trust-note,
        body.public-body #propertyContent .pricing-sidebar-card #dealBuyerProof {
            font-family: 'Archivo', 'Segoe UI', sans-serif !important;
            font-size: 0.72rem !important;
            letter-spacing: 0.005em !important;
        }

        /* Escape-to-dismiss for the two hero tooltips (see wireTooltipDismiss at
           the foot of the page). This has to outrank the :hover / :focus-within
           reveal rules, which is why it is stated here, last, with !important. */
        body.public-body #propertyContent .tip-dismissed .deal-price-tip,
        body.public-body #propertyContent .tip-dismissed .deal-status-tip {
            opacity: 0 !important;
            visibility: hidden !important;
        }

        /* The four in-card CTAs keep the shared .email-btn skin (they are the
           page's standardized red / gold / navy set and are deliberately not
           re-skinned here); they only lose a little roundness so they sit in the
           same family as everything above. */
        body.public-body #propertyContent .pricing-sidebar-card .email-btn {
            border-radius: 0.8rem !important;
        }

        /* =====================================================================
           URGENCY STRIP — recoloured into the navy/gold system.
           =====================================================================
           It was amber-200 on an amber -> white -> rose gradient: three warm
           hues in one 60px bar, none of them brand colours, and the rose end
           collided with the crimson CTA sitting directly beneath it.

           It stays LIGHT on purpose. This strip sits immediately above Submit
           an Offer, and a dark block there competes with the CTA for the eye —
           the same reason the cash-buyers card was pulled back off navy. So the
           surface is a near-white cool wash and the COLOUR lives in two small
           places: a gold accent edge (the alert cue) and a navy tile with a
           gold bell, which is exactly the .deal-kind-chip treatment from the
           top bar. Utility classes for the old border/gradient were removed
           from the markup so this owns the whole look without !important. */
        body.public-body #propertyContent .investor-summary-urgency {
            position: relative;
            overflow: hidden;
            border-radius: 1rem;
            background: linear-gradient(100deg, #f6f9fd 0%, #ffffff 46%, #fdfaf3 100%);
            border: 1px solid rgba(30, 58, 95, 0.14);
            box-shadow:
                inset 0 1px 0 rgba(255, 255, 255, 0.9),
                0 12px 26px -16px rgba(30, 58, 95, 0.28);
        }
        /* Gold accent edge — the page's existing "this row matters" idiom
           (same shape as the #datesSection rows' left rail). */
        body.public-body #propertyContent .investor-summary-urgency::before {
            content: '';
            position: absolute;
            left: 0; top: 0; bottom: 0;
            width: 3px;
            background: linear-gradient(180deg, #f3d9a4, #e7c277 55%, #cba24f);
        }
        /* Navy tile + gold bell: identical treatment to .deal-kind-chip, so the
           two "badge" objects on the page read as one component. */
        body.public-body #propertyContent .investor-summary-urgency-icon {
            border-radius: 0.75rem;
            background: linear-gradient(135deg, #10243f 0%, #1e3a5f 100%);
            border: 1px solid rgba(255, 255, 255, 0.16);
            box-shadow:
                inset 0 1px 0 rgba(255, 255, 255, 0.14),
                0 10px 20px -10px rgba(30, 58, 95, 0.55);
        }
        body.public-body #propertyContent .investor-summary-urgency-icon i,
        body.public-body #propertyContent .investor-summary-urgency-icon svg {
            color: #e7c277 !important;
            stroke: #e7c277 !important;
        }
    
        /* ==== 26) The offer CTA follows the buyer down the page. =============
           The deal body is a 2:1 grid whose LEFT column runs nine sections tall
           (photos → highlights → summary → transaction → condition → records →
           comps → video → map) while the right rail ends after the agent card.
           Nothing was sticky, and the offer bar was `lg:hidden` — so a desktop
           buyer reading the comparables, the moment they are deciding, had no
           price, no deadline and no Submit an Offer anywhere on screen.

           Two independent fixes, because they cover different scroll bands:
             a) the pricing card pins inside the rail (rail is the containing
                block, and .deal-showcase already sets align-items:start, so the
                card travels the full height of the taller media column);
             b) the offer bar is no longer phone-only — it covers everything
                BELOW the rail, where nothing can be sticky at all.
           `standDownOfferBarWhenCtaVisible` already hides the bar whenever a
           real CTA is on screen, so the pinned card and the bar never both
           show the same button.

           (a) is GONE. A sticky FIRST child of a 3,000px rail does not travel
           over the media column — it travels over its own SEVEN siblings.
           Sticky leaves the element's box behind in flow, so once the 786px
           card pinned, Property Details / Rent Estimate / the contact card
           scrolled up underneath it and the card's own red Submit an Offer
           button sat on top of their copy (measured at 1440x900). Only (b)
           survives, and (b) covers the whole page, not just the rail — the
           offer bar was always the honest version of this idea. */
        /* The bar is full-bleed on a phone. Above that it becomes a centred pill
           on the same 80rem measure as the page, so it reads as page furniture
           rather than a second nav bar nailed across the viewport.

           2026-08-17: the pill starts at 768px, not 1024px. Between the two the
           bar was full-bleed AND still reserving the phone's 5.5rem chat gutter,
           so on every tablet and small laptop its contents sat shoved into the
           left two-thirds with a hand's width of empty white to their right —
           the "off-centre" read, and it came from a gutter defending against a
           bubble the layout no longer runs under.

           768px is where a centred pill first clears the bottom-right chat
           bubble on its own. That needs the width floor to be the binding term
           at the low end: `100vw - 12rem` leaves 96px of margin at 768 (the GHL
           bubble reaches ~80px in from the right), where the old `- 4rem` left
           80px and touched it. From ~1000px up the 38rem cap binds instead and
           the geometry is exactly what it has been. */
        @media (min-width: 768px) {
            body.public-body #mobileOfferBar {
                inset-inline: 0;
                bottom: 1.25rem;
                border: 1px solid rgba(226, 232, 240, 0.9);
                border-radius: 1rem;
                width: min(38rem, calc(100vw - 12rem));
                margin-inline: auto;
                box-shadow: 0 18px 40px -18px rgba(15, 23, 42, 0.32);
            }
            /* The phone layout reserves the right end for the chat bubble. A
               centred pill does not sit under it, so that gutter is dead space —
               and it was what pushed the row off-centre inside the pill. */
            body.public-body #mobileOfferBar > div {
                padding-right: 1rem !important;
            }
            /* public-ui.css lifts the chat launcher 6rem whenever the offer bar is
               up, because on a phone the bar runs under it. A centred pill does
               not, so hand the launcher its normal corner back. */
            body.public-body.has-mobile-offer-bar .public-chat-launcher,
            body.public-body.has-ghl-livechat.has-mobile-offer-bar .public-chat-launcher {
                bottom: var(--public-floating-inset-y);
            }
        }

        /* ==== 27) 375px: three controls in ~270px of bar. ====================
           The bar carries a price block, a Walkthrough button and Submit an
           Offer, inside `px-4` plus the 4.5rem gutter the chat bubble needs —
           which left the price truncating on the narrowest phones that are the
           bar's whole reason for existing. The Walkthrough label goes (the
           button keeps its aria-label and its calendar glyph); the price gets
           the space back. */
        /* The short "Offer" label is the exception, so it is off by default and
           only the narrow query turns it on — the reverse would flash both
           labels for one frame before the query applied. */
        body.public-body #mobileOfferBar .offer-bar-cta-short { display: none; }
        /* 2026-08-08: raised from 419px. The bar's own controls, not the bar's
           background, were landing under the GoHighLevel chat bubble on ordinary
           phones (390–430px) — the two full-word labels are what made the row
           wider than the space left beside the launcher.
           2026-08-17: raised again, 480 → 560. The chat gutter above went from
           3.9rem to 5.75rem to actually clear that bubble, which costs the row
           30px; at 481px with both full labels the price had ~7px of slack left
           and `truncate` would have started eating it. The bar exists to keep a
           price and an offer button in reach, so the price wins and the word
           goes (both buttons keep their aria-label and the calendar glyph). */
        @media (max-width: 560px) {
            body.public-body #mobileOfferBar .offer-bar-cta-text { display: none; }
            body.public-body #mobileOfferBar .offer-bar-cta-short { display: inline; }
        }

        /* ==== 28) DEAL TIMELINE: moved. =====================================
           The rail-and-nodes pass that lived here fought the ID-specificity
           brand-tile rules and produced the muddled hybrid. Section 17 is now
           the timeline's ONE owner. */

        /* ==== 29) Offer-modal preset chips. =================================
           The closing-timeframe field is free text on purpose (a buyer with a
           hard date has to be able to type it). These just remove the typing
           for the four answers that cover most offers. */
        body.public-body #contactModal .offer-preset-chip {
            padding: 0.3rem 0.7rem;
            border-radius: 999px;
            border: 1px solid #e2e8f0;
            background: #f8fafc;
            font-size: 0.75rem;
            font-weight: 700;
            color: #475569;
            transition: background-color 120ms ease, border-color 120ms ease, color 120ms ease;
        }
        body.public-body #contactModal .offer-preset-chip:hover {
            border-color: #cbd5e1;
            background: #f1f5f9;
            color: #1e3a5f;
        }
        body.public-body #contactModal .offer-preset-chip.is-selected {
            border-color: #1e3a5f;
            background: #1e3a5f;
            color: #ffffff;
        }

        /* ==== 30) Comparables: the SUBJECT row. =============================
           The table listed six other houses with nothing to measure them
           against, so "is this ARV real?" — the one question the section
           exists to answer — still meant scrolling back to the pricing card.
           The subject sits at the top in the same columns, visually distinct
           so it is never mistaken for a sale that happened. */
        body.public-body #propertyContent .comp-row--subject {
            margin: -0.25rem -0.6rem 0.25rem;
            padding-left: 0.6rem;
            padding-right: 0.6rem;
            border-bottom: 2px solid #cbd5e1;
            border-radius: 0.6rem 0.6rem 0 0;
            background: linear-gradient(90deg, rgba(30, 58, 95, 0.06), rgba(30, 58, 95, 0));
        }
        body.public-body #propertyContent .comp-row--subject .comp-addr { color: #1e3a5f; }
        /* Navy, not the comps' green: this is an ESTIMATE of what the property
           could be worth after repair, and the green is reserved on this page
           for money that actually changed hands. */
        body.public-body #propertyContent .comp-row--subject .comp-price { color: #1e3a5f; }
        body.public-body #propertyContent .comp-row--subject .comp-status {
            background: #1e3a5f;
            color: #ffffff;
        }

        /* ==== 31) Comparables map — pin numbers on the rows, legend dots. ====
           The row's number is the cross-reference to its pin, so it wears the
           pin's colour: comps GREEN (money that changed hands, same green as
           .comp-price), subject NAVY with a star (an ESTIMATE — that property
           has not sold). Shape and size differ too, so the pairing never rests
           on colour alone.

           .comp-row is `1fr auto` in deal-detail-base.css; the marker adds a
           leading column. Declared here rather than edited there so the base
           file keeps working for any other surface that renders a comp row. */
        body.public-body #propertyContent .comp-row {
            grid-template-columns: auto minmax(0, 1fr) auto;
        }
        body.public-body #propertyContent .comp-pin-no,
        body.public-body #propertyContent .comp-legend-dot {
            display: inline-flex;
            align-items: center;
            justify-content: center;
            width: 1.375rem;
            height: 1.375rem;
            flex: 0 0 auto;
            border-radius: 999px;
            font-size: 0.6875rem;
            font-weight: 800;
            line-height: 1;
            color: #ffffff;
            background: #15803d;
        }
        body.public-body #propertyContent .comp-pin-no--subject,
        body.public-body #propertyContent .comp-legend-dot--subject {
            background: #1e3a5f;
            font-size: 0.75rem;
        }
        /* Google draws its own controls; the canvas just needs to not collapse
           before the library paints into it. */
        body.public-body #propertyContent #comparablesMap [data-comps-map-canvas] > div { border-radius: inherit; }
