// CyberVanguard - Main JavaScript // Theme Toggle const initTheme = () => { const theme = localStorage.getItem('theme') || 'dark'; document.documentElement.setAttribute('data-theme', theme); return theme; }; const toggleTheme = () => { const current = document.documentElement.getAttribute('data-theme'); const next = current === 'dark' ? 'light' : 'dark'; document.documentElement.setAttribute('data-theme', next); localStorage.setItem('theme', next); }; // Matrix Rain Effect class MatrixRain { constructor(canvas) { this.canvas = canvas; this.ctx = canvas.getContext('2d'); this.chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ$#@%&*'; this.drops = []; this.fontSize = 14; this.init(); } init() { this.resize(); window.addEventListener('resize', () => this.resize()); const columns = Math.floor(this.canvas.width / this.fontSize); this.drops = Array(columns).fill(1); this.animate(); } resize() { this.canvas.width = this.canvas.scrollWidth; this.canvas.height = this.canvas.scrollHeight; } animate() { this.ctx.fillStyle = 'rgba(2, 6, 23, 0.05)'; this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height); this.ctx.fillStyle = '#22c55e'; this.ctx.font = `${this.fontSize}px JetBrains Mono`; for (let i = 0; i < this.drops.length; i++) { const char = this.chars[Math.floor(Math.random() * this.chars.length)]; const x = i * this.fontSize; const y = this.drops[i] * this.fontSize; // Randomize colors for visual interest const hue = Math.random() > 0.95 ? 340 : 142; // Green or pink this.ctx.fillStyle = `hsl(${hue}, 70%, ${Math.random() > 0.5 ? 60 : 40}%)`; this.ctx.fillText(char, x, y); if (y > this.canvas.height && Math.random() > 0.975) { this.drops[i] = 0; } this.drops[i]++; } this.animationId = requestAnimationFrame(() => this.animate()); } destroy() { cancelAnimationFrame(this.animationId); } } // Counter Animation const animateCounters = () => { const counters = document.querySelectorAll('[data-count]'); const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { const counter = entry.target; const target = parseInt(counter.dataset.count); const duration = 2000; const step = target / (duration / 16); let current = 0; const updateCounter = () => { current += step; if (current < target) { counter.textContent = Math.floor(current).toLocaleString(); requestAnimationFrame(updateCounter); } else { counter.textContent = target.toLocaleString() + (target < 100 ? '%' : '+'); } }; updateCounter(); observer.unobserve(counter); } }); }, { threshold: 0.5 }); counters.forEach(counter => observer.observe(counter)); }; // Scroll Animations const initScrollAnimations = () => { const observerOptions = { threshold: 0.1, rootMargin: '0px 0px -50px 0px' }; const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { entry.target.classList.add('animate-slide-up'); observer.unobserve(entry.target); } }); }, observerOptions); document.querySelectorAll('.hover-lift').forEach(el => { el.classList.add('opacity-0', 'translate-y-4'); observer.observe(el); }); }; // Terminal Interaction class TerminalController { constructor(element) { this.element = element; this.history = []; this.historyIndex = -1; this.currentLine = ''; this.isTyping = false; } async typeLine(text, type = 'command') { const line = document.createElement('div'); line.className = 'terminal-line'; if (type === 'command') { line.innerHTML = `student@cybervanguard:~$ `; } this.element.appendChild(line); for (let i = 0; i < text.length; i++) { await this.delay(30); if (type === 'command') { line.innerHTML += `${text[i]}`; } else { line.innerHTML += `${text[i]}`; } } this.element.scrollTop = this.element.scrollHeight; } delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } async runDemo() { const commands = [ { cmd: 'whoami', out: 'student' }, { cmd: 'nmap -sV 192.168.1.0/24', out: 'Starting Nmap 7.94...\nScanning 256 hosts...\nFound: 192.168.1.1 (router)\nFound: 192.168.1.100 (web-server)\nPorts: 22/ssh, 80/http, 443/https open' }, { cmd: 'enum4linux -a 192.168.1.100', out: 'Starting enum4linux...\n[+] Got domain/workgroup name: CYBERLAB\n[+] OS: Windows Server 2019\n[+] Users: admin, backup_svc, guest' }, { cmd: 'python3 exploit.py --target 192.168.1.100', out: '[*] Checking target vulnerability...\n[+] Target is vulnerable to CVE-2023-1234\n[*] Sending payload...\n[+] Got shell! spawn /bin/bash\nstudent@web-server:~$' } ]; for (const { cmd, out } of commands) { await this.typeLine(cmd, 'command'); await this.delay(500); await this.typeLine(out, 'output'); await this.delay(800); } // Add blinking cursor const cursor = document.createElement('span'); cursor.className = 'terminal-cursor'; this.element.lastElementChild?.appendChild(cursor); } } // Navigation const initNavigation = () => { let lastScroll = 0; const navbar = document.querySelector('cyber-navbar'); window.addEventListener('scroll', () => { const current = window.pageYOffset; if (current > 100) { navbar?.classList.add('scrolled'); } else { navbar?.classList.remove('scrolled'); } lastScroll = current; }); }; // Mobile Menu const initMobileMenu = () => { const toggle = document.querySelector('[data-menu-toggle]'); const menu = document.querySelector('[data-mobile-menu]'); toggle?.addEventListener('click', () => { menu?.classList.toggle('hidden'); toggle.setAttribute('aria-expanded', menu?.classList.contains('hidden') ? 'false' : 'true' ); }); }; // Initialize document.addEventListener('DOMContentLoaded', () => { // Initialize theme initTheme(); // Initialize Matrix effect if canvas exists const matrixCanvas = document.getElementById('matrix-canvas'); if (matrixCanvas) { new MatrixRain(matrixCanvas); } // Initialize counters animateCounters(); // Initialize scroll animations initScrollAnimations(); // Initialize navigation initNavigation(); // Initialize mobile menu initMobileMenu(); // Initialize terminal if exists const terminalBody = document.querySelector('[data-terminal-body]'); if (terminalBody) { const terminal = new TerminalController(terminalBody); setTimeout(() => terminal.runDemo(), 1000); } // Smooth scroll for anchor links document.querySelectorAll('a[href^="#"]').forEach(anchor => { anchor.addEventListener('click', function (e) { e.preventDefault(); const target = document.querySelector(this.getAttribute('href')); if (target) { target.scrollIntoView({ behavior: 'smooth', block: 'start' }); } }); }); }); // Export for use in components window.CyberVanguard = { MatrixRain, TerminalController, toggleTheme, initTheme };