Spaces:
Running
Running
File size: 7,824 Bytes
d511c9b 5abca18 d511c9b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 | <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Holographic Estate — a11oy</title>
<!-- 0 runtime CDN. All 3D libs vendored in-image and served same-origin via the
/static/3d/vendor/... importmap below (see VENDOR_MANIFEST.md). System fonts only. -->
<script type="importmap">
{
"imports": {
"three": "/static/3d/vendor/three/three.module.min.js",
"three/webgpu": "/static/3d/vendor/three/three.webgpu.min.js",
"three/addons/": "/static/3d/vendor/three/addons/"
}
}
</script>
<style>
:root{--bg:#05070d;--panel:#0b121b;--line:#1b2734;--teal:#39d3c4;--gold:#e8c074;--cream:#eef3f6;--para:#9fb1bf;}
*{box-sizing:border-box}
html,body{margin:0;height:100%}
body{background:var(--bg);color:var(--cream);font:14px/1.5 ui-sans-serif,system-ui,Segoe UI,Roboto,Arial;overflow:hidden}
header{padding:10px 16px;border-bottom:1px solid var(--line);background:linear-gradient(180deg,#08101a,#05070d);
display:flex;align-items:center;gap:14px;flex-wrap:wrap}
h1{font-size:16px;margin:0;letter-spacing:.4px}
.badge{display:inline-block;font:10.5px ui-monospace,monospace;padding:2px 7px;border-radius:6px;
border:1px solid var(--line);color:var(--gold);background:#10171f}
#backend{color:var(--teal)}
.tabs{display:flex;gap:6px;flex-wrap:wrap;padding:8px 12px;border-bottom:1px solid var(--line);background:#070d15}
.tab{font:11.5px ui-monospace,monospace;padding:6px 12px;border-radius:7px;border:1px solid var(--line);
background:#0a121b;color:var(--para);cursor:pointer;letter-spacing:.3px;transition:.12s}
.tab:hover{border-color:var(--teal);color:var(--cream)}
.tab[aria-selected="true"]{background:#12202b;color:var(--cream);border-color:var(--teal);box-shadow:0 0 0 1px var(--teal) inset}
#stage-wrap{position:relative;width:100vw;height:calc(100vh - 96px)}
#stage{position:absolute;inset:0}
#stage canvas{display:block;width:100%;height:100%}
#fallback{position:absolute;inset:0;display:none;align-items:center;justify-content:center;
text-align:center;color:var(--para);padding:24px;font:13px ui-monospace,monospace}
footer{position:fixed;bottom:0;left:0;right:0;padding:6px 14px;border-top:1px solid var(--line);
background:#070d15;color:var(--para);font:10.5px ui-monospace,monospace;letter-spacing:.3px;z-index:6}
a{color:var(--teal);text-decoration:none}
</style>
</head>
<body>
<header>
<h1>◇ Holographic Estate</h1>
<span class="badge" id="backend">renderer: …</span>
<span class="badge">three r<span id="three-rev">…</span></span>
<span class="badge">0 runtime CDN</span>
<span class="badge">Λ = Conjecture 1</span>
<a href="/" style="margin-left:auto;font:11px ui-monospace,monospace">← a11oy</a>
</header>
<div class="tabs" id="tabs" role="tablist"></div>
<div id="stage-wrap">
<div id="stage"></div>
<div id="fallback">3D unavailable on this device — the holographic estate needs a WebGL2 or WebGPU canvas.<br>
All underlying data is still available as JSON at the per-surface endpoints.</div>
</div>
<footer>Doctrine v11 · locked = 8 @ c7c0ba17 · Λ = Conjecture 1 · Khipu BFT = Conjecture 2 ·
shared szl3d toolkit (Dev0) · every value carries its honesty label · trust < 100%</footer>
<script type="module">
import szl3d from "/static/3d/szl3d/szl3d_boot.js";
import * as live from "/static/3d/szl3d/szl3d_live.js";
import * as label from "/static/3d/szl3d/szl3d_label.js";
import * as THREE from "three";
// The 9 surface slots the other devs fill. Lazy-loaded per tab.
const SURFACES = [
{ id: "energy", title: "Energy", mod: "/static/3d/surfaces/energy.js" },
{ id: "fabric", title: "Fabric", mod: "/static/3d/surfaces/fabric.js" },
{ id: "pnt", title: "PNT", mod: "/static/3d/surfaces/pnt.js" },
{ id: "counter-uas", title: "Counter-UAS", mod: "/static/3d/surfaces/counter-uas.js" },
{ id: "governance", title: "Governance", mod: "/static/3d/surfaces/governance.js" },
{ id: "pinn", title: "PINN", mod: "/static/3d/surfaces/pinn.js" },
{ id: "router", title: "Router", mod: "/static/3d/surfaces/router.js" },
{ id: "anatomy", title: "Anatomy", mod: "/static/3d/surfaces/anatomy.js" },
{ id: "estate", title: "Estate", mod: "/static/3d/surfaces/estate.js" },
];
const stageEl = document.getElementById("stage");
const tabsEl = document.getElementById("tabs");
const fallbackEl = document.getElementById("fallback");
document.getElementById("three-rev").textContent = THREE.REVISION;
let stage = null;
let current = null; // { def, instance }
let loadToken = 0;
async function ensureStage() {
if (stage) return stage;
try {
// Default to the proven WebGL2 path (matches /estate-hologram). WebGPU is not
// production-safe across all browsers/drivers yet (doctrine) and the bloom pass
// is WebGL2-only, so the shell stays on WebGL2 unless explicitly opted in with
// ?webgpu=1. The toolkit's WebGPU probe is timeout-guarded either way.
const wantWebGPU = /[?&]webgpu=1\b/.test(location.search);
stage = await szl3d.boot(stageEl, {
bloom: { strength: 0.85, radius: 0.5, threshold: 0.18 },
cameraPos: [0, 5, 16],
forceWebGL: !wantWebGPU,
});
document.getElementById("backend").textContent = "renderer: " + stage.backend.toUpperCase();
stage.start();
} catch (e) {
fallbackEl.style.display = "flex";
document.getElementById("backend").textContent = "renderer: UNAVAILABLE";
console.error("[holographic] stage boot failed:", e);
throw e;
}
return stage;
}
function clearScene() {
if (!stage) return;
// Remove everything the previous surface added except the default lights.
const keep = new Set();
stage.scene.traverse((o) => { if (o.isLight) keep.add(o); });
for (let i = stage.scene.children.length - 1; i >= 0; i--) {
const o = stage.scene.children[i];
if (!keep.has(o)) stage.scene.remove(o);
}
// reset per-frame callbacks by re-booting frame list is overkill; surfaces guard on null.
}
async function selectSurface(id) {
const def = SURFACES.find((s) => s.id === id);
if (!def) return;
const token = ++loadToken;
// visual selection state
[...tabsEl.children].forEach((t) => t.setAttribute("aria-selected", String(t.dataset.id === id)));
await ensureStage();
// tear down previous
if (current && current.instance && current.instance.unmount) {
try { current.instance.unmount(); } catch (_) {}
}
clearScene();
let mod;
try { mod = await import(def.mod); }
catch (e) { console.error("[holographic] failed to load surface", id, e); return; }
if (token !== loadToken) return; // a newer tab click superseded us
const surface = mod.default || mod;
const ctx = { stage, container: stageEl, live, label, THREE, szl3d };
try {
surface.mount(ctx);
current = { def, instance: surface };
history.replaceState(null, "", "#" + id);
} catch (e) {
console.error("[holographic] surface mount threw", id, e);
}
}
// build tabs
SURFACES.forEach((s) => {
const b = document.createElement("button");
b.className = "tab"; b.textContent = s.title; b.dataset.id = s.id;
b.setAttribute("role", "tab"); b.setAttribute("aria-selected", "false");
b.addEventListener("click", () => selectSurface(s.id));
tabsEl.appendChild(b);
});
// expose a tiny API for the selftest harness to drive the shell headlessly.
window.__SZL3D_SHELL__ = {
surfaces: SURFACES,
select: selectSurface,
get stage() { return stage; },
get current() { return current; },
ensureStage,
};
// initial surface from hash or default to energy
const initial = (location.hash || "").replace("#", "");
selectSurface(SURFACES.some((s) => s.id === initial) ? initial : "energy");
</script>
</body>
</html>
|