mirror of
https://github.com/mileswolfallen2/miles-web.git
synced 2026-09-08 11:23:17 +00:00
130 lines
30 KiB
HTML
130 lines
30 KiB
HTML
<!doctype html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<title>Miles City // A Personal Portfolio</title>
|
||
<meta name="description" content="Explore Miles City — a map of tools, games, communities, and ideas by Miles Wolf Allen.">
|
||
<meta name="theme-color" content="#101a1f">
|
||
<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='18' fill='%23d9f99d'/%3E%3Cpath d='M23 73V27h13l14 19 14-19h13v46H64V51L50 68 36 51v22z' fill='%23101a1f'/%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=Space+Grotesk:wght@400;500;600;700&display=swap" rel="stylesheet">
|
||
<style>
|
||
:root {
|
||
--night:#101a1f; --night-2:#17242a; --paper:#edf0e6; --muted:#879791; --line:rgba(237,240,230,.15);
|
||
--lime:#d9f99d; --orange:#ff8365; --cyan:#88d8d2; --violet:#b6a5ff; --mono:'DM Mono',monospace; --display:'Space Grotesk',sans-serif; --body:Manrope,sans-serif; --ease:cubic-bezier(.2,.8,.2,1);
|
||
}
|
||
* { box-sizing:border-box; }
|
||
html { scroll-behavior:smooth; background:var(--night); }
|
||
body { margin:0; color:var(--paper); background:var(--night); font-family:var(--body); overflow-x:hidden; }
|
||
body.panel-open { overflow:hidden; }
|
||
::selection { color:var(--night); background:var(--lime); }
|
||
a { color:inherit; text-decoration:none; }
|
||
button { color:inherit; font:inherit; cursor:pointer; }
|
||
.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:30; 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 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; }
|
||
.stars { position:fixed; inset:0; z-index:-3; opacity:.75; background-image:radial-gradient(circle,rgba(237,240,230,.7) 0 1px,transparent 1.5px),radial-gradient(circle,rgba(136,216,210,.45) 0 1px,transparent 1.5px); background-size:91px 91px,147px 147px; background-position:17px 21px,55px 4px; }
|
||
.glow { position:fixed; z-index:-2; left:var(--mx,50%); top:var(--my,40%); width:600px; height:600px; pointer-events:none; transform:translate(-50%,-50%); background:radial-gradient(circle,rgba(136,216,210,.1),transparent 67%); }
|
||
.progress { position:fixed; z-index:50; left:0; top:0; width:0; height:3px; background:var(--lime); box-shadow:0 0 14px var(--lime); }
|
||
|
||
.topbar { position:fixed; z-index:20; top:0; left:0; right:0; height:76px; display:flex; align-items:center; justify-content:space-between; gap:20px; padding:0 5vw; border-bottom:1px solid transparent; transition:background .3s,border-color .3s; }
|
||
.topbar.scrolled { background:rgba(16,26,31,.8); border-color:var(--line); backdrop-filter:blur(17px); }
|
||
.brand { display:flex; align-items:center; gap:11px; font:500 11px var(--mono); letter-spacing:.1em; text-transform:uppercase; }
|
||
.brand i { width:12px; height:12px; display:block; border:2px solid var(--lime); border-radius:50% 50% 50% 0; transform:rotate(-45deg); box-shadow:0 0 14px rgba(217,249,157,.5); }
|
||
.topnav { display:flex; gap:30px; color:var(--muted); font:400 10px var(--mono); letter-spacing:.08em; text-transform:uppercase; }
|
||
.topnav a { position:relative; padding:8px 0; }
|
||
.topnav a::after { content:''; position:absolute; left:0; right:100%; bottom:1px; height:1px; background:var(--lime); transition:right .3s var(--ease); }
|
||
.topnav a:hover,.topnav a:focus-visible { color:var(--paper); } .topnav a:hover::after,.topnav a:focus-visible::after { right:0; }
|
||
.city-status { color:var(--lime); font:400 10px var(--mono); text-transform:uppercase; } .city-status::before { content:'●'; margin-right:7px; animation:blink 1.7s steps(1) infinite; } @keyframes blink { 50% { opacity:.3; } }
|
||
@media(max-width:680px) { .topbar { height:64px; } .topnav { display:none; } .city-status { font-size:9px; } }
|
||
|
||
.hero { position:relative; min-height:100svh; padding:135px 5vw 75px; overflow:hidden; }
|
||
.hero-copy { position:relative; z-index:4; width:min(450px,90vw); }
|
||
.eyebrow { display:flex; align-items:center; gap:12px; color:var(--lime); font:400 10px var(--mono); letter-spacing:.14em; text-transform:uppercase; }
|
||
.eyebrow::before { content:''; width:29px; height:1px; background:var(--lime); }
|
||
h1 { margin:22px 0 24px; font:700 clamp(4.5rem,11.5vw,11rem)/.78 var(--display); letter-spacing:-.12em; }
|
||
h1 span { display:block; } h1 .outline { color:transparent; -webkit-text-stroke:1px var(--paper); } h1 .lime { color:var(--lime); } h1 em { color:var(--orange); font:600 .76em/.8 Georgia,serif; letter-spacing:-.04em; }
|
||
.hero-copy p { max-width:400px; color:var(--muted); font-size:14px; line-height:1.8; }
|
||
.hero-copy p strong { color:var(--paper); font-weight:600; }
|
||
.hero-actions { display:flex; flex-wrap:wrap; align-items:center; gap:18px; margin-top:30px; }
|
||
.primary { display:inline-flex; align-items:center; gap:12px; padding:13px 16px; color:var(--night); background:var(--lime); box-shadow:5px 5px 0 var(--orange); font:500 10px var(--mono); text-transform:uppercase; transition:transform .2s var(--ease),box-shadow .2s var(--ease); }
|
||
.primary:hover { transform:translate(-3px,-3px); box-shadow:8px 8px 0 var(--orange); }
|
||
.primary::after { content:'↘'; font-size:15px; }
|
||
.quiet-link { display:inline-flex; align-items:center; gap:9px; color:var(--paper); font:400 10px var(--mono); text-transform:uppercase; }
|
||
.quiet-link::before { content:''; width:24px; height:1px; background:var(--paper); transition:width .25s var(--ease); } .quiet-link:hover { color:var(--lime); } .quiet-link:hover::before { width:42px; background:var(--lime); }
|
||
|
||
.map-wrap { position:absolute; z-index:1; right:-4vw; top:11vh; width:min(78vw,1050px); height:min(82vh,760px); min-height:510px; perspective:1100px; }
|
||
.map-stage { position:absolute; inset:0; transform:rotateX(48deg) rotateZ(-9deg) rotateY(-4deg); transform-style:preserve-3d; transition:transform .8s var(--ease); }
|
||
.map-surface { position:absolute; inset:4%; overflow:hidden; border:1px solid rgba(217,249,157,.35); background:linear-gradient(135deg,rgba(25,43,45,.97),rgba(14,25,30,.98)); box-shadow:28px 30px 0 rgba(0,0,0,.22),0 0 80px rgba(136,216,210,.08); transform-style:preserve-3d; }
|
||
.map-surface::before { content:''; position:absolute; inset:0; opacity:.17; background-image:linear-gradient(rgba(136,216,210,.2) 1px,transparent 1px),linear-gradient(90deg,rgba(136,216,210,.2) 1px,transparent 1px); background-size:42px 42px; }
|
||
.map-surface::after { content:'MILES CITY / EST. 2008'; position:absolute; right:25px; top:20px; color:rgba(237,240,230,.36); font:400 9px var(--mono); letter-spacing:.12em; }
|
||
.city-map { position:absolute; inset:4%; width:92%; height:92%; overflow:visible; }
|
||
.map-label { position:absolute; z-index:2; color:rgba(237,240,230,.33); font:400 9px var(--mono); letter-spacing:.14em; text-transform:uppercase; pointer-events:none; }
|
||
.label-north { left:13%; top:10%; } .label-west { left:9%; bottom:20%; } .label-east { right:9%; top:39%; } .label-south { left:44%; bottom:10%; }
|
||
.map-legend { position:absolute; z-index:3; left:24px; bottom:21px; display:flex; gap:16px; color:rgba(237,240,230,.52); font:400 8px var(--mono); text-transform:uppercase; } .map-legend span::before { content:''; display:inline-block; width:7px; height:7px; margin-right:6px; border:1px solid currentColor; border-radius:50%; } .map-legend span:first-child::before { background:var(--lime); border-color:var(--lime); } .map-legend span:last-child::before { background:var(--orange); border-color:var(--orange); }
|
||
.road { fill:none; stroke:#66817d; stroke-linecap:round; stroke-linejoin:round; } .road.major { stroke:#90aca3; stroke-width:13; opacity:.27; } .road.minor { stroke:#52706d; stroke-width:5; opacity:.45; } .road.center { stroke:var(--lime); stroke-width:1; stroke-dasharray:9 14; opacity:.6; } .water { fill:#12313b; stroke:#4b7777; stroke-width:1; opacity:.78; } .park { fill:#1f423b; stroke:#6a9b75; stroke-width:1; opacity:.8; } .district { fill:#1a2d31; stroke:rgba(217,249,157,.28); stroke-width:1; } .block { fill:#263d3d; opacity:.72; }
|
||
.pin { position:absolute; z-index:5; display:flex; align-items:center; gap:8px; min-width:125px; padding:8px 10px; border:1px solid rgba(237,240,230,.3); color:var(--paper); background:rgba(16,26,31,.83); text-align:left; transform:translate(-50%,-50%); backdrop-filter:blur(8px); transition:transform .3s var(--ease),background .25s,border-color .25s,box-shadow .25s; }
|
||
.pin:hover,.pin:focus-visible,.pin.active { z-index:8; border-color:var(--lime); background:var(--lime); color:var(--night); outline:none; box-shadow:7px 7px 0 rgba(0,0,0,.25); transform:translate(-50%,-50%) translateY(-7px); }
|
||
.pin::before { content:''; flex:0 0 9px; width:9px; height:9px; border-radius:50% 50% 50% 0; background:var(--orange); transform:rotate(-45deg); } .pin.active::before,.pin:hover::before,.pin:focus-visible::before { background:var(--night); }
|
||
.pin .pin-name { display:block; font:500 10px var(--mono); text-transform:uppercase; letter-spacing:.05em; } .pin .pin-kind { display:block; margin-top:3px; color:var(--muted); font:400 8px var(--mono); text-transform:uppercase; } .pin:hover .pin-kind,.pin:focus-visible .pin-kind,.pin.active .pin-kind { color:rgba(16,26,31,.68); }
|
||
.pin-arcade { left:38%; top:30%; } .pin-foundry { left:69%; top:28%; } .pin-stadium { left:72%; top:66%; } .pin-library { left:35%; top:70%; } .pin-home { left:51%; top:49%; } .pin-contact { left:20%; top:56%; }
|
||
.route { position:absolute; z-index:1; width:1px; height:60px; background:linear-gradient(var(--lime),transparent); transform-origin:top; opacity:.6; }
|
||
.route-a { left:38%; top:34%; transform:rotate(27deg); } .route-b { left:67%; top:32%; transform:rotate(-30deg); } .route-c { left:70%; top:62%; transform:rotate(18deg); } .route-d { left:39%; top:66%; transform:rotate(-18deg); }
|
||
.map-pulse { position:absolute; z-index:4; width:20px; height:20px; border:1px solid var(--lime); border-radius:50%; transform:translate(-50%,-50%); animation:ping 2.4s ease-out infinite; pointer-events:none; } .pulse-home { left:51%; top:49%; } @keyframes ping { 0% { opacity:.8; transform:translate(-50%,-50%) scale(.55); } 100% { opacity:0; transform:translate(-50%,-50%) scale(2.7); } }
|
||
@media(max-width:900px) { .map-wrap { right:-13vw; top:27vh; width:105vw; height:58vh; min-height:430px; opacity:.9; } .map-stage { transform:rotateX(48deg) rotateZ(-7deg) rotateY(0); } .hero-copy { position:relative; z-index:6; } .pin { min-width:105px; } .pin .pin-kind { display:none; } }
|
||
@media(max-width:580px) { .hero { min-height:920px; padding:110px 5vw 70px; } .map-wrap { top:34vh; right:-27vw; width:135vw; height:520px; min-height:0; } .map-surface { inset:5%; } .pin { min-width:0; padding:7px; } .pin .pin-name { font-size:8px; } .pin::before { width:7px; height:7px; flex-basis:7px; } .pin-home,.pin-contact { display:none; } .map-legend { display:none; } }
|
||
|
||
.panel-scrim { position:fixed; z-index:39; inset:0; background:rgba(3,7,9,.55); opacity:0; visibility:hidden; transition:opacity .35s,visibility .35s; }
|
||
.panel-scrim.open { opacity:1; visibility:visible; }
|
||
.city-panel { position:fixed; z-index:40; top:50%; right:4vw; width:min(430px,calc(100vw - 40px)); padding:29px; border:1px solid var(--lime); background:rgba(18,29,32,.96); box-shadow:18px 18px 0 rgba(0,0,0,.3); transform:translate(45px,-50%); opacity:0; visibility:hidden; transition:opacity .4s ease,transform .55s var(--ease),visibility .4s; backdrop-filter:blur(15px); }
|
||
.city-panel.open { transform:translate(0,-50%); opacity:1; visibility:visible; }
|
||
.panel-close { position:absolute; right:14px; top:14px; width:27px; height:27px; display:grid; place-items:center; border:1px solid var(--line); color:var(--muted); background:transparent; font-size:17px; line-height:1; } .panel-close:hover { color:var(--night); background:var(--lime); border-color:var(--lime); }
|
||
.panel-kicker { color:var(--orange); font:400 9px var(--mono); text-transform:uppercase; letter-spacing:.13em; } .city-panel h2 { max-width:340px; margin:17px 0 13px; font:600 clamp(2.4rem,5vw,4rem)/.84 var(--display); letter-spacing:-.1em; } .city-panel p { margin:0; color:var(--muted); font-size:13px; line-height:1.8; } .panel-rule { height:1px; margin:24px 0 15px; background:var(--line); } .panel-meta { display:flex; justify-content:space-between; gap:15px; color:var(--muted); font:400 9px var(--mono); text-transform:uppercase; } .panel-meta b { color:var(--lime); font-weight:400; } .panel-link { display:inline-flex; gap:10px; align-items:center; margin-top:25px; color:var(--lime); font:500 10px var(--mono); text-transform:uppercase; } .panel-link::after { content:'↗'; font-size:16px; } .panel-link:hover { color:var(--orange); }
|
||
@media(max-width:580px) { .city-panel { top:auto; right:15px; bottom:15px; left:15px; width:auto; padding:24px; transform:translateY(30px); } .city-panel.open { transform:translateY(0); } .city-panel h2 { font-size:2.7rem; } }
|
||
|
||
.directory { position:relative; z-index:4; padding:145px 0 105px; background:var(--night); border-top:1px solid var(--line); }
|
||
.directory-inner { width:min(1150px,90vw); margin:auto; }
|
||
.section-head { display:flex; align-items:end; justify-content:space-between; gap:30px; margin-bottom:48px; } .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(3rem,7vw,6.5rem)/.8 var(--display); letter-spacing:-.11em; } h2.section-title em { color:var(--orange); font:600 .82em Georgia,serif; letter-spacing:-.04em; } .section-head p { max-width:290px; margin:0 0 4px; color:var(--muted); font:400 11px/1.75 var(--mono); }
|
||
.directory-list { display:grid; border-top:1px solid var(--line); } .directory-item { display:grid; grid-template-columns:57px minmax(160px,.8fr) minmax(260px,1.3fr) auto auto; gap:20px; align-items:center; padding:23px 0; border-bottom:1px solid var(--line); transition:padding .25s var(--ease),background .25s; } .directory-item:hover { padding-left:13px; background:linear-gradient(90deg,rgba(217,249,157,.08),transparent 70%); } .directory-no { color:var(--orange); font:400 10px var(--mono); } .directory-item h3 { margin:0; font:600 18px var(--display); letter-spacing:-.05em; } .directory-item p { margin:0; color:var(--muted); font:400 11px/1.65 var(--mono); } .directory-type { color:var(--lime); font:400 9px var(--mono); text-transform:uppercase; } .directory-arrow { color:var(--lime); font-size:18px; }
|
||
.city-bands { display:grid; grid-template-columns:1fr 1fr; gap:2px; margin-top:120px; background:var(--line); } .city-band { min-height:260px; padding:28px; background:var(--night-2); } .city-band h3 { margin:10px 0 13px; font:600 clamp(2rem,4vw,3.4rem)/.85 var(--display); letter-spacing:-.09em; } .city-band h3 em { color:var(--lime); font:600 .88em Georgia,serif; } .city-band p { max-width:410px; color:var(--muted); font-size:13px; line-height:1.8; } .city-band a { display:inline-block; margin-top:14px; color:var(--lime); font:400 10px var(--mono); text-transform:uppercase; } .city-band a:hover { color:var(--orange); }
|
||
.footer-links { display:flex; justify-content:space-between; flex-wrap:wrap; gap:20px; margin-top:80px; padding-top:24px; border-top:1px solid var(--line); color:var(--muted); font:400 10px var(--mono); text-transform:uppercase; } .footer-links a { color:var(--lime); } .footer-links a:hover { color:var(--orange); }
|
||
@media(max-width:760px) { .directory { padding-top:100px; } .section-head { display:block; } .section-head p { margin-top:20px; } .directory-item { grid-template-columns:35px 1fr auto; gap:10px; } .directory-item p { grid-column:2 / -1; grid-row:2; } .directory-type { grid-column:2; grid-row:3; } .city-bands { grid-template-columns:1fr; margin-top:90px; } }
|
||
|
||
.reveal { opacity:0; transform:translateY(26px); transition:opacity .75s var(--ease),transform .75s var(--ease); } .reveal.visible { 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; } .reveal { opacity:1; transform:none; } .map-stage { transform:rotateX(48deg) rotateZ(-9deg) rotateY(-4deg)!important; } }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="stars" aria-hidden="true"></div><div class="glow" aria-hidden="true"></div><div class="grain" aria-hidden="true"></div><div class="progress" id="progress"></div>
|
||
<nav class="topbar" id="topbar"><a class="brand" href="#top"><i></i><span>Miles City / city guide</span></a><div class="topnav"><a href="#city-map">Map</a><a href="#directory">Directory</a><a href="#about">About</a><a href="#contact">Contact</a></div><span class="city-status">city is open</span></nav>
|
||
<main id="top">
|
||
<section class="hero" id="city-map"><div class="hero-copy"><div class="eyebrow">welcome to miles city</div><h1><span class="outline">MILES</span><span>WOLF <em>ALLEN</em><span class="lime">.</span></span></h1><p>A map of the things I build: <strong>tools, games, communities, and experiments</strong> connected by one slightly overactive curiosity.</p><div class="hero-actions"><a class="primary" href="#map-surface">explore the city</a><a class="quiet-link" href="#directory">skip to the directory</a></div></div><div class="map-wrap" id="mapWrap"><div class="map-stage" id="mapStage"><div class="map-surface" id="map-surface"><svg class="city-map" viewBox="0 0 1000 650" role="img" aria-label="Stylized map of Miles City showing roads, parks, water, and districts"><path class="water" d="M760 0h240v650H850c35-54 42-108 13-158-25-44-28-83-8-126 22-49 3-94-35-124-40-32-63-78-60-130z"></path><path class="park" d="M78 404c45-31 101-31 135 4 29 31 23 87-8 112-45 36-114 30-148-12-24-29-17-79 21-104z"></path><path class="park" d="M426 49c62-24 127-4 143 42 13 39-28 78-81 79-62 0-111-47-95-86 6-15 16-27 33-35z"></path><path class="district" d="M146 74h242l31 145-89 96-169-28-52-117z"></path><path class="district" d="M438 177l143-31 142 83-22 155-142 20-124-91z"></path><path class="district" d="M130 323l173-25 119 95-30 154-178 34-127-94z"></path><path class="district" d="M431 404l128-31 132 21 70 130-161 77-166-74z"></path><path class="road major" d="M-30 288C174 268 311 281 466 338S747 448 1028 370"></path><path class="road major" d="M352-25c35 150 47 257 34 357s-31 190-4 347"></path><path class="road minor" d="M76 122c165 94 308 105 461 84s259-13 410 94"></path><path class="road minor" d="M27 490c154-95 283-108 409-63s278 98 537 21"></path><path class="road minor" d="M192 20c43 124 57 245 39 369s-3 190 55 277"></path><path class="road minor" d="M602 16c-43 113-59 233-33 343s72 180 151 291"></path><path class="road center" d="M-30 288C174 268 311 281 466 338S747 448 1028 370"></path><path class="road center" d="M352-25c35 150 47 257 34 357s-31 190-4 347"></path><g class="blocks"><rect class="block" x="176" y="122" width="54" height="35" rx="3"></rect><rect class="block" x="246" y="102" width="72" height="42" rx="3"></rect><rect class="block" x="174" y="188" width="95" height="31" rx="3"></rect><rect class="block" x="481" y="222" width="54" height="45" rx="3"></rect><rect class="block" x="558" y="202" width="75" height="35" rx="3"></rect><rect class="block" x="467" y="291" width="82" height="34" rx="3"></rect><rect class="block" x="590" y="284" width="59" height="53" rx="3"></rect><rect class="block" x="191" y="363" width="70" height="42" rx="3"></rect><rect class="block" x="282" y="346" width="77" height="31" rx="3"></rect><rect class="block" x="151" y="435" width="96" height="39" rx="3"></rect><rect class="block" x="268" y="439" width="63" height="55" rx="3"></rect><rect class="block" x="466" y="438" width="71" height="35" rx="3"></rect><rect class="block" x="552" y="423" width="72" height="47" rx="3"></rect></g></svg><span class="map-label label-north">north loop / ideas</span><span class="map-label label-west">west commons</span><span class="map-label label-east">east river / systems</span><span class="map-label label-south">southside / play</span><span class="route route-a"></span><span class="route route-b"></span><span class="route route-c"></span><span class="route route-d"></span><span class="map-pulse pulse-home"></span><button class="pin pin-arcade" type="button" data-location="arcade"><span><b class="pin-name">Arcade</b><small class="pin-kind">OmniEmu / tools</small></span></button><button class="pin pin-foundry" type="button" data-location="foundry"><span><b class="pin-name">Foundry</b><small class="pin-kind">Gelectron / systems</small></span></button><button class="pin pin-stadium" type="button" data-location="stadium"><span><b class="pin-name">Stadium</b><small class="pin-kind">FEDL / community</small></span></button><button class="pin pin-library" type="button" data-location="library"><span><b class="pin-name">Library</b><small class="pin-kind">Noto / notes</small></span></button><button class="pin pin-home" type="button" data-location="home"><span><b class="pin-name">Home Base</b><small class="pin-kind">About Miles</small></span></button><button class="pin pin-contact" type="button" data-location="contact"><span><b class="pin-name">Post Office</b><small class="pin-kind">Say hello</small></span></button><div class="map-legend"><span>district</span><span>open channel</span></div></div></div>
|
||
</section>
|
||
<section class="directory" id="directory"><div class="directory-inner"><div class="section-head reveal"><div><div class="section-label">the city guide / 01</div><h2 class="section-title">A readable<br><em>directory.</em></h2></div><p>Prefer the direct route? Here’s every district with the useful details up front.</p></div><div class="directory-list"><a class="directory-item reveal" href="https://milesallen.site/projects/omniemu.html"><span class="directory-no">01</span><h3>OmniEmu 2.0</h3><p>All your emulators in one place — scan ROMs, install what you need, and launch without opening fifteen different apps.</p><span class="directory-type">arcade / active ↗</span><span class="directory-arrow">↗</span></a><a class="directory-item reveal" href="https://milesallen.site/projects/gelectron.html"><span class="directory-no">02</span><h3>Gelectron</h3><p>A drop-in Electron replacement using native web views instead of bundling an entire copy of Chromium with every app.</p><span class="directory-type">foundry / in progress ↗</span><span class="directory-arrow">↗</span></a><a class="directory-item reveal" href="https://milesallen.site/projects/fedl.html"><span class="directory-no">03</span><h3>FEDL</h3><p>The Geometry Dash demon list: ranked levels, run submissions, and a community that keeps raising the ceiling.</p><span class="directory-type">stadium / live ↗</span><span class="directory-arrow">↗</span></a><a class="directory-item reveal" href="https://milesallen.site/projects/noto.html"><span class="directory-no">04</span><h3>Noto</h3><p>Note-taking with AI built in — a calmer way to turn a pile of fragments into something you can find later.</p><span class="directory-type">library / active ↗</span><span class="directory-arrow">↗</span></a><a class="directory-item reveal" href="https://milesallen.site/projects/moon-gaming.html"><span class="directory-no">05</span><h3>Moon Gaming</h3><p>A browser game hub with a suspicious number of commits and a library that keeps getting bigger at 2am.</p><span class="directory-type">arcade annex / growing ↗</span><span class="directory-arrow">↗</span></a></div><div class="city-bands"><article class="city-band reveal" id="about"><div class="section-label">home base / 02</div><h3>The person<br>behind the <em>map.</em></h3><p>I’m 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.</p><a href="../about-me.html">read more about me ↗</a></article><article class="city-band reveal" id="contact"><div class="section-label">post office / 03</div><h3>Send a<br><em>message.</em></h3><p>Have a question, a strange idea, or a link to something you’re making? The city is open to visitors.</p><a href="mailto:[email protected]">open a channel ↗</a></article></div><div class="footer-links"><span>© 2026 Miles Wolf Allen / Miles City</span><a href="https://github.com/mileswolfallen2" target="_blank" rel="noopener">github ↗</a><a href="https://diskettelabs.com/" target="_blank" rel="noopener">diskette labs ↗</a><a href="#top">return to city hall ↑</a></div></div></section>
|
||
</main>
|
||
<div class="panel-scrim" id="panelScrim"></div><aside class="city-panel" id="cityPanel" role="dialog" aria-modal="true" aria-labelledby="panelTitle"><button class="panel-close" id="panelClose" type="button" aria-label="Close location details">×</button><div class="panel-kicker" id="panelKicker">district / arcade</div><h2 id="panelTitle">OmniEmu 2.0</h2><p id="panelDescription">All your emulators in one place. Scan ROMs, install what you need, and launch without opening fifteen different apps.</p><div class="panel-rule"></div><div class="panel-meta"><span id="panelStack">typescript / desktop</span><b id="panelStatus">active</b></div><a class="panel-link" id="panelLink" href="https://milesallen.site/projects/omniemu.html" target="_blank" rel="noopener">visit the project</a></aside>
|
||
<script>
|
||
(() => {
|
||
const locations = {
|
||
arcade:{ kicker:'district / arcade',title:'OmniEmu 2.0',description:'All your emulators in one place. Scan ROMs, install what you need, and launch without opening fifteen different apps.',stack:'typescript / desktop',status:'active',link:'https://milesallen.site/projects/omniemu.html' },
|
||
foundry:{ kicker:'district / industrial systems',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',status:'in progress',link:'https://milesallen.site/projects/gelectron.html' },
|
||
stadium:{ kicker:'district / community stadium',title:'FEDL',description:'The Geometry Dash demon list: ranked levels, run submissions, and a community that keeps raising the ceiling.',stack:'node / community',status:'live',link:'https://milesallen.site/projects/fedl.html' },
|
||
library:{ kicker:'district / library of thoughts',title:'Noto',description:'Note-taking with AI built in — a calmer way to turn a pile of fragments into something you can find later.',stack:'flutter / ai',status:'active',link:'https://milesallen.site/projects/noto.html' },
|
||
home:{ kicker:'neighborhood / home base',title:'Miles Wolf Allen',description:'Developer, 3D artist, co-founder of Diskette Labs, and a person who keeps turning “that should be easier” into a repository.',stack:'curiosity / perpetual beginner',status:'online',link:'../about-me.html' },
|
||
contact:{ kicker:'neighborhood / post office',title:'Come say hello.',description:'Have a question, a strange idea, or a link to something you’re making? The city is open to visitors.',stack:'email / github / diskette labs',status:'accepting mail',link:'mailto:[email protected]' }
|
||
};
|
||
const body=document.body, panel=document.getElementById('cityPanel'), scrim=document.getElementById('panelScrim');
|
||
const openLocation = key => { const item=locations[key]; document.querySelectorAll('.pin').forEach(pin=>pin.classList.toggle('active',pin.dataset.location===key)); document.getElementById('panelKicker').textContent=item.kicker; document.getElementById('panelTitle').textContent=item.title; document.getElementById('panelDescription').textContent=item.description; document.getElementById('panelStack').textContent=item.stack; document.getElementById('panelStatus').textContent=item.status; document.getElementById('panelLink').href=item.link; panel.classList.add('open'); scrim.classList.add('open'); body.classList.add('panel-open'); document.getElementById('panelClose').focus(); };
|
||
const closeLocation = () => { panel.classList.remove('open'); scrim.classList.remove('open'); body.classList.remove('panel-open'); document.querySelectorAll('.pin').forEach(pin=>pin.classList.remove('active')); };
|
||
document.querySelectorAll('.pin').forEach(pin=>pin.addEventListener('click',()=>openLocation(pin.dataset.location))); document.getElementById('panelClose').addEventListener('click',closeLocation); scrim.addEventListener('click',closeLocation); addEventListener('keydown',event=>{ if(event.key==='Escape') closeLocation(); });
|
||
const topbar=document.getElementById('topbar'), progress=document.getElementById('progress'); const updateScroll=()=>{ topbar.classList.toggle('scrolled',scrollY>20); const max=document.documentElement.scrollHeight-innerHeight; progress.style.width=`${max?scrollY/max*100:0}%`; }; addEventListener('scroll',updateScroll,{passive:true}); updateScroll();
|
||
const glow=document.querySelector('.glow'); addEventListener('pointermove',event=>{ document.documentElement.style.setProperty('--mx',`${event.clientX}px`); document.documentElement.style.setProperty('--my',`${event.clientY}px`); if(glow) { glow.style.left=`${event.clientX}px`; glow.style.top=`${event.clientY}px`; } },{passive:true});
|
||
const mapStage=document.getElementById('mapStage'); addEventListener('pointermove',event=>{ if(matchMedia('(pointer:coarse)').matches) return; const x=event.clientX/innerWidth-.5; const y=event.clientY/innerHeight-.5; mapStage.style.transform=`rotateX(${48-y*3}deg) rotateZ(${-9+x*2}deg) rotateY(${-4+x*3}deg)`; },{passive:true});
|
||
const reveal=new IntersectionObserver(entries=>entries.forEach(entry=>{ if(entry.isIntersecting){ entry.target.classList.add('visible'); reveal.unobserve(entry.target); } }),{threshold:.12}); document.querySelectorAll('.reveal').forEach((item,index)=>{ item.style.transitionDelay=`${Math.min(index%4,3)*70}ms`; reveal.observe(item); });
|
||
})();
|
||
</script>
|
||
</body>
|
||
</html>
|