Spaces:
Running on Zero
Running on Zero
| <html lang="en"> | |
| <head> | |
| <meta charset="utf-8" /> | |
| <meta name="viewport" content="width=device-width, initial-scale=1" /> | |
| <meta http-equiv="Cache-Control" content="no-store" /> | |
| <title>Hatchimera — Compendium</title> | |
| <style> | |
| :root { --bg:#eef3fb; --panel:#ffffff; --line:#dce6f5; --ink:#1d2433; --dim:#6b7891; --accent:#ff7a18; } | |
| * { box-sizing:border-box; } | |
| /* Backdrop on <html> so the behind-content WebGL canvas (z-index:-1) sits above | |
| it; <body> stays transparent so the 3D shows through the card stages. */ | |
| html { background:var(--bg); } | |
| body { margin:0; background:transparent; color:var(--ink); font:14px/1.5 -apple-system,"Segoe UI",system-ui,sans-serif; } | |
| header { padding:22px 26px 14px; } | |
| h1 { margin:0 0 4px; font-size:20px; } | |
| .sub { color:var(--dim); font-size:13px; max-width:760px; } | |
| .controls { margin-top:12px; display:flex; gap:8px; flex-wrap:wrap; } | |
| .controls button { background:#fff; color:var(--ink); border:1px solid var(--line); border-radius:999px; padding:5px 13px; cursor:pointer; font-size:12.5px; } | |
| .controls button.active { background:var(--accent); color:#fff; border-color:var(--accent); } | |
| .count { color:var(--dim); font-size:12.5px; align-self:center; margin-left:6px; } | |
| .grid { display:grid; grid-template-columns:repeat(auto-fill,minmax(220px,1fr)); gap:16px; padding:14px 26px 48px; } | |
| /* transparent card + stage so the behind-content canvas shows the 3D through it */ | |
| .card { background:transparent; border:1px solid var(--line); border-radius:16px; overflow:hidden; box-shadow:0 8px 24px #5a93c722; } | |
| .card[hidden] { display:none; } | |
| .card .buddy-voxel-stage { aspect-ratio:1/1; width:100%; position:relative; background:transparent; } | |
| .meta { padding:10px 14px 12px; border-top:1px solid var(--line); background:var(--panel); } | |
| .name { font-weight:700; font-size:15px; color:var(--accent); } | |
| .theme { color:var(--dim); font-size:11.5px; text-transform:uppercase; letter-spacing:.5px; } | |
| </style> | |
| </head> | |
| <body> | |
| <header> | |
| <h1>🧬 Hatchimera — Compendium</h1> | |
| <div class="sub">The built-in starting roster. Each creature is a hand-authored box-layout, rendered <b>live</b> with the real in-game rig — production lighting, real contact shadows, ACES tone mapping, turntable. <b>Drag</b> any one to orbit.</div> | |
| <div class="controls" id="filters"></div> | |
| </header> | |
| <div class="grid" id="grid"></div> | |
| <!-- 50+ cards: drive a capped manager ourselves instead of the rig auto-booting all of them --> | |
| <script>window.__VOXEL_NO_AUTOBOOT = true;</script> | |
| <script src="./report_data.js"></script> | |
| <script src="../shared/voxel-rig.js"></script> | |
| <script src="../shared/voxel-cards.js"></script> | |
| <script> | |
| (function () { | |
| const DATA = window.COMPENDIUM_DATA || []; | |
| const grid = document.getElementById("grid"); | |
| const filters = document.getElementById("filters"); | |
| const themes = ["all", ...[...new Set(DATA.map(d => d.theme))]]; | |
| let active = "all"; | |
| themes.forEach(t => { | |
| const b = document.createElement("button"); | |
| b.textContent = t; | |
| if (t === "all") b.classList.add("active"); | |
| b.onclick = () => { | |
| active = t; | |
| [...filters.children].forEach(x => x.classList.toggle("active", x.textContent === t)); | |
| apply(); | |
| }; | |
| filters.appendChild(b); | |
| }); | |
| const count = document.createElement("span"); | |
| count.className = "count"; | |
| filters.appendChild(count); | |
| DATA.forEach(d => { | |
| const card = document.createElement("div"); | |
| card.className = "card"; | |
| card.dataset.theme = d.theme; | |
| card.appendChild(window.makeVoxelCard({ boxes: d.boxes, build: false })); | |
| const meta = document.createElement("div"); | |
| meta.className = "meta"; | |
| meta.innerHTML = `<div class="name">${d.name}</div><div class="theme">${d.theme}</div>`; | |
| card.appendChild(meta); | |
| grid.appendChild(card); | |
| }); | |
| function apply() { | |
| let n = 0; | |
| [...grid.children].forEach(c => { | |
| const show = active === "all" || c.dataset.theme === active; | |
| c.hidden = !show; | |
| if (show) n++; | |
| }); | |
| count.textContent = `${n} creatures`; | |
| } | |
| apply(); | |
| window.installVoxelCardManager({ maxLive: 12 }); | |
| })(); | |
| </script> | |
| </body> | |
| </html> | |