document.addEventListener('DOMContentLoaded', function () { // ===== THEME SWITCHER ===== var themeBtn = document.getElementById('theme-btn'); var themeIcon = document.getElementById('theme-icon'); var themeTooltip = document.getElementById('theme-tooltip'); var html = document.documentElement; var themes = ['system', 'dark', 'light']; var icons = { system: 'πŸ’»', dark: 'πŸŒ™', light: 'β˜€οΈ' }; var labels = { system: 'БистСмная Ρ‚Π΅ΠΌΠ°', dark: 'Вёмная Ρ‚Π΅ΠΌΠ°', light: 'БвСтлая Ρ‚Π΅ΠΌΠ°' }; function getSystemTheme() { return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'; } function applyTheme(mode) { var actual = mode === 'system' ? getSystemTheme() : mode; html.setAttribute('data-theme', actual); if (themeIcon) themeIcon.textContent = icons[mode]; if (themeTooltip) themeTooltip.textContent = labels[mode] + ' β€” Π½Π°ΠΆΠΌΠΈΡ‚Π΅ для смСны'; } function getStoredTheme() { return localStorage.getItem('theme') || 'system'; } function cycleTheme() { var current = getStoredTheme(); var idx = themes.indexOf(current); var next = themes[(idx + 1) % themes.length]; localStorage.setItem('theme', next); applyTheme(next); } // Init theme applyTheme(getStoredTheme()); // Listen for system theme changes window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', function () { if (getStoredTheme() === 'system') { applyTheme('system'); } }); if (themeBtn) { themeBtn.addEventListener('click', cycleTheme); } // ===== YANDEX MAP THEME ===== var mapFrame = document.getElementById('yandex-map'); if (mapFrame) { var mapLon = mapFrame.getAttribute('data-lon'); var mapLat = mapFrame.getAttribute('data-lat'); var mapAddress = mapFrame.getAttribute('data-address') || ''; function updateMapTheme() { var theme = html.getAttribute('data-theme') || 'light'; var params = 'll=' + mapLon + ',' + mapLat + '&z=16' + '&pt=' + mapLon + ',' + mapLat + ',pm2rdl' + '&text=' + encodeURIComponent(mapAddress) + '&theme=' + theme; mapFrame.src = 'https://yandex.ru/map-widget/v1/?' + params; } updateMapTheme(); var mapObserver = new MutationObserver(function (mutations) { for (var i = 0; i < mutations.length; i++) { if (mutations[i].attributeName === 'data-theme') { updateMapTheme(); break; } } }); mapObserver.observe(html, { attributes: true }); } // ===== BURGER MENU ===== var burger = document.getElementById('burger'); var nav = document.querySelector('.header__nav'); if (burger && nav) { burger.addEventListener('click', function () { nav.classList.toggle('active'); }); } // ===== SMOOTH SCROLL ===== document.querySelectorAll('a[href^="#"]').forEach(function (link) { link.addEventListener('click', function (e) { var id = this.getAttribute('href'); if (id === '#') return; var target = document.querySelector(id); if (target) { e.preventDefault(); var headerH = document.querySelector('.header'); var offset = headerH ? headerH.offsetHeight : 0; var top = target.getBoundingClientRect().top + window.pageYOffset - offset; window.scrollTo({ top: top, behavior: 'smooth' }); if (nav) nav.classList.remove('active'); } }); }); // ===== PHONE MASK ===== var phoneInput = document.getElementById('phone'); if (phoneInput) { phoneInput.addEventListener('focus', function () { if (this.value === '') { this.value = '8 (___) ___-__-__'; } }); phoneInput.addEventListener('input', function () { var val = this.value.replace(/\D/g, ''); var formatted = '8 ('; if (val.length > 1) formatted += val.substring(1, 4); if (val.length >= 4) formatted += ') '; if (val.length > 4) formatted += val.substring(4, 7); if (val.length >= 7) formatted += '-'; if (val.length > 7) formatted += val.substring(7, 9); if (val.length >= 9) formatted += '-'; if (val.length > 9) formatted += val.substring(9, 11); this.value = formatted.trim(); }); phoneInput.addEventListener('blur', function () { if (this.value === '8 (___) ___-__-__' || this.value.replace(/\D/g, '').length < 11) { this.value = ''; } }); } // ===== CHARACTER COUNTER ===== var messageField = document.getElementById('message'); var charCount = document.querySelector('.char-count'); if (messageField && charCount) { messageField.addEventListener('input', function () { var remaining = 500 - this.value.length; charCount.textContent = 'ΠžΡΡ‚Π°Π»ΠΎΡΡŒ: ' + remaining; }); } // ===== CAROUSEL ===== var carouselEl = document.querySelector('.carousel'); var track = document.querySelector('.carousel__track'); var slides = track ? Array.from(track.querySelectorAll('.case')) : []; var prevBtn = document.querySelector('.carousel__prev'); var nextBtn = document.querySelector('.carousel__next'); var counterEl = document.getElementById('carousel-counter'); if (carouselEl && track && slides.length > 0 && prevBtn && nextBtn) { var realCount = slides.length; var isTransitioning = false; // Clone first and last slide for infinite loop if (realCount > 1) { var firstClone = slides[0].cloneNode(true); var lastClone = slides[realCount - 1].cloneNode(true); firstClone.classList.add('clone'); lastClone.classList.add('clone'); track.insertBefore(lastClone, track.firstChild); track.appendChild(firstClone); } // Re-query all slides including clones slides = Array.from(track.querySelectorAll('.case')); var totalSlides = slides.length; // Start at real slide #2 (index 2 because clone of last is at index 0) var currentIndex = realCount > 1 ? 2 : 1; var autoTimer = null; function getSlideWidth() { return Math.round(carouselEl.clientWidth * 0.72); } function setupSlides() { var w = getSlideWidth(); for (var i = 0; i < slides.length; i++) { slides[i].style.width = w + 'px'; } } function updateActiveClass() { var realIdx = getRealIndex(currentIndex); for (var i = 0; i < slides.length; i++) { if (slides[i].classList.contains('clone')) { slides[i].classList.remove('case--active'); } else { var thisRealIdx = i - 1; slides[i].classList.toggle('case--active', thisRealIdx === realIdx); } } } function getRealIndex(idx) { if (idx <= 0) return realCount - 1; if (idx >= realCount + 1) return 0; return idx - 1; } function goToSlide(index, animate) { var slideW = getSlideWidth(); var carouselW = carouselEl.clientWidth; var offset = (slideW * index) - (carouselW / 2) + (slideW / 2); if (offset < 0) offset = 0; if (animate === false) { track.style.transition = 'none'; } else { track.style.transition = 'transform 0.5s cubic-bezier(0.4, 0, 0.2, 1)'; } track.style.transform = 'translateX(-' + offset + 'px)'; updateActiveClass(); if (counterEl) { counterEl.textContent = (getRealIndex(currentIndex) + 1) + ' / ' + realCount; } } function handleTransitionEnd() { isTransitioning = false; // If we landed on a clone, jump to the real slide without animation if (currentIndex <= 0) { currentIndex = realCount; goToSlide(currentIndex, false); } else if (currentIndex >= realCount + 1) { currentIndex = 1; goToSlide(currentIndex, false); } } track.addEventListener('transitionend', handleTransitionEnd); function startAuto() { stopAuto(); if (realCount > 1) { autoTimer = setInterval(function () { currentIndex++; goToSlide(currentIndex, true); }, 5000); } } function stopAuto() { if (autoTimer) { clearInterval(autoTimer); autoTimer = null; } } prevBtn.addEventListener('click', function () { if (isTransitioning) return; isTransitioning = true; stopAuto(); currentIndex--; goToSlide(currentIndex, true); startAuto(); }); nextBtn.addEventListener('click', function () { if (isTransitioning) return; isTransitioning = true; stopAuto(); currentIndex++; goToSlide(currentIndex, true); startAuto(); }); var resizeTimer; window.addEventListener('resize', function () { clearTimeout(resizeTimer); resizeTimer = setTimeout(function () { setupSlides(); goToSlide(currentIndex, false); }, 150); }); setupSlides(); goToSlide(currentIndex, false); startAuto(); } // ===== COOKIE BANNER ===== var cookieBanner = document.getElementById('cookie-banner'); var cookieAccept = document.getElementById('cookie-accept'); if (cookieBanner && cookieAccept) { if (!localStorage.getItem('cookies_accepted')) { cookieBanner.classList.add('active'); } cookieAccept.addEventListener('click', function () { localStorage.setItem('cookies_accepted', '1'); cookieBanner.classList.remove('active'); }); } // ===== STICKY PANEL ===== var stickyPanel = document.getElementById('sticky-panel'); var heroSection = document.getElementById('hero'); var footerEl = document.querySelector('.footer'); if (stickyPanel && heroSection) { var footerVisible = false; if (footerEl) { var footerObserver = new IntersectionObserver(function (entries) { footerVisible = entries[0].isIntersecting; if (footerVisible) { stickyPanel.classList.remove('active'); } }, { threshold: 0.1 }); footerObserver.observe(footerEl); } var ticking = false; function updateSticky() { var heroBottom = heroSection.getBoundingClientRect().bottom; if (!footerVisible) { stickyPanel.classList.toggle('active', heroBottom < 0); } ticking = false; } window.addEventListener('scroll', function () { if (!ticking) { window.requestAnimationFrame(updateSticky); ticking = true; } }, { passive: true }); updateSticky(); } // ===== FAQ ACCORDION ===== document.querySelectorAll('.faq-question').forEach(function (btn) { btn.addEventListener('click', function () { var item = this.closest('.faq-item'); if (!item) return; var isActive = item.classList.contains('active'); document.querySelectorAll('.faq-item').forEach(function (el) { el.classList.remove('active'); }); if (!isActive) { item.classList.add('active'); } }); }); // ===== SCROLL REVEAL ANIMATIONS ===== var revealElements = document.querySelectorAll( '.problem-card, .service-card, .industry-card, .step, .case, .faq-item, .testimonial-card, .info-card, .about-card' ); if (revealElements.length > 0) { var revealObserver = new IntersectionObserver(function (entries) { entries.forEach(function (entry) { if (entry.isIntersecting) { entry.target.classList.add('visible'); revealObserver.unobserve(entry.target); } }); }, { threshold: 0.1, rootMargin: '0px 0px -40px 0px' }); revealElements.forEach(function (el, i) { el.style.transitionDelay = (i % 3) * 0.08 + 's'; revealObserver.observe(el); }); } // ===== FORM SUBMIT ===== var form = document.getElementById('contact-form'); var responseDiv = document.getElementById('form-response'); if (form && responseDiv) { // Π£Π±ΠΈΡ€Π°Π΅ΠΌ ΠΎΡˆΠΈΠ±ΠΊΡƒ ΠΏΡ€ΠΈ фокусС Π½Π° ΠΏΠΎΠ»Π΅ form.querySelectorAll('input, textarea').forEach(function (input) { input.addEventListener('focus', function () { var group = this.closest('.form-group'); if (group) { group.classList.remove('form-group--error'); var err = group.querySelector('.error-msg'); if (err) { err.classList.remove('visible'); err.textContent = ''; } } }); }); form.addEventListener('submit', async function (e) { e.preventDefault(); // Бброс всСх ошибок document.querySelectorAll('.form-group--error').forEach(function (el) { el.classList.remove('form-group--error'); }); document.querySelectorAll('.error-msg.visible').forEach(function (el) { el.classList.remove('visible'); el.textContent = ''; }); // ΠšΠ»ΠΈΠ΅Π½Ρ‚ΡΠΊΠ°Ρ валидация var hasError = false; var nameInput = document.getElementById('name'); if (nameInput && !nameInput.value.trim()) { showFieldError(nameInput, 'Π’Π²Π΅Π΄ΠΈΡ‚Π΅ вашС имя'); hasError = true; } var phoneInput = document.getElementById('phone'); if (phoneInput) { var digits = phoneInput.value.replace(/\D/g, ''); if (digits.length < 11) { showFieldError(phoneInput, 'Π’Π²Π΅Π΄ΠΈΡ‚Π΅ ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½Ρ‹ΠΉ Π½ΠΎΠΌΠ΅Ρ€ Ρ‚Π΅Π»Π΅Ρ„ΠΎΠ½Π°'); hasError = true; } } var agreeInput = document.getElementById('agree'); if (agreeInput && !agreeInput.checked) { var agreeGroup = agreeInput.closest('.form-group'); if (agreeGroup) { agreeGroup.classList.add('form-group--error'); var errSpan = agreeGroup.querySelector('.error-msg'); if (errSpan) { errSpan.textContent = 'НСобходимо ΡΠΎΠ³Π»Π°ΡΠΈΡ‚ΡŒΡΡ с ΠΏΠΎΠ»ΠΈΡ‚ΠΈΠΊΠΎΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ ΠΏΠ΅Ρ€ΡΠΎΠ½Π°Π»ΡŒΠ½Ρ‹Ρ… Π΄Π°Π½Π½Ρ‹Ρ…'; errSpan.classList.add('visible'); } } hasError = true; } if (hasError) return; var formData = new FormData(form); formData.append('ajax', '1'); try { var res = await fetch(window.location.href, { method: 'POST', body: formData }); var data = await res.json(); if (data.success) { form.style.display = 'none'; responseDiv.innerHTML = '
' + '
' + '' + '
' + '

' + data.message + '

' + '
'; } else { responseDiv.innerHTML = '

' + data.message + '

'; } } catch (err) { responseDiv.innerHTML = '

ΠŸΡ€ΠΎΠΈΠ·ΠΎΡˆΠ»Π° ошибка. ΠŸΠΎΠΏΡ€ΠΎΠ±ΡƒΠΉΡ‚Π΅ ΠΏΠΎΠ·ΠΆΠ΅.

'; } }); } function showFieldError(input, message) { var group = input.closest('.form-group'); if (!group) return; group.classList.add('form-group--error'); var errSpan = group.querySelector('.error-msg'); if (errSpan) { errSpan.textContent = message; errSpan.classList.add('visible'); } } });