feat(effects): sitewide effects suite — 25 CLI-triggered visual modes
This commit is contained in:
parent
92db92423a
commit
2c498efbfb
16 changed files with 1747 additions and 239 deletions
|
|
@ -1,42 +1,65 @@
|
||||||
{
|
{
|
||||||
"site": "jaeswift.xyz",
|
"site": "jaeswift.xyz",
|
||||||
"entries": [
|
"entries": [
|
||||||
|
{
|
||||||
|
"version": "1.39.0",
|
||||||
|
"date": "20/04/2026",
|
||||||
|
"category": "FEATURE",
|
||||||
|
"title": "Sitewide Effects Suite \u2014 25 CLI-triggered visual modes",
|
||||||
|
"changes": [
|
||||||
|
"New /js/sitewide-effects.js (~1100 lines) + /css/sitewide-effects.css (~330 lines) \u2014 single central module, exposes window.__jaeEffects (toggle/enable/disable/active/disableAll)",
|
||||||
|
"Injected into 12 pages: index, hq/{telemetry,leaderboards,logs,briefing,profile,index}, depot/{contraband,recon}, recon, armoury/lab, transmissions/radar",
|
||||||
|
"VISUAL DISTORTION (7): /crt CRT scanlines + phosphor flicker + vignette; /vhs chromatic shift + roll bar + noise + glitch blocks; /glitch periodic text corruption + chroma shake; /redalert (/red alias) sepia-red filter + pulsing inset + Web Audio two-tone klaxon + DEFCON 1 banner; /invert; /blueprint hue-shift + grid overlay; /typewriter retype all text with click beeps",
|
||||||
|
"PHYSICS & MOTION (5): /gravity \u2014 panels + headings become fixed, fall with bounce physics; /earthquake \u2014 10s viewport shake; /lowgravity \u2014 1.2s transitions + floating bob; /melt \u2014 progressive vertical drip over 15s; /shuffle \u2014 scramble word order across visible text",
|
||||||
|
"ENVIRONMENTAL (5): /rain 200 drops + thunder flash + filtered-noise ambient; /snow 150 drifting flakes with sine sway; /fog dark overlay + torchlight circle around cursor; /night body dim + cursor spotlight via CSS vars; /underwater hue-rotate + wave overlay + bubble particles + lowpass noise",
|
||||||
|
"MIND-BENDING (3): /dimensions 3D perspective tilt tracking mouse; /portal \u2014 150px circular iframe lens following cursor showing random other page; /retro <1995|2005|2015|now> applies themed HTML classes (Comic Sans/yellow, Web 2.0 glossy, Material flat)",
|
||||||
|
"BONUS (5): /partymode disco hue-rotate + confetti + panel flashes + 120 BPM kick drum; /ghostmode invisible cursor + text fade until hover; /quantum panels teleport every 3s; /sneak replace all a/button labels with CLASSIFIED/REDACTED/etc; /hacker full-viewport scrolling fake code",
|
||||||
|
"Meta command /effects \u2014 shows ASCII status table of active effects; /effects off disables all; /effects all enables everything (chaos mode)",
|
||||||
|
"/matrix and /cmatrix migrated out of chat-cli.js into the sitewide-effects.js registry \u2014 commands stay identical but share the same single-source-of-truth module; dead toggleMatrix/toggleCMatrix code removed",
|
||||||
|
"Mobile + prefers-reduced-motion gating: all effects downgrade particle counts / disable audio gracefully on small screens or reduced-motion preference",
|
||||||
|
"Boss key (Escape / Ctrl+Shift+B) now calls window.__jaeEffects.disableAll() for a universal panic exit",
|
||||||
|
"Z-index ladder: 9000-9500 for overlays, 9600-9700 for loud UI (banners), leaves 9999+ for modals/toasts",
|
||||||
|
"CSS classes prefixed fx-* applied to <html> when active; each effect self-contained with enable/disable lifecycle, proper cleanup of RAF / intervals / AudioContext nodes / canvases",
|
||||||
|
"/help output extended with new EFFECTS category listing all 25 commands + /effects meta",
|
||||||
|
"Files: NEW js/sitewide-effects.js (1143 lines), NEW css/sitewide-effects.css (331 lines); MOD js/chat-cli.js (1142 \u2192 ~1129 lines \u2014 stripped 110 lines of matrix/cmatrix internals, added ~90 lines of thin command wrappers + EFFECTS help category); MOD 12 HTML files (+2 lines each for <link> + <script>)"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"version": "1.38.1",
|
"version": "1.38.1",
|
||||||
"date": "20/04/2026",
|
"date": "20/04/2026",
|
||||||
"category": "FEATURE",
|
"category": "FEATURE",
|
||||||
"title": "CLI Extensions: SSH, Adventure, Fortunes, Figlet, Achievements, Leaderboard, Boss Key",
|
"title": "CLI Extensions: SSH, Adventure, Fortunes, Figlet, Achievements, Leaderboard, Boss Key",
|
||||||
"changes": [
|
"changes": [
|
||||||
"JAE-AI terminal (/) now has 7 new commands and 3 meta-features — type /help to see the categorised menu (SYSTEM / FUN / MODES / STATS)",
|
"JAE-AI terminal (/) now has 7 new commands and 3 meta-features \u2014 type /help to see the categorised menu (SYSTEM / FUN / MODES / STATS)",
|
||||||
"/ssh <user>@<host> — fake SSH session with ED25519 handshake, MOTD, nested shell (ls/cat/cd/pwd/whoami/hostname/uname/date); exit via /exit-ssh or 'exit'",
|
"/ssh <user>@<host> \u2014 fake SSH session with ED25519 handshake, MOTD, nested shell (ls/cat/cd/pwd/whoami/hostname/uname/date); exit via /exit-ssh or 'exit'",
|
||||||
"/adventure — short cyberpunk text adventure (DARK ALLEY → NEON ARCADE → HACKER DEN → LOW ROOFTOP → NEON ROOFTOP boss fight) with inventory, drone HP, /exit-adventure",
|
"/adventure \u2014 short cyberpunk text adventure (DARK ALLEY \u2192 NEON ARCADE \u2192 HACKER DEN \u2192 LOW ROOFTOP \u2192 NEON ROOFTOP boss fight) with inventory, drone HP, /exit-adventure",
|
||||||
"/ttyper — typing-speed test with random programming quote, timer, WPM + accuracy calc, all-time best persisted in localStorage (jae-cli-ttyper-best-v1)",
|
"/ttyper \u2014 typing-speed test with random programming quote, timer, WPM + accuracy calc, all-time best persisted in localStorage (jae-cli-ttyper-best-v1)",
|
||||||
"/cowsay <msg> — classic ASCII cow with auto-sized speech bubble",
|
"/cowsay <msg> \u2014 classic ASCII cow with auto-sized speech bubble",
|
||||||
"/figlet <text> — block-font ASCII banner (5-row UNICODE █ glyphs, full A-Z/0-9/punctuation, truncated to 20 chars)",
|
"/figlet <text> \u2014 block-font ASCII banner (5-row UNICODE \u2588 glyphs, full A-Z/0-9/punctuation, truncated to 20 chars)",
|
||||||
"/fortune -o — offensive mode with 30 crude operator-themed quips; /fortune alone returns 20 tame SITREP entries",
|
"/fortune -o \u2014 offensive mode with 30 crude operator-themed quips; /fortune alone returns 20 tame SITREP entries",
|
||||||
"/cmatrix — enhanced matrix rain: dual-colour green+cyan, denser (14px), speed ramps over 30s cycles, optional square-wave AudioContext ticks for typing-sound effect",
|
"/cmatrix \u2014 enhanced matrix rain: dual-colour green+cyan, denser (14px), speed ramps over 30s cycles, optional square-wave AudioContext ticks for typing-sound effect",
|
||||||
"/achievements — progress tracker showing X/24 commands discovered with ASCII progress bar [███░░░░░░░], list of unlocked commands, persists via localStorage (jae-cli-achievements-v1); toast pops for each new unlock",
|
"/achievements \u2014 progress tracker showing X/24 commands discovered with ASCII progress bar [\u2588\u2588\u2588\u2591\u2591\u2591\u2591\u2591\u2591\u2591], list of unlocked commands, persists via localStorage (jae-cli-achievements-v1); toast pops for each new unlock",
|
||||||
"/leaderboard — session + all-time stats for this browser: command counts, unlocks, most-used command, top-5 session & all-time, military rank (recruit → general based on 20/50/100/200/500/1000/2000 thresholds)",
|
"/leaderboard \u2014 session + all-time stats for this browser: command counts, unlocks, most-used command, top-5 session & all-time, military rank (recruit \u2192 general based on 20/50/100/200/500/1000/2000 thresholds)",
|
||||||
"Boss key — press Escape (while anything is 'hot') or Ctrl+Shift+B to instantly hide matrix rains, dev-mode badge, toasts, and clear chat input; shows 'NORMAL MODE' tooltip for ~2s",
|
"Boss key \u2014 press Escape (while anything is 'hot') or Ctrl+Shift+B to instantly hide matrix rains, dev-mode badge, toasts, and clear chat input; shows 'NORMAL MODE' tooltip for ~2s",
|
||||||
"Nested mode routing — when inside /ssh, /adventure, /ttyper, plain (non-slash) chat input is routed to the nested handler instead of JAE-AI; chat.js updated with isInMode() check",
|
"Nested mode routing \u2014 when inside /ssh, /adventure, /ttyper, plain (non-slash) chat input is routed to the nested handler instead of JAE-AI; chat.js updated with isInMode() check",
|
||||||
"Stats tracked in localStorage (jae-cli-stats-v1) and in-memory session counter; commands object grown from 17 → 24",
|
"Stats tracked in localStorage (jae-cli-stats-v1) and in-memory session counter; commands object grown from 17 \u2192 24",
|
||||||
"Files: js/chat-cli.js (+632 lines → 1142 total), css/chat-cli.css (+21 lines), js/chat.js (+1 line — mode-aware CLI interception)"
|
"Files: js/chat-cli.js (+632 lines \u2192 1142 total), css/chat-cli.css (+21 lines), js/chat.js (+1 line \u2014 mode-aware CLI interception)"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"version": "1.38.0",
|
"version": "1.38.0",
|
||||||
"date": "20/04/2026",
|
"date": "20/04/2026",
|
||||||
"category": "FEATURE",
|
"category": "FEATURE",
|
||||||
"title": "Globe — Live Traffic Arcs from Real Visitors",
|
"title": "Globe \u2014 Live Traffic Arcs from Real Visitors",
|
||||||
"changes": [
|
"changes": [
|
||||||
"Homepage 3D globe (globe.gl) now draws glowing arcs from real visitor country centroids into Manchester HQ (53.48°N, -2.24°W) instead of random fake cities",
|
"Homepage 3D globe (globe.gl) now draws glowing arcs from real visitor country centroids into Manchester HQ (53.48\u00b0N, -2.24\u00b0W) instead of random fake cities",
|
||||||
"Data sourced live from /api/visitor/recent-arcs — tails last 20k lines of nginx access.log, GeoIPs unique IPs, maps country_code → centroid (130+ countries in api/data/country_centroids.json)",
|
"Data sourced live from /api/visitor/recent-arcs \u2014 tails last 20k lines of nginx access.log, GeoIPs unique IPs, maps country_code \u2192 centroid (130+ countries in api/data/country_centroids.json)",
|
||||||
"Frontend polls endpoint every 30s; tactical green arcs (rgba(0,255,60,.85)) fade to turquoise Solana (#14F195) tail for depth, 2.2s dash animation, 0.38 altitude auto-scale",
|
"Frontend polls endpoint every 30s; tactical green arcs (rgba(0,255,60,.85)) fade to turquoise Solana (#14F195) tail for depth, 2.2s dash animation, 0.38 altitude auto-scale",
|
||||||
"Per-arc interactive labels on hover: \"COUNTRY → MCR · Xm ago · /page_path\"",
|
"Per-arc interactive labels on hover: \"COUNTRY \u2192 MCR \u00b7 Xm ago \u00b7 /page_path\"",
|
||||||
"New ARCS LIVE counter badge added to globe overlay HUD (turquoise accent), updates with each refresh",
|
"New ARCS LIVE counter badge added to globe overlay HUD (turquoise accent), updates with each refresh",
|
||||||
"Sub-degree lat/lon jitter applied so multiple visitors from same country no longer stack on a single line",
|
"Sub-degree lat/lon jitter applied so multiple visitors from same country no longer stack on a single line",
|
||||||
"Graceful fallback: if endpoint returns empty/errors, shows 8 demo city arcs (New York/Tokyo/Paris/Sydney/Moscow/Singapore/Berlin/LA) so the globe is never bare",
|
"Graceful fallback: if endpoint returns empty/errors, shows 8 demo city arcs (New York/Tokyo/Paris/Sydney/Moscow/Singapore/Berlin/LA) so the globe is never bare",
|
||||||
"Timestamp parser handles nginx common-log format (DD/Mon/YYYY:HH:MM:SS ±ZZZZ) for accurate relative times",
|
"Timestamp parser handles nginx common-log format (DD/Mon/YYYY:HH:MM:SS \u00b1ZZZZ) for accurate relative times",
|
||||||
"Backend endpoint cache: 5-min TTL, deduped by IP, capped at 50 most-recent unique visitors"
|
"Backend endpoint cache: 5-min TTL, deduped by IP, capped at 50 most-recent unique visitors"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -44,19 +67,19 @@
|
||||||
"version": "1.37.2",
|
"version": "1.37.2",
|
||||||
"date": "20/04/2026",
|
"date": "20/04/2026",
|
||||||
"category": "FEATURE",
|
"category": "FEATURE",
|
||||||
"title": "LEADERBOARDS — Live Operational Rankings",
|
"title": "LEADERBOARDS \u2014 Live Operational Rankings",
|
||||||
"changes": [
|
"changes": [
|
||||||
"New page /hq/leaderboards with 6-panel grid showing real-time traffic intelligence pulled from nginx access logs",
|
"New page /hq/leaderboards with 6-panel grid showing real-time traffic intelligence pulled from nginx access logs",
|
||||||
"TOP COUNTRIES (24h): GeoIP-resolved top 15 origins with auto-generated flag emojis and animated ranked bars",
|
"TOP COUNTRIES (24h): GeoIP-resolved top 15 origins with auto-generated flag emojis and animated ranked bars",
|
||||||
"TOP PAGES (24h): most-hit routes (API/CSS/JS/favicons filtered out), top 20 with green-code path display",
|
"TOP PAGES (24h): most-hit routes (API/CSS/JS/favicons filtered out), top 20 with green-code path display",
|
||||||
"TOP REFERRERS (7d): inbound link sources filtered for own domain — graceful empty state for direct-traffic sites",
|
"TOP REFERRERS (7d): inbound link sources filtered for own domain \u2014 graceful empty state for direct-traffic sites",
|
||||||
"PEAK HOURS (24h UTC): 24-bar hourly chart with amber-highlighted peak column, hover tooltips, auto-summary showing peak hour + total req/24h",
|
"PEAK HOURS (24h UTC): 24-bar hourly chart with amber-highlighted peak column, hover tooltips, auto-summary showing peak hour + total req/24h",
|
||||||
"BROWSER BREAKDOWN (24h): top 10 UA families with per-browser emoji (🟢 Chrome / 🦊 Firefox / 🧭 Safari / 🌀 Edge / 🤖 Bot)",
|
"BROWSER BREAKDOWN (24h): top 10 UA families with per-browser emoji (\ud83d\udfe2 Chrome / \ud83e\udd8a Firefox / \ud83e\udded Safari / \ud83c\udf00 Edge / \ud83e\udd16 Bot)",
|
||||||
"OPERATOR LEADERBOARD (7d): top 10 most-active IPs (privacy-masked first/last octet), request counts, last-seen relative timestamps — self-IP highlighted with amber (YOU) badge",
|
"OPERATOR LEADERBOARD (7d): top 10 most-active IPs (privacy-masked first/last octet), request counts, last-seen relative timestamps \u2014 self-IP highlighted with amber (YOU) badge",
|
||||||
"Gold/silver/bronze rank styling for top-3 rows across all panels; #01–#NN zero-padded ranks elsewhere",
|
"Gold/silver/bronze rank styling for top-3 rows across all panels; #01\u2013#NN zero-padded ranks elsewhere",
|
||||||
"60s auto-refresh + manual refresh button + live LAST UPDATED counter (ticks per second)",
|
"60s auto-refresh + manual refresh button + live LAST UPDATED counter (ticks per second)",
|
||||||
"Backend /api/leaderboards endpoint returns JSON aggregating countries, pages, referrers, peak_hours, browsers, top_operators — 60s in-memory cache",
|
"Backend /api/leaderboards endpoint returns JSON aggregating countries, pages, referrers, peak_hours, browsers, top_operators \u2014 60s in-memory cache",
|
||||||
"New files: hq/leaderboards.html · css/leaderboards.css · js/leaderboards.js",
|
"New files: hq/leaderboards.html \u00b7 css/leaderboards.css \u00b7 js/leaderboards.js",
|
||||||
"Nav updated: HQ menu now includes LEADERBOARDS link with description \"Live traffic rankings & operator stats\"",
|
"Nav updated: HQ menu now includes LEADERBOARDS link with description \"Live traffic rankings & operator stats\"",
|
||||||
"Fully mobile responsive (768px stack / 420px compact) with scanlines + grid-bg matching site theme"
|
"Fully mobile responsive (768px stack / 420px compact) with scanlines + grid-bg matching site theme"
|
||||||
]
|
]
|
||||||
|
|
@ -65,31 +88,31 @@
|
||||||
"version": "1.37.1",
|
"version": "1.37.1",
|
||||||
"date": "20/04/2026",
|
"date": "20/04/2026",
|
||||||
"category": "FEATURE",
|
"category": "FEATURE",
|
||||||
"title": "JAE-AI CLI Easter Egg — Local Pseudo-Shell",
|
"title": "JAE-AI CLI Easter Egg \u2014 Local Pseudo-Shell",
|
||||||
"changes": [
|
"changes": [
|
||||||
"JAE-AI chat now detects messages starting with / and handles them locally as a fake CLI shell — never hits the Venice API, all 100% client-side JavaScript",
|
"JAE-AI chat now detects messages starting with / and handles them locally as a fake CLI shell \u2014 never hits the Venice API, all 100% client-side JavaScript",
|
||||||
"New js/chat-cli.js + css/chat-cli.css — 17 built-in commands: /help /ls /cat <file> /whoami /uptime /uname -a /date /ping <host> /sudo <cmd> /rm -rf / /hack <target> /matrix /clear /exit /fortune /history /neofetch",
|
"New js/chat-cli.js + css/chat-cli.css \u2014 17 built-in commands: /help /ls /cat <file> /whoami /uptime /uname -a /date /ping <host> /sudo <cmd> /rm -rf / /hack <target> /matrix /clear /exit /fortune /history /neofetch",
|
||||||
"Virtual filesystem: /cat about.md|projects.json|skills.md|secrets.enc|mascot.txt|whoami.txt — with glitchy ASCII art ACCESS DENIED screen on secrets.enc",
|
"Virtual filesystem: /cat about.md|projects.json|skills.md|secrets.enc|mascot.txt|whoami.txt \u2014 with glitchy ASCII art ACCESS DENIED screen on secrets.enc",
|
||||||
"/whoami pulls real data from /api/visitor/scan; /uptime pulls from /api/telemetry/overview; /neofetch shows ASCII dragon with browser/OS/screen data",
|
"/whoami pulls real data from /api/visitor/scan; /uptime pulls from /api/telemetry/overview; /neofetch shows ASCII dragon with browser/OS/screen data",
|
||||||
"/matrix toggles a full-screen green Katakana matrix-rain canvas overlay (opacity 18%, 16px JetBrains Mono, var(--status-green))",
|
"/matrix toggles a full-screen green Katakana matrix-rain canvas overlay (opacity 18%, 16px JetBrains Mono, var(--status-green))",
|
||||||
"/hack runs hollywood-style fake progress bars with payload injection drama before revealing it was all fake",
|
"/hack runs hollywood-style fake progress bars with payload injection drama before revealing it was all fake",
|
||||||
"/rm -rf / shows an ASCII destruction sequence then restores from backup with a cheeky message",
|
"/rm -rf / shows an ASCII destruction sequence then restores from backup with a cheeky message",
|
||||||
"Unknown commands route to: command not found: /<cmd>. Type /help for available commands.",
|
"Unknown commands route to: command not found: /<cmd>. Type /help for available commands.",
|
||||||
"Persistent /history ring-buffer (50 entries) stored in localStorage.jaeCliHist",
|
"Persistent /history ring-buffer (50 entries) stored in localStorage.jaeCliHist",
|
||||||
"BONUS: Konami code (↑↑↓↓←→←→BA) unlocks DEVELOPER MODE — amber badge top-right + extra commands: /api (list real endpoints), /curl <url> (actually fetch public URLs, 2KB truncated), /geo (pull live 24h country breakdown from telemetry)",
|
"BONUS: Konami code (\u2191\u2191\u2193\u2193\u2190\u2192\u2190\u2192BA) unlocks DEVELOPER MODE \u2014 amber badge top-right + extra commands: /api (list real endpoints), /curl <url> (actually fetch public URLs, 2KB truncated), /geo (pull live 24h country breakdown from telemetry)",
|
||||||
"chat.js sendMessage() patched to intercept /-prefix messages before hitting /api/chat — user bubble gets $ shell prompt, response styled in terminal-green monospace"
|
"chat.js sendMessage() patched to intercept /-prefix messages before hitting /api/chat \u2014 user bubble gets $ shell prompt, response styled in terminal-green monospace"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"version": "1.37.0",
|
"version": "1.37.0",
|
||||||
"date": "20/04/2026",
|
"date": "20/04/2026",
|
||||||
"category": "FEATURE",
|
"category": "FEATURE",
|
||||||
"title": "SCAN THE VISITOR — Typewriter Operator Recon Overlay",
|
"title": "SCAN THE VISITOR \u2014 Typewriter Operator Recon Overlay",
|
||||||
"changes": [
|
"changes": [
|
||||||
"New homepage overlay greets every visitor with a dramatic typewriter-animated recon scan (~22ms/char): geolocation via GeoLite2, reverse-DNS-derived ISP, user-agent parsing (browser/OS/device) via user-agents pip package, masked IP (X.***.***.Y), screen/language/timezone/connection fingerprinting, plus GREEN/AMBER/RED threat-level status bar",
|
"New homepage overlay greets every visitor with a dramatic typewriter-animated recon scan (~22ms/char): geolocation via GeoLite2, reverse-DNS-derived ISP, user-agent parsing (browser/OS/device) via user-agents pip package, masked IP (X.***.***.Y), screen/language/timezone/connection fingerprinting, plus GREEN/AMBER/RED threat-level status bar",
|
||||||
"Backend: new api/visitor_routes.py Flask blueprint with /api/visitor/scan endpoint — in-memory per-IP rate limiting (1 req / 10s), lazy GeoIP reader (country + city when available), 1s-timeout reverse DNS hostname lookup with ISP dictionary (BT/Virgin/Sky/AWS/Cloudflare/Hetzner etc.), country-flag emoji auto-generation, TOR exit-node heuristic",
|
"Backend: new api/visitor_routes.py Flask blueprint with /api/visitor/scan endpoint \u2014 in-memory per-IP rate limiting (1 req / 10s), lazy GeoIP reader (country + city when available), 1s-timeout reverse DNS hostname lookup with ISP dictionary (BT/Virgin/Sky/AWS/Cloudflare/Hetzner etc.), country-flag emoji auto-generation, TOR exit-node heuristic",
|
||||||
"Frontend: js/scan-visitor.js + css/scan-visitor.css — 720px CRT-scanline overlay with blur backdrop, monospace green typewriter output, blink cursor, three action buttons (CLOSE / DISMISS 7D / ACKNOWLEDGE), ESC-to-close, collapses into a persistent bottom-right OPERATOR ID badge on close, click badge to re-run scan",
|
"Frontend: js/scan-visitor.js + css/scan-visitor.css \u2014 720px CRT-scanline overlay with blur backdrop, monospace green typewriter output, blink cursor, three action buttons (CLOSE / DISMISS 7D / ACKNOWLEDGE), ESC-to-close, collapses into a persistent bottom-right OPERATOR ID badge on close, click badge to re-run scan",
|
||||||
"localStorage persistence: scanDismissed (7-day auto-expiry so returning operators only see the badge), scanBadgeHidden (× on badge hides it permanently)",
|
"localStorage persistence: scanDismissed (7-day auto-expiry so returning operators only see the badge), scanBadgeHidden (\u00d7 on badge hides it permanently)",
|
||||||
"Fully mobile responsive: panel narrows to 96vw at <600px, reduces typography, adjusts badge position above bottom HUD bar",
|
"Fully mobile responsive: panel narrows to 96vw at <600px, reduces typography, adjusts badge position above bottom HUD bar",
|
||||||
"Bundled api/data/country_centroids.json (130+ ISO-3166 country lat/lon centroids) to power upcoming 3D globe traffic-arc feature",
|
"Bundled api/data/country_centroids.json (130+ ISO-3166 country lat/lon centroids) to power upcoming 3D globe traffic-arc feature",
|
||||||
"Exposed window.__jaeScan.run() / window.__jaeScan.reset() for debug re-triggering"
|
"Exposed window.__jaeScan.run() / window.__jaeScan.reset() for debug re-triggering"
|
||||||
|
|
@ -99,12 +122,12 @@
|
||||||
"version": "1.36.2",
|
"version": "1.36.2",
|
||||||
"date": "20/04/2026",
|
"date": "20/04/2026",
|
||||||
"category": "FIX",
|
"category": "FIX",
|
||||||
"title": "Telemetry Polish — GeoIP Live, Service Watchlist Cleanup, Git Hygiene",
|
"title": "Telemetry Polish \u2014 GeoIP Live, Service Watchlist Cleanup, Git Hygiene",
|
||||||
"changes": [
|
"changes": [
|
||||||
"GEO INTEL panel now LIVE — installed DB-IP Country Lite mmdb (8.4MB, April 2026) at /usr/share/GeoIP/GeoLite2-Country.mmdb on VPS plus geoip2==5.2.0 Python package; telemetry dashboard now shows per-country traffic bars (US/GB/RU/CN/SG/DE/AD/UA currently top)",
|
"GEO INTEL panel now LIVE \u2014 installed DB-IP Country Lite mmdb (8.4MB, April 2026) at /usr/share/GeoIP/GeoLite2-Country.mmdb on VPS plus geoip2==5.2.0 Python package; telemetry dashboard now shows per-country traffic bars (US/GB/RU/CN/SG/DE/AD/UA currently top)",
|
||||||
"Monthly GeoIP auto-refresh: new /usr/local/bin/update-geoip.sh bash script + cron '0 4 2 * *' fetches fresh DB-IP mmdb on 2nd of each month, gunzips, restarts jaeswift-api.service, logs to /var/log/geoip-update.log",
|
"Monthly GeoIP auto-refresh: new /usr/local/bin/update-geoip.sh bash script + cron '0 4 2 * *' fetches fresh DB-IP mmdb on 2nd of each month, gunzips, restarts jaeswift-api.service, logs to /var/log/geoip-update.log",
|
||||||
"Service watchlist cleaned — removed matty-lol, caddy, n8n from SYSTEMD_SERVICES in telemetry_routes.py (they were generating false SERVICE DOWN alerts; matty-lol runs on PM2, caddy+n8n unused)",
|
"Service watchlist cleaned \u2014 removed matty-lol, caddy, n8n from SYSTEMD_SERVICES in telemetry_routes.py (they were generating false SERVICE DOWN alerts; matty-lol runs on PM2, caddy+n8n unused)",
|
||||||
"Git DIRTY flag cleared — added runtime-generated files to .gitignore: api/data/telemetry_history.json, api/data/telemetry_netstate.json, api/govdomains-source/ (these are written by cron jobs, not source code)",
|
"Git DIRTY flag cleared \u2014 added runtime-generated files to .gitignore: api/data/telemetry_history.json, api/data/telemetry_netstate.json, api/govdomains-source/ (these are written by cron jobs, not source code)",
|
||||||
"Repos panel now reports CLEAN instead of DIRTY for jaeswift-homepage"
|
"Repos panel now reports CLEAN instead of DIRTY for jaeswift-homepage"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -114,8 +137,8 @@
|
||||||
"category": "FIX",
|
"category": "FIX",
|
||||||
"title": "Cron Log Path Corrections",
|
"title": "Cron Log Path Corrections",
|
||||||
"changes": [
|
"changes": [
|
||||||
"Fixed CRON_JOBS definitions in telemetry_routes.py — contraband/awesomelist/govdomains logs use hyphens not underscores on VPS (contraband-sync.log not contraband_sync.log)",
|
"Fixed CRON_JOBS definitions in telemetry_routes.py \u2014 contraband/awesomelist/govdomains logs use hyphens not underscores on VPS (contraband-sync.log not contraband_sync.log)",
|
||||||
"Corrected govdomains_sync schedule from Sunday 05:00 to every 12 hours (0 */12 * * *) — matches actual crontab",
|
"Corrected govdomains_sync schedule from Sunday 05:00 to every 12 hours (0 */12 * * *) \u2014 matches actual crontab",
|
||||||
"All 5 crons now report OK status on telemetry dashboard instead of UNKNOWN"
|
"All 5 crons now report OK status on telemetry dashboard instead of UNKNOWN"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -123,30 +146,30 @@
|
||||||
"version": "1.36.0",
|
"version": "1.36.0",
|
||||||
"date": "19/04/2026",
|
"date": "19/04/2026",
|
||||||
"category": "FEATURE",
|
"category": "FEATURE",
|
||||||
"title": "TELEMETRY Dashboard — Live Ops Command Centre",
|
"title": "TELEMETRY Dashboard \u2014 Live Ops Command Centre",
|
||||||
"changes": [
|
"changes": [
|
||||||
"New /hq/telemetry page replacing placeholder — full live ops dashboard with boot sequence animation, CRT aesthetic, real-time metrics",
|
"New /hq/telemetry page replacing placeholder \u2014 full live ops dashboard with boot sequence animation, CRT aesthetic, real-time metrics",
|
||||||
"Backend blueprint api/telemetry_routes.py — 6 new endpoints: /api/telemetry/overview, /history, /nginx-tail, /geo, /alerts, /visitors, /commits",
|
"Backend blueprint api/telemetry_routes.py \u2014 6 new endpoints: /api/telemetry/overview, /history, /nginx-tail, /geo, /alerts, /visitors, /commits",
|
||||||
"System metrics: CPU gauge + 24h sparkline, memory gauge + sparkline, per-mount disk ASCII bars, network RX/TX rates + history graph, uptime, load avg, kernel",
|
"System metrics: CPU gauge + 24h sparkline, memory gauge + sparkline, per-mount disk ASCII bars, network RX/TX rates + history graph, uptime, load avg, kernel",
|
||||||
"Services panel: systemctl state for jaeswift-api, matty-lol, nginx, filebrowser, caddy, n8n, docker, ssh — plus PM2 processes — with uptime, mem, CPU per service",
|
"Services panel: systemctl state for jaeswift-api, matty-lol, nginx, filebrowser, caddy, n8n, docker, ssh \u2014 plus PM2 processes \u2014 with uptime, mem, CPU per service",
|
||||||
"Cron tracker: schedule + last run + status (ok/fail/unknown) for contraband_sync, awesomelist_sync, govdomains_sync, sitrep, telemetry_snapshot — expandable log tails",
|
"Cron tracker: schedule + last run + status (ok/fail/unknown) for contraband_sync, awesomelist_sync, govdomains_sync, sitrep, telemetry_snapshot \u2014 expandable log tails",
|
||||||
"Nginx 24h analytics: total requests, bandwidth, avg RPM, top 10 pages, top 10 IPs (masked), 4xx/5xx counts, avg response time — 60s cache",
|
"Nginx 24h analytics: total requests, bandwidth, avg RPM, top 10 pages, top 10 IPs (masked), 4xx/5xx counts, avg response time \u2014 60s cache",
|
||||||
"Security panel: fail2ban jails + ban counts, UFW rules, SSH bruteforce attempts 24h, last reboot timestamp",
|
"Security panel: fail2ban jails + ban counts, UFW rules, SSH bruteforce attempts 24h, last reboot timestamp",
|
||||||
"SSL expiry tracker: per-domain days-remaining with colour coding (red <14d, amber <30d, green otherwise) for jaeswift.xyz, git, files, plex, agentzero",
|
"SSL expiry tracker: per-domain days-remaining with colour coding (red <14d, amber <30d, green otherwise) for jaeswift.xyz, git, files, plex, agentzero",
|
||||||
"Stack inventory: auto-detected versions of Python, Node, nginx, Docker, ffmpeg, kernel, OS — cached at startup",
|
"Stack inventory: auto-detected versions of Python, Node, nginx, Docker, ffmpeg, kernel, OS \u2014 cached at startup",
|
||||||
"Git activity panel: repo name, last commit SHA, message, timestamp, dirty flag for /var/www/jaeswift-homepage",
|
"Git activity panel: repo name, last commit SHA, message, timestamp, dirty flag for /var/www/jaeswift-homepage",
|
||||||
"Geo-distribution: parses nginx IPs through GeoLite2 mmdb (if installed) — horizontal bar chart of top 15 countries by traffic, graceful empty state if mmdb missing",
|
"Geo-distribution: parses nginx IPs through GeoLite2 mmdb (if installed) \u2014 horizontal bar chart of top 15 countries by traffic, graceful empty state if mmdb missing",
|
||||||
"Live nginx tail widget: last 20 requests auto-scrolling every 5s with fade-in animation, colour-coded status codes, masked IPs",
|
"Live nginx tail widget: last 20 requests auto-scrolling every 5s with fade-in animation, colour-coded status codes, masked IPs",
|
||||||
"Alert engine: real-time /api/telemetry/alerts computes CPU/mem/disk/service/cron/5xx/SSL/SSH thresholds — red/amber/info levels — scrolling marquee banner on page",
|
"Alert engine: real-time /api/telemetry/alerts computes CPU/mem/disk/service/cron/5xx/SSL/SSH thresholds \u2014 red/amber/info levels \u2014 scrolling marquee banner on page",
|
||||||
"Visitor counter: active unique IPs in last 5min + req/min — animated ONLINE NOW strong number",
|
"Visitor counter: active unique IPs in last 5min + req/min \u2014 animated ONLINE NOW strong number",
|
||||||
"Burn rate panel: free disk GB, 24h bandwidth totals (↑/↓), load avg breakdown, kernel@hostname",
|
"Burn rate panel: free disk GB, 24h bandwidth totals (\u2191/\u2193), load avg breakdown, kernel@hostname",
|
||||||
"Deployment ticker: horizontal marquee of last 10 git commits (SHA + message + ago)",
|
"Deployment ticker: horizontal marquee of last 10 git commits (SHA + message + ago)",
|
||||||
"Boot animation: 1.5s cinematic sequence — INITIALISING → SECURE CHANNEL → DECRYPTING → AUTHORISED — with progress bar, fades out to reveal grid",
|
"Boot animation: 1.5s cinematic sequence \u2014 INITIALISING \u2192 SECURE CHANNEL \u2192 DECRYPTING \u2192 AUTHORISED \u2014 with progress bar, fades out to reveal grid",
|
||||||
"Alarm sound toggle: Web Audio API generates beep on new alert (urgent=880Hz for red, 440Hz for amber), default OFF, speaker icon top-right",
|
"Alarm sound toggle: Web Audio API generates beep on new alert (urgent=880Hz for red, 440Hz for amber), default OFF, speaker icon top-right",
|
||||||
"Blinking LIVE indicator showing last-sync seconds, dot colour shifts green→amber→red as staleness grows",
|
"Blinking LIVE indicator showing last-sync seconds, dot colour shifts green\u2192amber\u2192red as staleness grows",
|
||||||
"Mobile responsive — all 7 rows stack to single column below 768px, alerts shrink, grid reflows",
|
"Mobile responsive \u2014 all 7 rows stack to single column below 768px, alerts shrink, grid reflows",
|
||||||
"New api/telemetry_snapshot.py ring-buffer cron (every 5min) appends CPU/mem/net to api/data/telemetry_history.json (288 points = 24h)",
|
"New api/telemetry_snapshot.py ring-buffer cron (every 5min) appends CPU/mem/net to api/data/telemetry_history.json (288 points = 24h)",
|
||||||
"New styles: css/telemetry.css (~620 lines) with full dashboard grid, canvas gauges, ASCII disk bars, terminal tail, geo chart, marquee banners — all theming existing var(--tm-green/amber/red/sol) CRT scheme"
|
"New styles: css/telemetry.css (~620 lines) with full dashboard grid, canvas gauges, ASCII disk bars, terminal tail, geo chart, marquee banners \u2014 all theming existing var(--tm-green/amber/red/sol) CRT scheme"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -172,9 +195,9 @@
|
||||||
"Chat history persistence across page reloads (last 50 messages in localStorage key jae-ai-history-v1, auto-restored with RESTORED FROM MEMORY divider)",
|
"Chat history persistence across page reloads (last 50 messages in localStorage key jae-ai-history-v1, auto-restored with RESTORED FROM MEMORY divider)",
|
||||||
"Memory Vault modal UI: military/terminal themed, grouped by category (identity/preference/project/skill/goal/relationship/other) with per-entry delete, importance/timestamp display",
|
"Memory Vault modal UI: military/terminal themed, grouped by category (identity/preference/project/skill/goal/relationship/other) with per-entry delete, importance/timestamp display",
|
||||||
"Modal controls: EXPORT JSON (download backup), FORCE EXTRACT (manual trigger), CLEAR HISTORY (wipes conversation), CLEAR ALL MEMORIES (with confirm)",
|
"Modal controls: EXPORT JSON (download backup), FORCE EXTRACT (manual trigger), CLEAR HISTORY (wipes conversation), CLEAR ALL MEMORIES (with confirm)",
|
||||||
"Memory button in chat header with live count badge + privacy info tooltip (ℹ) explaining local-only storage",
|
"Memory button in chat header with live count badge + privacy info tooltip (\u2139) explaining local-only storage",
|
||||||
"Fuzzy dedup: new memories >80% similar to existing are merged (importance boosted) instead of duplicated",
|
"Fuzzy dedup: new memories >80% similar to existing are merged (importance boosted) instead of duplicated",
|
||||||
"Privacy-first design: all memories stay in the user’s browser; only current query + small relevant subset sent to Venice per message",
|
"Privacy-first design: all memories stay in the user\u2019s browser; only current query + small relevant subset sent to Venice per message",
|
||||||
"Graceful degradation: missing localStorage or extraction failures never break the chat loop"
|
"Graceful degradation: missing localStorage or extraction failures never break the chat loop"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -182,7 +205,7 @@
|
||||||
"version": "1.33.0",
|
"version": "1.33.0",
|
||||||
"date": "19/04/2026",
|
"date": "19/04/2026",
|
||||||
"category": "FEATURE",
|
"category": "FEATURE",
|
||||||
"title": "Homepage SERVER METRICS — Real Live Data",
|
"title": "Homepage SERVER METRICS \u2014 Real Live Data",
|
||||||
"changes": [
|
"changes": [
|
||||||
"SERVER METRICS panel now shows real VPS metrics via /api/stats",
|
"SERVER METRICS panel now shows real VPS metrics via /api/stats",
|
||||||
"CPU LOAD bar: real load_avg / nproc percentage",
|
"CPU LOAD bar: real load_avg / nproc percentage",
|
||||||
|
|
@ -211,7 +234,7 @@
|
||||||
"Purged file from entire git history via git-filter-repo (all 120 commits rewritten)",
|
"Purged file from entire git history via git-filter-repo (all 120 commits rewritten)",
|
||||||
"Force-pushed cleaned history to Gitea (old commits garbage-collected)",
|
"Force-pushed cleaned history to Gitea (old commits garbage-collected)",
|
||||||
"Created apikeys.example.json template for future contributors",
|
"Created apikeys.example.json template for future contributors",
|
||||||
"Rotated Venice API key — old key revoked by user",
|
"Rotated Venice API key \u2014 old key revoked by user",
|
||||||
"VPS file permissions hardened: chmod 600 api/data/apikeys.json",
|
"VPS file permissions hardened: chmod 600 api/data/apikeys.json",
|
||||||
"Verified raw URL git.jaeswift.xyz/.../apikeys.json now returns HTTP 404",
|
"Verified raw URL git.jaeswift.xyz/.../apikeys.json now returns HTTP 404",
|
||||||
"Audit confirmed: zero occurrences of any API key in git history across all branches"
|
"Audit confirmed: zero occurrences of any API key in git history across all branches"
|
||||||
|
|
@ -221,21 +244,21 @@
|
||||||
"version": "1.31.0",
|
"version": "1.31.0",
|
||||||
"date": "19/04/2026",
|
"date": "19/04/2026",
|
||||||
"category": "AI",
|
"category": "AI",
|
||||||
"title": "AI Model Switch — Gemma-4-Uncensored",
|
"title": "AI Model Switch \u2014 Gemma-4-Uncensored",
|
||||||
"changes": [
|
"changes": [
|
||||||
"Switched JAE AI chat model from olafangensan-glm-4.7-flash-heretic to gemma-4-uncensored",
|
"Switched JAE AI chat model from olafangensan-glm-4.7-flash-heretic to gemma-4-uncensored",
|
||||||
"Switched SITREP daily briefing generator to same model for consistency",
|
"Switched SITREP daily briefing generator to same model for consistency",
|
||||||
"Updated admin panel chat defaults: model + header tag now reflect GEMMA-4-UNCENSORED",
|
"Updated admin panel chat defaults: model + header tag now reflect GEMMA-4-UNCENSORED",
|
||||||
"API restarted and verified live — chat now returns tighter, more natural replies"
|
"API restarted and verified live \u2014 chat now returns tighter, more natural replies"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"version": "v1.30.0",
|
"version": "v1.30.0",
|
||||||
"date": "18/04/2026",
|
"date": "18/04/2026",
|
||||||
"title": "ARMOURY: Wallet X-Ray — Solana Wallet Analyser",
|
"title": "ARMOURY: Wallet X-Ray \u2014 Solana Wallet Analyser",
|
||||||
"category": "ARMOURY",
|
"category": "ARMOURY",
|
||||||
"changes": [
|
"changes": [
|
||||||
"New tool: Wallet X-Ray — deep scan any Solana wallet address or connect your own wallet",
|
"New tool: Wallet X-Ray \u2014 deep scan any Solana wallet address or connect your own wallet",
|
||||||
"Overview panel: SOL balance with live USD value, total portfolio value, wallet age, transaction count, and activity rating",
|
"Overview panel: SOL balance with live USD value, total portfolio value, wallet age, transaction count, and activity rating",
|
||||||
"Token Holdings: full SPL token table with logos, balances, live prices via Jupiter Price API, and USD values sorted by value",
|
"Token Holdings: full SPL token table with logos, balances, live prices via Jupiter Price API, and USD values sorted by value",
|
||||||
"NFT Detection: identifies NFTs (0-decimal single-supply tokens) with image grid and Solscan links",
|
"NFT Detection: identifies NFTs (0-decimal single-supply tokens) with image grid and Solscan links",
|
||||||
|
|
@ -247,7 +270,7 @@
|
||||||
"URL parameter support: ?address=... for direct wallet scanning via shared links",
|
"URL parameter support: ?address=... for direct wallet scanning via shared links",
|
||||||
"Wallet X-Ray card added to LAB page with cyan/turquoise theme",
|
"Wallet X-Ray card added to LAB page with cyan/turquoise theme",
|
||||||
"Military radar sweep loading animation during wallet scan",
|
"Military radar sweep loading animation during wallet scan",
|
||||||
"Fully responsive design — works on mobile and desktop"
|
"Fully responsive design \u2014 works on mobile and desktop"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -257,14 +280,14 @@
|
||||||
"category": "UNREDACTED",
|
"category": "UNREDACTED",
|
||||||
"changes": [
|
"changes": [
|
||||||
"Added 9 new collections across UFO/UAP, Covert Operations, and Government categories with 15 indexed documents",
|
"Added 9 new collections across UFO/UAP, Covert Operations, and Government categories with 15 indexed documents",
|
||||||
"COMETA Report (France, 1999): 2 English translations of landmark French military UFO assessment — 163 pages total",
|
"COMETA Report (France, 1999): 2 English translations of landmark French military UFO assessment \u2014 163 pages total",
|
||||||
"RAAF UFO Files (Australia): Declassified Royal Australian Air Force intelligence file — 18 pages",
|
"RAAF UFO Files (Australia): Declassified Royal Australian Air Force intelligence file \u2014 18 pages",
|
||||||
"Project Magnet (Canada, 1950-54): Official Canadian government UFO research programme documents — 6 pages",
|
"Project Magnet (Canada, 1950-54): Official Canadian government UFO research programme documents \u2014 6 pages",
|
||||||
"NZDF UFO/UAP Files (New Zealand, 1984-2024): 3 documents including Cold War sighting reports and modern OIA responses — 136 pages",
|
"NZDF UFO/UAP Files (New Zealand, 1984-2024): 3 documents including Cold War sighting reports and modern OIA responses \u2014 136 pages",
|
||||||
"Operação Prato (Brazil, 1977): Secret Brazilian Air Force UFO investigation in the Amazon — 58 pages",
|
"Opera\u00e7\u00e3o Prato (Brazil, 1977): Secret Brazilian Air Force UFO investigation in the Amazon \u2014 58 pages",
|
||||||
"COINTELPRO: 758-page FBI surveillance programme compilation plus analytical examination added to existing collection",
|
"COINTELPRO: 758-page FBI surveillance programme compilation plus analytical examination added to existing collection",
|
||||||
"Operation Paperclip (1945-59): Declassified CIA documents on Nazi scientist recruitment programme — 11 pages",
|
"Operation Paperclip (1945-59): Declassified CIA documents on Nazi scientist recruitment programme \u2014 11 pages",
|
||||||
"Watergate Scandal (1972-74): Ford Presidential Library documents on the constitutional crisis — 35 pages",
|
"Watergate Scandal (1972-74): Ford Presidential Library documents on the constitutional crisis \u2014 35 pages",
|
||||||
"Iran-Contra Affair (1985-87): Complete 506-page Congressional investigation report",
|
"Iran-Contra Affair (1985-87): Complete 506-page Congressional investigation report",
|
||||||
"New countries added to UFO/UAP category: France, Australia, Canada, New Zealand, Brazil"
|
"New countries added to UFO/UAP category: France, Australia, Canada, New Zealand, Brazil"
|
||||||
]
|
]
|
||||||
|
|
@ -276,12 +299,12 @@
|
||||||
"category": "CRIME SCENE",
|
"category": "CRIME SCENE",
|
||||||
"changes": [
|
"changes": [
|
||||||
"Added 6 new crime case collections across cold-cases, serial-killers, and landmark-cases with 11 indexed documents",
|
"Added 6 new crime case collections across cold-cases, serial-killers, and landmark-cases with 11 indexed documents",
|
||||||
"D.B. Cooper Hijacking (1971): FBI investigation files — 162 pages on America's only unsolved aircraft hijacking",
|
"D.B. Cooper Hijacking (1971): FBI investigation files \u2014 162 pages on America's only unsolved aircraft hijacking",
|
||||||
"JonBenét Ramsey Murder (1996): Autopsy report, unsealed grand jury indictment, and analytical case study — 19 pages",
|
"JonBen\u00e9t Ramsey Murder (1996): Autopsy report, unsealed grand jury indictment, and analytical case study \u2014 19 pages",
|
||||||
"Black Dahlia / Elizabeth Short (1947): Complete FBI investigation file — 204 pages on LA's most famous unsolved murder",
|
"Black Dahlia / Elizabeth Short (1947): Complete FBI investigation file \u2014 204 pages on LA's most famous unsolved murder",
|
||||||
"Delphi Murders (2017): Probable cause affidavit and court documents from the Richard Allen prosecution — 95 pages",
|
"Delphi Murders (2017): Probable cause affidavit and court documents from the Richard Allen prosecution \u2014 95 pages",
|
||||||
"Harold Shipman (1975-98): First three reports of the Shipman Inquiry (Dame Janet Smith) — 1,162 pages on Britain's worst serial killer",
|
"Harold Shipman (1975-98): First three reports of the Shipman Inquiry (Dame Janet Smith) \u2014 1,162 pages on Britain's worst serial killer",
|
||||||
"Moors Murders — Brady & Hindley (1963-65): Mental Health Review Tribunal academic paper — 22 pages",
|
"Moors Murders \u2014 Brady & Hindley (1963-65): Mental Health Review Tribunal academic paper \u2014 22 pages",
|
||||||
"New landmark-cases/US subcategory with Delphi Murders as first entry",
|
"New landmark-cases/US subcategory with Delphi Murders as first entry",
|
||||||
"Total new document pages added: 1,664 across all crime scene collections"
|
"Total new document pages added: 1,664 across all crime scene collections"
|
||||||
]
|
]
|
||||||
|
|
@ -289,18 +312,18 @@
|
||||||
{
|
{
|
||||||
"version": "v1.27.0",
|
"version": "v1.27.0",
|
||||||
"date": "18/04/2026",
|
"date": "18/04/2026",
|
||||||
"title": "CRIME SCENE: UK Murder Cases — Mass Upload",
|
"title": "CRIME SCENE: UK Murder Cases \u2014 Mass Upload",
|
||||||
"category": "CRIME SCENE",
|
"category": "CRIME SCENE",
|
||||||
"changes": [
|
"changes": [
|
||||||
"Added 11 UK murder case collections across 4 categories with 57 indexed documents",
|
"Added 11 UK murder case collections across 4 categories with 57 indexed documents",
|
||||||
"New 'Landmark Cases' category for cases that changed British law and policing",
|
"New 'Landmark Cases' category for cases that changed British law and policing",
|
||||||
"Daniel Morgan (1987): 3-volume Independent Panel Report — 1,276 pages on Met Police corruption",
|
"Daniel Morgan (1987): 3-volume Independent Panel Report \u2014 1,276 pages on Met Police corruption",
|
||||||
"Claudia Lawrence (2009): ICO FOI audit of North Yorkshire Police practices",
|
"Claudia Lawrence (2009): ICO FOI audit of North Yorkshire Police practices",
|
||||||
"Jill Dando (1999): Barry George appeal judgment and CCRC referral decision",
|
"Jill Dando (1999): Barry George appeal judgment and CCRC referral decision",
|
||||||
"Suzy Lamplugh (1986): Suzy Lamplugh Trust safety resources and case documentation",
|
"Suzy Lamplugh (1986): Suzy Lamplugh Trust safety resources and case documentation",
|
||||||
"Stephen Lawrence (1993): Complete Macpherson Report — 389 pages, coined 'institutional racism'",
|
"Stephen Lawrence (1993): Complete Macpherson Report \u2014 389 pages, coined 'institutional racism'",
|
||||||
"James Bulger (1993): ECHR Grand Chamber judgments, anonymity injunction, minimum term review",
|
"James Bulger (1993): ECHR Grand Chamber judgments, anonymity injunction, minimum term review",
|
||||||
"Damilola Taylor (2000): Sentamu Oversight Panel investigation review — 56 pages",
|
"Damilola Taylor (2000): Sentamu Oversight Panel investigation review \u2014 56 pages",
|
||||||
"Lee Rigby (2013): ISC intelligence report (200 pages), Government response, sentencing remarks",
|
"Lee Rigby (2013): ISC intelligence report (200 pages), Government response, sentencing remarks",
|
||||||
"Lord Lucan (1974): Presumption of Death Act legal analysis for Sandra Rivett murder",
|
"Lord Lucan (1974): Presumption of Death Act legal analysis for Sandra Rivett murder",
|
||||||
"Madeleine McCann (2007): PJ Police Report translation (57 pages), Jane Tanner statements (4 parts)",
|
"Madeleine McCann (2007): PJ Police Report translation (57 pages), Jane Tanner statements (4 parts)",
|
||||||
|
|
@ -315,10 +338,10 @@
|
||||||
"category": "CRIME SCENE",
|
"category": "CRIME SCENE",
|
||||||
"changes": [
|
"changes": [
|
||||||
"Populated the Police Reports subcollection for the Zodiac Killer with 5 documents (207 pages, 26.4 MB)",
|
"Populated the Police Reports subcollection for the Zodiac Killer with 5 documents (207 pages, 26.4 MB)",
|
||||||
"Added Lake Herman Road police reports — Benicia PD & Solano County Sheriff (60 pages, 5.6 MB)",
|
"Added Lake Herman Road police reports \u2014 Benicia PD & Solano County Sheriff (60 pages, 5.6 MB)",
|
||||||
"Added Blue Rock Springs police reports — Vallejo PD (75 pages, 10.3 MB)",
|
"Added Blue Rock Springs police reports \u2014 Vallejo PD (75 pages, 10.3 MB)",
|
||||||
"Added Lake Berryessa police reports — Napa County Sheriff's Office (35 pages, 5.1 MB)",
|
"Added Lake Berryessa police reports \u2014 Napa County Sheriff's Office (35 pages, 5.1 MB)",
|
||||||
"Added Presidio Heights / Paul Stine police reports — SFPD (2 pages, 0.4 MB)",
|
"Added Presidio Heights / Paul Stine police reports \u2014 SFPD (2 pages, 0.4 MB)",
|
||||||
"Added California Department of Justice investigation report (35 pages, 5.0 MB)",
|
"Added California Department of Justice investigation report (35 pages, 5.0 MB)",
|
||||||
"Zodiac Killer collection now contains 26 documents across 4 subcollections totalling approximately 78 MB",
|
"Zodiac Killer collection now contains 26 documents across 4 subcollections totalling approximately 78 MB",
|
||||||
"All documents sourced from zodiackiller.com's authenticated police report archive"
|
"All documents sourced from zodiackiller.com's authenticated police report archive"
|
||||||
|
|
@ -327,7 +350,7 @@
|
||||||
{
|
{
|
||||||
"version": "1.25.0",
|
"version": "1.25.0",
|
||||||
"date": "16/04/2026",
|
"date": "16/04/2026",
|
||||||
"title": "Changelog Fix — Date Format & Missing Entries",
|
"title": "Changelog Fix \u2014 Date Format & Missing Entries",
|
||||||
"category": "fix",
|
"category": "fix",
|
||||||
"changes": [
|
"changes": [
|
||||||
"Fixed NaN/NaN/NaN date display bug in changelog renderer",
|
"Fixed NaN/NaN/NaN date display bug in changelog renderer",
|
||||||
|
|
@ -344,18 +367,18 @@
|
||||||
"category": "fix",
|
"category": "fix",
|
||||||
"changes": [
|
"changes": [
|
||||||
"Replaced encrypted/unreadable MKUltra PDF with two working documents",
|
"Replaced encrypted/unreadable MKUltra PDF with two working documents",
|
||||||
"Added CIA Inspector General Report (1963) — 48-page TOP SECRET internal review",
|
"Added CIA Inspector General Report (1963) \u2014 48-page TOP SECRET internal review",
|
||||||
"Added Senate Hearing transcript (1977) — 171-page Congressional testimony exposing 149 sub-projects"
|
"Added Senate Hearing transcript (1977) \u2014 171-page Congressional testimony exposing 149 sub-projects"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"version": "1.23.0",
|
"version": "1.23.0",
|
||||||
"date": "16/04/2026",
|
"date": "16/04/2026",
|
||||||
"title": "PROPAGANDA → UNREDACTED Rename + Nav Animation + CRIME SCENE",
|
"title": "PROPAGANDA \u2192 UNREDACTED Rename + Nav Animation + CRIME SCENE",
|
||||||
"category": "feature",
|
"category": "feature",
|
||||||
"changes": [
|
"changes": [
|
||||||
"Renamed PROPAGANDA section to UNREDACTED across all pages, nav, API, and URLs",
|
"Renamed PROPAGANDA section to UNREDACTED across all pages, nav, API, and URLs",
|
||||||
"Built block-reveal animation on UNREDACTED nav item (██████████ → UNREDACTED → reverse → loop)",
|
"Built block-reveal animation on UNREDACTED nav item (\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2192 UNREDACTED \u2192 reverse \u2192 loop)",
|
||||||
"Added global document search across all UNREDACTED categories, titles, and descriptions",
|
"Added global document search across all UNREDACTED categories, titles, and descriptions",
|
||||||
"Built new CRIME SCENE section at /depot/crimescene with red CRT theme",
|
"Built new CRIME SCENE section at /depot/crimescene with red CRT theme",
|
||||||
"Four crime categories: Unsolved Murders, Serial Killers, Court Transcripts, Cold Cases",
|
"Four crime categories: Unsolved Murders, Serial Killers, Court Transcripts, Cold Cases",
|
||||||
|
|
@ -366,12 +389,12 @@
|
||||||
{
|
{
|
||||||
"version": "1.22.0",
|
"version": "1.22.0",
|
||||||
"date": "15/04/2026",
|
"date": "15/04/2026",
|
||||||
"title": "CRIME SCENE: Zodiac Killer Expanded — Letters, Ciphers & Subcollections",
|
"title": "CRIME SCENE: Zodiac Killer Expanded \u2014 Letters, Ciphers & Subcollections",
|
||||||
"category": "CRIME SCENE",
|
"category": "CRIME SCENE",
|
||||||
"changes": [
|
"changes": [
|
||||||
"Fixed PDF path bug: document URLs now correctly include country code (US) via subcollection routing",
|
"Fixed PDF path bug: document URLs now correctly include country code (US) via subcollection routing",
|
||||||
"Restructured Zodiac Killer into 4 subcollections: FBI Investigation Files, Zodiac Letters & Cards, The Zodiac Ciphers, Police Reports & Crime Scene Documents",
|
"Restructured Zodiac Killer into 4 subcollections: FBI Investigation Files, Zodiac Letters & Cards, The Zodiac Ciphers, Police Reports & Crime Scene Documents",
|
||||||
"Added 11 original Zodiac letter PDFs (1969–1974) from zodiackiller.com: Chronicle/Examiner cipher letters, Debut letter, Stine bloody shirt letter, Bus Bomb letter, Belli letter, Dragon card, Phillips 66 map letter, Little List/Mikado letter, Exorcist letter, Citizen card",
|
"Added 11 original Zodiac letter PDFs (1969\u20131974) from zodiackiller.com: Chronicle/Examiner cipher letters, Debut letter, Stine bloody shirt letter, Bus Bomb letter, Belli letter, Dragon card, Phillips 66 map letter, Little List/Mikado letter, Exorcist letter, Citizen card",
|
||||||
"Added 3 cipher PDFs: Z408 three-part cipher (solved 1969), Z340 cipher (solved 2020), Z32 map code cipher (unsolved)",
|
"Added 3 cipher PDFs: Z408 three-part cipher (solved 1969), Z340 cipher (solved 2020), Z32 map code cipher (unsolved)",
|
||||||
"Added Z340 Solution academic paper by Oranchak, Blake & Van Eycke (2024, 38 pages) from arXiv",
|
"Added Z340 Solution academic paper by Oranchak, Blake & Van Eycke (2024, 38 pages) from arXiv",
|
||||||
"Each of the 21 new documents has a unique historical description with contextual detail",
|
"Each of the 21 new documents has a unique historical description with contextual detail",
|
||||||
|
|
@ -387,7 +410,7 @@
|
||||||
"category": "CRIME SCENE",
|
"category": "CRIME SCENE",
|
||||||
"changes": [
|
"changes": [
|
||||||
"Added complete FBI Zodiac Killer investigation files (6 parts, 1,116 pages, 34MB)",
|
"Added complete FBI Zodiac Killer investigation files (6 parts, 1,116 pages, 34MB)",
|
||||||
"Files sourced from FBI Vault via Archive.org — declassified FOIA release",
|
"Files sourced from FBI Vault via Archive.org \u2014 declassified FOIA release",
|
||||||
"Each document includes unique summary describing specific contents",
|
"Each document includes unique summary describing specific contents",
|
||||||
"Covers: Arthur Leigh Allen suspect investigation, cipher analysis, forensic lab reports, fingerprint comparisons, decades of tips and suspect referrals",
|
"Covers: Arthur Leigh Allen suspect investigation, cipher analysis, forensic lab reports, fingerprint comparisons, decades of tips and suspect referrals",
|
||||||
"PDFs served from /crimescene/docs/serial-killers/US/zodiac-killer/",
|
"PDFs served from /crimescene/docs/serial-killers/US/zodiac-killer/",
|
||||||
|
|
@ -401,9 +424,9 @@
|
||||||
"category": "feature",
|
"category": "feature",
|
||||||
"changes": [
|
"changes": [
|
||||||
"Added PDF text search to document viewer (Ctrl+F, green/amber highlights, match counter, case toggle)",
|
"Added PDF text search to document viewer (Ctrl+F, green/amber highlights, match counter, case toggle)",
|
||||||
"Text layer enabled — select and copy text from PDFs",
|
"Text layer enabled \u2014 select and copy text from PDFs",
|
||||||
"Added unique descriptions to all 113 UK MOD UFO documents sourced from National Archives highlights guides",
|
"Added unique descriptions to all 113 UK MOD UFO documents sourced from National Archives highlights guides",
|
||||||
"Added Project Condign (250MB, 460pp SECRET UK EYES ONLY) — the classified DI55 UAP study",
|
"Added Project Condign (250MB, 460pp SECRET UK EYES ONLY) \u2014 the classified DI55 UAP study",
|
||||||
"Downloaded US documents: Project Blue Book, CIA UFO Collection, NSA UFO Documents, Pentagon UAP Report",
|
"Downloaded US documents: Project Blue Book, CIA UFO Collection, NSA UFO Documents, Pentagon UAP Report",
|
||||||
"Downloaded Covert Ops: MKUltra, Stargate Program, Operation Northwoods",
|
"Downloaded Covert Ops: MKUltra, Stargate Program, Operation Northwoods",
|
||||||
"Downloaded Government: JFK Warren Commission, Pentagon Papers, CIA Torture Report",
|
"Downloaded Government: JFK Warren Commission, Pentagon Papers, CIA Torture Report",
|
||||||
|
|
@ -417,7 +440,7 @@
|
||||||
"category": "fix",
|
"category": "fix",
|
||||||
"changes": [
|
"changes": [
|
||||||
"Fixed dispatches post pages crashing (mood type error + fallback path)",
|
"Fixed dispatches post pages crashing (mood type error + fallback path)",
|
||||||
"SOL price ticker fixed — switched to Binance API (CORS-friendly)",
|
"SOL price ticker fixed \u2014 switched to Binance API (CORS-friendly)",
|
||||||
"Tightened navbar spacing between SOL price and wallet connect",
|
"Tightened navbar spacing between SOL price and wallet connect",
|
||||||
"Converted all post mood values from integers to proper strings"
|
"Converted all post mood values from integers to proper strings"
|
||||||
]
|
]
|
||||||
|
|
@ -428,19 +451,19 @@
|
||||||
"title": "Admin Panel Overhaul",
|
"title": "Admin Panel Overhaul",
|
||||||
"category": "feature",
|
"category": "feature",
|
||||||
"changes": [
|
"changes": [
|
||||||
"Fixed broken Editor section — full post editing with live preview",
|
"Fixed broken Editor section \u2014 full post editing with live preview",
|
||||||
"Fixed broken Backups section — export/import site data as ZIP",
|
"Fixed broken Backups section \u2014 export/import site data as ZIP",
|
||||||
"Added SITREP admin section — generate reports, view archive",
|
"Added SITREP admin section \u2014 generate reports, view archive",
|
||||||
"Added Data Sync section — trigger Contraband/RECON syncs, view stats",
|
"Added Data Sync section \u2014 trigger Contraband/RECON syncs, view stats",
|
||||||
"Added Changelog admin section — CRUD for maintenance log entries",
|
"Added Changelog admin section \u2014 CRUD for maintenance log entries",
|
||||||
"Added Cron Jobs section — view/toggle all scheduled tasks",
|
"Added Cron Jobs section \u2014 view/toggle all scheduled tasks",
|
||||||
"Reorganised sidebar into grouped sections"
|
"Reorganised sidebar into grouped sections"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"version": "1.18.0",
|
"version": "1.18.0",
|
||||||
"date": "06/04/2026",
|
"date": "06/04/2026",
|
||||||
"title": "SITREP — Daily AI Briefing System",
|
"title": "SITREP \u2014 Daily AI Briefing System",
|
||||||
"category": "feature",
|
"category": "feature",
|
||||||
"changes": [
|
"changes": [
|
||||||
"Built automated daily intelligence briefing at /transmissions/sitrep",
|
"Built automated daily intelligence briefing at /transmissions/sitrep",
|
||||||
|
|
@ -454,7 +477,7 @@
|
||||||
{
|
{
|
||||||
"version": "1.17.0",
|
"version": "1.17.0",
|
||||||
"date": "06/04/2026",
|
"date": "06/04/2026",
|
||||||
"title": "TOKEN FORGE — SPL Token Launcher",
|
"title": "TOKEN FORGE \u2014 SPL Token Launcher",
|
||||||
"category": "feature",
|
"category": "feature",
|
||||||
"changes": [
|
"changes": [
|
||||||
"Built token launcher at /tokenlauncher with full SPL token creation",
|
"Built token launcher at /tokenlauncher with full SPL token creation",
|
||||||
|
|
@ -498,7 +521,7 @@
|
||||||
"changes": [
|
"changes": [
|
||||||
"Global wallet connect button in navbar across all 28 pages",
|
"Global wallet connect button in navbar across all 28 pages",
|
||||||
"Multi-wallet support: Phantom, Solflare, Backpack, Coinbase, Trust, MetaMask, Jupiter",
|
"Multi-wallet support: Phantom, Solflare, Backpack, Coinbase, Trust, MetaMask, Jupiter",
|
||||||
"Persistent connection via localStorage — survives page navigation",
|
"Persistent connection via localStorage \u2014 survives page navigation",
|
||||||
"Connected dropdown with address copy, Solscan link, disconnect",
|
"Connected dropdown with address copy, Solscan link, disconnect",
|
||||||
"Global window.solWallet API for all Solana features",
|
"Global window.solWallet API for all Solana features",
|
||||||
"Refactored soldomains.js to use shared wallet (removed 146 lines)"
|
"Refactored soldomains.js to use shared wallet (removed 146 lines)"
|
||||||
|
|
@ -507,7 +530,7 @@
|
||||||
{
|
{
|
||||||
"version": "1.13.0",
|
"version": "1.13.0",
|
||||||
"date": "05/04/2026",
|
"date": "05/04/2026",
|
||||||
"title": "RADAR — Live Tech News Feed",
|
"title": "RADAR \u2014 Live Tech News Feed",
|
||||||
"category": "feature",
|
"category": "feature",
|
||||||
"changes": [
|
"changes": [
|
||||||
"Built live tech news aggregator at /transmissions/radar",
|
"Built live tech news aggregator at /transmissions/radar",
|
||||||
|
|
@ -530,7 +553,7 @@
|
||||||
{
|
{
|
||||||
"version": "1.11.0",
|
"version": "1.11.0",
|
||||||
"date": "04/04/2026",
|
"date": "04/04/2026",
|
||||||
"title": "RECON — Site Restructure & Accordion Navigation",
|
"title": "RECON \u2014 Site Restructure & Accordion Navigation",
|
||||||
"category": "feature",
|
"category": "feature",
|
||||||
"changes": [
|
"changes": [
|
||||||
"Moved RECON to /depot/recon for consistency with other depot pages",
|
"Moved RECON to /depot/recon for consistency with other depot pages",
|
||||||
|
|
@ -543,7 +566,7 @@
|
||||||
{
|
{
|
||||||
"version": "1.10.0",
|
"version": "1.10.0",
|
||||||
"date": "04/04/2026",
|
"date": "04/04/2026",
|
||||||
"title": "RECON — Curated Lists Rebuild",
|
"title": "RECON \u2014 Curated Lists Rebuild",
|
||||||
"category": "feature",
|
"category": "feature",
|
||||||
"changes": [
|
"changes": [
|
||||||
"Flattened 4-level navigation to 2-level (sector > list > entries)",
|
"Flattened 4-level navigation to 2-level (sector > list > entries)",
|
||||||
|
|
@ -555,7 +578,7 @@
|
||||||
{
|
{
|
||||||
"version": "1.9.0",
|
"version": "1.9.0",
|
||||||
"date": "04/04/2026",
|
"date": "04/04/2026",
|
||||||
"title": "RECON — Curated Lists Database",
|
"title": "RECON \u2014 Curated Lists Database",
|
||||||
"category": "feature",
|
"category": "feature",
|
||||||
"changes": [
|
"changes": [
|
||||||
"Parsed 660 curated lists into 28 themed sectors",
|
"Parsed 660 curated lists into 28 themed sectors",
|
||||||
|
|
@ -572,7 +595,7 @@
|
||||||
"category": "feature",
|
"category": "feature",
|
||||||
"changes": [
|
"changes": [
|
||||||
"Subcategories now display as 2-column card grid with expandable detail panels",
|
"Subcategories now display as 2-column card grid with expandable detail panels",
|
||||||
"Added weekly auto-sync — resource database updates every Sunday at 03:00",
|
"Added weekly auto-sync \u2014 resource database updates every Sunday at 03:00",
|
||||||
"Click any subcategory card to expand/collapse its entries below",
|
"Click any subcategory card to expand/collapse its entries below",
|
||||||
"Active card highlighting with amber glow",
|
"Active card highlighting with amber glow",
|
||||||
"Responsive grid: 2-col desktop, 1-col mobile"
|
"Responsive grid: 2-col desktop, 1-col mobile"
|
||||||
|
|
@ -584,8 +607,8 @@
|
||||||
"title": "Sitewide Visual Overhaul",
|
"title": "Sitewide Visual Overhaul",
|
||||||
"category": "fix",
|
"category": "fix",
|
||||||
"changes": [
|
"changes": [
|
||||||
"Bumped 64 font sizes sitewide — no more microscopic text",
|
"Bumped 64 font sizes sitewide \u2014 no more microscopic text",
|
||||||
"Brightened all text colours: primary #c0c0c0→#d8d8d8, secondary #707070→#999999, muted #3a3a3a→#666666",
|
"Brightened all text colours: primary #c0c0c0\u2192#d8d8d8, secondary #707070\u2192#999999, muted #3a3a3a\u2192#666666",
|
||||||
"CONTRABAND page: 4-column category grid with responsive breakpoints",
|
"CONTRABAND page: 4-column category grid with responsive breakpoints",
|
||||||
"Purged all third-party attribution references from entire codebase"
|
"Purged all third-party attribution references from entire codebase"
|
||||||
]
|
]
|
||||||
|
|
@ -593,13 +616,13 @@
|
||||||
{
|
{
|
||||||
"version": "1.6.0",
|
"version": "1.6.0",
|
||||||
"date": "03/04/2026",
|
"date": "03/04/2026",
|
||||||
"title": "CONTRABAND — Classified Resource Index",
|
"title": "CONTRABAND \u2014 Classified Resource Index",
|
||||||
"category": "feature",
|
"category": "feature",
|
||||||
"changes": [
|
"changes": [
|
||||||
"Launched CONTRABAND page at /depot/contraband with 15,800+ indexed assets",
|
"Launched CONTRABAND page at /depot/contraband with 15,800+ indexed assets",
|
||||||
"24 categories with military codenames (CRT-001 through CRT-024)",
|
"24 categories with military codenames (CRT-001 through CRT-024)",
|
||||||
"Full-text search across all entries via API",
|
"Full-text search across all entries via API",
|
||||||
"Starred/top-pick filter system with ⭐ indicators",
|
"Starred/top-pick filter system with \u2b50 indicators",
|
||||||
"Collapsible subcategories with item counts",
|
"Collapsible subcategories with item counts",
|
||||||
"Flask API endpoints: /api/contraband, /api/contraband/<slug>, /api/contraband/search"
|
"Flask API endpoints: /api/contraband, /api/contraband/<slug>, /api/contraband/search"
|
||||||
]
|
]
|
||||||
|
|
@ -621,8 +644,8 @@
|
||||||
"title": "Globe & Chat AI Admin Panels",
|
"title": "Globe & Chat AI Admin Panels",
|
||||||
"category": "feature",
|
"category": "feature",
|
||||||
"changes": [
|
"changes": [
|
||||||
"Admin panel: Globe management section — server location, rotation speed, arc cities, colours",
|
"Admin panel: Globe management section \u2014 server location, rotation speed, arc cities, colours",
|
||||||
"Admin panel: Chat AI configuration — model selection, system prompt, greeting toggle",
|
"Admin panel: Chat AI configuration \u2014 model selection, system prompt, greeting toggle",
|
||||||
"New API endpoints: /api/globe, /api/chat-config with auth-protected GET/POST",
|
"New API endpoints: /api/globe, /api/chat-config with auth-protected GET/POST",
|
||||||
"Interactive colour picker and slider controls for globe parameters",
|
"Interactive colour picker and slider controls for globe parameters",
|
||||||
"Arc cities table with add/remove functionality"
|
"Arc cities table with add/remove functionality"
|
||||||
|
|
|
||||||
|
|
@ -99,6 +99,7 @@
|
||||||
letter-spacing: 1px;
|
letter-spacing: 1px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
<link rel="stylesheet" href="/css/sitewide-effects.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="scanline-overlay"></div>
|
<div class="scanline-overlay"></div>
|
||||||
|
|
@ -200,5 +201,6 @@
|
||||||
<script src="/js/wallet-connect.js"></script>
|
<script src="/js/wallet-connect.js"></script>
|
||||||
<script src="/js/nav.js"></script>
|
<script src="/js/nav.js"></script>
|
||||||
<script src="/js/clock.js"></script>
|
<script src="/js/clock.js"></script>
|
||||||
|
<script src="/js/sitewide-effects.js" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
331
css/sitewide-effects.css
Normal file
331
css/sitewide-effects.css
Normal file
|
|
@ -0,0 +1,331 @@
|
||||||
|
/* =================================================
|
||||||
|
JAESWIFT Sitewide Effects CSS
|
||||||
|
================================================= */
|
||||||
|
|
||||||
|
/* 1. CRT */
|
||||||
|
html.fx-crt {
|
||||||
|
filter: contrast(1.1) saturate(1.2) brightness(0.95);
|
||||||
|
animation: fx-crt-flicker 0.15s infinite;
|
||||||
|
}
|
||||||
|
html.fx-crt body {
|
||||||
|
transform: perspective(1500px) rotateX(0.5deg);
|
||||||
|
transform-origin: center top;
|
||||||
|
background: radial-gradient(ellipse at center, #0a1a0a 0%, #000 100%);
|
||||||
|
}
|
||||||
|
@keyframes fx-crt-flicker {
|
||||||
|
0%, 98% { opacity: 1; }
|
||||||
|
99% { opacity: 0.94; }
|
||||||
|
100% { opacity: 1; }
|
||||||
|
}
|
||||||
|
.fx-crt-overlay {
|
||||||
|
position: fixed; inset: 0; pointer-events: none; z-index: 9400;
|
||||||
|
background:
|
||||||
|
repeating-linear-gradient(
|
||||||
|
to bottom,
|
||||||
|
rgba(0,0,0,0) 0px,
|
||||||
|
rgba(0,0,0,0) 2px,
|
||||||
|
rgba(0,0,0,0.18) 3px,
|
||||||
|
rgba(0,0,0,0.18) 4px
|
||||||
|
),
|
||||||
|
radial-gradient(ellipse at center, transparent 55%, rgba(0,0,0,0.7) 100%);
|
||||||
|
mix-blend-mode: multiply;
|
||||||
|
}
|
||||||
|
.fx-crt-overlay::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute; inset: 0;
|
||||||
|
background: linear-gradient(90deg, rgba(255,0,0,0.03), transparent 3%, transparent 97%, rgba(0,255,255,0.03));
|
||||||
|
mix-blend-mode: screen;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 2. VHS */
|
||||||
|
html.fx-vhs body {
|
||||||
|
filter: saturate(1.4) contrast(1.1) hue-rotate(-4deg);
|
||||||
|
text-shadow: -1px 0 rgba(255,0,0,0.5), 1px 0 rgba(0,255,255,0.5);
|
||||||
|
}
|
||||||
|
.fx-vhs-roll {
|
||||||
|
position: fixed; left: 0; right: 0; height: 60px;
|
||||||
|
background: linear-gradient(180deg, transparent, rgba(255,255,255,0.09), transparent);
|
||||||
|
pointer-events: none; z-index: 9300;
|
||||||
|
animation: fx-vhs-roll 8s linear infinite;
|
||||||
|
}
|
||||||
|
@keyframes fx-vhs-roll {
|
||||||
|
0% { top: -10%; } 100% { top: 110%; }
|
||||||
|
}
|
||||||
|
.fx-vhs-glitch-block {
|
||||||
|
position: fixed; left: 0; right: 0;
|
||||||
|
background: rgba(0,255,255,0.4);
|
||||||
|
mix-blend-mode: difference;
|
||||||
|
pointer-events: none; z-index: 9310;
|
||||||
|
transform: translateX(5px);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 3. GLITCH */
|
||||||
|
html.fx-glitch body {
|
||||||
|
animation: fx-glitch-shake 3.5s infinite steps(1);
|
||||||
|
}
|
||||||
|
html.fx-glitch h1, html.fx-glitch h2, html.fx-glitch .panel-title {
|
||||||
|
position: relative;
|
||||||
|
animation: fx-glitch-chroma 2.8s infinite steps(1);
|
||||||
|
}
|
||||||
|
@keyframes fx-glitch-shake {
|
||||||
|
0%, 97%, 100% { transform: translate(0, 0); }
|
||||||
|
98% { transform: translate(2px, -1px); }
|
||||||
|
99% { transform: translate(-2px, 1px); }
|
||||||
|
}
|
||||||
|
@keyframes fx-glitch-chroma {
|
||||||
|
0%, 95%, 100% { text-shadow: none; }
|
||||||
|
96% { text-shadow: -2px 0 red, 2px 0 cyan; }
|
||||||
|
97% { text-shadow: 3px 0 lime, -3px 0 magenta; }
|
||||||
|
98% { text-shadow: -1px 0 red, 1px 0 cyan; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 4. RED ALERT */
|
||||||
|
html.fx-redalert body {
|
||||||
|
filter: sepia(1) hue-rotate(-50deg) saturate(4) brightness(0.95);
|
||||||
|
animation: fx-redalert-pulse 1s infinite;
|
||||||
|
}
|
||||||
|
@keyframes fx-redalert-pulse {
|
||||||
|
0%, 100% { box-shadow: inset 0 0 60px 10px rgba(255,0,0,0.3); }
|
||||||
|
50% { box-shadow: inset 0 0 120px 20px rgba(255,0,0,0.7); }
|
||||||
|
}
|
||||||
|
html.fx-redalert body::after {
|
||||||
|
content: '';
|
||||||
|
position: fixed; inset: 0;
|
||||||
|
border: 8px solid transparent;
|
||||||
|
box-shadow: inset 0 0 80px 20px rgba(255,0,0,0.5);
|
||||||
|
pointer-events: none; z-index: 9400;
|
||||||
|
animation: fx-redalert-pulse 1s infinite;
|
||||||
|
}
|
||||||
|
.fx-redalert-banner {
|
||||||
|
position: fixed; top: 0; left: 0; right: 0;
|
||||||
|
background: rgba(120,0,0,0.95); color: #fff;
|
||||||
|
text-align: center; padding: 8px;
|
||||||
|
font-family: 'Orbitron', monospace; letter-spacing: 4px;
|
||||||
|
font-size: 14px; font-weight: bold;
|
||||||
|
z-index: 9700;
|
||||||
|
animation: fx-redalert-blink 0.8s infinite;
|
||||||
|
border-bottom: 2px solid #ff3333;
|
||||||
|
}
|
||||||
|
@keyframes fx-redalert-blink {
|
||||||
|
0%, 49% { opacity: 1; }
|
||||||
|
50%, 100% { opacity: 0.4; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 5. INVERT */
|
||||||
|
html.fx-invert { filter: invert(1) hue-rotate(180deg); }
|
||||||
|
|
||||||
|
/* 6. BLUEPRINT */
|
||||||
|
html.fx-blueprint body {
|
||||||
|
filter: sepia(1) hue-rotate(180deg) saturate(3) brightness(0.9);
|
||||||
|
}
|
||||||
|
.fx-blueprint-grid {
|
||||||
|
position: fixed; inset: 0; pointer-events: none; z-index: 9050;
|
||||||
|
background-image:
|
||||||
|
linear-gradient(rgba(255,255,255,0.1) 1px, transparent 1px),
|
||||||
|
linear-gradient(90deg, rgba(255,255,255,0.1) 1px, transparent 1px);
|
||||||
|
background-size: 40px 40px;
|
||||||
|
mix-blend-mode: screen;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 7. TYPEWRITER (no special styling, just spans) */
|
||||||
|
.fx-typewriter-span { display: inline; }
|
||||||
|
|
||||||
|
/* 10. LOW GRAVITY */
|
||||||
|
html.fx-lowgrav .panel, html.fx-lowgrav .card {
|
||||||
|
transition: transform 1.2s ease-out !important;
|
||||||
|
}
|
||||||
|
.fx-lowgrav-bob {
|
||||||
|
animation: fx-lowgrav-bob 4s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
@keyframes fx-lowgrav-bob {
|
||||||
|
0%, 100% { transform: translateY(0); }
|
||||||
|
50% { transform: translateY(-6px); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 13. RAIN thunder flash */
|
||||||
|
html.fx-rain-flash body {
|
||||||
|
filter: brightness(1.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 15. FOG */
|
||||||
|
.fx-fog {
|
||||||
|
position: fixed; inset: 0; pointer-events: none; z-index: 9300;
|
||||||
|
background: radial-gradient(
|
||||||
|
circle 150px at var(--fx-fog-x, 50%) var(--fx-fog-y, 50%),
|
||||||
|
transparent 0%,
|
||||||
|
rgba(20,25,35,0.5) 40%,
|
||||||
|
rgba(10,15,25,0.92) 100%
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 16. NIGHT */
|
||||||
|
html.fx-night body {
|
||||||
|
filter: brightness(0.5) contrast(1.2);
|
||||||
|
cursor: crosshair;
|
||||||
|
}
|
||||||
|
.fx-night-spot {
|
||||||
|
position: fixed; inset: 0; pointer-events: none; z-index: 9300;
|
||||||
|
background: radial-gradient(
|
||||||
|
circle 200px at var(--fx-spot-x, 50%) var(--fx-spot-y, 50%),
|
||||||
|
rgba(255,240,180,0.3) 0%,
|
||||||
|
transparent 100%
|
||||||
|
);
|
||||||
|
mix-blend-mode: screen;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 17. UNDERWATER */
|
||||||
|
html.fx-underwater body {
|
||||||
|
filter: hue-rotate(180deg) saturate(1.3) brightness(0.85);
|
||||||
|
animation: fx-underwater-sway 6s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
@keyframes fx-underwater-sway {
|
||||||
|
0%, 100% { transform: skewX(0deg); }
|
||||||
|
50% { transform: skewX(0.5deg); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 18. DIMENSIONS */
|
||||||
|
html.fx-dimensions body {
|
||||||
|
transform: perspective(1000px)
|
||||||
|
rotateX(var(--fx-tilt-x, 0deg))
|
||||||
|
rotateY(var(--fx-tilt-y, 0deg));
|
||||||
|
transition: transform 0.3s ease-out;
|
||||||
|
transform-style: preserve-3d;
|
||||||
|
}
|
||||||
|
html.fx-dimensions .panel {
|
||||||
|
transform: translateZ(20px);
|
||||||
|
transform-style: preserve-3d;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 19. PORTAL */
|
||||||
|
.fx-portal {
|
||||||
|
position: fixed;
|
||||||
|
width: 150px; height: 150px;
|
||||||
|
border-radius: 50%;
|
||||||
|
overflow: hidden;
|
||||||
|
pointer-events: none;
|
||||||
|
z-index: 9400;
|
||||||
|
border: 2px solid #00ffc8;
|
||||||
|
box-shadow:
|
||||||
|
0 0 30px rgba(0,255,200,0.6),
|
||||||
|
inset 0 0 30px rgba(0,255,200,0.4);
|
||||||
|
animation: fx-portal-ripple 1.5s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
.fx-portal iframe {
|
||||||
|
width: 1200px; height: 900px;
|
||||||
|
border: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
@keyframes fx-portal-ripple {
|
||||||
|
0%, 100% { box-shadow: 0 0 30px rgba(0,255,200,0.6), inset 0 0 30px rgba(0,255,200,0.4); }
|
||||||
|
50% { box-shadow: 0 0 60px rgba(0,255,200,0.9), inset 0 0 60px rgba(0,255,200,0.7); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 20. RETRO */
|
||||||
|
html.retro-1995 body {
|
||||||
|
font-family: 'Comic Sans MS', 'Comic Sans', cursive !important;
|
||||||
|
background: #ffff99 !important;
|
||||||
|
color: #000 !important;
|
||||||
|
}
|
||||||
|
html.retro-1995 a { color: #0000ee !important; text-decoration: underline !important; }
|
||||||
|
html.retro-1995 a:visited { color: #551a8b !important; }
|
||||||
|
html.retro-1995 .panel {
|
||||||
|
border: 3px ridge #c0c0c0 !important;
|
||||||
|
background: #e0e0e0 !important;
|
||||||
|
color: #000 !important;
|
||||||
|
}
|
||||||
|
html.retro-1995 h1, html.retro-1995 h2, html.retro-1995 h3 {
|
||||||
|
color: #ff0066 !important;
|
||||||
|
text-shadow: 2px 2px 0 #ffff00 !important;
|
||||||
|
}
|
||||||
|
.fx-retro-1995-banner {
|
||||||
|
position: fixed; top: 0; left: 0; right: 0;
|
||||||
|
background: #ffcc00; color: #000;
|
||||||
|
text-align: center; padding: 6px;
|
||||||
|
font-family: 'Comic Sans MS', cursive;
|
||||||
|
font-weight: bold; font-size: 13px;
|
||||||
|
border-bottom: 3px ridge #ff0000;
|
||||||
|
z-index: 9700;
|
||||||
|
}
|
||||||
|
.fx-retro-1995-banner blink {
|
||||||
|
animation: fx-blink 1s steps(2) infinite;
|
||||||
|
}
|
||||||
|
@keyframes fx-blink { to { visibility: hidden; } }
|
||||||
|
|
||||||
|
html.retro-2005 body {
|
||||||
|
background: linear-gradient(180deg, #cfe8ff 0%, #9dc5f0 100%) !important;
|
||||||
|
font-family: 'Trebuchet MS', 'Verdana', sans-serif !important;
|
||||||
|
}
|
||||||
|
html.retro-2005 .panel {
|
||||||
|
background: linear-gradient(180deg, #ffffff 0%, #d6e8ff 100%) !important;
|
||||||
|
border: 1px solid #4a90d9 !important;
|
||||||
|
border-radius: 12px !important;
|
||||||
|
box-shadow: 0 4px 12px rgba(74,144,217,0.3), inset 0 1px 0 #fff !important;
|
||||||
|
color: #0a3a6a !important;
|
||||||
|
}
|
||||||
|
html.retro-2005 h1, html.retro-2005 h2 {
|
||||||
|
background: linear-gradient(180deg, #1a5eae, #0a3a6a) !important;
|
||||||
|
-webkit-background-clip: text !important;
|
||||||
|
background-clip: text !important;
|
||||||
|
color: transparent !important;
|
||||||
|
text-shadow: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html.retro-2015 body {
|
||||||
|
background: #fafafa !important;
|
||||||
|
color: #212121 !important;
|
||||||
|
font-family: 'Roboto', 'Arial', sans-serif !important;
|
||||||
|
}
|
||||||
|
html.retro-2015 .panel {
|
||||||
|
background: #fff !important;
|
||||||
|
border: none !important;
|
||||||
|
border-radius: 4px !important;
|
||||||
|
box-shadow: 0 2px 4px rgba(0,0,0,0.1), 0 4px 12px rgba(0,0,0,0.08) !important;
|
||||||
|
color: #212121 !important;
|
||||||
|
}
|
||||||
|
html.retro-2015 h1 { color: #ff5722 !important; font-weight: 300 !important; }
|
||||||
|
html.retro-2015 h2 { color: #2196f3 !important; font-weight: 300 !important; }
|
||||||
|
html.retro-2015 a { color: #2196f3 !important; }
|
||||||
|
|
||||||
|
/* 21. PARTY */
|
||||||
|
html.fx-party body {
|
||||||
|
animation: fx-party-hue 2s linear infinite;
|
||||||
|
}
|
||||||
|
@keyframes fx-party-hue {
|
||||||
|
0% { filter: hue-rotate(0deg); }
|
||||||
|
100% { filter: hue-rotate(360deg); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 22. GHOST */
|
||||||
|
html.fx-ghost * {
|
||||||
|
cursor: none !important;
|
||||||
|
}
|
||||||
|
html.fx-ghost body,
|
||||||
|
html.fx-ghost .panel,
|
||||||
|
html.fx-ghost a,
|
||||||
|
html.fx-ghost button,
|
||||||
|
html.fx-ghost h1, html.fx-ghost h2, html.fx-ghost h3, html.fx-ghost p, html.fx-ghost span {
|
||||||
|
transition: opacity 0.3s;
|
||||||
|
}
|
||||||
|
html.fx-ghost .panel,
|
||||||
|
html.fx-ghost h1, html.fx-ghost h2, html.fx-ghost h3,
|
||||||
|
html.fx-ghost p, html.fx-ghost a, html.fx-ghost button, html.fx-ghost li {
|
||||||
|
opacity: 0.08;
|
||||||
|
}
|
||||||
|
html.fx-ghost .panel:hover,
|
||||||
|
html.fx-ghost h1:hover, html.fx-ghost h2:hover, html.fx-ghost h3:hover,
|
||||||
|
html.fx-ghost p:hover, html.fx-ghost a:hover, html.fx-ghost button:hover, html.fx-ghost li:hover {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 25. HACKER */
|
||||||
|
html.fx-hacker body > *:not(canvas):not(script):not(style) {
|
||||||
|
filter: brightness(0.25);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reduced motion: neutralize heavy animations */
|
||||||
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
html.fx-crt, html.fx-redalert body, html.fx-party body,
|
||||||
|
.fx-vhs-roll, .fx-redalert-banner {
|
||||||
|
animation: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
<link rel="stylesheet" href="/css/style.css">
|
<link rel="stylesheet" href="/css/style.css">
|
||||||
<link rel="stylesheet" href="/css/section.css">
|
<link rel="stylesheet" href="/css/section.css">
|
||||||
<link rel="stylesheet" href="/css/contraband.css">
|
<link rel="stylesheet" href="/css/contraband.css">
|
||||||
|
<link rel="stylesheet" href="/css/sitewide-effects.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="scanline-overlay"></div>
|
<div class="scanline-overlay"></div>
|
||||||
|
|
@ -66,5 +67,6 @@
|
||||||
<script src="/js/nav.js"></script>
|
<script src="/js/nav.js"></script>
|
||||||
<script src="/js/clock.js"></script>
|
<script src="/js/clock.js"></script>
|
||||||
<script src="/js/contraband.js"></script>
|
<script src="/js/contraband.js"></script>
|
||||||
|
<script src="/js/sitewide-effects.js" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
<link rel="stylesheet" href="/css/style.css">
|
<link rel="stylesheet" href="/css/style.css">
|
||||||
<link rel="stylesheet" href="/css/section.css">
|
<link rel="stylesheet" href="/css/section.css">
|
||||||
<link rel="stylesheet" href="/css/contraband.css?v=20260404">
|
<link rel="stylesheet" href="/css/contraband.css?v=20260404">
|
||||||
|
<link rel="stylesheet" href="/css/sitewide-effects.css">
|
||||||
</head>
|
</head>
|
||||||
<body style="background:#0a0a0c;">
|
<body style="background:#0a0a0c;">
|
||||||
<div class="scanline-overlay"></div>
|
<div class="scanline-overlay"></div>
|
||||||
|
|
@ -63,5 +64,6 @@
|
||||||
<script src="/js/nav.js"></script>
|
<script src="/js/nav.js"></script>
|
||||||
<script src="/js/clock.js"></script>
|
<script src="/js/clock.js"></script>
|
||||||
<script src="/js/awesomelist.js?v=20260404"></script>
|
<script src="/js/awesomelist.js?v=20260404"></script>
|
||||||
|
<script src="/js/sitewide-effects.js" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700;900&family=JetBrains+Mono:wght@300;400;500;700&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700;900&family=JetBrains+Mono:wght@300;400;500;700&display=swap" rel="stylesheet">
|
||||||
<link rel="stylesheet" href="/css/style.css">
|
<link rel="stylesheet" href="/css/style.css">
|
||||||
<link rel="stylesheet" href="/css/section.css">
|
<link rel="stylesheet" href="/css/section.css">
|
||||||
|
<link rel="stylesheet" href="/css/sitewide-effects.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="scanline-overlay"></div>
|
<div class="scanline-overlay"></div>
|
||||||
|
|
@ -66,5 +67,6 @@
|
||||||
<script src="/js/wallet-connect.js"></script>
|
<script src="/js/wallet-connect.js"></script>
|
||||||
<script src="/js/nav.js"></script>
|
<script src="/js/nav.js"></script>
|
||||||
<script src="/js/clock.js"></script>
|
<script src="/js/clock.js"></script>
|
||||||
|
<script src="/js/sitewide-effects.js" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700;900&family=JetBrains+Mono:wght@300;400;500;700&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700;900&family=JetBrains+Mono:wght@300;400;500;700&display=swap" rel="stylesheet">
|
||||||
<link rel="stylesheet" href="/css/style.css">
|
<link rel="stylesheet" href="/css/style.css">
|
||||||
<link rel="stylesheet" href="/css/section.css">
|
<link rel="stylesheet" href="/css/section.css">
|
||||||
|
<link rel="stylesheet" href="/css/sitewide-effects.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="scanline-overlay"></div>
|
<div class="scanline-overlay"></div>
|
||||||
|
|
@ -78,5 +79,6 @@
|
||||||
<script src="/js/wallet-connect.js"></script>
|
<script src="/js/wallet-connect.js"></script>
|
||||||
<script src="/js/nav.js"></script>
|
<script src="/js/nav.js"></script>
|
||||||
<script src="/js/clock.js"></script>
|
<script src="/js/clock.js"></script>
|
||||||
|
<script src="/js/sitewide-effects.js" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@300;400;500;600;700&family=Orbitron:wght@400;500;600;700;800;900&family=Share+Tech+Mono&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@300;400;500;600;700&family=Orbitron:wght@400;500;600;700;800;900&family=Share+Tech+Mono&display=swap" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="/css/sitewide-effects.css">
|
||||||
</head>
|
</head>
|
||||||
<body class="section-page">
|
<body class="section-page">
|
||||||
|
|
||||||
|
|
@ -112,5 +113,6 @@
|
||||||
<script src="/js/main.js"></script>
|
<script src="/js/main.js"></script>
|
||||||
<script src="/js/nav.js"></script>
|
<script src="/js/nav.js"></script>
|
||||||
<script src="/js/leaderboards.js"></script>
|
<script src="/js/leaderboards.js"></script>
|
||||||
|
<script src="/js/sitewide-effects.js" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
<link rel="stylesheet" href="/css/style.css">
|
<link rel="stylesheet" href="/css/style.css">
|
||||||
<link rel="stylesheet" href="/css/section.css">
|
<link rel="stylesheet" href="/css/section.css">
|
||||||
<link rel="stylesheet" href="/css/changelog.css">
|
<link rel="stylesheet" href="/css/changelog.css">
|
||||||
|
<link rel="stylesheet" href="/css/sitewide-effects.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="scanline-overlay"></div>
|
<div class="scanline-overlay"></div>
|
||||||
|
|
@ -53,5 +54,6 @@
|
||||||
<script src="/js/nav.js"></script>
|
<script src="/js/nav.js"></script>
|
||||||
<script src="/js/clock.js"></script>
|
<script src="/js/clock.js"></script>
|
||||||
<script src="/js/changelog.js"></script>
|
<script src="/js/changelog.js"></script>
|
||||||
|
<script src="/js/sitewide-effects.js" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700;900&family=JetBrains+Mono:wght@300;400;500;700&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700;900&family=JetBrains+Mono:wght@300;400;500;700&display=swap" rel="stylesheet">
|
||||||
<link rel="stylesheet" href="/css/style.css">
|
<link rel="stylesheet" href="/css/style.css">
|
||||||
<link rel="stylesheet" href="/css/section.css">
|
<link rel="stylesheet" href="/css/section.css">
|
||||||
|
<link rel="stylesheet" href="/css/sitewide-effects.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="scanline-overlay"></div>
|
<div class="scanline-overlay"></div>
|
||||||
|
|
@ -66,5 +67,6 @@
|
||||||
<script src="/js/wallet-connect.js"></script>
|
<script src="/js/wallet-connect.js"></script>
|
||||||
<script src="/js/nav.js"></script>
|
<script src="/js/nav.js"></script>
|
||||||
<script src="/js/clock.js"></script>
|
<script src="/js/clock.js"></script>
|
||||||
|
<script src="/js/sitewide-effects.js" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
<link rel="stylesheet" href="/css/style.css">
|
<link rel="stylesheet" href="/css/style.css">
|
||||||
<link rel="stylesheet" href="/css/section.css">
|
<link rel="stylesheet" href="/css/section.css">
|
||||||
<link rel="stylesheet" href="/css/telemetry.css">
|
<link rel="stylesheet" href="/css/telemetry.css">
|
||||||
|
<link rel="stylesheet" href="/css/sitewide-effects.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="scanline-overlay"></div>
|
<div class="scanline-overlay"></div>
|
||||||
|
|
@ -226,5 +227,6 @@
|
||||||
<script src="/js/nav.js"></script>
|
<script src="/js/nav.js"></script>
|
||||||
<script src="/js/clock.js"></script>
|
<script src="/js/clock.js"></script>
|
||||||
<script src="/js/telemetry.js"></script>
|
<script src="/js/telemetry.js"></script>
|
||||||
|
<script src="/js/sitewide-effects.js" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@300;400;500;600;700&family=Orbitron:wght@400;500;600;700;800;900&family=Share+Tech+Mono&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@300;400;500;600;700&family=Orbitron:wght@400;500;600;700;800;900&family=Share+Tech+Mono&display=swap" rel="stylesheet">
|
||||||
<script src="https://unpkg.com/globe.gl@2.45.1/dist/globe.gl.min.js"></script>
|
<script src="https://unpkg.com/globe.gl@2.45.1/dist/globe.gl.min.js"></script>
|
||||||
|
<link rel="stylesheet" href="/css/sitewide-effects.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<!-- Scanline overlay -->
|
<!-- Scanline overlay -->
|
||||||
|
|
@ -597,5 +598,6 @@
|
||||||
<script src="/js/globe.js"></script>
|
<script src="/js/globe.js"></script>
|
||||||
<script src="/js/processes.js"></script>
|
<script src="/js/processes.js"></script>
|
||||||
<script src="/js/clock.js"></script>
|
<script src="/js/clock.js"></script>
|
||||||
|
<script src="/js/sitewide-effects.js" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
229
js/chat-cli.js
229
js/chat-cli.js
|
|
@ -10,7 +10,6 @@
|
||||||
const HIST_KEY = 'jaeCliHist';
|
const HIST_KEY = 'jaeCliHist';
|
||||||
let cmdHistory = [];
|
let cmdHistory = [];
|
||||||
let devMode = false;
|
let devMode = false;
|
||||||
let matrixActive = false;
|
|
||||||
let sessionCmdCount = 0;
|
let sessionCmdCount = 0;
|
||||||
let sessionPerCmd = {};
|
let sessionPerCmd = {};
|
||||||
let mode = null; // null | 'ssh' | 'adventure' | 'ttyper'
|
let mode = null; // null | 'ssh' | 'adventure' | 'ttyper'
|
||||||
|
|
@ -190,6 +189,15 @@
|
||||||
' /adventure cyberpunk text adventure',
|
' /adventure cyberpunk text adventure',
|
||||||
' /ttyper typing speed test',
|
' /ttyper typing speed test',
|
||||||
'',
|
'',
|
||||||
|
'— EFFECTS (sitewide visual overlays) —',
|
||||||
|
' /crt /vhs /glitch /redalert /invert /blueprint /typewriter',
|
||||||
|
' /gravity /earthquake /lowgravity /melt /shuffle',
|
||||||
|
' /rain /snow /fog /night /underwater',
|
||||||
|
' /dimensions /portal /retro <1995|2005|2015|now>',
|
||||||
|
' /partymode /ghostmode /quantum /sneak /hacker',
|
||||||
|
' /matrix /cmatrix matrix rain overlays',
|
||||||
|
' /effects show active · /effects off · /effects all (chaos)',
|
||||||
|
'',
|
||||||
'— STATS —',
|
'— STATS —',
|
||||||
' /achievements your unlocked commands',
|
' /achievements your unlocked commands',
|
||||||
' /leaderboard session & all-time stats',
|
' /leaderboard session & all-time stats',
|
||||||
|
|
@ -334,11 +342,10 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
commands.matrix = function () {
|
commands.matrix = function () {
|
||||||
matrixActive = !matrixActive;
|
if (!window.__jaeEffects) return 'effects module not loaded.';
|
||||||
toggleMatrix(matrixActive);
|
const on = window.__jaeEffects.toggle('matrix');
|
||||||
return matrixActive
|
return on ? 'Matrix rain enabled. Follow the white rabbit.'
|
||||||
? 'Matrix rain enabled. Follow the white rabbit.'
|
: 'Matrix rain disabled. Back to the desert of the real.';
|
||||||
: 'Matrix rain disabled. Back to the desert of the real.';
|
|
||||||
};
|
};
|
||||||
|
|
||||||
commands.clear = function () {
|
commands.clear = function () {
|
||||||
|
|
@ -837,79 +844,100 @@
|
||||||
].filter(Boolean));
|
].filter(Boolean));
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─── /cmatrix — enhanced matrix rain ─────────────
|
// ─── /cmatrix — migrated to sitewide-effects.js ──
|
||||||
let cmatrixCanvas = null, cmatrixRAF = null, cmatrixAudio = null, cmatrixStart = 0;
|
|
||||||
function toggleCMatrix(on) {
|
|
||||||
if (on) {
|
|
||||||
cmatrixCanvas = document.createElement('canvas');
|
|
||||||
cmatrixCanvas.id = 'cmatrixRain';
|
|
||||||
Object.assign(cmatrixCanvas.style, {
|
|
||||||
position: 'fixed', inset: '0', width: '100%', height: '100%',
|
|
||||||
pointerEvents: 'none', zIndex: '8', opacity: '0.32',
|
|
||||||
});
|
|
||||||
document.body.appendChild(cmatrixCanvas);
|
|
||||||
const ctx = cmatrixCanvas.getContext('2d');
|
|
||||||
function resize() { cmatrixCanvas.width = innerWidth; cmatrixCanvas.height = innerHeight; }
|
|
||||||
resize();
|
|
||||||
window.addEventListener('resize', resize);
|
|
||||||
const chars = 'アイウエオカキクケコサシスセソタチツテトナニヌネノ01JAESWIFT░▒▓█'.split('');
|
|
||||||
const size = 14;
|
|
||||||
const cols = Math.floor(cmatrixCanvas.width / size);
|
|
||||||
const drops = new Array(cols).fill(0).map(() => Math.random() * 40);
|
|
||||||
cmatrixStart = Date.now();
|
|
||||||
try {
|
|
||||||
const AC = window.AudioContext || window.webkitAudioContext;
|
|
||||||
if (AC) cmatrixAudio = new AC();
|
|
||||||
} catch (e) {}
|
|
||||||
let tick = 0;
|
|
||||||
function draw() {
|
|
||||||
const t = (Date.now() - cmatrixStart) / 1000;
|
|
||||||
const phase = (t % 30) / 30;
|
|
||||||
const speed = 1 + phase * 2.5;
|
|
||||||
ctx.fillStyle = 'rgba(0, 0, 0, 0.08)';
|
|
||||||
ctx.fillRect(0, 0, cmatrixCanvas.width, cmatrixCanvas.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 % 2 === 0) ? '#00ff66' : '#33ddff';
|
|
||||||
ctx.fillText(ch, i * size, drops[i] * size);
|
|
||||||
if (drops[i] * size > cmatrixCanvas.height && Math.random() > 0.97) drops[i] = 0;
|
|
||||||
drops[i] += speed;
|
|
||||||
}
|
|
||||||
tick++;
|
|
||||||
if (cmatrixAudio && tick % 4 === 0) {
|
|
||||||
try {
|
|
||||||
const osc = cmatrixAudio.createOscillator();
|
|
||||||
const g = cmatrixAudio.createGain();
|
|
||||||
osc.type = 'square';
|
|
||||||
osc.frequency.value = 1600 + Math.random() * 800;
|
|
||||||
g.gain.value = 0.0035;
|
|
||||||
osc.connect(g); g.connect(cmatrixAudio.destination);
|
|
||||||
osc.start();
|
|
||||||
osc.stop(cmatrixAudio.currentTime + 0.02);
|
|
||||||
} catch (e) {}
|
|
||||||
}
|
|
||||||
cmatrixRAF = requestAnimationFrame(draw);
|
|
||||||
}
|
|
||||||
draw();
|
|
||||||
} else {
|
|
||||||
if (cmatrixRAF) cancelAnimationFrame(cmatrixRAF);
|
|
||||||
if (cmatrixCanvas) cmatrixCanvas.remove();
|
|
||||||
if (cmatrixAudio) { try { cmatrixAudio.close(); } catch(e){} }
|
|
||||||
cmatrixCanvas = null; cmatrixAudio = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let cmatrixActive = false;
|
|
||||||
commands.cmatrix = function () {
|
commands.cmatrix = function () {
|
||||||
cmatrixActive = !cmatrixActive;
|
if (!window.__jaeEffects) return 'effects module not loaded.';
|
||||||
toggleCMatrix(cmatrixActive);
|
const on = window.__jaeEffects.toggle('cmatrix');
|
||||||
return cmatrixActive
|
return on ? 'CMATRIX engaged. Dual-colour rain with audio. Toggle off with /cmatrix.'
|
||||||
? 'CMATRIX engaged. Dual-colour rain with audio. Toggle off with /cmatrix.'
|
: 'CMATRIX disengaged.';
|
||||||
: 'CMATRIX disengaged.';
|
};
|
||||||
|
|
||||||
|
// ─── EFFECTS SUITE — thin wrappers over window.__jaeEffects ──
|
||||||
|
function fx(name, onMsg, offMsg) {
|
||||||
|
return function () {
|
||||||
|
if (!window.__jaeEffects) return 'effects module not loaded.';
|
||||||
|
const on = window.__jaeEffects.toggle(name);
|
||||||
|
return on ? onMsg : offMsg;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
commands.crt = fx('crt', 'CRT mode engaged. [VINTAGE BEAM ONLINE]', 'CRT mode disengaged.');
|
||||||
|
commands.vhs = fx('vhs', 'VHS tape loaded. Tracking...', 'VHS ejected.');
|
||||||
|
commands.glitch = fx('glitch', 'Reality corrupted. Good luck.', 'Reality stabilised.');
|
||||||
|
commands.redalert = fx('redalert', '⚠ DEFCON 1. Battle stations. ⚠', 'Red alert stood down.');
|
||||||
|
commands.red = commands.redalert;
|
||||||
|
commands.invert = fx('invert', 'Polarity inverted.', 'Polarity restored.');
|
||||||
|
commands.blueprint = fx('blueprint', 'Blueprint mode. Architect vision enabled.', 'Blueprint mode disabled.');
|
||||||
|
commands.typewriter = fx('typewriter', 'Typewriter engaged. Retyping...', 'Typewriter reset.');
|
||||||
|
commands.gravity = fx('gravity', '🌍 Gravity enabled. Everything falls.', '🌍 Gravity disabled. Restored.');
|
||||||
|
commands.earthquake = fx('earthquake', '🌋 7.5 magnitude — hold on (10s).', '🌋 Earthquake over.');
|
||||||
|
commands.lowgravity = fx('lowgravity', '🚀 Low-gravity environment active.', '🚀 Gravity normalised.');
|
||||||
|
commands.melt = fx('melt', 'Pixels liquifying...', 'Reformed.');
|
||||||
|
commands.shuffle = fx('shuffle', 'Words scrambled.', 'Words restored.');
|
||||||
|
commands.rain = fx('rain', '🌧️ Rain enabled. Manchester vibes.', '🌧️ Rain stopped.');
|
||||||
|
commands.snow = fx('snow', '❄️ Snow enabled. Winter is here.', '❄️ Thaw complete.');
|
||||||
|
commands.fog = fx('fog', '🌫️ Fog of war. Mind the torchlight.', '🌫️ Fog lifted.');
|
||||||
|
commands.night = fx('night', '🌙 Night-vision enabled. Spotlight tracking cursor.', '🌙 Dawn.');
|
||||||
|
commands.underwater = fx('underwater', '🌊 Submerged. Pressure nominal.', '🌊 Surfaced.');
|
||||||
|
commands.dimensions = fx('dimensions', '🔺 3D tilt engaged. Follow the cursor.', '🔺 2D restored.');
|
||||||
|
commands.portal = fx('portal', '🌀 Portal opened. Cursor is now a window.', '🌀 Portal closed.');
|
||||||
|
commands.partymode = fx('partymode', '🎉 PARTY MODE. Can someone get the disco ball?', '🎉 Party over. Clean-up on aisle 4.');
|
||||||
|
commands.ghostmode = fx('ghostmode', '👻 Ghost mode. Only the brave shall see.', '👻 Visible again.');
|
||||||
|
commands.quantum = fx('quantum', '⚛️ Quantum uncertainty enabled. Panels teleporting.', '⚛️ Observation collapsed. Panels reset.');
|
||||||
|
commands.sneak = fx('sneak', 'All labels redacted. █████.', 'Labels restored.');
|
||||||
|
commands.hacker = fx('hacker', 'H4X0R M0D3 3NG4G3D. We are in.', 'Exited.');
|
||||||
|
|
||||||
|
commands.retro = function (args) {
|
||||||
|
if (!window.__jaeEffects) return 'effects module not loaded.';
|
||||||
|
const year = (args[0] || '').toLowerCase();
|
||||||
|
const fx = window.__jaeEffects.registry.retro;
|
||||||
|
if (!year || year === 'now' || year === 'off') {
|
||||||
|
fx.disable();
|
||||||
|
return 'Retro mode disabled. Welcome back to 2026.';
|
||||||
|
}
|
||||||
|
if (!['1995','2005','2015'].includes(year)) {
|
||||||
|
return 'usage: /retro <1995|2005|2015|now>';
|
||||||
|
}
|
||||||
|
fx.disable();
|
||||||
|
fx.enable(year);
|
||||||
|
const flavour = {
|
||||||
|
'1995': 'Welcome to the World Wide Web! 🌐 Best viewed in Netscape Navigator.',
|
||||||
|
'2005': 'Web 2.0, baby. Glossy gradients incoming.',
|
||||||
|
'2015': 'Material Design. Clean. Flat. Safe.',
|
||||||
|
};
|
||||||
|
return flavour[year];
|
||||||
|
};
|
||||||
|
|
||||||
|
commands.effects = function (args) {
|
||||||
|
if (!window.__jaeEffects) return 'effects module not loaded.';
|
||||||
|
const sub = (args[0] || '').toLowerCase();
|
||||||
|
if (sub === 'off') {
|
||||||
|
const n = window.__jaeEffects.active().length;
|
||||||
|
window.__jaeEffects.disableAll();
|
||||||
|
return `Disabled ${n} effect(s).`;
|
||||||
|
}
|
||||||
|
if (sub === 'all') {
|
||||||
|
const list = window.__jaeEffects.list().filter(n => n !== 'retro');
|
||||||
|
list.forEach(n => { try { window.__jaeEffects.enable(n); } catch(e){} });
|
||||||
|
return '⚠ CHAOS MODE. ' + list.length + ' effects enabled simultaneously. RIP your CPU.';
|
||||||
|
}
|
||||||
|
const active = window.__jaeEffects.active();
|
||||||
|
if (!active.length) return 'No effects currently active. Try /help for the EFFECTS list.';
|
||||||
|
const lines = [
|
||||||
|
'═══ ACTIVE EFFECTS ═══',
|
||||||
|
'┌─────────────────────┬────────┐',
|
||||||
|
'│ NAME │ STATUS │',
|
||||||
|
'├─────────────────────┼────────┤',
|
||||||
|
];
|
||||||
|
active.forEach(n => {
|
||||||
|
lines.push('│ ' + n.padEnd(20) + '│ ACTIVE │');
|
||||||
|
});
|
||||||
|
lines.push('└─────────────────────┴────────┘');
|
||||||
|
lines.push(`Total: ${active.length} · /effects off to disable all`);
|
||||||
|
return lines.join('\n');
|
||||||
};
|
};
|
||||||
|
|
||||||
// ─── /achievements ───────────────────────────────
|
// ─── /achievements ───────────────────────────────
|
||||||
const TOTAL_COMMANDS = 24;
|
const TOTAL_COMMANDS = 50;
|
||||||
commands.achievements = function () {
|
commands.achievements = function () {
|
||||||
const unlocked = [...achievements].sort();
|
const unlocked = [...achievements].sort();
|
||||||
const n = unlocked.length;
|
const n = unlocked.length;
|
||||||
|
|
@ -964,49 +992,8 @@
|
||||||
]);
|
]);
|
||||||
};
|
};
|
||||||
|
|
||||||
// ─── Matrix rain overlay ─────────────────────────
|
// ─── Matrix rain migrated to sitewide-effects.js ──
|
||||||
let matrixCanvas = null;
|
|
||||||
let matrixRAF = null;
|
|
||||||
function toggleMatrix(on) {
|
|
||||||
if (on) {
|
|
||||||
matrixCanvas = document.createElement('canvas');
|
|
||||||
matrixCanvas.id = 'matrixRain';
|
|
||||||
Object.assign(matrixCanvas.style, {
|
|
||||||
position: 'fixed', inset: '0', width: '100%', height: '100%',
|
|
||||||
pointerEvents: 'none', zIndex: '7', opacity: '0.18',
|
|
||||||
});
|
|
||||||
document.body.appendChild(matrixCanvas);
|
|
||||||
const ctx = matrixCanvas.getContext('2d');
|
|
||||||
function resize() {
|
|
||||||
matrixCanvas.width = window.innerWidth;
|
|
||||||
matrixCanvas.height = window.innerHeight;
|
|
||||||
}
|
|
||||||
resize();
|
|
||||||
window.addEventListener('resize', resize);
|
|
||||||
const chars = 'アイウエオカキクケコサシスセソタチツテトナニヌネノ01JAESWIFT'.split('');
|
|
||||||
const size = 16;
|
|
||||||
const cols = Math.floor(matrixCanvas.width / size);
|
|
||||||
const drops = new Array(cols).fill(1);
|
|
||||||
function draw() {
|
|
||||||
ctx.fillStyle = 'rgba(0, 0, 0, 0.06)';
|
|
||||||
ctx.fillRect(0, 0, matrixCanvas.width, matrixCanvas.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 > matrixCanvas.height && Math.random() > 0.975) drops[i] = 0;
|
|
||||||
drops[i]++;
|
|
||||||
}
|
|
||||||
matrixRAF = requestAnimationFrame(draw);
|
|
||||||
}
|
|
||||||
draw();
|
|
||||||
} else {
|
|
||||||
if (matrixRAF) cancelAnimationFrame(matrixRAF);
|
|
||||||
if (matrixCanvas) matrixCanvas.remove();
|
|
||||||
matrixCanvas = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ─── Konami Code → Developer Mode ────────────────
|
// ─── Konami Code → Developer Mode ────────────────
|
||||||
const KONAMI = ['ArrowUp','ArrowUp','ArrowDown','ArrowDown','ArrowLeft','ArrowRight','ArrowLeft','ArrowRight','b','a'];
|
const KONAMI = ['ArrowUp','ArrowUp','ArrowDown','ArrowDown','ArrowLeft','ArrowRight','ArrowLeft','ArrowRight','b','a'];
|
||||||
|
|
@ -1096,8 +1083,7 @@
|
||||||
// ─── Boss key — Escape / Ctrl+Shift+B ────────────
|
// ─── Boss key — Escape / Ctrl+Shift+B ────────────
|
||||||
function bossKeyActivate() {
|
function bossKeyActivate() {
|
||||||
try {
|
try {
|
||||||
if (matrixActive) { matrixActive = false; toggleMatrix(false); }
|
if (window.__jaeEffects) { try { window.__jaeEffects.disableAll(); } catch(e){} }
|
||||||
if (cmatrixActive) { cmatrixActive = false; toggleCMatrix(false); }
|
|
||||||
const badge = document.getElementById('devModeBadge');
|
const badge = document.getElementById('devModeBadge');
|
||||||
if (badge) badge.style.display = 'none';
|
if (badge) badge.style.display = 'none';
|
||||||
const toasts = document.querySelectorAll('.jae-cli-toast');
|
const toasts = document.querySelectorAll('.jae-cli-toast');
|
||||||
|
|
@ -1123,7 +1109,8 @@
|
||||||
const isCtrlShiftB = (e.ctrlKey && e.shiftKey && (e.key === 'B' || e.key === 'b'));
|
const isCtrlShiftB = (e.ctrlKey && e.shiftKey && (e.key === 'B' || e.key === 'b'));
|
||||||
if (isEsc || isCtrlShiftB) {
|
if (isEsc || isCtrlShiftB) {
|
||||||
// Don't nuke on Escape while user is typing in chat unless something is actually "hot"
|
// Don't nuke on Escape while user is typing in chat unless something is actually "hot"
|
||||||
const hot = matrixActive || cmatrixActive || document.getElementById('devModeBadge') || document.querySelector('.jae-cli-toast');
|
const anyFx = window.__jaeEffects && window.__jaeEffects.active().length > 0;
|
||||||
|
const hot = anyFx || document.getElementById('devModeBadge') || document.querySelector('.jae-cli-toast');
|
||||||
if (isCtrlShiftB || (isEsc && hot)) {
|
if (isCtrlShiftB || (isEsc && hot)) {
|
||||||
bossKeyActivate();
|
bossKeyActivate();
|
||||||
if (isCtrlShiftB) e.preventDefault();
|
if (isCtrlShiftB) e.preventDefault();
|
||||||
|
|
|
||||||
1143
js/sitewide-effects.js
Normal file
1143
js/sitewide-effects.js
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -4,8 +4,10 @@
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta http-equiv="refresh" content="0;url=/depot/recon">
|
<meta http-equiv="refresh" content="0;url=/depot/recon">
|
||||||
<title>Redirecting to RECON...</title>
|
<title>Redirecting to RECON...</title>
|
||||||
|
<link rel="stylesheet" href="/css/sitewide-effects.css">
|
||||||
</head>
|
</head>
|
||||||
<body style="background:#0a0a0c;">
|
<body style="background:#0a0a0c;">
|
||||||
<p>Redirecting to <a href="/depot/recon">RECON</a>...</p>
|
<p>Redirecting to <a href="/depot/recon">RECON</a>...</p>
|
||||||
|
<script src="/js/sitewide-effects.js" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
<link rel="stylesheet" href="/css/section.css">
|
<link rel="stylesheet" href="/css/section.css">
|
||||||
<link rel="stylesheet" href="/css/radar.css?v=20260415">
|
<link rel="stylesheet" href="/css/radar.css?v=20260415">
|
||||||
<style>body{background:#0a0a0a;}</style>
|
<style>body{background:#0a0a0a;}</style>
|
||||||
|
<link rel="stylesheet" href="/css/sitewide-effects.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="scanline-overlay"></div>
|
<div class="scanline-overlay"></div>
|
||||||
|
|
@ -139,5 +140,6 @@
|
||||||
<script src="/js/nav.js"></script>
|
<script src="/js/nav.js"></script>
|
||||||
<script src="/js/clock.js"></script>
|
<script src="/js/clock.js"></script>
|
||||||
<script src="/js/radar.js?v=20260415"></script>
|
<script src="/js/radar.js?v=20260415"></script>
|
||||||
|
<script src="/js/sitewide-effects.js" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue