const wraps = gsap.utils.toArray('[data-gsap-stack="yes"]');

wraps.forEach((wrap) => {
  const cards = gsap.utils.toArray(
    wrap.querySelectorAll(wrap.dataset.gsapStackSelector || ".card")
  );
  if (!cards.length) return;

  const scrubAnim       = wrap.dataset.gsapStackScrubAnim === "yes";
  const scrubScale      = parseFloat(wrap.dataset.gsapStackScrubScale) || 0.85;
  const translateEnable = wrap.dataset.gsapStackTranslateEnable === "yes";
  const moveX           = parseFloat(wrap.dataset.gsapStackX) || 0;
  const moveY           = parseFloat(wrap.dataset.gsapStackY) || 0;
  const moveZ           = parseFloat(wrap.dataset.gsapStackZ) || 0;
  const brightnessOn    = wrap.dataset.gsapStackPushBrightnessEnable === "yes";
  const brightness      = parseFloat(wrap.dataset.gsapStackPushBrightness) || 1;
  const bgTint          = wrap.dataset.gsapStackScrubBg || "";
  const markers         = wrap.dataset.gsapStackMarkers === "yes";
  const pinStart        = wrap.dataset.gsapStackPinStart || "top top";
  const mobileDisable   = wrap.dataset.gsapStackMobileDisable === "yes";
  const mobileBp        = parseInt(wrap.dataset.gsapStackMobileBp) || 768;
  const ease            = wrap.dataset.gsapStackEase || "power2.out";

  // Parse offset from pinStart e.g. "top top+=80" → sticky top = 80px
  const offsetMatch = pinStart.match(/top\+=(\d+)/);
  const stickyTop   = offsetMatch ? parseInt(offsetMatch[1]) : 0;

  const applyStack = () => {
    // ── Apply sticky CSS via JS so no separate CSS file needed ──
    gsap.set(wrap, { position: "relative" });
    cards.forEach((card, index) => {
      gsap.set(card, {
        position: "sticky",
        top: stickyTop,
        zIndex: index + 1,          // later cards sit on top
      });
    });

    // ── For each card (except last), animate it when the NEXT card overlaps ──
    cards.forEach((card, index) => {
      if (index === cards.length - 1) return; // last card — nothing to push it

      const nextCard = cards[index + 1];

      ScrollTrigger.create({
        trigger: nextCard,          // fires when next card enters viewport
        start: "top bottom",        // next card just enters from bottom
        end: "top top",             // next card reaches sticky position
        scrub: true,                // smooth, tied to scroll position
        markers: markers,
        invalidateOnRefresh: true,
        onUpdate: (self) => {
          const progress = self.progress; // 0 → 1 as next card scrolls up

          const tweenVars = { overwrite: "auto" };
          if (scrubAnim)       tweenVars.scale   = 1 - (1 - scrubScale) * progress;
          if (translateEnable) {
            tweenVars.x = moveX * progress;
            tweenVars.y = moveY * progress;
            tweenVars.z = moveZ * progress;
          }
          if (brightnessOn)    tweenVars.opacity = 1 - (1 - brightness) * progress;

          gsap.set(card, tweenVars);

          // background tint
          if (bgTint) {
            card.style.setProperty("--sits-tint-opacity", progress);
            if (!card.querySelector(".sits-stack-tint")) {
              const tintEl = document.createElement("div");
              tintEl.className = "sits-stack-tint";
              tintEl.style.cssText = `
                position:absolute;inset:0;pointer-events:none;
                background:${bgTint};
                opacity:0;border-radius:inherit;z-index:1;
              `;
              card.style.position = "relative";
              card.appendChild(tintEl);
            }
            const tintEl = card.querySelector(".sits-stack-tint");
            if (tintEl) tintEl.style.opacity = progress;
          }
        },
      });
    });
  };

  const destroyStack = () => {
    // Reset sticky styles when disabled (mobile)
    cards.forEach((card) => {
      gsap.set(card, { clearProps: "position,top,zIndex,scale,x,y,z,opacity" });
      const tint = card.querySelector(".sits-stack-tint");
      if (tint) tint.remove();
    });
  };

  if (mobileDisable) {
    ScrollTrigger.matchMedia({
      [`(min-width: ${mobileBp + 1}px)`]: function () {
        applyStack();
        return destroyStack; // cleanup on breakpoint exit
      },
    });
  } else {
    applyStack();
  }
});