Something went wrong. Try again.
Monorepo for Aesthetic.Computer aesthetic.computer
Something went wrong. Try again.
8.2 kB · 301 lines
HTML
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="Content-Security-Policy" content="default-src 'self' 'unsafe-inline' https://cdnjs.cloudflare.com https://cdn.jsdelivr.net; connect-src ws://127.0.0.1:7890 ws://localhost:5556 wss://localhost:8889;"> <title>Process Tree - Dev</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; } :root { --header-height: 40px; --status-height: 28px; --z-canvas: 1; --z-labels: 50; --z-ui: 100; --z-overlay: 500; } body { background: #181318; color: #fff; font-family: monospace; overflow: hidden; height: 100vh; } body[data-theme="light"] { background: #fcf7c5; color: #281e5a; } /* ====== 3D CANVAS (layer 1) ====== */ #canvas { position: fixed; top: 0; left: 0; width: 100%; height: 100%; z-index: var(--z-canvas); } /* ====== LABELS (layer 50) ====== */ #labels { position: fixed; top: var(--header-height); left: 0; right: 0; bottom: var(--status-height); pointer-events: none; z-index: var(--z-labels); overflow: hidden; } /* ====== UI LAYER (layer 100) ====== */ /* HEADER: fixed height strip at top */ #header { position: fixed; top: 0; left: 0; right: 0; height: var(--header-height); display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; padding: 0 12px; z-index: var(--z-ui); pointer-events: none; font-size: 11px; } #header-left { display: flex; align-items: center; gap: 8px; justify-self: start; } #header-center { display: flex; align-items: center; gap: 12px; justify-self: center; color: #666; } body[data-theme="light"] #header-center { color: #806060; } #header-center .val { color: #fff; } body[data-theme="light"] #header-center .val { color: #281e5a; } #header-right { display: flex; align-items: center; gap: 6px; justify-self: end; pointer-events: auto; } .status-dot { width: 6px; height: 6px; border-radius: 50%; background: #ff69b4; } .status-dot.online { background: #0f0; } body[data-theme="light"] .status-dot { background: #387adf; } body[data-theme="light"] .status-dot.online { background: #006400; } .title { font-size: 12px; white-space: nowrap; } .title .dot { color: #ff69b4; } body[data-theme="light"] .title .dot { color: #006400; } .hdr-btn { background: rgba(255,255,255,0.08); border: 1px solid rgba(255,255,255,0.12); color: #aaa; padding: 4px 8px; border-radius: 3px; font-size: 10px; font-family: monospace; cursor: pointer; } body[data-theme="light"] .hdr-btn { background: rgba(0,0,0,0.06); border-color: rgba(0,0,0,0.1); color: #666; } .hdr-btn:hover { border-color: #ff69b4; color: #fff; } body[data-theme="light"] .hdr-btn:hover { border-color: #006400; color: #281e5a; } /* STATUS BAR: fixed height strip at bottom */ #status { position: fixed; bottom: 0; left: 0; right: 0; height: var(--status-height); display: flex; align-items: center; justify-content: space-between; padding: 0 12px; z-index: var(--z-ui); pointer-events: none; font-size: 10px; color: #555; } body[data-theme="light"] #status { color: #806060; } #status-left { display: flex; align-items: center; gap: 12px; } #status-right { display: flex; align-items: center; gap: 12px; } .badge { background: #ff69b4; color: #000; padding: 2px 6px; border-radius: 2px; font-size: 8px; font-weight: bold; text-transform: uppercase; } body[data-theme="light"] .badge { background: #006400; color: #fff; } /* CENTER DISPLAY: absolutely centered, above status bar */ #center-display { position: fixed; bottom: calc(var(--status-height) + 16px); left: 50%; transform: translateX(-50%); text-align: center; z-index: var(--z-ui); pointer-events: none; padding: 10px 16px; background: rgba(0,0,0,0.6); border-radius: 8px; border: 1px solid rgba(255,255,255,0.06); } body[data-theme="light"] #center-display { background: rgba(252,247,197,0.8); border-color: rgba(0,0,0,0.08); } #process-count { font-size: 28px; font-weight: bold; line-height: 1; } #center-display .label { font-size: 9px; color: #666; text-transform: uppercase; letter-spacing: 1px; margin-top: 2px; } body[data-theme="light"] #center-display .label { color: #806060; } /* PROC LABELS */ .proc-label { position: absolute; text-align: center; transform: translate(-50%, -100%); white-space: nowrap; pointer-events: none; padding: 2px 4px; border-radius: 3px; background: rgba(0,0,0,0.4); text-shadow: 0 1px 2px #000; } body[data-theme="light"] .proc-label { background: rgba(252,247,197,0.6); text-shadow: none; } .proc-label .icon { font-size: 14px; line-height: 1.2; } .proc-label .name { font-size: 9px; font-weight: bold; margin-top: 1px; } .proc-label .info { font-size: 7px; color: #888; margin-top: 1px; } body[data-theme="light"] .proc-label .info { color: #806060; } </style></head><body data-theme="dark"> <script> const urlTheme = new URLSearchParams(window.location.search).get('theme'); if (urlTheme === 'light' || urlTheme === 'dark') document.body.dataset.theme = urlTheme; </script> <canvas id="canvas"></canvas> <!-- HEADER (top 40px) --> <div id="header"> <div id="header-left"> <div class="status-dot" id="status-dot"></div> <span class="title">Aesthetic<span class="dot">.</span>Computer</span> </div> <div id="header-center"> <span><span class="val" id="uptime">—</span></span> <span><span class="val" id="cpus">—</span> cpus</span> </div> <div id="header-right"> </div> </div> <!-- STATUS BAR (bottom 28px) --> <div id="status"> <div id="status-left"> <span class="badge">DEV</span> <span id="reload-status">● connecting</span> </div> <div id="status-right"> <span><span id="mem-text">— / —</span> MB</span> </div> </div> <!-- CENTER DISPLAY --> <div id="center-display"> <div id="process-count">0</div> <div class="label">processes</div> </div> <!-- LABELS CONTAINER (between header and status) --> <div id="labels"></div> <script src="process-tree-2d.js"></script> <script src="ast-tree.js"></script> <script> // VS Code message handler window.addEventListener('message', (event) => { if (event.data.command === 'astUpdate' && window.ASTTreeViz) { window.ASTTreeViz.updateASTVisualization(event.data.files); } }); // Live reload (function() { const el = document.getElementById('reload-status'); function connect() { try { const ws = new WebSocket('ws://localhost:5556'); ws.onopen = () => { el.textContent = '● live'; el.style.color = '#ff69b4'; }; ws.onmessage = (e) => { const msg = JSON.parse(e.data); if (msg.type === 'reload') location.reload(); }; ws.onclose = () => { el.textContent = '○ offline'; el.style.color = '#555'; setTimeout(connect, 3000); }; ws.onerror = () => ws.close(); } catch { el.textContent = '○ offline'; el.style.color = '#555'; setTimeout(connect, 3000); } } connect(); })(); </script></body></html>