fractal-drift-through-stati.../exploration.html

73 lines
No EOL
16 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Fractal Drift Through Static — exploration</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { background: #0a0a0f; color: #3a3a4a; font-family: ui-monospace, monospace; overflow: hidden; }
#grid { padding: 20px; font-size: 12px; line-height: 1.4; white-space: pre; }
.c { display: inline-block; transition: all 0.3s; }
.c.active { color: #fde68a; text-shadow: 0 0 6px rgba(253,230,138,0.5); }
.c.strong { color: #34d399; text-shadow: 0 0 10px rgba(52,211,153,0.6); font-weight: bold; }
.c.dead { color: #1a1a2a; }
#info { position: fixed; bottom: 10px; left: 20px; color: #3a3a4a; font-size: 11px; }
#controls { position: fixed; top: 10px; right: 20px; color: #666; font-size: 11px; }
#controls span { cursor: pointer; margin-left: 12px; color: #fde68a; }
</style>
</head>
<body>
<div id="grid"></div>
<div id="info">neurameba · physarum exploration</div>
<div id="controls"><span id="play-btn">play</span><span id="reset-btn">reset</span></div>
<script>
const text = "# Command Reference\n\nEverything in motd happens through commands. Type them in the input bar at the bottom of the terminal.\n\n---\n\n## Shell\n\n### /help\nShow all available commands grouped by category.\n```\n> /help\n```\n\n### /menu\nToggle the sidebar. Shows motd branding, commands, doc links, and footer. Click any command to run it.\n```\n> /menu\n```\n\n### /clear\nClear the terminal output.\n```\n> /clear\n```\n\n### /terminal --width [value]\nSet the terminal width. Accepts px, %, or `reset`.\n```\n> /terminal --width 1000\n Terminal width set to 1000px.\n\n> /terminal --width 80%\n Terminal width set to 80%.\n\n> /terminal --width reset\n Terminal width reset to default (800px).\n```\n\nWidth is stored in localStorage and restored on next visit. On mobile, the terminal is always 100% width.\n\n### /close\nClose the left panel.\n```\n> /close\n```\n\n### /settings cli [position]\nMove the terminal input line. Positions: bottom (default), top, right, left, middle.\n```\n> /settings cli top\n CLI position set to top.\n\n> /settings cli\n CLI position: top\n```\n\nPosition persists across sessions. On mobile, always bottom.\n\n### /config export\nDownload your current config as a JSON file.\n```\n> /config export\n Config downloaded.\n```\n\n### /config import\nLoad config from a JSON file. Opens a file picker.\n```\n> /config import\n [file picker opens]\n Config imported.\n```\n\n### /config reset\nReset all client-side config overrides to server defaults.\n```\n> /config reset\n Config reset to defaults.\n```\n\nThe config system merges localStorage overrides with server defaults. Export/import lets you back up or transfer your settings.\n\n### /read [path]\nRead a documentation file. Renders markdown inline in the terminal.\n```\n> /read about\n> /read api\n> /read commands\n```\n\nWithout arguments, lists all available docs.\n```\n> /read\n```\n\n### /tree -cat\nBrowse categories and their tags. Click a tag to search for posts with it.\n```\n> /tree -cat\n\n coding/\n [rust] [python] [wasm] [js] [frontend] [backend]\n creative/\n [music] [art] [writing] [gamedev]\n meta/\n [motd] [bugs] [ideas] [feedback]\n general/\n [offtopic] [introductions] [showcase]\n```\n\n### /link [target]\nUniversal navigation. Resolves the target and takes you there.\n```\n> /link @alice → opens alice's profile\n> /link rust → searches for [rust] posts\n> /link a3kf9x → shows a specific post\n> /link docs/api → reads the API doc\n```\n\nResolution order: user > tag > post > doc.\n\n---\n\n## Auth\n\n### /register\nCreate an account. Interactive prompts for username and password.\n```\n> /register\n username: alice\n password: ********\n Registered as alice.\n```\n- Username: 3-20 characters, letters/numbers/underscore\n- Password: minimum 8 characters\n\n### /login\nLog in. Session lasts until you close the tab.\n```\n> /login\n username: alice\n password: ********\n Logged in as alice.\n```\n\n### /login-permanently\nLog in with a persistent session. Survives tab closes and browser restarts.\n```\n> /login-permanently\n username: alice\n password: ********\n Logged in as alice (persistent).\n```\n\n### /logout\nEnd your session.\n```\n> /logout\n Logged out.\n```\n\n---\n\n## Profile\n\n### /profile\nView your own profile.\n```\n> /profile\n\n ████ ████\n ████████\n ████████████\n ████████\n ██ ████ ██\n\n @alice (Alice)\n building things\n Posts: 42\n Joined: 2026-03-15\n```\n\n### /profile @user\nView another user's profile.\n```\n> /profile @bob\n```\n\n### /settings\nEdit your display name and bio. Interactive prompts.\n```\n> /settings\n display_name (Alice): Alice W.\n bio (building things): shipping code\n Settings updated.\n```\n\n---\n\n## Posts\n\n### /post [text]\nPublish a post. Max 500 characters. Tags use [brackets].\n```\n> /post just shipped the wasm compiler [rust] [wasm]\n\n @alice · just shipped the wasm compiler [rust] [wasm]\n a3kf9x · just now\n```\n\n### /post [text] /attach [media_id]\nPublish a post with media attached. Upload first with `/upload`, then attach the returned ID.\n```\n> /post screenshot of the new UI /attach x7km2p [showcase]\n```\n\n### /feed\nShow recent posts. Chronological. Filtered by your kill list.\n```\n> /feed\n\n @alice · just shipped the wasm compiler [rust] [wasm]\n a3kf9x · 2m ago\n\n @bob · working on a new side project [coding]\n c9xk4m · 15m ago\n```\n\n### /reply [post_id] [text]\nReply to a post.\n```\n> /reply a3kf9x nice work! what was the hardest part?\n```\n\n### /thread [post_id]\nView a post and its replies.\n```\n> /thread a3kf9x\n```\n\n### /goto [post_id]\nJump to a specific post.\n```\n> /goto a3kf9x\n```\n\n---\n\n## Discovery\n\n### /find [query]\nSearch users and posts.\n```\n> /find rust\n> /find @alice\n> /find [wasm]\n```\n\nBrackets optional — `/find rust` and `/find [rust]` both work.\n\n### /find --archive [query]\nSearch archived posts (30-120 days old).\n```\n> /find --archive old project\n```\n\n### /tree -cat\nBrowse the category tree. See the Shell section above.\n\n### /link [target]\nUniversal navigation. See the Shell section above.\n\n---\n\n## Media\n\n### /upload\nUpload a file. Opens a file picker. Accepted: PNG (max 5MB), MP3 (max 10MB), MP4 (max 25MB).\n```\n> /upload\n [file picker opens]\n Uploaded: x7km2p (png)\n```\n\nPNG images are processed into: original (max 1MB), thumbnail (80px), large (800px), ASCII art.\n\n### /attach [media_id]\nAttach media to a post. Used inline with `/post`:\n```\n> /post check this out /attach x7km2p\n```\n\n### /view [media_id]\nView the original media file.\n```\n> /view x7km2p\n```\n\n### /play [media_id]\nPlay audio or video.\n```\n> /play x7km2p\n```\n\n### /pause\nPause current playback.\n```\n> /pause\n```\n\n### /expand [media|nada|id]\nExpand or collapse media inline in the terminal.\n```\n> /expand media expand all media in view\n> /expand same as /expand media\n> /expand a3kf9x expand media from a specific post\n> /expand nada collapse all inline media, stop playback\n```\n\n### /rmedia [media_id]\nDelete a media file you uploaded. Removes from disk, clears from posts and avatar.\n```\n> /rmedia x7km2p\n Media deleted.\n```\n\n---\n\n## Moderation\n\n### /kill @user\nHide a user from your feed. They won't know. Their posts disappear from your view.\n```\n> /kill @spammer\n Process @spammer terminated.\n```\n\n### /kill [post_id]\nHide a specific post.\n```\n> /kill b7xm2k\n Process b7xm2k terminated.\n```\n\nKills are private. The `/kill` command maps to the filter system internally the word \"kill\" never touches the database.\n\nWhen enough users filter the same person, their posts get silently suppressed from everyone's feed. No ban. No notification. They just fade out.\n\n---\n\n## Bookmarks\n\n### /bookmark [target]\nBookmark a user, tag, post, or doc. Bookmarks are private — nobody sees them.\n```\n> /bookmark @alice\n Bookmarked @alice.\n\n> /bookmark rust\n Bookmarked [rust].\n\n> /bookmark a3kf9x\n Bookmarked post a3kf9x.\n\n> /bookmark docs/api\n Bookmarked doc api.\n```\n\nThe system auto-detects what you're bookmarking:\n- Starts with `@` — user\n- Matches a known tag — tag\n- Matches a post ID (6-8 alphanumeric) — post\n- Matches a doc path — doc\n\n### /unbookmark [target]\nRemove a bookmark.\n```\n> /unbookmark @alice\n Unbookmarked @alice.\n```\n\n### /bookmarks\nView all your bookmarks, grouped by type.\n```\n> /bookmarks\n\n users/\n [@alice] [@bob]\n\n tags/\n [rust] [wasm] [frontend]\n\n posts/\n [a3kf9x] @alice · \"just shipped the wasm compiler...\"\n [b7xm2k] @carol · \"demo of the new feature...\"\n\n docs/\n [api] [plugins]\n```\n\n### /bookmarks --users\nShow only bookmarked users.\n```\n> /bookmarks --users\n```\n\nSame for `--tags`, `--posts`, `--docs`.\n\n---\n\n## Account\n\n### /terminate-account\nPermanently delete your account. All posts, media, sessions, and data are wiped. Irreversible.\n```\n> /terminate-account\n Type your username to confirm: alice\n Account terminated.\n```\n\n---\n\n## Telegram\n\n### /connect telegram\nLink your Telegram account. Generates a one-time deep link.\n```\n> /connect telegram\n\nConnect Telegram:\n\n https://t.me/motdsocial_bot?start=alice_a8f3k2\n\n Click the link. Tap Start in Telegram. Done.\n```\n\nClick the link, tap Start in Telegram. Done. The link expires after 10 minutes.\n\n### /disconnect telegram\nUnlink your Telegram account.\n```\n> /disconnect telegram\n ✓ Telegram disconnected.\n```\n\nSee `/read telegram` for full details on the Telegram bridge.\n\n---\n\n## Email\n\n### /connect email\nLink your email address. Sends a verification email.\n```\n> /connect email\n\n Enter your email address: you@gmail.com\n\n Verification email sent to you@gmail.com\n Click the link in the email to confirm.\n```\n\n### /disconnect email\nUnlink your email address.\n```\n> /disconnect email\n ✓ Email disconnected.\n```\n\nSee `/read email` for full details on the email bridge.\n\n---\n\n## Right-Click Context Menu\n\nRight-clicking interactive elements (usernames, tags, posts, doc links, media) shows a terminal-styled context menu with relevant actions. Each menu item writes the corresponding command into the input and executes it.\n\nRight-clicking empty space shows the normal browser menu.\n";
const passes = [{"t":0,"r":316,"c":7,"a":"hold","s":0.15695500514114294,"ps":9,"e":99.90564004112915,"pr":1.1},{"t":0,"r":285,"c":69,"a":"extend","s":0.30809761159341226,"ps":9,"e":70.78034662492311,"pr":1.1},{"t":0,"r":393,"c":4,"a":"hold","s":0.1639470305239032,"ps":9,"e":99.96157624419122,"pr":1.1},{"t":0,"r":16,"c":1,"a":"extend","s":0.3434941901040408,"ps":9,"e":70.97856746458262,"pr":1.1},{"t":0,"r":356,"c":4,"a":"hold","s":0.12304258594501032,"ps":9,"e":99.63434068756008,"pr":1.1},{"t":1,"r":316,"c":7,"a":"hold","s":0.16343051095050176,"ps":8,"e":100.01308412873315,"pr":1.05},{"t":1,"r":285,"c":69,"a":"hold","s":0.2999667714434493,"ps":8,"e":71.9800807964707,"pr":1.05},{"t":1,"r":393,"c":4,"a":"hold","s":0.17487376434730637,"ps":8,"e":100.16056635896967,"pr":1.05},{"t":1,"r":16,"c":1,"a":"extend","s":0.37596963636734954,"ps":9,"e":50.845427188864996,"pr":1.1},{"t":1,"r":356,"c":4,"a":"hold","s":0.1590145683689509,"ps":9,"e":99.5564572345117,"pr":1.1},{"t":1,"r":16,"c":2,"a":"extend","s":0.36229770354582275,"ps":5,"e":22.797437379231393,"pr":1.2000000000000002},{"t":1,"r":15,"c":1,"a":"hold","s":0.223509541799257,"ps":5,"e":31.457462390643755,"pr":1.2000000000000002},{"t":2,"r":316,"c":7,"a":"retracted","s":0.15695500514114294,"ps":7,"e":100.2187241698623,"pr":1},{"t":2,"r":285,"c":69,"a":"hold","s":0.30809761159341226,"ps":7,"e":73.394861689218,"pr":1},{"t":2,"r":393,"c":4,"a":"retracted","s":0.1639470305239032,"ps":7,"e":100.4221426031609,"pr":1},{"t":2,"r":16,"c":1,"a":"extend","s":0.37596963636734954,"ps":8,"e":36.85722899586265,"pr":1.05},{"t":2,"r":356,"c":4,"a":"retracted","s":0.15709024499045207,"ps":8,"e":99.61317919443532,"pr":1.05},{"t":2,"r":16,"c":2,"a":"hold","s":0.2363487969192705,"ps":5,"e":23.938227754585558,"pr":1.2000000000000002},{"t":2,"r":15,"c":1,"a":"hold","s":0.19190678917339965,"ps":5,"e":32.242716704030954,"pr":1.2000000000000002},{"t":2,"r":17,"c":1,"a":"hold","s":0.34912852672756667,"ps":5,"e":23.83392558047696,"pr":1.2000000000000002},{"t":2,"r":15,"c":2,"a":"hold","s":0.061715900074679746,"ps":5,"e":9.51405750598232,"pr":1.3000000000000003},{"t":3,"r":285,"c":69,"a":"retracted","s":0.30947893761440404,"ps":6,"e":74.97069319013323,"pr":0.95},{"t":3,"r":16,"c":1,"a":"hold","s":0.3434941901040408,"ps":8,"e":38.40518251669498,"pr":1.05},{"t":3,"r":16,"c":2,"a":"hold","s":0.2363487969192705,"ps":4,"e":25.22901812993972,"pr":1.1500000000000001},{"t":3,"r":15,"c":1,"a":"retracted","s":0.19190678917339965,"ps":4,"e":33.17797101741815,"pr":1.1500000000000001},{"t":3,"r":17,"c":1,"a":"hold","s":0.3346772661569516,"ps":4,"e":25.911343709732574,"pr":1.1500000000000001},{"t":3,"r":15,"c":2,"a":"hold","s":0.09339129654980961,"ps":5,"e":9.511187878380797,"pr":1.3000000000000003},{"t":3,"r":16,"c":0,"a":"hold","s":0.18748914649167336,"ps":5,"e":16.545868455874523,"pr":1.1500000000000001},{"t":4,"r":16,"c":1,"a":"hold","s":0.3434941901040408,"ps":7,"e":40.10313603752731,"pr":1},{"t":4,"r":16,"c":2,"a":"retracted","s":0.36229770354582275,"ps":4,"e":27.527399758306302,"pr":1.1500000000000001},{"t":4,"r":17,"c":1,"a":"retracted","s":0.34912852672756667,"ps":4,"e":28.104371923553106,"pr":1.1},{"t":4,"r":15,"c":2,"a":"retracted","s":0.09266546073471935,"ps":4,"e":9.652511564258552,"pr":1.2500000000000002},{"t":4,"r":16,"c":0,"a":"hold","s":0.20701218821321257,"ps":5,"e":17.451965961580225,"pr":1.1500000000000001},{"t":5,"r":16,"c":1,"a":"retracted","s":0.32695910626811864,"ps":7,"e":41.668808887672256,"pr":1},{"t":5,"r":16,"c":0,"a":"retracted","s":0.20701218821321257,"ps":4,"e":18.508063467285925,"pr":1.1}];
const lines = text.split('\n');
const gridEl = document.getElementById('grid');
const charEls = [];
for (let r = 0; r < lines.length; r++) {
const row = [];
for (let c = 0; c < lines[r].length; c++) {
const s = document.createElement('span');
s.className = 'c';
s.textContent = lines[r][c];
row.push(s);
gridEl.appendChild(s);
}
charEls.push(row);
gridEl.appendChild(document.createTextNode('\n'));
}
let tick = -1, playing = false, iv;
function apply(t) {
for (const r of charEls) for (const e of r) e.className = 'c';
const active = new Map();
for (const p of passes) {
if (p.t > t) break;
const k = p.r+','+p.c;
if (p.a === 'died' || p.a === 'retracted') active.set(k, 'dead');
else if (p.ps > 16) active.set(k, 'strong');
else active.set(k, 'active');
}
for (const [k, cls] of active) {
const [r, c] = k.split(',').map(Number);
if (charEls[r]?.[c]) charEls[r][c].className = 'c ' + cls;
}
document.getElementById('info').textContent = 'tick ' + t + ' · ' + [...active.values()].filter(v=>v!=='dead').length + ' alive';
}
function play() {
if (playing) return;
playing = true;
document.getElementById('play-btn').textContent = 'pause';
const max = passes.length > 0 ? passes[passes.length-1].t : 0;
iv = setInterval(() => { tick++; if (tick > max) { pause(); return; } apply(tick); }, 900);
}
function pause() { playing = false; clearInterval(iv); document.getElementById('play-btn').textContent = 'play'; }
function reset() { pause(); tick = -1; for (const r of charEls) for (const e of r) e.className = 'c'; document.getElementById('info').textContent = 'neurameba'; }
document.getElementById('play-btn').addEventListener('click', () => playing ? pause() : play());
document.getElementById('reset-btn').addEventListener('click', reset);
setTimeout(play, 1000);
</script>
</body>
</html>