gsap.registerPlugin(ScrollTrigger); // =============== THEME TOGGLER =============== const toggleButton = document.getElementById("theme-toggle"); const body = document.body; const setTheme = (theme) => { body.dataset.theme = theme; localStorage.setItem("preferred-theme", theme); }; const getTheme = () => { const stored = localStorage.getItem("preferred-theme"); return stored || "dark"; }; const toggleTheme = () => { const currentTheme = body.dataset.theme; setTheme(currentTheme === "light" ? "dark" : "light"); }; toggleButton.addEventListener("click", toggleTheme); setTheme(getTheme()); // =============== LOADER =============== function runLoaderAnimation() { const loaderText = document.querySelector(".loader-text"); loaderText.textContent = "0"; gsap.to(loaderText, { duration: 1, textContent: 100, snap: { textContent: 1 }, onComplete: () => { const loaderTl = gsap.timeline(); loaderTl .to(".loader-text", { duration: 1.5, yPercent: -800, opacity: 0, ease: "power3.inOut", }) .to( ".loader", { duration: 1.5, yPercent: 110, ease: "power3.inOut", }, 0 ) .from( ".slogan", { ease: "power3.out", filter: "blur(0.5rem)", yPercent: -100, opacity: 0, }, 0.5 ) .from( ".nav_item", { ease: "power3.out", filter: "blur(0.5rem)", yPercent: -100, opacity: 0, stagger: 0.05, }, 0.55 ); }, }); } runLoaderAnimation(); window.addEventListener("pageshow", function (event) { if (event.persisted) { console.log("Page was restored from bfcache. Resetting and re-running loader."); gsap.set("#logo", { yPercent: 0, filter: "blur(0)", opacity: 1 }); gsap.set(".loader", { yPercent: -101 }); } }); // =============== STRONA: PRZEJŚCIA MIĘDZY LINKAMI =============== (function initPageTransitions() { document.querySelectorAll("a").forEach((link) => { const isSameDomain = link.host === window.location.host; if (!isSameDomain) return; link.addEventListener("click", function (event) { event.preventDefault(); const targetUrl = this.getAttribute("href"); // Zakrycie loaderem od góry gsap.fromTo( ".loader", { yPercent: -101 }, { yPercent: 0, ease: "power3.inOut", duration: 0.5, onComplete: () => { window.location.href = targetUrl; }, } ); // Animacja logo gsap.to("#logo", { duration: 0.5, yPercent: -50, filter: "blur(1rem)", opacity: 0, ease: "power3.in", onComplete: () => { window.location.href = targetUrl; }, }); }); }); })(); // =============== KURSOR =============== (function initCustomCursor() { const cursor = document.querySelector(".cursor"); const cursorStroke = document.querySelector(".cursor_stroke"); const interactiveElements = document.querySelectorAll("a, button, input"); // Ustawienia początkowe dla GSAP gsap.set([cursor, cursorStroke], { xPercent: -50, yPercent: -50 }); const xCursor = gsap.quickSetter(cursor, "x", "px"); const yCursor = gsap.quickSetter(cursor, "y", "px"); window.addEventListener("mousemove", (e) => { xCursor(e.x); yCursor(e.y); gsap.to(cursorStroke, { duration: 0.2, x: e.clientX, y: e.clientY, }); }); // Funkcja obsługująca hover na linkach/przyciskach const handleHover = (element, opacityOnHover, scaleOnHover, duration = 0.4, ease = "power3.inOut") => { element.addEventListener("mouseover", () => { cursor.style.opacity = opacityOnHover; cursorStroke.style.opacity = opacityOnHover; gsap.to(cursorStroke, { scale: scaleOnHover, duration, ease }); }); element.addEventListener("mouseout", () => { cursor.style.opacity = 1; cursorStroke.style.opacity = 1; gsap.to(cursorStroke, { scale: 1, duration, ease }); }); }; interactiveElements.forEach((elem) => handleHover(elem, 0, 1.75)); document.addEventListener("mousedown", () => { gsap.to(cursorStroke, { scale: 1.5, ease: "power2.in", }); }); document.addEventListener("mouseup", () => { gsap.to(cursorStroke, { scale: 1, delay: 0.3, ease: "power2.out", }); }); const orangeSection = document.querySelector(".section_process"); orangeSection.addEventListener("mouseover", () => { cursorStroke.style.borderColor = 'var(--black)'; }); orangeSection.addEventListener('mouseout', () => { cursorStroke.style.borderColor = 'var(--swatch--brand)'; }); })(); // =============== StartScript =============== window.addEventListener("load", () => { // =============== NAVBAR SCROLL ANIMATIONS =============== (function initNavbar() { const navLoad = gsap.timeline(); navLoad.fromTo( "#logo path", { filter: "blur(1rem)", yPercent: -50, opacity: 0 }, { filter: "blur(0rem)", yPercent: 0, opacity: 1, ease: "power3.out", stagger: 0.05, } ); let navbarLogoWrapper = document.querySelector( ".navbar_logo_wrapper" ).offsetHeight; let startPosition = `top+=${navbarLogoWrapper}px top`; function navChange() { navbarLogoWrapper = document.querySelector( ".navbar_logo_wrapper" ).offsetHeight; startPosition = `top+=${navbarLogoWrapper}px top`; ScrollTrigger.refresh(); } window.addEventListener("resize", navChange); // Pojawianie się / znikanie Nav const showAnim = gsap .fromTo( ".nav_component", { yPercent: -150, opacity: 0 }, { yPercent: 0, opacity: 1, paused: true, duration: 0.45, ease: "power3.inOut", } ) .progress(1); let navTrigger = ScrollTrigger.create({ start: "top top", end: 99999, onUpdate: (self) => { self.direction === -1 ? showAnim.play() : showAnim.reverse(); }, }); // Po wejściu w obszar stopki ScrollTrigger.create({ trigger: ".footer", start: "top bottom", onEnter: () => { navTrigger.disable(); showAnim.restart(true); }, onLeaveBack: () => { navTrigger.enable(); showAnim.pause(); }, }); })(); // =============== ANIMACJA CTA =============== const splitMission = new SplitType("#why", { types: "words, chars", }); const tlInfo = gsap .timeline({ scrollTrigger: { trigger: ".section_one-column", start: "center 80%", end: "center center", scrub: 1.5, // pin: true }, }) .from(splitMission.chars, { opacity: 0.05 , scale: 0.95, filter:"blur(" + 8 + "px)", stagger: 0.01, yPercent: 10, duration: 0.1, }); const split = new SplitType(".main_cta_component h2, .main_cta_component p", { types: "words, chars", }); gsap.timeline({ scrollTrigger: { trigger: ".section_main_cta", start: "center 80%", end: "center center", scrub: 2, }, }).from(split.chars, { opacity: 0.1, filter: "blur(1rem)", scale: 0.9, stagger: 0.01, yPercent: 10, duration: 0.1, }); }, "500"); gsap.utils.toArray(".services_process-card").forEach((card, index) => { gsap.from(card, { yPercent: 50, opacity: 0, filter: "blur(.5rem)", duration: 0.8, delay: index * 0.3, ease: "power3.out", scrollTrigger: { trigger: card, start: "top 85%", end: "bottom 20%", toggleActions: "play none none none", } }); }); // =============== ANIMACJA Zdjęć =============== let splide = new Splide( '.splide', { type : 'loop', drag : 'free', gap: '1.5rem', pagination: false, arrows: false, autoWidth: true, autoScroll: { speed: 2, }, } ); splide.mount( window.splide.Extensions ); const portfolioItems = document.querySelectorAll('.portfolio_item_wrapper'); portfolioItems.forEach(item => { // Po najechaniu kursorem item.addEventListener('mouseenter', () => { // Znajdź dziecko