/*
 * Hagzi property channel — search-results and listing-detail page styles.
 *
 * SEPARATE FILE ON PURPOSE. property.css was being edited by another session
 * while these pages were built, so nothing here was added to that file. This
 * one is loaded by a single <link> in
 * resources/themes/property/views/components/layouts/footer/styles.blade.php,
 * immediately after property.css, using the same filemtime cache-buster.
 *
 * Plain CSS served straight out of public/, deliberately outside the Vite
 * pipeline. The Shop package's vite config carries emptyOutDir: true and the
 * live cars bundle in public/themes/shop/default/build cannot be regenerated,
 * so no file in this theme may ever require an asset build. Nothing here does.
 *
 * SCOPING CONTRACT — this stylesheet loads on EVERY page of the property
 * channel, including the homepage, which another session owns. Therefore:
 *   - every selector begins with .hzp-, or is a descendant of .hzp-page;
 *   - there are no bare element selectors, no :root block and no overrides of
 *     any .hz-* class.
 * The homepage's rendered HTML must be unchanged by this file's presence.
 *
 * Colour: the channel's primary #0745D9 for accents, black for headings, mid
 * grey for secondary text, light neutral greys for borders and fills.
 *
 * THIS PARAGRAPH USED TO SAY THE OPPOSITE, AND IS CORRECTED RATHER THAN QUIETLY
 * REPLACED. It read "Hagzi red for accents ... deliberately no purple — the
 * layout follows the Zoopla reference, the palette does not". That was true the
 * day it was written and was contradicted by this file's own last six hundred
 * lines from the day the purple landed. A header that states the wrong palette
 * with confidence is worse than no header, because it tells the next reader not
 * to check: two links in this theme's header and footer spent a redirect on
 * every click for months because a comment explained, correctly at the time,
 * why they should not.
 *
 * THE --hzp-red* NAMES ARE MISNOMERS. --hzp-red, --hzp-red-dark and
 * --hzp-red-tint all resolve to the accent, which is blue. They kept the old
 * names because renaming means editing thirty-four call sites in the most
 * contended stylesheet in this theme without changing one rendered pixel. If
 * you are reading one of those names and expecting red, this is where you are
 * meant to find out otherwise; the note on the declarations themselves says the
 * same thing.
 *
 * THE RED THAT IS STILL RED IS ELSEWHERE, and none of it is reachable from
 * here: --hz-red in property.css is the warning red, --hzf-red carries the
 * error and validation states on the Add Listing form, and --hzfav-saved
 * (#e11d48) is the crimson of a saved favourite.
 *
 * Tokens defer to property.css's --hagzi-* and --hz-* so the two files cannot
 * drift, and carry literal fallbacks so these pages still render if that file
 * changes.
 */

.hzp-page {
    /* ------------------------------------------------------------------
       THESE THREE ARE THE PRIMARY NOW. THE NAMES ARE KEPT ON PURPOSE.

       The block at the end of this file repainted the accent blue by
       overriding rules rather than by editing them, which left two sets of
       declarations: eighteen that a later rule already wins, and a dozen
       that nothing overrides and which were still painting #d92228 -- the
       filter checkboxes' accent-color, the search submit's focus ring, the
       feature and address and map-pin icon strokes, the range thumb's glow,
       and the rail arrow's hover border. Redefining here fixes all of them
       at once and leaves the eighteen dead ones agreeing with the override
       instead of contradicting it, so removing an override later cannot
       bring the red back.

       Renaming to --hzp-accent would read better and would mean editing
       thirty-four call sites in the most contended sheet in the theme, for
       no change in output. The names stay; this note is the apology.

       SAFE TO DO BECAUSE IT WAS CHECKED, NOT ASSUMED:
         - every remaining use is an accent. No error, validation or warning
           state reads any of these. The one thing that ever used the tint is
           .hzp-calc__out, the mortgage panel, and a later rule already gives
           it the blue wash;
         - nothing derives from them. --hzf-red, which DOES carry error states
           on the Add Listing form, is taken off --hz-red directly and is not
           reachable from here;
         - --hz-red itself is untouched and still means the warning red.

       Contrast improves everywhere the colour carries meaning, measured
       rather than assumed: white on the fill and the accent on white both go
       4.99:1 -> 7.34:1, and .hzp-calc__amount on its own panel is 6.60:1,
       which keeps it over AA for body text.
       ------------------------------------------------------------------ */
    --hzp-red: var(--hzp-accent, var(--hagzi-primary, #0745D9));
    --hzp-red-dark: var(--hzp-accent-dark, var(--hagzi-primary-dark, #0638B0));
    --hzp-red-tint: var(--hzp-accent-wash, #EEF3FF);
    --hzp-ink: var(--hz-ink, #12141a);
    --hzp-body: #3c414c;
    --hzp-muted: #6b7280;
    --hzp-line: var(--hz-line, #e7e9ee);
    --hzp-line-strong: #d6dae1;
    --hzp-fill: #f4f5f7;
    --hzp-fill-soft: #fafbfc;
    --hzp-radius: 10px;
    --hzp-radius-sm: 6px;

    background: var(--hzp-fill);
    color: var(--hzp-ink);
    font-family: Roboto, sans-serif;
}

.hzp-page.hzp-serp,
.hzp-page.hzp-detail {
    background: #fff;
}

/*
    Every box in this namespace is border-box. Scoped to descendants of
    .hzp-page so it cannot reach the homepage or the shared header/footer.
*/
.hzp-page *,
.hzp-page *::before,
.hzp-page *::after {
    box-sizing: border-box;
}

/*
    Mirrors .hz-shell from property.css rather than referencing it, so these
    pages line up with the header and footer even if that class is renamed.
    Same 1200/24 at every width, on purpose: a different gutter here would
    visibly misalign the content edge against the header logo.
*/
.hzp-shell {
    width: 100%;
    max-width: 1200px;
    margin: 0 auto;
    padding: 0 24px;
}

/*
    Visually hidden, still announced.

    left/top are pinned rather than left to auto, and this is load-bearing:
    with auto offsets an absolutely positioned box sits at its static position
    and resolves against the nearest POSITIONED ancestor. Inside a horizontal
    scroller whose ancestors are all static, that containing block is the
    initial one — outside the scroller — so the scroller does not clip it and
    its static x extends the document. That is exactly what happened: the
    "bedrooms"/"bathrooms" spans inside the related-listing rails pushed
    documentElement.scrollWidth to 986px at a 390px viewport, a real 596px
    horizontal overflow, with nothing visible out of place.

    Pinning left/top removes the dependence on static position entirely, so
    these spans can never extend the document from inside any scroller.
*/
.hzp-sr {
    position: absolute;
    inset-inline-start: 0;
    top: 0;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    border: 0;
    white-space: nowrap;
    clip-path: inset(50%);
}

/*
    Shared look for the inert controls. These are <span>s, never buttons or
    links: no href, no tabindex, so they take no click and never land in the
    tab order as a dead end. aria-disabled + title carry the reason.
*/
.hzp-page [aria-disabled="true"] {
    cursor: not-allowed;
}

.hzp-page a:focus-visible,
.hzp-page button:focus-visible,
.hzp-page input:focus-visible,
.hzp-page summary:focus-visible {
    outline: 3px solid var(--hzp-red);
    outline-offset: 2px;
    border-radius: var(--hzp-radius-sm);
}

/*
    The red banner's three rules stood here — .hzp-demo-note, its icon and its
    strong — and are deleted with the markup, so nothing in this sheet is left
    addressing an element that no longer renders. A sweep across the property
    theme's views, stylesheets and scripts found no remaining reference to the
    class before they went.

    Nothing replaces them and no spacing was adjusted to compensate. The banner
    carried its own 18px bottom margin and sat alone in a .hzp-shell that went
    with it, so the gap it used to occupy closed on the section margins either
    side rather than needing a value of its own.

    The other notices on these pages keep their rules and their markup: the map
    caption, the location line, the agent line, the Safe & transparent card and
    the card partial's tooltips were restored after a scope correction, and the
    mortgage calculator's disclaimer — a financial one rather than a demo one —
    was never in scope.
*/

/* ==========================================================================
   FILTER BAR — search results page
   ========================================================================== */

/*
    Pinned to the top of the viewport while the results scroll under it.

    top: 0 rather than an offset, because the site header above it
    (header.hz-header, 69px) is position: static and scrolls away — measured in
    the browser, not assumed. So the two cannot overlap: at rest the bar sits
    below the header in flow, and by the time the bar is pinned the header has
    gone. Nothing between here and <html> sets an overflow or a transform, which
    was checked at the same time, because either would silently turn this back
    into position: static.

    z-index is modest on purpose. It has to sit over the cards and the aside; it
    does not need to fight the header, which is never on screen at the same time.
*/
.hzp-filterbar {
    position: sticky;
    top: 0;
    z-index: 20;
    border-bottom: 1px solid var(--hzp-line);
    background: #ffffff;
    /* Only visible once pinned, when there is content behind it to separate. */
    box-shadow: 0 6px 18px -14px rgba(18, 20, 26, 0.4);
}

/*
    One consistent gap everywhere, one control height everywhere, and the action
    buttons pushed to the far end behind a rule rather than crowded up against
    the last menu. The row wraps rather than being squeezed: at 1280 there is not
    quite room for the whole thing on one line, and a second tidy line reads
    better than four controls compressed to fit.
*/
.hzp-fb {
    position: relative;
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 12px;
    padding-top: 12px;
    padding-bottom: 12px;
}

/*
    Explicit order on every child, because the visual order differs from the DOM
    order: the actions follow the controls on a wide screen and precede them on a
    narrow one, where the controls are folded away and the Filters button needs
    to stay beside the search box.
*/
.hzp-field--location {
    order: 1;
}

/*
    Grows to take the slack, rather than leaving it to an auto margin on the
    actions. That was the first attempt and it laid out wrongly: a wrapping flex
    container's base size is intrinsic, so the row kept 418px of its 489px of
    content, wrapped the price field onto a second line, and — because the bar is
    bottom-aligned — dropped the search box a line below the two menus beside it.
    Letting the row grow gives it 588px and it stays on one line.
*/
/*
    nowrap, so the row can never break its own line. The bar is bottom-aligned —
    the action buttons have no label above them and have to line up with the
    controls, not with the labels — and a wrapped row is therefore taller than
    the search box beside it, which drops the search box a line below the two
    menus. Shrinking a menu by a few pixels is a far smaller price than that, and
    with the widths below it does not come to that.

    Rewrapped deliberately in the narrow media query, where the row is a stacked
    panel and wrapping is the point.
*/
.hzp-fb__row {
    display: flex;
    flex: 1 1 auto;
    flex-wrap: nowrap;
    order: 2;
    align-items: flex-end;
    gap: 12px;
    min-width: 0;
}

/*
    The rule and the padding are what separate the actions from the controls,
    deliberately rather than incidentally. No auto margin: the row above absorbs
    the free space, which leaves these at the end of the bar anyway.
*/
.hzp-fb__actions {
    display: flex;
    order: 3;
    align-items: flex-end;
    gap: 10px;
    padding-inline-start: 16px;
    border-inline-start: 1px solid var(--hzp-line);
}

/*
    The Filters disclosure.

    A native <details> now, where it used to be a visually hidden checkbox and a
    <label>. The checkbox worked, and the reason for changing it is not that it
    did not: the panel is a floating dropdown rather than a block that pushes the
    results down, and a dropdown wants a control that owns an open/closed state
    the accessibility tree already understands. <summary> is that control, it is
    focusable and togglable from the keyboard without a line of script, and --
    the part that actually decided it -- the browser owns the state, so the Vue
    mount that wraps this whole page cannot discard it the way it discards a
    listener attached before it runs.

    position stays static so that the panel below resolves against .hzp-fb, which
    is the positioned ancestor and the box the panel should be measured from.
*/
.hzp-fb__more {
    position: static;
    /*
        In front of Clear, where the label used to be. The toggle is LAST in the
        markup because the panel has to be inside the <details> and the panel has
        to come after the row's other buttons in source order. Every other
        reordering on this bar is done the same way -- see the order values on
        .hzp-fb's children.
    */
    order: -1;
}

.hzp-fb__toggle {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    cursor: pointer;
    /*
        The disclosure triangle, removed twice: `list-style` is what Firefox and
        current Chrome honour, the ::-webkit- pseudo is what older WebKit needs.
        Both are kept because the button carries its own icon and a triangle
        beside it reads as a second, broken one.
    */
    list-style: none;
}

.hzp-fb__toggle::-webkit-details-marker {
    display: none;
}

.hzp-fb__more[open] > .hzp-fb__toggle {
    border-color: var(--hzp-ink);
    background: var(--hzp-fill);
}

/* The summary carries the focus itself now, so it shows it itself. */
.hzp-fb__toggle:focus-visible {
    outline: 2px solid var(--hzp-ink);
    outline-offset: 2px;
}

/* How many filters are on. Written by script, so it starts hidden. */
.hzp-fb__count {
    display: inline-grid;
    place-items: center;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    border-radius: 9px;
    background: var(--hzp-red);
    color: #ffffff;
    font-size: 11.5px;
    font-weight: 700;
    line-height: 1;
}

/*
    The panel, floating.

    Absolute rather than in flow, and that is the whole change: in flow it grew
    the sticky bar, which pushed the results down the page and, once the bar was
    pinned, took a third of the viewport away from them for as long as it was
    open. Floating, it overlays the results and costs the bar nothing.

    Measured from .hzp-fb -- the form -- so `top: 100%` is the bar's own bottom
    edge whatever height the bar happens to be, which matters below 1120px where
    the bar grows a second row. inset-inline-end rather than right, so it hangs
    from the Filters button in English and from the mirrored position in Arabic
    with no second rule; 24px is .hzp-shell's own padding, which is what lines it
    up with the content rather than with the shell's outer edge.

    The width is capped in two ways at once, and both are needed: 720px so it
    does not stretch across a wide screen, and 100vw minus twice the shell
    padding so it can never be the thing that gives the page a horizontal
    scrollbar.

    The height is capped on the panel and NOT on the form. It used to be capped
    on the form, below 720px, with overflow-y: auto -- which was correct while
    the panel was inside the form's flow and is exactly wrong now: an overflow on
    an ancestor clips an absolutely positioned descendant, so the bottom of this
    panel would have been cut off on a phone. The cap moved down here with it.
*/
/*
    A closed <details> does not paint its contents, but Chrome still generates
    boxes for out-of-flow descendants inside it -- the closed panel measures its
    full 720x560 through getBoundingClientRect while nothing appears on screen,
    and elementFromPoint over it returns the cards behind. Nothing is visible
    either way, so this rule changes no pixel; it is here because relying on a
    browser choosing not to paint boxes it has laid out is not a guarantee, and
    because phantom boxes make any element-versus-viewport audit report overflow
    that does not exist. [open] is set by the browser itself, so this costs
    nothing when script is off.
*/
.hzp-fb__more:not([open]) .hzp-fb__panel {
    display: none;
}

.hzp-fb__panel {
    position: absolute;
    top: calc(100% + 1px);
    inset-inline-end: 24px;
    z-index: 30;
    display: flex;
    flex-direction: column;
    width: min(720px, calc(100vw - 48px));
    max-height: min(600px, calc(100vh - 280px));
    border: 1px solid var(--hzp-line);
    border-radius: 12px;
    background: #ffffff;
    box-shadow: 0 18px 44px -18px rgba(18, 20, 26, 0.45);
}

/*
    Only the groups scroll. The submit at the foot stays reachable without
    scrolling to it, which is the point of putting it in the panel at all.
*/
.hzp-fb__panelbody {
    display: grid;
    gap: 0;
    overflow-y: auto;
    padding: 16px;
}

/* A fieldset, so the reset is fieldset-shaped. */
.hzp-fb__sec {
    min-width: 0;
    margin: 0;
    padding: 0;
    border: 0;
}

/*
    One separator, one number, every time: 13px of air, the hairline, 13px of
    air. It used to be the body's 18px grid gap plus this padding's 16px, which
    read as 34px above a rule sitting 16px off its own heading -- uneven by
    accident rather than by choice.
*/
.hzp-fb__sec + .hzp-fb__sec {
    margin-top: 13px;
    padding-top: 13px;
    border-top: 1px solid var(--hzp-line);
}

/*
    No letter-spacing and no uppercase, deliberately. Both are common on a label
    like this and both are wrong in Arabic: uppercase does nothing, and
    letter-spacing prises apart letters that are supposed to join.
*/
.hzp-fb__sectitle {
    margin: 0 0 7px;
    padding: 0;
    color: var(--hzp-ink);
    font-size: 13.5px;
    font-weight: 700;
}

.hzp-fb__secgrid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
    gap: 12px 16px;
}

/*
    Two roomy controls to a row. A menu of words and a pair of number boxes both
    want the room, and giving them the same footprint is what makes the two rows
    above the building section line up with each other.
*/
.hzp-fb__sec--pairs .hzp-fb__secgrid {
    grid-template-columns: repeat(auto-fit, minmax(216px, 1fr));
}

/*
    Four compact menus to a row. Floor, parking, tenure and the year are all one
    short value each, and at the old 190px minimum only three of the four fitted
    -- so the year dropped onto a row of its own, 122px wide beside three 213px
    siblings, with half the panel's width empty to the right of it. Four equal
    tracks put the whole group on one line and make the four the same size,
    which is what they are.
*/
.hzp-fb__sec--quads .hzp-fb__secgrid {
    grid-template-columns: repeat(auto-fit, minmax(146px, 1fr));
}

/* The amenities checklist is its own group and wants the full width. */
.hzp-fb__sec--wide .hzp-checks {
    margin-top: 6px;
}

.hzp-fb__foot {
    display: flex;
    flex: none;
    align-items: center;
    gap: 10px;
    padding: 11px 16px;
    border-top: 1px solid var(--hzp-line);
    border-radius: 0 0 12px 12px;
    background: var(--hzp-fill);
}

/*
    margin rather than justify-content: space-between, because the quiet action
    beside it is conditional -- it renders only when there is something to clear.
    space-between would send the submit to the start of the bar on the panel a
    visitor sees most often, the one with nothing selected yet.
*/
.hzp-fb__show {
    margin-inline-start: auto;
    white-space: nowrap;
}

/*
    Quiet, because it undoes work rather than doing any, and it must not compete
    with the submit two inches away. Same height as the submit so the bar reads
    as one row of actions.
*/
.hzp-fb__reset {
    border-color: transparent;
    background: transparent;
    color: var(--hzp-body);
    font-weight: 500;
    text-decoration: underline;
    text-underline-offset: 3px;
    white-space: nowrap;
}

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

/*
    Which label the submit shows. Default is the one WITHOUT a number, because
    the default is "no script has run", and without script a visitor can change
    four menus before pressing this -- so the count the server rendered would
    describe a state that is two selections old. With script, every control here
    navigates on change, no unsubmitted state can exist, and the number is
    exactly right.

    Keyed on .hzp-js, which the page's script puts on <html> as its first
    statement, so the swap happens before first paint.
*/
.hzp-fb__shownum {
    display: none;
}

html.hzp-js .hzp-fb__shownum {
    display: inline;
}

html.hzp-js .hzp-fb__showplain {
    display: none;
}

.hzp-fb__group {
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: 0;
    margin: 0;
    padding: 0;
    border: 0;
}

.hzp-fb__hint {
    margin: 0;
    color: var(--hzp-muted);
    font-size: 12.5px;
}

.hzp-checks {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    /* Column gap matches .hzp-fb__secgrid, so the ticks share the menus' columns. */
    gap: 6px 16px;
    margin-top: 4px;
}

.hzp-check {
    display: flex;
    align-items: center;
    gap: 8px;
    min-width: 0;
    padding: 2px 0;
    color: var(--hzp-body);
    font-size: 13.5px;
    line-height: 1.35;
    cursor: pointer;
}

.hzp-check input {
    flex: none;
    width: 15px;
    height: 15px;
    margin: 0;
    accent-color: var(--hzp-red);
}

.hzp-field {
    display: flex;
    flex-direction: column;
    gap: 5px;
    min-width: 0;
}

/*
    Grows into the space the row leaves, but capped: past about a third of the
    bar a single text field starts to look like the only thing on it, and the
    cap is what leaves room for the actions to sit at the far end rather than
    being pushed onto a second line.
*/
.hzp-field--location {
    flex: 1 1 240px;
    max-width: 300px;
    min-width: 0;
}

/*
    The widths are set so the whole bar still fits on one line in its widest
    state, which is with Clear showing: 300 + 477 + 318 + gaps = 1119 inside the
    1152px shell. Clear only appears once something is filtered, so sizing for
    the state without it is sizing for the state nobody stays in.
*/
.hzp-field--sm {
    flex: 0 1 128px;
}

.hzp-field--price {
    flex: 0 0 auto;
}

/*
    Both scripted states use the hidden attribute, which loses to the display
    value on .hzp-btn and the badge unless it is made to win. Scoped to this page
    rather than set globally.
*/
.hzp-serp [hidden] {
    display: none !important;
}

.hzp-field__label {
    color: var(--hzp-body);
    font-size: 12px;
    font-weight: 500;
    line-height: 1.2;
}

.hzp-input {
    position: relative;
    display: flex;
    align-items: center;
    height: 40px;
    border: 1px solid var(--hzp-line-strong);
    border-radius: var(--hzp-radius-sm);
    background: #ffffff;
}

.hzp-input:focus-within {
    border-color: var(--hzp-ink);
}

.hzp-input__field {
    width: 100%;
    min-width: 0;
    height: 100%;
    padding: 0 34px;
    padding-inline-start: 12px;
    border: 0;
    border-radius: var(--hzp-radius-sm);
    background: transparent;
    color: var(--hzp-ink);
    font-family: inherit;
    font-size: 14px;
}

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

/*
    A link back to the unfiltered page, rendered only when there is a term to
    clear. It used to be a type="reset" button, which restores the field's
    initial value — on /search?query=abdoun that value IS "abdoun", so the
    control did nothing in the one case where it looked like it should do
    something. Hence no :placeholder-shown rule here any more: the server decides
    whether it exists at all.
*/
.hzp-input__clear {
    position: absolute;
    inset-inline-end: 6px;
    display: grid;
    place-items: center;
    width: 26px;
    height: 26px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: var(--hzp-body);
    cursor: pointer;
}

.hzp-input__clear:hover {
    background: var(--hzp-fill);
}

.hzp-input__clear svg {
    width: 15px;
    height: 15px;
    fill: none;
    stroke: currentColor;
    stroke-width: 2;
    stroke-linecap: round;
}

/*
    The field's leading magnifier, which used to be a filled accent submit
    button and is now decoration.

    It is positioned rather than laid out, on purpose. As a flex item the old
    button occupied 32px plus its margins of the row, and the field was padded
    to 4px to sit beside it; taking it out of the flow instead lets the field be
    the full width of the box again and reclaim that space, which is the whole
    visible gain from the removal. The field is then padded to clear the icon,
    in the inline direction, so the same rule puts the icon on the left in
    English and on the right in Arabic with nothing locale-specific written
    here.

    pointer-events: none because the icon overlays the input's own padding: a
    click on it would otherwise land on the wrapper, which cannot take focus,
    and the field would not open. Passing the click through means the icon
    behaves like part of the field, which is what it looks like.
*/
.hzp-input--go .hzp-input__field {
    padding-inline-start: 36px;
}

.hzp-input__icon {
    position: absolute;
    inset-inline-start: 12px;
    width: 16px;
    height: 16px;
    color: var(--hzp-muted);
    fill: none;
    stroke: currentColor;
    stroke-width: 2;
    stroke-linecap: round;
    pointer-events: none;
}

/*
    The hidden submit takes the clip from .hzp-sr, which is on the element too.
    What is added here is a visible state for the one case where a clipped
    control is a defect rather than a convenience: a sighted visitor tabbing
    through the bar would otherwise land on a focused element they cannot see.

    So it un-clips on focus, into the slot the removed button used to fill —
    inline-start, which is free at both directions, unlike inline-end where the
    clear control sits. Opaque, so it covers the decorative icon while it is
    there rather than needing the icon hidden separately, and capped in width so
    a long translation cannot push it out of the field.

    :focus-visible only, so a click on the field never flashes it: the button is
    not what was clicked, but a mouse user has no need of it either way.
*/
.hzp-input__submit:focus-visible {
    inset-inline-start: 4px;
    top: 50%;
    width: auto;
    max-width: calc(100% - 8px);
    height: 32px;
    margin: -16px 0 0;
    padding: 0 10px;
    overflow: hidden;
    border-radius: var(--hzp-radius-sm);
    background: var(--hzp-accent, var(--hzp-red));
    color: #ffffff;
    font-family: inherit;
    font-size: 13px;
    white-space: nowrap;
    cursor: pointer;
    clip-path: none;
}

/*
    Now a wrapper around a real <select>. It was an inert span while nothing
    backed these menus; the attributes exist, so the control is the native one.
    Native means the mobile picker, keyboard type-ahead and form semantics all
    come free, and there is no custom menu to keep open across the Vue mount.

    appearance: none removes the platform arrow so the theme's chevron can sit
    where the reference puts it; the chevron takes pointer-events: none so the
    click still reaches the select underneath.
*/
.hzp-select {
    position: relative;
    display: flex;
    align-items: center;
    height: 40px;
    border: 1px solid var(--hzp-line-strong);
    border-radius: var(--hzp-radius-sm);
    background: #ffffff;
}

.hzp-select:focus-within {
    border-color: var(--hzp-ink);
}

.hzp-select__el {
    width: 100%;
    min-width: 0;
    height: 100%;
    padding: 0 30px;
    padding-inline-start: 11px;
    border: 0;
    border-radius: var(--hzp-radius-sm);
    background: transparent;
    color: var(--hzp-ink);
    font-family: inherit;
    font-size: 14px;
    cursor: pointer;
    appearance: none;
}

.hzp-select svg {
    position: absolute;
    inset-inline-end: 9px;
    flex: none;
    width: 16px;
    height: 16px;
    fill: none;
    stroke: var(--hzp-body);
    stroke-width: 1.8;
    stroke-linecap: round;
    stroke-linejoin: round;
    pointer-events: none;
}

/*
    Inside the panel the grid owns the width. These three rules do not change any
    value or any name; they stop a fixed pixel width from leaving a third of a
    cell empty, and they are scoped to the panel so the price boxes on the bar --
    where 88px is deliberately the width of "145,000" -- are untouched.
*/
.hzp-fb__panel .hzp-range {
    gap: 8px;
}

.hzp-fb__panel .hzp-range__el {
    flex: 1 1 0;
    width: auto;
    min-width: 0;
}

.hzp-fb__panel .hzp-range__el--wide {
    width: 100%;
}

/* Price, as two numbers rather than a menu of bands. */
.hzp-range {
    display: flex;
    align-items: center;
    gap: 6px;
}

/* Wide enough for the largest bound it shows as a placeholder: "145,000". */
.hzp-range__el {
    width: 88px;
    height: 40px;
    padding: 0 9px;
    border: 1px solid var(--hzp-line-strong);
    border-radius: var(--hzp-radius-sm);
    background: #ffffff;
    color: var(--hzp-ink);
    font-family: inherit;
    font-size: 14px;
}

.hzp-range__el--wide {
    width: 122px;
}

.hzp-range__el:focus {
    border-color: var(--hzp-ink);
    outline: none;
}

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

.hzp-range__dash {
    color: var(--hzp-muted);
    font-size: 14px;
}

.hzp-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    height: 40px;
    padding: 0 16px;
    border: 1px solid var(--hzp-line-strong);
    border-radius: var(--hzp-radius-sm);
    background: #ffffff;
    color: var(--hzp-ink);
    font-family: inherit;
    font-size: 14px;
    font-weight: 500;
    white-space: nowrap;
}

.hzp-btn svg {
    flex: none;
    width: 16px;
    height: 16px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.8;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.hzp-btn--accent {
    border-color: var(--hzp-red);
    background: var(--hzp-red);
    color: #ffffff;
}

/*
    Stroke only. An earlier `fill: #ffffff` here filled every closed path in
    the icon, which turned the calendar glyph on "Request a viewing" into a
    solid white block. Every icon in this stylesheet is drawn as an outline,
    so the accent variant only needs to recolour the stroke.
*/
.hzp-btn--accent svg {
    fill: none;
    stroke: #ffffff;
}

.hzp-btn--wide {
    width: 100%;
}

/* Genuine controls get hover feedback; inert ones deliberately do not. */
a.hzp-btn:hover,
button.hzp-btn:hover {
    border-color: var(--hzp-ink);
}

a.hzp-btn--accent:hover,
button.hzp-btn--accent:hover {
    border-color: var(--hzp-red-dark);
    background: var(--hzp-red-dark);
}

/* --------------------------------------------------------- secondary row --- */

.hzp-subbar {
    border-bottom: 1px solid var(--hzp-line);
    background: #ffffff;
}

.hzp-subbar__inner {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 22px;
    min-height: 44px;
    padding-top: 8px;
    padding-bottom: 8px;
}

.hzp-subbar__item {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    color: var(--hzp-ink);
    font-size: 14px;
    font-weight: 500;
}

.hzp-subbar__item span {
    text-decoration: underline;
    text-underline-offset: 3px;
}

.hzp-subbar__item svg {
    flex: none;
    width: 18px;
    height: 18px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.7;
    stroke-linejoin: round;
}

/* ==========================================================================
   RESULTS COLUMN + SIDEBAR
   ========================================================================== */

.hzp-serp__grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 300px);
    grid-template-areas:
        "heading ."
        "results side";
    align-items: start;
    gap: 16px 24px;
    padding-top: 22px;
    padding-bottom: 48px;
}

.hzp-results {
    min-width: 0;
}

.hzp-serp__grid > .hzp-results {
    display: contents;
}

.hzp-serp__grid .hzp-results__top {
    grid-area: heading;
    min-width: 0;
}

.hzp-serp__grid .hzp-results__body {
    grid-area: results;
    min-width: 0;
}

.hzp-serp__grid > .hzp-side {
    grid-area: side;
}

.hzp-results__head {
    display: grid;
    grid-template-columns: minmax(0, 1fr) max-content;
    align-items: center;
    gap: 14px;
    margin-bottom: 0;
}

.hzp-results__heading-copy {
    grid-column: 1 / -1;
    min-width: 0;
}

.hzp-results__head > .hzp-sort {
    grid-column: 1;
    justify-self: start;
}

.hzp-results__head > .hzp-view-switch {
    grid-column: 2;
    justify-self: end;
}

.hzp-results__breadcrumbs .hzp-crumbs {
    padding: 0 0 14px;
    gap: 8px;
    font-size: 13px;
}

.hzp-results__breadcrumbs .hzp-crumbs a {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    text-decoration: none;
}

.hzp-results__breadcrumbs svg {
    width: 18px;
    height: 18px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.8;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.hzp-results__breadcrumbs .hzp-crumbs li + li::before {
    content: "";
    width: 6px;
    height: 6px;
    margin-inline: 4px;
    border-top: 1.5px solid currentColor;
    border-inline-end: 1.5px solid currentColor;
    transform: rotate(45deg);
    flex-shrink: 0;
}

[dir="rtl"] .hzp-results__breadcrumbs .hzp-crumbs li + li::before {
    transform: rotate(-45deg);
}

.hzp-results__title {
    margin: 0;
    color: var(--hzp-ink);
    font-size: clamp(24px, 2vw, 30px);
    font-weight: 700;
    line-height: 1.2;
}

.hzp-results__count {
    margin: 4px 0 0;
    color: var(--hzp-muted);
    font-size: 13px;
}

.hzp-sort {
    display: inline-flex;
    align-items: center;
    margin-inline-start: 0;
    color: var(--hzp-ink);
    font-size: 14px;
}

.hzp-sort__label {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

.hzp-sort__control {
    position: relative;
    display: inline-flex;
    align-items: center;
    min-width: 164px;
    min-height: 46px;
    border: 1px solid var(--hzp-line-strong);
    border-radius: 12px;
    background: #ffffff;
}

.hzp-sort__control:focus-within {
    border-color: var(--hzp-accent, var(--hagzi-primary, #0745D9));
    box-shadow: 0 0 0 3px rgba(7, 69, 217, 0.12);
}

.hzp-sort__el {
    width: 100%;
    max-width: 100%;
    min-height: 44px;
    padding: 8px 38px;
    border: 0;
    background: transparent;
    color: var(--hzp-ink);
    font-family: inherit;
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    appearance: none;
}

.hzp-sort__control svg {
    position: absolute;
    pointer-events: none;
}

.hzp-sort svg {
    width: 18px;
    height: 18px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.7;
    stroke-linecap: round;
}

.hzp-sort__control .hzp-sort__icon {
    inset-inline-start: 12px;
    width: 20px;
    height: 20px;
}

.hzp-sort__control .hzp-sort__chevron {
    inset-inline-end: 10px;
    width: 18px;
    height: 18px;
}

/*
    How many listings a filter set aside for recording nothing. It sits directly
    under the count and qualifies it, so it is the count's own colour and size
    rather than a warning: nothing has gone wrong, the catalogue is simply
    incomplete and the page is saying so.
*/
.hzp-results__absent {
    margin: 4px 0 0;
    color: var(--hzp-muted);
    font-size: 12.5px;
    line-height: 1.55;
}

.hzp-cards {
    display: grid;
    gap: 16px;
    margin: 0;
    padding: 0;
    list-style: none;
}

/* Grid is a desktop choice; mobile always renders the list layout. */
@media (min-width: 768px) {
    .hzp-cards--grid {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }

    .hzp-cards--grid .hzp-card {
        grid-template-columns: minmax(0, 1fr);
        grid-template-rows: auto minmax(0, 1fr);
    }

    .hzp-cards--grid .hzp-card__media {
        grid-template-columns: minmax(0, 1fr);
    }

    .hzp-cards--grid .hzp-card__thumbs,
    .hzp-cards--grid .hzp-card__desc {
        display: none;
    }

    .hzp-cards--grid .hzp-card__photo {
        min-height: 0;
        height: auto;
        max-height: none;
        aspect-ratio: 16 / 10;
    }
}

/* ------------------------------------------------------------ result card --- */

/* position: relative for the same containing-block reason as .hzp-mini. */
.hzp-card {
    position: relative;
    display: grid;
    grid-template-columns: minmax(0, 300px) minmax(0, 1fr);
    overflow: hidden;
    border: 1px solid var(--hzp-line);
    border-radius: var(--hzp-radius);
    background: #ffffff;
}

.hzp-card__media {
    position: relative;
    display: grid;
    grid-template-columns: minmax(0, 1fr) 64px;
    gap: 3px;
    background: var(--hzp-fill);
}

.hzp-card__photo {
    display: block;
    width: 100%;
    height: 100%;
    min-height: 196px;
    max-height: none;
    object-fit: cover;
}

/*
    A static preview strip, not a control: these thumbnails are images with alt
    text and no click target, because there is no lightbox behind them.
*/
.hzp-card__thumbs {
    display: grid;
    grid-template-rows: repeat(3, minmax(0, 1fr));
    gap: 3px;
    min-width: 0;
}

.hzp-card__thumb {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.hzp-badges {
    position: absolute;
    top: 10px;
    inset-inline-start: 10px;
    z-index: 2;
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    max-width: calc(100% - 20px);
}

.hzp-badge {
    padding: 4px 9px;
    border-radius: 999px;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.01em;
    line-height: 1.35;
}

/*
    Status badges are ink, not red.

    A badge states what a listing IS — For Sale, For Rent, New, Featured — and
    a statement of fact is not something to click. Red is this theme's action
    colour, so a badge wearing it invites a press that does nothing. For Rent
    and Featured were already ink; this brings the other two into line rather
    than keeping a split that only ever reflected which tone was passed in.

    Written as one rule over both selectors, not two rules with identical
    bodies. The card template builds the class from listing data
    (hzp-badge--{{ tone }}), so --accent still has to resolve to something —
    but a second copy of the same declarations is exactly the sort of duplicate
    that drifts apart the next time somebody edits one of them.
*/
.hzp-badge--accent,
.hzp-badge--ink {
    background: var(--hzp-ink);
    color: #ffffff;
}

.hzp-badge--soft {
    background: #ffffff;
    color: var(--hzp-ink);
    box-shadow: 0 1px 3px rgba(18, 20, 26, 0.22);
}

.hzp-card__body {
    display: flex;
    flex-direction: column;
    min-width: 0;
    padding: 14px 16px 12px;
}

.hzp-card__top {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 12px;
}

.hzp-price {
    margin: 0;
    color: var(--hzp-ink);
    font-size: 23px;
    font-weight: 700;
    line-height: 1.2;
}

.hzp-price small {
    color: var(--hzp-muted);
    font-size: 14px;
    font-weight: 500;
}

/* Inert, like the homepage card heart: a span, so it takes no click. */
.hzp-fav {
    display: grid;
    flex: none;
    place-items: center;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    color: var(--hzp-body);
}

.hzp-fav svg {
    width: 21px;
    height: 21px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.7;
}

.hzp-pill {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    align-self: flex-start;
    margin-top: 7px;
    padding: 4px 10px;
    border-radius: 999px;
    background: var(--hzp-line);
    color: var(--hzp-ink);
    font-size: 12.5px;
    font-weight: 500;
}

.hzp-pill svg {
    width: 14px;
    height: 14px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.8;
}

.hzp-specs {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 4px 8px;
    margin: 10px 0 0;
    padding: 0;
    color: var(--hzp-ink);
    font-size: 13.5px;
    list-style: none;
}

.hzp-specs li {
    display: inline-flex;
    align-items: center;
    gap: 5px;
}

/*
    The separator trails its item rather than leading the next one.

    Identical while the row fits on one line -- the dot sits in the same place
    either way, 8px from the item on each side. The difference is what happens
    when the row wraps, which it now does at 390 for a listing whose type is a
    long word: as a leading ::before the dot was carried onto the second line
    and read as a stray bullet in front of it. Trailing, it stays at the end of
    the line it belongs to and reads as a continuation.

    This was always the behaviour; nothing was long enough to reach it until
    the property type joined the row.
*/
.hzp-specs li:not(:last-child)::after {
    content: "";
    display: inline-block;
    width: 3px;
    height: 3px;
    margin-inline-start: 3px;
    border-radius: 50%;
    background: var(--hzp-line-strong);
}

.hzp-card__addr {
    margin: 5px 0 0;
    color: var(--hzp-body);
    font-size: 13.5px;
    font-weight: 400;
    line-height: 1.45;
}

.hzp-card__addr a {
    color: inherit;
    text-decoration: none;
}

.hzp-card__addr a:hover {
    color: var(--hzp-red);
    text-decoration: underline;
    text-underline-offset: 3px;
}

/*
    Two lines then ellipsis, matching the reference. -webkit-line-clamp is the
    only cross-browser way to clamp by line count and is supported everywhere
    this theme targets; max-height keeps the box honest if it is ignored.
*/
.hzp-card__desc {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    overflow: hidden;
    margin: 8px 0 0;
    max-height: 3.1em;
    color: var(--hzp-body);
    font-size: 13.5px;
    line-height: 1.55;
}

.hzp-card__listed {
    margin: 8px 0 0;
    color: var(--hzp-muted);
    font-size: 12.5px;
}

.hzp-ticks {
    display: flex;
    flex-wrap: wrap;
    gap: 6px 18px;
    margin: 10px 0 0;
    padding: 0;
    list-style: none;
}

.hzp-ticks li {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    color: var(--hzp-ink);
    font-size: 13px;
}

.hzp-ticks svg {
    flex: none;
    width: 15px;
    height: 15px;
    fill: none;
    stroke: var(--hzp-red);
    stroke-width: 2.2;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.hzp-card__foot {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 10px 16px;
    margin-top: auto;
    padding-top: 11px;
}

.hzp-agent {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    min-width: 0;
}

/*
    Initials tile rather than an agent logo image: these agencies are invented,
    so there is no real mark to show and none was generated.
*/
.hzp-agent__mark {
    display: grid;
    flex: none;
    place-items: center;
    width: 30px;
    height: 30px;
    border-radius: var(--hzp-radius-sm);
    background: var(--hzp-ink);
    color: #ffffff;
    font-size: 11.5px;
    font-weight: 700;
    letter-spacing: 0.02em;
}

.hzp-agent__name {
    overflow: hidden;
    color: var(--hzp-body);
    font-size: 12.5px;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/*
    The card's two contact actions, now buttons rather than underlined text.

    .hzp-contact and its span and svg rules stood here and drew the old pair:
    a 13.5px underlined label with a 16px glyph beside it, for two controls
    that did nothing. Both are real links now and take .hzp-btn, so the whole
    treatment came from the button the rest of the site already uses and there
    is nothing card-specific left to declare about their appearance.

    What is card-specific is the wrapping. The foot is a flex row that already
    wraps the agent name away at narrow widths; this lets the pair wrap within
    itself as a last resort, so a card narrower than the two buttons stacks
    them rather than pushing them past its own edge.
*/
.hzp-contacts {
    display: inline-flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
}

/*
    Neither button shrinks below its label. .hzp-btn is nowrap, so without this
    a tight card would compress the boxes while the text kept its width and
    spilled out of them.
*/
.hzp-contacts__btn {
    flex: none;
}

/* ------------------------------------------------------------- sidebar --- */

.hzp-side {
    display: grid;
    gap: 16px;
    min-width: 0;
}

.hzp-side__card {
    padding: 16px;
    border: 1px solid var(--hzp-line);
    border-radius: var(--hzp-radius);
    background: #ffffff;
}

.hzp-side__actions {
    display: grid;
    gap: 10px;
}

/*
    Save this search, once it is saved.

    The heart fills and turns red. The label and the border stay exactly as the
    unsaved button drew them, and that is the deliberate half of this rule.

    Colouring the whole control was the first version and it was wrong. This is
    a full-width bordered button, and a full-width button whose border and text
    are both red is the shape every interface on earth uses for "delete this" —
    so the more red it carried, the more it read as a warning about the search
    rather than a confirmation of it. Red on the heart alone is unambiguous,
    because a filled red heart already means saved everywhere, and it leaves the
    button looking like a button.

    THE COLOUR

    Taken from --hzfav-saved, which is declared in property-favorites.css: that
    file loads on every page of this channel, and the favourite hearts on the
    cards, the listing page, the home page and the favourites grid are being
    moved onto the same variable. One declaration, so the two saved states on
    this channel cannot drift apart, and this file does not have to be edited
    again when the shade is tuned.

    The fallback is a crimson rather than the #d92228 already in use for the
    demo notices on the project pages. That one is the warning red, and
    borrowing it would say "problem" in a place that means "kept" -- the exact
    confusion the paragraph above is avoiding. This is pinker and further from a
    pure alert red, which is also the hue the convention actually uses. It is
    4.7:1 against the white panel, comfortably past the 3:1 that non-text
    graphics need.

    Colour is never the only carrier of the state: the glyph goes from outline
    to filled, the label changes from "Save this search" to "Search saved", and
    aria-pressed flips. Someone who cannot see the difference between crimson
    and grey still has all three.
*/
.hzp-savesearch--on svg {
    color: var(--hzfav-saved, #e11d48);
    fill: currentColor;
}

.hzp-side__links {
    display: grid;
    gap: 13px;
    margin: 18px 0 0;
    padding: 18px 0 0;
    border-top: 1px solid var(--hzp-line);
    list-style: none;
}

.hzp-side__links a {
    color: var(--hzp-ink);
    font-size: 13.5px;
    text-decoration: underline;
    text-underline-offset: 3px;
}

.hzp-side__links a:hover {
    color: var(--hzp-red);
}

/* ------------------------------------------------ recommended searches --- */

.hzp-recommended {
    overflow: hidden;
    border: 1px solid var(--hzp-line);
    border-radius: var(--hzp-radius);
    background: #ffffff;
}

.hzp-recommended__head {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 16px;
    border-bottom: 1px solid var(--hzp-line);
}

.hzp-recommended__icon {
    display: inline-flex;
    flex: none;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    background: #DCE7FF;
    color: var(--hzp-accent, var(--hagzi-primary, #0745D9));
}

.hzp-recommended__icon svg {
    width: 22px;
    height: 22px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.8;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.hzp-recommended__title {
    margin: 0;
    color: var(--hzp-ink);
    font-size: 17px;
    font-weight: 750;
    line-height: 1.25;
}

.hzp-recommended__hint {
    margin: 4px 0 0;
    color: var(--hzp-muted);
    font-size: 13px;
    line-height: 1.4;
}

.hzp-recommended__list {
    display: grid;
    gap: 9px;
    margin: 0;
    padding: 14px;
    list-style: none;
}

.hzp-recommended__link {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    min-height: 52px;
    padding: 11px 12px;
    border: 1px solid #BCD0FB;
    border-radius: 11px;
    background: #ffffff;
    color: var(--hzp-ink);
    font-size: 13.5px;
    font-weight: 650;
    line-height: 1.35;
    text-decoration: none;
    box-shadow: 0 2px 5px rgba(7, 69, 217, 0.08);
}

.hzp-recommended__link:hover {
    border-color: var(--hzp-accent, var(--hagzi-primary, #0745D9));
    background: #F7F9FF;
}

.hzp-recommended__link:focus-visible {
    outline: 2px solid var(--hzp-accent, var(--hagzi-primary, #0745D9));
    outline-offset: 2px;
}

.hzp-recommended__link svg {
    flex: none;
    width: 17px;
    height: 17px;
    color: var(--hzp-accent, var(--hagzi-primary, #0745D9));
    fill: none;
    stroke: currentColor;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
}

[dir="rtl"] .hzp-recommended__link svg {
    transform: scaleX(-1);
}

/*
    Promotional slot placeholder. Reserves the space the reference gives an ad
    without inventing an advertiser or a product claim.
*/


/* ==========================================================================
   LISTING DETAIL
   ========================================================================== */

.hzp-crumbs {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    margin: 0;
    padding: 14px 0;
    color: var(--hzp-muted);
    font-size: 12.5px;
    list-style: none;
}

.hzp-crumbs li {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

.hzp-crumbs li + li::before {
    content: "/";
    color: var(--hzp-line-strong);
}

.hzp-crumbs a {
    color: var(--hzp-body);
    text-decoration: underline;
    text-underline-offset: 3px;
}

.hzp-crumbs a:hover {
    color: var(--hzp-red);
}

.hzp-crumbs [aria-current="page"] {
    color: var(--hzp-ink);
    font-weight: 500;
}

.hzp-dgrid {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 330px);
    align-items: start;
    gap: 24px;
    padding-bottom: 40px;
}

.hzp-dmain {
    display: grid;
    gap: 16px;
    min-width: 0;
}

.hzp-dside {
    display: grid;
    gap: 16px;
    min-width: 0;
}

/* ----------------------------------------------------------- price block --- */

.hzp-panel {
    padding: 18px;
    border: 1px solid var(--hzp-line);
    border-radius: var(--hzp-radius);
    background: #ffffff;
}

/* The gallery spans both columns; the sidebar starts beside the price. */
.hzp-detail .hzp-dgallery {
    grid-column: 1 / -1;
    min-width: 0;
}
.hzp-detail .hzp-dmain > .hzp-panel:first-child {
    padding-top: 0;
}

/* Open content sections, matching the project detail page layout. */
.hzp-detail .hzp-dmain {
    gap: 0;
}

.hzp-detail .hzp-dmain > .hzp-panel {
    padding: 30px 0;
    border: 0;
    border-radius: 0;
    background: transparent;
    box-shadow: none;
}

.hzp-detail .hzp-dmain > section.hzp-panel {
    border-top: 1px solid var(--hzp-line);
}

.hzp-detail .hzp-dmain > .hzp-panel > .hzp-panel__title {
    margin-bottom: 22px;
}

.hzp-panel__title {
    margin: 0 0 14px;
    color: var(--hzp-ink);
    font-size: 17px;
    font-weight: 700;
}

.hzp-dprice {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 10px;
}

.hzp-dprice__value {
    margin: 0;
    color: var(--hzp-ink);
    font-size: 30px;
    font-weight: 700;
    line-height: 1.15;
}

.hzp-dprice__value small {
    color: var(--hzp-muted);
    font-size: 15px;
    font-weight: 500;
}

.hzp-dtitle {
    margin: 10px 0 0;
    color: var(--hzp-ink);
    font-size: 17px;
    font-weight: 600;
    line-height: 1.35;
}

.hzp-daddr {
    margin: 4px 0 0;
    color: var(--hzp-body);
    font-size: 14px;
}

.hzp-dspecs {
    display: flex;
    flex-wrap: wrap;
    gap: 10px 22px;
    margin: 14px 0 0;
    padding: 14px 0 0;
    border-top: 1px solid var(--hzp-line);
    list-style: none;
}

.hzp-dspecs li {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    color: var(--hzp-ink);
    font-size: 14px;
    font-weight: 500;
}

.hzp-dspecs svg {
    flex: none;
    width: 19px;
    height: 19px;
    fill: none;
    stroke: var(--hzp-body);
    stroke-width: 1.6;
    stroke-linecap: round;
    stroke-linejoin: round;
}

/* --------------------------------------------------- about this property --- */

.hzp-features {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 9px 22px;
    margin: 0 0 16px;
    padding: 0;
    list-style: none;
}

.hzp-features li {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    color: var(--hzp-ink);
    font-size: 13.5px;
    line-height: 1.45;
}

.hzp-features svg {
    flex: none;
    width: 15px;
    height: 15px;
    margin-top: 2px;
    fill: none;
    stroke: var(--hzp-red);
    stroke-width: 2.2;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.hzp-prose p {
    margin: 0 0 10px;
    color: var(--hzp-body);
    font-size: 14px;
    line-height: 1.65;
}

.hzp-prose p:last-child {
    margin-bottom: 0;
}

/* ------------------------------------------------- mortgage illustration --- */

.hzp-calc {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 230px);
    gap: 18px;
    padding: 16px;
    border: 1px solid var(--hzp-line);
    border-radius: var(--hzp-radius);
    background: var(--hzp-fill-soft);
}

.hzp-calc__fields {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 12px;
}

.hzp-calc__field {
    display: grid;
    gap: 5px;
    min-width: 0;
}

.hzp-calc__label {
    color: var(--hzp-muted);
    font-size: 11.5px;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

/*
    Static readouts, not inputs. The figures they show are the ones the monthly
    total was actually computed from, in PHP, at render time.
*/
.hzp-calc__value {
    display: flex;
    align-items: center;
    height: 38px;
    padding: 0 11px;
    overflow: hidden;
    border: 1px solid var(--hzp-line);
    border-radius: var(--hzp-radius-sm);
    background: #ffffff;
    color: var(--hzp-ink);
    font-size: 14px;
    font-weight: 500;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.hzp-calc__out {
    display: grid;
    align-content: center;
    justify-items: center;
    gap: 3px;
    padding: 14px;
    border: 1px solid #f2d7d8;
    border-radius: var(--hzp-radius);
    background: var(--hzp-red-tint);
    text-align: center;
}

.hzp-calc__outlabel {
    color: #7a1d20;
    font-size: 12px;
    font-weight: 500;
}

.hzp-calc__amount {
    color: var(--hzp-red-dark);
    font-size: 25px;
    font-weight: 700;
    line-height: 1.15;
}

.hzp-note {
    margin: 12px 0 0;
    color: var(--hzp-muted);
    font-size: 11.5px;
    line-height: 1.55;
}

/* --------------------------------------------------------- location/map --- */

.hzp-detail .hzp-location__nearby {
    margin-top: 24px;
}


.hzp-map {
    position: relative;
    display: grid;
    place-items: center;
    min-height: 240px;
    overflow: hidden;
    border: 1px solid var(--hzp-line);
    border-radius: var(--hzp-radius);
    background:
        repeating-linear-gradient(0deg, #eceef1 0 1px, transparent 1px 42px),
        repeating-linear-gradient(90deg, #eceef1 0 1px, transparent 1px 42px),
        #f6f7f9;
}

.hzp-map__pin {
    display: grid;
    justify-items: center;
    gap: 6px;
    padding: 12px 16px;
    border: 1px solid var(--hzp-line);
    border-radius: var(--hzp-radius);
    background: rgba(255, 255, 255, 0.94);
    text-align: center;
}

.hzp-map__pin svg {
    width: 26px;
    height: 26px;
    fill: none;
    stroke: var(--hzp-red);
    stroke-width: 1.8;
    stroke-linejoin: round;
}

.hzp-map__label {
    color: var(--hzp-ink);
    font-size: 13.5px;
    font-weight: 600;
}

.hzp-map__sub {
    color: var(--hzp-muted);
    font-size: 11.5px;
}

/* ----------------------------------------------------- more information --- */

.hzp-info {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0 26px;
    margin: 0;
}

.hzp-info__row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 14px;
    padding: 11px 0;
    border-bottom: 1px solid var(--hzp-line);
}

/* Only the final visible Property details row has no bottom divider. */
.hzp-detail .hzp-info > .hzp-info__row:last-child {
    border-bottom: 0;
}

@media (min-width: 768px) {
    .hzp-detail .hzp-info > .hzp-info__row:nth-last-child(2):nth-child(odd) {
        border-bottom: 0;
    }
}

.hzp-info__key {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    margin: 0;
    color: var(--hzp-body);
    font-size: 13.5px;
}

.hzp-info__key svg {
    flex: none;
    width: 16px;
    height: 16px;
    fill: none;
    stroke: var(--hzp-muted);
    stroke-width: 1.7;
    stroke-linejoin: round;
}

.hzp-info__val {
    margin: 0;
    color: var(--hzp-ink);
    font-size: 13.5px;
    font-weight: 600;
    text-align: end;
}

/* ------------------------------------------------------- agent contact --- */

.hzp-contactcard {
    position: sticky;
    top: 16px;
    padding: 16px;
    border: 1px solid var(--hzp-line);
    border-radius: var(--hzp-radius);
    background: #ffffff;
}

.hzp-contactcard__title {
    margin: 0 0 4px;
    color: var(--hzp-ink);
    font-size: 16px;
    font-weight: 700;
}

.hzp-contactcard__sub {
    margin: 0 0 14px;
    color: var(--hzp-muted);
    font-size: 12.5px;
    line-height: 1.5;
}

.hzp-contactcard__actions {
    display: grid;
    gap: 9px;
}

.hzp-agentrow {
    display: flex;
    align-items: center;
    gap: 11px;
    margin-top: 15px;
    padding-top: 15px;
    border-top: 1px solid var(--hzp-line);
}

.hzp-agentrow__mark {
    display: grid;
    flex: none;
    place-items: center;
    width: 44px;
    height: 44px;
    border-radius: var(--hzp-radius-sm);
    background: var(--hzp-ink);
    color: #ffffff;
    font-size: 14px;
    font-weight: 700;
}

.hzp-agentrow__name {
    margin: 0;
    color: var(--hzp-ink);
    font-size: 13.5px;
    font-weight: 600;
}

.hzp-agentrow__meta {
    margin: 2px 0 0;
    color: var(--hzp-muted);
    font-size: 12px;
}

/* --------------------------------------------------------- related rails --- */

.hzp-rail {
    padding-bottom: 34px;
}

.hzp-rail__title {
    margin: 0 0 12px;
    color: var(--hzp-ink);
    font-size: 17px;
    font-weight: 700;
}

/*
    Own scroll container, same reason as the gallery strip: fixed-width cards
    in a row must never be allowed to widen the document.
*/
.hzp-rail__track {
    display: flex;
    gap: 14px;
    margin: 0;
    padding: 2px 2px 10px;
    overflow-x: auto;
    scrollbar-width: thin;
    list-style: none;
}

/*
    position: relative is deliberate, not decoration. It makes this card the
    containing block for the visually hidden spans inside it, so they are
    clipped by this card's own overflow instead of resolving against the
    initial containing block and escaping the rail's scroller.
*/
.hzp-mini {
    position: relative;
    display: flex;
    flex: none;
    flex-direction: column;
    width: 214px;
    overflow: hidden;
    border: 1px solid var(--hzp-line);
    border-radius: var(--hzp-radius);
    background: #ffffff;
}

.hzp-mini__img {
    display: block;
    width: 100%;
    height: 128px;
    object-fit: cover;
}

.hzp-mini__body {
    padding: 10px 12px 12px;
}

.hzp-mini__price {
    margin: 0;
    color: var(--hzp-ink);
    font-size: 16px;
    font-weight: 700;
}

.hzp-mini__specs {
    display: flex;
    flex-wrap: wrap;
    gap: 3px 10px;
    margin: 6px 0 0;
    padding: 0;
    color: var(--hzp-body);
    font-size: 12.5px;
    list-style: none;
}

.hzp-mini__specs li {
    display: inline-flex;
    align-items: center;
    gap: 4px;
}

.hzp-mini__specs svg {
    width: 14px;
    height: 14px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.6;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.hzp-mini__addr {
    margin: 6px 0 0;
    overflow: hidden;
    color: var(--hzp-muted);
    font-size: 12px;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.hzp-mini__addr a {
    color: inherit;
    text-decoration: none;
}

.hzp-mini__addr a:hover {
    color: var(--hzp-red);
    text-decoration: underline;
    text-underline-offset: 3px;
}

/* ==========================================================================
   RESPONSIVE
   ========================================================================== */

/* Sidebar no longer fits beside the results column. */
@media (max-width: 1023.98px) {
    .hzp-serp__grid,
    .hzp-dgrid {
        grid-template-columns: minmax(0, 1fr);
    }

    .hzp-serp__grid {
        grid-template-areas:
            "heading"
            "results"
            "side";
    }

    .hzp-contactcard {
        position: static;
    }
}

@media (max-width: 767.98px) {
    .hzp-card {
        grid-template-columns: minmax(0, 1fr);
    }

    .hzp-card__media {
        grid-template-columns: minmax(0, 1fr);
    }

    .hzp-card__photo {
        min-height: 0;
        max-height: none;
        aspect-ratio: 3 / 2;
    }

    /*
        The stacked thumbnail column becomes a three-across row under the photo
        rather than disappearing, so the card keeps the reference's gallery cue.
    */
    .hzp-card__thumbs {
        grid-template-rows: none;
        grid-template-columns: repeat(3, minmax(0, 1fr));
        height: 62px;
    }

    .hzp-calc {
        grid-template-columns: minmax(0, 1fr);
    }

    .hzp-features,
    .hzp-info {
        grid-template-columns: minmax(0, 1fr);
    }

    .hzp-field--sm {
        flex: 1 1 calc(50% - 6px);
    }

    .hzp-results__head {
        align-items: flex-start;
        grid-template-columns: minmax(138px, 0.9fr) minmax(0, 1.5fr);
    }

    .hzp-results__heading-copy {
        grid-column: 1 / -1;
    }

    .hzp-results__head > .hzp-sort {
        grid-column: 1;
        justify-self: start;
    }

    .hzp-results__head > .hzp-view-switch {
        grid-column: 2;
        justify-self: stretch;
    }

    .hzp-sort {
        width: 100%;
        margin-inline-start: 0;
    }

    .hzp-sort__control {
        width: 100%;
        min-width: 0;
    }

    .hzp-dprice__value {
        font-size: 26px;
    }
}

@media (max-width: 479.98px) {
    .hzp-price {
        font-size: 21px;
    }

    .hzp-card__foot {
        align-items: flex-start;
        flex-direction: column;
    }

    .hzp-calc__fields {
        grid-template-columns: minmax(0, 1fr);
    }

    .hzp-filterbar__inner {
        gap: 10px;
    }

    /* Filters and Save share the last row rather than each taking a full one. */
    .hzp-filterbar__tail {
        display: flex;
        flex: 1 1 100%;
        gap: 10px;
    }

    .hzp-filterbar__tail > * {
        flex: 1 1 0;
    }
}

@media (prefers-reduced-motion: reduce) {
    .hzp-page * {
        transition: none !important;
    }
}

/* ==========================================================================
   States a real result set has and a fixed mockup never did
   ==========================================================================

   Added when the search page stopped rendering six hard-coded cards and started
   rendering the channel's catalogue. A real listing can carry one photograph
   rather than a photograph plus a gallery strip, or no photograph at all, and a
   real search can match nothing.

   This section sits after the media queries on purpose. Every selector is
   either new, or a modifier whose declaration matches what the mobile query
   already sets for its base class, so nothing above is overridden at any width.
*/

/*
    One photograph and no strip. The card's media area is a two-column grid
    whose second track holds the thumbnails, so without this the 64px track
    would sit empty beside the photo on every current listing.
*/
.hzp-card__media--single {
    grid-template-columns: minmax(0, 1fr);
}

/* The photograph is a link now, so the largest thing on the card opens it. */
.hzp-card__medialink,
.hzp-mini__medialink {
    display: block;
    min-width: 0;
}

/*
    Stands in for a missing photograph. Deliberately not one of the theme's demo
    JPEGs: an invented interior against a real address is a claim about a real
    property, which is the whole thing this page is trying not to do.
*/
.hzp-card__photo--none {
    display: grid;
    place-items: center;
    padding: 16px;
    background: var(--hzp-fill);
    color: var(--hzp-muted);
    font-size: 13px;
    text-align: center;
}

/* The specification rows state an absence rather than printing digits. */
.hzp-specs--none {
    color: var(--hzp-muted);
    font-size: 13px;
}

.hzp-dspecs__none {
    color: var(--hzp-muted);
    font-weight: 400;
}

.hzp-empty {
    display: grid;
    justify-items: start;
    gap: 10px;
    padding: 32px 24px;
    border: 1px solid var(--hzp-line);
    border-radius: var(--hzp-radius);
    background: var(--hzp-fill-soft);
}

.hzp-empty svg {
    width: 28px;
    height: 28px;
    fill: none;
    stroke: var(--hzp-muted);
    stroke-width: 1.6;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.hzp-empty__title {
    margin: 0;
    color: var(--hzp-ink);
    font-size: 19px;
    font-weight: 700;
    letter-spacing: -0.2px;
}

.hzp-empty__text {
    max-width: 62ch;
    margin: 0;
    color: var(--hzp-body);
    font-size: 14.5px;
    line-height: 1.55;
}

.hzp-empty .hzp-btn {
    margin-top: 6px;
}

/* Only rendered when the result set genuinely spans more than one page. */
.hzp-pager {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-top: 18px;
}

.hzp-pager__at {
    color: var(--hzp-muted);
    font-size: 13.5px;
}

/*
    Scoped to anchors so the inert spans that also use .hzp-btn are untouched:
    they are not links and must not be drawn as though they were.
*/
a.hzp-btn {
    text-decoration: none;
}

/* ==========================================================================
   The property attributes
   ==========================================================================

   Added when the two pages stopped saying "not recorded" and started rendering
   the eleven property attributes. Two things needed styling: the search card's
   specification row, which now carries an icon per item where it previously
   held one line of grey text, and the district line under each card heading.

   Appended after the media queries deliberately. Both selectors are new, so
   nothing above is overridden at any width.
*/

/*
    The search card's specification row gained icons. .hzp-specs already laid
    the row out but had no rule for an <svg> inside it, because until now the
    row held only text — without this the icons would render at the browser's
    default replaced-element size and shove the row apart.

    Deliberately a little smaller than the detail page's .hzp-dspecs svg: this
    row is secondary information on a card, not the headline facts on a page.
*/
.hzp-specs svg {
    flex: none;
    width: 16px;
    height: 16px;
    fill: none;
    stroke: var(--hzp-body);
    stroke-width: 1.6;
    stroke-linecap: round;
    stroke-linejoin: round;
}

/*
    District, under the card heading. This is the card's location line, so it is
    drawn like secondary text rather than like the heading above it — the
    district is real, but it is not a street address and should not be read as
    one.
*/
.hzp-card__district {
    display: flex;
    align-items: center;
    gap: 5px;
    margin: 4px 0 0;
    color: var(--hzp-muted);
    font-size: 13px;
}

.hzp-card__district svg {
    flex: none;
    width: 15px;
    height: 15px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.6;
    stroke-linecap: round;
    stroke-linejoin: round;
}

/* ==========================================================================
   The filter bar at narrower widths
   ==========================================================================

   A sticky bar has to stay short, because whatever it occupies is taken away
   from the results for the whole scroll. So below the width where the primary
   controls stop fitting on one line, they fold behind the Filters toggle that
   already exists for the advanced panel — one control, one disclosure, and a
   bar that is a single line tall until someone asks for more.

   Appended after the base rules and after the earlier media queries, so the
   cascade order is explicit rather than depending on where each rule happens to
   sit above.
*/
@media (max-width: 1120px) {
    .hzp-fb__row {
        display: none;
    }

    /*
        Revealed below the search box and the Filters button, which is why the
        two swap order here.
    */
    .hzp-fb__actions {
        order: 2;
    }

    /*
        :has(), because the <details> that replaced the checkbox is a descendant
        of .hzp-fb__actions while the row it reveals is a sibling of that -- so
        there is no sibling combinator that reaches from one to the other, and
        reordering the markup to create one would mean moving the panel out of
        the <details> that owns it.

        The same effect through a sibling selector was what the checkbox bought,
        and it is the only thing lost by dropping it. :has() is in every browser
        this theme already targets, and the failure mode if it were not is the
        row staying folded on a narrow screen -- the panel, the filters and the
        submit all keep working.
    */
    .hzp-fb:has(.hzp-fb__more[open]) .hzp-fb__row {
        display: flex;
        /* Here the row IS a stacked panel, so it wraps on purpose. */
        flex-wrap: wrap;
        flex: 1 1 100%;
        order: 3;
        padding-top: 14px;
        border-top: 1px solid var(--hzp-line);
    }

    /*
        Hung from both edges of the bar rather than from the Filters button.
        There is not enough width here for a 720px panel to sit inside the
        viewport, and a dropdown narrower than the bar it belongs to reads as a
        menu rather than as a panel.
    */
    .hzp-fb__panel {
        inset-inline: 24px;
        width: auto;
        /*
            Lower than the 68vh above, because the panel starts further down
            here: below this width the bar grows a second row when it opens, and
            the panel hangs from the bottom of that. A cap measured only against
            the viewport does not know how far down the panel begins, so the cap
            has to leave room for the tallest bar rather than the shortest.
            Measured at 1120x700, the worst combination this width sees.
        */
        max-height: min(460px, calc(100vh - 320px));
    }
}

/*
    721 to 799px. The bar wraps one more time here, which pushes the panel's top
    edge from 278px down to 369px in Arabic, so the room underneath it is 91px
    less than the band above assumes. Only the cap changes; the panel still hangs
    from the bar at this width.
*/
@media (max-width: 799px) {
    .hzp-fb__panel {
        max-height: min(460px, calc(100vh - 420px));
    }
}

@media (max-width: 720px) {
    .hzp-fb {
        gap: 10px;
        padding-top: 10px;
        padding-bottom: 10px;
    }

    /*
        The field and the Filters button share one line, which keeps the closed
        bar 80px tall instead of 130px. That is the difference between the bar
        costing a tenth of a phone viewport and costing a sixth of it, for the
        whole scroll.
    */
    .hzp-field--location {
        flex: 1 1 150px;
        max-width: none;
    }

    /*
        No rule: at this width the actions sit beside the field rather than at
        the end of a row of controls, so a divider would be separating the search
        box from its own button.
    */
    .hzp-fb__actions {
        flex: 0 0 auto;
        padding-inline-start: 0;
        border-inline-start: 0;
    }

    /*
        The inert Save button this hid is gone, and the rule had to go with it
        rather than being left as dead CSS: the panel's "Show N results" submit
        is also an accent button and IS a descendant of .hzp-fb__actions now, so
        this rule had started hiding the one control in the panel that applies
        the filters -- on phones only, which is where it would have been found
        last.
    */

    /*
        The height cap that used to be here, on the form, is gone for a reason
        rather than forgotten. It existed because the panel was inside the form's
        flow and could grow taller than the viewport. The panel floats now, and
        an overflow on an ancestor CLIPS an absolutely positioned descendant --
        so keeping the cap here would have cut the bottom off the panel, submit
        button included, at exactly the width where the panel is tallest. The cap
        moved onto .hzp-fb__panel itself.
    */
    /*
        On a phone the panel stops hanging from the bar and becomes a sheet held
        against the bottom of the viewport.

        This is a correctness fix, not a restyle. Hanging from the bar, the
        panel's top edge depends on how tall the bar is and on whether the page
        has scrolled far enough to pin it -- measured, that top ranged from 409px
        to 536px on a 844px-tall viewport. A max-height in vh cannot know that
        offset, so any cap generous enough to be useful when the bar is pinned
        ran off the bottom of the screen when it was not, and the submit button
        went with it. The browser check caught it at 390 in both languages.

        Anchored to the bottom instead, the offset stops mattering: the sheet is
        positioned against the viewport, so it is inside the viewport by
        construction at any bar height and any scroll position. It is also the
        pattern a phone actually uses for this, and the Filters button stays
        visible above it, which is what closes it when there is no script.

        dvh with a vh fallback: dvh is what excludes a mobile browser's
        retracting toolbar from the measurement, and vh is what answers if it is
        not supported.
    */
    .hzp-fb__panel {
        position: fixed;
        inset-inline: 8px;
        top: auto;
        bottom: 8px;
        width: auto;
        max-height: 76vh;
        max-height: 76dvh;
        border-radius: 14px;
        z-index: 60;
    }

    .hzp-fb__panelbody,
    .hzp-fb__foot {
        padding-inline: 14px;
    }

    .hzp-checks {
        grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    }
}

/* ==========================================================================
   Add Listing form  (.hzf-*)
   ==========================================================================

   Namespaced .hzf-* and scoped under .hzf-page, so this block cannot reach the
   homepage, the search page or the listing page. Tokens are re-declared here
   rather than inherited, because .hzf-page is not inside .hzp-page; they defer
   to the same --hz-* variables property.css owns, with the same literal
   fallbacks, so the two files stay in step.

   Control heights, radii and the select chrome deliberately match the search
   filter bar: the same 40px control, the same 1px neutral border, the same red
   for the one primary action on the page.
   ========================================================================== */

.hzf-page {
    --hzf-red: var(--hz-red, #d92228);
    --hzf-red-dark: var(--hz-red-dark, #b3171c);
    --hzf-red-tint: #fdecec;
    --hzf-ink: var(--hz-ink, #12141a);
    --hzf-body: #3c414c;
    --hzf-muted: #6b7280;
    --hzf-line: var(--hz-line, #e7e9ee);
    --hzf-line-strong: #d6dae1;
    --hzf-fill: #f4f5f7;
    --hzf-fill-soft: #fafbfc;
    --hzf-radius: 10px;
    --hzf-radius-sm: 6px;

    background: var(--hzf-fill);
    color: var(--hzf-ink);
    font-family: Roboto, sans-serif;
    padding: 28px 20px 64px;
}

.hzf-page *,
.hzf-page *::before,
.hzf-page *::after {
    box-sizing: border-box;
}

/* The conditional fields depend on this. `hidden` has to beat any display rule
   a class of ours sets, or a hidden field stays on screen -- the exact bug the
   search page's empty state hit. */
.hzf-page [hidden] {
    display: none !important;
}

.hzf-page a:focus-visible,
.hzf-page button:focus-visible,
.hzf-page input:focus-visible,
.hzf-page select:focus-visible,
.hzf-page textarea:focus-visible {
    outline: 2px solid var(--hzf-red);
    outline-offset: 2px;
    border-radius: var(--hzf-radius-sm);
}

.hzf-wrap {
    max-width: 880px;
    margin: 0 auto;
}

/* ---------- heading ---------- */

.hzf-head {
    margin-bottom: 20px;
}

.hzf-head__title {
    margin: 0 0 6px;
    font-size: 28px;
    font-weight: 700;
    line-height: 1.2;
    color: var(--hzf-ink);
}

.hzf-head__sub {
    margin: 0;
    max-width: 62ch;
    font-size: 14px;
    line-height: 1.6;
    color: var(--hzf-muted);
}

/* ---------- the honesty notice ---------- */

.hzf-notice {
    display: flex;
    gap: 12px;
    margin-bottom: 22px;
    padding: 14px 16px;
    border: 1px solid #f3c9cb;
    border-inline-start: 3px solid var(--hzf-red);
    border-radius: var(--hzf-radius);
    background: var(--hzf-red-tint);
}

.hzf-notice > svg {
    flex: 0 0 auto;
    width: 20px;
    height: 20px;
    margin-top: 1px;
    fill: none;
    stroke: var(--hzf-red);
    stroke-width: 1.7;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.hzf-notice p {
    margin: 0;
    font-size: 13px;
    line-height: 1.65;
    color: var(--hzf-body);
}

.hzf-notice__title {
    margin-bottom: 3px !important;
    font-weight: 700;
    color: var(--hzf-ink) !important;
}

.hzf-notice a {
    color: var(--hzf-red-dark);
    font-weight: 600;
    text-decoration: underline;
}

.hzf-noscript {
    display: none;
}

/* ---------- cards ---------- */

.hzf-card {
    margin-bottom: 16px;
    padding: 20px;
    border: 1px solid var(--hzf-line);
    border-radius: var(--hzf-radius);
    background: #fff;
}

.hzf-card__head {
    display: flex;
    align-items: center;
    gap: 9px;
    margin-bottom: 16px;
    padding-bottom: 12px;
    border-bottom: 1px solid var(--hzf-line);
}

.hzf-card__title {
    margin: 0;
    font-size: 15px;
    font-weight: 700;
    letter-spacing: .01em;
    color: var(--hzf-ink);
}

.hzf-i {
    flex: 0 0 auto;
    width: 18px;
    height: 18px;
    fill: none;
    stroke: var(--hzf-red);
    stroke-width: 1.7;
    stroke-linecap: round;
    stroke-linejoin: round;
}

/* ---------- grid ---------- */

.hzf-grid {
    display: flex;
    flex-wrap: wrap;
    gap: 16px;
}

.hzf-field {
    flex: 1 1 100%;
    min-width: 0;
}

.hzf-field--half {
    flex: 1 1 calc(50% - 8px);
}

.hzf-field--third {
    flex: 1 1 calc(33.333% - 11px);
}

.hzf-label {
    display: block;
    margin-bottom: 6px;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: .01em;
    color: var(--hzf-body);
}

.hzf-req {
    color: var(--hzf-red);
}

.hzf-hint {
    margin: 6px 0 0;
    font-size: 12px;
    line-height: 1.5;
    color: var(--hzf-muted);
}

.hzf-hint--block {
    margin: 0 0 14px;
}

/* ---------- controls: same 40px as the filter bar ---------- */

.hzf-input {
    display: block;
    width: 100%;
    height: 40px;
    padding: 0 12px;
    border: 1px solid var(--hzf-line-strong);
    border-radius: var(--hzf-radius-sm);
    background: #fff;
    color: var(--hzf-ink);
    font-family: inherit;
    font-size: 14px;
}

.hzf-input::placeholder {
    color: #9aa1ad;
}

.hzf-textarea {
    height: auto;
    min-height: 108px;
    padding: 10px 12px;
    line-height: 1.6;
    resize: vertical;
}

.hzf-select {
    position: relative;
    display: block;
}

.hzf-select::after {
    content: "";
    position: absolute;
    top: 50%;
    inset-inline-end: 12px;
    width: 8px;
    height: 8px;
    margin-top: -6px;
    border-right: 1.6px solid var(--hzf-muted);
    border-bottom: 1.6px solid var(--hzf-muted);
    transform: rotate(45deg);
    pointer-events: none;
}

.hzf-select__el {
    display: block;
    width: 100%;
    height: 40px;
    padding: 0 32px;
    padding-inline-start: 12px;
    border: 1px solid var(--hzf-line-strong);
    border-radius: var(--hzf-radius-sm);
    background: #fff;
    color: var(--hzf-ink);
    font-family: inherit;
    font-size: 14px;
    appearance: none;
    -webkit-appearance: none;
}

/* ---------- error state ---------- */

.hzf-field--bad .hzf-input,
.hzf-field--bad .hzf-select__el {
    border-color: var(--hzf-red);
    background: #fffafa;
}

.hzf-err {
    margin: 6px 0 0;
    font-size: 12px;
    font-weight: 500;
    line-height: 1.5;
    color: var(--hzf-red-dark);
}

/* ---------- amenities ---------- */

.hzf-checks {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 8px 14px;
}

.hzf-check {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 7px 9px;
    border: 1px solid var(--hzf-line);
    border-radius: var(--hzf-radius-sm);
    background: var(--hzf-fill-soft);
    cursor: pointer;
}

.hzf-check:hover {
    border-color: var(--hzf-line-strong);
    background: #fff;
}

.hzf-check__box {
    flex: 0 0 auto;
    width: 15px;
    height: 15px;
    margin: 0;
    accent-color: var(--hzf-red);
    cursor: pointer;
}

.hzf-check__label {
    font-size: 13px;
    line-height: 1.35;
    color: var(--hzf-body);
}

.hzf-check:has(.hzf-check__box:checked) {
    border-color: var(--hzf-red);
    background: var(--hzf-red-tint);
}

.hzf-check:has(.hzf-check__box:checked) .hzf-check__label {
    font-weight: 600;
    color: var(--hzf-ink);
}

.hzf-count {
    margin: 12px 0 0;
    font-size: 12px;
    font-weight: 600;
    color: var(--hzf-muted);
}

/* ---------- photographs ---------- */

.hzf-drop {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    padding: 26px 16px;
    border: 1.5px dashed var(--hzf-line-strong);
    border-radius: var(--hzf-radius);
    background: var(--hzf-fill-soft);
    cursor: pointer;
    text-align: center;
}

.hzf-drop:hover {
    border-color: var(--hzf-red);
    background: #fff;
}

.hzf-drop:focus-within {
    outline: 2px solid var(--hzf-red);
    outline-offset: 2px;
}

.hzf-drop__lead {
    font-size: 14px;
    font-weight: 600;
    color: var(--hzf-ink);
}

.hzf-drop__hint {
    font-size: 12px;
    color: var(--hzf-muted);
}

/* Visually replaced by the label, but still the real focusable control, so it
   is offset rather than display:none -- a hidden input cannot be tabbed to. */
.hzf-drop__input {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
}

.hzf-files {
    margin: 12px 0 0;
    padding: 0;
    list-style: none;
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

.hzf-files__item {
    padding: 4px 9px;
    border: 1px solid var(--hzf-line);
    border-radius: 999px;
    background: var(--hzf-fill);
    font-size: 12px;
    color: var(--hzf-body);
}

/* ---------- actions ---------- */

.hzf-actions {
    margin-top: 20px;
    padding: 18px 20px;
    border: 1px solid var(--hzf-line);
    border-radius: var(--hzf-radius);
    background: #fff;
}

.hzf-actions__row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
}

.hzf-actions__note {
    margin: 12px 0 0;
    font-size: 12px;
    line-height: 1.55;
    color: var(--hzf-muted);
}

.hzf-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    height: 42px;
    padding: 0 18px;
    border: 1px solid var(--hzf-line-strong);
    border-radius: var(--hzf-radius-sm);
    background: #fff;
    color: var(--hzf-ink);
    font-family: inherit;
    font-size: 14px;
    font-weight: 600;
    text-decoration: none;
    cursor: pointer;
}

.hzf-btn svg {
    width: 17px;
    height: 17px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.7;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.hzf-btn--primary {
    border-color: var(--hzf-red);
    background: var(--hzf-red);
    color: #fff;
}

.hzf-btn--primary:hover {
    border-color: var(--hzf-red-dark);
    background: var(--hzf-red-dark);
}

.hzf-btn--ghost:hover {
    border-color: var(--hzf-red);
    color: var(--hzf-red-dark);
}

/* ---------- validation summary ---------- */

.hzf-summary {
    margin-bottom: 16px;
    padding: 14px 16px;
    border: 1px solid #f3c9cb;
    border-inline-start: 3px solid var(--hzf-red);
    border-radius: var(--hzf-radius);
    background: var(--hzf-red-tint);
}

.hzf-summary__title {
    margin: 0 0 8px;
    font-size: 13px;
    font-weight: 700;
    color: var(--hzf-ink);
}

.hzf-summary__list {
    margin: 0;
    padding-inline-start: 18px;
}

.hzf-summary__list li {
    margin-bottom: 3px;
    font-size: 13px;
    line-height: 1.55;
}

.hzf-summary__list a {
    color: var(--hzf-red-dark);
    text-decoration: underline;
}

/* ---------- responsive ---------- */

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

    .hzf-field--third {
        flex: 1 1 calc(50% - 8px);
    }
}

@media (max-width: 640px) {
    .hzf-page {
        padding: 20px 14px 48px;
    }

    .hzf-head__title {
        font-size: 22px;
    }

    .hzf-card {
        padding: 16px 14px;
    }

    .hzf-checks {
        grid-template-columns: 1fr;
    }

    /* One field per line below this width: two 50% fields with a Choose... menu
       inside them cannot show their own labels without truncating. */
    .hzf-field--half,
    .hzf-field--third {
        flex: 1 1 100%;
    }

    .hzf-actions {
        padding: 14px;
    }

    /* Full-width stacked buttons, so the primary action is not a 40%-wide
       target next to a phone link of the same weight. */
    .hzf-actions__row {
        flex-direction: column;
        align-items: stretch;
    }

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

/* ==========================================================================
   LISTING DETAIL REDESIGN
   ==========================================================================

   Appended for the redesigned listing detail page. Everything here is scoped
   under .hzp-detail or a .hzp-* class only that page uses, so nothing reaches
   the homepage, the header/footer or the search page. Tokens are the ones
   already declared on .hzp-page — no new colour, radius or hairline is
   introduced, because the point is that this page looks like the rest of the
   site rather than like a second design.

   Three groups: the gallery's overlay and thumbnail controls, the payment
   calculator's real inputs, and the sidebar's four cards.
   ========================================================================== */

/* Links styled as buttons: three of the sidebar actions are anchors now that
   they genuinely go somewhere, and an anchor carries an underline. */
.hzp-detail .hzp-btn {
    text-decoration: none;
}

/* ------------------------------------------------------ gallery overlay --- */

/*
    Top-right of the primary photograph, as the mockup has it. A span for the
    heart and a button for share sit side by side and must look identical, so
    the appearance is on the shared class and only the cursor differs.
*/



/* Only the share control is a real button, so only it gets a pointer and a
   hover. The heart deliberately looks the same and does nothing, matching the
   inert-heart treatment used on the search and home cards. */



/* The share button reports which of the two things it did. */

/* --------------------------------------------------- gallery thumbnails --- */

/*
    Real controls now: each thumbnail swaps the main photograph. Styled as a
    button with the chrome stripped, because a button is what it is.
*/


/* The selected thumbnail, so it is obvious which photograph is showing. */


/*
    The mockup's "+N Photos" plate. N is computed from the gallery, so this only
    appears when there genuinely are more photographs than the strip shows.
*/

/* Shown instead of a strip when there is one photograph, which is every
   listing in this catalogue today. */

/* ------------------------------------------------------- price and head --- */

/*
    The red payment pill from the mockup. Filled rather than tinted, because in
    the mockup it is the one saturated element beside the price and that is what
    gives the block its balance. It is a link to the calculator that produced it.
*/
.hzp-paypill {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    align-self: center;
    padding: 6px 13px;
    border-radius: 999px;
    background: var(--hzp-red);
    color: #ffffff;
    font-size: 13.5px;
    font-weight: 600;
    text-decoration: none;
    white-space: nowrap;
}

.hzp-paypill svg {
    flex: none;
    width: 15px;
    height: 15px;
    fill: none;
    stroke: #ffffff;
    stroke-width: 1.7;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.hzp-paypill:hover {
    background: var(--hzp-red-dark);
}

.hzp-paypill:focus-visible {
    outline: 2px solid var(--hzp-ink);
    outline-offset: 2px;
}

/* The location line takes a pin, as the mockup has it. */
.hzp-daddr {
    display: flex;
    align-items: center;
    gap: 6px;
}

.hzp-daddr svg {
    flex: none;
    width: 15px;
    height: 15px;
    fill: none;
    stroke: var(--hzp-red);
    stroke-width: 1.7;
    stroke-linecap: round;
    stroke-linejoin: round;
}

/* --------------------------------------------------------- key features --- */

/*
    Bordered chips rather than a ticked list. A tick reads as a verified claim;
    a chip reads as a label, which is what an amenity option is.
*/
/*
    A grid rather than a wrapping flex row, so the chips share the width evenly
    and the row reads as a set — which is how the mockup has it. auto-fit
    collapses the empty tracks, so four amenities give four equal chips rather
    than four narrow ones and a gap; and unlike flex there is no stretched
    last row when the count does not divide evenly.
*/
.hzp-chips {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
    gap: 8px;
    margin: 0;
    padding: 0;
    list-style: none;
}

/* flex, not inline-flex: as a grid item it should fill its track. */
.hzp-chip {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 9px 13px;
    border: 1px solid var(--hzp-line);
    border-radius: var(--hzp-radius-sm);
    background: #ffffff;
    color: var(--hzp-ink);
    font-size: 13px;
    font-weight: 500;
}

.hzp-chip svg {
    flex: none;
    width: 16px;
    height: 16px;
    fill: none;
    stroke: var(--hzp-red);
    stroke-width: 1.6;
    stroke-linecap: round;
    stroke-linejoin: round;
}

/* ---------------------------------------------------- payment calculator --- */

/*
    Fields hug the top of their row. Property price is the one field with no
    slider under it, so its two rows were sharing the height of a three-row
    neighbour and its readout sat visibly lower than the deposit's. Scoped to
    this page because the class predates it.
*/
.hzp-detail .hzp-calc__field {
    align-content: start;
}

/*
    The sliders. Cross-browser range styling needs the two vendor track/thumb
    pairs written out; there is no shorthand that covers both.

    Named .hzp-slider, NOT .hzp-range. The search page has owned .hzp-range
    since the filter bar was built — it is the wrapper around the price min/max
    pair — and this file is shared by both pages. Calling the mortgage input
    .hzp-range put "height: 18px" on that wrapper from further down the
    stylesheet, which collapsed it to 18px around two 40px inputs; the wrapper's
    own "align-items: center" then centred them, so they overflowed 11px above
    the box and struck the "Price (JOD)" label. The detail page looked correct
    throughout, because the collision only shows on the other page. Anything
    added here needs a name the earlier sections do not already use.
*/
.hzp-slider {
    width: 100%;
    height: 18px;
    margin: 1px 0 0;
    padding: 0;
    background: none;
    -webkit-appearance: none;
    appearance: none;
    cursor: pointer;
}

.hzp-slider::-webkit-slider-runnable-track {
    height: 4px;
    border-radius: 999px;
    background: var(--hzp-line-strong);
}

.hzp-slider::-webkit-slider-thumb {
    width: 15px;
    height: 15px;
    margin-top: -5.5px;
    border: 2px solid #ffffff;
    border-radius: 999px;
    background: var(--hzp-red);
    box-shadow: 0 0 0 1px var(--hzp-red);
    -webkit-appearance: none;
    appearance: none;
}

.hzp-slider::-moz-range-track {
    height: 4px;
    border-radius: 999px;
    background: var(--hzp-line-strong);
}

.hzp-slider::-moz-range-thumb {
    width: 13px;
    height: 13px;
    border: 2px solid #ffffff;
    border-radius: 999px;
    background: var(--hzp-red);
    box-shadow: 0 0 0 1px var(--hzp-red);
}

.hzp-slider:focus-visible {
    outline: 2px solid var(--hzp-red);
    outline-offset: 3px;
}

/*
    Replaces the mockup's "View full mortgage guide" link with the disclosure it
    would have to lead to. Sits inside the red output box, so it inherits that
    box's darker red for text.
*/
.hzp-calc__how {
    margin-top: 8px;
    text-align: start;
}

.hzp-calc__how summary {
    color: var(--hzp-red-dark);
    cursor: pointer;
    font-size: 12px;
    font-weight: 600;
    text-align: center;
    text-decoration: underline;
}

.hzp-calc__how summary:focus-visible {
    outline: 2px solid var(--hzp-red-dark);
    outline-offset: 2px;
}

.hzp-calc__how p {
    margin: 8px 0 0;
    color: #7a1d20;
    font-size: 11.5px;
    line-height: 1.55;
}

/* The mockup's summary row: loan amount, total interest, total payment. All
   three recompute with the sliders. */
.hzp-sums {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 12px;
    margin-top: 14px;
    padding-top: 14px;
    border-top: 1px solid var(--hzp-line);
}

.hzp-sums__item {
    display: grid;
    gap: 3px;
    min-width: 0;
}

.hzp-sums__label {
    color: var(--hzp-muted);
    font-size: 11.5px;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

.hzp-sums__value {
    color: var(--hzp-ink);
    font-size: 14.5px;
    font-weight: 600;
}

/* ------------------------------------------------------------- sidebar --- */

.hzp-agentcard {
    padding: 16px;
    border: 1px solid var(--hzp-line);
    border-radius: var(--hzp-radius);
    background: #ffffff;
}

.hzp-agentcard__title {
    margin: 0 0 12px;
    color: var(--hzp-ink);
    font-size: 15px;
    font-weight: 700;
}

.hzp-agentcard__line {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 12px 0;
    font-size: 13.5px;
}

.hzp-agentcard__line svg {
    flex: none;
    width: 15px;
    height: 15px;
    fill: none;
    stroke: var(--hzp-red);
    stroke-width: 1.7;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.hzp-agentcard__line a {
    color: var(--hzp-ink);
    font-weight: 600;
    text-decoration: none;
}

.hzp-agentcard__line a:hover {
    color: var(--hzp-red);
}

/* The "Safe & transparent" note. A statement about this page's own policy,
   which is the one thing on the card that can be said without data. */
.hzp-safe {
    display: flex;
    gap: 11px;
    padding: 14px 16px;
    border: 1px solid var(--hzp-line);
    border-radius: var(--hzp-radius);
    background: var(--hzp-fill-soft);
}

.hzp-safe svg {
    flex: none;
    width: 19px;
    height: 19px;
    margin-top: 1px;
    fill: none;
    stroke: #1f9d63;
    stroke-width: 1.6;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.hzp-safe__title {
    margin: 0 0 3px;
    color: var(--hzp-ink);
    font-size: 13.5px;
    font-weight: 600;
}

.hzp-safe__text {
    margin: 0;
    color: var(--hzp-muted);
    font-size: 11.5px;
    line-height: 1.55;
}

/* --------------------------------------------------- similar properties --- */

.hzp-rail__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    margin-bottom: 12px;
}

/* The rail title carries its own bottom margin elsewhere; inside the flex head
   it would push the controls out of line. */
.hzp-rail__head .hzp-rail__title {
    margin: 0;
}

.hzp-rail__tools {
    display: flex;
    flex: none;
    align-items: center;
    gap: 8px;
}

.hzp-rail__nav {
    display: inline-flex;
    width: 32px;
    height: 32px;
    padding: 0;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--hzp-line-strong);
    border-radius: 999px;
    background: #ffffff;
    color: var(--hzp-ink);
    cursor: pointer;
    font: inherit;
}

.hzp-rail__nav svg {
    width: 15px;
    height: 15px;
    fill: none;
    stroke: currentColor;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
}

/* The back arrow is the same glyph turned round, so there is one path to keep
   correct rather than two. */
.hzp-rail__nav[data-hzd-scroll="-1"] svg {
    transform: rotate(180deg);
}

.hzp-rail__nav:hover:not([disabled]) {
    border-color: var(--hzp-red);
    color: var(--hzp-red);
}

.hzp-rail__nav[disabled] {
    color: var(--hzp-line-strong);
    cursor: default;
}

.hzp-rail__nav:focus-visible {
    outline: 2px solid var(--hzp-red);
    outline-offset: 2px;
}

.hzp-rail__all {
    color: var(--hzp-ink);
    font-size: 13px;
    font-weight: 600;
    text-decoration: none;
    white-space: nowrap;
}

.hzp-rail__all:hover {
    color: var(--hzp-red);
}

/*
    Wider cards than the base .hzp-mini, and scoped to this page so nothing else
    that uses the class moves.

    This is load-bearing rather than cosmetic. Five cards at the base 214px plus
    four 14px gaps is 1126px, which fits inside the 1152px shell — so the track
    did not overflow, there was nothing to scroll, and both arrows correctly
    disabled themselves. A carousel whose controls are always dead is not a
    carousel. At 246px the five come to 1286px, so the fifth is clipped and the
    arrows have something to do, which is also how the mockup shows it.
*/
.hzp-detail .hzp-mini {
    width: 246px;
}

/*
    [hidden] sets display: none at a specificity a class rule beats, and
    .hzp-rail__nav sets display: inline-flex — so without this the script can
    hide an arrow and nothing happens. This is the same collision that bit the
    search page's empty state.
*/
.hzp-rail__nav[hidden] {
    display: none;
}

/* The district under each carousel card, which is a real attribute. */
.hzp-mini__where {
    margin: 3px 0 0;
    color: var(--hzp-muted);
    font-size: 12px;
}

/* ------------------------------------------------------------ narrower --- */

/*
    The two breakpoints the RESPONSIVE section above already uses, reused rather
    than introduced: 1023.98px is where .hzp-dgrid drops its sidebar column and
    767.98px is where .hzp-calc drops its output column. Adding 1080 and 760 here
    would give this page two sets of breakpoints a few pixels apart, which is how
    a stylesheet starts disagreeing with itself.
*/

@media (max-width: 1023.98px) {
    /* The sidebar is under the main column from here down (see .hzp-dgrid
       above), so its cards sit two across rather than as a tall stack below
       the fold. */
    .hzp-dside {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@media (max-width: 767.98px) {
    .hzp-dside {
        grid-template-columns: minmax(0, 1fr);
    }

    /*
        One column for the calculator fields from here rather than at 479.98px,
        where the base rule puts them. Two 38px readouts each with a slider
        under it leaves the thumb about 60px of travel at this width, which is
        not a usable control — and the slider is the point of the panel now.
    */
    .hzp-calc__fields {
        grid-template-columns: minmax(0, 1fr);
    }

    /* Three figures side by side wrap mid-number at this width. */
    .hzp-sums {
        grid-template-columns: minmax(0, 1fr);
        gap: 10px;
    }

    /* .hzp-dprice already wraps; the pill just needs to stop centring on the
       price's baseline once it is on its own line. */
    .hzp-paypill {
        align-self: flex-start;
    }



    /* The rail's arrows and "View all" go under the heading. */
    .hzp-rail__head {
        flex-wrap: wrap;
        gap: 10px;
    }
}

/*
   ====================================================================
   SERP SIDEBAR — SELL YOUR PROPERTY PANEL
   Replaces the dashed "Promotional slot" placeholder. Built to the
   supplied reference: deep blue ground, two white feature chips and
   a coral pill CTA.

   Prefix .hzp-sell, which no other rule or template in this theme uses.
   ==================================================================== */

.hzp-sell {
    position: relative;
    overflow: hidden;
    padding: 20px 18px;
    border-radius: var(--hzp-radius);
    background: #06358F;
}

/* The reference's soft tonal circles. Painted with white at low alpha so
   they track the ground rather than needing colours of their own. */
.hzp-sell::before {
    position: absolute;
    inset-inline-end: -38px;
    bottom: -46px;
    width: 150px;
    height: 150px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.05);
    content: "";
}

.hzp-sell > * {
    position: relative;
    z-index: 1;
}

/* The illustration. At a 300px column it cannot sit beside the headline
   without squeezing it to four lines, so it sits behind the top-right
   corner as a watermark instead — present, but not competing. */
.hzp-sell__art {
    position: absolute;
    top: 6px;
    inset-inline-end: 2px;
    z-index: 0;
    width: 84px;
    height: auto;
    opacity: 0.92;
    pointer-events: none;
}

.hzp-sell__title {
    max-width: 8.5em;
    margin: 0;
    color: #ffffff;
    font-size: 21px;
    font-weight: 800;
    letter-spacing: -0.01em;
    line-height: 1.18;
}

.hzp-sell__text {
    max-width: 15em;
    margin: 9px 0 0;
    color: #D7E3FF;
    font-size: 13px;
    line-height: 1.45;
}

.hzp-sell__chips {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 15px;
}

/* Labels, not controls: no hover, no pointer, no focus target. */
.hzp-sell__chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 7px 11px;
    border-radius: 999px;
    background: #ffffff;
    color: #212026;
    font-size: 12.5px;
    font-weight: 700;
    cursor: default;
}

.hzp-sell__chip svg {
    flex: none;
    width: 15px;
    height: 15px;
}

.hzp-sell__cta {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 9px;
    margin-top: 15px;
    padding: 13px 16px;
    border-radius: 999px;
    background: #ec6555;
    color: #ffffff;
    font-size: 14.5px;
    font-weight: 700;
    text-align: center;
    text-decoration: none;
}

.hzp-sell__cta:hover {
    background: #e2513f;
}

.hzp-sell__cta:focus-visible {
    outline: 2px solid #ffffff;
    outline-offset: 2px;
}

.hzp-sell__cta svg {
    flex: none;
    width: 17px;
    height: 17px;
    fill: none;
    stroke: currentColor;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
}

/*
   Below the sidebar breakpoint the column stacks under the results, so the
   panel lands between the last listing and the footer. Kept, but tightened:
   the headline drops a step, the chips sit on one row and the artwork goes,
   since a full-height promo there pushes the footer a long way down.
*/
@media (max-width: 1023.98px) {
    .hzp-sell {
        padding: 17px 16px;
    }

    .hzp-sell__art {
        display: none;
    }

    .hzp-sell__title {
        max-width: none;
        font-size: 19px;
    }
}

/* ====================================================================
   PROPERTY GALLERY  (.hzpg-)
   Prefix chosen because .hzp-g* already carries the old gallery and
   .hzg- belongs to the Add Listing page. Nothing else in this theme
   uses .hzpg-.

   Blue is the token another stylesheet defines; the literal fallback
   keeps these rules correct on their own. It is used for the active
   thumbnail edge and focus rings only — the gallery stays white, dark
   neutral and grey.
   ==================================================================== */

.hzp-detail .hzpg {
    --hzpg-accent: var(--hagzi-primary, #0745D9);

    display: grid;
    gap: 10px;
    min-width: 0;
}

/* Desktop mosaic; phones use a full-size swipe carousel without thumbnails. */
.hzp-detail .hzpg__side { display: none; }
.hzp-detail .hzpg__swipe { display: none; }
.hzp-detail .hzpg__dots { display: none; }
@media (min-width: 768px) {
    /* Keep the gallery frame the same height for one or many photographs. */
    .hzp-detail .hzpg--mosaic,
    .hzp-detail .hzpg--single {
        grid-template-rows: minmax(0, 1fr);
        gap: 8px;
        aspect-ratio: 2.1 / 1;
    }
    .hzp-detail .hzpg--mosaic {
        grid-template-columns: minmax(0, 2.5fr) minmax(0, 1fr);
    }
    .hzp-detail .hzpg--single {
        grid-template-columns: minmax(0, 1fr);
    }
    .hzp-detail .hzpg--mosaic .hzpg__stage,
    .hzp-detail .hzpg--single .hzpg__stage {
        min-width: 0;
        min-height: 0;
        height: 100%;
        aspect-ratio: auto;
        border-radius: 12px;
    }
    .hzp-detail .hzpg--mosaic .hzpg__rail { display: none; }
    .hzp-detail .hzpg__side {
        display: grid;
        grid-template-rows: repeat(2, minmax(0, 1fr));
        gap: 8px;
        min-width: 0;
        min-height: 0;
    }
    .hzp-detail .hzpg__side[data-hzpg-previews="3"] {
        grid-template-rows: minmax(0, 2fr) repeat(2, minmax(0, 1fr));
    }
    .hzp-detail .hzpg__preview {
        position: relative;
        display: block;
        min-width: 0;
        min-height: 0;
        width: 100%;
        height: 100%;
        overflow: hidden;
        padding: 0;
        border: 0;
        border-radius: 8px;
        background: var(--hzp-fill);
        cursor: pointer;
    }
    .hzp-detail .hzpg__preview.hzpg__thumb--on {
        padding: 0;
        outline: 2px solid var(--hzpg-accent);
        outline-offset: -2px;
    }
    .hzp-detail .hzpg__preview:focus-visible {
        outline: 3px solid var(--hzpg-accent);
        outline-offset: 2px;
    }
    .hzp-detail .hzpg__previewimg {
        display: block;
        width: 100%;
        height: 100%;
        object-fit: cover;
    }
    .hzp-detail .hzpg__more {
        position: absolute;
        inset-inline-end: 12px;
        bottom: 12px;
        padding: 8px 12px;
        border-radius: 999px;
        background: rgba(18, 20, 26, .78);
        color: #fff;
        font-size: 14px;
        font-weight: 600;
        line-height: 1.4;
    }
}

/* ------------------------------------------------------------ stage ---- */

.hzp-detail .hzpg__stage {
    position: relative;
    overflow: hidden;
    aspect-ratio: 16 / 9;
    border-radius: 14px;
    background: var(--hzp-fill);
}

/* The photo opens the popup; favorite and share stay independent above it. */
.hzp-detail .hzpg__image-open {
    position: absolute;
    inset: 0;
    display: block;
    width: 100%;
    height: 100%;
    padding: 0;
    border: 0;
    background: transparent;
    cursor: pointer;
}
.hzp-detail .hzpg__image-open:focus-visible {
    outline: 3px solid var(--hzpg-accent);
    outline-offset: -3px;
}
.hzp-detail .hzpg__badges,
.hzp-detail .hzpg__count { pointer-events: none; }
.hzp-detail .hzpg__preview .hzpg__all {
    max-width: calc(100% - 24px);
    justify-content: center;
    font-size: 13px;
    line-height: 1.4;
}

.hzp-detail .hzpg__img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.hzp-detail .hzpg__badges {
    position: absolute;
    top: 12px;
    inset-inline-start: 12px;
    z-index: 3;
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    max-width: calc(100% - 120px);
}

.hzp-detail .hzpg__tools {
    position: absolute;
    top: 12px;
    inset-inline-end: 12px;
    z-index: 3;
    display: flex;
    gap: 8px;
}

/* Circular, white, neutral border. Blue only on hover and focus, so
   neither reads as permanently active. */
.hzp-detail .hzpg__tool {
    display: grid;
    place-items: center;
    width: 36px;
    height: 36px;
    padding: 0;
    border: 1px solid var(--hzp-line-strong);
    border-radius: 50%;
    background: #ffffff;
    color: var(--hzp-ink);
    cursor: pointer;
}

.hzp-detail .hzpg__tool[aria-disabled="true"] {
    cursor: default;
}

.hzp-detail button.hzpg__tool:hover {
    border-color: var(--hzpg-accent);
    color: var(--hzpg-accent);
}

.hzp-detail .hzpg__tool:focus-visible {
    outline: 2px solid var(--hzpg-accent);
    outline-offset: 2px;
}

.hzp-detail .hzpg__tool svg {
    width: 17px;
    height: 17px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.7;
    stroke-linecap: round;
    stroke-linejoin: round;
}

/* --------------------------------------------------- stage controls ---- */

.hzp-detail .hzpg__nav {
    position: absolute;
    top: 50%;
    z-index: 3;
    display: grid;
    place-items: center;
    width: 40px;
    height: 40px;
    margin-top: -20px;
    padding: 0;
    border: 1px solid var(--hzp-line-strong);
    border-radius: 50%;
    background: #ffffff;
    color: var(--hzp-ink);
    cursor: pointer;
}

.hzp-detail .hzpg__nav:hover {
    border-color: var(--hzpg-accent);
    color: var(--hzpg-accent);
}

.hzp-detail .hzpg__nav:focus-visible {
    outline: 2px solid var(--hzpg-accent);
    outline-offset: 2px;
}

.hzp-detail .hzpg__nav svg {
    width: 18px;
    height: 18px;
}

.hzp-detail .hzpg__nav--prev { inset-inline-start: 12px; }
.hzp-detail .hzpg__nav--next { inset-inline-end: 12px; }

.hzp-detail .hzpg__count {
    position: absolute;
    inset-inline-start: 12px;
    bottom: 12px;
    z-index: 3;
    margin: 0;
    padding: 5px 10px;
    border-radius: 999px;
    background: rgba(18, 20, 26, 0.62);
    color: #ffffff;
    font-size: 12.5px;
    font-weight: 600;
}

.hzp-detail .hzpg__all {
    position: absolute;
    inset-inline-end: 12px;
    bottom: 12px;
    z-index: 3;
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 8px 13px;
    border: 1px solid var(--hzp-line-strong);
    border-radius: 999px;
    background: #ffffff;
    color: var(--hzp-ink);
    font-family: inherit;
    font-size: 12.5px;
    font-weight: 600;
    cursor: pointer;
}

.hzp-detail .hzpg__all:hover {
    border-color: var(--hzpg-accent);
    color: var(--hzpg-accent);
}

.hzp-detail .hzpg__all:focus-visible {
    outline: 2px solid var(--hzpg-accent);
    outline-offset: 2px;
}

.hzp-detail .hzpg__all svg {
    width: 15px;
    height: 15px;
}

/* ------------------------------------------------------------- rail ---- */

.hzp-detail .hzpg__rail {
    position: relative;
    min-width: 0;
}

/* Room for the arrows, so neither of them covers a thumbnail — and only when
   there are arrows. The attribute is set by the rail's own measurement. This
   way round rather than the reverse because the roomier state is the default,
   so adding the padding can never turn a row that fits into one that does not. */
.hzp-detail .hzpg__rail[data-hzpg-scrolls] {
    padding: 0 36px;
}

/* One row, never wrapping. The scroll lives here, so the page cannot
   gain a horizontal scrollbar however many photographs arrive. */
.hzp-detail .hzpg__strip {
    display: flex;
    flex-wrap: nowrap;
    gap: 8px;
    overflow-x: auto;
    overflow-y: hidden;
    scroll-behavior: smooth;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
}

.hzp-detail .hzpg__strip::-webkit-scrollbar {
    display: none;
}

.hzp-detail .hzpg__thumb {
    flex: 1 0 112px;
    overflow: hidden;
    max-width: 172px;
    height: 82px;
    padding: 0;
    border: 2px solid transparent;
    border-radius: 8px;
    background: var(--hzp-fill);
    cursor: pointer;
}

/* The active outline, in Hagzi's primary rather than the reference's blue.
   The 2px inset lets a little of the card show inside the outline, so the
   selected thumbnail reads as ringed rather than merely bordered. */
.hzp-detail .hzpg__thumb--on {
    border-color: var(--hzpg-accent);
    padding: 2px;
    background: #ffffff;
}

.hzp-detail .hzpg__thumb--on .hzpg__thumbimg {
    border-radius: 4px;
}

.hzp-detail .hzpg__thumb:focus-visible {
    outline: 2px solid var(--hzpg-accent);
    outline-offset: 2px;
}

.hzp-detail .hzpg__thumbimg {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.hzp-detail .hzpg__railnav {
    position: absolute;
    top: 50%;
    z-index: 2;
    display: grid;
    place-items: center;
    width: 30px;
    height: 30px;
    margin-top: -15px;
    padding: 0;
    border: 1px solid var(--hzp-line-strong);
    border-radius: 50%;
    background: #ffffff;
    color: var(--hzp-ink);
    cursor: pointer;
}

.hzp-detail .hzpg__railnav[hidden] {
    display: none;
}

.hzp-detail .hzpg__railnav[disabled] {
    opacity: 0.35;
    cursor: default;
}

.hzp-detail .hzpg__railnav:hover:not([disabled]) {
    border-color: var(--hzpg-accent);
    color: var(--hzpg-accent);
}

.hzp-detail .hzpg__railnav:focus-visible {
    outline: 2px solid var(--hzpg-accent);
    outline-offset: 2px;
}

.hzp-detail .hzpg__railnav svg {
    width: 15px;
    height: 15px;
}

.hzp-detail .hzpg__railnav--prev { inset-inline-start: 0; }
.hzp-detail .hzpg__railnav--next { inset-inline-end: 0; }

/* --------------------------------------------------------- lightbox ---- */

.hzpg-locked,
.hzpg-locked body {
    overflow: hidden;
}

.hzp-detail .hzpg-lb {
    position: fixed;
    inset: 0;
    z-index: 120;
    display: grid;
    grid-template-rows: auto minmax(0, 1fr) auto auto;
    gap: 12px;
    padding: 12px 0 max(12px, env(safe-area-inset-bottom));
    overflow: hidden;
    background: rgba(8, 9, 11, 0.94);
    color: #fff;
}

.hzp-detail .hzpg-lb[hidden] {
    display: none;
}

.hzp-detail .hzpg-lb__header {
    display: flex;
    justify-content: center;
    min-width: 0;
    padding: 0 60px;
}

.hzp-detail .hzpg-lb__collection {
    padding: 10px 16px 12px;
    border-bottom: 2px solid #79b9f2;
    color: #79b9f2;
    font-size: 14px;
    font-weight: 600;
    line-height: 1.4;
    text-align: center;
}

.hzp-detail .hzpg-lb__stage {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 0;
    min-width: 0;
    padding: 0 60px;
    touch-action: pan-y;
}

.hzp-detail .hzpg-lb__img {
    display: block;
    width: 100%;
    height: 100%;
    min-height: 0;
    max-width: 100%;
    max-height: 100%;
    margin: 0;
    border-radius: 0;
    object-fit: contain;
}

.hzp-detail .hzpg-lb__nav,
.hzp-detail .hzpg-lb__close {
    display: grid;
    place-items: center;
    width: 44px;
    height: 44px;
    padding: 0;
    border: 0;
    border-radius: 6px;
    background: transparent;
    color: #fff;
    cursor: pointer;
}

.hzp-detail .hzpg-lb__nav:hover,
.hzp-detail .hzpg-lb__close:hover {
    background: rgba(255, 255, 255, 0.12);
}

.hzp-detail .hzpg-lb__nav:focus-visible,
.hzp-detail .hzpg-lb__close:focus-visible,
.hzp-detail .hzpg-lb__thumb:focus-visible {
    outline: 2px solid #fff;
    outline-offset: -2px;
}

.hzp-detail .hzpg-lb__nav svg,
.hzp-detail .hzpg-lb__close svg {
    width: 24px;
    height: 24px;
}

.hzp-detail .hzpg-lb__nav {
    position: absolute;
    top: 50%;
    z-index: 1;
    transform: translateY(-50%);
}

.hzp-detail .hzpg-lb__nav--prev { left: 8px; }
.hzp-detail .hzpg-lb__nav--next { right: 8px; }

.hzp-detail .hzpg-lb__close {
    position: absolute;
    top: 12px;
    right: 12px;
    z-index: 2;
}

.hzp-detail .hzpg-lb__count {
    margin: 0;
    color: #fff;
    font-size: 16px;
    font-weight: 500;
    line-height: 1.5;
    text-align: center;
    font-variant-numeric: tabular-nums;
}

.hzp-detail .hzpg-lb__strip {
    min-width: 0;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scrollbar-width: thin;
    scrollbar-color: #62666d transparent;
    direction: ltr;
}

.hzp-detail .hzpg-lb__thumbnails {
    display: flex;
    gap: 10px;
    width: max-content;
    margin: 0 auto;
    padding: 2px 20px 6px;
}

.hzp-detail .hzpg-lb__thumb {
    display: block;
    flex: 0 0 auto;
    width: clamp(72px, 11vh, 112px);
    height: clamp(64px, 10vh, 100px);
    padding: 0;
    overflow: hidden;
    border: 2px solid transparent;
    border-radius: 3px;
    background: #181a1d;
    opacity: 0.5;
    cursor: pointer;
    transition: opacity 120ms ease, border-color 120ms ease;
}

.hzp-detail .hzpg-lb__thumb:hover {
    opacity: 0.85;
}

.hzp-detail .hzpg-lb__thumb--on {
    border-color: #79b9f2;
    opacity: 1;
}

.hzp-detail .hzpg-lb__thumb img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* ------------------------------------------------------------ small ---- */

@media (max-width: 767.98px) {
    /* Break out of the shell's 24px gutters for edge-to-edge mobile photos. */
    .hzp-detail .hzp-dgallery {
        margin-inline: -24px;
    }

    .hzp-detail .hzpg { gap: 0; }

    .hzp-detail .hzpg__stage {
        aspect-ratio: 4 / 3;
        border-radius: 0;
    }

    .hzp-detail .hzpg__dots {
        position: absolute;
        z-index: 4;
        bottom: 12px;
        left: 50%;
        transform: translateX(-50%);
        display: flex;
        flex-wrap: wrap;
        justify-content: center;
        width: max-content;
        max-width: calc(100% - 128px);
        direction: ltr;
    }

    .hzp-detail .hzpg__dot {
        display: grid;
        place-items: center;
        flex: 0 0 24px;
        width: 24px;
        height: 32px;
        padding: 0;
        border: 0;
        border-radius: 50%;
        background: transparent;
        cursor: pointer;
    }

    .hzp-detail .hzpg__dot span {
        width: 8px;
        height: 8px;
        border-radius: 50%;
        background: rgba(255, 255, 255, .8);
        box-shadow: 0 1px 4px rgba(0, 0, 0, .4);
    }

    .hzp-detail .hzpg__dot[aria-pressed="true"] span {
        background: var(--hzpg-accent);
        transform: scale(1.25);
    }

    .hzp-detail .hzpg__dot:focus-visible {
        outline: 2px solid var(--hzpg-accent);
        outline-offset: -2px;
    }

    /* Swipe is the better gesture at this width and the arrows cover the
       photograph, so they go and the swipe handler carries it. */
    .hzp-detail .hzpg__nav {
        display: none;
    }

    .hzp-detail .hzpg__rail,
    .hzp-detail .hzpg__stage > .hzpg__image-open {
        display: none;
    }

    .hzp-detail .hzpg__swipe {
        position: absolute;
        inset: 0;
        display: flex;
        overflow-x: auto;
        overflow-y: hidden;
        scroll-snap-type: x mandatory;
        overscroll-behavior-x: contain;
        scrollbar-width: none;
        direction: ltr;
        -webkit-overflow-scrolling: touch;
    }

    .hzp-detail .hzpg__swipe::-webkit-scrollbar { display: none; }

    .hzp-detail .hzpg__swipe-photo {
        flex: 0 0 100%;
        min-width: 0;
        height: 100%;
        padding: 0;
        border: 0;
        background: transparent;
        scroll-snap-align: start;
        scroll-snap-stop: always;
        cursor: pointer;
    }

    .hzp-detail .hzpg__swipe-photo:focus-visible {
        outline: 3px solid var(--hzpg-accent);
        outline-offset: -3px;
    }

    /* Compact photo action on narrow screens. */
    .hzp-detail .hzpg__all {
        padding: 9px 13px;
        font-size: 12px;
    }

    .hzp-detail .hzpg__railnav {
        display: none;
    }

    .hzp-detail .hzpg__rail[data-hzpg-scrolls] {
        padding: 0;
    }

    .hzp-detail .hzpg-lb {
        gap: 10px;
        padding-top: max(8px, env(safe-area-inset-top));
    }

    .hzp-detail .hzpg-lb__stage {
        padding: 0 36px;
    }

    .hzp-detail .hzpg-lb__nav--prev { left: 0; }
    .hzp-detail .hzpg-lb__nav--next { right: 0; }
    .hzp-detail .hzpg-lb__close { top: 8px; right: 6px; }

    .hzp-detail .hzpg-lb__thumbnails {
        gap: 8px;
        padding-inline: 12px;
    }

}

/* ====================================================================
   AGENT / SELLER PROFILE  (.hzpa-)
   Served at /showrooms. Prefix is unused anywhere else in this theme.
   ==================================================================== */

.hzpa {
    --hzpa-accent: var(--hagzi-primary, #0745D9);

    padding-bottom: 48px;
}

/* ------------------------------------------------------------- hero ---- */

.hzpa__hero {
    position: relative;
    overflow: hidden;
    height: 240px;
    background: var(--hzp-fill);
}

.hzpa__cover {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* Keeps the card edge legible over whatever the photograph is doing. */
.hzpa__scrim {
    position: absolute;
    inset: 0;
    background: linear-gradient(180deg, rgba(16, 18, 24, 0.12) 0%, rgba(16, 18, 24, 0.42) 100%);
}

/* ---------------------------------------------------------- id card ---- */

.hzpa__idcard {
    position: relative;
    z-index: 2;
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto auto;
    align-items: center;
    gap: 18px;
    margin-top: -56px;
    padding: 20px;
    border: 1px solid var(--hzp-line);
    border-radius: var(--hzp-radius);
    background: #ffffff;
}

.hzpa__mark {
    display: grid;
    place-items: center;
    width: 76px;
    height: 76px;
    border-radius: 14px;
    background: var(--hzp-ink);
    color: #ffffff;
    font-size: 24px;
    font-weight: 700;
    letter-spacing: 0.02em;
}

.hzpa__name {
    margin: 0 0 4px;
    color: var(--hzp-ink);
    font-size: 25px;
    font-weight: 700;
    line-height: 1.2;
}

.hzpa__where,
.hzpa__phone {
    display: flex;
    align-items: center;
    gap: 6px;
    margin: 0;
    color: var(--hzp-body);
    font-size: 13.5px;
}

.hzpa__phone {
    margin-top: 2px;
}

.hzpa__where svg,
.hzpa__phone svg {
    flex: none;
    width: 15px;
    height: 15px;
    fill: none;
    stroke: var(--hzpa-accent);
    stroke-width: 1.7;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.hzpa__phone a {
    color: var(--hzp-ink);
    font-weight: 600;
    text-decoration: none;
}

.hzpa__phone a:hover {
    color: var(--hzpa-accent);
    text-decoration: underline;
}

/* ------------------------------------------------------------ stats ---- */

.hzpa__stats {
    display: flex;
    gap: 26px;
    margin: 0;
    padding: 0 4px;
}

.hzpa__stat {
    text-align: center;
}

.hzpa__stat dt {
    color: var(--hzp-muted);
    font-size: 11.5px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

.hzpa__stat dd {
    margin: 2px 0 0;
    color: var(--hzp-ink);
    font-size: 22px;
    font-weight: 700;
    line-height: 1.1;
}

/* ---------------------------------------------------------- actions ---- */

.hzpa__actions {
    display: flex;
    gap: 8px;
}

/* Primary is the only filled control on the page. 46px, inside the
   44–48 the brief asks for, flat, no shadow. */
.hzpa__actions .hzp-btn {
    height: 46px;
    padding: 0 20px;
}

/* ------------------------------------------------------------ about ---- */

.hzpa__h2 {
    margin: 0 0 10px;
    color: var(--hzp-ink);
    font-size: 19px;
    font-weight: 700;
}

.hzpa__about {
    margin-top: 30px;
}

.hzpa__text {
    max-width: 74ch;
    margin: 0 0 8px;
    color: var(--hzp-body);
    font-size: 14.5px;
    line-height: 1.65;
}

.hzpa__chips {
    display: flex;
    flex-wrap: wrap;
    gap: 7px;
    margin: 12px 0 0;
    padding: 0;
    list-style: none;
}

/* Labels, not controls: no pointer, no hover. */
.hzpa__chip {
    padding: 6px 12px;
    border: 1px solid var(--hzp-line);
    border-radius: 999px;
    background: var(--hzp-fill);
    color: var(--hzp-body);
    font-size: 12.5px;
    font-weight: 500;
}

/* --------------------------------------------------------- listings ---- */

.hzpa__listings {
    margin-top: 34px;
}

.hzpa__tabs {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    margin-bottom: 16px;
    border-bottom: 1px solid var(--hzp-line);
}

/* Active is blue text with an underline that sits on the border, not a
   filled blue pill. */
.hzpa__tab {
    position: relative;
    margin-bottom: -1px;
    padding: 9px 14px;
    border: 0;
    border-bottom: 2px solid transparent;
    background: none;
    color: var(--hzp-body);
    font-family: inherit;
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
}

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

/* Listed with :hover so the active tab keeps its colour under the cursor;
   the bare .hzpa__tab:hover above is more specific than the class alone. */
.hzpa__tab--on,
.hzpa__tab--on:hover {
    border-bottom-color: var(--hzpa-accent);
    color: var(--hzpa-accent);
}

.hzpa__tab:focus-visible {
    outline: 2px solid var(--hzpa-accent);
    outline-offset: -2px;
}

.hzpa__tabn {
    margin-inline-start: 4px;
    color: var(--hzp-muted);
    font-weight: 600;
}

.hzpa__tab--on .hzpa__tabn {
    color: inherit;
}

/* The card grid.
   .hzp-cards and .hzp-card carry the card language from the search page. What
   changes here is only the axis: the search page gives a card one wide column
   and lays it out as a photograph beside its text, while this page gives it a
   third of the width, where that split leaves no room for the text. So the
   card takes the stacked form it already has at narrow widths — the same
   declarations as the max-width: 767.98px block, applied by column width
   rather than by viewport. No new card, and nothing about the card itself
   changes. */
.hzpa__grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
}

.hzpa__grid .hzp-card,
.hzpa__grid .hzp-card__media {
    grid-template-columns: minmax(0, 1fr);
}

.hzpa__grid .hzp-card__photo {
    min-height: 0;
    max-height: none;
    aspect-ratio: 3 / 2;
}

.hzpa__grid .hzp-card__thumbs {
    grid-template-rows: none;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    height: 62px;
}

.hzpa__grid > [hidden] {
    display: none;
}

.hzpa__more {
    display: flex;
    justify-content: center;
    margin-top: 20px;
}

.hzpa__more .hzp-btn[hidden] {
    display: none;
}

.hzpa__empty {
    margin: 0;
    padding: 34px 18px;
    border: 1px solid var(--hzp-line);
    border-radius: var(--hzp-radius);
    background: var(--hzp-fill);
    color: var(--hzp-body);
    font-size: 14.5px;
    text-align: center;
}

.hzpa__empty[hidden] {
    display: none;
}

/* ------------------------------------------------------ responsive ---- */

@media (max-width: 1279.98px) {
    .hzpa__stats {
        gap: 20px;
    }
}

@media (max-width: 1023.98px) {
    /* The actions drop to their own row before the stats do, because a
       wrapped Call agent is worse than a wrapped count. */
    .hzpa__idcard {
        grid-template-columns: auto minmax(0, 1fr);
    }

    .hzpa__stats {
        grid-column: 1 / -1;
        justify-content: flex-start;
        padding: 0;
    }

    .hzpa__actions {
        grid-column: 1 / -1;
    }

    .hzpa__actions .hzp-btn {
        flex: 1;
    }

    .hzpa__grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@media (max-width: 767.98px) {
    .hzpa__hero {
        height: 160px;
    }

    .hzpa__idcard {
        margin-top: -40px;
        padding: 16px;
        gap: 14px;
    }

    .hzpa__mark {
        width: 58px;
        height: 58px;
        border-radius: 12px;
        font-size: 19px;
    }

    .hzpa__name {
        font-size: 21px;
    }

    .hzpa__stats {
        gap: 22px;
    }

    .hzpa__stat dd {
        font-size: 19px;
    }

    .hzpa__grid {
        grid-template-columns: minmax(0, 1fr);
    }

    .hzpa__tabs {
        overflow-x: auto;
        flex-wrap: nowrap;
        scrollbar-width: none;
    }

    .hzpa__tabs::-webkit-scrollbar {
        display: none;
    }

    .hzpa__tab {
        white-space: nowrap;
    }
}

@media (max-width: 479.98px) {
    .hzpa__actions {
        flex-wrap: wrap;
    }

    .hzpa__actions .hzp-btn {
        flex: 1 1 100%;
    }
}

/* ====================================================================
   PRIMARY COLOUR TOKEN
   Hagzi's primary becomes #0745D9. property.css defines
   --hagzi-primary in :root and loads first; every rule here carries the
   literal fallback so this file is correct on its own either way.

   Scope is deliberate and narrow: primary calls to action, active and
   selected states, and interactive accents that used to be red. White,
   dark neutral and light grey stay dominant — the blue is the action
   signal, not the surface.

   These rules sit at the end of the stylesheet so they win over the
   earlier declarations without editing them in place.

   THAT LEFT A GAP, WHICH IS NOW CLOSED. Overriding rules instead of
   editing them repaints only what an override actually names, and this
   block named eighteen of the thirty-four sites that read the --hzp-red*
   tokens. The other sixteen went on painting #d92228 underneath a purple
   page: the filter checkboxes' accent-color, the search submit's focus
   ring, the chip, address and map-pin icon strokes, the range thumb's
   glow and the rail arrow's hover border. Rather than edit thirty-four
   sites, the three --hzp-red* tokens at the top of this file now resolve
   to the accent. The overridden and the un-overridden therefore agree,
   and deleting a rule from this block can no longer bring red back.

   The sentence that stood here said the red tokens stayed defined
   because a warning notice still used the tint. There is no such notice.
   The tint's only consumer was .hzp-calc__out, the mortgage panel, which
   this block already repaints.
   ==================================================================== */

.hzp-page {
    --hzp-accent: var(--hagzi-primary, #0745D9);
    --hzp-accent-dark: var(--hagzi-primary-dark, #0638B0);

    /* A very light wash of the primary, for the calculator's output panel
       and the financing banner. Mixed from the token where the browser
       supports it, with a flat fallback for those that do not. */
    --hzp-accent-wash: #EEF3FF;
    --hzp-accent-line: #C4D4FA;
}

/* ------------------------------------------------- primary buttons ---- */

.hzp-page .hzp-btn--accent {
    border-color: var(--hzp-accent);
    background: var(--hzp-accent);
    color: #ffffff;
}

.hzp-page .hzp-btn--accent:hover {
    border-color: var(--hzp-accent-dark);
    background: var(--hzp-accent-dark);
}

.hzp-page .hzp-btn--accent svg {
    stroke: #ffffff;
}

.hzp-page .hzp-btn:focus-visible,
.hzp-page .hzp-select__el:focus-visible {
    outline: 2px solid var(--hzp-accent);
    outline-offset: 2px;
}

/* Call Agent is the one primary action in the contact card; the other
   three stay white with a neutral border and dark text, which is what
   .hzp-btn already gives them. Stated here so a later edit does not
   quietly promote one of them. */
.hzp-page .hzp-contactcard__actions .hzp-btn:not(.hzp-btn--accent) {
    border-color: var(--hzp-line-strong);
    background: #ffffff;
    color: var(--hzp-ink);
}

.hzp-page .hzp-contactcard__actions .hzp-btn:not(.hzp-btn--accent):hover {
    border-color: var(--hzp-accent);
    color: var(--hzp-accent);
}

/* Active state: the count of filters currently applied. */
.hzp-page .hzp-fb__count {
    background: var(--hzp-accent);
}

.hzp-page .hzp-range__el:focus,
.hzp-page .hzp-input:focus-within {
    border-color: var(--hzp-accent);
}

/* --------------------------------------------------------- payment ---- */

.hzp-page .hzp-paypill {
    background: #ffffff;
    border: 1px solid #d1d5db;
    color: #374151;
}

.hzp-page .hzp-paypill svg {
    stroke: currentColor;
}

.hzp-page .hzp-paypill:hover {
    background: #ffffff;
    border-color: #9ca3af;
    color: #374151;
}

.hzp-page .hzp-paypill:focus-visible {
    outline-color: var(--hzp-accent);
}

/* ---------------------------------------------- the loan calculator ---- */
/* Structure unchanged. Its interactive parts carry the primary instead
   of red, and the monthly figure stays the largest thing in the panel. */

.hzp-page .hzp-calc__out {
    border-color: var(--hzp-accent-line);
    background: var(--hzp-accent-wash);
}

.hzp-page .hzp-calc__outlabel {
    color: var(--hzp-body);
}

.hzp-page .hzp-calc__amount {
    color: var(--hzp-accent);
}

.hzp-page .hzp-calc__how summary {
    color: var(--hzp-accent);
}

.hzp-page .hzp-calc__how summary:focus-visible {
    outline-color: var(--hzp-accent);
}

.hzp-page .hzp-slider::-webkit-slider-thumb {
    background: var(--hzp-accent);
}

.hzp-page .hzp-slider::-moz-range-thumb {
    background: var(--hzp-accent);
}

.hzp-page .hzp-slider:focus-visible {
    outline-color: var(--hzp-accent);
}

/* ------------------------------------------- interactive text accents -- */
/* Everything that reddened on hover now takes the primary, so no stray
   red survives next to it. */

.hzp-page .hzp-card__addr a:hover,
.hzp-page .hzp-side__links a:hover,
.hzp-page .hzp-crumbs a:hover,
.hzp-page .hzp-mini__addr a:hover,
.hzp-page .hzp-agentcard__line a:hover,
.hzp-page .hzp-rail__all:hover,
.hzp-page .hzp-rail__nav:hover:not([disabled]) {
    color: var(--hzp-accent);
}

.hzp-page .hzp-agentcard__line svg {
    stroke: var(--hzp-accent);
}

/* Body copy inside the panel whose ground is now the light blue wash. Its
   dark red predates the token and is the one leftover that reads as a mistake
   rather than as an accent. The warning notice is untouched: it is red because
   it is a warning. */
.hzp-page .hzp-calc__how p {
    color: var(--hzp-body);
}

/* ==========================================================================
   MAP MODE  --  the split view
   ==========================================================================

   Reached at ?view=map, which carries the filters, the term and the sort, so
   the mode is a way of looking at a result set and never a different result
   set. Both halves are rendered from the same collection in the same request.

   Four regions, three of which come from markup that cannot move: the header
   is inside the results column, and the chips are inside the map partial
   because the map is drawn FROM them. Named areas put each region where it
   reads best while it stays where it belongs in the document.

        head  head         heading, count and sort, full width
        chips chips        the district filter, under the count it changes
        list  map          the card grid, and the map beside it

   The columns are logical, so Arabic needs no rule of its own: the first
   column is the inline start, which is the right-hand side there, and the map
   takes the other one.
   ========================================================================== */

html.hzp-js .hzp-split {
    display: grid;
    /* Full width: this element is not given .hzp-shell in map mode. */
    width: 100%;
    /* Even. The map is half the page, as a map worth looking at has to be. */
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    grid-template-areas:
        "head  head"
        "chips chips"
        "list  map";
    align-items: start;
    gap: 14px 24px;
    padding-top: 18px;
    padding-bottom: 0;
}

/*
    The padding the container used to give, put back on the regions instead. The
    map is the only thing that touches the edge; text never does.
*/
html.hzp-js .hzp-split .hzp-results__top,
html.hzp-js .hzp-split .hzpm__bar {
    padding-inline: 24px;
}

html.hzp-js .hzp-split .hzp-results__body {
    padding-inline-start: 24px;
    padding-bottom: 48px;
}

/*
    Two wrappers give their children to the grid instead of boxing them. The
    alternative was moving the markup, and the markup belongs where it is: the
    header is part of the results column in every other mode, and the chips are
    the map's own data.
*/
html.hzp-js .hzp-split .hzpm,
html.hzp-js .hzp-split .hzp-results {
    display: contents;
}

html.hzp-js .hzp-split .hzpm__bar {
    grid-area: chips;
}

html.hzp-js .hzp-split .hzp-results__top {
    grid-area: head;
}

html.hzp-js .hzp-split .hzp-results__body {
    grid-area: list;
    min-width: 0;
}

/*
    Full height, held in place. --hzp-split-top is the filter bar's measured
    height, written on the root element rather than on this one so that the Vue
    mount -- which replaces the markup inside #app -- cannot discard it.

    Two height declarations: vh for browsers without dvh, dvh for those with
    it, so a mobile browser's collapsing toolbar does not leave the map short.
*/
/*
    Squared off against the glass and rounded on the side that faces the
    results, in logical corners so Arabic mirrors without a second rule. The
    outer border goes too: there is nothing beyond it to be separated from.
*/
html.hzp-js .hzp-split .hzpm-pane {
    grid-area: map;
    border-inline-end: 0;
    border-start-end-radius: 0;
    border-end-end-radius: 0;
    position: sticky;
    top: calc(var(--hzp-split-top, 64px) + 12px);
    height: calc(100vh - var(--hzp-split-top, 64px) - 28px);
    height: calc(100dvh - var(--hzp-split-top, 64px) - 28px);
    min-height: 460px;
}

/*
    The card, stood up.

    The partial is owned by another session and is used by four other pages, so
    nothing about it is edited: the wide card is a two-column grid on .hzp-card,
    and one column here puts the photograph above the body. The thumbnail rail
    is a 64px column beside the photo and has no room in a half-width card, so
    it is not shown in this mode; every one of those photographs is on the
    listing the card links to.
*/
html.hzp-js .hzp-split .hzp-cards {
    grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
}

html.hzp-js .hzp-split .hzp-card,
html.hzp-js .hzp-split .hzp-card__media {
    grid-template-columns: minmax(0, 1fr);
}

html.hzp-js .hzp-split .hzp-card__thumbs {
    display: none;
}

/*
    And the description. It is clamped to two lines, which in a half-width card
    means it stops mid-sentence -- length without information. display: none
    takes it out of the accessibility tree as well as the layout, because a
    truncated sentence read aloud is worse than one that was never offered.

    Only here. The full-width list, favourites, the agent profile and the
    similar rail all keep it: this is scoped to .hzp-split, which exists on no
    other page and in no other mode.
*/
html.hzp-js .hzp-split .hzp-card__desc {
    display: none;
}

html.hzp-js .hzp-split .hzp-card__photo {
    min-height: 0;
    height: 186px;
    max-height: none;
}

/* The counted sentence the map reveals when a district is chosen. Sits with the
   results, not with the map, because it describes the column. */
.hzp-split__note {
    margin: 0 0 12px;
    padding: 9px 12px;
    border: 1px solid var(--hzp-accent-line, #C4D4FA);
    border-radius: var(--hzp-radius-sm);
    background: var(--hzp-accent-wash, #EEF3FF);
    color: var(--hzp-ink);
    font-size: 13px;
}

/* The mode switch in the sub-bar reads as a link, since it goes somewhere. */
.hzp-view-switch {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    min-width: 220px;
    min-height: 46px;
    margin-inline: 0;
    padding: 3px;
    border: 1px solid var(--hzp-line-strong);
    border-radius: 12px;
    background: #ffffff;
}

.hzp-subbar__view {
    flex: 1 1 50%;
    justify-content: center;
    gap: 6px;
    min-height: 38px;
    padding: 7px 14px;
    white-space: nowrap;
    border-radius: 9px;
    color: var(--hzp-body);
    font-weight: 600;
    text-decoration: none;
}

.hzp-subbar__view:hover {
    color: var(--hzp-accent, var(--hagzi-primary, #0745D9));
    background: #ffffff;
}

.hzp-subbar__view svg {
    stroke: currentColor;
}

.hzp-subbar__view span {
    text-decoration: none;
}

.hzp-subbar__view[aria-current="page"] {
    background: var(--hzp-accent-wash, #EEF3FF);
    color: var(--hzp-accent, var(--hagzi-primary, #0745D9));
    box-shadow: none;
}

@media (max-width: 767.98px) {
    .hzp-cards--grid {
        grid-template-columns: minmax(0, 1fr);
    }

    .hzp-view-switch {
        width: 100%;
        min-width: 0;
        margin-inline: 0;
    }

    .hzp-subbar__view {
        flex: 1 1 50%;
        justify-content: center;
    }
}

@media (max-width: 479.98px) {
    .hzp-results__head {
        grid-template-columns: minmax(0, 0.95fr) minmax(0, 1.05fr);
        gap: 14px 8px;
    }

    .hzp-sort__el {
        min-width: 0;
        padding-inline: 28px;
        font-size: 12px;
        text-overflow: ellipsis;
    }

    .hzp-sort__control .hzp-sort__icon {
        inset-inline-start: 8px;
        width: 16px;
        height: 16px;
    }

    .hzp-sort__control .hzp-sort__chevron {
        inset-inline-end: 6px;
        width: 14px;
        height: 14px;
    }

    .hzp-subbar__view {
        gap: 4px;
        padding-inline: 4px;
        font-size: 12px;
    }

    .hzp-subbar__view svg {
        width: 14px;
        height: 14px;
        flex-shrink: 0;
    }
}

/* Compact icon-only listing layout controls; link names remain accessible. */
.hzp-results__head > .hzp-view-switch {
    width: max-content;
    min-width: 0;
    justify-self: end;
}

.hzp-view-switch .hzp-subbar__view {
    flex: 0 0 42px;
    width: 42px;
    padding: 7px;
}

/*
    One column below 900, map above the results.

    A split needs two columns' worth of width; at 390 there is one. The map
    takes a share of the viewport and the results run underneath in the
    ordinary flow -- one scroll, no sheet to drag, the chips reachable, and the
    way back to the list still sitting in the sub-bar above it. A bottom sheet
    over a full-screen map would need a scripted drag surface and a second
    scroll context to show a map that marks districts rather than addresses; it
    would be more machinery for no more information.
*/
@media (max-width: 899.98px) {
    html.hzp-js .hzp-split {
        grid-template-columns: minmax(0, 1fr);
        grid-template-areas:
            "head"
            "chips"
            "map"
            "list";
        gap: 12px;
    }

    /* Both sides now: there is no map beside the cards to leave room for. */
    html.hzp-js .hzp-split .hzp-results__body {
        padding-inline: 16px 16px;
    }

    html.hzp-js .hzp-split .hzp-results__top,
    html.hzp-js .hzp-split .hzpm__bar {
        padding-inline: 16px;
    }

    /* One column, so the map spans it and squares off on both sides. */
    html.hzp-js .hzp-split .hzpm-pane {
        border-inline: 0;
        border-radius: 0;
        position: static;
        height: 46vh;
        height: 46dvh;
        min-height: 300px;
    }
}

/*
    The footer, in map mode only.

    A map that holds the viewport's height leaves the page without a natural
    bottom, and a footer under it is a long scroll to a set of links that has
    nothing to do with what the reader is doing. The list view keeps it, and is
    one click away in the sub-bar.

    The class is written by the search page's own script when the split is on
    the page. That is what makes the no-script case correct for free: with no
    scripting there is no map, the reader gets the plain list, and the plain
    list keeps its footer.
*/
body.hzp-mapmode .hzf {
    display: none;
}

/* ------------------------------------------- and when the script did not run */

/*
    No class, so none of the rules above are in force and there is nothing to
    undo: the cards are the wide cards, in one column, with their descriptions,
    exactly as on the plain list. Only three things need saying.
*/
html:not(.hzp-js) .hzpm,
html:not(.hzp-js) .hzpm-pane,
html:not(.hzp-js) .hzp-subbar__view {
    display: none;
}

/* The container the full-bleed mode declined to take. */
html:not(.hzp-js) .hzp-split {
    width: 100%;
    max-width: 1200px;
    margin: 0 auto;
    padding: 22px 24px 48px;
}

/* ======================================================================
   FILTER PILLS — the single-choice facets in the More filters panel

   A pill is a radio and its label, never a div with a click handler. The
   panel has a working no-script path and a native radio group is what
   keeps it, along with the one tab stop, the arrow-key walk and the group
   semantics that the <select> these replaced was giving for free.

   The input is clipped rather than display:none. A display:none radio is
   out of the tab order and out of the accessibility tree, which would
   cost exactly what this pattern exists to keep. It sits immediately
   before its own label so the checked and focus states are drawable with
   an adjacent-sibling selector and need no script.

   NAMED .hzp-fpill, NOT .hzp-pill. The short name was already taken: the
   listing card's "see monthly" badge is a .hzp-pill, and a rule written
   later in this sheet under that name silently restyles it wherever a
   card appears. Nothing here may be renamed back.
   ====================================================================== */

/*
    ONE GROUP PER ROW.

    The two grids this overrides -- two-up for the pairs sections, four-up
    for the building section -- were laid out for controls that were all
    menus and all one line tall. A pill row is as tall as its options need,
    and in a half or a quarter track it wraps for want of width rather than
    for want of options: Bathrooms' four pills overrun a 336px column by
    about forty of them, which put "5+ baths" on a line by itself.
*/
.hzp-fb__panel .hzp-fb__sec .hzp-fb__secgrid {
    grid-template-columns: 1fr;
    gap: 18px;
}

/*
    THE FILTER LABELS, INSIDE THE PANEL ONLY.

    16px rather than 12px. With the section captions gone these are the only
    hierarchy left in the panel, so they carry the weight the captions used
    to; 12px was sized to sit under one.

    Scoped, and deliberately so: .hzp-field__label is shared with the labels
    on the bar above and with every field on the valuation page, and neither
    was asked to change. The rule they share is left exactly as it is.
*/
.hzp-fb__panel .hzp-field__label {
    font-size: 16px;
}

/*
    The label-to-control gap grows with the label. The number that matters is
    not this one on its own but its distance from the 18px either side of a
    separator: a label has to read as belonging to the control under it
    rather than to the rule above it, and 8 against 37 keeps that obvious
    now that the text is a third larger.
*/
.hzp-fb__panel .hzp-fb__group {
    gap: 8px;
}

/*
    SEPARATORS INSTEAD OF SECTION HEADINGS.

    "Property details", "Status" and "Building and ownership" are gone, and
    with them the spacing that said a new group was starting. A hairline
    between consecutive filters does that job instead.

    Drawn as a top border on the FOLLOWING block, which is what buys the
    two rules a bottom border would not: nothing above the first filter,
    and nothing hard against the sticky footer under the last one.

    18px above the line and 18px below it, the same either side and the
    same as the row gap, so the rhythm does not change depending on whether
    two filters share a container or straddle two of them. It was 16 while
    the labels were 12px and read tight once they grew to 16.
*/
.hzp-fb__panel .hzp-fb__secgrid > .hzp-fb__group + .hzp-fb__group {
    border-top: 1px solid var(--hzp-line);
    padding-top: 18px;
}

.hzp-fb__panel .hzp-fb__sec + .hzp-fb__sec {
    margin-top: 18px;
    padding-top: 18px;
    border-top: 1px solid var(--hzp-line);
}

/*
    The two ranges -- Property size and Year built -- are the panel's only
    non-pill controls, and they are now the same control twice: a from box,
    a dash and a to box. One cap for both, so they are the same size as each
    other rather than one full-width pair beside a single small box, and so
    a full-width row does not stretch either across 688px.
*/
.hzp-fb__panel .hzp-fb__group .hzp-range {
    max-width: 336px;
}

/*
    The button's number is a preview of the pending selection, fetched from
    the page that selection would land on. When that fetch cannot be
    trusted the script marks the button and the wordless label takes over
    -- the same swap the no-script path already uses, and for the same
    reason: a count that no longer describes the controls is worse than no
    count at all.
*/
html.hzp-js .hzp-fb__show.is-nocount .hzp-fb__shownum {
    display: none;
}

html.hzp-js .hzp-fb__show.is-nocount .hzp-fb__showplain {
    display: inline;
}

.hzp-fpills {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    min-width: 0;
}

.hzp-fpill__input {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
}

/*
    max-width with a label that is allowed to wrap, together. Arabic runs
    longer than English and the panel is 310px wide inside at a 390px
    viewport, so a pill that cannot fit its label breaks the line within
    its own border instead of pushing a scrollbar across the page.
*/
.hzp-fpill {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    max-width: 100%;
    min-height: 32px;
    border: 1px solid var(--hzp-line-strong);
    border-radius: 999px;
    padding: 4px 14px;
    color: var(--hzp-body);
    background: #ffffff;
    font-size: 13px;
    line-height: 1.35;
    text-align: center;
    overflow-wrap: break-word;
    cursor: pointer;
    transition: background-color .15s ease, color .15s ease, border-color .15s ease;
}

.hzp-fpill:hover {
    border-color: var(--hzp-accent-line, #C4D4FA);
    background: var(--hzp-accent-wash, #EEF3FF);
}

.hzp-fpill__input:checked + .hzp-fpill {
    border-color: var(--hzp-accent, var(--hagzi-primary, #0745D9));
    background: var(--hzp-accent, var(--hagzi-primary, #0745D9));
    color: #ffffff;
}

/*
    The ring is drawn on the label because the input it belongs to is a
    1px box clipped out of sight. Same outline the page already gives
    .hzp-btn and .hzp-select__el, so a keyboard walk down the panel does
    not change appearance halfway through it.
*/
.hzp-fpill__input:focus-visible + .hzp-fpill {
    outline: 2px solid var(--hzp-accent, var(--hagzi-primary, #0745D9));
    outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
    .hzp-fpill {
        transition: none;
    }
}

/*
    ==========================================================================
    A LISTING WITH NO PHOTOGRAPH
    ==========================================================================

    The panel that stands where the gallery would be when a seller has
    uploaded nothing.

    It carried no rules of its own and borrowed .hzp-card__photo--none, which
    is written for a 428x256 card tile and contributes no height. On the detail
    page that rendered as a thin grey strip under the breadcrumbs, which reads
    as a broken image rather than as a stated absence — the opposite of what
    the panel is for.

    DASHED, AND DELIBERATELY. A solid panel carrying the same border and fill
    as the price and specification panels below it says "here is a thing". A
    dashed outline is the ordinary way of saying "this is where a thing would
    go", and it is the one cue that separates an empty state from a failure
    without spending a word on it.

    SHORTER THAN THE GALLERY IT REPLACES. The gallery stage is 16/9, which at
    the width of this column is a little over five hundred pixels tall. That
    much empty dashed box is its own kind of broken, so this takes enough
    height to be unmistakably intentional and no more. The consequence — a
    listing gets taller when it gains its first photograph — is the right way
    round: the page grows when there is something to show.

    Nothing here needs a mirrored rule in property-rtl.css. The box centres on
    both axes and the only directional thing inside it is the sentence, which
    follows the document direction by itself.
*/
.hzp-detail .hzp-dphoto-none {
    display: grid;
    place-items: center;
    align-content: center;
    gap: 10px;
    min-height: 300px;
    border-style: dashed;
    background: var(--hzp-fill-soft);
    text-align: center;
}

.hzp-detail .hzp-dphoto-none__mark {
    width: 34px;
    height: 34px;
    fill: none;
    stroke: var(--hzp-muted);
    stroke-width: 1.5;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.hzp-detail .hzp-dphoto-none__text {
    margin: 0;
    color: var(--hzp-muted);
    font-size: 15px;
}

@media (max-width: 767.98px) {
    .hzp-detail .hzp-dphoto-none {
        min-height: 210px;
    }

    .hzp-detail .hzp-dphoto-none__mark {
        width: 30px;
        height: 30px;
    }
}

/*
    ==========================================================================
    SELLER PROFILE  —  the parts /showrooms did not already have
    ==========================================================================

    The profile at /property/sellers/{name}-{id} reuses the .hzpa__ block this
    file already defines for the agent page, because it is the same layout
    doing the same job for one seller instead of for the platform. Only the
    three things that page has no equivalent of are below.

    .hzpa__stats is deliberately not reused. The agent page prints active, for
    sale and for rent counts; a seller profile does not, because a count beside
    a name is read as a credibility signal and the reader can already count the
    cards.
*/

/*
    Whether this is a private seller or a partner agency, directly under the
    name. Muted and small: it is context for reading the rest of the page, not
    a badge, and it must not compete with the name above it.
*/
.hzpa__kind {
    margin: 2px 0 0;
    color: var(--hzp-muted);
    font-size: 14px;
}

/*
    The line explaining that per-property contact details are on each listing.
    It sits under the actions because it qualifies them — the number above is
    the account's, not this or that property's.
*/
.hzpa__note {
    margin: 10px 0 0;
    color: var(--hzp-muted);
    font-size: 13px;
    line-height: 1.5;
}

/*
    Shown instead of the call and message controls when the account has no
    telephone number on it. Given a soft fill and a border so it reads as a
    deliberate notice rather than as a caption that lost its buttons — this is
    the state every account on this channel is in today, so it is the common
    case and not an edge one.

    Logical properties throughout, so the Arabic page mirrors it without a rule
    of its own.
*/
.hzpa__nocontact {
    margin: 14px 0 0;
    padding: 12px 14px;
    border: 1px solid var(--hzp-line);
    border-radius: var(--hzp-radius);
    background: var(--hzp-fill-soft);
    color: var(--hzp-muted);
    font-size: 13px;
    line-height: 1.55;
}

/*
    Both of the elements above are direct children of .hzpa__idcard, which is a
    grid, so they are placed by it rather than flowing under the buttons as the
    markup reads.

    That placement is what made the profile scroll sideways on a 390px screen:
    the card's first column is `auto`, meaning content-sized with no lower
    bound, and an auto-placed sentence sized it to the sentence. The card's
    content came out 396px wide inside a 340px box and the whole document
    inherited the 31px of overflow. The pre-existing children never hit this
    because the mobile rules at 1023.98px explicitly span .hzpa__stats and
    .hzpa__actions across the row; these two were added later and were never
    added to that list.

    Spanning the full row is the same fix, applied at every width rather than
    only below 1024px: a note that qualifies the buttons belongs under them,
    not beside them, on a wide screen too. min-inline-size:0 keeps the track
    from being sized by an unbreakable run of text.
*/
.hzpa__note,
.hzpa__nocontact {
    grid-column: 1 / -1;
    min-inline-size: 0;
}

/*
    The card's seller chip is a link now that it names a real account with a
    profile page behind it, rather than a "HZ" placeholder standing in for
    nobody. The anchor replaces the span in the same slot and inherits the
    chip's existing layout, so this adds only what a link needs: the colour it
    would otherwise take from the user-agent stylesheet, and an underline on
    hover and keyboard focus so it is discoverable as a link without being
    underlined at rest among eleven other cards.
*/
a.hzp-agent--link {
    color: inherit;
    text-decoration: none;
}

a.hzp-agent--link:hover .hzp-agent__name,
a.hzp-agent--link:focus-visible .hzp-agent__name {
    text-decoration: underline;
}

/*
    The thumbnail strip on a card inside .hzpa__grid — the seller profile and
    the showrooms page.

    The rule above it declares `grid-template-rows: none` with `height: 62px`,
    intending a single 62px-tall row of three thumbnails under the photo. What
    it produces is an AUTO-sized implicit row: `none` leaves the row track
    indefinite, so `.hzp-card__thumb`'s `height: 100%` has nothing to resolve
    against and falls back to the image's intrinsic height. At the card widths
    this grid produces that is roughly 120-155px, so the images render at more
    than twice the strip's height and spill out of it — `height` on the
    container clamps nothing, because overflow is visible and the track is not
    definite. On the profile that put the thumbnails over the favourite control
    and the "See monthly cost" pill, with the title and spec line running
    underneath them.

    The strip works everywhere else because everywhere else the rows are
    definite: the default card puts the thumbnails in a 64px column with
    `grid-template-rows: repeat(3, minmax(0, 1fr))`, which resolves, and
    `object-fit: cover` then crops rather than stretches. Nothing was wrong
    with the card; this container asked for a row size and then withheld it.

    The bug has been latent since the showrooms grid was written and only
    surfaced now because the seller profile is the first page to render a
    multi-photograph card in this container — every showrooms card currently
    has a single image and takes the --single branch, which has no strip at
    all.

    Fixed here rather than on the shared card, because the shared card is
    correct in the two contexts that already use it and this selector cannot
    reach them: search and the home page carry .hzp-cards without .hzpa__grid.

    NOTE: the same defect exists in the unscoped `.hzp-card__thumbs` rule
    inside `@media (max-width: 767.98px)` — identical `grid-template-rows:
    none` with `height: 62px`. It is latent for the same reason (no
    multi-photograph card renders there yet) and is deliberately NOT changed
    here, because that rule is shared with search and the detail page's split
    view and another session is working in this theme. It wants the same
    one-line fix.
*/
.hzpa__grid .hzp-card__thumbs {
    grid-template-rows: 62px;
    overflow: hidden;
}

/*
    The same defect as above, in the unscoped mobile rule.

    The note attached to the .hzpa__grid fix called this one latent. It is not:
    measuring search at 390 found three cards whose thumbnails overhang their
    media box by 49px, over the card body beneath. It read as latent only
    because the profile was checked first and search's desktop widths — where
    the strip is a 64px column with definite rows — are correct.

    Identical cause, identical fix: `grid-template-rows: none` alongside
    `height: 62px` leaves the row indefinite, `.hzp-card__thumb`'s
    `height: 100%` cannot resolve against it, and the image falls back to its
    intrinsic height. Naming the track restores what `height: 62px` was already
    asking for, and `object-fit: cover` then crops as it does everywhere else.

    Scoped to the same breakpoint as the rule it corrects, so the desktop
    column layout is untouched. The detail page's split view is unaffected: it
    hides the strip outright at a higher specificity.
*/
@media (max-width: 767.98px) {
    .hzp-card__thumbs {
        grid-template-rows: 62px;
        overflow: hidden;
    }
}

/* ====================================================================
   EVEN CARDS IN A ROW
   Three cards in the profile's Live listings row ended at three
   different points. The height was never the problem in itself — it was
   three separate causes stacking, so each is addressed rather than a
   height being imposed on the row.
   ==================================================================== */

/*
    1. The card fills its cell.

    A grid item stretches by default, so the <li> was already the row's full
    height — but the card inside it was not told to fill the <li>, so it sat at
    its content height and the <li> held empty space beneath. `.hzp-card__foot`
    has carried `margin-top: auto` all along; it did nothing because the body it
    lives in had no spare height to push against. Giving the card the row's
    height and making the body the flexible row is what finally lets that
    existing rule work, which is why the actions line up without a rule of their
    own.
*/
.hzp-cards__item {
    display: grid;
}

.hzp-cards__item > .hzp-card {
    block-size: 100%;
}

.hzpa__grid .hzp-card {
    grid-template-rows: auto minmax(0, 1fr);
}

/*
    2. The media region occupies the same space whatever is in it.

    It previously sized itself to its contents, so three cards produced three
    different media heights: a photograph alone, a photograph plus a strip, and
    the "no photograph yet" panel, which is shorter than either. No amount of
    evening out below can survive that, because the difference is above the
    text.

    The media box is now a fixed 3:2 block and the rows divide it: the
    photograph takes what is left after the 62px strip, or all of it when there
    is no strip. Every card's media is therefore exactly two-thirds of the card
    width tall — including the empty state, which reserves the same room as a
    photograph rather than collapsing and pulling its card up.

    `object-fit: cover` on the image means the photograph is cropped to the box
    rather than distorted, which is the same treatment it already had.
*/
.hzpa__grid .hzp-card__media {
    aspect-ratio: 3 / 2;
    grid-template-rows: minmax(0, 1fr) 62px;
}

.hzpa__grid .hzp-card__media--single {
    grid-template-rows: minmax(0, 1fr);
}

.hzpa__grid .hzp-card__medialink {
    block-size: 100%;
}

.hzpa__grid .hzp-card__photo {
    aspect-ratio: auto;
    block-size: 100%;
}

/*
    3. The strip fills its row whatever the thumbnail count.

    It was three fixed columns, so a listing with three photographs (one main,
    two thumbnails) filled two of them and left the third empty — the "narrow
    band of partial images" rather than a tidy row. The count is not fixed and
    should not be assumed: auto-flow columns divide the row evenly between
    however many thumbnails there are, so two sit as halves and three as thirds.
*/
.hzpa__grid .hzp-card__thumbs {
    grid-template-columns: none;
    grid-auto-flow: column;
    grid-auto-columns: minmax(0, 1fr);
}


/* ====================================================================
   SELLER PROFILE: IDENTITY HEADER, REDESIGNED
   ====================================================================

   The header used to place the call controls in one auto column and then
   span the explanatory sentence across the whole row underneath. On the
   common case -- an account with no telephone number, which is every member
   account on this channel today -- that produced a header with a name on the
   left, nothing on the right, and a full-width grey band beneath.

   Contact is now one column that owns all of it: the number, the buttons and
   the sentence that qualifies them. The band becomes a notice in a narrow
   column, which is what it always was.

   Logical properties throughout, so the Arabic page mirrors without a rule of
   its own.
   ==================================================================== */

/* ===== seller profile: identity header, redesigned ===== */

.hzpa__idcard {
    /* Was `auto minmax(0,1fr) auto auto` for mark / id / stats / actions.
       Stats were never rendered on this page and actions are now inside the
       contact column, so three tracks describe what is actually there. */
    grid-template-columns: auto minmax(0, 1fr) auto;

    /* Top-aligned rather than centred: the contact column is taller than the
       name block whenever it carries buttons, and centring made the name
       drift down the card as the column grew. */
    align-items: start;
    gap: 20px 24px;
}

.hzpa__id {
    min-inline-size: 0;
}

/* The account's facts, as a list. No bullets and no indent: it is a list for
   the benefit of a screen reader, not visually. */
.hzpa__facts {
    display: grid;
    gap: 4px;
    margin: 10px 0 0;
    padding: 0;
    list-style: none;
}

/* --------------------------------------------------------- contact ---- */

.hzpa__contact {
    display: grid;
    align-content: start;
    gap: 0;

    /* Wide enough for two buttons side by side, narrow enough that the notice
       reads as a panel rather than as a banner. */
    inline-size: min(304px, 100%);
    justify-self: end;
    min-inline-size: 0;
}

.hzpa__contactlabel {
    margin: 0 0 8px;
    color: var(--hzp-muted);
    font-size: 11.5px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

/* Inside the panel the number sits above its own buttons, so it needs the
   spacing the standalone paragraph had, not the 2px that stacked it under a
   join date. */
.hzpa__contact .hzpa__phone {
    margin: 0 0 10px;
    font-size: 15px;
}

.hzpa__contact .hzpa__actions {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: minmax(0, 1fr);
    gap: 8px;
}

/* The buttons are equal halves of the column rather than content-width, so
   Call and WhatsApp line up regardless of how long the words are in either
   language. */
.hzpa__contact .hzpa__actions .hzp-btn {
    padding: 0 12px;
    min-inline-size: 0;
}

.hzpa__contact .hzpa__note {
    margin: 10px 0 0;
}

/* The no-number notice keeps its own border and fill; the column around it is
   deliberately unstyled so the two do not nest into a double frame. */
.hzpa__contact .hzpa__nocontact {
    margin: 0;
}

/* The full-row span these two used to need applied when they were direct
   children of the card's grid. They are inside .hzpa__contact now, so the
   rule is scoped to the case it was written for and stops applying to the
   case it was not. */
.hzpa__idcard > .hzpa__note,
.hzpa__idcard > .hzpa__nocontact {
    grid-column: 1 / -1;
    min-inline-size: 0;
}

/* ----------------------------------------------------------- about ---- */

/* .hzpa__about, .hzpa__h2 and .hzpa__text already exist above; only the
   spacing below the redesigned header is new. */
.hzpa__about {
    margin-top: 26px;
}

/* ------------------------------------------------------ responsive ---- */

@media (max-width: 1023.98px) {
    /* Contact drops to its own full-width row under the name, and stretches,
       so the buttons stay comfortably tappable rather than staying in a 304px
       column pinned to one edge. */
    .hzpa__contact {
        grid-column: 1 / -1;
        inline-size: 100%;
        justify-self: stretch;
    }
}

@media (max-width: 479.98px) {
    /* Below this the two buttons side by side start truncating in Arabic, so
       they stack. Overrides the column flow set above. */
    .hzpa__contact .hzpa__actions {
        grid-auto-flow: row;
    }
}

/* ==================================================== seller avatar photo === */

/*
 * The member's uploaded picture, standing in for the initial in a seller tile.
 *
 * It carries the tile's own class as well as this one, so its size and its
 * corner radius come from whichever tile it is in — 30px on a card, 44px in
 * "Listed by", 76px on a profile header — and this rule only says what differs
 * between a photograph and a letter.
 *
 * `object-fit: cover` is what stops a tall or a very wide photograph being
 * squashed into the square: the image fills the box and the overflow is
 * cropped, rather than the aspect ratio being bent to fit. It matters on the
 * fallback path in particular, where PropertyAvatar could not write a
 * derivative and is serving the member's original at its own proportions.
 *
 * `display: block` overrides the `display: grid` the tile classes set to centre
 * their letter, which on a replaced element would leave a baseline gap under
 * the image.
 */
.hzp-avatarphoto {
    display: block;
    object-fit: cover;
    /* A neutral ground rather than the tile's ink, so a picture that fails to
       load leaves a quiet square instead of a black one. */
    background: var(--hzp-line, #e6e6ea);
}

/* ============================== listed-by card, without the phone row ===== */

/*
 * The profile link now follows the identity row directly.
 *
 * It never carried a margin of its own: the printed telephone row sat between
 * the two and its `margin: 12px 0` did the spacing on both sides. With that row
 * gone the button would butt straight up against the seller's name, so the gap
 * it used to inherit is stated here instead.
 *
 * Scoped to this card. `.hzp-btn--wide` is also the enquiry panel's button
 * class, and that panel spaces its own actions with a flex gap that this must
 * not add to.
 */
.hzp-agentcard .hzp-btn--wide {
    margin-block-start: 14px;
}

/* ============================ identity header, with no contact panel ====== */

/*
 * The header when the member has no account telephone number.
 *
 * The contact panel is not rendered at all in that case; sellers/show.blade.php
 * says why. What is left has to be told it is a two-track header, because the
 * three-track template does not collapse on its own: the empty third track
 * costs nothing, but the 24px column gap in front of it stays, and the result
 * is a visible hole at the end of the row rather than a name block that runs
 * the width of the card.
 *
 * Two classes so source order cannot undo it, whatever else is appended here
 * later. Below 1024px the header is already two columns and the contact panel
 * already spanned its own row, so this changes nothing at that width.
 */
.hzpa__idcard.hzpa__idcard--nocontact {
    grid-template-columns: auto minmax(0, 1fr);
}

/* ========================================================================== 
   Mobile SERP primary-filter chips
   ========================================================================== 

   Desktop keeps the existing filter bar because this wrapper has no box there.
   On phones the same form controls become a horizontally scrolling sequence:
   listing type, property type, catalogue city, neighbourhood, bedrooms, price.
   No duplicate controls or query names are introduced, so native submission,
   the delegated filter script and no-JS behaviour keep their existing contract.
*/
.hzp-fb__basic-strip {
    display: contents;
}

.hzp-fb__city {
    display: none;
}

@media (max-width: 720px) {
    .hzp-fb {
        align-items: center;
        gap: 8px;
    }

    .hzp-fb__basic-strip {
        display: flex;
        flex: 1 1 100%;
        order: 1;
        align-items: center;
        gap: 8px;
        width: 100%;
        min-width: 0;
        padding: 1px 0 3px;
        overflow-x: auto;
        overflow-y: hidden;
        overscroll-behavior-inline: contain;
        scroll-snap-type: inline proximity;
        scrollbar-width: none;
        -webkit-overflow-scrolling: touch;
    }

    .hzp-fb__basic-strip::-webkit-scrollbar {
        display: none;
    }

    /* The row owns no box on mobile; its real fields join the chip rail. */
    .hzp-fb__basic-strip .hzp-fb__row,
    .hzp-fb.hzp-fb--set .hzp-fb__basic-strip .hzp-fb__row,
    .hzp-fb:has(.hzp-fb__more[open]) .hzp-fb__basic-strip .hzp-fb__row {
        display: contents !important;
    }

    .hzp-fb__basic-strip .hzp-field {
        flex: 0 0 auto;
        max-width: none;
        gap: 0;
        scroll-snap-align: start;
    }

    /* Keep labels available to assistive technology without spending a row. */
    .hzp-fb__basic-strip .hzp-field__label {
        position: absolute;
        top: 0;
        left: 0;
        width: 1px;
        height: 1px;
        margin: -1px;
        padding: 0;
        overflow: hidden;
        border: 0;
        clip: rect(0 0 0 0);
        clip-path: inset(50%);
        white-space: nowrap;
    }

    .hzp-fb__basic-strip .hzp-select,
    .hzp-fb__basic-strip .hzp-input,
    .hzp-fb__city,
    .hzp-fb__basic-strip .hzp-range__el {
        height: 42px;
        border-color: var(--hzp-line-strong);
        border-radius: 999px;
        background: #ffffff;
        box-shadow: 0 1px 2px rgba(18, 20, 26, 0.05);
    }

    .hzp-fb__basic-strip .hzp-select__el,
    .hzp-fb__basic-strip .hzp-input__field,
    .hzp-fb__basic-strip .hzp-range__el {
        font-size: 14px;
        font-weight: 600;
    }

    .hzp-field--listing-type {
        order: 1;
        width: 116px;
    }

    .hzp-field--property-type {
        order: 2;
        width: 132px;
    }

    .hzp-fb__city {
        order: 3;
        flex: 0 0 auto;
        display: inline-flex;
        align-items: center;
        gap: 7px;
        min-width: 96px;
        padding: 0 15px;
        color: var(--hzp-body);
        font-size: 14px;
        font-weight: 600;
        line-height: 42px;
        white-space: nowrap;
        scroll-snap-align: start;
    }

    .hzp-fb__city svg {
        width: 16px;
        height: 16px;
        fill: none;
        stroke: currentColor;
        stroke-width: 1.8;
        stroke-linecap: round;
        stroke-linejoin: round;
    }

    .hzp-fb__basic-strip .hzp-field--location {
        order: 4;
        width: 176px;
    }

    .hzp-field--bedrooms {
        order: 5;
        width: 118px;
    }

    .hzp-fb__basic-strip .hzp-field--price {
        order: 6;
        width: 206px;
    }

    .hzp-fb__basic-strip .hzp-field--price .hzp-range {
        gap: 5px;
    }

    .hzp-fb__basic-strip .hzp-field--price .hzp-range__el {
        width: 94px;
        min-width: 0;
        padding-inline: 11px;
    }

    .hzp-fb__basic-strip .hzp-field--price .hzp-range__dash {
        flex: 0 0 auto;
    }

    /* Selected values read as active tags while retaining the native controls. */
    .hzp-fb__basic-strip .hzp-fb__chip--active .hzp-select,
    .hzp-fb__basic-strip .hzp-fb__chip--active .hzp-input,
    .hzp-fb__basic-strip .hzp-fb__chip--active .hzp-range__el {
        border-color: color-mix(in srgb, var(--hzp-red) 36%, white);
        background: var(--hzp-red-tint);
    }

    .hzp-fb__basic-strip .hzp-fb__chip--active .hzp-select__el,
    .hzp-fb__basic-strip .hzp-fb__chip--active .hzp-input__field,
    .hzp-fb__basic-strip .hzp-fb__chip--active .hzp-range__el,
    .hzp-fb__basic-strip .hzp-fb__chip--active .hzp-select svg {
        color: var(--hzp-red);
        stroke: currentColor;
    }

    /* Actions stay directly below the chips instead of beside a tall form. */
    .hzp-fb__actions {
        flex: 1 1 100%;
        order: 2;
        justify-content: flex-start;
        padding: 0;
        border: 0;
    }

    .hzp-fb__actions .hzp-btn {
        border-radius: 999px;
    }

    /* The horizontal rail must not crop the neighbourhood chooser. */
    .hzp-fb__basic-strip .hzloc__panel {
        position: fixed;
        inset-inline: 8px;
        top: auto;
        bottom: 8px;
        width: auto;
        max-height: 58vh;
        max-height: 58dvh;
        border-radius: 14px;
        z-index: 70;
    }
}

/* ========================================================================== 
   Mobile SERP guided tab flow
   ========================================================================== */
.hzp-mf {
    display: none;
}

@media (max-width: 720px) {
    /* JavaScript upgrades the native chip rail to the guided tab experience. */
    html.hzp-js .hzp-fb__basic-strip {
        display: none;
    }

    html.hzp-js .hzp-mf {
        display: flex;
        flex: 1 1 100%;
        order: 1;
        flex-direction: column;
        gap: 9px;
        width: 100%;
        min-width: 0;
    }

    .hzp-mf__steps,
    .hzp-mf__options {
        display: flex;
        align-items: center;
        gap: 8px;
        min-width: 0;
        overflow-x: auto;
        overscroll-behavior-inline: contain;
        scrollbar-width: none;
        -webkit-overflow-scrolling: touch;
    }

    .hzp-mf__steps::-webkit-scrollbar,
    .hzp-mf__options::-webkit-scrollbar {
        display: none;
    }

    .hzp-mf__step,
    .hzp-mf__option,
    .hzp-mf__apply {
        appearance: none;
        display: inline-flex;
        flex: 0 0 auto;
        align-items: center;
        justify-content: center;
        min-height: 42px;
        margin: 0;
        border: 1px solid var(--hzp-line-strong);
        border-radius: 999px;
        background: #ffffff;
        color: var(--hzp-body);
        font-family: inherit;
        font-size: 14px;
        font-weight: 650;
        line-height: 1.1;
        white-space: nowrap;
        cursor: pointer;
    }

    .hzp-mf__step {
        position: relative;
        padding: 0 16px;
        background: var(--hzp-fill);
    }

    .hzp-mf__step.is-current {
        border-color: color-mix(in srgb, var(--hzp-red) 42%, white);
        background: var(--hzp-red-tint);
        color: var(--hzp-red);
        box-shadow: 0 2px 8px rgba(7, 69, 217, 0.1);
    }

    .hzp-mf__body {
        display: flex;
        align-items: center;
        gap: 8px;
        width: 100%;
        min-width: 0;
    }

    .hzp-mf__panels {
        flex: 1 1 auto;
        min-width: 0;
    }

    .hzp-mf__panel,
    .hzp-mf__options {
        width: 100%;
        min-width: 0;
    }

    .hzp-mf__option {
        padding: 0 17px;
        box-shadow: 0 1px 2px rgba(18, 20, 26, 0.04);
    }

    .hzp-mf__option.is-selected {
        border-color: var(--hzp-red);
        background: var(--hzp-red);
        color: #ffffff;
        box-shadow: 0 3px 10px rgba(7, 69, 217, 0.18);
    }

    .hzp-mf__option svg {
        width: 16px;
        height: 16px;
        margin-inline-end: 7px;
        fill: none;
        stroke: currentColor;
        stroke-width: 1.8;
        stroke-linecap: round;
        stroke-linejoin: round;
    }

    .hzp-mf__apply {
        min-width: 116px;
        padding: 0 18px;
        border-color: var(--hzp-red);
        background: var(--hzp-red);
        color: #ffffff;
        box-shadow: 0 3px 10px rgba(7, 69, 217, 0.18);
    }

    .hzp-mf__price {
        display: flex;
        align-items: center;
        gap: 6px;
        width: max-content;
        min-width: 0;
    }

    .hzp-mf__price-input {
        width: 96px;
        height: 42px;
        padding: 0 12px;
        border: 1px solid var(--hzp-line-strong);
        border-radius: 999px;
        background: #ffffff;
        color: var(--hzp-ink);
        font-family: inherit;
        font-size: 14px;
        font-weight: 600;
    }

    .hzp-mf__price-input:focus {
        border-color: var(--hzp-red);
        outline: 2px solid var(--hzp-red-tint);
        outline-offset: 1px;
    }

    .hzp-mf__step:focus-visible,
    .hzp-mf__option:focus-visible,
    .hzp-mf__apply:focus-visible {
        outline: 2px solid var(--hzp-red);
        outline-offset: 2px;
    }

    /* The advanced Filters/Clear controls sit below the guided tabs. */
    html.hzp-js .hzp-fb__actions {
        margin-top: 1px;
    }
}

/* ==========================================================================
   SERP cards: one listing target without swallowing the real controls
   ========================================================================== */

/*
    The card heading remains the one semantic listing link and the only extra
    tab stop. Its transparent pseudo-element extends that same link across the
    card, so clicking price, specifications, location or empty space follows
    the normal listing URL and keeps native modifier-click behaviour.

    The media link, favourite button, member profile and contact group sit one
    layer above it. Their markup, hrefs and scripts are unchanged, so each keeps
    its existing action instead of falling through to the listing link.

    This is scoped to the SERP. The shared card partial also renders on seller
    profiles, and those pages are intentionally outside this request.
*/
.hzp-serp .hzp-card {
    isolation: isolate;
}

.hzp-serp .hzp-card__addr a::after {
    position: absolute;
    z-index: 1;
    inset: 0;
    border-radius: var(--hzp-radius);
    content: '';
    cursor: pointer;
}

.hzp-serp .hzp-card__medialink,
.hzp-serp .hzp-card .hzp-fav,
.hzp-serp .hzp-card a.hzp-agent--link,
.hzp-serp .hzp-card .hzp-contacts {
    position: relative;
    z-index: 2;
}

/* The single keyboard link outlines the whole card it opens. */
.hzp-serp .hzp-card__addr a:focus-visible {
    outline: 0;
}

.hzp-serp .hzp-card__addr a:focus-visible::after {
    outline: 3px solid rgba(7, 69, 217, .32);
    outline-offset: -3px;
}

/* ========================================================================== 
   SERP card gallery: one large photograph with previous/next controls
   ========================================================================== */

.hzp-serp .hzp-card__media--gallery {
    display: block;
    min-height: 196px;
    overflow: hidden;
}

.hzp-serp .hzp-card__gallery {
    position: absolute;
    inset: 0;
    overflow: hidden;
    background: var(--hzp-fill);
}

.hzp-serp .hzp-card__gallery .hzp-card__medialink {
    position: absolute;
    z-index: 2;
    inset: 0;
    display: block;
}

.hzp-serp .hzp-card__gallery .hzp-card__photo {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    min-height: 0;
    object-fit: cover;
}

.hzp-serp .hzp-card__media--gallery .hzp-badges {
    z-index: 4;
}

.hzp-card__gallery-nav {
    position: absolute;
    top: 50%;
    z-index: 4;
    display: none;
    width: 24px;
    height: 24px;
    padding: 0;
    border: 1px solid rgba(255, 255, 255, .5);
    border-radius: 50%;
    background: rgba(255, 255, 255, .5);
    color: #272b33;
    box-shadow: 0 3px 12px rgba(16, 20, 28, .16);
    cursor: pointer;
    place-items: center;
    transform: translateY(-50%);
    transition: background-color 140ms ease, box-shadow 140ms ease, transform 140ms ease;
}

html.hzp-js .hzp-serp .hzp-card__gallery-nav {
    display: grid;
}

.hzp-card__gallery-nav--prev {
    inset-inline-start: 12px;
}

.hzp-card__gallery-nav--next {
    inset-inline-end: 12px;
}

.hzp-card__gallery-nav:hover {
    background: rgba(255, 255, 255, .5);
    box-shadow: 0 5px 16px rgba(16, 20, 28, .22);
    transform: translateY(-50%);
}

.hzp-card__gallery-nav:focus-visible {
    outline: 3px solid rgba(7, 69, 217, .48);
    outline-offset: 2px;
}

.hzp-card__gallery-nav svg {
    width: 14px;
    height: 14px;
    fill: none;
    stroke: currentColor;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.hzp-card__gallery-dots {
    position: absolute;
    z-index: 4;
    inset-inline-start: 50%;
    bottom: 12px;
    display: flex;
    gap: 6px;
    align-items: center;
    padding: 5px 8px;
    border-radius: 999px;
    background: rgba(16, 20, 28, .34);
    pointer-events: none;
    transform: translateX(-50%);
}

.hzp-card__gallery-dot {
    display: block;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: rgba(255, 255, 255, .58);
    transition: background-color 140ms ease, transform 140ms ease;
}

.hzp-card__gallery-dot.is-active {
    background: #ffffff;
    transform: scale(1.25);
}

[dir="rtl"] .hzp-card__gallery-nav svg {
    transform: scaleX(-1);
}

[dir="rtl"] .hzp-card__gallery-dots {
    transform: translateX(50%);
}

@media (min-width: 768px) {
    .hzp-cards--grid .hzp-card__media--gallery {
        min-height: 0;
        aspect-ratio: 16 / 10;
    }
}

@media (max-width: 767.98px) {
    .hzp-serp .hzp-card__media--gallery {
        min-height: 0;
        aspect-ratio: 3 / 2;
    }

    .hzp-card__gallery-nav {
        width: 24px;
        height: 24px;
    }
}

@media (prefers-reduced-motion: reduce) {
    .hzp-card__gallery-nav,
    .hzp-card__gallery-dot {
        transition: none;
    }
}


/* Truncate only the title text, preserving the link overlay across the card. */
.hzp-serp .hzp-card__top > div {
    flex: 1;
    min-width: 0;
}

.hzp-serp .hzp-card__addr--compact {
    margin: 12px 0 8px;
    font-size: 16px;
    line-height: 1.5;
    font-weight: 600;
}

.hzp-serp .hzp-card__addr--compact a,
.hzp-serp .hzp-card__addr--compact span {
    display: block;
}

.hzp-serp .hzp-card__addr--compact span {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.hzp-serp .hzp-card__foot .hzp-card__district {
    margin: 0;
    min-width: 0;
}

@media (min-width: 768px) {
    .hzp-serp .hzp-cards:not(.hzp-cards--grid) .hzp-card {
        min-height: 210px;
    }

    .hzp-serp .hzp-cards:not(.hzp-cards--grid) .hzp-card__media--gallery {
        min-height: 0;
    }
}

.hzp-serp .hzp-card .hzp-contacts__btn {
    font-size: 16px;
}

/* Listing key information uses the project detail label-and-value layout. */
.hzp-detail .hzp-key-info {
    margin-top: 30px;
    padding: 24px;
    border-radius: 12px;
    background: #f5f7fc;
}
.hzp-detail .hzp-key-info > .hzp-panel__title { margin-bottom: 22px; }
.hzp-detail .hzp-dspecs {
    display: grid;
    grid-template-columns: repeat(var(--hzp-summary-columns, 3), minmax(0, 1fr));
    gap: 24px 16px;
    margin: 0;
    padding: 0;
    border: 0;
}
.hzp-detail .hzp-dspecs li {
    display: flex;
    align-items: flex-start;
    min-width: 0;
    gap: 10px;
    padding: 0;
    border: 0;
    background: transparent;
}
.hzp-detail .hzp-dspecs svg {
    width: 20px;
    height: 20px;
    margin-top: 2px;
    stroke: var(--hzp-red);
}
.hzp-detail .hzp-dspecs li > span { min-width: 0; }
.hzp-detail .hzp-dspecs__label {
    display: block;
    color: var(--hzp-muted);
    font-size: 13px;
    font-weight: 400;
    line-height: 1.6;
}
.hzp-detail .hzp-dspecs__value {
    display: block;
    margin-top: 7px;
    font-size: 15px;
    font-weight: 600;
    line-height: 1.45;
    overflow-wrap: anywhere;
}
.hzp-detail .hzp-dspecs__none { grid-column: 1 / -1; }
.hzp-detail .hzp-dmain > div.hzp-panel + section.hzp-panel { border-top: 0; }
/* Mobile facts form one readable row; long labels can scroll without wrapping. */
.hzp-detail .hzp-dspecs__compact { display: none; }
@media (max-width: 767.98px) {
    .hzp-detail .hzp-dmain > div.hzp-panel { min-width: 0; }
    .hzp-detail .hzp-key-info {
        min-width: 0;
        margin-top: 16px;
        margin-inline: -12px;
        padding: 12px;
        border-radius: 12px;
        background: #f5f7fc;
    }
    .hzp-detail .hzp-dspecs {
        display: flex;
        flex-wrap: nowrap;
        gap: 16px;
        max-width: 100%;
        overflow-x: auto;
        overscroll-behavior-x: contain;
        padding-block: 4px;
        scrollbar-width: thin;
        scrollbar-color: var(--hzp-line) transparent;
    }
    .hzp-detail .hzp-dspecs li {
        position: relative;
        flex: none;
        align-items: center;
        gap: 6px;
        white-space: nowrap;
    }
    .hzp-detail .hzp-dspecs svg {
        width: 18px;
        height: 18px;
        margin-top: 0;
        stroke: var(--hzp-muted);
    }
    .hzp-detail .hzp-dspecs__stacked {
        position: absolute;
        width: 1px;
        height: 1px;
        margin: -1px;
        overflow: hidden;
        clip-path: inset(50%);
        white-space: nowrap;
    }
    .hzp-detail .hzp-dspecs__compact {
        display: inline;
        font-size: 14px;
        font-weight: 400;
        line-height: 1.5;
    }
}

/* Match project detail typography while keeping listing content and layout. */
.hzp-detail .hzp-dtitle {
    margin: 20px 0;
    font-size: 20px;
    font-weight: 700;
    line-height: 1.2;
    letter-spacing: -.025em;
    overflow-wrap: anywhere;
}
.hzp-detail .hzp-dprice__value { font-size: 32px; }
.hzp-detail .hzp-dprice__value small { font-size: 16px; font-weight: 600; }
.hzp-detail .hzp-daddr { margin-top: 0; font-size: 15px; line-height: 1.6; }
.hzp-detail .hzp-panel__title,
.hzp-detail .hzp-rail__title {
    font-size: 24px;
    font-weight: 650;
    line-height: 1.3;
    letter-spacing: -.02em;
}
.hzp-detail .hzp-prose p { margin-bottom: 16px; font-size: 14px; line-height: 1.72; }
.hzp-detail .hzp-prose p:last-child { margin-bottom: 0; }
.hzp-detail .hzp-overview__content.is-collapsed {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 4;
    overflow: hidden;
}
.hzp-detail .hzp-overview__toggle {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin-top: 14px;
    padding: 4px 0;
    border: 0;
    background: transparent;
    color: var(--hzp-red);
    font: inherit;
    font-size: 14px;
    font-weight: 600;
    line-height: 1.5;
    cursor: pointer;
}
.hzp-detail .hzp-overview__toggle[hidden] { display: none; }
.hzp-detail .hzp-overview__toggle:hover { text-decoration: underline; }
.hzp-detail .hzp-overview__toggle:focus-visible {
    outline: 2px solid var(--hzp-red);
    outline-offset: 4px;
    border-radius: 3px;
}
.hzp-detail .hzp-overview__toggle svg {
    width: 18px;
    height: 18px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.8;
    stroke-linecap: round;
    stroke-linejoin: round;
}
.hzp-detail .hzp-overview__toggle[aria-expanded="true"] svg { transform: rotate(180deg); }

.hzp-detail .hzp-info__key { font-size: 13px; line-height: 1.6; }
.hzp-detail .hzp-info__val,
.hzp-detail .hzp-dspecs li { font-size: 15px; font-weight: 600; line-height: 1.45; }
.hzp-detail .hzp-chip { font-size: 16px; font-weight: 400; line-height: 1.6; }
.hzp-detail .hzp-contactcard__title,
.hzp-detail .hzp-agentcard__title { font-size: 20px; line-height: 1.4; }
.hzp-detail .hzp-contactcard__sub,
.hzp-detail .hzp-safe__text { font-size: 13px; line-height: 1.65; }
.hzp-detail .hzp-agentrow__name,
.hzp-detail .hzp-agentcard__line { font-size: 15px; line-height: 1.6; }
.hzp-detail .hzp-agentrow__meta { font-size: 13px; line-height: 1.6; }

@media (max-width: 639.98px) {
    .hzp-detail .hzp-panel__title,
    .hzp-detail .hzp-rail__title { font-size: 22px; }
    .hzp-detail .hzp-chip { font-size: 14px; }
}

/* Tighter reading rhythm on phones, without changing desktop sections. */
@media (max-width: 767.98px) {
    .hzp-detail .hzp-dgrid { row-gap: 16px; }
    .hzp-detail .hzp-dmain > .hzp-panel { padding-block: 16px; }
    .hzp-detail .hzp-dmain > .hzp-panel[aria-labelledby="hzp-overview"] { padding-top: 0; }
    .hzp-detail .hzp-dmain > .hzp-panel > .hzp-panel__title { margin-bottom: 14px; }
    .hzp-detail .hzp-dtitle { margin-block: 12px; }
    .hzp-detail .hzp-overview__toggle { margin-top: 10px; }
    .hzp-detail .hzp-location__nearby { margin-top: 16px; }
}

/* Match the project detail contact buttons and rounded enquiry card. */
.hzp-detail .hzp-contactcard__actions .hzp-btn,
.hzp-detail .hzd-callbar__btn {
    min-height: 48px;
    height: auto;
    padding: 12px;
    border-radius: 8px;
    font-size: 16px;
    font-weight: 600;
    line-height: 1.6;
}

.hzp-detail .hzp-contactcard {
    padding: 24px;
    border-radius: 14px;
    border-top: 3px solid var(--hzp-red);
    box-shadow: 0 8px 24px rgba(15, 23, 42, .05);
}

.hzp-detail .hzp-contactcard__actions {
    gap: 12px;
}

@media (max-width: 639.98px) {
    .hzp-detail .hzp-contactcard {
        padding: 20px;
    }
}

.hzp-serp .hzp-card a.hzp-btn[href^="tel:"] > svg,
.hzp-detail a.hzp-btn[href^="tel:"] > svg,
.hzp-serp .hzp-card__whatsapp-icon,
.hzp-detail .hzp-whatsapp-icon {
    display: block;
    flex: 0 0 20px;
    width: 20px;
    height: 20px;
    object-fit: contain;
}

.hzp-detail a.hzp-btn[href^="https://wa.me/"]:not(.hzp-btn--accent):hover,
.hzp-serp a.hzp-btn[href^="https://wa.me/"]:not(.hzp-btn--accent):hover {
    border-color: #25d366;
}

/* Small visible arrows keep a comfortable touch target. */
.hzp-serp .hzp-card__gallery-nav::before {
    content: "";
    position: absolute;
    inset: -10px;
}

/* Keep sorting available while removing the layout choice on phones. */
@media (max-width: 767.98px) {
    .hzp-serp .hzp-results__head > .hzp-view-switch {
        display: none;
    }

    .hzp-serp .hzp-results__head {
        grid-template-columns: minmax(0, 1fr);
    }

    .hzp-serp .hzp-results__head > .hzp-sort {
        width: auto;
        max-width: 100%;
    }
}

/* Member contact controls use the same branded treatment as search results. */
.hzp-member .hzp-card__whatsapp-icon,
.hzp-member .hzp-member__whatsapp-icon,
.hzp-member a.hzp-btn[href^="tel:"] > svg {
    display: block;
    flex: 0 0 20px;
    width: 20px;
    height: 20px;
    object-fit: contain;
}

.hzp-member .hzp-contacts__btn,
.hzp-member .hzpa__actions .hzp-btn {
    font-size: 16px;
}

.hzp-member a.hzp-btn[href^="https://wa.me/"]:not(.hzp-btn--accent):hover {
    border-color: #25d366;
}

/* Listing enquiry component, shared with the reference storefront. */
        .hzp-detail .hzp-enquiry__separator {
            display: flex;
            align-items: center;
            gap: 12px;
            margin: 20px 0;
            color: var(--hzp-muted);
            font-size: 13px;
            text-align: center;
        }
        .hzp-detail .hzp-enquiry__separator::before,
        .hzp-detail .hzp-enquiry__separator::after {
            content: "";
            flex: 1;
            border-top: 1px solid var(--hzp-line);
        }
        .hzp-detail .hzp-enquiry__form { display: grid; gap: 12px; }
        .hzp-detail .hzp-enquiry__field {
            display: block;
            padding: 6px 10px;
            border: 1px solid var(--hzp-line);
            border-radius: 7px;
            background: #f9fbff;
        }
        .hzp-detail .hzp-enquiry__field:focus-within {
            border-color: var(--hzp-red);
            box-shadow: 0 0 0 2px rgba(7, 69, 217, .10);
        }
        .hzp-detail .hzp-enquiry__field-label {
            display: block;
            color: var(--hzp-muted);
            font-size: 11px;
            font-weight: 600;
            line-height: 1.3;
            text-transform: uppercase;
        }
        .hzp-detail .hzp-enquiry__field input,
        .hzp-detail .hzp-enquiry__field textarea {
            display: block;
            width: 100%;
            min-height: 24px;
            margin: 0;
            padding: 0;
            border: 0;
            outline: 0;
            background: transparent;
            color: var(--hzp-ink);
            font: inherit;
            font-size: 14px;
        }
        .hzp-detail .hzp-enquiry__field textarea {
            min-height: 74px;
            resize: vertical;
            line-height: 1.45;
        }
        .hzp-detail .hzp-enquiry__phone {
            display: flex;
            align-items: center;
            gap: 8px;
        }
        .hzp-detail .hzp-enquiry__prefix {
            flex: none;
            color: var(--hzp-ink);
            font-size: 14px;
        }
        .hzp-detail .hzp-enquiry__role {
            display: flex;
            flex-wrap: wrap;
            align-items: center;
            gap: 8px 12px;
            margin: 6px 0 0;
            padding: 0;
            border: 0;
            color: var(--hzp-ink);
            font-size: 13px;
        }
        .hzp-detail .hzp-enquiry__role legend { float: inline-start; margin-inline-end: 10px; }
        .hzp-detail .hzp-enquiry__role label,
        .hzp-detail .hzp-enquiry__updates {
            display: inline-flex;
            align-items: center;
            gap: 6px;
            color: var(--hzp-ink);
            font-size: 13px;
            line-height: 1.4;
        }
        .hzp-detail .hzp-enquiry__role input,
        .hzp-detail .hzp-enquiry__updates input { accent-color: var(--hzp-red); }
        .hzp-detail .hzp-enquiry__updates { margin: 2px 0 6px; }
        .hzp-detail .hzp-enquiry__submit {
            display: flex;
            align-items: center;
            justify-content: center;
            gap: 9px;
            min-height: 48px;
            padding: 10px 14px;
            border: 1px solid var(--hzp-red);
            border-radius: 6px;
            background: #fff;
            color: var(--hzp-red);
            font-size: 15px;
            font-weight: 700;
            cursor: pointer;
        }
        .hzp-detail .hzp-enquiry__submit:hover { background: var(--hzp-red-tint); }
        .hzp-detail .hzp-enquiry__submit:disabled { opacity: .55; cursor: wait; }
        .hzp-detail .hzp-enquiry__submit svg { width: 20px; height: 20px; }
        .hzp-detail .hzp-enquiry__status { min-height: 1.3em; margin: 0; font-size: 13px; }
        .hzp-detail .hzp-enquiry__status.is-error { color: #aa2424; }
        .hzp-detail .hzp-enquiry__status.is-success { color: #21813e; }

.hzp-results__title .hzp-results__title-count { font-size: 14px; font-weight: 400; white-space: nowrap; }
.hzp-detail .hzp-enquiry__phone input { min-width: 0; }
