Files
miles-web/redesign/index.html
T

897 lines
51 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>MILES WOLF ALLEN // VERY MAXIMALIST</title>
<meta name="description" content="Miles Wolf Allen — developer, 3D artist, and the guy trying to replace Electron. Games, tools, websites, and way too many repos.">
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Crect width='100' height='100' fill='%23F7FF00'/%3E%3Ctext x='50' y='72' font-size='60' font-family='Arial Black' font-weight='900' text-anchor='middle' fill='%23000'%3EM%3C/text%3E%3C/svg%3E">
<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=Archivo+Black&family=Press+Start+2P&family=Space+Mono:ital,wght@0,400;0,700&display=swap" rel="stylesheet">
<style>
:root{
--bg:#0b0b0d; --bg2:#121215; --ink:#ffffff; --muted:#9a9aa2;
--pink:#FF2EA6; --yellow:#F7FF00; --cyan:#00F4FF; --orange:#FF5C00;
--purple:#8A2BFF; --red:#FF1F1F; --green:#00FF85;
--d:'Archivo Black',Impact,sans-serif;
--m:'Space Mono',monospace;
--p:'Press Start 2P',monospace;
--blk:#000;
}
*{margin:0;padding:0;box-sizing:border-box;}
html{scroll-behavior:smooth;overflow-x:hidden;}
body{
background:var(--bg);color:var(--ink);
font-family:var(--m);font-size:15px;line-height:1.6;
overflow-x:hidden;-webkit-font-smoothing:antialiased;
}
::selection{background:var(--yellow);color:#000;}
a{color:inherit;text-decoration:none;}
::-webkit-scrollbar{width:12px;}
::-webkit-scrollbar-track{background:#000;}
::-webkit-scrollbar-thumb{background:var(--pink);border:3px solid #000;}
/* ---------- fixed layers ---------- */
.bg-grid{
position:fixed;inset:0;z-index:-3;pointer-events:none;
background-image:
linear-gradient(rgba(255,255,255,0.045) 1px,transparent 1px),
linear-gradient(90deg,rgba(255,255,255,0.045) 1px,transparent 1px);
background-size:44px 44px;
}
.noise{
position:fixed;inset:0;z-index:-2;pointer-events:none;opacity:.06;
background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='120' height='120' filter='url(%23n)' opacity='1'/%3E%3C/svg%3E");
}
.vignette{position:fixed;inset:0;z-index:-1;pointer-events:none;
background:radial-gradient(ellipse at center,transparent 55%,rgba(0,0,0,0.55) 100%);}
.progress{position:fixed;top:0;left:0;height:5px;width:0;background:var(--yellow);z-index:600;box-shadow:0 0 12px var(--yellow);}
/* ---------- cursor ---------- */
.cursor,.glow{position:fixed;top:0;left:0;pointer-events:none;z-index:900;border-radius:50%;}
.cursor{width:12px;height:12px;background:#fff;transform:translate(-50%,-50%);mix-blend-mode:difference;}
.glow{width:320px;height:320px;background:radial-gradient(circle,rgba(255,46,166,0.18),transparent 65%);transform:translate(-50%,-50%);z-index:800;transition:opacity .3s;}
.cursor.on{width:44px;height:44px;border:2px solid #fff;background:transparent;transition:width .18s,height .18s;mix-blend-mode:difference;}
@media(pointer:coarse){.cursor,.glow{display:none;}}
/* ---------- splash ---------- */
.splash{
position:fixed;inset:0;z-index:1000;background:var(--bg);
display:flex;align-items:center;justify-content:center;gap:0;
pointer-events:none;
animation:splashOut .55s ease forwards .95s;
}
.splash span{
font-family:var(--d);font-size:clamp(64px,18vw,220px);color:#fff;
display:inline-block;opacity:0;
animation:splashIn .6s cubic-bezier(.2,1.6,.3,1) forwards;
}
.splash span:nth-child(1){animation-delay:.05s;color:var(--yellow);-webkit-text-stroke:3px #000;}
.splash span:nth-child(2){animation-delay:.15s;}
.splash span:nth-child(3){animation-delay:.25s;color:var(--pink);-webkit-text-stroke:3px #000;}
.splash span:nth-child(4){animation-delay:.35s;}
.splash span:nth-child(5){animation-delay:.45s;color:var(--cyan);-webkit-text-stroke:3px #000;}
.splash .splash-tag{
position:absolute;bottom:12%;left:50%;transform:translateX(-50%) rotate(-3deg);
font-family:var(--p);font-size:9px;background:var(--yellow);color:#000;
padding:10px 16px;border:3px solid #000;box-shadow:5px 5px 0 var(--pink);
}
@keyframes splashIn{0%{opacity:0;transform:translateY(120%) rotate(4deg);}100%{opacity:1;transform:translateY(0) rotate(0);}}
@keyframes splashOut{0%{opacity:1;}100%{opacity:0;visibility:hidden;}}
/* ---------- nav ---------- */
.nav{
position:fixed;top:14px;left:14px;right:14px;z-index:500;
display:flex;align-items:center;justify-content:space-between;gap:14px;
background:rgba(11,11,13,0.78);border:3px solid #000;box-shadow:5px 5px 0 #000;
padding:10px 14px;backdrop-filter:blur(6px);
}
.nav-logo{font-family:var(--d);font-size:20px;display:flex;align-items:center;gap:9px;letter-spacing:.5px;}
.nav-logo .dot{width:12px;height:12px;background:var(--green);border:2px solid #000;animation:blink 1.6s steps(1) infinite;}
.nav-links{display:flex;gap:6px;flex-wrap:wrap;}
.nav-links a{font-family:var(--p);font-size:8px;color:#fff;padding:9px 12px;border:2px solid #fff;text-transform:uppercase;transition:all .15s;}
.nav-links a:hover{background:var(--pink);color:#000;transform:translate(-2px,-2px);box-shadow:3px 3px 0 #fff;}
.nav-status{display:flex;align-items:center;gap:8px;font-family:var(--p);font-size:8px;color:var(--yellow);}
.nav-status b{width:9px;height:9px;background:var(--yellow);border-radius:50%;animation:blink 1s steps(1) infinite;}
@keyframes blink{50%{opacity:.2;}}
@media(max-width:720px){.nav-links{display:none;}}
/* ---------- utility ---------- */
.btn{
display:inline-flex;align-items:center;gap:10px;cursor:pointer;
font-family:var(--p);font-size:11px;text-transform:uppercase;letter-spacing:.05em;
padding:16px 22px;border:3px solid #000;color:#000;
box-shadow:5px 5px 0 #000;transition:transform .12s,box-shadow .12s,background .12s;
user-select:none;
}
.btn:hover{transform:translate(-2px,-2px);box-shadow:8px 8px 0 #000;}
.btn:active{transform:translate(3px,3px);box-shadow:1px 1px 0 #000;}
.btn-pink{background:var(--pink);}
.btn-yellow{background:var(--yellow);}
.btn-cyan{background:var(--cyan);}
.btn-ghost{background:transparent;color:#fff;}
.btn-ghost:hover{background:#fff;color:#000;box-shadow:8px 8px 0 var(--pink);}
.chip{
display:inline-flex;align-items:center;gap:8px;
font-family:var(--p);font-size:8px;text-transform:uppercase;
border:2px solid #000;padding:8px 12px;background:#fff;color:#000;
box-shadow:3px 3px 0 #000;
}
.chip-y{background:var(--yellow);} .chip-p{background:var(--pink);} .chip-c{background:var(--cyan);} .chip-o{background:var(--orange);}
.marquee{overflow:hidden;white-space:nowrap;position:relative;z-index:3;border-top:3px solid #000;border-bottom:3px solid #000;}
.marquee .mq-track{display:inline-flex;white-space:nowrap;animation:mq 22s linear infinite;}
.marquee.mq-rev .mq-track{animation:mq 22s linear infinite reverse;}
.marquee span{font-family:var(--p);font-size:12px;padding:14px 0;margin:0 22px;flex-shrink:0;}
.mq-y{background:var(--yellow);} .mq-y span{color:#000;}
.mq-p{background:var(--pink);} .mq-p span{color:#000;}
.mq-c{background:var(--cyan);} .mq-c span{color:#000;}
.mq-b{background:#fff;} .mq-b span{color:#000;}
@keyframes mq{0%{transform:translateX(0);}100%{transform:translateX(-50%);}}
.stick{
position:absolute;z-index:5;pointer-events:none;display:flex;align-items:center;justify-content:center;
font-family:var(--p);font-size:9px;text-transform:uppercase;text-align:center;line-height:1.5;
border:3px solid #000;box-shadow:5px 5px 0 #000;padding:10px 14px;
}
.stick-s{font-size:7px;border-radius:50%;width:120px;height:120px;box-shadow:none;}
.star{display:inline-block;color:var(--yellow);filter:drop-shadow(2px 2px 0 #000);}
.sec{position:relative;padding:110px 5vw 90px;}
.sec-index{
font-family:var(--d);font-size:clamp(120px,26vw,300px);line-height:.8;
color:transparent;-webkit-text-stroke:1.5px rgba(255,255,255,0.10);
position:absolute;top:30px;right:-2vw;z-index:0;user-select:none;pointer-events:none;
}
.sec-band{
position:relative;z-index:2;margin-bottom:56px;overflow:hidden;
}
.sec-band .band-inner{display:flex;align-items:baseline;gap:20px;flex-wrap:nowrap;}
.sec-tag{
font-family:var(--p);font-size:9px;color:#000;background:var(--yellow);
border:3px solid #000;padding:8px 12px;box-shadow:3px 3px 0 #000;
transform:rotate(-2deg);white-space:nowrap;
}
.sec-title{
font-family:var(--d);font-size:clamp(44px,10vw,130px);line-height:.9;letter-spacing:-.02em;
white-space:nowrap;text-transform:uppercase;position:relative;display:inline-block;
}
.sec-title .out{color:transparent;-webkit-text-stroke:2px #fff;}
.sec-sub{font-family:var(--m);color:var(--muted);font-size:15px;margin-top:14px;max-width:520px;}
/* ---------- hero ---------- */
.hero{position:relative;min-height:100vh;display:flex;flex-direction:column;justify-content:center;padding:120px 5vw 40px;overflow:hidden;}
.hero-top{display:flex;gap:10px;flex-wrap:wrap;margin-bottom:26px;position:relative;z-index:2;}
.hero-title{
position:relative;z-index:2;font-family:var(--d);line-height:.88;letter-spacing:-.03em;
font-size:clamp(72px,22vw,300px);text-transform:uppercase;
}
.hero-title .l{display:block;}
.hero-title .l2{margin-left:1.1em;}
.hero-title em{font-style:normal;color:transparent;-webkit-text-stroke:2.5px #fff;}
.hero-title .dot{color:var(--yellow);}
.hero-rings{position:absolute;top:50%;right:4vw;transform:translateY(-55%);width:min(46vw,560px);height:min(46vw,560px);z-index:0;pointer-events:none;}
.hero-rings .ring{position:absolute;inset:0;border-radius:50%;border:3px dashed rgba(255,255,255,0.35);animation:spin 30s linear infinite;}
.hero-rings .ring.r2{inset:9%;border:3px solid rgba(255,46,166,0.5);animation-duration:20s;animation-direction:reverse;}
.hero-rings .ring.r3{inset:18%;border:3px dashed rgba(0,244,255,0.5);animation-duration:45s;}
.hero-rings .ring-star{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-size:64px;animation:pop 1s cubic-bezier(.2,1.6,.3,1) 1.2s both;}
.hero-ring-mid{position:absolute;top:50%;right:4vw;transform:translateY(-55%);width:14px;height:14px;background:var(--yellow);border:3px solid #000;z-index:1;animation:blink 1s steps(1) infinite;}
.hero-sub{position:relative;z-index:2;font-family:var(--m);font-size:clamp(14px,1.6vw,19px);color:var(--muted);max-width:560px;line-height:1.7;margin:26px 0 30px;padding-left:18px;border-left:6px solid var(--pink);}
.hero-sub b{color:#fff;}
.hero-cta{display:flex;gap:14px;flex-wrap:wrap;position:relative;z-index:2;}
.hero-float{position:absolute;z-index:2;}
.hf-1{top:22%;left:6%;}
.hf-2{top:32%;right:6%;}
.hf-3{bottom:16%;left:44%;}
.hf-4{bottom:30%;left:12%;}
.hero-scroll{position:absolute;bottom:24px;left:50%;transform:translateX(-50%);font-family:var(--p);font-size:9px;color:var(--muted);display:flex;flex-direction:column;align-items:center;gap:8px;z-index:2;}
.hero-scroll .a{font-size:18px;animation:bob 1.4s ease-in-out infinite;}
@keyframes bob{50%{transform:translateY(6px);}}
@keyframes spin{to{transform:rotate(360deg);}}
@keyframes pop{0%{opacity:0;transform:scale(0) rotate(-40deg);}100%{opacity:1;transform:scale(1) rotate(0);}}
@media(max-width:720px){.hero-rings,.hero-ring-mid{display:none;} .hero-title .l2{margin-left:.6em;}}
/* ---------- stats ---------- */
.stats{display:grid;grid-template-columns:repeat(4,1fr);gap:18px;padding:0 5vw 30px;position:relative;z-index:2;}
.stat{
border:4px solid #000;padding:34px 18px;text-align:center;position:relative;
box-shadow:8px 8px 0 #000;transition:transform .15s,box-shadow .15s;
}
.stat:hover{transform:translate(-3px,-3px);box-shadow:12px 12px 0 #000;}
.stat .n{font-family:var(--d);font-size:clamp(40px,6vw,84px);line-height:1;display:block;}
.stat .l{font-family:var(--p);font-size:8px;text-transform:uppercase;margin-top:12px;display:block;letter-spacing:.06em;}
.st-pink{background:var(--pink);} .st-yellow{background:var(--yellow);} .st-cyan{background:var(--cyan);} .st-orange{background:var(--orange);}
.st-yellow .n,.st-pink .n{color:#000;} .st-cyan .n,.st-orange .n{color:#000;}
.st-pink{transform:rotate(-2deg);} .st-yellow{transform:rotate(1.5deg) translateY(10px);} .st-cyan{transform:rotate(-1deg) translateY(-6px);} .st-orange{transform:rotate(2deg) translateY(6px);}
.stat .tick{position:absolute;top:-12px;right:-12px;width:34px;height:34px;background:#fff;border:3px solid #000;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:14px;box-shadow:3px 3px 0 #000;}
@media(max-width:860px){.stats{grid-template-columns:repeat(2,1fr);gap:26px 14px;} .st-yellow,.st-cyan,.st-orange{transform:none;}}
/* ---------- about ---------- */
.about-grid{display:grid;grid-template-columns:280px 1fr;gap:40px;position:relative;z-index:2;}
.avatar-wrap{position:relative;align-self:start;}
.avatar{width:100%;border:5px solid #000;box-shadow:10px 10px 0 var(--pink);transform:rotate(-3deg);display:block;filter:grayscale(.2) contrast(1.1);transition:transform .2s;}
.avatar:hover{transform:rotate(0) scale(1.02);box-shadow:12px 12px 0 var(--pink);}
.avatar-sticker{position:absolute;bottom:-20px;left:-16px;background:var(--yellow);border:3px solid #000;padding:10px 14px;font-family:var(--p);font-size:8px;transform:rotate(-5deg);box-shadow:4px 4px 0 #000;text-transform:uppercase;}
.card{
background:var(--bg2);border:4px solid #000;box-shadow:10px 10px 0 #000;padding:34px;position:relative;
}
.card::before{content:'';position:absolute;top:-14px;right:30px;width:70px;height:26px;background:var(--tape,#FFC93C);opacity:.85;transform:rotate(3deg);box-shadow:0 0 0 2px #000;}
.card h3{font-family:var(--d);font-size:clamp(24px,3vw,40px);margin-bottom:16px;}
.card p{color:var(--muted);margin-bottom:18px;font-size:14.5px;}
.badges{display:flex;gap:10px;flex-wrap:wrap;margin-bottom:22px;}
.badge{font-family:var(--p);font-size:8px;padding:10px 14px;border:2px solid #000;box-shadow:3px 3px 0 #000;text-transform:uppercase;}
.bg-pink{background:var(--pink);} .bg-cyan{background:var(--cyan);} .bg-green{background:var(--green);} .bg-orange{background:var(--orange);} .bg-purple{background:var(--purple);} .bg-yellow{background:var(--yellow);} .bg-red{background:var(--red);}
.bg-pink,.bg-green,.bg-orange,.bg-yellow,.bg-cyan{color:#000;}
.about-links{display:flex;gap:12px;flex-wrap:wrap;border-top:3px dashed rgba(255,255,255,0.2);padding-top:20px;margin-top:6px;}
@media(max-width:860px){.about-grid{grid-template-columns:1fr;} .avatar{max-width:240px;}}
/* ---------- skills ---------- */
.skills-wrap{position:relative;z-index:2;display:flex;flex-direction:column;gap:40px;}
.skill-group{display:flex;flex-direction:column;gap:16px;}
.skill-group .gl{font-family:var(--p);font-size:10px;text-transform:uppercase;color:var(--yellow);display:flex;align-items:center;gap:12px;}
.skill-group .gl::after{content:'';flex:1;height:3px;background:rgba(255,255,255,0.12);}
.skill-pills{display:flex;flex-wrap:wrap;gap:12px;}
.pill{
font-family:var(--m);font-weight:700;font-size:14px;text-transform:uppercase;letter-spacing:.02em;
padding:13px 18px;background:#fff;color:#000;border:3px solid #000;box-shadow:4px 4px 0 #000;
display:inline-flex;align-items:center;gap:10px;transition:transform .12s,box-shadow .12s,background .12s,color .12s;
}
.pill:nth-child(5n){transform:rotate(-2deg);} .pill:nth-child(5n+2){transform:rotate(1.5deg);} .pill:nth-child(5n+4){transform:rotate(-1deg);}
.pill:hover{transform:translate(-2px,-3px) rotate(0) scale(1.04);box-shadow:8px 8px 0 var(--pink);}
.pill .si{width:20px;height:20px;flex-shrink:0;}
.pill.learn{background:var(--bg2);color:#fff;border-style:dashed;box-shadow:none;}
.pill.learn:hover{background:var(--orange);color:#000;border-style:solid;box-shadow:8px 8px 0 #000;}
/* ---------- projects ---------- */
.proj-list{display:flex;flex-direction:column;gap:26px;position:relative;z-index:2;}
.proj{
background:var(--bg2);border:4px solid #000;box-shadow:10px 10px 0 #000;padding:30px 32px;position:relative;
transition:transform .16s,box-shadow .16s;display:block;overflow:hidden;
}
.proj:nth-child(odd){transform:rotate(-1.2deg);}
.proj:nth-child(even){transform:rotate(1deg);}
.proj:nth-child(3n){transform:rotate(-0.5deg);}
.proj:hover{transform:rotate(0) translate(-3px,-3px);box-shadow:16px 16px 0 var(--pink);}
.proj .num{
position:absolute;top:14px;right:20px;font-family:var(--d);font-size:clamp(56px,9vw,110px);line-height:1;
color:transparent;-webkit-text-stroke:1.5px rgba(255,255,255,0.14);user-select:none;pointer-events:none;
}
.proj-top{display:flex;align-items:center;gap:12px;margin-bottom:18px;flex-wrap:wrap;position:relative;z-index:2;}
.tag{font-family:var(--p);font-size:8px;padding:8px 12px;border:2px solid #000;box-shadow:3px 3px 0 #000;text-transform:uppercase;color:#000;}
.proj-title{font-family:var(--d);font-size:clamp(26px,4.5vw,52px);line-height:1;text-transform:uppercase;position:relative;z-index:2;display:flex;align-items:baseline;gap:14px;}
.proj-title .go{font-family:var(--p);font-size:16px;color:var(--yellow);transition:transform .15s;}
.proj:hover .go{transform:translate(4px,-4px);}
.proj-desc{color:var(--muted);margin-top:14px;max-width:640px;position:relative;z-index:2;font-size:14px;}
.proj:hover .proj-desc{color:#fff;}
/* ---------- scoreboard ---------- */
.score-block{margin-bottom:40px;position:relative;z-index:2;}
.score-head{display:flex;align-items:center;gap:14px;margin-bottom:18px;}
.score-head h3{font-family:var(--d);font-size:clamp(22px,3vw,36px);text-transform:uppercase;}
.score-head .lvl{font-family:var(--p);font-size:9px;background:var(--cyan);color:#000;border:3px solid #000;padding:8px 12px;box-shadow:3px 3px 0 #000;}
.score-cells{display:grid;grid-template-columns:repeat(4,1fr);gap:16px;}
.scell{border:4px solid #000;padding:26px 18px;text-align:center;box-shadow:6px 6px 0 #000;background:var(--bg2);}
.scell .v{font-family:var(--d);font-size:clamp(26px,4vw,48px);display:block;line-height:1;}
.scell .k{font-family:var(--p);font-size:7px;margin-top:10px;display:block;color:var(--muted);text-transform:uppercase;}
.scell.filled{background:var(--pink);color:#000;} .scell.filled .k{color:#000;}
.scell.filled.s2{background:var(--yellow);} .scell.filled.s3{background:var(--cyan);} .scell.filled.s4{background:var(--orange);}
@media(max-width:860px){.score-cells{grid-template-columns:repeat(2,1fr);}}
/* ---------- blog ---------- */
.blog-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(290px,1fr));gap:22px;position:relative;z-index:2;}
.blog{border:4px solid #000;background:var(--bg2);box-shadow:8px 8px 0 #000;padding:26px;display:block;position:relative;transition:transform .15s,box-shadow .15s;}
.blog:nth-child(3n+1){transform:rotate(-1deg);} .blog:nth-child(3n+2){transform:rotate(0.8deg) translateY(6px);} .blog:nth-child(3n){transform:rotate(-0.6deg);}
.blog:hover{transform:translate(-3px,-3px) rotate(0);box-shadow:14px 14px 0 var(--cyan);}
.blog .date{font-family:var(--p);font-size:8px;color:var(--pink);display:block;margin-bottom:12px;}
.blog h3{font-family:var(--d);font-size:19px;line-height:1.15;text-transform:uppercase;margin-bottom:10px;}
.blog p{font-size:13px;color:var(--muted);margin-bottom:16px;}
.blog .tags{display:flex;gap:8px;flex-wrap:wrap;}
.blog .bt{font-family:var(--p);font-size:7px;background:#fff;color:#000;border:2px solid #000;padding:6px 9px;box-shadow:2px 2px 0 #000;}
/* ---------- contact ---------- */
.contact-rows{position:relative;z-index:2;display:flex;flex-direction:column;border-top:4px solid #000;}
.crow{
display:flex;align-items:center;justify-content:space-between;gap:20px;
padding:26px 20px;border:4px solid #000;border-top:none;margin-top:-4px;position:relative;background:var(--bg2);
transition:background .12s,color .12s,padding-left .15s;box-shadow:6px 6px 0 #000;margin-bottom:8px;
}
.crow .k{font-family:var(--p);font-size:10px;color:var(--yellow);text-transform:uppercase;}
.crow .v{font-family:var(--d);font-size:clamp(18px,3vw,30px);text-transform:lowercase;display:flex;align-items:center;gap:10px;}
.crow .arrow{font-size:22px;transition:transform .15s;color:var(--pink);}
.crow:hover{background:var(--pink);color:#000;padding-left:30px;}
.crow:hover .k,.crow:hover .arrow{color:#000;}
.crow:hover .arrow{transform:translate(6px,0);}
/* ---------- footer ---------- */
.footer{position:relative;padding:90px 5vw 40px;text-align:center;overflow:hidden;}
.footer .fword{font-family:var(--d);font-size:clamp(70px,20vw,280px);line-height:.9;color:transparent;-webkit-text-stroke:2px rgba(255,255,255,0.14);text-transform:uppercase;user-select:none;}
.footer .fmeta{font-family:var(--p);font-size:9px;color:var(--muted);margin-top:26px;display:flex;justify-content:center;gap:18px;flex-wrap:wrap;}
.footer .fmeta a{color:#fff;text-decoration:underline;text-underline-offset:4px;}
.footer .fmeta a:hover{color:var(--pink);}
.top-btn{margin-top:30px;}
/* ---------- reveal system ---------- */
html.js [data-in]{opacity:0;transition:opacity .7s ease,transform .7s cubic-bezier(.2,1.3,.3,1);will-change:transform,opacity;}
html.js [data-in="up"]{transform:translateY(60px) rotate(-1.2deg);}
html.js [data-in="down"]{transform:translateY(-60px) rotate(1deg);}
html.js [data-in="left"]{transform:translateX(-80px) rotate(-1.5deg);}
html.js [data-in="right"]{transform:translateX(80px) rotate(1.5deg);}
html.js [data-in="pop"]{transform:scale(.6) rotate(-6deg);}
html.js [data-in="flip"]{transform:translateY(40px) rotateX(-60deg);transform-style:preserve-3d;}
html.js [data-in].in{opacity:1;transform:none;}
@media(max-width:720px){
.sec{padding:80px 5vw 70px;}
.sec-band .band-inner{flex-direction:column;align-items:flex-start;gap:10px;}
.sec-title{white-space:normal;}
.proj .num{font-size:60px;}
}
@media(prefers-reduced-motion:reduce){
*,*::before,*::after{animation:none!important;transition:none!important;}
.splash{display:none;}
}
</style>
</head>
<body>
<div class="splash" aria-hidden="true"><span>M</span><span>I</span><span>L</span><span>E</span><span>S</span><div class="splash-tag">MAXIMALISM ON</div></div>
<div class="bg-grid" aria-hidden="true"></div>
<div class="noise" aria-hidden="true"></div>
<div class="vignette" aria-hidden="true"></div>
<div class="cursor" id="cursor"></div>
<div class="glow" id="glow"></div>
<div class="progress" id="progress"></div>
<nav class="nav">
<a class="nav-logo" href="#top"><span class="dot"></span>MILES</a>
<div class="nav-links">
<a href="#about">About</a>
<a href="#skills">Skills</a>
<a href="#projects">Builds</a>
<a href="#blog">Devlog</a>
<a href="#contact">Contact</a>
</div>
<span class="nav-status"><b></b> USUALLY ONLINE</span>
</nav>
<header class="hero" id="top">
<div class="hero-rings" aria-hidden="true">
<div class="ring"></div>
<div class="ring r2"></div>
<div class="ring r3"></div>
<div class="ring-star"><span class="star"></span></div>
</div>
<div class="hero-ring-mid" aria-hidden="true"></div>
<div class="hero-top">
<span class="chip chip-y">★ MILES WOLF ALLEN</span>
<span class="chip chip-p">DEVELOPER &amp; 3D ARTIST</span>
<span class="chip chip-c">DISKETTE LABS CO-FOUNDER</span>
</div>
<h1 class="hero-title" id="heroTitle">
<span class="l"><em>MI</em>L</span>
<span class="l l2"><em>E</em>S<span class="dot">.</span></span>
</h1>
<div class="hero-float hf-1 stick" data-speed="18">★ EST. 2008</div>
<div class="hero-float hf-2 stick stick-s"><span class="star"></span></div>
<div class="hero-float hf-3 stick" style="background:var(--yellow);color:#000;" data-speed="-14">THE WOW</div>
<div class="hero-float hf-4 stick stick-s" style="border-radius:50%;background:var(--pink);"><span class="star"></span></div>
<p class="hero-sub">I make <b>games</b>, <b>tools</b>, and <b>websites</b>. Still in school, currently building a full <b>Electron replacement</b> — send help. 160 repos and counting.</p>
<div class="hero-cta">
<a class="btn btn-pink" href="#projects">SEE THE BUILDS ↓</a>
<a class="btn btn-ghost" href="https://github.com/mileswolfallen2" target="_blank" rel="noopener">GITHUB ↗</a>
</div>
<div class="hero-scroll">SCROLL<div class="a"></div></div>
</header>
<div class="marquee mq-y" data-mq="build"> </div>
<section class="sec" id="stats">
<div class="sec-index" data-par="12">000</div>
<div class="sec-band">
<div class="band-inner">
<span class="sec-tag">LEVEL 00</span>
<h2 class="sec-title" data-band="1">THE <span class="out">NUMBERS</span>.</h2>
</div>
</div>
<div class="stats">
<div class="stat st-pink" data-in="left"><span class="tick"></span><span class="n num" data-count="160">0</span><span class="l">REPOS ONLINE</span></div>
<div class="stat st-yellow" data-in="pop"><span class="tick"></span><span class="n num" data-count="91">0</span><span class="l">STARS EARNED</span></div>
<div class="stat st-cyan" data-in="right"><span class="tick"></span><span class="n num" data-count="13">0</span><span class="l">WATCHING ME</span></div>
<div class="stat st-orange" data-in="down"><span class="tick"></span><span class="n num" data-count="37">0</span><span class="l">I WATCH</span></div>
</div>
</section>
<section class="sec" id="about">
<div class="sec-index" data-par="8">01</div>
<div class="sec-band">
<div class="band-inner">
<span class="sec-tag">LEVEL 01 // IDENTITY</span>
<h2 class="sec-title" data-band="-1"><span class="out">WHO'S</span> MILES<span class="dot">?</span></h2>
</div>
<p class="sec-sub">the human behind the commits. pancakes &gt; waffles, cereal is soup, software should feel good to use.</p>
</div>
<div class="about-grid">
<div class="avatar-wrap" data-in="left">
<img class="avatar" src="https://avatars.githubusercontent.com/u/115095719?v=4" alt="Miles Wolf Allen" loading="lazy" width="280" height="280">
<span class="avatar-sticker">@mileswolfallen2</span>
</div>
<div class="card" data-in="up">
<h3>// PLAYER BIO</h3>
<p>I build things on the internet. Some are games, some are tools, and some are just because I thought it'd be fun. I'm co-founder of <b style="color:#fff">Diskette Labs</b>, still in school, and chasing the dream of a world without bundled Chromium.</p>
<div class="badges">
<span class="badge bg-pink">PULL SHARK ×2</span>
<span class="badge bg-yellow">YOLO</span>
<span class="badge bg-green">QUICKDRAW</span>
<span class="badge bg-orange">GEOMETRY DASH ADDICT</span>
</div>
<div class="about-links">
<a class="btn btn-yellow" href="https://diskettelabs.com/" target="_blank" rel="noopener">DISKETTE LABS ↗</a>
<a class="btn btn-ghost" href="about-me.html">MORE ABOUT ME →</a>
</div>
</div>
</div>
</section>
<div class="marquee mq-p mq-rev" data-mq="warn"> </div>
<section class="sec" id="skills">
<div class="sec-index" data-par="10">02</div>
<div class="sec-band">
<div class="band-inner">
<span class="sec-tag">LEVEL 02 // LOADOUT</span>
<h2 class="sec-title" data-band="1">MY <span class="out">LOADOUT</span>.</h2>
</div>
<p class="sec-sub">what I actually know how to use (and what I'm currently failing at).</p>
</div>
<div class="skills-wrap">
<div class="skill-group" data-in="up">
<span class="gl">READY TO USE</span>
<div class="skill-pills" id="skillPills">
<span class="pill" data-si="javascript">JS</span>
<span class="pill" data-si="nodedotjs">BACKEND JS</span>
<span class="pill" data-si="html5">HTML</span>
<span class="pill" data-si="css3">CSS</span>
<span class="pill" data-si="python">PYTHON</span>
<span class="pill" data-si="git">GIT</span>
<span class="pill" data-si="blender">BLENDER</span>
<span class="pill" data-si="unity">UNITY</span>
<span class="pill" data-si="unrealengine">UNREAL</span>
<span class="pill" data-si="cloudflare">CLOUDFLARE</span>
<span class="pill" data-si="linux">LINUX</span>
<span class="pill" data-si="netlify">NETLIFY</span>
<span class="pill" data-si="gnubash">BASH</span>
<span class="pill" data-si="github">GITHUB</span>
<span class="pill" data-si="electron">ELECTRON</span>
<span class="pill" data-si="c">GELECTRON</span>
</div>
</div>
<div class="skill-group" data-in="up">
<span class="gl">CURRENTLY UNLOCKING</span>
<div class="skill-pills">
<span class="pill learn" data-si="php">PHP</span>
<span class="pill learn" data-si="dotnet">.NET</span>
<span class="pill learn" data-si="nixos">NIX</span>
<span class="pill learn" data-si="yarn">YARN</span>
</div>
</div>
</div>
</section>
<section class="sec" id="projects">
<div class="sec-index" data-par="14">03</div>
<div class="sec-band">
<div class="band-inner">
<span class="sec-tag">LEVEL 03 // BUILDS</span>
<h2 class="sec-title" data-band="-1">THE <span class="out">BUILDS</span>.</h2>
</div>
<p class="sec-sub">stuff I've made (and some I forked). every one of these was at least 80% 2am.</p>
</div>
<div class="proj-list">
<a class="proj" href="https://milesallen.site/projects/omniemu.html" data-par="-8">
<span class="num">01</span>
<div class="proj-top"><span class="tag" style="background:var(--green);">ACTIVE</span><span class="chip" style="font-size:7px;">MIT · v0.3.2 · TS</span></div>
<div class="proj-title">OmniEmu 2.0 <span class="go"></span></div>
<div class="proj-desc">All your emulators in one place. Install 20+ emulators, scan your ROMs, launch games without opening 15 apps.</div>
</a>
<a class="proj" href="https://milesallen.site/projects/gelectron.html" data-par="10">
<span class="num">02</span>
<div class="proj-top"><span class="tag" style="background:var(--yellow);">EARLY</span><span class="chip" style="font-size:7px;">RUST + NODE · MIT</span></div>
<div class="proj-title">Gelectron <span class="go"></span></div>
<div class="proj-desc">Drop-in Electron replacement using native web views (WKWebView / WebView2 / WebKitGTK) instead of bundling Chromium. The send-help project.</div>
</a>
<a class="proj" href="https://vanilla.milesallen.site/" target="_blank" rel="noopener" data-par="-12">
<span class="num">03</span>
<div class="proj-top"><span class="tag" style="background:var(--cyan);">UNRELEASED</span><span class="chip" style="font-size:7px;">VANILLA JS</span></div>
<div class="proj-title">Vanilla <span class="go"></span></div>
<div class="proj-desc">A clean, minimal web experiment. Pure vanilla JS, no frameworks, no cruft.</div>
</a>
<a class="proj" href="https://milesallen.site/projects/fedl.html" data-par="6">
<span class="num">04</span>
<div class="proj-top"><span class="tag" style="background:var(--red);">LIVE</span><span class="chip" style="font-size:7px;">2196 COMMITS</span></div>
<div class="proj-title">FEDL <span class="go"></span></div>
<div class="proj-desc">The demon list for Geometry Dash. Ranked levels, run submissions, and a community way better at the game than me.</div>
</a>
<a class="proj" href="https://milesallen.site/projects/command-move.html" data-par="-10">
<span class="num">05</span>
<div class="proj-top"><span class="tag" style="background:var(--purple);">SWIFT</span><span class="chip" style="font-size:7px;">MACOS · MIT</span></div>
<div class="proj-title">CommandMove <span class="go"></span></div>
<div class="proj-desc">True cut-and-paste for Finder on macOS. Select files, Cmd+X, navigate, Cmd+V. What Apple forgot to build.</div>
</a>
<a class="proj" href="https://milesallen.site/projects/noto.html" data-par="8">
<span class="num">06</span>
<div class="proj-top"><span class="tag" style="background:var(--green);">ACTIVE</span><span class="chip" style="font-size:7px;">FLUTTER · AI</span></div>
<div class="proj-title">Noto <span class="go"></span></div>
<div class="proj-desc">Note-taking with AI built in. Flutter, powered by Cortex AI, actually good at organizing my chaos.</div>
</a>
<a class="proj" href="https://milesallen.site/projects/nova.html" data-par="-6">
<span class="num">07</span>
<div class="proj-top"><span class="tag" style="background:var(--yellow);">PYTHON</span><span class="chip" style="font-size:7px;">MIT · LOCAL AI</span></div>
<div class="proj-title">Nova AI <span class="go"></span></div>
<div class="proj-desc">AI that runs on your machine. Desktop GUI, web interface, CLI. No cloud, no subscriptions, just vibes.</div>
</a>
<a class="proj" href="https://milesallen.site/projects/music-app.html" data-par="12">
<span class="num">08</span>
<div class="proj-top"><span class="tag" style="background:var(--cyan);">JS</span><span class="chip" style="font-size:7px;">APACHE-2.0</span></div>
<div class="proj-title">Music App <span class="go"></span></div>
<div class="proj-desc">Music player that doesn't interrupt you with ads. YouTube Music minus the annoying parts.</div>
</a>
<a class="proj" href="https://milesallen.site/projects/rhythm-game.html" data-par="-8">
<span class="num">09</span>
<div class="proj-top"><span class="tag" style="background:var(--pink);">HTML</span><span class="chip" style="font-size:7px;">MPL-2.0</span></div>
<div class="proj-title">Rhythm Game <span class="go"></span></div>
<div class="proj-desc">Hit keys to the beat. Song selection, real-time notes, keyboard controls. My fingers hurt.</div>
</a>
<a class="proj" href="https://milesallen.site/projects/geode-mod.html" data-par="9">
<span class="num">10</span>
<div class="proj-top"><span class="tag" style="background:var(--orange);">WIP</span><span class="chip" style="font-size:7px;">MIT</span></div>
<div class="proj-title">FEDL Geode Mod <span class="go"></span></div>
<div class="proj-desc">Geometry Dash mod that shows the demon list in-game. Roulette mode, banned mod detection, more.</div>
</a>
<a class="proj" href="https://milesallen.site/projects/decompilations.html" data-par="-9">
<span class="num">11</span>
<div class="proj-top"><span class="tag" style="background:var(--pink);">HTML</span><span class="chip" style="font-size:7px;">MIT</span></div>
<div class="proj-title">Decompilations <span class="go"></span></div>
<div class="proj-desc">Native PC ports and decompilations of games. Progress tracking for projects that probably shouldn't exist.</div>
</a>
<a class="proj" href="https://milesallen.site/projects/issue-tracker.html" data-par="7">
<span class="num">12</span>
<div class="proj-top"><span class="tag" style="background:var(--cyan);">HTML</span><span class="chip" style="font-size:7px;">MIT · NODE</span></div>
<div class="proj-title">Issue Tracker <span class="go"></span></div>
<div class="proj-desc">Built my own issue tracker because why not. Node.js backend, no frameworks, raw determination.</div>
</a>
<a class="proj" href="https://milesallen.site/projects/moon-gaming.html" data-par="-11">
<span class="num">13</span>
<div class="proj-top"><span class="tag" style="background:var(--yellow);">HTML</span><span class="chip" style="font-size:7px;">1542 COMMITS</span></div>
<div class="proj-title">Moon Gaming <span class="go"></span></div>
<div class="proj-desc">Game hub with 1,500+ commits. A growing library of browser games I made at 2am.</div>
</a>
</div>
</section>
<div class="marquee mq-c" data-mq="project"> </div>
<section class="sec" id="highlights">
<div class="sec-index" data-par="9">04</div>
<div class="sec-band">
<div class="band-inner">
<span class="sec-tag">LEVEL 04 // SCOREBOARD</span>
<h2 class="sec-title" data-band="1">SCORE<span class="out">BOARD</span>.</h2>
</div>
<p class="sec-sub">what my projects have achieved. all numbers real, some embarrassing.</p>
</div>
<div class="score-block" data-in="up">
<div class="score-head"><span class="lvl">HIGH SCORE</span><h3>FEDL</h3></div>
<div class="score-cells">
<div class="scell filled"><span class="v num" data-count="3839">0</span><span class="k">VERIFIED RUNS</span></div>
<div class="scell filled s2"><span class="v num" data-count="341">0</span><span class="k">RANKED LEVELS</span></div>
<div class="scell filled s3"><span class="v num" data-count="250" data-suffix="+">0</span><span class="k">ACTIVE PLAYERS</span></div>
<div class="scell filled s4"><span class="v num" data-count="3800" data-suffix="+">0</span><span class="k">YOUTUBE VIDEOS</span></div>
</div>
</div>
<div class="score-block" data-in="up">
<div class="score-head"><span class="lvl">STAGE CLEAR</span><h3>OmniEmu 2.0</h3></div>
<div class="score-cells">
<div class="scell filled"><span class="v num" data-count="20" data-suffix="+">0</span><span class="k">EMULATORS</span></div>
<div class="scell filled s2"><span class="v num" data-count="3">0</span><span class="k">PLATFORMS</span></div>
<div class="scell"><span class="v">v0.3.2</span><span class="k">LATEST</span></div>
<div class="scell"><span class="v">TS</span><span class="k">BUILT WITH</span></div>
</div>
</div>
<div class="score-block" data-in="up">
<div class="score-head"><span class="lvl">SIDE QUESTS</span><h3>Other projects</h3></div>
<div class="score-cells">
<div class="scell filled"><span class="v num" data-count="3">0</span><span class="k">NOVA INTERFACES</span></div>
<div class="scell filled s2"><span class="v num" data-count="5">0</span><span class="k">NOTO AI FEATURES</span></div>
<div class="scell filled s3"><span class="v num" data-count="1542">0</span><span class="k">MOON GAMING COMMITS</span></div>
<div class="scell"><span class="v">MIT</span><span class="k">LICENSED</span></div>
</div>
</div>
</section>
<section class="sec" id="blog">
<div class="sec-index" data-par="13">05</div>
<div class="sec-band">
<div class="band-inner">
<span class="sec-tag">LEVEL 05 // DEVLOG</span>
<h2 class="sec-title" data-band="-1">THE <span class="out">DEVLOG</span>.</h2>
</div>
<p class="sec-sub">things I've learned, broken, and fixed.</p>
</div>
<div class="blog-grid">
<a class="blog" href="https://milesallen.site/blog/diskette-devlog.html" data-in="up">
<span class="date">2026 // 001</span><h3>Focusing on Diskette Labs</h3>
<p>I'm co-founder of Diskette Labs, a product design collective started by Owen. It's where my focus is now — still open to collabs.</p>
<div class="tags"><span class="bt">DESIGN</span><span class="bt">COLLECTIVE</span></div>
</a>
<a class="blog" href="https://milesallen.site/blog/gelectron-devlog.html" data-in="up">
<span class="date">2026 // 002</span><h3>Why I Built Gelectron</h3>
<p>Electron bundles Chromium with every app. 150-300MB per app, hundreds of MB of RAM. Native web views fix that.</p>
<div class="tags"><span class="bt">RUST</span><span class="bt">NATIVE</span></div>
</a>
<a class="blog" href="https://milesallen.site/blog/omniemu-devlog.html" data-in="up">
<span class="date">2026 // 003</span><h3>Why I Built OmniEmu</h3>
<p>I got tired of opening 15 different emulator apps. So I built one that manages them all. Here's how it started.</p>
<div class="tags"><span class="bt">TYPESCRIPT</span><span class="bt">ELECTRON</span></div>
</a>
<a class="blog" href="https://milesallen.site/blog/command-move-devlog.html" data-in="up">
<span class="date">2026 // 004</span><h3>CommandMove: Cut &amp; Paste</h3>
<p>macOS doesn't have Cmd+X for files. I fixed that. Global event taps, AppleScript, and a lot of Accessibility permissions.</p>
<div class="tags"><span class="bt">SWIFT</span><span class="bt">MACOS</span></div>
</a>
<a class="blog" href="https://milesallen.site/blog/fedl-devlog.html" data-in="up">
<span class="date">2025 // 005</span><h3>Running the FEDL</h3>
<p>What it takes to maintain a Geometry Dash demon list. 3,800+ verified runs, ranked levels, a community that never sleeps.</p>
<div class="tags"><span class="bt">NODE.JS</span><span class="bt">COMMUNITY</span></div>
</a>
<a class="blog" href="https://milesallen.site/blog/nova-devlog.html" data-in="up">
<span class="date">2025 // 006</span><h3>Building Nova AI</h3>
<p>Local AI that doesn't phone home. Desktop GUI, web interface, CLI — no subscriptions, no cloud, no nonsense.</p>
<div class="tags"><span class="bt">PYTHON</span><span class="bt">AI</span></div>
</a>
</div>
</section>
<div class="marquee mq-b mq-rev" data-mq="final"> </div>
<section class="sec" id="contact">
<div class="sec-index" data-par="7">06</div>
<div class="sec-band">
<div class="band-inner">
<span class="sec-tag">LEVEL 06 // REACH OUT</span>
<h2 class="sec-title" data-band="1">GET IN <span class="out">TOUCH</span>.</h2>
</div>
<p class="sec-sub">unless you're a bot, then please go away.</p>
</div>
<div class="contact-rows" data-in="up">
<a class="crow" href="mailto:[email protected]"><span class="k">EMAIL</span><span class="v">[email protected]<span class="arrow"></span></span></a>
<a class="crow" href="https://github.com/mileswolfallen2" target="_blank" rel="noopener"><span class="k">GITHUB</span><span class="v">mileswolfallen2<span class="arrow"></span></span></a>
<a class="crow" href="https://replit.com/@MilesAllen1" target="_blank" rel="noopener"><span class="k">REPLIT</span><span class="v">@MilesAllen1<span class="arrow"></span></span></a>
<a class="crow" href="https://codepen.io/mileswolfallen2-the-typescripter" target="_blank" rel="noopener"><span class="k">CODEPEN</span><span class="v">mileswolfallen2<span class="arrow"></span></span></a>
<a class="crow" href="https://me.fedl.site" target="_blank" rel="noopener"><span class="k">WEBSITE</span><span class="v">me.fedl.site<span class="arrow"></span></span></a>
</div>
</section>
<footer class="footer">
<div class="fword">MILES</div>
<div class="fmeta">
<a href="#top">BACK TO TOP ↑</a>
<a href="https://milesallen.site/uses.html">USES</a>
<a href="https://milesallen.site/now.html">NOW</a>
<a href="https://milesallen.site/colophon.html">COLOPHON</a>
<span>BUILT BY MILES © 2026</span>
</div>
<div class="top-btn"><button class="btn btn-yellow" onclick="document.getElementById('top').scrollIntoView({behavior:'smooth'})"></button></div>
</footer>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/gsap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/ScrollTrigger.min.js"></script>
<script>
(function(){
'use strict';
var body=document.body, html=document.documentElement;
var reduce=window.matchMedia&&window.matchMedia('(prefers-reduced-motion: reduce)').matches;
var fine=window.matchMedia&&window.matchMedia('(pointer: fine)').matches;
/* ---------- marquees: render track ---------- */
function renderMarquees(){
var sets={
build:['BUILDING EMULATORS','SEND HELP','160 REPOS AND COUNTING','STILL DEBUGGING','GEOMETRY DASH ADDICT','USUALLY ONLINE','FULL MAXIMALISM','CEREAL IS SOUP'],
warn:['RATED ★★★★★','EST. 2008','PULL SHARK ×2','OVERCLOCKED','DISKETTE LABS','COFFEE COUNT: UNKNOWN','BUGS: INFINITE'],
project:['OMNIEMU 2.0','GELECTRON','FEDL','NOTO','NOVA AI','COMMANDMOVE','MOON GAMING','1,500+ COMMITS','MIT LICENSE'],
final:['EMAIL ME','PLEASE','GITHUB ↗','REPLIT ↗','CODEPEN ↗','I RESPOND','MAYBE','FAST'],
};
Object.keys(sets).forEach(function(k){
document.querySelectorAll('[data-mq="'+k+'"]').forEach(function(wrap){
var track=document.createElement('div');
track.className='mq-track';
var half='';
sets[k].forEach(function(t){ half+='<span>★ '+t+'</span>'; });
track.innerHTML=half+half;
wrap.appendChild(track);
});
});
}
renderMarquees();
/* ---------- skill icons ---------- */
function addSkillIcons(){
document.querySelectorAll('.pill[data-si]').forEach(function(pill){
var img=document.createElement('img');
img.className='si';
img.alt='';
img.loading='lazy';
img.src='https://cdn.simpleicons.org/'+pill.getAttribute('data-si')+'/000000';
pill.insertBefore(img,pill.firstChild);
});
}
addSkillIcons();
/* ---------- cursor ---------- */
var cur=document.getElementById('cursor'), glow=document.getElementById('glow');
if (cur && fine){
var cx=-100,cy=-100,tx=-100,ty=-100,gx=-100,gy=-100,gtx=-100,gty=-100;
document.addEventListener('mousemove',function(e){ tx=e.clientX; ty=e.clientY; },{passive:true});
function loop(){
cx+=(tx-cx)*0.35; cy+=(ty-cy)*0.35;
gx+=(tx-gx)*0.08; gy+=(ty-gy)*0.08;
cur.style.transform='translate('+(cx-6)+'px,'+(cy-6)+'px)';
glow.style.transform='translate('+(gx-160)+'px,'+(gy-160)+'px)';
requestAnimationFrame(loop);
}
loop();
document.addEventListener('mouseover',function(e){
if (e.target.closest&&e.target.closest('a,button,.btn,.pill,.proj,.crow')){
cur.classList.add('on');
document.documentElement.style.setProperty('--mouse','auto');
}
},{passive:true});
document.addEventListener('mouseout',function(e){
if (e.target.closest&&e.target.closest('a,button,.btn,.pill,.proj,.crow')){
cur.classList.remove('on');
}
},{passive:true});
}
/* ---------- scroll progress ---------- */
var prog=document.getElementById('progress');
function onScroll(){ prog.style.width=(window.scrollY/(document.body.scrollHeight-window.innerHeight)*100)+'%'; }
window.addEventListener('scroll',onScroll,{passive:true});
onScroll();
/* ---------- count-up ---------- */
function countUp(el){
var target=parseInt(el.getAttribute('data-count'),10)||0;
var suffix=el.getAttribute('data-suffix')||'';
var t0=null;
function fmt(n){ return Math.round(n).toLocaleString('en-US')+suffix; }
function step(ts){
if(t0===null) t0=ts;
var p=Math.min(1,(ts-t0)/1200);
var ease=1-Math.pow(1-p,3);
el.textContent=fmt(target*ease);
if(p<1) requestAnimationFrame(step);
else el.textContent=fmt(target);
}
if(reduce){ el.textContent=fmt(target); return; }
requestAnimationFrame(step);
}
if('IntersectionObserver' in window){
var io=new IntersectionObserver(function(entries){
entries.forEach(function(e){
if(e.isIntersecting){
countUp(e.target);
io.unobserve(e.target);
}
});
},{threshold:0.5});
document.querySelectorAll('.num[data-count]').forEach(function(el){ io.observe(el); });
}
/* ---------- reveal system ---------- */
function revealAll(){
document.querySelectorAll('[data-in]').forEach(function(el){ el.classList.add('in'); });
}
if('IntersectionObserver' in window && !reduce){
var rio=new IntersectionObserver(function(entries){
entries.forEach(function(e){
if(e.isIntersecting){
e.target.classList.add('in');
rio.unobserve(e.target);
}
});
},{threshold:0.15,rootMargin:'0px 0px -40px 0px'});
document.querySelectorAll('[data-in]').forEach(function(el){ rio.observe(el); });
} else {
revealAll();
}
/* ---------- konami ---------- */
(function(){
var seq=[38,38,40,40,37,39,37,39,66,65];
var pos=0;
document.addEventListener('keydown',function(e){
if(e.keyCode===seq[pos]){ pos++; if(pos===seq.length){ pos=0; party(); } }
else pos=0;
});
function party(){
var colors=['#FF2EA6','#F7FF00','#00F4FF','#FF5C00','#00FF85','#FF1F1F'];
for(var i=0;i<36;i++){
var s=document.createElement('div');
s.style.cssText='position:fixed;left:50%;top:50%;width:'+(6+Math.random()*16)+'px;height:'+(6+Math.random()*16)+'px;z-index:950;pointer-events:none;border:2px solid #000;background:'+colors[i%colors.length]+';box-shadow:3px 3px 0 #000;';
document.body.appendChild(s);
var ang=Math.random()*Math.PI*2;
var dist=60+Math.random()*360;
var dx=Math.cos(ang)*dist, dy=Math.sin(ang)*dist;
s.animate([
{transform:'translate(-50%,-50%) rotate(0deg)',opacity:1},
{transform:'translate(calc(-50% + '+dx+'px), calc(-50% + '+dy+'px)) rotate('+(Math.random()*720-360)+'deg)',opacity:0}
],{duration:900+Math.random()*500,easing:'cubic-bezier(.2,.8,.2,1)'}).onfinish=function(){ s.remove(); };
}
}
})();
/* ---------- GSAP scroll choreography ---------- */
if (window.gsap && window.ScrollTrigger && !reduce){
gsap.registerPlugin(ScrollTrigger);
/* hero parallax */
gsap.to('#heroTitle',{yPercent:-18,scale:.96,opacity:.25,ease:'none',
scrollTrigger:{trigger:'#top',start:'top top',end:'bottom top',scrub:1}});
gsap.to('.hero-sub',{yPercent:-60,opacity:0,ease:'none',
scrollTrigger:{trigger:'#top',start:'10% top',end:'bottom top',scrub:1}});
gsap.to('.hero-rings',{scale:1.15,opacity:.3,ease:'none',
scrollTrigger:{trigger:'#top',start:'top top',end:'bottom top',scrub:1}});
/* floating stickers: parallax via data-speed */
gsap.utils.toArray('[data-par]').forEach(function(el){
if(el.classList && el.classList.contains('proj'))return;
var rate=parseFloat(el.getAttribute('data-par'))||0;
if(!rate)return;
gsap.to(el,{y:rate*10,ease:'none',
scrollTrigger:{trigger:el,start:'top bottom',end:'bottom top',scrub:1}});
});
gsap.utils.toArray('[data-speed]').forEach(function(el){
var rate=parseFloat(el.getAttribute('data-speed'))||0;
gsap.to(el,{y:rate*12,ease:'none',
scrollTrigger:{trigger:el,start:'top bottom',end:'bottom top',scrub:1}});
});
/* section title bands slide */
gsap.utils.toArray('[data-band]').forEach(function(t){
var dir=parseFloat(t.getAttribute('data-band'))||0;
gsap.fromTo(t,{xPercent:dir*8},{xPercent:dir*-8,ease:'none',
scrollTrigger:{trigger:t,start:'top bottom',end:'bottom top',scrub:1}});
});
/* project cards: flip + rise */
gsap.utils.toArray('.proj').forEach(function(card){
var side=(parseFloat(card.getAttribute('data-par'))||0)>0?-1:1;
gsap.set(card,{transition:'none'});
gsap.fromTo(card,
{y:80,rotation:side*4,opacity:0},
{y:0,rotation:0,opacity:1,duration:1,ease:'power3.out',
scrollTrigger:{trigger:card,start:'top 94%'},
onComplete:function(){ gsap.set(card,{clearProps:'transform,opacity,transition'}); }});
});
ScrollTrigger.refresh();
}
/* if no gsap, still make sure proj cards visible */
else if(!reduce){
setTimeout(function(){
document.querySelectorAll('.proj').forEach(function(c){ c.style.opacity='1'; });
},1200);
}
})();
</script>
</body>
</html>