/* ═════════════════════════════════════════════ Malerei Flachberger – Premium Interactions ════════════════════════════════════════════ */ // ── NAVBAR SCROLL EFFECT ── const navbar = document.querySelector('.navbar'); window.addEventListener('scroll', () => { navbar.classList.toggle('scrolled', window.scrollY > 40); updateBackToTop(); }, { passive: true }); // ── BACK TO TOP ── const backToTop = document.getElementById('backToTop'); function updateBackToTop() { backToTop.classList.toggle('visible', window.scrollY > 500); } backToTop.addEventListener('click', () => { window.scrollTo({ top: 0, behavior: 'smooth' }); }); // ── BURGER MENU ── const burger = document.querySelector('.burger'); const mobileMenu = document.getElementById('mobileMenu'); burger.addEventListener('click', () => { burger.classList.toggle('open'); mobileMenu.classList.toggle('open'); document.body.style.overflow = mobileMenu.classList.contains('open') ? 'hidden' : ''; }); mobileMenu.querySelectorAll('a').forEach(link => { link.addEventListener('click', () => { burger.classList.remove('open'); mobileMenu.classList.remove('open'); document.body.style.overflow = ''; }); }); // ── SMOOTH SCROLL FOR ANCHOR LINKS ── document.querySelectorAll('a[href^="#"]').forEach(link => { link.addEventListener('click', e => { const target = document.querySelector(link.getAttribute('href')); if (!target) return; e.preventDefault(); const offset = navbar.offsetHeight + 20; window.scrollTo({ top: target.offsetTop - offset, behavior: 'smooth' }); }); }); // ── FORM VALIDATION & SUBMISSION ── const form = document.getElementById('kontaktForm'); if (form) { const submitBtn = form.querySelector('button[type="submit"]'); form.addEventListener('submit', async e => { e.preventDefault(); const name = document.getElementById('name'); const email = document.getElementById('email'); const message = document.getElementById('message'); let valid = true; // Clear previous errors [name, email, message].forEach(f => f.style.borderColor = ''); // Validate if (!name.value.trim()) { name.style.borderColor = '#ff6b6b'; valid = false; } const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; if (!email.value.trim() || !emailRegex.test(email.value)) { email.style.borderColor = '#ff6b6b'; valid = false; } if (!message.value.trim()) { message.style.borderColor = '#ff6b6b'; valid = false; } if (!valid) return; // Simulate send submitBtn.textContent = 'Wird gesendet...'; submitBtn.disabled = true; await new Promise(r => setTimeout(r, 1200)); form.innerHTML = '

✓ Vielen Dank!

Wir melden uns bald bei Ihnen.

'; }); } // ── REVIEW CAROUSEL ── const reviewsTrack = document.getElementById('reviewsTrack'); const carouselDots = document.getElementById('carouselDots'); if (reviewsTrack) { const cards = reviewsTrack.querySelectorAll('.review-card'); let currentSlide = 0; let slideWidth = 0; let slidesPerView = 3; let autoplayTimer; function updateSlideWidth() { slideWidth = cards[0]?.offsetWidth ?? 0; const gapStyle = window.getComputedStyle(reviewsTrack).gap; const gap = parseInt(gapStyle) || 0; slidesPerView = window.innerWidth <= 768 ? 1 : window.innerWidth <=1024 ? 2 : 3; } function buildDots() { carouselDots.innerHTML='' ; const totalSlides=Math.ceil(cards.length / slidesPerView); for (let i=0; i < totalSlides; i++) { const dot=document.createElement('button'); dot.className='carousel-dots ' + (i===0 ? 'active' : '' ); dot.addEventListener('click', ()=> goToSlide(i)); carouselDots.appendChild(dot); } } function goToSlide(index) { const totalSlides = Math.ceil(cards.length / slidesPerView); currentSlide = Math.max(0, Math.min(index, totalSlides - 1)); const offset = -(currentSlide * slideWidth * slidesPerView + currentSlide * 32); reviewsTrack.style.transform = `translateX(${offset}px)`; document.querySelectorAll('.carousel-dots').forEach((d, i) => { d.classList.toggle('active', i === currentSlide); }); } function autoplay() { const totalSlides = Math.ceil(cards.length / slidesPerView); goToSlide((currentSlide + 1) % totalSlides); } function startAutoplay() { autoplayTimer = setInterval(autoplay, 5000); } updateSlideWidth(); buildDots(); startAutoplay(); reviewsTrack.addEventListener('mouseenter', () => clearInterval(autoplayTimer)); reviewsTrack.addEventListener('mouseleave', startAutoplay); window.addEventListener('resize', () => { updateSlideWidth(); goToSlide(0); buildDots(); }); // Touch swipe let touchStart = 0; reviewsTrack.addEventListener('touchstart', e => { touchStart = e.touches[0].clientX; }, { passive: true }); reviewsTrack.addEventListener('touchend', e => { const diff = touchStart - e.changedTouches[0].clientX; if (Math.abs(diff) > 50) { goToSlide(diff > 0 ? currentSlide + 1 : currentSlide - 1); } }, { passive: true }); } // ── SCROLL ANIMATIONS ── const observerOptions = { threshold: 0.15, rootMargin: '0px 0px -60px 0px' }; const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { entry.target.style.opacity = '1'; entry.target.style.transform = 'translateY(0)'; observer.unobserve(entry.target); } }); }, observerOptions); // Observe cards and elements for animation document.querySelectorAll('.leistung-card, .galerie-item, .review-card, .value-item').forEach(el => { el.style.opacity = '0'; el.style.transform = 'translateY(30px)'; el.style.transition = 'opacity 0.7s cubic-bezier(0.25, 0.46, 0.45, 0.94), transform 0.7s cubic-bezier(0.25, 0.46, 0.45, 0.94)'; observer.observe(el); }); Skip to content