fractal-bloom-in-monochrome.../exploration.html

73 lines
54 KiB
HTML
Raw Normal View History

2026-03-25 19:31:30 +00:00
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Fractal Bloom in Monochrome — 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 = "# Terms of Service\n\nLast updated: 2026-03-22\n\nThese are the rules. Written for humans, not lawyers.\n\n## Age\n\nYou must be at least 16 years old to use motd.\n\n## Your Content\n\nYou own what you post. motd doesn't claim ownership of your content. We don't sell it, mine it, or train models on it.\n\n## What We'll Remove\n\nContent that violates basic decency:\n- Hate speech\n- Harassment or targeted abuse\n- Illegal content\n- Spam or coordinated manipulation\n\nIf you see it, `/kill` it. If enough people kill it, it fades from everyone's view automatically. Admins can also remove content and terminate accounts for terms violations.\n\n## Accounts\n\n- You can delete your account at any time with `/terminate-account`. This is immediate and irreversible. All your posts, media, and data are wiped.\n- Admins can terminate accounts that violate these terms.\n- One account per person. Alts for abuse evasion will be terminated.\n\n## Data Lifecycle\n\nPosts are ephemeral by design:\n- **Active:** visible in the feed for 30 days\n- **Archived:** searchable for 90 more days\n- **Purged:** permanently deleted after 120 days total\n\nThis is not a permanent record. It's a conversation.\n\n## Privacy\n\nWhat we store:\n- Username and display name\n- Password (hashed, never stored in plain text)\n- Posts and media you upload\n- Your preferences and settings\n- Session tokens\n\nWhat we don't do:\n- No tracking\n- No ads\n- No data sales\n- No third-party analytics\n- No cookies beyond the session token\n\nYour kill list (filters) is private and never shared with anyone — not other users, not admins viewing your profile.\n\n## Your Rights (EU)\n\nmotd operates from Finland under EU data protection law.\n\n- You can request a copy of all data we store about you.\n- You can delete all your data at any time with `/terminate-account`.\n- We don't transfer your data outside the EU.\n- Our servers are in Helsinki, Finland (Hetzner).\n- Contact: hello@motd.social\n\n## The Service\n\nmotd is provided as-is. No guarantees on uptime, availability, or data preservation beyond the stated lifecycle. We run it because we want it to exist. We'll do our best to keep it running.\n\n## Changes\n\nThese terms may be updated. Continued use means you accept the current terms. Major changes will be announced via a post from @motd.\n\n## Questions\n\nPost with an @motd mention or email hello@motd.social.\n";
const passes = [{"t":0,"r":7,"c":0,"a":"died","s":0,"ps":8,"e":100,"pr":1},{"t":0,"r":39,"c":7,"a":"hold","s":0.28637017074920745,"ps":9,"e":100.94096136599366,"pr":1.1},{"t":0,"r":55,"c":62,"a":"hold","s":0.2641185257539532,"ps":9,"e":100.76294820603162,"pr":1.1},{"t":0,"r":46,"c":11,"a":"extend","s":0.4175645397932876,"ps":9,"e":71.3933614228424,"pr":1.1},{"t":0,"r":50,"c":7,"a":"hold","s":0.2945285771582814,"ps":9,"e":101.00622861726625,"pr":1.1},{"t":1,"r":39,"c":7,"a":"hold","s":0.2815412076339615,"ps":8,"e":101.99329102706535,"pr":1.05},{"t":1,"r":55,"c":62,"a":"hold","s":0.21403927579520532,"ps":9,"e":101.12526241239327,"pr":1.1},{"t":1,"r":46,"c":11,"a":"extend","s":0.4437412024747522,"ps":9,"e":51.51530372984829,"pr":1.1},{"t":1,"r":50,"c":7,"a":"hold","s":0.30835192183410165,"ps":9,"e":102.12304399193906,"pr":1.1},{"t":1,"r":45,"c":11,"a":"hold","s":0.20001520766385203,"ps":5,"e":31.447276556814703,"pr":1.2000000000000002},{"t":2,"r":39,"c":7,"a":"retracted","s":0.27448648934644815,"ps":7,"e":103.13918294183694,"pr":1},{"t":2,"r":55,"c":62,"a":"retracted","s":0.21403927579520532,"ps":8,"e":101.6375766187549,"pr":1.05},{"t":2,"r":46,"c":11,"a":"extend","s":0.4316232249252057,"ps":8,"e":37.637802670474954,"pr":1.05},{"t":2,"r":50,"c":7,"a":"retracted","s":0.3025444391962833,"ps":8,"e":103.34339950550932,"pr":1.05},{"t":2,"r":45,"c":11,"a":"hold","s":0.30493648215449254,"ps":5,"e":33.13676841405064,"pr":1.2000000000000002},{"t":3,"r":46,"c":11,"a":"extend","s":0.38517166244300016,"ps":8,"e":27.663423179013268,"pr":1.05},{"t":3,"r":45,"c":11,"a":"retracted","s":0.29928953818532755,"ps":4,"e":34.93108471953326,"pr":1.1500000000000001},{"t":3,"r":46,"c":12,"a":"hold","s":0.27209511745353965,"ps":5,"e":17.5572477984033,"pr":1.1500000000000001},{"t":3,"r":46,"c":10,"a":"hold","s":0.2985828113310641,"ps":5,"e":17.769149349423497,"pr":1.1500000000000001},{"t":4,"r":46,"c":11,"a":"hold","s":0.37552162076483453,"ps":7,"e":29.617596145131944,"pr":1},{"t":4,"r":46,"c":12,"a":"extend","s":0.396791395315243,"ps":6,"e":13.882105272647669,"pr":1.2500000000000002},{"t":4,"r":46,"c":10,"a":"hold","s":0.260007756211626,"ps":4,"e":19.249211399116504,"pr":1.1},{"t":5,"r":46,"c":11,"a":"hold","s":0.3972197688835074,"ps":7,"e":31.745354296200006,"pr":1},{"t":5,"r":46,"c":12,"a":"hold","s":0.3810575512371051,"ps":5,"e":16.18056568254451,"pr":1.2000000000000002},{"t":5,"r":46,"c":10,"a":"retracted","s":0.28857567880866947,"ps":4,"e":20.95781682958586,"pr":1.05},{"t":5,"r":45,"c":12,"a":"extend","s":0.40759266140731604,"ps":5,"e":5.92215048567527,"pr":1.3500000000000003},{"t":6,"r":46,"c":11,"a":"retracted","s":0.38642232378601354,"ps":6,"e":33.936732886488116,"pr":0.95},{"t":6,"r":46,"c":12,"a":"hold","s":0.377965421856863,"ps":4,"e":18.604289057399416,"pr":1.1500000000000001},{"t":6,"r":45,"c":12,"a":"extend","s":0.4333613500814993,"ps":4,"e":6.152328900429085,"pr":1.3000000000000003},{"t":6,"r":44,"c":12,"a":"hold","s":0.2655071110055332,"ps":5,"e":3.912121381905096,"pr":1.4500000000000004},{"t":6,"r":45,"c":13,"a":"hold","s":0.21305622173554378,"ps":5,"e":3.4925142677451806,"pr":1.4500000000000004},{"t":7,"r":46,"c":12,"a":"retracted","s":0.24878348549740872,"ps":5,"e":19.844556941378688,"pr":1.2500000000000002},{"t":7,"r":45,"c":12,"a":"extend","s":0.38702666038748296,"ps":4,"e":6.053979528470264,"pr":1.2500000000000002},{"t":7,"r":44,"c":12,"a":"hold","s":0.34105764879968836,"ps":5,"e":5.890582572302603,"pr":1.4500000000000004},{"t":7,"r":45,"c":13,"a":"hold","s":0.18665141114583753,"ps":4,"e":4.385725556911881,"pr":1.4000000000000004},{"t":8,"r":45,"c":12,"a":"extend","s":0.3775617067949078,"ps":4,"e":5.932131227980669,"pr":1.2000000000000002},{"t":8,"r":44,"c":12,"a":"retracted","s":0.3339654478238969,"ps":4,"e":7.962306154893778,"pr":1.4000000000000004},{"t":8,"r":45,"c":13,"a":"retracted","s":0.20794660985190988,"ps":4,"e":5.44929843572716,"pr":1.3500000000000003},{"t":8,"r":45,"c":11,"a":"hold","s":0.1640940459523742,"ps":5,"e":3.1573150226776785,"pr":1.3500000000000003},{"t":9,"r":45,"c":12,"a":"extend","s":0.3683282239398263
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>