/* Novizun — Interactive Script */
// Initialize Lucide icons
lucide.createIcons();
// Dark mode toggle
(function () {
const toggle = document.querySelector('[data-theme-toggle]');
const root = document.documentElement;
let dark = matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
root.setAttribute('data-theme', dark);
if (toggle) {
toggle.addEventListener('click', function () {
dark = dark === 'dark' ? 'light' : 'dark';
root.setAttribute('data-theme', dark);
toggle.setAttribute('aria-label', 'Switch to ' + (dark === 'dark' ? 'light' : 'dark') + ' mode');
toggle.innerHTML = dark === 'dark'
? ''
: '';
});
}
})();
// Mobile menu toggle
(function () {
const btn = document.getElementById('mobile-menu-btn');
const nav = document.getElementById('nav');
if (btn && nav) {
btn.addEventListener('click', function () {
const expanded = btn.getAttribute('aria-expanded') === 'true';
btn.setAttribute('aria-expanded', String(!expanded));
nav.classList.toggle('open');
});
// Close on link click
nav.querySelectorAll('.nav-link').forEach(function (link) {
link.addEventListener('click', function () {
btn.setAttribute('aria-expanded', 'false');
nav.classList.remove('open');
});
});
}
})();
// Header scroll behavior
(function () {
const header = document.getElementById('header');
let lastScroll = 0;
window.addEventListener('scroll', function () {
const scrollY = window.scrollY;
if (scrollY > 10) {
header.classList.add('header--scrolled');
} else {
header.classList.remove('header--scrolled');
}
lastScroll = scrollY;
}, { passive: true });
})();
// Product category filtering
(function () {
const tabs = document.querySelectorAll('.product-tab');
const cards = document.querySelectorAll('.product-card');
tabs.forEach(function (tab) {
tab.addEventListener('click', function () {
// Update active tab
tabs.forEach(function (t) {
t.classList.remove('active');
t.setAttribute('aria-selected', 'false');
});
tab.classList.add('active');
tab.setAttribute('aria-selected', 'true');
const filter = tab.getAttribute('data-filter');
cards.forEach(function (card) {
if (filter === 'all') {
card.classList.remove('hidden');
} else {
const category = card.getAttribute('data-category') || '';
if (category.includes(filter)) {
card.classList.remove('hidden');
} else {
card.classList.add('hidden');
}
}
});
});
});
})();
// Smooth scroll for anchor links
document.querySelectorAll('a[href^="#"]').forEach(function (anchor) {
anchor.addEventListener('click', function (e) {
const target = document.querySelector(this.getAttribute('href'));
if (target) {
e.preventDefault();
target.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
});
});
// Intersection Observer for scroll reveal
(function () {
const sections = document.querySelectorAll('.section');
if (!('IntersectionObserver' in window)) return;
const observer = new IntersectionObserver(function (entries) {
entries.forEach(function (entry) {
if (entry.isIntersecting) {
entry.target.style.opacity = '1';
entry.target.style.transform = 'translateY(0)';
observer.unobserve(entry.target);
}
});
}, { threshold: 0.1, rootMargin: '0px 0px -50px 0px' });
sections.forEach(function (section) {
section.style.opacity = '0';
section.style.transform = 'translateY(20px)';
section.style.transition = 'opacity 0.6s cubic-bezier(0.16, 1, 0.3, 1), transform 0.6s cubic-bezier(0.16, 1, 0.3, 1)';
observer.observe(section);
});
})();
// Floating CTA — show after scrolling past hero
(function () {
var floatingCta = document.getElementById('floating-cta');
if (!floatingCta) return;
var hero = document.querySelector('.hero');
if (!hero) return;
// Check if mobile (floating CTA hidden on desktop via CSS, but let's be safe)
function checkMobile() {
return window.innerWidth < 768;
}
function toggleFloatingCta() {
if (!checkMobile()) {
floatingCta.classList.remove('visible');
return;
}
var heroBottom = hero.getBoundingClientRect().bottom;
if (heroBottom < 0) {
floatingCta.classList.add('visible');
} else {
floatingCta.classList.remove('visible');
}
}
window.addEventListener('scroll', toggleFloatingCta, { passive: true });
window.addEventListener('resize', toggleFloatingCta, { passive: true });
// Initial check
toggleFloatingCta();
})();