dev-rexpro's picture
Initial DeepSite commit
776ea28 verified
Raw
History Blame Contribute Delete
6.46 kB
// ====== Lucide Icons Init ======
function initIcons() {
if (typeof lucide !== 'undefined') {
lucide.createIcons();
}
}
initIcons();
// ====== Theme Toggle ======
(function () {
const root = document.documentElement;
const toggle = document.getElementById('theme-toggle');
const stored = localStorage.getItem('omniverse-theme');
// Determine initial theme: stored > system preference > dark
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
const initialTheme = stored || (prefersDark ? 'dark' : 'dark'); // Default to dark for premium feel
if (initialTheme === 'light') {
root.classList.remove('dark');
} else {
root.classList.add('dark');
}
toggle?.addEventListener('click', () => {
root.classList.toggle('dark');
const isDark = root.classList.contains('dark');
localStorage.setItem('omniverse-theme', isDark ? 'dark' : 'light');
initIcons();
});
})();
// ====== Navbar Scroll Effect ======
(function () {
const navbar = document.getElementById('navbar');
let ticking = false;
function updateNavbar() {
if (window.scrollY > 20) {
navbar.classList.add('scrolled');
} else {
navbar.classList.remove('scrolled');
}
ticking = false;
}
window.addEventListener('scroll', () => {
if (!ticking) {
requestAnimationFrame(updateNavbar);
ticking = true;
}
});
})();
// ====== Mobile Menu ======
(function () {
const toggle = document.getElementById('mobile-toggle');
const menu = document.getElementById('mobile-menu');
const menuIcon = document.getElementById('menu-icon');
let isOpen = false;
function toggleMenu() {
isOpen = !isOpen;
if (isOpen) {
menu.classList.remove('hidden');
menuIcon.setAttribute('data-lucide', 'x');
} else {
menu.classList.add('hidden');
menuIcon.setAttribute('data-lucide', 'menu');
}
initIcons();
}
toggle?.addEventListener('click', toggleMenu);
// Close on link click
menu?.querySelectorAll('a').forEach((link) => {
link.addEventListener('click', () => {
if (isOpen) toggleMenu();
});
});
// Close on outside click
document.addEventListener('click', (e) => {
if (isOpen && !menu.contains(e.target) && !toggle.contains(e.target)) {
toggleMenu();
}
});
})();
// ====== Scroll Reveal Animation ======
(function () {
const reveals = document.querySelectorAll('.reveal');
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
entry.target.classList.add('revealed');
observer.unobserve(entry.target);
}
});
},
{ threshold: 0.12, rootMargin: '0px 0px -60px 0px' }
);
reveals.forEach((el) => observer.observe(el));
})();
// ====== FAQ Accordion ======
(function () {
const faqItems = document.querySelectorAll('.faq-item');
faqItems.forEach((item) => {
const trigger = item.querySelector('.faq-trigger');
trigger?.addEventListener('click', () => {
const isActive = item.classList.contains('active');
// Close all
faqItems.forEach((other) => {
other.classList.remove('active');
const otherTrigger = other.querySelector('.faq-trigger');
if (otherTrigger) otherTrigger.setAttribute('aria-expanded', 'false');
});
// Open clicked
if (!isActive) {
item.classList.add('active');
trigger.setAttribute('aria-expanded', 'true');
}
});
});
})();
// ====== Contact Form (WhatsApp) ======
(function () {
const form = document.getElementById('contact-form');
form?.addEventListener('submit', (e) => {
e.preventDefault();
const name = document.getElementById('name')?.value.trim() || '';
const clientType = document.getElementById('client-type')?.value || '';
const service = document.getElementById('service')?.value || '';
const notes = document.getElementById('notes')?.value.trim() || '';
if (!name) return;
const message = [
`Halo Omniverse One,`,
``,
`Nama: ${name}`,
`Kategori Klien: ${clientType}`,
`Layanan: ${service}`,
notes ? `Catatan: ${notes}` : '',
]
.filter(Boolean)
.join('\n');
const encoded = encodeURIComponent(message);
window.open(`https://wa.me/?text=${encoded}`, '_blank');
});
})();
// ====== Back to Top ======
(function () {
const btn = document.getElementById('back-to-top');
let ticking = false;
function updateBtn() {
if (window.scrollY > 600) {
btn?.classList.remove('hidden');
btn?.classList.add('flex');
} else {
btn?.classList.add('hidden');
btn?.classList.remove('flex');
}
ticking = false;
}
window.addEventListener('scroll', () => {
if (!ticking) {
requestAnimationFrame(updateBtn);
ticking = true;
}
});
btn?.addEventListener('click', () => {
window.scrollTo({ top: 0, behavior: 'smooth' });
});
})();
// ====== Year ======
document.getElementById('year').textContent = new Date().getFullYear();
// ====== Active Nav Link Highlighting ======
(function () {
const sections = document.querySelectorAll('section[id]');
const navLinks = document.querySelectorAll('.nav-link');
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
const id = entry.target.getAttribute('id');
navLinks.forEach((link) => {
const href = link.getAttribute('href');
if (href === `#${id}`) {
link.style.color = 'var(--foreground)';
} else {
link.style.color = '';
}
});
}
});
},
{ threshold: 0.3, rootMargin: '-80px 0px -50% 0px' }
);
sections.forEach((sec) => observer.observe(sec));
})();
// ====== Smooth Anchor Scroll ======
document.querySelectorAll('a[href^="#"]').forEach((anchor) => {
anchor.addEventListener('click', function (e) {
const href = this.getAttribute('href');
if (href === '#') return;
const target = document.querySelector(href);
if (target) {
e.preventDefault();
const offset = 80;
const top = target.getBoundingClientRect().top + window.scrollY - offset;
window.scrollTo({ top, behavior: 'smooth' });
}
});
});
// Re-init icons after dynamic changes
setTimeout(initIcons, 100);