// ===== LOADING PROGRESS BAR =====
function initLoadingProgress() {
const loadingProgress = document.getElementById('loading-progress');
if (!loadingProgress) return;
// Simple loading with delay
setTimeout(() => {
loadingProgress.classList.add('hidden');
setTimeout(() => {
loadingProgress.style.display = 'none';
initPageAnimations();
}, 500);
}, 1500); // Show loading for 1.5 seconds
}
// ===== SKELETON LOADING =====
function initSkeletonLoading() {
const skeletonElements = document.querySelectorAll('.skeleton');
// Show skeleton while content loads
skeletonElements.forEach(element => {
element.style.display = 'block';
});
// Hide skeleton when content is ready
window.addEventListener('load', () => {
setTimeout(() => {
skeletonElements.forEach(element => {
element.style.display = 'none';
});
}, 1000);
});
}
// ===== ENHANCED PAGE ANIMATIONS =====
function initPageAnimations() {
// Intersection Observer for sections
const sections = document.querySelectorAll('section');
const sectionObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('in-view');
}
});
}, {
threshold: 0.1,
rootMargin: '0px 0px -50px 0px'
});
sections.forEach(section => {
sectionObserver.observe(section);
});
// Parallax effect for background elements
const parallaxElements = document.querySelectorAll('.parallax-shape');
let ticking = false;
function updateParallax() {
const scrolled = window.pageYOffset;
parallaxElements.forEach((element, index) => {
const speed = 0.5 + (index * 0.1);
const yPos = -(scrolled * speed);
element.style.transform = `translateY(${yPos}px) rotate(${scrolled * 0.1}deg)`;
});
ticking = false;
}
function requestParallaxTick() {
if (!ticking) {
requestAnimationFrame(updateParallax);
ticking = true;
}
}
window.addEventListener('scroll', requestParallaxTick, { passive: true });
}
// ===== ENHANCED MOBILE GESTURES =====
function initMobileGestures() {
// Swipe gestures for carousel
let touchStartX = 0;
let touchEndX = 0;
const carouselContainer = document.querySelector('.carousel-container');
if (carouselContainer) {
carouselContainer.addEventListener('touchstart', (e) => {
touchStartX = e.changedTouches[0].screenX;
}, { passive: true });
carouselContainer.addEventListener('touchend', (e) => {
touchEndX = e.changedTouches[0].screenX;
handleSwipe();
}, { passive: true });
function handleSwipe() {
const swipeThreshold = 50;
const diff = touchStartX - touchEndX;
if (Math.abs(diff) > swipeThreshold) {
if (diff > 0) {
// Swipe left - next
console.log('Swipe left - next card');
// Add your carousel next logic here
} else {
// Swipe right - previous
console.log('Swipe right - previous card');
// Add your carousel previous logic here
}
}
}
}
// Pull-to-refresh functionality
let pullStartY = 0;
let pullDistance = 0;
const pullThreshold = 100;
document.addEventListener('touchstart', (e) => {
if (window.pageYOffset === 0) {
pullStartY = e.touches[0].clientY;
}
}, { passive: true });
document.addEventListener('touchmove', (e) => {
if (window.pageYOffset === 0 && pullStartY > 0) {
pullDistance = e.touches[0].clientY - pullStartY;
if (pullDistance > 0) {
e.preventDefault();
document.body.style.transform = `translateY(${Math.min(pullDistance * 0.5, pullThreshold)}px)`;
}
}
}, { passive: false });
document.addEventListener('touchend', () => {
if (pullDistance > pullThreshold) {
// Trigger refresh
console.log('Pull-to-refresh triggered');
location.reload();
}
// Reset
document.body.style.transform = '';
pullStartY = 0;
pullDistance = 0;
}, { passive: true });
// Enhanced touch feedback
const touchElements = document.querySelectorAll('.btn, .click-button, .accordion-header, .carousel-nav, .mobile-nav-link');
touchElements.forEach(element => {
element.addEventListener('touchstart', function() {
this.style.transform = 'scale(0.95)';
}, { passive: true });
element.addEventListener('touchend', function() {
this.style.transform = 'scale(1)';
}, { passive: true });
});
}
// Initialize all enhancements
document.addEventListener('DOMContentLoaded', () => {
initLoadingProgress();
initSkeletonLoading();
initMobileGestures();
initPurpleGlowSpots();
});
// Optimized Custom Cursor with throttling
const cursor = document.querySelector('.cursor');
if (cursor) {
let mouseMoveThrottled = false;
document.addEventListener('mousemove', (e) => {
if (!mouseMoveThrottled) {
requestAnimationFrame(() => {
cursor.style.transform = `translate(${e.clientX}px, ${e.clientY}px)`;
mouseMoveThrottled = false;
});
mouseMoveThrottled = true;
}
}, { passive: true });
document.addEventListener('mousedown', () => {
cursor.style.transform += ' scale(0.8)';
}, { passive: true });
document.addEventListener('mouseup', () => {
cursor.style.transform = cursor.style.transform.replace(' scale(0.8)', '');
}, { passive: true });
}
// Auto-animate stats section when in viewport
document.addEventListener('DOMContentLoaded', () => {
const statsSection = document.querySelector('.stats-section');
const statCards = document.querySelectorAll('.stat-card');
if (statsSection && statCards.length > 0) {
// Set card indices for staggered animation
statCards.forEach((card, index) => {
card.style.setProperty('--card-index', index);
});
// Create Intersection Observer for stats section
const statsObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
// Add animation class when section comes into view
entry.target.classList.add('in-view');
// Unobserve after animation is triggered
statsObserver.unobserve(entry.target);
}
});
}, {
threshold: 0.2, // Trigger when 20% of section is visible
rootMargin: '0px 0px -100px 0px'
});
// Start observing the stats section
statsObserver.observe(statsSection);
}
});
// Accordion functionality
document.addEventListener('DOMContentLoaded', () => {
const accordionItems = document.querySelectorAll('.accordion-item');
accordionItems.forEach(item => {
const header = item.querySelector('.accordion-header');
header.addEventListener('click', () => {
const isActive = item.classList.contains('active');
// Close all other accordion items
accordionItems.forEach(otherItem => {
if (otherItem !== item) {
otherItem.classList.remove('active');
}
});
// Toggle current item
if (isActive) {
item.classList.remove('active');
} else {
item.classList.add('active');
}
});
});
});
// Click Button Ripple Effect and Scroll
document.addEventListener('DOMContentLoaded', () => {
const clickButton = document.querySelector('.click-button');
if (clickButton) {
// Функция создания эффекта кругов при клике
function createClickRipple(e) {
// Предотвращаем стандартное поведение ссылки
e.preventDefault();
const rippleContainer = document.createElement('div');
rippleContainer.className = 'click-ripple';
// Создаем 4 больших круга без задержек но разных размеров
for (let i = 0; i < 4; i++) {
const circle = document.createElement('div');
circle.className = 'ripple-circle';
circle.style.animationDelay = '0s'; // Все круги начинаются сразу
circle.style.borderColor = `rgba(255, 255, 255, ${0.9 - i * 0.15})`;
circle.style.borderWidth = `${4 - i}px`;
// Разные финальные размеры для каждого круга
circle.style.setProperty('--final-size', `${200 + i * 50}px`);
rippleContainer.appendChild(circle);
}
clickButton.appendChild(rippleContainer);
// Удаляем эффект через 2 секунды
setTimeout(() => {
if (rippleContainer.parentNode) {
rippleContainer.remove();
}
}, 2000);
// Скролл к форме после завершения анимации
setTimeout(() => {
const contactSection = document.querySelector('#contact');
if (contactSection) {
contactSection.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
}
}, 800); // Скролл начинается через 0.8 секунды
}
// Добавляем обработчик клика
clickButton.addEventListener('click', createClickRipple);
}
});
// Optimized Header scroll effect with throttling
const header = document.querySelector('.header');
if (header) {
let scrollThrottled = false;
window.addEventListener('scroll', () => {
if (!scrollThrottled) {
requestAnimationFrame(() => {
if (window.scrollY > 100) {
header.classList.add('scrolled');
} else {
header.classList.remove('scrolled');
}
scrollThrottled = false;
});
scrollThrottled = true;
}
}, { passive: true });
}
// Intersection Observer for Animations
const observerOptions = {
threshold: 0.1,
rootMargin: '0px 0px -30px 0px'
};
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('animate-slide-up');
// Handle elements with delay
const delay = entry.target.getAttribute('data-delay');
if (delay) {
entry.target.style.animationDelay = `${delay}ms`;
}
// Animate numbers if it's a stat number or trust number
if (entry.target.classList.contains('stat-number') || entry.target.classList.contains('trust-number')) {
animateNumber(entry.target);
}
// Unobserve element after animation to save performance
observer.unobserve(entry.target);
}
});
}, observerOptions);
// Observe elements - убираем .stat-number из наблюдателя для новых карточек
document.querySelectorAll('.animate-slide-up, .method-card, .exam-card, .success-card, .trust-number').forEach(el => {
observer.observe(el);
});
// Number Animation
function animateNumber(element) {
const target = parseInt(element.getAttribute('data-target'));
// Если нет data-target атрибута, не анимируем
if (!target || isNaN(target)) {
return;
}
const duration = 2000; // 2 seconds
const step = target / (duration / 16); // 60fps
let current = 0;
const updateNumber = () => {
current += step;
if (current < target) {
element.textContent = Math.round(current);
requestAnimationFrame(updateNumber);
} else {
element.textContent = target;
}
};
updateNumber();
}
// Mobile Navigation
const navToggle = document.getElementById('navToggle');
const navLinks = document.querySelector('.nav-links');
if (navToggle && navLinks) {
navToggle.addEventListener('click', () => {
navLinks.classList.toggle('active');
});
}
// Close mobile menu when clicking outside
document.addEventListener('click', (e) => {
if (navLinks && !e.target.closest('.nav-container')) {
navLinks.classList.remove('active');
}
});
// Smooth Scrolling (except click-button)
document.querySelectorAll('a[href^="#"]:not(.click-button)').forEach(anchor => {
anchor.addEventListener('click', function (e) {
e.preventDefault();
if (navLinks) {
navLinks.classList.remove('active');
}
const href = this.getAttribute('href');
if (href && href !== '#') {
const target = document.querySelector(href);
if (target) {
const headerOffset = 80;
const elementPosition = target.getBoundingClientRect().top;
const offsetPosition = elementPosition + window.pageYOffset - headerOffset;
window.scrollTo({
top: offsetPosition,
behavior: 'smooth'
});
}
}
});
});
// Form Animations
const formInputs = document.querySelectorAll('.animate-input');
formInputs.forEach(input => {
input.addEventListener('focus', () => {
input.parentElement.classList.add('focused');
});
input.addEventListener('blur', () => {
if (!input.value) {
input.parentElement.classList.remove('focused');
}
});
});
// Phone number formatting
const phoneInput = document.querySelector('input[type="tel"]');
if (phoneInput) {
phoneInput.addEventListener('input', function(e) {
let value = e.target.value.replace(/\D/g, '');
if (value.length > 0) {
if (value.length <= 1) {
value = '+7 (' + value;
} else if (value.length <= 4) {
value = '+7 (' + value.substring(1);
} else if (value.length <= 7) {
value = '+7 (' + value.substring(1, 4) + ') ' + value.substring(4);
} else if (value.length <= 9) {
value = '+7 (' + value.substring(1, 4) + ') ' + value.substring(4, 7) + '-' + value.substring(7);
} else {
value = '+7 (' + value.substring(1, 4) + ') ' + value.substring(4, 7) + '-' + value.substring(7, 9) + '-' + value.substring(9, 11);
}
}
e.target.value = value;
});
}
// Contact Form Submission
const contactForm = document.querySelector('#contactForm');
if (contactForm) {
contactForm.addEventListener('submit', function(e) {
e.preventDefault();
const button = this.querySelector('.submit-btn');
const originalContent = button.innerHTML;
// Get form data
const firstName = this.querySelector('#firstName').value;
const lastName = this.querySelector('#lastName').value;
const phone = this.querySelector('#phone').value;
// Add loading state
if (button) {
button.disabled = true;
button.innerHTML = ' Sending...';
}
// Simulate form submission (replace with actual API call)
setTimeout(() => {
if (button) {
button.innerHTML = ' Message Sent!';
button.style.background = 'linear-gradient(135deg, #10b981, #059669)';
// Reset form after delay
setTimeout(() => {
this.reset();
if (button) {
button.disabled = false;
button.innerHTML = originalContent;
button.style.background = 'linear-gradient(135deg, var(--primary-color), #4f46e5)';
}
}, 3000);
}
}, 2000);
});
}
// Active Navigation Link on Scroll
const sections = document.querySelectorAll('section');
const navItems = document.querySelectorAll('.nav-links a');
function setActiveNavItem() {
let current = '';
sections.forEach(section => {
const sectionTop = section.offsetTop;
const sectionHeight = section.clientHeight;
if (window.pageYOffset >= sectionTop - 200) {
current = section.getAttribute('id');
}
});
navItems.forEach(item => {
item.classList.remove('active');
if (item.getAttribute('href') === `#${current}`) {
item.classList.add('active');
}
});
}
window.addEventListener('scroll', setActiveNavItem);
window.addEventListener('load', setActiveNavItem);
// Hover Animations for Cards
document.querySelectorAll('.method-card, .exam-card, .success-card').forEach(card => {
card.addEventListener('mouseenter', () => {
card.style.transform = 'translateY(-10px)';
card.style.boxShadow = 'var(--shadow-lg)';
});
card.addEventListener('mouseleave', () => {
card.style.transform = 'translateY(0)';
card.style.boxShadow = 'var(--shadow)';
});
});
// Add animation classes
document.addEventListener('DOMContentLoaded', () => {
// Animate title on load
const mainTitle = document.querySelector('.main-title');
if (mainTitle) {
mainTitle.classList.add('animate-in');
}
// Animate university logos
const logos = document.querySelectorAll('.university-logos img');
logos.forEach((logo, index) => {
setTimeout(() => {
logo.style.opacity = '1';
}, index * 200);
});
});
// Language switcher functionality is now handled by i18n.js
// Parallax Effect for Hero Section
const heroContent = document.querySelector('.hero-content');
const shapes = document.querySelectorAll('.shape');
window.addEventListener('scroll', () => {
const scrolled = window.pageYOffset;
if (heroContent) {
heroContent.style.transform = `translateY(${scrolled * 0.3}px)`;
}
shapes.forEach(shape => {
shape.style.transform = `translateY(${scrolled * 0.4}px)`;
});
});
// Service Card Hover Effect
document.querySelectorAll('.service-card').forEach(card => {
card.addEventListener('mouseenter', (e) => {
const icon = card.querySelector('.card-icon i');
if (icon) {
icon.style.transform = 'scale(1.2) rotate(10deg)';
}
});
card.addEventListener('mouseleave', (e) => {
const icon = card.querySelector('.card-icon i');
if (icon) {
icon.style.transform = 'scale(1) rotate(0deg)';
}
});
});
// Carousel functionality moved to inline script in HTML
// Exam links functionality - открытие аккордеонов
const examLinks = document.querySelectorAll('.exam-link');
examLinks.forEach(link => {
link.addEventListener('click', function(e) {
e.preventDefault();
const targetId = this.getAttribute('href').substring(1);
const targetAccordion = document.getElementById(targetId);
if (targetAccordion) {
// Скролл к секции
targetAccordion.scrollIntoView({
behavior: 'smooth',
block: 'center'
});
// Закрыть все аккордеоны
const allAccordions = document.querySelectorAll('.accordion-item');
allAccordions.forEach(accordion => {
accordion.classList.remove('active');
});
// Открыть целевой аккордеон
setTimeout(() => {
targetAccordion.classList.add('active');
}, 500);
}
});
});
// Logo click functionality - скролл к началу страницы
const logo = document.querySelector('.logo');
if (logo) {
logo.addEventListener('click', function(e) {
e.preventDefault();
// Плавный скролл к началу страницы
window.scrollTo({
top: 0,
behavior: 'smooth'
});
});
}
// Mobile Navigation Functionality
let mobileMenuBtn, mobileNav, mobileOverlay, mobileCloseBtn, mobileNavLinks, mobileNavLogo;
function openMobileMenu() {
console.log('Opening mobile menu...');
if (mobileMenuBtn) {
mobileMenuBtn.classList.add('active');
console.log('Menu button activated');
}
if (mobileNav) {
mobileNav.classList.add('active');
// FORCE FIX CSS WHEN OPENING
mobileNav.style.setProperty('backdrop-filter', 'none', 'important');
mobileNav.style.setProperty('-webkit-backdrop-filter', 'none', 'important');
mobileNav.style.setProperty('background', 'linear-gradient(135deg, rgba(55, 48, 163, 0.98) 0%, rgba(79, 70, 229, 0.98) 100%)', 'important');
mobileNav.style.setProperty('z-index', '10001', 'important');
mobileNav.style.setProperty('pointer-events', 'auto', 'important');
// FORCE FIX ALL ELEMENTS INSIDE MENU
const allMenuElements = mobileNav.querySelectorAll('*');
allMenuElements.forEach(element => {
element.style.setProperty('pointer-events', 'auto', 'important');
element.style.setProperty('z-index', '10002', 'important');
});
// SPECIFIC FIXES FOR CRITICAL ELEMENTS
const navLinks = mobileNav.querySelectorAll('.mobile-nav-link');
navLinks.forEach(link => {
link.style.setProperty('pointer-events', 'auto', 'important');
link.style.setProperty('z-index', '10003', 'important');
link.style.setProperty('position', 'relative', 'important');
link.style.setProperty('cursor', 'pointer', 'important');
});
const closeBtn = mobileNav.querySelector('.mobile-close-btn');
if (closeBtn) {
closeBtn.style.setProperty('pointer-events', 'auto', 'important');
closeBtn.style.setProperty('z-index', '10003', 'important');
closeBtn.style.setProperty('cursor', 'pointer', 'important');
}
const langLinks = mobileNav.querySelectorAll('.mobile-lang-switch a');
langLinks.forEach(link => {
link.style.setProperty('pointer-events', 'auto', 'important');
link.style.setProperty('z-index', '10003', 'important');
link.style.setProperty('cursor', 'pointer', 'important');
});
// FORCE RE-ACTIVATE ALL EVENT LISTENERS AFTER MENU OPENS
setTimeout(() => {
console.log('Re-activating event listeners for menu elements...');
// Simple approach: just force all elements to be clickable
const allClickableElements = mobileNav.querySelectorAll('a, button');
allClickableElements.forEach(element => {
element.style.setProperty('pointer-events', 'auto', 'important');
element.style.setProperty('z-index', '10003', 'important');
element.style.setProperty('cursor', 'pointer', 'important');
element.style.setProperty('position', 'relative', 'important');
// Add click handler if not already present
if (!element.hasAttribute('data-click-handler-added')) {
element.setAttribute('data-click-handler-added', 'true');
element.addEventListener('click', function(e) {
e.preventDefault();
e.stopPropagation();
console.log('🎯 ELEMENT CLICKED:', this.textContent || this.className);
// Handle navigation links
if (this.classList.contains('mobile-nav-link')) {
const targetId = this.getAttribute('href');
if (targetId && targetId.startsWith('#')) {
const targetElement = document.querySelector(targetId);
if (targetElement) {
closeMobileMenu();
setTimeout(() => {
targetElement.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
}, 300);
}
}
}
// Handle language switcher
if (this.closest('.mobile-lang-switch')) {
const lang = this.textContent.toLowerCase();
console.log('Switching language to:', lang);
if (window.i18n && typeof window.i18n.setLanguage === 'function') {
window.i18n.setLanguage(lang === 'ru' ? 'ru' : 'en');
} else {
document.documentElement.lang = lang;
}
closeMobileMenu();
}
// Handle close button
if (this.classList.contains('mobile-close-btn')) {
closeMobileMenu();
}
});
element.addEventListener('touchstart', function(e) {
e.preventDefault();
e.stopPropagation();
console.log('🎯 ELEMENT TOUCHED:', this.textContent || this.className);
// Same logic as click
if (this.classList.contains('mobile-nav-link')) {
const targetId = this.getAttribute('href');
if (targetId && targetId.startsWith('#')) {
const targetElement = document.querySelector(targetId);
if (targetElement) {
closeMobileMenu();
setTimeout(() => {
targetElement.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
}, 300);
}
}
}
if (this.closest('.mobile-lang-switch')) {
const lang = this.textContent.toLowerCase();
console.log('Switching language to:', lang);
if (window.i18n && typeof window.i18n.setLanguage === 'function') {
window.i18n.setLanguage(lang === 'ru' ? 'ru' : 'en');
} else {
document.documentElement.lang = lang;
}
closeMobileMenu();
}
if (this.classList.contains('mobile-close-btn')) {
closeMobileMenu();
}
}, { passive: false });
}
});
console.log('✅ Event listeners re-activated for', allClickableElements.length, 'elements');
}, 100);
console.log('Mobile nav activated with forced CSS fixes');
}
if (mobileOverlay) {
mobileOverlay.classList.add('active');
mobileOverlay.style.setProperty('z-index', '10000', 'important');
mobileOverlay.style.setProperty('pointer-events', 'auto', 'important');
console.log('Overlay activated');
}
document.body.style.overflow = 'hidden';
console.log('Mobile menu opened successfully');
}
function closeMobileMenu() {
console.log('Closing mobile menu...');
if (mobileMenuBtn) {
mobileMenuBtn.classList.remove('active');
console.log('Menu button deactivated');
}
if (mobileNav) {
mobileNav.classList.remove('active');
console.log('Mobile nav deactivated');
}
if (mobileOverlay) {
mobileOverlay.classList.remove('active');
mobileOverlay.style.setProperty('pointer-events', 'none', 'important');
console.log('Overlay deactivated');
}
document.body.style.overflow = '';
console.log('Mobile menu closed successfully');
}
// Initialize mobile menu functionality
function initMobileMenu() {
mobileMenuBtn = document.querySelector('.mobile-menu-btn');
mobileNav = document.querySelector('.mobile-nav');
mobileOverlay = document.querySelector('.mobile-overlay');
mobileCloseBtn = document.querySelector('.mobile-close-btn');
mobileNavLinks = document.querySelectorAll('.mobile-nav-link');
mobileNavLogo = document.querySelector('.mobile-logo');
console.log('Mobile menu elements found:', {
btn: !!mobileMenuBtn,
nav: !!mobileNav,
overlay: !!mobileOverlay,
closeBtn: !!mobileCloseBtn,
links: mobileNavLinks.length
});
// FORCE FIX CSS STYLES
if (mobileNav) {
// Force remove backdrop-filter and fix styles
mobileNav.style.setProperty('backdrop-filter', 'none', 'important');
mobileNav.style.setProperty('-webkit-backdrop-filter', 'none', 'important');
mobileNav.style.setProperty('background', 'linear-gradient(135deg, rgba(55, 48, 163, 0.98) 0%, rgba(79, 70, 229, 0.98) 100%)', 'important');
mobileNav.style.setProperty('z-index', '10001', 'important');
mobileNav.style.setProperty('pointer-events', 'auto', 'important');
console.log('✅ Forced CSS fixes applied to mobile-nav');
}
if (mobileOverlay) {
mobileOverlay.style.setProperty('z-index', '10000', 'important');
mobileOverlay.style.setProperty('pointer-events', 'none', 'important');
console.log('✅ Forced CSS fixes applied to mobile-overlay');
}
// Event listeners for mobile menu button - multiple event types for better compatibility
if (mobileMenuBtn) {
// Click event
mobileMenuBtn.addEventListener('click', (e) => {
e.preventDefault();
e.stopPropagation();
console.log('Mobile menu button clicked');
openMobileMenu();
});
// Touch events for better mobile compatibility
mobileMenuBtn.addEventListener('touchstart', (e) => {
e.preventDefault();
e.stopPropagation();
console.log('Mobile menu button touched');
openMobileMenu();
}, { passive: false });
// Mouse events as fallback
mobileMenuBtn.addEventListener('mousedown', (e) => {
e.preventDefault();
e.stopPropagation();
console.log('Mobile menu button mousedown');
openMobileMenu();
});
}
if (mobileCloseBtn) {
mobileCloseBtn.addEventListener('click', (e) => {
e.preventDefault();
e.stopPropagation();
console.log('Mobile close button clicked');
closeMobileMenu();
});
mobileCloseBtn.addEventListener('touchstart', (e) => {
e.preventDefault();
e.stopPropagation();
console.log('Mobile close button touched');
closeMobileMenu();
}, { passive: false });
}
if (mobileOverlay) {
mobileOverlay.addEventListener('click', (e) => {
e.preventDefault();
e.stopPropagation();
console.log('Mobile overlay clicked');
closeMobileMenu();
});
mobileOverlay.addEventListener('touchstart', (e) => {
e.preventDefault();
e.stopPropagation();
console.log('Mobile overlay touched');
closeMobileMenu();
}, { passive: false });
}
// Close mobile menu when clicking on nav links
mobileNavLinks.forEach(link => {
// FORCE FIX CSS FOR LINKS
link.style.setProperty('pointer-events', 'auto', 'important');
link.style.setProperty('z-index', '10002', 'important');
link.style.setProperty('position', 'relative', 'important');
link.addEventListener('click', (e) => {
e.preventDefault();
e.stopPropagation();
console.log('Mobile nav link clicked:', link.getAttribute('href'));
closeMobileMenu();
// Smooth scroll to section
const targetId = link.getAttribute('href');
if (targetId && targetId.startsWith('#')) {
const targetElement = document.querySelector(targetId);
if (targetElement) {
setTimeout(() => {
targetElement.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
}, 300);
}
}
});
// Touch events for links
link.addEventListener('touchstart', (e) => {
e.preventDefault();
e.stopPropagation();
console.log('Mobile nav link touched:', link.getAttribute('href'));
closeMobileMenu();
const targetId = link.getAttribute('href');
if (targetId && targetId.startsWith('#')) {
const targetElement = document.querySelector(targetId);
if (targetElement) {
setTimeout(() => {
targetElement.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
}, 300);
}
}
}, { passive: false });
});
// Mobile logo click
if (mobileNavLogo) {
// FORCE FIX CSS FOR LOGO
mobileNavLogo.style.setProperty('pointer-events', 'auto', 'important');
mobileNavLogo.style.setProperty('z-index', '10002', 'important');
mobileNavLogo.style.setProperty('position', 'relative', 'important');
mobileNavLogo.addEventListener('click', function(e) {
e.preventDefault();
e.stopPropagation();
console.log('Mobile logo clicked');
closeMobileMenu();
setTimeout(() => {
window.scrollTo({
top: 0,
behavior: 'smooth'
});
}, 300);
});
mobileNavLogo.addEventListener('touchstart', function(e) {
e.preventDefault();
e.stopPropagation();
console.log('Mobile logo touched');
closeMobileMenu();
setTimeout(() => {
window.scrollTo({
top: 0,
behavior: 'smooth'
});
}, 300);
}, { passive: false });
}
// FIX LANGUAGE SWITCHER
const mobileLangSwitch = document.querySelector('.mobile-lang-switch');
if (mobileLangSwitch) {
console.log('Mobile language switcher found');
// FORCE FIX CSS FOR LANGUAGE SWITCHER
mobileLangSwitch.style.setProperty('pointer-events', 'auto', 'important');
mobileLangSwitch.style.setProperty('z-index', '10002', 'important');
mobileLangSwitch.style.setProperty('position', 'relative', 'important');
const langLinks = mobileLangSwitch.querySelectorAll('a');
langLinks.forEach(link => {
// FORCE FIX CSS FOR EACH LANGUAGE LINK
link.style.setProperty('pointer-events', 'auto', 'important');
link.style.setProperty('z-index', '10003', 'important');
link.style.setProperty('position', 'relative', 'important');
link.style.setProperty('cursor', 'pointer', 'important');
link.addEventListener('click', function(e) {
e.preventDefault();
e.stopPropagation();
console.log('Language link clicked:', this.textContent);
// Remove active class from all links
langLinks.forEach(l => l.classList.remove('active'));
// Add active class to clicked link
this.classList.add('active');
// Switch language
const lang = this.textContent.toLowerCase();
if (window.i18n && typeof window.i18n.setLanguage === 'function') {
window.i18n.setLanguage(lang === 'ru' ? 'ru' : 'en');
} else {
console.log('i18n not available, manual language switch');
// Manual language switch fallback
document.documentElement.lang = lang;
}
closeMobileMenu();
});
link.addEventListener('touchstart', function(e) {
e.preventDefault();
e.stopPropagation();
console.log('Language link touched:', this.textContent);
// Remove active class from all links
langLinks.forEach(l => l.classList.remove('active'));
// Add active class to clicked link
this.classList.add('active');
// Switch language
const lang = this.textContent.toLowerCase();
if (window.i18n && typeof window.i18n.setLanguage === 'function') {
window.i18n.setLanguage(lang === 'ru' ? 'ru' : 'en');
} else {
console.log('i18n not available, manual language switch');
// Manual language switch fallback
document.documentElement.lang = lang;
}
closeMobileMenu();
}, { passive: false });
});
}
}
// Close mobile menu on escape key
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape') {
closeMobileMenu();
}
});
// Close mobile menu on window resize
window.addEventListener('resize', function() {
if (window.innerWidth > 992) {
closeMobileMenu();
}
});
// Enhanced mobile functionality
document.addEventListener('DOMContentLoaded', () => {
console.log('DOM Content Loaded - Initializing mobile functionality...');
// Initialize mobile menu
initMobileMenu();
// Additional check for mobile menu elements
setTimeout(() => {
const btn = document.querySelector('.mobile-menu-btn');
const nav = document.querySelector('.mobile-nav');
const overlay = document.querySelector('.mobile-overlay');
console.log('Mobile menu elements check after 100ms:', {
button: btn,
nav: nav,
overlay: overlay,
buttonVisible: btn ? window.getComputedStyle(btn).display !== 'none' : false,
navVisible: nav ? window.getComputedStyle(nav).display !== 'none' : false
});
// Test click simulation
if (btn) {
console.log('Mobile menu button found, testing click simulation...');
// Simulate a click to test if it works
setTimeout(() => {
console.log('Simulating click on mobile menu button...');
btn.click();
setTimeout(() => {
console.log('Menu state after simulated click:', {
buttonActive: btn.classList.contains('active'),
navActive: nav ? nav.classList.contains('active') : false,
overlayActive: overlay ? overlay.classList.contains('active') : false
});
// Close menu after test
closeMobileMenu();
}, 100);
}, 200);
}
}, 100);
// Touch gesture support for mobile
let touchStartY = 0;
let touchEndY = 0;
document.addEventListener('touchstart', (e) => {
touchStartY = e.changedTouches[0].screenY;
}, { passive: true });
document.addEventListener('touchend', (e) => {
touchEndY = e.changedTouches[0].screenY;
handleSwipe();
}, { passive: true });
function handleSwipe() {
const swipeThreshold = 50;
const diff = touchStartY - touchEndY;
// Swipe up to close mobile menu
if (diff > swipeThreshold && mobileNav && mobileNav.classList.contains('active')) {
closeMobileMenu();
}
}
// Improved mobile scrolling performance
let ticking = false;
function updateOnScroll() {
// Add scroll-based animations for mobile
const scrolled = window.pageYOffset;
const parallax = document.querySelectorAll('.floating-shapes .shape');
parallax.forEach((shape, index) => {
const speed = 0.5 + (index * 0.1);
const yPos = -(scrolled * speed);
shape.style.transform = `translateY(${yPos}px)`;
});
ticking = false;
}
function requestTick() {
if (!ticking) {
requestAnimationFrame(updateOnScroll);
ticking = true;
}
}
window.addEventListener('scroll', requestTick, { passive: true });
// Mobile-specific optimizations
if (window.innerWidth <= 768) {
// Reduce animation complexity on mobile
document.body.classList.add('mobile-device');
// Optimize images for mobile
const images = document.querySelectorAll('img');
images.forEach(img => {
if (img.dataset.mobileSrc) {
img.src = img.dataset.mobileSrc;
}
});
// Add mobile-specific event listeners
const touchElements = document.querySelectorAll('.btn, .click-button, .accordion-header');
touchElements.forEach(element => {
element.addEventListener('touchstart', function() {
this.style.transform = 'scale(0.95)';
}, { passive: true });
element.addEventListener('touchend', function() {
this.style.transform = 'scale(1)';
}, { passive: true });
});
}
// Lazy loading for mobile
if ('IntersectionObserver' in window) {
const imageObserver = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
if (img.dataset.src) {
img.src = img.dataset.src;
img.classList.remove('lazy');
observer.unobserve(img);
}
}
});
});
const lazyImages = document.querySelectorAll('img[data-src]');
lazyImages.forEach(img => imageObserver.observe(img));
}
// Mobile form improvements
const formInputs = document.querySelectorAll('input, textarea');
formInputs.forEach(input => {
// Prevent zoom on focus for iOS
input.addEventListener('focus', function() {
if (window.innerWidth <= 768) {
this.style.fontSize = '16px';
}
});
input.addEventListener('blur', function() {
if (window.innerWidth <= 768) {
this.style.fontSize = '';
}
});
});
// Mobile carousel improvements
const carouselContainer = document.querySelector('.carousel-container');
if (carouselContainer && window.innerWidth <= 768) {
let startX = 0;
let currentX = 0;
let isDragging = false;
carouselContainer.addEventListener('touchstart', (e) => {
startX = e.touches[0].clientX;
isDragging = true;
}, { passive: true });
carouselContainer.addEventListener('touchmove', (e) => {
if (!isDragging) return;
currentX = e.touches[0].clientX;
const diff = startX - currentX;
if (Math.abs(diff) > 50) {
if (diff > 0) {
// Swipe left - next
document.querySelector('.carousel-next')?.click();
} else {
// Swipe right - previous
document.querySelector('.carousel-prev')?.click();
}
isDragging = false;
}
}, { passive: true });
carouselContainer.addEventListener('touchend', () => {
isDragging = false;
}, { passive: true });
}
});
// ===== PURPLE GLOW SPOTS ANIMATION =====
function initPurpleGlowSpots() {
const whiteSections = document.querySelectorAll('.white-section');
whiteSections.forEach(section => {
// Create additional random spots
for (let i = 0; i < 3; i++) {
const spot = document.createElement('div');
spot.className = 'glow-spot';
// Random position and size
const size = Math.random() * 150 + 100;
const x = Math.random() * 80 + 10;
const y = Math.random() * 80 + 10;
const delay = Math.random() * 10;
const duration = Math.random() * 10 + 15;
spot.style.cssText = `
width: ${size}px;
height: ${size}px;
left: ${x}%;
top: ${y}%;
animation-delay: -${delay}s;
animation-duration: ${duration}s;
`;
const spotsContainer = section.querySelector('.purple-glow-spots');
if (spotsContainer) {
spotsContainer.appendChild(spot);
}
}
});
// Add subtle mouse interaction
document.addEventListener('mousemove', (e) => {
const spots = document.querySelectorAll('.glow-spot');
const mouseX = e.clientX / window.innerWidth;
const mouseY = e.clientY / window.innerHeight;
spots.forEach((spot, index) => {
const speed = (index + 1) * 0.5;
const x = (mouseX - 0.5) * speed * 20;
const y = (mouseY - 0.5) * speed * 20;
spot.style.transform = `translate(${x}px, ${y}px)`;
});
}, { passive: true });
}