/**
 * @file
 * Slider Grid Component — vertical fade+slide model, masonry-style corner clipping.
 *
 * DESIGN CONTRACT
 * ============================================================================
 * - Shows ONE card at a time. Slide transitions are VERTICAL (drop-in from
 *   above on Next; rise-in from below on Prev).
 * - Height animates between differently-sized cards.
 * - Prev / Next round pill buttons injected at the bottom-left / bottom-right
 *   of the SLIDER (not the individual card). The slider container has
 *   overflow:hidden + border-radius so the buttons' corner-merged corners
 *   get clipped INVISIBLY by the slider's rounded corner — same technique
 *   masonry-drawer-close uses (that's why it looks flush there).
 * - Container carries a soft shadow so the visual weight of the card is
 *   preserved even though card shadows themselves are now clipped.
 * ============================================================================
 *
 * MINIMAL MARKUP
 *
 *   <div class="slider-grid" data-slider-grid>
 *     <div class="slider-grid__slide">…paste any card…</div>
 *     <div class="slider-grid__slide">…paste any card…</div>
 *   </div>
 *
 * The legacy `slider-grid__viewport` / `slider-grid__track` wrappers are
 * still accepted for backward compat — the JS finds slides at any depth.
 *
 * OPTIONAL: `data-next-target="#anchor"` on the wrapper turns the last
 * slide's Next button into a smooth-scroll link to that anchor.
 */

.slider-grid {
  position: relative;
  width: 100%;
  /* Scroll anchor: when slider-grid.js falls back to native
     `scrollIntoView` (Lenis off — reduced-motion users, admin
     toolbar, CDN failures), the browser aligns the slider top to
     viewport-top + this margin. 36 px = a small breathing gap, no
     more. The JS helper uses the matching `{ offset: -36 }` when
     driving Lenis. */
  scroll-margin-top: 36px;
  /* Kill browser scroll-anchoring inside the slider. Without this the
     browser watches the height:… inline style transition (1200 ms)
     that render() applies on every slide change, silently adjusts
     window.scrollY to "compensate" for the height delta, and that
     compensation fights our explicit scrollIntoView() — producing
     the "sometimes it re-aligns, sometimes it doesn't" bug the user
     reported. `overflow-anchor: none` disables the compensation
     inside this subtree so only our scrollIntoView drives scroll. */
  overflow-anchor: none;
  /* The slider stays transparent. The CARD inside each slide is the
     clipping context for the Prev/Next buttons (JS appends them there
     on each render). This keeps the pill buttons' corner-merge cleanly
     hidden inside the card's rounded corner — the masonry pattern. */
  transition: height 1200ms cubic-bezier(0.16, 1, 0.3, 1);
}

/* Buttons anchor to card corners → card needs a positioning context. */
.slider-grid .side-image-card,
.slider-grid .basic-card,
.slider-grid .card {
  position: relative;
}

/* Legacy inner wrappers — kept for backward compat with existing content.
   If present, they're transparent pass-throughs. */
.slider-grid__viewport,
.slider-grid__track {
  position: relative;
  width: 100%;
}

/* Slides are STACKED via absolute positioning. Only `.is-active` is
   visible; the others sit offstage translated 200 px up (or down for
   prev) at 94% scale. The three layered signals — vertical translate,
   scale, opacity — combined with easeOutExpo produce a decisive
   drop-in that clearly reads as "coming from above" or "rising from
   below". translate3d primes the GPU for 60 fps. */
.slider-grid__slide {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  opacity: 0;
  pointer-events: none;
  /* No vertical offset in the CSS resting state — direction is driven
     100 % by inline styles set in JS per-transition. This eliminates
     the "data-direction change re-animates every slide" race that
     produced first-click direction bugs. */
  transform: scale(0.92);
  transition: opacity 1200ms cubic-bezier(0.16, 1, 0.3, 1),
              transform 1200ms cubic-bezier(0.16, 1, 0.3, 1);
  will-change: transform, opacity;
}

.slider-grid__slide.is-active {
  opacity: 1;
  transform: translate3d(0, 0, 0) scale(1);
  pointer-events: auto;
}

/* Prev / Next round-icon buttons — appended INSIDE the active card by
   JS. The card's overflow:hidden + border-radius clips the button's
   corner-merged corner invisibly (masonry pattern). Buttons stay
   visible from the first frame of a transition — they ride with the
   card as it slides in/out. */
.slider-grid__prev,
.slider-grid__next {
  position: absolute;
  bottom: 0;
  z-index: 5;
}

.slider-grid__prev { left: 0; }
.slider-grid__next { right: 0; }

.slider-grid__prev.is-hidden,
.slider-grid__next.is-hidden {
  opacity: 0;
  pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
  .slider-grid,
  .slider-grid__slide {
    transition: none;
  }
}
