← Deckbuilder results

Deckbuilder

GPT 5.6 Luna Pro · typescript

Initial view of Deckbuilder

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 23,464 bytes · SHA-256 776da4cae1e6
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Shadows of Aethelgard</title>
<style>
/* ── css: base ── */
@import url('https://fonts.googleapis.com/css2?family=Cinzel:wght@500;600;700;800&family=Manrope:wght@400;500;600;700&display=swap');
:root{--ink:#090b12;--panel:#131725;--panel2:#1a2030;--line:#30394d;--muted:#8590a7;--paper:#d9cdb0;--gold:#d6a84d;--red:#d85d57;--blue:#66a4c8;--violet:#a477cc;--green:#83b88e}*{box-sizing:border-box}body{margin:0;background:#080b12;color:var(--paper);font:13px Manrope,system-ui,sans-serif;letter-spacing:.02em}button{font:inherit;color:inherit;cursor:pointer}#game{min-height:100vh;position:relative;overflow:hidden;background:radial-gradient(ellipse at 50% -20%,#28314b 0,#111625 38%,#080b12 75%)}.noise{position:absolute;inset:0;opacity:.04;pointer-events:none;background:repeating-linear-gradient(0deg,transparent 0 3px,#fff 4px,#fff 5px)}.topbar{height:82px;border-bottom:1px solid #2d3546;background:rgba(8,11,18,.72);display:flex;align-items:center;justify-content:space-between;padding:0 5.5vw;position:relative;z-index:2}.brand{display:flex;gap:15px;align-items:center}.sigil{font-size:31px;color:var(--gold);text-shadow:0 0 22px #db994c}.eyebrow,.panel-kicker{font-size:10px;letter-spacing:.2em;color:#9e8b63;font-weight:700}.brand h1{font:700 20px Cinzel,serif;letter-spacing:.13em;margin:4px 0 0;color:#e6dbc0}.brand h1 i{font-size:11px;color:var(--gold);font-weight:500}.run-stats{display:flex;gap:34px;text-align:right}.run-stats div{display:flex;flex-direction:column;gap:3px}.run-stats span{font-size:9px;color:var(--muted);letter-spacing:.18em}.run-stats b{font:600 16px Cinzel;color:#eee4cc}.run-stats .gold b{color:var(--gold)}.run-stats em{font-style:normal}.stage{display:grid;grid-template-columns:210px minmax(400px,1fr) 190px;gap:30px;max-width:1280px;margin:0 auto;padding:35px 5.5vw 20px}.hero-panel,.energy-panel{padding-top:5px}.portrait{height:158px;margin:15px 0 18px;border:1px solid #6b5a3b;position:relative;display:flex;align-items:center;justify-content:center;overflow:hidden;background:radial-gradient(circle at 50% 40%,#4a3143,#191827 60%,#0d101a)}.portrait:before{content:'';position:absolute;width:120px;height:170px;border-radius:50% 50% 15% 15%;background:linear-gradient(145deg,#c4a15c 0,#514064 14%,#171c2e 54%,#090c15 55%);opacity:.8;filter:drop-shadow(0 0 20px #5e3d59)}.portrait-mark{font-size:60px;color:#d7bb72;z-index:1;opacity:.8}.portrait-name{position:absolute;bottom:10px;z-index:1;font:700 11px Cinzel;letter-spacing:.18em}.portrait.wither{background:radial-gradient(circle,#563f29,#1b1720 65%,#0d101a)}.portrait.shroud{background:radial-gradient(circle,#253d4e,#131728 65%,#0d101a)}.stat-row{display:flex;justify-content:space-between;margin:11px 0 5px;font-size:10px;color:var(--muted);letter-spacing:.1em}.stat-row b{color:#e9dec7;font-size:13px}.stat-row small{font-size:10px;color:var(--muted);font-weight:400}.bar{height:6px;background:#252b39;border:1px solid #353c4c;overflow:hidden}.bar i{display:block;height:100%;transition:width .3s;background:var(--red);box-shadow:0 0 10px #e75f55}.bar.enemy i{background:#c05952}.ability{margin-top:20px;padding:12px;border:1px solid #353c4c;background:#171c2a;color:var(--gold);font:600 10px Cinzel;line-height:1.6}.ability small{display:block;color:#8994aa;font:10px Manrope;margin-top:3px}.metal{border:1px solid #79683f;background:linear-gradient(#3c3d42,#20252e);padding:12px 15px;font-size:10px;letter-spacing:.12em;font-weight:700;box-shadow:inset 0 0 0 1px #151923,0 5px 12px #0008}.metal:hover{border-color:var(--gold);filter:brightness(1.2)}.wide{width:100%;margin-top:22px;color:#e1c37b}.combat{min-width:0}.combat-head{display:flex;justify-content:space-between;align-items:end;border-bottom:1px solid #353c4d;padding-bottom:15px}.combat h2,.shop-card h2,.modal-card h2{font:700 24px Cinzel;margin:6px 0 0;letter-spacing:.07em;color:#eee4cc}.intent{text-align:right}.intent span{display:block;font-size:9px;color:var(--muted);letter-spacing:.15em}.intent b{display:block;color:var(--red);font:600 13px Cinzel;margin-top:5px}.enemy-zone{min-height:250px;display:flex;flex-direction:column;align-items:center;justify-content:center}.enemy-art{width:150px;height:125px;display:flex;align-items:center;justify-content:center;position:relative;background:radial-gradient(ellipse,#47323c,#141725 65%,transparent 70%);filter:drop-shadow(0 0 18px #bc5b4c55)}.enemy-art span{font-size:86px;color:#b66c54;text-shadow:0 0 12px #df6045;transform:translateY(-4px)}.enemy-art.vampire span{color:#9a7fa8}.enemy-art.ogre span{color:#777e62}.enemy-art.void span{color:#7c71c2}.enemy-info{width:min(430px,90%)}.enemy-label{display:flex;justify-content:space-between;color:#aeb5c3;font-size:10px;letter-spacing:.14em;margin-bottom:6px}.enemy-label b{font:13px Cinzel;color:#e7d9b5}.status-pills{height:23px;padding-top:7px}.pill{display:inline-block;padding:3px 7px;border:1px solid #8b5b38;color:#dc9d58;font-size:9px;margin-right:4px}.enemy-info p{text-align:center;color:#6e7890;font-size:11px;margin:8px 0}.log{border-top:1px solid #30384a;border-bottom:1px solid #30384a;padding:12px 0;text-align:center;color:#a7afbe;font-size:11px}.log-title{font:10px Cinzel;color:#8d744d;letter-spacing:.14em;margin-bottom:5px}.energy-panel{text-align:center}.energy-orb{width:112px;height:112px;margin:25px auto 18px;border-radius:50%;border:1px solid #6f5b89;background:radial-gradient(circle,#332e58 0,#1b203a 55%,#121624 70%);box-shadow:0 0 25px #59448866,inset 0 0 18px #000}.energy-orb b{font:700 38px Cinzel;color:#e0d2ee}.energy-orb div{padding-top:25px}.energy-orb span{color:#9b8eae}.energy-orb small{font-size:9px;letter-spacing:.2em;color:#a895c6}.tips{text-align:left;line-height:2.1;color:#7f8ba2;font-size:10px;margin:20px 0}.tips span{color:var(--gold);margin-right:5px}.end{width:100%;margin-top:8px;color:#e4d09a}.end span{float:right;color:#8e896f}.ghost{background:none;border:0;color:#657087;font-size:9px;letter-spacing:.14em;margin-top:20px}.hand-area{border-top:1px solid #2e3748;background:linear-gradient(180deg,#111623,#0c1018);padding:17px 5.5vw 28px;min-height:240px}.hand-header{max-width:1280px;margin:auto;display:flex;justify-content:space-between;align-items:end}.hand-sub{font-size:10px;color:#798398;margin-top:5px}.deck-count{text-align:right}.deck-count span{font-size:9px;color:#748096;letter-spacing:.14em}.deck-count b{display:block;font:20px Cinzel;color:#c5b38b;margin-top:3px}.hand{max-width:1060px;margin:14px auto 0;display:flex;justify-content:center;gap:10px}.card{width:132px;height:178px;padding:10px;position:relative;border:1px solid #685b45;background:linear-gradient(145deg,#292a2d,#121721 75%);box-shadow:0 8px 18px #0009;transition:.18s transform,.18s filter;cursor:pointer;overflow:hidden}.card:before{content:'';position:absolute;inset:4px;border:1px solid #4e4b43;pointer-events:none}.card:hover{transform:translateY(-10px);filter:brightness(1.22)}.card.unplayable{opacity:.48;filter:saturate(.5)}.card.attack{border-color:#945348;background:linear-gradient(145deg,#38282c,#161821 70%)}.card.defense{border-color:#537a94;background:linear-gradient(145deg,#263647,#141a25 70%)}.card.other{border-color:#80609c;background:linear-gradient(145deg,#31273d,#161822 70%)}.card-top{display:flex;justify-content:space-between;font:700 11px Cinzel;color:#e8d9b3;position:relative}.cost{width:21px;height:21px;border-radius:50%;background:#262b38;color:#e7c56f;text-align:center;padding-top:3px;border:1px solid #8e7548}.card-art{height:68px;margin:8px 0 6px;display:flex;align-items:center;justify-content:center;border:1px solid #3d4249;background:radial-gradient(circle,#3d414e,#171b24 65%);font-size:35px;color:#d27b57}.defense .card-art{color:#75aecb}.other .card-art{color:#b184cf}.card-name{font:700 10px Cinzel;letter-spacing:.06em}.card-desc{font-size:9px;line-height:1.3;color:#a8adba;margin-top:5px}.card-foot{position:absolute;bottom:9px;left:10px;right:10px;font-size:8px;color:#887f6d;letter-spacing:.08em}.shop-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:10px;margin-top:22px}.shop-grid .card{width:100%;cursor:default}.buy{position:absolute;bottom:7px;right:8px;border:1px solid #816b40;background:#292a2d;color:#e7c776;font-size:9px;padding:5px}.overlay{position:fixed;inset:0;background:#05070dcc;display:flex;align-items:center;justify-content:center;z-index:10}.hidden{display:none}.shop-card,.modal-card{width:min(900px,90vw);padding:30px;background:linear-gradient(145deg,#1b2130,#0d111b);border:1px solid #7b6845;box-shadow:0 20px 70px #000;position:relative}.shop-card h2{font-size:25px}.shop-note{color:#858ea1}.close{position:absolute;right:18px;top:12px;border:0;background:none;color:#aaa;font-size:25px}.modal-card{text-align:center;width:min(460px,90vw)}.modal-card>div:first-child{font-size:48px;color:var(--gold)}.modal-card p{color:#99a1b1;line-height:1.6}.modal-card .metal{margin-top:12px}@media(max-width:800px){.topbar{padding:0 18px}.brand h1{font-size:15px}.run-stats{gap:12px}.stage{grid-template-columns:1fr;gap:16px;padding:20px 18px}.hero-panel,.energy-panel{display:none}.combat-head h2{font-size:18px}.enemy-zone{min-height:200px}.hand-area{padding:15px 10px}.hand{overflow-x:auto;justify-content:flex-start;padding:5px}.card{min-width:125px}.shop-grid{grid-template-columns:repeat(2,1fr)}}
/* ── css: animations ── */
@keyframes pulse{50%{box-shadow:0 0 30px #a85e4e88}}.enemy-art{animation:pulse 3s ease-in-out infinite}.card.played{transform:translateY(-18px) scale(1.04);filter:brightness(1.5)}
</style>
</head>
<body>
<main id="game"><div class="noise"></div><header class="topbar"><div class="brand"><span class="sigil">✦</span><div><div class="eyebrow">ROGUELITE CARD BATTler</div><h1>SHADOWS <i>of</i> AETHELGARD</h1></div></div><div class="run-stats"><div><span>FLOOR</span><b id="floorText">I</b></div><div><span>ROOM</span><b id="roomText">01 / 03</b></div><div class="gold"><span>GOLD</span><b>◈ <em id="goldText">0</em></b></div></div></header><section class="stage"><aside class="hero-panel"><div class="panel-kicker">YOUR VESSEL</div><div id="heroPortrait" class="portrait bastion"><div class="portrait-mark">✧</div><div class="portrait-name" id="heroName">THE BASTION</div></div><div class="stat-row"><span>VITALITY</span><b><strong id="hpText">35</strong> <small>/ <span id="maxHpText">35</span></small></b></div><div class="bar hp"><i id="hpBar"></i></div><div class="stat-row"><span>DEFENSE</span><b id="defText">0</b></div><div class="stat-row"><span>DRAW</span><b id="handText">4</b></div><div class="ability" id="heroAbility">IMMOVABLE OBJECT <small>Reduce incoming damage with layered defense.</small></div><button id="shopBtn" class="metal wide">✦ ENTER THE NIGHT MARKET</button></aside><section class="combat"><div class="combat-head"><div><div class="panel-kicker">CURRENT ENCOUNTER</div><h2 id="encounterTitle">THE DROWNED GOBLIN</h2></div><div class="intent"><span>INTENT</span><b id="intentText">ATTACK 3</b></div></div><div class="enemy-zone"><div id="enemyArt" class="enemy-art goblin"><span>☠</span></div><div class="enemy-info"><div class="enemy-label"><span id="enemyKind">VOID-TOUCHED</span><b><span id="enemyHp">20</span> / <span id="enemyMaxHp">20</span></b></div><div class="bar enemy"><i id="enemyBar"></i></div><div class="status-pills" id="enemyStatuses"></div><p id="enemyDesc">A starving thing crawled out of the black tide. It watches your hands.</p></div></div><div class="log" id="log"><div class="log-title">✦ WHISPERS FROM THE DARK</div><div id="logText">The encounter begins. Choose your cards carefully.</div></div></section><aside class="energy-panel"><div class="panel-kicker">RESOURCES</div><div class="energy-orb"><div><b id="energyText">3</b><span>/ <span id="maxEnergyText">3</span></span></div><small>ENERGY</small></div><div class="tips"><span>✦</span> Cards resolve instantly.<br><span>✦</span> End your turn to invite danger.<br><span>✦</span> Defeat foes to earn 5 gold.</div><button id="endTurn" class="metal end">END TURN <span>↵</span></button><button id="restartBtn" class="ghost">ABANDON RUN</button></aside></section><section class="hand-area"><div class="hand-header"><div><div class="panel-kicker">YOUR HAND</div><div class="hand-sub">Select a card to play • <span id="handCount">4</span> cards drawn</div></div><div class="deck-count"><span>DRAW PILE</span><b id="deckText">12</b></div></div><div id="hand" class="hand"></div></section><div id="shop" class="overlay hidden"><div class="shop-card"><button class="close" id="closeShop">×</button><div class="panel-kicker">THE NIGHT MARKET</div><h2>Buy power. Pay in blood.</h2><p class="shop-note">Common cards return to your deck. Prices rise with each copy.</p><div id="shopGrid" class="shop-grid"></div></div></div><div id="modal" class="overlay hidden"><div class="modal-card"><div id="modalIcon">✦</div><h2 id="modalTitle">FLOOR CLEARED</h2><p id="modalText"></p><button id="modalAction" class="metal">CONTINUE</button></div></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 $ = (id) => document.getElementById(id);
const pools = { Bastion: [['BA-A01', 'Slam', 'attack', 2, 3, 'Deal 3 damage.', 'ϟ'], ['BA-A02', 'Earthquake', 'attack', 3, 4, 'Deal 4 to all foes.', '⌁'], ['BA-A03', 'Stone Fist', 'attack', 1, 2, 'Deal 2 damage.', '✦'], ['BA-A04', 'Boulder', 'attack', 4, 6, 'Deal 6 damage.', '◆'], ['BA-D01', 'Shield Wall', 'defense', 0, 4, 'Gain 4 Defense this turn.', '⬡'], ['BA-D02', 'Iron Skin', 'defense', 2, 5, 'Gain 5 Defense permanently.', '◈'], ['BA-D03', 'Stand Firm', 'defense', 1, 2, 'Gain 2 Defense.', '◒'], ['BA-D04', 'Taunt', 'defense', 2, 3, 'Gain 3 Defense. Stun foe.', '⚑'], ['BA-U01', 'Search', 'other', 2, 0, 'Draw 1 card.', '⌕'], ['BA-U02', 'Repair', 'other', 3, 0, 'Heal 6 HP.', '✚'], ['BA-U03', 'Rally', 'other', 1, 0, 'Draw 1. Gain 1 Energy.', '↟'], ['BA-U04', 'Loot', 'other', 2, 0, 'Gain 5 Gold.', '◈']].map(x => ({ id: x[0], name: x[1], kind: x[2], cost: x[3], power: x[4], desc: x[5], icon: x[6] })) };
pools.Wither = pools.Bastion.map((c, i) => ({ ...c, id: c.id.replace('BA', 'WI'), name: ['Fireball', 'Inferno', 'Ember', 'Pyre', 'Scorch Shield', 'Heat Resist', 'Smoke', 'Endure', 'Poison', 'Burn', 'Slow', 'Wither'][i], desc: ['Deal 3 damage. Apply Burn.', 'Deal 4 damage. Apply 3 Burn.', 'Deal 2 + 1 each turn.', 'Deal 5. Burn all foes.', 'Gain 3 Defense.', 'Gain 1 Defense and Energy.', 'Gain 4 Defense.', 'Gain 2 Defense. Heal 2.', 'Apply Poison.', 'Deal 3 + 2 Burn to all.', 'Draw 1. Stun foe.', 'Heal 5. Weaken foe.'][i], icon: ['☼', '✹', '·', '♨', '◉', '◌', '◇', '✚', '☠', '♨', '≈', '☽'][i] }));
pools.Shroud = pools.Bastion.map((c, i) => ({ ...c, id: c.id.replace('BA', 'SH'), name: ['Backstab', 'Shadow Bolt', 'Silence', 'Vengeance', 'Blur', 'Step', 'Evasion', 'Phantom', 'Dash', 'Teleport', 'Hide', 'Assassinate'][i], desc: ['Deal 4 +1 unarmored.', 'Deal 5, bypass block.', 'Deal 3. Silence foe.', 'Deal 6. Gain 2 Energy.', 'Gain 2 Defense.', 'Gain 3 Defense + Energy.', 'Gain 1. Skip attack.', 'Gain 4 Defense.', 'Gain Energy. Skip attack.', 'Deal 2 damage.', 'Discard 1. Draw 2.', 'Deal 8, unblockable.'][i], icon: ['◈', '↯', '⟡', '†', '◌', '⇢', '◒', '◇', '↟', '✦', '⌁', '☾'][i] }));
let cls = 'Bastion', floor = 1, room = 1, gold = 0, hp = 35, maxHp = 35, energy = 3, maxEnergy = 3, defense = 0, handSize = 4, deck = [], hand = [], enemy, over = false;
const enemies = [['The Drowned Goblin', 20, 3, 'goblin'], ['Grave Rat Swarm', 20, 3, 'rat'], ['The Gatekeeper', 80, 15, 'boss']];
function makeEnemy() { let e = enemies[room - 1] ?? ['Void Warrior', 40, 8, 'void']; if (room === 3 && floor === 2)
    e = ['The Corrupted', 80, 15, 'vampire']; if (floor === 3 && room === 3)
    e = ['THE VOID LORD', 80, 15, 'void']; const scale = floor === 1 ? 1 : floor === 2 ? 1.5 : 2; return { name: e[0], hp: e[1] * (e[3] === 'boss' && floor === 1 ? 1 : scale), max: e[1] * (e[3] === 'boss' && floor === 1 ? 1 : scale), damage: e[2] * (e[3] === 'boss' ? 1 : floor === 3 ? 1 : 1), kind: e[3], boss: e[3] === 'boss' || room === 3, status: { burn: 0, poison: 0, stun: 0 }, desc: 'A silhouette shaped by the void. Its next move is written in your blood.' }; }
function log(s) { $('logText').textContent = s; }
function draw(n = 1) { for (let i = 0; i < n && hand.length < handSize; i++)
    hand.push(deck[hand.length % deck.length]); }
function render() { $('floorText').textContent = ['', 'I', 'II', 'III'][floor]; $('roomText').textContent = `0${room} / 03`; $('goldText').textContent = String(gold); $('hpText').textContent = String(Math.max(0, hp)); $('maxHpText').textContent = String(maxHp); $('hpBar').style.width = `${Math.max(0, hp / maxHp * 100)}%`; $('defText').textContent = String(defense); $('energyText').textContent = String(energy); $('maxEnergyText').textContent = String(maxEnergy); $('handCount').textContent = String(hand.length); $('deckText').textContent = String(deck.length); $('enemyHp').textContent = String(Math.max(0, Math.ceil(enemy.hp))); $('enemyMaxHp').textContent = String(Math.ceil(enemy.max)); $('enemyBar').style.width = `${Math.max(0, enemy.hp / enemy.max * 100)}%`; $('encounterTitle').textContent = enemy.name; $('enemyKind').textContent = enemy.boss ? 'VOID LORD' : 'VOID-TOUCHED'; $('intentText').textContent = `ATTACK ${enemy.damage}`; $('enemyDesc').textContent = enemy.desc; $('heroName').textContent = 'THE ' + cls.toUpperCase(); $('heroPortrait').className = 'portrait ' + cls.toLowerCase(); $('enemyArt').className = 'enemy-art ' + enemy.kind; const st = $('enemyStatuses'); st.innerHTML = (enemy.status.burn ? `<span class="pill">BURN ${enemy.status.burn}</span>` : '') + (enemy.status.poison ? `<span class="pill">POISON ${enemy.status.poison}</span>` : '') + (enemy.status.stun ? `<span class="pill">STUN</span>` : ''); $('hand').innerHTML = ''; hand.forEach((c, i) => { const el = document.createElement('div'); el.className = `card ${c.kind} ${c.cost > energy ? 'unplayable' : ''}`; el.innerHTML = `<div class="card-top"><span>${c.kind.toUpperCase()}</span><b class="cost">${c.cost}</b></div><div class="card-art">${c.icon}</div><div class="card-name">${c.name}</div><div class="card-desc">${c.desc}</div><div class="card-foot">COMMON · ${c.id}</div>`; el.onclick = () => play(i); $('hand').appendChild(el); }); }
function play(i) { if (over)
    return; const c = hand[i]; if (!c || c.cost > energy) {
    log('Not enough energy. The void waits.');
    return;
} energy -= c.cost; hand.splice(i, 1); if (c.kind === 'attack') {
    let dmg = c.power;
    if (c.name === 'Backstab' && enemy.status.stun === 0)
        dmg++;
    enemy.hp -= dmg;
    if (c.name === 'Fireball' || c.name === 'Inferno')
        enemy.status.burn += c.name === 'Inferno' ? 3 : 1;
    if (c.name === 'Assassinate')
        enemy.hp -= 2;
    log(`${c.name} tears ${dmg} vitality from ${enemy.name}.`);
}
else if (c.kind === 'defense') {
    defense += c.power;
    if (c.name === 'Taunt')
        enemy.status.stun = 1;
    if (c.name === 'Endure')
        hp = Math.min(maxHp, hp + 2);
    log(`${c.name}: your defenses rise.`);
}
else {
    if (c.name === 'Repair' || c.name === 'Wither')
        hp = Math.min(maxHp, hp + (c.name === 'Repair' ? 6 : 5));
    if (c.name === 'Loot')
        gold += 5;
    if (c.name === 'Rally' || c.name === 'Dash')
        energy++;
    if (c.name === 'Poison')
        enemy.status.poison++;
    if (c.name === 'Burn') {
        enemy.hp -= 3;
        enemy.status.burn += 2;
    }
    if (c.name === 'Slow')
        enemy.status.stun = 1;
    log(`${c.name} resolves in a flash.`);
} if (enemy.hp <= 0)
    winRoom(); render(); }
function endTurn() { if (over)
    return; if (enemy.status.burn) {
    enemy.hp -= enemy.status.burn;
    enemy.status.burn = Math.max(0, enemy.status.burn - 1);
} if (enemy.status.poison) {
    enemy.hp -= enemy.status.poison;
    enemy.status.poison = Math.max(0, enemy.status.poison - 1);
} if (enemy.hp <= 0) {
    winRoom();
    return;
} if (enemy.status.stun)
    enemy.status.stun = 0;
else {
    const hit = Math.max(0, enemy.damage - defense);
    hp -= hit;
    log(`${enemy.name} strikes for ${hit} damage through your guard.`);
} defense = 0; energy = Math.min(maxEnergy, energy + 1); hand = []; draw(4); if (hp <= 0) {
    over = true;
    showModal('THE VOID CLAIMS YOU', 'Your vessel has fallen. Restart the run and choose a new path.', 'RESTART');
} render(); }
function winRoom() { gold += enemy.boss ? 15 : 5; if (room < 3) {
    room++;
    enemy = makeEnemy();
    hand = [];
    draw(4);
    energy = maxEnergy;
    log(`Victory. ${gold} gold weighs in your purse.`);
}
else if (floor < 3) {
    floor++;
    room = 1;
    enemy = makeEnemy();
    hand = [];
    draw(4);
    energy = maxEnergy;
    log(`Floor ${floor} descends beneath your feet.`);
}
else {
    over = true;
    showModal('VICTORY PORTAL', 'The Void Lord dissolves. Aethelgard breathes again—for now.', 'PLAY AGAIN');
} }
function showModal(title, text, button) { $('modalTitle').textContent = title; $('modalText').textContent = text; $('modalAction').textContent = button; $('modal').classList.remove('hidden'); }
function reset() { cls = 'Bastion'; floor = 1; room = 1; gold = 0; hp = maxHp = 35; energy = maxEnergy = 3; defense = 0; over = false; deck = [...pools[cls], ...pools[cls], ...pools[cls]]; hand = []; enemy = makeEnemy(); draw(4); $('modal').classList.add('hidden'); render(); }
function shop() { const grid = $('shopGrid'); grid.innerHTML = ''; pools[cls].forEach(c => { const el = document.createElement('div'); el.className = `card ${c.kind}`; el.innerHTML = `<div class="card-top"><span>${c.kind.toUpperCase()}</span><b class="cost">${c.cost}</b></div><div class="card-art">${c.icon}</div><div class="card-name">${c.name}</div><div class="card-desc">${c.desc}</div><button class="buy">BUY · 1◈</button>`; el.querySelector('button').onclick = () => { if (gold < 1) {
    log('The market requires gold.');
    return;
} gold--; deck.push(c); log(`${c.name} joins your deck.`); render(); }; grid.appendChild(el); }); $('shop').classList.remove('hidden'); }
$('endTurn').onclick = endTurn;
$('restartBtn').onclick = reset;
$('shopBtn').onclick = shop;
$('closeShop').onclick = () => $('shop').classList.add('hidden');
$('modalAction').onclick = reset;
reset();
};

// ── entry ──
__require("src/main.ts");
})();
</script>
</body>
</html>
<!-- agent-meta {"model":"openai/gpt-5.6-luna-pro","provider":"openrouter","persona":"typescript","sessionId":"b7cc2f5d-ae63-4bce-b293-25704308814e","tokensIn":980530,"tokensOut":29073,"tokensTotal":1009603,"turns":17,"toolCalls":24,"failedToolCalls":3,"timestamp":"2026-07-31T03:14:34.053Z"} -->