/* =================================================== JAESWIFT.XYZ — Sitewide Visual Effects Suite 27 effects (25 new + matrix + cmatrix migration) Exposed as window.__jaeEffects Each effect: { enable(), disable(), active: bool } =================================================== */ (function () { 'use strict'; // ─── Environment gates ───────────────────────── const reducedMotion = () => window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches; const isMobile = () => window.matchMedia && window.matchMedia('(max-width: 640px)').matches; const shouldDowngrade = () => reducedMotion() || isMobile(); // ─── Shared audio context (created on demand) ───────── let _audioCtx = null; function getAudio() { if (!_audioCtx) { try { const AC = window.AudioContext || window.webkitAudioContext; if (AC) _audioCtx = new AC(); } catch (e) {} } if (_audioCtx && _audioCtx.state === 'suspended') { try { _audioCtx.resume(); } catch (e) {} } return _audioCtx; } // ─── Helpers ────────────────────────────────────── function makeFullCanvas(z, opacity) { const c = document.createElement('canvas'); Object.assign(c.style, { position: 'fixed', inset: '0', width: '100%', height: '100%', pointerEvents: 'none', zIndex: String(z || 9100), opacity: String(opacity != null ? opacity : 1), }); function resize() { c.width = window.innerWidth; c.height = window.innerHeight; } resize(); c._resize = resize; window.addEventListener('resize', resize); document.body.appendChild(c); return c; } function destroyCanvas(c) { if (!c) return; if (c._resize) window.removeEventListener('resize', c._resize); c.remove(); } function injectStyle(id, css) { if (document.getElementById(id)) return; const s = document.createElement('style'); s.id = id; s.textContent = css; document.head.appendChild(s); } function ejectStyle(id) { const s = document.getElementById(id); if (s) s.remove(); } function walkText(root, skipSelector) { // Return array of text nodes in visible elements (skipping nav/inputs/scripts) const skip = /^(SCRIPT|STYLE|NOSCRIPT|NAV|INPUT|TEXTAREA|CODE|PRE|CANVAS|SVG|IFRAME|BUTTON)$/i; const out = []; const w = document.createTreeWalker(root || document.body, NodeFilter.SHOW_TEXT, { acceptNode: (n) => { if (!n.parentElement) return NodeFilter.FILTER_REJECT; let p = n.parentElement; while (p && p !== document.body) { if (skip.test(p.tagName)) return NodeFilter.FILTER_REJECT; if (p.classList && (p.classList.contains('chat-messages') || p.classList.contains('chat-msg') || p.id === 'chatMessages' || p.id === 'chatInput')) return NodeFilter.FILTER_REJECT; p = p.parentElement; } if (skipSelector && n.parentElement.closest(skipSelector)) return NodeFilter.FILTER_REJECT; if (!/\S/.test(n.nodeValue)) return NodeFilter.FILTER_REJECT; return NodeFilter.FILTER_ACCEPT; } }); let node; while ((node = w.nextNode())) out.push(node); return out; } function snapshotRect(el) { const r = el.getBoundingClientRect(); return { left: r.left, top: r.top, width: r.width, height: r.height }; } // ================================================== // EFFECT REGISTRY // ================================================== const R = {}; // --- MATRIX (migrated) --- R.matrix = (function () { let canvas = null, raf = null; return { active: false, enable() { if (this.active) return; this.active = true; canvas = makeFullCanvas(9050, 0.18); const ctx = canvas.getContext('2d'); const chars = 'アイウエオカキクケコサシスセソタチツテトナニヌネノ01JAESWIFT'.split(''); const size = 16; let cols = Math.floor(canvas.width / size); let drops = new Array(cols).fill(1); const onResize = () => { cols = Math.floor(canvas.width / size); drops = new Array(cols).fill(1); }; window.addEventListener('resize', onResize); canvas._onResize2 = onResize; function draw() { ctx.fillStyle = 'rgba(0,0,0,0.06)'; ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.fillStyle = '#00cc33'; ctx.font = size + 'px JetBrains Mono, monospace'; for (let i = 0; i < drops.length; i++) { const ch = chars[Math.floor(Math.random() * chars.length)]; ctx.fillText(ch, i * size, drops[i] * size); if (drops[i] * size > canvas.height && Math.random() > 0.975) drops[i] = 0; drops[i]++; } raf = requestAnimationFrame(draw); } draw(); }, disable() { if (!this.active) return; this.active = false; if (raf) cancelAnimationFrame(raf); if (canvas && canvas._onResize2) window.removeEventListener('resize', canvas._onResize2); destroyCanvas(canvas); canvas = null; raf = null; } }; })(); // --- CMATRIX (migrated, enhanced) --- R.cmatrix = (function () { let canvas = null, raf = null, audio = null, start = 0; return { active: false, enable() { if (this.active) return; this.active = true; canvas = makeFullCanvas(9060, 0.32); const ctx = canvas.getContext('2d'); const chars = 'アイウエオカキクケコサシスセソタチツテトナニヌネノ01JAESWIFT'.split(''); const size = 16; let cols = Math.floor(canvas.width / size); let drops = new Array(cols).fill(1); const onResize = () => { cols = Math.floor(canvas.width / size); drops = new Array(cols).fill(1); }; window.addEventListener('resize', onResize); canvas._onResize2 = onResize; start = Date.now(); audio = getAudio(); let tick = 0; function draw() { const t = (Date.now() - start) / 1000; const phase = Math.min(1, t / 30); const speed = 1 + phase * 2.5; ctx.fillStyle = 'rgba(0,0,0,0.07)'; ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.font = size + 'px JetBrains Mono, monospace'; for (let i = 0; i < drops.length; i++) { const ch = chars[Math.floor(Math.random() * chars.length)]; ctx.fillStyle = (i % 7 === 0) ? '#33ddff' : '#00ff66'; ctx.fillText(ch, i * size, drops[i] * size); if (drops[i] * size > canvas.height && Math.random() > 0.97) drops[i] = 0; drops[i] += speed; } if (audio && tick % 4 === 0) { try { const osc = audio.createOscillator(); const g = audio.createGain(); osc.type = 'square'; osc.frequency.value = 1600 + Math.random() * 800; g.gain.value = 0.0035; osc.connect(g); g.connect(audio.destination); osc.start(); osc.stop(audio.currentTime + 0.02); } catch (e) {} } tick++; raf = requestAnimationFrame(draw); } draw(); }, disable() { if (!this.active) return; this.active = false; if (raf) cancelAnimationFrame(raf); if (canvas && canvas._onResize2) window.removeEventListener('resize', canvas._onResize2); destroyCanvas(canvas); canvas = null; raf = null; audio = null; } }; })(); // --- 1. CRT --- R.crt = { active: false, enable() { if (this.active) return; this.active = true; document.documentElement.classList.add('fx-crt'); const overlay = document.createElement('div'); overlay.className = 'fx-crt-overlay'; overlay.id = 'fx-crt-overlay'; document.body.appendChild(overlay); }, disable() { if (!this.active) return; this.active = false; document.documentElement.classList.remove('fx-crt'); const o = document.getElementById('fx-crt-overlay'); if (o) o.remove(); } }; // --- 2. VHS --- R.vhs = (function () { let noiseCanvas = null, noiseRaf = null, glitchInterval = null; return { active: false, enable() { if (this.active) return; this.active = true; document.documentElement.classList.add('fx-vhs'); const rollBar = document.createElement('div'); rollBar.className = 'fx-vhs-roll'; rollBar.id = 'fx-vhs-roll'; document.body.appendChild(rollBar); noiseCanvas = makeFullCanvas(9200, 0.12); const ctx = noiseCanvas.getContext('2d'); function noise() { const w = noiseCanvas.width, h = noiseCanvas.height; const img = ctx.createImageData(w, h); for (let i = 0; i < img.data.length; i += 4) { const v = Math.random() * 255 | 0; img.data[i] = v; img.data[i + 1] = v; img.data[i + 2] = v; img.data[i + 3] = 60; } ctx.putImageData(img, 0, 0); noiseRaf = setTimeout(() => requestAnimationFrame(noise), 80); } if (!shouldDowngrade()) noise(); glitchInterval = setInterval(() => { const b = document.createElement('div'); b.className = 'fx-vhs-glitch-block'; b.style.top = Math.random() * 100 + '%'; b.style.height = (4 + Math.random() * 14) + 'px'; document.body.appendChild(b); setTimeout(() => b.remove(), 80); }, 3000 + Math.random() * 2000); }, disable() { if (!this.active) return; this.active = false; document.documentElement.classList.remove('fx-vhs'); const r = document.getElementById('fx-vhs-roll'); if (r) r.remove(); if (noiseRaf) clearTimeout(noiseRaf); destroyCanvas(noiseCanvas); noiseCanvas = null; if (glitchInterval) clearInterval(glitchInterval); glitchInterval = null; document.querySelectorAll('.fx-vhs-glitch-block').forEach(e => e.remove()); } }; })(); // --- 3. GLITCH --- R.glitch = (function () { let scrambleInterval = null; const origValues = new WeakMap(); return { active: false, enable() { if (this.active) return; this.active = true; document.documentElement.classList.add('fx-glitch'); if (shouldDowngrade()) return; scrambleInterval = setInterval(() => { const nodes = walkText(); if (!nodes.length) return; const picks = []; for (let i = 0; i < 3; i++) picks.push(nodes[Math.floor(Math.random() * nodes.length)]); picks.forEach(n => { if (!n || !n.nodeValue || n.nodeValue.length < 3) return; if (!origValues.has(n)) origValues.set(n, n.nodeValue); const orig = origValues.get(n); const arr = orig.split(''); const idx = Math.floor(Math.random() * (arr.length - 1)); const tmp = arr[idx]; arr[idx] = arr[idx + 1]; arr[idx + 1] = tmp; n.nodeValue = arr.join(''); setTimeout(() => { try { n.nodeValue = orig; } catch (e) {} }, 80); }); }, 2000); }, disable() { if (!this.active) return; this.active = false; document.documentElement.classList.remove('fx-glitch'); if (scrambleInterval) clearInterval(scrambleInterval); scrambleInterval = null; } }; })(); // --- 4. RED ALERT --- R.redalert = (function () { let banner = null, oscA = null, gain = null, toggle = null, audio = null; return { active: false, enable() { if (this.active) return; this.active = true; document.documentElement.classList.add('fx-redalert'); banner = document.createElement('div'); banner.id = 'fx-redalert-banner'; banner.className = 'fx-redalert-banner'; banner.textContent = '⚠ DEFCON 1 — RED ALERT ⚠'; document.body.appendChild(banner); audio = getAudio(); if (audio && !shouldDowngrade()) { try { oscA = audio.createOscillator(); gain = audio.createGain(); gain.gain.value = 0.03; oscA.type = 'sine'; oscA.frequency.value = 400; oscA.connect(gain); gain.connect(audio.destination); oscA.start(); let hi = false; toggle = setInterval(() => { hi = !hi; try { oscA.frequency.setValueAtTime(hi ? 800 : 400, audio.currentTime); } catch (e) {} }, 500); } catch (e) {} } }, disable() { if (!this.active) return; this.active = false; document.documentElement.classList.remove('fx-redalert'); if (banner) banner.remove(); banner = null; if (toggle) clearInterval(toggle); toggle = null; if (oscA) { try { oscA.stop(); } catch (e) {} oscA = null; } gain = null; } }; })(); // --- 5. INVERT --- R.invert = { active: false, enable() { if (this.active) return; this.active = true; document.documentElement.classList.add('fx-invert'); }, disable() { if (!this.active) return; this.active = false; document.documentElement.classList.remove('fx-invert'); } }; // --- 6. BLUEPRINT --- R.blueprint = { active: false, enable() { if (this.active) return; this.active = true; document.documentElement.classList.add('fx-blueprint'); const g = document.createElement('div'); g.id = 'fx-blueprint-grid'; g.className = 'fx-blueprint-grid'; document.body.appendChild(g); }, disable() { if (!this.active) return; this.active = false; document.documentElement.classList.remove('fx-blueprint'); const g = document.getElementById('fx-blueprint-grid'); if (g) g.remove(); } }; // --- 7. TYPEWRITER --- R.typewriter = (function () { const wrapped = []; let running = false; return { active: false, enable() { if (this.active) return; this.active = true; if (shouldDowngrade()) return; const nodes = walkText(); const audio = getAudio(); nodes.forEach(n => { const text = n.nodeValue; if (text.length < 2) return; const span = document.createElement('span'); span.className = 'fx-typewriter-span'; n.parentNode.replaceChild(span, n); wrapped.push({ span, text, parent: span.parentNode }); span.textContent = ''; }); running = true; let idx = 0; const self = this; function typeNext() { if (!running || idx >= wrapped.length) return; const { span, text } = wrapped[idx]; let i = 0; const interval = setInterval(() => { if (!running) { clearInterval(interval); return; } if (i >= text.length) { clearInterval(interval); idx++; setTimeout(typeNext, 40); return; } span.textContent += text[i]; if (audio && i % 5 === 0) { try { const osc = audio.createOscillator(); const g = audio.createGain(); osc.frequency.value = 1200; g.gain.value = 0.004; osc.connect(g); g.connect(audio.destination); osc.start(); osc.stop(audio.currentTime + 0.01); } catch (e) {} } i++; }, 30); } typeNext(); }, disable() { if (!this.active) return; this.active = false; running = false; wrapped.forEach(({ span, text }) => { if (span.parentNode) { const tn = document.createTextNode(text); span.parentNode.replaceChild(tn, span); } }); wrapped.length = 0; } }; })(); // --- 8. GRAVITY --- R.gravity = (function () { let items = [], raf = null; return { active: false, enable() { if (this.active) return; this.active = true; const selectors = '.panel, .card, h1, h2, h3'; const els = Array.from(document.querySelectorAll(selectors)).slice(0, 40); items = els.map(el => { const r = snapshotRect(el); const data = { el, origStyle: el.getAttribute('style') || '', x: r.left, y: r.top, w: r.width, h: r.height, vx: (Math.random() - 0.5) * 3, vy: -Math.random() * 4, }; el.style.position = 'fixed'; el.style.left = r.left + 'px'; el.style.top = r.top + 'px'; el.style.width = r.width + 'px'; el.style.margin = '0'; el.style.zIndex = '8000'; return data; }); function step() { const floor = window.innerHeight; items.forEach(it => { it.vy += 0.6; it.x += it.vx; it.y += it.vy; if (it.y + it.h >= floor) { it.y = floor - it.h; it.vy *= -0.3; it.vx *= 0.8; if (Math.abs(it.vy) < 0.5) it.vy = 0; } if (it.x < 0) { it.x = 0; it.vx *= -0.5; } if (it.x + it.w > window.innerWidth) { it.x = window.innerWidth - it.w; it.vx *= -0.5; } it.el.style.left = it.x + 'px'; it.el.style.top = it.y + 'px'; }); raf = requestAnimationFrame(step); } step(); }, disable() { if (!this.active) return; this.active = false; if (raf) cancelAnimationFrame(raf); raf = null; items.forEach(it => { if (it.origStyle) it.el.setAttribute('style', it.origStyle); else it.el.removeAttribute('style'); }); items = []; } }; })(); // --- 9. EARTHQUAKE --- R.earthquake = (function () { let interval = null, stopTimer = null; return { active: false, enable() { if (this.active) return; this.active = true; const self = this; interval = setInterval(() => { const x = (Math.random() - 0.5) * 20; const y = (Math.random() - 0.5) * 20; document.body.style.transform = `translate(${x}px, ${y}px)`; }, 50); stopTimer = setTimeout(() => self.disable(), 10000); }, disable() { if (!this.active) return; this.active = false; if (interval) clearInterval(interval); interval = null; if (stopTimer) clearTimeout(stopTimer); stopTimer = null; document.body.style.transform = ''; } }; })(); // --- 10. LOW GRAVITY --- R.lowgravity = { active: false, enable() { if (this.active) return; this.active = true; document.documentElement.classList.add('fx-lowgrav'); document.querySelectorAll('.panel, .card').forEach((el, i) => { el.style.animationDelay = (Math.random() * 4) + 's'; el.classList.add('fx-lowgrav-bob'); }); }, disable() { if (!this.active) return; this.active = false; document.documentElement.classList.remove('fx-lowgrav'); document.querySelectorAll('.fx-lowgrav-bob').forEach(el => { el.classList.remove('fx-lowgrav-bob'); el.style.animationDelay = ''; }); } }; // --- 11. MELT --- R.melt = (function () { let items = [], raf = null, t0 = 0; return { active: false, enable() { if (this.active) return; this.active = true; const els = Array.from(document.querySelectorAll('p, h1, h2, h3, h4, li, span, a')).filter(el => el.offsetParent !== null).slice(0, 200); items = els.map(el => ({ el, origTransform: el.style.transform || '', drop: window.innerHeight - el.getBoundingClientRect().top - 20 + Math.random() * 60, jitter: (Math.random() - 0.5) * 10 })); t0 = performance.now(); const self = this; function step(t) { const elapsed = (t - t0) / 15000; // 15s to fully melt const p = Math.min(1, elapsed); items.forEach(it => { const y = it.drop * easeInCubic(p); it.el.style.transform = `translate(${it.jitter * p}px, ${y}px)`; it.el.style.transition = 'transform 0.1s linear'; }); if (p < 1 && self.active) raf = requestAnimationFrame(step); } function easeInCubic(x) { return x * x * x; } step(t0); }, disable() { if (!this.active) return; this.active = false; if (raf) cancelAnimationFrame(raf); raf = null; items.forEach(it => { it.el.style.transform = it.origTransform; it.el.style.transition = ''; }); items = []; } }; })(); // --- 12. SHUFFLE --- R.shuffle = (function () { const saved = []; return { active: false, enable() { if (this.active) return; this.active = true; const nodes = walkText(); nodes.forEach(n => { const text = n.nodeValue; if (!/\s/.test(text)) return; saved.push({ node: n, orig: text }); const words = text.split(/(\s+)/); const content = words.filter(w => /\S/.test(w)); for (let i = content.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [content[i], content[j]] = [content[j], content[i]]; } let ci = 0; const shuffled = words.map(w => /\S/.test(w) ? content[ci++] : w).join(''); n.nodeValue = shuffled; }); }, disable() { if (!this.active) return; this.active = false; saved.forEach(({ node, orig }) => { try { node.nodeValue = orig; } catch (e) {} }); saved.length = 0; } }; })(); // --- 13. RAIN --- R.rain = (function () { let canvas = null, raf = null, drops = [], thunder = null, audio = null, noiseNode = null; return { active: false, enable() { if (this.active) return; this.active = true; canvas = makeFullCanvas(9100, 0.55); const ctx = canvas.getContext('2d'); const count = shouldDowngrade() ? 60 : 200; drops = []; for (let i = 0; i < count; i++) { drops.push({ x: Math.random() * canvas.width, y: Math.random() * canvas.height, len: 8 + Math.random() * 12, spd: 10 + Math.random() * 8 }); } function draw() { ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.strokeStyle = 'rgba(180,220,255,0.55)'; ctx.lineWidth = 1; drops.forEach(d => { ctx.beginPath(); ctx.moveTo(d.x, d.y); ctx.lineTo(d.x - 2, d.y + d.len); ctx.stroke(); d.y += d.spd; if (d.y > canvas.height) { d.y = -d.len; d.x = Math.random() * canvas.width; } }); raf = requestAnimationFrame(draw); } draw(); // thunder flicker function flash() { document.documentElement.classList.add('fx-rain-flash'); setTimeout(() => document.documentElement.classList.remove('fx-rain-flash'), 80); thunder = setTimeout(flash, 15000 + Math.random() * 15000); } thunder = setTimeout(flash, 15000); // ambient noise audio = getAudio(); if (audio && !shouldDowngrade()) { try { const bufferSize = 2 * audio.sampleRate; const buffer = audio.createBuffer(1, bufferSize, audio.sampleRate); const data = buffer.getChannelData(0); let lastOut = 0; for (let i = 0; i < bufferSize; i++) { const white = Math.random() * 2 - 1; data[i] = (lastOut + (0.02 * white)) / 1.02; lastOut = data[i]; data[i] *= 3.5; } noiseNode = audio.createBufferSource(); noiseNode.buffer = buffer; noiseNode.loop = true; const filter = audio.createBiquadFilter(); filter.type = 'highpass'; filter.frequency.value = 800; const g = audio.createGain(); g.gain.value = 0.04; noiseNode.connect(filter); filter.connect(g); g.connect(audio.destination); noiseNode.start(); } catch (e) {} } }, disable() { if (!this.active) return; this.active = false; if (raf) cancelAnimationFrame(raf); raf = null; if (thunder) clearTimeout(thunder); thunder = null; destroyCanvas(canvas); canvas = null; if (noiseNode) { try { noiseNode.stop(); } catch (e) {} noiseNode = null; } document.documentElement.classList.remove('fx-rain-flash'); } }; })(); // --- 14. SNOW --- R.snow = (function () { let canvas = null, raf = null, flakes = []; return { active: false, enable() { if (this.active) return; this.active = true; canvas = makeFullCanvas(9100, 0.75); const ctx = canvas.getContext('2d'); const count = shouldDowngrade() ? 50 : 150; flakes = []; for (let i = 0; i < count; i++) { flakes.push({ x: Math.random() * canvas.width, y: Math.random() * canvas.height, r: 1 + Math.random() * 3, vy: 0.5 + Math.random() * 1.5, phase: Math.random() * Math.PI * 2 }); } function draw() { ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.fillStyle = 'rgba(255,255,255,0.85)'; flakes.forEach(f => { f.phase += 0.02; f.y += f.vy; const x = f.x + Math.sin(f.phase) * 12; ctx.beginPath(); ctx.arc(x, f.y, f.r, 0, Math.PI * 2); ctx.fill(); if (f.y > canvas.height) { f.y = -5; f.x = Math.random() * canvas.width; } }); raf = requestAnimationFrame(draw); } draw(); }, disable() { if (!this.active) return; this.active = false; if (raf) cancelAnimationFrame(raf); raf = null; destroyCanvas(canvas); canvas = null; } }; })(); // --- 15. FOG --- R.fog = (function () { let overlay = null, onMove = null; return { active: false, enable() { if (this.active) return; this.active = true; overlay = document.createElement('div'); overlay.id = 'fx-fog'; overlay.className = 'fx-fog'; document.body.appendChild(overlay); onMove = (e) => { overlay.style.setProperty('--fx-fog-x', e.clientX + 'px'); overlay.style.setProperty('--fx-fog-y', e.clientY + 'px'); }; window.addEventListener('mousemove', onMove); }, disable() { if (!this.active) return; this.active = false; if (onMove) window.removeEventListener('mousemove', onMove); onMove = null; if (overlay) overlay.remove(); overlay = null; } }; })(); // --- 16. NIGHT --- R.night = (function () { let overlay = null, onMove = null; return { active: false, enable() { if (this.active) return; this.active = true; document.documentElement.classList.add('fx-night'); overlay = document.createElement('div'); overlay.id = 'fx-night-spot'; overlay.className = 'fx-night-spot'; document.body.appendChild(overlay); onMove = (e) => { overlay.style.setProperty('--fx-spot-x', e.clientX + 'px'); overlay.style.setProperty('--fx-spot-y', e.clientY + 'px'); }; window.addEventListener('mousemove', onMove); }, disable() { if (!this.active) return; this.active = false; document.documentElement.classList.remove('fx-night'); if (onMove) window.removeEventListener('mousemove', onMove); onMove = null; if (overlay) overlay.remove(); overlay = null; } }; })(); // --- 17. UNDERWATER --- R.underwater = (function () { let canvas = null, raf = null, bubbles = [], audio = null, noiseNode = null; return { active: false, enable() { if (this.active) return; this.active = true; document.documentElement.classList.add('fx-underwater'); canvas = makeFullCanvas(9100, 0.6); const ctx = canvas.getContext('2d'); const count = shouldDowngrade() ? 15 : 30; bubbles = []; for (let i = 0; i < count; i++) { bubbles.push({ x: Math.random() * canvas.width, y: canvas.height + Math.random() * canvas.height, r: 3 + Math.random() * 8, vy: 0.5 + Math.random() * 1.2, phase: Math.random() * Math.PI * 2 }); } let t = 0; function draw() { t += 0.02; ctx.clearRect(0, 0, canvas.width, canvas.height); // wave overlay ctx.fillStyle = 'rgba(80,140,200,0.08)'; for (let y = 0; y < canvas.height; y += 30) { const off = Math.sin(t + y * 0.02) * 10; ctx.fillRect(off, y, canvas.width, 15); } // bubbles ctx.strokeStyle = 'rgba(200,230,255,0.8)'; ctx.lineWidth = 1; bubbles.forEach(b => { b.phase += 0.05; b.y -= b.vy; const x = b.x + Math.sin(b.phase) * 8; ctx.beginPath(); ctx.arc(x, b.y, b.r, 0, Math.PI * 2); ctx.stroke(); if (b.y + b.r < 0) { b.y = canvas.height + 10; b.x = Math.random() * canvas.width; } }); raf = requestAnimationFrame(draw); } draw(); audio = getAudio(); if (audio && !shouldDowngrade()) { try { const bufferSize = 2 * audio.sampleRate; const buffer = audio.createBuffer(1, bufferSize, audio.sampleRate); const data = buffer.getChannelData(0); for (let i = 0; i < bufferSize; i++) data[i] = (Math.random() * 2 - 1) * 0.5; noiseNode = audio.createBufferSource(); noiseNode.buffer = buffer; noiseNode.loop = true; const filter = audio.createBiquadFilter(); filter.type = 'lowpass'; filter.frequency.value = 400; const g = audio.createGain(); g.gain.value = 0.03; noiseNode.connect(filter); filter.connect(g); g.connect(audio.destination); noiseNode.start(); } catch (e) {} } }, disable() { if (!this.active) return; this.active = false; document.documentElement.classList.remove('fx-underwater'); if (raf) cancelAnimationFrame(raf); raf = null; destroyCanvas(canvas); canvas = null; if (noiseNode) { try { noiseNode.stop(); } catch (e) {} noiseNode = null; } } }; })(); // --- 18. DIMENSIONS --- R.dimensions = (function () { let onMove = null; return { active: false, enable() { if (this.active) return; this.active = true; document.documentElement.classList.add('fx-dimensions'); onMove = (e) => { const rx = ((e.clientY / window.innerHeight) - 0.5) * -10; const ry = ((e.clientX / window.innerWidth) - 0.5) * 10; document.body.style.setProperty('--fx-tilt-x', rx + 'deg'); document.body.style.setProperty('--fx-tilt-y', ry + 'deg'); }; window.addEventListener('mousemove', onMove); }, disable() { if (!this.active) return; this.active = false; document.documentElement.classList.remove('fx-dimensions'); if (onMove) window.removeEventListener('mousemove', onMove); onMove = null; document.body.style.removeProperty('--fx-tilt-x'); document.body.style.removeProperty('--fx-tilt-y'); } }; })(); // --- 19. PORTAL --- R.portal = (function () { let portal = null, onMove = null; return { active: false, enable() { if (this.active) return; this.active = true; portal = document.createElement('div'); portal.id = 'fx-portal'; portal.className = 'fx-portal'; const targets = ['/hq/telemetry', '/depot/contraband', '/recon', '/armoury/lab', '/transmissions/radar', '/hq/leaderboards']; const pick = targets[Math.floor(Math.random() * targets.length)]; portal.innerHTML = ''; document.body.appendChild(portal); onMove = (e) => { portal.style.left = (e.clientX - 75) + 'px'; portal.style.top = (e.clientY - 75) + 'px'; const iframe = portal.querySelector('iframe'); if (iframe) { const tx = -((e.clientX / window.innerWidth) * 1000) + 400; const ty = -((e.clientY / window.innerHeight) * 800) + 300; iframe.style.transform = `translate(${tx}px, ${ty}px)`; } }; window.addEventListener('mousemove', onMove); }, disable() { if (!this.active) return; this.active = false; if (onMove) window.removeEventListener('mousemove', onMove); onMove = null; if (portal) portal.remove(); portal = null; } }; })(); // --- 20. RETRO --- R.retro = (function () { let currentTheme = null, banner = null; function clearAll() { ['retro-1995', 'retro-2005', 'retro-2015'].forEach(c => document.documentElement.classList.remove(c)); if (banner) { banner.remove(); banner = null; } } return { active: false, currentArg: null, enable(arg) { const year = (arg || 'now').toLowerCase(); clearAll(); this.currentArg = year; if (year === '1995') { document.documentElement.classList.add('retro-1995'); banner = document.createElement('div'); banner.className = 'fx-retro-1995-banner'; banner.innerHTML = '🚧 UNDER CONSTRUCTION 🚧   VISITORS: 000' + (1000 + Math.floor(Math.random() * 9000)) + '   BEST VIEWED IN NETSCAPE'; document.body.appendChild(banner); this.active = true; } else if (year === '2005') { document.documentElement.classList.add('retro-2005'); this.active = true; } else if (year === '2015') { document.documentElement.classList.add('retro-2015'); this.active = true; } else { this.active = false; } }, disable() { this.active = false; this.currentArg = null; clearAll(); } }; })(); // --- 21. PARTY MODE --- R.partymode = (function () { let canvas = null, raf = null, audio = null, confettiTimer = null, flashTimer = null, particles = [], kickInterval = null; const palette = ['#ff3366', '#33ffcc', '#ffcc33', '#cc33ff', '#66ff33', '#3366ff']; return { active: false, enable() { if (this.active) return; this.active = true; document.documentElement.classList.add('fx-party'); canvas = makeFullCanvas(9300, 0.85); const ctx = canvas.getContext('2d'); function spawn() { if (shouldDowngrade()) return; for (let i = 0; i < 30; i++) { particles.push({ x: Math.random() * canvas.width, y: -10, vx: (Math.random() - 0.5) * 4, vy: 1 + Math.random() * 4, size: 3 + Math.random() * 5, color: palette[Math.floor(Math.random() * palette.length)], rot: Math.random() * Math.PI * 2, vr: (Math.random() - 0.5) * 0.2, }); } } spawn(); confettiTimer = setInterval(spawn, 3000); function draw() { ctx.clearRect(0, 0, canvas.width, canvas.height); particles.forEach(p => { p.vy += 0.05; p.x += p.vx; p.y += p.vy; p.rot += p.vr; ctx.save(); ctx.translate(p.x, p.y); ctx.rotate(p.rot); ctx.fillStyle = p.color; ctx.fillRect(-p.size / 2, -p.size / 2, p.size, p.size); ctx.restore(); }); particles = particles.filter(p => p.y < canvas.height + 20); raf = requestAnimationFrame(draw); } draw(); flashTimer = setInterval(() => { const panels = document.querySelectorAll('.panel'); if (panels.length) { const el = panels[Math.floor(Math.random() * panels.length)]; const c = palette[Math.floor(Math.random() * palette.length)]; const orig = el.style.backgroundColor; el.style.transition = 'background-color 0.2s'; el.style.backgroundColor = c; setTimeout(() => { el.style.backgroundColor = orig; }, 200); } }, 500); audio = getAudio(); if (audio && !shouldDowngrade()) { kickInterval = setInterval(() => { try { const osc = audio.createOscillator(); const g = audio.createGain(); osc.frequency.setValueAtTime(120, audio.currentTime); osc.frequency.exponentialRampToValueAtTime(40, audio.currentTime + 0.15); g.gain.setValueAtTime(0.15, audio.currentTime); g.gain.exponentialRampToValueAtTime(0.001, audio.currentTime + 0.15); osc.connect(g); g.connect(audio.destination); osc.start(); osc.stop(audio.currentTime + 0.15); } catch (e) {} }, 500); } }, disable() { if (!this.active) return; this.active = false; document.documentElement.classList.remove('fx-party'); if (raf) cancelAnimationFrame(raf); raf = null; if (confettiTimer) clearInterval(confettiTimer); confettiTimer = null; if (flashTimer) clearInterval(flashTimer); flashTimer = null; if (kickInterval) clearInterval(kickInterval); kickInterval = null; destroyCanvas(canvas); canvas = null; particles = []; } }; })(); // --- 22. GHOST MODE --- R.ghostmode = { active: false, enable() { if (this.active) return; this.active = true; document.documentElement.classList.add('fx-ghost'); }, disable() { if (!this.active) return; this.active = false; document.documentElement.classList.remove('fx-ghost'); } }; // --- 23. QUANTUM --- R.quantum = (function () { let timer = null, originals = []; return { active: false, enable() { if (this.active) return; this.active = true; const panels = document.querySelectorAll('.panel'); panels.forEach(p => { originals.push({ el: p, transform: p.style.transform, transition: p.style.transition }); p.style.transition = 'transform 0.5s ease'; }); timer = setInterval(() => { panels.forEach(p => { const x = (Math.random() - 0.5) * 60; const y = (Math.random() - 0.5) * 60; p.style.transform = `translate(${x}vw, ${y}vh)`; }); }, 3000); }, disable() { if (!this.active) return; this.active = false; if (timer) clearInterval(timer); timer = null; originals.forEach(o => { o.el.style.transform = o.transform; o.el.style.transition = o.transition; }); originals = []; } }; })(); // --- 24. SNEAK --- R.sneak = (function () { const SNEAKY = ['CLASSIFIED', 'REDACTED', 'ACCESS GRANTED', 'DO NOT CLICK', 'FREE MONEY', 'TOP SECRET', '█████', 'COMPROMISED', 'SUSPECT', 'EYES ONLY', 'TRAP', 'HONEYPOT']; const saved = []; return { active: false, enable() { if (this.active) return; this.active = true; document.querySelectorAll('a, button').forEach(el => { if (!el.childNodes.length) return; const hasOnlyText = Array.from(el.childNodes).every(c => c.nodeType === 3); if (!hasOnlyText) return; const orig = el.textContent; if (!orig.trim()) return; saved.push({ el, orig, title: el.getAttribute('title') }); el.setAttribute('title', orig); el.textContent = SNEAKY[Math.floor(Math.random() * SNEAKY.length)]; }); }, disable() { if (!this.active) return; this.active = false; saved.forEach(({ el, orig, title }) => { el.textContent = orig; if (title == null) el.removeAttribute('title'); else el.setAttribute('title', title); }); saved.length = 0; } }; })(); // --- 25. HACKER --- R.hacker = (function () { let canvas = null, raf = null, lines = []; const snippets = [ '#include ', 'int main(int argc, char** argv) {', ' for (int i = 0; i < n; i++) {', ' if (ptr[i] == NULL) return -1;', ' }', ' exit(0);', '}', 'def exploit(target):', ' shellcode = b"\\x31\\xc0\\x50\\x68"', ' payload = nop_sled(128) + shellcode', ' return pwn(target, payload)', 'mov eax, 0x1337', 'push ebp', 'call 0xdeadbeef', 'jmp short $-5', 'INFO: Scanning 10.0.0.0/24...', 'CRIT: Buffer overflow detected', 'WARN: Rootkit signature found', 'ALERT: Firewall breach imminent', 'echo "pwned" > /root/.hacked', 'sudo rm -rf / --no-preserve-root', '0x00007fff5fbff7b8: 0x00007fff8b4a3d80', 'SEGFAULT at 0x0', 'while(1) fork();', 'cat /etc/shadow', 'nmap -p- -sS -T4 target.com', ]; return { active: false, enable() { if (this.active) return; this.active = true; canvas = makeFullCanvas(9500, 0.88); const ctx = canvas.getContext('2d'); document.documentElement.classList.add('fx-hacker'); const size = 13; lines = []; for (let y = 0; y < canvas.height; y += size) { lines.push({ text: snippets[Math.floor(Math.random() * snippets.length)], y: y }); } function draw() { ctx.fillStyle = 'rgba(0,0,0,0.9)'; ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.fillStyle = '#00ff33'; ctx.font = size + 'px JetBrains Mono, monospace'; lines.forEach(l => { ctx.fillText(l.text, 10, l.y); l.y -= 2; if (l.y < -size) { l.y = canvas.height + size; l.text = snippets[Math.floor(Math.random() * snippets.length)]; } }); raf = requestAnimationFrame(draw); } draw(); }, disable() { if (!this.active) return; this.active = false; document.documentElement.classList.remove('fx-hacker'); if (raf) cancelAnimationFrame(raf); raf = null; destroyCanvas(canvas); canvas = null; lines = []; } }; })(); // ================================================== // Public API // ================================================== function toggle(name, arg) { const fx = R[name]; if (!fx) return false; if (fx.active) { fx.disable(); return false; } fx.enable(arg); return true; } function enable(name, arg) { const fx = R[name]; if (fx && !fx.active) fx.enable(arg); } function disable(name) { const fx = R[name]; if (fx && fx.active) fx.disable(); } function active() { return Object.keys(R).filter(k => R[k].active); } function disableAll() { Object.keys(R).forEach(k => { if (R[k].active) R[k].disable(); }); } window.__jaeEffects = { toggle, enable, disable, active, disableAll, registry: R, list: () => Object.keys(R), }; })();