html {
    font-size: 14px;
}

@media (min-width: 768px) {
    html {
        font-size: 16px;
    }
}

/* ---------------------------------------------------------------------------
   Reveal-animation sad-path failsafe (CSS-only).

   The theme paints every `[data-anim^='slide-']` / `[data-anim^='fade']`
   element (and their `[data-anim-child]` variants) `opacity: 0` and
   `pointer-events: none` by default — they are only made visible when
   `RevealAnim.init()` (called from the tail of `initComponents()` in
   main.js) adds `.is-in-view` via a ScrollMagic observer. The full chain
   is `vendors.js -> main.js (gsap.registerPlugin) -> window.onload ->
   initComponents -> RevealAnim.init`. If `gsap.registerPlugin(ScrollTrigger)`
   on main.js line 4 throws (gsap undefined because vendors.js failed or
   stalled) the whole chain aborts and the entire page — including the
   header (`<div data-anim="fade delay-3">`) — stays invisible.

   The keyframes below run unconditionally 2 s after the stylesheet applies
   and force the element to its revealed state (`opacity: 1`, identity
   transform, `pointer-events: auto`). When the happy path runs, JS adds
   `.is-in-view` first and the `:not(.is-in-view)` selector mismatches,
   removing the animation rule — at that point the existing `transition:
   opacity, transform` on the base rule takes over for a smooth fade-in
   identical to the original UX.

   `[data-anim-wrap]` is also nuked because the base rule sets
   `pointer-events: none` on it (re-enabled only when JS adds `.animated`);
   without the failsafe, clicks fall through containers around revealed
   cards even after the children become visible.

   Trade-off: below-the-fold reveal-on-scroll elements appear at T = ~2 s
   instead of when scrolled into view. We lose a small bit of progressive-
   reveal polish in exchange for the page being reliably interactive when
   the JS chain breaks.
   --------------------------------------------------------------------------- */
[data-anim^='slide-']:not(.is-in-view),
[data-anim-child^='slide-']:not(.is-in-view),
[data-anim^='fade']:not(.is-in-view),
[data-anim-child^='fade']:not(.is-in-view) {
    animation: dataAnimAutoReveal 0.8s ease-out 2s forwards;
}

[data-anim-wrap]:not(.animated) {
    animation: dataAnimWrapAutoReveal 0s linear 2s forwards;
}

@keyframes dataAnimAutoReveal {
    to {
        opacity: 1;
        transform: translate3d(0, 0, 0);
        pointer-events: auto;
    }
}

@keyframes dataAnimWrapAutoReveal {
    to {
        pointer-events: auto;
    }
}

/* ---------------------------------------------------------------------------
   Preloader auto-hide (CSS-only).

   The project does NOT run any JS to hide the preloader. The theme's main.js
   still owns the polished happy path (window.onload -> fonts.ready -> 600 ms
   -> add `.-is-hidden`), and the keyframe animation below is the unconditional
   failsafe: it starts the moment the stylesheet applies and fades the
   preloader 2 s later regardless of script execution. Flaky mobile networks
   that never finish pulling `vendors.js` / `main.js` still get a usable page.

   The `:not(.-is-hidden)` selector makes the animation a no-op the instant
   JS adds the class — the more specific `.preloader.-is-hidden` rule in
   main.css then takes over with its existing 0.6 s opacity transition, so
   the fade looks identical to the theme's original.
   --------------------------------------------------------------------------- */
.preloader:not(.-is-hidden) {
    animation: preloaderAutoHide 0.6s ease-in 2s forwards;
}

@keyframes preloaderAutoHide {
    to {
        opacity: 0;
        pointer-events: none;
        visibility: hidden;
    }
}

.btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus {
    box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem #258cfb;
}

html {
    position: relative;
    min-height: 100%;
}

.form-floating > .form-control-plaintext::placeholder, .form-floating > .form-control::placeholder {
    color: var(--bs-secondary-color);
    text-align: end;
}

.form-floating > .form-control-plaintext:focus::placeholder, .form-floating > .form-control:focus::placeholder {
    text-align: start;
}

/* =========================================================================
   Header search

   Desktop (≥ 768px): the search form is rendered INLINE between the logo
   cluster and the phone number — no toggle needed. The form sits in the
   normal flow of .header__container, transparent over the header.
   Mobile (< 768px): the form is hidden behind a toggle (.js-search-toggle)
   that opens a full-width dark drawer below the header chrome.
   ========================================================================= */
.header.-type-1 .header__container {
    position: relative;
}

.header__search-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: 1px solid currentColor;
    border-radius: 2px;
    cursor: pointer;
    width: 38px;
    height: 38px;
    padding: 0;
    color: inherit;
    font-size: 16px;
    transition: background-color 0.2s ease, color 0.2s ease;
}

.header__search-toggle:hover {
    background: var(--color-accent-1);
    border-color: var(--color-accent-1);
    color: #fff;
}

.header__search-toggle > i {
    line-height: 1;
}

/* Default (desktop ≥ 768px): the toggle button is mobile-only, so hide it. */
.header__search-toggle.-mobile {
    display: none;
}

/* Mobile (< 768px): show the mobile toggle, force the visual order in the
   left cluster to [logo] ... [search-toggle][menuBtn]. */
@media (max-width: 767px) {
    .header.-type-1 .header__left {
        display: flex;
        align-items: center;
        width: 100%;
    }

    .header.-type-1 .header__left > .header__logo {
        order: 1;
        margin-left: 0;
        margin-right: auto;
    }

    .header.-type-1 .header__left > .header__search-toggle.-mobile {
        display: inline-flex;
        order: 2;
        margin-left: 0;
        margin-right: 20px;
    }

    .header.-type-1 .header__left > .header__menuBtn {
        order: 3;
        margin-left: 0;
    }
}

.header__search {
    display: none;
    align-items: center;
    gap: 8px;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    padding: 14px 24px;
    background: var(--color-dark-1, #181D24);
    z-index: 50;
    box-shadow: 0 8px 16px rgba(0, 0, 0, 0.18);
}

.header__search.is-open {
    display: flex;
}

/* Desktop: render the form inline in the normal flow of .header__container,
   between header__left (logo) and header__right (phone, socials, ...).
   Transparent so it blends with the header — the input keeps its own border. */
@media (min-width: 768px) {
    .header__search {
        display: flex;
        position: static;
        padding: 0;
        margin: 0 24px;
        background: transparent;
        box-shadow: none;
        flex: 0 1 320px;
        max-width: 320px;
    }
}

.header__search__input {
    flex: 1;
    min-width: 0;
    background: transparent;
    border: 1px solid #ffffff80;
    border-radius: 2px;
    padding: 10px 12px;
    font-size: 15px;
    line-height: 1.2;
    color: #fff;
    outline: none;
    transition: border-color 0.2s ease;
}

.header__search__input::placeholder {
    color: #ffffffaa;
}

.header__search__input:focus {
    border-color: var(--color-accent-1);
}

.header__search__button {
    background: var(--color-accent-1);
    border: 1px solid var(--color-accent-1);
    border-radius: 2px;
    cursor: pointer;
    padding: 9px 9px;
    color: #fff;
    line-height: 1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: background-color 0.2s ease;
}

.header__search__button:hover {
    background: #8a0d1a;
}

.header__search__button > i {
    line-height: 1;
    font-size: 14px;
}

/* Desktop submit button: override the base (red filled) treatment so the
   button reads as a ghost CTA — square 9×9 padding, transparent background,
   white border + white glyph; flips to solid red on hover. Must come AFTER
   the base .header__search__button rules so it wins on equal specificity. */
@media (min-width: 768px) {
    .header__search__button {
        background: transparent;
        border: 1px solid #fff;
        padding: 9px 9px;
        color: #fff;
        transition: background-color 0.2s ease, border-color 0.2s ease, color 0.2s ease;
    }

    .header__search__button > i {
        color: #fff;
    }

    .header__search__button:hover {
        background: var(--color-accent-1);
        border-color: var(--color-accent-1);
        color: #fff;
    }
}

/* When the burger menu opens, the theme adds .-dark to .js-header which
   force-paints the header background white and the foreground black. Our
   inline search form (and its drawer at narrower widths) used white text
   and a white border, which becomes invisible on the now-white header.
   Under .header.-dark, swap to a dark-on-white treatment. Higher specificity
   (parent class chained) beats the base rules without needing !important. */
.header.-dark .header__search {
    background: transparent;
}

.header.-dark .header__search__input {
    color: var(--color-dark-1, #181D24);
    border-color: rgba(0, 0, 0, 0.35);
}

.header.-dark .header__search__input::placeholder {
    color: rgba(0, 0, 0, 0.55);
}

.header.-dark .header__search__input:focus {
    border-color: var(--color-accent-1);
}

.header.-dark .header__search__button {
    background: transparent;
    border-color: var(--color-dark-1, #181D24);
    color: var(--color-dark-1, #181D24);
}

.header.-dark .header__search__button > i {
    color: var(--color-dark-1, #181D24);
}

.header.-dark .header__search__button:hover {
    background: var(--color-accent-1);
    border-color: var(--color-accent-1);
    color: #fff;
}

.header.-dark .header__search__button:hover > i {
    color: #fff;
}

/* ---------------------------------------------------------------------------
   LGPD cookie consent banner. Theme-matched: dark card on a fixed bottom-left
   anchor, Jost typography (inherited), accent-red CTA + white secondary
   button. Reuses the global `button -md` size + the existing color variables
   so it slots into the rest of the chrome without bespoke palette work.
   The `.js-cookieBanner` element renders with `hidden` attribute by default
   and the inline script in _Layout.cshtml unhides it only when no consent
   choice has been persisted yet.
   --------------------------------------------------------------------------- */
.cookieBanner {
    position: fixed;
    left: 24px;
    right: 24px;
    /* Sits well above the Leadster chat bubble (anchored to the bottom-right
       corner; closed bubble + label can run up to ~120 px tall). 160 px gives
       comfortable clearance even when the chat shows its expanded teaser. */
    bottom: 160px;
    z-index: 9999;
    margin: 0 auto;
    max-width: 760px;
    padding: 24px 28px;
    border-radius: 12px;
    background: var(--color-dark-1, #181D24);
    color: #fff;
    box-shadow: 0 16px 48px rgba(0, 0, 0, 0.32);
}

.cookieBanner[hidden] {
    display: none;
}

.cookieBanner__inner {
    display: flex;
    align-items: center;
    gap: 28px;
}

.cookieBanner__content {
    flex: 1 1 auto;
}

.cookieBanner__title {
    margin: 0 0 6px;
    font-size: 16px;
    line-height: 1.3;
    font-weight: 600;
    color: #fff;
}

.cookieBanner__text {
    margin: 0;
    font-size: 14px;
    line-height: 1.55;
    color: rgba(255, 255, 255, 0.85);
}

.cookieBanner__actions {
    display: flex;
    flex: 0 0 auto;
    gap: 10px;
}

.cookieBanner__actions .button {
    white-space: nowrap;
}

@media (max-width: 768px) {
    .cookieBanner {
        left: 12px;
        right: 12px;
        /* Same rationale on mobile — 130 px clears the smaller chat bubble
           plus its expanded teaser without forcing the banner to bury the
           CTAs behind the chat trigger. */
        bottom: 130px;
        padding: 18px 20px;
        border-radius: 10px;
    }

    .cookieBanner__inner {
        flex-direction: column;
        align-items: stretch;
        gap: 16px;
        text-align: left;
    }

    .cookieBanner__actions {
        flex-direction: row;
        justify-content: stretch;
    }

    .cookieBanner__actions .button {
        flex: 1 1 0;
        justify-content: center;
    }
}


/* ============================================================
   Grouped select dropdown — used by the search-form neighborhood
   picker to break a long list into labelled city sections
   (Florianópolis, Balneário Camboriú, Itapema, …). The label is a
   direct child of `.js-options` so the theme's `singleSelect` JS
   still binds a click handler to it (it iterates `.js-options > *`),
   but `pointer-events: none` keeps the click from actually
   reaching the element — the handler never fires, the selected
   value never gets stomped to the city name. The empty
   `data-value=""` in markup is a belt-and-suspenders fallback in
   case a future theme update lowers the pointer-events shield.
   ============================================================ */
.select__options__group-label {
    pointer-events: none;
    user-select: none;
    cursor: default;
    padding: 14px 20px 4px;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: #8c8079;
}

.select__options__group-label + .select__options__button {
    /* Tuck the first option of a group flush against its label so the
       grouping reads as a unit instead of floating apart. */
    padding-top: 6px;
}

.select__options__group-label:not(:first-of-type) {
    /* Visual divider between groups — only kicks in from the second
       group onward, leaving the top of the dropdown clean. */
    margin-top: 6px;
    border-top: 1px solid #f1ece8;
    padding-top: 14px;
}


/* ============================================================
   Featured-listing badge — applied to property cards on the
   homepage Index, the Search results grid, and (inline variant)
   the property Detail page header. Drives the visible "Destacado"
   marker the operator toggles via AppProperty.Featured in the
   admin. Sits over the card's image as a small accent chip; the
   inline variant strips the absolute positioning for the Detail
   page where it lives in normal flow next to the title.
   ============================================================ */
.featuredBadge {
    position: absolute;
    top: 14px;
    left: 14px;
    z-index: 2;
    display: inline-flex;
    align-items: center;
    padding: 6px 14px;
    background: var(--color-accent-1);
    color: #fff;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    border-radius: 999px;
    box-shadow: 0 6px 18px rgba(170, 17, 32, 0.18);
    pointer-events: none;
}

.featuredBadge--inline {
    /* Detail-page header variant — drops the overlay positioning so
       the chip flows above the property title instead of floating
       over an image. */
    position: static;
    margin-bottom: 12px;
}


/* ============================================================
   Property-detail Google Map. Wrapper div sized to a fixed
   responsive height; the Google Maps JS API takes over the
   element and renders its tiles + circle overlay (see
   wwwroot/js/property-map.js). Border-radius + faint
   accent-tinted shadow tie the block to the rest of the
   imageCard / numberCard family. Mobile: shorter height so
   the section doesn't push the rest of the page below the
   fold on small screens.
   ============================================================ */
.property-map {
    width: 100%;
    height: 420px;
    border-radius: 12px;
    overflow: hidden;
    background: var(--color-accent-2, #F7F0EC);
    box-shadow: 0 12px 28px rgba(170, 17, 32, 0.08);
}

@media (max-width: 768px) {
    .property-map {
        height: 300px;
    }
}

/* ============================================================
   Listing-acquisition form — custom consent checkbox + invalid-field hint
   ============================================================
   The native input is hidden (opacity:0 + absolute) so screen
   readers + tab order still find it; the visual "box" is a
   sibling pseudo-element drawn next to the label. Active state
   uses the RE/MAX accent red (--color-accent-1, falls back to
   the hardcoded brand hex if the variable is missing). The
   .form-invalid hint is reused by site.js to mark fields that
   failed the client-side required check.
*/
.listing-acquisition-consent {
    /* line-height matches the box's 22px height so the first line of
       the legend sits at the same vertical centre as the checkbox.
       With align-items:flex-start, wrapped lines cascade below the
       box without dragging it to the multi-line midpoint. */
    display: flex;
    align-items: flex-start;
    gap: 14px;
    cursor: pointer;
    padding: 12px 0;
    line-height: 22px;
}

.listing-acquisition-consent__box {
    /* margin-top:0 keeps the box top aligned to the line top — with
       line-height equal to the box height (22px), centres line up
       naturally and the visual misalignment from the previous
       2px-magic-offset version is gone. */
    flex: 0 0 22px;
    width: 22px;
    height: 22px;
    margin-top: 0;
    border: 2px solid var(--color-dark-2, #232323);
    border-radius: 4px;
    background-color: #fff;
    position: relative;
    transition: background-color .15s ease, border-color .15s ease;
}

.listing-acquisition-consent__box::after {
    /* The checkmark — drawn with two CSS borders rotated -45deg,
       no font-icon dependency so the visual works even if the
       theme icon font fails to load. */
    content: "";
    position: absolute;
    left: 6px;
    top: 2px;
    width: 6px;
    height: 11px;
    border: solid #fff;
    border-width: 0 2px 2px 0;
    transform: rotate(45deg);
    opacity: 0;
    transition: opacity .15s ease;
}

.listing-acquisition-consent__input {
    /* Hidden but focusable — keyboard users still get a focus
       ring on the sibling box below. */
    position: absolute;
    opacity: 0;
    pointer-events: none;
    width: 0;
    height: 0;
}

.listing-acquisition-consent__input:checked ~ .listing-acquisition-consent__box {
    background-color: var(--color-accent-1, #AA1120);
    border-color: var(--color-accent-1, #AA1120);
}

.listing-acquisition-consent__input:checked ~ .listing-acquisition-consent__box::after {
    opacity: 1;
}

.listing-acquisition-consent__input:focus-visible ~ .listing-acquisition-consent__box {
    outline: 2px solid var(--color-accent-1, #AA1120);
    outline-offset: 2px;
}

.listing-acquisition-consent__text {
    flex: 1 1 auto;
}

/* Client-side required-field highlight. Driven by the listing-
   acquisition-form JS handler — same red as the server-side
   validation summary so the visitor sees a consistent
   "this needs attention" colour. */
.contactForm__field.is-invalid input,
.contactForm__field.is-invalid textarea {
    border-color: var(--color-accent-1, #AA1120);
}

/* Default colour for every client-error slot — the consent checkbox
   lives OUTSIDE a .contactForm__field wrapper (it's a stand-alone
   <label>), so the parent-scoped rule below never matches it. Setting
   the colour at the base selector lets both contexts share the same
   accent red without duplicating rules. */
.contactForm__error {
    color: var(--color-accent-1, #AA1120);
    font-size: 14px;
}

.contactForm__field.is-invalid .contactForm__error {
    margin-top: 4px;
    display: block;
}

/* ============================================================
   Submit button — inline preloader / busy state
   ============================================================
   Used by listing-acquisition-form.js to prevent double-click
   on the listing-acquisition submit. While the AJAX request is in flight
   we set [data-busy="true"] on the button: the label text is
   hidden via opacity (preserves the button width so the layout
   doesn't reflow), the spinner appears centred on top, and the
   button is disabled so a second click is a no-op. Restoring the
   button on response = reset data-busy + disabled. Spinner is
   pure CSS (border + animation), no font / image dependency.
*/
button[data-busy="true"] {
    position: relative;
    cursor: progress;
}

button[data-busy="true"] > .button__label {
    opacity: 0;
}

button[data-busy="true"]::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 20px;
    height: 20px;
    margin-top: -10px;
    margin-left: -10px;
    border: 2px solid rgba(255, 255, 255, 0.35);
    border-top-color: #ffffff;
    border-radius: 50%;
    animation: form-submit-spin 0.7s linear infinite;
}

@keyframes form-submit-spin {
    to { transform: rotate(360deg); }
}

/* ============================================================
   Listing-acquisition deep-link anchors
   ============================================================
   Both #listing-acquisition (technical id on the <section>) and
   #vender (short, share-friendly secondary anchor inside the
   section) scroll-margin past the sticky theme header so a
   visitor following a deep link lands on the section heading,
   not under it. 100 px clears the header at every breakpoint
   the project supports.
*/
#listing-acquisition,
.listing-acquisition-anchor {
    scroll-margin-top: 100px;
}

/* ============================================================
   Footer privacy-policy link — centered, at the very bottom of
   the footer, beneath the copyright row.
   ============================================================ */
.footer__legal {
    margin-top: 16px;
    text-align: center;
}
.footer__legal a {
    color: inherit;
    text-decoration: underline;
    font-size: 14px;
    opacity: 0.85;
}
.footer__legal a:hover,
.footer__legal a:focus {
    opacity: 1;
}
.footer__legal-sep {
    margin: 0 8px;
    opacity: 0.5;
}

/* ============================================================
   Map search — interactive property finder (MapSearch.cshtml).
   Sits inside the standard pageHeader + .container content. Split:
   scrollable result sidebar (left) + Google map (right). Filters use
   the theme .select component + a noUiSlider price range. Brand
   colours only. Behaviour in /js/map-search.js.
   ============================================================ */
.mapSearch__legend {
    margin: 0 0 24px;
    color: var(--color-dark-4);
}

/* --- Filters: row 1 = dropdowns, row 2 = search input + price slider --- */
.mapSearch__filters {
    position: relative;
    z-index: 5;
    display: flex;
    flex-direction: column;
    gap: 22px;
    margin-bottom: 30px;
}
.mapSearch__filtersRow {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 18px 20px;
}
.mapSearch__filter {
    flex: 1 1 180px;
    min-width: 170px;
}
.mapSearch__filter .contactForm__caption {
    margin-bottom: 8px;
}
.mapSearch__filter .select {
    width: 100%;
}
.mapSearch__filter--q {
    flex: 1 1 280px;
}
.mapSearch__filter--price {
    flex: 1 1 300px;
    min-width: 240px;
}
.mapSearch__qInput {
    width: 100%;
    height: 50px;
    padding: 0 14px;
    font-size: 15px;
    color: var(--color-dark-1);
    background: var(--color-white);
    border: 1px solid var(--color-border);
    border-radius: 8px;
}
.mapSearch__qInput:focus {
    outline: 2px solid var(--color-accent-1);
    outline-offset: 1px;
    border-color: var(--color-accent-1);
}
.mapSearch__clear {
    flex: 0 0 auto;
    align-self: flex-end;
}

/* price range slider (structure styled by vendors.css .noUi-*) — value
   legends sit ABOVE the bar so the field lines up with the search input. */
.mapSearch__priceSlider .js-slider {
    margin: 0 6px 13px;
}
/* The theme forces .noUi-connect green with !important — override to brand. */
.mapSearch__priceSlider .noUi-connect {
    background-color: var(--color-accent-1) !important;
}
/* The theme centers the handle with top:50% + translateY(-50%), which lands
   it on the 4px track's TOP edge (2px high). Position it explicitly so the
   20px handle is centered on the track: top = (trackH - handleH) / 2 = -8px. */
.mapSearch__priceSlider .noUi-handle {
    top: -8px !important;
    transform: none !important;
    border-color: var(--color-accent-1);
}
.mapSearch__priceVals {
    margin-bottom: 12px;
    display: flex;
    gap: 6px;
    align-items: center;
    font-size: 14px;
    font-weight: 500;
    color: var(--color-dark-1);
}
.mapSearch__priceSep {
    color: var(--color-dark-4);
}

/* --- Split body --- */
.mapSearch__body {
    position: relative;
    display: flex;
    height: 72vh;
    min-height: 540px;
    border: 1px solid var(--color-border);
    border-radius: 12px;
    overflow: hidden;
}
.mapSearch__sidebar {
    flex: 0 0 40%;
    max-width: 460px;
    display: flex;
    flex-direction: column;
    border-right: 1px solid var(--color-border);
    overflow: hidden;
}
.mapSearch__status {
    flex: 0 0 auto;
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 12px 20px;
    border-bottom: 1px solid var(--color-border);
    font-size: 13px;
    color: var(--color-dark-4);
}
.mapSearch--nomap .mapSearch__sidebar {
    flex: 1 1 100%;
    max-width: none;
    border-right: 0;
}

/* list + loading overlay (preloader while filtering) */
.mapSearch__listWrap {
    position: relative;
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
}
.mapSearch__list {
    flex: 1 1 auto;
    overflow-y: auto;
    padding: 12px;
    display: flex;
    flex-direction: column;
    gap: 12px;
}
.mapSearch__empty {
    padding: 40px 20px;
    text-align: center;
    color: var(--color-dark-4);
}
.mapSearch__overlay {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    background: rgba(255, 255, 255, 0.72);
    color: var(--color-accent-1);
    font-weight: 500;
    z-index: 2;
}
.mapSearch__overlay[hidden] {
    display: none;
}
.mapSearch__spinner {
    width: 22px;
    height: 22px;
    border: 2px solid rgba(170, 17, 32, 0.25);
    border-top-color: var(--color-accent-1);
    border-radius: 50%;
    animation: mapSearchSpin 0.7s linear infinite;
}
@keyframes mapSearchSpin {
    to { transform: rotate(360deg); }
}

/* sidebar collapse: status-bar header (collapse arrow + count) */
.mapSearch__statusLeft {
    display: flex;
    align-items: center;
    gap: 8px;
}
.mapSearch__collapseBtn {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    padding: 0;
    background: transparent;
    border: 1px solid var(--color-border);
    border-radius: 6px;
    color: var(--color-dark-1);
    cursor: pointer;
}
.mapSearch__collapseBtn:hover {
    border-color: var(--color-accent-1);
    color: var(--color-accent-1);
}
.mapSearch__collapseBtn:focus-visible {
    outline: 2px solid var(--color-accent-1);
}
/* floating re-open button — only while collapsed */
.mapSearch__expandBtn {
    display: none;
    position: absolute;
    left: 12px;
    top: 12px;
    z-index: 4;
    width: 36px;
    height: 36px;
    align-items: center;
    justify-content: center;
    background: var(--color-white);
    border: 1px solid var(--color-border);
    border-radius: 8px;
    color: var(--color-dark-1);
    cursor: pointer;
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.12);
}
.mapSearch__expandBtn:hover {
    border-color: var(--color-accent-1);
    color: var(--color-accent-1);
}
.mapSearch__expandBtn:focus-visible {
    outline: 2px solid var(--color-accent-1);
}
.mapSearch--collapsed .mapSearch__sidebar {
    flex-basis: 0;
    width: 0;
    max-width: 0;
    border-right: 0;
    overflow: hidden;
}
.mapSearch--collapsed .mapSearch__expandBtn {
    display: flex;
}

/* map toggle (mobile only) */
.mapSearch__mapToggle {
    display: none;
    align-items: center;
    gap: 6px;
    padding: 0;
    background: transparent;
    border: 0;
    color: var(--color-accent-1);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    font-size: 13px;
    cursor: pointer;
}
.mapSearch__mapToggle svg {
    transition: transform 0.2s ease;
}
/* map shown → chevron up (collapse); map hidden → flip down (expand) */
.mapSearch--mapHidden .mapSearch__mapToggle svg {
    transform: rotate(180deg);
}
.mapSearch__map {
    flex: 1 1 auto;
    min-height: 0;
}

/* --- Result card --- */
.mapSearchCard {
    display: flex;
    flex-direction: column;
    padding: 8px;
    border: 1px solid var(--color-border);
    border-radius: 10px;
    background: var(--color-white);
    color: var(--color-dark-1);
    cursor: pointer;
    transition: box-shadow 0.2s ease, border-color 0.2s ease, transform 0.2s ease;
}
.mapSearchCard__top {
    display: flex;
    gap: 12px;
}
.mapSearchCard:hover,
.mapSearchCard:focus-visible,
.mapSearchCard.isCardActive {
    border-color: var(--color-accent-1);
    box-shadow: 0 6px 20px rgba(170, 17, 32, 0.16);
    transform: translateY(-1px);
    outline: none;
}
.mapSearchCard__image {
    position: relative;
    flex: 0 0 112px;
    width: 112px;
    height: 96px;
    border-radius: 8px;
    overflow: hidden;
    background: var(--color-accent-2);
}
.mapSearchCard__image img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}
.mapSearchCard__badge {
    position: absolute;
    top: 6px;
    left: 6px;
    width: 22px;
    height: 22px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: var(--color-accent-1);
    color: var(--color-white);
}
.mapSearchCard__badge svg {
    width: 13px;
    height: 13px;
}
.mapSearchCard__body {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 3px;
}
.mapSearchCard__price {
    font-weight: 600;
    color: var(--color-accent-1);
}
.mapSearchCard__title {
    font-weight: 500;
    line-height: 1.3;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.mapSearchCard__meta {
    font-size: 13px;
    color: var(--color-dark-4);
}
/* footer: features start from the left (below the image) with a little inset,
   detail link aligned right */
.mapSearchCard__footer {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 6px 16px;
    margin-top: 10px;
    padding: 0 6px;
}
.mapSearchCard__features {
    display: flex;
    flex-wrap: wrap;
    gap: 6px 14px;
    align-items: center;
    font-size: 13px;
    color: var(--color-dark-4);
}
.mapSearchCard__feature {
    display: inline-flex;
    align-items: center;
    gap: 4px;
}
.mapSearchCard__feature svg {
    flex: 0 0 auto;
    color: var(--color-dark-4);
}
.mapSearchCard__feature i {
    flex: 0 0 auto;
    font-size: 16px;
    line-height: 1;
    color: var(--color-dark-4);
}
.mapSearchCard__detail {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 13px;
    font-weight: 500;
    color: var(--color-accent-1);
    text-decoration: none;
}
.mapSearchCard__detail:hover,
.mapSearchCard__detail:focus-visible {
    text-decoration: underline;
}

/* --- Map info window: horizontal (photo + content), compact --- */
.mapSearchInfo {
    display: flex;
    gap: 12px;
    width: 312px;
    max-width: 312px;
    padding: 12px;
    align-items: center;
}
.mapSearchInfo__image {
    flex: 0 0 96px;
    width: 96px;
    height: 96px;
    object-fit: cover;
    border-radius: 8px;
}
.mapSearchInfo__body {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
    /* room so the title never slides under the floating close button */
    padding-right: 16px;
}
.mapSearchInfo__tag {
    align-self: flex-start;
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--color-dark-1);
}
.mapSearchInfo__price {
    font-weight: 600;
    font-size: 15px;
    color: var(--color-accent-1);
}
.mapSearchInfo__title {
    font-weight: 500;
    line-height: 1.25;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.mapSearchInfo__meta {
    font-size: 13px;
    color: var(--color-dark-4);
}
.mapSearchInfo__detail {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    margin-top: 4px;
    font-weight: 500;
    color: var(--color-accent-1);
    text-decoration: none;
}
.mapSearchInfo__detail:hover {
    text-decoration: underline;
}

/* Tighten Google's info-window chrome: kill the padding + the header row that
   adds dead space on top, and shrink + float the close button into the corner.
   Scoped to this map; the site's only other map (Detail) has no info window. */
.mapSearch__map .gm-style-iw-c {
    padding: 0 !important;
    border-radius: 10px !important;
}
.mapSearch__map .gm-style-iw-d {
    overflow: hidden !important;
    padding: 0 !important;
}
.mapSearch__map .gm-style-iw-chr {
    height: 0 !important;
    min-height: 0 !important;
}
.mapSearch__map .gm-style-iw-chr .gm-style-iw-ch {
    padding: 0 !important;
}
.mapSearch__map button.gm-ui-hover-effect {
    position: absolute !important;
    top: 5px !important;
    right: 5px !important;
    width: 22px !important;
    height: 22px !important;
    min-width: 0 !important;
    opacity: 0.75;
    z-index: 2;
}
.mapSearch__map button.gm-ui-hover-effect > span {
    width: 15px !important;
    height: 15px !important;
    margin: 3px !important;
}

/* Mobile: pin the info window to a fixed, compact size so its content never
   overlaps inside the narrow Google bubble (and the close button clears the
   text). */
@media (max-width: 991px) {
    .mapSearchInfo {
        width: 232px;
        max-width: 232px;
        gap: 9px;
        padding: 9px;
    }
    .mapSearchInfo__image {
        flex: 0 0 74px;
        width: 74px;
        height: 74px;
    }
    .mapSearchInfo__body {
        padding-right: 14px;
    }
    .mapSearchInfo__price {
        font-size: 14px;
    }
    .mapSearchInfo__title {
        font-size: 13px;
        -webkit-line-clamp: 2;
    }
}

/* --- Responsive: stack map over the list on small screens --- */
@media (max-width: 991px) {
    .mapSearch__body {
        flex-direction: column;
        height: auto;
        min-height: 0;
    }
    .mapSearch__sidebar {
        flex: 1 1 auto;
        max-width: none;
        border-right: 0;
        border-top: 1px solid var(--color-border);
        order: 2;
        overflow: visible;
    }
    .mapSearch__list {
        overflow: visible;
    }
    .mapSearch__map {
        order: 1;
        height: 50vh;
        min-height: 320px;
    }
    .mapSearch__collapseBtn,
    .mapSearch__expandBtn {
        display: none !important;
    }
    .mapSearch__mapToggle {
        display: inline-flex;
    }
    .mapSearch--mapHidden .mapSearch__map {
        display: none;
    }
}

/* Honor reduced-motion: drop the card hover lift/transition. */
@media (prefers-reduced-motion: reduce) {
    .mapSearchCard {
        transition: none;
    }
    .mapSearchCard:hover,
    .mapSearchCard:focus-visible,
    .mapSearchCard.isCardActive {
        transform: none;
    }
}
