← Creature Collection results

Creature Collection

GPT 5.6 terra · legacy

Initial view of Creature Collection

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 32,259 bytes · SHA-256 4cb9b04e99f4
<!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 Bindings</title><style>
:root{--ink:#eaf5ff;--dim:#a8bbd3;--glass:rgba(10,19,42,.76);--line:rgba(173,225,255,.25);--a:#61e9d2;--b:#ff9e7e;--c:#a790ff;--gold:#ffe27a}*{box-sizing:border-box}body{margin:0;background:#071021;color:var(--ink);font:14px system-ui,sans-serif;overflow:hidden;user-select:none}canvas{display:block;width:100vw;height:100vh}button{font:inherit;color:inherit;background:linear-gradient(135deg,#223c68,#182746);border:1px solid var(--line);border-radius:12px;padding:10px 14px;cursor:pointer;transition:.15s}button:hover,button:focus{background:#30558b;transform:translateY(-1px)}button:disabled{opacity:.4;cursor:default;transform:none}.screen,.modal{position:fixed;inset:0;display:flex;align-items:center;justify-content:center;background:radial-gradient(circle at 50% 35%,rgba(82,154,224,.2),transparent 48%),rgba(3,8,20,.7);z-index:10}.hidden{display:none!important}.panel{max-width:760px;width:min(94vw,760px);max-height:90vh;overflow:auto;padding:24px;border:1px solid var(--line);border-radius:22px;background:var(--glass);box-shadow:0 20px 80px #0009;backdrop-filter:blur(15px)}h1{font-size:clamp(38px,8vw,70px);letter-spacing:.12em;margin:0;text-align:center;text-shadow:0 0 26px var(--a)}h2{margin:0 0 12px;color:#d8f9ff}h3{margin:10px 0 4px}.logoSub{text-align:center;letter-spacing:.28em;color:var(--a);margin:10px 0 35px}.actions{display:flex;gap:12px;justify-content:center;flex-wrap:wrap}.primary{background:linear-gradient(135deg,#16746f,#215188);border-color:#78fff2}.tip{color:var(--dim);text-align:center;line-height:1.55}.hud{position:fixed;top:12px;left:12px;right:12px;display:flex;justify-content:space-between;pointer-events:none;z-index:3}.hudBox{background:#08142bcc;border:1px solid var(--line);padding:8px 11px;border-radius:12px;box-shadow:0 4px 18px #0008}.bar{height:9px;background:#10152a;border-radius:9px;overflow:hidden;border:1px solid #ffffff19}.bar i{display:block;height:100%;width:100%;background:linear-gradient(90deg,#58e8a1,#b6f47f);transition:width .45s}.bar.low i{background:linear-gradient(90deg,#ff756f,#ffbc74)}#notice{position:fixed;top:85px;left:50%;transform:translateX(-50%);z-index:8;background:#101c37eF;border:1px solid var(--line);padding:10px 18px;border-radius:99px;transition:.3s;pointer-events:none}.dialogue{position:fixed;bottom:72px;left:50%;transform:translateX(-50%);width:min(92vw,700px);background:#08142beb;border:1px solid var(--line);border-left:4px solid var(--a);border-radius:14px;padding:15px 19px;z-index:6;line-height:1.5}.dialogue small{display:block;color:var(--a);letter-spacing:.12em;margin-bottom:4px}.touch{position:fixed;bottom:10px;left:10px;display:grid;grid-template-columns:50px 50px 50px;grid-template-rows:42px 42px;z-index:5;opacity:.75}.touch button{padding:0;border-radius:10px}.touch .u{grid-column:2}.touch .l{grid-row:2}.touch .d{grid-row:2;grid-column:2}.touch .r{grid-row:2;grid-column:3}.battleUI{position:fixed;inset:0;pointer-events:none;z-index:4}.combatant{position:absolute;width:min(42vw,360px);padding:12px;background:#08142bd9;border:1px solid var(--line);border-radius:14px}.enemy{top:16%;left:5%}.ally{bottom:19%;right:5%}.combatant strong{font-size:16px}.combatant .meta{color:var(--dim);float:right}.status{font-size:11px;color:#ffd978;min-height:14px}.commands{position:absolute;bottom:10px;left:50%;transform:translateX(-50%);width:min(94vw,700px);display:grid;grid-template-columns:repeat(2,1fr);gap:8px;pointer-events:auto}.move{min-height:55px;text-align:left}.move small{display:block;color:var(--dim)}.float{position:fixed;z-index:9;font-size:22px;font-weight:bold;pointer-events:none;animation:float .9s forwards;text-shadow:0 2px 4px #000}@keyframes float{to{transform:translateY(-55px);opacity:0}}.shake{animation:shake .28s}@keyframes shake{25%{transform:translate(5px,-2px)}75%{transform:translate(-5px,2px)}}.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(175px,1fr));gap:10px}.card{border:1px solid var(--line);background:#101d39aa;border-radius:13px;padding:11px}.card.selected{outline:2px solid var(--a)}.aff{font-size:11px;color:var(--gold);letter-spacing:.08em}.mini{font-size:12px;color:var(--dim);line-height:1.4}.tabs{display:flex;gap:7px;flex-wrap:wrap;margin-bottom:12px}.tabs button{padding:6px 10px}.close{float:right}.slot{display:flex;align-items:center;justify-content:space-between;padding:10px;border-bottom:1px solid #ffffff16}.story{border-left:3px solid var(--c);padding-left:12px;color:#d5caff}.rhythm{text-align:center}.orb{width:130px;height:130px;border-radius:50%;margin:18px auto;background:radial-gradient(circle at 35% 30%,#fff, #62e8df 18%,#285bb2 55%,#111b5c);box-shadow:0 0 15px #69f8ff,0 0 50px #2669e9;cursor:pointer;transition:.15s}.orb.ready{transform:scale(1.17);box-shadow:0 0 25px #fff,0 0 85px #75fff7}.warn{color:#ffb19b}@media(max-width:620px){.touch{display:grid}.hud{font-size:12px}.enemy{top:10%}.ally{bottom:26%}.panel{padding:17px}.commands{bottom:4px}.dialogue{bottom:100px}}@media(min-width:621px){.touch{display:none}}
</style></head><body><canvas id="world"></canvas><div id="title" class="screen"><div class="panel"><h1>VEYRA</h1><div class="logoSub">BINDINGS OF THE LUMENWILD</div><p class="tip">The six drifting reaches are losing their anchor-song. Bind the wild echoes, restore four anchors, and learn what calls beneath the tide of light.</p><div class="actions"><button class="primary" onclick="newGame()">New Binding</button><button onclick="continueGame()" id="continue">Continue</button><button onclick="toggleSound()" id="sound">Sound: On</button></div><p class="tip">Move: WASD / arrows • Menus: mouse or touch • P pause</p></div></div><div id="hud" class="hud hidden"><div class="hudBox" id="hParty"></div><div class="hudBox" id="hZone"></div></div><div id="notice" class="hidden"></div><div id="dialogue" class="dialogue hidden"></div><div id="battle" class="battleUI hidden"><div class="combatant enemy" id="enemyBox"></div><div class="combatant ally" id="allyBox"></div><div class="commands" id="commands"></div></div><div class="touch"><button class="u" data-k="ArrowUp">▲</button><button class="l" data-k="ArrowLeft">◀</button><button class="d" data-k="ArrowDown">▼</button><button class="r" data-k="ArrowRight">▶</button></div><div id="modal" class="modal hidden"><div class="panel" id="modalContent"></div></div>
<script>
'use strict';
const C=document.getElementById('world'),X=C.getContext('2d'),$=id=>document.getElementById(id),types=['Gleam','Cinder','Tide','Bramble','Zephyr','Rune','Null'];
const typeColor={Gleam:'#ffe477',Cinder:'#ff8068',Tide:'#67bfff',Bramble:'#76e28f',Zephyr:'#b195ff',Rune:'#ff8bd4',Null:'#bdc9d8'};
// Gleam > Cinder > Tide > Gleam; Bramble > Gleam/Tide; Zephyr > Bramble/Cinder; Rune is broadly strong; Null resists all except Rune.
const moves=[
['Glint Peck','Gleam',10,95,''],['Halo Mend','Gleam',0,100,'heal'],['Prism Spur','Gleam',17,88,'priority'],['Sunspoke','Gleam',25,85,'burn'],['Lumen Lash','Gleam',31,85,'multi'],['Dawn Ward','Gleam',0,100,'barrier'],
['Ember Knot','Cinder',11,96,'burn'],['Coal Skip','Cinder',16,92,'speed'],['Ashwheel','Cinder',22,89,'multi'],['Furnace Call','Cinder',30,82,'burn'],['Sear Pulse','Cinder',19,90,'shock'],['Kindle Veil','Cinder',0,100,'barrier'],
['Rill Dart','Tide',10,97,''],['Undertow','Tide',18,91,'frost'],['Mistsalve','Tide',0,100,'heal'],['Wave Needle','Tide',24,88,'multi'],['Drown Chime','Tide',30,84,'frost'],['Current Step','Tide',14,100,'priority'],
['Thorn Tether','Bramble',11,95,''],['Verdant Sip','Bramble',0,100,'regen'],['Briar Burst','Bramble',20,90,''],['Root Lock','Bramble',17,90,'frost'],['Canopy Crash','Bramble',29,82,'multi'],['Sap Shield','Bramble',0,100,'barrier'],
['Draft Pin','Zephyr',11,97,'speed'],['Gale Flick','Zephyr',17,93,''],['Whistle Shock','Zephyr',21,89,'shock'],['Sky Stitch','Zephyr',0,100,'heal'],['Cyclone Arc','Zephyr',30,83,'multi'],['Slipstream','Zephyr',14,100,'priority'],
['Sigil Tap','Rune',12,96,''],['Glyph Frost','Rune',18,91,'frost'],['Markflare','Rune',22,88,'burn'],['Arc Echo','Rune',28,84,'multi'],['Quiet Hex','Rune',17,90,'shock'],['Rune Bloom','Rune',0,100,'regen'],
['Still Strike','Null',13,96,''],['Hush Field','Null',0,100,'barrier'],['Pale Draw','Null',18,91,'heal'],['Vacant Pulse','Null',22,87,'shock'],['Grey Orbit','Null',29,83,'multi'],['Zero Step','Null',15,100,'priority']];
const M=Object.fromEntries(moves.map((m,i)=>[m[0],{n:m[0],t:m[1],p:m[2],a:m[3],e:m[4],cost:m[2]?1+Math.floor(m[2]/11):2}]));
const raw=[
['Auralet','Gleam',36,13,9,15,'A candle-winged scout that gathers stray colors at daybreak. Its soft chirr marks safe paths.',0],['Brisken','Cinder',40,15,8,12,'A small furnace beast with a pebble shell. It naps beside warm fault-lines.',1],['Nerilli','Tide',43,10,12,11,'Its glassy fins hum whenever rain is near. It keeps droplets suspended above its brow.',2],['Mossel','Bramble',48,11,14,7,'A patient knot of moss and antler-vines. Fallen seeds awaken in its footprints.',3],['Vellune','Zephyr',35,12,8,18,'A ribbon-tailed glider that sleeps in updrafts. It can hear doors opening miles away.',4],['Scrypt','Rune',39,14,10,12,'Tiny symbols rotate within its lantern body. It is drawn to unfinished promises.',5],['Pallid','Null',54,12,15,6,'A silent creature shaped from the pauses between echoes. It watches without blinking.',6],['Cindrel','Cinder',47,18,10,10,'A coal-maned runner that leaves harmless sparks in tall grass.',1],['Tideroot','Tide/Bramble',50,13,14,8,'Its roots drink from hidden springs while its crest navigates moonlit water.',2],['Glimmerjaw','Gleam',45,17,9,13,'Its mirrored teeth split light into tiny guiding stars.',0],['Breezle','Zephyr',38,10,9,20,'A curious spiral of feathers that borrows hats from travelers.',4],['Runebit','Rune',42,16,11,11,'It carves temporary maps into stone with a patient little claw.',5],['Hollowmoth','Null',46,14,12,13,'Its wings make no sound, even in a storm. It nests in abandoned bells.',6],['Briarva','Bramble',52,14,16,7,'This guardian of seedlings wears a crown of bright thorns.',3],['Siltfin','Tide',41,15,10,15,'It skims shallow water as though it were polished glass.',2],['Pyrel','Cinder/Gleam',39,16,8,16,'A swift ember-kite whose tail scribes warm loops in the air.',1],['Auricub','Gleam',50,15,13,9,'It hoards sun-warmed stones and shares them only with trusted friends.',0],['Zephram','Zephyr/Rune',44,15,10,17,'A cloud-horned wanderer that plays tones through its hollow crest.',4],
['Auralis','Gleam',66,25,18,23,'Its wide wings turn twilight into a gentle beacon. It leads lost flocks home.',0],['Briskarn','Cinder',72,29,16,18,'An ancient heat pulses under its basalt plates. Its roar wakes sleeping vents.',1],['Nerivane','Tide',76,20,25,17,'A river-crown blooms along its back, holding water clear as memory.',2],['Mossovar','Bramble',82,22,30,12,'An old grove walks wherever it wishes. New paths root behind it.',3],['Vellurion','Zephyr',63,23,16,31,'It sails the highest currents and gathers thunder in its silver plumes.',4],['Scryptor','Rune',70,28,20,19,'A constellation of living marks flows under its crystal hide.',5],['Palladon','Null',88,22,31,11,'It carries a tranquil absence that quiets even the noisiest storms.',6],['Cindrelix','Cinder',75,32,18,16,'Its ember mane has become a bright, deliberate crown.',1],['Tiderune','Tide/Bramble',80,24,27,14,'A moving estuary follows in its wake, full of shining reeds.',2]];
const species=raw.map((r,i)=>({id:i,n:r[0],aff:r[1].split('/'),hp:r[2],at:r[3],df:r[4],sp:r[5],lore:r[6],family:r[7],evo:i>=18}));
const zones=[
['Morrow Verge',['#18396a','#56a8bd'],.15,'First Bell','The verge hums with a new binding. Find the pale shrine ahead.'],['Cinderfold',['#4b1d37','#cf684d'],.19,'Ember Anchor','The ember anchor sputters beneath a ridge of singing stone.'],['Tideglass Basin',['#12395e','#42b7ca'],.22,'Tide Anchor','A clear basin reflects a sky that does not belong to this hour.'],['Bramble Choir',['#173f37','#6aaf65'],.25,'Root Anchor','The choir grove has forgotten the cadence that holds its roots.'],['Zephyr Steps',['#3a3771','#a77dda'],.28,'Sky Anchor','Wind-stairs lead toward a broken chord in the clouds.'],['Null Meridian',['#20263c','#68748e'],.32,'The Quiet Gate','Beyond the anchors, the Meridian listens for every bound echo.']];
let S,scene='title',battle=null,muted=false,ac=null,particles=[],last=0;
function fresh(){return {v:1,zone:0,x:3,y:4,unlocked:0,anchors:0,story:0,tutorial:0,party:[make(0,5)],box:[],seen:[0],caught:[0],bag:{wisp:8,orbit:2,crown:0,tonic:3,panacea:1,ember:1,tideseed:1},bonus:{hp:0,at:0,df:0,sp:0},shrine:{0:{x:3,y:4}},mute:false};}
function make(id,lvl){let q=species[id],learn=learnset(q,lvl);return {id,lvl,xp:0,hp:maxhp({id,lvl}),energy:8,status:[],moves:learn};}
function maxhp(c){let q=species[c.id];return Math.floor(q.hp+(c.lvl-1)*(2+q.hp/38)+S?.bonus.hp||q.hp)}function stat(c,k){let q=species[c.id],b={at:q.at,df:q.df,sp:q.sp}[k];let v=Math.floor(b+(c.lvl-1)*(1+b/42)+(S?.bonus[k]||0));if(k==='at'&&c.status.includes('Burn'))v=Math.max(1,Math.floor(v/2));if(k==='sp'&&c.status.includes('Frost'))v=Math.max(1,Math.floor(v/2));if(k==='sp'&&c.status.includes('Swift'))v=Math.floor(v*1.35);return v;}
function learnset(q,l){let pool=moves.filter(m=>m[1]===q.aff[0]).map(x=>x[0]);if(q.aff[1])pool=pool.concat(moves.filter(m=>m[1]===q.aff[1]).map(x=>x[0])); return [...new Set(pool.slice(0,Math.min(4,1+Math.floor(l/6))))];}
function save(){if(S)localStorage.setItem('veyraBinding',JSON.stringify(S));}function load(){try{return JSON.parse(localStorage.getItem('veyraBinding'))}catch(e){return null}}
function newGame(){S=fresh();scene='world';$('title').classList.add('hidden');$('hud').classList.remove('hidden');resize();say('ORIEL, KEEPER OF THE VERGE','Welcome, binder. Move with the arrow keys or the touch compass. Walk to the luminous shrine.');draw();}
function continueGame(){let z=load();if(!z){notice('No binding record yet. Begin a New Binding.');return}S=z;muted=!!S.mute;scene='world';$('title').classList.add('hidden');$('hud').classList.remove('hidden');resize();notice('Returned to the last shrine.');draw();}
$('continue').onclick=continueGame;function resize(){C.width=innerWidth*devicePixelRatio;C.height=innerHeight*devicePixelRatio;X.setTransform(devicePixelRatio,0,0,devicePixelRatio,0,0);}
addEventListener('resize',resize);addEventListener('keydown',e=>{if(e.key==='p'||e.key==='P'){if(scene==='world')menu();return}if(scene==='world'&&['ArrowUp','ArrowDown','ArrowLeft','ArrowRight','w','a','s','d','W','A','S','D'].includes(e.key)){e.preventDefault();move(e.key)}});document.querySelectorAll('[data-k]').forEach(b=>b.onclick=()=>move(b.dataset.k));
function move(k){if(scene!=='world'||$('modal').classList.contains('hidden')===false)return;let d={ArrowUp:[0,-1],w:[0,-1],W:[0,-1],ArrowDown:[0,1],s:[0,1],S:[0,1],ArrowLeft:[-1,0],a:[-1,0],A:[-1,0],ArrowRight:[1,0],d:[1,0],D:[1,0]}[k];if(!d)return;S.x=Math.max(0,Math.min(8,S.x+d[0]));S.y=Math.max(0,Math.min(6,S.y+d[1]));interact();draw();}
function interact(){let shrine=S.x===3&&S.y===4,anchor=S.x===7&&S.y===1;if(shrine){shrineMenu();return}if(anchor){guardian();return}if(S.tutorial===0){S.tutorial=1;say('ORIEL','The ground has answered. A wild echo approaches—choose a resonance.');setTimeout(()=>startBattle([wild(0,4)],true),500);return}if(Math.random()<zones[S.zone][2]){let count=(S.zone>=3&&Math.random()<.28)?(Math.random()<.35?3:2):1;startBattle(Array.from({length:count},()=>wild(S.zone)),false);}}
function wild(z){let available=species.map((q,i)=>i).filter(i=>!species[i].evo&&((i%6)<=z+1));let id=available[Math.floor(Math.random()*available.length)],base=4+z*5+(S.anchors===4?5:0);return make(id,Math.min(50,base+Math.floor(Math.random()*5)));}
function guardian(){if(S.zone>3){if(S.anchors>=4){say('ORIEL','The four anchors sing together. The Quiet Gate opens—but the Meridian has no guardian to defeat. You have restored the reaches.');S.story=4;save();return}notice('A distant anchor remains silent.');return}if(S.anchors>S.zone){notice('This anchor is already bright.');return}let fam=[1,2,3,4][S.zone],id=[19,20,21,22][S.zone];say('ANCHOR ECHO',zones[S.zone][3]+' rises to test the strength of your bonds.');setTimeout(()=>startBattle([make(id,10+S.zone*8)],false,true),450);}
function draw(){if(scene!=='world')return;let w=innerWidth,h=innerHeight,z=zones[S.zone],g=X.createLinearGradient(0,0,w,h);g.addColorStop(0,z[1][0]);g.addColorStop(1,z[1][1]);X.fillStyle=g;X.fillRect(0,0,w,h);let tw=w/9,th=h/7;for(let y=0;y<7;y++)for(let x=0;x<9;x++){X.fillStyle=(x+y)%2?'#ffffff0b':'#0000000b';X.fillRect(x*tw,y*th,tw-1,th-1)}for(let i=0;i<35;i++){let px=(i*83+performance.now()*.015*(i%3+1))%w,py=(i*137+Math.sin(performance.now()/900+i)*35)%h;X.fillStyle=typeColor[types[(i+S.zone)%7]]+'88';X.beginPath();X.arc(px,py,1+(i%3),0,7);X.fill()}let sx=3*tw+tw/2,sy=4*th+th/2;X.fillStyle='#d7ffff';X.shadowBlur=25;X.shadowColor='#62fff2';X.beginPath();X.arc(sx,sy,Math.min(tw,th)*.23,0,7);X.fill();X.shadowBlur=0;let ax=7*tw+tw/2,ay=1*th+th/2;X.fillStyle=S.anchors>S.zone?'#fff1a0':'#6a5a83';X.beginPath();X.moveTo(ax,ay-25);X.lineTo(ax+20,ay);X.lineTo(ax,ay+25);X.lineTo(ax-20,ay);X.fill();let px=S.x*tw+tw/2,py=S.y*th+th/2;X.fillStyle='#fff';X.shadowBlur=18;X.shadowColor='#75ffff';X.beginPath();X.arc(px,py,16,0,7);X.fill();X.fillStyle='#1e5b88';X.beginPath();X.arc(px,py,9,0,7);X.fill();X.shadowBlur=0;hud();requestAnimationFrame(draw)}
function hud(){if(!S)return;let p=S.party[0];$('hParty').innerHTML='<b>'+species[p.id].n+'</b> Lv '+p.lvl+'<div class="bar '+(p.hp/maxhp(p)<.3?'low':'')+'"><i style="width:'+100*p.hp/maxhp(p)+'%"></i></div>';$('hZone').innerHTML='<b>'+zones[S.zone][0]+'</b><br><span style="color:#a8bbd3">Anchors '+S.anchors+'/4 · '+S.caught.length+'/8 bound</span>';}
function say(w,t){$('dialogue').innerHTML='<small>'+w+'</small>'+t+' <span style="color:#78fff2">[tap]</span>';$('dialogue').classList.remove('hidden');$('dialogue').onclick=()=>$('dialogue').classList.add('hidden');}function notice(t){let n=$('notice');n.textContent=t;n.classList.remove('hidden');clearTimeout(n._t);n._t=setTimeout(()=>n.classList.add('hidden'),2500)}
function shrineMenu(){open('<button class="close" onclick="closeModal()">×</button><h2>Luminous Shrine</h2><p class="tip">The shrine remembers your shape and refills the warm current.</p><div class="actions"><button class="primary" onclick="rest()">Rest & Save</button><button onclick="shop()">Wayfarer Cache</button><button onclick="menu()">Binding Ledger</button></div>');}
function rest(){S.party.forEach(c=>{c.hp=maxhp(c);c.energy=8;c.status=[]});S.shrine[S.zone]={x:S.x,y:S.y};save();closeModal();notice('The shrine restores every bound echo.');}
function shop(){open('<button class="close" onclick="shrineMenu()">←</button><h2>Wayfarer Cache</h2><p class="tip">Anchor light has stocked modest supplies.</p><div class="grid"><div class="card">Wisp Capsule ×2<br><button onclick="buy(\'wisp\',2)">Take</button></div><div class="card">Orbit Capsule ×1<br><button onclick="buy(\'orbit\',1)">Take</button></div><div class="card">Glow Tonic ×1<br><button onclick="buy(\'tonic\',1)">Take</button></div></div>');}function buy(k,n){S.bag[k]=(S.bag[k]||0)+n;notice('Added to your field pouch.');save();}
function menu(){if(scene!=='world')return;open('<button class="close" onclick="closeModal()">×</button><h2>Binding Ledger</h2><div class="tabs"><button onclick="teamTab()">Team</button><button onclick="bagTab()">Pouch</button><button onclick="dexTab()">Echo Taxonomy</button><button onclick="mapTab()">Reach Map</button><button onclick="manualSave()">Save</button></div><div id="tab"></div>');teamTab();}
function teamTab(){let html='<h3>Bound Team ('+S.party.length+'/6)</h3>';S.party.forEach((c,i)=>{let q=species[c.id];html+='<div class="slot"><span><b>'+q.n+'</b> Lv '+c.lvl+' <span class="aff">'+q.aff.join(' / ')+'</span><br><span class="mini">HP '+c.hp+'/'+maxhp(c)+' · '+c.moves.join(', ')+'</span></span><span>'+(!q.evo&&c.lvl>=12?'<button onclick="transform('+i+')">Transform</button>':'')+'</span></div>'});$('tab').innerHTML=html;}function bagTab(){$('tab').innerHTML='<h3>Field Pouch</h3><div class="grid">'+Object.entries(S.bag).map(([k,v])=>'<div class="card"><b>'+({wisp:'Wisp Capsule',orbit:'Orbit Capsule',crown:'Crown Capsule',tonic:'Glow Tonic',panacea:'Clear Tonic',ember:'Ember Kernel',tideseed:'Tide Seed'}[k]||k)+'</b><br>× '+v+'</div>').join('')+'</div><p class="mini">Catalysts transform compatible echoes at level 12 or higher. Ember Kernel favors Cinder families; Tide Seed favors Tide families.</p>';}function dexTab(){$('tab').innerHTML='<h3>Echo Taxonomy · '+S.caught.length+'/27 bound</h3><div class="grid">'+species.map((q,i)=>S.seen.includes(i)?'<div class="card '+(S.caught.includes(i)?'selected':'')+'"><b>'+q.n+'</b><div class="aff">'+q.aff.join(' · ')+'</div><div class="mini">'+q.lore+'</div></div>':'<div class="card mini">Unheard echo</div>').join('')+'</div>';}function mapTab(){$('tab').innerHTML='<h3>Six Reaches</h3>'+zones.map((z,i)=>'<div class="card '+(i===S.zone?'selected':'')+'"><b>'+z[0]+'</b> '+(i<=S.unlocked?'<button onclick="travel('+i+')">Travel</button>':'<span class="mini"> sealed</span>')+'<div class="mini">'+z[4]+'</div></div>').join('');}function travel(i){S.zone=i;let r=S.shrine[i]||{x:3,y:4};S.x=r.x;S.y=r.y;closeModal();save();notice('Crossing into '+zones[i][0]+'.');}function manualSave(){save();notice('Binding recorded.');}
function transform(i){let c=S.party[i],q=species[c.id],target=species.findIndex(x=>x.evo&&x.family===q.family);if(target<0){notice('This echo has no further form.');return}let catalyst=q.aff.includes('Cinder')?'ember':q.aff.includes('Tide')?'tideseed':null;if(catalyst&&!(S.bag[catalyst]>0)){notice('A '+(catalyst==='ember'?'Ember Kernel':'Tide Seed')+' is needed.');return}if(catalyst)S.bag[catalyst]--;c.id=target;c.hp=maxhp(c);c.moves=learnset(species[target],c.lvl);if(!S.caught.includes(target))S.caught.push(target);if(!S.seen.includes(target))S.seen.push(target);notice(q.n+' unfolded into '+species[target].n+'!');teamTab();save();}
function open(html){$('modalContent').innerHTML=html;$('modal').classList.remove('hidden');}function closeModal(){$('modal').classList.add('hidden');}
function typeMult(at,def){let r=1;if(at==='Rune')r=1.15;if(def==='Null')r=at==='Rune'?1.5:.6;let beats={Gleam:['Cinder'],Cinder:['Tide'],Tide:['Gleam'],Bramble:['Gleam','Tide'],Zephyr:['Bramble','Cinder']}[at]||[];if(beats.includes(def))r*=1.55;return r;}
function startBattle(enemies,tutorial=false,boss=false){scene='battle';battle={foes:enemies,active:0,foe:0,tutorial,boss,turn:0};$('battle').classList.remove('hidden');$('dialogue').classList.add('hidden');enemies.forEach(e=>{if(!S.seen.includes(e.id))S.seen.push(e.id)});notice(tutorial?'Select a resonance to begin.':'Wild echoes converge!');renderBattle();}
function aliveParty(){return S.party.filter(c=>c.hp>0)}function current(){return S.party[battle.active]}function foe(){return battle.foes[battle.foe]}function renderBattle(){if(scene!=='battle')return;let a=current(),e=foe(),aq=species[a.id],eq=species[e.id];$('allyBox').innerHTML='<strong>'+aq.n+'</strong> <span class="meta">Lv '+a.lvl+'</span><div class="bar '+(a.hp/maxhp(a)<.3?'low':'')+'"><i style="width:'+100*a.hp/maxhp(a)+'%"></i></div><span class="mini">HP '+a.hp+'/'+maxhp(a)+' · Energy '+a.energy+'/8</span><div class="status">'+a.status.join(' · ')+'</div>';$('enemyBox').innerHTML='<strong>'+eq.n+'</strong> <span class="meta">Lv '+e.lvl+'</span><div class="bar"><i style="width:'+100*e.hp/maxhp(e)+'%"></i></div><span class="mini">HP '+e.hp+'/'+maxhp(e)+' · '+eq.aff.join(' / ')+'</span><div class="status">'+e.status.join(' · ')+'</div>';let cmd=a.moves.map((n,i)=>{let m=M[n];return '<button class="move" '+(a.energy<m.cost?'disabled':'')+' onclick="act('+i+')"><b style="color:'+typeColor[m.t]+'">'+m.n+'</b><small>'+m.t+' · '+m.p+' force · '+m.a+'% · '+m.cost+' energy</small></button>'}).join('');cmd+='<button class="move" onclick="switchMenu()"><b>Rotate Binding</b><small>Choose another conscious ally</small></button><button class="move" onclick="captureMenu()"><b>Cast Capsule</b><small>Bind this echo while its light is low</small></button>';$('commands').innerHTML=cmd;}
function act(i){let a=current(),m=M[a.moves[i]];if(a.energy<m.cost)return;resolve(a,foe(),m,()=>{if(foe().hp<=0)return defeatFoe();enemyTurn();});}function enemyTurn(){if(scene!=='battle')return;let e=foe(),pool=e.moves.map(n=>M[n]).filter(m=>m.p||m.e==='heal'),m=pool[Math.floor(Math.random()*pool.length)]||M['Still Strike'];setTimeout(()=>resolve(e,current(),m,()=>{if(current().hp<=0)knockout();else {endTick();renderBattle()}}),500);}
function resolve(att,tar,m,done){if(att.status.includes('Shock')&&Math.random()<.25){notice(species[att.id].n+' faltered in the shock!');done();return}att.energy=Math.max(0,att.energy-m.cost);if(m.p&&Math.random()*100>m.a){notice(species[att.id].n+' missed '+m.n+'!');done();return}if(m.e==='heal'){let h=Math.floor(maxhp(att)*.28);att.hp=Math.min(maxhp(att),att.hp+h);floatNum(att===current()?'.ally':'.enemy','+'+h,'#79f5aa');notice(species[att.id].n+' used '+m.n+'.');done();return}if(m.e==='barrier'){att.status=att.status.filter(x=>x!=='Barrier');att.status.push('Barrier');notice(species[att.id].n+' raised a Barrier.');done();return}let mult=typeMult(m.t,species[tar.id].aff[0]);if(species[tar.id].aff[1])mult=Math.max(mult,typeMult(m.t,species[tar.id].aff[1]));if(species[att.id].aff.includes(m.t))mult*=1.25;let crit=Math.random()<.1;if(crit)mult*=1.5;let hits=m.e==='multi'?2+Math.floor(Math.random()*2):1,total=0;for(let i=0;i<hits;i++){let d=Math.max(1,Math.floor(.4*att.lvl*stat(att,'at')/Math.max(1,stat(tar,'df'))*mult+(Math.random()*4)));if(tar.status.includes('Barrier')){tar.status=tar.status.filter(x=>x!=='Barrier');d=0;notice('Barrier deflected the strike!')}tar.hp=Math.max(0,tar.hp-d);total+=d}if(m.e==='burn'&&!tar.status.includes('Burn'))tar.status.push('Burn');if(m.e==='frost'&&!tar.status.includes('Frost'))tar.status.push('Frost');if(m.e==='shock'&&!tar.status.includes('Shock'))tar.status.push('Shock');if(m.e==='regen'&&!att.status.includes('Regen'))att.status.push('Regen');if(m.e==='speed'&&!att.status.includes('Swift'))att.status.push('Swift');floatNum(tar===current()?'.ally':'.enemy','-'+total,crit?'#fff5a5':'#fff');if(mult>1.25){notice((crit?'CRITICAL! ':'')+'Resonance surges!');burst();}else if(mult<.9)notice('The resonance dulls.');done();}
function endTick(){[current(),foe()].forEach(c=>{if(c.hp<=0)return;if(c.status.includes('Burn'))c.hp=Math.max(0,c.hp-Math.max(1,Math.floor(maxhp(c)*.07)));if(c.status.includes('Regen'))c.hp=Math.min(maxhp(c),c.hp+Math.floor(maxhp(c)*.06));c.energy=Math.min(8,c.energy+1)});if(current().hp<=0)knockout();else if(foe().hp<=0)defeatFoe();}
function knockout(){let next=S.party.findIndex(c=>c.hp>0);if(next<0){endBattle(false);return}battle.active=next;notice(species[current().id].n+' fades—another binding steps forward.');renderBattle();}function defeatFoe(){let e=foe(),gain=Math.floor(8+e.lvl*5*Math.max(.6,e.lvl/current().lvl));notice(species[e.id].n+' dissolved into motes. +'+gain+' resonance.');gainXP(current(),gain);battle.foe++;if(battle.foe<battle.foes.length){renderBattle();return}if(battle.boss){S.anchors++;S.unlocked=Math.max(S.unlocked,Math.min(5,S.anchors));let b=['hp','at','df','sp'][S.anchors-1];S.bonus[b]+=3;S.story=Math.max(S.story,S.anchors);say('ANCHOR RESTORED',zones[S.zone][3]+' ignites. Your bound echoes gain a permanent '+b.toUpperCase()+' weave. '+(S.anchors===4?'All four anchors harmonize; the Quiet Gate can now be heard.':'A new reach opens.'));}endBattle(true);}
function gainXP(c,n){c.xp+=n;while(c.xp>=c.lvl*18&&c.lvl<50){c.xp-=c.lvl*18;c.lvl++;c.hp=maxhp(c);let before=c.moves.join();c.moves=learnset(species[c.id],c.lvl);notice(species[c.id].n+' reached level '+c.lvl+'!'+(before!==c.moves.join()?' It shaped a new resonance.':''));}}
function endBattle(win){$('battle').classList.add('hidden');scene='world';battle=null;if(!win){let r=S.shrine[S.zone]||{x:3,y:4};S.x=r.x;S.y=r.y;S.party.forEach(c=>{c.hp=Math.max(1,Math.floor(maxhp(c)*.5));c.status=[]});say('ORIEL','The shrine gathers your scattered light. Return wiser; no binding is broken forever.')}else if(S.tutorial===1){S.tutorial=2;say('ORIEL','A loosened echo can be bound. In the next encounter, use a capsule after weakening it. Shrines restore and record your journey.')}save();renderBattle();}
function switchMenu(){let choices=S.party.map((c,i)=>'<button '+(i===battle.active||c.hp<=0?'disabled':'')+' onclick="doSwitch('+i+')">'+species[c.id].n+' Lv '+c.lvl+' · '+c.hp+'/'+maxhp(c)+'</button>').join(' ');open('<button class="close" onclick="closeModal()">×</button><h2>Rotate Binding</h2>'+choices);}function doSwitch(i){battle.active=i;closeModal();notice(species[current().id].n+' enters the current.');setTimeout(enemyTurn,250);renderBattle();}
function captureMenu(){let h='<button class="close" onclick="closeModal()">×</button><h2>Choose a Capsule</h2><p class="tip">Match the pulse: tap the orb when it brightens. Precision adds to the binding chance.</p>';[['wisp','Wisp Capsule',.35],['orbit','Orbit Capsule',.58],['crown','Crown Capsule',.8]].forEach(x=>h+='<button '+(!S.bag[x[0]]?'disabled':'')+' onclick="beginCapture(\''+x[0]+'\','+x[2]+')">'+x[1]+' ×'+(S.bag[x[0]]||0)+'</button> ');open(h);}
function beginCapture(k,q){S.bag[k]--;let taps=0,active=true;open('<h2>Binding Pulse</h2><div class="rhythm"><p>Tap as the core expands — 3 pulses.</p><div class="orb" id="orb"></div><b id="pulse">Prepare…</b></div>');let orb=$('orb'),p=$('pulse'),count=0;let timer=setInterval(()=>{if(!active)return;orb.classList.toggle('ready');p.textContent=orb.classList.contains('ready')?'NOW':'Listen…'},480);orb.onclick=()=>{if(!active)return;if(orb.classList.contains('ready'))taps++;count++;if(count>=3){active=false;clearInterval(timer);finishCapture(q,taps)}};}
function finishCapture(quality,taps){let e=foe(),chance=Math.min(.94,quality*.45+(1-e.hp/maxhp(e))*.5+taps*.08);closeModal();if(Math.random()<chance){let c=make(e.id,e.lvl);c.hp=Math.max(1,e.hp);if(S.party.length<6)S.party.push(c);else S.box.push(c);if(!S.caught.includes(e.id))S.caught.push(e.id);notice(species[e.id].n+' is bound to your chorus!');if(S.caught.length>=8&&S.anchors>=4)say('ORIEL','Eight unique echoes answer your call. The Lumenwild is whole enough to wander freely.');endBattle(true)}else{notice('The echo slips free!');setTimeout(enemyTurn,400)}save();}
function floatNum(selector,t,col){let r=document.querySelector(selector)?.getBoundingClientRect();if(!r)return;let d=document.createElement('div');d.className='float';d.textContent=t;d.style.color=col;d.style.left=(r.left+r.width/2)+'px';d.style.top=(r.top+r.height/2)+'px';document.body.append(d);setTimeout(()=>d.remove(),900)}function burst(){document.body.classList.add('shake');setTimeout(()=>document.body.classList.remove('shake'),280)}
function toggleSound(){muted=!muted;if(S)S.mute=muted;$('sound').textContent='Sound: '+(muted?'Off':'On');if(!muted)tone(220,.06);save();}function tone(f,d){if(muted)return;try{ac=ac||new AudioContext();let o=ac.createOscillator(),g=ac.createGain();o.frequency.value=f;o.type='sine';g.gain.setValueAtTime(.025,ac.currentTime);g.gain.exponentialRampToValueAtTime(.001,ac.currentTime+d);o.connect(g);g.connect(ac.destination);o.start();o.stop(ac.currentTime+d)}catch(e){}}
setInterval(()=>{if(scene==='world'&&!muted&&Math.random()<.22)tone(160+S.zone*35,.13)},2600);window.newGame=newGame;window.continueGame=continueGame;window.toggleSound=toggleSound;window.closeModal=closeModal;window.rest=rest;window.shop=shop;window.menu=menu;window.teamTab=teamTab;window.bagTab=bagTab;window.dexTab=dexTab;window.mapTab=mapTab;window.travel=travel;window.manualSave=manualSave;window.buy=buy;window.transform=transform;window.act=act;window.switchMenu=switchMenu;window.doSwitch=doSwitch;window.captureMenu=captureMenu;window.beginCapture=beginCapture;resize();
</script></body></html>