/* =========================================================================
   InHouse Dark — Real Estate theme, dark ground with a gold accent
   Single stylesheet. All rules live here, nothing inline in the markup.

   Same component set and class names as the light InHouse theme, so markup
   ports between the two untouched. What differs is section 01: the palette
   is inverted, and two roles the light theme could fold into one token are
   split apart here —

     --ink   is TEXT ONLY. In the light theme it doubled as the dark band
             colour; on a dark ground those pull in opposite directions.
     --band  is that dark band: header, footer, CTA, .section--ink.

   So `color: var(--ink)` is near-white and `background: var(--band)` is
   near-black. Never use one for the other.

   TABLE OF CONTENTS
   01. Design tokens
   02. Reset & base
   03. Typography
   04. Layout (container, section, grid)
   05. Buttons
   06. Forms
   07. Badges & tags
   08. Header & navigation
   09. Hero
   09b. Hero slider (homepage 2)
   09c. Hero search
   10. Search panel
   10b. Search bar (minimal)
   11. Section head
   12. Property card
   12b. Property card — gallery variant
   12c. Property rail
   13. Feature blocks
   14. Steps
   15. Stats
   16. Agents
   16b. Agent profile
   17. Testimonials
   18. Partners
   19. CTA band
   20. Blog card
   21. Newsletter
   22. Footer
   23. Page header & breadcrumb
   24. Filter sidebar
   25. Toolbar & pagination
   25b. Map search
   25c. Filter drawer
   26. Property detail
   26b. Lightbox
   26c. Property page - mosaic layout
   27. Accordion
   28. Contact & map
   29. Article body
   30. Back to top
   31. Utilities
   32. Elements page (style guide)
   33. Homepage 3 (avant-garde)
   34. Responsive
   35. Century sections (watermark head, category band, region map,
       brand stats, sell steps, statement band)
   36. Floating WhatsApp
   37. Language switcher
   38. Print
   39. Select menu
   40. Search form — wide
   ========================================================================= */


/* =========================================================================
   01. DESIGN TOKENS
   One gold, one near-white, and a stack of near-blacks. Change the four
   --brand-* values and the theme is rebranded; change --band/--paper and
   the whole ground shifts with every component still in step.
   ========================================================================= */
:root {

    /* --- brand ------------------------------------------------------------
       The gold does three different jobs and each needs its own value: a
       hairline/icon gold, a fill you can put dark type on, and a text gold
       bright enough to clear AA against --paper. */
    --brand:            #C6A96B;   /* icons, borders, focus rings, accents */
    --brand-fill:       #BFA164;   /* filled surfaces carrying --on-brand type */
    --brand-hover:      #D9C08A;   /* those fills, hovered — lighter, not darker */
    --brand-text:       #CBAF78;   /* gold used AS text: links, eyebrows, prices */
    --brand-soft:       #221D14;   /* tinted chip and icon beds */
    --on-brand:         #14120C;   /* type and glyphs sitting ON a gold fill */

    /* --- type -------------------------------------------------------------
       --ink is text, never a background. See the note at the top of the file. */
    --ink:              #F3F0E9;   /* headings and strong text */
    --ink-2:            #C2BDB2;   /* body copy */
    --muted:            #8E8A80;   /* meta, captions, placeholders */
    --white:            #FFFFFF;   /* fixed white — type and chrome over photos */

    /* --- surfaces, deepest first ------------------------------------------
       --band is the deep band (header, footer, CTA, .section--ink), --paper
       the card sitting on it, --paper-hi a card raised off another card. */
    --ground:           #0E0E0E;   /* the page itself, under every section */
    --band:             #070707;   /* deepest: header, footer, CTA, .section--ink */
    --sand:             #141414;   /* alternating section tone */
    --mist:             #1A1A1A;   /* the second alternating tone */
    --paper:            #1E1E1E;   /* cards, panels, dropdowns */
    --paper-hi:         #272727;   /* a card raised off another card */
    --field:            #161616;   /* form control ground */
    --field-hi:         #262626;   /* a field that has focus */

    /* glass laid over photography — dark here, where a light theme goes white */
    --glass:            rgba(18, 18, 18, .88);
    --glass-solid:      rgba(16, 16, 16, .97);

    /* --- hairlines --------------------------------------------------------- */
    --line:             #2E2B26;
    --line-soft:        #232120;
    --line-strong:      #464137;   /* the 1px rules that carry a section */

    /* state */
    --gold:             #D9B44A;   /* "featured" — brighter than the brand gold */
    --danger:           #C9564A;

    /* typography */
    --font-body:        'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
    --font-display:     'Manrope', 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
    --font-mono:        ui-monospace, SFMono-Regular, Menlo, Consolas, 'Liberation Mono', monospace;

    /* rhythm */
    --container:        1200px;
    --container-sm:     720px;
    --container-narrow: 820px;
    --container-md:     960px;
    --container-lg:     1360px;
    --container-xl:     1600px;
    --gutter:           24px;
    --section-y:        clamp(64px, 8vw, 120px);

    /* shape */
    --r-sm:             8px;
    --r:                12px;
    --r-lg:             20px;
    --r-pill:           999px;

    /* elevation — used sparingly, the theme leans on borders */
    --shadow-sm:        0 1px 2px rgba(0, 0, 0, .45);
    --shadow:           0 8px 24px rgba(0, 0, 0, .55);
    --shadow-lg:        0 24px 60px rgba(0, 0, 0, .7);

    /* motion */
    --t:                .25s cubic-bezier(.4, 0, .2, 1);

    /* the vertical line the floating buttons share, measured from the right
       edge. Each is centred on it, so their differing widths do not offset
       one from the other. */
    --float-x:          52px;

    /* layering */
    --z-header:         100;
    --header-h:         79px;   /* header 78 + the 1px rule under it */
    --z-drawer:         200;
    --z-top:            300;
}


/* =========================================================================
   02. RESET & BASE
   ========================================================================= */
*,
*::before,
*::after {
    box-sizing: border-box;
}

html {
    -webkit-text-size-adjust: 100%;
    scroll-behavior: smooth;

    /* hands the browser the theme's ground so scrollbars, native pickers and
       the overscroll gutter come up dark instead of flashing white */
    color-scheme: dark;
}

::selection {
    background: var(--brand-fill);
    color: var(--on-brand);
}

body {
    margin: 0;
    background: var(--ground);
    color: var(--ink-2);
    font-family: var(--font-body);
    font-size: 16px;
    line-height: 1.7;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

/* stop the page jumping when a drawer or modal locks scrolling */
body.is-locked {
    overflow: hidden;
}

img,
svg,
video {
    max-width: 100%;
    height: auto;
    display: block;
}

/* any class that sets display outranks the browsers own [hidden] rule,
   so hiding a flex or grid child needs saying out loud */
[hidden] {
    display: none !important;
}

a {
    color: var(--brand-text);
    text-decoration: none;
    transition: color var(--t);
}

a:hover {
    color: var(--ink);
}

ul,
ol {
    margin: 0;
    padding: 0;
    list-style: none;
}

button {
    font: inherit;
    color: inherit;
    cursor: pointer;
}

hr {
    border: 0;
    border-top: 1px solid var(--line);
    margin: 32px 0;
}

/* visible keyboard focus everywhere — never remove without a replacement */
:focus-visible {
    outline: 2px solid var(--brand);
    outline-offset: 3px;
    border-radius: 4px;
}

/* screen-reader only, but focusable (skip link) */
.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
}

.skip-link {
    position: absolute;
    left: 16px;
    top: -60px;
    z-index: var(--z-top);
    background: var(--brand-fill);
    color: var(--on-brand);
    padding: 10px 18px;
    border-radius: var(--r-sm);
    transition: top var(--t);
}

.skip-link:focus {
    top: 16px;
    color: var(--on-brand);
}

/* respect users who asked for less motion */
@media (prefers-reduced-motion: reduce) {

    html {
        scroll-behavior: auto;
    }

    *,
    *::before,
    *::after {
        animation-duration: .01ms !important;
        transition-duration: .01ms !important;
    }
}


/* =========================================================================
   03. TYPOGRAPHY
   ========================================================================= */
h1, h2, h3, h4, h5, h6,
.as-h1 {
    margin: 0 0 .5em;
    color: var(--ink);
    font-family: var(--font-display);
    font-weight: 600;
    line-height: 1.14;
    letter-spacing: -.02em;
}

/* the bigger the type, the tighter it is set */
h1,
.as-h1 { font-size: clamp(2.25rem, 5vw, 3.75rem); letter-spacing: -.035em; }
h2 { font-size: clamp(1.75rem, 3.4vw, 2.6rem); letter-spacing: -.03em; }
h3 { font-size: clamp(1.3rem, 2.2vw, 1.75rem); letter-spacing: -.025em; }
h4 { font-size: 1.2rem; }
h5 { font-size: 1.05rem; }
h6 { font-size: .95rem; }

p {
    margin: 0 0 1.1em;
}

p:last-child {
    margin-bottom: 0;
}

/* small uppercase label that sits above a heading */
.eyebrow {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 14px;
    color: var(--brand-text);
    font-size: .78rem;
    font-weight: 600;
    letter-spacing: .16em;
    text-transform: uppercase;
}

.eyebrow::before {
    content: "";
    width: 26px;
    height: 1px;
    background: currentColor;
}

.eyebrow--center::before {
    display: none;
}

.lead {
    font-size: 1.075rem;
    color: var(--muted);
}

.text-muted {
    color: var(--muted);
}

/* a word or two of the headline picked out in the accent colour */
.accent {
    color: var(--brand-text);
}


/* =========================================================================
   04. LAYOUT
   ========================================================================= */
/* Wrap any section's content in .container. The modifiers only change the
   max width — the gutter is shared, so nothing ever touches the viewport
   edge. Every width is a token, so the scale is changed in one place. */
.container {
    width: 100%;
    max-width: var(--container);
    margin-inline: auto;
    padding-inline: var(--gutter);
}

.container--sm     { max-width: var(--container-sm); }
.container--narrow { max-width: var(--container-narrow); }
.container--md     { max-width: var(--container-md); }
.container--lg     { max-width: var(--container-lg); }
.container--xl     { max-width: var(--container-xl); }

/* full width, gutters kept */
.container--fluid {
    max-width: none;
}

/* full bleed — no max width and no gutter, for edge-to-edge media */
.container--flush {
    max-width: none;
    padding-inline: 0;
}

/* Put one of these on <body> to reset the page's default width in a single
   place. Every .container follows, and so does anything else reading the
   token — the hero slider controls, for one — so nothing falls out of line. */
.page--sm { --container: var(--container-sm); }
.page--md { --container: var(--container-md); }
.page--lg { --container: var(--container-lg); }
.page--xl { --container: var(--container-xl); }

.section {
    padding-block: var(--section-y);
}

.section--tight {
    padding-block: clamp(48px, 5vw, 72px);
}

/* for a section that continues the one above it — without this the two
   paddings stack and leave a band twice the intended rhythm */
.section--flush-top {
    padding-top: 0;
}

/* for a page that opens straight onto its content - enough to breathe
   under the page header without a full section gap */
.section--half-top {
    padding-top: calc(var(--section-y) / 2);
}

.section--sand {
    background: var(--sand);
}

.section--mist {
    background: var(--mist);
}

.section--ink {
    background: var(--band);
    color: rgba(255, 255, 255, .78);
}

.section--ink h1,
.section--ink h2,
.section--ink h3,
.section--ink h4 {
    color: var(--ink);
}

/* generic auto-fit grid — column count comes from a modifier class */
.grid {
    display: grid;
    gap: 28px;
}

.grid.col-2 { grid-template-columns: repeat(2, 1fr); }
.grid.col-3 { grid-template-columns: repeat(3, 1fr); }
.grid.col-4 { grid-template-columns: repeat(4, 1fr); }
.grid.col-5 { grid-template-columns: repeat(5, 1fr); }
.grid.col-6 { grid-template-columns: repeat(6, 1fr); }

/* two-column content/media split */
.split {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: clamp(32px, 5vw, 72px);
    align-items: center;
}

.split--media-first .split__media {
    order: -1;
}

.split__media img {
    width: 100%;
    border-radius: var(--r-lg);
}


/* =========================================================================
   05. BUTTONS
   ========================================================================= */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    padding: 13px 26px;
    border: 1px solid transparent;
    border-radius: var(--r-pill);
    background: var(--brand-fill);
    color: var(--on-brand);
    font-size: .93rem;
    font-weight: 600;
    line-height: 1.2;
    text-align: center;
    white-space: nowrap;
    transition: background var(--t), color var(--t), border-color var(--t), transform var(--t);
}

.btn:hover {
    background: var(--brand-hover);
    color: var(--on-brand);
    transform: translateY(-1px);
}

.btn svg {
    width: 17px;
    height: 17px;
    flex: none;
}

.btn--outline {
    background: transparent;
    border-color: var(--line);
    color: var(--ink);
}

.btn--outline:hover {
    background: var(--brand-fill);
    border-color: var(--brand-fill);
    color: var(--on-brand);
}

/* solid dark button — what btn--outline only showed on hover */
.btn--ink {
    background: var(--paper-hi);
    border-color: var(--line-strong);
    color: var(--ink);
}

.btn--ink:hover {
    background: var(--brand-fill);
    border-color: var(--brand-fill);
    color: var(--on-brand);
}

.btn--ghost {
    background: transparent;
    color: var(--ink);
    padding-inline: 8px;
}

.btn--ghost:hover {
    background: transparent;
    color: var(--brand-text);
}

.btn--light {
    background: var(--white);
    color: var(--band);
}

.btn--light:hover {
    background: var(--brand-soft);
    color: var(--brand-text);
}

.btn--sm {
    padding: 9px 18px;
    font-size: .85rem;
}

.btn--lg {
    padding: 16px 34px;
    font-size: 1rem;
}

.btn--block {
    width: 100%;
}

/* text link that carries an arrow */
.link-arrow {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    font-weight: 600;
    font-size: .92rem;
}

.link-arrow svg {
    width: 16px;
    height: 16px;
    transition: transform var(--t);
}

.link-arrow:hover svg {
    transform: translateX(4px);
}

/* small square icon button (favourite, share, slider arrows) */
.icon-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 42px;
    height: 42px;
    border: 1px solid var(--line);
    border-radius: var(--r-pill);
    background: var(--paper);
    color: var(--ink);
    transition: background var(--t), color var(--t), border-color var(--t);
}

.icon-btn:hover {
    background: var(--brand-fill);
    border-color: var(--brand-fill);
    color: var(--on-brand);
}

.icon-btn svg {
    width: 18px;
    height: 18px;
}

.icon-btn[disabled] {
    opacity: .4;
    cursor: not-allowed;
}


/* =========================================================================
   06. FORMS
   ========================================================================= */
.field {
    display: block;
    margin-bottom: 18px;
}

.field__label {
    display: block;
    margin-bottom: 7px;
    color: var(--ink);
    font-size: .82rem;
    font-weight: 600;
    letter-spacing: .02em;
}

.input,
.select,
.textarea {
    width: 100%;
    padding: 13px 16px;
    border: 1px solid var(--line);
    border-radius: var(--r-sm);
    background: var(--field);
    color: var(--ink);
    font: inherit;
    font-size: .93rem;
    transition: border-color var(--t), box-shadow var(--t);
}

.input::placeholder,
.textarea::placeholder {
    color: var(--muted);
}

.input:focus,
.select:focus,
.textarea:focus {
    border-color: var(--brand);
    box-shadow: 0 0 0 3px rgba(198, 169, 107, .12);
    outline: none;
}

.textarea {
    min-height: 150px;
    resize: vertical;
}

/* native select needs its own caret since appearance is stripped */
.select {
    appearance: none;
    padding-right: 42px;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238E8A80' stroke-width='2'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 14px center;
    background-size: 16px;
    cursor: pointer;
}

/* Several components make the select itself transparent so it can sit
   inside a pill or a filled field. Some browsers then paint the native
   popup transparent as well and the options become unreadable, so they
   get their own colours here — once, for every select in the theme. */
option {
    background-color: var(--paper);
    color: var(--ink);
}

/* The chosen row. Firefox honours the background; chrome ignores it there and
   paints the row itself, so the inset shadow is what actually colours it. */
option:checked {
    background: var(--brand-soft);
    box-shadow: inset 0 0 0 100px var(--brand-soft);
    color: var(--brand-text);
}

option:disabled {
    color: var(--muted);
}

.check {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    margin-bottom: 11px;
    font-size: .9rem;
    cursor: pointer;
}

.check input {
    width: 17px;
    height: 17px;
    margin: 4px 0 0;
    accent-color: var(--brand);
    flex: none;
}

.form-note {
    margin-top: 14px;
    font-size: .82rem;
    color: var(--muted);
}

/* validation feedback rendered by main.js */
.field.is-invalid .input,
.field.is-invalid .select,
.field.is-invalid .textarea {
    border-color: var(--danger);
}

.field__error {
    display: none;
    margin-top: 6px;
    color: var(--danger);
    font-size: .8rem;
}

.field.is-invalid .field__error {
    display: block;
}

.form-alert {
    display: none;
    margin-bottom: 20px;
    padding: 14px 18px;
    border: 1px solid var(--brand-soft);
    border-radius: var(--r-sm);
    background: var(--brand-soft);
    color: var(--brand-text);
    font-size: .9rem;
}

.form-alert.is-visible {
    display: block;
}

/* the same box, handed to an error and given back afterwards */
.form-alert.is-error {
    border-color: var(--danger);
    background: rgba(201, 86, 74, .12);
    color: var(--danger);
}


/* =========================================================================
   07. BADGES & TAGS
   ========================================================================= */
.badge {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 13px;
    border-radius: var(--r-pill);
    background: var(--brand-fill);
    color: var(--on-brand);
    font-size: .72rem;
    font-weight: 600;
    letter-spacing: .06em;
    text-transform: uppercase;
}

.badge--sale     { background: var(--brand-fill); }
.badge--rent     { background: var(--ink); color: var(--band); }
.badge--featured { background: var(--gold); color: var(--on-brand); }
.badge--soft     { background: var(--brand-soft); color: var(--brand-text); }
.badge--off      { background: var(--muted); color: var(--band); }

.tag {
    display: inline-block;
    padding: 5px 13px;
    border: 1px solid var(--line);
    border-radius: var(--r-pill);
    color: var(--muted);
    font-size: .8rem;
}

a.tag:hover {
    border-color: var(--brand-text);
    color: var(--brand-text);
}


/* =========================================================================
   08. HEADER & NAVIGATION
   Repeated verbatim on every page so any file can be opened standalone.
   ========================================================================= */
.topbar {
    background: var(--band);
    color: rgba(255, 255, 255, .7);
    font-size: .82rem;
}

.topbar__inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 24px;
    min-height: 44px;
}

.topbar__list {
    display: flex;
    align-items: center;
    gap: 24px;
}

/* svg is display:block in the reset, so each item lays its own icon out */
.topbar__list li {
    display: inline-flex;
    align-items: center;
}

.topbar a {
    color: rgba(255, 255, 255, .7);
}

.topbar a:hover {
    color: var(--ink);
}

.topbar svg {
    width: 15px;
    height: 15px;
    flex: none;
    margin-right: 7px;
}

.site-header {
    position: sticky;
    top: 0;
    z-index: var(--z-header);
    background: var(--glass);
    backdrop-filter: saturate(180%) blur(12px);
    border-bottom: 1px solid var(--line-soft);
    transition: box-shadow var(--t);
}

/* main.js adds this once the page scrolls past the header */
.site-header.is-stuck {
    box-shadow: var(--shadow-sm);
}

/* --- header 2: sits over the hero -----------------------------------------
   Transparent with white type at the top of the page. The header keeps
   position: sticky, so the moment main.js adds .is-stuck every override drops
   away and it looks exactly like the default header again.
   -------------------------------------------------------------------------- */
.site-header--overlay:not(.is-stuck) {
    background: transparent;
    backdrop-filter: none;
    border-bottom-color: transparent;
}

/* the hero slides up under both bars. Targeted by hero class rather than
   main's first child, because a builder page opens with a <style> tag. */
.site-header--overlay ~ main .hero,
.site-header--overlay ~ main .hero-slider,
.site-header--overlay ~ main .hero-video,
.site-header--overlay ~ main .hero-3 {
    margin-top: calc(-1 * var(--header-h));
}

.site-header--overlay:not(.is-stuck) .brand__name,
.site-header--overlay:not(.is-stuck) .nav__link,
.site-header--overlay:not(.is-stuck) .nav__link.is-active,
.site-header--overlay:not(.is-stuck) .header-phone strong,
.site-header--overlay:not(.is-stuck) .nav-toggle {
    color: var(--white);
}

.site-header--overlay:not(.is-stuck) .header-phone span,
.site-header--overlay:not(.is-stuck) .nav__link:hover {
    color: rgba(255, 255, 255, .78);
}

/* the outline button needs a light edge to read on artwork */
.site-header--overlay:not(.is-stuck) .btn--outline {
    border-color: rgba(255, 255, 255, .55);
    color: var(--white);
}

.site-header--overlay:not(.is-stuck) .btn--outline:hover {
    background: var(--brand-fill);
    border-color: var(--brand-fill);
    color: var(--on-brand);
}

/* a photo can be light anywhere, so lay a soft scrim behind the type */
.site-header--overlay:not(.is-stuck)::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    background: linear-gradient(to bottom, rgba(0, 0, 0, .42), rgba(0, 0, 0, .12));
    pointer-events: none;
}

/* once it sticks the scrim is not wanted - the solid background is back */
.site-header--overlay.is-stuck::before {
    content: none;
}

.site-header__inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 24px;
    min-height: 78px;
}

/* --- brand ------------------------------------------------------------ */
.brand {
    display: inline-flex;
    align-items: center;
    gap: 11px;
    color: var(--ink);
    font-family: var(--font-display);
    font-size: 1.4rem;
    letter-spacing: -.02em;
}

.brand:hover {
    color: var(--ink);
}

.brand__mark {
    width: 38px;
    height: 38px;
    flex: none;
}

.brand__name strong {
    font-weight: 600;
}

/* --- primary nav ------------------------------------------------------ */
.nav {
    display: flex;
    align-items: center;
    gap: 4px;
    margin-inline: auto;
}

.nav__item {
    position: relative;
}

.nav__link {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 10px 15px;
    border-radius: var(--r-sm);
    color: var(--ink-2);
    font-size: .93rem;
    font-weight: 500;
}

.nav__link:hover,
.nav__item.is-open > .nav__link {
    color: var(--brand-text);
}

/* current page marker */
.nav__link.is-active {
    color: var(--ink);
    font-weight: 600;
}

.nav__link.is-active::after {
    content: "";
    position: absolute;
    left: 15px;
    right: 15px;
    bottom: 2px;
    height: 2px;
    background: var(--brand);
    border-radius: 2px;
}

.nav__caret {
    width: 14px;
    height: 14px;
    transition: transform var(--t);
}

.nav__item.is-open .nav__caret {
    transform: rotate(180deg);
}

/* --- dropdown --------------------------------------------------------- */
.dropdown {
    position: absolute;
    top: calc(100% + 10px);
    left: 0;
    min-width: 210px;
    padding: 10px;
    border: 1px solid var(--line);
    border-radius: var(--r);
    background: var(--paper);
    box-shadow: var(--shadow);
    opacity: 0;
    visibility: hidden;
    transform: translateY(8px);
    transition: opacity var(--t), transform var(--t), visibility var(--t);
}

.nav__item.is-open .dropdown {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
}

.dropdown a {
    display: block;
    padding: 9px 14px;
    border-radius: var(--r-sm);
    color: var(--ink-2);
    font-size: .9rem;
}

.dropdown a:hover {
    background: var(--mist);
    color: var(--brand-text);
}

/* --- header actions --------------------------------------------------- */
.header-actions {
    display: flex;
    align-items: center;
    gap: 12px;
}

.header-phone {
    display: flex;
    align-items: center;
    gap: 10px;
}

.header-phone svg {
    width: 20px;
    height: 20px;
    color: var(--brand);
}

.header-phone span {
    display: block;
    font-size: .72rem;
    color: var(--muted);
    line-height: 1.3;
}

.header-phone strong {
    display: block;
    color: var(--ink);
    font-size: .93rem;
}

/* --- mobile toggle + drawer ------------------------------------------- */
.nav-toggle {
    display: none;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    border: 1px solid var(--line);
    border-radius: var(--r-sm);
    background: var(--paper);
}

.nav-toggle svg {
    width: 20px;
    height: 20px;
}

.nav-backdrop {
    position: fixed;
    inset: 0;
    z-index: var(--z-drawer);
    background: rgba(0, 0, 0, .5);
    opacity: 0;
    visibility: hidden;
    transition: opacity var(--t), visibility var(--t);
}

.nav-backdrop.is-open {
    opacity: 1;
    visibility: visible;
}

.mobile-nav {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    z-index: calc(var(--z-drawer) + 1);
    width: min(360px, 86vw);
    padding: 24px;
    background: var(--paper);
    overflow-y: auto;
    transform: translateX(100%);
    transition: transform var(--t);
}

.mobile-nav.is-open {
    transform: translateX(0);
}

.mobile-nav__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding-bottom: 20px;
    margin-bottom: 12px;
    border-bottom: 1px solid var(--line);
}

.mobile-nav a {
    display: block;
    padding: 12px 4px;
    border-bottom: 1px solid var(--line-soft);
    color: var(--ink);
    font-size: 1rem;
    font-weight: 500;
}

.mobile-nav a:hover {
    color: var(--brand-text);
}

.mobile-nav .dropdown-mobile a {
    padding-left: 18px;
    font-size: .92rem;
    font-weight: 400;
    color: var(--muted);
}

/* .mobile-nav a makes every link a list row, which the button is not */
.mobile-nav .btn {
    display: inline-flex;
    margin-top: 22px;
    border-bottom: 0;
}


/* =========================================================================
   09. HERO
   ========================================================================= */
.hero {
    position: relative;
    padding-block: clamp(56px, 7vw, 96px) clamp(40px, 5vw, 64px);
    background: linear-gradient(180deg, var(--mist) 0%, var(--paper) 100%);
    overflow: hidden;
}

.hero__grid {
    display: grid;
    grid-template-columns: 1.05fr 1fr;
    gap: clamp(32px, 5vw, 64px);
    align-items: center;
}

.hero__title {
    margin-bottom: 20px;
}

.hero__text {
    max-width: 46ch;
    margin-bottom: 32px;
    font-size: 1.075rem;
    color: var(--muted);
}

.hero__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 14px;
    align-items: center;
}

/* small proof row under the hero copy */
.hero__proof {
    display: flex;
    flex-wrap: wrap;
    gap: 36px;
    margin-top: 44px;
    padding-top: 30px;
    border-top: 1px solid var(--line);
}

.hero__proof strong {
    display: block;
    font-family: var(--font-display);
    font-size: 1.85rem;
    color: var(--ink);
    line-height: 1.1;
}

.hero__proof span {
    font-size: .85rem;
    color: var(--muted);
}

.hero__media {
    position: relative;
}

.hero__media img {
    width: 100%;
    border-radius: var(--r-lg);
}

/* floating card overlapping the hero image */
.hero__card {
    position: absolute;
    left: -28px;
    bottom: 32px;
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 16px 20px;
    border-radius: var(--r);
    background: var(--paper);
    box-shadow: var(--shadow-lg);
}

.hero__card svg {
    width: 22px;
    height: 22px;
    color: var(--brand);
}

.hero__card strong {
    display: block;
    color: var(--ink);
    font-size: .95rem;
}

.hero__card span {
    font-size: .8rem;
    color: var(--muted);
}

/* compact hero used on inner pages that still want a search bar */
.hero--compact {
    padding-block: clamp(48px, 5vw, 72px);
}


/* =========================================================================
   09b. HERO SLIDER + OVERLAID SEARCH (homepage 2)
   The slides carry no copy — they are imagery only. The search panel is
   the hero content and sits centred over them. Used by index-2.html.
   ========================================================================= */
.hero-slider {
    position: relative;
}

/* 88vh rather than a full 100: the sliver of the next section showing under
   the fold is what tells a reader there is more page. The floor keeps the
   search panel comfortable on a short laptop window, the ceiling stops the
   hero ballooning on a tall monitor. */
.hero-slider__stage {
    position: relative;
    min-height: clamp(640px, 88vh, 900px);
    background: var(--band);
    overflow: hidden;
}

/* slides stack on top of each other and cross-fade. overflow lives here
   rather than on the stage so the push-in stays contained without the
   stage clipping anything that has to escape it, like a filter panel */
.hero-slide {
    position: absolute;
    inset: 0;
    overflow: hidden;
    opacity: 0;
    visibility: hidden;
    transition: opacity .9s ease, visibility .9s ease;
}

.hero-slide.is-active {
    opacity: 1;
    visibility: visible;
}

.hero-slide__media {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* slow push-in while a slide is on screen */
.hero-slide.is-active .hero-slide__media {
    animation: hero-zoom 10s ease-out forwards;
}

@keyframes hero-zoom {

    from { transform: scale(1); }
    to   { transform: scale(1.07); }
}

/* even wash — the panel sits centred, so no side is favoured */
.hero-slide::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(180deg, rgba(0, 0, 0, .58) 0%, rgba(0, 0, 0, .38) 42%, rgba(0, 0, 0, .68) 100%);
}

/* transparent layer so clicks fall through to the arrows behind it */
.hero-slider__overlay {
    position: absolute;
    inset: 0;
    z-index: 5;
    display: flex;
    align-items: center;
    justify-content: center;

    /* the block is centred, so the bottom padding is what lifts it: the
       88px over the top figure sits it 44px above dead centre */
    padding: 48px var(--gutter) 208px;
    pointer-events: none;
}

.hero-slider__overlay > * {
    width: 100%;
    pointer-events: auto;
}

/* --- hero: video ------------------------------------------------------ */

/* borrows .hero-slider__stage for its height and .hero-slider__overlay for
   the panel, so the two heroes stay the same size wherever they are swapped */
.hero-video {
    position: relative;
}

.hero-video__frame {
    position: absolute;
    inset: 0;
    overflow: hidden;
}

/* shown until the frame paints, and on its own when no link is set */
.hero-video__poster {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* youtube only ever gives back 16:9, so the frame is oversized on whichever
   axis is short and centred — the overflow is clipped by the frame */
.hero-video__player {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 100vw;
    height: 56.25vw;
    min-width: 177.78vh;
    min-height: 100%;
    border: 0;
    pointer-events: none;
}

/* On a phone the poster is the hero. Block 33 already withholds the url at
   this width, so this only matters when a desktop window is dragged narrow
   after the player has loaded. */
@media (max-width: 900px) {

    .hero-video__player {
        display: none;
    }
}

/* the same wash a slide carries, scaled by the level picked on the widget.
   the number on the widget is the top stop, 0-100; the other two hold
   their relative weight so the gradient keeps its shape */
.hero-video__frame::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(180deg,
        rgba(0, 0, 0, calc(var(--scrim, 55) * 1%)) 0%,
        rgba(0, 0, 0, calc(var(--scrim, 55) * .66%)) 42%,
        rgba(0, 0, 0, calc(var(--scrim, 55) * 1.17%)) 100%);
}

/* --- arrows + dots ---------------------------------------------------- */
.hero-slider__controls {
    position: absolute;
    z-index: 6;
    left: 50%;
    bottom: 34px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    width: min(100%, var(--container));
    padding-inline: var(--gutter);
    transform: translateX(-50%);
}

.hero-slider__dots {
    display: flex;
    gap: 8px;
}

.hero-slider__dot {
    width: 28px;
    height: 4px;
    padding: 0;
    border: 0;
    border-radius: var(--r-pill);
    background: rgba(255, 255, 255, .35);
    transition: width var(--t), background var(--t);
}

.hero-slider__dot:hover {
    background: rgba(255, 255, 255, .6);
}

.hero-slider__dot.is-active {
    width: 46px;
    background: var(--brand);
}

.hero-slider__arrows {
    display: flex;
    gap: 10px;
}

.hero-slider__arrow {
    background: rgba(255, 255, 255, .14);
    border-color: rgba(255, 255, 255, .32);
    color: var(--white);
}

.hero-slider__arrow:hover {
    background: var(--brand-fill);
    border-color: var(--brand-fill);
    color: var(--on-brand);
}


/* =========================================================================
   09c. HERO SEARCH
   The larger search panel used on homepage 2, with a collapsible
   second tier of filters.
   ========================================================================= */
.hero-search {
    width: min(100%, 1040px);
    margin-inline: auto;
    padding: 16px;
    border-radius: var(--r-lg);
    background: var(--glass-solid);
    box-shadow: var(--shadow-lg);
}

.hero-search__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    padding: 2px 6px 14px;
}

.hero-search__count {
    color: var(--muted);
    font-size: .84rem;
}

.hero-search__count strong {
    color: var(--ink);
}

/* --- segmented sale / rent switch ------------------------------------- */
/* scoped so it outranks the base .search-tabs rule defined further down */
.hero-search .search-tabs--segmented {
    gap: 4px;
    padding: 4px;
    border: 1px solid var(--line);
    border-radius: var(--r-pill);
    background: var(--mist);
}

.search-tabs--segmented .search-tabs__btn {
    padding: 8px 22px;
    border-radius: var(--r-pill);
}

.search-tabs--segmented .search-tabs__btn.is-active {
    background: var(--brand-fill);
    color: var(--on-brand);
}

/* --- primary field row ------------------------------------------------ */
.hero-search__row {
    display: grid;
    grid-template-columns: 1.6fr 1fr 1fr 1.15fr auto;
    gap: 8px;
    align-items: stretch;
}

.hero-search .field {
    display: flex;
    align-items: center;
    gap: 11px;
    margin: 0;
    padding: 11px 16px;
    border: 1px solid transparent;
    border-radius: var(--r);
    background: var(--mist);
    transition: border-color var(--t), background var(--t);
}

.hero-search .field:focus-within {
    border-color: var(--brand);
    background: var(--field-hi);
}

.hero-search .field > svg {
    width: 18px;
    height: 18px;
    flex: none;
    color: var(--brand);
}

.hero-search .field__body {
    flex: 1;
    min-width: 0;
}

.hero-search .field__label {
    margin-bottom: 1px;
    color: var(--muted);
    font-size: .69rem;
    letter-spacing: .12em;
    text-transform: uppercase;
}

.hero-search .input,
.hero-search .select {
    padding: 0;
    border: 0;
    background-color: transparent;
    font-size: .94rem;
    font-weight: 500;
}

.hero-search .input:focus,
.hero-search .select:focus {
    box-shadow: none;
}

.hero-search .select {
    padding-right: 22px;
    background-position: right 0 center;
}

.hero-search__submit {
    align-self: stretch;
    padding-inline: 34px;
}

/* --- collapsible second tier ------------------------------------------ */
.hero-search__more {
    max-height: 0;
    overflow: hidden;
    transition: max-height var(--t);
}

.hero-search.is-expanded .hero-search__more {
    max-height: 420px;
}

.hero-search__more-inner {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 24px;
    padding-top: 20px;
    margin-top: 16px;
    border-top: 1px solid var(--line-soft);
}

.hero-search__group-title {
    margin-bottom: 10px;
    color: var(--ink);
    font-family: var(--font-body);
    font-size: .72rem;
    font-weight: 600;
    letter-spacing: .12em;
    text-transform: uppercase;
}

/* the second tier reuses the plain bordered inputs, not the filled ones */
.hero-search__more .field {
    display: block;
    padding: 0;
    border: 0;
    background: transparent;
}

.hero-search__more .input {
    padding: 11px 14px;
    border: 1px solid var(--line);
    border-radius: var(--r-sm);
    background: var(--field);
    font-weight: 400;
}

.hero-search__more .check {
    margin-bottom: 8px;
    font-size: .86rem;
}

/* --- panel foot ------------------------------------------------------- */
.hero-search__foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    padding: 14px 6px 2px;
}

.hero-search__toggle {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--brand-text);
    font-size: .88rem;
    font-weight: 600;
}

.hero-search__toggle:hover {
    color: var(--ink);
}

.hero-search__toggle svg {
    width: 15px;
    height: 15px;
    transition: transform var(--t);
}

.hero-search.is-expanded .hero-search__toggle svg {
    transform: rotate(180deg);
}

.hero-search__reset {
    color: var(--muted);
    font-size: .86rem;
}

.hero-search__reset:hover {
    color: var(--ink);
}


/* =========================================================================
   10. SEARCH PANEL
   ========================================================================= */
/* only when the panel is a component in its own right — nested inside
   .search-stack or the split hero it should fill its parent */
.search-panel--standalone {
    width: min(100%, 980px);
    margin-inline: auto;
}

.search-panel {
    position: relative;
    z-index: 2;
    margin-top: clamp(32px, 4vw, 56px);
    padding: 10px;
    border: 1px solid var(--line);
    border-radius: var(--r-lg);
    background: var(--paper);
    box-shadow: var(--shadow);
}

/* pill tabs above the fields */
.search-tabs {
    display: flex;
    gap: 6px;
    padding: 0 6px 10px;
}

.search-tabs__btn {
    padding: 8px 18px;
    border: 0;
    border-radius: var(--r-pill);
    background: transparent;
    color: var(--muted);
    font-size: .88rem;
    font-weight: 600;
    transition: background var(--t), color var(--t);
}

.search-tabs__btn:hover {
    color: var(--ink);
}

.search-tabs__btn.is-active {
    background: var(--brand-soft);
    color: var(--brand-text);
}

.search-form {
    display: grid;
    grid-template-columns: 1.4fr 1fr 1fr 1fr auto;
    gap: 8px;
    align-items: end;
}

/* three fields instead of four, for the stacked form that carries the
   advanced panel underneath */
.search-form--3 {
    grid-template-columns: 1.4fr 1fr 1fr auto;
}

.search-form .field {
    margin: 0;
    padding: 8px 14px;
    border-radius: var(--r);
}

/* the location picker brings its own pill; inside a search field the frame
   is already drawn, so it gives it up and reads like the selects beside it */
.search-form .field--divisions .divisions__control {
    min-height: 0;
    padding: 0;
    border: 0;
    border-radius: 0;
    background: none;
}

.search-form .field--divisions .divisions__control:focus-within {
    box-shadow: none;
}

.search-form .field--divisions .divisions__menu {
    left: -14px;
    width: min(360px, calc(100% + 28px));
}

/* thin divider between search fields instead of boxed inputs */
.search-form .field + .field {
    box-shadow: inset 1px 0 0 var(--line-soft);
}

.search-form .field__label {
    margin-bottom: 2px;
    font-size: .72rem;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--muted);
}

.search-form .input,
.search-form .select {
    padding: 2px 0;
    border: 0;
    font-weight: 500;
    background-color: transparent;
}

.search-form .select {
    padding-right: 24px;
    background-position: right 0 center;
}

.search-form .input:focus,
.search-form .select:focus {
    box-shadow: none;
}

.search-form__submit {
    padding: 0 8px 0 0;
}


/* =========================================================================
   10b. SEARCH BAR — minimal
   A single pill. No visible labels, no field boxes: just hairline dividers
   and one circular action. Sits well over imagery or on a plain section.
   ========================================================================= */
.search-bar {
    display: flex;
    align-items: center;
    width: min(100%, 780px);
    padding: 6px 6px 6px 10px;
    border: 1px solid var(--line);
    border-radius: var(--r-pill);
    background: var(--paper);
    transition: border-color var(--t), box-shadow var(--t);
}

.search-bar:focus-within {
    border-color: var(--brand);
    box-shadow: 0 0 0 4px rgba(198, 169, 107, .14);
}

.search-bar__field {
    display: flex;
    align-items: center;
    gap: 9px;
    flex: 1;
    min-width: 0;
    padding: 10px 18px;
}

/* hairline between segments, drawn with a shadow so it needs no extra element */
.search-bar__field + .search-bar__field {
    box-shadow: inset 1px 0 0 var(--line);
}

.search-bar__field > svg {
    width: 17px;
    height: 17px;
    flex: none;
    color: var(--brand-text);
}

.search-bar__input,
.search-bar__select {
    width: 100%;
    padding: 0;
    border: 0;
    background-color: transparent;
    color: var(--ink);
    font: inherit;
    font-size: .93rem;
}

.search-bar__input::placeholder {
    color: var(--muted);
}

.search-bar__input:focus,
.search-bar__select:focus {
    outline: none;
}

.search-bar__select {
    appearance: none;
    padding-right: 20px;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238E8A80' stroke-width='2'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 0 center;
    background-size: 14px;
    cursor: pointer;
}

/* --- segments that open a panel ----------------------------------------
   The town and type lists are too long, and the price is a range, so those
   segments drop the native select for the .map-drop panel used on the map
   bar. The trigger is styled to read exactly like the fields beside it.
   ------------------------------------------------------------------------ */
.search-bar__trigger {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    width: 100%;
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--ink);
    font: inherit;
    font-size: .93rem;
    text-align: left;
}

/* until something is chosen it reads as a placeholder, like the input beside it */
.search-bar__field:not(.is-set) .search-bar__trigger {
    color: var(--muted);
}

.search-bar__trigger svg {
    width: 14px;
    height: 14px;
    flex: none;
    color: var(--muted);
    transition: transform var(--t);
}

.search-bar__field.is-open .search-bar__trigger svg {
    transform: rotate(180deg);
}

/* clear the pill's own padding so the panel hangs off the bar, not the text */
.search-bar__field > .map-drop {
    top: calc(100% + 20px);
    left: -18px;
}

.search-bar__submit {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 9px;
    width: 46px;
    height: 46px;
    flex: none;
    padding: 0;
    border: 0;
    border-radius: var(--r-pill);
    background: var(--brand-fill);
    color: var(--on-brand);
    transition: background var(--t);
}

/* icon-only while the bar is a pill; the words appear once the buttons
   stretch to full width and an icon alone stops being self-explanatory */
.search-bar__btn-label {
    display: none;
}

.search-bar__submit:hover {
    background: var(--brand-hover);
}

.search-bar__submit svg {
    width: 18px;
    height: 18px;
}

/* centred variant, for a hero or an empty state */
.search-bar--center {
    margin-inline: auto;
}

/* --- advanced filters ------------------------------------------------- */

/* wrapper so the hidden panel can anchor to the pill */
/* the tabs and the pill are one component, so they need one box around them —
   a hero overlay is a flex row and would otherwise stand them side by side */
.search-minimal-wrap {
    width: min(100%, 780px);
    margin-inline: auto;
}

.search-minimal {
    position: relative;
    width: min(100%, 780px);
}

.search-minimal--center {
    margin-inline: auto;
}

.search-minimal .search-bar {
    width: 100%;
}

.search-bar__filters {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 42px;
    height: 42px;
    flex: none;
    margin-right: 4px;
    padding: 0;
    border: 0;
    border-radius: var(--r-pill);
    background: transparent;
    color: var(--ink-2);
    transition: background var(--t), color var(--t);
}

.search-bar__filters:hover {
    background: var(--mist);
    color: var(--ink);
}

.search-minimal.is-open .search-bar__filters {
    background: var(--brand-soft);
    color: var(--brand-text);
}

.search-bar__filters svg {
    width: 18px;
    height: 18px;
}

/* the panel floats rather than pushing the page around */
.search-bar__more {
    position: absolute;
    top: calc(100% + 10px);
    left: 0;
    right: 0;
    z-index: 20;
    padding: 24px;
    border: 1px solid var(--line);
    border-radius: var(--r-lg);
    background: var(--paper);
    box-shadow: var(--shadow-lg);
    text-align: left;
    opacity: 0;
    visibility: hidden;
    transform: translateY(-6px);
    transition: opacity var(--t), visibility var(--t), transform var(--t);
}

/* [data-search-minimal] is what block 18 puts .is-open on, so keying off it
   means any form that opts into the behaviour reveals its panel — the two
   class selectors below it are kept for markup that predates the attribute */
[data-search-minimal].is-open .search-bar__more,
.search-minimal.is-open .search-bar__more,
.search-form.is-open .search-bar__more {
    opacity: 1;
    visibility: visible;
    transform: none;
}

/* The stacked form wraps this panel, so .search-form's own field treatment
   reaches in: no borders on inputs, padding on every .field, a divider line
   between adjacent ones. None of that belongs here — these are plain boxed
   inputs. Declared unprefixed so both search forms match. */
.search-bar__more .field {
    padding: 0;
}

/* matching .search-form .field + .field class for class, or it keeps winning */
.search-bar__more .field + .field {
    box-shadow: none;
}

.search-bar__more .input {
    padding: 9px 12px;
    border: 1px solid var(--line);
    background: var(--field);
    font-size: .9rem;

    /* the page line-height of 1.7 makes a one-line input needlessly tall */
    line-height: 1.3;
}

/* Inside a filter panel the select sits in a row of boxed inputs, so it has
   to be boxed too — a bare word with a caret reads as a label, not as
   something you can open. Matches .search-bar__more .input above. */
.search-bar__more .select-menu__toggle {
    padding: 9px 12px;
    border: 1px solid var(--line);
    border-radius: var(--r-sm);
    background: var(--field);
    font-size: .9rem;
    font-weight: 500;
    line-height: 1.3;
    transition: border-color var(--t), background var(--t);
}

.search-bar__more .select-menu__toggle:hover,
.search-bar__more .select-menu.is-open .select-menu__toggle {
    border-color: var(--brand);
    background: var(--field-hi);
}

/* the list overhangs a bare toggle; against a boxed one it lines up */
.search-bar__more .select-menu__list {
    left: 0;
    right: 0;
}

.search-bar__more .input:focus {
    border-color: var(--brand);
    box-shadow: 0 0 0 3px rgba(198, 169, 107, .18);
}

/* only earns its place where the panel becomes a sheet; the media query
   below turns it on */
.search-bar__more-close {
    display: none;
    position: absolute;
    top: 12px;
    right: 12px;
    z-index: 1;
}

.search-bar__more-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 24px;
}

.search-bar__more-foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    margin-top: 22px;
    padding-top: 18px;
    border-top: 1px solid var(--line-soft);
}

.search-bar__reset {
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--muted);
    font-size: .86rem;
}

.search-bar__reset:hover {
    color: var(--ink);
}


/* =========================================================================
   10c. SEARCH STACK
   Section 10's bar with the sale / rent switch lifted out of the panel and
   centred above it. The panel and form markup are unchanged.
   ========================================================================= */
/* caps and centres itself the way .hero-search does — a hero overlay stretches
   its children to full width, so a component that does not size itself bleeds
   to the edges of the page */
.search-stack {
    width: min(100%, 980px);
    margin-inline: auto;
}

/* a bordered pill group, centred over the bar */
.search-stack__tabs {
    display: flex;
    justify-content: center;
    gap: 4px;
    width: fit-content;
    margin: 0 auto 16px;
    padding: 4px;
    border: 1px solid var(--line);
    border-radius: var(--r-pill);
    background: var(--paper);
}

.search-stack__tabs .search-tabs__btn {
    padding: 9px 26px;
    border-radius: var(--r-pill);
}

.search-stack__tabs .search-tabs__btn.is-active {
    background: var(--brand-fill);
    color: var(--on-brand);
}

/* the switch supplies the spacing above, so the panel drops its own */
.search-stack .search-panel {
    margin-top: 0;
}


/* =========================================================================
   11. SECTION HEAD
   ========================================================================= */
.section-head {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 32px;
    margin-bottom: clamp(32px, 4vw, 52px);
}

.section-head__title {
    max-width: 34ch;
    margin-bottom: 0;
}

.section-head__text {
    max-width: 52ch;
    margin-top: 14px;
    color: var(--muted);
}

.section-head--center {
    flex-direction: column;
    align-items: center;
    text-align: center;
}

.section-head--center .section-head__title,
.section-head--center .section-head__text {
    max-width: 56ch;
}


/* =========================================================================
   12. PROPERTY CARD
   ========================================================================= */
/* position:relative so the title link can stretch over the whole card */
.property-card {
    position: relative;
    display: flex;
    flex-direction: column;
    border: 1px solid var(--line);
    border-radius: var(--r);
    background: var(--paper);
    overflow: hidden;
    transition: border-color var(--t), box-shadow var(--t), transform var(--t);
}

.property-card:hover {
    border-color: transparent;
    box-shadow: var(--shadow);
    transform: translateY(-3px);
}

.property-card__media {
    position: relative;
    aspect-ratio: 3 / 2;
    overflow: hidden;
    background: var(--mist);
}

.property-card__media img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform .5s ease;
}

.property-card:hover .property-card__media img {
    transform: scale(1.04);
}

.property-card__badges {
    position: absolute;
    top: 14px;
    left: 14px;
    display: flex;
    gap: 8px;
}

/* z-index keeps it above the stretched title link */
.property-card__fav {
    position: absolute;
    top: 12px;
    right: 12px;
    z-index: 2;
    width: 38px;
    height: 38px;
    border: 0;
    background: var(--glass);
}

/* toggled by main.js */
.property-card__fav.is-active {
    background: var(--brand-fill);
    color: var(--on-brand);
}

.property-card__body {
    display: flex;
    flex-direction: column;
    flex: 1;
    padding: 22px;
}

.property-card__price {
    display: flex;
    align-items: baseline;
    gap: 5px;
    margin-bottom: 8px;
    color: var(--brand-text);
    font-family: var(--font-display);
    font-size: 1.4rem;
    font-weight: 600;
}

.property-card__price small {
    color: var(--muted);
    font-family: var(--font-body);
    font-size: .8rem;
    font-weight: 400;
}

/* the address belongs to the title, so it sits tight under it — same pairing
   as the category card's heading and its count */
.property-card__title {
    margin-bottom: 2px;
    font-size: 1.15rem;
}

.property-card__title a {
    color: var(--ink);
}

.property-card__title a:hover {
    color: var(--brand-text);
}

/* The title link covers the whole card, so the image, price and address are
   all clickable without a second anchor and a second tab stop. Anything that
   must stay clickable on top of it carries z-index 2. */
.property-card__title a::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 1;
}

.property-card__address {
    display: flex;
    align-items: center;
    gap: 7px;
    margin-bottom: 18px;
    color: var(--muted);
    font-size: .87rem;
}

.property-card__address svg {
    width: 15px;
    height: 15px;
    flex: none;
    color: var(--brand);
}

/* beds / baths / area strip */
.property-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 18px;
    margin-top: auto;
    padding-top: 16px;
    border-top: 1px solid var(--line);
}

.property-meta li {
    display: flex;
    align-items: center;
    gap: 7px;
    color: var(--ink-2);
    font-size: .85rem;
}

.property-meta svg {
    width: 17px;
    height: 17px;
    color: var(--muted);
}

/* horizontal variant used by the list view on the listings page */
.property-card--row {
    flex-direction: row;
}

/* aspect-ratio is dropped so the photo matches however tall the body runs.
   The gallery variant has nothing in flow to fall back on though - its
   carousel is absolutely positioned - so without a floor its photo collapses
   to the height of the price and the title. */
.property-card--row .property-card__media {
    flex: 0 0 40%;
    aspect-ratio: auto;
    min-height: 210px;
}

.property-card--row .property-card__body {
    padding: 26px;
}


/* =========================================================================
   12b. PROPERTY CARD — GALLERY VARIANT
   .property-card--gallery swaps the single photo for an in-card carousel:
   dots, a photo count, arrows on hover and swipe on touch.
   ========================================================================= */
.card-slider {
    position: absolute;
    inset: 0;
}

/* the slides cross-fade in place, so nothing is set from JS but a class */
.card-slider__slide {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    opacity: 0;
    visibility: hidden;
    transition: opacity .4s ease, visibility .4s ease;
}

.card-slider__slide.is-active {
    opacity: 1;
    visibility: visible;
}

/* the card-wide hover zoom would fight the carousel */
.property-card--gallery:hover .property-card__media img {
    transform: none;
}

/* --- arrows ----------------------------------------------------------- */
.card-slider__arrow {
    position: absolute;
    top: 50%;
    z-index: 2;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    padding: 0;
    border: 0;
    border-radius: var(--r-pill);
    background: var(--glass);
    color: var(--ink);
    opacity: 0;
    transform: translateY(-50%);
    transition: opacity var(--t), background var(--t);
}

.card-slider__arrow:hover {
    background: var(--brand-fill);
    color: var(--on-brand);
}

.card-slider__arrow svg {
    width: 15px;
    height: 15px;
}

.card-slider__arrow--prev { left: 10px; }
.card-slider__arrow--next { right: 10px; }

.property-card:hover .card-slider__arrow,
.card-slider__arrow:focus-visible {
    opacity: 1;
}

/* nothing hovers on a touch screen, so the arrows stay put */
@media (hover: none) {

    .card-slider__arrow {
        opacity: 1;
    }
}

/* --- dots ------------------------------------------------------------- */
.card-slider__dots {
    position: absolute;
    left: 50%;
    bottom: 12px;
    z-index: 2;
    display: flex;
    gap: 5px;
    transform: translateX(-50%);
}

.card-slider__dot {
    width: 6px;
    height: 6px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: rgba(255, 255, 255, .6);
    transition: width var(--t), background var(--t);
}

.card-slider__dot.is-active {
    width: 16px;
    border-radius: var(--r-pill);
    background: var(--brand);
}

/* --- photo count ------------------------------------------------------ */
.card-slider__count {
    position: absolute;
    right: 12px;
    bottom: 10px;
    z-index: 2;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 10px;
    border-radius: var(--r-sm);
    background: rgba(0, 0, 0, .62);
    color: var(--white);
    font-size: .75rem;
    font-weight: 600;
}

.card-slider__count svg {
    width: 13px;
    height: 13px;
}

/* a single photo needs no controls */
.card-slider--solo .card-slider__dots,
.card-slider--solo .card-slider__arrow {
    display: none;
}

/* --- body ------------------------------------------------------------- */

/* the price leads in ink here and the type line carries the brand colour */


.property-card__type {
    margin-bottom: 16px;
    color: var(--brand-text);
    font-size: .88rem;
    font-weight: 500;
}

/* =========================================================================
   12c. PROPERTY RAIL
   A row of cards that scrolls sideways a page at a time. Arrows sit in the
   section head, dots underneath. Dots are built by main.js because how many
   pages there are depends on the viewport.
   ========================================================================= */
.card-rail {
    position: relative;
}

.card-rail__nav {
    display: flex;
    gap: 10px;
}

.card-rail__track {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: calc((100% - 84px) / 4);
    gap: 28px;
    /* room for the card lift and its shadow, which would otherwise clip */
    padding: 8px 0 28px;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scroll-behavior: smooth;
    scrollbar-width: none;
    -ms-overflow-style: none;
}

.card-rail__track::-webkit-scrollbar {
    display: none;
}

.card-rail__track > * {
    scroll-snap-align: start;
}

/* --- page dots -------------------------------------------------------- */
.card-rail__dots {
    display: flex;
    justify-content: center;
    gap: 8px;
}

.card-rail__dots:empty {
    display: none;
}

.card-rail__dot {
    width: 8px;
    height: 8px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: var(--line);
    transition: width var(--t), background var(--t);
}

.card-rail__dot:hover {
    background: var(--muted);
}

.card-rail__dot.is-active {
    width: 22px;
    border-radius: var(--r-pill);
    background: var(--brand-fill);
}


/* =========================================================================
   13. FEATURE BLOCKS
   ========================================================================= */
.feature {
    padding: 30px;
    border: 1px solid var(--line);
    border-radius: var(--r);
    background: var(--paper);
    transition: border-color var(--t), box-shadow var(--t);
}

.feature:hover {
    border-color: transparent;
    box-shadow: var(--shadow);
}

.feature__icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 54px;
    height: 54px;
    margin-bottom: 20px;
    border-radius: var(--r);
    background: var(--brand-soft);
    color: var(--brand-text);
}

.feature__icon svg {
    width: 24px;
    height: 24px;
}

.feature__title {
    margin-bottom: 8px;
    font-size: 1.15rem;
}

.feature p {
    color: var(--muted);
    font-size: .93rem;
}

/* category tile (apartments, villas, …) */
.category {
    position: relative;
    display: flex;
    align-items: flex-end;
    min-height: 240px;
    padding: 24px;
    border-radius: var(--r);
    background: var(--mist);
    overflow: hidden;
}

.category img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform .5s ease;
}

.category:hover img {
    transform: scale(1.05);
}

.category__body {
    position: relative;
    width: 100%;
    padding: 16px 18px;
    border-radius: var(--r-sm);
    background: var(--glass);
}

.category__body h3 {
    margin-bottom: 2px;
    font-size: 1.1rem;
}

.category__body span {
    color: var(--muted);
    font-size: .84rem;
}


/* =========================================================================
   14. STEPS
   ========================================================================= */
.steps {
    counter-reset: step;
}

.step {
    position: relative;
    padding-top: 28px;
    border-top: 2px solid var(--line);
}

.step::before {
    counter-increment: step;
    content: "0" counter(step);
    display: block;
    margin-bottom: 14px;
    color: var(--brand-text);
    font-family: var(--font-display);
    font-size: 1.5rem;
}

/* the active step keeps the accent rule */
.step:first-child {
    border-top-color: var(--brand);
}

.step h3 {
    margin-bottom: 8px;
    font-size: 1.2rem;
}

.step p {
    color: var(--muted);
    font-size: .93rem;
}


/* =========================================================================
   15. STATS
   ========================================================================= */
.stat {
    text-align: center;
}

.stat__value {
    display: block;
    color: var(--ink);
    font-family: var(--font-display);
    font-size: clamp(2.1rem, 4vw, 3rem);
    line-height: 1.1;
}

.section:not(.section--ink) .stat__value {
    color: var(--ink);
}

.stat__label {
    display: block;
    margin-top: 6px;
    font-size: .88rem;
    letter-spacing: .04em;
}


/* =========================================================================
   16. AGENTS
   ========================================================================= */
.agent-card {
    border: 1px solid var(--line);
    border-radius: var(--r);
    background: var(--paper);
    overflow: hidden;
    text-align: center;
    transition: border-color var(--t), box-shadow var(--t), transform var(--t);
}

.agent-card:hover {
    border-color: transparent;
    box-shadow: var(--shadow);
    transform: translateY(-3px);
}

/* it is an <a>, so it needs display:block before aspect-ratio means anything.
   4/5 rather than square: portraits crop badly at 1:1 */
.agent-card__media {
    display: block;
    aspect-ratio: 4 / 5;
    background: var(--mist);
    overflow: hidden;
}

.agent-card__media img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform .5s ease;
}

.agent-card:hover .agent-card__media img {
    transform: scale(1.05);
}

.agent-card__body {
    padding: 24px 20px;
}

.agent-card__name {
    margin-bottom: 4px;
    font-size: 1.2rem;
    line-height: 1.2;
}

.agent-card__name a {
    color: inherit;
    text-decoration: none;
}

.agent-card__name a:hover {
    color: var(--brand-text);
}

.agent-card__role {
    display: block;
    color: var(--brand-text);
    font-size: .74rem;
    font-weight: 600;
    letter-spacing: .12em;
    text-transform: uppercase;
}

.agent-card__note {
    margin: 10px 0 0;
    color: var(--muted);
    font-size: .88rem;
}

/* hairline between who they are and how to reach them */
.agent-card .socials {
    margin-top: 18px;
    padding-top: 18px;
    border-top: 1px solid var(--line-soft);
}

/* softer at rest than the footer's, filled on hover like the contact tiles */
.agent-card .socials a {
    width: 34px;
    height: 34px;
    border-color: transparent;
    background: var(--brand-soft);
    color: var(--brand-text);
}

.agent-card .socials a:hover {
    background: var(--brand-fill);
    color: var(--on-brand);
}

.socials {
    display: flex;
    justify-content: center;
    gap: 8px;
}

.socials a {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    border: 1px solid var(--line);
    border-radius: var(--r-pill);
    color: var(--muted);
    transition: background var(--t), color var(--t), border-color var(--t);
}

.socials a:hover {
    background: var(--brand-fill);
    border-color: var(--brand-fill);
    color: var(--on-brand);
}

.socials svg {
    width: 16px;
    height: 16px;
}


/* =========================================================================
   16b. AGENT PROFILE
   The header block on the single-agent page. Used by agent.html.
   ========================================================================= */
.agent-profile {
    display: grid;
    grid-template-columns: 280px 1fr;
    gap: clamp(28px, 4vw, 48px);
    align-items: center;
}

.agent-profile__media {
    aspect-ratio: 1 / 1;
    border-radius: var(--r-lg);
    background: var(--paper);
    overflow: hidden;
}

.agent-profile__media img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.agent-profile__role {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 12px;
    color: var(--brand-text);
    font-size: .8rem;
    font-weight: 600;
    letter-spacing: .14em;
    text-transform: uppercase;
}

.agent-profile__name {
    margin-bottom: 14px;
}

.agent-profile__bio {
    max-width: 62ch;
    margin-bottom: 24px;
    color: var(--muted);
}

.agent-profile__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
}

/* licence, languages, patch — the facts that qualify an agent */
.agent-profile__meta {
    display: flex;
    flex-wrap: wrap;
    gap: 12px 28px;
    padding-top: 22px;
    margin-top: 24px;
    border-top: 1px solid var(--line);
}

.agent-profile__meta li {
    display: flex;
    align-items: center;
    gap: 9px;
    color: var(--ink-2);
    font-size: .9rem;
}

.agent-profile__meta svg {
    width: 17px;
    height: 17px;
    flex: none;
    color: var(--brand-text);
}


/* =========================================================================
   17. TESTIMONIALS
   ========================================================================= */
.quote {
    padding: 32px;
    border: 1px solid var(--line);
    border-radius: var(--r);
    background: var(--paper);
}

.quote__mark {
    width: 34px;
    height: 34px;
    margin-bottom: 18px;
    color: var(--brand-soft);
}

/* the browser default is margin: 1em 40px, which eats most of a card this
   narrow and wraps the quote to a few words a line */
.quote blockquote {
    margin: 0;
}

.quote p {
    margin-bottom: 24px;
    color: var(--ink-2);
    font-size: 1rem;
}

.quote__author {
    display: flex;
    align-items: center;
    gap: 13px;
    padding-top: 20px;
    border-top: 1px solid var(--line-soft);
}

.quote__author img {
    width: 46px;
    height: 46px;
    border-radius: var(--r-pill);
    object-fit: cover;
}

.quote__author strong {
    display: block;
    color: var(--ink);
    font-size: .95rem;
}

.quote__author span {
    color: var(--muted);
    font-size: .82rem;
}

.rating {
    display: flex;
    gap: 3px;
    margin-bottom: 14px;
    color: var(--gold);
}

.rating svg {
    width: 16px;
    height: 16px;
}


/* =========================================================================
   18. PARTNERS
   ========================================================================= */
.partners {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 32px;
}

.partners span {
    color: var(--muted);
    font-family: var(--font-display);
    font-size: 1.35rem;
    letter-spacing: .02em;
    opacity: .65;
    transition: opacity var(--t);
}

.partners span:hover {
    opacity: 1;
}


/* =========================================================================
   19. CTA BAND
   ========================================================================= */
.cta {
    display: grid;
    grid-template-columns: 1.4fr auto;
    gap: 40px;
    align-items: center;
    padding: clamp(36px, 5vw, 64px);
    border-radius: var(--r-lg);
    background: var(--band);
    color: rgba(255, 255, 255, .75);
}

.cta h2 {
    max-width: 22ch;
    margin-bottom: 12px;
    color: var(--ink);
}

.cta p {
    max-width: 48ch;
}

.cta__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
}


/* =========================================================================
   20. BLOG CARD
   ========================================================================= */
.post-card {
    display: flex;
    flex-direction: column;
    height: 100%;
}

.post-card__media {
    aspect-ratio: 3 / 2;
    margin-bottom: 20px;
    border-radius: var(--r);
    background: var(--mist);
    overflow: hidden;
}

.post-card__media img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform .5s ease;
}

.post-card:hover .post-card__media img {
    transform: scale(1.04);
}

.post-card__meta {
    display: flex;
    flex-wrap: wrap;
    gap: 14px;
    margin-bottom: 10px;
    color: var(--muted);
    font-size: .8rem;
    letter-spacing: .04em;
    text-transform: uppercase;
}

.post-card__title {
    margin-bottom: 10px;
    font-size: 1.25rem;
}

.post-card__title a {
    color: var(--ink);
}

.post-card__title a:hover {
    color: var(--brand-text);
}

.post-card p {
    margin-bottom: 16px;
    color: var(--muted);
    font-size: .93rem;
}

.post-card .link-arrow {
    margin-top: auto;
}


/* =========================================================================
   21. NEWSLETTER
   ========================================================================= */
.newsletter {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 40px;
    align-items: center;
}

.newsletter__form {
    display: flex;
    gap: 10px;
}

.newsletter__form .input {
    flex: 1;
    border-radius: var(--r-pill);
    padding-inline: 22px;
}


/* =========================================================================
   22. FOOTER
   ========================================================================= */
.site-footer {
    padding-top: clamp(56px, 6vw, 88px);
    background: var(--band);
    color: rgba(255, 255, 255, .65);
    font-size: .92rem;
}

.site-footer .brand,
.site-footer .brand:hover {
    color: var(--ink);
}

/* headings sit on the dark band, so they invert */
.site-footer h1,
.site-footer h2,
.site-footer h3,
.site-footer h4 {
    color: var(--ink);
}

.site-footer hr {
    border-top-color: rgba(255, 255, 255, .1);
}

.footer-grid {
    display: grid;
    grid-template-columns: 1.6fr 1fr 1fr 1.2fr;
    gap: 40px;
    padding-bottom: 56px;
}

.footer-about p {
    max-width: 34ch;
    margin: 20px 0 24px;
}

.footer-col__title {
    margin-bottom: 20px;
    color: var(--ink);
    font-family: var(--font-body);
    font-size: .8rem;
    font-weight: 600;
    letter-spacing: .14em;
    text-transform: uppercase;
}

.footer-links li + li {
    margin-top: 11px;
}

/* the phone and email in the contact list are links too, so they follow the
   same rule as the nav lists rather than the page-wide link colour */
.footer-links a,
.footer-contact a {
    color: rgba(255, 255, 255, .65);
}

.footer-links a:hover,
.footer-contact a:hover {
    color: var(--ink);
}

.footer-contact li {
    display: flex;
    gap: 12px;
    margin-bottom: 15px;
}

.footer-contact svg {
    width: 18px;
    height: 18px;
    flex: none;
    margin-top: 3px;
    color: var(--brand);
}

.site-footer .socials a {
    border-color: rgba(255, 255, 255, .16);
    color: rgba(255, 255, 255, .7);
}

.site-footer .socials a:hover {
    background: var(--brand-fill);
    border-color: var(--brand-fill);
    color: var(--ink);
}

.footer-bottom {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 20px;
    padding-block: 24px;
    border-top: 1px solid rgba(255, 255, 255, .1);
    font-size: .85rem;
}

.footer-bottom ul {
    display: flex;
    gap: 22px;
}

.footer-bottom a {
    color: rgba(255, 255, 255, .65);
}

.footer-bottom a:hover {
    color: var(--ink);
}


/* =========================================================================
   23. PAGE HEADER & BREADCRUMB
   ========================================================================= */
.page-header {
    padding-block: clamp(44px, 5vw, 72px);
    background: var(--mist);
    border-bottom: 1px solid var(--line-soft);
}

.page-header__title {
    margin-bottom: 10px;
}

/* Wide enough for the standfirst to hold one line on a desktop container;
   the reading-width cap that suits body copy would break it in two. */
.page-header p {
    max-width: min(100%, 96ch);
    color: var(--muted);
}

/* the strip between the page header and the listings. Equal padding above and
   below so the button sits centred in the gap rather than hugging the header. */
.view-switch-bar {
    padding-block: 28px;
}

.view-switch-bar .container {
    display: flex;
    align-items: center;
    justify-content: center;
}

/* the listings already pay for the space below, so do not stack a second gap */
.view-switch-bar + .section {
    padding-top: 0;
}

.breadcrumb {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 9px;
    margin-bottom: 16px;
    color: var(--muted);
    font-size: .85rem;
}

.breadcrumb li:not(:last-child)::after {
    content: "/";
    margin-left: 9px;
    color: var(--line);
}

.breadcrumb a {
    color: var(--muted);
}

.breadcrumb a:hover {
    color: var(--ink);
}


/* =========================================================================
   24. FILTER SIDEBAR
   ========================================================================= */
.layout-sidebar {
    display: grid;
    grid-template-columns: 310px 1fr;
    gap: 40px;
    align-items: start;
}

.layout-sidebar--right {
    grid-template-columns: 1fr 340px;
}

/* sticky panel that follows the listing scroll */
.sidebar {
    position: sticky;
    top: 100px;
}

.panel {
    padding: 26px;
    border: 1px solid var(--line);
    border-radius: var(--r);
    background: var(--paper);
}

.panel + .panel {
    margin-top: 24px;
}

.panel__title {
    margin-bottom: 18px;
    font-size: 1.1rem;
}

.filter-group {
    padding-bottom: 20px;
    margin-bottom: 20px;
    border-bottom: 1px solid var(--line-soft);
}

.filter-group:last-of-type {
    border-bottom: 0;
    margin-bottom: 0;
}

.filter-group__title {
    margin-bottom: 12px;
    color: var(--ink);
    font-family: var(--font-body);
    font-size: .8rem;
    font-weight: 600;
    letter-spacing: .1em;
    text-transform: uppercase;
}

/* --- keyword -------------------------------------------------------------
   The magnifier sits inside the field rather than beside it, so the group
   reads as one control and lines up with the fields under it. */
.filter-search {
    position: relative;
    display: block;
}

.filter-search__icon {
    position: absolute;
    top: 50%;
    left: 14px;
    width: 17px;
    height: 17px;
    transform: translateY(-50%);
    color: var(--muted);
    pointer-events: none;
}

.filter-search__input {
    padding-left: 41px;
}

/* the browser's own clear cross is drawn dark on dark and is barely
   visible, so it is replaced with one that takes the theme */
.filter-search__input::-webkit-search-cancel-button {
    appearance: none;
    width: 15px;
    height: 15px;
    background: currentColor;
    color: var(--muted);
    cursor: pointer;
    mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='2.4'%3E%3Cpath d='M18 6 6 18M6 6l12 12'/%3E%3C/svg%3E") center / contain no-repeat;
}

.filter-search__input:hover::-webkit-search-cancel-button {
    color: var(--ink);
}

.range-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
}

/* choice chips for beds / baths */
.chips {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.chip {
    padding: 7px 15px;
    border: 1px solid var(--line);
    border-radius: var(--r-pill);
    background: var(--paper);
    color: var(--ink-2);
    font-size: .85rem;
    transition: background var(--t), border-color var(--t), color var(--t);
}

.chip:hover {
    border-color: var(--brand-text);
    color: var(--brand-text);
}

.chip.is-active {
    background: var(--brand-fill);
    border-color: var(--brand-fill);
    color: var(--on-brand);
}


/* =========================================================================
   25. TOOLBAR & PAGINATION
   ========================================================================= */
.toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    margin-bottom: 26px;
    padding-bottom: 18px;
    border-bottom: 1px solid var(--line);
}

.toolbar__count {
    color: var(--muted);
    font-size: .9rem;
}

.toolbar__count strong {
    color: var(--ink);
}

.toolbar__actions {
    display: flex;
    align-items: center;
    gap: 12px;
}

.toolbar .select {
    padding-block: 9px;
    font-size: .88rem;
}

/* grid / list view switch */
.view-switch {
    display: flex;
    gap: 4px;
    padding: 3px;
    border: 1px solid var(--line);
    border-radius: var(--r-sm);
}

.view-switch button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 32px;
    border: 0;
    border-radius: 5px;
    background: transparent;
    color: var(--muted);
    transition: background var(--t), color var(--t);
}

.view-switch button.is-active {
    background: var(--brand-soft);
    color: var(--brand-text);
}

.view-switch svg {
    width: 17px;
    height: 17px;
}

/* results list — becomes single column in list view */
.results.is-list {
    grid-template-columns: 1fr;
}

/* --- ajax states --------------------------------------------------------
   The list dims rather than emptying, so the page keeps its height and
   nothing jumps while the next set is on its way.
   ------------------------------------------------------------------------ */
.results.is-loading {
    opacity: .4;
    pointer-events: none;
    transition: opacity var(--t);
}

/* the wrapper holds the spinner, so it stays centred over whatever height
   the current results happen to have */
[data-results] {
    position: relative;
}

[data-results].is-loading::after {
    content: "";
    position: absolute;
    top: 90px;
    left: 50%;
    z-index: 2;
    width: 34px;
    height: 34px;
    margin-left: -17px;
    border: 3px solid var(--line);
    border-top-color: var(--brand-fill);
    border-radius: 50%;
    animation: results-spin .7s linear infinite;
}

/* on a short list the spinner would hang below the cards, so pull it in */
[data-results].is-loading:has(.results-empty)::after {
    top: 40px;
}

/* the sentinel at the foot of an endlessly scrolling list — hidden until
   the script takes over, so the pagination stays the no-JS fallback */
.results-more {
    display: none;
    align-items: center;
    justify-content: center;
    gap: 12px;
    padding: 30px 0 4px;
    color: var(--muted);
    font-size: .9rem;
}

.results-more.is-on {
    display: flex;
}

.results-more__spin {
    width: 18px;
    height: 18px;
    border: 2px solid var(--line);
    border-top-color: var(--brand-fill);
    border-radius: 50%;
    animation: results-spin .7s linear infinite;

    /* only while a page is actually on its way — a permanently spinning
       sentinel reads as a stuck page */
    visibility: hidden;
}

.results-more.is-busy .results-more__spin {
    visibility: visible;
}

.results-more.is-done .results-more__spin {
    display: none;
}

@keyframes results-spin {

    to { transform: rotate(360deg); }
}

.results-empty {
    grid-column: 1 / -1;
    padding: clamp(40px, 6vw, 72px) 28px;
    border: 1px dashed var(--line);
    border-radius: var(--r);
    text-align: center;
}

.results-empty svg {
    width: 34px;
    height: 34px;
    margin: 0 auto 16px;
    color: var(--muted);
}

.results-empty h3 {
    margin-bottom: 8px;
    font-size: 1.2rem;
}

.results-empty p {
    max-width: 40ch;
    margin: 0 auto 20px;
    color: var(--muted);
    font-size: .93rem;
}

.pagination {
    display: flex;
    justify-content: center;
    gap: 8px;
    margin-top: 48px;
}

.pagination a,
.pagination span {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 44px;
    height: 44px;
    padding-inline: 12px;
    border: 1px solid var(--line);
    border-radius: var(--r-sm);
    color: var(--ink-2);
    font-size: .9rem;
    font-weight: 500;
}

.pagination a:hover {
    border-color: var(--brand-text);
    color: var(--brand-text);
}

.pagination .is-active {
    background: var(--brand-fill);
    border-color: var(--brand-fill);
    color: var(--on-brand);
}

.pagination svg {
    width: 16px;
    height: 16px;
}


/* =========================================================================
   25b. MAP SEARCH
   Split view: results scroll with the page, the map stays put beside them.
   Used by map-search.html.

   The pin coordinates below are demo positions. A real map library sets
   them from latitude and longitude — swap .map-pin--n for whatever your
   provider outputs and nothing else here changes.
   ========================================================================= */

/* How far down the sticky map starts: header height plus the filter bar.
   Overestimate rather than under — too small and the map slides beneath
   the bar, too large just leaves a little air above it. */
.map-search {
    --map-top: 176px;

    display: grid;

    /* minmax(0, …) so a wide card cannot push its column past its share */
    grid-template-columns: minmax(0, 45fr) minmax(0, 55fr);
}

/* --- filter bar -------------------------------------------------------- */
.map-bar {
    position: sticky;
    top: 78px;
    z-index: 80;
    border-bottom: 1px solid var(--line);
    background: var(--paper);
}

.map-bar__inner {
    --pill-h: 44px;

    display: flex;
    align-items: flex-end;
    flex-wrap: wrap;
    gap: 10px;
    padding-block: 14px;
}

/* each control sits under its own caption */
.map-field {
    display: flex;
    flex-direction: column;
}

.map-field__label {
    margin-bottom: 6px;
    color: var(--muted);
    font-size: .76rem;
}

/* pill-shaped filter controls; the select inside keeps them native */
.map-pill {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    min-height: var(--pill-h, auto);
    padding: 9px 15px;
    border: 1px solid var(--line);
    border-radius: var(--r-pill);
    background: var(--paper);
    color: var(--ink);
    font-size: .88rem;
    font-weight: 500;
    white-space: nowrap;
    transition: background var(--t), border-color var(--t), color var(--t);
}

.map-pill:hover {
    border-color: var(--muted);
}

.map-pill:focus-within {
    border-color: var(--brand);
    box-shadow: 0 0 0 3px rgba(198, 169, 107, .14);
}

.map-pill > svg {
    width: 16px;
    height: 16px;
    flex: none;
    color: var(--muted);
}

/* a filter that is actually narrowing the results */
.map-pill--set {
    border-color: var(--brand);
    background: var(--brand-soft);
    color: var(--brand-text);
}

.map-pill--set > svg,
.map-pill--set .map-pill__select {
    color: var(--brand-text);
}

.map-pill__select {
    appearance: none;
    padding: 0 21px 0 0;
    border: 0;
    color: inherit;
    font: inherit;
    background-color: transparent;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238E8A80' stroke-width='2'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 0 center;
    background-size: 14px;
    cursor: pointer;
}

.map-pill__select:focus {
    outline: none;
}

/* the Filters pill is a button, not a select */
.map-pill--button {
    cursor: pointer;
}

.map-pill--button .map-pill__caret {
    width: 14px;
    height: 14px;
    color: var(--muted);
    transition: transform var(--t);
}

/* --- pill dropdown ------------------------------------------------------
   A pill whose control is too rich for a select — a price range, say —
   opens this panel underneath instead.
   ----------------------------------------------------------------------- */
.map-drop-wrap {
    position: relative;
}

.map-drop-wrap.is-open .map-pill__caret {
    transform: rotate(180deg);
}

.map-drop {
    position: absolute;
    top: calc(100% + 10px);
    left: 0;
    z-index: 90;
    width: 300px;
    padding: 20px;
    border: 1px solid var(--line);
    border-radius: var(--r-lg);
    background: var(--paper);
    box-shadow: var(--shadow-lg);
    opacity: 0;
    visibility: hidden;
    transform: translateY(-6px);
    transition: opacity var(--t), visibility var(--t), transform var(--t);
}

.map-drop-wrap.is-open .map-drop {
    opacity: 1;
    visibility: visible;
    transform: none;
}

/* for a pill near the right edge of the bar */
.map-drop--right {
    left: auto;
    right: 0;
}

.map-drop__title {
    display: block;
    margin-bottom: 12px;
    color: var(--muted);
    font-size: .72rem;
    font-weight: 600;
    letter-spacing: .12em;
    text-transform: uppercase;
}

.map-drop__row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
}

/* type-to-filter above a long choice list */
.map-drop__filter {
    position: relative;
    margin-bottom: 12px;
}

.map-drop__filter > svg {
    position: absolute;
    top: 50%;
    left: 12px;
    width: 15px;
    height: 15px;
    color: var(--muted);
    pointer-events: none;
    transform: translateY(-50%);
}

.map-drop__filter input {
    width: 100%;
    padding: 9px 12px 9px 34px;
    border: 1px solid var(--line);
    border-radius: var(--r-sm);
    background: var(--paper);
    color: var(--ink);
    font: inherit;
    font-size: .88rem;
}

.map-drop__filter input:focus {
    border-color: var(--brand);
    box-shadow: 0 0 0 3px rgba(198, 169, 107, .14);
    outline: none;
}

.map-drop__none {
    padding: 8px 2px;
    color: var(--muted);
    font-size: .88rem;
}

/* .check is display:flex, so it needs telling that hidden means hidden */
.check[hidden] {
    display: none;
}

/* a choice list inside a pill panel — scrolls once it outgrows the box */
.map-drop__list {
    max-height: 230px;
    padding-right: 6px;
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-width: thin;
    scrollbar-color: var(--line) transparent;
}

.map-drop__list::-webkit-scrollbar {
    width: 6px;
}

.map-drop__list::-webkit-scrollbar-thumb {
    border-radius: var(--r-pill);
    background: var(--line);
}

.map-drop__list .check {
    margin-bottom: 11px;
}

.map-drop__list .check:last-child {
    margin-bottom: 0;
}

.map-drop__foot {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
    margin-top: 18px;
    padding-top: 16px;
    border-top: 1px solid var(--line-soft);
}

/* amount field with the currency sitting inside it */
.money {
    position: relative;
}

.money__sign {
    position: absolute;
    top: 50%;
    left: 13px;
    color: var(--muted);
    font-size: .9rem;
    pointer-events: none;
    transform: translateY(-50%);
}

.money__input {
    width: 100%;
    padding: 11px 12px 11px 30px;
    border: 1px solid var(--line);
    border-radius: var(--r-sm);
    background: var(--paper);
    color: var(--ink);
    font: inherit;
    font-size: .9rem;
}

.money__input::placeholder {
    color: var(--muted);
}

.money__input:focus {
    border-color: var(--brand);
    box-shadow: 0 0 0 3px rgba(198, 169, 107, .14);
    outline: none;
}

/* --- bar actions ------------------------------------------------------- */
.map-bar__links {
    display: flex;
    align-items: center;
    gap: 24px;
    margin-left: auto;
    padding-bottom: 8px;
}

.map-bar__link {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    color: var(--ink);
    font-size: .9rem;
    font-weight: 600;
}

.map-bar__link:hover {
    color: var(--brand-text);
    text-decoration: underline;
}

.map-bar__link svg {
    width: 17px;
    height: 17px;
}

/* --- applied filters --------------------------------------------------- */
.applied {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
    margin-bottom: 22px;
}

.applied__chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 8px 6px 14px;
    border: 1px solid var(--brand);
    border-radius: var(--r-pill);
    background: var(--brand-soft);
    color: var(--brand-text);
    font-size: .84rem;
}

.applied__remove {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: inherit;
    transition: background var(--t);
}

.applied__remove:hover {
    background: rgba(198, 169, 107, .16);
}

.applied__remove svg {
    width: 12px;
    height: 12px;
}

.applied__clear {
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--muted);
    font-size: .86rem;
}

.applied__clear:hover {
    color: var(--ink);
    text-decoration: underline;
}

.applied:empty {
    display: none;
}

/* --- results column ---------------------------------------------------- */
.map-search__results {
    padding: 26px var(--gutter) 48px;
    min-width: 0;
}

/* smaller than a page h1: it shares the column with the results and the
   map, so it heads a panel rather than the page */
.map-search__title {
    font-size: 1.75rem;
}

.map-search__head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 14px;
    margin-bottom: 22px;
}

.map-search__count {
    color: var(--muted);
    font-size: .9rem;
}

.map-search__count strong {
    color: var(--ink);
}

/* the card matching the pin under the cursor */
.property-card.is-highlight {
    border-color: var(--brand);
    box-shadow: var(--shadow);
}

/* --- map column -------------------------------------------------------- */
.map-search__map {
    position: sticky;
    top: var(--map-top);
    height: calc(100vh - var(--map-top));
}

.map-canvas {
    position: relative;
    height: 100%;
    border-left: 1px solid var(--line);
    background-color: var(--mist);
    overflow: hidden;
}

/* Google renders into this layer. Until a key is set it just shows the
   placeholder artwork, so the page works offline. */
.map-canvas__surface {
    position: absolute;
    inset: 0;
    background-image: url("../img/map.svg");
    background-position: center;
    background-size: cover;
}

.map-canvas.is-live .map-canvas__surface {
    background-image: none;
}

/* once markers own the pins, Google positions them, not our CSS */
.is-live .map-pin {
    position: static;
    transform: none;
}

/* the pin only exists to become marker content, so keep it out of sight
   until Google has taken it — and if the script never loads, for good */
.map-frame .map-pin {
    visibility: hidden;
}

.map-frame.is-live .map-pin {
    visibility: visible;
}

.is-live .map-pin:hover,
.is-live .map-pin.is-active {
    transform: scale(1.06);
}

/* --- saved properties --------------------------------------------------- */

.header-saved {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 38px;
    height: 38px;
    border-radius: 50%;
    color: var(--ink);
    transition: background var(--t), color var(--t);
}

.header-saved svg {
    width: 19px;
    height: 19px;
}

.header-saved:hover {
    background: var(--mist);
}

/* only there once something is saved, so an empty list is silent */
.header-saved__count {
    position: absolute;
    top: 1px;
    right: 0;
    min-width: 17px;
    height: 17px;
    padding: 0 4px;
    border-radius: var(--r-pill);
    background: var(--brand-fill);
    color: var(--on-brand);
    font-size: .68rem;
    font-weight: 700;
    line-height: 17px;
    text-align: center;
}

/* the heart fills in once the listing is on the list */
.property-card__fav.is-active svg {
    fill: currentColor;
}

/* --- location search --------------------------------------------------- */

/* on trial in the map bar beside the Town pill. Speaks the same pill
   language, but holds several places at once instead of one */
.map-field--grow {
    flex: 1 1 320px;
    min-width: 260px;
    max-width: 500px;
}

.divisions {
    position: relative;
}

.divisions__control {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 6px;
    min-height: var(--pill-h, 44px);
    padding: 9px 14px;
    border: 1px solid var(--line);
    border-radius: var(--r-pill);
    background: var(--paper);
    transition: border-color var(--t), box-shadow var(--t);
}

/* the same pin the Town pill carries */
.divisions__icon {
    width: 16px;
    height: 16px;
    flex: none;
    color: var(--muted);
}

.divisions__control:focus-within {
    border-color: var(--brand);
    box-shadow: 0 0 0 3px rgba(198, 169, 107, .12);
}

.divisions__tags {
    display: contents;
}

.divisions__tag {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 2px 5px 2px 10px;
    border-radius: var(--r-pill);
    background: var(--mist);
    color: var(--ink);
    font-size: .82rem;
    font-weight: 600;
    line-height: 1.5;
    white-space: nowrap;
}

.divisions__drop {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    height: 18px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: var(--muted);
    transition: background var(--t), color var(--t);
}

.divisions__drop svg {
    width: 12px;
    height: 12px;
}

.divisions__drop:hover {
    background: var(--brand-fill);
    color: var(--on-brand);
}

/* takes only the room left over, so the badges keep their size */
.divisions__input {
    flex: 1 1 90px;
    min-width: 90px;
    border: 0;
    background: none;
    color: var(--ink);
    font-size: .88rem;
}

.divisions__input:focus {
    outline: none;
}

.divisions__menu {
    position: absolute;
    top: calc(100% + 8px);
    left: 0;
    z-index: 90;
    width: min(100%, 360px);
    max-height: 280px;
    padding: 6px;
    border: 1px solid var(--line);
    border-radius: var(--r-lg);
    background: var(--paper);
    box-shadow: var(--shadow-lg);
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-width: thin;
    scrollbar-color: var(--line) transparent;
}

.divisions__option {
    display: flex;
    border: 0;
    background: none;
    align-items: baseline;
    gap: 8px;
    width: 100%;
    padding: 9px 12px;
    border-radius: var(--r-sm);
    text-align: left;
    transition: background var(--t);
}

.divisions__option:hover {
    background: var(--mist);
}

.divisions__name {
    font-size: .9rem;
    font-weight: 500;
}

/* zone names repeat across towns, so the parent has to show */
.divisions__where {
    color: var(--muted);
    font-size: .78rem;
}

.divisions__none {
    padding: 12px;
    color: var(--muted);
    font-size: .85rem;
    text-align: center;
}

/* --- price pins -------------------------------------------------------- */
.map-pin {
    position: absolute;
    z-index: 2;
    padding: 7px 14px;
    border: 1px solid var(--line);
    border-radius: var(--r-pill);
    background: var(--paper);
    color: var(--ink);
    font-size: .82rem;
    font-weight: 600;
    white-space: nowrap;
    box-shadow: var(--shadow);
    transform: translate(-50%, -100%);
    transition: background var(--t), color var(--t), border-color var(--t), transform var(--t);
}

.map-pin:hover,
.map-pin.is-active {
    z-index: 3;
    background: var(--brand-fill);
    border-color: var(--brand-fill);
    color: var(--on-brand);
    transform: translate(-50%, -100%) scale(1.06);
}

/* little stem so the pill points at its spot */
.map-pin::after {
    content: "";
    position: absolute;
    left: 50%;
    bottom: -5px;
    width: 9px;
    height: 9px;
    background: inherit;
    border-right: inherit;
    border-bottom: inherit;
    transform: translateX(-50%) rotate(45deg);
}

/* single location: a plain brand-coloured pin instead of a price pill.
   Used on the property page, where there is nothing to compare a price to. */
.map-pin--marker {
    padding: 0;
    border: 0;
    background: none;
    box-shadow: none;
    color: var(--brand-fill);
    line-height: 0;
}

.map-pin--marker svg {
    width: 42px;
    height: 42px;
    filter: drop-shadow(0 3px 6px rgba(0, 0, 0, .28));
}

.map-pin--marker:hover {
    background: none;
    border-color: transparent;
    color: var(--brand-hover);
    transform: translate(-50%, -100%) scale(1.08);
}

/* the pill's little stem would show through the pin artwork */
.map-pin--marker::after {
    content: none;
}

.map-pin--1 { left: 22%; top: 32%; }
.map-pin--2 { left: 38%; top: 56%; }
.map-pin--3 { left: 55%; top: 26%; }
.map-pin--4 { left: 63%; top: 63%; }
.map-pin--5 { left: 30%; top: 73%; }
.map-pin--6 { left: 75%; top: 41%; }
.map-pin--7 { left: 47%; top: 39%; }
.map-pin--8 { left: 68%; top: 80%; }

/* --- map furniture ----------------------------------------------------- */
.map-tools {
    position: absolute;
    top: 16px;
    right: 16px;
    z-index: 4;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.map-tools .icon-btn {
    background: var(--glass);
    border-color: transparent;
    box-shadow: var(--shadow-sm);
}

.map-note {
    position: absolute;
    top: 16px;
    left: 16px;
    z-index: 4;
    display: inline-flex;
    align-items: center;
    gap: 9px;
    padding: 9px 15px;
    border-radius: var(--r-pill);
    background: var(--glass);
    color: var(--ink-2);
    font-size: .84rem;
    box-shadow: var(--shadow-sm);
}

.map-note input {
    accent-color: var(--brand-fill);
}


/* =========================================================================
   25c. FILTER DRAWER
   The full filter set, slid in from the left. Opened by anything carrying
   data-filters-open, so the same drawer serves the map bar and the archive.
   ========================================================================= */
.filter-backdrop {
    position: fixed;
    inset: 0;
    z-index: var(--z-drawer);
    background: rgba(0, 0, 0, .5);
    opacity: 0;
    visibility: hidden;
    transition: opacity var(--t), visibility var(--t);
}

.filter-backdrop.is-open {
    opacity: 1;
    visibility: visible;
}

.filter-drawer {
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    z-index: calc(var(--z-drawer) + 1);
    display: flex;
    flex-direction: column;
    width: min(350px, 88vw);
    background: var(--paper);
    transform: translateX(-100%);
    transition: transform var(--t);
}

.filter-drawer.is-open {
    transform: none;
}

/* --- head -------------------------------------------------------------- */
.filter-drawer__head {
    display: flex;
    align-items: center;
    gap: 14px;
    flex: none;
    padding: 18px 22px;
    border-bottom: 1px solid var(--line);
}

.filter-drawer__title {
    margin: 0;
    font-size: 1.2rem;
}

.filter-drawer__clear {
    margin-left: auto;
    padding: 0;
    border: 0;
    background: transparent;
    color: var(--brand-text);
    font-size: .86rem;
    font-weight: 600;
}

.filter-drawer__clear:hover {
    text-decoration: underline;
}

.filter-drawer__close {
    width: 34px;
    height: 34px;
    flex: none;
}

.filter-drawer__close svg {
    width: 16px;
    height: 16px;
}

/* --- body -------------------------------------------------------------- */

/* the only scrolling part, so the footer button stays reachable */
.filter-drawer__body {
    flex: 1;
    padding: 22px;
    overflow-y: auto;
    overscroll-behavior: contain;
}

.filter-drawer__body .filter-group:last-of-type {
    padding-bottom: 0;
    border-bottom: 0;
}

/* --- foot -------------------------------------------------------------- */
.filter-drawer__foot {
    flex: none;
    padding: 16px 22px;
    border-top: 1px solid var(--line);
}

/* --- inline variant -----------------------------------------------------
   Same markup, two presentations: a panel in the sidebar on a wide screen,
   the sliding drawer below 900px. The archive uses it so its filters match
   the map page exactly.
   ------------------------------------------------------------------------ */
.filter-drawer--inline {
    position: static;
    width: auto;
    border: 1px solid var(--line);
    border-radius: var(--r);
    transform: none;
}

.filter-drawer--inline .filter-drawer__body {
    overflow-y: visible;
}

/* nothing to close when it is just a panel */
.filter-drawer--inline .filter-drawer__close {
    display: none;
}

/* the button that opens it only exists once it becomes a drawer */
.filters-trigger {
    display: none;
}


/* =========================================================================
   26. PROPERTY DETAIL
   ========================================================================= */
/* a button, so the full-screen view is reachable by keyboard too */
.gallery__main {
    position: relative;
    display: block;
    width: 100%;
    padding: 0;
    border: 0;
    aspect-ratio: 16 / 10;
    border-radius: var(--r-lg);
    background: var(--mist);
    overflow: hidden;
    cursor: zoom-in;
}

.gallery__main img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform .5s ease;
}

.gallery__main:hover img {
    transform: scale(1.02);
}

/* the affordance telling people the image opens */
.gallery__expand {
    position: absolute;
    right: 16px;
    bottom: 16px;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 9px 16px;
    border-radius: var(--r-pill);
    background: var(--glass);
    color: var(--ink);
    font-size: .82rem;
    font-weight: 600;
    transition: background var(--t);
}

.gallery__main:hover .gallery__expand {
    background: var(--brand-fill);
    color: var(--on-brand);
}

.gallery__expand svg {
    width: 15px;
    height: 15px;
}

/* five thumbs fill the row; past that the strip slides under arrow control
   and follows the selection on its own — never a visible scrollbar */
.gallery__strip {
    position: relative;
    margin-top: 12px;
}

.gallery__thumbs {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: calc((100% - 48px) / 5);
    gap: 12px;
    overflow-x: auto;
    scroll-behavior: smooth;
    scrollbar-width: none;
    -ms-overflow-style: none;
}

/* the strip is still swipeable on touch, the bar is simply not drawn */
.gallery__thumbs::-webkit-scrollbar {
    display: none;
}

/* --- strip arrows ----------------------------------------------------- */
.gallery__strip-btn {
    position: absolute;
    top: 50%;
    z-index: 2;
    width: 40px;
    height: 40px;
    background: var(--glass);
    border-color: transparent;
    box-shadow: var(--shadow);
    opacity: 0;
    visibility: hidden;
    transform: translateY(-50%);
    transition: opacity var(--t), visibility var(--t), background var(--t), color var(--t);
}

.gallery__strip-btn svg {
    width: 16px;
    height: 16px;
}

.gallery__strip-btn--prev { left: -8px; }
.gallery__strip-btn--next { right: -8px; }

/* each arrow appears only while there is something that way to reach */
.gallery__strip.can-prev .gallery__strip-btn--prev,
.gallery__strip.can-next .gallery__strip-btn--next {
    opacity: 1;
    visibility: visible;
}

/* soft edge telling the eye the row continues */
.gallery__strip::before,
.gallery__strip::after {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    z-index: 1;
    width: 72px;
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--t);
}

.gallery__strip::before {
    left: 0;
    background: linear-gradient(to right, var(--paper), transparent);
}

.gallery__strip::after {
    right: 0;
    background: linear-gradient(to left, var(--paper), transparent);
}

.gallery__strip.can-prev::before,
.gallery__strip.can-next::after {
    opacity: 1;
}

.gallery__thumb {
    aspect-ratio: 3 / 2;
    padding: 0;
    border: 2px solid transparent;
    border-radius: var(--r-sm);
    background: var(--mist);
    overflow: hidden;
}

.gallery__thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.gallery__thumb.is-active {
    border-color: var(--brand);
}

/* headline block above the gallery */
.property-head {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    justify-content: space-between;
    gap: 24px;
    margin-bottom: 28px;
}

/* the title column shrinks so a long name wraps inside it, instead of
   filling the row and pushing the price onto the next line */
.property-head__main {
    flex: 1 1 380px;
    min-width: 0;
}

.property-head__main h1 {
    overflow-wrap: break-word;
}

/* price column keeps its natural width and never shrinks */
.property-head__aside {
    flex: 0 0 auto;
}

.property-head__price {
    color: var(--brand-text);
    font-family: var(--font-display);
    font-size: clamp(1.7rem, 3vw, 2.3rem);
    line-height: 1.1;
}

.property-head__actions {
    display: flex;
    gap: 10px;
}

/* key specs strip */
.specs {
    display: grid;
    /* auto-fit so three specs fill the row instead of leaving a grey cell,
       the container background shows through any empty track */
    grid-template-columns: repeat(auto-fit, minmax(0, 1fr));
    gap: 1px;
    margin-block: 32px 0;
    border: 1px solid var(--line);
    border-radius: var(--r);
    background: var(--line);
    overflow: hidden;
}

.specs li {
    padding: 22px;
    background: var(--paper);
}

.specs svg {
    width: 20px;
    height: 20px;
    margin-bottom: 10px;
    color: var(--brand);
}

.specs strong {
    display: block;
    color: var(--ink);
    font-size: 1.05rem;
}

.specs span {
    color: var(--muted);
    font-size: .82rem;
}

/* detail body blocks */
.detail-block {
    padding-bottom: 34px;
    margin-bottom: 34px;
    border-bottom: 1px solid var(--line-soft);
}

.detail-block:last-child {
    padding-bottom: 0;
    margin-bottom: 0;
    border-bottom: 0;
}

.detail-block h2 {
    margin-bottom: 16px;
    font-size: 1.5rem;
}

/* two-column key/value table */
.detail-list {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 0 40px;
}

.detail-list li {
    display: flex;
    justify-content: space-between;
    gap: 16px;
    padding: 11px 0;
    border-bottom: 1px solid var(--line-soft);
    font-size: .92rem;
}

/* a sidebar panel is too narrow for two columns */
.panel .detail-list {
    grid-template-columns: 1fr;
}

.detail-list span {
    color: var(--muted);
}

.detail-list strong {
    color: var(--ink);
    font-weight: 500;
}

/* amenity checklist */
.amenities {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 12px 24px;
}

.amenities li {
    display: flex;
    align-items: center;
    gap: 10px;
    font-size: .92rem;
}

.amenities svg {
    width: 17px;
    height: 17px;
    flex: none;
    color: var(--brand);
}

/* agent contact box in the detail sidebar */
.agent-box {
    display: flex;
    align-items: center;
    gap: 15px;
    padding-bottom: 20px;
    margin-bottom: 20px;
    border-bottom: 1px solid var(--line-soft);
}

.agent-box img {
    width: 62px;
    height: 62px;
    border-radius: var(--r-pill);
    object-fit: cover;
}

/* ways to reach the agent. Kept light on purpose: the send button further
   down the panel is the primary action and should stay the loudest thing. */
.agent-contact {
    display: grid;
    gap: 8px;
    margin-bottom: 22px;
}

.agent-contact.col-2 { grid-template-columns: repeat(2, 1fr); }
.agent-contact.col-3 { grid-template-columns: repeat(3, 1fr); }

.agent-contact__link {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    padding: 14px 6px 12px;
    border: 1px solid var(--line);
    border-radius: var(--r-sm);
    background: var(--paper);
    color: var(--ink-2);
    font-size: .82rem;
    font-weight: 600;
    line-height: 1;
    text-decoration: none;
    transition: border-color .18s ease, background .18s ease, color .18s ease, transform .18s ease;
}

/* the icon carries the brand colour, the tile stays neutral until hover */
.agent-contact__icon {
    display: grid;
    place-items: center;
    width: 34px;
    height: 34px;
    border-radius: var(--r-pill);
    background: var(--brand-soft);
    color: var(--brand-text);
    transition: background .18s ease, color .18s ease;
}

.agent-contact__icon svg {
    width: 17px;
    height: 17px;
}

.agent-contact__link:hover {
    border-color: var(--brand);
    color: var(--brand-text);
    transform: translateY(-2px);
}

.agent-contact__link:hover .agent-contact__icon {
    background: var(--brand-fill);
    color: var(--on-brand);
}

.agent-box strong {
    display: block;
    color: var(--ink);
    font-size: 1.02rem;
}

.agent-box span {
    color: var(--muted);
    font-size: .84rem;
}


/* =========================================================================
   26b. LIGHTBOX
   Full-screen gallery viewer. One instance per page, driven by the
   thumbnails of the .gallery it sits next to.
   ========================================================================= */
.lightbox {
    position: fixed;
    inset: 0;
    z-index: var(--z-top);
    display: flex;
    align-items: center;
    justify-content: center;
    gap: clamp(10px, 2vw, 30px);
    padding: clamp(56px, 6vw, 80px) clamp(16px, 4vw, 48px);
    background: rgba(6, 6, 6, .96);
    opacity: 0;
    visibility: hidden;
    transition: opacity var(--t), visibility var(--t);
}

/* visibility keeps the controls out of the tab order while closed */
.lightbox.is-open {
    opacity: 1;
    visibility: visible;
}

.lightbox__stage {
    display: flex;
    flex-direction: column;
    align-items: center;
    max-width: min(1240px, 100%);
    margin: 0;
}

.lightbox__image {
    width: auto;
    max-width: 100%;
    max-height: 78vh;
    border-radius: var(--r);
    background: var(--band);
}

.lightbox__caption {
    display: flex;
    align-items: center;
    gap: 14px;
    margin-top: 18px;
    color: rgba(255, 255, 255, .7);
    font-size: .86rem;
}

.lightbox__counter {
    padding: 4px 12px;
    border-radius: var(--r-pill);
    background: rgba(255, 255, 255, .12);
    color: var(--white);
    font-family: var(--font-mono);
    font-size: .78rem;
}

/* --- controls --------------------------------------------------------- */
.lightbox__nav,
.lightbox__close {
    flex: none;
    background: rgba(255, 255, 255, .12);
    border-color: rgba(255, 255, 255, .28);
    color: var(--white);
}

.lightbox__nav:hover,
.lightbox__close:hover {
    background: var(--brand-fill);
    border-color: var(--brand-fill);
    color: var(--on-brand);
}

.lightbox__nav {
    width: 52px;
    height: 52px;
}

.lightbox__nav svg {
    width: 20px;
    height: 20px;
}

.lightbox__close {
    position: absolute;
    top: clamp(16px, 3vw, 28px);
    right: clamp(16px, 3vw, 28px);
}

/* a single-image gallery has nothing to step through */
.lightbox--solo .lightbox__nav,
.lightbox--solo .lightbox__counter {
    display: none;
}


/* =========================================================================
   26c. PROPERTY PAGE — MOSAIC LAYOUT
   The alternative single-listing page: a sticky section nav, a mosaic
   gallery that opens the lightbox, and a headline card. Used by
   property-2.html; property.html keeps the strip gallery.
   ========================================================================= */

/* --- sticky section nav ----------------------------------------------- */
.page-nav {
    position: sticky;
    top: 78px;
    z-index: 90;
    border-bottom: 1px solid var(--line-soft);
    background: var(--glass);
    backdrop-filter: saturate(180%) blur(10px);
}

.page-nav__inner {
    display: flex;
    align-items: center;
    gap: 30px;
    overflow-x: auto;
    scrollbar-width: none;
    -ms-overflow-style: none;
}

.page-nav__inner::-webkit-scrollbar {
    display: none;
}

.page-nav__back {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    flex: none;
    padding-right: 8px;
    color: var(--ink);
    font-size: .9rem;
    font-weight: 600;
    white-space: nowrap;
}

.page-nav__back svg {
    width: 16px;
    height: 16px;
}

.page-nav__link {
    position: relative;
    flex: none;
    padding: 19px 0;
    color: var(--muted);
    font-size: .92rem;
    white-space: nowrap;
}

.page-nav__link:hover {
    color: var(--ink);
}

/* set by the scroll spy in main.js */
.page-nav__link.is-active {
    color: var(--ink);
    font-weight: 600;
}

.page-nav__link.is-active::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: -1px;
    height: 2px;
    background: var(--brand-fill);
}

/* --- mosaic gallery ---------------------------------------------------- */
/* The main frame takes exactly half the width; the fr columns split what is
   left after the gaps, so the two side columns stay equal. Row height comes
   from the side cells, so the ratio below drives the whole mosaic. */
.gallery-mosaic {
    display: grid;
    grid-template-columns: 50% 1fr 1fr;
    grid-template-rows: auto auto;
    gap: 12px;
}

/* 3:2 is what interior photography is shot at — 16:9 would slice the
   ceiling and floor off a room shot */
.gallery-mosaic__cell {
    position: relative;
    aspect-ratio: 3 / 2;
    padding: 0;
    border: 0;
    border-radius: var(--r);
    background: var(--mist);
    overflow: hidden;
    cursor: zoom-in;
}

.gallery-mosaic__cell img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform .5s ease;
}

.gallery-mosaic__cell:hover img {
    transform: scale(1.04);
}

/* spans both rows and stretches to their combined height, which lands it
   on the same 3:2 as the cells that set them */
.gallery-mosaic__main {
    grid-row: span 2;
    aspect-ratio: auto;
    min-height: 0;
    border-radius: var(--r-lg);
}

/* out of flow on purpose: in normal flow the photo's own ratio becomes the
   cell's content height, and since this cell spans both rows it would drag
   the whole grid taller or shorter with every listing */
.gallery-mosaic__main img {
    position: absolute;
    inset: 0;
}

/* --- the mosaic with fewer than five photos ----------------------------- */
/* The grid, the cell sizes and the height stay exactly what they are at five
   frames — the cells with no photo behind them are simply not there. With no
   full row of tiles to set the row height, the ratio has to come from here:
   3:1 is what the five-frame mosaic works out to. */
.gallery-mosaic--1,
.gallery-mosaic--2,
.gallery-mosaic--3,
.gallery-mosaic--4 {
    grid-template-rows: 1fr 1fr;
    aspect-ratio: 3 / 1;
}

/* that ratio already fixes the row height — a per-cell ratio fights it */
.gallery-mosaic--1 .gallery-mosaic__cell,
.gallery-mosaic--2 .gallery-mosaic__cell,
.gallery-mosaic--3 .gallery-mosaic__cell,
.gallery-mosaic--4 .gallery-mosaic__cell {
    aspect-ratio: auto;
}

/* frames beyond the five on show — the lightbox still counts them */
.gallery-mosaic__cell--more {
    display: none;
}

.gallery-mosaic__all {
    position: absolute;
    right: 16px;
    bottom: 16px;
    display: inline-flex;
    align-items: center;
    gap: 9px;
    padding: 11px 18px;
    border-radius: var(--r-pill);
    background: var(--glass);
    color: var(--ink);
    font-size: .86rem;
    font-weight: 600;
    box-shadow: var(--shadow-sm);
    transition: background var(--t);
}

.gallery-mosaic__main:hover .gallery-mosaic__all {
    background: var(--brand-fill);
    color: var(--on-brand);
}

.gallery-mosaic__all svg {
    width: 16px;
    height: 16px;
}

/* --- listing head ------------------------------------------------------ */
.listing-head__badges {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
    margin-bottom: 18px;
}

.listing-head__age {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    color: var(--muted);
    font-size: .84rem;
}

.listing-head__age svg {
    width: 15px;
    height: 15px;
}

/* name + status, above both columns. The card below opens with the price. */
.listing-title {
    margin-bottom: 28px;
}

.listing-title h1 {
    margin-bottom: 14px;
    overflow-wrap: break-word;
}

.listing-title .listing-head__badges {
    margin-bottom: 0;
}

.listing-head__price {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 12px;
    margin-bottom: 12px;
    color: var(--brand-text);
    font-family: var(--font-display);
    font-size: clamp(1.9rem, 3.4vw, 2.6rem);
    font-weight: 600;
    line-height: 1;
    letter-spacing: -.03em;
}

.listing-head__price small {
    color: var(--muted);
    font-family: var(--font-body);
    font-size: .92rem;
    font-weight: 400;
    letter-spacing: 0;
}

.listing-head__where {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px 16px;
    padding-bottom: 20px;
    margin-bottom: 20px;
    border-bottom: 1px solid var(--line-soft);
    color: var(--muted);
    font-size: .92rem;
}

.listing-head__where > span {
    display: inline-flex;
    align-items: center;
    gap: 8px;
}

.listing-head__where svg {
    width: 16px;
    height: 16px;
    flex: none;
    color: var(--brand-text);
}

.listing-head__id {
    font-family: var(--font-mono);
    font-size: .8rem;
}

/* key figures, no divider — the card above already has one */
.listing-facts {
    display: flex;
    flex-wrap: wrap;
    gap: 12px 26px;
    margin-bottom: 18px;
}

.listing-facts li {
    display: flex;
    align-items: center;
    gap: 8px;
    color: var(--ink-2);
    font-size: .92rem;
}

.listing-facts svg {
    width: 17px;
    height: 17px;
    color: var(--muted);
}

.listing-actions {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 12px;
    margin-top: 22px;
}

/* --- agent panel ------------------------------------------------------- */
.agent-line {
    display: flex;
    align-items: center;
    gap: 14px;
    margin-bottom: 18px;
}

.agent-avatar {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 48px;
    height: 48px;
    flex: none;
    border-radius: var(--r-pill);
    background: var(--brand-soft);
    color: var(--brand-text);
    font-size: .95rem;
    font-weight: 600;
    letter-spacing: .04em;
}

.agent-line strong {
    display: block;
    color: var(--ink);
    font-size: 1rem;
}

.agent-line span {
    color: var(--muted);
    font-size: .85rem;
}

.agent-panel .btn + .btn {
    margin-top: 10px;
}


/* =========================================================================
   27. ACCORDION
   ========================================================================= */
.accordion__item {
    border: 1px solid var(--line);
    border-radius: var(--r);
    background: var(--paper);
}

.accordion__item + .accordion__item {
    margin-top: 12px;
}

.accordion__trigger {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 20px;
    width: 100%;
    padding: 20px 24px;
    border: 0;
    background: transparent;
    color: var(--ink);
    font-family: var(--font-display);
    font-size: 1.08rem;
    text-align: left;
}

.accordion__trigger svg {
    width: 18px;
    height: 18px;
    flex: none;
    color: var(--brand);
    transition: transform var(--t);
}

.accordion__item.is-open .accordion__trigger svg {
    transform: rotate(45deg);
}

/* height animated from JS-free max-height so it works without measuring */
.accordion__panel {
    max-height: 0;
    overflow: hidden;
    transition: max-height var(--t);
}

.accordion__item.is-open .accordion__panel {
    max-height: 400px;
}

.accordion__panel p {
    padding: 0 24px 22px;
    color: var(--muted);
    font-size: .94rem;
}


/* =========================================================================
   28. CONTACT & MAP
   ========================================================================= */
.contact-card {
    display: flex;
    gap: 16px;
    padding: 26px;
    border: 1px solid var(--line);
    border-radius: var(--r);
    background: var(--paper);
}

.contact-card__icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 46px;
    height: 46px;
    flex: none;
    border-radius: var(--r-sm);
    background: var(--brand-soft);
    color: var(--brand-text);
}

.contact-card__icon svg {
    width: 20px;
    height: 20px;
}

.contact-card h3 {
    margin-bottom: 4px;
    font-size: 1.05rem;
}

.contact-card p {
    color: var(--muted);
    font-size: .92rem;
}

.map-frame {
    position: relative;
    border-radius: var(--r-lg);
    overflow: hidden;
    border: 1px solid var(--line);
}

.map-frame img,
.map-frame iframe,
.map-frame [data-map] {
    display: block;
    width: 100%;
    height: 440px;
    object-fit: cover;
    border: 0;
}


/* =========================================================================
   29. ARTICLE BODY
   Long-form typography for the single post page.
   ========================================================================= */
.article__cover {
    aspect-ratio: 2 / 1;
    margin-bottom: 36px;
    border-radius: var(--r-lg);
    overflow: hidden;
    background: var(--mist);
}

.article__cover img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.article__body {
    font-size: 1.02rem;
}

.article__body h2 {
    margin-top: 40px;
    font-size: 1.7rem;
}

.article__body h3 {
    margin-top: 30px;
    font-size: 1.3rem;
}

.article__body ul {
    margin: 0 0 1.2em;
    padding-left: 22px;
    list-style: disc;
}

.article__body li {
    margin-bottom: 8px;
}

.article__body blockquote {
    margin: 32px 0;
    padding: 4px 0 4px 26px;
    border-left: 3px solid var(--brand);
    color: var(--ink);
    font-family: var(--font-display);
    font-size: 1.3rem;
    line-height: 1.5;
}

.article__footer {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 20px;
    margin-top: 44px;
    padding-top: 26px;
    border-top: 1px solid var(--line);
}

.article__tags {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}


/* =========================================================================
   30. BACK TO TOP
   ========================================================================= */
.to-top {
    position: fixed;

    /* centred on the shared line rather than offset from the edge: translate
       is its own property, so transform stays free for the show/hide slide */
    right: var(--float-x);
    translate: 50% 0;
    bottom: 24px;
    z-index: var(--z-header);
    opacity: 0;
    visibility: hidden;
    transform: translateY(10px);
    transition: opacity var(--t), transform var(--t), visibility var(--t);
}

.to-top.is-visible {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
}


/* =========================================================================
   31. UTILITIES
   ========================================================================= */
.d-none         { display: none !important; }
.text-center    { text-align: center; }
.mt-0           { margin-top: 0; }
.mb-0           { margin-bottom: 0; }
.mt-24          { margin-top: 24px; }
.mt-32          { margin-top: 32px; }
.mt-40          { margin-top: 40px; }
.mb-24          { margin-bottom: 24px; }
.mb-32          { margin-bottom: 32px; }
.gap-16         { gap: 16px; }
.flex-center    { display: flex; align-items: center; }
.justify-center { display: flex; justify-content: center; }

/* elements revealed on scroll by main.js */
.reveal {
    opacity: 0;
    transform: translateY(18px);
    transition: opacity .6s ease, transform .6s ease;
}

.reveal.is-visible {
    opacity: 1;
    transform: none;
}


/* =========================================================================
   32. ELEMENTS PAGE (style guide)
   Only used by elements.html. Delete this section and the page if you do
   not want to ship the style guide with the site.
   ========================================================================= */

/* sticky index of everything on the page */
.ui-index {
    position: sticky;
    top: 78px;
    z-index: 10;
    padding-block: 14px;
    border-bottom: 1px solid var(--line);
    background: var(--glass);
    backdrop-filter: saturate(180%) blur(10px);
}

.ui-index ul {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.ui-index a {
    display: inline-block;
    padding: 6px 14px;
    border: 1px solid var(--line);
    border-radius: var(--r-pill);
    color: var(--ink-2);
    font-size: .82rem;
}

.ui-index a:hover {
    border-color: var(--brand);
    background: var(--brand-soft);
    color: var(--brand-text);
}

/* one component per group */
.ui-group {
    padding-top: clamp(48px, 6vw, 80px);
}

.ui-group__head {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 24px;
    padding-bottom: 16px;
    margin-bottom: 28px;
    border-bottom: 2px solid var(--line-strong);
}

.ui-group__head h2 {
    margin-bottom: 0;
    font-size: clamp(1.5rem, 2.6vw, 2rem);
}

.ui-group__head p {
    max-width: 46ch;
    color: var(--muted);
    font-size: .9rem;
}

/* the framed area a demo sits in */
.ui-demo {
    padding: 28px;
    border: 1px solid var(--line);
    border-radius: var(--r);
    background: var(--paper);
}

.ui-demo + .ui-demo {
    margin-top: 20px;
}

.ui-demo--mist {
    background: var(--mist);
}

.ui-demo--ink {
    background: var(--band);
}

/* the container demo needs the full demo width to read truthfully */
.ui-demo--flush {
    padding-inline: 0;
}

.ui-demo--flush > .ui-label {
    padding-inline: 28px;
}

.ui-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 14px;
}

.ui-stack > * + * {
    margin-top: 14px;
}

.ui-label {
    display: block;
    margin-bottom: 14px;
    color: var(--muted);
    font-size: .71rem;
    font-weight: 600;
    letter-spacing: .14em;
    text-transform: uppercase;
}

.ui-demo--ink .ui-label {
    color: rgba(255, 255, 255, .6);
}

/* the class name that produces the thing above it */
.ui-code {
    display: inline-block;
    padding: 2px 8px;
    border-radius: 5px;
    background: var(--mist);
    color: var(--brand-text);
    font-family: var(--font-mono);
    font-size: .78rem;
}

.ui-demo--mist .ui-code {
    background: var(--paper);
}

.ui-note {
    margin-top: 14px;
    color: var(--muted);
    font-size: .85rem;
}

/* --- colour swatches -------------------------------------------------- */
.swatches {
    display: grid;
    grid-template-columns: repeat(6, 1fr);
    gap: 18px;
}

.swatch__chip {
    height: 92px;
    margin-bottom: 12px;
    border: 1px solid var(--line);
    border-radius: var(--r);
}

.swatch__name {
    display: block;
    color: var(--ink);
    font-size: .87rem;
    font-weight: 600;
}

.swatch__hex {
    display: block;
    color: var(--muted);
    font-family: var(--font-mono);
    font-size: .76rem;
}

.swatch--brand      .swatch__chip { background: var(--brand); }
.swatch--brand-fill .swatch__chip { background: var(--brand-fill); }
.swatch--brand-hover .swatch__chip { background: var(--brand-hover); }
.swatch--brand-text .swatch__chip { background: var(--brand-text); }
.swatch--brand-soft .swatch__chip { background: var(--brand-soft); }
.swatch--ink        .swatch__chip { background: var(--band); }
.swatch--ink-2      .swatch__chip { background: var(--ink-2); }
.swatch--muted      .swatch__chip { background: var(--muted); }
.swatch--paper      .swatch__chip { background: var(--paper); }
.swatch--sand       .swatch__chip { background: var(--sand); }
.swatch--mist       .swatch__chip { background: var(--mist); }
.swatch--line       .swatch__chip { background: var(--line); }
.swatch--gold       .swatch__chip { background: var(--gold); }
.swatch--danger     .swatch__chip { background: var(--danger); }

/* --- type specimen ---------------------------------------------------- */
.specimen li {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 32px;
    padding: 16px 0;
    border-bottom: 1px solid var(--line-soft);
}

.specimen li:last-child {
    border-bottom: 0;
}

.specimen__demo {
    min-width: 0;
}

.specimen__demo > * {
    margin-bottom: 0;
}

.specimen__meta {
    flex: none;
    color: var(--muted);
    font-family: var(--font-mono);
    font-size: .76rem;
    text-align: right;
}

/* --- icon set --------------------------------------------------------- */
.icon-grid {
    display: grid;
    grid-template-columns: repeat(8, 1fr);
    gap: 14px;
}

.icon-tile {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    padding: 18px 8px;
    border: 1px solid var(--line);
    border-radius: var(--r-sm);
    text-align: center;
}

.icon-tile svg {
    width: 24px;
    height: 24px;
    color: var(--brand-text);
}

.icon-tile span {
    color: var(--muted);
    font-family: var(--font-mono);
    font-size: .7rem;
    word-break: break-word;
}

/* --- spacing + radius scales ------------------------------------------ */
.scale-row {
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 9px 0;
}

.scale-row__bar {
    height: 16px;
    border-radius: 3px;
    background: var(--brand-soft);
    border: 1px solid var(--brand);
}

.scale-row__name {
    width: 130px;
    flex: none;
    font-family: var(--font-mono);
    font-size: .78rem;
    color: var(--ink);
}

.radius-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 18px;
    text-align: center;
}

.radius-tile {
    height: 86px;
    margin-bottom: 10px;
    border: 1px solid var(--brand);
    background: var(--brand-soft);
}

.radius-tile--sm   { border-radius: var(--r-sm); }
.radius-tile--md   { border-radius: var(--r); }
.radius-tile--lg   { border-radius: var(--r-lg); }
.radius-tile--pill { border-radius: var(--r-pill); }

/* --- container demo --------------------------------------------------- */
.container-demo {
    padding: 12px;
    margin-bottom: 10px;
    border: 1px dashed var(--brand);
    border-radius: var(--r-sm);
    background: var(--brand-soft);
    color: var(--brand-text);
    font-family: var(--font-mono);
    font-size: .76rem;
    text-align: center;
}

/* --- grid demo -------------------------------------------------------- */
.grid-demo {
    padding: 22px 10px;
    border-radius: var(--r-sm);
    background: var(--brand-soft);
    color: var(--brand-text);
    font-family: var(--font-mono);
    font-size: .78rem;
    text-align: center;
}


/* =========================================================================
   33. HOMEPAGE 3 — avant-garde
   A quieter, more editorial take: type does the work, chrome is reduced to
   hairlines and numerals, listings are an index rather than a grid. Reuses
   the slide machinery from 09b, so no extra JS. Used by index-3.html.
   ========================================================================= */

/* --- hero ---------------------------------------------------------------- */
/* the top bar and header sit above the hero, so subtract them or the
   slider runs past the fold and the slide index needs scrolling to reach */
.hero-3 {
    --hero-offset: 123px;

    position: relative;
    background: var(--band);
}

/* no overflow here on purpose — the slides clip themselves, and the
   advanced filter panel has to be able to hang below the fold */
.hero-3__stage {
    position: relative;
    height: calc(100vh - var(--hero-offset));
    height: calc(100svh - var(--hero-offset));
    min-height: 480px;
}

/* no copy on the slides — the search is the whole hero. It sits above
   centre rather than on it, so the advanced panel has somewhere to open */
.hero-3__inner {
    position: absolute;
    inset: 0;
    z-index: 5;
    display: flex;

    /* a column so the optional headline can sit above the search; with no
       headline there is one child and the gap never applies */
    flex-direction: column;
    gap: clamp(24px, 4vw, 44px);
    align-items: center;
    justify-content: center;
    padding: clamp(40px, 6vw, 72px) var(--gutter) clamp(160px, 26vh, 300px);
    pointer-events: none;
}

.hero-3__inner > .hero-lede {
    width: min(100%, 940px);
}

.hero-3__inner > * {
    pointer-events: auto;
}

.hero-3__search {
    width: min(100%, 680px);
}

/* the slide index, borrowed from the slider dots and set as numerals,
   pinned to the floor of the frame so it stays clear of the search */
.hero-3 .hero-slider__dots {
    position: absolute;
    left: 50%;
    bottom: clamp(24px, 4vw, 40px);
    z-index: 6;
    gap: 20px;
    transform: translateX(-50%);
}

.hero-3 .hero-slider__dot {
    width: auto;
    height: auto;
    padding-bottom: 6px;
    border-radius: 0;
    border-bottom: 1px solid transparent;
    background: none;
    color: rgba(255, 255, 255, .45);
    font-family: var(--font-display);
    font-size: .95rem;
    letter-spacing: .08em;
}

.hero-3 .hero-slider__dot:hover {
    background: none;
    color: var(--white);
}

.hero-3 .hero-slider__dot.is-active {
    width: auto;
    background: none;
    color: var(--white);
    border-bottom-color: var(--brand);
}

/* --- statement ----------------------------------------------------------- */
.statement {
    display: grid;
    grid-template-columns: 1fr 1.5fr;
    gap: clamp(24px, 5vw, 72px);
    align-items: start;
}

.statement__label {
    padding-top: 12px;
    border-top: 1px solid var(--line-strong);
    color: var(--muted);
    font-size: .74rem;
    font-weight: 500;
    letter-spacing: .22em;
    text-transform: uppercase;
}

.statement__text {
    margin: 0;
    color: var(--ink);
    font-family: var(--font-display);
    font-size: clamp(1.35rem, 2.6vw, 2.1rem);
    font-weight: 500;
    line-height: 1.3;
    letter-spacing: -.025em;
}

.statement__text + .statement__text {
    margin-top: 1em;
    color: var(--muted);
    font-family: var(--font-body);
    font-size: 1rem;
    font-weight: 400;
    line-height: 1.7;
    letter-spacing: 0;
}

/* --- property index ------------------------------------------------------ */
.index-list {
    border-top: 1px solid var(--line-strong);
}

.index-row {
    position: relative;
    display: grid;
    grid-template-columns: 44px 104px 1fr auto auto;
    gap: clamp(14px, 3vw, 40px);
    align-items: center;
    padding: 20px 0;
    border-bottom: 1px solid var(--line);
    transition: padding var(--t);
}

/* the row breathes outward under the cursor instead of filling in */
.index-row:hover {
    padding-inline: 10px;
}

.index-row__no {
    color: var(--muted);
    font-family: var(--font-mono);
    font-size: .76rem;
}

.index-row__thumb {
    aspect-ratio: 4 / 3;
    border-radius: var(--r-sm);
    background: var(--mist);
    overflow: hidden;
}

.index-row__thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform .5s ease;
}

.index-row:hover .index-row__thumb img {
    transform: scale(1.07);
}

.index-row__title {
    margin: 0;
    color: var(--ink);
    font-family: var(--font-display);
    font-size: clamp(1.05rem, 1.8vw, 1.4rem);
    font-weight: 600;
    letter-spacing: -.025em;
}

.index-row__title a {
    color: inherit;
}

/* same stretched link as the cards: the whole row is the target */
.index-row__title a::after {
    content: "";
    position: absolute;
    inset: 0;
}

.index-row__where {
    margin: 4px 0 0;
    color: var(--muted);
    font-size: .86rem;
}

.index-row__meta {
    color: var(--ink-2);
    font-size: .88rem;
    white-space: nowrap;
}

.index-row__price {
    color: var(--ink);
    font-family: var(--font-display);
    font-size: clamp(1.05rem, 1.8vw, 1.35rem);
    font-weight: 600;
    letter-spacing: -.02em;
    white-space: nowrap;
}

/* --- oversized figures --------------------------------------------------- */
.figures {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: clamp(20px, 4vw, 48px);
}

.figures li {
    padding-top: 22px;
    border-top: 1px solid var(--line-strong);
}

.figures strong {
    display: block;
    color: var(--ink);
    font-family: var(--font-display);
    font-size: clamp(2rem, 5vw, 3.4rem);
    font-weight: 600;
    line-height: 1;
    letter-spacing: -.045em;
}

.figures span {
    display: block;
    margin-top: 12px;
    color: var(--muted);
    font-size: .78rem;
    letter-spacing: .16em;
    text-transform: uppercase;
}


/* =========================================================================
   34. RESPONSIVE
   Breakpoints: 1100 (tablet landscape), 900 (tablet), 640 (phone)
   ========================================================================= */
@media (max-width: 1100px) {

    .search-form {
        grid-template-columns: 1fr 1fr;
    }

    .search-form .field + .field {
        box-shadow: none;
    }

    .search-form__submit {
        grid-column: 1 / -1;
        padding: 4px 8px 8px;
    }

    /* a hero clips its contents, and down here the panel is far taller than
       the hero is — hanging it off the form leaves most of it cut off. As a
       sheet pinned to the viewport it escapes the clip and can scroll. */
    .search-bar__more {
        position: fixed;
        top: auto;
        left: 12px;
        right: 12px;
        bottom: 12px;
        z-index: var(--z-drawer);
        max-height: 78vh;
        overflow-y: auto;
        overscroll-behavior: contain;
    }

    .search-bar__more-close {
        display: inline-flex;
    }

    /* The sheet is fixed but lives inside .hero-slider__overlay, which has a
       z-index of its own — so nothing the sheet sets can lift it over the
       slider's arrows or a floating button anchored outside the hero. They
       step aside instead: neither belongs on top of an open sheet.
       Driven by a body class rather than :has(), which has to re-evaluate
       on every class change and is the one thing here that has to be sure. */
    body.is-filtering .hero-slider__controls,
    body.is-filtering .wa-float {
        display: none;
    }

    /* room for the close button, so the first heading does not sit under it */
    .search-bar__more-grid {
        grid-template-columns: 1fr;
        gap: 18px;
        padding-top: 28px;
    }

    .hero-search__row {
        grid-template-columns: 1fr 1fr;
    }

    .card-rail__track {
        grid-auto-columns: calc((100% - 56px) / 3);
    }

    /* the filter bar wraps to two rows at this width */
    .map-search {
        --map-top: 258px;
    }

    .hero-search__submit {
        grid-column: 1 / -1;
        padding-block: 14px;
    }

    .layout-sidebar,
    .layout-sidebar--right {
        grid-template-columns: 1fr;
    }

    .sidebar {
        position: static;
    }

    .footer-grid {
        grid-template-columns: 1fr 1fr;
    }
}

@media (max-width: 900px) {

    /* swap desktop nav for the drawer */
    .nav,
    .header-phone,
    .topbar {
        display: none;
    }

    .nav-toggle {
        display: inline-flex;
    }

    /* the icon says it on its own here; the word is what crowds the bar
       against the burger */
    .header-login span {
        display: none;
    }

    .header-login {
        gap: 0;
        width: 38px;
        height: 38px;
        padding: 0;
    }

    .site-header__inner {
        min-height: 68px;
    }

    .page-nav {
        top: 68px;
    }

    .map-bar {
        top: 68px;
    }

    .map-search {
        grid-template-columns: 1fr;
    }

    /* a sticky map would eat the screen once the columns stack */
    .map-search__map {
        position: static;
        height: 380px;
        order: -1;
    }

    .map-canvas {
        border-left: 0;
        border-bottom: 1px solid var(--line);
    }

    /* the sidebar panel becomes the sliding drawer */
    .filter-drawer--inline {
        position: fixed;
        top: 0;
        left: 0;
        bottom: 0;
        width: min(350px, 88vw);
        border: 0;
        border-radius: 0;
        transform: translateX(-100%);
    }

    .filter-drawer--inline .filter-drawer__body {
        overflow-y: auto;
    }

    .filter-drawer--inline .filter-drawer__close {
        display: inline-flex;
    }

    .filters-trigger {
        display: inline-flex;
    }

    /* the top bar is hidden here and the header is shorter */
    .hero-3 {
        --hero-offset: 69px;
    }

    .statement,
    .figures {
        grid-template-columns: 1fr 1fr;
    }

    .index-row {
        grid-template-columns: 36px 84px 1fr auto;
    }

    .index-row__meta {
        display: none;
    }

    /* the mosaic becomes a hero image with a strip beneath it */
    .gallery-mosaic {
        grid-template-columns: repeat(4, 1fr);
    }

    .gallery-mosaic__main {
        grid-column: 1 / -1;
        grid-row: auto;
        aspect-ratio: 3 / 2;
    }

    /* the hero and its strip carry their own ratios here, so the small counts
       hand the height back to the cells */
    .gallery-mosaic--1,
    .gallery-mosaic--2,
    .gallery-mosaic--3,
    .gallery-mosaic--4 {
        grid-template-rows: auto;
        aspect-ratio: auto;
    }

    .gallery-mosaic--1 .gallery-mosaic__cell,
    .gallery-mosaic--2 .gallery-mosaic__cell,
    .gallery-mosaic--3 .gallery-mosaic__cell,
    .gallery-mosaic--4 .gallery-mosaic__cell {
        aspect-ratio: 3 / 2;
    }

    .listing-actions {
        grid-template-columns: 1fr;
    }

    .agent-profile {
        grid-template-columns: 1fr;
    }

    .agent-profile__media {
        width: 100%;
        max-width: 240px;
    }

    .ui-index {
        top: 68px;
    }

    .hero__grid,
    .split,
    .newsletter,
    .cta {
        grid-template-columns: 1fr;
    }

    .split--media-first .split__media {
        order: 0;
    }

    .hero__card {
        left: 16px;
    }

    .grid.col-3,
    .grid.col-4 {
        grid-template-columns: repeat(2, 1fr);
    }

    /* the wide grids step down to three rather than straight to two - they
       hold small items (type icons, figures), so two would leave them huge */
    .grid.col-5,
    .grid.col-6 {
        grid-template-columns: repeat(3, 1fr);
    }

    .section-head {
        flex-direction: column;
        align-items: flex-start;
    }

    .specs,
    .amenities {
        grid-template-columns: repeat(2, 1fr);
    }

    .detail-list {
        grid-template-columns: 1fr;
    }

    .property-card--row {
        flex-direction: column;
    }

    .property-card--row .property-card__media {
        flex: none;
        aspect-ratio: 3 / 2;
    }

    .gallery__thumbs {
        grid-auto-columns: calc((100% - 36px) / 4);
    }

    .hero-slider__stage {
        min-height: 660px;
    }

    .hero-search__more-inner {
        grid-template-columns: 1fr 1fr;
    }

    .card-rail__track {
        grid-auto-columns: calc((100% - 28px) / 2);
    }

    .swatches,
    .icon-grid {
        grid-template-columns: repeat(4, 1fr);
    }

    .ui-group__head {
        flex-direction: column;
        align-items: flex-start;
    }
}

@media (max-width: 640px) {

    .grid.col-2,
    .grid.col-3,
    .grid.col-4 {
        grid-template-columns: 1fr;
    }

    .grid.col-5,
    .grid.col-6 {
        grid-template-columns: repeat(2, 1fr);
    }

    .search-form {
        grid-template-columns: 1fr;
    }

    .search-bar {
        flex-direction: column;
        align-items: stretch;
        padding: 8px;
        border-radius: var(--r-lg);
    }

    .search-bar__field + .search-bar__field {
        box-shadow: inset 0 1px 0 var(--line);
    }

    .search-bar__submit {
        width: 100%;
        margin-top: 10px;
    }

    /* both buttons stop being icons and become labelled full-width rows */
    .search-bar__btn-label {
        display: inline;
    }

    /* scoped to the bar: it stacks its controls into full-width rows. The
       stacked form shares this button but keeps it a compact icon. */
    .search-minimal .search-bar__filters,
    .search-bar__submit {
        height: 46px;
        font-size: .9rem;
        font-weight: 600;
    }

    .search-minimal .search-bar__filters {
        width: 100%;
        margin-right: 0;
        margin-top: 10px;
        border: 1px solid var(--line);
        background: var(--paper);
        color: var(--ink);
    }

    .search-minimal .search-bar__filters:hover {
        border-color: var(--muted);
        background: var(--paper);
    }

    /* Search takes the room left beside the filters icon */
    .search-form__submit .btn {
        flex: 1;
        justify-content: center;
    }

    .search-bar__more-grid {
        grid-template-columns: 1fr;
    }

    .gallery-mosaic {
        grid-template-columns: repeat(2, 1fr);
    }

    .statement,
    .figures {
        grid-template-columns: 1fr;
    }

    .index-row {
        grid-template-columns: 72px 1fr;
        gap: 16px;
    }

    .index-row__no {
        display: none;
    }

    .index-row__price {
        grid-column: 2;
    }

    /* only two supporting frames fit; the rest live in the lightbox */
    .gallery-mosaic__cell:nth-child(n+4) {
        display: none;
    }

    .hero__proof {
        gap: 24px;
    }

    .hero__card {
        position: static;
        margin-top: 14px;
        box-shadow: var(--shadow);
    }

    .footer-grid,
    .specs,
    .amenities {
        grid-template-columns: 1fr;
    }

    .gallery__thumbs {
        grid-auto-columns: calc((100% - 24px) / 3);
    }

    .footer-bottom {
        flex-direction: column;
        text-align: center;
    }

    .toolbar {
        align-items: flex-start;
    }

    .newsletter__form {
        flex-direction: column;
    }

    .newsletter__form .btn {
        width: 100%;
    }

    /* the stacked panel needs the full stage height */
    .hero-slider__stage {
        min-height: 720px;
    }

    .hero-slider__overlay {
        padding-bottom: 184px;
    }

    .hero-search__row,
    .hero-search__more-inner {
        grid-template-columns: 1fr;
    }

    .hero-search__head {
        flex-direction: column;
        align-items: flex-start;
        gap: 10px;
    }

    .hero-slider__controls {
        bottom: 24px;
    }

    /* one card with the next peeking, so the row reads as scrollable */
    .card-rail__track {
        grid-auto-columns: 86%;
        gap: 16px;
    }

    .lightbox__nav {
        position: absolute;
        bottom: 18px;
    }

    .lightbox__nav--prev { left: 18px; }
    .lightbox__nav--next { right: 18px; }

    .lightbox__image {
        max-height: 68vh;
    }

    .swatches,
    .icon-grid,
    .radius-grid {
        grid-template-columns: repeat(2, 1fr);
    }

    .specimen li {
        flex-direction: column;
        gap: 8px;
    }

    .specimen__meta {
        text-align: left;
    }
}


/* =========================================================================
   35. CENTURY SECTIONS
   The blocks the light theme has no equivalent for: the running order of
   the reference homepage. Everything here is built from the same tokens as
   the rest of the file, so it rebrands with section 01 and nothing else.

   This section carries its own media queries rather than adding to 34, so
   it can be lifted out whole - delete from here to the end of the file and
   the theme still stands, minus these blocks.
   ========================================================================= */

/* --- 35a. watermark section head ---------------------------------------
   The ghost word behind a section title. The text comes from data-watermark
   on the .section-head, so the markup states it once and the CSS draws it.
   The title turns gold here: on the reference site the ghost word and the
   gold title always travel together, so one modifier carries both. */
.section-head--watermark {
    position: relative;
    isolation: isolate;
}

.section-head--watermark::before {
    content: attr(data-watermark);
    position: absolute;
    z-index: -1;
    left: -.035em;
    top: 50%;
    transform: translateY(-78%);
    font-family: var(--font-display);
    font-size: clamp(3.5rem, 9vw, 7.5rem);
    font-weight: 700;
    line-height: 1;
    letter-spacing: -.045em;
    white-space: nowrap;
    color: rgba(255, 255, 255, .045);
    pointer-events: none;
    user-select: none;
}

.section-head--watermark .section-head__title {
    color: var(--brand-text);
}

/* a centred head puts the ghost word behind the middle, not the edge */
.section-head--center.section-head--watermark::before {
    left: 50%;
    transform: translate(-50%, -78%);
}


/* --- 35b. type band -----------------------------------------------------
   The row of property types under the hero. Cells touch and are divided by
   hairlines rather than gaps, so the list takes .grid for its column count
   and drops the gap. Change col-5 in the markup to change the count. */
.type-band {
    background: var(--band);
    border-block: 1px solid var(--line-soft);
}

.type-band__list {
    gap: 0;
}

.type-band__item {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 13px;
    padding: 30px 14px;
    color: var(--ink-2);
    text-align: center;
    transition: background var(--t), color var(--t);
}

/* Each cell is its own <li>, so the anchor is always its parent's first
   child — :first-child on the anchor would match every one of them. The
   divider goes between list items instead. */
.type-band__list > li + li .type-band__item {
    border-left: 1px solid var(--line-soft);
}

.type-band__item:hover {
    background: var(--sand);
    color: var(--brand-text);
}

.type-band__item svg {
    width: 32px;
    height: 32px;
    color: var(--brand);
    transition: transform var(--t);
}

.type-band__item:hover svg {
    transform: translateY(-3px);
}

/* --- swipeable ----------------------------------------------------------
   Same grid, only the flow changes, so the hairlines still divide the cells.
   Applied by the widget past five cells, and below 900 whatever the count. */
.type-band__list--rail {
    grid-template-columns: none;
    grid-auto-flow: column;
    grid-auto-columns: minmax(132px, 1fr);
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x proximity;

    /* a scrollbar under a row this short reads as a broken layout */
    scrollbar-width: none;
}

.type-band__list--rail::-webkit-scrollbar {
    display: none;
}

.type-band__list--rail > li {
    scroll-snap-align: start;
}

.type-band__label {
    font-size: .74rem;
    font-weight: 600;
    letter-spacing: .17em;
    text-transform: uppercase;
}


/* --- 35c. region search -------------------------------------------------
   A town shortlist on one side, a clickable map on the other. The map is an
   ordinary inline SVG: every region is a path carrying data-region, and the
   chip beside it carries the same value, which is all block 29 of main.js
   needs to pair them. */
.region-search__grid {
    display: grid;
    grid-template-columns: 1.05fr .95fr;
    gap: clamp(32px, 5vw, 72px);
    align-items: center;
}

.region-search__panel {
    padding: clamp(26px, 4vw, 46px);
    border: 1px solid var(--line);
    border-radius: var(--r-lg);
    background: var(--paper);
}

.region-search__title {
    margin-bottom: 12px;
}

.region-search__text {
    margin-bottom: 26px;
    color: var(--muted);
}

.region-search__label {
    display: block;
    margin-bottom: 14px;
    color: var(--ink);
    font-size: .82rem;
    font-weight: 600;
    letter-spacing: .12em;
    text-transform: uppercase;
}

.region-search__towns {
    gap: 10px;
    margin-bottom: 26px;
}

.region-town {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 11px 15px;
    border: 1px solid var(--line);
    border-radius: var(--r-sm);
    background: var(--field);
    color: var(--ink-2);
    font-size: .9rem;
    transition: border-color var(--t), background var(--t), color var(--t);
}

.region-town:hover,
.region-town.is-active {
    border-color: var(--brand);
    background: var(--brand-soft);
    color: var(--brand-text);
}

.region-town span {
    color: var(--muted);
    font-size: .8rem;
    font-variant-numeric: tabular-nums;
}

.region-town:hover span,
.region-town.is-active span {
    color: var(--brand-text);
}

.region-map {
    display: flex;
    align-items: center;
    justify-content: center;
}

/* the real outline is a tall, narrow country - sizing it by height keeps it
   beside the panel instead of towering over it */
.region-map svg {
    width: auto;
    max-width: 100%;
    height: clamp(420px, 50vw, 680px);
}

.region-map__area {
    fill: var(--paper-hi);
    stroke: rgba(198, 169, 107, .45);

    /* the viewBox is ~935 units wide drawn at ~300px, so a scaled stroke
       would come out under half a pixel and the borders would vanish */
    stroke-width: 1;
    vector-effect: non-scaling-stroke;
    stroke-linejoin: round;
    cursor: pointer;
    transition: fill var(--t);
}

.region-map__area:hover,
.region-map__area.is-active {
    fill: var(--brand-fill);
}

.region-map__label {
    fill: var(--muted);
    font-family: var(--font-body);
    font-size: 9px;
    font-weight: 600;
    letter-spacing: .05em;
    text-anchor: middle;
    pointer-events: none;
    user-select: none;
}


/* --- 35d. brand band ----------------------------------------------------
   Headline and the letterspaced wordmark side by side, then the city tiles
   underneath. The wordmark is type rather than an image, so it stays crisp
   at any size and is set in the markup where it can be translated. */
.brand-band__head {
    display: grid;
    grid-template-columns: 1fr auto;
    gap: clamp(28px, 5vw, 64px);
    align-items: center;
    margin-bottom: clamp(32px, 4vw, 52px);
}

.brand-band__title {
    max-width: 18ch;
    margin-bottom: 24px;
}

.brand-band__mark {
    font-family: var(--font-display);
    font-size: clamp(1.4rem, 3vw, 2.4rem);
    font-weight: 600;
    line-height: 1.35;
    letter-spacing: .3em;
    text-align: center;
    color: var(--brand-text);
    white-space: pre-line;
    user-select: none;
}

.city-tile {
    position: relative;
    display: block;
    aspect-ratio: 16 / 10;
    border-radius: var(--r);
    overflow: hidden;
}

.city-tile img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform .6s ease;
}

.city-tile:hover img {
    transform: scale(1.06);
}

/* the numbers sit on photography, so the tile carries its own scrim */
.city-tile::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(180deg, rgba(0, 0, 0, .15) 0%, rgba(0, 0, 0, .72) 100%);
}

.city-tile__body {
    position: absolute;
    inset: auto 0 0 0;
    z-index: 1;
    padding: 24px;
    text-align: center;
}

.city-tile__value {
    display: block;
    font-family: var(--font-display);
    font-size: clamp(1.8rem, 3.4vw, 2.8rem);
    font-weight: 700;
    line-height: 1.1;
    letter-spacing: -.03em;
    color: var(--white);
}

.city-tile__name {
    display: block;
    margin-top: 4px;
    color: rgba(255, 255, 255, .82);
    font-size: .9rem;
}


/* --- 35e. sell steps ----------------------------------------------------
   Picture beside a numbered list. The rows are separated by rules rather
   than boxed, so the block reads as one list and not three cards. */
.sell {
    display: grid;
    grid-template-columns: .92fr 1.08fr;
    gap: clamp(32px, 5vw, 68px);
    align-items: center;
}

.sell__media img {
    width: 100%;
    border-radius: var(--r-lg);
}

.sell__title {
    margin-bottom: 28px;
}

.sell__list {
    border-top: 1px solid var(--line);
}

.sell__item {
    display: grid;
    grid-template-columns: auto 1fr;
    align-items: baseline;
    gap: 22px;
    padding: 24px 4px;
    border-bottom: 1px solid var(--line);
    transition: border-color var(--t);
}

.sell__item:hover {
    border-bottom-color: var(--brand);
}

.sell__num {
    font-family: var(--font-display);
    font-size: 1.35rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--brand-text);
}

.sell__step-title {
    margin: 0;
    font-size: 1.1rem;
    letter-spacing: .01em;
    color: var(--ink);
}

.sell__step-text {
    margin: 6px 0 0;
    color: var(--muted);
    font-size: .92rem;
}

.sell__actions {
    margin-top: 30px;
}


/* --- 35f. feature band --------------------------------------------------
   A full-bleed photograph with the agency statement laid over it in a card.
   The picture is set with an inline background-image on the section, so the
   same block serves any page without a class per image. */
.feature-band {
    position: relative;
    padding-block: clamp(72px, 10vw, 150px);
    background-color: var(--band);
    background-size: cover;
    background-position: center;
}

.feature-band::before {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(180deg, rgba(0, 0, 0, .55) 0%, rgba(0, 0, 0, .78) 100%);
}

.feature-band .container {
    position: relative;
}

.feature-band__card {
    max-width: 780px;
    padding: clamp(28px, 4vw, 52px);
    border: 1px solid var(--line);
    border-radius: var(--r-lg);
    background: var(--glass-solid);
}

.feature-band__card h2 {
    margin-bottom: 18px;
}

.feature-band__card p {
    color: var(--ink-2);
}


/* --- 35g. hero lede -----------------------------------------------------
   Optional copy above the search panel in the slider hero. Leave the title
   out and the hero behaves exactly as it does on home 2, imagery only. */
.hero-slider__overlay {
    flex-direction: column;
    gap: clamp(24px, 4vw, 44px);
}

/* No ch here: on the wrapper it resolves against the body's 16px, not the
   headline's, so 30ch came out around 240px and broke the title over five
   lines. The paragraph below sets its own measure in its own font size. */
.hero-lede {
    width: min(100%, 940px);
    margin-inline: auto;
    text-align: center;
}

.hero-lede h1 {
    margin-bottom: 0;
    color: var(--white);
    text-shadow: 0 2px 24px rgba(0, 0, 0, .5);

    /* two lines, split evenly rather than left long-then-short */
    text-wrap: balance;
}

.hero-lede h1 .accent {
    color: var(--brand-text);
}

.hero-lede p {
    max-width: 56ch;
    margin: 16px auto 0;
    color: rgba(255, 255, 255, .82);
}


/* --- 35h. responsive ---------------------------------------------------- */

/* the hero's "Hide on mobile" option. Hidden, not removed: the headline is
   still in the markup for search engines and screen readers, and the flex
   gap around it goes with it so nothing is left holding space. */
@media (max-width: 900px) {

    .hero-lede--desktop {
        display: none;
    }
}

@media (max-width: 1100px) {

    .region-search__grid,
    .sell {
        grid-template-columns: 1fr;
    }

    /* the map leads on a narrow screen: pick a place, then read the list */
    .region-map {
        order: -1;
    }

    .brand-band__head {
        grid-template-columns: 1fr;
    }

    .brand-band__mark {
        text-align: left;
        letter-spacing: .22em;
    }
}

@media (max-width: 900px) {

    /* one line that swipes, rather than wrapping into rows — two classes
       deep so it outranks .grid.col-N */
    .type-band .type-band__list {
        grid-template-columns: none;
        grid-auto-flow: column;
        grid-auto-columns: minmax(128px, 1fr);
        overflow-x: auto;
        overscroll-behavior-x: contain;
        scroll-snap-type: x proximity;
        scrollbar-width: none;
    }

    .type-band .type-band__list::-webkit-scrollbar {
        display: none;
    }

    .type-band .type-band__list > li {
        scroll-snap-align: start;
    }

    .section-head--watermark::before {
        font-size: clamp(3rem, 14vw, 5rem);
    }
}

@media (max-width: 640px) {

    /* narrower cells, so more of the next one peeks in and the row reads
       as something that scrolls */
    .type-band .type-band__list {
        grid-auto-columns: minmax(116px, 1fr);
    }

    .region-search__towns.col-2 {
        grid-template-columns: 1fr;
    }

    .sell__item {
        gap: 14px;
    }
}


/* --- share ------------------------------------------------------------- */

.share {
    position: relative;
}

/* the trigger is a grid cell like its neighbours, so it fills its column */
.share > .btn {
    width: 100%;
}

/* one icon among a row of them, so it must not take a whole line, and its
   menu hangs from the right or it runs off the edge of a right-aligned row */
.share--icon {
    display: inline-flex;
}

.share--icon .share__menu {
    left: auto;
    right: 0;
}

.share__menu {
    position: absolute;
    top: calc(100% + 8px);
    left: 0;
    z-index: 60;
    min-width: 220px;
    padding: 6px;
    border: 1px solid var(--line);
    border-radius: var(--r-lg);
    background: var(--paper);
    box-shadow: var(--shadow-lg);
}

.share__item {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 10px 12px;
    border: 0;
    border-radius: var(--r-sm);
    background: none;
    color: var(--ink);
    font-size: .9rem;
    text-align: left;
    transition: background var(--t);
}

.share__item:hover {
    background: var(--mist);
    color: var(--ink);
}

.share__item svg {
    width: 17px;
    height: 17px;
    flex: none;
    color: var(--muted);
}

/* the icon-only heart, same saved state as the one on a card */
.property-head__actions .icon-btn.is-active {
    border-color: var(--brand);
    background: var(--brand-fill);
    color: var(--on-brand);
}

.property-head__actions .icon-btn.is-active svg {
    fill: currentColor;
}

/* saved: the heart fills in and the button takes the brand tint, so the
   state is readable without relying on the word alone */
.listing-actions .btn.is-active {
    border-color: var(--brand);
    background: var(--brand-soft);
    color: var(--brand-text);
}

.listing-actions .btn.is-active svg {
    fill: currentColor;
}

/* =========================================================================
   36. FLOATING WHATSAPP
   Size and position are per-install, so the Whatsapp tab writes those five
   properties inline and everything else lives here. Any value the tenant
   leaves blank simply falls through to these defaults.
   ========================================================================= */
.wa-float {
    position: fixed;
    right: var(--float-x);
    translate: 50% 0;
    bottom: 24px;

    /* under the drawer and the filter sheet: a chat button has no business
       sitting on top of whatever the reader just opened */
    z-index: calc(var(--z-drawer) - 50);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 56px;
    height: 56px;
    border-radius: var(--r-pill);
    border: 1px solid var(--brand);
    background: var(--brand-fill);
    color: var(--on-brand);
    box-shadow: var(--shadow);
    transition: transform var(--t), background var(--t), box-shadow var(--t);
}

.wa-float svg {
    width: 60%;
    height: 60%;
}

.wa-float:hover {
    background: var(--brand-hover);
    color: var(--on-brand);
    transform: translateY(-2px) scale(1.04);
    box-shadow: var(--shadow-lg);
}

/* Back to top is fixed to the same corner, so it steps above the chat
   button - but only when there is one, otherwise it would float clear of
   the corner for no reason. On a browser without :has() the two overlap,
   which is the one thing that degrades here. */
body:has(.wa-float) .to-top {
    bottom: 92px;
}

@media (max-width: 640px) {

    :root {
        --float-x: 41px;
    }

    .wa-float {
        bottom: 16px;
        width: 50px;
        height: 50px;
    }

    body:has(.wa-float) .to-top {
        bottom: 78px;
    }
}


/* =========================================================================
   37. LANGUAGE SWITCHER
   An ordinary menu item, so it inherits .nav__link and .dropdown. Only the
   flag and the dropdown's width are particular to it.
   ========================================================================= */
.lang__flag {
    width: 18px;
    height: 12px;
    flex: none;
    border-radius: 2px;

    /* flags are light rectangles on a dark bar; a hairline stops them glowing */
    box-shadow: 0 0 0 1px rgba(255, 255, 255, .18);
    object-fit: cover;
}

.nav__item--lang .nav__link {
    gap: 8px;
}

.dropdown--lang {
    min-width: 172px;
}

.dropdown--lang a {
    display: flex;
    align-items: center;
    gap: 10px;
}

/* --- in the drawer ------------------------------------------------------ */
.lang-row {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 22px;
    padding-top: 22px;
    border-top: 1px solid var(--line);
}

/* scoped to the drawer, which is the only place it is used - and which
   styles every link as a full-width list row unless told otherwise */
.mobile-nav .lang-row__item {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 9px 14px;
    border: 1px solid var(--line);
    border-radius: var(--r-pill);
    color: var(--ink-2);
    font-size: .88rem;
    font-weight: 500;
    transition: border-color var(--t), background var(--t), color var(--t);
}

.mobile-nav .lang-row__item:hover {
    border-color: var(--brand);
    color: var(--brand-text);
}

.mobile-nav .lang-row__item.is-active {
    border-color: var(--brand);
    background: var(--brand-soft);
    color: var(--brand-text);
}


/* =========================================================================
   38. PRINT
   Ported from the light theme, plus the token flip a dark theme needs.
   ========================================================================= */
@media print {

    /* Everything in this theme reads a token tuned for a black page. Browsers
       do not print backgrounds by default, so without flipping these the
       Print button would hand over a sheet of white text on white paper.
       Redefining the tokens fixes every component at once. */
    :root {
        --ground:      #FFFFFF;
        --band:        #FFFFFF;
        --sand:        #FFFFFF;
        --mist:        #FFFFFF;
        --paper:       #FFFFFF;
        --paper-hi:    #FFFFFF;
        --field:       #FFFFFF;
        --field-hi:    #FFFFFF;
        --glass:       #FFFFFF;
        --glass-solid: #FFFFFF;

        --ink:         #000000;
        --ink-2:       #1A1A1A;
        --muted:       #555555;
        --white:       #000000;

        --brand:       #7A6636;
        --brand-fill:  #FFFFFF;
        --brand-text:  #6B5A2E;
        --brand-soft:  #FFFFFF;
        --on-brand:    #000000;

        --line:        #CCCCCC;
        --line-soft:   #DDDDDD;
        --line-strong: #999999;

        --shadow-sm:   none;
        --shadow:      none;
        --shadow-lg:   none;
    }

    /* the floating chat button is a screen control */
    .wa-float {
        display: none !important;
    }

    .topbar,
    .site-header,
    .mobile-nav,
    .nav-backdrop,
    .page-nav,
    .listing-actions,
    .property-head__actions,
    .gallery__strip,
    .site-footer,
    .to-top,
    .lightbox,
    .filter-drawer,
    .filter-backdrop,
    .section--mist,
    .map-frame,
    .gallery-mosaic__all,
    .share__menu {
        display: none !important;
    }

    /* the booking form is a screen control; the agent's details are not */
    .sidebar .panel:has(form),
    .sidebar form {
        display: none !important;
    }

    body {
        background: #fff;
        color: #000;
        font-size: 11pt;
    }

    /* two columns of a screen layout become one column of paper */
    .layout-sidebar,
    .layout-sidebar--right,
    .grid.col-2,
    .grid.col-3,
    .grid.col-4 {
        display: block !important;
    }

    .sidebar {
        position: static !important;
        margin-top: 18pt;
    }

    .section,
    .section--tight {
        padding-block: 0 !important;
    }

    .container {
        max-width: none;
        padding: 0;
    }

    /* no shadows or tints survive a printer usefully */
    .panel,
    .detail-block {
        box-shadow: none !important;
        background: none !important;
        border-color: #ccc !important;
    }

    /* keep a heading with the text under it */
    .detail-block,
    .panel,
    figure,
    img {
        break-inside: avoid;
        page-break-inside: avoid;
    }

    h1, h2, h3 {
        break-after: avoid;
        page-break-after: avoid;
    }

    /* the lead photo is worth printing, the other tiles are not */
    .gallery-mosaic__cell:not(.gallery-mosaic__main) {
        display: none !important;
    }

    .gallery-mosaic {
        display: block !important;
    }

    .gallery-mosaic img {
        max-height: 90mm;
        object-fit: cover;
    }

    a[href^="http"]::after {
        content: " (" attr(href) ")";
        font-size: 9pt;
        color: #555;
    }

    /* but not for every link in the body copy */
    .detail-block a[href^="http"]::after,
    .breadcrumb a::after {
        content: "";
    }
}


/* =========================================================================
   39. SELECT MENU
   A list drawn in the page rather than by the browser, so the row under the
   pointer can carry the theme. The closed control deliberately matches
   .hero-search .select to the pixel — swapping one for the other should not
   move anything.
   ========================================================================= */
.select-menu {
    position: relative;
}

.select-menu__toggle {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    width: 100%;
    padding: 0;
    border: 0;
    background: none;
    color: var(--ink);
    font: inherit;
    font-size: .94rem;
    font-weight: 500;
    line-height: 1.5;
    text-align: left;
}

.select-menu__toggle > span {
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}

.select-menu__caret {
    width: 14px;
    height: 14px;
    flex: none;
    color: var(--muted);
    transition: transform var(--t);
}

.select-menu.is-open .select-menu__caret {
    transform: rotate(180deg);
}

.select-menu__list {
    position: absolute;
    top: calc(100% + 12px);
    left: -14px;
    right: -14px;
    z-index: var(--z-drawer);
    max-height: 280px;
    padding: 6px;
    border: 1px solid var(--line);
    border-radius: var(--r);
    background: var(--paper);
    box-shadow: var(--shadow-lg);
    overflow-y: auto;
    overscroll-behavior: contain;
}

/* the box above a long list. Sticky, so it stays put while the options
   scroll under it, and it scrolls with nothing of its own behind it */
.select-menu__filter {
    position: sticky;
    top: -6px;
    z-index: 1;
    display: flex;
    align-items: center;
    gap: 8px;
    margin: -6px -6px 6px;
    padding: 10px 14px;
    border-bottom: 1px solid var(--line);
    background: var(--paper);
}

.select-menu__filter svg {
    width: 15px;
    height: 15px;
    flex: none;
    color: var(--muted);
}

.select-menu__filter input {
    width: 100%;
    border: 0;
    background: none;
    color: var(--ink);
    font: inherit;
    font-size: .9rem;
    outline: 0;
}

.select-menu__option {
    display: block;
    width: 100%;
    padding: 9px 12px;
    border: 0;
    border-radius: var(--r-sm);
    background: none;
    color: var(--ink-2);
    font: inherit;
    font-size: .9rem;
    text-align: left;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    transition: background var(--t), color var(--t);
}

/* the whole point of the exercise: this row is ours to colour */
.select-menu__option:hover,
.select-menu__option:focus-visible {
    background: var(--brand-fill);
    color: var(--white);
    outline: none;
}

.select-menu__option.is-active {
    background: var(--brand-soft);
    color: var(--brand-text);
    font-weight: 600;
}

.select-menu__option.is-active:hover {
    background: var(--brand-fill);
    color: var(--white);
}

/* the field owns the focus ring, so the button inside must not draw its own */
.select-menu__toggle:focus-visible {
    outline: none;
}

/* --- boxed ---------------------------------------------------------------
   For a menu that stands on its own rather than inside a field: it has to
   look like the control it replaces, not like a label. */
.select-menu--boxed .select-menu__toggle {
    padding: 9px 14px;
    border: 1px solid var(--line);
    border-radius: var(--r-sm);
    background: var(--field);
    font-size: .88rem;
    line-height: 1.5;
    transition: border-color var(--t), background var(--t);
}

.select-menu--boxed .select-menu__toggle:hover,
.select-menu--boxed.is-open .select-menu__toggle {
    border-color: var(--brand);
    background: var(--field-hi);
}

.select-menu--boxed .select-menu__list {
    left: 0;
    right: 0;
    min-width: 190px;
}

@media (max-width: 900px) {

    .select-menu__list {
        left: 0;
        right: 0;
    }
}


/* =========================================================================
   40. SEARCH FORM — WIDE
   One keyword field with the filters folded away behind it. The panel is
   .search-bar__more, so everything section 10b already says about opening,
   closing and the mobile sheet applies here too — only the bar and the tab
   row are new.
   ========================================================================= */
.search-wide {
    width: min(100%, 900px);
    margin-inline: auto;
}

/* --- the bar ------------------------------------------------------------ */

/* the panel hangs off this, so it is the positioning context */
.search-wide__form {
    position: relative;
}

.search-wide__bar {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 8px 8px 20px;
    border: 1px solid var(--line);
    border-radius: var(--r-lg);
    background: var(--paper);
    box-shadow: var(--shadow);
    transition: border-color var(--t);
}

.search-wide__bar:focus-within {
    border-color: var(--brand);
}

.search-wide__icon {
    width: 19px;
    height: 19px;
    flex: none;
    color: var(--brand);
}

.search-wide__input {
    flex: 1;
    min-width: 0;
    padding: 12px 0;
    border: 0;
    background: none;
    color: var(--ink);
    font: inherit;
    font-size: .96rem;
}

.search-wide__input::placeholder {
    color: var(--muted);
}

.search-wide__input:focus {
    outline: none;
}

/* the browser's own clear cross sits badly in a bar this dark */
.search-wide__input::-webkit-search-cancel-button {
    appearance: none;
}

/* a hairline rather than a box, so it reads as part of the bar and not as a
   second control dropped into it */
.search-wide__nature {
    flex: none;
    width: 168px;
    padding-left: 18px;
    border-left: 1px solid var(--line-strong);
}

.search-wide__toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 42px;
    height: 42px;
    flex: none;
    padding: 0;
    border: 1px solid var(--line);
    border-radius: var(--r-pill);
    background: none;
    color: var(--ink-2);
    transition: border-color var(--t), background var(--t), color var(--t);
}

.search-wide__toggle:hover,
.search-wide__form.is-open .search-wide__toggle {
    border-color: var(--brand);
    background: var(--brand-soft);
    color: var(--brand-text);
}

.search-wide__toggle svg {
    width: 18px;
    height: 18px;
}

.search-wide__submit {
    flex: none;
}

/* --- the panel ----------------------------------------------------------- */
.search-wide__filters-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    margin-bottom: 18px;
}

.search-wide__filters-title {
    margin: 0;
    font-size: 1.05rem;
    letter-spacing: .01em;
}

/* this panel is titled, so unlike the shared one its close is always shown */
.search-wide__filters-close {
    width: 36px;
    height: 36px;
}

.search-wide__filters-close svg {
    width: 16px;
    height: 16px;
}

.search-wide__filters-grid {
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    gap: 12px;
}

.search-wide__filters-grid .field {
    margin: 0;
}


/* --- responsive ---------------------------------------------------------- */
@media (max-width: 900px) {

    .search-wide__filters-grid {
        grid-template-columns: repeat(2, 1fr);
    }

    /* the area picker leads, so it takes the full width above the pairs */
    .search-wide__filters-grid .field:first-child {
        grid-column: 1 / -1;
    }
}

@media (max-width: 640px) {

    .search-wide__bar {
        flex-wrap: wrap;
        padding: 12px;
        row-gap: 12px;
    }

    .search-wide__icon {
        display: none;
    }

    .search-wide__input {
        flex: 1 1 100%;
        padding: 0 0 10px;
        border-bottom: 1px solid var(--line-soft);
    }

    /* stacked, so the divider becomes a rule under the row above it */
    .search-wide__nature {
        width: 100%;
        padding: 0 0 10px;
        border-left: 0;
        border-bottom: 1px solid var(--line-soft);
    }

    /* the button takes the room left beside the filters icon */
    .search-wide__submit {
        flex: 1;
        justify-content: center;
    }
}
