Files

132 lines
18 KiB
HTML
Raw Permalink 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>The Miles Museum // A Digital Collection</title>
<meta name="description" content="A digital museum of tools, games, experiments, and unfinished ideas by Miles Wolf Allen.">
<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='%23ff8b5c'/%3E%3Ccircle cx='50' cy='50' r='31' fill='none' stroke='%230a0d11' stroke-width='9'/%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=Outfit:wght@400;500;600;700;800&display=swap" rel="stylesheet">
<style>
:root { --black:#080b0f; --wall:#11171c; --wall-2:#182128; --white:#e9edf0; --dim:#7d8990; --orange:#ff8b5c; --cyan:#7be7df; --yellow:#f6dd76; --mono:'DM Mono',monospace; --display:Outfit,sans-serif; }
* { box-sizing:border-box; }
html { background:var(--black); scroll-behavior:smooth; }
body { margin:0; min-height:100vh; color:var(--white); background:radial-gradient(circle at 50% 35%,#202c32 0,#0b1014 42%,var(--black) 80%); font-family:var(--display); overflow-x:hidden; }
body.modal-open { overflow:hidden; }
::selection { background:var(--orange); color:var(--black); }
a { color:inherit; text-decoration:none; }
button { font:inherit; cursor:pointer; }
.ambient { position:fixed; inset:0; z-index:-2; pointer-events:none; opacity:.35; background:radial-gradient(ellipse at 20% 10%,rgba(123,231,223,.16),transparent 32%),radial-gradient(ellipse at 84% 63%,rgba(255,139,92,.12),transparent 29%); }
.stars { position:fixed; inset:0; z-index:-3; background-image:radial-gradient(circle,rgba(233,237,240,.7) 0 1px,transparent 1.5px),radial-gradient(circle,rgba(123,231,223,.45) 0 1px,transparent 1.5px); background-size:73px 73px,131px 131px; background-position:11px 23px,50px 3px; opacity:.25; }
.topbar { position:fixed; z-index:30; top:0; left:0; right:0; display:flex; justify-content:space-between; align-items:center; padding:22px 4vw; border-bottom:1px solid rgba(233,237,240,.13); background:rgba(8,11,15,.72); backdrop-filter:blur(15px); }
.brand { display:flex; align-items:center; gap:12px; font:500 11px var(--mono); letter-spacing:.1em; text-transform:uppercase; }
.brand i { width:15px; height:15px; display:block; border:2px solid var(--orange); border-radius:50%; box-shadow:0 0 16px rgba(255,139,92,.7); }
.topbar .meta { color:var(--dim); font:400 10px var(--mono); letter-spacing:.08em; text-transform:uppercase; }
.topbar .meta b { color:var(--cyan); font-weight:400; }
.hero { min-height:82vh; display:flex; flex-direction:column; justify-content:center; width:min(1180px,88vw); margin:auto; padding-top:105px; }
.eyebrow { color:var(--orange); font:400 10px var(--mono); text-transform:uppercase; letter-spacing:.14em; }
h1 { max-width:850px; margin:25px 0 20px; font:600 clamp(4.7rem,13vw,12rem)/.78 var(--display); letter-spacing:-.095em; }
h1 span { display:block; }
h1 .outline { color:transparent; -webkit-text-stroke:1px var(--white); }
h1 .cyan { color:var(--cyan); }
.hero p { max-width:440px; color:var(--dim); font:400 13px/1.8 var(--mono); }
.hero-footer { display:flex; align-items:center; gap:30px; margin-top:42px; color:var(--dim); font:400 10px var(--mono); text-transform:uppercase; letter-spacing:.1em; }
.hero-footer a { color:var(--cyan); }
.museum { position:relative; min-height:1050px; padding:100px 0 180px; overflow:hidden; perspective:1300px; }
.room-label { position:absolute; z-index:3; top:55px; left:6vw; right:6vw; display:flex; justify-content:space-between; color:var(--dim); font:400 10px var(--mono); letter-spacing:.1em; text-transform:uppercase; }
.room-label b { color:var(--orange); font-weight:400; }
.gallery { position:relative; width:min(1050px,86vw); height:750px; margin:auto; transform-style:preserve-3d; transform:rotateX(var(--rx, 4deg)) rotateY(var(--ry, 0deg)); transition:transform .25s ease-out; }
.back-wall { position:absolute; left:6%; right:6%; top:5%; height:520px; border:1px solid rgba(233,237,240,.15); background:linear-gradient(180deg,rgba(233,237,240,.04),rgba(233,237,240,.01)); transform:translateZ(-210px); box-shadow:inset 0 0 80px rgba(123,231,223,.04); }
.back-wall::before { content:'COLLECTION / 2026'; position:absolute; top:25px; left:28px; color:rgba(233,237,240,.25); font:400 9px var(--mono); letter-spacing:.14em; }
.floor { position:absolute; left:-10%; right:-10%; top:56%; height:48%; border-top:1px solid rgba(123,231,223,.25); background:repeating-linear-gradient(90deg,transparent 0 79px,rgba(123,231,223,.10) 80px),repeating-linear-gradient(0deg,transparent 0 59px,rgba(123,231,223,.10) 60px); transform:rotateX(67deg) translateZ(-30px); transform-origin:top center; }
.ceiling-light { position:absolute; left:25%; top:6%; width:50%; height:2px; background:var(--cyan); box-shadow:0 0 30px 10px rgba(123,231,223,.16); transform:translateZ(-100px); }
.exhibit { position:absolute; z-index:2; width:220px; min-height:260px; padding:18px; display:flex; flex-direction:column; justify-content:space-between; border:1px solid rgba(233,237,240,.55); background:rgba(24,33,40,.9); box-shadow:0 20px 55px rgba(0,0,0,.35); transform-style:preserve-3d; transition:transform .5s cubic-bezier(.2,.8,.2,1), border-color .3s, box-shadow .3s; }
.exhibit:hover { border-color:var(--orange); box-shadow:0 25px 65px rgba(255,139,92,.18); transform:translateZ(55px) rotateY(0deg)!important; }
.exhibit::after { content:attr(data-number); position:absolute; right:15px; top:12px; color:rgba(233,237,240,.25); font:400 27px var(--display); }
.exhibit:nth-of-type(1) { left:10%; top:19%; transform:translateZ(80px) rotateY(9deg) rotateZ(-2deg); }
.exhibit:nth-of-type(2) { left:39%; top:12%; transform:translateZ(160px) rotateY(-2deg) rotateZ(1deg); }
.exhibit:nth-of-type(3) { right:8%; top:25%; transform:translateZ(38px) rotateY(-10deg) rotateZ(2deg); }
.exhibit:nth-of-type(4) { left:26%; top:53%; transform:translateZ(115px) rotateY(6deg) rotateZ(-1deg); }
.exhibit:nth-of-type(5) { right:17%; top:61%; transform:translateZ(70px) rotateY(-6deg) rotateZ(1deg); }
.exhibit .top { display:flex; justify-content:space-between; color:var(--dim); font:400 9px var(--mono); text-transform:uppercase; letter-spacing:.08em; }
.exhibit .top b { color:var(--orange); font-weight:400; }
.exhibit-art { position:relative; height:105px; display:grid; place-items:center; margin:18px 0; border:1px solid rgba(233,237,240,.16); background:radial-gradient(circle,rgba(123,231,223,.12),transparent 65%); overflow:hidden; }
.exhibit-art::before, .exhibit-art::after { content:''; position:absolute; width:70px; height:70px; border:1px solid var(--cyan); transform:rotate(45deg); }
.exhibit-art::after { width:32px; height:32px; border-color:var(--orange); border-radius:50%; transform:rotate(0); box-shadow:0 0 25px var(--orange); }
.art-2 { background:radial-gradient(circle,rgba(255,139,92,.15),transparent 65%); }
.art-2::before { width:90px; height:25px; border-color:var(--orange); border-radius:50%; transform:rotate(-25deg); }
.art-2::after { width:8px; height:8px; background:var(--yellow); border:0; box-shadow:0 0 30px var(--yellow); }
.art-3::before { width:65px; height:65px; border-radius:50%; border-style:dashed; animation:spin 15s linear infinite; }
.art-3::after { width:45px; height:45px; border:1px solid var(--yellow); transform:rotate(45deg); }
.art-4::before { width:80px; height:1px; border:0; background:var(--cyan); transform:rotate(45deg); box-shadow:0 -19px 0 rgba(123,231,223,.45),0 19px 0 rgba(123,231,223,.25); }
.art-4::after { width:10px; height:10px; border:0; background:var(--orange); transform:none; }
@keyframes spin { to { transform:rotate(360deg); } }
.exhibit h2 { margin:0 0 8px; font:500 24px/.95 var(--display); letter-spacing:-.06em; }
.exhibit p { margin:0; color:var(--dim); font:400 10px/1.65 var(--mono); }
.exhibit .open { display:inline-flex; justify-content:space-between; align-items:center; margin-top:17px; padding-top:11px; border-top:1px solid rgba(233,237,240,.16); color:var(--cyan); font:400 9px var(--mono); text-transform:uppercase; }
.exhibit .open::after { content:'↗'; font-size:15px; }
.museum-caption { position:absolute; z-index:4; bottom:65px; left:50%; transform:translateX(-50%); color:var(--dim); font:400 10px var(--mono); letter-spacing:.12em; text-transform:uppercase; white-space:nowrap; }
.museum-caption b { color:var(--orange); font-weight:400; }
.facts { display:grid; grid-template-columns:repeat(3,1fr); gap:1px; width:min(1180px,88vw); margin:0 auto; border:1px solid rgba(233,237,240,.13); background:rgba(233,237,240,.13); }
.fact { padding:25px; background:var(--wall); }
.fact small { display:block; color:var(--dim); font:400 9px var(--mono); text-transform:uppercase; letter-spacing:.1em; }
.fact strong { display:block; margin-top:10px; color:var(--cyan); font:500 28px var(--display); }
.fact p { margin:6px 0 0; color:var(--dim); font:400 10px/1.6 var(--mono); }
.exit { display:grid; grid-template-columns:1fr 1fr; gap:8vw; align-items:center; width:min(1180px,88vw); margin:180px auto 130px; padding:65px 0 0; border-top:1px solid rgba(233,237,240,.18); }
.exit h2 { margin:0; font:500 clamp(3.5rem,8vw,8.5rem)/.8 var(--display); letter-spacing:-.09em; }
.exit h2 span { color:var(--orange); }
.exit-copy { color:var(--dim); font:400 12px/1.8 var(--mono); }
.exit-copy a { display:inline-block; margin-top:22px; color:var(--cyan); }
footer { display:flex; justify-content:space-between; gap:20px; width:min(1180px,88vw); margin:auto; padding:25px 0 40px; border-top:1px solid rgba(233,237,240,.13); color:var(--dim); font:400 10px var(--mono); text-transform:uppercase; }
footer a { color:var(--orange); }
.modal { position:fixed; inset:0; z-index:50; display:none; place-items:center; padding:25px; background:rgba(8,11,15,.84); backdrop-filter:blur(14px); }
.modal.open { display:grid; }
.modal-card { position:relative; width:min(590px,100%); padding:32px; border:1px solid var(--orange); background:var(--wall-2); box-shadow:0 0 70px rgba(255,139,92,.14); }
.modal-card .close { position:absolute; top:16px; right:16px; width:30px; height:30px; border:1px solid rgba(233,237,240,.3); background:transparent; color:var(--white); }
.modal-card .close:hover { background:var(--orange); color:var(--black); }
.modal-kicker { color:var(--orange); font:400 10px var(--mono); text-transform:uppercase; letter-spacing:.1em; }
.modal-card h2 { margin:18px 0 15px; font:500 45px/.9 var(--display); letter-spacing:-.07em; }
.modal-card p { max-width:470px; color:var(--dim); font:400 12px/1.8 var(--mono); }
.modal-card a { display:inline-block; margin-top:20px; color:var(--cyan); font:400 11px var(--mono); }
@media(max-width:760px) { .topbar .meta { display:none; } .hero { min-height:70vh; } .museum { min-height:1250px; } .gallery { height:990px; transform:rotateX(2deg)!important; } .exhibit { width:190px; min-height:240px; } .exhibit:nth-of-type(1) { left:0; top:14%; } .exhibit:nth-of-type(2) { left:auto; right:0; top:8%; } .exhibit:nth-of-type(3) { right:0; top:35%; } .exhibit:nth-of-type(4) { left:0; top:54%; } .exhibit:nth-of-type(5) { right:0; top:73%; } .facts { grid-template-columns:1fr; } .exit { grid-template-columns:1fr; margin-top:120px; } }
@media(max-width:460px) { .exhibit { width:158px; padding:13px; } .exhibit h2 { font-size:20px; } .exhibit p { font-size:9px; } .exhibit-art { height:80px; } .gallery { width:94vw; } }
@media(prefers-reduced-motion:reduce) { *,*::before,*::after { animation:none!important; transition:none!important; scroll-behavior:auto!important; } }
</style>
</head>
<body>
<div class="stars" aria-hidden="true"></div><div class="ambient" aria-hidden="true"></div>
<nav class="topbar"><a class="brand" href="#top"><i></i><span>The Miles Museum</span></a><div class="meta"><b>● open</b> / gallery hours: always</div></nav>
<main id="top">
<header class="hero"><div class="eyebrow">digital collection / room 01</div><h1><span class="outline">A SMALL</span><span> MUSEUM OF</span><span class="cyan">BIG IDEAS.</span></h1><p>A spatial index of tools, games, experiments, and unfinished thoughts by Miles Wolf Allen. Walk around. Touch the exhibits. Nothing is behind glass.</p><div class="hero-footer"><span>↓ enter the collection</span><a href="#gallery">skip to exhibits ↘</a></div></header>
<section class="museum" id="gallery"><div class="room-label"><span>ROOM 01 / THE WORKS</span><b>CAMERA: ACTIVE</b></div><div class="gallery" id="galleryScene"><div class="back-wall"></div><div class="ceiling-light"></div><div class="floor"></div>
<article class="exhibit" data-number="01" data-title="OmniEmu 2.0" data-kicker="The emulator cabinet" data-copy="All your emulators in one place. Scan ROMs, install what you need, and launch without opening fifteen different apps." data-link="https://milesallen.site/projects/omniemu.html"><div><div class="top"><span>tool / active</span><b>2026</b></div><div class="exhibit-art"></div><h2>OmniEmu 2.0</h2><p>The cabinet that keeps the whole collection in one place.</p></div><button class="open" type="button">open exhibit</button></article>
<article class="exhibit" data-number="02" data-title="Gelectron" data-kicker="The native wing" data-copy="A drop-in Electron replacement using native web views instead of bundling an entire copy of Chromium with every app." data-link="https://milesallen.site/projects/gelectron.html"><div><div class="top"><span>tool / in progress</span><b>2026</b></div><div class="exhibit-art art-2"></div><h2>Gelectron</h2><p>A lighter future for desktop web apps.</p></div><button class="open" type="button">open exhibit</button></article>
<article class="exhibit" data-number="03" data-title="FEDL" data-kicker="The community hall" data-copy="The Geometry Dash demon list: ranked levels, run submissions, and a community that keeps raising the ceiling." data-link="https://milesallen.site/projects/fedl.html"><div><div class="top"><span>community / live</span><b>2024—</b></div><div class="exhibit-art art-3"></div><h2>FEDL</h2><p>A ranking system that turned into a place.</p></div><button class="open" type="button">open exhibit</button></article>
<article class="exhibit" data-number="04" data-title="Noto" data-kicker="The memory room" data-copy="Note-taking with AI built in. A calmer way to turn a pile of fragments into something you can actually find later." data-link="https://milesallen.site/projects/noto.html"><div><div class="top"><span>tool / active</span><b>2025—</b></div><div class="exhibit-art art-4"></div><h2>Noto</h2><p>A second brain with better lighting.</p></div><button class="open" type="button">open exhibit</button></article>
<article class="exhibit" data-number="05" data-title="Moon Gaming" data-kicker="The arcade annex" data-copy="A browser game hub with a suspicious number of commits and a library that keeps getting bigger at 2am." data-link="https://milesallen.site/projects/moon-gaming.html"><div><div class="top"><span>game hub / growing</span><b>2023—</b></div><div class="exhibit-art art-2"></div><h2>Moon Gaming</h2><p>Small games, big late-night energy.</p></div><button class="open" type="button">open exhibit</button></article>
</div><p class="museum-caption"><b>tip:</b> move your cursor to orbit the room / click an exhibit to learn more</p></section>
<div class="facts"><div class="fact"><small>collection size</small><strong>160+</strong><p>repositories and counting</p></div><div class="fact"><small>materials</small><strong>TS / RUST</strong><p>plus a lot of stubbornness</p></div><div class="fact"><small>last acquisition</small><strong>NOW</strong><p>still adding new rooms</p></div></div>
<section class="exit"><h2>Keep<br>looking <span>around.</span></h2><div class="exit-copy">The museum is never finished. There are more experiments in the archive, more notes in the margins, and probably another project open in a neighboring tab.<br><a href="../about-me.html">learn about the person behind the collection ↗</a></div></section>
</main>
<footer><span>© 2026 Miles Wolf Allen / The Miles Museum</span><a href="#top">return to entrance ↑</a></footer>
<div class="modal" id="modal" role="dialog" aria-modal="true" aria-labelledby="modalTitle"><div class="modal-card"><button class="close" id="closeModal" type="button" aria-label="Close exhibit">×</button><div class="modal-kicker" id="modalKicker"></div><h2 id="modalTitle"></h2><p id="modalCopy"></p><a id="modalLink" href="#" target="_blank" rel="noopener">visit the project ↗</a></div></div>
<script>
const scene = document.getElementById('galleryScene');
const reduce = matchMedia('(prefers-reduced-motion: reduce)').matches;
if (!reduce && !matchMedia('(pointer: coarse)').matches) {
scene.addEventListener('pointermove', event => { const rect = scene.getBoundingClientRect(); const x = (event.clientX - rect.left) / rect.width - .5; const y = (event.clientY - rect.top) / rect.height - .5; scene.style.setProperty('--ry', `${x * 7}deg`); scene.style.setProperty('--rx', `${4 - y * 6}deg`); });
scene.addEventListener('pointerleave', () => { scene.style.setProperty('--ry', '0deg'); scene.style.setProperty('--rx', '4deg'); });
}
const modal = document.getElementById('modal');
const openModal = exhibit => { document.getElementById('modalKicker').textContent = exhibit.dataset.kicker; document.getElementById('modalTitle').textContent = exhibit.dataset.title; document.getElementById('modalCopy').textContent = exhibit.dataset.copy; document.getElementById('modalLink').href = exhibit.dataset.link; modal.classList.add('open'); document.body.classList.add('modal-open'); document.getElementById('closeModal').focus(); };
const closeModal = () => { modal.classList.remove('open'); document.body.classList.remove('modal-open'); };
document.querySelectorAll('.exhibit').forEach(exhibit => exhibit.querySelector('.open').addEventListener('click', () => openModal(exhibit)));
document.getElementById('closeModal').addEventListener('click', closeModal);
modal.addEventListener('click', event => { if (event.target === modal) closeModal(); });
addEventListener('keydown', event => { if (event.key === 'Escape') closeModal(); });
</script>
</body>
</html>