<!– ============================================================
PASTE INTO: Elementor → Custom Code → Body End
Only handles scroll pinning — Elementor controls all card styles
============================================================ –>
<style>
/* Only what’s needed to make pinning work cleanly */
.parents-container {
overflow: hidden !important;
transition: none !important;
}
.parents-container .swiper-wrapper {
will-change: transform;
transition: none !important;
}
</style>
<link rel=”stylesheet” href=”https://unpkg.com/[email protected]/dist/lenis.css” />
<script src=”https://unpkg.com/[email protected]/dist/lenis.min.js”></script>
<script src=”https://cdn.jsdelivr.net/npm/[email protected]/dist/gsap.min.js”></script>
<script src=”https://cdn.jsdelivr.net/npm/[email protected]/dist/ScrollTrigger.min.js”></script>
<script>
(function () {
“use strict”;
var SECTION = “.parents-container”;
window.addEventListener(“load”, function () {
setTimeout(init, 800);
});
/* ── Lenis (desktop only) ── */
var lenis;
function startLenis() {
if (window.innerWidth <= 1024 || lenis || typeof Lenis === “undefined”) return;
lenis = new Lenis({ duration: 1.4 });
(function raf(t) { lenis.raf(t); requestAnimationFrame(raf); })(0);
ScrollTrigger.scrollerProxy(document.documentElement, {
scrollTop: function (v) {
if (arguments.length) lenis.scrollTo(v, { immediate: true });
return window.scrollY;
},
getBoundingClientRect: function () {
return { top: 0, left: 0, width: window.innerWidth, height: window.innerHeight };
},
fixedMarkers: true
});
lenis.on(“scroll”, ScrollTrigger.update);
}
/* ── Main init ── */
function init() {
gsap.registerPlugin(ScrollTrigger);
var section = document.querySelector(SECTION);
if (!section) {
console.error(“[HScroll] ❌ .parents-container not found”);
return;
}
/* Find the swiper wrapper — Elementor Carousel renders it */
var wrapper = section.querySelector(“.swiper-wrapper”);
if (!wrapper) {
console.error(“[HScroll] ❌ .swiper-wrapper not found”);
return;
}
var slides = wrapper.querySelectorAll(“.swiper-slide”);
console.log(“[HScroll] Found”, slides.length, “slides”);
console.log(“[HScroll] wrapper.scrollWidth:”, wrapper.scrollWidth);
/* ── Disable Swiper touch/drag — GSAP scroll takes over ── */
var swiperEl = section.querySelector(“.swiper”);
if (swiperEl && swiperEl.swiper) {
swiperEl.swiper.allowTouchMove = false;
swiperEl.swiper.allowSlideNext = false;
swiperEl.swiper.allowSlidePrev = false;
console.log(“[HScroll] Swiper touch disabled ✓”);
}
startLenis();
if (window.matchMedia(“(max-width: 1024px)”).matches) {
ScrollTrigger.normalizeScroll(true);
}
buildScroll(section, wrapper);
}
/* ── Measure real overflow from DOM ── */
function measure(section, wrapper, extra) {
extra = extra || 0;
var saved = wrapper.style.transform;
wrapper.style.transform = “translate3d(0px,0px,0px)”;
var sRect = section.getBoundingClientRect();
var lastEl = wrapper.lastElementChild;
var lastRect = lastEl.getBoundingClientRect();
var padR = parseFloat(getComputedStyle(section).paddingRight) || 0;
var overflow = lastRect.right – (sRect.right – padR);
var result = Math.max(0, Math.ceil(overflow) + extra);
wrapper.style.transform = saved;
console.log(“[HScroll] Measured overflow:”, result, “px”);
return result;
}
/* ── Build ScrollTrigger ── */
function buildScroll(section, wrapper) {
var tl;
var mm = gsap.matchMedia();
function make(extra) {
ScrollTrigger.getAll().forEach(function (st) {
if (st.vars && st.vars.trigger === section) st.kill();
});
gsap.set(wrapper, { x: 0 });
var endLen = measure(section, wrapper, extra);
if (endLen <= 0) {
console.warn(“[HScroll] ⚠️ endLen is 0 — retrying in 600ms”);
setTimeout(function () { buildScroll(section, wrapper); }, 600);
return;
}
tl = gsap.timeline({
scrollTrigger: {
trigger: section,
start: “top top”,
end: “+=” + endLen,
scrub: true,
pin: true,
pinSpacing: true,
pinType: window.matchMedia(“(max-width: 767px)”).matches
? “transform”
: “fixed”,
anticipatePin: 1,
fastScrollEnd: true,
invalidateOnRefresh: true,
onRefreshInit: function () { gsap.set(wrapper, { x: 0 }); },
onRefresh: function () {
endLen = measure(section, wrapper, extra);
tl.scrollTrigger.end = tl.scrollTrigger.start + endLen;
}
}
}).to(wrapper, {
x: -endLen,
ease: “none”,
immediateRender: false
});
console.log(“[HScroll] 🟢 Running | scrolls”, endLen + “px”);
}
mm.add(“(max-width: 767px)”, function () { make(0); });
mm.add(“(min-width: 768px) and (max-width: 1024px)”, function () { make(20); });
mm.add(“(min-width: 1025px)”, function () { make(80); });
}
/* ── Resize ── */
var rTO;
window.addEventListener(“resize”, function () {
clearTimeout(rTO);
rTO = setTimeout(function () { startLenis(); ScrollTrigger.refresh(); }, 150);
});
})();
</script>
