/* Kingdom Advisors Elementor Widgets — Cascading Slider
   A click-to-open slider (adapted from Osmo's "Cascading Slider"). The open slide widens to reveal
   a glassmorphic content box (title + text) that fades/blurs up; closed slides show only their
   image/video background. Built on GSAP.

   TWO layout modes, chosen at runtime by assets/js/cascading-slider.js:
     • FILL     (desktop, up to 5 slides) — every slide is visible; the open slide takes the Active
                Width and the closed slides split the rest EQUALLY. Root gets .is-fill.
     • CASCADE  (mobile at any count, or more than 5 slides) — a windowed cascade (wide active +
                small neighbour peeks) that loops infinitely. Root gets .is-cascade.
   In both modes every slide has the SAME DOM width (the active width); the JS positions each slide
   with translateX and reveals only its target width with clip-path (--clip). This keeps the motion
   on cheap, GPU-friendly transform/clip-path instead of animating layout width.

   Escapes/fallbacks: with no JS (and, when the widget's Reduced Motion → Layout is "Stacked list", under
   reduced motion) the slides fall back to a simple stacked, content-first list so the titles/text are always
   readable. Since v1.42.0 the reduced-motion DEFAULT is the slider itself with every change instant (the
   engine's instant mode); only the content-box transitions are switched off here (bottom of the file).

   MINIFIER RULE (v1.41.1): every declaration stays on ONE line. WP Rocket's CSS minifier on the Conference
   site corrupted a function call whose comma-separated arguments spanned lines. */

.kaw-casc,
.kaw-casc *,
.kaw-casc *::before,
.kaw-casc *::after {
  box-sizing: border-box;
}

.kaw-casc {
  --kaw-casc-gap: 12px;
  --kaw-casc-active: 60%;   /* open slide width (JS reads this; responsive) */
  --kaw-casc-sibling: 12%;  /* neighbour peek width in CASCADE mode (JS reads this; responsive) */
  /* Preview By — how much width the hovered slide takes from the open one. JS reads this with
     readLen() the same way it reads the two above, so the control can be responsive. Declaring the
     default HERE rather than only in the script means a widget whose slider was cleared falls back to
     the registered default instead of silently losing the preview. */
  --kaw-casc-hover-grow: 20px;
  --kaw-casc-radius: 12px;
  position: relative;
  width: 100%;
}

/* ------------------------------------------------------------------ Viewport / track */
.kaw-casc__viewport {
  position: relative;
  width: 100%;
  height: 560px;            /* Height control (responsive) */
  overflow: hidden;
  /* Contain the slides' inline z-indexes (the JS gives visible slides z-index up to 10) in their
     own stacking context, so the arrows — a later sibling of the viewport — always paint above. */
  isolation: isolate;
}

.kaw-casc__track {
  position: relative;
  width: 100%;
  height: 100%;
}

/* ------------------------------------------------------------------ Slide */
.kaw-casc__slide {
  position: absolute;
  inset: 0 auto auto 0;
  height: 100%;
  color: #fff;
  cursor: pointer;
  will-change: transform, clip-path;
  -webkit-user-select: none;
  user-select: none;
  /* --clip is a px number set by JS; the inset clip hides the sides down to the target width.
     The hover preview also rides on --clip, written by the engine — see assets/js/cascading-slider.js
     and §8c of the rundown for why it belongs there and not in a CSS hover rule. */
  clip-path: inset(0px calc(var(--clip, 0) * 1px) round var(--kaw-casc-radius));
}

.kaw-casc__slide[data-status="active"] {
  cursor: default;
}

/* Focus ring for a slide. Effectively unreachable (slides are tabindex -1 and only mouse-focused, so
   :focus-visible does not match); the element keyboard users actually reach is the ROOT, which gets a ring
   only when Focus Ring Color is set (a {{WRAPPER}} .kaw-casc:focus-visible rule from the control). The
   colour is that control's variable, falling back to the pre-1.42.0 white. */
.kaw-casc__slide:focus-visible {
  outline: 2px solid var(--kaw-casc-focus, #ffffff);
  outline-offset: -4px;
}

/* Clones exist only to make the CASCADE loop seamless; FILL mode shows the real slides only. */
.kaw-casc.is-fill .kaw-casc__slide[data-clone] {
  display: none;
}

.kaw-casc__slide-inner {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
}

/* Background media (image, or self-hosted video over an optional poster <img>).
   FRAMING VARIABLES (v1.42.0) — deliberately NOT declared on .kaw-casc. Style → Media writes them on the
   root, a slide's own Framing writes them on the slide ({{CURRENT_ITEM}}), and a poster's on the slide as
   --kaw-casc-poster-*. The nearest one wins by plain inheritance and each var() below falls back to the
   pre-1.42.0 value, so an untouched widget computes exactly what it did: backdrop #0b1c28, object-fit cover,
   object-position 50% 50%, scale none. Declaring a default on .kaw-casc would sit between the levels and
   break the poster → slide → widget chain. transform-origin only matters once a zoom is set. */
.kaw-casc__bg {
  position: absolute;
  inset: 0;
  z-index: 0;
  background-color: var(--kaw-casc-bg, #0b1c28);
}

.kaw-casc__media {
  position: absolute;
  inset: 0;
  width: 100% !important;
  height: 100% !important;
  max-width: none !important;
  object-fit: var(--kaw-casc-fit, cover);
  object-position: var(--kaw-casc-pos-x, 50%) var(--kaw-casc-pos-y, 50%);
  scale: var(--kaw-casc-zoom, none);
  transform-origin: var(--kaw-casc-pos-x, 50%) var(--kaw-casc-pos-y, 50%);
  pointer-events: none;
  -webkit-user-select: none;
  user-select: none;
}

/* The poster: its own framing first, then the slide's, then the widget's, then the default. */
.kaw-casc__poster {
  object-fit: var(--kaw-casc-poster-fit, var(--kaw-casc-fit, cover));
  object-position: var(--kaw-casc-poster-x, var(--kaw-casc-pos-x, 50%)) var(--kaw-casc-poster-y, var(--kaw-casc-pos-y, 50%));
  scale: var(--kaw-casc-poster-zoom, var(--kaw-casc-zoom, none));
  transform-origin: var(--kaw-casc-poster-x, var(--kaw-casc-pos-x, 50%)) var(--kaw-casc-poster-y, var(--kaw-casc-pos-y, 50%));
}

/* POSTER HAND-OFF. The video sits over its poster (a later sibling) but stays transparent until it has
   ACTUALLY played — the engine adds .has-played on the first real frame, including when that happened before
   the deferred script attached its listeners (it reads paused/readyState on attach). A <video> that has not
   shown a frame yet is not reliably transparent: WebKit can paint it as a black box while it loads (the
   well-known black flash before playback), which would cover the poster.
   TWO RULES, the same declaration. The first holds from the FIRST PAINT whenever scripting is on: the pack's
   script is deferred on the Conference site, `autoplay` is in the markup, and before this rule a Safari visitor
   could see that black box until the engine ran. If the engine never runs at all (the script blocked or
   missing) the poster simply stays, which is the intended "an image if the video doesn't work". prepVideo()
   runs even without GSAP, so the no-GSAP stacked list still hands over. The second, keyed on the engine's init
   flag, covers browsers without the `scripting` media feature (Safari before 17, Chrome before 120, Firefox
   before 113); they keep the pre-init behaviour. A no-JS page is never gated: its video just autoplays. */
@media (scripting: enabled) { .kaw-casc__slide.has-poster .kaw-casc__video:not(.has-played) { opacity: 0; } }
.kaw-casc[data-kaw-casc-init] .kaw-casc__slide.has-poster .kaw-casc__video:not(.has-played) { opacity: 0; }

/* The video cannot play (blocked autoplay / Low Power Mode, an error, a stall past the timeout) or the widget
   shows posters under reduced motion: the engine puts .is-poster on the slide and the poster shows.
   OPACITY, NOT VISIBILITY, on purpose (here and in the gate above): WebKit refuses a muted autoplay whose
   renderer is visibility:hidden (MediaElementSession::autoplayPermitted) but never looks at opacity, so a video
   that stalled and then recovers can still start, and the engine's .has-played then takes the poster away. */
.kaw-casc__slide.is-poster .kaw-casc__video { opacity: 0; }

/* iOS draws a big start-playback glyph over a video it refuses to autoplay. These videos never have controls. */
.kaw-casc__video::-webkit-media-controls-start-playback-button { display: none !important; -webkit-appearance: none; }

/* ------------------------------------------------------------------ Content box (open slide) */
.kaw-casc__content {
  position: absolute;
  inset: auto 0 0 0;    /* anchored to the bottom by default; Content Position can move it */
  z-index: 2;
  display: flex;
  padding: 24px;        /* OUTER padding — space between the content box and the slide edges */
  pointer-events: none;
}

.kaw-casc__content--top    { inset: 0 0 auto 0; align-items: flex-start; }
.kaw-casc__content--middle { inset: 0; align-items: center; }
.kaw-casc__content--bottom { inset: auto 0 0 0; align-items: flex-end; }

.kaw-casc__content-box {
  width: 100%;          /* the box always spans the content area (minus the outer padding) */
  /* A flex column so the Title/Text gap, a Box Min Height, and the Content Distribution
     (top / middle / bottom / space-between) controls all work. */
  display: flex;
  flex-direction: column;
  gap: 8px;             /* Title & Text Gap */
  padding: 24px;        /* INNER padding — space inside the box, around the text */
  border-radius: 12px;
  background-color: rgba(5, 28, 44, 0.35);
  /* The glassmorphism. Users can raise this (Backdrop Blur) or add their own filter blur. */
  -webkit-backdrop-filter: blur(20px);
  backdrop-filter: blur(20px);
  /* Fade / blur up: hidden until the slide is active, then eases in (with a delay). */
  opacity: 0;
  transform: translateY(18px);
  filter: blur(6px);
  transition: opacity 0.4s ease, transform 0.5s cubic-bezier(0.22, 1, 0.36, 1), filter 0.4s ease;
  transition-delay: 0ms;
}

.kaw-casc__slide[data-status="active"] .kaw-casc__content-box {
  opacity: 1;
  transform: translateY(0);
  filter: blur(0);
  transition-delay: 320ms;   /* wait for the slide to finish widening before the box appears */
}

.kaw-casc__title {
  margin: 0;
  font-size: 2rem;
  line-height: 1.1;
  font-weight: 650;
  letter-spacing: -0.01em;
}

.kaw-casc__text {
  margin: 0;            /* spacing from the title is the flex gap on the content box */
  font-size: 1rem;
  line-height: 1.45;
}

.kaw-casc__text :last-child { margin-bottom: 0; }

/* ------------------------------------------------------------------ Arrows
   Each arrow is absolutely positioned in the slider and placed by two orientation choices
   (left/center/right + top/middle/bottom) plus signed px offsets. Orientation anchors the arrow to
   an edge and contributes a centring translate (-50%); the offsets add a px nudge — both are
   composed in one transform so H and V never fight. */
.kaw-casc__arrow {
  position: absolute;
  z-index: 10;
  top: auto; right: auto; bottom: auto; left: auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  padding: 12px;
  border: none;
  border-radius: 8px;
  color: #ffffff;
  background-color: rgba(5, 28, 44, 0.6);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background-color 0.25s ease, color 0.25s ease, border-color 0.25s ease, opacity 0.25s ease;
  transform: translate(calc(var(--kaw-arrow-cx, 0%) + var(--kaw-arrow-x, 0px)), calc(var(--kaw-arrow-cy, 0%) + var(--kaw-arrow-y, 0px)));
}

/* aria-disabled (set by the JS) rather than the disabled property, so keyboard focus is not
   dropped when an arrow reaches an end in the non-looping fill case. */
.kaw-casc__arrow.is-disabled {
  opacity: 0.4;
  cursor: default;
}

.kaw-casc__arrow svg {
  display: block;
  width: 100%;
  height: 100%;
}

/* The icon may be an uploaded SVG (default) or a font icon; size the font icon and flip both. */
.kaw-casc__arrow i {
  font-size: 1.25em;
  line-height: 1;
}

.kaw-casc__arrow--prev svg,
.kaw-casc__arrow--prev i { transform: rotate(180deg); }

/* Screen-reader-only live region: the JS writes the open slide here so navigation is announced. */
.kaw-casc__status {
  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;
}

/* ------------------------------------------------------------------ No-JS / stacked list
   Without the JS engine (root never gets .is-fill/.is-cascade/.is-single) — no JS, GSAP missing, the
   Elementor editor, or reduced motion with Layout = "Stacked list" — show a simple, readable stacked list:
   every slide static and full width, content boxes shown. The 320px card height is also a constant in the
   image `sizes` maths (KAW_Cascading_Slider_Widget::sizes_attr()); change both together. */
.kaw-casc:not(.is-fill):not(.is-cascade):not(.is-single) .kaw-casc__track {
  display: flex;
  flex-direction: column;
  gap: 16px;
  height: auto;
}

.kaw-casc:not(.is-fill):not(.is-cascade):not(.is-single) .kaw-casc__viewport {
  height: auto;
  overflow: visible;
}

.kaw-casc:not(.is-fill):not(.is-cascade):not(.is-single) .kaw-casc__slide {
  position: relative;
  inset: auto;
  width: 100% !important;
  height: 320px;
  clip-path: inset(0 round var(--kaw-casc-radius));
  cursor: default;
}

.kaw-casc:not(.is-fill):not(.is-cascade):not(.is-single) .kaw-casc__content-box {
  opacity: 1;
  transform: none;
  filter: none;
}

.kaw-casc:not(.is-fill):not(.is-cascade):not(.is-single) .kaw-casc__arrow { display: none; }

@media (prefers-reduced-motion: reduce) {
  .kaw-casc__slide,
  .kaw-casc__content-box { transition: none !important; }
  /* "Show the poster" under reduced motion: hide a poster-backed video BEFORE any script runs (the pack's
     script is deferred on the Conference site, and `autoplay` is still in the markup until it does). Here
     visibility IS the point: WebKit will not autoplay a visibility:hidden muted video, so it is not fetched
     and played unseen while the script loads. */
  .kaw-casc[data-reduced-video="poster"] .kaw-casc__slide.has-poster .kaw-casc__video { visibility: hidden; }
}
