Instructions

Lenis Smooth Scrolling

This provides smooth scrolling across the entire template. To turn off just comment out this code.

<link rel="stylesheet" href="https://unpkg.com/lenis@1.3.20/dist/lenis.css" />
<script src="https://unpkg.com/lenis@1.3.20/dist/lenis.min.js"></script> 
<script>
  gsap.registerPlugin(ScrollTrigger);

  const lenis = new Lenis({
    duration: 1.5,
    easing: (t) => 1 - Math.pow(1 - t, 3),
    smooth: true,
    smoothTouch: false, // ✅ important
  });

  // sync
  lenis.on('scroll', ScrollTrigger.update);

  // raf loop
  function raf(time) {
    lenis.raf(time);
    requestAnimationFrame(raf);
  }
  requestAnimationFrame(raf);

  // ✅ correct scroller
  ScrollTrigger.scrollerProxy(document.documentElement, {
    scrollTop(value) {
      return arguments.length ? lenis.scrollTo(value, { immediate: true }) : lenis.scroll;
    },
    getBoundingClientRect() {
      return {
        top: 0,
        left: 0,
        width: window.innerWidth,
        height: window.innerHeight,
      };
    },
  });

  // ✅ important
  ScrollTrigger.defaults({
    scroller: document.documentElement,
  });

  // refresh fix
  ScrollTrigger.addEventListener('refresh', () => lenis.resize());

  ScrollTrigger.refresh();
</script>

Number Counter

<script>
        gsap.registerPlugin(ScrollTrigger);

        gsap.utils.toArray(".counter").forEach(counter => {

            const finalText = counter.textContent.trim();

            const endValue = parseFloat(finalText.replace(/[^0-9.-]/g, ""));
            const suffix = finalText.replace(/[0-9.-]/g, "");
            const decimals = finalText.includes(".") ? 1 : 0;

            // Reset to zero
            counter.textContent = "0" + suffix;

            const obj = {
                value: 0
            };

            gsap.to(obj, {
                value: endValue,
                duration: 2,
                ease: "power2.out",
                scrollTrigger: {
                    trigger: counter,
                    start: "top 95%",
                    once: true
                },
                onUpdate() {
                    counter.textContent =
                        obj.value.toFixed(decimals) + suffix;
                }
            });

        }); 
  </script>