1 document.addEventListener("DOMContentLoaded", () => { 2 gsap.registerPlugin(ScrollTrigger); 3 4 // âââ FADE-IN ENTRATA âââââââââââââââââââââââââââââââââââââââââââââââââââââ 5 gsap.to("#page-content", { opacity: 1, y: 0, duration: 0.6, ease: "power3.out" }); 6 7 if (document.getElementById("real-header")) { 8 gsap.to("#real-header", { opacity: 1, duration: 0.6, ease: "power2.out", delay: 0.2 }); 9 } else if (document.getElementById("real-header-logo")) { 10 gsap.to(["#real-header-logo", "#menu-toggle"], { opacity: 1, duration: 0.6, ease: "power2.out", delay: 0.2 }); 11 } 12 13 // âââ SCROLL REVEAL âââââââââââââââââââââââââââââââââââââââââââââââââââââââ 14 gsap.utils.toArray(".reveal-text").forEach(el => { 15 gsap.from(el, { 16 scrollTrigger: { trigger: el, start: "top 85%", toggleActions: "play none none reverse" }, 17 y: 30, opacity: 0, duration: 0.8, ease: "power2.out" 18 }); 19 }); 20 21 // âââ HAMBURGER MENU ââââââââââââââââââââââââââââââââââââââââââââââââââââââ 22 const menuToggle = document.getElementById("menu-toggle"); 23 if (!menuToggle) return; 24 25 const line1 = menuToggle.querySelector(".line-1"); 26 const line2 = menuToggle.querySelector(".line-2"); 27 28 // Stato iniziale: menu fuori schermo a destra, invisibile 29 gsap.set("#fullscreen-menu", { xPercent: 100, autoAlpha: 0 }); 30 31 const menuTl = gsap.timeline({ paused: true, reversed: true }) 32 .set("#fullscreen-menu", { autoAlpha: 1, pointerEvents: "auto" }) 33 .to("#fullscreen-menu", { xPercent: 0, duration: 0.7, ease: "power4.inOut" }) 34 .to(".menu-link", { y: "0%", duration: 0.5, stagger: 0.1, ease: "power3.out" }, "-=0.3") 35 .to(".menu-info", { opacity: 1, x: 0, duration: 0.5, stagger: 0.1, ease: "power3.out" }, "-=0.4"); 36 37 function closeMenu() { 38 menuToggle.classList.remove("active"); 39 document.body.style.overflow = "auto"; 40 gsap.to(line1, { top: 14, rotate: 0, duration: 0.4, ease: "back.out(1.5)" }); 41 gsap.to(line2, { top: 26, rotate: 0, duration: 0.4, ease: "back.out(1.5)", width: "2rem", backgroundColor: "#ffffff" }); 42 menuTl.timeScale(1.5).reverse(); 43 } 44 45 menuToggle.addEventListener("click", () => { 46 menuToggle.classList.toggle("active"); 47 if (menuToggle.classList.contains("active")) { 48 document.body.style.overflow = "hidden"; 49 gsap.to(line1, { top: 20, rotate: 45, duration: 0.4, ease: "back.out(1.5)" }); 50 gsap.to(line2, { top: 20, rotate: -45, duration: 0.4, ease: "back.out(1.5)", width: "2rem", backgroundColor: "#8eb353" }); 51 menuTl.timeScale(1).play(); 52 } else { 53 closeMenu(); 54 } 55 }); 56 57 document.querySelectorAll(".menu-link").forEach(link => { 58 link.addEventListener("click", () => { if (menuToggle.classList.contains("active")) closeMenu(); }); 59 }); 60 61 62 // ANIMAZIONE ALLO SCROLL DEI BLOCCHI 63 gsap.utils.toArray('.reveal-block').forEach(block => { 64 gsap.from(block, { 65 scrollTrigger: { 66 trigger: block, 67 start: "top 85%", 68 toggleActions: "play none none reverse" 69 }, 70 y: 40, 71 opacity: 0, 72 duration: 0.8, 73 ease: "power2.out" 74 }); 75 }); 76 77 // âââ PANEL REVEAL (stile megacard, ma allo scroll invece che al load) âââââ 78 gsap.utils.toArray('.panel-reveal').forEach(panel => { 79 gsap.from(panel, { 80 scrollTrigger: { trigger: panel, start: "top 90%", toggleActions: "play none none reverse" }, 81 y: 100, opacity: 0, duration: 1, ease: "power3.out" 82 }); 83 }); 84 85 // TECH SPECS DAI CONTENUTI TYPO3 86 // L'elenco puntato nel testo del servizio viene spostato nel pannello "Tech Specs". 87 // Se il servizio non ha un elenco, pulsante e pannello vengono rimossi. 88 document.querySelectorAll('.nv-service').forEach(card => { 89 const list = card.querySelector('.service-body ul'); 90 const specs = card.querySelector('.service-specs'); 91 if (!list || !specs) { 92 card.querySelector('.service-trigger')?.remove(); 93 card.querySelector('.service-content')?.remove(); 94 return; 95 } 96 list.className = 'space-y-4 font-mono text-xs text-gray-400'; 97 list.querySelectorAll('li').forEach(li => { 98 li.classList.add('flex', 'gap-4'); 99 const marker = document.createElement('span'); 100 marker.className = 'text-newtgreen'; 101 marker.textContent = '>'; 102 li.prepend(marker); 103 }); 104 specs.appendChild(list); 105 }); 106 107 // MOTORE ESPANSIONE SERVIZI (Accordion GSAP) 108 const serviceTriggers = document.querySelectorAll('.service-trigger'); 109
110 serviceTriggers.forEach(trigger => { 111 let isOpen = false; 112 const content = trigger.nextElementSibling; 113 const icon = trigger.querySelector('.trigger-icon svg'); 114 115 trigger.addEventListener('click', () => { 116 isOpen = !isOpen; 117 118 if (isOpen) { 119 // Ruota l'icona a 45 gradi (X) e colora il bottone 120 gsap.to(icon, { rotation: 45, duration: 0.3, ease: "back.out(1.5)" }); 121 trigger.querySelector('.trigger-icon').classList.add('border-newtgreen', 'text-newtgreen'); 122 trigger.querySelector('.trigger-icon').classList.remove('border-white/20', 'text-white'); 123 124 // Srotola il contenuto 125 gsap.to(content, { 126 height: "auto", 127 opacity: 1, 128 duration: 0.5, 129 ease: "power2.out" 130 }); 131 } else { 132 // Riporta l'icona a 0 gradi (+) 133 gsap.to(icon, { rotation: 0, duration: 0.3, ease: "power2.inOut" }); 134 trigger.querySelector('.trigger-icon').classList.remove('border-newtgreen', 'text-newtgreen'); 135 trigger.querySelector('.trigger-icon').classList.add('border-white/20', 'text-white'); 136 137 // Richiudi il contenuto 138 gsap.to(content, { 139 height: 0, 140 opacity: 0, 141 duration: 0.4, 142 ease: "power2.inOut" 143 }); 144 } 145 }); 146 }); 147 }); 148
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.