// DOM Content Loaded document.addEventListener('DOMContentLoaded', function() { // Mobile Navigation Toggle const hamburger = document.querySelector('.hamburger'); const navMenu = document.querySelector('.nav-menu'); hamburger.addEventListener('click', function() { hamburger.classList.toggle('active'); navMenu.classList.toggle('active'); }); // Close mobile menu when clicking on a link document.querySelectorAll('.nav-link').forEach(link => { link.addEventListener('click', () => { hamburger.classList.remove('active'); navMenu.classList.remove('active'); }); }); // Smooth scrolling for navigation links document.querySelectorAll('a[href^="#"]').forEach(anchor => { anchor.addEventListener('click', function (e) { e.preventDefault(); const target = document.querySelector(this.getAttribute('href')); if (target) { const offsetTop = target.offsetTop - 70; // Account for fixed navbar window.scrollTo({ top: offsetTop, behavior: 'smooth' }); } }); }); // Navbar background on scroll const navbar = document.querySelector('.navbar'); window.addEventListener('scroll', function() { if (window.scrollY > 50) { navbar.style.background = 'rgba(255, 255, 255, 0.98)'; navbar.style.boxShadow = '0 2px 20px rgba(0, 0, 0, 0.1)'; } else { navbar.style.background = 'rgba(255, 255, 255, 0.95)'; navbar.style.boxShadow = 'none'; } }); // Animated counter for hero stats function animateCounter(element, target, duration = 2000) { let start = 0; const increment = target / (duration / 16); function updateCounter() { start += increment; if (start < target) { element.textContent = Math.floor(start); requestAnimationFrame(updateCounter); } else { element.textContent = target; } } updateCounter(); } // Intersection Observer for animations const observerOptions = { threshold: 0.1, rootMargin: '0px 0px -50px 0px' }; const observer = new IntersectionObserver(function(entries) { entries.forEach(entry => { if (entry.isIntersecting) { entry.target.classList.add('fade-in-up'); // Animate counters when hero section is visible if (entry.target.classList.contains('hero-stats')) { const counters = entry.target.querySelectorAll('.stat-number'); counters.forEach(counter => { const target = parseInt(counter.getAttribute('data-target')); animateCounter(counter, target); }); } observer.unobserve(entry.target); } }); }, observerOptions); // Observe elements for animation const animatedElements = document.querySelectorAll('.contribution-item, .finding-item, .resource-item, .hero-stats, .example-container, .categories-visual'); animatedElements.forEach(el => observer.observe(el)); // Active navigation link highlighting const sections = document.querySelectorAll('section[id]'); const navLinks = document.querySelectorAll('.nav-link'); function highlightNavigation() { let current = ''; sections.forEach(section => { const sectionTop = section.offsetTop - 100; const sectionHeight = section.clientHeight; if (window.scrollY >= sectionTop && window.scrollY < sectionTop + sectionHeight) { current = section.getAttribute('id'); } }); navLinks.forEach(link => { link.classList.remove('active'); if (link.getAttribute('href') === `#${current}`) { link.classList.add('active'); } }); } window.addEventListener('scroll', highlightNavigation); // Parallax effect for hero section const hero = document.querySelector('.hero'); window.addEventListener('scroll', function() { const scrolled = window.pageYOffset; const rate = scrolled * -0.5; if (hero) { hero.style.transform = `translateY(${rate}px)`; } }); // Copy citation to clipboard const citationBox = document.querySelector('.citation-box'); if (citationBox) { citationBox.addEventListener('click', function() { const text = this.textContent; navigator.clipboard.writeText(text).then(function() { // Show feedback const feedback = document.createElement('div'); feedback.textContent = 'Citation copied to clipboard!'; feedback.style.cssText = ` position: fixed; top: 20px; right: 20px; background: #10b981; color: white; padding: 1rem 2rem; border-radius: 10px; z-index: 10000; animation: slideInRight 0.3s ease; `; document.body.appendChild(feedback); setTimeout(() => { feedback.remove(); }, 3000); }); }); } // Add hover effects to performance table rows const tableRows = document.querySelectorAll('.performance-table tbody tr'); tableRows.forEach(row => { row.addEventListener('mouseenter', function() { this.style.backgroundColor = 'rgba(37, 99, 235, 0.05)'; this.style.transform = 'scale(1.02)'; this.style.transition = 'all 0.3s ease'; }); row.addEventListener('mouseleave', function() { if (!this.classList.contains('top-performer')) { this.style.backgroundColor = ''; } this.style.transform = 'scale(1)'; }); }); /* Ensure images are visible and properly loaded */ const images = document.querySelectorAll('img[src]'); images.forEach(img => { img.style.opacity = '1'; img.style.transition = 'opacity 0.3s ease'; // Ensure image is loaded if (!img.complete) { img.onload = function() { this.style.opacity = '1'; }; } }); // Add scroll progress indicator const progressBar = document.createElement('div'); progressBar.style.cssText = ` position: fixed; top: 0; left: 0; width: 0%; height: 3px; background: linear-gradient(90deg, #667eea, #764ba2); z-index: 10000; transition: width 0.1s ease; `; document.body.appendChild(progressBar); window.addEventListener('scroll', function() { const scrollTop = window.pageYOffset; const docHeight = document.body.scrollHeight - window.innerHeight; const scrollPercent = (scrollTop / docHeight) * 100; progressBar.style.width = scrollPercent + '%'; }); // Add smooth fade-in effect to hero title instead of typing const heroTitle = document.querySelector('.hero-title'); if (heroTitle) { heroTitle.style.opacity = '0'; heroTitle.style.transform = 'translateY(30px)'; heroTitle.style.transition = 'opacity 1s ease, transform 1s ease'; setTimeout(() => { heroTitle.style.opacity = '1'; heroTitle.style.transform = 'translateY(0)'; }, 300); } // Add floating animation to contribution items const contributionItems = document.querySelectorAll('.contribution-item'); contributionItems.forEach((item, index) => { item.style.animationDelay = `${index * 0.1}s`; item.classList.add('float-animation'); }); // Add CSS for floating animation const style = document.createElement('style'); style.textContent = ` @keyframes float { 0%, 100% { transform: translateY(0px); } 50% { transform: translateY(-10px); } } .float-animation { animation: float 3s ease-in-out infinite; } @keyframes slideInRight { from { transform: translateX(100%); opacity: 0; } to { transform: translateX(0); opacity: 1; } } .nav-link.active { color: var(--primary-color); } .nav-link.active::after { width: 100%; } `; document.head.appendChild(style); // Add click effects to buttons const buttons = document.querySelectorAll('.btn, .resource-link'); buttons.forEach(button => { button.addEventListener('click', function(e) { const ripple = document.createElement('span'); const rect = this.getBoundingClientRect(); const size = Math.max(rect.width, rect.height); const x = e.clientX - rect.left - size / 2; const y = e.clientY - rect.top - size / 2; ripple.style.cssText = ` position: absolute; width: ${size}px; height: ${size}px; left: ${x}px; top: ${y}px; background: rgba(255, 255, 255, 0.3); border-radius: 50%; transform: scale(0); animation: ripple 0.6s linear; pointer-events: none; `; this.style.position = 'relative'; this.style.overflow = 'hidden'; this.appendChild(ripple); setTimeout(() => { ripple.remove(); }, 600); }); }); // Add ripple animation CSS const rippleStyle = document.createElement('style'); rippleStyle.textContent = ` @keyframes ripple { to { transform: scale(4); opacity: 0; } } `; document.head.appendChild(rippleStyle); // Performance optimization: Debounce scroll events function debounce(func, wait) { let timeout; return function executedFunction(...args) { const later = () => { clearTimeout(timeout); func(...args); }; clearTimeout(timeout); timeout = setTimeout(later, wait); }; } // Apply debouncing to scroll events const debouncedScrollHandler = debounce(() => { highlightNavigation(); }, 10); window.addEventListener('scroll', debouncedScrollHandler); console.log('BIS Reasoning 1.0 website loaded successfully!'); });