1// Mobile menu toggle 2const menuToggle = document.getElementById('menuToggle'); 3const mainNav = document.getElementById('mainNav'); 4const headerElement = document.querySelector('header'); 5 6if (menuToggle && mainNav) { 7 menuToggle.addEventListener('click', () => { 8 const isActive = mainNav.classList.toggle('active'); 9 menuToggle.innerHTML = isActive 10 ? '<i class="fas fa-times"></i>' 11 : '<i class="fas fa-bars"></i>'; 12 }); 13} 14 15// Logo (top-left) -> go to home (smooth scroll) and close mobile nav if open 16const logoLink = document.getElementById('logoLink'); 17if (logoLink) { 18 logoLink.addEventListener('click', function(e) { 19 // Prevent full page reload when clicked; smooth-scroll to top / home section 20 e.preventDefault(); 21 if (mainNav && mainNav.classList.contains('active')) { 22 mainNav.classList.remove('active'); 23 if (menuToggle) menuToggle.innerHTML = '<i class="fas fa-bars"></i>'; 24 } 25 window.scrollTo({ top: 0, behavior: 'smooth' }); 26 // update URL to reflect actual home link without reloading 27 try { history.replaceState(null, '', logoLink.getAttribute('href')); } catch (err) {} 28 }); 29} 30 31document.querySelectorAll('a[href^="#"]').forEach(anchor => { 32 anchor.addEventListener('click', function(e) { 33 e.preventDefault(); 34 const href = this.getAttribute('href'); 35 if (!href || href === '#') return; 36 const target = document.querySelector(href); 37 if (target) { 38 if (mainNav && mainNav.classList.contains('active')) { 39 mainNav.classList.remove('active'); 40 if (menuToggle) menuToggle.innerHTML = '<i class="fas fa-bars"></i>'; 41 } 42 const headerOffset = headerElement ? headerElement.offsetHeight : 60; 43 const elementPosition = target.getBoundingClientRect().top + window.pageYOffset; 44 const offsetPosition = elementPosition - headerOffset; 45 window.scrollTo({ top: offsetPosition, behavior: 'smooth' }); 46 } 47 }); 48}); 49 50// Intersection observer for .animate elements 51const animateElements = document.querySelectorAll('.animate'); 52if (animateElements.length) { 53 const observer = new IntersectionObserver((entries, obs) => { 54 entries.forEach(entry => { 55 if (entry.isIntersecting) { 56 entry.target.style.opacity = 1; 57 entry.target.style.transform = 'translateY(0)'; 58 obs.unobserve(entry.target); 59 } 60 }); 61 }, { threshold: 0.1 }); 62 63 animateElements.forEach(el => { 64 el.style.opacity = 0; 65 el.style.transform = 'translateY(15px)'; 66 el.style.transition = 'opacity 0.6s ease-out, transform 0.6s ease-out'; 67 observer.observe(el); 68 }); 69} 70 71// Load Imgur embed script once (needed for the blockquote to render) 72(function loadImgurEmbed(){ 73 if (!document.getElementById('imgur-embed-script')) { 74 const s = document.createElement('script'); 75 s.id = 'imgur-embed-script'; 76 s.async = true; 77 s.src = 'https://s.imgur.com/min/embed.js'; 78 s.charset = 'utf-8'; 79 document.body.appendChild(s); 80 } 81})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.