Aethelgard
GPT 5.6 terra 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 33,727 bytes · SHA-256 ef97d8a23cdb
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1.0"><title>Aethelgard: Resonance Odyssey</title><script src="https://cdn.tailwindcss.com"></script><link rel="preconnect" href="https://fonts.googleapis.com"><link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=Press+Start+2P&display=swap" rel="stylesheet"><style>
:root{--bg:#080b18;--panel:rgba(18,24,48,.72);--line:rgba(169,185,255,.18);--ink:#edf0ff;--muted:#9ba7cf;--a:#8d6bff;--b:#31d8ff}*{box-sizing:border-box}body{margin:0;min-height:100vh;background:radial-gradient(circle at 20% 0%,#252256 0,transparent 32%),radial-gradient(circle at 90% 80%,#0d4053 0,transparent 30%),var(--bg);color:var(--ink);font-family:Inter,sans-serif;overflow-x:hidden}body:before{content:"";position:fixed;inset:0;pointer-events:none;opacity:.16;background-image:linear-gradient(rgba(255,255,255,.06) 1px,transparent 1px),linear-gradient(90deg,rgba(255,255,255,.05) 1px,transparent 1px);background-size:38px 38px;mask-image:linear-gradient(#000,transparent)}button{font:inherit;color:inherit;cursor:pointer}.screen{display:none;min-height:100vh;padding:26px;animation:enter .45s ease}.screen.active{display:block}.shell{max-width:1180px;margin:auto}.glass{background:var(--panel);border:1px solid var(--line);box-shadow:0 16px 55px rgba(0,0,0,.32),inset 0 1px rgba(255,255,255,.06);backdrop-filter:blur(18px);border-radius:22px}.brand{font-family:'Press Start 2P';font-size:clamp(16px,3vw,28px);line-height:1.55;background:linear-gradient(90deg,#fff,#b5c5ff 45%,#75eeff);-webkit-background-clip:text;color:transparent;text-shadow:0 0 22px #608aff55}.kicker{color:#7eeaff;text-transform:uppercase;letter-spacing:.18em;font-weight:800;font-size:11px}.btn{border:1px solid #6a67bd;background:linear-gradient(135deg,#5446bd,#246aaf);padding:12px 17px;border-radius:12px;font-weight:800;transition:.2s;box-shadow:0 6px 20px #4d3cd533}.btn:hover{transform:translateY(-2px);filter:brightness(1.18)}.btn:disabled{opacity:.4;cursor:not-allowed;transform:none}.btn.secondary{background:#1b2345;border-color:#46527d;box-shadow:none}.btn.danger{background:#742b51;border-color:#d05e88}.iconbtn{border:1px solid var(--line);background:#151b36;border-radius:10px;padding:9px 11px}.topbar{display:flex;justify-content:space-between;align-items:center;gap:12px;margin-bottom:22px}.hud{display:flex;gap:9px;align-items:center;flex-wrap:wrap}.pill{font-size:12px;padding:7px 10px;border:1px solid var(--line);border-radius:999px;background:#111832;color:#cbd4ff}.hero{min-height:580px;padding:clamp(28px,7vw,80px);display:flex;align-items:center;position:relative;overflow:hidden}.hero:after{content:"◇";font-size:420px;position:absolute;right:-70px;top:10px;color:#5dc8ff0d}.hero-copy{max-width:650px;position:relative;z-index:1}.hero h1{font-size:clamp(36px,6vw,70px);line-height:1.03;margin:14px 0 20px;letter-spacing:-.06em}.hero p{color:#bdc7ec;line-height:1.7;max-width:570px}.menu-actions{display:flex;gap:11px;flex-wrap:wrap;margin-top:27px}.tip{font-size:12px;color:var(--muted);margin-top:20px}.zone-head{padding:19px 22px;margin-bottom:18px;display:flex;justify-content:space-between;align-items:center;gap:15px;flex-wrap:wrap}.trail{padding:28px;overflow:auto}.nodes{min-width:850px;display:flex;align-items:center;justify-content:space-between;position:relative;height:340px}.nodes:before{content:"";position:absolute;left:7%;right:7%;top:50%;height:3px;background:linear-gradient(90deg,#6aab9a,#6f70e8,#e7864d);opacity:.55}.node{z-index:1;text-align:center;width:125px}.node button{width:78px;height:78px;border-radius:50%;border:2px solid #7181bf;background:#15203c;box-shadow:0 0 0 7px #10172d,0 0 22px #5577ca70;font-size:28px;transition:.25s}.node button:hover:not(:disabled){transform:scale(1.12);filter:brightness(1.2)}.node button:disabled{opacity:.25}.node .label{font-size:11px;font-weight:800;margin-top:16px}.node.done button{background:#254d50;border-color:#6ce6bd}.node.current button{border-color:#ffdc71;animation:pulse 1.6s infinite}.party-grid,.shop-grid,.dex-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:14px}.card{padding:16px}.monster-card{position:relative;overflow:hidden}.monster-card:before{content:"";position:absolute;inset:0;background:radial-gradient(circle at 85% 5%,var(--el),transparent 43%);opacity:.25;pointer-events:none}.monster-card>*{position:relative}.type{font-size:10px;font-weight:800;letter-spacing:.1em;padding:5px 8px;border-radius:7px;background:color-mix(in srgb,var(--el) 23%,#10162e);color:#fff;border:1px solid color-mix(in srgb,var(--el) 60%,transparent)}.monster-row{display:flex;gap:12px;align-items:center}.mini{width:52px;height:52px}.hpbar,.xpbar{height:9px;background:#090d1c;border-radius:99px;overflow:hidden;border:1px solid #ffffff17}.hpbar i,.xpbar i{display:block;height:100%;border-radius:99px;transition:width .5s;background:#55d786}.xpbar{height:5px;margin-top:7px}.xpbar i{background:linear-gradient(90deg,#7b6cff,#35e1ff)}.statline{display:flex;justify-content:space-between;font-size:11px;color:#bac5eb;margin-top:9px}.section-title{margin:26px 0 13px;font-size:17px}.battle{max-width:1080px;margin:auto}.arena{height:390px;padding:24px;position:relative;overflow:hidden;background:linear-gradient(160deg,#20265b99,#152c3c99)}.arena:before,.arena:after{content:"";position:absolute;width:430px;height:180px;border-radius:50%;filter:blur(3px);opacity:.6}.arena:before{background:#387f7b;bottom:-76px;left:-30px}.arena:after{background:#6e4874;top:-110px;right:-70px}.combatant{position:absolute;z-index:1;width:min(45%,360px)}.enemy{right:28px;top:28px}.ally{left:28px;bottom:28px}.combatant .monster-row{justify-content:flex-end}.ally .monster-row{justify-content:flex-start}.sprite{width:150px;height:150px;filter:drop-shadow(0 12px 13px #0008);animation:bob 2.2s ease-in-out infinite}.enemy .sprite{transform:scaleX(-1)}.battle-info{padding:11px 14px;background:#111832d9;border:1px solid #ffffff20;border-radius:13px;min-width:170px}.battle-info h3{margin:0;font-size:14px}.battle-info small{color:#abb6d8;font-size:10px}.battle-bottom{display:grid;grid-template-columns:1.1fr .9fr;gap:14px;margin-top:14px}.log{padding:18px;min-height:160px;color:#cbd4ee;line-height:1.55;font-size:14px}.actions{padding:13px;display:grid;grid-template-columns:repeat(2,1fr);gap:9px}.action{border:1px solid #3d4f80;background:#151d3a;border-radius:12px;padding:11px;text-align:left;transition:.2s}.action:hover{border-color:#7f8cff;background:#202b54}.action b{display:block;font-size:13px}.action span{font-size:10px;color:#9da8cf}.modal{position:fixed;inset:0;background:#050714b8;display:none;align-items:center;justify-content:center;padding:20px;z-index:20;backdrop-filter:blur(8px)}.modal.open{display:flex}.modal-box{width:min(650px,100%);max-height:88vh;overflow:auto;padding:22px}.modal-box h2{margin-top:0}.choice{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:10px;margin-top:8px;border:1px solid #34446f;background:#111a34;border-radius:12px}.choice.dead{opacity:.4}.toast{position:fixed;bottom:22px;left:50%;transform:translateX(-50%) translateY(90px);background:#19234a;border:1px solid #6e7ee2;padding:12px 17px;border-radius:12px;z-index:40;transition:.35s;box-shadow:0 10px 30px #0008;font-size:13px}.toast.show{transform:translateX(-50%) translateY(0)}.dex-top{padding:23px;margin-bottom:15px}.filterbar{display:flex;gap:8px;flex-wrap:wrap;margin-top:13px}.filter{padding:7px 10px;border-radius:9px;background:#151c38;border:1px solid #34436d;font-size:11px}.filter.on{border-color:#91aaff;background:#253467}.dex-card{padding:15px}.dex-card.locked{filter:grayscale(1);opacity:.45}.dex-card .sprite{width:90px;height:90px;float:right;margin-top:-15px}.dex-card p{color:#9facd1;font-size:11px;line-height:1.4;min-height:32px}.shake{animation:shake .4s}.flash{animation:flash .35s}.particles{position:absolute;inset:0;pointer-events:none;overflow:hidden}.particle{position:absolute;width:8px;height:8px;background:var(--p);border-radius:50%;animation:drift 1s ease-out forwards}@keyframes enter{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}@keyframes bob{50%{transform:translateY(-11px)}}.enemy .sprite{animation-name:bobenemy}@keyframes bobenemy{50%{transform:scaleX(-1) translateY(-11px)}}@keyframes pulse{50%{box-shadow:0 0 0 10px #252453,0 0 31px #ffe36a}}@keyframes shake{25%{transform:translateX(-9px)}75%{transform:translateX(9px)}}@keyframes flash{50%{filter:brightness(2.5)}}@keyframes drift{to{transform:translate(var(--x),var(--y)) scale(.1);opacity:0}}@media(max-width:680px){.screen{padding:14px}.arena{height:360px;padding:10px}.combatant{width:65%}.enemy{right:8px}.ally{left:8px}.sprite{width:112px;height:112px}.battle-info{min-width:135px;padding:8px}.battle-bottom{grid-template-columns:1fr}.topbar{align-items:flex-start}.hero{min-height:580px}.nodes{height:270px}.trail{padding:18px}.brand{font-size:13px}}
</style></head><body><div id="app">
<section id="menu" class="screen active"><div class="shell"><div class="topbar"><div class="brand">AETHELGARD</div><button class="iconbtn" onclick="showScreen('dex')">◈ CONDUCTOR'S DEX</button></div><div class="glass hero"><div class="hero-copy"><div class="kicker">Resonance Odyssey · v1.0</div><h1>Answer the world’s elemental call.</h1><p>Bind wild Resonants with Aether Prisms, tune a three-spirit ensemble, and climb from the living boughs of Verdant Canopy to the impossible summit of Apex Pillar.</p><div class="menu-actions"><button class="btn" onclick="beginGame()">Begin Resonance <b>→</b></button><button class="btn secondary" onclick="showScreen('camp')">Camp & Shop</button><button class="btn danger" onclick="resetGame()">Reset Progress</button></div><div class="tip">⌁ Your progress is sealed locally in this device after every choice.</div></div></div><div id="menuParty" class="party-grid" style="margin-top:18px"></div></div></section>
<section id="world" class="screen"><div class="shell"><div class="topbar"><div><div class="brand">AETHELGARD</div><div class="kicker">Harmonic trail map</div></div><div class="hud"><span class="pill">✦ <b id="shards">0</b> shards</span><button class="iconbtn" onclick="showScreen('camp')">Camp</button><button class="iconbtn" onclick="showScreen('dex')">Dex</button><button class="iconbtn" onclick="showScreen('menu')">Menu</button></div></div><div id="zoneHeader" class="glass zone-head"></div><div class="glass trail"><div id="nodes" class="nodes"></div></div><h2 class="section-title">Active Ensemble</h2><div id="worldParty" class="party-grid"></div></div></section>
<section id="battle" class="screen"><div class="battle"><div class="topbar"><div class="brand" style="font-size:15px">RESONANCE DUEL</div><div id="battleTag" class="pill">Wild harmonic</div></div><div id="arena" class="glass arena"><div class="particles" id="particles"></div><div class="combatant enemy"><div id="enemyInfo" class="battle-info"></div><div id="enemySprite"></div></div><div class="combatant ally"><div id="allySprite"></div><div id="allyInfo" class="battle-info"></div></div></div><div class="battle-bottom"><div id="battleLog" class="glass log">A frequency stirs in the aether…</div><div id="actionBox" class="glass actions"></div></div></div></section>
<section id="camp" class="screen"><div class="shell"><div class="topbar"><div><div class="brand">CONDUCTOR'S CAMP</div><div class="kicker">Repair · prepare · recalibrate</div></div><div class="hud"><span class="pill">✦ <b id="campShards">0</b> shards</span><button class="iconbtn" onclick="showScreen('world')">← Trail</button></div></div><div class="glass card"><h2 style="margin-top:0">Camp Shop</h2><p style="color:#acb8dc">Spend Aether Shards on field equipment. Supplies are retained across every expedition.</p><div id="shop" class="shop-grid"></div></div><h2 class="section-title">Your Resonants</h2><div id="campParty" class="party-grid"></div></div></section>
<section id="dex" class="screen"><div class="shell"><div class="topbar"><div><div class="brand">CONDUCTOR'S DEX</div><div class="kicker">Frequency encyclopaedia</div></div><button class="iconbtn" onclick="showScreen(lastScreen==='dex'?'menu':lastScreen)">← Back</button></div><div class="glass dex-top"><b id="dexCount">0 / 18 harmonics catalogued</b><div id="filters" class="filterbar"></div></div><div id="dexGrid" class="dex-grid"></div></div></section>
</div><div id="modal" class="modal"><div id="modalBox" class="glass modal-box"></div></div><div id="toast" class="toast"></div>
<script>
const EL={Pyro:'#ff6a4f',Hydro:'#42b8ff',Flora:'#62d98a',Volt:'#f6d94d',Zephyr:'#a3efea',Earth:'#b38a62',Cosmos:'#b38cff'};
const moves={Pyro:[['Cinder Tap',38,100,1],['Flare Arc',58,92,5],['Inferno Pulse',82,88,12],['Nova Roar',105,84,17]],Hydro:[['Ripple Jab',38,100,1],['Tidal Slice',58,94,5],['Pressure Wave',82,89,12],['Abyssal Call',105,85,17]],Flora:[['Vine Flick',38,100,1],['Petal Volley',57,94,5],['Bramble Guard',76,91,12],['Verdant Crown',103,86,17]],Volt:[['Static Nip',39,100,1],['Arc Dash',60,93,5],['Thunder Lattice',84,88,12],['Skybreaker',106,84,17]],Zephyr:[['Breeze Cut',38,100,1],['Gale Spiral',57,95,5],['Cyclone Lance',81,89,12],['Tempest Choir',103,85,17]],Earth:[['Stone Knuckle',40,100,1],['Fault Line',60,92,5],['Crystal Ram',83,88,12],['Worldsplitter',108,83,17]]};
const raw=[['Emberkit','Pyro',42,55,35,58,8,'A coal-tailed fox spirit whose purr warms frozen stones.'],['Pyrowolf','Pyro',63,76,53,76,15,'A vigilant ember wolf that patrols volcanic ley lines.'],['Ignisaur','Pyro',88,108,75,88,99,'An ancient flame titan with a furnace heart.'],['Droplet','Hydro',46,43,48,47,8,'A curious water mote with a liquid-glass crown.'],['Geoxus','Hydro',66,62,70,62,15,'A deep-current guardian armoured in riverstone.'],['Neptunian','Hydro',93,88,101,81,99,'A serene abyssal monarch that bends whole tides.'],['Seedling','Flora',48,47,49,40,8,'A sprouting guardian that listens to every root.'],['Thornback','Flora',69,69,73,52,15,'A steadfast grove beast with a mantle of thorns.'],['Bloomgoliath','Flora',98,94,103,60,99,'A walking sanctuary whose blossoms heal ruined land.'],['Sparky','Volt',40,58,33,67,8,'A bright-eared charge sprite that races lightning.'],['Boltsaber','Volt',62,82,50,91,15,'A precision hunter traced in blue-white current.'],['Stormlord','Volt',86,112,73,108,99,'A sky sovereign with thunder folded beneath its mane.'],['Gusty','Zephyr',43,44,40,64,8,'A windling that plays in the wakes of birds.'],['Slipstream','Zephyr',64,64,57,91,15,'A sleek air dancer that never leaves a footprint.'],['Zephyrus','Zephyr',89,91,78,111,99,'A horizon spirit that conducts the jetstream.'],['Pebble','Earth',52,51,62,28,8,'A patient quartz-shell spirit born under old hills.'],['Obsidian','Earth',74,74,87,40,15,'A black-glass sentinel polished by tectonic song.'],['Terrasunder','Earth',104,102,120,53,99,'A continental colossus carrying a mountain’s memory.']];
const DB=raw.map((r,i)=>({id:i,name:r[0],type:r[1],base:{hp:r[2],atk:r[3],def:r[4],spd:r[5]},evo:r[6],lore:r[7],moves:moves[r[1]].map(x=>({name:x[0],power:x[1],accuracy:x[2],level:x[3],type:r[1]}))}));
const zones=[{name:'The Verdant Canopy',range:[1,5],theme:'#67d89b',pool:[6,12,0],nodes:['wild','cache','spring','trainer','wild','boss'],boss:'Warden Liora',dialog:'“The canopy does not yield to force, Conductor. Let your harmony prove it belongs among these roots.”'},{name:'The Sunken Grotto',range:[5,10],theme:'#4bbcff',pool:[3,15,6],nodes:['wild','cache','trainer','spring','wild','boss'],boss:'Tidekeeper Orin',dialog:'“Every echo here returns changed. Show me a resonance that can endure the depths.”'},{name:'The Obsidian Crags',range:[10,15],theme:'#ff8054',pool:[0,9,15],nodes:['wild','trainer','cache','wild','spring','boss'],boss:'Forgecaller Sera',dialog:'“Heat reveals every flaw in crystal and character. Strike true, or be shattered.”'},{name:'The Apex Pillar',range:[15,20],theme:'#b794ff',pool:[9,0,3,12,15],nodes:['trainer','wild','cache','trainer','wild','boss'],boss:'Arch-Conductor Vael',dialog:'“At the apex, all elements become one song. Can you conduct the final measure?”'}];
let state,battle,lastScreen='menu',filter='All';
class Synth{constructor(){this.ctx=null}play(kind){try{this.ctx??=new AudioContext();let c=this.ctx,o=c.createOscillator(),g=c.createGain(),map={hover:[440,.035,'sine'],select:[660,.09,'square'],hit:[125,.12,'square'],element:[780,.16,'sawtooth'],level:[523,.3,'square'],capture:[880,.38,'sine']},v=map[kind]||map.hover;o.type=v[2];o.frequency.setValueAtTime(v[0],c.currentTime);o.frequency.exponentialRampToValueAtTime(v[0]*1.5,c.currentTime+v[1]);g.gain.setValueAtTime(.055,c.currentTime);g.gain.exponentialRampToValueAtTime(.001,c.currentTime+v[1]);o.connect(g);g.connect(c.destination);o.start();o.stop(c.currentTime+v[1])}catch(e){}}}const sfx=new Synth();
function fresh(){return {party:[make(0,5),make(3,4),make(6,3)],inventory:{basic:6,hyper:1,restore:2,cleanser:1},shards:60,zone:0,node:0,done:[false,false,false,false],seen:[0,3,6],caught:[0,3,6]}}
function make(id,level){let d=DB[id];return {id,level,xp:0,hp:maxhp({id,level}),status:null}}function maxhp(m){return Math.floor((DB[m.id].base.hp+12)*m.level/5)+10}function stats(m){let b=DB[m.id].base,l=m.level;return {hp:maxhp(m),atk:Math.floor((b.atk+7)*l/5)+5,def:Math.floor((b.def+7)*l/5)+5,spd:Math.floor((b.spd+7)*l/5)+5}}function xpNeed(l){return 22+l*l*8}function save(){localStorage.setItem('aethelgard-save',JSON.stringify(state))}function load(){try{state=JSON.parse(localStorage.getItem('aethelgard-save'))||fresh()}catch(e){state=fresh()}}load();
function svg(mon,cls='sprite'){let d=DB[mon.id??mon],c=EL[d.type],n=d.id%3,shape=n===0?'M90 20 L120 45 L111 105 Q90 137 58 111 L51 48Z':n===1?'M45 42 Q89 3 133 43 L143 104 Q93 146 37 106Z':'M42 33 Q93 1 145 43 L132 117 Q91 152 43 117 L29 71Z';let accent=d.type==='Pyro'?'M90 26 C120 58 75 63 99 105 C57 76 72 42 90 26':d.type==='Hydro'?'M90 24 C120 66 126 94 90 123 C53 94 61 65 90 24':d.type==='Flora'?'M90 36 C124 23 131 55 101 75 C120 104 91 119 75 89 C48 92 45 61 76 63Z':d.type==='Volt'?'M93 22 L120 63 L103 64 L123 108 L73 72 L91 70 L65 36Z':d.type==='Zephyr'?'M45 75 Q82 35 126 56 Q103 63 89 78 Q111 79 129 101 Q78 105 45 75': 'M51 93 L74 37 L112 42 L133 96 L100 122 L62 115Z';return `<svg class="${cls}" viewBox="0 0 180 160" aria-label="${d.name}"><defs><linearGradient id="g${d.id}" x1="0" x2="1"><stop stop-color="${c}"/><stop offset="1" stop-color="#f3f6ff"/></linearGradient><filter id="gl${d.id}"><feGaussianBlur stdDeviation="3" result="b"/><feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge></filter></defs><path d="${shape}" fill="#111a38" stroke="url(#g${d.id})" stroke-width="5"/><path d="${accent}" fill="${c}" opacity=".86" filter="url(#gl${d.id})"/><circle cx="70" cy="69" r="7" fill="#f7fbff"/><circle cx="110" cy="69" r="7" fill="#f7fbff"/><circle cx="70" cy="70" r="3" fill="#10182f"/><circle cx="110" cy="70" r="3" fill="#10182f"/><path d="M75 96 Q90 105 105 96" fill="none" stroke="#edf5ff" stroke-width="3" stroke-linecap="round"/></svg>`}
function showScreen(id){if(id==='dex')lastScreen=document.querySelector('.screen.active')?.id||'menu';document.querySelectorAll('.screen').forEach(x=>x.classList.toggle('active',x.id===id));if(id==='world')renderWorld();if(id==='camp')renderCamp();if(id==='dex')renderDex();if(id==='menu')renderMenu()}
function renderMonster(m){let d=DB[m.id],pct=Math.max(0,m.hp/maxhp(m)*100);return `<div class="glass card monster-card" style="--el:${EL[d.type]}"><div class="monster-row">${svg(m,'mini')}<div><b>${d.name}</b> <span class="type" style="--el:${EL[d.type]}">${d.type}</span><div class="statline"><span>Lv. ${m.level}</span><span>${Math.ceil(m.hp)}/${maxhp(m)} HP</span></div><div class="hpbar"><i style="width:${pct}%;background:${pct<25?'#f45d68':pct<55?'#f2c458':'#55d786'}"></i></div><div class="xpbar"><i style="width:${m.xp/xpNeed(m.level)*100}%"></i></div></div></div></div>`}
function renderMenu(){document.getElementById('menuParty').innerHTML=state.party.map(renderMonster).join('')}function renderWorld(){let z=zones[state.zone],locked=state.node;document.getElementById('shards').textContent=state.shards;document.getElementById('zoneHeader').innerHTML=`<div><div class="kicker">Zone ${state.zone+1} / 4 · recommended lv ${z.range[0]}–${z.range[1]}</div><h1 style="margin:5px 0;font-size:25px">${z.name}</h1></div><div class="pill">${state.done[state.zone]?'Gatekeeper attuned':'Follow the illuminated trail'}</div>`;document.getElementById('nodes').innerHTML=z.nodes.map((n,i)=>`<div class="node ${i<locked?'done':''} ${i===locked?'current':''}"><button ${i!==locked||state.done[state.zone]?'disabled':''} onclick="visit(${i})">${{wild:'♧',cache:'◇',spring:'✧',trainer:'⚔',boss:'♛'}[n]}</button><div class="label">${{wild:'Wild Signal',cache:'Mystery Cache',spring:'Healing Spring',trainer:'Wandering Conductor',boss:'Zone Gatekeeper'}[n]}</div></div>`).join('');document.getElementById('worldParty').innerHTML=state.party.map(renderMonster).join('')}
function renderCamp(){document.getElementById('campShards').textContent=state.shards;let goods=[['basic','Harmonizer Prism',18,'A stable basic capture matrix.'],['hyper','Hyper-Conductive Prism',55,'An amplified high-catch prism.'],['restore','Core Restorer',28,'Restores 50% of a Resonant’s core HP.'],['cleanser','Resonance Elixir',22,'Cleanses disruptive status frequency.']];document.getElementById('shop').innerHTML=goods.map(g=>`<div class="glass card"><b>${g[1]}</b><p style="font-size:12px;color:#aeb9dd">${g[3]}</p><div style="display:flex;justify-content:space-between;align-items:center"><span class="pill">${state.inventory[g[0]]} held</span><button class="btn" onclick="buy('${g[0]}',${g[2]})">${g[2]} ✦</button></div></div>`).join('');document.getElementById('campParty').innerHTML=state.party.map(renderMonster).join('')}
function buy(k,c){if(state.shards<c)return toast('Not enough Aether Shards.');state.shards-=c;state.inventory[k]++;save();renderCamp();sfx.play('select');toast('Supply matrix added.')}
function visit(i){let type=zones[state.zone].nodes[i];if(type==='cache'){state.shards+=20+state.zone*12;state.node++;save();renderWorld();toast('Mystery Cache: +'+(20+state.zone*12)+' Shards');sfx.play('capture')}else if(type==='spring'){state.party.forEach(m=>{m.hp=maxhp(m);m.status=null});state.node++;save();renderWorld();toast('Your ensemble resonates anew.');sfx.play('level')}else startEncounter(type)}
function enemyFor(type){let z=zones[state.zone],id;if(type==='boss')id=[8,5,2,11][state.zone];else if(type==='trainer')id=z.pool[(state.node+1)%z.pool.length];else id=z.pool[Math.floor(Math.random()*z.pool.length)];let lv=type==='boss'?z.range[1]+2:type==='trainer'?z.range[1]:z.range[0]+Math.floor(Math.random()*(z.range[1]-z.range[0]+1));return make(id,lv)}
function startEncounter(kind){battle={kind,enemy:enemyFor(kind),active:state.party.findIndex(x=>x.hp>0),busy:false};state.seen.includes(battle.enemy.id)||state.seen.push(battle.enemy.id);showScreen('battle');renderBattle();if(kind==='boss')setTimeout(()=>modal(`<h2>${zones[state.zone].boss}</h2><p>${zones[state.zone].dialog}</p><button class="btn" onclick="closeModal()">Accept the challenge</button>`),200)}
function info(m,enemy=false){let d=DB[m.id],pct=Math.max(0,m.hp/maxhp(m)*100);return `<h3>${d.name} <span class="type" style="--el:${EL[d.type]}">${d.type}</span></h3><small>Lv. ${m.level}${m.status?' · '+m.status:''}</small><div class="statline"><span>CORE</span><span>${Math.max(0,Math.ceil(m.hp))}/${maxhp(m)}</span></div><div class="hpbar"><i style="width:${pct}%;background:${pct<25?'#f45d68':pct<55?'#f2c458':'#55d786'}"></i></div>${!enemy?`<div class="xpbar"><i style="width:${m.xp/xpNeed(m.level)*100}%"></i></div>`:''}`}
function renderBattle(){let a=state.party[battle.active],e=battle.enemy;document.getElementById('battleTag').textContent=battle.kind==='boss'?zones[state.zone].boss:battle.kind==='trainer'?'Wandering Conductor':'Wild Resonant';document.getElementById('allyInfo').innerHTML=info(a);document.getElementById('enemyInfo').innerHTML=info(e,true);document.getElementById('allySprite').innerHTML=svg(a);document.getElementById('enemySprite').innerHTML=svg(e);let ms=DB[a.id].moves.filter(x=>x.level<=a.level).slice(-4);document.getElementById('actionBox').innerHTML=ms.map((m,i)=>`<button class="action" onclick="attack(${i})"><b>${m.name}</b><span>${m.type} · PWR ${m.power} · ${m.accuracy}%</span></button>`).join('')+`<button class="action" onclick="prisms()"><b>◇ Aether Prisms</b><span>${state.inventory.basic} basic · ${state.inventory.hyper} hyper</span></button><button class="action" onclick="exchange()"><b>⇄ Exchange</b><span>Retune active Resonant</span></button><button class="action" onclick="inventory()"><b>✦ Inventory</b><span>Restorers & elixirs</span></button>`}
function log(t){document.getElementById('battleLog').innerHTML=t}function typeMod(a,b){let good={Pyro:'Flora',Flora:'Hydro',Hydro:'Pyro',Zephyr:'Earth',Earth:'Volt',Volt:'Zephyr'};return good[a]===b?1.65:good[b]===a?.62:1}function particles(color){let p=document.getElementById('particles');for(let i=0;i<13;i++){let x=document.createElement('i');x.className='particle';x.style.cssText=`--p:${color};left:${25+Math.random()*55}%;top:${25+Math.random()*50}%;--x:${(Math.random()-.5)*150}px;--y:${(Math.random()-.5)*140}px`;p.append(x);setTimeout(()=>x.remove(),1100)}}
function attack(index){if(battle.busy)return;let a=state.party[battle.active],m=DB[a.id].moves.filter(x=>x.level<=a.level).slice(-4)[index];battle.busy=true;if(Math.random()*100>m.accuracy){log(`${DB[a.id].name}'s ${m.name} dissolved into static!`);return setTimeout(enemyTurn,700)}let crit=Math.random()<.1,mod=typeMod(m.type,DB[battle.enemy.id].type),dmg=Math.max(1,Math.floor((((2*a.level/5+2)*m.power*(stats(a).atk/stats(battle.enemy).def))/50+2)*mod*(.85+Math.random()*.15)*(crit?1.5:1)));battle.enemy.hp-=dmg;document.getElementById('arena').classList.add('flash');particles(EL[m.type]);sfx.play(mod>1?'element':'hit');log(`<b>${DB[a.id].name}</b> used <b>${m.name}</b>! ${mod>1?'It resonates super effectively! ':mod<1?'The frequency is resisted. ':''}${crit?'<b>Critical harmony!</b> ':''}−${dmg} core.`);setTimeout(()=>{document.getElementById('arena').classList.remove('flash');if(battle.enemy.hp<=0)winBattle();else{renderBattle();setTimeout(enemyTurn,450)}},650)}
function enemyTurn(){let e=battle.enemy,a=state.party[battle.active],m=DB[e.id].moves.filter(x=>x.level<=e.level).at(-1);if(Math.random()*100>m.accuracy){log(`${DB[e.id].name} missed ${m.name}!`);battle.busy=false;return renderBattle()}let mod=typeMod(m.type,DB[a.id].type),dmg=Math.max(1,Math.floor((((2*e.level/5+2)*m.power*(stats(e).atk/stats(a).def))/50+2)*mod*(.85+Math.random()*.15)));a.hp-=dmg;document.getElementById('arena').classList.add('shake');particles(EL[m.type]);sfx.play('hit');log(`<b>${DB[e.id].name}</b> answers with <b>${m.name}</b>! −${dmg} core.`);setTimeout(()=>{document.getElementById('arena').classList.remove('shake');if(a.hp<=0)faint();else{battle.busy=false;renderBattle()}},600)}
function faint(){let next=state.party.findIndex((m,i)=>i!==battle.active&&m.hp>0);if(next<0){state.party.forEach(m=>m.hp=Math.ceil(maxhp(m)*.5));save();modal(`<h2>Resonance scattered</h2><p>Your ensemble was returned to camp and stabilized at half core. The trail remains where you left it.</p><button class="btn" onclick="closeModal();showScreen('camp')">Return to camp</button>`)}else{battle.active=next;battle.busy=false;log('Retune a conscious Resonant!');renderBattle()}}
function winBattle(){let a=state.party[battle.active],xp=18+battle.enemy.level*10+(battle.kind==='boss'?70:0),sh=8+battle.enemy.level*3+(battle.kind==='trainer'?14:0);a.xp+=xp;state.shards+=sh;let msg=`${DB[battle.enemy.id].name}'s signal quiets. +${xp} XP · +${sh} Shards.`;while(a.xp>=xpNeed(a.level)&&a.level<25){a.xp-=xpNeed(a.level);a.level++;msg+=`<br><b>${DB[a.id].name} reached Lv. ${a.level}!</b>`;sfx.play('level');let d=DB[a.id],next=DB.find(x=>x.type===d.type&&x.id===d.id+1);if(next&&a.level===d.evo){a.id=next.id;msg+=`<br><b>✦ It evolved into ${next.name}!</b>`;state.caught.includes(next.id)||state.caught.push(next.id)}}if(battle.kind==='boss'){state.done[state.zone]=true;msg+=`<br><b>${zones[state.zone].boss} attuned the gate.</b>`;if(state.zone<3)state.zone++;state.node=0}else state.node++;save();modal(`<h2>Frequency resolved</h2><p>${msg}</p><button class="btn" onclick="closeModal();showScreen('world')">Continue trail →</button>`)}
function prisms(){if(battle.kind!=='wild')return toast('Prisms only harmonize unbound wild Resonants.');modal(`<h2>Choose Aether Prism</h2><div class="choice"><span>Harmonizer Prism <small>· ${state.inventory.basic} held</small></span><button class="btn" ${!state.inventory.basic?'disabled':''} onclick="capture('basic')">Use</button></div><div class="choice"><span>Hyper-Conductive Prism <small>· ${state.inventory.hyper} held</small></span><button class="btn" ${!state.inventory.hyper?'disabled':''} onclick="capture('hyper')">Use</button></div><button class="btn secondary" style="margin-top:15px" onclick="closeModal()">Cancel</button>`)}
function capture(kind){closeModal();state.inventory[kind]--;let e=battle.enemy,chance=(kind==='hyper'?.65:.35)+(.55*(1-e.hp/maxhp(e)))+(e.status?.1:0);battle.busy=true;particles('#c495ff');log(`The ${kind==='hyper'?'Hyper-Conductive':'Harmonizer'} Prism forms a crystalline lattice…`);setTimeout(()=>{if(Math.random()<chance){state.caught.includes(e.id)||state.caught.push(e.id);if(state.party.length<3)state.party.push({...e,hp:maxhp(e)});else state.shards+=20;save();sfx.play('capture');modal(`<h2>Harmonic secured!</h2><p><b>${DB[e.id].name}</b> joined your catalogue.${state.party.length>=3?' Your ensemble is full, so its echo was exchanged for 20 Shards.':''}</p><button class="btn" onclick="closeModal();showScreen('world')">Continue trail</button>`)}else{log('The lattice fractured! The wild signal breaks free.');battle.busy=false;renderBattle();setTimeout(enemyTurn,600)}},900)}
function exchange(){modal(`<h2>Exchange Resonant</h2>${state.party.map((m,i)=>`<div class="choice ${m.hp<=0?'dead':''}"><span>${DB[m.id].name} · Lv. ${m.level} · ${Math.max(0,Math.ceil(m.hp))} core</span><button class="btn" ${i===battle.active||m.hp<=0?'disabled':''} onclick="battle.active=${i};battle.busy=false;closeModal();renderBattle()">Tune</button></div>`).join('')}<button class="btn secondary" style="margin-top:15px" onclick="closeModal()">Cancel</button>`)}
function inventory(){modal(`<h2>Field Inventory</h2><div class="choice"><span>Core Restorer · ${state.inventory.restore} held<br><small>Restore 50% core to active Resonant</small></span><button class="btn" ${!state.inventory.restore?'disabled':''} onclick="useItem('restore')">Use</button></div><div class="choice"><span>Resonance Elixir · ${state.inventory.cleanser} held<br><small>Cleanse active status disruption</small></span><button class="btn" ${!state.inventory.cleanser?'disabled':''} onclick="useItem('cleanser')">Use</button></div><button class="btn secondary" style="margin-top:15px" onclick="closeModal()">Cancel</button>`)}function useItem(k){let a=state.party[battle.active];state.inventory[k]--;if(k==='restore')a.hp=Math.min(maxhp(a),a.hp+Math.ceil(maxhp(a)/2));else a.status=null;save();closeModal();battle.busy=true;log(k==='restore'?'The core lattice brightens.':'Static is cleansed from the frequency.');setTimeout(()=>{battle.busy=false;renderBattle();enemyTurn()},500)}
function renderDex(){let types=['All',...Object.keys(EL)];document.getElementById('filters').innerHTML=types.map(x=>`<button class="filter ${filter===x?'on':''}" onclick="filter='${x}';renderDex()">${x}</button>`).join('');let list=DB.filter(d=>filter==='All'||d.type===filter);document.getElementById('dexCount').textContent=`${state.caught.length} / 18 harmonics catalogued`;document.getElementById('dexGrid').innerHTML=list.map(d=>{let have=state.seen.includes(d.id),caught=state.caught.includes(d.id);return `<div class="glass dex-card ${have?'':'locked'}" style="--el:${EL[d.type]}">${svg({id:d.id},'sprite')}<div class="kicker">${caught?'Bound':'Uncharted'} · #${String(d.id+1).padStart(2,'0')}</div><h3>${have?d.name:'Unknown Resonant'}</h3><span class="type" style="--el:${EL[d.type]}">${have?d.type:'???'}</span><p>${have?d.lore:'An unmeasured frequency awaits discovery in Aethelgard.'}</p><small>Evolution threshold: ${d.evo===99?'Final resonance':'Lv. '+d.evo}</small></div>`}).join('')}
function modal(h){document.getElementById('modalBox').innerHTML=h;document.getElementById('modal').classList.add('open')}function closeModal(){document.getElementById('modal').classList.remove('open')}function toast(t){let x=document.getElementById('toast');x.textContent=t;x.classList.add('show');setTimeout(()=>x.classList.remove('show'),2600)}function beginGame(){showScreen('world');sfx.play('select')}function resetGame(){if(confirm('Erase this local Aethelgard expedition?')){state=fresh();save();renderMenu();toast('A new resonance begins.')}}
document.addEventListener('pointerover',e=>{if(e.target.closest('button'))sfx.play('hover')});renderMenu();
</script></body></html>
<!-- agent-meta {"model":"openai/gpt-5.6-terra-pro","provider":"openrouter","persona":"full","sessionId":"38a73170-8503-4200-8e0d-daef90ed14f2","tokensIn":456291,"tokensOut":34196,"tokensTotal":490487,"cost":0.38782365,"turns":8,"toolCalls":9,"failedToolCalls":2,"timestamp":"2026-08-01T05:30:26.370Z"} -->