-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathneurovoid_hackaccino.html
More file actions
303 lines (294 loc) · 22.3 KB
/
neurovoid_hackaccino.html
File metadata and controls
303 lines (294 loc) · 22.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="slides-format" content="viewport">
<title>NeuroVoid - Hackaccino Phase 1</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;700;800&family=Inter:wght@300;400;500;600;700;800&display=swap" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
<style type="text/tailwindcss">
@theme {
--color-bg: #0a0a0a;
--color-bg-deep: #111111;
--color-surface: #171717;
--color-text: #f5f5f5;
--color-text-secondary: #d4d4d4;
--color-text-muted: #a3a3a3;
--color-accent-1: #00ff41;
--color-accent-2: #ffa500;
--color-accent-3: #ff3b30;
--color-glass-bg: rgba(0,255,65,0.05);
--color-glass-border: rgba(0,255,65,0.12);
--color-vignette: rgba(0,0,0,0.42);
--font-display: 'JetBrains Mono', monospace;
--font-body: 'Inter', sans-serif;
}
</style>
<style>
:root { --color-bg: #0a0a0a; --color-text: #f5f5f5; --glow-color-rgb: 0,255,65; }
*, *::before, *::after { box-sizing: border-box; }
html, body { background: var(--color-bg); margin: 0; }
body { font-family: var(--font-body); color: var(--color-text); overflow: hidden; height: 100vh; width: 100vw; }
.deck { width: 100vw; height: 100vh; position: relative; }
.slide { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: var(--color-bg); display: flex; flex-direction: column; align-items: center; justify-content: center; opacity: 0; transform: scale(0.95); transition: opacity 0.7s ease, transform 0.7s ease; pointer-events: none; overflow: hidden; }
.slide.active { opacity: 1; transform: scale(1); pointer-events: all; }
.slide > .content { position: relative; z-index: 2; width: 100%; max-width: 1180px; padding: clamp(1.5rem, 4vw, 4rem); }
.nav-controls { position: fixed; bottom: 24px; left: 50%; transform: translateX(-50%); display: flex; align-items: center; gap: 16px; z-index: 100; background: rgba(0,0,0,0.45); backdrop-filter: blur(10px); padding: 10px 24px; border-radius: 40px; border: 1px solid rgba(0,255,65,0.12); }
.nav-btn { width: 40px; height: 40px; border: none; background: rgba(0,255,65,0.06); color: #00ff41; border-radius: 50%; font-size: 1.2rem; cursor: pointer; display: flex; align-items: center; justify-content: center; }
.slide-dots { display: flex; gap: 8px; }
.slide-dots .dot { width: 10px; height: 10px; border-radius: 50%; background: rgba(255,255,255,0.18); cursor: pointer; transition: background 0.3s, transform 0.3s; }
.slide-dots .dot.active { background: #00ff41; transform: scale(1.3); }
.slide-counter { font-size: 0.8rem; color: #a3a3a3; min-width: 40px; text-align: center; }
.reveal { opacity: 0; transform: translateY(20px); }
.gradient-mesh { position: absolute; inset: 0; z-index: 0; overflow: hidden; pointer-events: none; }
.blob { position: absolute; border-radius: 50%; filter: blur(80px); animation: float-slow 12s ease-in-out infinite; }
.blob:nth-child(2) { animation: float-drift 15s ease-in-out infinite; }
.blob:nth-child(3) { animation: float-slow 18s ease-in-out infinite reverse; }
.slide::before { content: ''; position: absolute; inset: 0; z-index: 1; pointer-events: none; background-image: linear-gradient(rgba(255,255,255,0.03) 1px, transparent 1px), linear-gradient(90deg, rgba(255,255,255,0.03) 1px, transparent 1px); background-size: 48px 48px; opacity: 0.12; }
.slide::after { content: ''; position: absolute; inset: 0; z-index: 1; pointer-events: none; background: radial-gradient(ellipse at center, transparent 50%, var(--color-vignette) 100%); }
.text-glow { text-shadow: 0 0 18px rgba(var(--glow-color-rgb),0.45), 0 0 40px rgba(var(--glow-color-rgb),0.18); }
.stat-card { background: rgba(0,255,65,0.04); border: 1px solid rgba(0,255,65,0.12); backdrop-filter: blur(10px); border-radius: 22px; }
.accent-orange { color: #ffa500; }
.accent-red { color: #ff5f56; }
.pill { border: 1px solid rgba(0,255,65,0.18); background: rgba(0,255,65,0.06); border-radius: 999px; padding: 0.4rem 0.8rem; }
@keyframes float-slow { 0% { transform: translate(0,0) scale(1); } 25% { transform: translate(60px,-50px) scale(1.08); } 50% { transform: translate(-35px,35px) scale(0.92); } 75% { transform: translate(45px,10px) scale(1.04); } 100% { transform: translate(0,0) scale(1); } }
@keyframes float-drift { 0% { transform: translate(0,0) scale(1) rotate(0deg);} 33% { transform: translate(-50px,-40px) scale(1.1) rotate(3deg);} 66% { transform: translate(30px,25px) scale(0.9) rotate(-2deg);} 100% { transform: translate(0,0) scale(1) rotate(0deg);} }
@keyframes float { 0%,100% { transform: translateY(0);} 50% { transform: translateY(-12px);} }
@media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.2s !important; } }
</style>
</head>
<body>
<div class="mouse-spotlight" style="position:fixed;inset:0;z-index:99;pointer-events:none;"></div>
<div class="deck">
<div class="slide slide-1 active" data-slide="1">
<div class="gradient-mesh">
<div class="blob" style="width:480px;height:480px;top:-120px;right:-100px;background:#00ff41;opacity:0.12;"></div>
<div class="blob" style="width:320px;height:320px;bottom:-100px;left:-60px;background:#ffa500;opacity:0.10;"></div>
<div class="blob" style="width:220px;height:220px;top:42%;left:18%;background:#ff3b30;opacity:0.08;"></div>
</div>
<canvas class="particle-canvas" style="position:absolute;inset:0;z-index:1;"></canvas>
<div class="content text-center">
<div class="text-[120px] mb-4 animate-[float_3s_ease-in-out_infinite] reveal">🛡️</div>
<h1 class="font-display text-[clamp(2.6rem,6vw,5rem)] font-extrabold bg-linear-to-br from-accent-1 via-accent-2 to-accent-1 bg-clip-text text-transparent tracking-tight mb-4 reveal">NeuroVoid</h1>
<p class="text-[clamp(0.95rem,1.7vw,1.35rem)] text-text-muted tracking-[6px] uppercase reveal">Hackaccino Phase 1 Pitch Deck</p>
<p class="max-w-3xl mx-auto mt-8 text-lg text-text-secondary reveal">An AI-first cybersecurity decision platform for everyday users and modern teams.</p>
</div>
</div>
<div class="slide slide-2" data-slide="2">
<div class="gradient-mesh">
<div class="blob" style="width:360px;height:360px;top:-70px;right:-70px;background:#00ff41;opacity:0.08;"></div>
<div class="blob" style="width:240px;height:240px;bottom:-60px;left:-30px;background:#ffa500;opacity:0.06;"></div>
</div>
<div class="content">
<div class="pill text-sm text-accent-1 inline-block mb-5 reveal">Problem Statement</div>
<h2 class="font-display text-[clamp(2rem,4.3vw,3.2rem)] font-bold mb-6 reveal">Cyber decisions are still too confusing</h2>
<div class="grid grid-cols-2 gap-6 mt-8">
<div class="stat-card p-8 reveal">
<div class="text-5xl mb-4">📩</div>
<h3 class="text-2xl font-semibold mb-3">Users face suspicious content daily</h3>
<p class="text-text-secondary text-lg">Phishing emails, fake job offers, payment scams, bank alerts, and malicious links all demand quick judgment.</p>
</div>
<div class="stat-card p-8 reveal">
<div class="text-5xl mb-4">😵</div>
<h3 class="text-2xl font-semibold mb-3">Current tools create friction</h3>
<p class="text-text-secondary text-lg">Most products either overwhelm users with technical jargon or focus on only one layer of security.</p>
</div>
</div>
<div class="stat-card p-7 mt-6 reveal">
<p class="text-xl text-text-secondary">The core problem: people often ask, <span class="text-glow text-accent-1 font-semibold">“Is this safe, and what should I do next?”</span></p>
</div>
</div>
</div>
<div class="slide slide-3" data-slide="3">
<div class="gradient-mesh">
<div class="blob" style="width:380px;height:380px;top:-100px;left:-80px;background:#00ff41;opacity:0.08;"></div>
<div class="blob" style="width:260px;height:260px;bottom:-80px;right:-60px;background:#ff3b30;opacity:0.06;"></div>
</div>
<div class="content">
<div class="pill text-sm text-accent-1 inline-block mb-5 reveal">Proposed Solution</div>
<h2 class="font-display text-[clamp(2rem,4.3vw,3.2rem)] font-bold mb-6 reveal">A decision-first cybersecurity companion</h2>
<div class="grid grid-cols-2 gap-8 items-center mt-8">
<div class="reveal">
<p class="text-xl text-text-secondary leading-relaxed mb-5">NeuroVoid turns suspicious content and device signals into simple verdicts such as SAFE, LOW, MEDIUM, or HIGH risk.</p>
<p class="text-xl text-text-secondary leading-relaxed">Instead of just detecting threats, it explains the situation and guides the user toward the safest next action through an intelligent assistant.</p>
</div>
<div class="stat-card p-8 reveal">
<div class="text-6xl mb-4">🧠</div>
<ul class="space-y-4 text-lg text-text-secondary">
<li>AI analysis for text and screenshots.</li>
<li>Local device posture checks.</li>
<li>Neuro Bot for security guidance.</li>
<li>Fallback heuristics when AI is offline.</li>
</ul>
</div>
</div>
</div>
</div>
<div class="slide slide-4" data-slide="4">
<div class="gradient-mesh">
<div class="blob" style="width:300px;height:300px;top:-80px;right:-50px;background:#00ff41;opacity:0.08;"></div>
<div class="blob" style="width:240px;height:240px;bottom:-70px;left:-40px;background:#ffa500;opacity:0.07;"></div>
</div>
<div class="content">
<div class="pill text-sm text-accent-1 inline-block mb-5 reveal">Key Features</div>
<h2 class="font-display text-[clamp(2rem,4.3vw,3.2rem)] font-bold mb-8 reveal">What NeuroVoid plans to build</h2>
<div class="grid grid-cols-3 gap-6">
<div class="stat-card p-6 reveal"><div class="text-4xl mb-3">🔎</div><h3 class="text-xl font-semibold mb-2">Suspicious message analysis</h3><p class="text-text-secondary">Checks phishing emails, fake offers, scam requests, and risky links.</p></div>
<div class="stat-card p-6 reveal"><div class="text-4xl mb-3">🖼️</div><h3 class="text-xl font-semibold mb-2">Screenshot review</h3><p class="text-text-secondary">Uses vision-capable models to inspect screenshots and social engineering content.</p></div>
<div class="stat-card p-6 reveal"><div class="text-4xl mb-3">💻</div><h3 class="text-xl font-semibold mb-2">Device safety checks</h3><p class="text-text-secondary">Reviews firewall status, Gatekeeper, temp files, and optional malware scanning.</p></div>
<div class="stat-card p-6 reveal"><div class="text-4xl mb-3">🤖</div><h3 class="text-xl font-semibold mb-2">Neuro Bot</h3><p class="text-text-secondary">Provides focused answers about privacy, phishing, malware, and protection steps.</p></div>
<div class="stat-card p-6 reveal"><div class="text-4xl mb-3">📊</div><h3 class="text-xl font-semibold mb-2">Recent reports and history</h3><p class="text-text-secondary">Lets users view previous scans, findings, and risk decisions.</p></div>
<div class="stat-card p-6 reveal"><div class="text-4xl mb-3">🚨</div><h3 class="text-xl font-semibold mb-2">Live alerts</h3><p class="text-text-secondary">Pushes real-time warnings through WebSocket-based alert flows.</p></div>
</div>
</div>
</div>
<div class="slide slide-5" data-slide="5">
<div class="gradient-mesh">
<div class="blob" style="width:420px;height:420px;top:-120px;right:-70px;background:#00ff41;opacity:0.1;"></div>
<div class="blob" style="width:260px;height:260px;bottom:-70px;left:-40px;background:#ffa500;opacity:0.06;"></div>
</div>
<canvas class="particle-canvas-ambient" style="position:absolute;inset:0;z-index:1;"></canvas>
<div class="content">
<div class="pill text-sm text-accent-1 inline-block mb-5 reveal">How It Works</div>
<h2 class="font-display text-[clamp(2rem,4.3vw,3.2rem)] font-bold mb-8 reveal">Simple flow, resilient architecture</h2>
<div class="grid grid-cols-5 gap-4 mt-8">
<div class="stat-card p-5 reveal"><div class="text-sm uppercase tracking-[3px] text-accent-1 mb-2">01</div><p class="text-text-secondary">User submits text, screenshot, or a question.</p></div>
<div class="stat-card p-5 reveal"><div class="text-sm uppercase tracking-[3px] text-accent-1 mb-2">02</div><p class="text-text-secondary">Backend selects local AI or fallback heuristics.</p></div>
<div class="stat-card p-5 reveal"><div class="text-sm uppercase tracking-[3px] text-accent-1 mb-2">03</div><p class="text-text-secondary">System returns risk level, indicators, explanation, and action.</p></div>
<div class="stat-card p-5 reveal"><div class="text-sm uppercase tracking-[3px] text-accent-1 mb-2">04</div><p class="text-text-secondary">Frontend shows a decision-first result instead of raw telemetry.</p></div>
<div class="stat-card p-5 reveal"><div class="text-sm uppercase tracking-[3px] text-accent-1 mb-2">05</div><p class="text-text-secondary">Critical findings trigger device reports and live alerts.</p></div>
</div>
</div>
</div>
<div class="slide slide-6" data-slide="6">
<div class="gradient-mesh">
<div class="blob" style="width:360px;height:360px;top:-80px;left:-60px;background:#00ff41;opacity:0.08;"></div>
<div class="blob" style="width:260px;height:260px;bottom:-60px;right:-50px;background:#ff3b30;opacity:0.06;"></div>
</div>
<div class="content">
<div class="pill text-sm text-accent-1 inline-block mb-5 reveal">Tech Stack</div>
<h2 class="font-display text-[clamp(2rem,4.3vw,3.2rem)] font-bold mb-8 reveal">Core technologies behind the idea</h2>
<div class="grid grid-cols-2 gap-6">
<div class="stat-card p-7 reveal">
<h3 class="text-2xl font-semibold mb-4">Application Layer</h3>
<ul class="space-y-3 text-lg text-text-secondary">
<li>Frontend: HTML, CSS, modern JavaScript modules</li>
<li>Backend: Node.js with Express</li>
<li>Realtime layer: Socket.IO</li>
<li>HTTP integrations: Axios</li>
<li>Desktop direction: Vite + Tauri</li>
</ul>
</div>
<div class="stat-card p-7 reveal">
<h3 class="text-2xl font-semibold mb-4">Security + AI Layer</h3>
<ul class="space-y-3 text-lg text-text-secondary">
<li>AI engine: Ollama for local model execution</li>
<li>Text model path: llama-family local models</li>
<li>Vision path: compatible multimodal models</li>
<li>Fallback engine: heuristic risk analysis</li>
<li>Scanning: firewall, Gatekeeper, temp review, optional ClamAV</li>
</ul>
</div>
</div>
</div>
</div>
<div class="slide slide-7" data-slide="7">
<div class="gradient-mesh">
<div class="blob" style="width:370px;height:370px;top:-100px;right:-70px;background:#00ff41;opacity:0.09;"></div>
<div class="blob" style="width:280px;height:280px;bottom:-80px;left:-50px;background:#ffa500;opacity:0.07;"></div>
</div>
<div class="content">
<div class="pill text-sm text-accent-1 inline-block mb-5 reveal">Impact & Innovation</div>
<h2 class="font-display text-[clamp(2rem,4.3vw,3.2rem)] font-bold mb-8 reveal">Why this approach is different</h2>
<div class="grid grid-cols-3 gap-6">
<div class="stat-card p-7 reveal"><div class="text-5xl mb-4">⚡</div><h3 class="text-xl font-semibold mb-3">Decision-first UX</h3><p class="text-text-secondary">Users get a clear risk verdict first, then the explanation and remediation path.</p></div>
<div class="stat-card p-7 reveal"><div class="text-5xl mb-4">🔐</div><h3 class="text-xl font-semibold mb-3">Privacy-aware AI</h3><p class="text-text-secondary">Local AI reduces dependency on external vendors and supports a stronger privacy story.</p></div>
<div class="stat-card p-7 reveal"><div class="text-5xl mb-4">🧩</div><h3 class="text-xl font-semibold mb-3">Content + device security</h3><p class="text-text-secondary">Combines message analysis, screenshot review, device posture, and guided action in one product.</p></div>
</div>
<div class="stat-card p-7 mt-6 reveal">
<p class="text-xl text-text-secondary">NeuroVoid is not just a scanner or chatbot. It is a <span class="text-accent-1 font-semibold">cybersecurity decision system</span> designed for people who need confidence before they click.</p>
</div>
</div>
</div>
<div class="slide slide-8" data-slide="8">
<div class="gradient-mesh">
<div class="blob" style="width:460px;height:460px;top:-120px;left:-120px;background:#00ff41;opacity:0.12;"></div>
<div class="blob" style="width:320px;height:320px;bottom:-100px;right:-60px;background:#ffa500;opacity:0.10;"></div>
<div class="blob" style="width:220px;height:220px;top:35%;right:18%;background:#ff3b30;opacity:0.08;"></div>
</div>
<canvas class="particle-canvas" style="position:absolute;inset:0;z-index:1;"></canvas>
<div class="content text-center">
<div class="pill text-sm text-accent-1 inline-block mb-5 reveal">Closing</div>
<h2 class="font-display text-[clamp(2.4rem,5vw,4.2rem)] font-bold bg-linear-to-br from-accent-1 via-accent-2 to-accent-1 bg-clip-text text-transparent mb-5 reveal">Safer decisions, faster</h2>
<p class="max-w-4xl mx-auto text-2xl text-text-secondary leading-relaxed reveal">NeuroVoid helps students, professionals, families, and small teams understand digital risk, act with clarity, and stay protected without needing to be cybersecurity experts.</p>
<div class="mt-10 text-lg tracking-[5px] uppercase text-text-muted reveal">Hackaccino Phase 1 • Vision, strategy, and technical direction</div>
</div>
</div>
</div>
<div class="nav-controls" aria-label="Slide navigation">
<button class="nav-btn" onclick="changeSlide(-1)" aria-label="Previous slide">‹</button>
<div class="slide-dots" id="dots"></div>
<button class="nav-btn" onclick="changeSlide(1)" aria-label="Next slide">›</button>
<span class="slide-counter" id="counter">1 / 8</span>
</div>
<script>
let current = 1;
const total = document.querySelectorAll('.slide').length;
const dotsContainer = document.getElementById('dots');
const counter = document.getElementById('counter');
for (let i = 1; i <= total; i++) { const dot = document.createElement('div'); dot.className = 'dot' + (i === 1 ? ' active' : ''); dot.onclick = () => goToSlide(i); dotsContainer.appendChild(dot); }
function goToSlide(n) { const prev = document.querySelector('.slide.active'); const next = document.querySelector(`.slide[data-slide="${n}"]`); if (prev) prev.classList.remove('active'); if (next) { next.classList.add('active'); animateSlide(next); } current = n; updateNav(); }
function changeSlide(dir) { let next = current + dir; if (next < 1) next = total; if (next > total) next = 1; goToSlide(next); }
function updateNav() { document.querySelectorAll('.dot').forEach((d, i) => d.classList.toggle('active', i + 1 === current)); counter.textContent = current + ' / ' + total; }
document.addEventListener('keydown', (e) => { if (e.key === 'ArrowRight' || e.key === ' ') { e.preventDefault(); changeSlide(1); } if (e.key === 'ArrowLeft') { e.preventDefault(); changeSlide(-1); } });
let touchStartX = 0;
document.addEventListener('touchstart', (e) => { touchStartX = e.touches[0].clientX; });
document.addEventListener('touchend', (e) => { const diff = touchStartX - e.changedTouches[0].clientX; if (Math.abs(diff) > 50) changeSlide(diff > 0 ? 1 : -1); });
function animateSlide(slide) {
slide.querySelectorAll('.reveal').forEach((el, i) => {
el.style.transition = 'none'; el.style.opacity = '0'; el.style.transform = 'translateY(20px)'; el.offsetHeight;
const delay = i * 0.08;
el.style.transition = `opacity 0.35s ease ${delay}s, transform 0.35s ease ${delay}s`;
el.style.opacity = '1'; el.style.transform = 'translateY(0px)';
});
}
document.addEventListener('mousemove', (e) => {
const spotlight = document.querySelector('.mouse-spotlight');
if (spotlight) spotlight.style.background = `radial-gradient(600px circle at ${e.clientX}px ${e.clientY}px, rgba(0,255,65,0.06), transparent 40%)`;
});
window.initParticles = function(canvas, options) {
if (!canvas) return;
const ctx = canvas.getContext('2d');
canvas.width = canvas.offsetWidth; canvas.height = canvas.offsetHeight;
const interactive = options.interactive !== false;
const count = options.count || (interactive ? 55 : 18);
let mx = -1000, my = -1000;
const particles = Array.from({ length: count }, () => ({ x: Math.random()*canvas.width, y: Math.random()*canvas.height, vx:(Math.random()-0.5)*0.3, vy:(Math.random()-0.5)*0.3, size:Math.random()*2.5+0.8, alpha:Math.random()*0.35+0.1 }));
if (interactive) {
canvas.addEventListener('mousemove', (e) => { const rect = canvas.getBoundingClientRect(); mx = e.clientX - rect.left; my = e.clientY - rect.top; });
canvas.addEventListener('mouseleave', () => { mx = -1000; my = -1000; });
}
(function animate() {
ctx.clearRect(0,0,canvas.width,canvas.height);
particles.forEach(p => {
if (interactive) {
const dx = p.x - mx, dy = p.y - my, dist = Math.sqrt(dx*dx + dy*dy) || 1;
if (dist < 120) { const force = (120 - dist) / 120 * 2; p.vx += (dx / dist) * force * 0.1; p.vy += (dy / dist) * force * 0.1; }
}
p.vx *= 0.98; p.vy *= 0.98; p.x += p.vx; p.y += p.vy;
if (p.x < 0) p.x = canvas.width; if (p.x > canvas.width) p.x = 0;
if (p.y < 0) p.y = canvas.height; if (p.y > canvas.height) p.y = 0;
ctx.beginPath(); ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2); ctx.fillStyle = `rgba(0,255,65,${p.alpha})`; ctx.fill();
});
requestAnimationFrame(animate);
})();
};
document.querySelectorAll('.particle-canvas').forEach(c => window.initParticles(c, { interactive: true, count: 55 }));
document.querySelectorAll('.particle-canvas-ambient').forEach(c => window.initParticles(c, { interactive: false, count: 18 }));
try { animateSlide(document.querySelector('.slide.active')); } catch(e) {}
</script>
</body>
</html>