document.addEventListener('DOMContentLoaded', () => {
if (window.mermaid) {
mermaid.initialize({
startOnLoad: true,
theme: 'dark',
securityLevel: 'loose',
fontFamily: 'Outfit, sans-serif'
});
}
const menuToggle = document.getElementById('menu-toggle');
const sidebar = document.querySelector('.sidebar');
const overlay = document.querySelector('.sidebar-overlay');
function openSidebar() {
if (!sidebar) return;
sidebar.classList.add('open');
if (overlay) overlay.classList.add('visible');
if (menuToggle) menuToggle.setAttribute('aria-expanded', 'true');
if (menuToggle) menuToggle.innerHTML = '✕';
}
function closeSidebar() {
if (!sidebar) return;
sidebar.classList.remove('open');
if (overlay) overlay.classList.remove('visible');
if (menuToggle) menuToggle.setAttribute('aria-expanded', 'false');
if (menuToggle) menuToggle.innerHTML = '☰';
}
if (menuToggle) {
menuToggle.addEventListener('click', () => {
if (sidebar && sidebar.classList.contains('open')) {
closeSidebar();
} else {
openSidebar();
}
});
}
if (overlay) {
overlay.addEventListener('click', closeSidebar);
}
document.addEventListener('click', (e) => {
if (window.innerWidth <= 768 && sidebar && sidebar.classList.contains('open')) {
if (!sidebar.contains(e.target) && menuToggle && !menuToggle.contains(e.target)) {
closeSidebar();
}
}
});
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape' && sidebar && sidebar.classList.contains('open')) {
closeSidebar();
if (menuToggle) menuToggle.focus();
}
});
const currentPath = window.location.pathname;
const currentPage = currentPath.substring(currentPath.lastIndexOf('/') + 1) || 'index.html';
const navLinks = document.querySelectorAll('.nav-links a');
navLinks.forEach((link) => {
const href = link.getAttribute('href');
if (href === currentPage) {
link.classList.add('active');
} else {
link.classList.remove('active');
}
});
const animateElements = document.querySelectorAll('.animate-in');
if (animateElements.length > 0) {
if ('IntersectionObserver' in window) {
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
entry.target.style.animationPlayState = 'running';
observer.unobserve(entry.target);
}
});
},
{ threshold: 0.1, rootMargin: '0px 0px -40px 0px' }
);
animateElements.forEach((el) => {
const rect = el.getBoundingClientRect();
if (rect.top > window.innerHeight) {
el.style.animationPlayState = 'paused';
observer.observe(el);
}
});
}
}
document.querySelectorAll('a[href^="http"]').forEach((link) => {
if (!link.hasAttribute('target')) {
link.setAttribute('target', '_blank');
link.setAttribute('rel', 'noopener noreferrer');
}
});
});