NEW RELEASE

This commit is contained in:
root
2026-07-04 14:25:02 +00:00
parent 1effe704f1
commit d92a0dc412
9 changed files with 3392 additions and 0 deletions

589
index.html Normal file
View File

@@ -0,0 +1,589 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="./support.js"></script>
</head>
<body>
<x-dc>
<helmet>
<title>Muaz Bhutta — Cloud &amp; Network Infrastructure Engineer</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@500;600;700&amp;family=JetBrains+Mono:wght@400;500;600&amp;display=swap" rel="stylesheet">
<style>
html, body { margin:0; padding:0; background:#080d1f; scroll-behavior:smooth; }
* { box-sizing:border-box; }
::selection { background:#2ee6ff; color:#04060d; }
@keyframes blink { 0%,49% { opacity:1; } 50%,100% { opacity:0; } }
@keyframes pulseDot { 0%,100% { box-shadow:0 0 0 0 rgba(46,230,255,0.5); } 50% { box-shadow:0 0 0 8px rgba(46,230,255,0); } }
@keyframes hopGlow { 0%, 12% { opacity:1; filter:drop-shadow(0 0 12px currentColor); } 20%, 100% { opacity:0.35; filter:none; } }
@keyframes floaty { 0%,100% { transform:translateY(0); } 50% { transform:translateY(-10px); } }
@keyframes scan { 0% { transform:translateY(-100%); } 100% { transform:translateY(1200%); } }
@keyframes dashMove { to { stroke-dashoffset:-24; } }
@keyframes gradientShift { 0% { background-position:0% 50%; } 50% { background-position:100% 50%; } 100% { background-position:0% 50%; } }
/* Mobile responsiveness */
#nav-toggle { display:none; }
@media (max-width: 760px) {
#nav-links { display:none !important; }
#nav-toggle { display:flex !important; }
#hero-status { position:static !important; margin-top:40px; animation:none !important; max-width:100%; }
#hero-inner { padding:100px 24px 8px !important; order:1; }
#hero-section { flex-direction:column; align-items:stretch; min-height:0 !important; padding-bottom:24px; }
#hero-canvas-wrap { position:relative !important; inset:auto !important; width:100%; height:340px; order:2; }
#hops-line { display:none !important; }
#hops-grid { grid-template-columns:1fr !important; gap:28px !important; }
#hops-grid > div { flex-direction:row !important; text-align:left !important; align-items:flex-start !important; }
#hops-grid > div > div:first-child { flex:0 0 auto; margin-top:2px; }
}
@keyframes ticker { from { transform:translateX(0); } to { transform:translateX(-50%); } }
</style>
</helmet>
<div style="min-height:100vh;background:#080d1f;color:#e8f0ff;font-family:'Space Grotesk',sans-serif;overflow-x:hidden;position:relative;">
<!-- Ambient aurora background -->
<div style="position:fixed;inset:0;pointer-events:none;z-index:0;background:radial-gradient(ellipse 55% 40% at 15% 0%, rgba(46,230,255,0.10), transparent 65%), radial-gradient(ellipse 50% 45% at 90% 20%, rgba(139,123,255,0.12), transparent 65%), radial-gradient(ellipse 60% 40% at 50% 60%, rgba(255,79,216,0.06), transparent 70%), radial-gradient(ellipse 55% 35% at 10% 95%, rgba(46,230,255,0.08), transparent 65%), radial-gradient(ellipse 45% 35% at 95% 90%, rgba(182,255,61,0.05), transparent 70%);"></div>
<div style="position:fixed;inset:0;pointer-events:none;z-index:0;background:linear-gradient(180deg, rgba(8,13,31,0) 0%, rgba(8,13,31,0.35) 100%);"></div>
<div style="position:relative;z-index:1;">
<!-- NAV -->
<header data-screen-label="Nav" style="position:fixed;top:0;left:0;right:0;z-index:50;backdrop-filter:blur(14px);background:rgba(13,20,48,0.65);border-bottom:1px solid rgba(255,255,255,0.07);">
<div style="max-width:1200px;margin:0 auto;display:flex;align-items:center;justify-content:space-between;padding:16px 32px;">
<div id="nav-prompt" style="font-family:'JetBrains Mono',monospace;font-size:14px;color:#2ee6ff;white-space:nowrap;">muaz@infra:<span style="color:#ff4fd8;">~</span>$ <span style="color:#e8f0ff;">whoami</span><span style="display:inline-block;width:8px;height:15px;background:#2ee6ff;margin-left:6px;vertical-align:middle;animation:blink 1.1s step-end infinite;"></span></div>
<nav id="nav-links" style="display:flex;gap:28px;font-size:14px;white-space:nowrap;">
<a href="#about" style="color:#8ea2c0;text-decoration:none;" style-hover="color:#2ee6ff;">About</a>
<a href="#skills" style="color:#8ea2c0;text-decoration:none;" style-hover="color:#8b7bff;">Skills</a>
<a href="#projects" style="color:#8ea2c0;text-decoration:none;" style-hover="color:#ff4fd8;">Projects</a>
<a href="#pipeline" style="color:#8ea2c0;text-decoration:none;" style-hover="color:#b6ff3d;">Pipeline</a>
<a href="#contact" style="color:#8ea2c0;text-decoration:none;" style-hover="color:#ffb84d;">Contact</a>
</nav>
<button id="nav-toggle" onClick="{{ toggleMenu }}" aria-label="Menu" style="display:none;align-items:center;justify-content:center;width:44px;height:44px;border-radius:8px;border:1px solid rgba(46,230,255,0.35);background:rgba(46,230,255,0.06);color:#2ee6ff;font-size:20px;cursor:pointer;padding:0;">{{ menuIcon }}</button>
</div>
<sc-if value="{{ menuOpen }}" hint-placeholder-val="{{ false }}">
<nav style="display:flex;flex-direction:column;padding:8px 20px 20px;gap:4px;border-top:1px solid rgba(255,255,255,0.07);background:rgba(13,20,48,0.9);backdrop-filter:blur(14px);">
<a href="#about" onClick="{{ closeMenu }}" style="color:#e8f0ff;text-decoration:none;font-size:16px;padding:14px 12px;border-radius:8px;display:flex;align-items:center;gap:12px;" style-hover="background:rgba(46,230,255,0.08);"><span style="width:7px;height:7px;border-radius:50%;background:#2ee6ff;"></span>About</a>
<a href="#skills" onClick="{{ closeMenu }}" style="color:#e8f0ff;text-decoration:none;font-size:16px;padding:14px 12px;border-radius:8px;display:flex;align-items:center;gap:12px;" style-hover="background:rgba(139,123,255,0.08);"><span style="width:7px;height:7px;border-radius:50%;background:#8b7bff;"></span>Skills</a>
<a href="#projects" onClick="{{ closeMenu }}" style="color:#e8f0ff;text-decoration:none;font-size:16px;padding:14px 12px;border-radius:8px;display:flex;align-items:center;gap:12px;" style-hover="background:rgba(255,79,216,0.08);"><span style="width:7px;height:7px;border-radius:50%;background:#ff4fd8;"></span>Projects</a>
<a href="#pipeline" onClick="{{ closeMenu }}" style="color:#e8f0ff;text-decoration:none;font-size:16px;padding:14px 12px;border-radius:8px;display:flex;align-items:center;gap:12px;" style-hover="background:rgba(182,255,61,0.08);"><span style="width:7px;height:7px;border-radius:50%;background:#b6ff3d;"></span>Pipeline</a>
<a href="#contact" onClick="{{ closeMenu }}" style="color:#e8f0ff;text-decoration:none;font-size:16px;padding:14px 12px;border-radius:8px;display:flex;align-items:center;gap:12px;" style-hover="background:rgba(255,184,77,0.08);"><span style="width:7px;height:7px;border-radius:50%;background:#ffb84d;"></span>Contact</a>
</nav>
</sc-if>
</header>
<!-- HERO with 3D network canvas -->
<section id="hero-section" data-screen-label="Hero" style="position:relative;min-height:100vh;display:flex;align-items:center;overflow:hidden;">
<div id="hero-canvas-wrap" style="position:absolute;inset:0;">
<canvas ref="{{ canvasRef }}" style="position:absolute;inset:0;width:100%;height:100%;"></canvas>
</div>
<div style="position:absolute;inset:0;background:radial-gradient(ellipse 60% 50% at 70% 50%, rgba(46,230,255,0.06), transparent 70%), radial-gradient(ellipse 40% 40% at 20% 80%, rgba(255,79,216,0.05), transparent 70%);pointer-events:none;"></div>
<div style="position:absolute;inset:0;background-image:linear-gradient(rgba(120,160,220,0.055) 1px,transparent 1px),linear-gradient(90deg,rgba(120,160,220,0.055) 1px,transparent 1px);background-size:56px 56px;-webkit-mask-image:radial-gradient(ellipse 85% 75% at 50% 45%,black,transparent 88%);mask-image:radial-gradient(ellipse 85% 75% at 50% 45%,black,transparent 88%);pointer-events:none;"></div>
<div id="hero-inner" style="position:relative;z-index:2;max-width:1200px;margin:0 auto;padding:120px 32px 80px;width:100%;">
<div style="max-width:640px;">
<p style="font-family:'JetBrains Mono',monospace;font-size:13px;letter-spacing:2px;color:#2ee6ff;margin:0 0 20px;">// CLOUD &amp; NETWORK INFRASTRUCTURE</p>
<h1 style="font-size:clamp(48px,7vw,84px);line-height:1.02;margin:0 0 20px;font-weight:700;background:linear-gradient(100deg,#2ee6ff 0%,#8b7bff 30%,#ff4fd8 55%,#ffb84d 75%,#2ee6ff 100%);background-size:220% 100%;animation:gradientShift 8s ease infinite;-webkit-background-clip:text;background-clip:text;color:transparent;filter:drop-shadow(0 0 28px rgba(139,123,255,0.35));">Muaz<br>Bhutta</h1>
<p style="font-size:20px;color:#c3d0e8;margin:0 0 12px;font-weight:500;">Cloud &amp; Network Infrastructure Engineer</p>
<p style="font-family:'JetBrains Mono',monospace;font-size:14px;line-height:1.7;color:#8ea2c0;margin:0 0 36px;max-width:520px;">From routing tables to cloud pipelines — I build infrastructure that runs, and I understand why it runs.</p>
<div style="display:flex;gap:16px;flex-wrap:wrap;align-items:center;">
<a href="#projects" style="text-decoration:none;display:inline-flex;align-items:center;gap:10px;padding:16px 32px;border-radius:99px;background:linear-gradient(120deg,#2ee6ff,#8b7bff 55%,#ff4fd8);background-size:180% 100%;color:#060a18;font-weight:700;font-size:15px;letter-spacing:0.3px;box-shadow:0 12px 40px -10px rgba(139,123,255,0.65), inset 0 1px 0 rgba(255,255,255,0.35);transition:all 0.3s ease;animation:gradientShift 6s ease infinite;" style-hover="transform:translateY(-2px);box-shadow:0 18px 50px -10px rgba(255,79,216,0.6), inset 0 1px 0 rgba(255,255,255,0.35);">View Projects <span style="font-size:17px;"></span></a>
<a href="#contact" style="text-decoration:none;display:inline-flex;align-items:center;gap:10px;padding:15px 30px;border-radius:99px;border:1px solid transparent;background:linear-gradient(rgba(13,20,48,0.85),rgba(13,20,48,0.85)) padding-box, linear-gradient(120deg,rgba(46,230,255,0.7),rgba(139,123,255,0.7)) border-box;color:#2ee6ff;font-weight:600;font-size:14px;font-family:'JetBrains Mono',monospace;backdrop-filter:blur(6px);transition:all 0.3s ease;" style-hover="transform:translateY(-2px);box-shadow:0 12px 36px -12px rgba(46,230,255,0.5);color:#7ff0ff;"><span style="width:8px;height:8px;border-radius:50%;background:#b6ff3d;animation:pulseDot 2s infinite;"></span>./contact.sh</a>
</div>
</div>
<div id="hero-status" style="position:absolute;right:32px;bottom:64px;display:flex;flex-direction:column;gap:10px;font-family:'JetBrains Mono',monospace;font-size:12px;color:#8ea2c0;animation:floaty 6s ease-in-out infinite;">
<div style="display:flex;align-items:center;gap:10px;padding:10px 16px;border:1px solid rgba(182,255,61,0.25);border-radius:6px;background:rgba(13,20,48,0.72);backdrop-filter:blur(6px);">
<span style="width:8px;height:8px;border-radius:50%;background:#b6ff3d;animation:pulseDot 2s infinite;"></span>
VPS 152.42.241.74 — all systems up
</div>
<div style="display:flex;align-items:center;gap:10px;padding:10px 16px;border:1px solid rgba(46,230,255,0.25);border-radius:6px;background:rgba(13,20,48,0.72);backdrop-filter:blur(6px);">
<span style="width:8px;height:8px;border-radius:50%;background:#2ee6ff;animation:pulseDot 2s 0.7s infinite;"></span>
Jeddah / Riyadh, Saudi Arabia
</div>
</div>
</div>
</section>
<!-- TICKER -->
<div data-screen-label="Ticker" style="overflow:hidden;border-top:1px solid rgba(255,255,255,0.07);border-bottom:1px solid rgba(255,255,255,0.07);background:rgba(255,255,255,0.015);padding:18px 0;">
<div style="display:flex;gap:44px;width:max-content;animation:ticker 30s linear infinite;font-family:'JetBrains Mono',monospace;font-size:13px;letter-spacing:3px;align-items:center;">
<span style="color:#2ee6ff;">OSPF</span><span style="color:#3a4560;"></span>
<span style="color:#8b7bff;">AWS</span><span style="color:#3a4560;"></span>
<span style="color:#ff4fd8;">DOCKER</span><span style="color:#3a4560;"></span>
<span style="color:#b6ff3d;">WIREGUARD</span><span style="color:#3a4560;"></span>
<span style="color:#ffb84d;">PROMETHEUS</span><span style="color:#3a4560;"></span>
<span style="color:#2ee6ff;">GRAFANA</span><span style="color:#3a4560;"></span>
<span style="color:#8b7bff;">CI/CD</span><span style="color:#3a4560;"></span>
<span style="color:#ff4fd8;">LINUX</span><span style="color:#3a4560;"></span>
<span style="color:#b6ff3d;">CADDY</span><span style="color:#3a4560;"></span>
<span style="color:#ffb84d;">VLAN</span><span style="color:#3a4560;"></span>
<span style="color:#2ee6ff;">FLASK</span><span style="color:#3a4560;"></span>
<span style="color:#8b7bff;">BASH</span><span style="color:#3a4560;"></span>
<span style="color:#2ee6ff;">OSPF</span><span style="color:#3a4560;"></span>
<span style="color:#8b7bff;">AWS</span><span style="color:#3a4560;"></span>
<span style="color:#ff4fd8;">DOCKER</span><span style="color:#3a4560;"></span>
<span style="color:#b6ff3d;">WIREGUARD</span><span style="color:#3a4560;"></span>
<span style="color:#ffb84d;">PROMETHEUS</span><span style="color:#3a4560;"></span>
<span style="color:#2ee6ff;">GRAFANA</span><span style="color:#3a4560;"></span>
<span style="color:#8b7bff;">CI/CD</span><span style="color:#3a4560;"></span>
<span style="color:#ff4fd8;">LINUX</span><span style="color:#3a4560;"></span>
<span style="color:#b6ff3d;">CADDY</span><span style="color:#3a4560;"></span>
<span style="color:#ffb84d;">VLAN</span><span style="color:#3a4560;"></span>
<span style="color:#2ee6ff;">FLASK</span><span style="color:#3a4560;"></span>
<span style="color:#8b7bff;">BASH</span><span style="color:#3a4560;"></span>
</div>
</div>
<!-- ABOUT / TRACEROUTE -->
<section id="about" data-screen-label="About — Traceroute" style="position:relative;padding:120px 32px;border-top:1px solid rgba(255,255,255,0.06);">
<div style="max-width:1200px;margin:0 auto;">
<p style="font-family:'JetBrains Mono',monospace;font-size:13px;letter-spacing:2px;color:#8b7bff;margin:0 0 12px;">$ traceroute muaz --journey</p>
<h2 style="font-size:40px;margin:0 0 56px;font-weight:700;">The route so far</h2>
<div id="hops-grid" style="display:grid;grid-template-columns:repeat(5,1fr);gap:0;position:relative;">
<div id="hops-line" style="position:absolute;top:11px;left:10%;right:10%;height:2px;background:linear-gradient(90deg,#2ee6ff,#8b7bff,#ff4fd8,#ffb84d,#b6ff3d);opacity:0.4;"></div>
<div style="display:flex;flex-direction:column;align-items:center;text-align:center;gap:14px;position:relative;">
<div style="width:24px;height:24px;border-radius:50%;background:#0b1226;border:2px solid #2ee6ff;color:#2ee6ff;animation:hopGlow 10s 0s infinite;"></div>
<div><div style="font-family:'JetBrains Mono',monospace;font-size:11px;color:#2ee6ff;margin-bottom:6px;">HOP 1</div><div style="font-weight:600;font-size:16px;">Multan, PK</div><div style="font-size:13px;color:#8ea2c0;margin-top:4px;">BS Computer Science</div></div>
</div>
<div style="display:flex;flex-direction:column;align-items:center;text-align:center;gap:14px;position:relative;">
<div style="width:24px;height:24px;border-radius:50%;background:#0b1226;border:2px solid #8b7bff;color:#8b7bff;animation:hopGlow 10s 2s infinite;"></div>
<div><div style="font-family:'JetBrains Mono',monospace;font-size:11px;color:#8b7bff;margin-bottom:6px;">HOP 2</div><div style="font-weight:600;font-size:16px;">CCNA</div><div style="font-size:13px;color:#8ea2c0;margin-top:4px;">Routing &amp; Switching foundation</div></div>
</div>
<div style="display:flex;flex-direction:column;align-items:center;text-align:center;gap:14px;position:relative;">
<div style="width:24px;height:24px;border-radius:50%;background:#0b1226;border:2px solid #ff4fd8;color:#ff4fd8;animation:hopGlow 10s 4s infinite;"></div>
<div><div style="font-family:'JetBrains Mono',monospace;font-size:11px;color:#ff4fd8;margin-bottom:6px;">HOP 3</div><div style="font-weight:600;font-size:16px;">AWS + Linux</div><div style="font-size:13px;color:#8ea2c0;margin-top:4px;">Cloud &amp; systems skills</div></div>
</div>
<div style="display:flex;flex-direction:column;align-items:center;text-align:center;gap:14px;position:relative;">
<div style="width:24px;height:24px;border-radius:50%;background:#0b1226;border:2px solid #ffb84d;color:#ffb84d;animation:hopGlow 10s 6s infinite;"></div>
<div><div style="font-family:'JetBrains Mono',monospace;font-size:11px;color:#ffb84d;margin-bottom:6px;">HOP 4</div><div style="font-weight:600;font-size:16px;">Self-hosted labs</div><div style="font-size:13px;color:#8ea2c0;margin-top:4px;">VPN, monitoring, APIs — live on VPS</div></div>
</div>
<div style="display:flex;flex-direction:column;align-items:center;text-align:center;gap:14px;position:relative;">
<div style="width:24px;height:24px;border-radius:50%;background:#0b1226;border:2px solid #b6ff3d;color:#b6ff3d;animation:hopGlow 10s 8s infinite;"></div>
<div><div style="font-family:'JetBrains Mono',monospace;font-size:11px;color:#b6ff3d;margin-bottom:6px;">HOP 5</div><div style="font-weight:600;font-size:16px;">Jeddah / Riyadh</div><div style="font-size:13px;color:#8ea2c0;margin-top:4px;">Junior Network / Cloud Engineer — target</div></div>
</div>
</div>
</div>
</section>
<!-- SKILLS -->
<section id="skills" data-screen-label="Skills" style="padding:120px 32px;border-top:1px solid rgba(255,255,255,0.06);background:radial-gradient(ellipse 50% 60% at 50% 0%, rgba(139,123,255,0.06), transparent 70%);">
<div style="max-width:1200px;margin:0 auto;">
<p style="font-family:'JetBrains Mono',monospace;font-size:13px;letter-spacing:2px;color:#2ee6ff;margin:0 0 12px;">$ show ip interface brief</p>
<h2 style="font-size:40px;margin:0 0 56px;font-weight:700;">Interfaces — all up / up</h2>
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));gap:20px;">
<div style="border:1px solid rgba(46,230,255,0.2);border-top:3px solid #2ee6ff;border-radius:10px;padding:28px;background:rgba(255,255,255,0.02);transition:all 0.35s ease;" style-hover="background:rgba(46,230,255,0.05);transform:translateY(-4px);box-shadow:0 20px 40px -20px rgba(46,230,255,0.35);">
<div style="font-family:'JetBrains Mono',monospace;font-size:12px;color:#2ee6ff;margin-bottom:16px;">Gi0/0 — NETWORKING</div>
<div style="display:flex;flex-direction:column;gap:12px;font-size:15px;color:#c3d0e8;">
<div style="display:flex;align-items:center;gap:10px;"><span style="width:6px;height:6px;border-radius:50%;background:#b6ff3d;"></span>CCNA (R&amp;S)</div>
<div style="display:flex;align-items:center;gap:10px;"><span style="width:6px;height:6px;border-radius:50%;background:#b6ff3d;"></span>OSPF / EIGRP</div>
<div style="display:flex;align-items:center;gap:10px;"><span style="width:6px;height:6px;border-radius:50%;background:#b6ff3d;"></span>VLAN &amp; Subnetting</div>
<div style="display:flex;align-items:center;gap:10px;"><span style="width:6px;height:6px;border-radius:50%;background:#b6ff3d;"></span>OpenVPN</div>
<div style="display:flex;align-items:center;gap:10px;"><span style="width:6px;height:6px;border-radius:50%;background:#b6ff3d;"></span>WireGuard</div>
</div>
</div>
<div style="border:1px solid rgba(139,123,255,0.2);border-top:3px solid #8b7bff;border-radius:10px;padding:28px;background:rgba(255,255,255,0.02);transition:all 0.35s ease;" style-hover="background:rgba(139,123,255,0.05);transform:translateY(-4px);box-shadow:0 20px 40px -20px rgba(139,123,255,0.35);">
<div style="font-family:'JetBrains Mono',monospace;font-size:12px;color:#8b7bff;margin-bottom:16px;">Gi0/1 — CLOUD</div>
<div style="display:flex;flex-direction:column;gap:12px;font-size:15px;color:#c3d0e8;">
<div style="display:flex;align-items:center;gap:10px;"><span style="width:6px;height:6px;border-radius:50%;background:#b6ff3d;"></span>AWS (EC2, S3, IAM)</div>
<div style="display:flex;align-items:center;gap:10px;"><span style="width:6px;height:6px;border-radius:50%;background:#b6ff3d;"></span>VPS Administration</div>
<div style="display:flex;align-items:center;gap:10px;"><span style="width:6px;height:6px;border-radius:50%;background:#b6ff3d;"></span>Caddy / Nginx</div>
<div style="display:flex;align-items:center;gap:10px;"><span style="width:6px;height:6px;border-radius:50%;background:#b6ff3d;"></span>DNS &amp; Domains</div>
</div>
</div>
<div style="border:1px solid rgba(255,79,216,0.2);border-top:3px solid #ff4fd8;border-radius:10px;padding:28px;background:rgba(255,255,255,0.02);transition:all 0.35s ease;" style-hover="background:rgba(255,79,216,0.05);transform:translateY(-4px);box-shadow:0 20px 40px -20px rgba(255,79,216,0.35);">
<div style="font-family:'JetBrains Mono',monospace;font-size:12px;color:#ff4fd8;margin-bottom:16px;">Gi0/2 — DEVOPS</div>
<div style="display:flex;flex-direction:column;gap:12px;font-size:15px;color:#c3d0e8;">
<div style="display:flex;align-items:center;gap:10px;"><span style="width:6px;height:6px;border-radius:50%;background:#b6ff3d;"></span>Docker &amp; Compose</div>
<div style="display:flex;align-items:center;gap:10px;"><span style="width:6px;height:6px;border-radius:50%;background:#b6ff3d;"></span>Prometheus + Grafana</div>
<div style="display:flex;align-items:center;gap:10px;"><span style="width:6px;height:6px;border-radius:50%;background:#b6ff3d;"></span>CI/CD (GitHub Actions)</div>
<div style="display:flex;align-items:center;gap:10px;"><span style="width:6px;height:6px;border-radius:50%;background:#b6ff3d;"></span>Bash scripting</div>
</div>
</div>
<div style="border:1px solid rgba(255,184,77,0.2);border-top:3px solid #ffb84d;border-radius:10px;padding:28px;background:rgba(255,255,255,0.02);transition:all 0.35s ease;" style-hover="background:rgba(255,184,77,0.05);transform:translateY(-4px);box-shadow:0 20px 40px -20px rgba(255,184,77,0.35);">
<div style="font-family:'JetBrains Mono',monospace;font-size:12px;color:#ffb84d;margin-bottom:16px;">Gi0/3 — DEVELOPMENT</div>
<div style="display:flex;flex-direction:column;gap:12px;font-size:15px;color:#c3d0e8;">
<div style="display:flex;align-items:center;gap:10px;"><span style="width:6px;height:6px;border-radius:50%;background:#b6ff3d;"></span>Linux (Ubuntu/Debian)</div>
<div style="display:flex;align-items:center;gap:10px;"><span style="width:6px;height:6px;border-radius:50%;background:#b6ff3d;"></span>Python + Flask</div>
<div style="display:flex;align-items:center;gap:10px;"><span style="width:6px;height:6px;border-radius:50%;background:#b6ff3d;"></span>REST APIs</div>
<div style="display:flex;align-items:center;gap:10px;"><span style="width:6px;height:6px;border-radius:50%;background:#b6ff3d;"></span>Git / GitHub</div>
</div>
</div>
</div>
</div>
</section>
<!-- PROJECTS -->
<section id="projects" data-screen-label="Projects" style="padding:120px 32px;border-top:1px solid rgba(255,255,255,0.06);">
<div style="max-width:1200px;margin:0 auto;">
<p style="font-family:'JetBrains Mono',monospace;font-size:13px;letter-spacing:2px;color:#ff4fd8;margin:0 0 12px;">$ show ip route — selected work</p>
<h2 style="font-size:40px;margin:0 0 16px;font-weight:700;">Routing table</h2>
<p style="color:#8ea2c0;margin:0 0 56px;max-width:560px;">Infrastructure I've designed, deployed, and maintain on my own VPS.</p>
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(320px,1fr));gap:20px;">
<div style="border:1px solid rgba(255,255,255,0.09);border-radius:10px;padding:28px;background:rgba(255,255,255,0.02);transition:all 0.35s ease;display:flex;flex-direction:column;gap:16px;" style-hover="border-color:rgba(46,230,255,0.5);box-shadow:0 24px 48px -24px rgba(46,230,255,0.4);transform:translateY(-4px);">
<div style="display:flex;justify-content:space-between;align-items:center;">
<span style="font-family:'JetBrains Mono',monospace;font-size:11px;color:#b6ff3d;border:1px solid rgba(182,255,61,0.35);padding:4px 10px;border-radius:99px;">● LIVE</span>
<span style="font-family:'JetBrains Mono',monospace;font-size:11px;color:#5a6a85;">vpn-dashboard</span>
</div>
<h3 style="margin:0;font-size:20px;font-weight:600;">OpenVPN Management Dashboard</h3>
<p style="margin:0;font-size:14px;line-height:1.7;color:#8ea2c0;">Full VPN control panel on my VPS — live client monitoring, connection status, and Server-Sent Events for real-time data.</p>
<div style="display:flex;flex-wrap:wrap;gap:8px;margin-top:auto;">
<span style="font-family:'JetBrains Mono',monospace;font-size:11px;color:#2ee6ff;background:rgba(46,230,255,0.08);padding:4px 10px;border-radius:4px;">Flask</span>
<span style="font-family:'JetBrains Mono',monospace;font-size:11px;color:#2ee6ff;background:rgba(46,230,255,0.08);padding:4px 10px;border-radius:4px;">OpenVPN</span>
<span style="font-family:'JetBrains Mono',monospace;font-size:11px;color:#2ee6ff;background:rgba(46,230,255,0.08);padding:4px 10px;border-radius:4px;">Easy-RSA</span>
<span style="font-family:'JetBrains Mono',monospace;font-size:11px;color:#2ee6ff;background:rgba(46,230,255,0.08);padding:4px 10px;border-radius:4px;">SSE</span>
<span style="font-family:'JetBrains Mono',monospace;font-size:11px;color:#2ee6ff;background:rgba(46,230,255,0.08);padding:4px 10px;border-radius:4px;">Linux</span>
</div>
</div>
<div style="border:1px solid rgba(255,255,255,0.09);border-radius:10px;padding:28px;background:rgba(255,255,255,0.02);transition:all 0.35s ease;display:flex;flex-direction:column;gap:16px;" style-hover="border-color:rgba(139,123,255,0.5);box-shadow:0 24px 48px -24px rgba(139,123,255,0.4);transform:translateY(-4px);">
<div style="display:flex;justify-content:space-between;align-items:center;">
<span style="font-family:'JetBrains Mono',monospace;font-size:11px;color:#b6ff3d;border:1px solid rgba(182,255,61,0.35);padding:4px 10px;border-radius:99px;">● LIVE</span>
<span style="font-family:'JetBrains Mono',monospace;font-size:11px;color:#5a6a85;">monitoring-stack</span>
</div>
<h3 style="margin:0;font-size:20px;font-weight:600;">Prometheus + Grafana Monitoring</h3>
<p style="margin:0;font-size:14px;line-height:1.7;color:#8ea2c0;">Monitoring stack deployed via Docker Compose — Node Exporter collects system metrics, visualized on Grafana dashboards.</p>
<div style="display:flex;flex-wrap:wrap;gap:8px;margin-top:auto;">
<span style="font-family:'JetBrains Mono',monospace;font-size:11px;color:#8b7bff;background:rgba(139,123,255,0.1);padding:4px 10px;border-radius:4px;">Docker Compose</span>
<span style="font-family:'JetBrains Mono',monospace;font-size:11px;color:#8b7bff;background:rgba(139,123,255,0.1);padding:4px 10px;border-radius:4px;">Prometheus</span>
<span style="font-family:'JetBrains Mono',monospace;font-size:11px;color:#8b7bff;background:rgba(139,123,255,0.1);padding:4px 10px;border-radius:4px;">Grafana</span>
<span style="font-family:'JetBrains Mono',monospace;font-size:11px;color:#8b7bff;background:rgba(139,123,255,0.1);padding:4px 10px;border-radius:4px;">Node Exporter</span>
</div>
</div>
<div style="border:1px solid rgba(255,255,255,0.09);border-radius:10px;padding:28px;background:rgba(255,255,255,0.02);transition:all 0.35s ease;display:flex;flex-direction:column;gap:16px;" style-hover="border-color:rgba(255,79,216,0.5);box-shadow:0 24px 48px -24px rgba(255,79,216,0.4);transform:translateY(-4px);">
<div style="display:flex;justify-content:space-between;align-items:center;">
<span style="font-family:'JetBrains Mono',monospace;font-size:11px;color:#b6ff3d;border:1px solid rgba(182,255,61,0.35);padding:4px 10px;border-radius:99px;">● LIVE</span>
<span style="font-family:'JetBrains Mono',monospace;font-size:11px;color:#5a6a85;">system-api</span>
</div>
<h3 style="margin:0;font-size:20px;font-weight:600;">Real-time System Status API</h3>
<p style="margin:0;font-size:14px;line-height:1.7;color:#8ea2c0;">Flask API streaming live CPU, RAM and disk metrics from psutil over SSE, with a dark-themed dashboard.</p>
<div style="display:flex;flex-wrap:wrap;gap:8px;margin-top:auto;">
<span style="font-family:'JetBrains Mono',monospace;font-size:11px;color:#ff4fd8;background:rgba(255,79,216,0.1);padding:4px 10px;border-radius:4px;">Python</span>
<span style="font-family:'JetBrains Mono',monospace;font-size:11px;color:#ff4fd8;background:rgba(255,79,216,0.1);padding:4px 10px;border-radius:4px;">Flask</span>
<span style="font-family:'JetBrains Mono',monospace;font-size:11px;color:#ff4fd8;background:rgba(255,79,216,0.1);padding:4px 10px;border-radius:4px;">psutil</span>
<span style="font-family:'JetBrains Mono',monospace;font-size:11px;color:#ff4fd8;background:rgba(255,79,216,0.1);padding:4px 10px;border-radius:4px;">SSE</span>
</div>
</div>
<div style="border:1px solid rgba(255,255,255,0.09);border-radius:10px;padding:28px;background:rgba(255,255,255,0.02);transition:all 0.35s ease;display:flex;flex-direction:column;gap:16px;" style-hover="border-color:rgba(255,184,77,0.5);box-shadow:0 24px 48px -24px rgba(255,184,77,0.4);transform:translateY(-4px);">
<div style="display:flex;justify-content:space-between;align-items:center;">
<span style="font-family:'JetBrains Mono',monospace;font-size:11px;color:#ffb84d;border:1px solid rgba(255,184,77,0.35);padding:4px 10px;border-radius:99px;">◐ LAB</span>
<span style="font-family:'JetBrains Mono',monospace;font-size:11px;color:#5a6a85;">wireguard-lab</span>
</div>
<h3 style="margin:0;font-size:20px;font-weight:600;">WireGuard VPN Lab</h3>
<p style="margin:0;font-size:14px;line-height:1.7;color:#8ea2c0;">WireGuard setup, WGDashboard integration, and troubleshooting mobile connectivity issues (carrier-level UDP blocking).</p>
<div style="display:flex;flex-wrap:wrap;gap:8px;margin-top:auto;">
<span style="font-family:'JetBrains Mono',monospace;font-size:11px;color:#ffb84d;background:rgba(255,184,77,0.1);padding:4px 10px;border-radius:4px;">WireGuard</span>
<span style="font-family:'JetBrains Mono',monospace;font-size:11px;color:#ffb84d;background:rgba(255,184,77,0.1);padding:4px 10px;border-radius:4px;">WGDashboard</span>
<span style="font-family:'JetBrains Mono',monospace;font-size:11px;color:#ffb84d;background:rgba(255,184,77,0.1);padding:4px 10px;border-radius:4px;">Networking</span>
</div>
</div>
<div style="border:1px solid rgba(255,255,255,0.09);border-radius:10px;padding:28px;background:rgba(255,255,255,0.02);transition:all 0.35s ease;display:flex;flex-direction:column;gap:16px;" style-hover="border-color:rgba(182,255,61,0.5);box-shadow:0 24px 48px -24px rgba(182,255,61,0.4);transform:translateY(-4px);">
<div style="display:flex;justify-content:space-between;align-items:center;">
<span style="font-family:'JetBrains Mono',monospace;font-size:11px;color:#b6ff3d;border:1px solid rgba(182,255,61,0.35);padding:4px 10px;border-radius:99px;">● LIVE</span>
<span style="font-family:'JetBrains Mono',monospace;font-size:11px;color:#5a6a85;">this-site</span>
</div>
<h3 style="margin:0;font-size:20px;font-weight:600;">This Portfolio</h3>
<p style="margin:0;font-size:14px;line-height:1.7;color:#8ea2c0;">Static site that auto-deploys to my own VPS via GitHub Actions — the CI/CD pipeline is itself part of the site.</p>
<div style="display:flex;flex-wrap:wrap;gap:8px;margin-top:auto;">
<span style="font-family:'JetBrains Mono',monospace;font-size:11px;color:#b6ff3d;background:rgba(182,255,61,0.1);padding:4px 10px;border-radius:4px;">HTML/CSS/JS</span>
<span style="font-family:'JetBrains Mono',monospace;font-size:11px;color:#b6ff3d;background:rgba(182,255,61,0.1);padding:4px 10px;border-radius:4px;">GitHub Actions</span>
<span style="font-family:'JetBrains Mono',monospace;font-size:11px;color:#b6ff3d;background:rgba(182,255,61,0.1);padding:4px 10px;border-radius:4px;">Caddy</span>
<span style="font-family:'JetBrains Mono',monospace;font-size:11px;color:#b6ff3d;background:rgba(182,255,61,0.1);padding:4px 10px;border-radius:4px;">VPS</span>
</div>
</div>
</div>
</div>
</section>
<!-- LIVE TERMINAL / PIPELINE -->
<section id="pipeline" data-screen-label="DevOps Terminal" style="padding:120px 32px;border-top:1px solid rgba(255,255,255,0.06);background:radial-gradient(ellipse 50% 60% at 50% 100%, rgba(182,255,61,0.05), transparent 70%);">
<div style="max-width:900px;margin:0 auto;">
<p style="font-family:'JetBrains Mono',monospace;font-size:13px;letter-spacing:2px;color:#b6ff3d;margin:0 0 12px;">$ tail -f /var/log/deploy.log</p>
<h2 style="font-size:40px;margin:0 0 56px;font-weight:700;">Live from the VPS</h2>
<div style="border:1px solid rgba(255,255,255,0.12);border-radius:12px;overflow:hidden;background:#0a101f;box-shadow:0 40px 100px -30px rgba(46,230,255,0.35), 0 0 0 1px rgba(46,230,255,0.08);position:relative;">
<div style="display:flex;align-items:center;gap:8px;padding:12px 16px;background:rgba(255,255,255,0.04);border-bottom:1px solid rgba(255,255,255,0.08);">
<span style="width:12px;height:12px;border-radius:50%;background:#ff5f57;"></span>
<span style="width:12px;height:12px;border-radius:50%;background:#febc2e;"></span>
<span style="width:12px;height:12px;border-radius:50%;background:#28c840;"></span>
<span style="margin-left:12px;font-family:'JetBrains Mono',monospace;font-size:12px;color:#8ea2c0;">muaz@mj — ssh — 152.42.241.74</span>
</div>
<div style="position:absolute;left:0;right:0;top:44px;height:60px;background:linear-gradient(180deg,rgba(46,230,255,0.05),transparent);animation:scan 7s linear infinite;pointer-events:none;"></div>
<div style="padding:24px 24px 32px;min-height:340px;font-family:'JetBrains Mono',monospace;font-size:14px;line-height:2;">
<sc-for list="{{ termLines }}" as="ln" hint-placeholder-count="4">
<div style="color:{{ ln.color }};white-space:pre-wrap;">{{ ln.text }}</div>
</sc-for>
<span style="display:inline-block;width:9px;height:17px;background:#b6ff3d;vertical-align:middle;animation:blink 1s step-end infinite;"></span>
</div>
</div>
</div>
</section>
<!-- CREDENTIALS -->
<section id="credentials" data-screen-label="Credentials" style="padding:120px 32px;border-top:1px solid rgba(255,255,255,0.06);">
<div style="max-width:900px;margin:0 auto;">
<p style="font-family:'JetBrains Mono',monospace;font-size:13px;letter-spacing:2px;color:#ffb84d;margin:0 0 12px;">$ cat /etc/credentials</p>
<h2 style="font-size:40px;margin:0 0 48px;font-weight:700;">Education &amp; Certifications</h2>
<div style="display:flex;flex-direction:column;gap:14px;">
<div style="display:flex;justify-content:space-between;align-items:center;gap:16px;padding:22px 28px;border:1px solid rgba(255,255,255,0.09);border-radius:10px;background:rgba(255,255,255,0.02);transition:all 0.3s ease;" style-hover="border-color:rgba(46,230,255,0.4);">
<div><div style="font-weight:600;font-size:17px;">BS Computer Science</div><div style="font-size:13px;color:#8ea2c0;margin-top:4px;">University</div></div>
<span style="font-family:'JetBrains Mono',monospace;font-size:12px;color:#2ee6ff;">DEGREE</span>
</div>
<div style="display:flex;justify-content:space-between;align-items:center;gap:16px;padding:22px 28px;border:1px solid rgba(255,255,255,0.09);border-radius:10px;background:rgba(255,255,255,0.02);transition:all 0.3s ease;" style-hover="border-color:rgba(139,123,255,0.4);">
<div><div style="font-weight:600;font-size:17px;">CCNA (200-301)</div><div style="font-size:13px;color:#8ea2c0;margin-top:4px;">Cisco — in progress / planned</div></div>
<span style="font-family:'JetBrains Mono',monospace;font-size:12px;color:#8b7bff;">CERT</span>
</div>
<div style="display:flex;justify-content:space-between;align-items:center;gap:16px;padding:22px 28px;border:1px solid rgba(255,255,255,0.09);border-radius:10px;background:rgba(255,255,255,0.02);transition:all 0.3s ease;" style-hover="border-color:rgba(255,79,216,0.4);">
<div><div style="font-weight:600;font-size:17px;">AWS Cloud Practitioner</div><div style="font-size:13px;color:#8ea2c0;margin-top:4px;">Amazon Web Services</div></div>
<span style="font-family:'JetBrains Mono',monospace;font-size:12px;color:#ff4fd8;">CERT</span>
</div>
</div>
</div>
</section>
<!-- CONTACT -->
<section id="contact" data-screen-label="Contact" style="padding:120px 32px 80px;border-top:1px solid rgba(255,255,255,0.06);">
<div style="max-width:900px;margin:0 auto;text-align:center;padding:72px 40px;border-radius:16px;border:1px solid transparent;background:linear-gradient(#101736,#101736) padding-box, linear-gradient(120deg,rgba(46,230,255,0.55),rgba(139,123,255,0.45),rgba(255,79,216,0.55)) border-box;box-shadow:0 40px 100px -50px rgba(139,123,255,0.45);">
<p style="font-family:'JetBrains Mono',monospace;font-size:13px;letter-spacing:2px;color:#2ee6ff;margin:0 0 16px;">// ESTABLISH CONNECTION</p>
<h2 style="font-size:44px;margin:0 0 16px;font-weight:700;background:linear-gradient(100deg,#2ee6ff,#8b7bff,#ff4fd8);-webkit-background-clip:text;background-clip:text;color:transparent;">Let's connect</h2>
<p style="color:#8ea2c0;margin:0 0 40px;">Open to Junior Network / Cloud Engineer roles in Jeddah &amp; Riyadh.</p>
<div style="display:flex;gap:14px;justify-content:center;flex-wrap:wrap;">
<a href="mailto:you@muazbhutta.online" style="text-decoration:none;padding:14px 28px;border-radius:6px;background:linear-gradient(90deg,#2ee6ff,#8b7bff);color:#04060d;font-weight:600;font-size:15px;box-shadow:0 8px 32px -8px rgba(46,230,255,0.55);transition:all 0.25s ease;" style-hover="filter:brightness(1.15);">Email</a>
<a href="https://github.com/yourusername" style="text-decoration:none;padding:14px 28px;border-radius:6px;border:1px solid rgba(255,255,255,0.2);color:#e8f0ff;font-weight:600;font-size:15px;" style-hover="border-color:#ff4fd8;color:#ff4fd8;">GitHub</a>
<a href="https://linkedin.com/in/yourusername" style="text-decoration:none;padding:14px 28px;border-radius:6px;border:1px solid rgba(255,255,255,0.2);color:#e8f0ff;font-weight:600;font-size:15px;" style-hover="border-color:#2ee6ff;color:#2ee6ff;">LinkedIn</a>
</div>
</div>
</section>
<footer style="padding:32px;text-align:center;font-family:'JetBrains Mono',monospace;font-size:12px;color:#5a6a85;border-top:1px solid rgba(255,255,255,0.06);">
© 2026 Muaz Bhutta
</footer>
</div>
</div>
</x-dc>
<script type="text/x-dc" data-dc-script data-props="{
&quot;colorScheme&quot;: { &quot;editor&quot;: &quot;enum&quot;, &quot;options&quot;: [&quot;spectrum&quot;, &quot;cyberpunk&quot;, &quot;aurora&quot;], &quot;default&quot;: &quot;spectrum&quot;, &quot;tsType&quot;: &quot;string&quot;, &quot;section&quot;: &quot;3D Network&quot; },
&quot;nodeDensity&quot;: { &quot;editor&quot;: &quot;range&quot;, &quot;min&quot;: 60, &quot;max&quot;: 320, &quot;step&quot;: 10, &quot;default&quot;: 170, &quot;tsType&quot;: &quot;number&quot;, &quot;section&quot;: &quot;3D Network&quot; },
&quot;rotationSpeed&quot;: { &quot;editor&quot;: &quot;range&quot;, &quot;min&quot;: 0.2, &quot;max&quot;: 3, &quot;step&quot;: 0.1, &quot;default&quot;: 1, &quot;tsType&quot;: &quot;number&quot;, &quot;section&quot;: &quot;3D Network&quot; }
}">
class Component extends DCLogic {
state = { done: [], cur: "", menuOpen: false };
palette() {
const scheme = this.props.colorScheme ?? "spectrum";
if (scheme === "cyberpunk") return ["#00f0ff", "#ff2ee6", "#ffe600", "#7d5cff"];
if (scheme === "aurora") return ["#3dffb0", "#2ee6ff", "#8b7bff", "#b6ff3d"];
return ["#2ee6ff", "#8b7bff", "#ff4fd8", "#b6ff3d", "#ffb84d"];
}
componentDidMount() {
this.startTyping();
this.startCanvas();
}
componentWillUnmount() {
cancelAnimationFrame(this._raf);
clearTimeout(this._typeT);
if (this._io) this._io.disconnect();
}
// ---------- terminal typing ----------
script() {
return [
{ text: "$ ssh muaz@152.42.241.74", color: "#e8f0ff" },
{ text: "Welcome to Ubuntu 24.04 LTS — uptime: 214 days", color: "#8ea2c0" },
{ text: "$ docker compose ps", color: "#e8f0ff" },
{ text: " vpn-dashboard running :8443", color: "#b6ff3d" },
{ text: " prometheus running :9090", color: "#b6ff3d" },
{ text: " grafana running :3000", color: "#b6ff3d" },
{ text: "$ git push origin main", color: "#e8f0ff" },
{ text: "→ GitHub Actions: deploy.yml triggered", color: "#2ee6ff" },
{ text: "→ rsync -avz --delete ./ /var/www/portfolio/", color: "#2ee6ff" },
{ text: "✔ muazbhutta.online deployed in 38s", color: "#ffb84d" },
];
}
startTyping() {
const lines = this.script();
let li = 0, ci = 0;
const step = () => {
if (li >= lines.length) {
this._typeT = setTimeout(() => {
li = 0; ci = 0;
this.setState({ done: [], cur: "" });
this._typeT = setTimeout(step, 400);
}, 4000);
return;
}
const line = lines[li];
ci += 3; // type in chunks — fewer re-renders, smoother page
if (ci >= line.text.length) {
this.setState(s => ({ done: [...s.done, line], cur: "" }));
li++; ci = 0;
this._typeT = setTimeout(step, line.text.startsWith("$") ? 500 : 180);
} else {
this.setState({ cur: line.text.slice(0, ci) });
this._typeT = setTimeout(step, 55 + Math.random() * 30);
}
};
this._typeT = setTimeout(step, 600);
}
// ---------- 3D network canvas ----------
startCanvas() {
const cv = this._cv;
if (!cv) return;
const ctx = cv.getContext("2d");
const N = Math.round(this.props.nodeDensity ?? 120);
const speed = this.props.rotationSpeed ?? 1;
const pal = this.palette();
const nodes = [];
for (let i = 0; i < N; i++) {
const t = Math.acos(2 * Math.random() - 1), p = Math.random() * Math.PI * 2;
const r = 0.75 + Math.random() * 0.25;
nodes.push({
x: Math.sin(t) * Math.cos(p) * r,
y: Math.cos(t) * r,
z: Math.sin(t) * Math.sin(p) * r,
c: pal[i % pal.length],
rad: 1.2 + Math.random() * 1.8,
});
}
const edges = [];
for (let i = 0; i < N; i++) {
for (let j = i + 1; j < N; j++) {
const dx = nodes[i].x - nodes[j].x, dy = nodes[i].y - nodes[j].y, dz = nodes[i].z - nodes[j].z;
if (dx * dx + dy * dy + dz * dz < 0.14) edges.push([i, j]);
}
}
const packets = Array.from({ length: Math.min(30, edges.length) }, () => ({
e: Math.floor(Math.random() * edges.length),
t: Math.random(),
s: 0.004 + Math.random() * 0.012,
}));
// Pre-rendered glow sprites (shadowBlur per-frame is very slow)
const sprites = {};
const makeSprite = (color) => {
const s = document.createElement("canvas");
s.width = 32; s.height = 32;
const sc = s.getContext("2d");
const g = sc.createRadialGradient(16, 16, 0, 16, 16, 16);
g.addColorStop(0, color);
g.addColorStop(0.35, color);
g.addColorStop(1, "rgba(0,0,0,0)");
sc.fillStyle = g;
sc.fillRect(0, 0, 32, 32);
return s;
};
for (const c of pal) sprites[c] = makeSprite(c);
// Only animate while the hero is on screen
this._heroVisible = true;
this._io = new IntersectionObserver((entries) => {
this._heroVisible = entries[0].isIntersecting;
});
this._io.observe(cv);
let ang = 0;
let mx = 0, my = 0;
cv.addEventListener("mousemove", (ev) => {
const b = cv.getBoundingClientRect();
mx = (ev.clientX - b.left) / b.width - 0.5;
my = (ev.clientY - b.top) / b.height - 0.5;
});
const loop = () => {
this._raf = requestAnimationFrame(loop);
if (!this._heroVisible) return;
const w = cv.clientWidth, h = cv.clientHeight;
if (!w || !h) return;
const dpr = Math.min(window.devicePixelRatio || 1, 2);
if (cv.width !== Math.round(w * dpr)) { cv.width = Math.round(w * dpr); cv.height = Math.round(h * dpr); }
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
ctx.clearRect(0, 0, w, h);
ang += 0.0022 * speed;
const tiltX = 0.25 + my * 0.3;
const mobile = window.innerWidth < 760;
const cx = w * (mobile ? 0.5 : 0.68);
const cy = h * (mobile ? 0.5 : 0.52);
const R = Math.min(w, h) * (mobile ? 0.46 : 0.42);
const dim = 1; // canvas has its own container on mobile now
const pts = nodes.map(n => {
let x = n.x * Math.cos(ang + mx * 0.6) - n.z * Math.sin(ang + mx * 0.6);
let z = n.x * Math.sin(ang + mx * 0.6) + n.z * Math.cos(ang + mx * 0.6);
let y = n.y * Math.cos(tiltX) - z * Math.sin(tiltX);
z = n.y * Math.sin(tiltX) + z * Math.cos(tiltX);
const s = 1 / (1.9 - z * 0.75);
return { X: cx + x * R * s, Y: cy + y * R * s, s, z, c: n.c, rad: n.rad };
});
// edges
ctx.lineWidth = 0.7;
for (const [i, j] of edges) {
const a = pts[i], b = pts[j];
const depth = (a.z + b.z) / 2;
const alpha = (0.05 + Math.max(0, depth + 0.6) * 0.16) * dim;
ctx.strokeStyle = "rgba(120,160,220," + alpha.toFixed(3) + ")";
ctx.beginPath(); ctx.moveTo(a.X, a.Y); ctx.lineTo(b.X, b.Y); ctx.stroke();
}
// packets (glow via pre-rendered sprite)
for (const p of packets) {
p.t += p.s * speed;
if (p.t > 1) { p.t = 0; p.e = Math.floor(Math.random() * edges.length); }
const [i, j] = edges[p.e];
const a = pts[i], b = pts[j];
const X = a.X + (b.X - a.X) * p.t, Y = a.Y + (b.Y - a.Y) * p.t;
ctx.globalAlpha = dim;
ctx.drawImage(sprites[pts[i].c] || sprites[pal[0]], X - 6, Y - 6, 12, 12);
ctx.globalAlpha = 1;
}
// nodes (glow via pre-rendered sprite)
for (const p of pts) {
const alpha = (0.35 + Math.max(0, p.z + 0.7) * 0.5) * dim;
ctx.globalAlpha = Math.min(1, alpha);
const d = p.rad * p.s * 6;
ctx.drawImage(sprites[p.c] || sprites[pal[0]], p.X - d / 2, p.Y - d / 2, d, d);
}
ctx.globalAlpha = 1;
};
this._raf = requestAnimationFrame(loop);
}
renderVals() {
const termLines = this.state.cur
? [...this.state.done, { text: this.state.cur, color: "#e8f0ff" }]
: this.state.done;
return {
termLines,
menuOpen: this.state.menuOpen,
menuIcon: this.state.menuOpen ? "✕" : "☰",
toggleMenu: () => this.setState(s => ({ menuOpen: !s.menuOpen })),
closeMenu: () => this.setState({ menuOpen: false }),
canvasRef: (el) => { if (el && el !== this._cv) { this._cv = el; if (this._mounted) this.startCanvas(); } },
};
}
}
</script>
</body>
</html>