function initHomeAnimations() { const canvasContainer = document.getElementById("homecanvas"); if (!canvasContainer) { console.warn("No canvas container found on the contributions page."); return; } loadCablesScript( "https://cdn.prod.website-files.com/670e3bce95be1572f35a93bc/6755eb81df4c47e427d17fa8_last-patchv2.txt", () => { if (typeof CABLES !== "undefined" && CABLES.exportedPatch) { CABLES.patch = new CABLES.Patch({ patch: CABLES.exportedPatch, prefixAssetPath: "", assetPath: "assets/", jsPath: "js/", glCanvasId: "homecanvas", glCanvasResizeToWindow: false, onError: showError, onPatchLoaded: patchInitialized, onFinishedLoading: patchFinishedLoading, canvas: { alpha: true, premultipliedAlpha: true }, variables: { fillBg: 0, }, }); console.log("CablesGL Patch Initialized on Contributions."); } else { console.error("CABLES or exportedPatch is undefined."); } } ); document.querySelector("#homecanvas").addEventListener("touchend", () => { // Reset the active element to the body document.body.focus(); // Remove the 'touch-action: none;' style from the body document.body.style.touchAction = ""; }); document.querySelector("#homecanvas").addEventListener("blur", () => { // Reset the active element to the body document.body.focus(); // Remove the 'touch-action: none;' style from the body document.body.style.touchAction = ""; }); document.addEventListener("DOMContentLoaded", () => { const currentUrl = window.location.href; const menuLinks = document.querySelectorAll(".menu-link-wrap"); menuLinks.forEach((link) => { if (link.href === currentUrl) { link.style.display = "none"; } }); }); let typeSplit = new SplitType(".footer-link, .menu-item-prefix", { types: "words, chars", tagName: "span", }); function getRandomLetter(length) { var result = ""; var characters = "{}[]();<>!?$%^&*"; var charactersLength = characters.length; for (var i = 0; i < length; i++) { result += characters.charAt(Math.floor(Math.random() * charactersLength)); } return result; } $(".char").each(function (index) { let text = $(this).text(); $(this).attr("letter", text); }); $(".footer-link").each(function (index) { function resetText() { if (myInterval !== undefined) { clearInterval(myInterval); } chars.each(function (index) { let letter = $(this).attr("letter"); $(this).text(letter); $(this).css("background-color", "transparent"); $(this).css("color", ""); }); } let myInterval; let chars = $(this).find(".char"); function startEffect() { let length = chars.length; let currentIndex = 0; let previousIndex = -1; myInterval = setInterval(function () { if (previousIndex >= 0) { let previousCharElement = chars.eq(previousIndex); let originalLetter = previousCharElement.attr("letter"); previousCharElement.text(originalLetter); previousCharElement.css("background-color", "transparent"); previousCharElement.css("color", ""); } if (currentIndex < length) { let charElement = chars.eq(currentIndex); let letter = getRandomLetter(1); charElement.text(letter); charElement.css("background-color", "#6EF0DC"); charElement.css("color", "#0a0a0a"); previousIndex = currentIndex; currentIndex++; } else { clearInterval(myInterval); setTimeout(() => { resetText(); }, 200); // Wait before resetting the text } }, 70); // Adjust the speed here if needed } $(this).on("mouseenter touchstart", function () { startEffect(); // Start the effect on hover or touchstart (for mobile) }); $(this).on("mouseleave touchend", function () { resetText(); // Reset the text when mouse leaves or finger is lifted }); }); document.querySelectorAll(".menu-link-wrap").forEach((menuLink) => { menuLink.addEventListener("mouseenter", () => { gsap.set(menuLink.querySelector(".menu-item-prefix"), { opacity: 1 }); gsap.set(menuLink.querySelector(".menu-item-sufix"), { opacity: 1 }); // Check if the viewport width is greater than or equal to 768px (non-mobile) const isMobile = window.innerWidth < 768; if (!isMobile) { gsap.set( ".menu-item-label, .logo-header-wrap, .section-home-header, .footer-links-wrap", { color: "#8C8C8C" } ); } else { gsap.set(".menu-item-label, .section-home-header", { color: "#8C8C8C", }); } gsap.set(menuLink.querySelector(".menu-item-label"), { color: "#FFFFFF", opacity: 1, }); // Animate each .char child of .word elements within menu-item-prefix one by one, sequentially const menuChars = menuLink.querySelectorAll( ".menu-item-prefix .word .char" ); let menuTimeline = gsap.timeline({ defaults: { duration: 0.07, ease: "none" }, }); Array.from(menuChars).forEach((char) => { menuTimeline.fromTo( char, { color: "#0a0a0a", backgroundColor: "transparent" }, { color: "#6EF0DC", backgroundColor: "#6EF0DC", onComplete: () => { gsap.set(char, { backgroundColor: "transparent" }); // Ensure background reverts after reveal }, } ); }); }); menuLink.addEventListener("mouseleave", () => { gsap.set(menuLink.querySelector(".menu-item-prefix"), { opacity: 0 }); gsap.set(menuLink.querySelector(".menu-item-sufix"), { opacity: 0 }); gsap.set( ".menu-item-label, .logo-header-wrap, .section-home-header, .footer-links-wrap", { color: "#FFFFFF", opacity: 1 } ); }); // Add click event listener to reduce opacity of other menu links menuLink.addEventListener("click", () => { // Check if the link has #opportunities in its href if (menuLink.href.includes("#opportunities")) { menuLink.setAttribute("data-animation", "third-out"); } else { menuLink.setAttribute("data-animation", "fourth-out"); } // Check if the viewport width is less than 768px (mobile) const isMobile = window.innerWidth < 768; if (isMobile) { // Check for an element with data-top attribute and remove it const currentTopElement = document.querySelector("[data-top]"); if (currentTopElement) { currentTopElement.removeAttribute("data-top"); } // Add data-top attribute to the .mobile-navbar element const mobileNavbar = document.querySelector(".mobile-navbar"); if (mobileNavbar) { mobileNavbar.setAttribute("data-top", ""); } } // Reduce opacity of all other menu links over 0.3 seconds document.querySelectorAll(".menu-link-wrap").forEach((otherLink) => { if (otherLink !== menuLink) { gsap.to(otherLink, { opacity: 0, duration: 0.3 }); otherLink.style.pointerEvents = "none"; // Disable pointer events for non-clicked links } }); // Disable pointer events for the clicked link as well menuLink.style.pointerEvents = "none"; // Reduce opacity of all children of the clicked link except .menu-item-label menuLink.querySelectorAll("*:not(.menu-item-label)").forEach((child) => { gsap.to(child, { opacity: 0, duration: 0.3 }); }); }); }); // Add click event listener for elements with data-homepage attribute document.querySelectorAll("[data-homepage]").forEach((homepageElement) => { homepageElement.addEventListener("click", () => { // Add data-animation="third-out" to the .menu-wrap element const menuWrap = document.querySelector(".menu-wrap"); if (menuWrap) { menuWrap.setAttribute("data-animation", "third-out"); } // Add data-animation="third-out" to the .mobile-menu-wrap element const mobileMenuWrap = document.querySelector(".mobile-menu-wrap"); if (mobileMenuWrap) { mobileMenuWrap.setAttribute("data-animation", "third-out"); } }); }); // Initial state setup using GSAP to make sure everything is set as expected gsap.set(".menu-item-prefix, .menu-item-sufix", { opacity: 0 }); gsap.set( ".menu-item-label, .section-home-header, .footer-links-wrap", { opacity: 1, color: "#FFFFFF" } ); } function initPortfolioAnimations() { const canvasContainer = document.getElementById("portfoliocanvas"); if (!canvasContainer) { console.warn("No canvas container found on the contributions page."); return; } loadCablesScript( "https://cdn.prod.website-files.com/670e3bce95be1572f35a93bc/6755eb81df4c47e427d17fa8_last-patchv2.txt", () => { if (typeof CABLES !== "undefined" && CABLES.exportedPatch) { CABLES.patch = new CABLES.Patch({ patch: CABLES.exportedPatch, prefixAssetPath: "", assetPath: "assets/", jsPath: "js/", glCanvasId: "portfoliocanvas", glCanvasResizeToWindow: false, onError: showError, onPatchLoaded: patchInitialized, onFinishedLoading: patchFinishedLoading, canvas: { alpha: true, premultipliedAlpha: true }, variables: { fillBg: 0, }, }); console.log("CablesGL Patch Initialized on Contributions."); } else { console.error("CABLES or exportedPatch is undefined."); } } ); document .querySelector("#portfoliocanvas") .addEventListener("touchend", () => { // Reset the active element to the body // document.body.focus(); // Remove the 'touch-action: none;' style from the body document.body.style.touchAction = ""; }); document.querySelector("#portfoliocanvas").addEventListener("blur", () => { // Reset the active element to the body // document.body.focus(); // Remove the 'touch-action: none;' style from the body document.body.style.touchAction = ""; }); document.addEventListener("DOMContentLoaded", () => { const currentUrl = window.location.href; const menuLinks = document.querySelectorAll(".menu-link-wrap"); menuLinks.forEach((link) => { if (link.href === currentUrl) { link.style.display = "none"; } }); }); let typeSplit = new SplitType( ".footer-link, .products-text-visit-website, .accordion-button-wrap, .menu-item-prefix", { types: "words, chars", tagName: "span", } ); function getRandomLetter(length) { var result = ""; var characters = "{}[]();<>!?$%^&*"; var charactersLength = characters.length; for (var i = 0; i < length; i++) { result += characters.charAt(Math.floor(Math.random() * charactersLength)); } return result; } $(".char").each(function (index) { let text = $(this).text(); $(this).attr("letter", text); }); $(".footer-link, .products-text-visit-website, .accordion-button-wrap").each( function (index) { function resetText() { if (myInterval !== undefined) { clearInterval(myInterval); } chars.each(function (index) { let letter = $(this).attr("letter"); $(this).text(letter); $(this).css("background-color", "transparent"); // Reset background color $(this).css("color", ""); // Reset text color }); } let myInterval; let chars = $(this).find(".char"); function startEffect() { let length = chars.length; let currentIndex = 0; // Start from the first character let previousIndex = -1; // Track the previous character myInterval = setInterval(function () { // Reset the previous character back to normal if (previousIndex >= 0) { let previousCharElement = chars.eq(previousIndex); let originalLetter = previousCharElement.attr("letter"); previousCharElement.text(originalLetter); // Reset to original letter previousCharElement.css("background-color", "transparent"); // Reset background color previousCharElement.css("color", ""); // Reset text color } if (currentIndex < length) { let charElement = chars.eq(currentIndex); // Get the current character let letter = getRandomLetter(1); // Get a random letter charElement.text(letter); // Replace the character with the random letter charElement.css("background-color", "#6EF0DC"); // Change background color charElement.css("color", "#0a0a0a"); // Change text color to black previousIndex = currentIndex; // Set the previous index to the current one currentIndex++; // Move to the next character } else { clearInterval(myInterval); // Stop the interval when all characters are processed setTimeout(() => { resetText(); }, 200); // Wait before resetting the text } }, 70); // Adjust the speed here if needed } $(this).on("mouseenter touchstart", function () { startEffect(); // Start the effect on hover or touchstart (for mobile) }); $(this).on("mouseleave touchend", function () { resetText(); // Reset the text when mouse leaves or finger is lifted }); } ); document.querySelectorAll(".menu-link-wrap").forEach((menuLink) => { menuLink.addEventListener("mouseenter", () => { gsap.set(menuLink.querySelector(".menu-item-prefix"), { opacity: 1 }); gsap.set(menuLink.querySelector(".menu-item-sufix"), { opacity: 1 }); gsap.set(".menu-item-label, .logo-header-wrap, .section-home-header", { color: "#8C8C8C", }); gsap.set(menuLink.querySelector(".menu-item-label"), { color: "#FFFFFF", opacity: 1, }); // Animate each .char child of .word elements within menu-item-prefix one by one, sequentially const menuChars = menuLink.querySelectorAll( ".menu-item-prefix .word .char" ); let menuTimeline = gsap.timeline({ defaults: { duration: 0.07, ease: "none" }, }); Array.from(menuChars).forEach((char) => { menuTimeline.fromTo( char, { color: "#0a0a0a", backgroundColor: "transparent" }, { color: "#6EF0DC", backgroundColor: "#6EF0DC", onComplete: () => { gsap.set(char, { backgroundColor: "transparent" }); // Ensure background reverts after reveal }, } ); }); }); menuLink.addEventListener("mouseleave", () => { gsap.set(menuLink.querySelector(".menu-item-prefix"), { opacity: 0 }); gsap.set(menuLink.querySelector(".menu-item-sufix"), { opacity: 0 }); gsap.set(".menu-item-label, .logo-header-wrap, .section-home-header", { color: "#FFFFFF", opacity: 1, }); }); // Add click event listener to reduce opacity of other menu links menuLink.addEventListener("click", () => { // Check if the link has #opportunities in its href if (menuLink.href.includes("#opportunities")) { menuLink.setAttribute("data-animation", "third-out"); } else { menuLink.setAttribute("data-animation", "fourth-out"); } // Reduce opacity of all other menu links over 1 second document.querySelectorAll(".menu-link-wrap").forEach((otherLink) => { if (otherLink !== menuLink) { gsap.to(otherLink, { opacity: 0, duration: 0.3 }); otherLink.style.pointerEvents = "none"; // Disable pointer events for non-clicked links } }); // Disable pointer events for the clicked link as well menuLink.style.pointerEvents = "none"; // Reduce opacity of all children of the clicked link except .menu-item-label menuLink.querySelectorAll("*:not(.menu-item-label)").forEach((child) => { gsap.to(child, { opacity: 0, duration: 0.3 }); }); }); }); // Add click event listener for elements with data-homepage attribute document.querySelectorAll("[data-homepage]").forEach((homepageElement) => { homepageElement.addEventListener("click", () => { // Add data-animation="third-out" to the .menu-wrap element const menuWrap = document.querySelector(".menu-wrap"); if (menuWrap) { menuWrap.setAttribute("data-animation", "third-out"); } // Add data-animation="third-out" to the .mobile-menu-wrap element const mobileMenuWrap = document.querySelector(".mobile-menu-wrap"); if (mobileMenuWrap) { mobileMenuWrap.setAttribute("data-animation", "third-out"); } }); }); // Select all the accordion elements const accordions = document.querySelectorAll(".products-accordion-wrap"); // Function to check if the device is mobile function isMobile() { return window.matchMedia("(max-width: 768px)").matches; } // Loop through each accordion element and add event listeners accordions.forEach((accordion, index) => { // Define descriptionWrap for each accordion const descriptionWrap = accordion.querySelector( ".products-description-wrap" ); accordion.isOpen = false; accordion.addEventListener("mouseenter", () => { if (isMobile()) return; // Skip hover effect if the accordion is open if (accordion.isOpen) { return; } // Set color for the text within the hovered item const headline = accordion .closest(".products-collection-item") .querySelector(".products-collection-headline"); if (headline) { headline.style.color = "#6EF0DC"; } // Set the bottom border color of the hovered item's content const itemContent = accordion .closest(".products-collection-item") .querySelector(".products-collection-item-content"); if (itemContent) { itemContent.style.borderBottomColor = "#6EF0DC"; } // Set the previous item's border color if it exists if (index > 0) { setTimeout(() => { const previousItem = accordions[index - 1] .closest(".products-collection-item") .querySelector(".products-collection-item-content"); if (previousItem) { previousItem.style.borderBottomColor = "#6EF0DC"; } }, 10); // Delay to ensure hover styles are set first } // Set all other items to greyed-out colors if they are not open accordions.forEach((otherAccordion) => { if (otherAccordion !== accordion) { const otherHeadline = otherAccordion .closest(".products-collection-item") .querySelector(".products-collection-headline"); const otherItemContent = otherAccordion .closest(".products-collection-item") .querySelector(".products-collection-item-content"); if (!otherAccordion.isOpen) { if (otherHeadline) { otherHeadline.style.color = "#8C8C8C"; } if (otherItemContent) { otherItemContent.style.borderBottomColor = "#8C8C8C"; } } } }); // Animate characters of the products text on hover if not open if (!accordion.isOpen) { const productsChars = accordion.querySelectorAll( ".products-text-visit-website .word .char" ); let productsTimeline = gsap.timeline({ defaults: { duration: 0.07, ease: "none" }, }); Array.from(productsChars).forEach((char) => { productsTimeline.fromTo( char, { color: "#0a0a0a", backgroundColor: "transparent" }, { color: "#6EF0DC", backgroundColor: "#6EF0DC", onComplete: () => { gsap.set(char, { backgroundColor: "transparent" }); }, } ); }); } // Set the opacity of the products text to 1 instantly if not open if (!accordion.isOpen) { gsap.set(accordion.querySelector(".products-text-visit-website"), { opacity: 1, }); } }); accordion.addEventListener("mouseleave", () => { if (isMobile()) return; // Reset color and border-bottom color for the hovered accordion if not open const headline = accordion .closest(".products-collection-item") .querySelector(".products-collection-headline"); const itemContent = accordion .closest(".products-collection-item") .querySelector(".products-collection-item-content"); if (!accordion.isOpen) { if (headline) { headline.style.color = "#FFFFFF"; } if (itemContent) { itemContent.style.borderBottomColor = "#FFFFFF"; } } // Reset all other items to their default state if not open accordions.forEach((otherAccordion) => { if (!otherAccordion.isOpen) { const otherHeadline = otherAccordion .closest(".products-collection-item") .querySelector(".products-collection-headline"); const otherItemContent = otherAccordion .closest(".products-collection-item") .querySelector(".products-collection-item-content"); if (otherHeadline) { otherHeadline.style.color = "#FFFFFF"; } if (otherItemContent) { otherItemContent.style.borderBottomColor = "#FFFFFF"; } } }); // If the previous accordion is open, set its border-bottom back to white if (index > 0 && accordions[index - 1].isOpen) { const previousItemContent = accordions[index - 1] .closest(".products-collection-item") .querySelector(".products-collection-item-content"); if (previousItemContent) { previousItemContent.style.borderBottomColor = "#FFFFFF"; } } // Set the opacity of the products text to 0 instantly if not open if (!accordion.isOpen) { gsap.set(accordion.querySelector(".products-text-visit-website"), { opacity: 0, }); } }); accordion.addEventListener("click", (event) => { // Prevent closing the accordion when clicking inside the descriptionWrap if (descriptionWrap.contains(event.target)) { return; } // Close all other accordions accordions.forEach((otherAccordion) => { const otherDescriptionWrap = otherAccordion.querySelector( ".products-description-wrap" ); if (otherAccordion !== accordion && otherAccordion.isOpen) { gsap.to(otherDescriptionWrap, { height: 0, duration: 0.3, ease: "power1.out", }); otherAccordion.isOpen = false; // Set the opacity of the products text view less to 0 when another accordion is closed gsap.set(otherAccordion.querySelector(".products-text-view-less"), { opacity: 0, }); // Reset the color of the previously open accordion to grey const otherHeadline = otherAccordion.querySelector( ".products-collection-headline" ); if (otherHeadline) { otherHeadline.style.color = "#8C8C8C"; } // Set the bottom border color of the content item to gray when the accordion is closed const otherItemContent = otherAccordion.querySelector( ".products-collection-item-content" ); if (otherItemContent) { otherItemContent.style.borderBottomColor = "#8C8C8C"; } } }); // Toggle the clicked accordion accordion.isOpen = !accordion.isOpen; gsap.to(descriptionWrap, { height: accordion.isOpen ? "auto" : 0, duration: 0.3, ease: "power1.out", }); if (accordion.isOpen) { // Set the opacity of the products text to 0 instantly when the accordion is opened gsap.set(accordion.querySelector(".products-text-visit-website"), { opacity: 0, }); // Set the opacity of the products text view less to 1 instantly when the accordion is opened gsap.set(accordion.querySelector(".products-text-view-less"), { opacity: 1, }); // Set the color of the headline to white when the accordion is opened const headline = accordion.querySelector( ".products-collection-headline" ); if (headline) { headline.style.color = "#FFFFFF"; } // Set the bottom border color of the content item to white when the accordion is opened const itemContent = accordion.querySelector( ".products-collection-item-content" ); if (itemContent) { itemContent.style.borderBottomColor = "#FFFFFF"; } // Set the previous item's border color to white if it exists if (index > 0) { const previousItem = accordions[index - 1]; const previousItemContent = previousItem .closest(".products-collection-item") .querySelector(".products-collection-item-content"); if (previousItemContent) { previousItemContent.style.borderBottomColor = "#FFFFFF"; } } } else { // Set the opacity of the products text view less to 0 when the accordion is closed gsap.set(accordion.querySelector(".products-text-view-less"), { opacity: 0, }); // If the accordion is closed and still hovered, reapply the hover effect if (!accordion.isOpen && accordion.matches(":hover")) { // Manually trigger the hover logic to reapply hover effect after closing const headline = accordion .closest(".products-collection-item") .querySelector(".products-collection-headline"); if (headline) { headline.style.color = "#6EF0DC"; } const itemContent = accordion .closest(".products-collection-item") .querySelector(".products-collection-item-content"); if (itemContent) { itemContent.style.borderBottomColor = "#6EF0DC"; } // Set the previous item's border color to green if it exists if (index > 0) { const previousItem = accordions[index - 1]; const previousItemContent = previousItem .closest(".products-collection-item") .querySelector(".products-collection-item-content"); if (previousItemContent) { previousItemContent.style.borderBottomColor = "#6EF0DC"; } } gsap.set(accordion.querySelector(".products-text-visit-website"), { opacity: 1, }); } } }); }); // Mobile version accordion functionality const mobileAccordions = document.querySelectorAll( ".products-accordion-wrap-mobile" ); mobileAccordions.forEach((accordion, index) => { const descriptionWrap = accordion.querySelector( ".products-description-wrap-mobile" ); const crossVertical = accordion.querySelector(".cross-vertical"); accordion.isOpen = false; accordion.addEventListener("click", (event) => { // Prevent closing the accordion when clicking inside the descriptionWrap if (descriptionWrap.contains(event.target)) { return; } // Close all other accordions mobileAccordions.forEach((otherAccordion, otherIndex) => { const otherDescriptionWrap = otherAccordion.querySelector( ".products-description-wrap-mobile" ); const otherCrossVertical = otherAccordion.querySelector(".cross-vertical"); if (otherAccordion !== accordion && otherAccordion.isOpen) { gsap.to(otherDescriptionWrap, { height: 0, duration: 0.3, ease: "power1.out", }); gsap.to(otherCrossVertical, { rotateZ: 0, duration: 0.3, ease: "power1.out", }); otherAccordion.isOpen = false; // Reset the border color and headline color to white for closed accordions gsap.set(otherAccordion, { borderBottomColor: "#FFFFFF", }); const otherHeadlineWrap = otherAccordion.querySelector( ".products-headline-wrap-mobile" ); const otherHeadlineChildren = otherHeadlineWrap.querySelectorAll("*"); gsap.set(otherHeadlineChildren, { color: "#FFFFFF", }); } }); // Toggle the clicked accordion accordion.isOpen = !accordion.isOpen; gsap.to(descriptionWrap, { height: accordion.isOpen ? "auto" : 0, duration: 0.3, ease: "power1.out", }); gsap.to(crossVertical, { rotateZ: accordion.isOpen ? 90 : 0, duration: 0.3, ease: "power1.out", }); const headlineWrap = accordion.querySelector( ".products-headline-wrap-mobile" ); const headlineChildren = headlineWrap.querySelectorAll("*"); if (accordion.isOpen) { // Set the clicked accordion's headline children color to green when open gsap.set(headlineChildren, { color: "#6EF0DC", }); // Set the clicked accordion's border color to green when open gsap.set(accordion, { borderBottomColor: "#6EF0DC", }); // Set the previous accordion's border to green if it exists if (index > 0) { const previousAccordion = mobileAccordions[index - 1]; gsap.set(previousAccordion, { borderBottomColor: "#6EF0DC", }); } } else { // Reset the clicked accordion's headline children color to white when closed gsap.set(headlineChildren, { color: "#FFFFFF", }); // Reset the clicked accordion's border color to white when closed gsap.set(accordion, { borderBottomColor: "#FFFFFF", }); } // Set the color of non-clicked accordions based on their open/close state mobileAccordions.forEach((otherAccordion, otherIndex) => { if (otherAccordion !== accordion) { const otherHeadlineWrap = otherAccordion.querySelector( ".products-headline-wrap-mobile" ); const otherHeadlineChildren = otherHeadlineWrap.querySelectorAll("*"); // Non-clicked accordions should have grey headline children and border bottom color when one is open gsap.set(otherHeadlineChildren, { color: accordion.isOpen ? "#8C8C8C" : "#FFFFFF", }); // If the current accordion is the one directly preceding the open accordion, set border color to green if (otherIndex === index - 1 && accordion.isOpen) { gsap.set(otherAccordion, { borderBottomColor: "#6EF0DC", }); } else { gsap.set(otherAccordion, { borderBottomColor: accordion.isOpen ? "#8C8C8C" : "#FFFFFF", }); } } }); // If all accordions are closed, reset all to full color if (mobileAccordions.every((acc) => !acc.isOpen)) { mobileAccordions.forEach((otherAccordion) => { const otherHeadlineWrap = otherAccordion.querySelector( ".products-headline-wrap-mobile" ); const otherHeadlineChildren = otherHeadlineWrap.querySelectorAll("*"); gsap.set(otherAccordion, { borderBottomColor: "#FFFFFF", }); gsap.set(otherHeadlineChildren, { color: "#FFFFFF", }); }); } }); }); // Initial state setup using GSAP to make sure everything is set as expected gsap.set(".menu-item-prefix, .menu-item-sufix", { opacity: 0 }); gsap.set(".menu-item-label, .logo-header-wrap, .section-home-header", { opacity: 1, color: "#FFFFFF", }); gsap.set(".products-text-visit-website", { opacity: 0 }); gsap.set(".products-content-collection-item", { opacity: 1, color: "#FFFFFF", }); gsap.set( ".products-headline-wrap .products-company-name, .products-headline-wrap .products-industry, .products-headline-wrap .products_icon-wrapper", { color: "#FFFFFF" } ); gsap.set(".products-description-wrap", { height: 0 }); gsap.set(".products-accordion-wrap", { borderBottomColor: "#FFFFFF" }); // Initial border-bottom color to grey } function initContributionsAnimations() { const canvasContainer = document.getElementById("contcanvas"); if (!canvasContainer) { console.warn("No canvas container found on the contributions page."); return; } loadCablesScript( "https://cdn.prod.website-files.com/670e3bce95be1572f35a93bc/6755eb81df4c47e427d17fa8_last-patchv2.txt", () => { if (typeof CABLES !== "undefined" && CABLES.exportedPatch) { CABLES.patch = new CABLES.Patch({ patch: CABLES.exportedPatch, prefixAssetPath: "", assetPath: "assets/", jsPath: "js/", glCanvasId: "contcanvas", glCanvasResizeToWindow: false, onError: showError, onPatchLoaded: patchInitialized, onFinishedLoading: patchFinishedLoading, canvas: { alpha: true, premultipliedAlpha: true }, variables: { fillBg: 0, }, }); console.log("CablesGL Patch Initialized on Contributions."); } else { console.error("CABLES or exportedPatch is undefined."); } } ); document.querySelector("#contcanvas").addEventListener("touchend", () => { // Reset the active element to the body document.body.focus(); // Remove the 'touch-action: none;' style from the body document.body.style.touchAction = ""; }); document.querySelector("#contcanvas").addEventListener("blur", () => { // Reset the active element to the body document.body.focus(); // Remove the 'touch-action: none;' style from the body document.body.style.touchAction = ""; }); document.addEventListener("DOMContentLoaded", () => { const currentUrl = window.location.href; const menuLinks = document.querySelectorAll(".menu-link-wrap"); menuLinks.forEach((link) => { if (link.href === currentUrl) { link.style.display = "none"; } }); }); let typeSplit = new SplitType( ".footer-link, .products-text-visit-website, .accordion-button-wrap, .menu-item-prefix", { types: "words, chars", tagName: "span", } ); function getRandomLetter(length) { var result = ""; var characters = "{}[]();<>!?$%^&*"; var charactersLength = characters.length; for (var i = 0; i < length; i++) { result += characters.charAt(Math.floor(Math.random() * charactersLength)); } return result; } $(".char").each(function (index) { let text = $(this).text(); $(this).attr("letter", text); }); $(".footer-link, .accordion-button-wrap").each(function (index) { function resetText() { if (myInterval !== undefined) { clearInterval(myInterval); } chars.each(function (index) { let letter = $(this).attr("letter"); $(this).text(letter); $(this).css("background-color", "transparent"); // Reset background color $(this).css("color", ""); // Reset text color }); } let myInterval; let chars = $(this).find(".char"); function startEffect() { let length = chars.length; let currentIndex = 0; // Start from the first character let previousIndex = -1; // Track the previous character myInterval = setInterval(function () { // Reset the previous character back to normal if (previousIndex >= 0) { let previousCharElement = chars.eq(previousIndex); let originalLetter = previousCharElement.attr("letter"); previousCharElement.text(originalLetter); // Reset to original letter previousCharElement.css("background-color", "transparent"); // Reset background color previousCharElement.css("color", ""); // Reset text color } if (currentIndex < length) { let charElement = chars.eq(currentIndex); // Get the current character let letter = getRandomLetter(1); // Get a random letter charElement.text(letter); // Replace the character with the random letter charElement.css("background-color", "#6EF0DC"); // Change background color charElement.css("color", "#0a0a0a"); // Change text color to black previousIndex = currentIndex; // Set the previous index to the current one currentIndex++; // Move to the next character } else { clearInterval(myInterval); // Stop the interval when all characters are processed setTimeout(() => { resetText(); }, 200); // Wait before resetting the text } }, 70); // Adjust the speed here if needed } $(this).on("mouseenter touchstart", function () { startEffect(); // Start the effect on hover or touchstart (for mobile) }); $(this).on("mouseleave touchend", function () { resetText(); // Reset the text when mouse leaves or finger is lifted }); }); document.querySelectorAll(".menu-link-wrap").forEach((menuLink) => { menuLink.addEventListener("mouseenter", () => { gsap.set(menuLink.querySelector(".menu-item-prefix"), { opacity: 1 }); gsap.set(menuLink.querySelector(".menu-item-sufix"), { opacity: 1 }); gsap.set(".menu-item-label, .logo-header-wrap, .section-home-header", { color: "#8C8C8C", }); gsap.set(menuLink.querySelector(".menu-item-label"), { color: "#FFFFFF", opacity: 1, }); // Animate each .char child of .word elements within menu-item-prefix one by one, sequentially const menuChars = menuLink.querySelectorAll( ".menu-item-prefix .word .char" ); let menuTimeline = gsap.timeline({ defaults: { duration: 0.07, ease: "none" }, }); Array.from(menuChars).forEach((char) => { menuTimeline.fromTo( char, { color: "#0a0a0a", backgroundColor: "transparent" }, { color: "#6EF0DC", backgroundColor: "#6EF0DC", onComplete: () => { gsap.set(char, { backgroundColor: "transparent" }); // Ensure background reverts after reveal }, } ); }); }); menuLink.addEventListener("mouseleave", () => { gsap.set(menuLink.querySelector(".menu-item-prefix"), { opacity: 0 }); gsap.set(menuLink.querySelector(".menu-item-sufix"), { opacity: 0 }); gsap.set(".menu-item-label, .logo-header-wrap, .section-home-header", { color: "#FFFFFF", opacity: 1, }); }); // Add click event listener to reduce opacity of other menu links menuLink.addEventListener("click", () => { // Check if the link has #opportunities in its href if (menuLink.href.includes("#opportunities")) { menuLink.setAttribute("data-animation", "third-out"); } else { menuLink.setAttribute("data-animation", "fourth-out"); } // Reduce opacity of all other menu links over 1 second document.querySelectorAll(".menu-link-wrap").forEach((otherLink) => { if (otherLink !== menuLink) { gsap.to(otherLink, { opacity: 0, duration: 0.3 }); otherLink.style.pointerEvents = "none"; // Disable pointer events for non-clicked links } }); // Disable pointer events for the clicked link as well menuLink.style.pointerEvents = "none"; // Reduce opacity of all children of the clicked link except .menu-item-label menuLink.querySelectorAll("*:not(.menu-item-label)").forEach((child) => { gsap.to(child, { opacity: 0, duration: 0.3 }); }); }); }); // Add click event listener for elements with data-homepage attribute document.querySelectorAll("[data-homepage]").forEach((homepageElement) => { homepageElement.addEventListener("click", () => { // Add data-animation="third-out" to the .menu-wrap element const menuWrap = document.querySelector(".menu-wrap"); if (menuWrap) { menuWrap.setAttribute("data-animation", "third-out"); } // Add data-animation="third-out" to the .mobile-menu-wrap element const mobileMenuWrap = document.querySelector(".mobile-menu-wrap"); if (mobileMenuWrap) { mobileMenuWrap.setAttribute("data-animation", "third-out"); } }); }); // Select all the accordion elements const accordions = document.querySelectorAll(".contributions-accordion-wrap"); // Function to check if the device is mobile function isMobile() { return window.matchMedia("(max-width: 768px)").matches; } // Loop through each accordion element and add event listeners accordions.forEach((accordion, index) => { // Define descriptionWrap for each accordion const descriptionWrap = accordion.querySelector( ".contributions-description-wrap" ); accordion.isOpen = false; accordion.addEventListener("mouseenter", () => { if (isMobile()) return; // Skip hover effect if the accordion is open if (accordion.isOpen) { return; } // Set color for the text within the hovered item const headline = accordion .closest(".contributions-collection-item") .querySelector(".contributions-collection-headline"); if (headline) { headline.style.color = "#6EF0DC"; } // Set the bottom border color of the hovered item's content const itemContent = accordion .closest(".contributions-collection-item") .querySelector(".contributions-collection-item-content"); if (itemContent) { itemContent.style.borderBottomColor = "#6EF0DC"; } // Set the previous item's border color if it exists if (index > 0) { setTimeout(() => { const previousItem = accordions[index - 1] .closest(".contributions-collection-item") .querySelector(".contributions-collection-item-content"); if (previousItem) { previousItem.style.borderBottomColor = "#6EF0DC"; } }, 10); // Delay to ensure hover styles are set first } // Set all other items to greyed-out colors if they are not open accordions.forEach((otherAccordion) => { if (otherAccordion !== accordion) { const otherHeadline = otherAccordion .closest(".contributions-collection-item") .querySelector(".contributions-collection-headline"); const otherItemContent = otherAccordion .closest(".contributions-collection-item") .querySelector(".contributions-collection-item-content"); if (!otherAccordion.isOpen) { if (otherHeadline) { otherHeadline.style.color = "#8C8C8C"; } if (otherItemContent) { otherItemContent.style.borderBottomColor = "#8C8C8C"; } } } }); // Animate characters of the products text on hover if not open if (!accordion.isOpen) { const contributionsChars = accordion.querySelectorAll( ".products-text-visit-website .word .char" ); let contributionsTimeline = gsap.timeline({ defaults: { duration: 0.07, ease: "none" }, }); Array.from(contributionsChars).forEach((char) => { contributionsTimeline.fromTo( char, { color: "#0a0a0a", backgroundColor: "transparent" }, { color: "#6EF0DC", backgroundColor: "#6EF0DC", onComplete: () => { gsap.set(char, { backgroundColor: "transparent" }); }, } ); }); } // Set the opacity of the products text to 1 instantly if not open if (!accordion.isOpen) { gsap.set(accordion.querySelector(".products-text-visit-website"), { opacity: 1, }); } }); accordion.addEventListener("mouseleave", () => { if (isMobile()) return; // Reset color and border-bottom color for the hovered accordion if not open const headline = accordion .closest(".contributions-collection-item") .querySelector(".contributions-collection-headline"); const itemContent = accordion .closest(".contributions-collection-item") .querySelector(".contributions-collection-item-content"); if (!accordion.isOpen) { if (headline) { headline.style.color = "#FFFFFF"; } if (itemContent) { itemContent.style.borderBottomColor = "#FFFFFF"; } } // Reset all other items to their default state if not open accordions.forEach((otherAccordion) => { if (!otherAccordion.isOpen) { const otherHeadline = otherAccordion .closest(".contributions-collection-item") .querySelector(".contributions-collection-headline"); const otherItemContent = otherAccordion .closest(".contributions-collection-item") .querySelector(".contributions-collection-item-content"); if (otherHeadline) { otherHeadline.style.color = "#FFFFFF"; } if (otherItemContent) { otherItemContent.style.borderBottomColor = "#FFFFFF"; } } }); // If the previous accordion is open, set its border-bottom back to white if (index > 0 && accordions[index - 1].isOpen) { const previousItemContent = accordions[index - 1] .closest(".contributions-collection-item") .querySelector(".contributions-collection-item-content"); if (previousItemContent) { previousItemContent.style.borderBottomColor = "#FFFFFF"; } } // Set the opacity of the products text to 0 instantly if not open if (!accordion.isOpen) { gsap.set(accordion.querySelector(".products-text-visit-website"), { opacity: 0, }); } }); accordion.addEventListener("click", (event) => { // Prevent closing the accordion when clicking inside the descriptionWrap if (descriptionWrap.contains(event.target)) { return; } // Close all other accordions accordions.forEach((otherAccordion) => { const otherDescriptionWrap = otherAccordion.querySelector( ".contributions-description-wrap" ); if (otherAccordion !== accordion && otherAccordion.isOpen) { gsap.to(otherDescriptionWrap, { height: 0, duration: 0.3, ease: "power1.out", }); otherAccordion.isOpen = false; // Set the opacity of the products text view less to 0 when another accordion is closed gsap.set(otherAccordion.querySelector(".products-text-view-less"), { opacity: 0, }); // Reset the color of the previously open accordion to grey const otherHeadline = otherAccordion.querySelector( ".contributions-collection-headline" ); if (otherHeadline) { otherHeadline.style.color = "#8C8C8C"; } // Set the bottom border color of the content item to gray when the accordion is closed const otherItemContent = otherAccordion.querySelector( ".contributions-collection-item-content" ); if (otherItemContent) { otherItemContent.style.borderBottomColor = "#8C8C8C"; } } }); // Toggle the clicked accordion accordion.isOpen = !accordion.isOpen; gsap.to(descriptionWrap, { height: accordion.isOpen ? "auto" : 0, duration: 0.3, ease: "power1.out", }); if (accordion.isOpen) { // Set the opacity of the products text to 0 instantly when the accordion is opened gsap.set(accordion.querySelector(".products-text-visit-website"), { opacity: 0, }); // Set the opacity of the products text view less to 1 instantly when the accordion is opened gsap.set(accordion.querySelector(".products-text-view-less"), { opacity: 1, }); // Set the color of the headline to white when the accordion is opened const headline = accordion.querySelector( ".contributions-collection-headline" ); if (headline) { headline.style.color = "#FFFFFF"; } // Set the bottom border color of the content item to white when the accordion is opened const itemContent = accordion.querySelector( ".contributions-collection-item-content" ); if (itemContent) { itemContent.style.borderBottomColor = "#FFFFFF"; } // Set the previous item's border color to white if it exists if (index > 0) { const previousItem = accordions[index - 1]; const previousItemContent = previousItem .closest(".contributions-collection-item") .querySelector(".contributions-collection-item-content"); if (previousItemContent) { previousItemContent.style.borderBottomColor = "#FFFFFF"; } } } else { // Set the opacity of the products text view less to 0 when the accordion is closed gsap.set(accordion.querySelector(".products-text-view-less"), { opacity: 0, }); // If the accordion is closed and still hovered, reapply the hover effect if (!accordion.isOpen && accordion.matches(":hover")) { // Manually trigger the hover logic to reapply hover effect after closing const headline = accordion .closest(".contributions-collection-item") .querySelector(".contributions-collection-headline"); if (headline) { headline.style.color = "#6EF0DC"; } const itemContent = accordion .closest(".contributions-collection-item") .querySelector(".contributions-collection-item-content"); if (itemContent) { itemContent.style.borderBottomColor = "#6EF0DC"; } // Set the previous item's border color to green if it exists if (index > 0) { const previousItem = accordions[index - 1]; const previousItemContent = previousItem .closest(".contributions-collection-item") .querySelector(".contributions-collection-item-content"); if (previousItemContent) { previousItemContent.style.borderBottomColor = "#6EF0DC"; } } gsap.set(accordion.querySelector(".products-text-visit-website"), { opacity: 1, }); } } }); }); // Mobile version accordion functionality const mobileAccordions = document.querySelectorAll( ".contributions-accordion-wrap-mobile" ); mobileAccordions.forEach((accordion, index) => { const descriptionWrap = accordion.querySelector( ".contributions-description-wrap-mobile" ); const crossVertical = accordion.querySelector(".cross-vertical"); accordion.isOpen = false; accordion.addEventListener("click", (event) => { // Prevent closing the accordion when clicking inside the descriptionWrap if (descriptionWrap.contains(event.target)) { return; } // Close all other accordions mobileAccordions.forEach((otherAccordion, otherIndex) => { const otherDescriptionWrap = otherAccordion.querySelector( ".contributions-description-wrap-mobile" ); const otherCrossVertical = otherAccordion.querySelector(".cross-vertical"); if (otherAccordion !== accordion && otherAccordion.isOpen) { gsap.to(otherDescriptionWrap, { height: 0, duration: 0.3, ease: "power1.out", }); gsap.to(otherCrossVertical, { rotateZ: 0, duration: 0.3, ease: "power1.out", }); otherAccordion.isOpen = false; // Reset the border color and headline color to white for closed accordions gsap.set(otherAccordion, { borderBottomColor: "#FFFFFF", }); const otherHeadlineWrap = otherAccordion.querySelector( ".contributions-headline-wrap-mobile" ); const otherHeadlineChildren = otherHeadlineWrap.querySelectorAll("*"); gsap.set(otherHeadlineChildren, { color: "#FFFFFF", }); } }); // Toggle the clicked accordion accordion.isOpen = !accordion.isOpen; gsap.to(descriptionWrap, { height: accordion.isOpen ? "auto" : 0, duration: 0.3, ease: "power1.out", }); gsap.to(crossVertical, { rotateZ: accordion.isOpen ? 90 : 0, duration: 0.3, ease: "power1.out", }); const headlineWrap = accordion.querySelector( ".contributions-headline-wrap-mobile" ); const headlineChildren = headlineWrap.querySelectorAll("*"); if (accordion.isOpen) { // Set the clicked accordion's headline children color to green when open gsap.set(headlineChildren, { color: "#6EF0DC", }); // Set the clicked accordion's border color to green when open gsap.set(accordion, { borderBottomColor: "#6EF0DC", }); // Set the previous accordion's border to green if it exists if (index > 0) { const previousAccordion = mobileAccordions[index - 1]; gsap.set(previousAccordion, { borderBottomColor: "#6EF0DC", }); } } else { // Reset the clicked accordion's headline children color to white when closed gsap.set(headlineChildren, { color: "#FFFFFF", }); // Reset the clicked accordion's border color to white when closed gsap.set(accordion, { borderBottomColor: "#FFFFFF", }); } // Set the color of non-clicked accordions based on their open/close state mobileAccordions.forEach((otherAccordion, otherIndex) => { if (otherAccordion !== accordion) { const otherHeadlineWrap = otherAccordion.querySelector( ".contributions-headline-wrap-mobile" ); const otherHeadlineChildren = otherHeadlineWrap.querySelectorAll("*"); // Non-clicked accordions should have grey headline children and border bottom color when one is open gsap.set(otherHeadlineChildren, { color: accordion.isOpen ? "#8C8C8C" : "#FFFFFF", }); // If the current accordion is the one directly preceding the open accordion, set border color to green if (otherIndex === index - 1 && accordion.isOpen) { gsap.set(otherAccordion, { borderBottomColor: "#6EF0DC", }); } else { gsap.set(otherAccordion, { borderBottomColor: accordion.isOpen ? "#8C8C8C" : "#FFFFFF", }); } } }); // If all accordions are closed, reset all to full color if (mobileAccordions.every((acc) => !acc.isOpen)) { mobileAccordions.forEach((otherAccordion) => { const otherHeadlineWrap = otherAccordion.querySelector( ".contributions-headline-wrap-mobile" ); const otherHeadlineChildren = otherHeadlineWrap.querySelectorAll("*"); gsap.set(otherAccordion, { borderBottomColor: "#FFFFFF", }); gsap.set(otherHeadlineChildren, { color: "#FFFFFF", }); }); } }); }); // Initial state setup using GSAP to make sure everything is set as expected gsap.set(".menu-item-prefix, .menu-item-sufix", { opacity: 0 }); gsap.set(".menu-item-label, .logo-header-wrap, .section-home-header", { opacity: 1, color: "#FFFFFF", }); gsap.set(".contributions-site", { opacity: 0, }); gsap.set(".accordion-button-wrap", { color: "#6EF0DC" }); gsap.set(".products-text-view-less", { opacity: 0 }); gsap.set(".contributions-content-collection-item", { opacity: 1, color: "#FFFFFF", }); gsap.set( ".contributors-headline-wrap .contributions-company-name, .contributors-headline-wrap .contributions-industry, .contributors-headline-wrap .contributions_icon-wrapper", { color: "#FFFFFF" } ); gsap.set(".contributors-description-wrap", { height: 0 }); gsap.set(".contributions-accordion-wrap", { borderBottomColor: "#FFFFFF" }); // Initial border-bottom color to grey } function initProductsAnimations() { const canvasContainer = document.getElementById("productscanvas"); if (!canvasContainer) { console.warn("No canvas container found on the contributions page."); return; } loadCablesScript( "https://cdn.prod.website-files.com/670e3bce95be1572f35a93bc/6755eb81df4c47e427d17fa8_last-patchv2.txt", () => { if (typeof CABLES !== "undefined" && CABLES.exportedPatch) { CABLES.patch = new CABLES.Patch({ patch: CABLES.exportedPatch, prefixAssetPath: "", assetPath: "assets/", jsPath: "js/", glCanvasId: "productscanvas", glCanvasResizeToWindow: false, onError: showError, onPatchLoaded: patchInitialized, onFinishedLoading: patchFinishedLoading, canvas: { alpha: true, premultipliedAlpha: true }, variables: { fillBg: 0, }, }); console.log("CablesGL Patch Initialized on Contributions."); } else { console.error("CABLES or exportedPatch is undefined."); } } ); document.querySelector("#productscanvas").addEventListener("touchend", () => { // Reset the active element to the body document.body.focus(); // Remove the 'touch-action: none;' style from the body document.body.style.touchAction = ""; }); document.querySelector("#productscanvas").addEventListener("blur", () => { // Reset the active element to the body document.body.focus(); // Remove the 'touch-action: none;' style from the body document.body.style.touchAction = ""; }); document.addEventListener("DOMContentLoaded", () => { const currentUrl = window.location.href; const menuLinks = document.querySelectorAll(".menu-link-wrap"); menuLinks.forEach((link) => { if (link.href === currentUrl) { link.style.display = "none"; } }); }); let typeSplit = new SplitType( ".footer-link, .products-text-visit-website, .accordion-button-wrap, .menu-item-prefix", { types: "words, chars", tagName: "span", } ); function getRandomLetter(length) { var result = ""; var characters = "{}[]();<>!?$%^&*"; var charactersLength = characters.length; for (var i = 0; i < length; i++) { result += characters.charAt(Math.floor(Math.random() * charactersLength)); } return result; } $(".char").each(function (index) { let text = $(this).text(); $(this).attr("letter", text); }); $(".footer-link, .accordion-button-wrap").each(function (index) { function resetText() { if (myInterval !== undefined) { clearInterval(myInterval); } chars.each(function (index) { let letter = $(this).attr("letter"); $(this).text(letter); $(this).css("background-color", "transparent"); // Reset background color $(this).css("color", ""); // Reset text color }); } let myInterval; let chars = $(this).find(".char"); function startEffect() { let length = chars.length; let currentIndex = 0; // Start from the first character let previousIndex = -1; // Track the previous character myInterval = setInterval(function () { // Reset the previous character back to normal if (previousIndex >= 0) { let previousCharElement = chars.eq(previousIndex); let originalLetter = previousCharElement.attr("letter"); previousCharElement.text(originalLetter); // Reset to original letter previousCharElement.css("background-color", "transparent"); // Reset background color previousCharElement.css("color", ""); // Reset text color } if (currentIndex < length) { let charElement = chars.eq(currentIndex); // Get the current character let letter = getRandomLetter(1); // Get a random letter charElement.text(letter); // Replace the character with the random letter charElement.css("background-color", "#6EF0DC"); // Change background color charElement.css("color", "#0a0a0a"); // Change text color to black previousIndex = currentIndex; // Set the previous index to the current one currentIndex++; // Move to the next character } else { clearInterval(myInterval); // Stop the interval when all characters are processed setTimeout(() => { resetText(); }, 200); // Wait before resetting the text } }, 70); // Adjust the speed here if needed } $(this).on("mouseenter touchstart", function () { startEffect(); // Start the effect on hover or touchstart (for mobile) }); $(this).on("mouseleave touchend", function () { resetText(); // Reset the text when mouse leaves or finger is lifted }); }); document.querySelectorAll(".menu-link-wrap").forEach((menuLink) => { menuLink.addEventListener("mouseenter", () => { gsap.set(menuLink.querySelector(".menu-item-prefix"), { opacity: 1 }); gsap.set(menuLink.querySelector(".menu-item-sufix"), { opacity: 1 }); gsap.set(".menu-item-label, .logo-header-wrap, .section-home-header", { color: "#8C8C8C", }); gsap.set(menuLink.querySelector(".menu-item-label"), { color: "#FFFFFF", opacity: 1, }); // Animate each .char child of .word elements within menu-item-prefix one by one, sequentially const menuChars = menuLink.querySelectorAll( ".menu-item-prefix .word .char" ); let menuTimeline = gsap.timeline({ defaults: { duration: 0.07, ease: "none" }, }); Array.from(menuChars).forEach((char) => { menuTimeline.fromTo( char, { color: "#0a0a0a", backgroundColor: "transparent" }, { color: "#6EF0DC", backgroundColor: "#6EF0DC", onComplete: () => { gsap.set(char, { backgroundColor: "transparent" }); // Ensure background reverts after reveal }, } ); }); }); menuLink.addEventListener("mouseleave", () => { gsap.set(menuLink.querySelector(".menu-item-prefix"), { opacity: 0 }); gsap.set(menuLink.querySelector(".menu-item-sufix"), { opacity: 0 }); gsap.set(".menu-item-label, .logo-header-wrap, .section-home-header", { color: "#FFFFFF", opacity: 1, }); }); // Add click event listener to reduce opacity of other menu links menuLink.addEventListener("click", () => { // Check if the link has #opportunities in its href if (menuLink.href.includes("#opportunities")) { menuLink.setAttribute("data-animation", "third-out"); } else { menuLink.setAttribute("data-animation", "fourth-out"); } // Reduce opacity of all other menu links over 1 second document.querySelectorAll(".menu-link-wrap").forEach((otherLink) => { if (otherLink !== menuLink) { gsap.to(otherLink, { opacity: 0, duration: 0.3 }); otherLink.style.pointerEvents = "none"; // Disable pointer events for non-clicked links } }); // Disable pointer events for the clicked link as well menuLink.style.pointerEvents = "none"; // Reduce opacity of all children of the clicked link except .menu-item-label menuLink.querySelectorAll("*:not(.menu-item-label)").forEach((child) => { gsap.to(child, { opacity: 0, duration: 0.3 }); }); }); }); // Add click event listener for elements with data-homepage attribute document.querySelectorAll("[data-homepage]").forEach((homepageElement) => { homepageElement.addEventListener("click", () => { // Add data-animation="third-out" to the .menu-wrap element const menuWrap = document.querySelector(".menu-wrap"); if (menuWrap) { menuWrap.setAttribute("data-animation", "third-out"); } // Add data-animation="third-out" to the .mobile-menu-wrap element const mobileMenuWrap = document.querySelector(".mobile-menu-wrap"); if (mobileMenuWrap) { mobileMenuWrap.setAttribute("data-animation", "third-out"); } }); }); // Select all the accordion elements const accordions = document.querySelectorAll(".products-accordion-wrap"); // Function to check if the device is mobile function isMobile() { return window.matchMedia("(max-width: 768px)").matches; } // Loop through each accordion element and add event listeners accordions.forEach((accordion, index) => { // Define descriptionWrap for each accordion const descriptionWrap = accordion.querySelector( ".products-description-wrap" ); accordion.isOpen = false; accordion.addEventListener("mouseenter", () => { if (isMobile()) return; // Skip hover effect if the accordion is open if (accordion.isOpen) { return; } // Set color for the text within the hovered item const headline = accordion .closest(".products-collection-item") .querySelector(".products-collection-headline"); if (headline) { headline.style.color = "#6EF0DC"; } // Set the bottom border color of the hovered item's content const itemContent = accordion .closest(".products-collection-item") .querySelector(".products-collection-item-content"); if (itemContent) { itemContent.style.borderBottomColor = "#6EF0DC"; } // Set the previous item's border color if it exists if (index > 0) { setTimeout(() => { const previousItem = accordions[index - 1] .closest(".products-collection-item") .querySelector(".products-collection-item-content"); if (previousItem) { previousItem.style.borderBottomColor = "#6EF0DC"; } }, 10); // Delay to ensure hover styles are set first } // Set all other items to greyed-out colors if they are not open accordions.forEach((otherAccordion) => { if (otherAccordion !== accordion) { const otherHeadline = otherAccordion .closest(".products-collection-item") .querySelector(".products-collection-headline"); const otherItemContent = otherAccordion .closest(".products-collection-item") .querySelector(".products-collection-item-content"); if (!otherAccordion.isOpen) { if (otherHeadline) { otherHeadline.style.color = "#8C8C8C"; } if (otherItemContent) { otherItemContent.style.borderBottomColor = "#8C8C8C"; } } } }); // Animate characters of the products text on hover if not open if (!accordion.isOpen) { const productsChars = accordion.querySelectorAll( ".products-text-visit-website .word .char" ); let productsTimeline = gsap.timeline({ defaults: { duration: 0.07, ease: "none" }, }); Array.from(productsChars).forEach((char) => { productsTimeline.fromTo( char, { color: "#0a0a0a", backgroundColor: "transparent" }, { color: "#6EF0DC", backgroundColor: "#6EF0DC", onComplete: () => { gsap.set(char, { backgroundColor: "transparent" }); }, } ); }); } // Set the opacity of the products text to 1 instantly if not open if (!accordion.isOpen) { gsap.set(accordion.querySelector(".products-text-visit-website"), { opacity: 1, }); } }); accordion.addEventListener("mouseleave", () => { if (isMobile()) return; // Reset color and border-bottom color for the hovered accordion if not open const headline = accordion .closest(".products-collection-item") .querySelector(".products-collection-headline"); const itemContent = accordion .closest(".products-collection-item") .querySelector(".products-collection-item-content"); if (!accordion.isOpen) { if (headline) { headline.style.color = "#FFFFFF"; } if (itemContent) { itemContent.style.borderBottomColor = "#FFFFFF"; } } // Reset all other items to their default state if not open accordions.forEach((otherAccordion) => { if (!otherAccordion.isOpen) { const otherHeadline = otherAccordion .closest(".products-collection-item") .querySelector(".products-collection-headline"); const otherItemContent = otherAccordion .closest(".products-collection-item") .querySelector(".products-collection-item-content"); if (otherHeadline) { otherHeadline.style.color = "#FFFFFF"; } if (otherItemContent) { otherItemContent.style.borderBottomColor = "#FFFFFF"; } } }); // If the previous accordion is open, set its border-bottom back to white if (index > 0 && accordions[index - 1].isOpen) { const previousItemContent = accordions[index - 1] .closest(".products-collection-item") .querySelector(".products-collection-item-content"); if (previousItemContent) { previousItemContent.style.borderBottomColor = "#FFFFFF"; } } // Set the opacity of the products text to 0 instantly if not open if (!accordion.isOpen) { gsap.set(accordion.querySelector(".products-text-visit-website"), { opacity: 0, }); } }); accordion.addEventListener("click", (event) => { // Prevent closing the accordion when clicking inside the descriptionWrap if (descriptionWrap.contains(event.target)) { return; } // Close all other accordions accordions.forEach((otherAccordion) => { const otherDescriptionWrap = otherAccordion.querySelector( ".products-description-wrap" ); if (otherAccordion !== accordion && otherAccordion.isOpen) { gsap.to(otherDescriptionWrap, { height: 0, duration: 0.3, ease: "power1.out", }); otherAccordion.isOpen = false; // Set the opacity of the products text view less to 0 when another accordion is closed gsap.set(otherAccordion.querySelector(".products-text-view-less"), { opacity: 0, }); // Reset the color of the previously open accordion to grey const otherHeadline = otherAccordion.querySelector( ".products-collection-headline" ); if (otherHeadline) { otherHeadline.style.color = "#8C8C8C"; } // Set the bottom border color of the content item to gray when the accordion is closed const otherItemContent = otherAccordion.querySelector( ".products-collection-item-content" ); if (otherItemContent) { otherItemContent.style.borderBottomColor = "#8C8C8C"; } } }); // Toggle the clicked accordion accordion.isOpen = !accordion.isOpen; gsap.to(descriptionWrap, { height: accordion.isOpen ? "auto" : 0, duration: 0.3, ease: "power1.out", }); if (accordion.isOpen) { // Set the opacity of the products text to 0 instantly when the accordion is opened gsap.set(accordion.querySelector(".products-text-visit-website"), { opacity: 0, }); // Set the opacity of the products text view less to 1 instantly when the accordion is opened gsap.set(accordion.querySelector(".products-text-view-less"), { opacity: 1, }); // Set the color of the headline to white when the accordion is opened const headline = accordion.querySelector( ".products-collection-headline" ); if (headline) { headline.style.color = "#FFFFFF"; } // Set the bottom border color of the content item to white when the accordion is opened const itemContent = accordion.querySelector( ".products-collection-item-content" ); if (itemContent) { itemContent.style.borderBottomColor = "#FFFFFF"; } // Set the previous item's border color to white if it exists if (index > 0) { const previousItem = accordions[index - 1]; const previousItemContent = previousItem .closest(".products-collection-item") .querySelector(".products-collection-item-content"); if (previousItemContent) { previousItemContent.style.borderBottomColor = "#FFFFFF"; } } } else { // Set the opacity of the products text view less to 0 when the accordion is closed gsap.set(accordion.querySelector(".products-text-view-less"), { opacity: 0, }); // If the accordion is closed and still hovered, reapply the hover effect if (!accordion.isOpen && accordion.matches(":hover")) { // Manually trigger the hover logic to reapply hover effect after closing const headline = accordion .closest(".products-collection-item") .querySelector(".products-collection-headline"); if (headline) { headline.style.color = "#6EF0DC"; } const itemContent = accordion .closest(".products-collection-item") .querySelector(".products-collection-item-content"); if (itemContent) { itemContent.style.borderBottomColor = "#6EF0DC"; } // Set the previous item's border color to green if it exists if (index > 0) { const previousItem = accordions[index - 1]; const previousItemContent = previousItem .closest(".products-collection-item") .querySelector(".products-collection-item-content"); if (previousItemContent) { previousItemContent.style.borderBottomColor = "#6EF0DC"; } } gsap.set(accordion.querySelector(".products-text-visit-website"), { opacity: 1, }); } } }); }); // Mobile version accordion functionality const mobileAccordions = document.querySelectorAll( ".products-accordion-wrap-mobile" ); mobileAccordions.forEach((accordion, index) => { const descriptionWrap = accordion.querySelector( ".products-description-wrap-mobile" ); const crossVertical = accordion.querySelector(".cross-vertical"); accordion.isOpen = false; accordion.addEventListener("click", (event) => { // Prevent closing the accordion when clicking inside the descriptionWrap if (descriptionWrap.contains(event.target)) { return; } // Close all other accordions mobileAccordions.forEach((otherAccordion, otherIndex) => { const otherDescriptionWrap = otherAccordion.querySelector( ".products-description-wrap-mobile" ); const otherCrossVertical = otherAccordion.querySelector(".cross-vertical"); if (otherAccordion !== accordion && otherAccordion.isOpen) { gsap.to(otherDescriptionWrap, { height: 0, duration: 0.3, ease: "power1.out", }); gsap.to(otherCrossVertical, { rotateZ: 0, duration: 0.3, ease: "power1.out", }); otherAccordion.isOpen = false; // Reset the border color and headline color to white for closed accordions gsap.set(otherAccordion, { borderBottomColor: "#FFFFFF", }); const otherHeadlineWrap = otherAccordion.querySelector( ".products-headline-wrap-mobile" ); const otherHeadlineChildren = otherHeadlineWrap.querySelectorAll("*"); gsap.set(otherHeadlineChildren, { color: "#FFFFFF", }); } }); // Toggle the clicked accordion accordion.isOpen = !accordion.isOpen; gsap.to(descriptionWrap, { height: accordion.isOpen ? "auto" : 0, duration: 0.3, ease: "power1.out", }); gsap.to(crossVertical, { rotateZ: accordion.isOpen ? 90 : 0, duration: 0.3, ease: "power1.out", }); const headlineWrap = accordion.querySelector( ".products-headline-wrap-mobile" ); const headlineChildren = headlineWrap.querySelectorAll("*"); if (accordion.isOpen) { // Set the clicked accordion's headline children color to green when open gsap.set(headlineChildren, { color: "#6EF0DC", }); // Set the clicked accordion's border color to green when open gsap.set(accordion, { borderBottomColor: "#6EF0DC", }); // Set the previous accordion's border to green if it exists if (index > 0) { const previousAccordion = mobileAccordions[index - 1]; gsap.set(previousAccordion, { borderBottomColor: "#6EF0DC", }); } } else { // Reset the clicked accordion's headline children color to white when closed gsap.set(headlineChildren, { color: "#FFFFFF", }); // Reset the clicked accordion's border color to white when closed gsap.set(accordion, { borderBottomColor: "#FFFFFF", }); } // Set the color of non-clicked accordions based on their open/close state mobileAccordions.forEach((otherAccordion, otherIndex) => { if (otherAccordion !== accordion) { const otherHeadlineWrap = otherAccordion.querySelector( ".products-headline-wrap-mobile" ); const otherHeadlineChildren = otherHeadlineWrap.querySelectorAll("*"); // Non-clicked accordions should have grey headline children and border bottom color when one is open gsap.set(otherHeadlineChildren, { color: accordion.isOpen ? "#8C8C8C" : "#FFFFFF", }); // If the current accordion is the one directly preceding the open accordion, set border color to green if (otherIndex === index - 1 && accordion.isOpen) { gsap.set(otherAccordion, { borderBottomColor: "#6EF0DC", }); } else { gsap.set(otherAccordion, { borderBottomColor: accordion.isOpen ? "#8C8C8C" : "#FFFFFF", }); } } }); // If all accordions are closed, reset all to full color if (mobileAccordions.every((acc) => !acc.isOpen)) { mobileAccordions.forEach((otherAccordion) => { const otherHeadlineWrap = otherAccordion.querySelector( ".products-headline-wrap-mobile" ); const otherHeadlineChildren = otherHeadlineWrap.querySelectorAll("*"); gsap.set(otherAccordion, { borderBottomColor: "#FFFFFF", }); gsap.set(otherHeadlineChildren, { color: "#FFFFFF", }); }); } }); }); // Set initial states gsap.set(".menu-item-prefix, .menu-item-sufix", { opacity: 0 }); gsap.set(".menu-item-label, .logo-header-wrap, .section-home-header", { opacity: 1, color: "#FFFFFF", }); gsap.set(".accordion-button-wrap", { color: "#6EF0DC" }); gsap.set(".products-text-view-less", { opacity: 0 }); gsap.set(".products-accordion-wrap", { opacity: 1, color: "#FFFFFF" }); gsap.set( ".products-headline-wrap-mobile .portfolio-company-name, .products-headline-wrap-mobile .portfolio-industry, .products-headline-wrap-mobile .portfolio_icon-wrapper", { color: "#FFFFFF" } ); gsap.set(".products-description-wrap", { height: 0 }); } function initAboutAnimations() { const canvasContainer = document.getElementById("aboutcanvas"); if (!canvasContainer) { console.warn("No canvas container found on the contributions page."); return; } loadCablesScript( "https://cdn.prod.website-files.com/670e3bce95be1572f35a93bc/6755eb81df4c47e427d17fa8_last-patchv2.txt", () => { if (typeof CABLES !== "undefined" && CABLES.exportedPatch) { CABLES.patch = new CABLES.Patch({ patch: CABLES.exportedPatch, prefixAssetPath: "", assetPath: "assets/", jsPath: "js/", glCanvasId: "aboutcanvas", glCanvasResizeToWindow: false, onError: showError, onPatchLoaded: patchInitialized, onFinishedLoading: patchFinishedLoading, canvas: { alpha: true, premultipliedAlpha: true }, variables: { fillBg: 0, }, }); console.log("CablesGL Patch Initialized on Contributions."); } else { console.error("CABLES or exportedPatch is undefined."); } } ); document.querySelector("#aboutcanvas").addEventListener("touchend", () => { // Reset the active element to the body document.body.focus(); // Remove the 'touch-action: none;' style from the body document.body.style.touchAction = ""; }); document.querySelector("#aboutcanvas").addEventListener("blur", () => { // Reset the active element to the body document.body.focus(); // Remove the 'touch-action: none;' style from the body document.body.style.touchAction = ""; }); document.addEventListener("DOMContentLoaded", () => { const currentUrl = window.location.href; const menuLinks = document.querySelectorAll(".menu-link-wrap"); menuLinks.forEach((link) => { if (link.href === currentUrl) { link.style.display = "none"; } }); }); gsap.set(".menu-item-label-about, .footer-links-wrap", { color: "#0a0a0a", }); document.querySelector(".section-open-menu").addEventListener("click", () => { gsap.set(".menu-item-label-about", { color: "#0a0a0a" }); }); // Initialize SplitType for text animation let typeSplit = new SplitType(".footer-link, .menu-item-prefix", { types: "words, chars", tagName: "span", }); function getRandomLetter(length) { var result = ""; var characters = "{}[]();<>!?$%^&*"; var charactersLength = characters.length; for (var i = 0; i < length; i++) { result += characters.charAt(Math.floor(Math.random() * charactersLength)); } return result; } $(".char").each(function () { let text = $(this).text(); $(this).attr("letter", text); }); $(".footer-link").each(function () { let chars = $(this).find(".char"); let myInterval; function resetText() { if (myInterval !== undefined) { clearInterval(myInterval); } chars.each(function () { let letter = $(this).attr("letter"); $(this).text(letter); $(this).css("background-color", "transparent"); $(this).css("color", ""); }); } function startEffect() { let length = chars.length; let currentIndex = 0; let previousIndex = -1; myInterval = setInterval(function () { if (previousIndex >= 0) { let previousCharElement = chars.eq(previousIndex); let originalLetter = previousCharElement.attr("letter"); previousCharElement.text(originalLetter); previousCharElement.css("background-color", "transparent"); previousCharElement.css("color", ""); } if (currentIndex < length) { let charElement = chars.eq(currentIndex); let letter = getRandomLetter(1); charElement.text(letter); charElement.css("background-color", "#0a0a0a"); charElement.css("color", "#6EF0DC"); previousIndex = currentIndex; currentIndex++; } else { clearInterval(myInterval); setTimeout(() => { resetText(); }, 200); } }, 70); } $(this).on("mouseenter touchstart", function () { startEffect(); }); $(this).on("mouseleave touchend", function () { resetText(); }); }); document.querySelectorAll(".menu-link-wrap.is-black").forEach((menuLink) => { menuLink.addEventListener("mouseenter", () => { gsap.set(menuLink.querySelector(".menu-item-prefix"), { opacity: 1 }); gsap.set(menuLink.querySelector(".menu-item-sufix"), { opacity: 1 }); gsap.set(".menu-item-label-about, .section-header", { color: "#8C8C8C", }); gsap.set(menuLink.querySelector(".menu-item-label-about"), { color: "#0a0a0a", opacity: 1, }); const menuChars = menuLink.querySelectorAll( ".menu-item-prefix .word .char" ); let menuTimeline = gsap.timeline({ defaults: { duration: 0.07, ease: "none" }, }); Array.from(menuChars).forEach((char) => { menuTimeline.fromTo( char, { color: "#6EF0DC", backgroundColor: "transparent" }, { color: "#0a0a0a", backgroundColor: "#0a0a0a", onComplete: () => { gsap.set(char, { backgroundColor: "transparent" }); }, } ); }); }); menuLink.addEventListener("mouseleave", () => { gsap.set(menuLink.querySelector(".menu-item-prefix"), { opacity: 0 }); gsap.set(menuLink.querySelector(".menu-item-sufix"), { opacity: 0 }); gsap.set(".menu-item-label-about, .section-header", { color: "#0a0a0a", opacity: 1, }); }); menuLink.addEventListener("click", () => { // Check if the link has #opportunities in its href if (menuLink.href.includes("#opportunities")) { menuLink.setAttribute("data-animation", "third-out"); } else { menuLink.setAttribute("data-animation", "fourth-out"); } document .querySelectorAll(".menu-link-wrap.is-black") .forEach((otherLink) => { if (otherLink !== menuLink) { gsap.to(otherLink, { opacity: 0, duration: 0.3 }); otherLink.style.pointerEvents = "none"; // Disable pointer events for non-clicked links } }); // Disable pointer events for the clicked link as well menuLink.style.pointerEvents = "none"; menuLink .querySelectorAll("*:not(.menu-item-label-about)") .forEach((child) => { gsap.to(child, { opacity: 0, duration: 0.3 }); }); }); }); // Add click event listener for elements with data-homepage attribute document.querySelectorAll("[data-homepage]").forEach((homepageElement) => { homepageElement.addEventListener("click", () => { // Add data-animation="third-out" to the .menu-wrap element const menuWrap = document.querySelector(".menu-wrap"); if (menuWrap) { menuWrap.setAttribute("data-animation", "third-out"); } // Add data-animation="third-out" to the .mobile-menu-wrap element const mobileMenuWrap = document.querySelector(".mobile-menu-wrap"); if (mobileMenuWrap) { mobileMenuWrap.setAttribute("data-animation", "third-out"); } }); }); } function initTeamAnimations() { document.addEventListener("DOMContentLoaded", () => { const currentUrl = window.location.href; const menuLinks = document.querySelectorAll(".menu-link-wrap"); menuLinks.forEach((link) => { if (link.href === currentUrl) { link.style.display = "none"; } }); }); document.querySelectorAll("a[opportunities]").forEach((link) => { link.addEventListener("click", (event) => { event.preventDefault(); // Prevent the default behavior of the opportunities link // Find the element with the class .section-open-menu and trigger a click const menuLink = document.querySelector(".section-open-menu"); if (menuLink) { menuLink.click(); } // Set the color of .section-page-name to #FFFFFF using GSAP const pageNameElement = document.querySelector(".section-page-name"); if (pageNameElement) { gsap.set(pageNameElement, { color: "#FFFFFF" }); } }); }); // Load Swiper CSS const swiperCSS = document.createElement("link"); swiperCSS.rel = "stylesheet"; swiperCSS.href = "https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.css"; document.head.appendChild(swiperCSS); // Load Swiper JS const swiperScript = document.createElement("script"); swiperScript.src = "https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.js"; swiperScript.onload = () => { // Initialize Swiper after the script has loaded const swiper = new Swiper(".swiper", { slidesPerView: 2.1, spaceBetween: 6, pagination: { el: ".swiper-pagination", clickable: true, }, }); }; document.body.appendChild(swiperScript); let typeSplit = new SplitType( ".footer-link, .opportunities-text-visit-website, .accordion-button-wrap, .menu-item-prefix, .nav-button", { types: "words, chars", tagName: "span", } ); function getRandomLetter(length) { var result = ""; var characters = "{}[]();<>!?$%^&*"; var charactersLength = characters.length; for (var i = 0; i < length; i++) { result += characters.charAt(Math.floor(Math.random() * charactersLength)); } return result; } $(".char").each(function (index) { let text = $(this).text(); $(this).attr("letter", text); }); $(".footer-link, .accordion-button-wrap, .nav-button").each(function (index) { function resetText() { if (myInterval !== undefined) { clearInterval(myInterval); } chars.each(function (index) { let letter = $(this).attr("letter"); $(this).text(letter); $(this).css("background-color", "transparent"); // Reset background color $(this).css("color", ""); // Reset text color }); } let myInterval; let chars = $(this).find(".char"); function startEffect() { let length = chars.length; let currentIndex = 0; // Start from the first character let previousIndex = -1; // Track the previous character myInterval = setInterval(function () { // Reset the previous character back to normal if (previousIndex >= 0) { let previousCharElement = chars.eq(previousIndex); let originalLetter = previousCharElement.attr("letter"); previousCharElement.text(originalLetter); // Reset to original letter previousCharElement.css("background-color", "transparent"); // Reset background color previousCharElement.css("color", ""); // Reset text color } if (currentIndex < length) { let charElement = chars.eq(currentIndex); // Get the current character let letter = getRandomLetter(1); // Get a random letter charElement.text(letter); // Replace the character with the random letter charElement.css("background-color", "#6EF0DC"); // Change background color charElement.css("color", "#0a0a0a"); // Change text color to black previousIndex = currentIndex; // Set the previous index to the current one currentIndex++; // Move to the next character } else { clearInterval(myInterval); // Stop the interval when all characters are processed setTimeout(() => { resetText(); }, 200); // Wait before resetting the text } }, 70); // Adjust the speed here if needed } $(this).on("mouseenter touchstart", function () { startEffect(); // Start the effect on hover or touchstart (for mobile) }); $(this).on("mouseleave touchend", function () { resetText(); // Reset the text when mouse leaves or finger is lifted }); }); document.querySelectorAll(".menu-link-wrap").forEach((menuLink) => { menuLink.addEventListener("mouseenter", () => { gsap.set(menuLink.querySelector(".menu-item-prefix"), { opacity: 1 }); gsap.set(menuLink.querySelector(".menu-item-sufix"), { opacity: 1 }); gsap.set(".menu-item-label, .section-header", { color: "#8C8C8C" }); gsap.set(menuLink.querySelector(".menu-item-label"), { color: "#FFFFFF", opacity: 1, }); // Animate each .char child of .word elements within menu-item-prefix one by one, sequentially const menuChars = menuLink.querySelectorAll( ".menu-item-prefix .word .char" ); let menuTimeline = gsap.timeline({ defaults: { duration: 0.07, ease: "none" }, }); Array.from(menuChars).forEach((char) => { menuTimeline.fromTo( char, { color: "#0a0a0a", backgroundColor: "transparent" }, { color: "#6EF0DC", backgroundColor: "#6EF0DC", onComplete: () => { gsap.set(char, { backgroundColor: "transparent" }); // Ensure background reverts after reveal }, } ); }); }); menuLink.addEventListener("mouseleave", () => { gsap.set(menuLink.querySelector(".menu-item-prefix"), { opacity: 0 }); gsap.set(menuLink.querySelector(".menu-item-sufix"), { opacity: 0 }); gsap.set(".menu-item-label, .section-logo-header-wrap, .section-header", { color: "#FFFFFF", opacity: 1, }); }); // Add click event listener to reduce opacity of other menu links menuLink.addEventListener("click", () => { // Check if the link has #opportunities in its href if (menuLink.href.includes("#opportunities")) { menuLink.setAttribute("data-animation", "third-out"); } else { menuLink.setAttribute("data-animation", "fourth-out"); } // Check if the clicked link's href is "#opportunities" if (menuLink.getAttribute("href") === "#opportunities") { return; // Exit the function without running the animations } // Reduce opacity of all other menu links over 1 second document.querySelectorAll(".menu-link-wrap").forEach((otherLink) => { if (otherLink !== menuLink) { gsap.to(otherLink, { opacity: 0, duration: 0.3 }); otherLink.style.pointerEvents = "none"; // Disable pointer events for non-clicked links } }); // Disable pointer events for the clicked link as well menuLink.style.pointerEvents = "none"; menuLink.querySelectorAll("*:not(.menu-item-label)").forEach((child) => { gsap.to(child, { opacity: 0, duration: 0.3 }); }); }); }); // Add click event listener for elements with data-homepage attribute document.querySelectorAll("[data-homepage]").forEach((homepageElement) => { homepageElement.addEventListener("click", () => { // Add data-animation="third-out" to the .menu-wrap element const menuWrap = document.querySelector(".menu-wrap"); if (menuWrap) { menuWrap.setAttribute("data-animation", "third-out"); } // Add data-animation="third-out" to the .mobile-menu-wrap element const mobileMenuWrap = document.querySelector(".mobile-menu-wrap"); if (mobileMenuWrap) { mobileMenuWrap.setAttribute("data-animation", "third-out"); } }); }); // Select all the accordion elements const accordions = document.querySelectorAll(".opportunities-accordion-wrap"); // Function to check if the device is mobile function isMobile() { return window.matchMedia("(max-width: 768px)").matches; } // Loop through each accordion element and add event listeners accordions.forEach((accordion) => { const descriptionWrap = accordion.querySelector( ".opportunities-description-wrap" ); accordion.isOpen = false; accordion.addEventListener("mouseenter", () => { if (isMobile()) return; // Skip hover effect if the accordion is open if (accordion.isOpen) { return; } // Change the color of the hovered accordion's child element instantly const headline = accordion.querySelector( ".opportunities-collection-headline" ); gsap.set(headline, { color: "#6EF0DC", borderBottomColor: "#6EF0DC", }); // Set bottom border color of hovered accordion's content item to #6EF0DC const contentItem = accordion.querySelector( ".opportunities-collection-item-content" ); gsap.set(contentItem, { borderBottomColor: "#6EF0DC", }); // Change the color of non-hovered accordions instantly accordions.forEach((otherAccordion) => { if (otherAccordion !== accordion && !otherAccordion.isOpen) { const otherHeadline = otherAccordion.querySelector( ".opportunities-collection-headline" ); gsap.set(otherHeadline, { color: "#8C8C8C", borderBottomColor: "#8C8C8C", }); // Set the bottom border color of non-hovered accordion's content item to #8C8C8C const otherContentItem = otherAccordion.querySelector( ".opportunities-collection-item-content" ); gsap.set(otherContentItem, { borderBottomColor: "#8C8C8C", }); } }); // Animate characters of opportunities text on hover if not open if (!accordion.isOpen) { const opportunitiesChars = accordion.querySelectorAll( ".opportunities-text-visit-website .word .char" ); let opportunitiesTimeline = gsap.timeline({ defaults: { duration: 0.07, ease: "none" }, }); Array.from(opportunitiesChars).forEach((char) => { opportunitiesTimeline.fromTo( char, { color: "#0a0a0a", backgroundColor: "transparent" }, { color: "#6EF0DC", backgroundColor: "#6EF0DC", onComplete: () => { gsap.set(char, { backgroundColor: "transparent" }); }, } ); }); } // Set the opacity of the opportunities text to 1 instantly if (!accordion.isOpen) { gsap.set(accordion.querySelector(".opportunities-text-visit-website"), { opacity: 1, }); } }); accordion.addEventListener("mouseleave", () => { if (isMobile()) return; // Reset the hovered accordion's border color to white if it's not open if (!accordion.isOpen) { const headline = accordion.querySelector( ".opportunities-collection-headline" ); gsap.set(headline, { color: "#FFFFFF", borderBottomColor: "#FFFFFF", }); const contentItem = accordion.querySelector( ".opportunities-collection-item-content" ); gsap.set(contentItem, { borderBottomColor: "#FFFFFF", }); // Set the opacity of the opportunities text to 0 instantly if not open gsap.set(accordion.querySelector(".opportunities-text-visit-website"), { opacity: 0, }); } // Update the colors for all other accordions that are not open accordions.forEach((otherAccordion) => { if (otherAccordion !== accordion && !otherAccordion.isOpen) { const otherHeadline = otherAccordion.querySelector( ".opportunities-collection-headline" ); const otherContentItem = otherAccordion.querySelector( ".opportunities-collection-item-content" ); gsap.set(otherHeadline, { color: "#FFFFFF", borderBottomColor: "#FFFFFF", }); gsap.set(otherContentItem, { borderBottomColor: "#FFFFFF", }); } }); // Check if no accordion is being hovered, reset all to white const noHoveredAccordion = Array.from(accordions).every( (acc) => !acc.matches(":hover") ); if (noHoveredAccordion) { accordions.forEach((acc) => { const accContentItem = acc.querySelector( ".opportunities-collection-item-content" ); gsap.set(accContentItem, { borderBottomColor: "#FFFFFF", }); // Reset the opacity of the opportunities text if no accordion is being hovered gsap.set(acc.querySelector(".opportunities-text-visit-website"), { opacity: 0, }); }); } }); accordion.addEventListener("click", (event) => { // Prevent closing the accordion when clicking inside the descriptionWrap if (descriptionWrap.contains(event.target)) { return; } // Close all other accordions accordions.forEach((otherAccordion) => { const otherDescriptionWrap = otherAccordion.querySelector( ".opportunities-description-wrap" ); if (otherAccordion !== accordion && otherAccordion.isOpen) { gsap.to(otherDescriptionWrap, { height: 0, duration: 0.3, ease: "power1.out", }); otherAccordion.isOpen = false; // Set the opacity of the opportunities text view less to 0 when another accordion is closed gsap.set( otherAccordion.querySelector(".opportunities-text-view-less"), { opacity: 0, } ); // Reset the color of the previously open accordion to grey const otherHeadline = otherAccordion.querySelector( ".opportunities-collection-headline" ); gsap.set(otherHeadline, { color: "#8C8C8C", borderBottomColor: "#8C8C8C", }); // Set the bottom border color of the content item to grey when the accordion is closed const otherContentItem = otherAccordion.querySelector( ".opportunities-collection-item-content" ); gsap.set(otherContentItem, { borderBottomColor: "#8C8C8C", }); } }); // Toggle the clicked accordion accordion.isOpen = !accordion.isOpen; gsap.to(descriptionWrap, { height: accordion.isOpen ? "auto" : 0, duration: 0.3, ease: "power1.out", }); if (accordion.isOpen) { // Set the opacity of the opportunities text to 0 instantly when the accordion is opened gsap.set(accordion.querySelector(".opportunities-text-visit-website"), { opacity: 0, }); // Set the opacity of the opportunities text view less to 1 instantly when the accordion is opened gsap.set(accordion.querySelector(".opportunities-text-view-less"), { opacity: 1, }); // Set the color of the headline to white when the accordion is opened const headline = accordion.querySelector( ".opportunities-collection-headline" ); gsap.set(headline, { color: "#FFFFFF", }); // Set the bottom border color of the content item to white when the accordion is opened const contentItem = accordion.querySelector( ".opportunities-collection-item-content" ); gsap.set(contentItem, { borderBottomColor: "#FFFFFF", }); } else { // Set the opacity of the opportunities text view less to 0 when the accordion is closed gsap.set(accordion.querySelector(".opportunities-text-view-less"), { opacity: 0, }); // If the accordion is closed and still hovered, reapply the hover effect if (!accordion.isOpen && accordion.matches(":hover")) { // Manually trigger the hover logic to reapply hover effect after closing const headline = accordion.querySelector( ".opportunities-collection-headline" ); gsap.set(headline, { color: "#6EF0DC", borderBottomColor: "#6EF0DC", }); const contentItem = accordion.querySelector( ".opportunities-collection-item-content" ); gsap.set(contentItem, { borderBottomColor: "#6EF0DC", }); gsap.set( accordion.querySelector(".opportunities-text-visit-website"), { opacity: 1, } ); } } }); }); // Mobile version accordion functionality const mobileAccordions = document.querySelectorAll( ".opportunities-collection-item" ); mobileAccordions.forEach((accordion) => { const descriptionWrap = accordion.querySelector( ".opportunities-description-wrap-mobile" ); const crossVertical = accordion.querySelector(".cross-vertical"); accordion.isOpen = false; accordion.addEventListener("click", (event) => { // Prevent closing the accordion when clicking inside the descriptionWrap if (descriptionWrap.contains(event.target)) { return; } // Close all other accordions mobileAccordions.forEach((otherAccordion) => { const otherDescriptionWrap = otherAccordion.querySelector( ".opportunities-description-wrap-mobile" ); const otherCrossVertical = otherAccordion.querySelector(".cross-vertical"); if (otherAccordion !== accordion && otherAccordion.isOpen) { gsap.to(otherDescriptionWrap, { height: 0, duration: 0.3, ease: "power1.out", }); gsap.to(otherCrossVertical, { rotateZ: 0, duration: 0.3, ease: "power1.out", }); otherAccordion.isOpen = false; } }); // Toggle the clicked accordion accordion.isOpen = !accordion.isOpen; gsap.to(descriptionWrap, { height: accordion.isOpen ? "auto" : 0, duration: 0.3, ease: "power1.out", }); gsap.to(crossVertical, { rotateZ: accordion.isOpen ? 90 : 0, duration: 0.3, ease: "power1.out", }); // Set the opacity of accordions based on their open/close state mobileAccordions.forEach((otherAccordion) => { if (otherAccordion === accordion) { // The clicked accordion should be fully opaque if open, otherwise reset to white gsap.set(otherAccordion, { opacity: accordion.isOpen ? 1 : 1, }); } else { // Non-clicked accordions should be greyed out if the clicked accordion is open gsap.set(otherAccordion, { opacity: accordion.isOpen ? 0.5 : 1, }); } }); // If all accordions are closed, reset all to full opacity if (mobileAccordions.every((acc) => !acc.isOpen)) { mobileAccordions.forEach((otherAccordion) => { gsap.set(otherAccordion, { opacity: 1, }); }); } }); }); gsap.set(".menu-item-prefix, .menu-item-sufix", { opacity: 0 }); gsap.set(".menu-item-label, .logo-header-wrap, .section-home-header", { opacity: 1, color: "#FFFFFF", }); gsap.set(".accordion-button-wrap", { color: "#6EF0DC" }); gsap.set(".opportunities-text-view-less", { opacity: 0 }); gsap.set(".opportunities-accordion-wrap", { opacity: 1, color: "#FFFFFF" }); gsap.set( ".products-headline-wrap .portfolio-company-name, .products-headline-wrap .portfolio-industry, .products-headline-wrap .portfolio_icon-wrapper", { color: "#FFFFFF" } ); gsap.set(".opportunities-description-wrap", { height: 0 }); } function initWritingAnimations() { const canvasContainer = document.getElementById("writingcanvas"); if (!canvasContainer) { console.warn("No canvas container found on the contributions page."); return; } loadCablesScript( "https://cdn.prod.website-files.com/670e3bce95be1572f35a93bc/6755eb81df4c47e427d17fa8_last-patchv2.txt", () => { if (typeof CABLES !== "undefined" && CABLES.exportedPatch) { CABLES.patch = new CABLES.Patch({ patch: CABLES.exportedPatch, prefixAssetPath: "", assetPath: "assets/", jsPath: "js/", glCanvasId: "writingcanvas", glCanvasResizeToWindow: false, onError: showError, onPatchLoaded: patchInitialized, onFinishedLoading: patchFinishedLoading, canvas: { alpha: true, premultipliedAlpha: true }, variables: { fillBg: 0, }, }); console.log("CablesGL Patch Initialized on Contributions."); } else { console.error("CABLES or exportedPatch is undefined."); } } ); document.querySelector("#writingcanvas").addEventListener("touchend", () => { // Reset the active element to the body document.body.focus(); // Remove the 'touch-action: none;' style from the body document.body.style.touchAction = ""; }); document.querySelector("#writingcanvas").addEventListener("blur", () => { // Reset the active element to the body document.body.focus(); // Remove the 'touch-action: none;' style from the body document.body.style.touchAction = ""; }); document.addEventListener("DOMContentLoaded", () => { const currentUrl = window.location.href; const menuLinks = document.querySelectorAll(".menu-link-wrap"); menuLinks.forEach((link) => { if (link.href === currentUrl) { link.style.display = "none"; } }); }); let typeSplit = new SplitType( ".footer-link, .writing-text-read, .menu-item-prefix", { types: "words, chars", tagName: "span", } ); function getRandomLetter(length) { var result = ""; var characters = "{}[]();<>!?$%^&*"; var charactersLength = characters.length; for (var i = 0; i < length; i++) { result += characters.charAt(Math.floor(Math.random() * charactersLength)); } return result; } $(".char").each(function (index) { let text = $(this).text(); $(this).attr("letter", text); }); $(".footer-link").each(function (index) { function resetText() { if (myInterval !== undefined) { clearInterval(myInterval); } chars.each(function (index) { let letter = $(this).attr("letter"); $(this).text(letter); $(this).css("background-color", "transparent"); // Reset background color $(this).css("color", ""); // Reset text color }); } let myInterval; let chars = $(this).find(".char"); function startEffect() { let length = chars.length; let currentIndex = 0; // Start from the first character let previousIndex = -1; // Track the previous character myInterval = setInterval(function () { // Reset the previous character back to normal if (previousIndex >= 0) { let previousCharElement = chars.eq(previousIndex); let originalLetter = previousCharElement.attr("letter"); previousCharElement.text(originalLetter); // Reset to original letter previousCharElement.css("background-color", "transparent"); // Reset background color previousCharElement.css("color", ""); // Reset text color } if (currentIndex < length) { let charElement = chars.eq(currentIndex); // Get the current character let letter = getRandomLetter(1); // Get a random letter charElement.text(letter); // Replace the character with the random letter charElement.css("background-color", "#6EF0DC"); // Change background color charElement.css("color", "#0a0a0a"); // Change text color to black previousIndex = currentIndex; // Set the previous index to the current one currentIndex++; // Move to the next character } else { clearInterval(myInterval); // Stop the interval when all characters are processed setTimeout(() => { resetText(); }, 200); // Wait before resetting the text } }, 70); // Adjust the speed here if needed } $(this).on("mouseenter touchstart", function () { startEffect(); // Start the effect on hover or touchstart (for mobile) }); $(this).on("mouseleave touchend", function () { resetText(); // Reset the text when mouse leaves or finger is lifted }); }); document.querySelectorAll(".menu-link-wrap").forEach((menuLink) => { menuLink.addEventListener("mouseenter", () => { gsap.set(menuLink.querySelector(".menu-item-prefix"), { opacity: 1 }); gsap.set(menuLink.querySelector(".menu-item-sufix"), { opacity: 1 }); gsap.set(".menu-item-label, .section-header", { color: "#8C8C8C" }); gsap.set(menuLink.querySelector(".menu-item-label"), { color: "#FFFFFF", opacity: 1, }); // Animate each .char child of .word elements within menu-item-prefix one by one, sequentially const menuChars = menuLink.querySelectorAll( ".menu-item-prefix .word .char" ); let menuTimeline = gsap.timeline({ defaults: { duration: 0.07, ease: "none" }, }); Array.from(menuChars).forEach((char) => { menuTimeline.fromTo( char, { color: "#0a0a0a", backgroundColor: "transparent" }, { color: "#6EF0DC", backgroundColor: "#6EF0DC", onComplete: () => { gsap.set(char, { backgroundColor: "transparent" }); // Ensure background reverts after reveal }, } ); }); }); menuLink.addEventListener("mouseleave", () => { gsap.set(menuLink.querySelector(".menu-item-prefix"), { opacity: 0 }); gsap.set(menuLink.querySelector(".menu-item-sufix"), { opacity: 0 }); gsap.set(".menu-item-label, .section-header", { color: "#FFFFFF", opacity: 1, }); }); // Add click event listener to reduce opacity of other menu links menuLink.addEventListener("click", () => { // Check if the link has #opportunities in its href if (menuLink.href.includes("#opportunities")) { menuLink.setAttribute("data-animation", "third-out"); } else { menuLink.setAttribute("data-animation", "fourth-out"); } // Reduce opacity of all other menu links over 1 second document.querySelectorAll(".menu-link-wrap").forEach((otherLink) => { if (otherLink !== menuLink) { gsap.to(otherLink, { opacity: 0, duration: 0.3 }); otherLink.style.pointerEvents = "none"; // Disable pointer events for non-clicked links } }); // Disable pointer events for the clicked link as well menuLink.style.pointerEvents = "none"; menuLink.querySelectorAll("*:not(.menu-item-label)").forEach((child) => { gsap.to(child, { opacity: 0, duration: 0.3 }); }); }); }); // Add click event listener for elements with data-homepage attribute document.querySelectorAll("[data-homepage]").forEach((homepageElement) => { homepageElement.addEventListener("click", () => { // Add data-animation="third-out" to the .menu-wrap element const menuWrap = document.querySelector(".menu-wrap"); if (menuWrap) { menuWrap.setAttribute("data-animation", "third-out"); } // Add data-animation="third-out" to the .mobile-menu-wrap element const mobileMenuWrap = document.querySelector(".mobile-menu-wrap"); if (mobileMenuWrap) { mobileMenuWrap.setAttribute("data-animation", "third-out"); } }); }); // Select all writing content items let writingItems = Array.from( document.querySelectorAll(".writing-content-collection-item") ); // Function to handle entering an item (either hover or touchstart) function handleItemEnter(item) { // Update the list to reflect the current DOM order writingItems = Array.from( document.querySelectorAll(".writing-content-collection-item") ); // Get the current index of the hovered item by finding it in the updated list const index = writingItems.indexOf(item); // Set the initial color and opacity of the .writing-text-read container gsap.set(item.querySelector(".writing-text-read"), { opacity: 1, color: "#6EF0DC", }); // Animate each character within .writing-text-read const writingChars = item.querySelectorAll( ".writing-text-read .word .char" ); let writingTimeline = gsap.timeline({ defaults: { duration: 0.07, ease: "none" }, }); Array.from(writingChars).forEach((char) => { writingTimeline.fromTo( char, { color: "#0a0a0a", backgroundColor: "transparent", opacity: 0 }, { color: "#6EF0DC", backgroundColor: "#6EF0DC", opacity: 1, onComplete: () => { gsap.set(char, { backgroundColor: "transparent" }); }, } ); }); // Set color and border color for the current hovered item const listWrap = item.querySelector(".writting-list-wrap"); const author = item.querySelector(".written-author"); const arrow = item.querySelector("#arrow"); if (listWrap) { listWrap.style.color = "#6EF0DC"; listWrap.style.borderBottomColor = "#6EF0DC"; } if (author) { author.style.color = "#6EF0DC"; } if (arrow) { arrow.style.fill = "#6EF0DC"; // Change the fill color of the element with ID arrow } // Set the previous item's border color if it exists if (index > 0) { setTimeout(() => { const previousItem = writingItems[index - 1]; const previousListWrap = previousItem.querySelector( ".writting-list-wrap" ); if (previousListWrap) { previousListWrap.style.borderBottomColor = "#6EF0DC"; } }, 10); // Delay to ensure hover styles are set first } // Set all other items to greyed-out colors writingItems.forEach((otherItem) => { if (otherItem !== item) { const otherListWrap = otherItem.querySelector(".writting-list-wrap"); const otherAuthor = otherItem.querySelector(".written-author"); const otherArrow = otherItem.querySelector("#arrow"); if (otherListWrap) { otherListWrap.style.color = "#8C8C8C"; otherListWrap.style.borderBottomColor = "#8C8C8C"; } if (otherAuthor) { otherAuthor.style.color = "#8C8C8C"; } if (otherArrow) { otherArrow.style.fill = "#8C8C8C"; // Change the fill color of the element with ID arrow to grey } } }); } // Function to handle leaving an item (either hover or touchend) function handleItemLeave(item) { // Reset the color and opacity of .writing-text-read and its characters on mouse leave gsap.set(item.querySelector(".writing-text-read"), { opacity: 0 }); gsap.set(item.querySelectorAll(".writing-text-read .word .char"), { color: "#0a0a0a", backgroundColor: "transparent", opacity: 0, }); // Set the color and border color of the current item to white on mouse leave const listWrap = item.querySelector(".writting-list-wrap"); const author = item.querySelector(".written-author"); const arrow = item.querySelector("#arrow"); if (listWrap) { listWrap.style.color = "#FFFFFF"; listWrap.style.borderBottomColor = "#FFFFFF"; } if (author) { author.style.color = "#FFFFFF"; } if (arrow) { arrow.style.fill = "#FFFFFF"; // Revert the fill color of the element with ID arrow to white } // Reset all other items to their default state (white) writingItems.forEach((otherItem) => { const otherListWrap = otherItem.querySelector(".writting-list-wrap"); const otherAuthor = otherItem.querySelector(".written-author"); const otherArrow = otherItem.querySelector("#arrow"); if (otherListWrap) { otherListWrap.style.color = "#FFFFFF"; otherListWrap.style.borderBottomColor = "#FFFFFF"; } if (otherAuthor) { otherAuthor.style.color = "#FFFFFF"; } if (otherArrow) { otherArrow.style.fill = "#FFFFFF"; // Revert the fill color of the element with ID arrow to white } }); } // Function to update writingItems and reassign event listeners function updateWritingItems() { // Refresh the list of items to ensure it's up-to-date writingItems = Array.from( document.querySelectorAll(".writing-content-collection-item") ); // Assign event listeners to all items writingItems.forEach((item, index) => { // Remove any existing event listeners to avoid duplicates item.removeEventListener("mouseenter", () => handleItemEnter(item, index) ); item.removeEventListener("mouseleave", () => handleItemLeave(item)); item.removeEventListener("touchstart", () => handleItemEnter(item, index) ); item.removeEventListener("touchend", () => handleItemLeave(item)); // Desktop: mouseenter and mouseleave item.addEventListener("mouseenter", () => handleItemEnter(item, index)); item.addEventListener("mouseleave", () => handleItemLeave(item)); // Mobile: touchstart and touchend item.addEventListener("touchstart", () => handleItemEnter(item, index)); item.addEventListener("touchend", () => handleItemLeave(item)); }); } updateWritingItems(); // Use MutationObserver to monitor changes in the list container const listContainer = document.querySelector( ".writing-collection-list.w-dyn-items" ); const observer = new MutationObserver(() => { updateWritingItems(); // Update items when a change in the list is detected // ADDED: also resync the empty state if the list display might have changed syncEmptyWithListDisplay(); }); // Observe changes in the child elements of the list container if (listContainer) { observer.observe(listContainer, { childList: true, // Watch for the addition or removal of child elements subtree: false, // Only watch for changes directly under the list container }); } // ADDED: keep `.new-search-empty` in sync with visibility of // `.writing-collection-list.is-list.w-dyn-items` const listForEmpty = document.querySelector( ".writing-collection-list.is-list.w-dyn-items" ); const newEmptyEl = document.querySelector(".new-search-empty"); function syncEmptyWithListDisplay() { if (!listForEmpty || !newEmptyEl) return; const hidden = getComputedStyle(listForEmpty).display === "none"; newEmptyEl.style.display = hidden ? "flex" : "none"; } // Initial sync syncEmptyWithListDisplay(); // React to inline style/class changes on the list element if (listForEmpty) { const emptyMO = new MutationObserver(syncEmptyWithListDisplay); emptyMO.observe(listForEmpty, { attributes: true, attributeFilter: ["style", "class"], }); } // Also re-check on resize (covers CSS-driven display changes) window.addEventListener("resize", syncEmptyWithListDisplay); // ------- CUSTOM TABS + TAB-AWARE SEARCH (with real empty-state) ------- function initWritingTabsAndSearch() { const SEARCH_INPUT = document.querySelector('#search-input'); const TABS_ROOT = document.querySelector('.writing-tabs'); if (!SEARCH_INPUT || !TABS_ROOT) { console.warn('Missing #search-input or .writing-tabs'); return; } // Structure const menus = Array.from(TABS_ROOT.querySelectorAll('.tabs-menu .tab-menu')); const panes = Array.from(TABS_ROOT.querySelectorAll('.tabs-content .tab-content')); // Inner selectors const LIST_SELECTOR = '.writing-collection-list.is-list.w-dyn-items'; const ITEM_SELECTOR = '.writing-collection-item.is-list'; const TITLE_SELECTOR = '.article-card-heading'; // Seed original order per pane panes.forEach((pane) => { const list = pane.querySelector(LIST_SELECTOR); if (!list) return; Array.from(list.querySelectorAll(ITEM_SELECTOR)).forEach((it, i) => { if (!it.dataset.originalIndex) it.dataset.originalIndex = String(i); }); }); const getActiveIndex = () => { const idx = menus.findIndex(m => m.classList.contains('is-active')); return idx >= 0 ? idx : 0; }; const getActivePane = () => panes[getActiveIndex()] || null; // --- Empty-state per pane: show .new-search-empty only if the pane has NO items --- function syncEmptyState(pane) { const emptyEl = pane.querySelector('.new-search-empty'); if (!emptyEl) return; const list = pane.querySelector(LIST_SELECTOR); const hasItems = !!(list && list.querySelector(ITEM_SELECTOR)); emptyEl.style.display = hasItems ? 'none' : 'flex'; } // Keep empties synced even if CMS/FS modifies the DOM panes.forEach((pane) => { const watchEl = pane.querySelector('.new-writing-collection-list-wrapper') || pane.querySelector('.w-dyn-list') || pane; new MutationObserver(() => syncEmptyState(pane)).observe(watchEl, { childList: true, subtree: true, attributes: true, attributeFilter: ['class', 'style'], }); // initial sync syncEmptyState(pane); }); function resetHighlights(items) { items.forEach((it) => { const t = it.querySelector(TITLE_SELECTOR); if (t) t.innerHTML = t.textContent || ''; }); } function performSearchInActivePane() { const pane = getActivePane(); if (!pane) return; const list = pane.querySelector(LIST_SELECTOR); if (!list) { syncEmptyState(pane); return; } const items = Array.from(list.querySelectorAll(ITEM_SELECTOR)); const q = (SEARCH_INPUT.value || '').trim().toLowerCase(); // Ensure original index for any new items items.forEach((it, i) => { if (!it.dataset.originalIndex) it.dataset.originalIndex = String(i); }); if (!q) { resetHighlights(items); items .sort((a, b) => (+a.dataset.originalIndex || 0) - (+b.dataset.originalIndex || 0)) .forEach(el => list.appendChild(el)); if (typeof updateWritingItems === 'function') updateWritingItems(); // Empty state depends ONLY on actual presence of items syncEmptyState(pane); return; } const results = items.map((item) => { const titleEl = item.querySelector(TITLE_SELECTOR); if (!titleEl) return { item, score: 0, pos: 1e9 }; const raw = titleEl.textContent || ''; const hay = raw.toLowerCase(); const pos = hay.indexOf(q); // clear previous markup titleEl.innerHTML = raw; if (pos !== -1) { const before = raw.slice(0, pos); const match = raw.slice(pos, pos + q.length); const after = raw.slice(pos + q.length); titleEl.innerHTML = `${before}${match}${after}`; return { item, score: 1, pos }; } return { item, score: 0, pos: 1e9 }; }); results .sort((a, b) => { if (a.score !== b.score) return b.score - a.score; if (a.pos !== b.pos) return a.pos - b.pos; const ai = +a.item.dataset.originalIndex || 0; const bi = +b.item.dataset.originalIndex || 0; return ai - bi; }) .forEach(r => list.appendChild(r.item)); if (typeof updateWritingItems === 'function') updateWritingItems(); // NOTE: we do NOT show the empty here for "no matches"; // it only reflects true CMS emptiness of the pane. syncEmptyState(pane); } // Tab switching function activateTab(index) { menus.forEach((m, i) => { if (i === index) m.classList.add('is-active'); else m.classList.remove('is-active'); }); panes.forEach((p, i) => { if (i === index) p.classList.remove('is-inactive'); else p.classList.add('is-inactive'); // Keep each pane’s empty state correct syncEmptyState(p); }); performSearchInActivePane(); } menus.forEach((menu, idx) => { menu.addEventListener('click', (e) => { e.preventDefault(); if (menu.classList.contains('is-active')) return; activateTab(idx); }); menu.setAttribute('tabindex', '0'); menu.addEventListener('keydown', (e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); activateTab(idx); } }); }); // Search bindings SEARCH_INPUT.addEventListener('keydown', (e) => { if (e.key === 'Enter') e.preventDefault(); }); SEARCH_INPUT.addEventListener('input', performSearchInActivePane); // Initial run performSearchInActivePane(); } // Call at the end of initWritingAnimations() initWritingTabsAndSearch(); initializeEmailValidation(); function initializeEmailValidation() { const emailInput = document.getElementById("Email"); const submitInput = document.getElementById("submit"); const errorElement = document.getElementById("error"); // Assuming an element with ID 'error' exists for error messages if (!emailInput || !submitInput || !errorElement) { // If the elements are not found, exit the function early return; } function validateEmail(email) { const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; return emailPattern.test(email); } function handleValidation() { const emailValue = emailInput.value.trim(); if (validateEmail(emailValue)) { console.log("Valid email:", emailValue); errorElement.style.display = "none"; // Hide the error message if email is valid // Simulate another click on the submit input if email is valid submitInput.removeEventListener("click", handleSubmitClick); submitInput.click(); submitInput.addEventListener("click", handleSubmitClick); } else { console.log("Invalid email:", emailValue); errorElement.style.display = "block"; // Show the error message if email is invalid } } function handleSubmitClick(event) { event.preventDefault(); // Prevent default submission for validation purposes console.log('Submit input with ID "submit" was clicked'); handleValidation(); // Validate email on click } // Track Enter key press and click events for input with ID 'Email' emailInput.addEventListener("keydown", function (event) { if (event.key === "Enter") { event.preventDefault(); console.log('Enter key press detected in input field with ID "Email"'); handleValidation(); // Validate email on Enter press } }); emailInput.addEventListener("click", function () { console.log('Input field with ID "Email" was clicked'); }); // Track Enter key press for input with ID 'submit' submitInput.addEventListener("keydown", function (event) { if (event.key === "Enter") { event.preventDefault(); console.log( 'Enter key press detected on submit input with ID "submit"' ); handleValidation(); } }); // Track click events for input with ID 'submit' submitInput.addEventListener("click", handleSubmitClick); } } function initWritingsAnimations() { window.scrollTo(0, 0); let typeSplit = new SplitType( ".footer-link, .writings-text-read, .menu-item-prefix, .fs_prevnext_block", { types: "words, chars", tagName: "span", } ); document.addEventListener("DOMContentLoaded", () => { const currentUrl = window.location.href; const menuLinks = document.querySelectorAll(".menu-link-wrap"); menuLinks.forEach((link) => { if (link.href === currentUrl) { link.style.display = "none"; } }); }); function getRandomLetter(length) { var result = ""; var characters = "{}[]();<>!?$%^&*"; var charactersLength = characters.length; for (var i = 0; i < length; i++) { result += characters.charAt(Math.floor(Math.random() * charactersLength)); } return result; } $(".char").each(function (index) { let text = $(this).text(); $(this).attr("letter", text); }); $(".footer-link, .fs_prevnext_block").each(function (index) { function resetText() { if (myInterval !== undefined) { clearInterval(myInterval); } chars.each(function (index) { let letter = $(this).attr("letter"); $(this).text(letter); $(this).css("background-color", "transparent"); // Reset background color $(this).css("color", ""); // Reset text color }); } let myInterval; let chars = $(this).find(".char"); function startEffect() { let length = chars.length; let currentIndex = 0; // Start from the first character let previousIndex = -1; // Track the previous character myInterval = setInterval(function () { // Reset the previous character back to normal if (previousIndex >= 0) { let previousCharElement = chars.eq(previousIndex); let originalLetter = previousCharElement.attr("letter"); previousCharElement.text(originalLetter); // Reset to original letter previousCharElement.css("background-color", "transparent"); // Reset background color previousCharElement.css("color", ""); // Reset text color } if (currentIndex < length) { let charElement = chars.eq(currentIndex); // Get the current character let letter = getRandomLetter(1); // Get a random letter charElement.text(letter); // Replace the character with the random letter charElement.css("background-color", "#6EF0DC"); // Change background color charElement.css("color", "#0a0a0a"); // Change text color to black previousIndex = currentIndex; // Set the previous index to the current one currentIndex++; // Move to the next character } else { clearInterval(myInterval); // Stop the interval when all characters are processed setTimeout(() => { resetText(); }, 200); // Wait before resetting the text } }, 70); // Adjust the speed here if needed } $(this).on("mouseenter touchstart", function () { startEffect(); // Start the effect on hover or touchstart (for mobile) }); $(this).on("mouseleave touchend", function () { resetText(); // Reset the text when mouse leaves or finger is lifted }); }); document.querySelectorAll(".menu-link-wrap").forEach((menuLink) => { menuLink.addEventListener("mouseenter", () => { gsap.set(menuLink.querySelector(".menu-item-prefix"), { opacity: 1 }); gsap.set(menuLink.querySelector(".menu-item-sufix"), { opacity: 1 }); gsap.set(".menu-item-label, .section-header", { color: "#8C8C8C" }); gsap.set(menuLink.querySelector(".menu-item-label"), { color: "#FFFFFF", opacity: 1, }); // Animate each .char child of .word elements within menu-item-prefix one by one, sequentially const menuChars = menuLink.querySelectorAll( ".menu-item-prefix .word .char" ); let menuTimeline = gsap.timeline({ defaults: { duration: 0.07, ease: "none" }, }); Array.from(menuChars).forEach((char) => { menuTimeline.fromTo( char, { color: "#0a0a0a", backgroundColor: "transparent" }, { color: "#6EF0DC", backgroundColor: "#6EF0DC", onComplete: () => { gsap.set(char, { backgroundColor: "transparent" }); // Ensure background reverts after reveal }, } ); }); }); menuLink.addEventListener("mouseleave", () => { gsap.set(menuLink.querySelector(".menu-item-prefix"), { opacity: 0 }); gsap.set(menuLink.querySelector(".menu-item-sufix"), { opacity: 0 }); gsap.set(".menu-item-label, .section-header", { color: "#FFFFFF", opacity: 1, }); }); // Add click event listener to reduce opacity of other menu links menuLink.addEventListener("click", () => { // Check if the link has #opportunities in its href if (menuLink.href.includes("#opportunities")) { menuLink.setAttribute("data-animation", "third-out"); } else { menuLink.setAttribute("data-animation", "fourth-out"); } // Reduce opacity of all other menu links over 1 second document.querySelectorAll(".menu-link-wrap").forEach((otherLink) => { if (otherLink !== menuLink) { gsap.to(otherLink, { opacity: 0, duration: 0.3 }); otherLink.style.pointerEvents = "none"; // Disable pointer events for non-clicked links } }); // Disable pointer events for the clicked link as well menuLink.style.pointerEvents = "none"; menuLink.querySelectorAll("*:not(.menu-item-label)").forEach((child) => { gsap.to(child, { opacity: 0, duration: 0.3 }); }); }); }); // Add click event listener for elements with data-homepage attribute document.querySelectorAll("[data-homepage]").forEach((homepageElement) => { homepageElement.addEventListener("click", () => { // Add data-animation="third-out" to the .menu-wrap element const menuWrap = document.querySelector(".menu-wrap"); if (menuWrap) { menuWrap.setAttribute("data-animation", "third-out"); } // Add data-animation="third-out" to the .mobile-menu-wrap element const mobileMenuWrap = document.querySelector(".mobile-menu-wrap"); if (mobileMenuWrap) { mobileMenuWrap.setAttribute("data-animation", "third-out"); } }); }); // Select all recommended article items const recommendedItems = document.querySelectorAll( ".recommended-articles-list-item" ); // Function to handle entering an item (either hover or touchstart) function handleItemEnter(item, index) { // Set the initial color and opacity of the .writings-text-read container gsap.set(item.querySelector(".writings-text-read"), { opacity: 1, color: "#6EF0DC", }); // Animate each character within .writings-text-read const writingChars = item.querySelectorAll( ".writings-text-read .word .char" ); let writingTimeline = gsap.timeline({ defaults: { duration: 0.07, ease: "none" }, }); writingChars.forEach((char) => { writingTimeline.fromTo( char, { color: "#0a0a0a", backgroundColor: "transparent", opacity: 0 }, { color: "#6EF0DC", backgroundColor: "#6EF0DC", opacity: 1, onComplete: () => { gsap.set(char, { backgroundColor: "transparent" }); }, } ); }); // Set color and border color for the current hovered item const listWrap = item.querySelector(".recommended-list-wrap"); const author = item.querySelector(".recommended-article-written"); const arrow = item.querySelector("#arrow"); if (listWrap) { listWrap.style.color = "#6EF0DC"; listWrap.style.borderBottomColor = "#6EF0DC"; } if (author) { author.style.color = "#6EF0DC"; } if (arrow) { arrow.style.fill = "#6EF0DC"; // Change the fill color of the element with ID arrow } // Set the previous item's border color if it exists if (index > 0) { setTimeout(() => { const previousItem = recommendedItems[index - 1]; const previousListWrap = previousItem.querySelector( ".recommended-list-wrap" ); if (previousListWrap) { previousListWrap.style.borderBottomColor = "#8C8C8C"; } }, 10); // Delay to ensure hover styles are set first } // Set all other items to greyed-out colors recommendedItems.forEach((otherItem) => { if (otherItem !== item) { const otherListWrap = otherItem.querySelector(".recommended-list-wrap"); const otherAuthor = otherItem.querySelector( ".recommended-article-written" ); const otherArrow = otherItem.querySelector("#arrow"); if (otherListWrap) { otherListWrap.style.color = "#8C8C8C"; otherListWrap.style.borderBottomColor = "#8C8C8C"; } if (otherAuthor) { otherAuthor.style.color = "#8C8C8C"; } if (otherArrow) { otherArrow.style.fill = "#8C8C8C"; // Change the fill color of the element with ID arrow to grey } } }); } // Function to handle leaving an item (either hover or touchend) function handleItemLeave(item) { // Reset the color and opacity of .writings-text-read and its characters on mouse leave gsap.set(item.querySelector(".writings-text-read"), { opacity: 0 }); gsap.set(item.querySelectorAll(".writings-text-read .word .char"), { color: "#0a0a0a", backgroundColor: "transparent", opacity: 0, }); // Set the color and border color of the current item to white on mouse leave const listWrap = item.querySelector(".recommended-list-wrap"); const author = item.querySelector(".recommended-article-written"); const arrow = item.querySelector("#arrow"); if (listWrap) { listWrap.style.color = "#FFFFFF"; listWrap.style.borderBottomColor = "#FFFFFF"; } if (author) { author.style.color = "#FFFFFF"; } if (arrow) { arrow.style.fill = "#FFFFFF"; // Revert the fill color of the element with ID arrow to white } // Reset all other items to their default state (white) recommendedItems.forEach((otherItem) => { const otherListWrap = otherItem.querySelector(".recommended-list-wrap"); const otherAuthor = otherItem.querySelector( ".recommended-article-written" ); const otherArrow = otherItem.querySelector("#arrow"); if (otherListWrap) { otherListWrap.style.color = "#FFFFFF"; otherListWrap.style.borderBottomColor = "#FFFFFF"; } if (otherAuthor) { otherAuthor.style.color = "#FFFFFF"; } if (otherArrow) { otherArrow.style.fill = "#FFFFFF"; // Revert the fill color of the element with ID arrow to white } }); } // Add event listeners for each item recommendedItems.forEach((item, index) => { item.addEventListener("mouseenter", () => handleItemEnter(item, index)); item.addEventListener("mouseleave", () => handleItemLeave(item)); item.addEventListener("touchstart", () => handleItemEnter(item, index)); item.addEventListener("touchend", () => handleItemLeave(item)); }); const script = document.createElement("script"); script.src = "https://cdn.jsdelivr.net/npm/@finsweet/attributes-cmsprevnext@1/cmsprevnext.js"; script.async = true; document.head.appendChild(script); } function initTeamsAnimations() { document.addEventListener("DOMContentLoaded", () => { const currentUrl = window.location.href; const menuLinks = document.querySelectorAll(".menu-link-wrap"); menuLinks.forEach((link) => { if (link.href === currentUrl) { link.style.display = "none"; } }); }); let typeSplit = new SplitType(".footer-link, .menu-item-prefix", { types: "words, chars", tagName: "span", }); function getRandomLetter(length) { var result = ""; var characters = "{}[]();<>!?$%^&*"; var charactersLength = characters.length; for (var i = 0; i < length; i++) { result += characters.charAt(Math.floor(Math.random() * charactersLength)); } return result; } $(".char").each(function (index) { let text = $(this).text(); $(this).attr("letter", text); }); $(".footer-link, .accordion-button-wrap").each(function (index) { function resetText() { if (myInterval !== undefined) { clearInterval(myInterval); } chars.each(function (index) { let letter = $(this).attr("letter"); $(this).text(letter); $(this).css("background-color", "transparent"); $(this).css("color", ""); }); } let myInterval; let chars = $(this).find(".char"); function startEffect() { let length = chars.length; let currentIndex = 0; let previousIndex = -1; myInterval = setInterval(function () { if (previousIndex >= 0) { let previousCharElement = chars.eq(previousIndex); let originalLetter = previousCharElement.attr("letter"); previousCharElement.text(originalLetter); previousCharElement.css("background-color", "transparent"); previousCharElement.css("color", ""); } if (currentIndex < length) { let charElement = chars.eq(currentIndex); let letter = getRandomLetter(1); charElement.text(letter); charElement.css("background-color", "#6EF0DC"); charElement.css("color", "black"); previousIndex = currentIndex; currentIndex++; } else { clearInterval(myInterval); setTimeout(() => { resetText(); }, 200); // Wait before resetting the text } }, 70); // Adjust the speed here if needed } $(this).on("mouseenter touchstart", function () { startEffect(); // Start the effect on hover or touchstart (for mobile) }); $(this).on("mouseleave touchend", function () { resetText(); // Reset the text when mouse leaves or finger is lifted }); }); document.querySelectorAll(".menu-link-wrap").forEach((menuLink) => { menuLink.addEventListener("mouseenter", () => { gsap.set(menuLink.querySelector(".menu-item-prefix"), { opacity: 1 }); gsap.set(menuLink.querySelector(".menu-item-sufix"), { opacity: 1 }); gsap.set( ".menu-item-label, .logo-header-wrap, .section-home-header, .footer-links-wrap", { color: "#8C8C8C" } ); gsap.set(menuLink.querySelector(".menu-item-label"), { color: "#FFFFFF", opacity: 1, }); // Animate each .char child of .word elements within menu-item-prefix one by one, sequentially const menuChars = menuLink.querySelectorAll( ".menu-item-prefix .word .char" ); let menuTimeline = gsap.timeline({ defaults: { duration: 0.07, ease: "none" }, }); Array.from(menuChars).forEach((char) => { menuTimeline.fromTo( char, { color: "black", backgroundColor: "transparent" }, { color: "#6EF0DC", backgroundColor: "#6EF0DC", onComplete: () => { gsap.set(char, { backgroundColor: "transparent" }); // Ensure background reverts after reveal }, } ); }); }); menuLink.addEventListener("mouseleave", () => { gsap.set(menuLink.querySelector(".menu-item-prefix"), { opacity: 0 }); gsap.set(menuLink.querySelector(".menu-item-sufix"), { opacity: 0 }); gsap.set( ".menu-item-label, .logo-header-wrap, .section-home-header, .footer-links-wrap", { color: "#FFFFFF", opacity: 1 } ); }); // Add click event listener to reduce opacity of other menu links menuLink.addEventListener("click", () => { // Check if the link has #opportunities in its href if (menuLink.href.includes("#opportunities")) { menuLink.setAttribute("data-animation", "third-out"); } else { menuLink.setAttribute("data-animation", "fourth-out"); } // Reduce opacity of all other menu links over 0.3 seconds document.querySelectorAll(".menu-link-wrap").forEach((otherLink) => { if (otherLink !== menuLink) { gsap.to(otherLink, { opacity: 0, duration: 0.3 }); otherLink.style.pointerEvents = "none"; // Disable pointer events for non-clicked links } }); // Disable pointer events for the clicked link as well menuLink.style.pointerEvents = "none"; // Reduce opacity of all children of the clicked link except .menu-item-label menuLink.querySelectorAll("*:not(.menu-item-label)").forEach((child) => { gsap.to(child, { opacity: 0, duration: 0.3 }); }); }); }); // Add click event listener for elements with data-homepage attribute document.querySelectorAll("[data-homepage]").forEach((homepageElement) => { homepageElement.addEventListener("click", () => { // Add data-animation="third-out" to the .menu-wrap element const menuWrap = document.querySelector(".menu-wrap"); if (menuWrap) { menuWrap.setAttribute("data-animation", "third-out"); } // Add data-animation="third-out" to the .mobile-menu-wrap element const mobileMenuWrap = document.querySelector(".mobile-menu-wrap"); if (mobileMenuWrap) { mobileMenuWrap.setAttribute("data-animation", "third-out"); } }); }); // Initial state setup using GSAP to make sure everything is set as expected gsap.set(".menu-item-prefix, .menu-item-sufix", { opacity: 0 }); gsap.set( ".menu-item-label, .logo-header-wrap, .section-home-header, .footer-links-wrap", { opacity: 1, color: "#FFFFFF" } ); } function init404Animations() { document.addEventListener("DOMContentLoaded", () => { const currentUrl = window.location.href; const menuLinks = document.querySelectorAll(".menu-link-wrap"); menuLinks.forEach((link) => { if (link.href === currentUrl) { link.style.display = "none"; } }); }); let typeSplit = new SplitType(".footer-link, .menu-item-prefix", { types: "words, chars", tagName: "span", }); function getRandomLetter(length) { var result = ""; var characters = "{}[]();<>!?$%^&*"; var charactersLength = characters.length; for (var i = 0; i < length; i++) { result += characters.charAt(Math.floor(Math.random() * charactersLength)); } return result; } $(".char").each(function (index) { let text = $(this).text(); $(this).attr("letter", text); }); $(".footer-link").each(function (index) { function resetText() { if (myInterval !== undefined) { clearInterval(myInterval); } chars.each(function (index) { let letter = $(this).attr("letter"); $(this).text(letter); $(this).css("background-color", "transparent"); // Reset background color $(this).css("color", ""); // Reset text color }); } let myInterval; let chars = $(this).find(".char"); function startEffect() { let length = chars.length; let currentIndex = 0; // Start from the first character let previousIndex = -1; // Track the previous character myInterval = setInterval(function () { // Reset the previous character back to normal if (previousIndex >= 0) { let previousCharElement = chars.eq(previousIndex); let originalLetter = previousCharElement.attr("letter"); previousCharElement.text(originalLetter); // Reset to original letter previousCharElement.css("background-color", "transparent"); // Reset background color previousCharElement.css("color", ""); // Reset text color } if (currentIndex < length) { let charElement = chars.eq(currentIndex); // Get the current character let letter = getRandomLetter(1); // Get a random letter charElement.text(letter); // Replace the character with the random letter charElement.css("background-color", "#6EF0DC"); // Change background color charElement.css("color", "#0a0a0a"); // Change text color to black previousIndex = currentIndex; // Set the previous index to the current one currentIndex++; // Move to the next character } else { clearInterval(myInterval); // Stop the interval when all characters are processed setTimeout(() => { resetText(); }, 200); // Wait before resetting the text } }, 70); // Adjust the speed here if needed } $(this).on("mouseenter touchstart", function () { startEffect(); // Start the effect on hover or touchstart (for mobile) }); $(this).on("mouseleave touchend", function () { resetText(); // Reset the text when mouse leaves or finger is lifted }); }); document.querySelectorAll(".menu-link-wrap").forEach((menuLink) => { menuLink.addEventListener("mouseenter", () => { gsap.set(menuLink.querySelector(".menu-item-prefix"), { opacity: 1 }); gsap.set(menuLink.querySelector(".menu-item-sufix"), { opacity: 1 }); gsap.set(".menu-item-label, .logo-header-wrap, .section-home-header", { color: "#8C8C8C", }); gsap.set(menuLink.querySelector(".menu-item-label"), { color: "#FFFFFF", opacity: 1, }); // Animate each .char child of .word elements within menu-item-prefix one by one, sequentially const menuChars = menuLink.querySelectorAll( ".menu-item-prefix .word .char" ); let menuTimeline = gsap.timeline({ defaults: { duration: 0.07, ease: "none" }, }); Array.from(menuChars).forEach((char) => { menuTimeline.fromTo( char, { color: "#0a0a0a", backgroundColor: "transparent" }, { color: "#6EF0DC", backgroundColor: "#6EF0DC", onComplete: () => { gsap.set(char, { backgroundColor: "transparent" }); // Ensure background reverts after reveal }, } ); }); }); menuLink.addEventListener("mouseleave", () => { gsap.set(menuLink.querySelector(".menu-item-prefix"), { opacity: 0 }); gsap.set(menuLink.querySelector(".menu-item-sufix"), { opacity: 0 }); gsap.set(".menu-item-label, .logo-header-wrap, .section-home-header", { color: "#FFFFFF", opacity: 1, }); }); // Add click event listener to reduce opacity of other menu links menuLink.addEventListener("click", () => { // Check if the link has #opportunities in its href if (menuLink.href.includes("#opportunities")) { menuLink.setAttribute("data-animation", "third-out"); } else { menuLink.setAttribute("data-animation", "fourth-out"); } // Reduce opacity of all other menu links over 1 second document.querySelectorAll(".menu-link-wrap").forEach((otherLink) => { if (otherLink !== menuLink) { gsap.to(otherLink, { opacity: 0, duration: 0.3 }); otherLink.style.pointerEvents = "none"; // Disable pointer events for non-clicked links } }); // Disable pointer events for the clicked link as well menuLink.style.pointerEvents = "none"; // Reduce opacity of all children of the clicked link except .menu-item-label menuLink.querySelectorAll("*:not(.menu-item-label)").forEach((child) => { gsap.to(child, { opacity: 0, duration: 0.3 }); }); }); }); // Add click event listener for elements with data-homepage attribute document.querySelectorAll("[data-homepage]").forEach((homepageElement) => { homepageElement.addEventListener("click", () => { // Add data-animation="third-out" to the .menu-wrap element const menuWrap = document.querySelector(".menu-wrap"); if (menuWrap) { menuWrap.setAttribute("data-animation", "third-out"); } // Add data-animation="third-out" to the .mobile-menu-wrap element const mobileMenuWrap = document.querySelector(".mobile-menu-wrap"); if (mobileMenuWrap) { mobileMenuWrap.setAttribute("data-animation", "third-out"); } }); }); } function initValidator() { let cachedPatch = null; // We'll cache the exported patch once loaded. // Helper to load the script and cache the patch. function loadAndCachePatch(callback) { loadCablesScript( "https://cdn.prod.website-files.com/670e3bce95be1572f35a93bc/6755eb81df4c47e427d17fa8_last-patchv2.txt", () => { if (typeof CABLES !== "undefined" && CABLES.exportedPatch) { cachedPatch = CABLES.exportedPatch; callback(); } else { console.error("CABLES or exportedPatch is undefined after loading the script."); } } ); } // Function to initialize the first canvas. function initValidatorCanvas1() { const canvasContainer = document.getElementById("validatorcanvas1"); if (!canvasContainer) { console.warn("No canvas container found with id validatorcanvas1."); return; } new CABLES.Patch({ patch: cachedPatch, prefixAssetPath: "", assetPath: "assets/", jsPath: "js/", glCanvasId: "validatorcanvas1", glCanvasResizeToWindow: false, onError: showError, onPatchLoaded: patchInitialized, onFinishedLoading: createPatchFinishedLoading("validatorcanvas1"), canvas: { alpha: true, premultipliedAlpha: true }, variables: { fillBg: 0, }, }); console.log("CablesGL Patch Initialized on canvas validatorcanvas1."); } // Function to initialize the second canvas. function initValidatorCanvas2() { const canvasContainer = document.getElementById("validatorcanvas2"); if (!canvasContainer) { console.warn("No canvas container found with id validatorcanvas2."); return; } new CABLES.Patch({ patch: cachedPatch, prefixAssetPath: "", assetPath: "assets/", jsPath: "js/", glCanvasId: "validatorcanvas2", glCanvasResizeToWindow: false, onError: showError, onPatchLoaded: patchInitialized, onFinishedLoading: createPatchFinishedLoading("validatorcanvas2"), canvas: { alpha: true, premultipliedAlpha: true }, variables: { fillBg: 0, }, }); console.log("CablesGL Patch Initialized on canvas validatorcanvas2."); } // Load the external script once, then initialize both canvases. loadAndCachePatch(() => { initValidatorCanvas1(); initValidatorCanvas2(); // Attach event listeners to all three canvas elements. ["validatorcanvas1", "validatorcanvas2"].forEach((id) => { const canvas = document.getElementById(id); if (canvas) { canvas.addEventListener("touchend", () => { // Reset the active element to the body document.body.focus(); // Remove the 'touch-action: none;' style from the body document.body.style.touchAction = ""; }); canvas.addEventListener("blur", () => { // Reset the active element to the body document.body.focus(); // Remove the 'touch-action: none;' style from the body document.body.style.touchAction = ""; }); } }); }); // ----------------------------- // GSAP Animation for .trusted-bullets // ----------------------------- // If the DOM is already loaded, run the animation immediately. // Otherwise, wrap it in a DOMContentLoaded listener. function runTrustedBulletsAnimation() { // Select all .trusted-bullets elements const trustedBullets = document.querySelectorAll(".trusted-bullets"); trustedBullets.forEach((bullet, index) => { // Set initial state for the container gsap.set(bullet, { opacity: 0 }); // Create a timeline for this bullet element, delaying each one slightly based on its index let tl = gsap.timeline({ delay: index * 0.2 }); // Fade in the container over 0.5 seconds tl.to(bullet, { opacity: 1, duration: 0.5 }); // Grab all .char elements within this bullet (assumes SplitType has already run) const chars = bullet.querySelectorAll('.char'); // Ensure each char starts fully transparent with a transparent background gsap.set(chars, { opacity: 0, backgroundColor: "transparent" }); // Create a nested timeline for the character animations so they start only after the container fades in let charTl = gsap.timeline(); chars.forEach((char) => { charTl.fromTo( char, { opacity: 0, backgroundColor: "transparent" }, { opacity: 1, backgroundColor: "#ffffff", // Animate to white background duration: 0.07, ease: "none", onComplete: () => { // Revert background to transparent after the reveal gsap.set(char, { backgroundColor: "transparent" }); } } ); }); // Add the nested character timeline to the main timeline. tl.add(charTl, "-=0.2"); }); } if (document.readyState === "loading") { document.addEventListener("DOMContentLoaded", runTrustedBulletsAnimation); } else { runTrustedBulletsAnimation(); } } function initNozemi() { let cachedPatch = null; // We'll cache the exported patch once loaded. // Helper to load the script and cache the patch. function loadAndCachePatch(callback) { loadCablesScript( "https://cdn.prod.website-files.com/670e3bce95be1572f35a93bc/6755eb81df4c47e427d17fa8_last-patchv2.txt", () => { if (typeof CABLES !== "undefined" && CABLES.exportedPatch) { cachedPatch = CABLES.exportedPatch; callback(); } else { console.error("CABLES or exportedPatch is undefined after loading the script."); } } ); } // Function to initialize the first canvas. function initNozemiCanvas1() { const canvasContainer = document.getElementById("nozemicanvas1"); if (!canvasContainer) { console.warn("No canvas container found with id nozemicanvas1."); return; } new CABLES.Patch({ patch: cachedPatch, prefixAssetPath: "", assetPath: "assets/", jsPath: "js/", glCanvasId: "nozemicanvas1", glCanvasResizeToWindow: false, onError: showError, onPatchLoaded: patchInitialized, onFinishedLoading: createPatchFinishedLoading("nozemicanvas1"), canvas: { alpha: true, premultipliedAlpha: true }, variables: { fillBg: 0, }, }); console.log("CablesGL Patch Initialized on canvas nozemicanvas1."); } // Function to initialize the second canvas. function initNozemiCanvas2() { const canvasContainer = document.getElementById("nozemicanvas2"); if (!canvasContainer) { console.warn("No canvas container found with id nozemicanvas2."); return; } new CABLES.Patch({ patch: cachedPatch, prefixAssetPath: "", assetPath: "assets/", jsPath: "js/", glCanvasId: "nozemicanvas2", glCanvasResizeToWindow: false, onError: showError, onPatchLoaded: patchInitialized, onFinishedLoading: createPatchFinishedLoading("nozemicanvas2"), canvas: { alpha: true, premultipliedAlpha: true }, variables: { fillBg: 0, }, }); console.log("CablesGL Patch Initialized on canvas nozemicanvas2."); } // Function to initialize the third canvas. function initNozemiCanvas3() { const canvasContainer = document.getElementById("nozemicanvas3"); if (!canvasContainer) { console.warn("No canvas container found with id nozemicanvas3."); return; } new CABLES.Patch({ patch: cachedPatch, prefixAssetPath: "", assetPath: "assets/", jsPath: "js/", glCanvasId: "nozemicanvas3", glCanvasResizeToWindow: false, onError: showError, onPatchLoaded: patchInitialized, onFinishedLoading: createPatchFinishedLoading("nozemicanvas3"), canvas: { alpha: true, premultipliedAlpha: true }, variables: { fillBg: 0, }, }); console.log("CablesGL Patch Initialized on canvas nozemicanvas3."); } // Load the external script once, then initialize all three canvases. loadAndCachePatch(() => { initNozemiCanvas1(); initNozemiCanvas2(); initNozemiCanvas3(); // Attach event listeners to all three canvas elements. ["nozemicanvas1", "nozemicanvas2", "nozemicanvas3"].forEach((id) => { const canvas = document.getElementById(id); if (canvas) { canvas.addEventListener("touchend", () => { // Reset the active element to the body document.body.focus(); // Remove the 'touch-action: none;' style from the body document.body.style.touchAction = ""; }); canvas.addEventListener("blur", () => { // Reset the active element to the body document.body.focus(); // Remove the 'touch-action: none;' style from the body document.body.style.touchAction = ""; }); } }); }); // ----------------------------- // GSAP Animation for .trusted-bullets // ----------------------------- // If the DOM is already loaded, run the animation immediately. // Otherwise, wrap it in a DOMContentLoaded listener. function runTrustedBulletsAnimation() { // Select all .trusted-bullets elements const trustedBullets = document.querySelectorAll(".trusted-bullets"); trustedBullets.forEach((bullet, index) => { // Set initial state for the container gsap.set(bullet, { opacity: 0 }); // Create a timeline for this bullet element, delaying each one slightly based on its index let tl = gsap.timeline({ delay: index * 0.2 }); // Fade in the container over 0.5 seconds tl.to(bullet, { opacity: 1, duration: 0.5 }); // Grab all .char elements within this bullet (assumes SplitType has already run) const chars = bullet.querySelectorAll('.char'); // Ensure each char starts fully transparent with a transparent background gsap.set(chars, { opacity: 0, backgroundColor: "transparent" }); // Create a nested timeline for the character animations so they start only after the container fades in let charTl = gsap.timeline(); chars.forEach((char) => { charTl.fromTo( char, { opacity: 0, backgroundColor: "transparent" }, { opacity: 1, backgroundColor: "#ffffff", // Animate to white background duration: 0.07, ease: "none", onComplete: () => { // Revert background to transparent after the reveal gsap.set(char, { backgroundColor: "transparent" }); } } ); }); // Add the nested character timeline to the main timeline. tl.add(charTl, "-=0.2"); }); } if (document.readyState === "loading") { document.addEventListener("DOMContentLoaded", runTrustedBulletsAnimation); } else { runTrustedBulletsAnimation(); } }