2026-10-24 11:50:48 +00:00
|
|
|
/* ==========================================================================
|
|
|
|
|
DmitriyVPN Client Scripts
|
|
|
|
|
Interactive UI: Theme Toggle, Burger Menu, Billing Toggle, FAQ, Scroll Reveal
|
|
|
|
|
========================================================================== */
|
|
|
|
|
|
|
|
|
|
/* ===== THEME TOGGLE (Light standard, Dark toggleable) ===== */
|
|
|
|
|
function initTheme() {
|
|
|
|
|
const savedTheme = localStorage.getItem('dmitriyvpn_theme');
|
|
|
|
|
if (savedTheme === 'dark') {
|
|
|
|
|
document.documentElement.setAttribute('data-theme', 'dark');
|
|
|
|
|
} else {
|
|
|
|
|
document.documentElement.setAttribute('data-theme', 'light');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function toggleTheme() {
|
|
|
|
|
const current = document.documentElement.getAttribute('data-theme') || 'light';
|
|
|
|
|
const next = current === 'dark' ? 'light' : 'dark';
|
|
|
|
|
document.documentElement.setAttribute('data-theme', next);
|
|
|
|
|
localStorage.setItem('dmitriyvpn_theme', next);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Initialize theme immediately
|
|
|
|
|
initTheme();
|
|
|
|
|
|
|
|
|
|
/* ===== BURGER & MOBILE NAVIGATION ===== */
|
2026-10-24 11:25:35 +00:00
|
|
|
function toggleMobile() {
|
|
|
|
|
const burger = document.getElementById('burger');
|
|
|
|
|
const nav = document.getElementById('mobileNav');
|
2026-10-24 11:50:48 +00:00
|
|
|
if (!burger || !nav) return;
|
2026-10-24 11:25:35 +00:00
|
|
|
const isOpen = burger.classList.toggle('open');
|
|
|
|
|
nav.classList.toggle('open', isOpen);
|
|
|
|
|
document.body.style.overflow = isOpen ? 'hidden' : '';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function closeMobile() {
|
|
|
|
|
const burger = document.getElementById('burger');
|
|
|
|
|
const nav = document.getElementById('mobileNav');
|
|
|
|
|
if (burger) burger.classList.remove('open');
|
|
|
|
|
if (nav) nav.classList.remove('open');
|
|
|
|
|
document.body.style.overflow = '';
|
|
|
|
|
}
|
|
|
|
|
|
2026-10-24 11:50:48 +00:00
|
|
|
// Close mobile nav on escape key
|
|
|
|
|
document.addEventListener('keydown', (e) => {
|
|
|
|
|
if (e.key === 'Escape') closeMobile();
|
|
|
|
|
});
|
|
|
|
|
|
2026-10-24 11:25:35 +00:00
|
|
|
/* ===== SCROLL REVEAL ===== */
|
|
|
|
|
const revealObserver = new IntersectionObserver((entries) => {
|
|
|
|
|
entries.forEach(entry => {
|
|
|
|
|
if (entry.isIntersecting) {
|
|
|
|
|
entry.target.classList.add('visible');
|
|
|
|
|
revealObserver.unobserve(entry.target);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}, { threshold: 0.08 });
|
|
|
|
|
|
|
|
|
|
document.querySelectorAll('.reveal').forEach(el => revealObserver.observe(el));
|
|
|
|
|
|
|
|
|
|
/* ===== BILLING TOGGLE ===== */
|
|
|
|
|
const prices = {
|
2026-10-24 11:50:48 +00:00
|
|
|
month: { standard: 109.22, pro: 194.41, premium: 291.62 },
|
2026-10-24 11:25:35 +00:00
|
|
|
'3month': { standard: 98.30, pro: 174.97, premium: 262.46 },
|
2026-10-24 11:50:48 +00:00
|
|
|
year: { standard: 87.38, pro: 155.53, premium: 233.30 }
|
2026-10-24 11:25:35 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
function setBilling(period, btn) {
|
2026-10-24 11:50:48 +00:00
|
|
|
document.querySelectorAll('.billing-opt-btn').forEach(b => b.classList.remove('active'));
|
2026-10-24 11:25:35 +00:00
|
|
|
btn.classList.add('active');
|
|
|
|
|
|
|
|
|
|
const p = prices[period];
|
2026-10-24 11:50:48 +00:00
|
|
|
if (!p) return;
|
|
|
|
|
|
2026-10-24 11:25:35 +00:00
|
|
|
const els = {
|
|
|
|
|
'price-from': p.standard,
|
|
|
|
|
'price-standard': p.standard,
|
|
|
|
|
'price-pro': p.pro,
|
|
|
|
|
'price-premium': p.premium
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Object.entries(els).forEach(([id, val]) => {
|
|
|
|
|
const el = document.getElementById(id);
|
|
|
|
|
if (el) {
|
|
|
|
|
el.classList.add('updating');
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
el.textContent = val.toFixed(2);
|
|
|
|
|
el.classList.remove('updating');
|
2026-10-24 11:50:48 +00:00
|
|
|
}, 120);
|
2026-10-24 11:25:35 +00:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ===== FAQ ACCORDION ===== */
|
|
|
|
|
function toggleFaq(btn) {
|
2026-10-24 11:50:48 +00:00
|
|
|
const item = btn.closest('.faq-item');
|
|
|
|
|
if (!item) return;
|
|
|
|
|
const answer = item.querySelector('.faq-answer-collapse');
|
2026-10-24 11:25:35 +00:00
|
|
|
const isOpen = item.classList.contains('open');
|
|
|
|
|
|
2026-10-24 11:50:48 +00:00
|
|
|
// Close all other open FAQ items
|
2026-10-24 11:25:35 +00:00
|
|
|
document.querySelectorAll('.faq-item').forEach(i => {
|
2026-10-24 11:50:48 +00:00
|
|
|
if (i !== item) {
|
|
|
|
|
i.classList.remove('open');
|
|
|
|
|
const a = i.querySelector('.faq-answer-collapse');
|
|
|
|
|
if (a) a.style.maxHeight = null;
|
|
|
|
|
}
|
2026-10-24 11:25:35 +00:00
|
|
|
});
|
|
|
|
|
|
2026-10-24 11:50:48 +00:00
|
|
|
// Toggle current item
|
2026-10-24 11:25:35 +00:00
|
|
|
if (!isOpen && answer) {
|
|
|
|
|
item.classList.add('open');
|
|
|
|
|
answer.style.maxHeight = answer.scrollHeight + 'px';
|
2026-10-24 11:50:48 +00:00
|
|
|
} else if (answer) {
|
|
|
|
|
item.classList.remove('open');
|
|
|
|
|
answer.style.maxHeight = null;
|
2026-10-24 11:25:35 +00:00
|
|
|
}
|
|
|
|
|
}
|