function getstart() { window.location.href = "/contacts.php"; } document.addEventListener('DOMContentLoaded', () => { const initPageAnimations = () => { if (typeof gsap === 'undefined' || typeof ScrollTrigger === 'undefined') return; gsap.registerPlugin(ScrollTrigger); ScrollTrigger.config({ ignoreMobileResize: true }); const reduceMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches; if (reduceMotion) { gsap.set('[data-gsap-ready]', { clearProps: 'all' }); return; } const ease = 'power3.out'; const touchDevice = window.matchMedia('(hover: none), (pointer: coarse)').matches; const sections = gsap.utils.toArray([ '.three-images-template-section', '.our-products-section', '.what-we-do-section' ].join(',')); const revealGroup = (trigger, targets, vars = {}) => { const items = gsap.utils.toArray(targets); if (!items.length || !document.querySelector(trigger)) return; gsap.from(items, { scrollTrigger: { trigger, start: vars.start || 'top 78%', toggleActions: 'play none none none' }, autoAlpha: 0, y: vars.y ?? 46, x: vars.x ?? 0, scale: vars.scale ?? 0.96, rotateX: vars.rotateX ?? 0, transformPerspective: 900, duration: vars.duration || 0.9, stagger: vars.stagger ?? 0.12, ease: vars.ease || ease, clearProps: vars.clearProps || 'transform' }); }; const revealImage = (trigger, target, vars = {}) => { if (!document.querySelector(target) || !document.querySelector(trigger)) return; gsap.from(target, { scrollTrigger: { trigger, start: vars.start || 'top 75%', toggleActions: 'play none none none' }, autoAlpha: 0, y: vars.y ?? 36, x: vars.x ?? 0, scale: vars.scale ?? 0.9, rotate: vars.rotate ?? 0, duration: vars.duration || 1.1, ease: vars.ease || ease, clearProps: vars.clearProps || 'transform' }); }; const addHoverLift = (selector) => { gsap.utils.toArray(selector).forEach((card) => { card.style.willChange = 'transform'; card.addEventListener('mouseenter', () => { gsap.to(card, { y: -8, scale: 1.015, duration: 0.32, ease: 'power2.out', overwrite: 'auto' }); }); card.addEventListener('mouseleave', () => { gsap.to(card, { x: 0, y: 0, rotateX: 0, rotateY: 0, scale: 1, duration: 0.45, ease: 'power2.out', overwrite: 'auto' }); }); card.addEventListener('mousemove', (event) => { const bounds = card.getBoundingClientRect(); const relX = (event.clientX - bounds.left) / bounds.width - 0.5; const relY = (event.clientY - bounds.top) / bounds.height - 0.5; gsap.to(card, { rotateY: relX * 5, rotateX: relY * -5, duration: 0.35, ease: 'power2.out', overwrite: 'auto' }); }); }); }; const addDesktopParallax = (trigger, target, yPercent = -7) => { if (!window.matchMedia('(min-width: 769px)').matches) return; if (!document.querySelector(trigger) || !document.querySelector(target)) return; gsap.to(target, { yPercent, ease: 'none', scrollTrigger: { trigger, start: 'top bottom', end: 'bottom top', scrub: 0.8 } }); }; const initGoldenPortalCards = () => { const cards = gsap.utils.toArray('.three-images-template-section .tit-img-wrapper'); if (!cards.length) return; const canHover = window.matchMedia('(hover: hover) and (pointer: fine)').matches; gsap.set(cards, { transformOrigin: 'center', transformPerspective: 1400, transformStyle: 'preserve-3d', opacity: 0, y: 72, scale: 0.9, rotateX: 10 }); cards.forEach((card) => card.classList.add('is-portal-ready')); gsap.timeline({ scrollTrigger: { trigger: '.three-images-template-section', start: 'top 76%', toggleActions: 'play none none none' } }) .to(cards, { opacity: 1, y: 0, scale: 1, rotateX: 0, duration: 1.15, stagger: 0.18, ease: 'power3.out', onStart: () => cards.forEach((card) => card.classList.add('is-portal-revealed')) }) .fromTo(cards.map((card) => card.querySelector('img')).filter(Boolean), { scale: 1.16, yPercent: 5 }, { scale: 1.01, yPercent: 0, duration: 1.25, stagger: 0.18, ease: 'power3.out' }, '<'); if (!canHover) return; cards.forEach((card) => { const image = card.querySelector('img'); const glowTo = gsap.quickTo(card, '--portal-glow', { duration: 0.35, ease: 'power2.out' }); const updatePortalPosition = (event) => { const bounds = card.getBoundingClientRect(); const relX = (event.clientX - bounds.left) / bounds.width; const relY = (event.clientY - bounds.top) / bounds.height; const clampedX = gsap.utils.clamp(0, 1, relX); const clampedY = gsap.utils.clamp(0, 1, relY); card.style.setProperty('--portal-x', `${clampedX * 100}%`); card.style.setProperty('--portal-y', `${clampedY * 100}%`); gsap.to(card, { y: -10, scale: 1.018, rotateY: (clampedX - 0.5) * 8, rotateX: (0.5 - clampedY) * 8, duration: 0.38, ease: 'power2.out', overwrite: 'auto' }); if (image) { gsap.to(image, { x: (clampedX - 0.5) * 8, y: (clampedY - 0.5) * 8, scale: 1.045, duration: 0.45, ease: 'power2.out', overwrite: 'auto' }); } }; card.addEventListener('mouseenter', (event) => { glowTo(1); updatePortalPosition(event); }); card.addEventListener('mousemove', updatePortalPosition); card.addEventListener('mouseleave', () => { glowTo(0); gsap.to(card, { x: 0, y: 0, rotateX: 0, rotateY: 0, scale: 1, duration: 0.55, ease: 'power3.out', overwrite: 'auto' }); if (image) { gsap.to(image, { x: 0, y: 0, scale: 1.01, duration: 0.55, ease: 'power3.out', overwrite: 'auto' }); } }); }); }; const revealText = (trigger, targets) => { const items = gsap.utils.toArray(targets); if (!items.length || !document.querySelector(trigger)) return; gsap.from(items, { scrollTrigger: { trigger, start: 'top 80%', toggleActions: 'play none none none' }, autoAlpha: 0, yPercent: 22, duration: 0.95, stagger: 0.08, ease: 'power3.out', clearProps: 'transform' }); }; const animateCounters = () => { const counters = gsap.utils.toArray([ '.spend-sense-total > div:nth-child(2)', '.spend-sense-legend span[style*="font-weight: 700"]' ].join(',')); counters.forEach((counter) => { const original = counter.textContent.trim(); const numeric = original.match(/[\d,.]+/); if (!numeric) return; const prefix = original.slice(0, numeric.index); const suffix = original.slice(numeric.index + numeric[0].length); const endValue = parseFloat(numeric[0].replace(/,/g, '')); const decimals = numeric[0].includes('.') ? numeric[0].split('.')[1].length : 0; const state = { value: 0 }; gsap.to(state, { value: endValue, duration: 1.4, ease: 'power2.out', scrollTrigger: { trigger: counter.closest('section') || counter, start: 'top 78%', toggleActions: 'play none none none', once: true }, onUpdate: () => { const value = state.value.toLocaleString('en-IN', { minimumFractionDigits: decimals, maximumFractionDigits: decimals }); counter.textContent = `${prefix}${value}${suffix}`; } }); }); }; const initHorizontalShowcase = () => { const productCards = gsap.utils.toArray('.our-products-section .product-card'); const layout = document.querySelector('.our-products-section .products-layout'); if (!layout || productCards.length < 3 || window.matchMedia('(max-width: 900px)').matches) return; gsap.fromTo(productCards, { xPercent: (index) => index % 2 === 0 ? -8 : 8 }, { xPercent: 0, ease: 'none', scrollTrigger: { trigger: '.our-products-section', start: 'top bottom', end: 'bottom top', scrub: 0.9 } }); }; const addCinematicMagnet = (selector, options = {}) => { if (touchDevice) return; const strength = options.strength || 10; const lift = options.lift || -10; const tilt = options.tilt || 5; gsap.utils.toArray(selector).forEach((element) => { element.style.willChange = 'transform, filter, box-shadow'; element.addEventListener('mouseenter', () => { gsap.to(element, { y: lift, scale: 1.025, filter: 'brightness(1.08) saturate(1.08)', duration: 0.45, ease: 'expo.out', overwrite: 'auto' }); }); element.addEventListener('mousemove', (event) => { const bounds = element.getBoundingClientRect(); const relX = (event.clientX - bounds.left) / bounds.width - 0.5; const relY = (event.clientY - bounds.top) / bounds.height - 0.5; gsap.to(element, { x: relX * strength, y: lift + relY * strength, rotateY: relX * tilt, rotateX: relY * -tilt, duration: 0.55, ease: 'expo.out', overwrite: 'auto' }); }); element.addEventListener('mouseleave', () => { gsap.to(element, { x: 0, y: 0, rotateX: 0, rotateY: 0, scale: 1, filter: 'brightness(1) saturate(1)', duration: 0.75, ease: 'elastic.out(1, 0.55)', overwrite: 'auto' }); }); }); }; const initAppleLoopMotion = () => { const section = document.querySelector('.the-loop-section'); if (!section) return; const container = section.querySelector('.loop-container'); const leftItems = gsap.utils.toArray('.the-loop-section .loop-left > *'); const orbit = section.querySelector('.loop-circle-container'); const orbitSvg = section.querySelector('.loop-circle-container > svg'); const robot = section.querySelector('.robot-center img'); const nodes = gsap.utils.toArray('.the-loop-section .loop-node'); const nodeIcons = nodes.map((node) => node.querySelector('div:first-child')).filter(Boolean); const mobile = window.matchMedia('(max-width: 1024px)').matches; gsap.set([container, orbit, orbitSvg, robot, ...leftItems, ...nodes, ...nodeIcons].filter(Boolean), { transformOrigin: 'center', transformPerspective: 1200, force3D: true }); const timeline = gsap.timeline({ defaults: { ease: 'expo.out' }, scrollTrigger: { trigger: section, start: 'top 76%', toggleActions: 'play none none none', once: true } }); timeline .from(container, { autoAlpha: 0, y: 54, scale: 0.97, filter: 'blur(10px)', duration: 1.08, clearProps: 'filter' }) .from(leftItems, { autoAlpha: 0, x: mobile ? 0 : -42, y: mobile ? 28 : 18, filter: 'blur(8px)', stagger: 0.09, duration: 0.78, clearProps: 'filter' }, '-=0.58') .from(orbitSvg, { autoAlpha: 0, scale: 0.78, rotate: -22, duration: 1.15 }, '-=0.7') .from(robot, { autoAlpha: 0, y: mobile ? 22 : 0, scale: 0.66, rotate: mobile ? 0 : 5, filter: 'blur(12px)', duration: 1.18, ease: 'expo.out', clearProps: 'filter' }, '-=0.9') .from(nodes, { autoAlpha: 0, scale: 0.78, y: mobile ? 28 : 0, filter: 'blur(9px)', stagger: { each: 0.14, from: 'center' }, duration: 0.88, clearProps: 'filter' }, '-=0.58') .from(nodeIcons, { scale: 0, rotate: -24, duration: 0.52, stagger: 0.08, ease: 'back.out(1.9)' }, '-=0.42'); if (!mobile && orbit) { gsap.to(orbit, { rotate: 5, ease: 'none', scrollTrigger: { trigger: section, start: 'top bottom', end: 'bottom top', scrub: 1.1, invalidateOnRefresh: true } }); } if (robot) { gsap.to(robot, { y: mobile ? -8 : -16, rotate: mobile ? 0 : -1.5, duration: 2.8, repeat: -1, yoyo: true, ease: 'sine.inOut' }); } if (!touchDevice && orbit) { orbit.addEventListener('mousemove', (event) => { const bounds = orbit.getBoundingClientRect(); const relX = (event.clientX - bounds.left) / bounds.width - 0.5; const relY = (event.clientY - bounds.top) / bounds.height - 0.5; if (robot) { gsap.to(robot, { x: relX * 14, rotateY: relX * 7, rotateX: relY * -5, duration: 0.65, ease: 'expo.out', overwrite: 'auto' }); } gsap.to(nodes, { x: relX * -8, y: relY * -8, duration: 0.75, ease: 'expo.out', overwrite: 'auto' }); }); orbit.addEventListener('mouseleave', () => { if (robot) { gsap.to(robot, { x: 0, rotateX: 0, rotateY: 0, duration: 0.8, ease: 'expo.out', overwrite: 'auto' }); } gsap.to(nodes, { x: 0, y: 0, rotateX: 0, rotateY: 0, duration: 0.8, ease: 'expo.out', overwrite: 'auto' }); }); } addCinematicMagnet('.the-loop-section .loop-node', { strength: 8, lift: -8, tilt: 4 }); }; gsap.set([ '.product-card', '.tit-img-wrapper', '.loop-node' ].join(','), { transformOrigin: 'center', transformPerspective: 900 }); gsap.from([ '.elementor-element-55f3e96', '.elementor-element-520d0b9', '.elementor-element-bb1e9c1 img' ], { autoAlpha: 0, y: 36, scale: 0.96, duration: 1, stagger: 0.16, ease, clearProps: 'transform' }); revealText('.elementor-element-aaa9419', '.elementor-element-55f3e96 h1, .elementor-element-55f3e96 p'); sections.forEach((section) => { gsap.from(section, { scrollTrigger: { trigger: section, start: 'top 86%', toggleActions: 'play none none none' }, autoAlpha: 0, y: 34, duration: 0.85, ease, clearProps: 'transform' }); }); initGoldenPortalCards(); revealGroup('.our-products-section', '.products-container > div:first-child, .products-container > div:nth-child(2)', { y: 28, stagger: 0.1 }); revealGroup('.our-products-section', '.product-card', { y: 56, scale: 0.94, stagger: 0.12 }); revealImage('.our-products-section', '.products-col-center img', { y: 46, scale: 0.86, duration: 1.15, ease: 'power3.out' }); initHorizontalShowcase(); initAppleLoopMotion(); addHoverLift('.product-card'); addDesktopParallax('.three-images-template-section', '.tit-img-wrapper:nth-child(1) img', -4); addDesktopParallax('.three-images-template-section', '.tit-img-wrapper:nth-child(2) img', -7); addDesktopParallax('.three-images-template-section', '.tit-img-wrapper:nth-child(3) img', -4); addDesktopParallax('.our-products-section', '.products-col-center img', -6); // What We Do Animations revealText('.what-we-do-section', '.wwd-text > div:first-of-type, .wwd-text h2'); revealImage('.what-we-do-section', '.wwd-image img', { x: 40, scale: 0.85, duration: 1.2, start: 'top 70%' }); revealGroup('.what-we-do-section', '.wwd-card', { y: 40, stagger: 0.15, start: 'top 75%' }); addHoverLift('.wwd-card'); addDesktopParallax('.what-we-do-section', '.wwd-image img', -5); animateCounters(); ScrollTrigger.refresh(); }; setTimeout(initPageAnimations, 350); let resizeTimer; window.addEventListener('resize', () => { window.clearTimeout(resizeTimer); resizeTimer = window.setTimeout(() => { if (typeof ScrollTrigger === 'undefined') return; ScrollTrigger.getAll().forEach((trigger) => { if (trigger.trigger && !document.documentElement.contains(trigger.trigger)) { trigger.kill(); } }); ScrollTrigger.refresh(); }, 180); }, { passive: true }); });