mirror of
https://github.com/mileswolfallen2/miles-web.git
synced 2026-09-08 19:45:55 +00:00
1327 lines
56 KiB
HTML
1327 lines
56 KiB
HTML
<!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</title>
|
||
<meta name="description" content="Miles Wolf Allen — Developer & 3D Artist. Games, tools, and websites built with craft and chaos.">
|
||
<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:wght@400;700&display=swap" rel="stylesheet">
|
||
<script>document.documentElement.className='js';</script>
|
||
<style>
|
||
/* ─── RESET & TOKENS ─── */
|
||
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
|
||
:root {
|
||
--bg: #08080a;
|
||
--bg2: #111116;
|
||
--bg3: #1c1c23;
|
||
--ink: #ffffff;
|
||
--muted: #72727c;
|
||
--dim: #2e2e38;
|
||
--pink: #FF2EA6;
|
||
--yellow: #F7FF00;
|
||
--cyan: #00F4FF;
|
||
--orange: #FF5C00;
|
||
--green: #00FF85;
|
||
--purple: #8A2BFF;
|
||
--red: #FF1F1F;
|
||
--rule: rgba(255,255,255,.08);
|
||
--serif: 'Archivo Black', Impact, sans-serif;
|
||
--mono: 'Space Mono', monospace;
|
||
--pixel: 'Press Start 2P', monospace;
|
||
}
|
||
html { scroll-behavior: auto; overflow-x: hidden; scrollbar-width: none; }
|
||
html::-webkit-scrollbar { display: none; }
|
||
body {
|
||
background: var(--bg);
|
||
color: var(--ink);
|
||
font-family: var(--mono);
|
||
font-size: 14px;
|
||
line-height: 1.65;
|
||
overflow-x: hidden;
|
||
-webkit-font-smoothing: antialiased;
|
||
cursor: none;
|
||
}
|
||
::selection { background: var(--yellow); color: #000; }
|
||
a { color: inherit; text-decoration: none; }
|
||
img { display: block; max-width: 100%; }
|
||
|
||
/* ─── FIXED BG GRID ─── */
|
||
.bg-grid {
|
||
position: fixed; inset: 0; z-index: 0; pointer-events: none;
|
||
background-image:
|
||
linear-gradient(rgba(255,255,255,.028) 1px, transparent 1px),
|
||
linear-gradient(90deg, rgba(255,255,255,.028) 1px, transparent 1px);
|
||
background-size: 48px 48px;
|
||
}
|
||
.noise {
|
||
position: fixed; inset: 0; z-index: 9000; pointer-events: none; opacity: .045;
|
||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.88' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)'/%3E%3C/svg%3E");
|
||
}
|
||
.vignette {
|
||
position: fixed; inset: 0; z-index: 1; pointer-events: none;
|
||
background: radial-gradient(ellipse at center, transparent 45%, rgba(0,0,0,.6) 100%);
|
||
}
|
||
</style>
|
||
<style>
|
||
/* ─── CUSTOM CURSOR ─── */
|
||
.c-dot {
|
||
position: fixed; top: 0; left: 0; z-index: 9500; pointer-events: none;
|
||
width: 12px; height: 12px; background: var(--yellow);
|
||
border: 2px solid #000; box-shadow: 3px 3px 0 #000;
|
||
transform: translate(-50%, -50%);
|
||
transition: width .2s, height .2s, border-radius .2s, background .2s;
|
||
will-change: left, top;
|
||
}
|
||
.c-ring {
|
||
position: fixed; top: 0; left: 0; z-index: 9499; pointer-events: none;
|
||
width: 44px; height: 44px;
|
||
border: 2px solid rgba(247,255,0,.4);
|
||
transform: translate(-50%, -50%);
|
||
transition: width .35s ease, height .35s ease, border-color .25s;
|
||
will-change: left, top;
|
||
}
|
||
body.cursor-hover .c-dot {
|
||
width: 52px; height: 52px; border-radius: 0;
|
||
background: var(--pink); box-shadow: 5px 5px 0 #000; border-width: 3px;
|
||
}
|
||
body.cursor-hover .c-ring { width: 0; height: 0; border-color: transparent; }
|
||
@media (pointer: coarse) { .c-dot, .c-ring { display: none; } body { cursor: auto; } }
|
||
|
||
/* ─── LOADER ─── */
|
||
.loader {
|
||
position: fixed; inset: 0; z-index: 8000;
|
||
background: var(--yellow);
|
||
display: flex; align-items: flex-end; justify-content: flex-start;
|
||
padding: clamp(24px,5vw,60px);
|
||
pointer-events: none;
|
||
overflow: hidden;
|
||
}
|
||
.loader::before {
|
||
content: 'LOADING';
|
||
position: absolute; top: clamp(24px,5vw,60px); right: clamp(24px,5vw,60px);
|
||
font-family: var(--pixel); font-size: clamp(8px,.7vw,12px); color: #000;
|
||
letter-spacing: .15em; opacity: .4;
|
||
}
|
||
.loader-count {
|
||
font-family: var(--serif); font-size: clamp(88px,20vw,220px);
|
||
font-weight: 900; color: #000; line-height: 1;
|
||
font-variant-numeric: tabular-nums;
|
||
position: relative; z-index: 2;
|
||
}
|
||
.loader-bar {
|
||
position: absolute; bottom: 0; left: 0;
|
||
height: 6px; width: 0; background: #000;
|
||
}
|
||
/* ink block that wipes over the yellow */
|
||
.loader-wipe {
|
||
position: absolute; inset: 0; background: var(--bg);
|
||
transform: scaleX(0); transform-origin: left;
|
||
z-index: 3;
|
||
}
|
||
.loader.done { display: none; }
|
||
|
||
/* ─── FIXED HEADER ─── */
|
||
header {
|
||
position: fixed; top: 0; left: 0; right: 0; z-index: 700;
|
||
padding: clamp(14px,2.2vw,24px) clamp(18px,4vw,52px);
|
||
display: flex; align-items: center; justify-content: space-between;
|
||
border-bottom: 3px solid #000;
|
||
background: rgba(8,8,10,.9);
|
||
backdrop-filter: blur(6px);
|
||
box-shadow: 0 3px 0 #000;
|
||
}
|
||
.h-logo {
|
||
font-family: var(--serif); font-size: clamp(16px,1.4vw,20px);
|
||
display: flex; align-items: center; gap: 9px; letter-spacing: .02em;
|
||
}
|
||
.h-logo-dot {
|
||
width: 10px; height: 10px; background: var(--green);
|
||
border: 2px solid #000; border-radius: 50%;
|
||
animation: blinkDot 1.6s steps(1) infinite;
|
||
}
|
||
@keyframes blinkDot { 50% { opacity: .1; } }
|
||
nav { display: flex; gap: 4px; }
|
||
nav a {
|
||
font-family: var(--pixel); font-size: clamp(7px,.58vw,9px);
|
||
text-transform: uppercase; letter-spacing: .05em;
|
||
padding: 9px 13px; border: 2px solid transparent;
|
||
color: rgba(255,255,255,.45);
|
||
transition: color .15s, border-color .15s, background .15s, transform .12s;
|
||
}
|
||
nav a:hover {
|
||
color: #000; background: var(--yellow); border-color: #000;
|
||
transform: translate(-2px,-2px); box-shadow: 3px 3px 0 #000;
|
||
}
|
||
.h-status {
|
||
display: flex; align-items: center; gap: 7px;
|
||
font-family: var(--pixel); font-size: clamp(6px,.52vw,8px);
|
||
text-transform: uppercase; letter-spacing: .07em; color: var(--yellow);
|
||
}
|
||
.h-status-dot {
|
||
width: 8px; height: 8px; border-radius: 50%; background: var(--green);
|
||
box-shadow: 0 0 0 0 rgba(0,255,133,.4);
|
||
animation: statusPulse 2.2s ease infinite;
|
||
}
|
||
@keyframes statusPulse {
|
||
0% { box-shadow: 0 0 0 0 rgba(0,255,133,.4); }
|
||
55% { box-shadow: 0 0 0 7px rgba(0,255,133,0); }
|
||
100% { box-shadow: 0 0 0 0 rgba(0,255,133,0); }
|
||
}
|
||
@media (max-width: 700px) { nav { display: none; } }
|
||
</style>
|
||
<style>
|
||
/* ─── HERO ─── */
|
||
.hero {
|
||
position: relative; min-height: 100svh;
|
||
display: flex; flex-direction: column; justify-content: flex-end;
|
||
padding: 0 clamp(18px,4vw,52px) clamp(44px,7vh,80px);
|
||
overflow: hidden; z-index: 2;
|
||
}
|
||
|
||
/* scan-line flicker overlay */
|
||
.hero::after {
|
||
content: ''; position: absolute; inset: 0; z-index: 0; pointer-events: none;
|
||
background: repeating-linear-gradient(0deg, transparent, transparent 3px, rgba(0,0,0,.07) 3px, rgba(0,0,0,.07) 4px);
|
||
animation: scanFlicker 8s linear infinite;
|
||
}
|
||
@keyframes scanFlicker {
|
||
0%,100% { opacity: 1; } 92% { opacity: 1; } 93% { opacity: .6; } 94% { opacity: 1; }
|
||
}
|
||
|
||
/* big decorative rings */
|
||
.hero-orb {
|
||
position: absolute; top: 50%; right: 2vw;
|
||
transform: translateY(-52%);
|
||
width: clamp(340px, 52vw, 760px);
|
||
height: clamp(340px, 52vw, 760px);
|
||
pointer-events: none; z-index: 0;
|
||
}
|
||
.h-ring {
|
||
position: absolute; inset: 0; border-radius: 50%;
|
||
transition: transform 1.8s cubic-bezier(.16,1,.3,1), opacity 1.8s ease;
|
||
}
|
||
.h-ring-1 { border: 2px dashed rgba(255,255,255,.18); animation: spinR 38s linear infinite; }
|
||
.h-ring-2 { inset: 9%; border: 2px solid rgba(255,46,166,.5); animation: spinR 24s linear infinite reverse; }
|
||
.h-ring-3 { inset: 18%; border: 2px dashed rgba(0,244,255,.45); animation: spinR 52s linear infinite; }
|
||
.h-ring-core {
|
||
position: absolute; inset: 35%; border-radius: 50%;
|
||
background: radial-gradient(circle at 40% 40%, rgba(247,255,0,.25), transparent 70%);
|
||
animation: corePulse 3.2s ease-in-out infinite;
|
||
}
|
||
@keyframes spinR { to { transform: rotate(360deg); } }
|
||
@keyframes corePulse { 0%,100% { transform: scale(.9); opacity: .5; } 50% { transform: scale(1.1); opacity: 1; } }
|
||
@media (max-width: 800px) { .hero-orb { display: none; } }
|
||
|
||
/* chips row */
|
||
.hero-chips {
|
||
position: relative; z-index: 3;
|
||
display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 26px;
|
||
}
|
||
.chip {
|
||
font-family: var(--pixel); font-size: clamp(6px,.55vw,8px);
|
||
text-transform: uppercase; border: 2px solid #000;
|
||
padding: 8px 12px; box-shadow: 3px 3px 0 #000; color: #000;
|
||
}
|
||
.chip-y { background: var(--yellow); }
|
||
.chip-p { background: var(--pink); }
|
||
.chip-c { background: var(--cyan); }
|
||
|
||
/* label above title */
|
||
.hero-label {
|
||
position: absolute; top: clamp(80px,11vh,120px); left: clamp(18px,4vw,52px);
|
||
font-family: var(--pixel); font-size: clamp(7px,.58vw,9px);
|
||
letter-spacing: .14em; text-transform: uppercase; color: var(--muted);
|
||
display: flex; align-items: center; gap: 10px; z-index: 3;
|
||
opacity: 0; transform: translateY(14px);
|
||
transition: opacity .8s ease .2s, transform .8s ease .2s;
|
||
}
|
||
.hero-label.in { opacity: 1; transform: none; }
|
||
.hero-label::before { content: ''; width: 24px; height: 2px; background: var(--yellow); }
|
||
|
||
/* THE NAME */
|
||
.hero-name {
|
||
position: relative; z-index: 3;
|
||
font-family: var(--serif); font-weight: 900;
|
||
font-size: clamp(70px,17vw,240px);
|
||
line-height: .86; letter-spacing: -.03em; text-transform: uppercase;
|
||
-webkit-text-stroke: 0;
|
||
}
|
||
.hero-name .word { display: block; overflow: hidden; }
|
||
.hero-name .word span {
|
||
display: block; transform: translateY(110%);
|
||
transition: transform 1.05s cubic-bezier(.16,1,.3,1);
|
||
will-change: transform;
|
||
}
|
||
.hero-name .word:nth-child(1) span { transition-delay: .05s; color: var(--yellow); -webkit-text-stroke: 3px #000; }
|
||
.hero-name .word:nth-child(2) span { transition-delay: .16s; color: transparent; -webkit-text-stroke: 2px #fff; }
|
||
.hero-name .word:nth-child(3) span { transition-delay: .27s; color: var(--pink); -webkit-text-stroke: 3px #000; }
|
||
html.js .hero-name.in .word span { transform: translateY(0); }
|
||
|
||
/* glitch pseudo */
|
||
.hero-name .word:nth-child(1) { position: relative; }
|
||
.hero-name .word:nth-child(1) span::before,
|
||
.hero-name .word:nth-child(1) span::after {
|
||
content: attr(data-text); position: absolute; left: 0; top: 0; pointer-events: none; display: block;
|
||
}
|
||
.hero-name .word:nth-child(1) span::before { color: var(--cyan); clip-path: polygon(0 30%,100% 30%,100% 50%,0 50%); animation: glA 5s steps(1) infinite 1.5s; }
|
||
.hero-name .word:nth-child(1) span::after { color: var(--red); clip-path: polygon(0 65%,100% 65%,100% 80%,0 80%); animation: glB 5s steps(1) infinite 1.5s; }
|
||
@keyframes glA {
|
||
0%,90%,100% { transform: none; opacity: 0; }
|
||
91% { transform: translateX(-4px); opacity: .9; }
|
||
92% { transform: translateX(4px); opacity: .9; }
|
||
93% { transform: none; opacity: 0; }
|
||
}
|
||
@keyframes glB {
|
||
0%,91%,100% { transform: none; opacity: 0; }
|
||
92% { transform: translateX(6px); opacity: .9; }
|
||
93% { transform: translateX(-2px); opacity: .9; }
|
||
94% { transform: none; opacity: 0; }
|
||
}
|
||
|
||
.hero-bottom {
|
||
position: relative; z-index: 3;
|
||
display: flex; align-items: flex-end; justify-content: space-between;
|
||
gap: 24px; margin-top: 36px; flex-wrap: wrap;
|
||
}
|
||
.hero-desc {
|
||
font-family: var(--mono); font-size: clamp(12px,1.1vw,15px);
|
||
color: var(--muted); max-width: 38ch; line-height: 1.8;
|
||
border-left: 4px solid var(--pink); padding-left: 16px;
|
||
opacity: 0; transform: translateY(22px);
|
||
transition: opacity .8s ease .5s, transform .8s ease .5s;
|
||
}
|
||
.hero-desc.in { opacity: 1; transform: none; }
|
||
.hero-desc b { color: #fff; }
|
||
.hero-cta {
|
||
display: flex; gap: 12px; align-items: center; flex-wrap: wrap;
|
||
opacity: 0; transform: translateY(22px);
|
||
transition: opacity .8s ease .65s, transform .8s ease .65s;
|
||
}
|
||
.hero-cta.in { opacity: 1; transform: none; }
|
||
|
||
/* buttons */
|
||
.btn {
|
||
font-family: var(--pixel); font-size: clamp(8px,.7vw,10px);
|
||
text-transform: uppercase; letter-spacing: .05em;
|
||
padding: 14px 22px; border: 3px solid #000;
|
||
box-shadow: 5px 5px 0 #000; cursor: pointer;
|
||
transition: transform .12s, box-shadow .12s;
|
||
display: inline-flex; align-items: center; gap: 8px;
|
||
}
|
||
.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); color: #000; }
|
||
.btn-ghost { background: transparent; color: #fff; border-color: rgba(255,255,255,.35); }
|
||
.btn-ghost:hover { background: #fff; color: #000; border-color: #000; box-shadow: 8px 8px 0 var(--pink); }
|
||
|
||
.hero-scroll {
|
||
position: absolute; bottom: clamp(22px,3.5vh,44px); left: 50%; transform: translateX(-50%);
|
||
display: flex; flex-direction: column; align-items: center; gap: 8px;
|
||
font-family: var(--pixel); font-size: 7px; letter-spacing: .14em; text-transform: uppercase;
|
||
color: var(--muted); z-index: 3; opacity: 0;
|
||
transition: opacity .8s ease 1s;
|
||
}
|
||
.hero-scroll.in { opacity: 1; }
|
||
.scroll-line {
|
||
width: 2px; height: 40px; background: linear-gradient(var(--pink), transparent);
|
||
transform-origin: top; animation: dropLine 2.2s cubic-bezier(.16,1,.3,1) infinite 1.4s;
|
||
}
|
||
@keyframes dropLine {
|
||
0% { transform: scaleY(0); opacity: 1; transform-origin: top; }
|
||
45% { transform: scaleY(1); opacity: 1; transform-origin: top; }
|
||
46% { transform-origin: bottom; }
|
||
100% { transform: scaleY(0); opacity: 0; transform-origin: bottom; }
|
||
}
|
||
</style>
|
||
<style>
|
||
/* ─── STATEMENT MARQUEE ─── */
|
||
.statement {
|
||
overflow: hidden; border-top: 4px solid #000; border-bottom: 4px solid #000;
|
||
position: relative; z-index: 2;
|
||
}
|
||
.mq-row { overflow: hidden; }
|
||
.mq-row + .mq-row { border-top: 3px solid #000; }
|
||
.mq-row-1 { background: var(--yellow); }
|
||
.mq-row-2 { background: var(--pink); }
|
||
.marquee-track {
|
||
display: flex; white-space: nowrap; align-items: center;
|
||
animation: mqFwd 20s linear infinite;
|
||
}
|
||
.marquee-track.rev { animation: mqRev 28s linear infinite; }
|
||
.marquee-item {
|
||
font-family: var(--serif); font-size: clamp(22px,4.5vw,60px);
|
||
font-weight: 900; text-transform: uppercase; letter-spacing: -.01em;
|
||
padding: clamp(12px,2vw,22px) clamp(20px,2.5vw,40px);
|
||
white-space: nowrap; color: #000;
|
||
}
|
||
.mq-star { font-size: clamp(16px,2.5vw,32px); color: #000; padding: 0 clamp(10px,1.5vw,22px); flex-shrink: 0; }
|
||
@keyframes mqFwd { to { transform: translateX(-50%); } }
|
||
@keyframes mqRev { 0% { transform: translateX(-50%); } 100% { transform: translateX(0); } }
|
||
|
||
/* ─── ABOUT ─── */
|
||
.about {
|
||
padding: clamp(70px,10vw,130px) clamp(18px,4vw,52px);
|
||
display: grid; grid-template-columns: 1fr 1fr;
|
||
gap: clamp(28px,4.5vw,70px); align-items: start;
|
||
border-bottom: 4px solid #000; position: relative; z-index: 2;
|
||
}
|
||
.about-eyebrow {
|
||
font-family: var(--pixel); font-size: clamp(7px,.58vw,9px);
|
||
letter-spacing: .12em; text-transform: uppercase; color: var(--yellow);
|
||
margin-bottom: 20px; display: flex; align-items: center; gap: 10px;
|
||
}
|
||
.about-eyebrow::before { content: '01 //'; opacity: .5; color: var(--muted); }
|
||
.about-heading {
|
||
font-family: var(--serif); font-size: clamp(44px,8vw,110px);
|
||
font-weight: 900; line-height: .88; letter-spacing: -.03em; text-transform: uppercase;
|
||
overflow: hidden;
|
||
}
|
||
.about-heading .line { overflow: hidden; }
|
||
.about-heading .line span {
|
||
display: block; transform: translateY(105%);
|
||
transition: transform 1.05s cubic-bezier(.16,1,.3,1);
|
||
}
|
||
.about-heading .line:nth-child(1) span { color: var(--yellow); -webkit-text-stroke: 2px #000; }
|
||
.about-heading .line:nth-child(2) span { color: transparent; -webkit-text-stroke: 2px #fff; transition-delay: .1s; }
|
||
.about-heading .line:nth-child(3) span { transition-delay: .2s; }
|
||
.about-heading.in .line span { transform: translateY(0); }
|
||
.about-number {
|
||
font-family: var(--serif); font-size: clamp(100px,18vw,200px);
|
||
font-weight: 900; color: transparent; -webkit-text-stroke: 1.5px rgba(255,255,255,.07);
|
||
line-height: .85; user-select: none; pointer-events: none; margin-top: -0.15em;
|
||
}
|
||
|
||
.about-right { padding-top: clamp(32px,5vw,64px); }
|
||
.about-photo-wrap { position: relative; margin-bottom: 28px; }
|
||
.about-photo {
|
||
width: 100%; aspect-ratio: 3/4; object-fit: cover; object-position: center top;
|
||
border: 5px solid #000; box-shadow: 12px 12px 0 var(--pink);
|
||
transform: rotate(-2deg) scale(.96); opacity: 0;
|
||
filter: grayscale(.1) contrast(1.1);
|
||
transition: transform 1.3s cubic-bezier(.16,1,.3,1), opacity 1.3s ease;
|
||
}
|
||
.about-photo.in { transform: rotate(-2deg) scale(1); opacity: 1; }
|
||
.about-photo:hover { transform: rotate(0) scale(1.02) !important; }
|
||
.about-photo-cap {
|
||
position: absolute; bottom: -6px; right: -6px;
|
||
font-family: var(--pixel); font-size: 7px; letter-spacing: .08em; text-transform: uppercase;
|
||
background: var(--yellow); color: #000; padding: 8px 12px;
|
||
border: 3px solid #000; box-shadow: 4px 4px 0 #000;
|
||
transform: rotate(2deg);
|
||
}
|
||
.about-body {
|
||
font-size: clamp(13px,1.1vw,15px); color: var(--muted); line-height: 1.9; max-width: 44ch;
|
||
opacity: 0; transform: translateY(24px);
|
||
transition: opacity .9s ease .2s, transform .9s ease .2s;
|
||
}
|
||
.about-body.in { opacity: 1; transform: none; }
|
||
.about-body b { color: #fff; font-weight: 700; }
|
||
.about-tags {
|
||
display: flex; flex-wrap: wrap; gap: 8px; margin-top: 22px;
|
||
opacity: 0; transition: opacity .8s ease .4s;
|
||
}
|
||
.about-tags.in { opacity: 1; }
|
||
.atag {
|
||
font-family: var(--pixel); font-size: 7px; letter-spacing: .06em; text-transform: uppercase;
|
||
border: 2px solid #000; padding: 8px 12px; box-shadow: 3px 3px 0 #000; color: #000;
|
||
}
|
||
.atag:nth-child(5n+1) { background: var(--yellow); }
|
||
.atag:nth-child(5n+2) { background: var(--pink); }
|
||
.atag:nth-child(5n+3) { background: var(--cyan); }
|
||
.atag:nth-child(5n+4) { background: var(--green); }
|
||
.atag:nth-child(5n) { background: var(--orange); }
|
||
@media (max-width: 768px) { .about { grid-template-columns: 1fr; } .about-number { font-size: 90px; } }
|
||
|
||
/* ─── STATS ─── */
|
||
.stats {
|
||
display: grid; grid-template-columns: repeat(4,1fr);
|
||
border-top: 4px solid #000;
|
||
position: relative; z-index: 2;
|
||
}
|
||
.stat {
|
||
padding: clamp(24px,4vw,48px) clamp(16px,2.5vw,32px);
|
||
border-right: 4px solid #000; position: relative; overflow: hidden;
|
||
transition: transform .15s, box-shadow .15s;
|
||
}
|
||
.stat:last-child { border-right: none; }
|
||
.stat:nth-child(1) { background: var(--pink); }
|
||
.stat:nth-child(2) { background: var(--yellow); }
|
||
.stat:nth-child(3) { background: var(--cyan); }
|
||
.stat:nth-child(4) { background: var(--orange); }
|
||
.stat-n {
|
||
font-family: var(--serif); font-size: clamp(40px,6.5vw,80px);
|
||
font-weight: 900; line-height: 1; display: block; color: #000; letter-spacing: -.04em;
|
||
}
|
||
.stat-l {
|
||
font-family: var(--pixel); font-size: clamp(6px,.55vw,8px);
|
||
letter-spacing: .08em; text-transform: uppercase;
|
||
color: #000; margin-top: 10px; display: block; opacity: .7;
|
||
}
|
||
.stat::after {
|
||
content: '★'; position: absolute; top: -10px; right: -10px;
|
||
width: 30px; height: 30px; background: #fff; border: 2px solid #000; border-radius: 50%;
|
||
display: flex; align-items: center; justify-content: center;
|
||
font-size: 13px; box-shadow: 2px 2px 0 #000; color: #000;
|
||
display: grid; place-items: center;
|
||
}
|
||
@media (max-width: 640px) { .stats { grid-template-columns: repeat(2,1fr); } .stat:nth-child(2) { border-right: 4px solid #000; } .stat:nth-child(even) { border-right: none; } }
|
||
</style>
|
||
<style>
|
||
/* ─── WORK / PROJECT ROWS ─── */
|
||
.work-header {
|
||
padding: clamp(14px,2vw,24px) clamp(18px,4vw,52px);
|
||
display: flex; align-items: center; justify-content: space-between;
|
||
border-top: 4px solid #000; border-bottom: 4px solid #000;
|
||
background: var(--bg2); position: relative; z-index: 2;
|
||
box-shadow: 0 4px 0 #000;
|
||
}
|
||
.work-header h2 {
|
||
font-family: var(--pixel); font-size: clamp(8px,.7vw,11px);
|
||
letter-spacing: .1em; text-transform: uppercase; color: #fff;
|
||
}
|
||
.work-count { font-family: var(--pixel); font-size: 8px; color: var(--yellow); letter-spacing: .06em; }
|
||
|
||
.proj-row {
|
||
display: grid; grid-template-columns: 70px 1fr auto auto;
|
||
align-items: center; gap: clamp(14px,2vw,36px);
|
||
padding: clamp(18px,2.8vw,36px) clamp(18px,4vw,52px);
|
||
border-bottom: 3px solid #000; position: relative; overflow: hidden;
|
||
cursor: pointer; background: var(--bg);
|
||
transition: padding-left .25s;
|
||
}
|
||
.proj-row::before {
|
||
content: ''; position: absolute; inset: 0;
|
||
background: var(--yellow); transform: scaleY(0); transform-origin: bottom;
|
||
transition: transform .5s cubic-bezier(.16,1,.3,1); z-index: 0;
|
||
}
|
||
.proj-row:nth-child(even)::before { background: var(--pink); }
|
||
.proj-row:nth-child(3n)::before { background: var(--cyan); }
|
||
.proj-row:hover { padding-left: calc(clamp(18px,4vw,52px) + 14px); }
|
||
.proj-row:hover::before { transform: scaleY(1); }
|
||
.proj-row:hover .pr-num,
|
||
.proj-row:hover .pr-name,
|
||
.proj-row:hover .pr-tags span,
|
||
.proj-row:hover .pr-year,
|
||
.proj-row:hover .pr-arrow { color: #000; }
|
||
.proj-row:hover .pr-tags span { border-color: rgba(0,0,0,.25); }
|
||
.proj-row > * { position: relative; z-index: 1; }
|
||
.pr-num {
|
||
font-family: var(--pixel); font-size: clamp(7px,.58vw,9px);
|
||
color: var(--muted); letter-spacing: .06em; transition: color .25s;
|
||
}
|
||
.pr-name {
|
||
font-family: var(--serif); font-size: clamp(22px,4.5vw,60px);
|
||
font-weight: 900; line-height: 1; letter-spacing: -.02em; text-transform: uppercase;
|
||
transition: color .25s;
|
||
}
|
||
.pr-right { display: flex; flex-direction: column; align-items: flex-end; gap: 5px; }
|
||
.pr-tags { display: flex; gap: 6px; flex-wrap: wrap; justify-content: flex-end; }
|
||
.pr-tags span {
|
||
font-family: var(--pixel); font-size: 6px; letter-spacing: .05em; text-transform: uppercase;
|
||
color: var(--muted); border: 1px solid var(--dim); padding: 5px 8px;
|
||
transition: color .25s, border-color .25s;
|
||
}
|
||
.pr-year {
|
||
font-family: var(--pixel); font-size: clamp(6px,.52vw,8px);
|
||
color: var(--muted); transition: color .25s;
|
||
}
|
||
.pr-arrow { font-size: 20px; color: var(--yellow); transition: color .25s, transform .25s; }
|
||
.proj-row:hover .pr-arrow { transform: translate(4px,-4px); color: #000; }
|
||
@media (max-width: 640px) { .proj-row { grid-template-columns: 44px 1fr; } .pr-right { display: none; } }
|
||
|
||
/* ─── SKILLS ─── */
|
||
.skills {
|
||
padding: clamp(70px,10vw,130px) clamp(18px,4vw,52px);
|
||
display: grid; grid-template-columns: 280px 1fr; gap: clamp(28px,4.5vw,70px);
|
||
align-items: start; border-top: 4px solid #000; position: relative; z-index: 2;
|
||
}
|
||
.skills-eyebrow {
|
||
font-family: var(--pixel); font-size: clamp(7px,.58vw,9px);
|
||
letter-spacing: .12em; text-transform: uppercase; color: var(--yellow);
|
||
margin-bottom: 20px; display: flex; align-items: center; gap: 10px;
|
||
}
|
||
.skills-eyebrow::before { content: '02 //'; opacity: .5; color: var(--muted); }
|
||
.skills-heading {
|
||
font-family: var(--serif); font-size: clamp(36px,5.5vw,72px);
|
||
font-weight: 900; line-height: .88; letter-spacing: -.03em; text-transform: uppercase;
|
||
overflow: hidden;
|
||
}
|
||
.skills-heading .line { overflow: hidden; }
|
||
.skills-heading .line span {
|
||
display: block; transform: translateY(105%);
|
||
transition: transform 1.05s cubic-bezier(.16,1,.3,1);
|
||
}
|
||
.skills-heading .line:nth-child(1) span { color: var(--yellow); }
|
||
.skills-heading .line:nth-child(2) span { transition-delay: .1s; color: transparent; -webkit-text-stroke: 2px #fff; }
|
||
.skills-heading.in .line span { transform: translateY(0); }
|
||
.skills-note { font-size: 12px; color: var(--muted); line-height: 1.75; margin-top: 20px; }
|
||
|
||
.skill-group { margin-bottom: 32px; }
|
||
.skill-group-label {
|
||
font-family: var(--pixel); font-size: 8px; letter-spacing: .1em; text-transform: uppercase;
|
||
color: var(--yellow); margin-bottom: 14px; padding-bottom: 10px;
|
||
border-bottom: 2px solid var(--dim);
|
||
display: flex; align-items: center; gap: 8px;
|
||
}
|
||
.skill-list { display: flex; flex-wrap: wrap; gap: 8px; }
|
||
.skill-item {
|
||
font-family: var(--mono); font-weight: 700; font-size: 12px; text-transform: uppercase;
|
||
padding: 10px 14px; border: 3px solid #000; background: #fff; color: #000;
|
||
box-shadow: 4px 4px 0 #000; display: flex; align-items: center; gap: 8px;
|
||
transition: transform .12s, box-shadow .12s, background .12s;
|
||
}
|
||
.skill-item:nth-child(5n) { transform: rotate(-1.5deg); }
|
||
.skill-item:nth-child(5n+2) { transform: rotate(1.2deg); }
|
||
.skill-item:nth-child(5n+4) { transform: rotate(-.8deg); }
|
||
.skill-item:hover { transform: translate(-2px,-3px) rotate(0) !important; box-shadow: 8px 8px 0 var(--pink); }
|
||
.skill-item img { width: 16px; height: 16px; }
|
||
.skill-item.dim {
|
||
background: var(--bg3); color: #fff; border-style: dashed; box-shadow: none; opacity: .65;
|
||
transform: none !important;
|
||
}
|
||
.skill-item.dim:hover { background: var(--orange); color: #000; border-style: solid; box-shadow: 8px 8px 0 #000; opacity: 1; }
|
||
@media (max-width: 768px) { .skills { grid-template-columns: 1fr; } }
|
||
</style>
|
||
<style>
|
||
/* ─── DEVLOG HORIZONTAL SCROLL ─── */
|
||
.h-scroll-outer {
|
||
overflow: hidden; border-top: 4px solid #000;
|
||
padding: clamp(48px,7vw,88px) 0;
|
||
background: var(--bg2); position: relative; z-index: 2;
|
||
}
|
||
.h-scroll-inner {
|
||
display: flex; gap: clamp(24px,3vw,40px);
|
||
will-change: transform;
|
||
padding: 0 clamp(18px,4vw,52px);
|
||
}
|
||
.h-card {
|
||
flex: none; width: clamp(260px,28vw,360px);
|
||
border: 4px solid #000; padding: 28px;
|
||
background: var(--bg); box-shadow: 8px 8px 0 #000;
|
||
transition: transform .2s, box-shadow .2s;
|
||
position: relative;
|
||
}
|
||
.h-card:nth-child(odd) { transform: rotate(-1.2deg); }
|
||
.h-card:nth-child(even) { transform: rotate(.9deg) translateY(8px); }
|
||
.h-card:hover { transform: rotate(0) translate(-3px,-3px) !important; box-shadow: 12px 12px 0 var(--pink); }
|
||
/* tape strip */
|
||
.h-card::before {
|
||
content: ''; position: absolute; top: -8px; right: 22px;
|
||
width: 54px; height: 18px; background: var(--yellow); opacity: .85;
|
||
transform: rotate(2deg); box-shadow: 0 0 0 2px #000;
|
||
}
|
||
.h-card-num {
|
||
font-family: var(--pixel); font-size: 8px; color: var(--muted); letter-spacing: .08em; margin-bottom: 16px;
|
||
}
|
||
.h-card-title {
|
||
font-family: var(--serif); font-size: clamp(17px,2vw,24px);
|
||
font-weight: 900; color: #fff; line-height: 1.1; margin-bottom: 12px;
|
||
letter-spacing: -.01em; text-transform: uppercase;
|
||
}
|
||
.h-card-body { font-size: 12px; color: var(--muted); line-height: 1.8; }
|
||
.h-card-tag {
|
||
display: inline-flex; align-items: center; gap: 6px; margin-top: 18px;
|
||
font-family: var(--pixel); font-size: 7px; letter-spacing: .07em; text-transform: uppercase;
|
||
color: var(--yellow); border-bottom: 2px solid var(--yellow); padding-bottom: 2px;
|
||
transition: color .2s, border-color .2s;
|
||
}
|
||
.h-card:hover .h-card-tag { color: var(--pink); border-color: var(--pink); }
|
||
|
||
/* ─── CONTACT ─── */
|
||
.contact {
|
||
padding: clamp(70px,10vw,130px) clamp(18px,4vw,52px) clamp(44px,6vw,80px);
|
||
border-top: 4px solid #000;
|
||
display: grid; grid-template-columns: 1fr 1fr; gap: clamp(36px,5vw,90px);
|
||
position: relative; z-index: 2;
|
||
}
|
||
.contact-eyebrow {
|
||
font-family: var(--pixel); font-size: clamp(7px,.58vw,9px);
|
||
letter-spacing: .12em; text-transform: uppercase; color: var(--yellow);
|
||
margin-bottom: 20px; display: flex; align-items: center; gap: 10px;
|
||
}
|
||
.contact-eyebrow::before { content: '03 //'; opacity: .5; color: var(--muted); }
|
||
.contact-heading {
|
||
font-family: var(--serif); font-size: clamp(50px,10vw,130px);
|
||
font-weight: 900; line-height: .86; letter-spacing: -.04em; text-transform: uppercase;
|
||
overflow: hidden;
|
||
}
|
||
.contact-heading .line { overflow: hidden; }
|
||
.contact-heading .line span {
|
||
display: block; transform: translateY(105%);
|
||
transition: transform 1.05s cubic-bezier(.16,1,.3,1);
|
||
}
|
||
.contact-heading .line:nth-child(1) span { color: var(--yellow); -webkit-text-stroke: 2px #000; }
|
||
.contact-heading .line:nth-child(2) span { transition-delay: .12s; color: transparent; -webkit-text-stroke: 2px #fff; }
|
||
.contact-heading.in .line span { transform: translateY(0); }
|
||
|
||
.contact-right { padding-top: clamp(20px,3vw,48px); }
|
||
.contact-link {
|
||
display: flex; align-items: center; justify-content: space-between;
|
||
padding: clamp(14px,1.8vw,24px) clamp(12px,1.5vw,20px);
|
||
border: 3px solid #000; border-bottom: none; background: var(--bg2);
|
||
box-shadow: 4px 4px 0 #000; margin-bottom: 0;
|
||
transition: background .18s, padding-left .22s;
|
||
position: relative;
|
||
}
|
||
.contact-link:first-child { border-top: 3px solid #000; }
|
||
.contact-link:last-child { border-bottom: 3px solid #000; margin-bottom: 0; }
|
||
.contact-link:hover { background: var(--pink); padding-left: calc(clamp(12px,1.5vw,20px) + 14px); }
|
||
.contact-link:hover .cl-label,
|
||
.contact-link:hover .cl-val,
|
||
.contact-link:hover .cl-arrow { color: #000; }
|
||
.cl-label { font-family: var(--pixel); font-size: 7px; letter-spacing: .1em; text-transform: uppercase; color: var(--yellow); transition: color .18s; }
|
||
.cl-val { font-family: var(--serif); font-size: clamp(14px,1.8vw,20px); font-weight: 700; color: #fff; transition: color .18s; }
|
||
.cl-arrow { font-size: 18px; color: var(--pink); transition: color .18s, transform .2s; }
|
||
.contact-link:hover .cl-arrow { transform: translate(4px,-4px); }
|
||
@media (max-width: 768px) { .contact { grid-template-columns: 1fr; } }
|
||
|
||
/* ─── FOOTER ─── */
|
||
.footer-bottom {
|
||
padding: clamp(20px,2.5vw,36px) clamp(18px,4vw,52px);
|
||
border-top: 4px solid #000;
|
||
display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap;
|
||
background: #000; position: relative; z-index: 2;
|
||
}
|
||
.footer-word {
|
||
font-family: var(--serif); font-size: clamp(60px,16vw,220px);
|
||
font-weight: 900; text-transform: uppercase; color: transparent;
|
||
-webkit-text-stroke: 2px rgba(255,255,255,.09);
|
||
user-select: none; pointer-events: none;
|
||
text-align: center; display: block;
|
||
border-top: 4px solid #000; padding: clamp(20px,3vw,48px) 0 0;
|
||
position: relative; z-index: 2;
|
||
}
|
||
.footer-copy { font-family: var(--pixel); font-size: 8px; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
|
||
.footer-links { display: flex; gap: 16px; flex-wrap: wrap; }
|
||
.footer-links a { font-family: var(--pixel); font-size: 8px; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); transition: color .2s; }
|
||
.footer-links a:hover { color: var(--yellow); }
|
||
|
||
/* ─── REVEAL HELPERS ─── */
|
||
.reveal-up { opacity: 0; transform: translateY(36px); transition: opacity .9s ease, transform .9s cubic-bezier(.16,1,.3,1); }
|
||
.reveal-up.in { opacity: 1; transform: none; }
|
||
.reveal-delay-1 { transition-delay: .12s; }
|
||
.reveal-delay-2 { transition-delay: .24s; }
|
||
|
||
/* ─── REDUCED MOTION ─── */
|
||
@media (prefers-reduced-motion: reduce) {
|
||
*, *::before, *::after { animation-duration: .001s !important; transition-duration: .001s !important; }
|
||
.hero-name .word span,
|
||
.about-heading .line span,
|
||
.skills-heading .line span,
|
||
.contact-heading .line span { transform: none !important; }
|
||
.loader { display: none; }
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
|
||
<!-- fixed layers -->
|
||
<div class="bg-grid" aria-hidden="true"></div>
|
||
<div class="noise" aria-hidden="true"></div>
|
||
<div class="vignette" aria-hidden="true"></div>
|
||
|
||
<!-- cursor -->
|
||
<div class="c-dot" id="cDot" aria-hidden="true"></div>
|
||
<div class="c-ring" id="cRing" aria-hidden="true"></div>
|
||
|
||
<!-- loader -->
|
||
<div class="loader" id="loader" aria-hidden="true">
|
||
<div class="loader-count" id="loaderCount">0</div>
|
||
<div class="loader-bar" id="loaderBar"></div>
|
||
<div class="loader-wipe" id="loaderWipe"></div>
|
||
</div>
|
||
|
||
<!-- header -->
|
||
<header>
|
||
<a class="h-logo" href="#hero">
|
||
<span class="h-logo-dot"></span>MILES
|
||
</a>
|
||
<nav>
|
||
<a href="#about">About</a>
|
||
<a href="#work">Builds</a>
|
||
<a href="#skills">Skills</a>
|
||
<a href="#contact">Contact</a>
|
||
</nav>
|
||
<div class="h-status">
|
||
<span class="h-status-dot"></span>USUALLY ONLINE
|
||
</div>
|
||
</header>
|
||
|
||
<!-- ══════════════ HERO ══════════════ -->
|
||
<section class="hero" id="hero">
|
||
<div class="hero-orb" aria-hidden="true">
|
||
<div class="h-ring h-ring-1"></div>
|
||
<div class="h-ring h-ring-2"></div>
|
||
<div class="h-ring h-ring-3"></div>
|
||
<div class="h-ring-core"></div>
|
||
</div>
|
||
|
||
<div class="hero-label" id="heroLabel">Developer & 3D Artist — Est. 2008</div>
|
||
|
||
<div class="hero-chips">
|
||
<span class="chip chip-y">★ MILES WOLF ALLEN</span>
|
||
<span class="chip chip-p">DEVELOPER & 3D ARTIST</span>
|
||
<span class="chip chip-c">DISKETTE LABS</span>
|
||
</div>
|
||
|
||
<h1 class="hero-name" id="heroName" aria-label="Miles Wolf Allen">
|
||
<span class="word"><span data-text="MILES">MILES</span></span>
|
||
<span class="word"><span data-text="WOLF">WOLF</span></span>
|
||
<span class="word"><span data-text="ALLEN">ALLEN</span></span>
|
||
</h1>
|
||
|
||
<div class="hero-bottom">
|
||
<p class="hero-desc" id="heroDesc">
|
||
I make <b>games</b>, <b>tools</b>, and <b>websites</b> — with craft
|
||
and a little chaos. Co-founder of <b>Diskette Labs</b>.
|
||
160 repos and counting. Send help.
|
||
</p>
|
||
<div class="hero-cta" id="heroCta">
|
||
<a class="btn btn-pink" href="#work">SEE THE BUILDS ↓</a>
|
||
<a class="btn btn-ghost" href="https://github.com/mileswolfallen2" target="_blank" rel="noopener">GITHUB ↗</a>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="hero-scroll" id="heroScroll" aria-hidden="true">
|
||
<span class="scroll-line"></span>
|
||
SCROLL
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ══════════════ MARQUEE ══════════════ -->
|
||
<div class="statement" aria-hidden="true">
|
||
<div class="mq-row mq-row-1">
|
||
<div class="marquee-track" id="mq1"></div>
|
||
</div>
|
||
<div class="mq-row mq-row-2">
|
||
<div class="marquee-track rev" id="mq2"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ══════════════ ABOUT ══════════════ -->
|
||
<section class="about" id="about">
|
||
<div class="about-left">
|
||
<div class="about-number" aria-hidden="true">01</div>
|
||
<div class="about-eyebrow reveal-up">About</div>
|
||
<h2 class="about-heading" id="aboutHeading">
|
||
<span class="line"><span>BUILD.</span></span>
|
||
<span class="line"><span>BREAK.</span></span>
|
||
<span class="line"><span>REPEAT.</span></span>
|
||
</h2>
|
||
</div>
|
||
<div class="about-right">
|
||
<div class="about-photo-wrap">
|
||
<img class="about-photo" id="aboutPhoto"
|
||
src="https://avatars.githubusercontent.com/u/115095719?v=4"
|
||
alt="Miles Wolf Allen" width="480" height="640" loading="lazy">
|
||
<span class="about-photo-cap">@mileswolfallen2</span>
|
||
</div>
|
||
<p class="about-body" id="aboutBody">
|
||
I'm <b>Miles Wolf Allen</b> — developer & 3D artist, still in school,
|
||
co-founder of <b>Diskette Labs</b>, and currently building
|
||
<b>Gelectron</b>: a drop-in Electron replacement using native web views
|
||
instead of bundling an entire Chromium. Pancakes > waffles.
|
||
Cereal is soup. Software should feel good to use.
|
||
</p>
|
||
<div class="about-tags" id="aboutTags">
|
||
<span class="atag">PULL SHARK ×2</span>
|
||
<span class="atag">YOLO</span>
|
||
<span class="atag">QUICKDRAW</span>
|
||
<span class="atag">GD ADDICT</span>
|
||
<span class="atag">MIT LICENSED</span>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ══════════════ STATS ══════════════ -->
|
||
<div class="stats" id="stats">
|
||
<div class="stat">
|
||
<span class="stat-n num" data-count="160">0</span>
|
||
<span class="stat-l">REPOS ONLINE</span>
|
||
</div>
|
||
<div class="stat">
|
||
<span class="stat-n num" data-count="91">0</span>
|
||
<span class="stat-l">STARS EARNED</span>
|
||
</div>
|
||
<div class="stat">
|
||
<span class="stat-n num" data-count="3839">0</span>
|
||
<span class="stat-l">FEDL VERIFIED RUNS</span>
|
||
</div>
|
||
<div class="stat">
|
||
<span class="stat-n num" data-count="1542">0</span>
|
||
<span class="stat-l">MOON GAMING COMMITS</span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ══════════════ WORK ══════════════ -->
|
||
<section id="work">
|
||
<div class="work-header reveal-up">
|
||
<h2>Selected Work</h2>
|
||
<span class="work-count">2022 — 2026 // 09 PROJECTS</span>
|
||
</div>
|
||
|
||
<a class="proj-row" href="../projects/omniemu.html">
|
||
<span class="pr-num">01</span>
|
||
<span class="pr-name">OmniEmu 2.0</span>
|
||
<div class="pr-right"><div class="pr-tags"><span>TypeScript</span><span>MIT</span><span>Active</span></div><span class="pr-year">2024–2026</span></div>
|
||
<span class="pr-arrow">↗</span>
|
||
</a>
|
||
<a class="proj-row" href="../projects/gelectron.html">
|
||
<span class="pr-num">02</span>
|
||
<span class="pr-name">Gelectron</span>
|
||
<div class="pr-right"><div class="pr-tags"><span>Rust</span><span>Node.js</span><span>Early</span></div><span class="pr-year">2025–2026</span></div>
|
||
<span class="pr-arrow">↗</span>
|
||
</a>
|
||
<a class="proj-row" href="../projects/fedl.html">
|
||
<span class="pr-num">03</span>
|
||
<span class="pr-name">FEDL</span>
|
||
<div class="pr-right"><div class="pr-tags"><span>Community</span><span>Live</span></div><span class="pr-year">2024–2026</span></div>
|
||
<span class="pr-arrow">↗</span>
|
||
</a>
|
||
<a class="proj-row" href="../projects/command-move.html">
|
||
<span class="pr-num">04</span>
|
||
<span class="pr-name">CommandMove</span>
|
||
<div class="pr-right"><div class="pr-tags"><span>Swift</span><span>macOS</span></div><span class="pr-year">2023</span></div>
|
||
<span class="pr-arrow">↗</span>
|
||
</a>
|
||
<a class="proj-row" href="../projects/noto.html">
|
||
<span class="pr-num">05</span>
|
||
<span class="pr-name">Noto</span>
|
||
<div class="pr-right"><div class="pr-tags"><span>Flutter</span><span>AI</span></div><span class="pr-year">2025–2026</span></div>
|
||
<span class="pr-arrow">↗</span>
|
||
</a>
|
||
<a class="proj-row" href="../projects/nova.html">
|
||
<span class="pr-num">06</span>
|
||
<span class="pr-name">Nova AI</span>
|
||
<div class="pr-right"><div class="pr-tags"><span>Python</span><span>Local AI</span></div><span class="pr-year">2024–2025</span></div>
|
||
<span class="pr-arrow">↗</span>
|
||
</a>
|
||
<a class="proj-row" href="../projects/music-app.html">
|
||
<span class="pr-num">07</span>
|
||
<span class="pr-name">Music App</span>
|
||
<div class="pr-right"><div class="pr-tags"><span>JavaScript</span><span>Web</span></div><span class="pr-year">2023–2024</span></div>
|
||
<span class="pr-arrow">↗</span>
|
||
</a>
|
||
<a class="proj-row" href="../projects/rhythm-game.html">
|
||
<span class="pr-num">08</span>
|
||
<span class="pr-name">Rhythm Game</span>
|
||
<div class="pr-right"><div class="pr-tags"><span>HTML</span><span>Game</span></div><span class="pr-year">2022–2023</span></div>
|
||
<span class="pr-arrow">↗</span>
|
||
</a>
|
||
<a class="proj-row" href="../projects/moon-gaming.html">
|
||
<span class="pr-num">09</span>
|
||
<span class="pr-name">Moon Gaming</span>
|
||
<div class="pr-right"><div class="pr-tags"><span>HTML</span><span>1542 commits</span></div><span class="pr-year">2022–2026</span></div>
|
||
<span class="pr-arrow">↗</span>
|
||
</a>
|
||
</section>
|
||
|
||
<!-- ══════════════ SKILLS ══════════════ -->
|
||
<section class="skills" id="skills">
|
||
<div class="skills-left">
|
||
<div class="skills-eyebrow reveal-up">Loadout</div>
|
||
<h2 class="skills-heading" id="skillsHeading">
|
||
<span class="line"><span>TOOLS</span></span>
|
||
<span class="line"><span>& TECH</span></span>
|
||
</h2>
|
||
<p class="skills-note reveal-up reveal-delay-1">
|
||
What I reach for daily — and what I'm currently beating my head against.
|
||
</p>
|
||
</div>
|
||
<div class="skills-right">
|
||
<div class="skill-group reveal-up">
|
||
<div class="skill-group-label">★ READY TO SHIP</div>
|
||
<div class="skill-list" id="pillsReady">
|
||
<span class="skill-item" data-si="javascript">JavaScript</span>
|
||
<span class="skill-item" data-si="nodedotjs">Node.js</span>
|
||
<span class="skill-item" data-si="html5">HTML</span>
|
||
<span class="skill-item" data-si="css3">CSS</span>
|
||
<span class="skill-item" data-si="python">Python</span>
|
||
<span class="skill-item" data-si="git">Git</span>
|
||
<span class="skill-item" data-si="blender">Blender</span>
|
||
<span class="skill-item" data-si="unity">Unity</span>
|
||
<span class="skill-item" data-si="unrealengine">Unreal</span>
|
||
<span class="skill-item" data-si="cloudflare">Cloudflare</span>
|
||
<span class="skill-item" data-si="linux">Linux</span>
|
||
<span class="skill-item" data-si="gnubash">Bash</span>
|
||
<span class="skill-item" data-si="electron">Electron</span>
|
||
<span class="skill-item" data-si="github">GitHub</span>
|
||
</div>
|
||
</div>
|
||
<div class="skill-group reveal-up reveal-delay-2">
|
||
<div class="skill-group-label">★ CURRENTLY UNLOCKING</div>
|
||
<div class="skill-list">
|
||
<span class="skill-item dim" data-si="rust">Rust</span>
|
||
<span class="skill-item dim" data-si="php">PHP</span>
|
||
<span class="skill-item dim" data-si="dotnet">.NET</span>
|
||
<span class="skill-item dim" data-si="nixos">Nix</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ══════════════ DEVLOG CARDS (horizontal scroll) ══════════════ -->
|
||
<div class="h-scroll-outer" id="devlog">
|
||
<div class="h-scroll-inner" id="hScrollInner">
|
||
<div class="h-card">
|
||
<div class="h-card-num">2026 // 001</div>
|
||
<div class="h-card-title">FOCUSING ON DISKETTE LABS</div>
|
||
<p class="h-card-body">Co-founder of a product design collective. Where my focus is now — still open to collabs.</p>
|
||
<a class="h-card-tag" href="../blog/diskette-devlog.html">READ ENTRY →</a>
|
||
</div>
|
||
<div class="h-card">
|
||
<div class="h-card-num">2026 // 002</div>
|
||
<div class="h-card-title">WHY I BUILT GELECTRON</div>
|
||
<p class="h-card-body">Electron bundles Chromium with every app. 150–300 MB per install. Native web views fix that.</p>
|
||
<a class="h-card-tag" href="../blog/gelectron-devlog.html">READ ENTRY →</a>
|
||
</div>
|
||
<div class="h-card">
|
||
<div class="h-card-num">2026 // 003</div>
|
||
<div class="h-card-title">WHY I BUILT OMNIEMU</div>
|
||
<p class="h-card-body">I got tired of opening 15 different emulator apps, so I built one that manages them all.</p>
|
||
<a class="h-card-tag" href="../blog/omniemu-devlog.html">READ ENTRY →</a>
|
||
</div>
|
||
<div class="h-card">
|
||
<div class="h-card-num">2026 // 004</div>
|
||
<div class="h-card-title">COMMANDMOVE: CUT & PASTE</div>
|
||
<p class="h-card-body">macOS doesn't have Cmd+X for files. Global event taps, AppleScript, and Accessibility perms.</p>
|
||
<a class="h-card-tag" href="../blog/command-move-devlog.html">READ ENTRY →</a>
|
||
</div>
|
||
<div class="h-card">
|
||
<div class="h-card-num">2025 // 005</div>
|
||
<div class="h-card-title">RUNNING THE FEDL</div>
|
||
<p class="h-card-body">3,800+ verified runs, ranked levels, and a GD community that never sleeps.</p>
|
||
<a class="h-card-tag" href="../blog/fedl-devlog.html">READ ENTRY →</a>
|
||
</div>
|
||
<div class="h-card">
|
||
<div class="h-card-num">2025 // 006</div>
|
||
<div class="h-card-title">BUILDING NOVA AI</div>
|
||
<p class="h-card-body">Local AI that doesn't phone home. Desktop GUI, web interface, CLI — no cloud, no subscriptions.</p>
|
||
<a class="h-card-tag" href="../blog/nova-devlog.html">READ ENTRY →</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ══════════════ CONTACT ══════════════ -->
|
||
<section class="contact" id="contact">
|
||
<div class="contact-left">
|
||
<div class="contact-eyebrow reveal-up">Contact</div>
|
||
<h2 class="contact-heading" id="contactHeading">
|
||
<span class="line"><span>LET'S</span></span>
|
||
<span class="line"><span>TALK.</span></span>
|
||
</h2>
|
||
</div>
|
||
<div class="contact-right">
|
||
<a class="contact-link" href="mailto:[email protected]">
|
||
<div><div class="cl-label">EMAIL</div><div class="cl-val">[email protected]</div></div>
|
||
<span class="cl-arrow">↗</span>
|
||
</a>
|
||
<a class="contact-link" href="https://github.com/mileswolfallen2" target="_blank" rel="noopener">
|
||
<div><div class="cl-label">GITHUB</div><div class="cl-val">mileswolfallen2</div></div>
|
||
<span class="cl-arrow">↗</span>
|
||
</a>
|
||
<a class="contact-link" href="https://diskettelabs.com/" target="_blank" rel="noopener">
|
||
<div><div class="cl-label">STUDIO</div><div class="cl-val">Diskette Labs</div></div>
|
||
<span class="cl-arrow">↗</span>
|
||
</a>
|
||
<a class="contact-link" href="https://replit.com/@MilesAllen1" target="_blank" rel="noopener">
|
||
<div><div class="cl-label">REPLIT</div><div class="cl-val">@MilesAllen1</div></div>
|
||
<span class="cl-arrow">↗</span>
|
||
</a>
|
||
<a class="contact-link" href="https://codepen.io/mileswolfallen2-the-typescripter" target="_blank" rel="noopener">
|
||
<div><div class="cl-label">CODEPEN</div><div class="cl-val">mileswolfallen2</div></div>
|
||
<span class="cl-arrow">↗</span>
|
||
</a>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ══════════════ FOOTER ══════════════ -->
|
||
<div class="footer-word" aria-hidden="true">MILES</div>
|
||
<div class="footer-bottom">
|
||
<span class="footer-copy">© 2026 MILES WOLF ALLEN — BUILT BY HAND</span>
|
||
<div class="footer-links">
|
||
<a href="../uses.html">USES</a>
|
||
<a href="../now.html">NOW</a>
|
||
<a href="../colophon.html">COLOPHON</a>
|
||
<a href="#hero">↑ TOP</a>
|
||
</div>
|
||
</div>
|
||
|
||
<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 reduce = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
||
var fine = window.matchMedia && window.matchMedia('(pointer: fine)').matches;
|
||
|
||
/* ── LOADER ── */
|
||
var loaderEl = document.getElementById('loader');
|
||
var loaderCount = document.getElementById('loaderCount');
|
||
var loaderBar = document.getElementById('loaderBar');
|
||
var loaderWipe = document.getElementById('loaderWipe');
|
||
var startTime = performance.now();
|
||
var loadDur = reduce ? 0 : 1500;
|
||
|
||
function runLoader() {
|
||
var elapsed = performance.now() - startTime;
|
||
var pct = Math.min(elapsed / loadDur, 1);
|
||
var eased = pct < .5 ? 2 * pct * pct : -1 + (4 - 2 * pct) * pct;
|
||
loaderCount.textContent = Math.floor(eased * 100);
|
||
loaderBar.style.width = (eased * 100) + '%';
|
||
if (pct < 1) {
|
||
requestAnimationFrame(runLoader);
|
||
} else {
|
||
loaderCount.textContent = '100';
|
||
loaderBar.style.width = '100%';
|
||
setTimeout(dismissLoader, 100);
|
||
}
|
||
}
|
||
|
||
function dismissLoader() {
|
||
if (!loaderWipe) return;
|
||
/* ink wipe sweeps right over the yellow panel, then whole loader goes up */
|
||
loaderWipe.style.transition = 'transform .6s cubic-bezier(.76,0,.24,1)';
|
||
loaderWipe.style.transform = 'scaleX(1)';
|
||
setTimeout(function () {
|
||
if (!loaderEl) return;
|
||
loaderEl.style.transition = 'transform .7s cubic-bezier(.76,0,.24,1)';
|
||
loaderEl.style.transform = 'translateY(-100%)';
|
||
setTimeout(function () {
|
||
loaderEl.classList.add('done');
|
||
triggerHeroIn();
|
||
}, 720);
|
||
}, 620);
|
||
}
|
||
|
||
function triggerHeroIn() {
|
||
var heroLabel = document.getElementById('heroLabel');
|
||
var heroName = document.getElementById('heroName');
|
||
var heroDesc = document.getElementById('heroDesc');
|
||
var heroCta = document.getElementById('heroCta');
|
||
var heroScroll = document.getElementById('heroScroll');
|
||
setTimeout(function () { if (heroLabel) heroLabel.classList.add('in'); }, 80);
|
||
setTimeout(function () { if (heroName) heroName.classList.add('in'); }, 160);
|
||
setTimeout(function () { if (heroDesc) heroDesc.classList.add('in'); }, 320);
|
||
setTimeout(function () { if (heroCta) heroCta.classList.add('in'); }, 440);
|
||
setTimeout(function () { if (heroScroll) heroScroll.classList.add('in'); }, 620);
|
||
}
|
||
|
||
if (reduce) {
|
||
if (loaderEl) loaderEl.classList.add('done');
|
||
triggerHeroIn();
|
||
} else {
|
||
requestAnimationFrame(runLoader);
|
||
}
|
||
|
||
/* ── MARQUEE CONTENT ── */
|
||
var mq1Words = ['BUILDING EMULATORS','★','SEND HELP','★','160 REPOS','★','STILL DEBUGGING','★','GD ADDICT','★','USUALLY ONLINE','★','FULL MAXIMALISM','★','CEREAL IS SOUP','★'];
|
||
var mq2Words = ['RATED ★★★★★','EST. 2008','PULL SHARK ×2','OVERCLOCKED','DISKETTE LABS','COFFEE: UNKNOWN','BUGS: INFINITE','YOLO'];
|
||
function buildMarquee(id, words) {
|
||
var el = document.getElementById(id);
|
||
if (!el) return;
|
||
var half = '';
|
||
words.forEach(function (w) {
|
||
half += '<span class="marquee-item">' + w + '</span>';
|
||
});
|
||
el.innerHTML = half + half;
|
||
}
|
||
buildMarquee('mq1', mq1Words);
|
||
buildMarquee('mq2', mq2Words);
|
||
|
||
/* ── SKILL ICONS ── */
|
||
document.querySelectorAll('[data-si]').forEach(function (el) {
|
||
var img = document.createElement('img');
|
||
img.alt = ''; img.loading = 'lazy';
|
||
img.src = 'https://cdn.simpleicons.org/' + el.getAttribute('data-si') + '/000000';
|
||
el.insertBefore(img, el.firstChild);
|
||
});
|
||
|
||
/* ── CURSOR ── */
|
||
var dot = document.getElementById('cDot');
|
||
var ring = document.getElementById('cRing');
|
||
if (fine && dot && ring) {
|
||
var mx=-200, my=-200, dx=-200, dy=-200, rx=-200, ry=-200;
|
||
document.addEventListener('mousemove', function (e) { mx = e.clientX; my = e.clientY; }, { passive: true });
|
||
(function loop() {
|
||
dx += (mx - dx) * 0.5; dy += (my - dy) * 0.5;
|
||
rx += (mx - rx) * 0.1; ry += (my - ry) * 0.1;
|
||
dot.style.left = dx + 'px'; dot.style.top = dy + 'px';
|
||
ring.style.left = rx + 'px'; ring.style.top = ry + 'px';
|
||
requestAnimationFrame(loop);
|
||
})();
|
||
var hoverEls = document.querySelectorAll('a, button, .proj-row, .skill-item, .contact-link, .h-card, .btn');
|
||
hoverEls.forEach(function (el) {
|
||
el.addEventListener('mouseenter', function () { document.body.classList.add('cursor-hover'); });
|
||
el.addEventListener('mouseleave', function () { document.body.classList.remove('cursor-hover'); });
|
||
});
|
||
}
|
||
|
||
/* ── INTERSECTION REVEALS ── */
|
||
if ('IntersectionObserver' in window && !reduce) {
|
||
var io = new IntersectionObserver(function (entries) {
|
||
entries.forEach(function (e) {
|
||
if (e.isIntersecting) { e.target.classList.add('in'); io.unobserve(e.target); }
|
||
});
|
||
}, { threshold: 0.13, rootMargin: '0px 0px -4% 0px' });
|
||
document.querySelectorAll(
|
||
'.reveal-up, .about-heading, .about-photo, .about-body, .about-tags, .skills-heading, .contact-heading'
|
||
).forEach(function (el) { io.observe(el); });
|
||
} else {
|
||
document.querySelectorAll(
|
||
'.reveal-up, .about-heading, .about-photo, .about-body, .about-tags, .skills-heading, .contact-heading'
|
||
).forEach(function (el) { el.classList.add('in'); });
|
||
}
|
||
|
||
/* ── COUNT-UP ── */
|
||
function countUp(el) {
|
||
var target = parseInt(el.getAttribute('data-count'), 10) || 0;
|
||
if (reduce) { el.textContent = target.toLocaleString('en-US'); return; }
|
||
var t0 = null;
|
||
function step(ts) {
|
||
if (t0 === null) t0 = ts;
|
||
var p = Math.min(1, (ts - t0) / 1500);
|
||
var ease = 1 - Math.pow(1 - p, 3);
|
||
el.textContent = Math.round(target * ease).toLocaleString('en-US');
|
||
if (p < 1) requestAnimationFrame(step);
|
||
}
|
||
requestAnimationFrame(step);
|
||
}
|
||
if ('IntersectionObserver' in window) {
|
||
var cio = new IntersectionObserver(function (entries) {
|
||
entries.forEach(function (e) {
|
||
if (e.isIntersecting) { countUp(e.target); cio.unobserve(e.target); }
|
||
});
|
||
}, { threshold: 0.4 });
|
||
document.querySelectorAll('.num[data-count]').forEach(function (el) { cio.observe(el); });
|
||
}
|
||
|
||
/* ── GSAP CHOREOGRAPHY ── */
|
||
if (window.gsap && window.ScrollTrigger && !reduce) {
|
||
gsap.registerPlugin(ScrollTrigger);
|
||
|
||
/* hero name parallax drift */
|
||
gsap.to('#heroName', {
|
||
yPercent: -16, ease: 'none',
|
||
scrollTrigger: { trigger: '.hero', start: 'top top', end: 'bottom top', scrub: 1.2 }
|
||
});
|
||
/* hero rings slow spin + scale */
|
||
gsap.to('.hero-orb', {
|
||
scale: 1.22, opacity: .2, rotation: 15, ease: 'none',
|
||
scrollTrigger: { trigger: '.hero', start: 'top top', end: 'bottom top', scrub: 1.4 }
|
||
});
|
||
|
||
/* project rows — stagger slide in from left */
|
||
gsap.utils.toArray('.proj-row').forEach(function (row, i) {
|
||
gsap.fromTo(row,
|
||
{ opacity: 0, x: -40 },
|
||
{ opacity: 1, x: 0, duration: .65, ease: 'power3.out', delay: i * .045,
|
||
scrollTrigger: { trigger: row, start: 'top 95%', toggleActions: 'play none none none' }
|
||
});
|
||
});
|
||
|
||
/* stats — pop in with spring */
|
||
gsap.utils.toArray('.stat').forEach(function (s, i) {
|
||
gsap.fromTo(s,
|
||
{ opacity: 0, y: 40, rotation: (i % 2 === 0 ? -2 : 2) },
|
||
{ opacity: 1, y: 0, rotation: 0, duration: .75, ease: 'back.out(1.6)', delay: i * .09,
|
||
scrollTrigger: { trigger: '.stats', start: 'top 88%' }
|
||
});
|
||
});
|
||
|
||
/* skill pills — fan in */
|
||
gsap.utils.toArray('.skill-item').forEach(function (item, i) {
|
||
gsap.fromTo(item,
|
||
{ opacity: 0, scale: .7, rotation: (Math.random() * 10 - 5) },
|
||
{ opacity: item.classList.contains('dim') ? .65 : 1,
|
||
scale: 1, rotation: 0,
|
||
duration: .45, ease: 'back.out(1.8)', delay: i * .025,
|
||
scrollTrigger: { trigger: '#skills', start: 'top 86%' }
|
||
});
|
||
});
|
||
|
||
/* horizontal devlog scroll — pinned scrub */
|
||
var hInner = document.getElementById('hScrollInner');
|
||
if (hInner) {
|
||
var totalW = 0;
|
||
hInner.querySelectorAll('.h-card').forEach(function (c) {
|
||
totalW += c.offsetWidth + 40; /* gap approx */
|
||
});
|
||
var overscroll = totalW - hInner.parentElement.offsetWidth + 104;
|
||
if (overscroll > 0) {
|
||
gsap.to(hInner, {
|
||
x: -overscroll, ease: 'none',
|
||
scrollTrigger: {
|
||
trigger: '.h-scroll-outer', pin: true,
|
||
start: 'top top', end: '+=' + (overscroll * 1.25),
|
||
scrub: 1.3
|
||
}
|
||
});
|
||
}
|
||
}
|
||
|
||
/* contact heading lines */
|
||
gsap.utils.toArray('.contact-heading .line span').forEach(function (el, i) {
|
||
gsap.fromTo(el, { y: '105%' }, {
|
||
y: '0%', duration: .95, ease: 'power3.out', delay: i * .14,
|
||
scrollTrigger: { trigger: '#contact', start: 'top 86%' }
|
||
});
|
||
});
|
||
|
||
/* about photo tilt scrub */
|
||
gsap.to('#aboutPhoto', {
|
||
rotation: 0, ease: 'none',
|
||
scrollTrigger: { trigger: '#about', start: 'top 80%', end: 'bottom 30%', scrub: 1.5 }
|
||
});
|
||
|
||
ScrollTrigger.refresh();
|
||
}
|
||
|
||
/* ── SMOOTH WHEEL INERTIA ── */
|
||
if (!reduce) {
|
||
var scrollY = window.scrollY, targetY = scrollY, ticking = false;
|
||
window.addEventListener('wheel', function (e) {
|
||
e.preventDefault();
|
||
targetY = Math.max(0, Math.min(document.body.scrollHeight - window.innerHeight, targetY + e.deltaY * 1.05));
|
||
if (!ticking) {
|
||
ticking = true;
|
||
(function step() {
|
||
scrollY += (targetY - scrollY) * .1;
|
||
window.scrollTo(0, scrollY);
|
||
if (Math.abs(targetY - scrollY) > 0.4) requestAnimationFrame(step);
|
||
else { scrollY = targetY; window.scrollTo(0, scrollY); ticking = false; }
|
||
})();
|
||
}
|
||
}, { passive: false });
|
||
window.addEventListener('touchstart', function () { targetY = scrollY = window.scrollY; }, { passive: true });
|
||
window.addEventListener('touchmove', function () { targetY = scrollY = window.scrollY; }, { passive: true });
|
||
}
|
||
|
||
/* ── KONAMI ── */
|
||
var seq = [38,38,40,40,37,39,37,39,66,65], pos = 0;
|
||
document.addEventListener('keydown', function (e) {
|
||
pos = e.keyCode === seq[pos] ? pos + 1 : 0;
|
||
if (pos === seq.length) {
|
||
pos = 0;
|
||
var colors = ['#FF2EA6','#F7FF00','#00F4FF','#FF5C00','#00FF85'];
|
||
for (var i = 0; i < 44; i++) {
|
||
var s = document.createElement('div');
|
||
s.style.cssText = 'position:fixed;left:50%;top:50%;z-index:9999;pointer-events:none;width:'+(7+Math.random()*16)+'px;height:'+(7+Math.random()*16)+'px;border:2px solid #000;background:'+colors[i%colors.length]+';box-shadow:3px 3px 0 #000;';
|
||
document.body.appendChild(s);
|
||
var a = Math.random()*Math.PI*2, d = 80+Math.random()*400;
|
||
s.animate([
|
||
{ transform:'translate(-50%,-50%) rotate(0deg)', opacity:1 },
|
||
{ transform:'translate(calc(-50% + '+(Math.cos(a)*d)+'px),calc(-50% + '+(Math.sin(a)*d)+'px)) rotate('+(Math.random()*720-360)+'deg)', opacity:0 }
|
||
], { duration:900+Math.random()*500, easing:'cubic-bezier(.2,.8,.2,1)' }).onfinish = (function(el){ return function(){ el.remove(); }; })(s);
|
||
}
|
||
}
|
||
});
|
||
|
||
})();
|
||
</script>
|
||
</body>
|
||
</html>
|