// ===== Cookie Banner ===== (function() { const banner = document.getElementById('cookieBanner'); const acceptBtn = document.getElementById('cookieAccept'); if (!banner || !acceptBtn) return; const consent = localStorage.getItem('olyapka_cookies_consent'); if (!consent) { setTimeout(() => banner.classList.add('show'), 800); } else { banner.classList.add('hidden'); } acceptBtn.addEventListener('click', function() { localStorage.setItem('olyapka_cookies_consent', '1'); banner.classList.remove('show'); setTimeout(() => banner.classList.add('hidden'), 400); // Goal for Yandex.Metrika if (typeof ym !== 'undefined') ym(110606131, 'reachGoal', 'cookie_accept'); if (typeof gtag !== 'undefined') gtag('event', 'cookie_accept'); }); })(); // ===== Mobile Menu ===== (function() { const burger = document.getElementById('burger'); const nav = document.getElementById('nav'); if (!burger || !nav) return; burger.addEventListener('click', function() { burger.classList.toggle('open'); nav.classList.toggle('open'); }); // Close on link click nav.querySelectorAll('.nav-link').forEach(link => { link.addEventListener('click', () => { burger.classList.remove('open'); nav.classList.remove('open'); }); }); })(); // ===== Goal Tracking (Yandex.Metrika + GA) ===== (function() { document.addEventListener('click', function(e) { const target = e.target.closest('[data-goal]'); if (!target) return; const goal = target.getAttribute('data-goal'); if (!goal) return; // Yandex.Metrika if (typeof ym !== 'undefined') { try { ym(110606131, 'reachGoal', goal); } catch(err) {} } // Google Analytics if (typeof gtag !== 'undefined') { try { gtag('event', goal); } catch(err) {} } }); })(); // ===== Smooth scroll for anchor links ===== document.querySelectorAll('a[href^="#"]').forEach(anchor => { anchor.addEventListener('click', function(e) { const target = document.querySelector(this.getAttribute('href')); if (target) { e.preventDefault(); target.scrollIntoView({ behavior: 'smooth', block: 'start' }); } }); }); // ===== Portfolio Video Lightbox ===== (function() { const modal = document.getElementById('videoModal'); const player = document.getElementById('videoModalPlayer'); const title = document.getElementById('videoModalTitle'); const fsBtn = document.getElementById('videoModalFullscreen'); const triggers = document.querySelectorAll('.work-video[data-video]'); if (!modal || !player || !triggers.length) return; let lastFocus = null; function open(src, label) { lastFocus = document.activeElement; title.textContent = label || ''; player.src = src; modal.classList.add('open'); modal.setAttribute('aria-hidden', 'false'); document.body.classList.add('video-modal-open'); const p = player.play(); if (p && typeof p.catch === 'function') p.catch(() => {}); player.focus({ preventScroll: true }); } function close() { if (document.fullscreenElement) { document.exitFullscreen().catch(() => {}); } player.pause(); modal.classList.remove('open'); modal.setAttribute('aria-hidden', 'true'); document.body.classList.remove('video-modal-open'); setTimeout(() => { if (!modal.classList.contains('open')) { player.removeAttribute('src'); player.load(); } }, 300); if (lastFocus && typeof lastFocus.focus === 'function') lastFocus.focus({ preventScroll: true }); } function toggleFullscreen() { if (document.fullscreenElement) { document.exitFullscreen().catch(() => {}); return; } if (player.requestFullscreen) { player.requestFullscreen().catch(() => {}); } else if (player.webkitEnterFullscreen) { player.webkitEnterFullscreen(); // iOS Safari } } triggers.forEach(btn => { btn.addEventListener('click', function(e) { e.preventDefault(); open(btn.getAttribute('data-video'), btn.getAttribute('data-title')); }); }); // Превью: когда карточка попадает в зону видимости, гарантируем загрузку первого кадра const previews = document.querySelectorAll('.work-video-preview'); if ('IntersectionObserver' in window && previews.length) { const io = new IntersectionObserver((entries, obs) => { entries.forEach(entry => { if (!entry.isIntersecting) return; const v = entry.target; obs.unobserve(v); if (v.readyState < 2) { v.preload = 'auto'; v.load(); } v.addEventListener('loadeddata', () => { if (v.currentTime === 0) { try { v.currentTime = 0.1; } catch (err) {} } v.preload = 'metadata'; }, { once: true }); }); }, { rootMargin: '200px 0px' }); previews.forEach(v => io.observe(v)); } modal.querySelectorAll('[data-video-close]').forEach(el => { el.addEventListener('click', close); }); // Клик по тёмной области вокруг плеера тоже закрывает окно modal.querySelectorAll('.video-modal-dialog, .video-modal-stage, .video-modal-bar').forEach(el => { el.addEventListener('click', function(e) { if (e.target === el) close(); }); }); if (fsBtn) fsBtn.addEventListener('click', toggleFullscreen); player.addEventListener('dblclick', toggleFullscreen); document.addEventListener('keydown', function(e) { if (!modal.classList.contains('open')) return; if (e.key === 'Escape') { close(); return; } if (e.key === ' ' && document.activeElement === player) return; // native handling if (e.key === 'f' || e.key === 'F') toggleFullscreen(); }); })();