/**
* ByMAS Landing — app.js
* Scroll reveal, burger menu, number counters, online counter
*/
/* ── Scroll reveal ─────────────────────────────── */
const revealObserver = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
entry.target.classList.add('visible');
revealObserver.unobserve(entry.target);
}
});
}, { threshold: 0.12 });
document.querySelectorAll('.reveal, .tl-item').forEach((el) => {
revealObserver.observe(el);
});
/* ── Header shadow on scroll ───────────────────── */
const header = document.getElementById('header');
window.addEventListener('scroll', () => {
header.style.boxShadow = window.scrollY > 10
? '0 2px 20px rgba(0,0,0,.12)'
: '0 2px 2px #c4c4c4';
}, { passive: true });
/* ── Burger menu ────────────────────────────────── */
const burger = document.getElementById('burger');
const mobileNav = document.getElementById('mobileNav');
const mobileClose = document.getElementById('mobileClose');
function openMobileNav() {
mobileNav.classList.add('open');
document.body.style.overflow = 'hidden';
}
function closeMobileNav() {
mobileNav.classList.remove('open');
document.body.style.overflow = '';
}
burger.addEventListener('click', openMobileNav);
mobileClose.addEventListener('click', closeMobileNav);
document.querySelectorAll('.mob-link, .mobile-nav a').forEach((link) => {
link.addEventListener('click', closeMobileNav);
});
/* ── Smooth anchor scroll ───────────────────────── */
document.querySelectorAll('a[href^="#"]').forEach((anchor) => {
anchor.addEventListener('click', (e) => {
const target = document.querySelector(anchor.getAttribute('href'));
if (target) {
e.preventDefault();
target.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
});
});
/* ── Number counter animation ───────────────────── */
function animateCounter(el, target, duration = 1600) {
const raw = target.replace(/\s/g, '');
const num = parseInt(raw, 10);
const start = performance.now();
function update(now) {
const elapsed = now - start;
const progress = Math.min(elapsed / duration, 1);
// easeOutQuart
const ease = 1 - Math.pow(1 - progress, 4);
const current = Math.floor(ease * num);
el.textContent = current.toLocaleString('ru-RU');
if (progress < 1) requestAnimationFrame(update);
else el.textContent = num.toLocaleString('ru-RU');
}
requestAnimationFrame(update);
}
const counterMap = {
cnt1: '14900',
cnt2: '618187',
cnt3: '183957',
cnt4: '166610',
cnt5: '95857',
cnt6: '86815',
cnt7: '84569',
};
const counterObserver = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
const id = entry.target.id;
const target = counterMap[id];
if (target) animateCounter(entry.target, target);
counterObserver.unobserve(entry.target);
}
});
}, { threshold: 0.4 });
Object.keys(counterMap).forEach((id) => {
const el = document.getElementById(id);
if (el) counterObserver.observe(el);
});
/* ── Fake "online" counter ──────────────────────── */
const onlineEl = document.getElementById('onlineCount');
if (onlineEl) {
let base = 247;
setInterval(() => {
const delta = Math.floor(Math.random() * 7) - 3;
base = Math.max(210, Math.min(310, base + delta));
onlineEl.textContent = base;
}, 3500);
}
/* ── Stagger hero stat numbers ─────────────────── */
document.querySelectorAll('.stat-num').forEach((el, i) => {
el.style.opacity = '0';
el.style.transform = 'translateY(12px)';
el.style.transition = 'opacity .5s, transform .5s';
setTimeout(() => {
el.style.opacity = '1';
el.style.transform = 'translateY(0)';
}, 600 + i * 120);
});
/* ── Stagger feature cards ──────────────────────── */
document.querySelectorAll('.feature-card').forEach((card, i) => {
card.style.transitionDelay = `${i * 60}ms`;
});
/* ── Stagger cat cards ──────────────────────────── */
document.querySelectorAll('.cat-card').forEach((card, i) => {
card.style.transitionDelay = `${i * 50}ms`;
});