/*
 * Property channel stylesheet.
 *
 * Plain CSS, served straight from public/ and loaded by
 * resources/themes/property/views/components/layouts/footer/styles.blade.php.
 * Deliberately outside the Vite pipeline: the shop build in
 * public/themes/shop/default/build is newer than its own sources and cannot be
 * regenerated, so nothing here may require an asset build.
 *
 * Width and gutter come from --site-container-width / --site-gutter, which the
 * shared container partial declares for every channel.
 */

/* ============================================================== footer ===== */
/*
 * Property channel footer.
 *
 * Replaces the dark green gradient block that sat here, along with its --pf-*
 * tokens: nothing outside the footer template referenced either, so both are
 * gone rather than left behind.
 *
 * The cars channel never reaches these rules. It resolves the default shop
 * theme's footer, which carries no .hzf-* class, and property.css is not in
 * its asset list at all.
 *
 * White page, one hairline, dark neutral text, grey secondary text, and the
 * primary reserved for hover and focus. No panel background, no shadow, no
 * gradient: the footer is the end of the page, not a component sitting on it.
 *
 * THE SPACE ABOVE THE FIRST ROW IS PADDING, NOT MARGIN
 *
 * It used to be `margin-top: 56px` here plus `padding: 48px 0 0` on the inner
 * shell, and both were wrong in a way that only showed on some pages.
 *
 * The margin sat outside the background, so those 56px were painted by
 * whatever was behind the footer -- and nothing is: `main` and `body` are both
 * transparent at that point, so it fell through to the canvas and came out
 * white. On a page that ends white nobody noticed. On the account area and the
 * Add Listing page, whose shells (.hzac and .hzf-page) paint #f4f5f7 right up
 * to the bottom of `main`, it read as a white strip wedged between the page and
 * the footer. Measured: the shells end exactly where `main` ends on every page,
 * so all 56px of that strip were this margin and none of it belonged to those
 * page shells.
 *
 * The inner padding never applied at all. `.hzf__inner` also carries .hz-shell,
 * and `.hz-shell { padding: 0 24px }` is declared ~220 lines below this at the
 * same specificity, so its shorthand reset the top padding to zero and the
 * footer opened with its logo flush against the border. That is why the
 * breathing room appeared to be outside the footer rather than inside it.
 *
 * So: padding on .hzf, which is the element that paints the background and the
 * hairline. The separation is now inside the footer, the background meets the
 * page background at the border with nothing between them, and there is no
 * shorthand competing for it. 40px because that is what .hzf__bottom already
 * uses for the gap below the last row -- one number for both ends of the
 * footer's interior.
 */

.hzf {
    padding-top: 40px;
    border-top: 1px solid var(--hz-line);
    background: #fafafa;
    color: var(--hz-ink);
    font-family: Roboto, "Helvetica Neue", Arial, sans-serif;
}

/*
 * The brand column is given more room than the link groups because it holds a
 * logo and a sentence rather than a stack of short labels. auto-fit is
 * deliberately not used: the groups are a fixed, known set, so an explicit
 * track list keeps the brand column from collapsing to a link column's width.
 */
.hzf__grid {
    display: grid;
    grid-template-columns: 1.6fr repeat(4, minmax(0, 1fr));
    gap: 32px 28px;
}

/* ---- brand ------------------------------------------------------------- */

.hzf__brand {
    display: inline-block;
    text-decoration: none;
}

.hzf__logo {
    display: block;
    width: auto;
    height: 34px;
    /* Same reason as the header mark: an auto grid track will otherwise squash
       it below its intrinsic width on narrow viewports. */
    min-width: max-content;
}

.hzf__tagline {
    margin: 14px 0 0;
    max-width: 30ch;
    color: #5c6270;
    font-size: 13.5px;
    line-height: 1.6;
}

/* ---- link groups -------------------------------------------------------- */

.hzf__title {
    margin: 0 0 14px;
    color: var(--hz-ink);
    font-size: 11.5px;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

.hzf__list {
    margin: 0;
    padding: 0;
    list-style: none;
}

/* Rows already carry 10px of padding between them from .hzf__link, so the
   margin only tops up the gap to the intended rhythm. */
.hzf__list li + li {
    margin-top: 2px;
}

/*
 * inline-block with vertical padding rather than a bare inline anchor: as
 * inline text the hit box is only the 15px line box, which is below the 24px
 * minimum target size. The padding takes it to 25px here and 35px once the
 * columns stack, where it is being tapped rather than clicked.
 */
.hzf__link {
    display: inline-block;
    padding: 5px 0;
    color: #5c6270;
    font-size: 13.5px;
    font-weight: 500;
    text-decoration: none;
    transition: color 0.15s ease;
}

.hzf__link:hover {
    color: var(--hagzi-primary);
}

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

.hzf__contact {
    margin: 0;
    color: #5c6270;
    font-size: 13.5px;
    font-style: normal;
    line-height: 1.6;
}

.hzf__contact p {
    margin: 0 0 4px;
}

/* ---- bottom bar --------------------------------------------------------- */

.hzf__bottom {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 10px 24px;
    margin-top: 40px;
    padding: 18px 0 22px;
    border-top: 1px solid var(--hz-line);
}

.hzf__copy {
    margin: 0;
    color: #6b7280;
    font-size: 12.5px;
}

.hzf__legal {
    display: flex;
    flex-wrap: wrap;
    gap: 20px;
    margin: 0;
    padding: 0;
    list-style: none;
}

.hzf__legal .hzf__link {
    color: #6b7280;
    font-size: 12.5px;
}

/* The footer sits on near-white, so the ring is the primary rather than the
   white one used over the hero photograph. */
.hzf a:focus-visible {
    outline: 3px solid var(--hagzi-primary);
    outline-offset: 3px;
    border-radius: 6px;
}

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

/*
 * Five tracks do not survive below roughly 1000px, so the brand takes a full
 * row and the four groups pair off beneath it. Stacked columns rather than
 * accordions: four groups of at most four links are short enough that
 * collapsing them would add a control for no gain.
 */
@media (max-width: 1000px) {
    .hzf__grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .hzf__brand-col {
        grid-column: 1 / -1;
    }

    .hzf__tagline {
        max-width: 46ch;
    }
}

@media (max-width: 560px) {
    /* Same pairing as at full width: the space above the first row matches the
       space .hzf__bottom leaves below the last one, which drops to 32px here. */
    .hzf {
        padding-top: 32px;
    }

    .hzf__grid {
        grid-template-columns: 1fr;
        gap: 28px;
    }

    /* Stacked, so these are being tapped. Taller targets, and the margin drops
       to nothing because the padding now supplies the whole gap. */
    .hzf__link {
        padding: 10px 0;
    }

    .hzf__list li + li {
        margin-top: 0;
    }

    .hzf__bottom {
        flex-direction: column;
        align-items: flex-start;
        margin-top: 32px;
    }
}

/* ==========================================================================
 * Header + hero (property channel) — Realtor-style direction
 *
 * Replaces the earlier .ph-* header block that sat here. Plain CSS served from
 * public/, no build step.
 *
 * The car header's own stylesheet (header.marketplace-styles) still loads on
 * this channel, but every one of its 92 rule blocks is scoped under .op-*, so
 * it cannot reach anything below.
 * ========================================================================== */

:root {
    --hz-red: #d92228;
    --hz-red-dark: #b3171c;
    --hz-ink: #12141a;
    --hz-nav: #3c414c;
    --hz-line: #e7e9ee;

    /*
     * Hagzi's primary action colour, for the whole channel.
     *
     * This file loads before property-pages.css, so a :root declaration here
     * is in scope for every stylesheet on the channel. Other themes' sheets
     * consume it as var(--hagzi-primary, #0745D9) with the literal repeated as
     * a fallback, so nothing breaks if this file is ever loaded second.
     *
     * Measured against white text: #0745D9 gives 7.34:1 and #0638B0 gives
     * 9.54:1, so both clear AA for body text with room to spare. The hover is
     * a darker blue, clear enough to read as a state change without shifting
     * hue.
     *
     * This is an action colour, not a brand wash. The channel stays white,
     * dark neutral and light grey; blue marks what can be clicked and what
     * is currently selected, and nothing else.
     */
    --hagzi-primary: #0745D9;
    --hagzi-primary-dark: #0638B0;
}

.hz-shell {
    width: 100%;
    max-width: 1200px;
    margin: 0 auto;
    padding: 0 24px;
}

/* Shared focus ring. Never removed, only restyled. */
.hz-nav__link:focus-visible,
.hz-phone:focus-visible,
.hz-cta:focus-visible,
.hz-brand:focus-visible,
.hz-band__cta:focus-visible,
.hz-band__link:focus-visible,
.hz-search__clear:focus-visible,
.hz-search__submit:focus-visible,
.hz-tab__input:focus-visible + .hz-tab__label {
    outline: 3px solid #ffffff;
    outline-offset: 2px;
    border-radius: 6px;
}

/*
 * On white the ring takes the primary: it is the channel's action colour and
 * measures 7.34:1 against white, so it is easier to see than the red it
 * replaces. The rings that sit on photographs stay white further down; blue
 * would disappear into a dark image.
 */
.hz-header .hz-nav__link:focus-visible,
.hz-header .hz-phone:focus-visible,
.hz-header .hz-brand:focus-visible,
.hz-band__cta:focus-visible,
.hz-band__link:focus-visible {
    outline-color: var(--hagzi-primary);
}

/* --------------------------------------------------------------- header ---- */

.hz-header {
    border-bottom: 1px solid var(--hz-line);
    background: #fff;
    font-family: Roboto, "Helvetica Neue", Arial, sans-serif;
}

.hz-header__inner {
    display: grid;
    grid-template-columns: auto 1fr auto;
    align-items: center;
    gap: 24px;
    min-height: 68px;
}

.hz-brand {
    display: inline-flex;
    align-items: center;
    text-decoration: none;
}

/*
 * The Hagzi mark and wordmark are supplied as one 133x38 SVG lockup.
 *
 * The intrinsic size sits on the element's width/height attributes so the box
 * is reserved before the image decodes; height drives the rendered size here
 * and width:auto holds the ratio. SVG keeps the lockup sharp at every size.
 *
 * min-width is a correctness guard, not a tweak. The brand sits in an `auto`
 * grid track, and a replaced element with width:auto contributes zero to
 * min-content, so under pressure the track could be crushed and the lockup
 * rendered distorted or to nothing at all — silently, because squashing the
 * image does not produce a document overflow for an overflow check to catch.
 * It measured 14px wide at 390px and 0 at 375px once two more items joined the
 * action row. Pinning the minimum to max-content makes the row give somewhere
 * else instead.
 */
.hz-brand__logo {
    display: block;
    width: auto;
    height: 30px;
    min-width: max-content;
}

/*
 * Sits immediately right of the logo and left-aligned with it, rather than
 * centred in its track: the realtor.com / Zoopla arrangement.
 *
 * The grid is unchanged, so the nav still owns the 1fr middle column. All the
 * slack therefore collects to the nav's right and the actions cluster stays
 * pinned to the far right exactly where it was.
 *
 * margin-left tops up the grid column-gap so the logo and the first link read
 * as two deliberate groups rather than one continuous run of text: 40px above
 * 1080px where the grid gap is 24px, 32px below it where the gap tightens to
 * 16px. It is reset at 720px, where the nav drops to its own full-width row and
 * needs to sit flush with the logo above it instead.
 */
.hz-nav {
    display: flex;
    justify-content: flex-start;
    gap: 30px;
    min-width: 0;
    margin-inline-start: 16px;
}

.hz-nav__link {
    padding: 4px 2px;
    color: var(--hz-nav);
    font-size: 14px;
    font-weight: 500;
    text-decoration: none;
    white-space: nowrap;
}

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

/*
 * The gap is measured between BOXES, but the eye reads the distance between
 * MARKS, and the two are not the same once a box is bigger than the glyph in
 * it. Measured at the old 18px gap with 40px icon boxes, mark to mark:
 * number to globe 19.7px, EN to heart 30.8px, heart to bell 44.0px. The last
 * one is worst because both icons contribute their own slack to it.
 *
 * So the gap is tightened and the boxes with it, and two small corrections
 * even out the rest: see .hz-locale and .hz-hicon + .hz-hicon below.
 */
.hz-actions {
    display: flex;
    align-items: center;
    gap: 9px;
}

.hz-phone,
.hz-locale {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 13px;
    font-weight: 600;
    white-space: nowrap;
}

.hz-phone {
    color: var(--hz-nav);
    text-decoration: none;
}

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

.hz-phone svg,
.hz-locale svg {
    width: 15px;
    height: 15px;
}

/* Static indicator, not a control: muted, no pointer, not focusable. */
.hz-locale {
    color: #9aa1ad;
    cursor: default;
    /*
     * The phone number is a text run whose last glyph ends flush with its box,
     * so it contributes no optical slack, while every glyph beside it does.
     * An equal CSS gap therefore looks tight here and loose everywhere else.
     * The correction rides on the locale rather than the phone so that it
     * disappears along with the locale at 860px.
     */
    margin-inline-start: 7px;
}

/*
 * Favourite and notification marks.
 *
 * Inert by construction like the locale beside them and the card hearts, so
 * they take the same muted grey rather than the phone's darker nav colour. That
 * is this header's existing signal for "indicator, not control", and using a
 * live-looking treatment on something with no destination is the thing we are
 * avoiding.
 *
 * A 32px square around a 22px glyph.
 *
 * The earlier pair were sized for optical balance against the 15px glyphs
 * beside them, which made them recede next to the CTA. These are meant to be
 * prominent instead, so the glyph stays at 22px.
 *
 * Only the box around it is tightened, from 40px. At 40 each icon padded
 * itself by roughly 13px a side and pushed its neighbours away, which is what
 * made the row read as four separated items rather than one group. 32px still
 * clears the 24px minimum target with room to spare.
 *
 * The square stays transparent — no chip, no border — because two filled pills
 * next to the purple CTA would out-compete it.
 *
 * No :focus-visible rule, because neither is focusable: they are spans with no
 * tabindex, so there is no focus to style. If either is later wired to a real
 * route it becomes an <a> and MUST be added to the .hz-header focus-ring
 * selector list near the top of this file.
 */
.hz-hicon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    color: #9aa1ad;
    cursor: default;
}

/*
 * The one gap with two icon boxes either side of it, so it collects twice the
 * slack of every other gap in the row. Pulling it back by the gap's own width
 * leaves the two boxes exactly touching: their hit areas stay contiguous with
 * no overlap and no dead strip between them, and the marks land at the same
 * spacing as the rest of the row.
 */
.hz-hicon + .hz-hicon {
    margin-inline-start: -9px;
}

/*
 * stroke-width is in viewBox units, so it scales with the glyph: leaving it at
 * the old 1.7 would have rendered these at 1.56px against the phone's 1.06px,
 * and the pair would have read as a heavier family sitting beside a lighter
 * one. 1.25 across a 22px glyph renders at 1.15px, which holds the line.
 */
.hz-hicon svg {
    width: 22px;
    height: 22px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.25;
    stroke-linecap: round;
    stroke-linejoin: round;
}

/* The bell's clapper arc reads heavy against its own body, so it keeps the
   same slight reduction it had before: 1.18 renders at 1.08px. */
.hz-hicon--bell svg {
    stroke-width: 1.18;
}

.hz-cta {
    padding: 9px 18px;
    border-radius: 999px;
    border: 1px solid var(--hagzi-primary);
    background: var(--hagzi-primary);
    color: #fff;
    transition: background-color 0.15s ease, border-color 0.15s ease;
    font-size: 13px;
    font-weight: 700;
    text-decoration: none;
    white-space: nowrap;
}

.hz-cta:hover {
    border-color: var(--hagzi-primary-dark);
    background: var(--hagzi-primary-dark);
}

/* ----------------------------------------------------------------- hero ---- */
/*
 * Bright image, light scrim, and the content block anchored below the top of
 * the photo.
 *
 * It was centred (align-items: center) inside a 660px min-height, which tied
 * the hero's height and the content's position to one knob: taking height off
 * the bottom dragged the search card up with it. Anchoring to the top separates
 * the two. padding-top alone now decides where the content sits, and the height
 * decides how much photograph is left underneath it — which is what lets the
 * empty band below the card be cut without the card moving.
 *
 * The height is content-driven at every width: padding-top + content +
 * padding-bottom. min-height is a floor, held roughly 30px under the natural
 * height so it only takes over if the content is ever unusually short.
 *
 * Image, crop and scrim are untouched. Note for anyone changing this: with the
 * photograph at 1920x873 and background-position at "center 72%", a hero
 * shorter than about 655px at 1440 starts cropping vertically, and 72% puts
 * roughly three quarters of that crop on the TOP edge rather than the bottom.
 * Shortening the hero therefore trims the ceiling, not the floor.
 */

.hz-hero {
    position: relative;
    display: flex;
    align-items: flex-start;
    min-height: 540px;
    overflow: hidden;
    background-color: #223046;
}

/*
 * The one state in which the hero must not clip: a filter chip's panel is open
 * and hangs below the search card, past the section's bottom edge.
 *
 * Measured before this rule existed: the amenities panel is 300px tall and the
 * hero ended 112px below its top, so four of seventeen options were reachable
 * and the rest were cut off with nothing on screen to say so. The panel passed
 * a "is it visible" check the whole time, because it had a non-zero box — it
 * was an ancestor doing the clipping, not the panel being hidden.
 *
 * Scoped with :has() rather than dropping overflow altogether, so the hero
 * clips exactly as it always has in every other state and this cannot become
 * the reason some future absolutely positioned thing bleeds out of it. The
 * hero is a flex container, so toggling overflow changes no layout: margins
 * do not collapse through a flex container either way. Verified no geometry
 * moves at 1440, 1280, 1024, 768, 430 and 390.
 *
 * A browser without :has() keeps the old clipping. That is the pre-existing
 * behaviour rather than a new failure, and the panels still open and still
 * submit; the lower options just need scrolling to reach.
 */
.hz-hero:has(details[data-hz-chip][open]) {
    overflow: visible;
}

.hz-hero__media {
    position: absolute;
    inset: 0;
    background-repeat: no-repeat;
    background-size: cover;
    /* Anchored to the top so `cover` takes its overflow off the bottom of the
       frame — bare floor — instead of the ceiling. Note this only has any
       effect where the crop is vertical, i.e. viewports wider than the image's
       2.2:1 ratio. Narrower boxes crop horizontally and ignore the Y value. */
    background-position: center 0%;
}

/*
 * Deliberately lighter than the previous cinematic treatment so the photo reads
 * clearly, as in the reference. Slightly stronger at the very top and bottom,
 * where the headline and the card edge need separation from the image.
 */
.hz-hero__scrim {
    position: absolute;
    inset: 0;
    background:
        linear-gradient(
            180deg,
            rgba(10, 16, 26, 0.48) 0%,
            rgba(10, 16, 26, 0.30) 38%,
            rgba(10, 16, 26, 0.32) 70%,
            rgba(10, 16, 26, 0.46) 100%
        );
}

.hz-hero__content {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    /* padding-top IS the content's vertical position now that the hero anchors
       to the top. 148px is where the centred 660px hero put the headline, to
       within a pixel, so the block did not move when the hero lost 90px off
       its bottom edge.

       padding-bottom is the floor of the band under the search card. It is a
       real minimum rather than decoration: if the content ever outgrows the
       min-height — a headline wrapping at some awkward width — this is what
       keeps the card off the section below instead of flush against it. */
    padding-top: 148px;
    padding-bottom: 96px;
    text-align: center;
}

.hz-hero__title {
    margin: 0 0 10px;
    color: #ffffff;
    font-size: 48px;
    font-weight: 800;
    line-height: 1.1;
    letter-spacing: -0.6px;
    text-shadow: 0 2px 18px rgba(8, 12, 20, 0.55);
}

.hz-hero__subtitle {
    margin: 0 0 26px;
    color: rgba(255, 255, 255, 0.96);
    font-size: 19px;
    font-weight: 500;
    line-height: 1.4;
    text-shadow: 0 1px 12px rgba(8, 12, 20, 0.6);
}

.hz-hero__form {
    display: flex;
    flex-direction: column;
    align-items: center;
    width: 100%;
}

/* ----------------------------------------------------------------- tabs ---- */
/*
 * A white pill bar holding the three segments. Still radio inputs and labels:
 * arrow keys move between them natively and there is no JavaScript involved,
 * so the tabs cannot break. Transactions and Agents are gone.
 */

.hz-tabbar {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    max-width: 100%;
    margin: 0 0 18px;
    padding: 5px;
    border-radius: 999px;
    background: #ffffff;
    box-shadow: 0 6px 22px rgba(6, 10, 18, 0.18);
    overflow-x: auto;
    scrollbar-width: none;
}

.hz-tabbar::-webkit-scrollbar {
    display: none;
}

.hz-tab {
    display: inline-flex;
    flex: 0 0 auto;
}

/* Off-screen rather than display:none, so the radio stays focusable. */
.hz-tab__input {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    border: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
}

.hz-tab__label {
    display: inline-block;
    padding: 9px 26px;
    border-radius: 999px;
    color: #2b3040;
    font-size: 14px;
    font-weight: 600;
    line-height: 1.2;
    white-space: nowrap;
    cursor: pointer;
    transition: background-color 0.15s ease, color 0.15s ease;
}

.hz-tab__label:hover {
    background: #f3f4f7;
}

/*
 * The two filters, grouped.
 *
 * A box of its own so that role="group" aria-label="Listing type" can name
 * exactly the controls that are listing types, and nothing else. It is a flex
 * row carrying the same 4px the bar carries, so the pills sit where they always
 * did: this adds a node, not a gap.
 */
.hz-tabbar__types {
    display: inline-flex;
    align-items: center;
    gap: 4px;
}

/*
 * New projects -- the one control in this bar that loads another page.
 *
 * It was .hz-tab__label on an anchor, which made it pixel-identical to the two
 * pills beside it: same padding, same weight, same grey hover wash. Two
 * behaviours in the same clothing, and the giveaway was that only its
 * neighbours could ever light up, because only they have a radio to check.
 *
 * So it drops the pill. It briefly also took the channel's action colour and
 * the forward arrow .hz-seeall uses elsewhere on this page; both were removed
 * on request, and the type is now the same near-black as .hz-tab__label.
 *
 * WHICH LEAVES THE HAIRLINE DOING ALL OF THE WORK. border-inline-start is the
 * only thing at rest that separates a control which loads another page from two
 * that set a filter in place, so it is load-bearing rather than trim -- please
 * do not fold it into the pills' 4px gap. The hover underline below is the only
 * other differentiator, and it needs a pointer to appear at all.
 *
 * It stays inside the white bar rather than moving out alongside it because
 * the bar is white for a reason: the hero behind it is a photograph, and text
 * out on the image has no contrast that holds at every crop and every hero.
 *
 * Nothing here can match .hz-tab__input:checked, which is the point. It is
 * never the selected anything -- the page it points at is not this one.
 */
.hz-tabbar__jump {
    display: inline-flex;
    align-items: center;
    flex: 0 0 auto;
    margin-inline-start: 4px;
    padding-block: 9px;
    padding-inline: 16px;
    border-inline-start: 1px solid var(--hz-line);
    /* The pills' own ink, literal for literal -- see .hz-tab__label. */
    color: #2b3040;
    font-size: 14px;
    font-weight: 600;
    line-height: 1.2;
    white-space: nowrap;
    text-decoration: none;
}

/*
 * An underline rather than the pills' background wash. The pills are answering
 * "which of these"; this is answering "go there", and filling a pill shape on
 * hover is exactly the suggestion this control should stop making.
 *
 * With the colour and the arrow gone this is the only thing that tells a
 * pointer user the two behaviours apart, so it earns its keep twice over.
 */
.hz-tabbar__jump:hover {
    text-decoration: underline;
    text-underline-offset: 3px;
}

/*
 * Inset, like the pills' own ring: the bar clips at its border radius, so an
 * outward ring on the last item in the row would be cut off.
 */
.hz-tabbar__jump:focus-visible {
    outline: 3px solid var(--hagzi-primary);
    outline-offset: -3px;
    border-radius: 6px;
}

/*
 * The selected segment. A tint of the primary rather than a fill, because the
 * hero already carries one solid purple control in the Search button and two
 * would compete for the same rank.
 *
 * The tint is the primary at 8% over white. Primary text on it measures
 * 7.92:1, so the label stays comfortably readable.
 */
.hz-tab__input:checked + .hz-tab__label {
    background: #EAF1FF;
    color: var(--hagzi-primary);
}

/* --------------------------------------------------------- search card ---- */
/*
 * The raised white panel from the reference: the search row and the filter row
 * live inside it.
 */

.hz-card {
    width: 100%;
    max-width: 920px;
    padding: 22px;
    border-radius: 22px;
    background: #ffffff;
    box-shadow: 0 20px 48px rgba(6, 10, 18, 0.24);
    text-align: start;
}

.hz-search {
    display: flex;
    align-items: center;
    gap: 10px;
    height: 54px;
    padding: 0 7px;
    padding-inline-start: 16px;
    border: 1px solid #e2e5ec;
    border-radius: 999px;
    background: #ffffff;
}

.hz-search:focus-within {
    border-color: #c9ced9;
    box-shadow: 0 0 0 3px rgba(7, 69, 217, 0.1);
}

.hz-search__icon {
    flex: 0 0 auto;
    width: 19px;
    height: 19px;
    color: #8b929f;
}

/* Visible label would duplicate the placeholder, but the field still needs a
   programmatic name, so it is hidden visually only. */
.hz-search__label {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    border: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
}

.hz-search__input {
    flex: 1 1 auto;
    min-width: 0;
    height: 100%;
    padding: 0;
    border: 0;
    outline: 0;
    background: transparent;
    color: var(--hz-ink);
    font-size: 15px;
    font-family: inherit;
}

.hz-search__input::placeholder {
    color: #9aa1ae;
    opacity: 1;
}

/* Chrome's own search affordance is suppressed in favour of the reset button,
   which works without JavaScript and is reachable by keyboard. */
.hz-search__input::-webkit-search-cancel-button,
.hz-search__input::-webkit-search-decoration {
    -webkit-appearance: none;
    appearance: none;
}

.hz-search__clear {
    display: none;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: #f1f2f5;
    color: #5c6270;
    cursor: pointer;
}

.hz-search__clear svg {
    width: 15px;
    height: 15px;
}

.hz-search__clear:hover {
    background: #e4e6ea;
    color: var(--hz-ink);
}

/* Only offered once there is something to clear. */
.hz-search__input:not(:placeholder-shown) ~ .hz-search__clear {
    display: inline-flex;
}

/*
 * Compact pill sitting inside the field, not a full-height block.
 *
 * The field is itself a pill, so a pill here is the concentric curve rather
 * than a stylistic choice: the field's radius is capped at half its height,
 * 27px, and the button is inset by 8px (1px border + 7px padding), which
 * leaves 19px — within a pixel of the button's own half-height of 20px. The
 * gap between the two therefore stays even the whole way round the right end.
 * The same holds at the 620px breakpoint, where 25 - 7 = 18 against 19.
 */
.hz-search__submit {
    flex: 0 0 auto;
    height: 40px;
    padding: 0 22px;
    border: 1px solid var(--hagzi-primary);
    border-radius: 999px;
    background: var(--hagzi-primary);
    color: #ffffff;
    font-size: 14px;
    font-weight: 700;
    font-family: inherit;
    line-height: 1;
    cursor: pointer;
    transition: background-color 0.15s ease, border-color 0.15s ease;
}

.hz-search__submit:hover {
    border-color: var(--hagzi-primary-dark);
    background: var(--hagzi-primary-dark);
}

/* --------------------------------------------------------- filter chips ---- */
/*
 * Layout parity with the reference, and nothing more. None of these attributes
 * exist in this catalogue, so the chips are spans rather than controls: they
 * carry no click target, stay out of the tab order, and cannot open an empty
 * dropdown. Muted rather than full-contrast so the inert state is visible
 * without hovering for the title.
 */

.hz-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    margin-top: 14px;
}

/*
 * The chips are real filters now, built on <details>, so the element is a
 * positioning context for its panel rather than the pill itself. The pill is
 * the <summary>.
 */
.hz-chip {
    position: relative;
}

.hz-chip__summary {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 9px 15px;
    border: 1px solid #dde1e9;
    border-radius: 999px;
    background: #fcfcfd;
    color: #5c6270;
    font-size: 13px;
    font-weight: 500;
    line-height: 1.2;
    white-space: nowrap;
    cursor: pointer;
    list-style: none;
    transition: border-color 0.15s ease, color 0.15s ease, background-color 0.15s ease;
}

/* Safari draws its own disclosure triangle unless both of these are set. */
.hz-chip__summary::-webkit-details-marker {
    display: none;
}

.hz-chip__summary::marker {
    content: "";
}

.hz-chip__summary:hover {
    border-color: #c3c9d4;
    color: var(--hz-ink);
}

.hz-chip[open] > .hz-chip__summary {
    border-color: var(--hagzi-primary);
    color: var(--hagzi-primary);
}

/*
 * A chip holding a selection. A tinted fill and a purple edge rather than a
 * solid purple pill: these are filters, and a solid fill would put them at the
 * same rank as the Search button sitting beside them.
 */
.hz-chip[data-hz-chip-active] > .hz-chip__summary {
    border-color: var(--hagzi-primary);
    background: #EAF1FF;
    color: var(--hagzi-primary);
    font-weight: 600;
}

.hz-chip[open] > .hz-chip__summary svg {
    transform: rotate(180deg);
}

.hz-chip__summary svg {
    transition: transform 0.15s ease;
}

.hz-chip__summary:focus-visible {
    outline: 3px solid var(--hagzi-primary);
    outline-offset: 2px;
}

/* ---- the panel ---------------------------------------------------------- */

.hz-chip__panel {
    position: absolute;
    z-index: 30;
    top: calc(100% + 6px);
    inset-inline-start: 0;
    min-width: 200px;
    /*
     * Tall enough that the seventeen amenities all fit at two columns, which
     * is what the 621-1100 band uses: measured scrollHeight is 390px there.
     * At 300 the last five needed an inner scroller, which is a poor way to
     * discover that Storage and Staff quarters exist. The three-column panel
     * is 256px tall and is unaffected by this.
     */
    max-height: 400px;
    overflow-y: auto;
    padding: 14px;
    border: 1px solid var(--hz-line);
    border-radius: 14px;
    background: #ffffff;
    box-shadow: 0 12px 28px rgba(16, 20, 30, 0.14);
    text-align: start;
}

/*
 * Amenities is seventeen options, and this panel is two columns at every width
 * now. There is no three-column case left.
 *
 * Three columns need 500px and 500px no longer fits. The property type chip
 * was added at the head of the row, which pushes the amenities chip along by
 * its width plus the gap, and the card the panel has to stay inside is a fixed
 * 920px from 968 up -- so the room does not come back at a wider viewport.
 * Measured at 1440 with a price range set, which is an ordinary thing to have
 * done before opening this panel: the panel's far edge lands 11px past the
 * card in English and 22px past it in Arabic, and by the same amount at 1024
 * as at 1920. No viewport check catches it -- there is a third of the screen
 * spare on either side.
 *
 * Two columns fit inside the 400px cap: measured scrollHeight is 390, so all
 * seventeen stay reachable without an inner scroller. Taller and narrower,
 * not truncated.
 */
.hz-chip[data-hz-chip="amenities"] .hz-chip__panel {
    min-width: 320px;
}

/*
 * EVERY PANEL OPENS FROM ITS OWN CHIP'S INLINE-START EDGE. Nothing is anchored
 * to the end of a chip, and nothing is anchored to the card.
 *
 * It used to end-anchor the last two, so their panels would not open past the
 * card's far edge. That held with four chips and stopped holding with three:
 * the chips clustered into the first half of the card, so the widest panel
 * anchored to the last of them hung 180px off the card's NEAR edge at 1440 --
 * inside the viewport, so no overflow check caught it, and visibly wrong.
 *
 * THE ROW IS FOUR CHIPS AGAIN, property type having been added at its head, so
 * this was re-measured rather than assumed. Two things had to move, and each
 * is explained where it is made: the amenities panel is two columns at every
 * width now, and the sheet further down takes over at 860 rather than 760.
 *
 * MEASURE WITH THE CHIPS CARRYING SELECTIONS, NOT AT REST. A chip's summary is
 * replaced by what is selected inside it, so a price range widens that chip by
 * about 66px and shoves everything after it along. At rest the row fits at
 * 1440 with 72px to spare; with a range set the same row does not fit at all.
 * The resting numbers are the ones that lie.
 *
 * Arabic is the tighter of the two directions, which is not obvious: its chip
 * labels are shorter at rest but longer once chosen -- "غرفتا نوم فأكثر"
 * against "2+ beds" -- and it is the chosen state that decides this.
 *
 * With two columns the widest panel is 320px. Worst case, selections set,
 * across 968 and up: 185px to spare in English, 161px in Arabic, and those do
 * not vary with the viewport because the card does not either. The tightest
 * width in the range is 861, the first that is not a sheet.
 *
 * If the row changes length again, re-measure, with selections set. Anchoring
 * by position is a guess about where a chip sits, and it only holds while the
 * row's length does.
 */

.hz-chip__set {
    margin: 0;
    padding: 0;
    border: 0;
}

.hz-chip__legend {
    margin: 0 0 10px;
    padding: 0;
    color: #8b929f;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}

.hz-chip[data-hz-chip="amenities"] .hz-chip__set {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 2px 16px;
}

.hz-chip[data-hz-chip="amenities"] .hz-chip__legend {
    grid-column: 1 / -1;
}

/*
 * THE 1340px BREAKPOINT THAT SAT HERE IS GONE, NOT MOVED.
 *
 * It dropped this panel from three columns to two below 1340, which was only
 * worth having while three columns fitted above it. They no longer fit at any
 * width: the card stops growing at 920px from 968 up, so a 500px panel has the
 * same room at 1920 as at 1024, and the property type chip at the head of the
 * row spent it. Two columns are unconditional now and there is nothing left
 * for a width query to switch between.
 */

/*
 * Labels wrap rather than being cut. Two columns in a 320px panel give each
 * label about 132px, and "Underground parking" and "Backup water supply" both
 * need more than that, so nowrap silently truncated them. Widening the panel
 * instead is what the note above rules out: there is no room left to widen it
 * into.
 */
.hz-chip__opt {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 7px 0;
    color: var(--hz-ink);
    font-size: 13.5px;
    font-weight: 500;
    line-height: 1.3;
    cursor: pointer;
}

.hz-chip__opt input {
    flex: 0 0 auto;
    width: 15px;
    height: 15px;
    margin: 0;
    accent-color: var(--hagzi-primary);
    cursor: pointer;
}

/* Homepage Bedrooms and Bathrooms share one pill-selection panel. */
.hz-chip__panel--rooms {
    width: 380px;
    padding: 20px;
}

.hz-chip__rooms-group + .hz-chip__rooms-group {
    margin-top: 28px;
}

.hz-chip__rooms-title {
    margin: 0 0 16px;
    padding: 0;
    color: var(--hz-ink);
    font-size: 18px;
    font-weight: 600;
    line-height: 1.4;
}

.hz-chip__pills {
    display: flex;
    flex-wrap: wrap;
    gap: 10px 8px;
}

.hz-chip__pill {
    position: relative;
    display: inline-flex;
    cursor: pointer;
}

.hz-chip__pill input {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    margin: 0;
    opacity: 0;
    cursor: pointer;
}

.hz-chip__pill span {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 54px;
    min-height: 38px;
    padding: 6px 12px;
    border: 1px solid var(--hz-line);
    border-radius: 999px;
    background: #fff;
    color: var(--hz-ink);
    font-size: 16px;
    font-weight: 400;
    line-height: 1.4;
    transition: color .15s ease, border-color .15s ease, background .15s ease;
}

.hz-chip__pill:hover span {
    border-color: var(--hagzi-primary);
}

.hz-chip__pill input:checked + span {
    border-color: var(--hagzi-primary);
    background: #eef3ff;
    color: var(--hagzi-primary);
}

.hz-chip__pill input:focus-visible + span {
    outline: 2px solid var(--hagzi-primary);
    outline-offset: 3px;
}

.hz-chip__range {
    display: flex;
    align-items: flex-end;
    gap: 10px;
}

.hz-chip__num {
    display: flex;
    flex-direction: column;
    gap: 5px;
    color: #8b929f;
    font-size: 11.5px;
    font-weight: 600;
}

.hz-chip__num input {
    width: 104px;
    padding: 8px 10px;
    border: 1px solid #dde1e9;
    border-radius: 9px;
    color: var(--hz-ink);
    font-family: inherit;
    font-size: 13.5px;
}

.hz-chip__num input:focus-visible {
    border-color: var(--hagzi-primary);
    outline: 2px solid var(--hagzi-primary);
    outline-offset: 0;
}

.hz-chip svg {
    width: 14px;
    height: 14px;
    opacity: 0.75;
}

/*
 * Focus ring overrides: the base ring is white for the header and hero, but the
 * tabs and the search buttons now sit on white, where white is invisible.
 */
.hz-tab__input:focus-visible + .hz-tab__label,
.hz-search__clear:focus-visible,
.hz-search__submit:focus-visible {
    outline-color: var(--hz-ink);
}

/* ------------------------------------------------------- below-hero band ---- */

.hz-band {
    padding: 72px 0 80px;
    background: #fff;
    font-family: Roboto, "Helvetica Neue", Arial, sans-serif;
}

.hz-band__inner {
    max-width: 760px;
    text-align: center;
}

.hz-band__title {
    margin: 0 0 14px;
    color: var(--hz-ink);
    font-size: 30px;
    font-weight: 800;
    letter-spacing: -0.02em;
}

.hz-band__text {
    margin: 0 auto 26px;
    max-width: 60ch;
    color: #5b6270;
    font-size: 16px;
    line-height: 1.65;
}

.hz-band__actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 14px;
}

/*
 * NOTHING RENDERS .hz-band TODAY. No view in the theme emits the class and the
 * homepage returns none of it in either locale; the markup went when the band
 * was reworked and the rules stayed. It is recoloured rather than deleted
 * because removing a block another session may be part-way through reinstating
 * is the more expensive mistake, and because a red button is exactly what
 * should not reappear if the band comes back. White on the primary is the same
 * pairing the Search button already uses.
 */
.hz-band__cta {
    padding: 12px 26px;
    border-radius: 8px;
    background: var(--hagzi-primary);
    color: #fff;
    font-size: 15px;
    font-weight: 700;
    text-decoration: none;
}

.hz-band__cta:hover {
    background: var(--hagzi-primary-dark);
}

.hz-band__link {
    padding: 12px 22px;
    border: 1px solid #d5d9e0;
    border-radius: 8px;
    color: var(--hz-ink);
    font-size: 15px;
    font-weight: 600;
    text-decoration: none;
}

.hz-band__link:hover {
    border-color: var(--hz-ink);
}

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

@media (max-width: 1080px) {
    .hz-header__inner {
        grid-template-columns: auto 1fr auto;
        gap: 16px;
    }

    .hz-nav {
        gap: 20px;
        overflow-x: auto;
        scrollbar-width: none;
    }

    .hz-nav::-webkit-scrollbar {
        display: none;
    }

    .hz-phone span {
        display: none;
    }

    .hz-hero {
        min-height: 500px;
    }

    /* 121px is where the 600px centred hero put the headline at this width, so
       the content holds its position here as well. */
    .hz-hero__content {
        padding-top: 121px;
        padding-bottom: 92px;
    }

    .hz-hero__title {
        font-size: 44px;
    }
}

@media (max-width: 860px) {
    .hz-locale {
        display: none;
    }
}

/*
 * Below this width the centred three-column header cannot hold a full nav row,
 * so the brand and actions share the top line and the nav scrolls underneath.
 */
@media (max-width: 720px) {
    .hz-header__inner {
        grid-template-columns: auto auto;
        justify-content: space-between;
        gap: 10px 16px;
        padding-top: 10px;
        padding-bottom: 4px;
    }

    .hz-brand {
        grid-column: 1;
        grid-row: 1;
    }

    /* The wordmark is baked into the lockup, so the whole mark scales down
       together on narrow screens. At 26px tall it remains compact enough for
       the header action row while keeping the brand readable. */
    .hz-brand__logo {
        height: 26px;
    }

    .hz-actions {
        grid-column: 2;
        grid-row: 1;
        justify-content: flex-end;
    }

    .hz-nav {
        grid-column: 1 / -1;
        grid-row: 2;
        justify-content: flex-start;
        padding-bottom: 8px;
        /* Own row now, so the offset that separated it from the logo on one
           line would only push it out of alignment with the logo above. */
        margin-inline-start: 0;
    }

    /* Row 2 frees up room again, so the number comes back rather than
       leaving a bare handset icon next to the CTA. */
    .hz-phone span {
        display: inline;
    }

    .hz-hero {
        min-height: 470px;
    }

    /* 117px is where the 560px centred hero put the headline. The band under
       the card is 80px here rather than the 96px used on desktop: the card
       fills far more of a phone's hero, so the same band would read as a gap
       rather than as breathing room. */
    .hz-hero__content {
        padding-top: 117px;
        padding-bottom: 80px;
    }

    .hz-hero__title {
        font-size: 33px;
    }

    .hz-hero__subtitle {
        margin-bottom: 20px;
        font-size: 16px;
    }

    .hz-tab__label {
        padding: 9px 17px;
        font-size: 13px;
    }

    /* Tightened with the pills, so the bar still fits a 390px viewport. */
    .hz-tabbar__jump {
        padding-inline: 12px;
        font-size: 13px;
    }

    .hz-card {
        padding: 14px;
        border-radius: 18px;
    }

    .hz-band {
        padding: 52px 0 56px;
    }

    .hz-band__title {
        font-size: 24px;
    }
}

/*
 * Handsets, with the favourite and notification marks now in the action row.
 *
 * Row one is brand + phone + heart + bell + CTA. The 720px block above restores
 * the phone number on the reasoning that row two had freed up space, and that
 * was true when the row held three items; with five it is not. The number is
 * ~85px of the ~312px row, far and away the cheapest thing to give up, so it
 * collapses back to its icon here.
 *
 * The two marks are NOT hidden at any width. They are the most compact items in
 * the row at 30px each, and hiding the thing that was just added in order to
 * keep an 11-digit phone number that also appears in the footer and one tap
 * away on the icon would be the wrong trade. Must come after the 720px block:
 * same specificity, so source order decides.
 *
 * Order of giving way across the whole header, for the record:
 *   1080px  phone number -> icon
 *    860px  locale hides entirely
 *    720px  nav drops to its own row; phone number returns
 *    480px  phone number -> icon again
 *   the heart and bell persist throughout
 */
@media (max-width: 480px) {
    .hz-phone span {
        display: none;
    }

}

/*
 * The chips are the first thing to give up room: they are inert, so scrolling
 * them sideways costs nothing, and it keeps them on one line as in the
 * reference instead of stacking three deep above the fold.
 */
@media (max-width: 620px) {
    .hz-search {
        height: 50px;
        padding: 0 6px;
        padding-inline-start: 13px;
    }

    .hz-search__submit {
        height: 38px;
        padding: 0 16px;
    }

    /*
     * THE ROW NO LONGER SCROLLS SIDEWAYS, AND THAT IS DELIBERATE.
     *
     * It used to be flex-wrap: nowrap with overflow-x: auto and contain: paint,
     * to keep six chips on one line as in the reference. Both of those clip an
     * absolutely positioned child, so every dropdown panel would be cut off at
     * the row's edge -- worst on the right-hand chips, which is exactly where
     * a panel has least room to begin with.
     *
     * Wrapping is affordable now because the six chips are four: two rows on a
     * handset rather than the three-deep stack that made scrolling worth it.
     * And they are controls rather than decoration now, so a chip a visitor
     * has to discover by swiping is a worse trade than a second row.
     */
    .hz-chips {
        flex-wrap: wrap;
    }

    /* Nothing chip-specific left here; the panel treatment moved to its own
       block below, which starts higher up than this one. */
}

/*
 * ONE FULL-WIDTH SHEET UNDER THE CARD, NOT A PANEL HANGING OFF A CHIP.
 *
 * A panel wide enough to be usable is wider than the chip that opens it, so it
 * has to extend past one of that chip's edges, and below this width there is
 * no edge that is safe. Measured with three chips: the amenities chip's right
 * edge sits 327px from the left of the screen at 640 and 700, so even the
 * two-column 320px panel is within a handful of pixels of running off, and
 * narrower still it is hopeless. If the row ever wraps again the problem gets
 * worse rather than better, because then which edge is safe depends on where
 * each chip landed -- right-anchoring threw the amenities panel 150px off the
 * left when it was the first chip on a second row, and left-anchoring does the
 * same to a chip at the end of the first.
 *
 * So below this width the panel takes the card as its containing block and
 * spans it. .hz-chip goes static to hand that role over and .hz-card takes it.
 * Nothing else about the card changes: it has no absolutely positioned
 * children of its own, so becoming a positioning context has no other effect.
 *
 * THIS STARTS AT 860, NOT AT THE 620 THE OTHER HANDSET RULES USE. The two
 * numbers answer different questions and have not been the same since the
 * chips became real controls.
 *
 * It was 760, measured with three chips. Property type makes four, so every
 * chip behind it starts about 141px further along and the panels stop fitting
 * that much sooner. Measured with a price range set, which is the case that
 * decides it: the amenities panel first breaks the card at about 783 in
 * English and about 807 in Arabic. Arabic is the tighter one because its
 * chosen labels are the longer ones -- see the note higher up.
 *
 * 860 clears the worse of the two by about 50px, which is a good deal more
 * price digits than the catalogue's own range needs.
 */
@media (max-width: 860px) {
    .hz-card {
        position: relative;
    }

    .hz-chip {
        position: static;
    }

    .hz-chip__panel,
    .hz-chip[data-hz-chip="amenities"] .hz-chip__panel {
        top: calc(100% + 8px);
        right: 0;
        left: 0;
        min-width: 0;
        /* A sheet under the card can afford to be taller than the cap a
           chip-anchored panel gets, and it should be: at 300px only twelve of
           the seventeen amenities were reachable without working a small inner
           scroller with a fingertip. */
        max-height: 60vh;
    }

    .hz-chip__panel--rooms {
        width: auto;
    }

    /* Three columns do not fit here. Two do. */
    .hz-chip[data-hz-chip="amenities"] .hz-chip__set {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

/* Very narrow handsets: the field alone needs the full row. */
@media (max-width: 360px) {
    .hz-search {
        flex-wrap: wrap;
        height: auto;
        padding: 10px;
        border-radius: 16px;
    }

    .hz-search__input {
        height: 38px;
    }

    /*
     * The field stops being a pill here and becomes a 16px box, and the button
     * stops being a chip inside it and becomes a full-width block along its
     * bottom edge. A pill would then curve harder than the container holding
     * it, which reads as a mistake, so the radius steps down to sit with the
     * field's corners instead.
     */
    .hz-search__submit {
        flex: 1 1 100%;
        height: 44px;
        margin-top: 8px;
        border-radius: 12px;
    }
}

/* ==========================================================================
 * Homepage sections below the hero (property channel)
 *
 * Appended: every rule above this line — footer, header, hero, tabs, search
 * card, chips and their media queries — is untouched.
 *
 * The content these style is hard-coded demo data. See the comment block at the
 * top of resources/themes/property/views/home/index.blade.php.
 * ========================================================================== */

/* Visually hidden but readable: metadata icons are aria-hidden, so the numbers
   need units in text for anyone not looking at the icon. */
.hz-sr {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    border: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
}

.hz-sec {
    padding: 44px 0 0;
    background: #ffffff;
}

.hz-sec--last {
    padding-bottom: 56px;
}

.hz-sec__head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 16px;
    margin-bottom: 18px;
}

.hz-sec__title {
    margin: 0;
    color: var(--hz-ink);
    font-size: 24px;
    font-weight: 700;
    letter-spacing: -0.3px;
}

.hz-sec__title--sm {
    font-size: 17px;
    font-weight: 600;
    letter-spacing: -0.1px;
}

.hz-seeall {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    flex: 0 0 auto;
    color: var(--hz-ink);
    font-size: 12.5px;
    font-weight: 600;
    text-decoration: none;
}

.hz-seeall svg {
    width: 15px;
    height: 15px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.8;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.hz-seeall:hover {
    color: var(--hagzi-primary);
}

/* -------------------------------------------------------------- areas ---- */
/*
 * Browse by Area: photographic cards in a horizontally scrolling row.
 *
 * The row is nothing more than an overflow-x container, so it scrolls with no
 * script at all — trackpad, touch, and tabbing between cards, which pulls the
 * focused one into view. The arrows and dots are BUILT BY SCRIPT (see the
 * template) and are simply absent when script does not run, rather than
 * sitting there looking live and doing nothing. Same principle as the inert
 * city spans in the off-plan grid below.
 */

.hz-areas-section .hz-sec__head {
    align-items: flex-end;
    margin-bottom: 28px;
}

.hz-areas-section .hz-sec__title--sm {
    font-size: 24px;
    font-weight: 700;
    letter-spacing: -0.5px;
}

.hz-areas__subtitle {
    margin: 6px 0 0;
    color: var(--hz-muted);
    font-size: 15px;
    line-height: 1.45;
}

.hz-areas-section .hz-seeall {
    color: var(--hagzi-primary);
    font-size: 14px;
    font-weight: 700;
}

/*
 * The Buy / Rent segmented control that used to sit here has gone, along with
 * .hz-areas__head, .hz-areas__seg and .hz-areas__segbtn.
 *
 * It rendered Buy as an enforced filter state. The cards below it now link to
 * real per-area searches, and those searches return whatever is in the area:
 * Deir Ghbar and Khalda each return a single FOR RENT listing. So the control
 * was not merely inert, it was describing the results wrongly. Marking both
 * halves aria-disabled would have fixed the lie and left two grey words in a
 * grey pill directly under the heading, saying nothing, in the most valuable
 * position in the section. Removing it was the smaller surface.
 *
 * Restoring it is a block of markup plus this block of CSS, once a real
 * listing-type filter exists to hang it on.
 */

.hz-areas__viewport {
    position: relative;
}

.hz-areas__track {
    display: flex;
    gap: 18px;
    margin: 0;
    padding: 0;
    /*
     * Its own scroll context, so however many cards there are they can never
     * push the document sideways. The card focus ring is inset, so nothing is
     * clipped by this either.
     */
    overflow-x: auto;
    scroll-snap-type: x proximity;
    scroll-behavior: smooth;
    scrollbar-width: none;
    list-style: none;
}

.hz-areas__track::-webkit-scrollbar {
    display: none;
}

/*
 * Fixed width, not a grid fraction: the card never grows with the viewport,
 * which is what keeps the photograph's density honest at every width and lets
 * the row show a partial card as a hint that it scrolls.
 */
.hz-areas__track > li {
    flex: 0 0 auto;
    width: 220px;
    scroll-snap-align: start;
}

.hz-area {
    display: flex;
    height: 100%;
    flex-direction: column;
}

.hz-area__media {
    display: block;
    height: 166px;
    flex: 0 0 auto;
    border-radius: 15px;
    overflow: hidden;
    background: #e9ebf0;
}

.hz-area__img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform 0.35s ease;
}

.hz-area:hover .hz-area__img {
    transform: scale(1.045);
}

.hz-area__body {
    display: flex;
    min-height: 118px;
    flex: 1 1 auto;
    flex-direction: column;
    padding: 13px 3px 0;
}

.hz-area__name {
    display: block;
    margin: 0;
    color: var(--hz-ink);
    font-size: 18px;
    font-weight: 700;
    letter-spacing: -0.15px;
    line-height: 1.3;
    text-decoration: none;
}

.hz-area__name:hover {
    color: var(--hagzi-primary);
}

.hz-area__count {
    display: block;
    margin-top: 4px;
    color: var(--hz-muted);
    font-size: 14px;
    line-height: 1.35;
}

.hz-area__actions {
    display: flex;
    align-items: center;
    gap: 16px;
    margin-top: 15px;
}

.hz-area__action {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 5px;
    color: var(--hagzi-primary);
    font-size: 15px;
    font-weight: 700;
    line-height: 1.2;
    text-align: center;
    text-decoration: none;
    transition: color 0.15s ease;
}

.hz-area__action:hover {
    color: var(--hagzi-primary-dark, #0638B0);
}

.hz-area__action svg {
    width: 15px;
    height: 15px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.9;
    stroke-linecap: round;
    stroke-linejoin: round;
}

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

.hz-area__divider {
    width: 1px;
    height: 20px;
    flex: 0 0 auto;
    background: #cfd3dc;
}

.hz-area__media:focus-visible,
.hz-area__name:focus-visible,
.hz-area__action:focus-visible {
    outline: 3px solid var(--hagzi-focus, rgba(82, 50, 137, 0.28));
    outline-offset: 2px;
}

/* ---- script-built controls ------------------------------------------- */

.hz-areas__nav {
    position: absolute;
    top: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    padding: 0;
    border: 1px solid var(--hz-line);
    border-radius: 999px;
    background: #ffffff;
    color: var(--hz-ink);
    box-shadow: 0 4px 14px rgba(6, 10, 18, 0.16);
    transform: translateY(-50%);
    cursor: pointer;
    transition: background-color 0.15s ease;
}

/*
 * Inside the row rather than out in the page margin as the mockup has them.
 * There is no margin to sit in below about 1250px, and anything hanging
 * outside the shell is a horizontal-overflow risk at every narrow width.
 */
.hz-areas__nav--prev {
    inset-inline-start: 8px;
}

.hz-areas__nav--next {
    inset-inline-end: 8px;
}

.hz-areas__nav:hover {
    background: #f3f4f7;
}

.hz-areas__nav svg {
    width: 17px;
    height: 17px;
    fill: none;
    stroke: currentColor;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
}

/*
 * Hidden, not greyed, at the ends. A visible disabled arrow still reads as
 * "this does something"; removing it from the flow and from the tab order
 * says plainly that there is nothing further that way.
 */
.hz-areas__nav[hidden] {
    display: none;
}

.hz-areas__dots {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 4px;
    margin-top: 14px;
}

/*
 * Needed because the display:flex above is an author rule and would otherwise
 * beat the user-agent's [hidden] { display: none }, leaving the dots visible
 * when script hides them.
 */
.hz-areas__dots[hidden] {
    display: none;
}

/* 22px box for a 8px dot: the visual stays small, the touch target does not. */
.hz-areas__dot {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    padding: 0;
    border: 0;
    background: none;
    cursor: pointer;
}

.hz-areas__dot::before {
    content: "";
    display: block;
    width: 8px;
    height: 8px;
    border-radius: 999px;
    background: #d2d6de;
    transition: background-color 0.15s ease;
}

.hz-areas__dot[aria-current="true"]::before {
    background: var(--hagzi-primary);
}

@media (prefers-reduced-motion: reduce) {
    .hz-areas__track {
        scroll-behavior: auto;
    }

    .hz-area,
    .hz-area__img {
        transition: none;
    }

    .hz-area:hover {
        transform: none;
    }

    .hz-area:hover .hz-area__img {
        transform: none;
    }
}

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

/*
 * Four columns, one row. Was three columns holding all six listings in two
 * rows; the page now shows them as three separate one-row sections — featured,
 * for sale, for rent — so the grid is a single row of at most four.
 */
.hz-listings {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 22px;
    margin: 0;
    padding: 0;
    list-style: none;
}

/*
 * Track count follows the item count, because the catalogue holds three sales
 * and three rentals and neither typed row can fill four slots. Four tracks with
 * the last one empty reads as a card that failed to load; three tracks reads as
 * a row of three.
 *
 * The rule is: fill the width down to three, cap below that. At three of four
 * the cards come out 329px against the featured row's 271px, which is wider but
 * still plainly the same card. At two they would be 505px and at one 1032px,
 * which stops looking like the same component, so those two cap their track to
 * the four-column card width and sit left-aligned instead. The calc reproduces
 * that width exactly: the shell minus the three gaps a four-column row has,
 * divided by four, plus the gaps the shorter row keeps.
 *
 * --4 needs no rule; it is the default above.
 */
.hz-listings--3 {
    grid-template-columns: repeat(3, minmax(0, 1fr));
}

.hz-listings--2 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    max-width: calc((100% - 66px) / 2 + 22px);
}

.hz-listings--1 {
    grid-template-columns: minmax(0, 1fr);
    max-width: calc((100% - 66px) / 4);
}

.hz-lcard {
    display: flex;
    flex-direction: column;
    height: 100%;
    border: 1px solid #edeff3;
    border-radius: 12px;
    background: #ffffff;
    overflow: hidden;
    /* Deliberately barely there: the mockup lifts cards off white by a hair. */
    box-shadow: 0 1px 3px rgba(16, 20, 28, 0.05);
    transition: box-shadow 0.15s ease, transform 0.15s ease;
}

.hz-lcard:hover {
    box-shadow: 0 8px 20px rgba(16, 20, 28, 0.1);
    transform: translateY(-2px);
}

.hz-lcard__media {
    position: relative;
    aspect-ratio: 16 / 11;
    /* Holds the crop, now that the photograph is bigger than this box. */
    overflow: hidden;
    background: #eef0f3;
}

/*
 * Absolutely positioned rather than merely sized to 100%, and that matters.
 *
 * With the photograph in normal flow its own intrinsic ratio wins whenever the
 * percentage height cannot resolve, and this box grows to fit it. That is how
 * moving from the 640x427 demo JPEGs to the catalogue's 350x360 renderings
 * silently turned a landscape card into a portrait one — 378px of photograph
 * where the design asks for 254 — and made every card in the row 124px taller
 * without a single line of layout CSS changing.
 *
 * Out of flow, the aspect-ratio above is the only thing that decides the
 * height, whatever dimensions the catalogue serves next.
 */
.hz-lcard__img {
    position: absolute;
    inset: 0;
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* A listing with no photograph says so, in the same words and the same grey as
   the search results card, rather than showing the browser's broken-image mark. */
.hz-lcard__img--none {
    display: grid;
    place-items: center;
    padding: 16px;
    background: #eef0f3;
    color: #6b7280;
    font-size: 13px;
    text-align: center;
}

.hz-lcard__badge {
    position: absolute;
    top: 10px;
    inset-inline-start: 10px;
    padding: 4px 8px;
    border-radius: 4px;
    color: #ffffff;
    font-size: 9.5px;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    line-height: 1.3;
}

.hz-lcard__badge--sale {
    background: #2c7a55;
}

.hz-lcard__badge--rent {
    background: #2560b4;
}

/*
 * Inert by construction, matching the hero filter chips: a span with no click
 * target and no tab stop. Present so the card anatomy reads correctly.
 */
.hz-lcard__fav {
    position: absolute;
    top: 9px;
    inset-inline-end: 9px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 29px;
    height: 29px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.94);
    color: #6a7180;
    box-shadow: 0 1px 4px rgba(16, 20, 28, 0.16);
    cursor: not-allowed;
}

.hz-lcard__fav svg {
    width: 15px;
    height: 15px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.7;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.hz-lcard__body {
    display: flex;
    flex: 1 1 auto;
    flex-direction: column;
    padding: 13px 14px 15px;
}

.hz-lcard__title {
    margin: 0 0 6px;
    font-size: 14px;
    font-weight: 700;
    line-height: 1.35;
}

.hz-lcard__title a {
    color: var(--hz-ink);
    text-decoration: none;
}

.hz-lcard__title a:hover {
    color: var(--hagzi-primary);
}

.hz-lcard__loc {
    display: flex;
    align-items: center;
    gap: 5px;
    margin: 0 0 11px;
    color: #8b929f;
    font-size: 12px;
}

.hz-lcard__loc svg {
    flex: 0 0 auto;
    width: 13px;
    height: 13px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.6;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.hz-lcard__meta {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 13px;
    margin: 0 0 12px;
    padding: 0;
    list-style: none;
}

.hz-lcard__meta li {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    color: #5c6270;
    font-size: 12px;
    white-space: nowrap;
}

.hz-lcard__meta svg {
    flex: 0 0 auto;
    width: 15px;
    height: 15px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.5;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.hz-lcard__price {
    display: flex;
    align-items: baseline;
    gap: 5px;
    /* Pushed to the bottom so prices align across cards of unequal title length. */
    margin: auto 0 0;
}

.hz-lcard__price strong {
    color: var(--hz-ink);
    font-size: 16px;
    font-weight: 700;
    letter-spacing: -0.2px;
}

.hz-lcard__price span {
    color: #8b929f;
    font-size: 11px;
    font-weight: 500;
}

/* --------------------------------------------------------- value props ---- */

.hz-why__head {
    margin-bottom: 16px;
    font-size: 20px;
    font-weight: 700;
}

.hz-why {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 26px;
    margin: 0;
    padding: 22px 0 0;
    border-top: 1px solid var(--hz-line);
    list-style: none;
}

/*
 * Icon beside the label, not above it: that is what the mockup shows, even
 * though the written brief said "above".
 */
.hz-why__item {
    display: flex;
    align-items: flex-start;
    gap: 13px;
}

.hz-why__icon {
    flex: 0 0 auto;
    width: 26px;
    height: 26px;
    margin-top: 1px;
    color: var(--hz-nav);
    fill: none;
    stroke: currentColor;
    stroke-width: 1.4;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.hz-why__title {
    margin: 0 0 4px;
    color: var(--hz-ink);
    font-size: 13.5px;
    font-weight: 700;
}

.hz-why__text {
    margin: 0;
    max-width: 21ch;
    color: #8b929f;
    font-size: 12.5px;
    line-height: 1.55;
}

/*
 * Focus rings for the new controls. The shared ring near the top of this file
 * is white, for the header and the hero; everything in these sections sits on
 * white, so it needs its own.
 */
.hz-seeall:focus-visible,
.hz-lcard__title a:focus-visible,
.hz-areas__nav:focus-visible,
.hz-areas__dot:focus-visible {
    outline: 3px solid var(--hagzi-primary);
    outline-offset: 2px;
    border-radius: 6px;
}

/* ------------------------------------------- responsive (new sections) ---- */

/*
 * Four columns only hold up while the shell is wide. Below that the row steps
 * down 4 -> 3 -> 2 and then becomes a scroller at 720, which keeps the card
 * between roughly 270px and 400px the whole way rather than jumping straight
 * from four columns to two and doubling the card width in one step.
 *
 * These reset the count modifiers as well as the base: a two-card row capped to
 * the four-column width is right at 1440 and far too narrow once the grid
 * itself is down to two tracks. Same specificity as the modifiers, and later in
 * the file, so source order decides.
 */
@media (max-width: 1080px) {
    .hz-listings,
    .hz-listings--1,
    .hz-listings--2,
    .hz-listings--3 {
        grid-template-columns: repeat(3, minmax(0, 1fr));
        max-width: none;
    }

    .hz-listings--1 {
        grid-template-columns: minmax(0, 1fr);
        max-width: calc((100% - 44px) / 3);
    }

    .hz-listings--2 {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        max-width: calc((100% - 44px) / 3 * 2 + 22px);
    }
}

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

    .hz-listings--1 {
        grid-template-columns: minmax(0, 1fr);
        max-width: calc((100% - 22px) / 2);
    }
}

@media (max-width: 720px) {
    /* The row keeps scrolling at every width, so the card only needs to shrink
       enough to keep more than one in view. */
    .hz-areas__track {
        gap: 14px;
    }

    .hz-areas__track > li {
        width: 204px;
    }

    .hz-area__media {
        height: 132px;
    }

    .hz-areas-section .hz-sec__head {
        align-items: flex-start;
        margin-bottom: 20px;
    }

    .hz-areas-section .hz-sec__title--sm {
        font-size: 24px;
    }

    .hz-areas__subtitle {
        margin-top: 4px;
        font-size: 13px;
    }

    .hz-areas-section .hz-seeall {
        padding-top: 4px;
        font-size: 12.5px;
    }

    .hz-sec {
        padding-top: 34px;
    }

    .hz-sec__title {
        font-size: 20px;
    }

    /*
     * Without this the small variant is left on its 17px base while the full
     * size steps down to 20px, so a --sm heading ends up LARGER on a phone
     * than on a desktop and the same size as the section titles it is meant
     * to sit below. The hierarchy inverted. Stepping 17 -> 16 keeps it in
     * proportion with the 24 -> 20 above. .hz-why__head follows and keeps its
     * own 18px, so that heading is unaffected.
     */
    .hz-sec__title--sm {
        font-size: 16px;
    }

    .hz-why__head {
        font-size: 18px;
    }

    /*
     * Cards become a snap-scrolling row. No arrow buttons: moving them needs
     * script, and a decorative arrow that does nothing is worse than none.
     * Bleeds to the viewport edges so the partial card reads as scrollable.
     */
    .hz-listings,
    .hz-listings--1,
    .hz-listings--2,
    .hz-listings--3 {
        display: flex;
        /* Cleared here too: a capped short row would otherwise keep its cap as
           a flex container and squeeze the scroller into part of the width. */
        max-width: none;
        gap: 14px;
        margin-right: -24px;
        margin-left: -24px;
        padding: 4px 24px;
        overflow-x: auto;
        scroll-snap-type: x mandatory;
        scrollbar-width: none;
        /*
         * Required, not cosmetic. Without it Chrome still counts this
         * scroller's 1157px of content toward the document scroll width, even
         * though every ancestor up to <main> measures 390 and overflow-x:hidden
         * does not suppress it. The result was a 962px document at a 390px
         * viewport, which made mobile Chrome shrink-to-fit the whole page.
         * Paint containment stops the overflow escaping; scrolling is
         * unaffected.
         */
        contain: paint;
    }

    .hz-listings::-webkit-scrollbar {
        display: none;
    }

    .hz-listings > li {
        flex: 0 0 78%;
        scroll-snap-align: start;
    }

    .hz-why {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 22px;
    }

    .hz-why__text {
        max-width: none;
    }
}

@media (max-width: 520px) {
    .hz-areas__track {
        gap: 12px;
    }

    .hz-areas__track > li {
        width: 184px;
    }

    .hz-area__name {
        font-size: 15px;
    }

    .hz-area__media {
        height: 120px;
    }

    .hz-area__body {
        min-height: 112px;
        padding: 11px 2px 0;
    }

    .hz-area__actions {
        gap: 12px;
        margin-top: 12px;
    }

    .hz-area__action {
        font-size: 14px;
    }

    .hz-why {
        grid-template-columns: minmax(0, 1fr);
        gap: 18px;
    }
}

/* =========================================================== new projects ===
 *
 * Off-plan project grid. Full-bleed photograph per card with every piece of
 * copy overlaid at the bottom over a scrim, which is what makes this section
 * look different from .hz-lcard above (photo on top, copy on white below).
 *
 * This block is appended after the existing responsive rules on purpose, so
 * its own media queries below can override the shared .hz-sec__title sizes
 * without a specificity bump.
 * ========================================================================= */

.hz-np__title {
    font-size: 28px;
}

.hz-np__sub {
    margin: 7px 0 0;
    color: #6b7280;
    font-size: 14px;
    line-height: 1.5;
}

/*
 * City strip. Wraps rather than scrolls sideways: a horizontal scroller here
 * would put a second overflow container on the page for the sake of four
 * short words, and .hz-listings already showed how easily that leaks into the
 * document scroll width.
 */
.hz-np__tabs {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 26px;
    margin: 18px 0 22px;
    padding: 0;
    border-bottom: 1px solid var(--hz-line);
    list-style: none;
}

.hz-np__tab {
    display: inline-block;
    /* Pulls the 2px indicator down onto the strip's own hairline. */
    margin-bottom: -1px;
    padding: 0 1px 9px;
    border-bottom: 2px solid transparent;
    font-size: 13.5px;
    font-weight: 500;
}

/*
 * The selected city. This is the same device as the tab strip in "Explore
 * more" lower down the page -- a 2px underline plus the accent on the label --
 * and it carried the same stale red for the same reason: both were written
 * against --hz-red and neither was moved when the channel took the purple.
 * They now read the same token, so the two strips cannot drift apart again.
 */
.hz-np__tab--on {
    border-bottom-color: var(--hagzi-primary);
    color: var(--hagzi-primary);
    font-weight: 600;
}

/* Inert, like the hero filter chips: there is no city filter to run yet. */
.hz-np__tab--off {
    color: #9aa1ad;
    cursor: default;
}

.hz-np {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 22px;
    margin: 0;
    padding: 0;
    list-style: none;
}

.hz-np__card {
    position: relative;
    display: flex;
    /* Copy sits on the floor of the card, photo fills whatever is left. */
    flex-direction: column;
    justify-content: flex-end;
    height: 100%;
    /*
     * min-height rather than aspect-ratio: only some cards carry a specs row,
     * so the copy block varies in height, and a fixed ratio would clip it in
     * a narrow column. This lets the card grow past the ratio if it must.
     */
    min-height: 408px;
    padding: 14px;
    border-radius: 12px;
    /* Holds the negative z-index layers below inside this card. */
    isolation: isolate;
    /* Shows through until the lazy photograph arrives; keeps text legible. */
    background: #2a2f38;
    overflow: hidden;
}

/*
 * Photo and scrim ride negative z-indexes instead of the copy riding a
 * positive one, so every text node below stays at auto and no stacking
 * order has to be maintained as the card's contents change.
 */
.hz-np__img {
    position: absolute;
    inset: 0;
    z-index: -2;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/*
 * Stop positions are set from measured contrast, not by eye. With the middle
 * stop at 0.54 the location line on the golden-hour tower photograph came out
 * at 3.1:1 against a (139,131,117) background, below the 4.5:1 that 11.5px
 * text needs. Raising the 58% stop to 0.68 is what clears it; a lighter scrim
 * with more opaque text does not, because the bright photo is the constraint
 * rather than the text alpha.
 */
.hz-np__scrim {
    position: absolute;
    inset: 0;
    z-index: -1;
    background: linear-gradient(
        to bottom,
        rgba(10, 13, 18, 0.46) 0%,
        rgba(10, 13, 18, 0.10) 26%,
        rgba(10, 13, 18, 0.68) 58%,
        rgba(10, 13, 18, 0.94) 100%
    );
}

.hz-np__flags {
    position: absolute;
    top: 12px;
    inset-inline-start: 12px;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 5px;
}

.hz-np__flag,
.hz-np__plan {
    padding: 3px 8px;
    border-radius: 4px;
    background: rgba(12, 16, 22, 0.74);
    color: #ffffff;
    font-size: 10.5px;
    font-weight: 600;
    line-height: 1.55;
    letter-spacing: 0.1px;
}

.hz-np__body {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
}

/*
 * Deliberately a text chip, not an image. These developers are invented for
 * the demo, so there is no logo to show, and a set-in-caps name is honest
 * about that where a fabricated wordmark would not be.
 *
 * A span rather than an anchor since the cards became clickable: there is no
 * developer page, and as an anchor it was a dead spot in the card's hit area.
 * cursor: default so it does not read as a control, matching the locale
 * indicator and the header's favourite and notification marks.
 */
.hz-np__dev {
    display: inline-block;
    cursor: default;
    max-width: 100%;
    margin-bottom: 9px;
    padding: 5px 9px;
    border-radius: 3px;
    background: #ffffff;
    color: #1b1f27;
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: 0.4px;
    text-decoration: none;
    text-transform: uppercase;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.hz-np__name {
    margin: 0;
    font-size: 17px;
    font-weight: 700;
    line-height: 1.25;
    letter-spacing: -0.2px;
}

.hz-np__name a {
    color: #ffffff;
    text-decoration: none;
}

.hz-np__name a:hover {
    text-decoration: underline;
}

/*
 * Whole-card click target.
 *
 * Now that the project pages exist, the name being the only hit area is a
 * 17px line on a 408px card. This stretches the name's own anchor over the
 * card with a transparent ::after, which is the one approach that adds no
 * nested anchor, no second tab stop and no script — worth insisting on here,
 * because anything scripted would be lost to the Vue remount on #app.
 *
 * Only applied via --linked, set in the template when the record has a url. An
 * unconditional rule would turn a url-less card into one big link to '#'.
 *
 * The card is already `position: relative` with `isolation: isolate`, and the
 * photo and scrim ride z-index -2 and -1, so the overlay needs no z-index of
 * its own: as a positioned box it paints above the in-flow copy while staying
 * below nothing that matters.
 *
 * Known trade-off: an overlay like this makes text inside the card hard to
 * select by dragging. Accepted — there is nothing here anyone needs to copy,
 * and the alternative of duplicating the link around the whole card would give
 * screen readers the card's entire contents as one link name.
 */
.hz-np__card--linked .hz-np__name a::after {
    content: '';
    position: absolute;
    inset: 0;
    /* No background: purely a hit area. */
}

/* The affordance has to match the target, or only the name looks clickable. */
.hz-np__card--linked:hover .hz-np__name a {
    text-decoration: underline;
}

/*
 * The one genuinely interactive thing inside the card has to stay above the
 * overlay or the card link would eat it. Positioned with a z-index so it wins
 * against the overlay's painting order regardless of DOM position.
 *
 * .hz-np__dev is deliberately NOT lifted: it is an inert span now, so letting
 * the card link cover it is the point.
 */
.hz-np__card--linked .hz-np__wa {
    position: relative;
    z-index: 1;
}

.hz-np__loc {
    margin: 4px 0 0;
    color: rgba(255, 255, 255, 0.88);
    font-size: 11.5px;
    line-height: 1.4;
}

.hz-np__specs {
    display: flex;
    align-items: center;
    margin: 8px 0 0;
    padding: 0;
    color: rgba(255, 255, 255, 0.9);
    font-size: 11.5px;
    list-style: none;
}

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

.hz-np__specs li + li {
    margin-inline-start: 10px;
    padding-inline-start: 10px;
    border-inline-start: 1px solid rgba(255, 255, 255, 0.34);
}

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

.hz-np__pricelabel {
    margin: 12px 0 0;
    color: rgba(255, 255, 255, 0.86);
    font-size: 10.5px;
}

.hz-np__price {
    display: flex;
    align-items: baseline;
    gap: 5px;
    margin: 2px 0 0;
    color: #ffffff;
    font-size: 20px;
    font-weight: 700;
    letter-spacing: -0.3px;
}

.hz-np__price span {
    font-size: 14px;
    font-weight: 600;
}

.hz-np__plan {
    margin-top: 9px;
}

.hz-np__wa {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    width: 100%;
    margin-top: 12px;
    padding: 9px 12px;
    border-radius: 6px;
    background: #ffffff;
    color: #1b1f27;
    font-size: 12.5px;
    font-weight: 600;
    text-decoration: none;
    transition: background-color 0.15s ease;
}

.hz-np__wa:hover {
    background: #eef0f4;
}

.hz-np__wa svg {
    flex: 0 0 auto;
    width: 16px;
    height: 16px;
}

.hz-np__wa-bubble {
    fill: #25d366;
}

.hz-np__wa-phone {
    fill: #ffffff;
}

/*
 * Everything in this section sits on a dark photo, so the ring is white.
 *
 * .hz-np__dev is no longer listed: it is an inert span with no tabindex, so it
 * cannot take focus and the selector would never match. The ring stays on the
 * name — the card's link — rather than being stretched around the whole card,
 * so a keyboard user sees which card is focused without a 408px outline.
 */
.hz-np__name a:focus-visible,
.hz-np__wa:focus-visible {
    outline: 3px solid #ffffff;
    outline-offset: 2px;
    border-radius: 6px;
}

@media (max-width: 1080px) {
    .hz-np {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@media (max-width: 720px) {
    .hz-np__title {
        font-size: 22px;
    }

    .hz-np__sub {
        font-size: 13.5px;
    }
}

/*
 * Two columns are held all the way down to 620 rather than dropping to one at
 * the usual 720. At 720 a single card would be 672px wide against a 408px
 * floor, a letterbox that crops the photograph hard and strands the copy in
 * one corner. Below 620 two columns would be under 280px each, too narrow for
 * a 20px price and a full-width button, so that is where it stacks.
 */
@media (max-width: 620px) {
    .hz-np {
        grid-template-columns: minmax(0, 1fr);
        gap: 16px;
    }

    .hz-np__card {
        min-height: 400px;
    }
}

/* Let the existing listing-title link open from anywhere on a home listing
   card. The favorite remains a separate control above the link overlay. */
.hz-lcard {
    position: relative;
    isolation: isolate;
}

.hz-lcard__title a::after {
    position: absolute;
    z-index: 1;
    inset: 0;
    border-radius: 12px;
    content: '';
    cursor: pointer;
}

.hz-lcard__fav {
    z-index: 2;
}
