/* ═════════════════════════════════════════════
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