/* cards-slider — adjusts Splide's defaults to match the menutech card aesthetic. */

.cards-slider {
  /* Prevent the slider track from growing past its parent — without this,
     Splide measures the intrinsic content (1920px image) and lets the
     track and slides expand beyond the .field--name-field-cards-slider-
     item container. */
  max-width: 100%;
  overflow: hidden;
  /* Establish a block-formatting context with a definite width so children
     (track / list / slides) resolve percentage widths against this root,
     not against an intrinsic-content sized ancestor. */
  width: 100%;
  box-sizing: border-box;
}

/* Stop the features-page right-hand column (`.field--name-field-cards-
   slider-item`) from being shrunk below its legacy `width: 50%` basis by
   the flex parent. Legacy markup wrapped slides in `.field--items >
   .field--item` whose intrinsic min-content reserved the column at 50%;
   the new SDC replaces those wrappers with `.cards-slider > .splide__
   track > .splide__list > .splide__slide`, all clamped to `width: 100%`
   with no intrinsic min-width. Without a counterweight the left column's
   text content pushes the right column down to ~25% width on local.
   Pinning the right column with `flex: 0 0 auto` restores the prod-style
   ~50/50 split. The :has() guard scopes this to the cards-slider markup
   so other field--items uses are unaffected. */
.paragraph--type--cards-slider
  > .field--name-field-cards-slider-item:has(.cards-slider) {
  flex: 0 0 auto;
}

/* The track is the overflow boundary. Constrain it explicitly so Splide's
   inline padding-left/right (set on the track) cannot push the track
   wider than its parent. */
.cards-slider .splide__track {
  width: 100% !important;
  max-width: 100%;
  box-sizing: border-box;
  overflow: hidden;
}

/* The list is the horizontally-translated flex strip of slides. Before
   Splide mounts (and on instances where Splide JS fails to run), the
   list collapses to its content width — letting each flex-shrink:0 slide
   take its intrinsic image width (1920px) and burst the visible area.
   Force-clamp the list to the track width so the slides have a percentage
   reference of the track, not of their content. */
.cards-slider .splide__list {
  width: 100% !important;
  max-width: 100%;
  box-sizing: border-box;
}

.cards-slider .splide__slide {
  height: auto;
  /* Clamp every slide to the list width. Splide will overwrite this with
     its computed pixel width once mounted, but on initial paint (or if
     mount fails) the slide cannot exceed its parent. */
  width: 100%;
  max-width: 100%;
  box-sizing: border-box;
}

/* Constrain raw imagery inside slides — content that bypasses an image
   style (e.g. field_swiper_block paragraphs) otherwise overflows the
   slider on its intrinsic width. Force aspect-preserving sizing and
   neutralise the global `body .region-content img { object-fit: cover }`
   rule from legacy.css which (combined with Splide's equal-height slide
   layout) was stretching the image vertically and cropping out everything
   but the left edge. */
.cards-slider .splide__slide img,
/* Match legacy specificity so the scoped >=1400px height:381px rule
   on .paragraph--type--cards-slider-item img is reliably beaten too. */
.cards-slider .splide__slide .paragraph--type--cards-slider-item img {
  max-width: 100% !important;
  width: 100% !important;
  height: auto !important;
  max-height: none !important;
  object-fit: contain !important;
  display: block !important;
}

/* Cap the inner list height — Splide's flex list otherwise stretches
   every slide to the tallest one's content, which collides with the
   legacy .field--name-field-cards-slider-item { height: 100% } rule and
   blows the slide up to the full vertical paragraph height. */
.cards-slider .splide__track,
.cards-slider .splide__list {
  height: auto !important;
}


.cards-slider .splide__pagination__page.is-active {
  background-color: var(--color-brand);
}

.cards-slider .splide__arrow {
  background-color: var(--color-brand);
  opacity: 1;
}

.cards-slider .splide__arrow svg {
  fill: var(--color-white);
}

/* ---------------------------------------------------------------------------
   Stacked-cards effect — opted into by data-stack="true" on the .cards-slider
   root, currently set only by the features-page field--field-cards-slider-item
   template. Re-creates the legacy menutech_swiper "cards" effect: the active
   slide is in front at full size, with 2–3 previous slides fanned out behind
   it to the LEFT at progressively smaller scale + lower opacity. Slides that
   come AFTER the active one stay hidden. JS writes data-stack-pos on each
   original slide (signed shortest-path distance from the active index, loop
   wrap-around aware); CSS handles the visual.
   --------------------------------------------------------------------------- */

/* Allow the previous cards to peek out beyond the track. The non-stack
   default keeps overflow:hidden so the gallery view's multi-slide layout
   continues to clip cleanly. */
.cards-slider[data-stack="true"],
.cards-slider[data-stack="true"] .splide__track {
  overflow: visible;
}

/* Stack all slides on top of each other so per-slide transforms produce the
   fanned-deck visual. Splide writes inline `width` on each slide once mounted;
   absolute positioning means it lays them all at the same origin and the
   transform places them. */
.cards-slider[data-stack="true"] .splide__list {
  position: relative;
  display: block;
  /* Cancel Splide's translate-x on the list — slide motion is handled by
     per-slide transforms. */
  transform: none !important;
}

.cards-slider[data-stack="true"] .splide__slide {
  position: absolute;
  inset: 0 auto auto 0;
  width: 100% !important;
  margin: 0 !important;
  transition:
    transform 0.45s cubic-bezier(0.4, 0, 0.2, 1),
    opacity 0.45s cubic-bezier(0.4, 0, 0.2, 1),
    filter 0.45s cubic-bezier(0.4, 0, 0.2, 1);
  will-change: transform, opacity, filter;
}

/* Active — front, full size. The list collapses to 0 height once children
   are absolutely positioned; switching the active slide back to position:
   relative reserves the parent's height from its content. The grab cursor
   advertises the drag affordance. */
.cards-slider[data-stack="true"] .splide__slide[data-stack-pos="0"] {
  position: relative;
  transform: translateX(0) translateY(0) scale(1);
  z-index: 10;
  opacity: 1;
  cursor: grab;
}

.cards-slider[data-stack="true"] .splide__slide[data-stack-pos="0"]:active {
  cursor: grabbing;
}

/* Previous cards — tight Rolodex behind the active, darkened so the
   active card reads as the foreground focus. The legacy Swiper "cards"
   effect kept the paragraph at opacity:1 (white bg, shadow, rounded
   corners) and overlaid a dark shadow div for depth. We achieve the
   same effect with filter:brightness() so the card stays fully opaque
   (preserving the legacy .paragraph--type--cards-slider-item appearance)
   but renders progressively darker the further back in the stack. */
.cards-slider[data-stack="true"] .splide__slide[data-stack-pos="-1"] {
  transform: translateX(-18px) translateY(6px) scale(0.97);
  z-index: 9;
  filter: brightness(0.92);
}
.cards-slider[data-stack="true"] .splide__slide[data-stack-pos="-2"] {
  transform: translateX(-34px) translateY(12px) scale(0.94);
  z-index: 8;
  filter: brightness(0.84);
}
.cards-slider[data-stack="true"] .splide__slide[data-stack-pos="-3"] {
  transform: translateX(-48px) translateY(18px) scale(0.91);
  z-index: 7;
  filter: brightness(0.76);
}

/* Slides farther back than -3 stay hidden (rare with 5-ish slides but the
   loop-wraparound math can briefly put a slide there). */
.cards-slider[data-stack="true"] .splide__slide[data-stack-pos="-4"],
.cards-slider[data-stack="true"] .splide__slide[data-stack-pos="-5"],
.cards-slider[data-stack="true"] .splide__slide[data-stack-pos="-6"] {
  opacity: 0;
  pointer-events: none;
  z-index: 1;
}

/* Next cards — mirror of the prev stack, peeking out behind to the RIGHT.
   Production shows previous AND next cards stacked symmetrically around
   the active one; transitioning a next card into pos 0 slides it LEFT
   (translateX +18 → 0) while the old active slides into pos -1
   (translateX 0 → -18). */
.cards-slider[data-stack="true"] .splide__slide[data-stack-pos="1"] {
  transform: translateX(18px) translateY(6px) scale(0.97);
  z-index: 9;
  filter: brightness(0.92);
}
.cards-slider[data-stack="true"] .splide__slide[data-stack-pos="2"] {
  transform: translateX(34px) translateY(12px) scale(0.94);
  z-index: 8;
  filter: brightness(0.84);
}
.cards-slider[data-stack="true"] .splide__slide[data-stack-pos="3"] {
  transform: translateX(48px) translateY(18px) scale(0.91);
  z-index: 7;
  filter: brightness(0.76);
}

/* Anything farther forward in the loop wrap stays hidden. */
.cards-slider[data-stack="true"] .splide__slide[data-stack-pos="4"],
.cards-slider[data-stack="true"] .splide__slide[data-stack-pos="5"],
.cards-slider[data-stack="true"] .splide__slide[data-stack-pos="6"] {
  opacity: 0;
  pointer-events: none;
  z-index: 1;
}

/* Splide-generated clones (loop type) are not in the original slide list;
   the sentinel value "9" is written on them by JS so they stay hidden. */
.cards-slider[data-stack="true"] .splide__slide[data-stack-pos="9"],
.cards-slider[data-stack="true"] .splide__slide.splide__slide--clone {
  opacity: 0 !important;
  pointer-events: none;
  z-index: 0;
}

/* Until JS writes data-stack-pos (brief pre-mount paint), keep the first
   slide visible in normal flow so the list reserves height, and hide the
   rest so they don't all paint at full opacity stacked at origin. Once JS
   tags slides with data-stack-pos, the keyed rules above take over.

   The `:not(.splide__slide--clone)` guard is critical: after Splide mounts,
   head clones become the actual first-child of .splide__list. Without the
   guard, a head clone that hadn't been tagged with data-stack-pos would
   match `:first-child:not([data-stack-pos])` and gain `position: relative`,
   stacking vertically alongside the active card and pushing the deck out
   of alignment. With the guard, the rule only matches actual originals,
   so we're protected even if JS misses tagging a clone. */
.cards-slider[data-stack="true"] .splide__list > .splide__slide:not(.splide__slide--clone):not([data-stack-pos]):first-child {
  position: relative;
}
.cards-slider[data-stack="true"] .splide__list > .splide__slide:not([data-stack-pos]):not(:first-child) {
  opacity: 0;
}
