/* MATRIX RAIN BACKGROUND */ (() => { const canvas = document.getElementById("matrix"); const ctx = canvas.getContext("2d"); let w = (canvas.width = innerWidth); let h = (canvas.height = innerHeight); const cols = Math.floor(w / 16) + 1; const ypos = Array(cols).fill(0); function matrix() { ctx.fillStyle = "rgba(0,0,0,0.08)"; ctx.fillRect(0, 0, w, h); ctx.fillStyle = "#0f0"; ctx.font = "14px monospace"; for (let i = 0; i < ypos.length; i++) { const text = String.fromCharCode(33 + Math.random() * 94); const x = i * 16; ctx.fillText(text, x, ypos[i] * 16); if (ypos[i] * 16 > h && Math.random() > 0.975) ypos[i] = 0; ypos[i]++; } } let raf; function loop() { matrix(); raf = requestAnimationFrame(loop); } loop(); addEventListener("resize", () => { cancelAnimationFrame(raf); w = canvas.width = innerWidth; h = canvas.height = innerHeight; }); })(); /* LOGIN BEHAVIOR & EFFECTS */ (() => { const form = document.getElementById("loginForm"); const log = document.getElementById("log"); const status = document.getElementById("status"); const demoBtn = document.getElementById("demoBtn"); const userInput = document.getElementById("user"); const passInput = document.getElementById("pass"); // small fake auth DB (for demo only) const CRED = { user: "neo", pass: "trinity" }; // "typing" helper used to show log messages function typeLog(text, speed = 20, cb) { log.textContent = ""; let i = 0; const t = setInterval(() => { log.textContent += text[i++] ?? ""; if (i >= text.length) { clearInterval(t); if (cb) setTimeout(cb, 200); } }, speed); } // show animated status (progress -> result) function runCheck(success) { status.textContent = ""; let pct = 0; const id = setInterval(() => { pct += Math.floor(Math.random() * 18) + 6; // ramp if (pct > 100) pct = 100; status.textContent = `scanning... ${pct}%`; if (pct >= 100) { clearInterval(id); if (success) accessGranted(); else accessDenied(); } }, 180); } // success animation function accessGranted() { status.textContent = "ACCESS GRANTED — Welcome."; status.style.color = "#fd8b19ff"; document.body.animate( [{ filter: "hue-rotate(0deg)" }, { filter: "hue-rotate(50deg)" }], { duration: 900, iterations: 1 } ); // small glow effect on terminal const term = document.querySelector(".terminal"); term.animate( [ { boxShadow: "0 10px 40px rgba(0,255,127,0.04)" }, { boxShadow: "0 30px 90px rgba(0,255,127,0.25)" } ], { duration: 500, fill: "forwards" } ); } // denied / shake effect function accessDenied() { status.textContent = "ACCESS DENIED — Invalid credentials."; status.style.color = "#ff0f0fff"; const term = document.querySelector(".terminal"); term.animate( [ { transform: "translateX(0px)" }, { transform: "translateX(-8px)" }, { transform: "translateX(8px)" }, { transform: "translateX(-6px)" }, { transform: "translateX(6px)" }, { transform: "translateX(0px)" } ], { duration: 450 } ); } // Form submit handler form.addEventListener("submit", (e) => { e.preventDefault(); status.style.color = ""; const u = userInput.value.trim(); const p = passInput.value; if (!u || !p) { typeLog("enter user & passcode first..."); return; } typeLog(`initiating secure handshake for ${u}...`, 20, () => { runCheck(u === CRED.user && p === CRED.pass); }); }); // Demo auto-fill demoBtn.addEventListener("click", () => { userInput.value = ""; passInput.value = ""; typeText(userInput, "neo", 80, () => { setTimeout( () => typeText(passInput, "trinity", 80, () => { // auto submit form.dispatchEvent(new Event("submit", { cancelable: true })); }), 250 ); }); }); // helper to simulate typing into an input function typeText(el, txt, speed = 80, cb) { el.focus(); el.value = ""; let i = 0; const t = setInterval(() => { el.value += txt[i++] ?? ""; if (i >= txt.length) { clearInterval(t); if (cb) cb(); } }, speed); } // submit when user presses Enter on inputs [userInput, passInput].forEach((inp) => { inp.addEventListener("keydown", (ev) => { if (ev.key === "Enter") { ev.preventDefault(); form.requestSubmit(); } }); }); // initial boot text setTimeout( () => typeLog("security core loaded. awaiting credentials.\n", 18), 700 ); })();