CustomEase.create( "loaderEase", "M0,0,C0,0,0.10,0.34,0.238,0.442,0.305,0.506,0.322,0.514,0.396,0.54,0.478,0.568,0.468,0.56,0.522,0.584,0.572,0.606,0.61,0.719,0.714,0.826,0.798,0.912,1,1,1,1" ); CustomEase.create("ease-1", "M0,0 C0.15,0 0.15,1 1,1"); CustomEase.create( "ease-2", "M0,0 C0.071,0.505 0.192,0.726 0.318,0.852 0.45,0.984 0.504,1 1,1" ); CustomEase.create("ease-3", "0.65, 0.01, 0.05, 0.99"); const lenis = new Lenis(); lenis.on("scroll", ScrollTrigger.update); gsap.ticker.add((time) => { lenis.raf(time * 1000); }); let winW = window.innerWidth; window.addEventListener("resize", () => { if (window.innerWidth !== winW) { winW = window.innerWidth; ScrollTrigger.refresh(); } }); const onDesktop = (fn) => gsap.matchMedia().add("(min-width: 992px)", fn); // const onTablet = (fn) => // gsap.matchMedia().add("(min-width: 768px) and (max-width: 991px)", fn); const onMobile = (fn) => gsap.matchMedia().add("(max-width: 991px)", fn); // line reveal animations onDesktop(() => { // document.fonts.ready.then(() => { // document.querySelectorAll(".line-reveal-1").forEach((block) => { // let split = SplitText.create(block, { // type: "lines", // linesClass: "line", // autoSplit: true, // }); // gsap.fromTo( // split.lines, // { // yPercent: 100, // clipPath: "polygon(-10% -10%, 100% -10%, 100% -10%, -10% -10%)", // }, // { // yPercent: 0, // clipPath: "polygon(0% 0%, 150% 0%, 150% 150%, 0% 150%)", // stagger: { amount: 0.3 }, // duration: 1.5, // ease: "expo.out", // scrollTrigger: { // trigger: block, // start: "top 85%", // end: "clamp(bottom 20%)", // toggleActions: "play none none none", // }, // } // ); // }); // }); ScrollTrigger.refresh(); //scroll Text document.fonts.ready.then(() => { let split = SplitText.create(".charsplit", { type: "chars", charsClass: "char", smartWrap: true, }); console.log("text split"); document.querySelectorAll(".char-reveal-1").forEach((section) => { const chars = section.querySelectorAll(".char"); gsap.fromTo( chars, { yPercent: -100, clipPath: "polygon(0% 100%, 100% 100%, 100% 100%, 0% 100%)", }, { scrollTrigger: { trigger: section, start: "clamp(top 80%)", end: "clamp(bottom 20%)", toggleActions: "play none none none", }, yPercent: 0, clipPath: "polygon(0% 0%, 150% 0%, 150% 150%, 0% 150%)", stagger: { amount: 0.8, }, duration: 2, ease: "power2.out", } ); }); }); // loop each reveal wrapper document.fonts.ready.then(() => { document.querySelectorAll(".char-reveal-load").forEach((section) => { const loadChars = section.querySelectorAll(".char"); gsap.fromTo( loadChars, { yPercent: -100, clipPath: "polygon(0% 100%, 100% 100%, 100% 100%, 0% 100%)", }, { scrollTrigger: { trigger: section, start: "top 95%", end: "bottom 80%", toggleActions: "play none none none", }, yPercent: 0, clipPath: "polygon(0% 0%, 150% 0%, 150% 150%, 0% 150%)", stagger: { amount: 0.8, }, duration: 2, ease: "power2.out", } ); }); }); }); // function hoverText() { // console.log("hoverText"); // $(".page_main").each(function () { // const staggerLinks = document.querySelectorAll("[stagger-link]"); // if (staggerLinks.length) { // staggerLinks.forEach((link) => { // const letters = link.querySelectorAll("[stagger-link-text] div"); // if (letters.length) { // link.addEventListener("mouseenter", function () { // gsap.to(letters, { // yPercent: -100, // duration: 0.4, // ease: "none", // overwrite: true, // }); // }); // link.addEventListener("mouseleave", function () { // gsap.to(letters, { // yPercent: 0, // duration: 0.4, // ease: "none", // }); // }); // } // }); // } // }); // } // hoverText(); document.addEventListener("DOMContentLoaded", function () { // Target the parent div that has nav_logo class const navLogo = document.querySelector("[mr-nav]"); // Find the dotlottie-player inside const lottiePlayer = navLogo.querySelector("dotlottie-player"); if (lottiePlayer && navLogo) { // Wait a bit for the player to fully load setTimeout(() => { navLogo.addEventListener("mouseenter", function () { lottiePlayer.setDirection(1); lottiePlayer.play(); }); navLogo.addEventListener("mouseleave", function () { lottiePlayer.setDirection(-1); lottiePlayer.play(); }); }, 500); } }); //SCRAMBLE TEXT function scrambleText() { $(document).ready(function () { class TextScramble { constructor(el) { this.$el = $(el); this.chars = "!<>-_\\/[]{}—=+*^?#________"; this.frame = 0; this.queue = []; this.resolve = null; } setText(newText) { const oldText = this.$el.text(); const length = Math.max(oldText.length, newText.length); const promise = new Promise((resolve) => (this.resolve = resolve)); this.queue = []; for (let i = 0; i < length; i++) { const from = oldText[i] || ""; const to = newText[i] || ""; const start = Math.floor(Math.random() * 40); const end = start + Math.floor(Math.random() * 40); this.queue.push({ from, to, start, end }); } this.frame = 0; this.animate(); return promise; } animate() { let output = ""; let complete = 0; for (let i = 0; i < this.queue.length; i++) { let { from, to, start, end, char } = this.queue[i]; if (this.frame >= end) { complete++; output += to; } else if (this.frame >= start) { if (!char || Math.random() < 0.28) { char = this.randomChar(); this.queue[i].char = char; } output += `${char}`; } else { output += from; } } this.$el.html(output); if (complete === this.queue.length) { this.resolve(); } else { gsap.delayedCall(0.016, () => this.animate()); this.frame++; } } randomChar() { return this.chars[Math.floor(Math.random() * this.chars.length)]; } } $(".scramble").each(function (index) { const $element = $(this); const originalText = $element.text(); $element.text(""); // Clear the text initially const fx = new TextScramble(this); ScrollTrigger.create({ trigger: this, start: "top bottom", once: true, onEnter: () => { const staggerDelay = index * 0.1; gsap.delayedCall(staggerDelay, () => { fx.setText(originalText); }); }, }); }); }); } onDesktop(() => { document.addEventListener("DOMContentLoaded", () => { function scrambleText(el, duration = 0.4, stagger = 0.01) { // Prevent overlapping animations if (el.dataset.animating === "true") return; el.dataset.animating = "true"; const original = el.textContent.split(""); const current = [...original]; const total = original.length; // Calculate when each character should stop scrambling const endTimes = original.map((_, i) => i * stagger + duration); const startTime = performance.now(); let animationId = null; // Track iteration count per character (limit to 3-4 changes) const iterations = new Array(total).fill(0); const maxIterations = 2; const iterationSpeed = 40; // ms between each letter change (lower = faster cycling) function animate(now) { const elapsed = (now - startTime) / 1000; let stillAnimating = false; for (let i = 0; i < total; i++) { if (elapsed < endTimes[i]) { // Calculate how many iterations should have happened by now const targetIterations = Math.floor( (now - startTime) / iterationSpeed ); // Only update if we haven't hit max iterations and it's time for next iteration if ( iterations[i] < maxIterations && iterations[i] < targetIterations ) { current[i] = original[Math.floor(Math.random() * total)]; iterations[i]++; } stillAnimating = true; } else if (current[i] !== original[i]) { // Lock in the original character current[i] = original[i]; } } el.textContent = current.join(""); if (stillAnimating) { animationId = requestAnimationFrame(animate); } else { // Animation complete - cleanup el.dataset.animating = "false"; el.textContent = original.join(""); } } animationId = requestAnimationFrame(animate); } // Initialize all buttons document.querySelectorAll(".button_main_wrap").forEach((btn) => { const textEl = btn.querySelector(".button_main_text"); if (textEl) { btn.addEventListener("mouseenter", () => { scrambleText(textEl, 0.2, 0.03); }); } }); }); }); //SCRAMBLE TEXT onDesktop(() => { $(".sticky_progress").each(function () { let stickySection = $(this); let stickyLeft = stickySection.find(".stickthis"); let stickyRight = stickySection.find(".stickyright"); let stickyStartTrigger = stickySection.find(".mr_sticky_img"); let stickyEndTrigger = stickySection.find(".stickyend"); let stickyProgress = stickySection.find(".mr_progress"); let stickyReveal = stickySection.find(".sticky_reveal"); let stickyNumber = stickySection.find(".mr_number .c-heading h2"); let stickImg = stickySection.find(".sticky_img_container"); ScrollTrigger.create({ trigger: stickImg, start: "clamp(center 53%)", end: "clamp(center center)", endTrigger: stickyEndTrigger, pin: stickyLeft, pinSpacing: false, scrub: true, }); const stickyProgressTl = gsap.timeline({ scrollTrigger: { trigger: stickyStartTrigger, start: "clamp(center center)", end: "clamp(center center)", endTrigger: stickyEndTrigger, scrub: 1.2, }, }); stickyProgressTl.fromTo( stickyProgress, { height: "0%" }, { height: "100%" } ); }); $(".sticky_progress").each(function () { let childTriggers = $(this).find(".stickyright"); let childTargets = $(this).find(".sticky_reveal_img"); let imgNumber = $(this).find(".mr_number .c-heading h2"); function makeItemActive(index) { childTriggers.removeClass("is-active"); childTargets.removeClass("is-active"); childTriggers.eq(index).addClass("is-active"); childTargets.eq(index).addClass("is-active"); imgNumber.text(String(index + 1).padStart(2, "0")); } makeItemActive(0); childTriggers.each(function (index) { ScrollTrigger.create({ trigger: $(this), start: "top center", end: "bottom center", onToggle: (self) => { if (self.isActive) makeItemActive(index); }, }); }); }); $(".page_main").each(function () { let insetMain = $(this); let insetHero = $(this).find("[hero-inset]"); let insetHeroClip = gsap.timeline({ scrollTrigger: { trigger: insetHero, start: "clamp(bottom bottom)", end: "clamp(bottom top)", scrub: true, }, }); insetHeroClip.fromTo( insetHero, { clipPath: "inset(0 0 0 0 round 0px)", }, { clipPath: "inset(0 3rem 0 3rem round 0.5rem)", } ); }); }); ///////??????////////////////STUCK ///////////////////////// onDesktop(() => { $(".stuck_section").each(function () { let stuckSection = $(this); let stuckPin = stuckSection.find(".stuckpin"); let stuckRight = stuckSection.find(".stuck_right"); let stuckTrigger = stuckSection.find(".stuck_spacer"); let stuckProgress = stuckSection.find(".stuck_progress"); // ScrollTrigger.create({ // trigger: stuckPin, // start: "clamp(top 10%)", // end: "clamp(bottom bottom)", // endTrigger: stuckTrigger, // pin: stuckPin, // pinSpacing: true, // scrub: true, // markers: true, // }); const stuckProgressTl = gsap.timeline({ scrollTrigger: { trigger: stuckSection, start: "clamp(top top)", end: "clamp(bottom bottom)", endTrigger: stuckTrigger, scrub: 1.2, }, }); stuckProgressTl.fromTo(stuckProgress, { height: "0%" }, { height: "100%" }); let childStuckTriggers = stuckSection.find(".stuck_spacer_trigger"); let childTargets = stuckSection.find(".acc_content"); let childStuckImgs = stuckSection.find(".stuck_img_right"); let childStuckDrop = stuckSection.find(".stuckdropdown"); function makeStuckActive(index) { childStuckImgs.removeClass("stuck_img_open"); childTargets.removeClass("acc_open"); childStuckDrop.removeClass("u-margin-bottom-3"); childStuckImgs.eq(index).addClass("stuck_img_open"); childTargets.eq(index).addClass("acc_open"); childStuckDrop.eq(index).css("margin-bottom", "3rem"); } makeStuckActive(0); childStuckTriggers.each(function (index) { ScrollTrigger.create({ trigger: $(this), start: "top bottom", end: "bottom bottom", onToggle: (self) => { if (self.isActive) makeStuckActive(index); }, }); }); }); }); // //Page blur // gsap.timeline({ // scrollTrigger: { // trigger: ".footer_wrap", // start: "clamp(top top)", // end: "clamp(top top)", // toggleActions: "play none reverse none", // onEnter: () => // document.querySelector(".hero_blur").classList.remove("active"), // onLeaveBack: () => // document.querySelector(".hero_blur").classList.add("active"), // }, // }); // // gsap.to(".hero_blur", { // // height: "11vh", // // }); // gsap.timeline({ // scrollTrigger: { // trigger: ".nav_trigger", // start: "clamp(top top)", // end: "clamp(top top)", // toggleActions: "play none reverse none", // onEnter: () => document.querySelector(".hero_blur").classList.add("active"), // onLeaveBack: () => // document.querySelector(".hero_blur").classList.remove("active"), // }, // }); //device section //button follow //BUTTON HOVER onDesktop(() => { $(".device_select").each(function () { const section = $(this); const btnFollow = section.find("[button-follow]"); let mouse = { x: window.innerWidth / 2, y: window.innerHeight / 2 }; let pos = { x: mouse.x, y: mouse.y }; window.addEventListener("mousemove", (e) => { mouse.x = e.clientX; mouse.y = e.clientY; }); gsap.ticker.add(() => { pos.x += (mouse.x - pos.x) * 0.1; pos.y += (mouse.y - pos.y) * 0.1; gsap.set(btnFollow, { x: pos.x, y: pos.y }); }); section.on("mouseenter", () => { gsap.to(btnFollow, { scale: 1, duration: 0.2, ease: "power3.out" }); }); section.on("mouseleave", () => { gsap.to(btnFollow, { scale: 0, duration: 0.2, ease: "power3.in" }); }); }); $(".anchor_hover").hover( function () { $(this).addClass("is-active"); }, function () { $(this).removeClass("is-active"); } ); //DEVICE ACTIVE $(".device-section").each(function () { const hoverLeft = document.querySelector(".device_hover_left"); const hoverRight = document.querySelector(".device_hover_right"); const deviceLeft = document.querySelector(".device_left"); const deviceRight = document.querySelector(".device_right"); hoverLeft.addEventListener("mouseenter", () => { deviceLeft.classList.add("is-active"); deviceRight.classList.remove("is-active"); }); hoverRight.addEventListener("mouseenter", () => { deviceRight.classList.add("is-active"); deviceLeft.classList.remove("is-active"); }); }); //device FOLLOW $(".device-move").each(function () { const holder = $(this); const baseRotationY = 0; let lastMouseX = null; let lastMouseY = null; function updateImagePosition() { if (lastMouseX === null || lastMouseY === null) return; const rect = holder[0].getBoundingClientRect(); const viewportCenterX = window.innerWidth / 2; const viewportCenterY = window.innerHeight / 2; const mouseX = lastMouseX; const mouseY = lastMouseY; const imgCenterX = rect.left + rect.width / 2; const imgCenterY = rect.top + rect.height / 2; const deltaX = mouseX - imgCenterX; const deltaY = mouseY - imgCenterY; const distance = Math.sqrt(deltaX ** 2 + deltaY ** 2); const maxDistance = Math.sqrt(window.innerWidth ** 2 + window.innerHeight ** 2) / 2; const intensity = 1 - Math.min(distance / maxDistance, 1); gsap.to(holder, { rotationX: (deltaY / window.innerHeight) * -60 * intensity, rotationY: ((deltaX / window.innerWidth) * 60 + baseRotationY) * intensity, x: (deltaX / window.innerWidth) * -300 * intensity, y: (deltaY / window.innerHeight) * 300 * intensity, ease: "power2.out", duration: 2, }); } $(document).on("mousemove", (e) => { lastMouseX = e.clientX; lastMouseY = e.clientY; updateImagePosition(); }); $(window).on("scroll", updateImagePosition); }); }); //nav dropdown $(".dropdown-hover").each(function () { let timeout; const navDropdown = $(".nav_dropdown"); const pageOverlay = $(".page_overlay"); $(this).on("mouseenter", function () { clearTimeout(timeout); navDropdown.addClass("open"); pageOverlay.css("display", "block"); requestAnimationFrame(() => { pageOverlay.addClass("is-active"); }); }); function closeDropdown() { navDropdown.removeClass("open"); pageOverlay.removeClass("is-active"); setTimeout(() => { if (!pageOverlay.hasClass("is-active")) { pageOverlay.css("display", "none"); } }, 300); } $(this).on("mouseleave", () => (timeout = setTimeout(closeDropdown, 200))); navDropdown.on("mouseenter", () => clearTimeout(timeout)); navDropdown.on( "mouseleave", () => (timeout = setTimeout(closeDropdown, 200)) ); }); //MENU // menu_toggle; function initMenu() { let navWrap = document.querySelector("[mr-nav]"); let state = navWrap.getAttribute("data-nav"); let overlay = navWrap.querySelector(".overlay_wrap"); let imgsWrap = navWrap.querySelector(".menu-img_inner"); let menu = navWrap.querySelector(".menu"); let menuClip = navWrap.querySelector(".menu-clip"); let buttons = navWrap.querySelectorAll(".button_main_wrap"); let toggleText = navWrap.querySelectorAll(".menu-toggle-text"); let menuToggles = document.querySelectorAll(".menu_toggle"); let arrow = document.querySelectorAll(".menu-arrow"); let menuLinks = navWrap.querySelectorAll(".menu-link"); let fadeTargets = navWrap.querySelectorAll("[data-menu-fade]"); let tl = gsap.timeline({}); // Initialize TextScramble for each toggle text class TextScramble { constructor(el) { this.el = el; this.chars = "!<>-_\\/[]{}—=+*^?#________"; this.frame = 0; this.queue = []; this.resolve = null; } setText(newText) { const oldText = this.el.textContent; const length = Math.max(oldText.length, newText.length); const promise = new Promise((resolve) => (this.resolve = resolve)); this.queue = []; for (let i = 0; i < length; i++) { const from = oldText[i] || ""; const to = newText[i] || ""; const start = Math.floor(Math.random() * 40); const end = start + Math.floor(Math.random() * 40); this.queue.push({ from, to, start, end }); } this.frame = 0; this.animate(); return promise; } animate() { let output = ""; let complete = 0; for (let i = 0; i < this.queue.length; i++) { let { from, to, start, end, char } = this.queue[i]; if (this.frame >= end) { complete++; output += to; } else if (this.frame >= start) { if (!char || Math.random() < 0.28) { char = this.randomChar(); this.queue[i].char = char; } output += `${char}`; } else { output += from; } } this.el.textContent = output; if (complete === this.queue.length) { this.resolve(); } else { gsap.delayedCall(0.016, () => this.animate()); this.frame++; } } randomChar() { return this.chars[Math.floor(Math.random() * this.chars.length)]; } } // Create TextScramble instances for each toggle text const scrambleInstances = Array.from(toggleText).map( (text) => new TextScramble(text) ); const openNav = () => { lenis.stop(); navWrap.setAttribute("data-nav", "open"); gsap.set(menu, { pointerEvents: "auto" }); // Scramble text to "close" scrambleInstances.forEach((fx) => { fx.setText("close"); }); tl.clear() .fromTo(overlay, { opacity: 0 }, { opacity: 0.4, ease: "expo" }) .fromTo( menuClip, { clipPath: "polygon(49.5% 0%, 50.5% 0%, 50.5% 0%, 49.5% 0%)" }, { clipPath: "polygon(49.5% 0%, 50.5% 0%, 50.5% 100%, 49.5% 100%)", duration: 0.6, ease: "ease-3", }, "<" ) .to( menuClip, { clipPath: "polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%)", duration: 2, ease: "ease-2", }, "<70%" ) .fromTo( menuLinks, { xPercent: -100, opacity: 0, }, { xPercent: 0, opacity: 1, duration: 1, ease: "ease-3", }, "<30%" ) .from( arrow, { opacity: 0, xPercent: -700, duration: 1, ease: "ease-3", }, "<" ) .fromTo( buttons, { opacity: 0 }, { opacity: 1, duration: 0.4, stagger: 0.1, ease: "ease-3", }, "<60%" ); }; const closeNav = () => { lenis.start(); navWrap.setAttribute("data-nav", "closed"); gsap.set(menu, { pointerEvents: "none" }); // Scramble text back to "menu" scrambleInstances.forEach((fx) => { fx.setText("menu"); }); tl.clear() .to(overlay, { opacity: 0 }) .to(buttons, { opacity: 0, duration: 0.575, ease: "expo.out" }, "<") .to( menuClip, { clipPath: "polygon(0% 0%, 100% 0%, 100% 0%, 0% 0%)", ease: "expo.out", }, "<10%" ); }; // Toggle menu open / close depending on its current state menuToggles.forEach((toggle) => { toggle.addEventListener("click", () => { state = navWrap.getAttribute("data-nav"); if (state === "open") { closeNav(); $(menuToggles).on("click", function () { $(".menu_products_wrap").removeClass("open"); $(".nav_logo").removeClass("nav_logo_hide"); $(".menu_layer_arrow").removeClass("open"); }); } else { openNav(); } }); }); // If menu is open, you can close it using the "escape" key document.addEventListener("keydown", (e) => { if (e.key === "Escape" && navWrap.getAttribute("data-nav") === "open") { closeNav(); } }); } initMenu(); $(".menu-layer-trigger").on("click", function () { $(".menu_products_wrap").addClass("open"); }); $(".menu-layer-trigger").on("click", function () { $(".nav_logo").addClass("nav_logo_hide"); $(".menu_layer_arrow").addClass("open"); }); $(".menu_layer_arrow").on("click", function () { $(".nav_logo").removeClass("nav_logo_hide"); $(".menu_layer_arrow").removeClass("open"); $(".menu_products_wrap").removeClass("open"); }); //nav ScrollTrigger.create({ trigger: ".nav_trigger", start: "bottom top", onEnter: () => gsap.to("[mr-nav]", { backgroundColor: "#f6f6f4", color: "#000", duration: 0.3, }), onLeaveBack: () => gsap.to("[mr-nav]", { backgroundColor: "transparent", color: "currentColor", duration: 0.3, }), }); let lastScroll = window.scrollY; let direction = "none"; gsap.ticker.add(() => { const currentScroll = window.scrollY; if (currentScroll > lastScroll && direction !== "down") { direction = "down"; gsap.to("[mr-nav]", { yPercent: -100, duration: 0.4, ease: "ease-3", }); } else if (currentScroll < lastScroll && direction !== "up") { direction = "up"; gsap.to("[mr-nav]", { yPercent: 0, duration: 0.4, ease: "ease-3", }); } lastScroll = currentScroll; }); function globalScript() {} //preloader $("html, body").scrollTop(0); let initPageLoad = gsap.timeline({}); initPageLoad.set(".page_main", { opacity: 1, delay: 1, }); let pageInTl = gsap.timeline({ defaults: { duration: 1 }, }); pageInTl.fromTo( ".fadein", { opacity: 0, }, { opacity: 1, delay: 1, } ); // gsap.set(".hero-text-animate .char", { // filter: "blur(10px) brightness(0%)", // opacity: 0, // scaleX: 1.8, // scaleY: 0.2, // }); function charAnimate() { gsap.fromTo( ".hero-text-animate .char", { yPercent: -100, clipPath: "polygon(0% 100%, 100% 100%, 100% 100%, 0% 100%)", }, { yPercent: 0, clipPath: "polygon(0% 0%, 150% 0%, 150% 150%, 0% 150%)", stagger: { amount: 0.8, }, duration: 2, ease: "power2.out", onComplete: () => { console.log("herotext"); }, } ); } $("[namespace='home']").each(function () { function homeIn() { let homeInTl = gsap.timeline({ defaults: { duration: 1 } }); // gsap.set(".preloader-hero", { opacity: 1 }); homeInTl.fromTo( ".page_main", { opacity: 0, }, { opacity: 1, ease: "ease-3", duration: 1, } ); homeInTl.to( ".hero-text-holder", { opacity: 1, ease: "ease-3", duration: 1, onStart: () => { charAnimate(); }, }, "<" ); // homeInTl.fromTo( // ".hero-text-animate .char", // { // yPercent: -100, // clipPath: "polygon(0% 100%, 100% 100%, 100% 100%, 0% 100%)", // }, // { // yPercent: 0, // clipPath: "polygon(0% 0%, 150% 0%, 150% 150%, 0% 150%)", // stagger: { // amount: 0.8, // }, // duration: 2, // ease: "power2.out", // onComplete: () => { // console.log("herotext"); // }, // } // ); homeInTl.fromTo( "[mr-nav]", { yPercent: -100, }, { yPercent: 0, ease: "ease-3", duration: 1.2, }, "<" ); homeInTl.fromTo( ".fade-in-pl", { opacity: 0, // yPercent: 100, }, { opacity: 1, // yPercent: 0, ease: "ease-3", duration: 1, onComplete: () => { scrambleText(); }, }, "<" ); } function preloader() { // const scope = $(this); let counter = { val: 0 }; let preloadPercent = gsap.timeline({ onStart: () => { $(".page_main").scrollTop(0); onDesktop(() => { gsap.set(".clip-holder", { scale: 0.2, }); }); onMobile(() => { gsap.set(".clip-holder", { scale: 0.5, }); }); gsap.set(".preloader-progress-bar", { width: "0%", }); gsap.set(".hero-img", { opacity: 0, }); gsap.set("[mr-nav]", { yPercent: -100, }); }, }); gsap.fromTo( ".preloader-progress-bar", { width: "0%", }, { width: "100%", duration: 3.5, delay: 0.5, ease: "ease-3", }, "<" ); gsap.to(counter, { val: 100, duration: 3, ease: "ease-3", delay: 0.5, onUpdate: () => { $(".preloader-counter-text").text( Math.floor(counter.val).toString().padStart(2, "0") ); }, }); onDesktop(() => { preloadPercent.fromTo( ".clip-holder", { scale: 0.2, }, { scale: 1, delay: 0.5, duration: 5, ease: CustomEase.create( "custom", "M0,0 C0.406,0.275 0.498,0.058 0.764,0.248 0.895,0.341 0.752,1 1,1 " ), } ); }); onMobile(() => { preloadPercent.fromTo( ".clip-holder", { scale: 0.5, }, { scale: 1, delay: 0.5, duration: 5, ease: CustomEase.create( "custom", "M0,0 C0.406,0.275 0.498,0.058 0.764,0.248 0.895,0.341 0.752,1 1,1 " ), } ); }); preloadPercent.fromTo( ".img-clip", { clipPath: "polygon(100% -1%, 0% 0%, 0% 100%, 100% 100%)", }, { clipPath: "polygon(100% 0%, 100% 0%, 100% 100%, 100% 100%)", stagger: { amount: 1.5, from: "end" }, duration: 3, ease: "expo.inOut", }, "<" ); preloadPercent.fromTo( ".clip-holder", { clipPath: "inset(1% 1% 1% 1%)", }, { clipPath: "inset(0% 0% 0% 0%)", duration: 1, }, "<+1" ); preloadPercent.to( ".preloader-progress-wrap", { opacity: 0, ease: "ease-3", }, "<+2" ); // preloadPercent.fromTo( // scope.find(".hero-text-animate .char"), // { // opacity: 0, // }, // { // opacity: 0.6, // duration: 0.1, // onStart: () => { // console.log("NOW"); // }, // } // ); preloadPercent.to( ".hero-text-holder", { opacity: 1, ease: "ease-3", duration: 2, }, "<+1.3" ); preloadPercent.fromTo( ".hero-text-animate .char", { yPercent: -100, clipPath: "polygon(0% 100%, 100% 100%, 100% 100%, 0% 100%)", }, { yPercent: 0, clipPath: "polygon(0% 0%, 150% 0%, 150% 150%, 0% 150%)", stagger: { amount: 0.8, }, duration: 2, ease: "power2.out", }, "<" ); preloadPercent.fromTo( "[mr-nav]", { yPercent: -100, }, { yPercent: 0, ease: "ease-3", duration: 1.2, }, "<+1" ); preloadPercent.fromTo( ".fade-in-pl", { opacity: 0, // yPercent: 100, }, { opacity: 1, // yPercent: 0, ease: "ease-3", duration: 1, onComplete: () => { scrambleText(); }, }, "<" ); preloadPercent.fromTo( ".preloader-section", { opacity: 1, }, { opacity: 0, duration: 0.2, } ); preloadPercent.to( ".hero-img", { opacity: 1, duration: 0.001, }, "<" ); preloadPercent.fromTo( ".preloader-darken", { opacity: 1, }, { opacity: 1, duration: 1, ease: "ease-3", onStart: () => {}, onComplete: () => { $(".body").removeClass("home-page"); lenis.start(); gsap.set(".preloader-section", { display: "none", }); }, }, "<" ); } // gsap.delayedCall(0.1, () => { // preloader(); // }); if (!sessionStorage.getItem("preloaderPlayed")) { gsap.delayedCall(0.1, () => { lenis.stop(); preloader(); }); $("body").addClass("no-load"); setTimeout(function () { $("body").removeClass("no-load"); }, 5000); sessionStorage.setItem("preloaderPlayed", "true"); } else { gsap.set(".preloader-section", { display: "none", }); // document.querySelector(".preloader-section").style.display = "none"; lenis.start(); homeIn(); // scrambleText(); } gsap.set(".hero_wrapper", { zIndex: 11, }); }); function homeScript() { console.log("homeScript"); //ASCII // // ASCII characters from darkest to lightest class WebGLASCII { constructor(element) { this.element = element; this.imageUrl = element.getAttribute("ascii"); this.charSize = parseFloat(element.getAttribute("ascii-size")) || 8; this.color = element.getAttribute("ascii-color") || "#ffffff"; this.hoverRadius = parseFloat(element.getAttribute("ascii-hover-radius")) || 10; this.hoverSpeed = parseFloat(element.getAttribute("ascii-hover-speed")) || 2; this.chars = element.getAttribute("ascii-chars") || " .:+=*#@"; this.hoverChars = element.getAttribute("ascii-hover-chars") || "!<>?/~^&"; this.mouse = new THREE.Vector2(0.5, 0.5); this.targetMouse = new THREE.Vector2(0.5, 0.5); this.init(); } async init() { this.setupRenderer(); this.setupCamera(); this.setupScene(); await this.loadTexture(); this.createMesh(); this.setupEvents(); this.animate(); } setupRenderer() { this.renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true, }); this.renderer.setPixelRatio(window.devicePixelRatio); const { width, height } = this.element.getBoundingClientRect(); this.width = width; this.height = height; this.renderer.setSize(width, height); this.element.appendChild(this.renderer.domElement); } setupCamera() { this.camera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1); } setupScene() { this.scene = new THREE.Scene(); } async loadTexture() { return new Promise((resolve, reject) => { const loader = new THREE.TextureLoader(); loader.setCrossOrigin("anonymous"); loader.load( this.imageUrl, (texture) => { this.texture = texture; this.texture.minFilter = THREE.LinearFilter; this.texture.magFilter = THREE.LinearFilter; resolve(); }, undefined, reject ); }); } createMesh() { // Convert hex color to RGB const hexToRgb = (hex) => { const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); return result ? { r: parseInt(result[1], 16) / 255, g: parseInt(result[2], 16) / 255, b: parseInt(result[3], 16) / 255, } : { r: 1, g: 1, b: 1 }; }; const rgb = hexToRgb(this.color); const geometry = new THREE.PlaneGeometry(2, 2); const material = new THREE.ShaderMaterial({ uniforms: { uTexture: { value: this.texture }, uResolution: { value: new THREE.Vector2(this.width, this.height) }, uMouse: { value: this.mouse }, uTime: { value: 0 }, uCharSize: { value: this.charSize }, uAspect: { value: this.width / this.height }, uColor: { value: new THREE.Vector3(rgb.r, rgb.g, rgb.b) }, uHoverRadius: { value: this.hoverRadius }, uHoverSpeed: { value: this.hoverSpeed }, }, vertexShader: ` varying vec2 vUv; void main() { vUv = uv; gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); } `, fragmentShader: ` uniform sampler2D uTexture; uniform vec2 uResolution; uniform vec2 uMouse; uniform float uTime; uniform float uCharSize; uniform float uAspect; uniform vec3 uColor; uniform float uHoverRadius; uniform float uHoverSpeed; varying vec2 vUv; // Simple character patterns float character(int n, vec2 p) { p = floor(p * vec2(5.0, 7.0)); if (p.x < 0.0 || p.x >= 5.0 || p.y < 0.0 || p.y >= 7.0) return 0.0; int idx = int(p.x) + int(p.y) * 5; if (n == 0) return 0.0; // space if (n == 1) { // . return (idx == 32) ? 1.0 : 0.0; } if (n == 2) { // : return (idx == 12 || idx == 22) ? 1.0 : 0.0; } if (n == 3) { // ! return (idx == 12 || idx == 16 || idx == 17 || idx == 18 || idx == 22) ? 1.0 : 0.0; } if (n == 4) { // + return (idx == 11 || idx == 12 || idx == 13 || idx == 21 || idx == 22 || idx == 23) ? 1.0 : 0.0; } if (n == 5) { // = return (idx == 7 || idx == 11 || idx == 12 || idx == 13 || idx == 17 || idx == 21 || idx == 23) ? 1.0 : 0.0; } if (n == 6) { // * return (idx == 6 || idx == 8 || idx == 10 || idx == 11 || idx == 12 || idx == 13 || idx == 14 || idx == 16 || idx == 18 || idx == 20 || idx == 21 || idx == 22 || idx == 23 || idx == 24 || idx == 26 || idx == 28) ? 1.0 : 0.0; } if (n == 7) { // @ return (idx == 6 || idx == 7 || idx == 8 || idx == 10 || idx == 14 || idx == 16 || idx == 18 || idx == 20 || idx == 21 || idx == 22 || idx == 24 || idx == 26 || idx == 31 || idx == 32 || idx == 33) ? 1.0 : 0.0; } // Default pattern for other characters float hash = fract(sin(float(n) * 12.9898 + p.x * 78.233 + p.y * 45.164) * 43758.5453); return (hash > 0.4) ? 1.0 : 0.0; } void main() { vec2 uv = vUv; // Calculate character grid vec2 charCoord = uv * uResolution / uCharSize; vec2 charIndex = floor(charCoord); vec2 charPos = fract(charCoord); // Sample at character center for brightness vec2 sampleUV = (charIndex + 0.5) * uCharSize / uResolution; vec4 sampleColor = texture2D(uTexture, sampleUV); float brightness = dot(sampleColor.rgb, vec3(0.299, 0.587, 0.114)); // Hover effect vec2 mouseGrid = uMouse * uResolution / uCharSize; float distToMouse = length(charIndex - mouseGrid); float hoverAmount = smoothstep(uHoverRadius, 0.0, distToMouse); // Map brightness to character index (inverted) int charType = 0; if (brightness < 0.14) charType = 7; // @ else if (brightness < 0.28) charType = 6; // # else if (brightness < 0.42) charType = 5; // * else if (brightness < 0.56) charType = 4; // = else if (brightness < 0.70) charType = 3; // + else if (brightness < 0.84) charType = 2; // : else if (brightness < 0.98) charType = 1; // . // Hover randomization if (hoverAmount > 0.5) { float slowTime = floor(uTime * uHoverSpeed); float random = fract(sin(dot(charIndex, vec2(12.9898, 78.233)) + slowTime) * 43758.5453); if (random > 0.8) { charType = int(mod(random * 15.0, 8.0)); } } // Render character float char = character(charType, charPos); // Apply base color vec3 color = uColor; // Hover glow color += vec3(0.2, 0.3, 0.8) * hoverAmount * 0.3; gl_FragColor = vec4(color * char, char); } `, transparent: true, }); this.mesh = new THREE.Mesh(geometry, material); this.scene.add(this.mesh); } setupEvents() { const updateMouse = (clientX, clientY) => { const rect = this.element.getBoundingClientRect(); const x = clientX - rect.left; const y = clientY - rect.top; if (x >= 0 && x <= rect.width && y >= 0 && y <= rect.height) { this.targetMouse.x = x / rect.width; this.targetMouse.y = 1.0 - y / rect.height; } }; document.addEventListener("mousemove", (e) => { updateMouse(e.clientX, e.clientY); }); window.addEventListener("scroll", () => { const rect = this.element.getBoundingClientRect(); if (rect.top < window.innerHeight && rect.bottom > 0) { updateMouse( this.targetMouse.x * this.width, this.targetMouse.y * this.height ); } }); window.addEventListener("resize", () => { const { width, height } = this.element.getBoundingClientRect(); this.width = width; this.height = height; this.renderer.setSize(width, height); this.mesh.material.uniforms.uResolution.value.set(width, height); this.mesh.material.uniforms.uAspect.value = width / height; }); } animate() { requestAnimationFrame(() => this.animate()); // Smooth mouse interpolation this.mouse.lerp(this.targetMouse, 0.1); // Update uniforms this.mesh.material.uniforms.uMouse.value.copy(this.mouse); this.mesh.material.uniforms.uTime.value = performance.now() * 0.001; this.renderer.render(this.scene, this.camera); } dispose() { this.renderer.dispose(); this.scene.clear(); } } document.addEventListener("DOMContentLoaded", () => { document.querySelectorAll("[ascii]").forEach((el) => { new WebGLASCII(el); }); }); $(".page_main").each(function () { let homeHero = $(this); let heroWrapper = homeHero.find(".hero_wrapper"); let heroAcsii = homeHero.find(".hero_acsii_wrap"); let heroAcsiiCanvas = homeHero.find(".ascii_wrap"); let heroAcsiiTrigger = homeHero.find(".hero-spacer"); let heroWait = homeHero.find(".herowait"); let heroImg = homeHero.find(".hero-img"); let heroLayer = homeHero.find(".layerhero"); // let pageBlur = homeHero.find(".hero_blur"); // let blurTrigger = homeHero.find(".nav_trigger"); // let blurTriggerFooter = homeHero.find(".footer_wrap"); let heroContent = homeHero.find(".hero-content"); ScrollTrigger.create({ trigger: heroAcsiiTrigger, start: "clamp(bottom bottom)", end: "clamp(bottom -90%)", pin: heroAcsii, pinSpacing: false, scrub: 1.1, }); const homeAcsiiMask = gsap.timeline({ scrollTrigger: { trigger: heroAcsiiTrigger, start: "clamp(bottom bottom)", end: "clamp(bottom 30%)", scrub: 1.1, }, }); homeAcsiiMask.fromTo( heroAcsii, { clipPath: "polygon(0% 100%, 100% 100%, 100% 100%, 0% 100%)", }, { clipPath: "polygon(0% 100%, 100% 100%, 100% 0%, 0% 0%)", } ); const heroImgParallax = gsap.timeline({ scrollTrigger: { trigger: heroAcsiiTrigger, start: "clamp(bottom bottom)", end: "clamp(bottom -100%)", scrub: 1.1, }, }); heroImgParallax.fromTo( heroImg, { filter: "brightness(100%)", yPercent: 0, }, { filter: "brightness(5%)", yPercent: -20, } ); const heroContentMove = gsap.timeline({ scrollTrigger: { trigger: heroAcsiiTrigger, start: "clamp(bottom bottom)", end: "clamp(bottom -100%)", scrub: 1.1, }, }); heroContentMove.fromTo( heroContent, { yPercent: 0, }, { yPercent: -100, } ); const heroLayerMove = gsap.timeline({ scrollTrigger: { trigger: heroAcsiiTrigger, start: "clamp(bottom bottom)", end: "clamp(bottom -100%)", scrub: 1.1, }, }); heroLayerMove.fromTo( heroContent, { yPercent: 0, }, { yPercent: -150, } ); // const pageBlurTl = gsap.timeline({ // scrollTrigger: { // trigger: blurTrigger, // start: "clamp(bottom top)", // end: "clamp(bottom top)", // toggleActions: "play none reverse none", // }, // }); // pageBlurTl.to(pageBlur, { // opacity: 1, // height: "11vh", // }); // const pageBlurFooter = gsap.timeline({ // scrollTrigger: { // trigger: blurTriggerFooter, // start: "clamp(top top)", // end: "clamp(top top)", // toggleActions: "play none reverse none", // }, // }); // pageBlurFooter.to(pageBlur, { // opacity: 0, // }); const heroAsciiParallax = gsap.timeline({ scrollTrigger: { trigger: heroAcsiiTrigger, start: "clamp(bottom bottom)", end: "clamp(bottom -100%)", scrub: 1.1, }, }); heroAsciiParallax.fromTo( heroAcsiiCanvas, { yPercent: 0, }, { yPercent: -40, } ); // const heroAsciiParallax = gsap.timeline({ // scrollTrigger: { // trigger: heroAcsiiTrigger, // start: "clamp(bottom bottom)", // end: "clamp(bottom -100%)", // scrub: 1.1, // }, // }); // heroAsciiParallax.fromTo( // heroAcsiiCanvas, // { // yPercent: 0, // }, // { // yPercent: -40, // } // ); ScrollTrigger.create({ trigger: heroAcsiiTrigger, start: "clamp(bottom bottom)", end: "clamp(bottom top)", pin: heroWrapper, pinSpacing: false, scrub: 1.1, }); ScrollTrigger.create({ trigger: heroAcsiiTrigger, start: "clamp(bottom bottom)", end: "clamp(bottom 50%)", pin: heroWait, pinSpacing: true, scrub: 1.1, }); }); } // if (document.querySelector("[mr-nav]")) { // pageInTl.fromTo( // "[mr-nav]", // { // yPercent: -100, // }, // { // delay: 2, // yPercent: 0, // duration: 1.2, // ease: "expo.out", // } // ); // } //scroll animations // gsap.from(".blur-in", { // filter: "blur(8px)", // duration: 0.3, // ease: "power2.out", // scrollTrigger: { // trigger: ".blur-in", // start: "top bottom", // end: "top 70%", // scrub: true, // }, // }); //footer links $(".footer_link_text").hover( function () { $(this).css("color", "#86BEAA"); // $(".footer_link_text").not(this).css("opacity", 0.4); }, function () { $(this).css("color", ""); // $(".footer_link_text").css("opacity", 1); } ); //sticky progress height function matchStickyHeights() { const img = document.querySelector(".mr_sticky_img"); const loader = document.querySelector(".mr_sticky_loader"); if (img && loader) loader.style.height = `${img.offsetHeight}px`; } matchStickyHeights(); window.addEventListener("resize", matchStickyHeights); //blur velocity // let velocityTimeout; // lenis.on("scroll", (e) => { // clearTimeout(velocityTimeout); // // Only animate when scrolling down (positive velocity) // if (e.velocity > 0) { // // Get the velocity value // const velocity = e.velocity; // // Map velocity to height (0-30vh) // // Adjust the divisor (2) to control sensitivity - lower = more sensitive // const height = Math.min(velocity / 1, 50); // // Apply the height // $(".hero_blur").css("height", height + "vh"); // // Reset to 0vh after scrolling stops // velocityTimeout = setTimeout(() => { // $(".hero_blur").css("height", "0vh"); // }, 150); // Adjust delay as needed // } else { // // When scrolling up, keep it at 0vh // $(".hero_blur").css("height", "0vh"); // } // }); //Page Scripts $("[namespace='home']").each(function () { homeScript(); }); $(".card-content").each(function () { let cardSection = $(this); let iconSvg = cardSection.find(".mr_simple_img"); const iconUp = gsap.timeline({ scrollTrigger: { trigger: cardSection, start: "clamp(top 90%)", end: "clamp(top 90%)", toggleActions: "play none none none", }, }); iconUp.fromTo( iconSvg, { opacity: 0, yPercent: 100, rotateY: 90, }, { rotateY: 0, yPercent: 0, opacity: 1, duration: 1.5, ease: "expo.inOut", stagger: { each: 0.2 }, } ); }); $("[namespace='contact']").each(function () { //contact form hubspot document.addEventListener("DOMContentLoaded", function () { const form = document.getElementById("hubspot-form"); const submitButton = form.querySelector('input[type="submit"]'); const originalButtonText = submitButton ? submitButton.value : "SUBMIT"; form.addEventListener("submit", function (e) { e.preventDefault(); // Disable submit button to prevent double submission if (submitButton) { submitButton.disabled = true; submitButton.value = ""; } // Get form values const formData = { fields: [ { objectTypeId: "0-1", name: "firstname", value: form.querySelector('[name="firstname"]').value, }, { objectTypeId: "0-1", name: "lastname", value: form.querySelector('[name="lastname"]').value, }, { objectTypeId: "0-1", name: "email", value: form.querySelector('[name="email"]').value, }, { objectTypeId: "0-1", name: "company", value: form.querySelector('[name="company"]').value, }, { objectTypeId: "0-1", name: "phone", value: form.querySelector('[name="phone"]').value, }, { objectTypeId: "0-1", name: "message", value: form.querySelector('[name="message"]').value, }, ], context: { pageUri: window.location.href, pageName: document.title, }, }; // Submit to HubSpot fetch( "https://api.hsforms.com/submissions/v3/integration/submit/47909521/c690d2a3-5707-4212-96f7-0548232394ba", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify(formData), } ) .then((response) => { if (!response.ok) { throw new Error("Form submission failed"); } return response.json(); }) .then((data) => { console.log("Success:", data); // Hide form form.style.display = "none"; // Show success message const successMessage = document.querySelector(".success-message"); if (successMessage) { successMessage.style.display = "block"; } }) .catch((error) => { console.error("Error:", error); alert( "Sorry, there was an error submitting the form. Please try again." ); // Re-enable button if (submitButton) { submitButton.disabled = false; submitButton.value = originalButtonText; } }); }); }); }); $(".dropdown-hover, .nav_dropdown").on("mouseenter", function () { $("[mr-nav]").css("color", "#000"); }); $(".dropdown-hover, .nav_dropdown").on("mouseleave", function () { $("[mr-nav]").css("color", ""); }); // $(".div-block-6.w-variant-3ff4cd4c-e8a4-4de0-3209-ea55fe39d7a6 .dropdown-hover") // .on("mouseenter", function () { // $(this).find(".nav-lottie.w-embed").css("filter", "invert(0)"); // }) // .on("mouseleave", function () { // $(this).find(".nav-lottie.w-embed").css("filter", "invert(1)"); // }); document.querySelectorAll(".clicktocopy").forEach((element) => { element.addEventListener("click", function () { const currentUrl = window.location.href; navigator.clipboard .writeText(currentUrl) .then(() => { console.log("URL copied to clipboard!"); // Optional: Change button text temporarily // const originalText = this.textContent; // this.textContent = "Copied!"; // setTimeout(() => { // this.textContent = originalText; // }, 2000); }) .catch((err) => { console.error("Failed to copy URL: ", err); }); }); }); document.addEventListener("DOMContentLoaded", function () { const form = document.getElementById("whitepaper-form"); if (!form) return; // Exit if form doesn't exist on this page const submitButton = form.querySelector('input[type="submit"]'); const originalButtonText = submitButton ? submitButton.value : "SUBMIT"; form.addEventListener("submit", function (e) { e.preventDefault(); // Disable submit button to prevent double submission if (submitButton) { submitButton.disabled = true; submitButton.value = "Submitting..."; } // Get form values const formData = { fields: [ { objectTypeId: "0-1", name: "firstname", value: form.querySelector('[name="firstname"]').value, }, { objectTypeId: "0-1", name: "lastname", value: form.querySelector('[name="lastname"]').value, }, { objectTypeId: "0-1", name: "email", value: form.querySelector('[name="email"]').value, }, { objectTypeId: "0-1", name: "company", value: form.querySelector('[name="company"]').value, }, { objectTypeId: "0-1", name: "jobtitle", value: form.querySelector('[name="jobtitle"]').value, }, ], context: { pageUri: window.location.href, pageName: document.title, }, }; // Submit to HubSpot - WHITEPAPER FORM fetch( "https://api.hsforms.com/submissions/v3/integration/submit/47909521/cbfd021a-938d-41e5-a0bc-53861ee2750e", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify(formData), } ) .then((response) => { if (!response.ok) { throw new Error("Form submission failed"); } return response.json(); }) .then((data) => { console.log("Success:", data); // Hide form form.style.display = "none"; // Show success message // const successMessage = document.querySelector(".success-message"); // if (successMessage) { // successMessage.style.display = "block"; // } }) .catch((error) => { console.error("Error:", error); alert( "Sorry, there was an error submitting the form. Please try again." ); // Re-enable button if (submitButton) { submitButton.disabled = false; submitButton.value = originalButtonText; } }); }); }); // Michael Harris Development start // function initPreloader() { // const $preloader = $(".preloader-section"); // const $counter = $(".preloader-counter-text"); // const $bar = $(".preloader-progress-bar"); // const $dots = $(".preloader-dot"); // const $imgSecond = $(".preloader-img-second"); // const $imgThird = $(".preloader-img-third"); // const $imgEnd = $(".preloader-img-end"); // const $scale = $(".preloader-scale"); // const $initial = $(".preloader-initial"); // const isActive = $("html").hasClass("preloader-active"); // if (!$preloader.length || !$counter.length) return; // const KEY = "preloaderShown_v1"; // const dev = !!window.PRELOAD_DEV || location.search.indexOf("preload=1") > -1; // // --- FIRST VISIT CONTROL (disabled for development) --- // // if (!isActive) { // // gsap.set($preloader, { opacity: 0, pointerEvents: "none" }); // // return; // // } // // ------------------------------------------------------ // gsap.set($preloader, { opacity: 1, pointerEvents: "none" }); // lenis.stop(); // let dotsTween = null; // let start = 0; // let minDuration = 3000; // let rafId = null; // const seg = (p, startSeg) => gsap.utils.clamp(0, 1, (p - startSeg) * 3); // function applyClip($el, t) { // if (!$el.length) return; // const right = (100 * (1 - t)).toFixed(3) + "%"; // $el.css("clip-path", `inset(0% ${right} 0% 0%)`); // } // function tick() { // const elapsed = performance.now() - start; // const p = Math.min(elapsed / minDuration, 1); // const val = Math.floor(p * 100); // $counter.text(String(val).padStart(2, "0") + "%"); // if ($bar.length) $bar.css("width", val + "%"); // applyClip($imgSecond, seg(p, 0 / 3)); // applyClip($imgThird, seg(p, 1 / 3)); // applyClip($imgEnd, seg(p, 2 / 3)); // if (p >= 1) { // if (rafId) cancelAnimationFrame(rafId); // $counter.text("100%"); // if ($bar.length) $bar.css("width", "100%"); // const clipEase = CustomEase.create( // "custom", // "M0,0 C0.087,0.257 0.063,0.3 0.2,0.3 0.303,0.3 0.499,0.406 0.499,0.486 0.566,0.832 0.89,1 1,1 " // ); // const clipDuration = 0.6; // if ($imgSecond.length) // gsap.to($imgSecond, { // clipPath: "inset(0% 0% 0% 0%)", // duration: clipDuration, // ease: clipEase, // }); // if ($imgThird.length) // gsap.to($imgThird, { // clipPath: "inset(0% 0% 0% 0%)", // duration: clipDuration, // ease: clipEase, // delay: 0.1, // }); // if ($imgEnd.length) // gsap.to($imgEnd, { // clipPath: "inset(0% 0% 0% 0%)", // duration: clipDuration, // ease: clipEase, // delay: 0.2, // }); // if (dotsTween) dotsTween.kill(); // if ($dots.length) gsap.set($dots, { opacity: 1 }); // $("html").removeClass("preloader-active"); // gsap.set($preloader, { pointerEvents: "none" }); // // --- FIRST VISIT STORAGE (disabled for development) --- // // if (!dev) { // // try { // // localStorage.setItem(KEY, "1"); // // } catch (e) {} // // } // // ------------------------------------------------------- // const preloaderEndTimeline = gsap.timeline(); // if ($scale.length) { // gsap.set($scale, { scale: 0.3 }); // preloaderEndTimeline.to($scale, { // scale: 1, // duration: 0.8, // ease: "power1.in", // onComplete: () => { // lenis.start(); // // lenis.refresh(); // }, // }); // } // preloaderEndTimeline.to($preloader, { // opacity: 0, // duration: 0.3, // ease: "power1.out", // }); // return; // } // rafId = requestAnimationFrame(tick); // } // function startMain() { // if ($dots.length) { // gsap.set($dots, { opacity: 1 }); // dotsTween = gsap.to($dots, { // keyframes: [ // { opacity: 0, duration: 0.3 }, // { opacity: 1, duration: 0.3 }, // ], // repeat: -1, // ease: "power3.in", // stagger: 0.2, // }); // } // start = performance.now(); // rafId = requestAnimationFrame(tick); // window.addEventListener("load", () => { // const loadElapsed = performance.now() - start; // if (loadElapsed > minDuration) minDuration = loadElapsed; // }); // } // if ($initial.length) { // gsap.set($initial, { opacity: 1, onComplete: startMain }); // } else { // startMain(); // } // } // initPreloader(); $(".modal_trigger_btn_wrap").on("click", function () { document.querySelector("[f-data-video='play-button']")?.click(); gsap.to(".full_vid_holder", { clipPath: "polygon(0% 100%, 100% 100%, 100% 0%, 0% 0%)", pointerEvents: "none", duration: 0.5, ease: "power2.out", }); gsap.to(".model-close-m", { pointerEvents: "auto", display: "block", }); }); function pauseVideoOnScroll() { const $players = $(".cms_video_player"); if (!$players.length) return; $players.each(function () { const $player = $(this); const $pauseButton = $player.find('[f-data-video="pause-button"]'); if (!$pauseButton.length) return; gsap.timeline({ scrollTrigger: { trigger: $player[0], start: "20% top", onEnter: () => $pauseButton.trigger("click"), onEnterBack: () => $pauseButton.trigger("click"), }, }); }); } pauseVideoOnScroll(); $(".model-close-m").on("click", function () { document.querySelector("[f-data-video='pause-button']")?.click(); gsap.to(".full_vid_holder", { clipPath: "polygon(0% 100%, 100% 100%, 100% 100%, 0% 100%)", pointerEvents: "none", duration: 0.5, ease: "power2.out", }); gsap.to(".model-close-m", { pointerEvents: "none", }); }); function visualVolumeSlider() { const wraps = document.querySelectorAll( ".video-volume-embed, .video-volum-embed" ); wraps.forEach((wrap) => { const slider = wrap.querySelector(".slider"); if (!slider) return; function setValueFromClick(e) { const rect = wrap.getBoundingClientRect(); let pct = (e.clientX - rect.left) / rect.width; pct = Math.min(Math.max(pct, 0), 1); const min = parseFloat(slider.min) || 0; const max = parseFloat(slider.max) || 1; const step = parseFloat(slider.step) || 0.01; let val = min + pct * (max - min); val = Math.round(val / step) * step; slider.value = val; slider.dispatchEvent(new Event("input")); } wrap.addEventListener("click", setValueFromClick); wrap.addEventListener( "touchstart", (e) => { if (e.touches && e.touches[0]) setValueFromClick(e.touches[0]); }, { passive: true } ); }); document.querySelectorAll(".slider").forEach((slider) => { slider.addEventListener("input", () => { const min = parseFloat(slider.min) || 0; const max = parseFloat(slider.max) || 1; const val = parseFloat(slider.value) || 0; const pct = ((val - min) / (max - min)) * 100; slider.style.backgroundImage = `linear-gradient(to right, white ${pct}%, rgba(255,255,255,.2) ${pct}%)`; }); slider.dispatchEvent(new Event("input")); }); } visualVolumeSlider(); function showNextThreeAfterCurrent() { const slug = window.location.pathname.replace(/\/$/, "").split("/").pop(); const $items = $("[project-slug]"); if (!$items.length) return; const curIndex = $items .toArray() .findIndex((el) => $(el).attr("project-slug") === slug); if (curIndex === -1) return; $items.hide(); let shown = 0; for (let o = 1; o < $items.length && shown < 3; o++) { const idx = (curIndex + o) % $items.length; if (idx === curIndex) continue; $items.eq(idx).css("display", ""); shown++; } $items.eq(curIndex).remove(); } showNextThreeAfterCurrent(); function galleryFilter() { const $slots = $("[gallery-slot]").sort( (a, b) => (parseInt(a.getAttribute("gallery-slot")) || 0) - (parseInt(b.getAttribute("gallery-slot")) || 0) ); let $items = $("[gallery-item]"); if (!$("[gallery-pool]").length) $("
").appendTo("body"); const $pool = $("[gallery-pool]"); let galleryFilterTimeline = null; function norm(v) { return (v || "") .toString() .toLowerCase() .replace(/\s+/g, "") .replace(/[^a-z0-9_-]/g, ""); } function getFiltered(key) { const k = norm(key); if (!k || k === "all") return $items; return $items.filter(function () { return norm(this.getAttribute("gallery-item")) === k; }); } function applyFilter(key) { if (galleryFilterTimeline && galleryFilterTimeline.isActive()) { galleryFilterTimeline.progress(1); galleryFilterTimeline.kill(); } const $current = $slots.find("[gallery-item]"); const $list = getFiltered(key); console.log("Filter click:", key, "| normalized:", norm(key)); console.log("Items total:", $items.length, "Filtered count:", $list.length); console.log( "Slots:", $slots.length, "Currently in slots:", $current.length ); const state = Flip.getState($items.toArray()); galleryFilterTimeline = gsap.timeline({ onComplete: () => { if (typeof lenis !== "undefined") lenis.start?.(); if (typeof lenis !== "undefined") lenis.resize?.(); if (typeof ScrollTrigger !== "undefined") ScrollTrigger.refresh(); }, }); if ($current.length) { galleryFilterTimeline.to( $current, { opacity: 1, duration: 0.2, stagger: 0.02 }, 0 ); } galleryFilterTimeline.add(() => { $slots.empty().css({ display: "", height: "" }); // reset slot visibility let i = 0; $list.each(function () { if (i >= $slots.length) return false; $(this).appendTo($slots.eq(i)); i++; }); $pool.append($items.not($slots.find("[gallery-item]"))); $items = $("[gallery-item]"); // hide empty slots (new bit) $slots.each(function () { const $s = $(this); if ($s.find("[gallery-item]").length === 0) $s.css({ display: "none", height: 0 }); }); console.log("Placed into slots:", Math.min($list.length, $slots.length)); Flip.from(state, { duration: 1, ease: "power2.out", absolute: true, stagger: 0.04, onEnter: (el) => gsap.fromTo(el, { opacity: 1 }, { opacity: 1, duration: 0.3 }), onLeave: (el) => gsap.to(el, { opacity: 1, duration: 0.2 }), }); }); } $(document).on("click", "[gallery-filter-btn]", function () { const key = $(this).attr("gallery-filter-btn") || "all"; $("[gallery-filter-btn].is-active").removeClass("is-active"); $(this).addClass("is-active"); applyFilter(key); }); const initialKey = $("[gallery-filter-btn].is-active").attr("gallery-filter-btn") || "all"; applyFilter(initialKey); } // galleryFilter(); // marquee component function attr(defaultVal, attrVal) { const defaultValType = typeof defaultVal; if (typeof attrVal !== "string" || attrVal.trim() === "") return defaultVal; if (attrVal === "true" && defaultValType === "boolean") return true; if (attrVal === "false" && defaultValType === "boolean") return false; if (isNaN(attrVal) && defaultValType === "string") return attrVal; if (!isNaN(attrVal) && defaultValType === "number") return +attrVal; return defaultVal; } $("[tr-marquee-element='component']").each(function (index) { let componentEl = $(this), panelEl = componentEl.find("[tr-marquee-element='panel']"), triggerHoverEl = componentEl.find("[tr-marquee-element='triggerhover']"), triggerClickEl = componentEl.find("[tr-marquee-element='triggerclick']"); let speedSetting = attr(100, componentEl.attr("tr-marquee-speed")), verticalSetting = attr(false, componentEl.attr("tr-marquee-vertical")), reverseSetting = attr(false, componentEl.attr("tr-marquee-reverse")), scrollDirectionSetting = attr( false, componentEl.attr("tr-marquee-scrolldirection") ), scrollScrubSetting = attr( false, componentEl.attr("tr-marquee-scrollscrub") ), moveDistanceSetting = -100, timeScaleSetting = 1, pausedStateSetting = false; if (reverseSetting) moveDistanceSetting = 100; let marqueeTimeline = gsap.timeline({ repeat: -1, onReverseComplete: () => marqueeTimeline.progress(1), }); if (verticalSetting) { speedSetting = panelEl.first().height() / speedSetting; marqueeTimeline.fromTo( panelEl, { yPercent: 0 }, { yPercent: moveDistanceSetting, ease: "none", duration: speedSetting } ); } else { speedSetting = panelEl.first().width() / speedSetting; marqueeTimeline.fromTo( panelEl, { xPercent: 0 }, { xPercent: moveDistanceSetting, ease: "none", duration: speedSetting } ); } let scrubObject = { value: 1 }; ScrollTrigger.create({ trigger: "body", start: "top top", end: "bottom bottom", onUpdate: (self) => { if (!pausedStateSetting) { if (scrollDirectionSetting && timeScaleSetting !== self.direction) { timeScaleSetting = self.direction; marqueeTimeline.timeScale(self.direction); } if (scrollScrubSetting) { let v = self.getVelocity() * 0.006; v = gsap.utils.clamp(-60, 60, v); let scrubTimeline = gsap.timeline({ onUpdate: () => marqueeTimeline.timeScale(scrubObject.value), }); scrubTimeline.fromTo( scrubObject, { value: v }, { value: timeScaleSetting, duration: 0.5 } ); } } }, }); function pauseMarquee(isPausing) { pausedStateSetting = isPausing; let pauseObject = { value: 1 }; let pauseTimeline = gsap.timeline({ onUpdate: () => marqueeTimeline.timeScale(pauseObject.value), }); if (isPausing) { pauseTimeline.fromTo( pauseObject, { value: timeScaleSetting }, { value: 0, duration: 0.5 } ); triggerClickEl.addClass("is-paused"); } else { pauseTimeline.fromTo( pauseObject, { value: 0 }, { value: timeScaleSetting, duration: 0.5 } ); triggerClickEl.removeClass("is-paused"); } } if (window.matchMedia("(pointer: fine)").matches) { triggerHoverEl.on("mouseenter", () => pauseMarquee(true)); triggerHoverEl.on("mouseleave", () => pauseMarquee(false)); } triggerClickEl.on("click", function () { !$(this).hasClass("is-paused") ? pauseMarquee(true) : pauseMarquee(false); }); });