Creature Collection
GPT 5.6 Luna Pro · full

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 24,121 bytes · SHA-256 204f1850198a
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
<title>Veyra: The Quiet Binding</title>
<style>
:root{--ink:#eef4ff;--muted:#9aa9c7;--glass:rgba(13,20,42,.78);--line:#31446d;--glow:#7af2d2;--hot:#ff9b72;--gold:#ffe28b;--danger:#ff668d}*{box-sizing:border-box}html,body{margin:0;background:#070b18;color:var(--ink);font:14px system-ui,sans-serif;overflow:hidden}#app{height:100vh;position:relative;background:radial-gradient(circle at 50% 0,#172951,#070b18 65%)}canvas{display:block;width:100%;height:100%;image-rendering:auto}.screen{position:absolute;inset:0}.hidden{display:none!important}.glass{background:var(--glass);border:1px solid #405585;border-radius:18px;box-shadow:0 20px 60px #0008,0 0 25px #69e1c61c;backdrop-filter:blur(14px)}button{color:var(--ink);background:#19294c;border:1px solid #5772aa;padding:11px 16px;border-radius:11px;font-weight:700;cursor:pointer;transition:.2s}button:hover{background:#294675;transform:translateY(-1px);border-color:var(--glow)}button:disabled{opacity:.4;cursor:not-allowed}.title{display:grid;place-items:center;text-align:center;background:linear-gradient(145deg,#090e21cc,#101f3ccc)}.title h1{font-size:clamp(42px,9vw,94px);letter-spacing:.08em;margin:0;background:linear-gradient(120deg,#c8fff0,#7af2d2 40%,#e7bdff);color:transparent;background-clip:text;text-shadow:0 0 35px #83f6de55}.title p{max-width:620px;color:var(--muted);font-size:16px}.title .panel{padding:42px 45px}.buttons{display:flex;gap:12px;justify-content:center;flex-wrap:wrap}.primary{background:linear-gradient(120deg,#287a76,#6b50a3);border-color:#95f7df}.hud{position:absolute;top:15px;left:15px;right:15px;display:flex;justify-content:space-between;pointer-events:none}.hud>*{pointer-events:auto}.chip{padding:10px 14px;border-radius:12px;background:#0c1630d9;border:1px solid #31446d}.hud b{color:var(--gold)}.corner{display:flex;gap:8px}.mapHint{position:absolute;bottom:15px;left:50%;transform:translateX(-50%);color:#c3cde3;background:#09132acc;padding:8px 15px;border-radius:99px}.touch{position:absolute;bottom:24px;left:24px;display:grid;grid-template-columns:45px 45px 45px;grid-template-rows:45px 45px;gap:4px}.touch button{padding:0;border-radius:12px;font-size:18px}.touch button:nth-child(1){grid-column:2}.touch button:nth-child(2){grid-column:1;grid-row:2}.touch button:nth-child(3){grid-column:2;grid-row:2}.touch button:nth-child(4){grid-column:3;grid-row:2}.modal{position:absolute;inset:7%;padding:25px;overflow:auto}.modal h2{margin-top:0;color:var(--glow)}.tabs{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:18px}.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:12px}.card{padding:14px;background:#12203cbb;border:1px solid #33496f;border-radius:14px}.card h3{margin:0 0 5px;color:#d7ddff}.card small,.muted{color:var(--muted)}.bar{height:9px;background:#26324d;border-radius:99px;overflow:hidden}.bar i{display:block;height:100%;background:linear-gradient(90deg,#50e5aa,#c4f47d);transition:width .5s}.battle{background:linear-gradient(145deg,#101b30,#211b36)}#battleCanvas{height:52%;margin-top:7%;}.battleHud{position:absolute;top:12%;left:5%;right:5%;display:flex;justify-content:space-between}.mon{min-width:190px;padding:12px}.actions{position:absolute;bottom:5%;left:5%;right:5%;display:grid;grid-template-columns:repeat(4,1fr);gap:9px}.actions button{min-height:48px}.dialogue{position:absolute;bottom:17%;left:7%;right:7%;padding:16px;text-align:center;min-height:55px}.partyRow{display:flex;gap:8px;flex-wrap:wrap}.partyRow button{flex:1;min-width:120px;text-align:left}.tag{font-size:11px;color:#c6b3ff;padding:3px 7px;border:1px solid #66529c;border-radius:99px}.encounter{position:absolute;inset:0;background:#060a15dd;display:grid;place-items:center}.encounter .box{padding:35px;text-align:center}.pulse{animation:pulse 1.8s infinite}@keyframes pulse{50%{box-shadow:0 0 38px #79efd655}}@keyframes float{to{transform:translateY(-50px);opacity:0}}.float{position:absolute;font-size:22px;font-weight:900;animation:float 1s forwards;pointer-events:none}.notice{position:absolute;top:80px;left:50%;transform:translateX(-50%);padding:10px 20px;background:#182c4eea;border:1px solid var(--glow);border-radius:99px;z-index:5}.rhythm{width:100%;height:20px;accent-color:var(--glow)}@media(max-width:650px){.modal{inset:3%;padding:17px}.battleHud{top:9%;font-size:12px}.mon{min-width:135px}.actions{grid-template-columns:repeat(2,1fr);bottom:3%}.dialogue{bottom:27%}.title .panel{padding:28px 18px}}
</style></head><body><main id="app"><section id="title" class="screen title"><div class="panel glass pulse"><div class="muted">A FIELD GUIDE TO THE UNMUTED</div><h1>VEYRA</h1><p>In the hollow between stars, living echoes called <b>Veyri</b> gather around old listening-stones. Bind eight distinct echoes, awaken their hidden shapes, and quiet the four Anchors before the world rings apart.</p><div class="buttons"><button class="primary" onclick="newGame()">New Binding</button><button onclick="continueGame()">Continue</button></div><p class="muted">WASD / arrows to wander · Space to interact · M toggles map · Esc pauses</p></div></section><section id="world" class="screen hidden"><canvas id="worldCanvas"></canvas><div class="hud"><div class="chip"><b id="zoneName">Murmur Vale</b> · <span id="levelText">R1</span><br><span id="objective" class="muted"></span></div><div class="corner"><button onclick="openMenu('team')">Team</button><button onclick="openMenu('map')">Map</button><button onclick="openMenu('bag')">Bag</button><button onclick="openMenu('pause')">Ⅱ</button></div></div><div id="touch" class="touch"><button data-d="up">▲</button><button data-d="left">◀</button><button data-d="down">▼</button><button data-d="right">▶</button></div><div class="mapHint">Find the luminous shrine · arrows/WASD move</div></section><section id="battle" class="screen battle hidden"><canvas id="battleCanvas"></canvas><div class="battleHud"><div id="enemyHud" class="mon glass"></div><div id="playerHud" class="mon glass"></div></div><div id="battleDialogue" class="dialogue glass">A wild echo stirs.</div><div id="actions" class="actions"></div></section><div id="modal" class="modal glass hidden"></div><div id="notice" class="notice hidden"></div></main>
<script>
const $=s=>document.querySelector(s),rnd=(a,b)=>Math.floor(Math.random()*(b-a+1))+a,cl=(n,a,b)=>Math.max(a,Math.min(b,n));
const TYPES=['Auralis','Brinefold','Cindrel','Duskweave','Emberveil','Fulgur','Gloam'];
const zones=[['Murmur Vale','#102b3b','#5b75a8',.12,'The first note rises.'],['Saffron Rifts','#452d25','#c27558',.16,'A warm fracture opens.'],['Lumen Fen','#172f37','#6ac7ad',.2,'Reeds remember your name.'],['Violet Expanse','#29203f','#a77edb',.23,'The sky folds inward.'],['Hush Crown','#26323d','#c7d4e5',.27,'Only the brave can hear it.'],['The Null Choir','#111523','#e8c477',.32,'Four anchors hum in unison.']];
const abilityNames=['Whorl','Nacre Jab','Serein Ray','Cinderpin','Tide Rake','Hushstep','Prism Knell','Mote Mend','Fevercoil','Glaze Fang','Volt Thread','Bulwark Bloom','Rift Peck','Morrow Mist','Kindle Arc','Skylance','Silt Snare','Blink Pollen','Quillstorm','Dawn Pulse','Grave Current','Lattice Lash','Oathspark','Thorn Choir','Crestfall','Moonwell','Scorch Sigil','Tanglebeam','Vesper Bite','Mendweft','Rainsong','Frostbell','Gale Pin','Iron Hymn','Quickening','Star Suture','Rattlewave','Brink Bloom','Many Motes','Last Light'];
const effects=['none','burn','frost','shock','heal','barrier','regen','priority','multi','speed'];
let abilities=abilityNames.map((name,i)=>({name,power:28+(i%8)*8,acc:82+(i%5)*4,type:TYPES[i%7],cost:4+(i%4)*2,effect:effects[i%10]}));
const lore=['A small dusk-colored listener that stores rain in its hollow ribs.','It drifts through cracked soil, carrying a private blue weather.','A bright knot of patience, often found beside warm stones.','Its many eyes close whenever someone tells the truth.','It braids loose sounds into sheltering nests.','A shy spark that prefers the company of moss.','It learned to glow by watching distant storms.','A weightless grazer that leaves silver thoughts behind.','It hums beneath bridges where no bridge remains.','A velvet crawler with a talent for finding lost paths.','It sleeps in daylight and maps dreams at night.','An amber swimmer that believes every ripple is a letter.','A swift little guardian of unclaimed thresholds.','It wears a mask of condensed twilight.','A calm shape that remembers every kindness.','A thorned wisp whose shadow points home.','It gathers fallen echoes into a patient crown.','A rare wanderer born where two silences overlap.'];
let species=[];for(let i=0;i<18;i++){species.push({id:i,name:['Orrin','Vaskel','Nimru','Sova','Kelune','Pryx','Avel','Murn','Ixi','Tallow','Ruun','Miraq','Zeph','Cowlit','Yavra','Bramblet','Ossin','Qel'][i],type:[TYPES[i%7],i%3===0?TYPES[(i+2)%7]:null].filter(Boolean),base:{hp:48+i%5*7,atk:27+i%7*3,def:24+i%6*4,spd:22+i%8*4},lore:lore[i],learn:[i%40,(i*3+4)%40,(i*5+9)%40,(i*7+12)%40],transform:i%3===0?{level:18+(i%3)*5,catalyst:'Resonant Shard',form:18+i}:null});}
for(let i=0;i<9;i++){let b=species[i*2];species.push({id:18+i,name:['Orrivane','Vaskora','Nimrulon','Sovaryn','Kelunox','Pryxion','Avelune','Murnarch','Ixial'][i],type:b.type,base:{hp:b.base.hp+28,atk:b.base.atk+14,def:b.base.def+12,spd:b.base.spd+9},lore:'A transformed echo whose inner cadence has become visible.',learn:b.learn,transform:null});}
let S,keys={},audio;
function fresh(){return{zone:0,x:8,y:7,party:[],box:[],bag:{snare:8,prism:2,restor:5,shard:1},anchors:0,discovered:[],story:0,lastShrine:[8,7,0],muted:false,started:false}};
function newGame(){S=fresh();chooseStarter()};function chooseStarter(){showModal(`<h2>Choose your first resonance</h2><p class="muted">Three quiet sparks answer your hand.</p><div class="grid">${[0,1,2].map(i=>`<div class="card"><h3>${species[i].name} <span class="tag">${species[i].type[0]}</span></h3><p>${species[i].lore}</p><button onclick="takeStarter(${i})">Bind ${species[i].name}</button></div>`).join('')}</div>`)}
function takeStarter(i){S.party=[makeMon(i,5)];S.discovered=[i];S.started=true;hideModal();startWorld();save()}
function makeMon(id,level){let d=species[id],m={sid:id,name:d.name,level,hp:0,max:0,atk:0,def:0,spd:0,xp:0,status:{},moves:d.learn.map(x=>x)};calc(m);m.hp=m.max;return m}function calc(m){let d=species[m.sid],q=m.level;m.max=d.base.hp+q*6;m.atk=d.base.atk+q*3;m.def=d.base.def+q*2;m.spd=d.base.spd+q*2;m.hp=cl(m.hp||m.max,0,m.max)}
function save(){if(S)localStorage.setItem('veyra-save',JSON.stringify(S))}function continueGame(){let x=localStorage.getItem('veyra-save');if(!x){toast('No binding found. Begin a new one.');return}S=JSON.parse(x);startWorld()}
function startWorld(){$('#title').classList.add('hidden');$('#world').classList.remove('hidden');resize();updateHud();if(!S.tutorial){S.tutorial=true;story('First Listening','Move with the arrows. The vale will answer when you step near a wandering mote. Find the cyan shrine to restore your team.');}requestAnimationFrame(loop)}
function resize(){let c=$('#worldCanvas');c.width=innerWidth*devicePixelRatio;c.height=innerHeight*devicePixelRatio}addEventListener('resize',resize);
function story(title,text){showModal(`<h2>${title}</h2><p>${text}</p><button class="primary" onclick="hideModal()">Continue</button>`)}
function updateHud(){let z=zones[S.zone];$('#zoneName').textContent=z[0];$('#levelText').textContent='R'+(S.anchors+1);$('#objective').textContent=S.zone<4?`Anchor ${S.zone+1} sleeps beyond the shrine`:'The Null Choir awaits · anchors '+S.anchors+'/4'}
const ctx=$('#worldCanvas').getContext('2d');let t=0;function loop(){if(!S||$('#world').classList.contains('hidden'))return;t++;drawWorld();requestAnimationFrame(loop)}
function drawWorld(){let c=$('#worldCanvas');ctx.setTransform(devicePixelRatio,0,0,devicePixelRatio,0,0);let w=innerWidth,h=innerHeight,z=zones[S.zone];let g=ctx.createLinearGradient(0,0,w,h);g.addColorStop(0,z[1]);g.addColorStop(1,'#080c19');ctx.fillStyle=g;ctx.fillRect(0,0,w,h);let tile=Math.min(w,h)/16;for(let y=0;y<15;y++)for(let x=0;x<18;x++){ctx.fillStyle=(x+y)%2?'#ffffff08':'#00000009';ctx.fillRect(x*tile,y*tile,tile-1,tile-1)}for(let i=0;i<35;i++){let px=(i*97+t*(.2+i%3*.07))%w,py=(i*53+Math.sin(t/35+i)*30)%h;ctx.fillStyle=z[2]+'55';ctx.beginPath();ctx.arc(px,py,1+i%3,0,7);ctx.fill()}let sx=8*tile+tile/2,sy=7*tile+tile/2;ctx.shadowBlur=22;ctx.shadowColor='#71f4db';ctx.fillStyle='#72f4d3';ctx.beginPath();ctx.arc(sx,sy,12+Math.sin(t/8)*3,0,7);ctx.fill();ctx.shadowBlur=0;ctx.fillStyle='#e8f4ff';ctx.font='12px system-ui';ctx.fillText('SHRINE',sx-25,sy-21);let px=S.x*tile+tile/2,py=S.y*tile+tile/2;ctx.fillStyle='#ffe7a4';ctx.shadowBlur=18;ctx.shadowColor='#ffe7a4';ctx.beginPath();ctx.arc(px,py,10,0,7);ctx.fill();ctx.shadowBlur=0;ctx.fillStyle='#fff';ctx.fillText(S.party[0]?.name||'',px-20,py+27)}
function move(dx,dy){if($('#modal').classList.contains('hidden')===false)return;S.x=cl(S.x+dx,0,17);S.y=cl(S.y+dy,0,14);if(S.x===8&&S.y===7){rest();return}if(Math.random()<zones[S.zone][3])wild()}
addEventListener('keydown',e=>{keys[e.key.toLowerCase()]=1;if(['arrowup','arrowdown','arrowleft','arrowright',' '].includes(e.key.toLowerCase()))e.preventDefault();if(e.key==='Escape')openMenu('pause');if(e.key.toLowerCase()==='m')openMenu('map')});addEventListener('keyup',e=>keys[e.key.toLowerCase()]=0);setInterval(()=>{if(keys.w||keys.arrowup)move(0,-1);else if(keys.s||keys.arrowdown)move(0,1);else if(keys.a||keys.arrowleft)move(-1,0);else if(keys.d||keys.arrowright)move(1,0)},180);document.querySelectorAll('.touch button').forEach(b=>b.onclick=()=>({up:move.bind(null,0,-1),down:move.bind(null,0,1),left:move.bind(null,-1,0),right:move.bind(null,1,0)}[b.dataset.d])());
function rest(){S.party.forEach(m=>{m.hp=m.max;m.status={}});S.lastShrine=[S.x,S.y,S.zone];save();toast('The shrine mends every thread. Binding saved.');if(S.anchors<=S.zone&&S.zone<4){showModal(`<h2>${zones[S.zone][0]} Anchor</h2><p>${zones[S.zone][4]} A deep cadence waits beneath the shrine. Defeat its warden to unlock the next listening ground.</p><div class="buttons"><button class="primary" onclick="challengeAnchor()">Challenge warden</button><button onclick="hideModal()">Rest quietly</button></div>`)}else if(S.anchors===0&&S.zone===0)story('The First Note','Your Veyri is restored. Wandering motes are nearby—step boldly into the grass of the vale.')}function challengeAnchor(){hideModal();let id=12+S.zone;let foe=makeMon(id,9+S.zone*7);foe.name=['Silt Regent','Cinder Regent','Fen Regent','Violet Regent'][S.zone];beginBattle([foe],true)}function wild(){if($('#battle').classList.contains('hidden')===false)return;let count=rnd(1,Math.min(3,1+Math.floor(S.zone/2))), foes=[];for(let i=0;i<count;i++){let id=(rnd(0,17)+S.zone*2)%18;foes.push(makeMon(id,cl(4+S.zone*4+rnd(0,3),1,50)))}beginBattle(foes)}
let B;function beginBattle(foes,anchor=false){B={foes,turn:0,active:0,phase:'choose',anchor};$('#world').classList.add('hidden');$('#battle').classList.remove('hidden');renderBattle();say(anchor?`The ${foes[0].name} rises from the shrine's deep chamber.`:`A ${foes[0].name} and its companions emerge from the hush.`);}
function drawBattle(){let c=$('#battleCanvas'),x=c.getContext('2d'),w=c.width=c.clientWidth*devicePixelRatio,h=c.height=c.clientHeight*devicePixelRatio;x.setTransform(devicePixelRatio,0,0,devicePixelRatio,0,0);x.clearRect(0,0,c.clientWidth,c.clientHeight);x.fillStyle='#ffffff0a';x.beginPath();x.ellipse(c.clientWidth*.72,c.clientHeight*.7,130,28,0,0,7);x.fill();x.fillStyle='#78f0d0';x.shadowBlur=25;x.shadowColor='#78f0d0';x.beginPath();x.arc(c.clientWidth*.72,c.clientHeight*.48,42,0,7);x.fill();x.fillStyle='#ffba84';x.shadowColor='#ffba84';x.beginPath();x.arc(c.clientWidth*.25,c.clientHeight*.68,31,0,7);x.fill();x.shadowBlur=0}function renderBattle(){drawBattle();let e=B.foes[0],p=S.party[B.active];$('#enemyHud').innerHTML=`<b>${e.name}</b> <span class="tag">${species[e.sid].type[0]}</span><br>Lv ${e.level}<div class="bar"><i style="width:${e.hp/e.max*100}%"></i></div>${e.hp}/${e.max}`;$('#playerHud').innerHTML=`<b>${p.name}</b> <span class="tag">${species[p.sid].type[0]}</span><br>Lv ${p.level}<div class="bar"><i style="width:${p.hp/p.max*100}%"></i></div>${p.hp}/${p.max}`;let a=$('#actions');a.innerHTML=p.moves.map((mi,j)=>{let ab=abilities[mi];return `<button onclick="playerMove(${j})">${ab.name}<br><small>${ab.type} · ${ab.power}p · ${ab.cost}e</small></button>`}).join('')+`<button onclick="showBagBattle()">Use restoration</button><button onclick="switchMon()">Switch Veyri</button><button onclick="attemptBind()">Use snare</button>`}
function say(x){$('#battleDialogue').textContent=x}function typeMult(a,d){let i=TYPES.indexOf(a),j=TYPES.indexOf(d);if((i+1)%3===j)return 1.5;if(i===3&&(j===0||j===2))return 1.5;if(i===4&&(j===3||j===1))return 1.5;if(i===5)return 1.12;if(i===6)return j===5?.5:.7;return 1}function playerMove(j){if(B.phase!=='choose')return;B.phase='busy';let p=S.party[B.active],e=B.foes[0],ab=abilities[p.moves[j]];resolve(p,e,ab,()=>enemyTurn())}function resolve(att,def,ab,done){if(Math.random()*100>ab.acc){say(`${att.name}'s ${ab.name} slips wide.`);setTimeout(done,650);return}let mult=typeMult(ab.type,species[def.sid].type[0]),stab=species[att.sid].type.includes(ab.type)?1.25:1,crit=Math.random()<.1?1.5:1;let dmg=Math.max(1,Math.floor(.4*att.level*att.atk/def.def*mult*stab*crit+rnd(0,3)));def.hp=cl(def.hp-dmg,0,def.max);if(ab.effect==='heal')att.hp=cl(att.hp+Math.floor(att.max*.18),0,att.max);if(ab.effect==='burn')def.status.burn=3;if(ab.effect==='frost')def.status.frost=3;if(ab.effect==='barrier')att.status.barrier=1;if(ab.effect==='regen')att.status.regen=3;say(`${att.name} used ${ab.name}! ${mult>1?'A resonant weakness! ':''}${crit>1?'Critical! ':''}-${dmg}`);floatText('-'+dmg);renderBattle();setTimeout(()=>{if(def.hp<=0)defeat(def);else done()},700)}
function enemyTurn(){let e=B.foes[0],p=S.party[B.active];if(e.status.burn){e.hp=cl(e.hp-Math.floor(e.level*.7),0,e.max)}let ab=abilities[e.moves[rnd(0,e.moves.length-1)]];resolve(e,p,ab,()=>{B.phase='choose';renderBattle()})}function defeat(e){let xp=e.level*12;let p=S.party[B.active];p.xp+=xp;while(p.xp>=p.level*30&&p.level<50){p.xp-=p.level*30;p.level++;calc(p);p.hp=p.max;say(`${p.name} reached level ${p.level}!`)}let idx=B.foes.indexOf(e);B.foes.splice(idx,1);if(B.foes.length){say('One echo fades, but another remains.');B.phase='choose';renderBattle();return}say('The wild resonance settles.');setTimeout(endBattle,900)}
function endBattle(){let wonAnchor=B&&B.anchor;B=null;$('#battle').classList.add('hidden');$('#world').classList.remove('hidden');if(wonAnchor){S.anchors++;if(S.anchors<4){S.zone=Math.min(5,S.anchors);S.x=8;S.y=7;toast(`Anchor silenced. ${zones[S.zone][0]} is now reachable.`)}else{toast('Four anchors are quiet. The Null Choir opens.');S.zone=5}updateHud();save();story('Anchor quieted','A permanent resonance settles into your binding: +3 maximum vigor for every companion. The next ground answers your steps.');S.party.forEach(m=>{m.max+=3;m.hp=m.max})}save()}function switchMon(){let alive=S.party.filter(m=>m.hp>0);if(alive.length<2){say('No other Veyri can answer.');return}let i=(B.active+1)%S.party.length;while(S.party[i].hp<=0)i=(i+1)%S.party.length;B.active=i;say(`${S.party[i].name} takes the lead.`);B.phase='busy';setTimeout(enemyTurn,500);renderBattle()}
function attemptBind(){if(S.bag.snare<=0){say('Your snare pouch is empty.');return}let e=B.foes[0];S.bag.snare--;let chance=cl(.18+.62*(1-e.hp/e.max)+(.12),.08,.92);showModal(`<h2>Resonance window</h2><p>Settle your breath at the right moment.</p><input id="rhythm" class="rhythm" type="range" min="0" max="100" value="50"><button class="primary" onclick="finishBind(${chance})">Bind</button>`)}function finishBind(chance){let v=+$('#rhythm').value;hideModal();let bonus=1-Math.abs(v-72)/200;if(Math.random()<chance*bonus){let m=makeMon(B.foes[0].sid,B.foes[0].level);if(S.party.length<6)S.party.push(m);else S.box.push(m);if(!S.discovered.includes(m.sid))S.discovered.push(m.sid);say('The snare sings. A new companion joins you!');setTimeout(endBattle,900)}else{say('The resonance breaks free!');B.phase='busy';setTimeout(enemyTurn,600)}renderBattle()}
function floatText(txt){let f=document.createElement('div');f.className='float';f.textContent=txt;f.style.left='70%';f.style.top='42%';$('#battle').append(f);setTimeout(()=>f.remove(),1000)}
function showBagBattle(){if(S.bag.restor<=0){say('No restoratives remain.');return}S.bag.restor--;let p=S.party[B.active];p.hp=cl(p.hp+35,0,p.max);say('A soft restorative closes the cracks.');renderBattle();B.phase='busy';setTimeout(enemyTurn,500)}
function openMenu(kind){if(!S)return;let body='';if(kind==='pause')body=`<h2>Paused</h2><p class="muted">The listening-stones wait patiently.</p><div class="buttons"><button onclick="save();toast('Manual save complete.')">Save</button><button onclick="toggleAudio()">${S.muted?'Sound on':'Mute sound'}</button><button onclick="hideModal()">Return</button></div>`;if(kind==='bag')body=`<h2>Satchel</h2><div class="grid"><div class="card">Serein Snares <b>${S.bag.snare}</b><small> Basic collection items.</small></div><div class="card">Prism Snares <b>${S.bag.prism}</b><small> Premium collection items.</small></div><div class="card">Restoratives <b>${S.bag.restor}</b></div><div class="card">Resonant Shards <b>${S.bag.shard}</b></div></div><button onclick="hideModal()">Close</button>`;if(kind==='team')body=`<h2>Your Binding · ${S.party.length}/6</h2><div class="grid">${S.party.map(m=>monCard(m)).join('')}</div><button onclick="hideModal()">Close</button>`;if(kind==='map')body=`<h2>Atlas of Listening</h2><div class="grid">${zones.map((z,i)=>`<div class="card"><h3>${i<=S.zone?'◈':'?' } ${z[0]}</h3><small>${i<=S.zone?z[4]:'Unlock the prior anchor.'}</small></div>`).join('')}</div><p>Anchors silenced: ${S.anchors}/4 · Discovered: ${S.discovered.length}/27</p><button onclick="hideModal()">Close</button>`;if(kind==='ency')body=`<h2>Veyri Codex</h2><div class="grid">${species.map((m,i)=>`<div class="card"><h3>${S.discovered.includes(i)?m.name:'Unknown echo'}</h3><small>${S.discovered.includes(i)?m.lore:'Bind this echo to reveal its cadence.'}</small></div>`).join('')}</div><button onclick="hideModal()">Close</button>`;showModal(body)}function monCard(m){let d=species[m.sid],can=d.transform&&m.level>=d.transform.level&&S.bag.shard>0;return `<div class="card"><h3>${m.name} <span class="tag">${d.type.join(' / ')}</span></h3><small>Lv ${m.level} · HP ${m.hp}/${m.max} · ATK ${m.atk} · DEF ${m.def} · SPD ${m.spd}</small><div class="bar"><i style="width:${m.hp/m.max*100}%"></i></div><p>${d.lore}</p>${can?`<button onclick="transformMon(${S.party.indexOf(m)})">Use Resonant Shard</button>`:''}</div>`}function transformMon(i){let m=S.party[i],d=species[m.sid];if(!d.transform||m.level<d.transform.level||S.bag.shard<1)return;S.bag.shard--;m.sid=d.transform.form;m.name=species[m.sid].name;calc(m);m.hp=m.max;toast(`${m.name} reveals its transformed cadence!`);save();openMenu('team')}
function showModal(x){$('#modal').innerHTML=x;$('#modal').classList.remove('hidden')}function hideModal(){$('#modal').classList.add('hidden')}function toast(x){let n=$('#notice');n.textContent=x;n.classList.remove('hidden');setTimeout(()=>n.classList.add('hidden'),2400)}function toggleAudio(){S.muted=!S.muted; if(!S.muted&&!audio){audio=new (window.AudioContext||window.webkitAudioContext)();let o=audio.createOscillator(),g=audio.createGain();o.frequency.value=110;g.gain.value=.025;o.connect(g).connect(audio.destination);o.start()}save();openMenu('pause')}
</script></body></html>
<!-- agent-meta {"model":"openai/gpt-5.6-luna-pro","provider":"openrouter","persona":"full","sessionId":"8c52446b-de4f-480d-bd41-e5ea17b2ed30","tokensIn":778360,"tokensOut":33205,"tokensTotal":811565,"turns":14,"toolCalls":13,"failedToolCalls":0,"timestamp":"2026-07-12T04:41:15.841Z"} -->