/* ============================================================================
   ACT Pools — motion system, preparation styles only.
   Nothing here hides content until JS has confirmed it can animate it: every
   rule is gated behind html.bd-motion-ready, which bd-motion.js sets before it
   prepares anything. If GSAP fails to load the page renders exactly as built.
   ========================================================================= */

/* The sticky header bar slides on transform only. The off-screen start is NOT set
   here: GSAP decomposes a stylesheet translateY(-100%) into pixels and loses the
   percent, so the tween to yPercent:0 became a no-op and the bar popped in. JS
   sets the start in the same task it adds this class, so there is no flash. */
.ap-header{will-change:auto}
.bd-header-fixed{position:fixed!important;top:0;left:0;right:0;width:100%;z-index:9980;will-change:transform}
.bd-header-spacer{display:block;width:100%;height:0}

/* SplitText's mask wrapper needs the overflow clip; the plugin adds the element,
   this makes sure nothing in the kit re-exposes it.

   It also clips at exactly the line box, and Manrope's descenders sit below that: a
   49px heading on a 54px line needs about 64px of content area, so the tails of g, y
   and p were being shaved off.

   overflow-clip-margin is the one way to enlarge the clip region without touching
   layout. Padding plus an equal negative margin looks equivalent but is not: adjacent
   negative margins collapse to the single most negative value instead of summing, so
   every line junction leaked a few pixels and multi-line headings grew by 6-11px.
   The line's from-offset is 125% rather than 100% (bd-motion.js) so it still starts
   clear of the enlarged clip box instead of peeking into it. Browsers without
   overflow-clip-margin simply keep today's tight clip - no breakage. */
html.bd-motion-ready .bd-mask-line-mask,
html.bd-motion-ready .bd-line-mask{display:block;overflow:clip;overflow-clip-margin:.22em}

/* image reveals clip from their own container */
html.bd-motion-ready .bd-img-clip{overflow:hidden}

/* The badge ring spins on a CSS scroll-timeline as a no-JS fallback. Once the motion
   layer is up, GSAP drives it instead - two rotations on one element would fight. */
html.bd-motion-ready .ap-sat-badge svg{animation:none!important}
/* the tilt needs a 3D context on the badge; GSAP writes the perspective itself */
.ap-sat-badge{transform-style:preserve-3d}

/* Process numbers: the pink fill layer sits exactly over the original glyph and is
   cut by a wavy clip-path. Both are the same text in the same box, so they register
   without any font metrics work. Nothing here applies until JS has built the layer. */
.bd-wf{position:relative}
.bd-wf-fill{position:absolute;left:0;top:0;width:100%;height:100%;color:var(--ap-rose,#F14FB2);pointer-events:none;-webkit-clip-path:polygon(0 130%,100% 130%,100% 130%,0 130%);clip-path:polygon(0 130%,100% 130%,100% 130%,0 130%)}

/* ---------------------------------------------------------------- button wave --
   Hover fills the button with its own existing hover colour, rising on a wave rather
   than switching. Nothing about the palette changes: --bd-fillc IS the colour that
   :hover already used, and the instant swap is then suppressed so the fill is what
   you see. This block is the whole configuration - a button with no --bd-fillc gets
   no layer at all, so adding a variant is one line here and nothing in JS.
   All of it is gated on html.bd-btn-wave, which JS only sets when it can actually
   run the effect: never without JS, never under reduced motion, never on touch. */
/* the layer's box is written inline by JS - Gravity Forms' reset for elements inside
   .gform_button beats a single class and pushed it back to position:static */
html.bd-btn-wave .ap-btn .elementor-button,
html.bd-btn-wave .gform_wrapper .gform_footer .gform_button{position:relative;isolation:isolate}

/* fill colour = the colour each variant's :hover already uses */
html.bd-btn-wave .ap-btn-primary .elementor-button{--bd-fillc:var(--ap-rose-h)}
html.bd-btn-wave .ap-btn-line .elementor-button{--bd-fillc:rgba(0,0,0,.05)}
html.bd-btn-wave .ap-btn-line-inv .elementor-button{--bd-fillc:rgba(255,255,255,.12)}
html.bd-btn-wave .ap-bloggrid .elementor-button,
html.bd-btn-wave .ap-galgrid .elementor-button{--bd-fillc:rgba(0,0,0,.05)}
html.bd-btn-wave .ap-quote .gform_wrapper .gform_footer .gform_button{--bd-fillc:#C03F8E}
html.bd-btn-wave .ap-bigform .gform_wrapper .gform_footer .gform_button{--bd-fillc:var(--ap-rose-h)}

/* and the instant swap goes away, back to each variant's resting colour */
html.bd-btn-wave .ap-btn-primary .elementor-button:hover{background:var(--ap-rose)!important}
html.bd-btn-wave .ap-btn-line .elementor-button:hover{background:transparent!important}
html.bd-btn-wave .ap-btn-line-inv .elementor-button:hover{background:transparent!important}
html.bd-btn-wave .ap-bloggrid .elementor-button:hover,
html.bd-btn-wave .ap-galgrid .elementor-button:hover{background:transparent!important}
html.bd-btn-wave .ap-quote .gform_wrapper .gform_footer .gform_button:hover{background:#F14FB2!important}
html.bd-btn-wave .ap-bigform .gform_wrapper .gform_footer .gform_button:hover{background:var(--ap-rose)!important}

/* The white button is the one that cannot be reproduced by painting on top: it sits on
   a dark section and its hover is a translucent white, so 88% white over its own white
   base is just white. It runs in reverse instead - the button takes the hover colour on
   hover exactly as it does today, and the opaque white base drains away upward. Same
   picture, same colour, no approximation. */
html.bd-btn-wave .ap-btn-white .elementor-button{--bd-fillc:#fff;--bd-fill-mode:invert}

/* ------------------------------------------------------------ nav dropdown --
   Elementor's nav menu runs on SmartMenus, which shows and hides the submenu by
   toggling display - nothing you can animate out of, and it will not activate
   programmatically either. So above 1024 (where .ap-nav is the only menu shown) the
   dropdown's position, look and open/close are taken over here and in bd-motion.js.
   SmartMenus keeps its markup and its ARIA; only the visuals are ours.

   All of it hangs off html.bd-nav-gsap, which JS sets when it takes over, so without
   JS SmartMenus behaves exactly as it does today. */
/* The background li is created at every width but only ever styled above 1024, so it is
   held out of the flow below that - otherwise it sits in the flex row as a real list item
   and spends one of the row's 8px gaps. The selector has to out-specify Elementor's own
   `.elementor-nav-menu li` display rule, which a bare `.bd-dd-bg` loses to. */
.ap-nav .elementor-nav-menu .bd-dd-bg{display:none}

@media (min-width:1025px){
  html.bd-nav-gsap .ap-nav .elementor-nav-menu .bd-dd-bg{display:block}
  html.bd-nav-gsap .ap-nav .elementor-nav-menu--main > ul > li.menu-item-has-children{position:relative}

  html.bd-nav-gsap .ap-nav .elementor-nav-menu--main .sub-menu{
    display:block!important;position:absolute!important;top:calc(100% + 10px)!important;
    left:-6px!important;right:auto!important;width:max-content;min-width:216px;
    margin:0!important;padding:8px!important;list-style:none;
    background:#fff;border:1px solid var(--ap-border);border-radius:var(--ap-r-card);
    box-shadow:0 18px 44px rgba(4,5,39,.13);
    opacity:0;visibility:hidden;z-index:60}

  /* bridges the 10px gap: it is inside the submenu, which is inside the li, so crossing
     it never counts as leaving the item and the dropdown cannot flicker shut */
  html.bd-nav-gsap .ap-nav .elementor-nav-menu--main .sub-menu::before{
    content:'';position:absolute;left:0;right:0;top:-12px;height:12px}

  /* Hit-testing is left to visibility, which GSAP animates, rather than to .bd-open,
     which used to be dropped the moment a close began - leaving a fully visible panel
     that the cursor fell straight through. A hidden panel is not hit-testable, so a
     closed one still intercepts nothing. */
  html.bd-nav-gsap .ap-nav .elementor-nav-menu--main .sub-menu > li{display:block;width:100%}

  /* Typography, padding and the hover colours are already configured on the widget
     (17px Nunito Sans, 22/14, #F14FB2 on #FFEBF7) - left alone deliberately. All that
     was missing is a radius so the hover wash is rounded inside a rounded panel, and
     nowrap so items keep to one line now that the panel sizes to its content. */
  html.bd-nav-gsap .ap-nav .elementor-nav-menu--dropdown .elementor-sub-item{
    display:block;border-radius:10px;white-space:nowrap;
    transition:background-color .18s ease,color .18s ease}

  /* The one white box every dropdown borrows. It sits behind the panels in the list's
     own coordinate space and GSAP moves and resizes it between them, so switching menus
     reads as one panel changing shape rather than two panels crossing. Never
     hit-testable: the links above it do all the work. */
  /* Elementor already gives this ul position:relative and z-index:2, which makes it a
     stacking context: the panels' z-index:60 only means anything inside it. So the
     background lives in here too, below them, rather than in the nav outside - out
     there its z-index outranked the whole menu and it painted over every link. */
  html.bd-nav-gsap .ap-nav .elementor-nav-menu--main > ul{position:relative}

  html.bd-nav-gsap .bd-dd-bg{
    position:absolute;left:0;top:0;width:0;height:0;box-sizing:border-box;
    margin:0;padding:0;list-style:none;
    background:#fff;border:1px solid var(--ap-border);border-radius:var(--ap-r-card);
    box-shadow:0 18px 44px rgba(4,5,39,.13);
    pointer-events:none;opacity:0;visibility:hidden;z-index:1;
    will-change:transform,width,height}

  /* with the shared box carrying the surface, the panels hold only their links */
  html.bd-dd-morph .ap-nav .elementor-nav-menu--main .sub-menu{
    background:transparent;border-color:transparent;box-shadow:none}

  /* The header carries overflow:clip. While it is in flow that clips nothing that matters,
     but the sticky state makes it position:fixed with a GSAP transform, and from then on the
     clip swallows the dropdown's hit area: the panel still paints, yet every point down it
     hit-tests to the page behind, so the menu looks open and answers nothing. Measured at
     six depths down the panel - with the clip every one returned the page image, with
     overflow visible every one returned the menu link, and the document gains no horizontal
     overflow either way. It bit after any jump that made the header sticky, which is why
     clicking a button (the quote buttons jumped to #enquire, ~5600px down) or changing a
     filter appeared to break the menu. */
  html.bd-nav-gsap .bd-header-fixed{overflow:visible!important}

  /* the arrow is rotated by GSAP, so nothing here may transition it */
  html.bd-nav-gsap .ap-nav .elementor-nav-menu .sub-arrow{transition:none!important;display:inline-flex;transform-origin:50% 50%}
}

/* The filter bar taking the top slot on Pool Range, Pool Type and Colours.

   Desktop only. Below 1025 the bar wraps to several rows and the off-canvas menu owns the
   top of the screen, so pinning it there would eat most of a phone viewport. z-index sits
   just under the header's 9980, so when both are on screen the header and its dropdowns
   always paint over the bar. The spacer holds the bar's place in the flow so the page does
   not jump the moment it is pinned. */
.bd-bar-spacer{height:0}

@media (min-width:1025px){
  html.bd-motion-ready .bd-bar-fixed{
    position:fixed!important;top:0;left:0;right:0;width:100%;
    z-index:9970;will-change:transform}
}

/* Elementor's own entrance animations are switched off so nothing double-animates */
.elementor-invisible{visibility:visible!important}

@media (prefers-reduced-motion:reduce){
  .bd-header-fixed{transition:none!important}
}
