1// CitrusBurn Review - Main JavaScript 2// Handles navigation, FAQ accordions, smooth scrolling, and header effects 3 4document.addEventListener('DOMContentLoaded', function() { 5 6 // Mobile Navigation Toggle 7 const hamburger = document.getElementById('hamburger'); 8 const navMobile = document.getElementById('nav-mobile'); 9 10 if (hamburger && navMobile) { 11 hamburger.addEventListener('click', function() { 12 hamburger.classList.toggle('active'); 13 navMobile.classList.toggle('active'); 14 }); 15 16 // Close mobile nav when clicking a link 17 const mobileLinks = navMobile.querySelectorAll('a'); 18 mobileLinks.forEach(link => { 19 link.addEventListener('click', function() { 20 hamburger.classList.remove('active'); 21 navMobile.classList.remove('active'); 22 }); 23 }); 24 } 25 26 // Header Scroll Effect 27 const header = document.getElementById('header'); 28 let lastScroll = 0; 29 30 window.addEventListener('scroll', function() { 31 const currentScroll = window.pageYOffset; 32 33 if (currentScroll > 100) { 34 header.style.boxShadow = '0 4px 12px rgba(0,0,0,0.15)'; 35 } else { 36 header.style.boxShadow = '0 2px 4px rgba(0,0,0,0.1)'; 37 } 38 39 lastScroll = currentScroll; 40 }); 41 42 // Smooth Scrolling for Anchor Links 43 document.querySelectorAll('a[href^="#"]').forEach(anchor => { 44 anchor.addEventListener('click', function(e) { 45 e.preventDefault(); 46 const targetId = this.getAttribute('href'); 47 48 if (targetId === '#') return; 49 50 const targetElement = document.querySelector(targetId); 51 52 if (targetElement) { 53 const headerOffset = 80; 54 const elementPosition = targetElement.getBoundingClientRect().top; 55 const offsetPosition = elementPosition + window.pageYOffset - headerOffset; 56 57 window.scrollTo({ 58 top: offsetPosition, 59 behavior: 'smooth' 60 }); 61 } 62 }); 63 }); 64 65 // FAQ Accordion 66 const faqItems = document.querySelectorAll('.faq-item'); 67 68 faqItems.forEach(item => { 69 const question = item.querySelector('.faq-question'); 70 71 if (question) { 72 question.addEventListener('click', function() { 73 const isActive = item.classList.contains('active'); 74 75 // Close all other FAQs in the same category 76 const category = item.closest('.faq-category'); 77 if (category) { 78 category.querySelectorAll('.faq-item').forEach(faq => { 79 faq.classList.remove('active'); 80 }); 81 } 82 83 // Toggle current FAQ 84 if (!isActive) { 85 item.classList.add('active'); 86 } 87 }); 88 } 89 }); 90 91 // Lazy Loading Images (fallback for browsers without native support) 92 if ('loading' in HTMLImageElement.prototype) { 93 // Native lazy loading supported 94 const images = document.querySelectorAll('img[loading="lazy"]'); 95 images.forEach(img => { 96 if (img.dataset.src) { 97 img.src = img.dataset.src; 98 } 99 }); 100 } else { 101 // Fallback for older browsers 102 const script = document.createElement('script'); 103 script.src = 'https://cdnjs.cloudflare.com/ajax/libs/lazysizes/5.3.2/lazysizes.min.js'; 104 document.body.appendChild(script); 105 } 106 107 // Track CTA Clicks (for analytics) 108 const ctaButtons = document.querySelectorAll('a[href="order.html"]'); 109 ctaButtons.forEach(btn => { 110 btn.addEventListener('click', function() { 111 // Track click event if analytics is available 112 if (typeof gtag !== 'undefined') { 113 gtag('event', 'click', { 114 'event_category': 'CTA', 115 'event_label': this.textContent.trim(), 116 'transport_type': 'beacon' 117 }); 118 } 119 }); 120 }); 121 122 // Intersection Observer for Animations 123 const observerOptions = { 124 root: null, 125 rootMargin: '0px', 126 threshold: 0.1 127 }; 128 129 const observer = new IntersectionObserver((entries) => {
130 entries.forEach(entry => { 131 if (entry.isIntersecting) { 132 entry.target.style.opacity = '1'; 133 entry.target.style.transform = 'translateY(0)'; 134 } 135 }); 136 }, observerOptions); 137 138 // Observe elements for fade-in animation 139 const animateElements = document.querySelectorAll('.summary-card, .step-card, .ingredient-card, .testimonial-card, .pricing-card'); 140 animateElements.forEach(el => { 141 el.style.opacity = '0'; 142 el.style.transform = 'translateY(20px)'; 143 el.style.transition = 'opacity 0.5s ease, transform 0.5s ease'; 144 observer.observe(el); 145 }); 146 147}); 148 149// Utility function to format numbers 150function formatNumber(num) { 151 return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); 152}
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.