← Creature Collection results

Creature Collection

GPT 5.6 terra · typescript

Initial view of Creature Collection

Browser check: Artifact runtime error. This is a technical check, not a quality review.

Reviews & generation details

Reviews

No human review yet. Unreviewed does not mean unsuccessful.

Generation context

Imported historical artifact. Its exact original instructions and lineage are not known.

Generation prompt · exact text unavailable

See the current prompt for reference. It may differ from the instructions used to generate this artifact.

Inspect original source 25,567 bytes · SHA-256 ed3fd8824a82
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Lumenbind: The Eightfold Wake</title>
<style>
/* ── css: base ── */
:root{--ink:#eaf7ff;--muted:#9ab6d5;--glass:rgba(8,17,42,.63);--line:rgba(166,227,255,.27);--mint:#75f7d3;--violet:#a589ff;--hot:#ff7898}*{box-sizing:border-box}html,body,#game{margin:0;width:100%;height:100%;overflow:hidden;background:#050a1c;color:var(--ink);font-family:ui-rounded,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif}button{font:inherit;color:inherit;cursor:pointer;border:1px solid var(--line);background:linear-gradient(135deg,rgba(117,247,211,.16),rgba(165,137,255,.16));border-radius:12px;padding:10px 14px;transition:.18s transform,.18s background,.18s box-shadow}button:hover{transform:translateY(-2px);background:linear-gradient(135deg,rgba(117,247,211,.29),rgba(165,137,255,.25));box-shadow:0 7px 22px rgba(87,164,255,.22)}button:active{transform:translateY(1px)}#world{width:100%;height:100%;display:block}#hud{position:fixed;inset:0;pointer-events:none;padding:20px;display:grid;grid-template-columns:1fr auto;grid-template-rows:auto auto 1fr}.brand{letter-spacing:.2em;font-weight:800;text-shadow:0 0 18px #83eaff;font-size:14px}.brand small{display:block;font-size:8px;letter-spacing:.28em;color:var(--mint);margin-top:3px}#zoneLabel,#objective{justify-self:end;background:var(--glass);backdrop-filter:blur(12px);border:1px solid var(--line);border-radius:99px;padding:7px 13px;font-size:12px}#objective{grid-column:2;color:var(--muted);margin-top:8px}.hudActions{pointer-events:auto;align-self:end;justify-self:end;display:flex;gap:8px}.hudActions button{font-size:11px;padding:8px 11px}#partyHud{align-self:end;display:flex;gap:7px;pointer-events:auto}.partyChip{width:118px;background:var(--glass);backdrop-filter:blur(10px);border:1px solid var(--line);border-radius:12px;padding:7px;font-size:10px}.partyChip b{display:block}.bar{height:5px;background:#111c37;border-radius:9px;overflow:hidden;margin-top:4px}.bar i{display:block;height:100%;border-radius:9px;background:linear-gradient(90deg,var(--mint),#b7ffe6);transition:width .35s}#touch{position:fixed;left:18px;bottom:18px;display:none;pointer-events:auto;text-align:center}#touch button{width:47px;height:42px;padding:0;margin:2px;border-radius:13px;background:rgba(13,30,63,.72)}#modal{position:fixed;inset:0;display:grid;place-items:center;pointer-events:none;background:rgba(1,5,19,.15);transition:.2s}#modal.show{pointer-events:auto;background:rgba(1,5,19,.54);backdrop-filter:blur(5px)}.panel{width:min(700px,92vw);max-height:88vh;overflow:auto;border:1px solid rgba(181,234,255,.34);border-radius:24px;padding:26px;background:linear-gradient(145deg,rgba(14,31,71,.94),rgba(15,14,48,.95));box-shadow:0 25px 90px #0008}.panel h1{margin:0 0 5px;font-size:30px;letter-spacing:.08em}.eyebrow{color:var(--mint);font-size:11px;letter-spacing:.18em}.panel p{color:#c8d9ee;line-height:1.55}.row{display:flex;gap:10px;flex-wrap:wrap}.grow{flex:1}.choice{min-width:180px;text-align:left;padding:15px}.choice strong{display:block;font-size:16px}.choice span{font-size:11px;color:var(--muted);display:block;margin-top:4px}.battle{width:min(940px,96vw);padding:17px}.battleTop{display:flex;justify-content:space-between;gap:20px;min-height:245px;position:relative;background:radial-gradient(ellipse at 65% 80%,#865cc244,transparent 43%),radial-gradient(ellipse at 18% 100%,#52d7d73d,transparent 40%);border-radius:17px;overflow:hidden}.combatant{position:absolute;width:42%;bottom:15px}.combatant.enemy{right:5%;text-align:right}.combatant.player{left:5%}.orb{width:102px;height:102px;border-radius:44% 56% 54% 46%;display:inline-grid;place-items:center;font-weight:900;font-size:21px;color:#07132b;border:3px solid #fff8;box-shadow:0 0 35px currentColor;animation:float 2.5s ease-in-out infinite}.enemy .orb{animation-delay:-1s}.stat{background:rgba(5,12,34,.72);border:1px solid var(--line);border-radius:12px;padding:8px 10px;max-width:245px}.enemy .stat{margin-left:auto}.stat small{color:var(--muted)}.hp i{background:linear-gradient(90deg,#ff6f8c,#ffb36d)}.moveGrid{display:grid;grid-template-columns:repeat(2,1fr);gap:8px;margin-top:13px}.move{padding:11px;text-align:left}.move span{display:block;font-size:10px;color:var(--muted);margin-top:3px}.log{font-size:12px;color:#cbdaf1;min-height:20px;padding:7px 2px}.menuGrid{display:grid;grid-template-columns:repeat(2,1fr);gap:10px}.dex{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:8px}.dexCard{border:1px solid var(--line);border-radius:12px;padding:10px;font-size:11px}.locked{opacity:.35;filter:grayscale(1)}#toast{position:fixed;left:50%;bottom:24px;transform:translate(-50%,25px);opacity:0;background:#0d2147eF;border:1px solid var(--line);border-radius:99px;padding:10px 17px;font-size:12px;transition:.28s;pointer-events:none}#toast.on{opacity:1;transform:translate(-50%,0)}.damage{position:fixed;font-weight:900;font-size:24px;color:#fff;pointer-events:none;animation:pop .75s forwards;text-shadow:0 3px 5px #000}.vignette{position:fixed;inset:0;pointer-events:none;animation:vign 1.2s ease-out forwards}@keyframes float{50%{transform:translateY(-10px) rotate(3deg)}}@keyframes pop{to{transform:translateY(-55px);opacity:0}}@keyframes vign{0%{box-shadow:inset 0 0 0 100vmax #a47dff55}100%{box-shadow:inset 0 0 0 0 #a47dff00}}@media(max-width:700px){#touch{display:block}.brand{font-size:11px}#partyHud{max-width:57vw;overflow:hidden}.partyChip{width:91px}.battleTop{min-height:210px}.moveGrid{grid-template-columns:1fr 1fr}.panel{padding:20px}#zoneLabel,#objective{font-size:10px}}
</style>
</head>
<body>
<main id="game"><canvas id="world" aria-label="Lumenbind overworld"></canvas><section id="hud"><div class="brand">LUMENBIND <small>THE EIGHTFOLD WAKE</small></div><div id="zoneLabel">Veilroot Reach</div><div id="objective">Find the prism shrine</div><div id="partyHud"></div><div class="hudActions"><button id="soundBtn">◖ SOUND</button><button id="menuBtn">☷ MENU</button></div></section><section id="touch"><button data-move="up">▲</button><div><button data-move="left">◀</button><button data-move="down">▼</button><button data-move="right">▶</button></div></section><div id="modal"></div><div id="toast"></div></main>
<script>
(function () {
'use strict';
var __mods = {};
var __cache = {};
var __map = {};
function __require(id) {
  if (__cache[id]) return __cache[id].exports;
  var module = __cache[id] = { exports: {} };
  var factory = __mods[id];
  if (!factory) throw new Error("Module not found: " + id);
  factory(module.exports, function (spec) {
    var target = (__map[id] && __map[id][spec]) || spec;
    return __require(target);
  }, module);
  return module.exports;
}

// ── module: src/main.ts ──
__mods["src/main.ts"] = function (exports, require, module) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const A = ['Ember', 'Tide', 'Gale', 'Stone', 'Bloom', 'Aether', 'Null'];
const species = [
    ['Cindrel', 'Ember', 'A coal-tailed skitterer that sleeps inside warm bellflowers.', 42, 59, 39, 54, 'Pyrrin'], ['Mirefin', 'Tide', 'It traces silver loops through puddles when rain is near.', 52, 43, 58, 39, 'Rillune'], ['Vespern', 'Gale', 'Its down catches dusk-light and scatters it across trails.', 40, 48, 40, 64, 'Zephra'], ['Pyrrin', 'Ember', 'A furnace-hearted runner whose footfalls wake old stones.', 64, 79, 57, 72], ['Rillune', 'Tide', 'Moonwater follows in its wake, soothing cracked ground.', 77, 56, 78, 52], ['Zephra', 'Gale', 'It rides quiet pressure currents above the canopy.', 59, 67, 55, 91], ['Bramblet', 'Bloom', 'A thorn-shelled seedling that hums to orchard roots.', 58, 55, 70, 31, 'Verdantyx'], ['Craggle', 'Stone', 'It stacks pebbles into tiny doorways for wandering wind.', 70, 72, 88, 22, 'Monolithra'], ['Glimmerwisp', 'Aether', 'A curious mote-being that collects unfinished wishes.', 39, 61, 36, 77, 'Lucidra'], ['Hushling', 'Null', 'It makes safe hollows wherever noise is too sharp.', 74, 39, 80, 27, 'Stillmaw'], ['Searook', 'Ember', 'It nests in glassy ravines and whistles at dawn.', 55, 68, 45, 62], ['Dewmora', 'Tide', 'Soft fins filter starlight from underground springs.', 66, 49, 67, 42], ['Kitevein', 'Gale', 'A ribbon-winged rover that maps storm corridors.', 47, 63, 43, 81], ['Mossmote', 'Bloom', 'It cultivates a pocket garden along its back.', 61, 48, 74, 35], ['Basaltin', 'Stone', 'Slow sparks pulse beneath its slate-plated hide.', 78, 75, 93, 18], ['Chimelet', 'Aether', 'Its ringing crown records the names of lost paths.', 44, 57, 46, 69], ['Orryx', 'Null', 'It is said to drink the color from dangerous dreams.', 82, 53, 89, 25], ['Flarrow', 'Ember', 'A flare-feathered sentinel of high red cliffs.', 62, 82, 51, 75], ['Verdantyx', 'Bloom', 'A living lattice of vine and lantern pollen.', 88, 76, 94, 48], ['Monolithra', 'Stone', 'A gentle giant whose crystal strata remember every season.', 108, 96, 125, 25], ['Lucidra', 'Aether', 'An aurora-bodied guardian of the forgotten skywells.', 67, 99, 64, 112], ['Stillmaw', 'Null', 'It carries a tranquil field where panic cannot root.', 112, 62, 124, 38], ['Tidelorn', 'Tide', 'A royal current given fins and a patient gaze.', 102, 79, 104, 61], ['Galeshade', 'Gale', 'A dusk-winged arbiter that cuts fog into clean ribbons.', 78, 94, 73, 121], ['Ashenova', 'Ember', 'Its ember halo is a promise that endings can bloom.', 91, 116, 76, 102], ['Bloomarch', 'Bloom', 'It grows luminous bridges between lonely places.', 106, 92, 116, 69], ['Nexolith', 'Aether', 'A prism mind assembled from the eight sleeping lights.', 125, 118, 112, 88]
].map(x => ({ n: x[0], aff: x[1], lore: x[2], h: x[3], at: x[4], de: x[5], sp: x[6], evo: x[7] }));
const moves = Array.from({ length: 42 }, (_, i) => ({ n: ['Cinder Pin', 'Ripple Thread', 'Breeze Arc', 'Pebble Hymn', 'Petal Latch', 'Gleam Pulse', 'Quiet Weight', 'Ash Chorus', 'Tide Needle', 'Sky Kink', 'Root Lantern', 'Prism Knell', 'Void Tuck', 'Solar Scuff'][i % 14] + ' ' + (i > 13 ? 'II' : ''), p: 18 + (i % 6) * 7, a: 78 + (i % 5) * 4, t: A[i % 7], e: ['burn', 'frost', 'speed', 'barrier', 'regen', 'multi', 'shock'][i % 7] }));
const zones = [['Veilroot Reach', '#17476c', '#4c8d85', .12], ['Cinder Steps', '#6b3041', '#d36a4c', .16], ['Morrowfen', '#263e58', '#599b90', .19], ['Prism Expanse', '#392c72', '#9a6fc5', .22], ['Hollow Meridian', '#5d3848', '#d78e66', .25], ['Aster Vault', '#183858', '#4a78ad', .29]];
let game = { zone: 0, x: 7, y: 7, party: [], box: [], items: [8, 3, 1], anchors: 0, story: 0, mute: false };
let battle = null;
const c = document.querySelector('#world'), ctx = c.getContext('2d');
const modal = document.querySelector('#modal'), toast = document.querySelector('#toast');
function save() { localStorage.setItem('lumenbind', JSON.stringify(game)); }
function say(t) { toast.textContent = t; toast.classList.add('on'); setTimeout(() => toast.classList.remove('on'), 2100); }
function calc(m) { let s = species[m.s], k = 1 + m.l * .035; return { hp: Math.floor(s.h * k), at: Math.floor(s.at * k), de: Math.floor(s.de * k), sp: Math.floor(s.sp * k) }; }
function fresh(s, l = 5) { let h = calc({ s, l, hp: 0, mhp: 0, moves: [], xp: 0 }).hp; return { s, l, hp: h, mhp: h, moves: [s % 42, (s + 7) % 42, (s + 15) % 42, (s + 25) % 42], xp: 0 }; }
function renderHud() { let p = game.party[0]; document.querySelector('#zoneLabel').textContent = zones[game.zone][0]; document.querySelector('#objective').textContent = game.anchors < 4 ? `Anchors aligned: ${game.anchors}/4 · Seek the shrine ✦` : 'Eightfold Wake complete — free roam'; document.querySelector('#partyHud').innerHTML = game.party.map((m, i) => { let s = species[m.s]; return `<div class="partyChip"><b>${i ? '· ' : ''}${s.n} Lv.${m.l}</b><div class="bar"><i style="width:${m.hp / m.mhp * 100}%"></i></div></div>`; }).join(''); }
function draw() { let w = innerWidth, h = innerHeight, d = devicePixelRatio; c.width = w * d; c.height = h * d; ctx.setTransform(d, 0, 0, d, 0, 0); let z = zones[game.zone], g = ctx.createLinearGradient(0, 0, w, h); g.addColorStop(0, z[1]); g.addColorStop(1, z[2]); ctx.fillStyle = g; ctx.fillRect(0, 0, w, h); let tile = Math.min(w, h) / 11; for (let y = 0; y < 11; y++)
    for (let x = 0; x < 16; x++) {
        ctx.fillStyle = (x + y) % 2 ? '#ffffff0a' : '#00000009';
        ctx.fillRect(x * tile, y * tile, tile - 1, tile - 1);
    } for (let i = 0; i < 40; i++) {
    ctx.fillStyle = i % 2 ? '#dfffb755' : '#ffffff50';
    ctx.beginPath();
    ctx.arc((i * 79 + performance.now() * .018) % w, (i * 47 + Math.sin(performance.now() / 1000 + i) * 25) % h, 1 + (i % 3), 0, 7);
    ctx.fill();
} let sx = w / 2 + (game.x - 7) * tile, sy = h / 2 + (game.y - 5) * tile; ctx.fillStyle = '#eaffff'; ctx.shadowColor = '#75f7d3'; ctx.shadowBlur = 20; ctx.beginPath(); ctx.arc(sx, sy, 15, 0, 7); ctx.fill(); ctx.shadowBlur = 0; ctx.fillStyle = '#17385d'; ctx.fillText('✦', sx - 4, sy + 5); let shrineX = w / 2 + (game.zone === 0 ? 3 : -3) * tile, shrineY = h / 2 - 2 * tile; ctx.strokeStyle = '#fff8'; ctx.lineWidth = 3; ctx.beginPath(); ctx.arc(shrineX, shrineY, 20, 0, 7); ctx.stroke(); ctx.fillStyle = '#fff'; ctx.fillText('✧', shrineX - 4, shrineY + 5); requestAnimationFrame(draw); }
function open(html) { modal.innerHTML = `<div class="panel">${html}</div>`; modal.classList.add('show'); }
function close() { modal.classList.remove('show'); modal.innerHTML = ''; }
function title() { open(`<div class="eyebrow">A QUIET WORLD IS WAITING</div><h1>LUMENBIND</h1><p>Thread through six wandering reaches. Bind the creatures of the living light, awaken four Anchors, and find the Eightfold Wake.</p><div class="row"><button class="grow" id="new">NEW BINDING</button><button class="grow" id="cont" ${localStorage.lumenbind ? '' : 'disabled'}>CONTINUE</button></div><p><small>Move with WASD / arrow keys. Touch controls appear on smaller screens.</small></p>`); document.querySelector('#new').addEventListener('click', starter); document.querySelector('#cont').addEventListener('click', () => { Object.assign(game, JSON.parse(localStorage.lumenbind)); close(); renderHud(); say('Returned to the last prism shrine.'); }); }
function starter() { open(`<div class="eyebrow">FIRST THREAD</div><h1>Choose a companion</h1><p>Each binding carries a different current. All can grow beyond their first shape.</p><div class="row">${[0, 1, 2].map(i => `<button class="choice" data-s="${i}"><strong>${species[i].n}</strong><span>${species[i].aff} · ${species[i].lore}</span></button>`).join('')}</div>`); document.querySelectorAll('[data-s]').forEach(b => b.addEventListener('click', () => { game.party = [fresh(+(b.dataset.s), 5)]; game.box = [game.party[0].s]; close(); renderHud(); story('A prism thread answers your touch. Walk into the luminous grass to meet a wild echo.'); save(); })); }
function story(t) { open(`<div class="eyebrow">STORY THREAD ${game.story + 1}/4</div><h1>The world listens</h1><p>${t}</p><button id="ok">CONTINUE</button>`); document.querySelector('#ok').addEventListener('click', () => { close(); game.story++; document.body.insertAdjacentHTML('beforeend', '<div class="vignette"></div>'); setTimeout(() => document.querySelector('.vignette')?.remove(), 1250); }); }
function encounter() { let level = Math.min(50, 4 + game.zone * 6 + Math.floor(Math.random() * 5) + (game.anchors >= 4 ? 8 : 0)), si = (game.zone * 3 + Math.floor(Math.random() * 6)) % 18; battle = { enemies: Array.from({ length: Math.random() < .18 ? 2 : 1 }, (_, i) => fresh((si + i) % 18, level)), active: 0, turn: 0, canCatch: true }; battleMenu('A wild echo steps from the shimmer!'); }
function typeMult(a, d) { if (a === 'Aether')
    return d === 'Null' ? 1.5 : 1.12; if (d === 'Null')
    return .55; let cyc = ['Ember', 'Tide', 'Gale']; let ix = cyc.indexOf(a); if (ix >= 0 && cyc[(ix + 1) % 3] === d)
    return 1.7; if (a === 'Stone' && (d === 'Ember' || d === 'Gale'))
    return 1.7; if (a === 'Bloom' && (d === 'Stone' || d === 'Tide'))
    return 1.7; return 1; }
function battleMenu(log) { let p = game.party[battle.active], e = battle.enemies[0], ps = species[p.s], es = species[e.s]; open(`<div class="panel battle"><div class="battleTop"><div class="combatant player"><div class="orb" style="background:${color(ps.aff)}">${ps.n.slice(0, 2)}</div><div class="stat"><b>${ps.n} · Lv.${p.l}</b><small>${ps.aff} · HP ${p.hp}/${p.mhp}</small><div class="bar"><i style="width:${p.hp / p.mhp * 100}%"></i></div></div></div><div class="combatant enemy"><div class="orb" style="background:${color(es.aff)}">${es.n.slice(0, 2)}</div><div class="stat"><b>${es.n} · Lv.${e.l}</b><small>${es.aff} · HP ${e.hp}/${e.mhp}</small><div class="bar hp"><i style="width:${e.hp / e.mhp * 100}%"></i></div></div></div></div><div class="log">${log}</div><div class="moveGrid">${p.moves.map(i => `<button class="move" data-m="${i}">${moves[i].n}<span>${moves[i].t} · Power ${moves[i].p} · ${moves[i].e}</span></button>`).join('')}<button class="move" id="bind">✦ CAST LURE <span>Glimmer Lure ×${game.items[0]} · rhythm bind</span></button><button class="move" id="switch">⇄ SWITCH THREAD</button></div></div>`); document.querySelectorAll('[data-m]').forEach(x => x.addEventListener('click', () => attack(+(x.dataset.m)))); document.querySelector('#bind').addEventListener('click', capture); document.querySelector('#switch').addEventListener('click', switcher); }
function color(a) { return { Ember: '#e86c72', Tide: '#55bcd2', Gale: '#9c80e5', Stone: '#c28a5d', Bloom: '#5ccf94', Aether: '#f2c464', Null: '#9aa7c5' }[a]; }
function attack(mi) { let p = game.party[battle.active], e = battle.enemies[0], m = moves[mi], pc = calc(p), ec = calc(e); let hit = Math.random() * 100 < m.a; if (!hit) {
    enemyTurn('The thread slips past.');
    return;
} let mul = typeMult(m.t, species[e.s].aff) * (m.t === species[p.s].aff ? 1.25 : 1), crit = Math.random() < .1 ? 1.5 : 1; let dmg = Math.max(1, Math.floor(.4 * p.l * pc.at / ec.de * mul * crit + Math.random() * 5)); e.hp = Math.max(0, e.hp - dmg); floatDamage('-' + dmg + (crit ? ' ✦' : '')); let text = `${species[p.s].n} used ${m.n}: ${dmg} harm.${mul > 1.3 ? ' Super-effective!' : ''}`; if (e.hp <= 0) {
    victory(text);
    return;
} enemyTurn(text); }
function enemyTurn(prefix) { setTimeout(() => { let e = battle.enemies[0], p = game.party[battle.active], ec = calc(e), pc = calc(p), d = Math.max(1, Math.floor(.4 * e.l * ec.at / pc.de + Math.random() * 5)); p.hp = Math.max(0, p.hp - d); floatDamage('-' + d); if (!p.hp) {
    let next = game.party.findIndex(x => x.hp > 0);
    if (next < 0) {
        game.party.forEach(x => x.hp = Math.max(1, Math.floor(x.mhp * .4)));
        close();
        say('Your threads scatter back to the shrine.');
        save();
        return;
    }
    battle.active = next;
    battleMenu(`${prefix} ${species[e.s].n} answers for ${d}. Your thread shifts!`);
}
else
    battleMenu(`${prefix} ${species[e.s].n} answers for ${d}.`); }, 420); }
function floatDamage(t) { let x = document.createElement('div'); x.className = 'damage'; x.textContent = t; x.style.left = (55 + Math.random() * 20) + '%'; x.style.top = (35 + Math.random() * 20) + '%'; document.body.append(x); setTimeout(() => x.remove(), 800); }
let victory = (t) => { let e = battle.enemies.shift(), p = game.party[battle.active], gain = e.l * 14; p.xp += gain; if (p.xp >= p.l * 30 && p.l < 50) {
    p.xp = 0;
    p.l++;
    let st = calc(p);
    p.mhp = st.hp;
    p.hp = st.hp;
    say(`${species[p.s].n} rises to level ${p.l}!`);
} if (battle.enemies.length) {
    battleMenu(t + ' Another echo closes in!');
    return;
} close(); say(`${t} Victory! +${gain} resonance.`); save(); renderHud(); };
function capture() { if (!game.items[0]) {
    say('No Glimmer Lures remain.');
    return;
} let e = battle.enemies[0]; open(`<div class="panel"><div class="eyebrow">LURE RHYTHM</div><h1>Catch the pulse</h1><p>Tap when the ring reaches the center. A weak echo is easier to bind.</p><button id="pulse" style="width:150px;height:150px;border-radius:50%;font-size:20px">✦</button><p id="capmsg">The prism is breathing...</p></div>`); let start = performance.now(); document.querySelector('#pulse').addEventListener('click', () => { let timing = Math.abs(((performance.now() - start) % 1800) - 900) / 900, chance = .2 + (1 - e.hp / e.mhp) * .55 + (timing < .25 ? .2 : 0); game.items[0]--; if (Math.random() < chance) {
    if (!game.box.includes(e.s))
        game.box.push(e.s);
    if (game.party.length < 6)
        game.party.push(fresh(e.s, e.l));
    close();
    say(`${species[e.s].n} joins your binding!`);
    save();
    renderHud();
}
else {
    battleMenu('The echo slips free from the lure!');
} }); }
function switcher() { open(`<div class="panel"><h1>Shift thread</h1><div class="row">${game.party.map((m, i) => `<button class="choice" data-sw="${i}"><strong>${species[m.s].n} Lv.${m.l}</strong><span>${m.hp}/${m.mhp} HP · ${species[m.s].aff}</span></button>`).join('')}</div></div>`); document.querySelectorAll('[data-sw]').forEach(x => x.addEventListener('click', () => { let i = +(x.dataset.sw); if (game.party[i].hp > 0) {
    battle.active = i;
    battleMenu('Threads interlace.');
} })); }
function shrine() { game.party.forEach(m => m.hp = m.mhp); game.items[0] += 2; save(); renderHud(); open(`<div class="eyebrow">PRISM SHRINE</div><h1>Rest & attune</h1><p>Your party is restored. The shrine yields two Glimmer Lures and records your path.</p><div class="row"><button id="anchor">${game.anchors < 4 ? 'CHALLENGE ANCHOR' : 'FREE ROAM'}</button><button id="shop">WEAVE SUPPLIES</button><button id="leave">LEAVE</button></div>`); document.querySelector('#leave').addEventListener('click', close); document.querySelector('#shop').addEventListener('click', () => { game.items[0] += 3; say('Three Lures woven from shrine-light.'); save(); close(); }); document.querySelector('#anchor').addEventListener('click', () => { if (game.anchors >= 4) {
    close();
    return;
} close(); battle = { enemies: [fresh(18 + game.anchors * 2, 12 + game.anchors * 9)], active: 0 }; let old = victory; victory = (t) => { game.anchors++; game.zone = Math.min(5, game.zone + 1); say(`Anchor awakened! ${zones[game.zone][0]} opens.`); renderHud(); save(); victory = old; if (game.anchors === 1 || game.anchors === 3)
    story('An Anchor answers, and a new color enters the sky.'); }; battleMenu('An Anchor guardian gathers itself from prism dust!'); }); }
function menu() { open(`<div class="eyebrow">FIELD WEAVE</div><h1>Bound Atlas</h1><div class="menuGrid"><button id="team">TEAM · ${game.party.length}/6</button><button id="dex">TAXONOMY · ${game.box.length}/27</button><button id="bag">SATCHEL · Lures ${game.items[0]}</button><button id="save">SAVE ATLAS</button></div><div class="row" style="margin-top:14px"><button id="close">CLOSE</button></div>`); document.querySelector('#close').addEventListener('click', close); document.querySelector('#save').addEventListener('click', () => { save(); say('Atlas recorded.'); close(); }); document.querySelector('#bag').addEventListener('click', () => say('Glimmer Lures catch echoes. Shrine restoration is always free.')); document.querySelector('#team').addEventListener('click', () => open(`<h1>Binding Team</h1>${game.party.map(m => `<p><b>${species[m.s].n}</b> · Lv ${m.l} · ${species[m.s].aff}<br><small>${species[m.s].lore}</small></p>`).join('')}<button onclick="document.querySelector('#menuBtn').click()">BACK</button>`)); document.querySelector('#dex').addEventListener('click', () => open(`<h1>Echo Taxonomy</h1><div class="dex">${species.map((s, i) => `<div class="dexCard ${game.box.includes(i) ? '' : 'locked'}"><b>${game.box.includes(i) ? s.n : 'Unbound echo'}</b><br>${game.box.includes(i) ? s.aff + ' · ' + s.lore : 'A silhouette beyond the prism haze.'}</div>`).join('')}</div><br><button onclick="document.querySelector('#menuBtn').click()">BACK</button>`)); }
function move(dx, dy) { if (modal.classList.contains('show'))
    return; game.x = Math.max(0, Math.min(15, game.x + dx)); game.y = Math.max(0, Math.min(10, game.y + dy)); let shrineNear = Math.abs(game.x - (game.zone === 0 ? 10 : 4)) + Math.abs(game.y - 3) < 2; if (shrineNear) {
    shrine();
    return;
} if (Math.random() < Number(zones[game.zone][3]))
    encounter(); }
addEventListener('keydown', e => { let k = e.key.toLowerCase(); if (k === 'arrowup' || k === 'w')
    move(0, -1); if (k === 'arrowdown' || k === 's')
    move(0, 1); if (k === 'arrowleft' || k === 'a')
    move(-1, 0); if (k === 'arrowright' || k === 'd')
    move(1, 0); if (k === 'escape')
    close(); });
document.querySelectorAll('[data-move]').forEach(b => b.addEventListener('click', () => { let q = b.dataset.move; move(q === 'left' ? -1 : q === 'right' ? 1 : 0, q === 'up' ? -1 : q === 'down' ? 1 : 0); }));
document.querySelector('#menuBtn').addEventListener('click', menu);
document.querySelector('#soundBtn').addEventListener('click', () => { game.mute = !game.mute; say(game.mute ? 'Sound cocooned.' : 'Sound uncoiled.'); });
renderHud();
draw();
title();
};

// ── entry ──
__require("src/main.ts");
})();
</script>
</body>
</html>
<!-- agent-meta {"model":"openai/gpt-5.6-terra","provider":"openrouter","persona":"typescript","sessionId":"d95f7417-593c-4169-8ad8-66db28d05235","tokensIn":117766,"tokensOut":8596,"tokensTotal":126362,"turns":11,"toolCalls":13,"failedToolCalls":1,"timestamp":"2026-07-31T16:31:26.932Z"} -->