/* =====================================================================
   Elementor Kit — glue layer
   =====================================================================
   style.css is kept as a byte-for-byte copy of the static build's
   stylesheet so the design can be re-synced without a merge. Anything the
   Elementor markup needs on top of it lives here, and this file always
   prints after it.

   Heading styling is not here: it is generated into kit-headings.css from
   style.css by tools/build-heading-mirror.py, so it stays exact.
   ===================================================================== */

/* ---------------------------------------------------------------------
   Elementor wrappers

   Every section in this kit is full-bleed. Elementor puts a
   .elementor-widget-container between the widget and the section element,
   which must not introduce a width of its own.
   --------------------------------------------------------------------- */
.elementor-widget-ek_header > .elementor-widget-container,
.elementor-widget-ek_hero > .elementor-widget-container,
.elementor-widget-ek_help > .elementor-widget-container,
.elementor-widget-ek_explore_pools > .elementor-widget-container,
.elementor-widget-ek_quality > .elementor-widget-container,
.elementor-widget-ek_projects > .elementor-widget-container,
.elementor-widget-ek_about > .elementor-widget-container,
.elementor-widget-ek_news > .elementor-widget-container,
.elementor-widget-ek_cta > .elementor-widget-container {
    width: 100%;
}

/* The editor placeholder never reaches visitors. */
.ek-empty {
    display: none;
}

/* ---------------------------------------------------------------------
   Hero poster frame

   Stands in for the <video> when none is set, and inside the editor
   canvas where an autoplaying loop makes the section hard to work in. It
   takes the same layer and fit as .hero-section video.
   --------------------------------------------------------------------- */
.hero-section .ek-hero-poster {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    position: absolute;
    inset: 0;
    z-index: -1;
}

/* ---------------------------------------------------------------------
   Standalone pool search bar  (widget: ek_pool_search)

   The design only ever places .pool-search-component inside the hero, so
   everything here is about the two assumptions that stop holding once it
   sits on its own: a dark backdrop, and a hero tall enough to host a
   full-screen sheet.
   --------------------------------------------------------------------- */
.ek-search-section {
    position: relative;
}

.ek-search-stretch {
    width: 100%;
}

/* ---- light backdrop ----
   The design's title is rgba(255,255,255,.70), for the dark hero. */
.pool-search-component.ek-search-on-light .ek-card-title {
    color: #101012;
}

.pool-search-component.ek-search-on-light .dropdown-list {
/*    border-bottom-color: rgba(0, 0, 0, 0.12);*/
}

/* ---- toggle anchoring ----
   .filter-toggle is position:absolute in the design, anchored to the hero.
   On a short section that lands inside the bar, so the default here pins it
   to the viewport instead. */
.ek-search-toggle-fixed .filter-toggle {
    position: fixed;
    right: 20px;
    bottom: 20px;
}

/* ---- staying in the flow below 768px ----
   Undoes the fixed full-screen sheet so the bar stacks its rows and remains
   visible. The sheet-only controls go with it.

   The design's sheet rules are `@media (max-width: 991px) .pool-search-component`
   (one class), so a compound selector wins on specificity at any order.

   991px, matching the sheet's own breakpoint — these rules exist to undo it. */
@media (max-width: 991px) {
    .pool-search-component.ek-search-inline {
        display: block;
        position: static;
        inset: auto;
        z-index: auto;
        background: none;
        padding: 0;
        overflow: visible;
        opacity: 1;
        visibility: visible;
        pointer-events: auto;
        transform: none;
    }

    /* Sheet chrome: in the flow there is nothing to close. */
    .pool-search-component.ek-search-inline .filter-close {
        display: none;
    }

    .pool-search-component.ek-search-inline .pool-search-inner {
        flex-direction: column;
        gap: 10px;
    }

    /* ---- dark backdrop, in the flow ----
       Below 768px the design recolours the title and the clear button to #000,
       because at that width they sit on the white sheet. Staying in the flow on
       a dark section they are back on the section's own background, so the
       light treatment has to come back.

       #fff for the clear button rather than the desktop blue: the blue reads on
       the white bar it normally sits inside, and #fff is the design's own answer
       for a clear button on a dark bar (.listing-filter-bar). */
    .pool-search-component.ek-search-inline:not(.ek-search-on-light) .ek-card-title {
        color: rgba(255, 255, 255, 0.70);
    }

    .pool-search-component.ek-search-inline:not(.ek-search-on-light) .clear-filter-btn {
        color: #FFF;
    }

    /* The design already centres and un-borders the clear button and stretches
       View Results at this width — no need to restate either. */
}

/* ---------------------------------------------------------------------
   Custom select  (opt-in via .ek-selects-custom, built by ek-widgets.js)

   Aims to be indistinguishable from the native field it replaces until
   opened: same type metrics, same colours, same active-row inversion. The
   only intentional visual addition is the chevron, which the native
   control used to draw itself.
   --------------------------------------------------------------------- */

/* The panel is positioned against the row, which the design only makes
   relative at 991px and down. align-items is explicit for the same reason the
   trigger sets it: the row's items are a 30px icon and a 26px line of text, and
   the design leaves them on the default `stretch`, which reads as the icon
   sitting low against the label. */
.dropdown-list {
    position: relative;
    align-items: center;
}

/* ---- equal-width fields (.ek-selects-fill) ----
   Left to itself each trigger is as wide as its own longest option, so the
   fields end up different widths and each chevron sits a different distance
   after its label — the gap is widest on the field with the longest option.
   Sharing the bar equally makes the widths uniform and lines the chevrons up. */
.ek-selects-fill .pool-search-inner > .dropdown-list {
    flex: 1 1 0;
    min-width: 0;
    border-radius: 4px;
}

/* The sizers exist only to stop an auto-width trigger reflowing when a value is
   picked. With a flex basis doing that job they would just force a min-content
   width the field cannot shrink below. */
.ek-selects-fill .ek-select-sizer {
    display: none;
}

/* Swapped out only once the enhancement is actually in place, so a JS
   failure leaves a working native field rather than a dead button. */
.dropdown-list.ek-select-ready > .search-dropdown {
    display: none;
}

.ek-select {
    flex: 1 1 auto;
    min-width: 0;
}

.ek-select.is-open {
    z-index: 40;
}

/* ---- trigger ---- */
.ek-select-toggle {
    display: flex;
    align-items: center;
    width: 100%;
    margin: 0;
    padding: 0 20px 0 0;
    border: 0;
    outline: 0;
    background: transparent;
    text-align: left;
    cursor: pointer;

    /* matches `select.search-dropdown` in the design */
    color: rgba(0, 0, 0, 0.80);
    font-size: 15px;
    font-weight: 500;
    line-height: 26px;
}

/* The label shares its grid cell with a hidden copy of every option, so the
   trigger takes the width of the longest one — the intrinsic width a native
   select has, which is what stops the bar reflowing on each choice. */
.ek-select-value {
    display: grid;
    min-width: 0;
}

.ek-select-value > * {
    grid-area: 1 / 1;
}

.ek-select-label {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ek-select-sizer {
    height: 0;
    overflow: hidden;
    visibility: hidden;
    white-space: nowrap;
}

/* The design's own chevron, so the two match. */
.ek-select-toggle::after {
    content: '';
    position: absolute;
    right: 0;
    top: 50%;
    width: 10px;
    height: 10px;
    margin-top: -5px;
    pointer-events: none;
    background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='10' viewBox='0 0 16 10' fill='none'%3E%3Cpath d='M1 1L8 8L15 1' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") no-repeat center / contain;
    transition: transform .25s var(--ease), filter .25s var(--ease);
}

.ek-select.is-open .ek-select-toggle::after {
    transform: rotate(180deg);
}

/* ---- panel ---- */
.ek-select-menu {
    position: absolute;
    top: calc(100% + 8px);
    left: 0;
    min-width: max(100%, var(--ek-menu-min-width, 220px));
    max-height: 260px;
    overflow-y: auto;
    margin: 0;
    padding: 6px 0;
    list-style: none;
    background: #FFF;
    box-shadow: 0 12px 30px rgba(0, 0, 0, 0.18);
    z-index: 40;
}

.ek-select-option {
    padding: 9px 18px;
    color: rgba(0, 0, 0, 0.80);
    font-size: 15px;
    font-weight: 500;
    line-height: 22px;
    white-space: nowrap;
    cursor: pointer;
    transition: background-color .18s var(--ease), color .18s var(--ease);
}

/* One highlight for pointer and keyboard: the script moves .is-current on
   mousemove too, so the two can never disagree. */
.ek-select-option:hover,
.ek-select-option.is-current {
    background: #F2F2F2;
}

.ek-select-option[aria-selected="true"] {
    color: #0078D6;
}

/* ---- states ---- */
.ek-select-toggle:focus-visible {
    outline: 2px solid #0078D6;
    outline-offset: 2px;
}
.dropdown-list:focus .ek-select-toggle,
.dropdown-list.is-active .ek-select-toggle {
    color: #fff;
}
@media (max-width: 991px) {
    /* The sheet's rows restate the field's type, and the row itself draws the
       chevron via .dropdown-list::after — so the trigger drops its own. */
    .ek-select-toggle {
        padding: 22px 34px 22px 26px;
        font-size: 17px;
        font-weight: 500;
        line-height: 1.4;
        color: #000;
        transition: color .25s var(--ease);
    }

    .ek-select-toggle::after {
        display: none;
    }

    /* Active row inverts to black; the label follows the native field's rule. */
    .dropdown-list:focus-within .ek-select-toggle,
    .dropdown-list.is-active .ek-select-toggle {
        color: #fff;
    }

    /* The row is the control at this width — a full-width pill drawing its own
       chevron at its right edge — so the panel spans the row rather than
       starting after the icon. Making .ek-select static hands the menu's
       containing block to .dropdown-list, which the design already positions.

       The menu keeps its own z-index, so it still paints above later rows even
       without a positioned .ek-select to raise. */
    .ek-select {
        position: static;
    }

    .ek-select-menu {
        top: 100%;
        left: 0;
        right: 0;
        min-width: 0;
    }
}

/* ---------------------------------------------------------------------
   Theme button reset, undone
   =====================================================================
   Hello Elementor's reset.css styles bare buttons:

     [type=button]:hover, [type=submit]:hover, button:hover, button:focus {
         background-color: #c36;  color: #fff;
     }

   That selector is (0,1,1). Almost every control in this design is styled
   with a single class — .filter-toggle, .clear-filter-btn, .menu-close —
   which is (0,1,0), so on hover the theme won and the control turned
   crimson. Nothing in the design's own CSS restates a hover background,
   because on a bare page there was nothing to restate it against.

   Each control below therefore repeats its resting background and colour
   for :hover and :focus, at (0,2,1), which beats the theme. The values
   mirror style.css — the render tests assert that a control's hover
   background still equals its resting one, so if the design changes and
   one of these goes stale, that test fails rather than the drift shipping.

   Only the controls that actually lose are listed. .view-results-btn,
   .explore-tab, .round-arrow and .pool-slider's arrows already carry a
   selector strong enough to win on their own.
   --------------------------------------------------------------------- */

/* ---- pool search ---- */

/* (0,1,1) in the design, so it survives `button:hover` on source order but not
   `[type=button]:focus`, which is (0,2,0). The disc stays blue on both states —
   the design's hover effect is the ::before ripple growing over it. */
button.view-results-btn:hover,
button.view-results-btn:focus {
    background-color: #0078D6;
}

button.ek-select-toggle:hover,
button.ek-select-toggle:focus {
    background-color: transparent;
    color: rgba(0, 0, 0, 0.80);
}

button.clear-filter-btn:hover,
button.clear-filter-btn:focus {
    background-color: #FFF;
}

/* ---- header ---- */
button.menu-toggle:hover,
button.menu-toggle:focus,
button.menu-close:hover,
button.menu-close:focus,
button.submenu-toggle:hover,
button.submenu-toggle:focus,
button.mobile-nav-search-btn:hover,
button.mobile-nav-search-btn:focus,
button.header-search-close:hover,
button.header-search-close:focus {
    background-color: transparent;
}

button.menu-close:hover,
button.menu-close:focus {
    color: #fff;
}

button.submenu-toggle:hover,
button.submenu-toggle:focus {
    color: #EEF2F2;
}

button.mobile-nav-search-btn:hover,
button.mobile-nav-search-btn:focus {
    color: #6b7075;
}

button.header-search-close:hover,
button.header-search-close:focus {
    color: #153540;
}

/* ---- listing page ----
   Both of these are <button>, so the theme's rule reaches them where the
   equivalent <a> is untouched.

   .default-btn only renders as a button for a form's submit control. Its
   background is set at (0,1,0) in the design and (0,2,0) by
   `[type=submit]:focus`, so each variant is restated here — including the base,
   since `.default-btn` alone carries the blue. */
button.faq-question:hover,
button.faq-question:focus {
    background-color: transparent;
    color: #101012;
}

button.default-btn:hover,
button.default-btn:focus {
    background-color: #0078D6;
}

button.default-btn.white:hover,
button.default-btn.white:focus {
    background-color: #FFF;
}

button.default-btn.dark:hover,
button.default-btn.dark:focus {
    background-color: #101012;
}

button.default-btn.outline:hover,
button.default-btn.outline:focus {
    background-color: transparent;
}

/* ---- carousels ----
   .carousel-arrow and the injected .help-arrow draw their glyph with
   background-image, so the theme's background-color would sit under it and
   tint the disc. */
button.carousel-arrow:hover,
button.carousel-arrow:focus,
button.help-arrow:hover,
button.help-arrow:focus {
    background-color: #FFF;
}

/* On a light section the trigger's resting colour is the dark title colour. */
.pool-search-component.ek-search-on-light button.ek-select-toggle:hover,
.pool-search-component.ek-search-on-light button.ek-select-toggle:focus {
    color: rgba(0, 0, 0, 0.80);
}

@media (max-width: 991px) {
    /* Both controls are display:none above this width, and the design declares
       their backgrounds inside this query — so the restatement lives here too,
       rather than painting a hover colour onto a hidden element. */
    button.filter-toggle:hover,
    button.filter-toggle:focus {
        background-color: #0078D6;
        color: #fff;
    }

    button.filter-close:hover,
    button.filter-close:focus {
        background-color: #fff;
    }

    /* The sheet's rows restate the field colour, including the inverted
       active row — both have to survive hover too. */
    button.ek-select-toggle:hover,
    button.ek-select-toggle:focus {
        color: #000;
    }

    .dropdown-list:focus-within button.ek-select-toggle,
    .dropdown-list.is-active button.ek-select-toggle,
    .dropdown-list.is-active button.ek-select-toggle:hover,
    .dropdown-list.is-active button.ek-select-toggle:focus {
        color: #fff;
    }

    button.clear-filter-btn:hover,
    button.clear-filter-btn:focus {
        background-color: transparent;
        color: #000;
    }
}

@media (max-width: 991px) {
    .pool-search-component.ek-search-inline:not(.ek-search-on-light) button.clear-filter-btn:hover,
    .pool-search-component.ek-search-inline:not(.ek-search-on-light) button.clear-filter-btn:focus {
        color: #FFF;
    }
}

/* ---------------------------------------------------------------------
   Native select, with the theme's form reset undone

   Hello Elementor's reset.css also styles form fields:

     input[…], select, textarea {
         border: 1px solid #666; border-radius: 3px;
         padding: .5rem 1rem; width: 100%;
     }

   The design overrides `border` on select.search-dropdown but never sets
   `width` or `padding`, because on a bare page it had no reason to — so in
   Native mode the field was squeezed to 100% of its row and indented by
   16px, which truncated the longer placeholders.

   Scoped to 992px and up: below that the design sets width and padding
   itself, deliberately, for the sheet's tall rows.
   --------------------------------------------------------------------- */
@media (min-width: 992px) {
    .pool-search-component select.search-dropdown {
        width: auto;
        padding: 0;
        border-radius: 0;
        background-color: transparent;
    }
}

/* ---------------------------------------------------------------------
   Pool models grid — configurable collapse

   The design collapses with
   `.spa-grid.is-collapsed .spa-card:nth-child(n+7)`, which fixes the count
   at six. nth-child cannot read a custom property, so the widget marks the
   cards past its own threshold in PHP and uses a different class to
   collapse — leaving the design's rule unmatched rather than fighting it.
   --------------------------------------------------------------------- */
.spa-grid.ek-collapsed .spa-card.ek-card-hidden {
    display: none;
}

/* A queried card links to its pool, so the image and the title are wrapped in
   an anchor the static markup never had. The design styles the heading, not a
   link around it, and does not reset anchors globally — so without this the
   title picks up the browser's underline and link colour. */
.spa-card a {
    color: inherit;
    text-decoration: none;
    display: block;
}

.spa-card-body a:hover .ek-card-title {
    text-decoration: underline;
}

/* ---------------------------------------------------------------------
   Listing widgets, in the Elementor canvas
   --------------------------------------------------------------------- */
.elementor-widget-ek_listing_hero > .elementor-widget-container,
.elementor-widget-ek_listing_intro > .elementor-widget-container,
.elementor-widget-ek_pool_grid > .elementor-widget-container,
.elementor-widget-ek_estimator > .elementor-widget-container,
.elementor-widget-ek_faq > .elementor-widget-container,
.elementor-widget-ek_builder_form > .elementor-widget-container {
    width: 100%;
}

/* ---------------------------------------------------------------------
   Single pool page widgets
   --------------------------------------------------------------------- */
.elementor-widget-ek_model_hero > .elementor-widget-container,
.elementor-widget-ek_model_overview > .elementor-widget-container,
.elementor-widget-ek_model_gallery > .elementor-widget-container,
.elementor-widget-ek_finishes > .elementor-widget-container,
.elementor-widget-ek_spacious > .elementor-widget-container,
.elementor-widget-ek_features > .elementor-widget-container,
.elementor-widget-ek_similar_models > .elementor-widget-container {
    width: 100%;
}

/* Queried cards link to their pool, so the image and name sit inside an
   anchor the static markup never had — same reasoning as .spa-card. */
.similar-model-slide a {
    color: inherit;
    text-decoration: none;
    display: block;
}

.similar-model-info a:hover .ek-card-title {
    text-decoration: underline;
}

/* ---------------------------------------------------------------------
   Header buttons

   The design never lets these wrap, but it does not say so — on the static
   page the nav fills the bar and leaves them room. As flex children they
   can shrink below their content width, and with a short menu (or none)
   "Contact Us" breaks across two lines.
   --------------------------------------------------------------------- */
header .nav-right .contact-us,
header .nav-right .find-dealer-btn {
    white-space: nowrap;
}

/* ---------------------------------------------------------------------
   Finishes v2

   Two switches the design has no markup for, plus the wrapper rule.
   --------------------------------------------------------------------- */
.elementor-widget-ek_finishes_v2 > .elementor-widget-container {
    width: 100%;
}

/* The copy column is position:sticky in the design; this releases it. */
.finish-palette-heading.ek-not-sticky {
    position: static;
}

/* The sheen is drawn by .finish-chip-img::after, so switching it off means
   suppressing that pseudo-element rather than removing markup. */
.finish-swatches-grid.ek-no-shine .finish-chip-img::after {
    content: none;
}

/* .finish-chip-color has an aspect-ratio of its own; .finish-chip-img has
   none, so its <img> has no box to fill — `height: 100%` of an auto-height
   parent resolves to auto and the chips end up different sizes. Once a ratio
   is set on the wrapper the image needs to actually cover it. */
.finish-chip .finish-chip-img {
    display: block;
}

.finish-chip .finish-chip-img img {
    display: block;
    height: 100%;
    object-fit: cover;
}

/* ---------------------------------------------------------------------
   Explore tabs — underlined row  (.ek-tabs-underline)

   The design's tabs are pills inside a bordered box, sized for two. With
   four or more they get cramped, so this is the alternative treatment: a
   plain row on a full-width rule, with the active tab marked by a glowing
   gradient underline sitting on that rule.

   Everything is scoped to the modifier, so the pill style is untouched.
   --------------------------------------------------------------------- */
.explore-tabs.ek-tabs-underline {
    width: 100%;
    max-width: max-content;
    margin: 26px auto 0;
    padding: 0;
    border: 0;
    border-bottom: 1px solid rgba(255, 255, 255, 0.14);
    border-radius: 0;
    background: none;
    display: flex;
    justify-content: center;
    gap: 8px;
    flex-wrap: wrap;
}

.ek-tabs-underline .explore-tab {
    flex: 0 1 auto;
    position: relative;
    gap: 10px;
    padding: 14px 26px 16px;
    border-radius: 0;
    background: none;
    color: rgba(255, 255, 255, 0.58);
    white-space: nowrap;
}

/* The faint wash rising off the underline behind the active tab. */
.ek-tabs-underline .explore-tab::before {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(180deg, rgba(56, 194, 237, 0) 30%, rgba(56, 194, 237, 0.16) 100%);
    opacity: 0;
    transition: opacity var(--dur) var(--ease);
    pointer-events: none;
}

/* The underline itself, overlapping the rule so it reads as sitting on it. */
.ek-tabs-underline .explore-tab::after {
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    bottom: -1px;
    height: 2px;
    /* Solid through the middle with quick fades at the ends, so it reads as a
       lit bar rather than a soft smear. */
    background: linear-gradient(90deg,
        rgba(56, 194, 237, 0) 0%,
        #38C2ED 18%,
        #7FE6FF 50%,
        #38C2ED 82%,
        rgba(56, 194, 237, 0) 100%);
    box-shadow: 0 0 10px rgba(56, 194, 237, 0.9), 0 0 22px rgba(56, 194, 237, 0.45);
    opacity: 0;
    transform: scaleX(.6);
    transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease);
}

/* The pill style paints .is-active with a gradient background; here the
   marker is the underline, so that has to be cleared. */
.ek-tabs-underline .explore-tab.is-active {
    background: none;
    color: #FFF;
}

.ek-tabs-underline .explore-tab.is-active::before,
.ek-tabs-underline .explore-tab.is-active::after {
    opacity: 1;
}

.ek-tabs-underline .explore-tab.is-active::after {
    transform: scaleX(1);
}

.ek-tabs-underline .explore-tab:not(.is-active):hover {
    background: none;
    color: rgba(255, 255, 255, 0.85);
}

.ek-tabs-underline .explore-tab:not(.is-active):hover::after {
    opacity: .35;
    transform: scaleX(.85);
}

/* Icons are line art on a dark ground: muted when inactive, full white when
   not. The design's own icons are already white, so only the dimming is new. */
.ek-tabs-underline .explore-tab img {
    opacity: .55;
    transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease);
}

.ek-tabs-underline .explore-tab.is-active img,
.ek-tabs-underline .explore-tab:hover img {
    opacity: 1;
}

@media (max-width: 767px) {
    .explore-tabs.ek-tabs-underline {
        gap: 0;
        justify-content: flex-start;
        overflow-x: auto;
        flex-wrap: nowrap;
        /* The rule should run the full width even when the row scrolls. */
        scrollbar-width: none;
    }

    .explore-tabs.ek-tabs-underline::-webkit-scrollbar {
        display: none;
    }

    .ek-tabs-underline .explore-tab {
        padding: 12px 16px 14px;
        font-size: 14px;
    }
}

/* ---------------------------------------------------------------------
   Hover image  (.ek-has-hover … img.ek-hover-image)

   A second <img> stacked over the first and cross-faded in, rather than
   swapping the src: swapping flashes on the first hover while the second
   file downloads, and leaves nothing to transition between.

   The overlay carries no z-index of its own. Both designs already layer
   something above the photo -- .model-card has z-index: 1, .spa-card-img
   has an ::after gradient -- and an auto z-index keeps the overlay below
   both without touching their positioning.
   --------------------------------------------------------------------- */
.ek-has-hover .ek-hover-image {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
    transition: opacity .45s var(--ease, ease);
    pointer-events: none;
}

/* ---- models grid card ---- */
/* .spa-card-img is already position: relative + overflow: hidden, and
   .spa-card img is object-fit: cover, so the overlay only has to inherit
   the fit. .spa-card:hover .spa-card-img img matches both images, so the
   design's 1.08 zoom drives them together. */
.spa-card.ek-has-hover .ek-hover-image {
    object-fit: cover;
}

.spa-card.ek-has-hover:hover .ek-hover-image,
.spa-card.ek-has-hover:focus-within .ek-hover-image {
    opacity: 1;
}

/* ---- models & spas slide ---- */
/* .pool-slide is position: relative at a fixed 500px, its img object-fit:
   cover at 100% height. */
.pool-slide.ek-has-hover .ek-hover-image {
    object-fit: cover;
}

/* Only the centred slide responds. The side slides are dimmed and partly
   cropped, so a swap there reads as a glitch rather than an affordance. */
.pool-slide.ek-has-hover.slick-center:hover .ek-hover-image,
.pool-slide.ek-has-hover.slick-center:focus-within .ek-hover-image {
    opacity: 1;
}

/* Without Slick there is no .slick-center -- the editor canvas and the
   unenhanced fallback -- so let any slide respond. */
.pool-slider:not(.slick-initialized) .pool-slide.ek-has-hover:hover .ek-hover-image {
    opacity: 1;
}

/* An anchor wrapping both images has to become the positioning context and
   fill the slot, or the overlay would size to the link's text box. */
.spa-card.ek-has-hover .spa-card-img > a,
.pool-slide.ek-has-hover > a {
    display: block;
    position: relative;
    height: 100%;
}

@media (prefers-reduced-motion: reduce) {
    .ek-has-hover .ek-hover-image {
        transition: none;
    }
}

/* ---------------------------------------------------------------------
   Elementor's inline font icons

   Elementor renders an ICONS control as `<svg class="e-font-icon-svg">`,
   not as the `<i>` the design's markup used. Its own stylesheet sizes
   those SVGs in exactly one place —

       .elementor-button-icon .e-font-icon-svg { height: 1em }

   — scoped to its Button widget. Everywhere else a bare inline SVG with a
   viewBox and no width/height attributes has no intrinsic size, so every
   icon this kit renders through Icons_Manager collapsed to 0x0: the light
   header's Contact Us, Find a Dealer, search and close icons, the mobile
   nav's search and close, and the filter bar's Clear all filter.

   The design styles those as `.clear-filter-btn i { font-size: 16px }` and
   friends, which an <svg> never matches — so nothing was left to size them.

   `height: 1em` with an auto width is the faithful mirror -- font-size
   already inherits correctly at each site, and letting the viewBox set the
   width keeps a narrow glyph like fa-mobile-alt (320x512) at its own
   proportions instead of padding it out to a square.

   `display: inline-block` is what makes that work. A viewBox gives the SVG
   an intrinsic aspect ratio, but Chrome resolves `width: auto` to zero on an
   `display: inline` replaced element with no width attribute -- so the icons
   whose parents are not flex containers (the mobile nav's, the search
   overlay's) measured 0x0 until they were blockified. The ones inside a flex
   parent were blockified by it and worked by accident.

   `fill: currentColor` restores what an icon font got from `color` for free.

   Scoped to this kit's own blocks, so Elementor's widgets keep sizing
   their own icons.
   --------------------------------------------------------------------- */
.ek-header svg.e-font-icon-svg,
.pool-search-component svg.e-font-icon-svg,
.listing-filter-bar svg.e-font-icon-svg,
.filter-toggle svg.e-font-icon-svg,
.post-share svg.e-font-icon-svg,
.default-btn svg.e-font-icon-svg {
    display: inline-block;
    height: 1em;
    width: auto;
    fill: currentColor;
    flex: 0 0 auto;
}

/* ---------------------------------------------------------------------
   A .default-btn that is a <button>

   The design only ever draws these as links, so .default-btn declares no
   border. The theme's reset does, for every button on the site:

       [type=submit], button { border: 1px solid #c36 }

   A submit button therefore paints a crimson hairline around the design's
   fill. It shows on any form the kit renders — the Find a Builder panel as
   well as the inquiry form.

   .outline is the one variant that means to have a border, so it keeps it.
   --------------------------------------------------------------------- */
button.default-btn:not(.outline),
[type="submit"].default-btn:not(.outline) {
    border: 0;
}

/* The two places the design sets an explicit icon size rather than letting
   it inherit from the control. Restated for the SVG so the glyph lands at
   the size the comp draws it. */
.clear-filter-btn svg.e-font-icon-svg {
    font-size: 16px;
    line-height: 1;
}

.find-dealer-btn svg.e-font-icon-svg {
    font-size: 14px;
}

/* ---------------------------------------------------------------------
   Linking a pool slide to its page

   The design's slide is a static <div>, so nothing here fought a link
   until the query-driven slider started wrapping the image in one. That
   anchor was in the markup but could never be clicked: `.pool-slide::after`
   is a full-bleed gradient at `inset: 0` with the default
   `pointer-events: auto`, painted after the image, so it took every click
   on the slide. The link looked right in the HTML and did nothing.

   The gradient is decoration and has no reason to be a hit target. Making
   it transparent to the pointer lets clicks fall through to the anchor
   underneath, without touching stacking order or the design's own z-index
   on .model-card (which already sits above the gradient at z-index: 1, and
   is how the caption's own link is reachable).

   The models grid has the same shape: .spa-card-img::after is another
   full-size gradient, and a hit test on a card's photo landed on the gradient
   rather than the anchor. The card title was clickable because it sits in
   .spa-card-body, outside that box -- which is why the cards looked linked.

   .similar-model-slide is the third: the design makes that element itself an
   <a>, so its identical ::after belonged to the link and never blocked it --
   but this widget renders the slide as a <div> with anchors inside (so the
   photo and the name can link separately, as the grid does), which puts the
   gradient back on top of them.
   --------------------------------------------------------------------- */
.pool-slide::after,
.spa-card-img::after,
.similar-model-slide::after {
    pointer-events: none;
}

/* The design styles the slide's heading, not a link around one, and does not
   reset anchors globally — so without this the linked title picks up the
   browser's underline and link colour. Same treatment as .spa-card a. */
.pool-slide a {
    color: inherit;
    text-decoration: none;
}

/* ---------------------------------------------------------------------
   No results

   Shown when a filter or a search narrows a grid to nothing. The shared
   render_empty_notice() helper is editor-only, which is right for a widget
   nobody has configured yet — but "no pools match" is a state a visitor
   reaches the moment they use the filter bar, and silence there reads as a
   broken page rather than an answer.

   Used by both the pool grid and the blog grid; both sit on a dark ground.
   --------------------------------------------------------------------- */
.ek-no-results {
    color: rgba(255, 255, 255, 0.70);
    font-size: 18px;
    line-height: 28px;
    text-align: center;
    margin: 0;
    padding: 60px 0;
}

/* ---------------------------------------------------------------------
   FAQ question wrapping

   The active theme's reset sets `white-space: nowrap` on every bare
   <button>. .faq-question is a button holding a full sentence, laid out as
   `display: flex; justify-content: space-between` with the toggle icon at
   the far end — so with nowrap the question cannot break, the flex line
   overflows, and the icon is pushed outside the button. On a 390px screen
   the longest question shoved it 57px past the viewport and gave the page a
   horizontal scrollbar.

   The design never had to defend against this: the static build does not
   load the theme's reset. Same root cause as the crimson button hovers.
   --------------------------------------------------------------------- */
.faq-question {
    white-space: normal;
}

/* ---------------------------------------------------------------------
   Live filtering

   While a filter request is in flight the grid dims rather than emptying,
   so the layout does not collapse and jump back — and the pointer is
   blocked so a second submit cannot race the first.
   --------------------------------------------------------------------- */
.spa-collection.ek-filtering .spa-grid {
    opacity: .45;
    transition: opacity var(--dur, .3s) var(--ease, ease);
    pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
    .spa-collection.ek-filtering .spa-grid {
        transition: none;
    }
}


/* ---------------------------------------------------------------------
   Listing hero — optional eyebrow and light-blue accent

   Both opt-in, so the existing listing heroes are unchanged: the eyebrow
   only renders when the field is filled, and the accent only applies to a
   `<span class="italic teal">` typed into the headline. The kit's orange
   eyebrow is too loud over a night photo, so this one is white.
   --------------------------------------------------------------------- */
.listing-hero-inner .listing-hero-eyebrow {
    color: rgba(255, 255, 255, 0.85);
    font-size: 13px;
    letter-spacing: 3px;
    text-transform: uppercase;
    max-width: none;
    margin: 0 0 18px;
}

.listing-hero-inner .ek-h1 .italic.teal {
    color: #71D8F0;
}
