Files
miles-web/redesign/concept-six.html
T

180 lines
29 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">
<title>Miles Wolf Allen — Designed in Public</title>
<meta name="description" content="The work and current thinking of Miles Wolf Allen — developer, builder, and 3D artist.">
<meta name="theme-color" content="#121210">
<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' rx='24' fill='%23d8f36a'/%3E%3Cpath d='M24 74V26h13l13 18 13-18h13v48H63V49L50 67 37 49v25z' fill='%23121210'/%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=DM+Mono:wght@400;500&family=Manrope:wght@400;500;600;700;800&family=Playfair+Display:ital,wght@0,600;0,700;1,600&display=swap" rel="stylesheet">
<style>
:root {
--bg:#121210; --bg-2:#1a1a17; --cream:#f4f1e8; --muted:#918f84; --line:rgba(244,241,232,.16);
--lime:#d8f36a; --coral:#ff765f; --sky:#9cc8ff; --serif:'Playfair Display',serif; --sans:Manrope,sans-serif; --mono:'DM Mono',monospace; --ease:cubic-bezier(.2,.8,.2,1);
}
* { box-sizing:border-box; }
html { background:var(--bg); scroll-behavior:smooth; }
body { margin:0; color:var(--cream); background:var(--bg); font-family:var(--sans); overflow-x:hidden; cursor:none; }
body.cursor-disabled { cursor:auto; }
::selection { color:var(--bg); background:var(--lime); }
a { color:inherit; text-decoration:none; }
button { color:inherit; font:inherit; cursor:none; }
.sr-only { position:absolute; width:1px; height:1px; padding:0; margin:-1px; overflow:hidden; clip:rect(0,0,0,0); white-space:nowrap; border:0; }
.grain { position:fixed; inset:0; z-index:40; pointer-events:none; opacity:.045; background-image:url("data:image/svg+xml,%3Csvg viewBox='0 0 160 160' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E"); mix-blend-mode:screen; }
.light { position:fixed; z-index:-1; left:var(--light-x,50%); top:var(--light-y,35%); width:550px; height:550px; border-radius:50%; pointer-events:none; transform:translate(-50%,-50%); background:radial-gradient(circle,rgba(216,243,106,.08),transparent 68%); }
.cursor-dot,.cursor-ring { position:fixed; z-index:70; top:0; left:0; pointer-events:none; border-radius:50%; transform:translate(-50%,-50%); }
.cursor-dot { width:6px; height:6px; background:var(--lime); box-shadow:0 0 15px var(--lime); }
.cursor-ring { width:28px; height:28px; border:1px solid rgba(216,243,106,.75); transition:width .28s var(--ease),height .28s var(--ease),border-color .28s; }
body.focused .cursor-ring { width:58px; height:58px; border-color:var(--coral); }
.progress { position:fixed; z-index:60; left:0; top:0; width:0; height:3px; background:var(--lime); box-shadow:0 0 18px rgba(216,243,106,.7); }
@media(pointer:coarse) { body { cursor:auto; } .cursor-dot,.cursor-ring { display:none; } }
.wrap { width:min(1240px,89vw); margin:auto; }
.nav { position:fixed; z-index:30; top:0; left:0; right:0; height:78px; display:flex; align-items:center; justify-content:space-between; gap:20px; padding:0 5.5vw; border-bottom:1px solid transparent; transition:background .35s,border-color .35s; }
.nav.scrolled { background:rgba(18,18,16,.8); border-color:var(--line); backdrop-filter:blur(18px); }
.wordmark { display:flex; align-items:center; gap:11px; font:500 11px var(--mono); letter-spacing:.08em; text-transform:uppercase; }
.wordmark i { width:12px; height:12px; display:block; border:2px solid var(--lime); border-radius:50%; }
.links { display:flex; gap:30px; color:var(--muted); font:400 10px var(--mono); text-transform:uppercase; letter-spacing:.08em; }
.links a { position:relative; padding:8px 0; }
.links a::after { content:''; position:absolute; right:100%; bottom:2px; left:0; height:1px; background:var(--lime); transition:right .3s var(--ease); }
.links a:hover { color:var(--cream); } .links a:hover::after { right:0; }
.nav-status { display:flex; align-items:center; gap:8px; color:var(--lime); font:400 10px var(--mono); text-transform:uppercase; }
.nav-status b { width:7px; height:7px; border-radius:50%; background:var(--lime); animation:pulse 1.8s ease-in-out infinite; }
@keyframes pulse { 50% { opacity:.3; } }
@media(max-width:650px) { .links { display:none; } .nav { height:63px; padding:0 5vw; } .nav-status { font-size:9px; } }
.hero { min-height:100svh; position:relative; display:flex; align-items:center; padding:155px 0 110px; }
.hero-grid { display:grid; grid-template-columns:minmax(0,1fr) 300px; gap:8vw; align-items:end; }
.eyebrow { display:flex; align-items:center; gap:13px; color:var(--lime); font:400 10px var(--mono); letter-spacing:.14em; text-transform:uppercase; }
.eyebrow::before { content:''; width:31px; height:1px; background:var(--lime); }
h1 { max-width:880px; margin:25px 0 30px; font:700 clamp(4.6rem,13vw,12.5rem)/.78 var(--sans); letter-spacing:-.115em; }
h1 span { display:block; }
h1 .thin { color:transparent; -webkit-text-stroke:1px var(--cream); }
h1 .lime { color:var(--lime); }
h1 em { color:var(--coral); font:600 .82em/.8 var(--serif); letter-spacing:-.07em; }
.hero-lede { max-width:520px; margin:0 0 34px 4px; color:var(--muted); font-size:15px; line-height:1.8; }
.hero-lede strong { color:var(--cream); font-weight:600; }
.hero-actions { display:flex; align-items:center; gap:19px; flex-wrap:wrap; }
.primary { display:inline-flex; align-items:center; gap:13px; padding:14px 18px; color:var(--bg); background:var(--lime); font:500 10px var(--mono); text-transform:uppercase; box-shadow:5px 5px 0 var(--coral); transition:transform .22s var(--ease),box-shadow .22s var(--ease); }
.primary:hover { transform:translate(-3px,-3px); box-shadow:8px 8px 0 var(--coral); }
.primary::after { content:'↘'; font-size:15px; }
.text-link { display:inline-flex; gap:10px; align-items:center; color:var(--cream); font:400 10px var(--mono); text-transform:uppercase; }
.text-link span { width:26px; height:1px; background:var(--cream); transition:width .25s var(--ease); } .text-link:hover { color:var(--lime); } .text-link:hover span { width:48px; background:var(--lime); }
.hero-side { padding-bottom:8px; }
.status-card { padding:20px; border-top:1px solid var(--line); border-bottom:1px solid var(--line); }
.status-top { display:flex; justify-content:space-between; color:var(--muted); font:400 9px var(--mono); text-transform:uppercase; }
.status-top b { color:var(--lime); font-weight:400; }
.status-card h2 { margin:36px 0 11px; font:600 27px/.95 var(--sans); letter-spacing:-.06em; }
.status-card p { margin:0; color:var(--muted); font:400 11px/1.7 var(--mono); }
.mini-orbit { position:relative; width:140px; height:140px; margin:38px auto 4px; border:1px solid rgba(156,200,255,.4); border-radius:50%; transform:rotate(-25deg); }
.mini-orbit::before { content:''; position:absolute; inset:18%; border:1px solid var(--coral); border-radius:50%; transform:rotate(55deg) scaleX(.35); }
.mini-orbit::after { content:''; position:absolute; left:50%; top:50%; width:10px; height:10px; border-radius:50%; background:var(--lime); box-shadow:0 0 25px var(--lime); transform:translate(-50%,-50%); }
@media(max-width:760px) { .hero { padding-top:130px; } .hero-grid { grid-template-columns:1fr; gap:58px; } .hero-side { max-width:340px; } }
.ticker { overflow:hidden; margin:0 -1vw; background:var(--lime); color:var(--bg); transform:rotate(-1deg) scale(1.02); }
.ticker-track { display:flex; width:max-content; animation:marquee 26s linear infinite; }
.ticker span { padding:12px 22px; font:500 10px var(--mono); letter-spacing:.12em; text-transform:uppercase; }
.ticker span::after { content:'✳'; padding-left:22px; }
@keyframes marquee { to { transform:translateX(-50%); } }
.section { padding:160px 0; }
.section-head { display:flex; align-items:end; justify-content:space-between; gap:30px; margin-bottom:54px; }
.section-label { color:var(--lime); font:400 10px var(--mono); letter-spacing:.14em; text-transform:uppercase; }
h2.section-title { margin:10px 0 0; font:600 clamp(3.3rem,8vw,7.5rem)/.8 var(--sans); letter-spacing:-.105em; }
h2.section-title em { color:var(--coral); font:600 .85em var(--serif); letter-spacing:-.07em; }
.section-head > p { max-width:280px; margin:0 0 5px; color:var(--muted); font:400 11px/1.75 var(--mono); }
@media(max-width:680px) { .section { padding:105px 0; } .section-head { display:block; margin-bottom:39px; } .section-head > p { margin-top:21px; } }
.work-layout { display:grid; grid-template-columns:370px 1fr; gap:2px; padding:2px; border:1px solid var(--line); background:var(--line); }
.work-list { background:var(--bg-2); }
.work-list-head { display:flex; justify-content:space-between; padding:22px 22px 19px; color:var(--muted); font:400 9px var(--mono); letter-spacing:.1em; text-transform:uppercase; }
.work-item { width:100%; display:grid; grid-template-columns:37px 1fr auto; gap:12px; align-items:center; padding:19px 22px; border:0; border-top:1px solid var(--line); background:transparent; color:var(--muted); text-align:left; transition:background .25s,color .25s,padding .25s var(--ease); }
.work-item:hover { color:var(--cream); padding-left:28px; } .work-item.active { color:var(--bg); background:var(--lime); } .work-item.active:hover { color:var(--bg); }
.work-item .no { font:400 9px var(--mono); } .work-item .name { font:600 14px var(--sans); } .work-item .type { margin-top:4px; font:400 9px var(--mono); text-transform:uppercase; } .work-item .arrow { font-size:15px; }
.work-display { position:relative; min-height:550px; padding:31px; background:var(--bg); overflow:hidden; }
.display-ambient { position:absolute; right:-12%; top:-25%; width:75%; aspect-ratio:1; border-radius:50%; background:radial-gradient(circle,rgba(216,243,106,.15),transparent 60%); pointer-events:none; transition:background .5s; }
.display-grid { position:absolute; inset:0; opacity:.16; background-image:linear-gradient(var(--line) 1px,transparent 1px),linear-gradient(90deg,var(--line) 1px,transparent 1px); background-size:45px 45px; mask-image:linear-gradient(to bottom right,black,transparent 72%); }
.display-top { position:relative; z-index:1; display:flex; justify-content:space-between; color:var(--muted); font:400 9px var(--mono); letter-spacing:.1em; text-transform:uppercase; }
.display-top b { color:var(--lime); font-weight:400; }
.display-art { position:relative; z-index:1; width:min(340px,68%); aspect-ratio:1; margin:38px auto 32px; display:grid; place-items:center; }
.art-ring { position:absolute; width:100%; height:100%; border:1px solid var(--lime); border-radius:50%; transform:rotate(-23deg) scaleY(.37); animation:artSpin 17s linear infinite; }
.art-ring:nth-child(2) { width:82%; height:82%; border-color:var(--coral); transform:rotate(46deg) scaleY(.43); animation-direction:reverse; animation-duration:13s; }
.art-ring:nth-child(3) { width:62%; height:62%; border-style:dashed; border-color:var(--sky); transform:rotate(-65deg) scaleY(.54); animation-duration:25s; }
.art-core { position:relative; z-index:1; width:28%; aspect-ratio:1; background:var(--lime); box-shadow:0 0 45px rgba(216,243,106,.4); transform:rotate(45deg); transition:background .4s,box-shadow .4s; }
.art-core::after { content:''; position:absolute; inset:26%; border:1px solid var(--bg); }
@keyframes artSpin { to { transform:rotate(337deg) scaleY(.37); } }
.display-copy { position:relative; z-index:1; max-width:510px; margin:auto; }
.display-copy .kicker { color:var(--coral); font:400 10px var(--mono); text-transform:uppercase; letter-spacing:.11em; }
.display-copy h3 { margin:12px 0 10px; font:600 clamp(2.4rem,5vw,5rem)/.85 var(--sans); letter-spacing:-.1em; }
.display-copy p { max-width:490px; margin:0; color:var(--muted); font-size:12px; line-height:1.75; }
.display-footer { position:relative; z-index:1; display:flex; justify-content:space-between; align-items:end; gap:15px; margin-top:32px; padding-top:15px; border-top:1px solid var(--line); color:var(--muted); font:400 9px var(--mono); text-transform:uppercase; }
.display-footer a { color:var(--lime); } .display-footer a:hover { color:var(--coral); }
@media(max-width:900px) { .work-layout { grid-template-columns:1fr; } .work-display { min-height:620px; } }
@media(max-width:510px) { .work-display { min-height:580px; padding:22px; } .display-art { width:280px; max-width:90%; margin:40px auto 30px; } }
.manifesto { display:grid; grid-template-columns:.8fr 1.2fr; gap:10vw; align-items:start; }
.portrait { position:relative; max-width:275px; }
.portrait img { display:block; width:100%; aspect-ratio:1; object-fit:cover; filter:grayscale(1) contrast(1.15); border:1px solid var(--line); padding:8px; background:var(--bg-2); }
.portrait::before { content:'MILES / 001'; position:absolute; z-index:1; top:-12px; right:-11px; padding:7px 9px; color:var(--bg); background:var(--lime); font:500 9px var(--mono); transform:rotate(5deg); }
.portrait figcaption { display:flex; justify-content:space-between; margin-top:13px; color:var(--muted); font:400 9px var(--mono); text-transform:uppercase; } .portrait figcaption b { color:var(--lime); font-weight:400; }
.manifesto-copy .lead { margin:0 0 28px; color:var(--cream); font:500 clamp(1.65rem,3.6vw,3.1rem)/1.13 var(--sans); letter-spacing:-.06em; }
.manifesto-copy p:not(.lead) { max-width:600px; color:var(--muted); font-size:14px; line-height:1.85; }
.capabilities { display:flex; flex-wrap:wrap; gap:8px; margin-top:32px; } .capability { padding:8px 10px; border:1px solid var(--line); color:var(--muted); font:400 10px var(--mono); } .capability:nth-child(2n) { color:var(--lime); border-color:rgba(216,243,106,.3); }
@media(max-width:700px) { .manifesto { grid-template-columns:1fr; gap:45px; } .portrait { max-width:230px; } }
.now { position:relative; display:grid; grid-template-columns:1fr 1fr; gap:2px; border:1px solid var(--line); background:var(--line); }
.now-main,.now-list { padding:32px; background:var(--bg-2); } .now-main { min-height:330px; } .now-label { display:flex; justify-content:space-between; color:var(--muted); font:400 9px var(--mono); text-transform:uppercase; } .now-label b { color:var(--coral); font-weight:400; } .now-main h3 { max-width:450px; margin:60px 0 16px; font:600 clamp(2.3rem,4vw,4.4rem)/.82 var(--sans); letter-spacing:-.1em; } .now-main p { max-width:400px; color:var(--muted); font:400 11px/1.75 var(--mono); }
.now-list { padding:0; } .now-row { display:grid; grid-template-columns:34px 1fr; gap:14px; padding:21px 25px; border-bottom:1px solid var(--line); } .now-row:last-child { border-bottom:0; } .now-row .n { color:var(--coral); font:400 9px var(--mono); } .now-row strong { font-size:14px; } .now-row span { display:block; margin-top:5px; color:var(--muted); font:400 10px/1.6 var(--mono); }
@media(max-width:700px) { .now { grid-template-columns:1fr; } .now-main { min-height:280px; } }
.contact { display:grid; grid-template-columns:.8fr 1.2fr; gap:10vw; align-items:end; } .contact h2 { margin:10px 0 0; font:600 clamp(4rem,9vw,9rem)/.75 var(--sans); letter-spacing:-.12em; } .contact h2 span { color:var(--lime); } .contact > div:first-child p { max-width:340px; color:var(--muted); font:400 13px/1.8 var(--mono); } .contact-links { border-top:1px solid var(--line); } .contact-link { display:flex; justify-content:space-between; gap:18px; padding:21px 0; border-bottom:1px solid var(--line); color:var(--muted); transition:.25s; } .contact-link:hover { padding-left:12px; color:var(--cream); } .contact-link span:first-child { font:400 10px var(--mono); letter-spacing:.1em; text-transform:uppercase; } .contact-link span:last-child { color:var(--lime); font:500 clamp(1rem,2vw,1.35rem) var(--sans); }
@media(max-width:700px) { .contact { grid-template-columns:1fr; gap:48px; } }
footer { display:flex; justify-content:space-between; gap:20px; padding:28px 0 42px; border-top:1px solid var(--line); color:var(--muted); font:400 10px var(--mono); text-transform:uppercase; } footer a { color:var(--lime); } footer a:hover { color:var(--coral); }
[data-reveal] { opacity:0; transform:translateY(30px); transition:opacity .8s var(--ease),transform .8s var(--ease); } [data-reveal].in { opacity:1; transform:none; }
@media(prefers-reduced-motion:reduce) { *,*::before,*::after { animation-duration:.001ms!important; animation-iteration-count:1!important; transition-duration:.001ms!important; scroll-behavior:auto!important; } body { cursor:auto; } [data-reveal] { opacity:1; transform:none; } }
</style>
</head>
<body>
<div class="grain" aria-hidden="true"></div><div class="light" aria-hidden="true"></div><div class="progress" id="progress"></div><div class="cursor-dot" id="cursorDot" aria-hidden="true"></div><div class="cursor-ring" id="cursorRing" aria-hidden="true"></div>
<nav class="nav" id="nav"><a class="wordmark" href="#top"><i></i><span>Miles Wolf Allen</span></a><div class="links"><a href="#work">Work</a><a href="#about">About</a><a href="#now">Now</a><a href="#contact">Contact</a></div><span class="nav-status"><b></b> available for good ideas</span></nav>
<main id="top">
<header class="hero wrap"><div class="hero-grid"><div><div class="eyebrow">developer / artist / perpetual beginner</div><h1><span class="thin">MILES</span><span>WOLF <em>ALLEN</em><span class="lime">.</span></span></h1><p class="hero-lede">I build <strong>games, tools, and websites</strong> for the space between a good question and a working answer.</p><div class="hero-actions"><a class="primary" href="#work">Explore the work</a><a class="text-link" href="#about"><span></span> a little about me</a></div></div><aside class="hero-side"><div class="status-card"><div class="status-top"><span>current signal</span><b>● live</b></div><h2>Making software<br>feel obvious.</h2><p>A running thesis, currently being tested through emulators, native apps, local AI, and tiny games.</p><div class="mini-orbit" aria-hidden="true"></div></div></aside></div></header>
<div class="ticker" aria-label="Interests"><div class="ticker-track"><span>tools with a point of view</span><span>games after midnight</span><span>native web views</span><span>curiosity as a method</span><span>tools with a point of view</span><span>games after midnight</span><span>native web views</span><span>curiosity as a method</span></div></div>
<section class="section wrap" id="work"><div class="section-head" data-reveal><div><div class="section-label">01 / selected work</div><h2 class="section-title">The <em>things</em><br>I keep building.</h2></div><p>Not a list of everything. Just the work with enough gravity to pull me back in.</p></div><div class="work-layout" data-reveal><div class="work-list"><div class="work-list-head"><span>project index</span><span>05 entries</span></div><button class="work-item active" type="button" data-key="omniemu"><span class="no">01</span><span><b class="name">OmniEmu 2.0</b><b class="type">tool / active</b></span><span class="arrow"></span></button><button class="work-item" type="button" data-key="gelectron"><span class="no">02</span><span><b class="name">Gelectron</b><b class="type">tool / in progress</b></span><span class="arrow"></span></button><button class="work-item" type="button" data-key="fedl"><span class="no">03</span><span><b class="name">FEDL</b><b class="type">community / live</b></span><span class="arrow"></span></button><button class="work-item" type="button" data-key="noto"><span class="no">04</span><span><b class="name">Noto</b><b class="type">tool / active</b></span><span class="arrow"></span></button><button class="work-item" type="button" data-key="moon"><span class="no">05</span><span><b class="name">Moon Gaming</b><b class="type">games / growing</b></span><span class="arrow"></span></button></div><div class="work-display" id="workDisplay"><div class="display-ambient" id="displayAmbient"></div><div class="display-grid"></div><div class="display-top"><span id="displayIndex">selected / 01</span><b id="displayStatus">active</b></div><div class="display-art" aria-hidden="true"><i class="art-ring"></i><i class="art-ring"></i><i class="art-ring"></i><i class="art-core" id="artCore"></i></div><div class="display-copy"><div class="kicker" id="displayKicker">a cabinet for the collection</div><h3 id="displayTitle">OmniEmu 2.0</h3><p id="displayDescription">All your emulators in one place. Scan your ROMs, install what you need, and launch without opening fifteen different apps.</p></div><div class="display-footer"><span id="displayStack">typescript / desktop</span><a id="displayLink" href="https://milesallen.site/projects/omniemu.html">view project ↗</a></div></div></div></section>
<section class="section wrap" id="about"><div class="section-head" data-reveal><div><div class="section-label">02 / a little context</div><h2 class="section-title">The person<br>behind the <em>tabs.</em></h2></div><p>Somewhere between a developer, a 3D artist, and a person who reads changelogs for fun.</p></div><div class="manifesto"><figure class="portrait" data-reveal><img src="https://avatars.githubusercontent.com/u/115095719?v=4" alt="Miles Wolf Allen" loading="lazy" width="275" height="275"><figcaption><span>subject / MWA</span><b>● online</b></figcaption></figure><div class="manifesto-copy" data-reveal><p class="lead">I like software that makes you feel a little more capable after using it.</p><p>Im Miles — a developer and 3D artist, co-founder of Diskette Labs, and a student who spends a lot of time turning “that should be easier” into a repository. I care about the small decisions: the shape of a button, the speed of a launch, the moment a complicated thing clicks.</p><div class="capabilities"><span class="capability">TypeScript</span><span class="capability">Rust</span><span class="capability">Swift</span><span class="capability">Blender</span><span class="capability">Game development</span><span class="capability">Web design</span></div></div></div></section>
<section class="section wrap" id="now"><div class="section-head" data-reveal><div><div class="section-label">03 / current signal</div><h2 class="section-title">Whats<br>happening <em>now.</em></h2></div><p>A small snapshot from the workbench. Updated when the work changes.</p></div><div class="now" data-reveal><div class="now-main"><div class="now-label"><span>transmission / 006</span><b>receiving</b></div><h3>Make room<br>for <em>play.</em></h3><p>Balancing the serious work with small games, bright interfaces, and experiments that dont need a business plan.</p></div><div class="now-list"><div class="now-row"><span class="n">A/01</span><div><strong>Gelectron is moving</strong><span>native web views / fewer megabytes</span></div></div><div class="now-row"><span class="n">B/02</span><div><strong>FEDL stays online</strong><span>the list keeps getting harder</span></div></div><div class="now-row"><span class="n">C/03</span><div><strong>Learning Rust</strong><span>the compiler is a co-designer</span></div></div><div class="now-row"><span class="n">D/04</span><div><strong>Making more space</strong><span>for the weird version</span></div></div></div></div></section>
<section class="section wrap" id="contact"><div class="contact"><div data-reveal><div class="section-label">04 / open channel</div><h2>Bring a<br><span>good idea.</span></h2><p>Send a question, a strange idea, or a link to something youre making. I like the internet best when people are actually in it.</p></div><div class="contact-links" data-reveal><a class="contact-link" href="mailto:[email protected]"><span>email</span><span>[email protected]</span></a><a class="contact-link" href="https://github.com/mileswolfallen2" target="_blank" rel="noopener"><span>github</span><span>@mileswolfallen2 ↗</span></a><a class="contact-link" href="https://diskettelabs.com/" target="_blank" rel="noopener"><span>collective</span><span>Diskette Labs ↗</span></a><a class="contact-link" href="https://codepen.io/mileswolfallen2-the-typescripter" target="_blank" rel="noopener"><span>experiments</span><span>CodePen ↗</span></a></div></div></section>
</main>
<footer class="wrap"><span>© 2026 Miles Wolf Allen / designed in public</span><a href="#top">return to the top ↑</a><span>signal stable ●</span></footer>
<script>
(() => {
const reduce = matchMedia('(prefers-reduced-motion: reduce)').matches;
const root = document.documentElement;
const body = document.body;
const dot = document.getElementById('cursorDot');
const ring = document.getElementById('cursorRing');
let x = innerWidth / 2, y = innerHeight / 2, rx = x, ry = y;
addEventListener('pointermove', event => { x = event.clientX; y = event.clientY; root.style.setProperty('--light-x', `${x}px`); root.style.setProperty('--light-y', `${y}px`); if (dot) { dot.style.left = `${x}px`; dot.style.top = `${y}px`; } });
const cursorLoop = () => { rx += (x - rx) * .15; ry += (y - ry) * .15; if (ring) { ring.style.left = `${rx}px`; ring.style.top = `${ry}px`; } if (!reduce) requestAnimationFrame(cursorLoop); }; if (!matchMedia('(pointer: coarse)').matches) cursorLoop(); else body.classList.add('cursor-disabled');
document.querySelectorAll('a,button').forEach(item => { item.addEventListener('mouseenter', () => body.classList.add('focused')); item.addEventListener('mouseleave', () => body.classList.remove('focused')); });
const nav = document.getElementById('nav'); const progress = document.getElementById('progress');
const scrollUpdate = () => { nav.classList.toggle('scrolled', scrollY > 20); const max = document.documentElement.scrollHeight - innerHeight; progress.style.width = `${max ? scrollY / max * 100 : 0}%`; }; addEventListener('scroll', scrollUpdate, { passive:true }); scrollUpdate();
const reveal = new IntersectionObserver(entries => entries.forEach(entry => { if (entry.isIntersecting) { entry.target.classList.add('in'); reveal.unobserve(entry.target); } }), { threshold:.12 }); document.querySelectorAll('[data-reveal]').forEach((item,index) => { item.style.transitionDelay = `${Math.min(index % 4,3) * 70}ms`; reveal.observe(item); });
const data = {
omniemu:{ index:'selected / 01',status:'active',kicker:'a cabinet for the collection',title:'OmniEmu 2.0',description:'All your emulators in one place. Scan your ROMs, install what you need, and launch without opening fifteen different apps.',stack:'typescript / desktop',link:'https://milesallen.site/projects/omniemu.html',color:'var(--lime)' },
gelelectron:{ index:'selected / 02',status:'in progress',kicker:'a lighter desktop future',title:'Gelectron',description:'A drop-in Electron replacement using native web views instead of bundling an entire copy of Chromium with every app.',stack:'rust / node / native',link:'https://milesallen.site/projects/gelectron.html',color:'var(--coral)' },
fedl:{ index:'selected / 03',status:'live',kicker:'a list that became a place',title:'FEDL',description:'The Geometry Dash demon list: ranked levels, run submissions, and a community that keeps raising the ceiling.',stack:'node / community',link:'https://milesallen.site/projects/fedl.html',color:'var(--sky)' },
noto:{ index:'selected / 04',status:'active',kicker:'a second brain with better lighting',title:'Noto',description:'Note-taking with AI built in. A calmer way to turn a pile of fragments into something you can actually find later.',stack:'flutter / ai',link:'https://milesallen.site/projects/noto.html',color:'var(--coral)' },
moon:{ index:'selected / 05',status:'growing',kicker:'small games, big late-night energy',title:'Moon Gaming',description:'A browser game hub with a suspicious number of commits and a library that keeps getting bigger at 2am.',stack:'web / games',link:'https://milesallen.site/projects/moon-gaming.html',color:'var(--lime)' }
};
const itemNodes = document.querySelectorAll('.work-item'); const display = document.getElementById('workDisplay');
const updateDisplay = key => { const item = data[key]; document.getElementById('displayIndex').textContent = item.index; document.getElementById('displayStatus').textContent = item.status; document.getElementById('displayKicker').textContent = item.kicker; document.getElementById('displayTitle').textContent = item.title; document.getElementById('displayDescription').textContent = item.description; document.getElementById('displayStack').textContent = item.stack; document.getElementById('displayLink').href = item.link; document.getElementById('displayAmbient').style.background = `radial-gradient(circle, color-mix(in srgb, ${item.color} 16%, transparent), transparent 61%)`; document.getElementById('artCore').style.background = item.color; document.getElementById('artCore').style.boxShadow = `0 0 45px color-mix(in srgb, ${item.color} 40%, transparent)`; };
itemNodes.forEach(node => node.addEventListener('click', () => { itemNodes.forEach(item => item.classList.remove('active')); node.classList.add('active'); updateDisplay(node.dataset.key); }));
})();
</script>
</body>
</html>