// App JS ohne Alpine-Initialisierung. Alpine wird von Livewire verwaltet. // Premium Scroll Animations with Intersection Observer (function() { 'use strict'; // Warte bis DOM vollständig geladen ist if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initAnimations); } else { initAnimations(); } function initAnimations() { // Intersection Observer Konfiguration const observerOptions = { threshold: 0.15, rootMargin: '0px 0px -80px 0px' }; // Erstelle Observer const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { // Füge is-visible Klasse mit kleinem Delay hinzu für sanfteren Effekt setTimeout(() => { entry.target.classList.add('is-visible'); }, 50); // Observer beenden nach Animation für bessere Performance observer.unobserve(entry.target); } }); }, observerOptions); // Finde alle Elemente mit Animation-Klassen const animatedElements = document.querySelectorAll( '.scroll-animate, .fade-in, .slide-up, .slide-right, .slide-left, .scale-in' ); // Beobachte jedes Element animatedElements.forEach(el => { observer.observe(el); }); // Smooth Scroll für Anchor-Links document.addEventListener('click', function(e) { const target = e.target.closest('a[href^="#"]'); if (target && target.hash) { const targetElement = document.querySelector(target.hash); if (targetElement) { e.preventDefault(); const headerOffset = 80; const elementPosition = targetElement.getBoundingClientRect().top; const offsetPosition = elementPosition + window.pageYOffset - headerOffset; window.scrollTo({ top: offsetPosition, behavior: 'smooth' }); } } }); // Scroll Progress Indicator initScrollProgress(); // Premium Sticky Header initStickyHeader(); } function initStickyHeader() { const header = document.getElementById('main-header'); if (!header) return; let lastScrollTop = 0; let scrollTimeout = null; function handleHeaderScroll() { const scrollTop = window.pageYOffset || document.documentElement.scrollTop; // Add/Remove scrolled class for enhanced shadow if (scrollTop > 50) { header.classList.add('scrolled'); } else { header.classList.remove('scrolled'); } // Optional: Hide header on scroll down, show on scroll up // Uncomment if you want auto-hide behavior /* if (scrollTop > lastScrollTop && scrollTop > 100) { // Scrolling down header.classList.add('hide'); } else { // Scrolling up header.classList.remove('hide'); } */ lastScrollTop = scrollTop <= 0 ? 0 : scrollTop; } // Listen to scroll with throttling let headerTicking = false; window.addEventListener('scroll', function() { if (!headerTicking) { window.requestAnimationFrame(function() { handleHeaderScroll(); headerTicking = false; }); headerTicking = true; } }); // Initial check handleHeaderScroll(); } function initScrollProgress() { // Erstelle Progress Bar Element const progressBar = document.createElement('div'); progressBar.className = 'scroll-progress-bar'; document.body.appendChild(progressBar); // Update Progress on Scroll function updateProgress() { const windowHeight = window.innerHeight; const documentHeight = document.documentElement.scrollHeight; const scrollTop = window.pageYOffset || document.documentElement.scrollTop; // Berechne Progress (0-100%) const scrollPercentage = (scrollTop / (documentHeight - windowHeight)) * 100; // Update Bar Width progressBar.style.width = `${Math.min(scrollPercentage, 100)}%`; // Optional: Show/Hide basierend auf Scroll-Position if (scrollTop > 100) { progressBar.classList.add('visible'); } else { progressBar.classList.remove('visible'); } } // Listen to scroll events mit Throttling für Performance let ticking = false; window.addEventListener('scroll', function() { if (!ticking) { window.requestAnimationFrame(function() { updateProgress(); ticking = false; }); ticking = true; } }); // Initial update updateProgress(); } })();