← Deckbuilder results

Deckbuilder

inkling · basic

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 48,143 bytes · SHA-256 efeb0aef9519
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Shadows of Aethelgard — Prototype</title>
<style>
@import url('https://fonts.googleapis.com/css2?family=Cinzel+Decorative:wght@700&family=Cinzel:wght@600&family=Spectral:ital,wght@0,400;1,400&display=swap');

:root {
  --void-dark: #06040a;
  --parchment: #1a1210;
  --gold-text: #caa84d;
  --gold-line: #8a6e2f;
  --steel: #6a7a8a;
  --red-attack: #9e2a2b;
  --blue-def: #2a4a6e;
  --purple-other: #3a1a4a;
  --burn: #c98a2b;
  --health: #5ab85a;
  --energy: #3a6ea5;
  --danger: #b12a2a;
}
* { box-sizing: border-box; margin: 0; padding: 0; user-select: none; }
html, body { height: 100vh; overflow: hidden; background: linear-gradient(180deg, #04020a 0%, #0f0b16 60%, #16101a 100%); color: #e8dcc9; font-family: 'Spectral', serif; }

body {
  display: flex;
  flex-direction: column;
  background-image:
    radial-gradient(circle at 20% 30%, rgba(70,40,80,0.15) 0%, transparent 40%),
    radial-gradient(circle at 80% 70%, rgba(100,70,30,0.1) 0%, transparent 40%),
    repeating-linear-gradient(0deg, transparent 0px, transparent 2px, rgba(255,255,255,0.015) 2px, rgba(255,255,255,0.015) 4px);
}

h1, h2, h3 { font-family: 'Cinzel Decorative', serif; letter-spacing: 2px; text-shadow: 0 2px 0 #000, 0 0 20px rgba(255,220,180,0.15); color: var(--gold-text); }

/* Header Bar */
header {
  height: 72px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 28px;
  border-bottom: 2px solid var(--gold-line);
  background: linear-gradient(180deg, #111016 0%, #0a0810 100%);
  box-shadow: 0 4px 20px rgba(0,0,0,0.6);
  z-index: 10;
  position: relative;
}
.header-group {
  display: flex;
  align-items: center;
  gap: 24px;
}
.stat-badge {
  background: linear-gradient(135deg, #121018 0%, #1a1125 100%);
  border: 1px solid #3a2a4a;
  border-radius: 10px;
  padding: 8px 16px;
  box-shadow: inset 0 0 8px rgba(255,255,255,0.03);
  min-width: 110px;
}
.stat-label { font-size: 10px; text-transform: uppercase; letter-spacing: 1.5px; color: #8a7a90; display: block; margin-bottom: 2px; }
.stat-value { font-family: 'Cinzel', serif; font-size: 18px; color: var(--gold-text); text-shadow: 0 1px 2px #000; }
.stat-value.danger { color: #e85555; }
.stat-value.green { color: #5ab85a; }
.stat-value.blue { color: #5aa3d5; }
.stat-badge .icon { width: 18px; height: 18px; display: inline-block; vertical-align: middle; margin-right: 6px; }

/* Center Arena */
main {
  flex: 1;
  display: grid;
  grid-template-columns: 1fr 2.4fr 1fr;
  gap: 20px;
  padding: 24px;
  overflow: hidden;
}

/* Player / Enemy Panels */
.side-panel {
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.panel-header {
  text-align: center;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--gold-line);
  margin-bottom: 8px;
}
.panel-card {
  background: linear-gradient(160deg, #161018 0%, #0d0a12 100%);
  border: 1px solid #2a2236;
  border-radius: 14px;
  padding: 20px;
  box-shadow: 0 8px 24px rgba(0,0,0,0.7), inset 0 1px 0 rgba(255,255,255,0.05);
}
.panel-card h3 { font-size: 16px; margin-bottom: 10px; color: var(--gold-text); }
.entity-preview {
  display: flex;
  flex-direction: column;
  align-items: center;
}
.entity-sprite {
  width: 160px;
  height: 160px;
  position: relative;
  margin-bottom: 12px;
}
.entity-sprite svg { width: 100%; height: 100%; filter: drop-shadow(0 0 12px rgba(255,220,180,0.15)); }

.hp-bar-container {
  width: 100%;
  height: 14px;
  background: #0d0a12;
  border-radius: 7px;
  border: 1px solid #2a2236;
  overflow: hidden;
  margin-bottom: 6px;
  box-shadow: inset 0 1px 3px #000;
}
.hp-bar-fill {
  height: 100%;
  background: linear-gradient(90deg, #8b1a1a 0%, #d93a3a 50%, #5ab85a 100%);
  width: 60%;
  transition: width 0.3s ease;
}
.entity-stats {
  display: flex;
  justify-content: space-around;
  font-size: 12px;
  color: #b8a8c0;
}

.defense-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: linear-gradient(135deg, #1a2a4a, #142a4e);
  padding: 4px 10px;
  border-radius: 20px;
  border: 1px solid #3a4a6a;
  font-weight: bold;
  color: #8ec3f0;
  font-size: 13px;
}
.defense-badge .shield-icon { width: 14px; height: 14px; }
.defense-badge.empty { color: #555; border-color: #2a2236; background: linear-gradient(135deg, #151015, #0d0a12); }

/* Center Arena */
.center-arena {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 24px;
}
.enemy-display {
  background: linear-gradient(160deg, rgba(30,10,25,0.9), rgba(10,5,15,0.95));
  border: 2px solid #3a243a;
  border-radius: 20px;
  padding: 28px 40px;
  box-shadow: 0 12px 40px rgba(0,0,0,0.8), inset 0 0 40px rgba(100,0,50,0.1);
  text-align: center;
  min-width: 320px;
  position: relative;
}
.enemy-display::before {
  content: "";
  position: absolute;
  top: -2px; left: -2px; right: -2px; bottom: -2px;
  background: linear-gradient(45deg, transparent 40%, rgba(255,255,255,0.03) 50%, transparent 60%);
  border-radius: 20px;
  pointer-events: none;
}
.enemy-title {
  font-family: 'Cinzel Decorative', serif;
  font-size: 22px;
  color: var(--gold-text);
  text-shadow: 0 2px 10px rgba(255,220,180,0.15);
  margin-bottom: 14px;
}
.enemy-sprite-area {
  width: 200px;
  height: 200px;
  margin: 0 auto 16px;
  position: relative;
}
.enemy-sprite-area svg { filter: drop-shadow(0 0 15px rgba(200,50,70,0.3)); }
.boss-tag {
  display: inline-block;
  background: linear-gradient(135deg, #6a1a3a, #3a0a20);
  border: 1px solid #9a2a4a;
  color: #f0a0b0;
  padding: 2px 10px;
  border-radius: 12px;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 1px;
  margin-top: 4px;
  box-shadow: 0 0 8px rgba(200,50,70,0.3);
}

/* Card Hand Area */
.hand-area {
  display: flex;
  gap: 14px;
  justify-content: center;
  min-height: 200px;
}
.card-wrapper {
  position: relative;
  width: 140px;
  height: 190px;
  perspective: 800px;
  transition: transform 0.15s ease;
  cursor: pointer;
}
.card-wrapper:hover { transform: translateY(-10px); }
.card-wrapper.playable { filter: drop-shadow(0 0 10px rgba(255,255,255,0.15)); }
.card-wrapper.unplayable { filter: grayscale(0.6) brightness(0.6); }

.card-inner {
  width: 100%;
  height: 100%;
  position: relative;
  border-radius: 10px;
  overflow: hidden;
  box-shadow: 0 4px 16px rgba(0,0,0,0.8), inset 0 0 20px rgba(0,0,0,0.5);
  background: var(--parchment);
  border: 1px solid #3a2a2a;
  display: flex;
  flex-direction: column;
  padding: 8px;
  transition: border-color 0.2s;
}
.card-wrapper.playable .card-inner { border-color: var(--gold-line); box-shadow: 0 4px 16px rgba(0,0,0,0.8), 0 0 0 1px var(--gold-line), inset 0 0 20px rgba(200,170,100,0.1); }

.card-type-header {
  display: flex;
  justify-content: space-between;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 1px;
  font-weight: bold;
  margin-bottom: 6px;
}
.card-cost {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: linear-gradient(135deg, #1a1210, #0d0808);
  border: 1px solid var(--gold-line);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: 'Cinzel', serif;
  font-size: 14px;
  color: var(--gold-text);
  box-shadow: 0 0 6px rgba(200,170,100,0.2);
}
.card-title {
  font-family: 'Cinzel', serif;
  font-size: 13px;
  color: #f0e6c8;
  text-align: center;
  margin: 4px 0;
  line-height: 1.2;
  text-shadow: 0 1px 3px #000;
}
.card-art {
  flex: 1;
  border-radius: 6px;
  overflow: hidden;
  border: 1px solid #2a1a1a;
  background: linear-gradient(160deg, #1a1010 0%, #0d0808 100%);
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  margin: 4px 0;
}
.card-art img { max-width: 90%; max-height: 60px; opacity: 0.9; filter: drop-shadow(0 0 6px rgba(255,255,255,0.1)); }
.card-ability {
  font-size: 11px;
  line-height: 1.3;
  color: #c8b8a8;
  padding-top: 6px;
  border-top: 1px solid #2a2222;
}
.card-desc { font-style: italic; color: #a89880; }
.card-stats-row {
  display: flex;
  justify-content: center;
  gap: 6px;
  margin-top: 4px;
  font-size: 10px;
}

/* Back of card */
.card-back {
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0; left: 0;
  border-radius: 10px;
  overflow: hidden;
  box-shadow: 0 4px 16px rgba(0,0,0,0.8), inset 0 0 20px rgba(0,0,0,0.5);
  border: 1px solid #3a2a2a;
  background: linear-gradient(160deg, #0f0815, #06030a);
  display: flex;
  align-items: center;
  justify-content: center;
}
.card-back svg { width: 80%; height: 80%; opacity: 0.9; filter: drop-shadow(0 0 8px rgba(200,170,100,0.15)); }

/* Bottom Controls */
.controls-bar {
  height: 90px;
  border-top: 2px solid var(--gold-line);
  background: linear-gradient(180deg, #0a0810 0%, #05030a 100%);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 40px;
  box-shadow: 0 -4px 20px rgba(0,0,0,0.6);
}
.control-btn {
  font-family: 'Cinzel', serif;
  font-size: 16px;
  letter-spacing: 1.5px;
  padding: 14px 36px;
  border-radius: 6px;
  border: 1px solid var(--gold-line);
  background: linear-gradient(180deg, #1a1510 0%, #0f0a08 100%);
  color: var(--gold-text);
  box-shadow: 0 4px 12px rgba(0,0,0,0.5), inset 0 1px 0 rgba(255,255,255,0.05);
  cursor: pointer;
  text-shadow: 0 1px 2px #000;
  transition: all 0.2s;
}
.control-btn:hover:not(:disabled) {
  background: linear-gradient(180deg, #2a1f10 0%, #16110d 100%);
  box-shadow: 0 6px 16px rgba(0,0,0,0.6), 0 0 10px rgba(200,170,100,0.15), inset 0 1px 0 rgba(255,255,255,0.08);
  transform: translateY(-2px);
}
.control-btn:disabled { opacity: 0.4; cursor: not-allowed; }
.control-btn.red { border-color: #4a1a1a; color: #e8a0a0; }
.control-btn.green { border-color: #1a4a2a; color: #a0e8a0; }

/* Shop Overlay */
.overlay {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.85);
  z-index: 100;
  display: none;
  align-items: center;
  justify-content: center;
  backdrop-filter: blur(4px);
}
.overlay.active { display: flex; }
.shop-modal {
  width: 920px;
  max-width: 96vw;
  max-height: 92vh;
  background: linear-gradient(180deg, #121018 0%, #0a0810 100%);
  border: 2px solid var(--gold-line);
  border-radius: 16px;
  padding: 30px;
  box-shadow: 0 20px 60px rgba(0,0,0,0.9), inset 0 0 30px rgba(200,170,100,0.05);
  overflow-y: auto;
}
.shop-header {
  text-align: center;
  margin-bottom: 24px;
  border-bottom: 1px solid var(--gold-line);
  padding-bottom: 16px;
}
.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: 16px;
}
.shop-card {
  background: linear-gradient(160deg, #161018 0%, #0d0a12 100%);
  border: 1px solid #2a2236;
  border-radius: 10px;
  padding: 14px;
  transition: transform 0.15s;
  cursor: pointer;
}
.shop-card:hover { transform: translateY(-4px); border-color: var(--gold-line); }
.shop-card .card-cost { margin-bottom: 8px; }
.shop-card h4 { font-family: 'Cinzel', serif; font-size: 14px; color: var(--gold-text); margin-bottom: 6px; }
.shop-card .ability { font-size: 11px; color: #b8a8c0; line-height: 1.3; }
.shop-card .price-tag { margin-top: 8px; font-size: 13px; color: #caa84d; font-weight: bold; }
.shop-card.disabled { opacity: 0.3; pointer-events: none; }

/* Utility */
.energy-meter {
  display: flex;
  gap: 4px;
}
.energy-orb {
  width: 26px; height: 26px;
  border-radius: 50%;
  background: linear-gradient(135deg, #3a6ea5, #1a3a5a);
  border: 1px solid #8ec3f0;
  box-shadow: 0 0 8px rgba(138,195,240,0.3), inset 0 -2px 3px rgba(0,0,0,0.5);
  display: flex; align-items: center; justify-content: center;
  font-size: 12px; font-family: 'Cinzel', serif; color: #fff;
}
.energy-orb.empty { background: linear-gradient(135deg, #1a1a2a, #0d0d15); border-color: #333; box-shadow: inset 0 2px 4px #000; color: #555; }

/* Class badges */
.class-badge {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 4px;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 1px;
  font-weight: bold;
  border: 1px solid;
}
.bastion { background: #1a1a0a; color: #caa84d; border-color: #8a6e2f; }
.wither { background: #1a0a0a; color: #e8a0a0; border-color: #8a2a2a; }
.shroud { background: #0a0a1a; color: #b0a0e0; border-color: #4a2a6e; }

/* Small text for turn log */
.log-area {
  height: 80px;
  overflow-y: auto;
  background: #06030a;
  border: 1px solid #1a1020;
  border-radius: 8px;
  padding: 8px;
  font-size: 12px;
  color: #a89888;
  line-height: 1.4;
}
.log-area .entry { margin-bottom: 2px; }
.log-area .entry.dmg { color: #e85555; }
.log-area .entry.heal { color: #5ab85a; }
.log-area .entry.gold { color: var(--gold-text); }
.log-area .entry.block { color: #5aa3d5; }

/* Responsive adjustments */
@media (max-width: 1200px) {
  main { grid-template-columns: 1fr; grid-template-rows: auto auto auto; gap: 10px; }
  .hand-area { order: 3; }
}
</style>
</head>
<body>

<header>
  <div class="header-group">
    <div>
      <h1 style="font-size: 22px;">Shadows of Aethelgard</h1>
    </div>
    <div style="font-size: 11px; color: #8a7a90;">Roguelite Deckbuilder — Prototype</div>
  </div>
  <div class="header-group" style="gap: 16px;">
    <div class="stat-badge"><span class="stat-label">Gold</span><span class="stat-value" id="hud-gold">0</span></div>
    <div class="stat-badge"><span class="stat-label">Floor</span><span class="stat-value" id="hud-floor">1 / 1</span></div>
    <div class="stat-badge"><span class="stat-label">Boss HP</span><span class="stat-value" id="hud-boss-hp">20</span></div>
  </div>
</header>

<main>
  <!-- Player Side -->
  <aside class="side-panel" style="align-items: flex-end; text-align: right;">
    <div style="display: flex; justify-content: flex-end; gap: 8px; align-items: center;">
      <span class="class-badge bastion">Bastion</span>
      <span class="class-badge wither">Wither</span>
      <span class="class-badge shroud">Shroud</span>
      <span style="font-size: 12px; color: #888;">Class: <strong id="hero-class">The Bastion</strong></span>
    </div>
    <div class="panel-card">
      <h3>Your Hero</h3>
      <div class="entity-preview">
        <div class="entity-sprite">
          <svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
            <defs>
              <linearGradient id="heroGrad" x1="0" y1="0" x2="0" y2="1">
                <stop offset="0%" stop-color="#d0b060"/>
                <stop offset="100%" stop-color="#8a6e2f"/>
              </linearGradient>
              <filter id="heroGlow">
                <feDropShadow dx="0" dy="0" stdDeviation="4" flood-color="#d0b060" flood-opacity="0.4"/>
              </filter>
            </defs>
            <g filter="url(#heroGlow)">
              <!-- Armor body -->
              <rect x="30" y="40" width="40" height="40" rx="6" fill="url(#heroGrad)" stroke="#5a4520" stroke-width="2"/>
              <!-- Helmet -->
              <path d="M25 35 L50 15 L75 35 L70 45 L30 45 Z" fill="#a08040" stroke="#6a5230" stroke-width="2"/>
              <!-- Shield -->
              <polygon points="10,30 35,50 35,80 10,65" fill="#2a4a6e" stroke="#8ec3f0" stroke-width="2"/>
              <polygon points="15,35 30,55 30,72 15,58" fill="#3a6ea5"/>
              <!-- Sword -->
              <line x1="65" y1="55" x2="90" y2="30" stroke="#e0c080" stroke-width="3" stroke-linecap="round"/>
              <rect x="62" y="55" width="8" height="12" fill="#5a3a20"/>
            </g>
          </svg>
        </div>
        <div style="font-size: 14px; margin-bottom: 8px;"><strong>HP</strong> <span id="hero-hp" style="color: #e85555;">30</span> / <span id="hero-max-hp">30</span></div>
        <div style="font-size: 14px; margin-bottom: 8px;"><strong>Energy</strong> <span id="hero-energy" style="color: #5aa3d5;">3</span> / <span id="hero-max-energy">3</span></div>
        <div style="font-size: 14px; margin-bottom: 8px;"><strong>Defense</strong> <span id="hero-defense" style="color: #8ec3f0;">0</span></div>
        <div style="font-size: 14px;"><strong>Hand Size</strong> <span id="hero-handsize">4</span></div>
      </div>
      <div style="margin-top: 12px;">
        <h4 style="font-family:'Cinzel',serif; font-size: 14px; color: var(--gold-text); margin-bottom: 6px;">Energy</h4>
        <div class="energy-meter" id="energy-meter">
          <!-- populated -->
        </div>
      </div>
    </div>
  </aside>

  <!-- Center Arena -->
  <section class="center-arena">
    <div class="enemy-display">
      <div class="boss-tag" id="boss-tag" style="display:none;">Boss</div>
      <h2 class="enemy-title" id="enemy-name">Goblin</h2>
      <div class="enemy-sprite-area">
        <svg viewBox="0 0 120 120" xmlns="http://www.w3.org/2000/svg">
          <defs>
            <linearGradient id="enemyGrad" x1="0" y1="0" x2="1" y2="1">
              <stop offset="0%" stop-color="#5a2a2a"/>
              <stop offset="100%" stop-color="#2a1010"/>
            </linearGradient>
            <filter id="enemyShadow">
              <feDropShadow dx="0" dy="2" stdDeviation="5" flood-color="#000" flood-opacity="0.8"/>
            </filter>
          </defs>
          <g filter="url(#enemyShadow)">
            <circle cx="60" cy="60" r="35" fill="url(#enemyGrad)" stroke="#8a3a3a" stroke-width="3"/>
            <circle cx="50" cy="55" r="4" fill="#ffe8a0"/>
            <circle cx="70" cy="55" r="4" fill="#ffe8a0"/>
            <path d="M50 70 Q60 80 70 70" stroke="#ffe8a0" stroke-width="2" fill="none"/>
            <path d="M40 45 L25 20 L35 30 Z" fill="#8a3a3a" stroke="#a05050"/>
            <path d="M80 45 L95 20 L85 30 Z" fill="#8a3a3a" stroke="#a05050"/>
          </g>
        </svg>
      </div>
      <div style="font-size: 18px; color: #e85555; font-family:'Cinzel',serif;" id="enemy-hp-display">20 / 20</div>
      <div style="margin-top: 6px; color: #aaa; font-size: 12px;">Attack: <strong id="enemy-dmg">3</strong> | Defense: <strong id="enemy-def" style="color:#8ec3f0;">0</strong></div>
    </div>

    <div class="hand-area" id="hand-container">
      <!-- Cards injected -->
    </div>
  </section>

  <!-- Player Shop / Stats Side -->
  <aside class="side-panel">
    <div class="panel-card">
      <h3>Combat Log</h3>
      <div class="log-area" id="log"></div>
    </div>
    <div class="panel-card">
      <h3>Shop</h3>
      <div style="text-align: center; margin-bottom: 10px;">
        <button class="control-btn" onclick="openShop()" id="shop-btn" style="padding: 10px 20px; font-size: 14px;">Open Shop</button>
      </div>
      <div style="font-size: 12px; color: #a89888; line-height: 1.5;">
        <p>Buy cards: 1 Gold each. If you own 3 copies, 4th costs <strong>10 Gold</strong>. Max 5 copies per card.</p>
        <p style="margin-top: 6px;">Floor <span id="shop-floor">1</span> — <span id="shop-enemy-type">Enemies</span></p>
      </div>
    </div>
  </aside>
</main>

<div style="position: absolute; bottom: 14px; left: 0; right: 0; display: flex; justify-content: center; gap: 30px; z-index: 5; pointer-events: none;">
  <button class="control-btn green" onclick="endTurn()" id="end-turn-btn" style="pointer-events: auto;">End Turn</button>
  <button class="control-btn red" onclick="playHand()" id="play-btn" style="pointer-events: auto;">Play Cards</button>
</div>

<!-- Shop Modal -->
<div class="overlay" id="shop-overlay" onclick="closeShop(event)">
  <div class="shop-modal" onclick="event.stopPropagation()">
    <div class="shop-header">
      <h2>Card Shop <span style="font-size: 14px; color: #8a7a90;">— 1 Gold per Card</span></h2>
      <p style="font-size: 12px; color: #aaa;">Select cards to add to your deck. Close to continue.</p>
    </div>
    <div class="card-grid" id="shop-grid"></div>
    <div style="text-align: center; margin-top: 20px;">
      <button class="control-btn" onclick="closeShop()">Continue Adventure</button>
    </div>
  </div>
</div>

<script>
/* =========================================================
   GAME STATE
   ========================================================= */
const STATE = {
  hero: {
    class: 'bastion', // bastion | wither | shroud
    hp: 35,
    maxHp: 35,
    energy: 3,
    maxEnergy: 3,
    defense: 0,
    gold: 0,
    handSize: 4,
    hand: [],
    deck: [],
    inventory: {}, // card id count
    energyRegen: 3,
    floor: 1,
    room: 1,
    maxCopy: 5,
    burn: 0,
    poison: 0,
    stunned: false
  },
  enemy: {
    name: 'Goblin',
    hp: 20,
    maxHp: 20,
    dmg: 3,
    defense: 0,
    stun: 0,
    burn: 0,
    poison: 0,
    isBoss: false,
    floor: 1
  },
  turnPhase: 'player', // player | enemy | shop
  selectedCards: [],
  log: []
};

/* =========================================================
   CARD DATABASE (36 cards)
   ========================================================= */
const CARDS = {
  'BA-A01': { id:'BA-A01', name:'Slam', class:'bastion', type:'Attack', cost:2, atk:3, def:0, desc:'Deals 3 damage. If you have 30 HP, draw 1 card.', color:'red' },
  'BA-A02': { id:'BA-A02', name:'Earthquake', class:'bastion', type:'Attack', cost:3, atk:4, def:0, desc:'Deals 4 damage to all enemies.', color:'red' },
  'BA-A03': { id:'BA-A03', name:'Stone Fist', class:'bastion', type:'Attack', cost:1, atk:2, def:0, desc:'Deals 2 damage.', color:'red' },
  'BA-A04': { id:'BA-A04', name:'Boulder', class:'bastion', type:'Attack', cost:4, atk:6, def:0, desc:'Deals 6 damage. Costs 4 Energy.', color:'red' },
  'BA-D01': { id:'BA-D01', name:'Shield Wall', class:'bastion', type:'Defense', cost:0, atk:0, def:4, desc:'Gain 4 Defense for this turn.', color:'blue' },
  'BA-D02': { id:'BA-D02', name:'Iron Skin', class:'bastion', type:'Defense', cost:2, atk:0, def:5, desc:'Gain 5 Defense permanently. Discard 1 card.', color:'blue' },
  'BA-D03': { id:'BA-D03', name:'Stand Firm', class:'bastion', type:'Defense', cost:1, atk:0, def:2, desc:'Gain 2 Defense. Blocks 1 incoming damage.', color:'blue' },
  'BA-D04': { id:'BA-D04', name:'Taunt', class:'bastion', type:'Defense', cost:2, atk:0, def:3, desc:'Gain 3 Defense. Stun 1 enemy for 1 turn.', color:'blue' },
  'BA-U01': { id:'BA-U01', name:'Search', class:'bastion', type:'Other', cost:2, atk:0, def:0, desc:'Draw 1 card. Discard hand if > 5 cards.', color:'purple' },
  'BA-U02': { id:'BA-U02', name:'Repair', class:'bastion', type:'Other', cost:3, atk:0, def:0, desc:'Heal 6 HP.', color:'purple' },
  'BA-U03': { id:'BA-U03', name:'Rally', class:'bastion', type:'Other', cost:1, atk:0, def:0, desc:'Draw 1 card. Gain 1 Energy.', color:'purple' },
  'BA-U04': { id:'BA-U04', name:'Loot', class:'bastion', type:'Other', cost:2, atk:0, def:0, desc:'Gain 5 Gold.', color:'purple' },

  'WI-A01': { id:'WI-A01', name:'Fireball', class:'wither', type:'Attack', cost:2, atk:3, def:0, desc:'Deals 3 damage. Apply 1 Burn.', color:'red' },
  'WI-A02': { id:'WI-A02', name:'Inferno', class:'wither', type:'Attack', cost:3, atk:4, def:0, desc:'Deals 4 damage. Applies 3 Burn.', color:'red' },
  'WI-A03': { id:'WI-A03', name:'Ember', class:'wither', type:'Attack', cost:1, atk:2, def:0, desc:'Deals 2 damage. Deals 1 damage every turn.', color:'red' },
  'WI-A04': { id:'WI-A04', name:'Pyre', class:'wither', type:'Attack', cost:4, atk:5, def:0, desc:'Deals 5 damage. All enemies take 1 damage next turn.', color:'red' },
  'WI-D01': { id:'WI-D01', name:'Scorch Shield', class:'wither', type:'Defense', cost:2, atk:0, def:3, desc:'Gain 3 Defense. Block 1 Burn damage.', color:'blue' },
  'WI-D02': { id:'WI-D02', name:'Heat Resist', class:'wither', type:'Defense', cost:1, atk:0, def:1, desc:'Gain 1 Defense. Gain 1 Energy.', color:'blue' },
  'WI-D03': { id:'WI-D03', name:'Smoke', class:'wither', type:'Defense', cost:2, atk:0, def:4, desc:'Gain 4 Defense. Block 1 Burn damage.', color:'blue' },
  'WI-D04': { id:'WI-D04', name:'Endure', class:'wither', type:'Defense', cost:3, atk:0, def:2, desc:'Gain 2 Defense. Heal 2 HP.', color:'blue' },
  'WI-U01': { id:'WI-U01', name:'Poison', class:'wither', type:'Other', cost:2, atk:0, def:0, desc:'Apply 1 Poison to target.', color:'purple' },
  'WI-U02': { id:'WI-U02', name:'Burn', class:'wither', type:'Other', cost:3, atk:0, def:0, desc:'Deal 3 damage + 2 Burn to all enemies.', color:'purple' },
  'WI-U03': { id:'WI-U03', name:'Slow', class:'wither', type:'Other', cost:1, atk:0, def:0, desc:'Draw 1 card. Target cannot move next turn (Stun).', color:'purple' },
  'WI-U04': { id:'WI-U04', name:'Wither', class:'wither', type:'Other', cost:2, atk:0, def:0, desc:'Heal 5 HP. Reduce enemy Attack by 1.', color:'purple' },

  'SH-A01': { id:'SH-A01', name:'Backstab', class:'shroud', type:'Attack', cost:2, atk:4, def:0, desc:'Deals 4 damage. +1 Damage if target has no Armor.', color:'red' },
  'SH-A02': { id:'SH-A02', name:'Shadow Bolt', class:'shroud', type:'Attack', cost:3, atk:5, def:0, desc:'Deals 5 damage. Target cannot block.', color:'red' },
  'SH-A03': { id:'SH-A03', name:'Silence', class:'shroud', type:'Attack', cost:1, atk:3, def:0, desc:'Deals 3 damage. Target loses ability to use cards.', color:'red' },
  'SH-A04': { id:'SH-A04', name:'Vengeance', class:'shroud', type:'Attack', cost:3, atk:6, def:0, desc:'Deals 6 damage. Gain 2 Energy.', color:'red' },
  'SH-D01': { id:'SH-D01', name:'Blur', class:'shroud', type:'Defense', cost:3, atk:0, def:2, desc:'Gain 2 Defense. Ignore next attack.', color:'blue' },
  'SH-D02': { id:'SH-D02', name:'Step', class:'shroud', type:'Defense', cost:2, atk:0, def:3, desc:'Gain 3 Defense. Gain 1 Energy.', color:'blue' },
  'SH-D03': { id:'SH-D03', name:'Evasion', class:'shroud', type:'Defense', cost:1, atk:0, def:1, desc:'Gain 1 Defense. Skip enemy action.', color:'blue' },
  'SH-D04': { id:'SH-D04', name:'Phantom', class:'shroud', type:'Defense', cost:2, atk:0, def:4, desc:'Gain 4 Defense. Ghost form for 1 turn.', color:'blue' },
  'SH-U01': { id:'SH-U01', name:'Dash', class:'shroud', type:'Other', cost:1, atk:0, def:0, desc:'Gain 1 Energy. Skip enemy attack.', color:'purple' },
  'SH-U02': { id:'SH-U02', name:'Teleport', class:'shroud', type:'Other', cost:2, atk:0, def:0, desc:'Move to back row. Deal 2 damage.', color:'purple' },
  'SH-U03': { id:'SH-U03', name:'Hide', class:'shroud', type:'Other', cost:2, atk:0, def:0, desc:'Gain 1 Defense. Discard 1 card. Draw 2 cards.', color:'purple' },
  'SH-U04': { id:'SH-U04', name:'Assassinate', class:'shroud', type:'Other', cost:3, atk:0, def:0, desc:'Deal 8 damage. Cannot be blocked this turn.', color:'purple' }
};

/* =========================================================
   INITIALIZATION
   ========================================================= */
function initGame() {
  STATE.hero.class = 'bastion';
  STATE.hero.hp = 35;
  STATE.hero.maxHp = 35;
  STATE.hero.energy = 3;
  STATE.hero.maxEnergy = 3;
  STATE.hero.defense = 0;
  STATE.hero.gold = 0;
  STATE.hero.hand = [];
  STATE.hero.deck = [];
  STATE.hero.inventory = {};
  STATE.hero.handSize = 4;
  STATE.hero.burn = 0;
  STATE.hero.poison = 0;
  STATE.hero.stunned = false;
  STATE.hero.floor = 1;
  STATE.hero.room = 1;

  STATE.enemy = { name:'Goblin', hp:20, maxHp:20, dmg:3, defense:0, stun:0, burn:0, poison:0, isBoss:false, floor:1 };

  STATE.selectedCards = [];
  STATE.log = [];

  // Build starter deck
  STATE.hero.deck = [
    'BA-A03','BA-D01','BA-U03',
    'BA-A01','BA-D03','BA-U01',
    'BA-A02','BA-U02','BA-U04',
    'BA-D02','BA-A04','BA-D04'
  ];
  for (const id of STATE.hero.deck) addToInventory(id);

  STATE.turnPhase = 'player';
  drawHand();
  updateUI();
  addLog("A new journey begins in the shadows of Aethelgard...");
  openShop(); // Force first shop
}

function addToInventory(id) {
  STATE.hero.inventory[id] = (STATE.hero.inventory[id] || 0) + 1;
  if (STATE.hero.inventory[id] > STATE.hero.maxCopy) STATE.hero.inventory[id] = STATE.hero.maxCopy;
}

function drawHand() {
  while (STATE.hero.hand.length < STATE.hero.handSize && STATE.hero.deck.length > 0) {
    const idx = Math.floor(Math.random() * STATE.hero.deck.length);
    const cardId = STATE.hero.deck.splice(idx, 1)[0];
    STATE.hero.hand.push(CARDS[cardId]);
  }
  renderHand();
}

function renderHand() {
  const container = document.getElementById('hand-container');
  container.innerHTML = '';
  STATE.hero.hand.forEach((card, i) => {
    const el = document.createElement('div');
    el.className = 'card-wrapper playable';
    el.innerHTML = buildCardHTML(card, i);
    el.onclick = () => toggleSelectCard(i);
    if (STATE.hero.energy < card.cost) el.classList.remove('playable');
    else if (STATE.hero.stunned) el.classList.remove('playable');
    else el.classList.add('playable');
    container.appendChild(el);
  });
}

function buildCardHTML(card, idx) {
  const className = card.class;
  const artSVG = cardSVGInner(card);
  let statRow = '';
  if (card.atk > 0 || card.def > 0) {
    statRow = `<div class="card-stats-row">
      <span>${card.atk ? '⚔ ' + card.atk : ''}</span>
      <span>${card.def ? '🛡 ' + card.def : ''}</span>
    </div>`;
  }
  // Placeholder art for main card image (unique frame per class)
  const frameColor = className === 'bastion' ? '#8a6e2f' : className === 'wither' ? '#6e2f2f' : '#3a2a6e';
  const artPlaceholder = `
    <svg viewBox="0 0 100 60" xmlns="http://www.w3.org/2000/svg" style="width:100%; height:100%;">
      <rect width="100" height="60" fill="#0a0808" stroke="${frameColor}" stroke-width="2"/>
      <text x="50" y="32" text-anchor="middle" font-size="8" fill="#aaa" font-family="serif">CARD ART</text>
      <text x="50" y="42" text-anchor="middle" font-size="6" fill="#555" font-family="sans-serif">PLACEHOLDER</text>
      <rect x="10" y="10" width="80" height="40" fill="none" stroke="${frameColor}" stroke-width="1" stroke-dasharray="2 2"/>
    </svg>
  `;

  return `
    <div class="card-inner" style="border-top: 3px solid ${frameColor};">
      <div class="card-type-header">
        <span style="color:${card.color === 'red' ? '#e85555' : card.color === 'blue' ? '#5aa3d5' : '#b87ad5'};">${card.type}</span>
        <span class="card-cost">${card.cost}</span>
      </div>
      <div class="card-title">${card.name}</div>
      <div class="card-art">${artPlaceholder}</div>
      <div class="card-ability">
        <div class="card-desc">${card.desc}</div>
        ${statRow}
      </div>
    </div>
  `;
}

function cardSVGInner(card) {
  // Unique art placeholder could vary; we keep it simple
  return '';
}

function toggleSelectCard(i) {
  if (STATE.turnPhase !== 'player') return;
  if (STATE.hero.stunned) { addLog("You are stunned and cannot play cards!"); return; }
  const card = STATE.hero.hand[i];
  if (STATE.hero.energy < card.cost) {
    addLog("Not enough Energy to play " + card.name + "!");
    return;
  }
  if (STATE.selectedCards.includes(i)) {
    STATE.selectedCards = STATE.selectedCards.filter(x => x !== i);
  } else {
    STATE.selectedCards.push(i);
  }
  renderHand();
  updateUI();
}

function buildBackHTML(className) {
  let color = '#4a2236'; // bastion default
  let text = 'B';
  if (className === 'wither') { color = '#4a2a1a'; text = 'W'; }
  if (className === 'shroud') { color = '#2a1a4a'; text = 'S'; }
  return `
    <div class="card-back">
      <svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
        <rect width="100" height="100" fill="#080510" stroke="${color}" stroke-width="3"/>
        <circle cx="50" cy="50" r="30" fill="none" stroke="${color}" stroke-width="2"/>
        <text x="50" y="58" text-anchor="middle" font-size="36" fill="${color}" font-family="Cinzel Decorative" font-weight="bold">${text}</text>
        <path d="M30 70 L50 40 L70 70" stroke="${color}" stroke-width="4" fill="none"/>
        <circle cx="50" cy="50" r="8" fill="${color}"/>
      </svg>
    </div>
  `;
}

function renderBackCards() {
  // Not needed for play area, but could be used in deck view
  return;
}

/* =========================================================
   GAME ACTIONS
   ========================================================= */
function playHand() {
  if (STATE.turnPhase !== 'player') return;
  if (STATE.selectedCards.length === 0) {
    addLog("Select cards to play.");
    return;
  }
  // Resolve selected cards in order
  STATE.selectedCards.sort((a,b) => a - b);
  const cardsToPlay = STATE.selectedCards.map(i => STATE.hero.hand[i]);
  STATE.hero.energy -= cardsToPlay.reduce((s, c) => s + c.cost, 0);

  for (const card of cardsToPlay) {
    resolveCardEffect(card);
  }

  // Remove played cards
  STATE.hero.hand = STATE.hero.hand.filter((_, i) => !STATE.selectedCards.includes(i));
  STATE.selectedCards = [];

  // Enemy turn after player actions
  STATE.turnPhase = 'enemy';
  addLog("--- Enemy Turn ---");
  setTimeout(() => {
    resolveEnemyTurn();
    STATE.turnPhase = 'player';
    STATE.hero.stunned = false;
    STATE.enemy.stun = Math.max(0, STATE.enemy.stun - 1);
    STATE.hero.defense = 0; // Defense resets per turn
    STATE.hero.energy = Math.min(STATE.hero.maxEnergy, STATE.hero.energy + 1);
    drawHand();
    renderHand();
    updateUI();
    addLog("Your turn begins.");
    // Check win/loss
    if (STATE.enemy.hp <= 0) {
      defeatEnemy();
    }
    if (STATE.hero.hp <= 0) {
      gameOver();
    }
  }, 600);
  updateUI();
}

function resolveCardEffect(card) {
  let dmg = card.atk || 0;
  // Bastion Slam bonus
  if (card.id === 'BA-A01' && STATE.hero.hp >= 30) {
    drawHand(); // draw 1 card simulated by adding extra draw attempt
    // Actually draw 1 immediately
    if (STATE.hero.deck.length > 0) {
      const c = STATE.hero.deck.splice(Math.floor(Math.random()*STATE.hero.deck.length),1)[0];
      STATE.hero.hand.push(CARDS[c]);
      addLog("Slam bonus: Draw a card!");
    }
  }
  // Shroud Backstab +1 if enemy has 0 defense
  if (card.id === 'SH-A01' && STATE.enemy.defense <= 0) dmg += 1;

  if (card.type === 'Attack') {
    addLog(`Played ${card.name}: Deals ${dmg} damage.`);
    let finalDmg = Math.max(0, dmg - STATE.enemy.defense);
    STATE.enemy.hp -= finalDmg;
    STATE.enemy.hp = Math.max(0, STATE.enemy.hp);
    addLog(`Enemy takes ${finalDmg} damage. (HP: ${STATE.enemy.hp}/${STATE.enemy.maxHp})`);

    // Apply burn / status
    if (card.id === 'WI-A01') { STATE.enemy.burn += 1; addLog("Applied 1 Burn."); }
    if (card.id === 'WI-A03') { STATE.enemy.burn += 1; STATE.enemy.poison += 1; addLog("Applied 1 Burn + Poison."); }
    if (card.id === 'WI-A02') { STATE.enemy.burn += 3; addLog("Applied 3 Burn."); }
    if (card.id === 'WI-A04') { STATE.enemy.burn += 1; /* All enemies next turn handled globally */ }
    if (card.id === 'WI-U02') { STATE.enemy.hp -= 3; STATE.enemy.burn += 2; addLog("Burn: 3 dmg + 2 Burn to all."); }
    if (card.id === 'SH-A03') { STATE.enemy.stun += 1; addLog("Silenced / Stunned enemy for 1 turn!"); }
    if (card.id === 'BA-D04') { STATE.enemy.stun += 1; addLog("Taunted enemy: Stunned 1 turn."); }
    if (card.id === 'BA-A02') { STATE.enemy.hp -= 4; addLog("Earthquake hits for 4!"); }
    if (card.id === 'BA-A04') { STATE.enemy.hp -= 6; addLog("Boulder smashes for 6!"); }
    if (card.id === 'BA-A03') { STATE.enemy.hp -= 2; addLog("Stone Fist hits for 2!"); }
    if (card.id === 'SH-A02') { STATE.enemy.hp -= 5; STATE.enemy.defense = 0; addLog("Shadow Bolt ignores block for 5!"); }
    if (card.id === 'SH-A04') { STATE.enemy.hp -= 6; STATE.hero.energy += 2; addLog("Vengeance: 6 dmg, gain 2 Energy!"); }
    if (card.id === 'SH-U04') { STATE.enemy.hp -= 8; addLog("Assassinate: 8 unblockable damage!"); }
    if (card.id === 'SH-A03') { STATE.enemy.hp -= 3; STATE.enemy.stun += 1; addLog("Silence: 3 dmg + Stun!"); }
    if (card.id === 'SH-U02') { STATE.enemy.hp -= 2; addLog("Teleport: 2 dmg!"); }
    if (card.id === 'WI-U03') { STATE.enemy.stun += 1; addLog("Slow: Target stunned!"); drawHand(); }
  }

  if (card.type === 'Defense') {
    let def = card.def;
    STATE.hero.defense += def;
    addLog(`Played ${card.name}: Gain ${def} Defense.`);
    // Specific triggers
    if (card.id === 'BA-D01') { addLog("Shield Wall active."); }
    if (card.id === 'BA-D02') { STATE.hero.defense += 5; addLog("Iron Skin: Permanent +5 Defense!"); STATE.hero.defense = 5; }
    if (card.id === 'BA-D03') { STATE.hero.defense += 2; addLog("Stand Firm: +1 Block."); STATE.enemy.defense = Math.max(0, STATE.enemy.defense - 1); }
    if (card.id === 'BA-U01') {
      // Search: Draw 1, discard if > 5
      if (STATE.hero.deck.length > 0) {
        const c = STATE.hero.deck.splice(Math.floor(Math.random()*STATE.hero.deck.length),1)[0];
        STATE.hero.hand.push(CARDS[c]);
      }
      if (STATE.hero.hand.length > 5) {
        STATE.hero.hand = STATE.hero.hand.slice(0, 5);
        addLog("Search: Drawn, but discarded to 5.");
      }
      addLog("Search: Draw 1 card.");
    }
    if (card.id === 'WI-D01') { addLog("Scorch Shield: Block 1 Burn damage next turn!"); }
    if (card.id === 'WI-D03') { addLog("Smoke: Block 1 Burn!"); }
    if (card.id === 'WI-D04') { STATE.hero.defense += 2; STATE.hero.hp = Math.min(STATE.hero.maxHp, STATE.hero.hp + 2); addLog("Endure: +2 Def, Heal 2."); }
    if (card.id === 'WI-U04') { STATE.hero.hp = Math.min(STATE.hero.maxHp, STATE.hero.hp + 5); STATE.enemy.dmg = Math.max(1, STATE.enemy.dmg - 1); addLog("Wither: Heal 5, reduce enemy Atk by 1!"); }
    if (card.id === 'SH-D01') { addLog("Blur: Ignore next attack!"); STATE.hero.defense += 10; /* temporary boost for turn */ }
    if (card.id === 'SH-D02') { STATE.hero.defense += 3; STATE.hero.energy += 1; addLog("Step: +3 Def, +1 Energy!"); }
    if (card.id === 'SH-D03') { STATE.hero.defense += 1; STATE.turnPhase = 'skip'; addLog("Evasion: Skip enemy action this turn!"); STATE.enemy.stun += 1; }
    if (card.id === 'SH-D04') { STATE.hero.defense += 4; addLog("Phantom: Ghost form active!"); }
  }

  if (card.type === 'Other') {
    if (card.id === 'BA-U02') { STATE.hero.hp = Math.min(STATE.hero.maxHp, STATE.hero.hp + 6); addLog("Repair: Heal 6 HP!"); }
    if (card.id === 'BA-U03') { STATE.hero.energy += 1; if (STATE.hero.deck.length > 0) { const c = STATE.hero.deck.splice(Math.floor(Math.random()*STATE.hero.deck.length),1)[0]; STATE.hero.hand.push(CARDS[c]); } addLog("Rally: Gain 1 Energy, Draw 1!"); }
    if (card.id === 'BA-U04') { STATE.hero.gold += 5; addLog("Loot: Gain 5 Gold!"); }
    if (card.id === 'WI-U01') { STATE.enemy.poison += 1; addLog("Poison: Apply 1 Poison!"); }
    if (card.id === 'WI-D02') { STATE.hero.defense += 1; STATE.hero.energy += 1; addLog("Heat Resist: +1 Def, +1 Energy!"); }
    if (card.id === 'WI-D04') { STATE.hero.hp = Math.min(STATE.hero.maxHp, STATE.hero.hp + 2); STATE.hero.defense += 2; addLog("Endure: +2 Def, Heal 2!"); }
    if (card.id === 'SH-U01') { STATE.hero.energy += 1; STATE.turnPhase = 'skip'; STATE.enemy.stun += 1; addLog("Dash: Gain 1 Energy, Skip enemy attack!"); }
    if (card.id === 'SH-U03') { STATE.hero.defense += 1; if (STATE.hero.hand.length > 1) STATE.hero.hand.splice(STATE.hero.hand.length-1, 1); addLog("Hide: +1 Def, discard 1, draw 2..."); STATE.hero.hand.push(CARDS['BA-A01']); STATE.hero.hand.push(CARDS['BA-D01']); }
  }

  // Status effects applied after effects
  if (STATE.enemy.burn > 0) {
    STATE.enemy.hp -= STATE.enemy.burn;
    STATE.enemy.hp = Math.max(0, STATE.enemy.hp);
    addLog(`Burn: Enemy takes ${STATE.enemy.burn} damage.`);
  }
  if (STATE.enemy.poison > 0) {
    STATE.enemy.hp -= STATE.enemy.poison;
    STATE.enemy.hp = Math.max(0, STATE.enemy.hp);
    addLog(`Poison: Enemy takes ${STATE.enemy.poison} damage.`);
  }
}

function resolveEnemyTurn() {
  if (STATE.enemy.stun > 0) {
    addLog("Enemy is stunned and skips its turn!");
    STATE.enemy.stun = Math.max(0, STATE.enemy.stun - 1);
    return;
  }
  // Enemy damage calculation
  let dmg = STATE.enemy.dmg;
  // Boss mechanics
  if (STATE.enemy.isBoss) {
    if (STATE.enemy.floor === 1 && STATE.enemy.hp > STATE.enemy.maxHp * 0.25) {
      dmg = Math.max(0, dmg - 5);
      addLog("Boss 1 blocks 5 damage until below 25% HP!");
    }
    if (STATE.enemy.floor === 2 && STATE.hero.energy < 3) {
      dmg += 5;
      addLog("Boss 2 deals +5 damage when you have < 3 Energy!");
    }
    if (STATE.enemy.floor === 3) {
      STATE.enemy.hp = Math.min(State.enemy.maxHp, STATE.enemy.hp + 10);
      addLog("Boss 3 regenerates 10 HP!");
    }
  }
  let finalDmg = Math.max(0, dmg - STATE.hero.defense);
  STATE.hero.defense = Math.max(0, STATE.hero.defense - dmg);
  STATE.hero.hp -= finalDmg;
  addLog(`Enemy attacks for ${finalDmg} damage! Your HP: ${STATE.hero.hp}/${STATE.hero.maxHp}`);
  STATE.hero.hp = Math.max(0, STATE.hero.hp);
}

function defeatEnemy() {
  STATE.hero.room++;
  let goldGain = STATE.enemy.isBoss ? 15 : 5;
  STATE.hero.gold += goldGain;
  // Boss kill advances floor
  if (STATE.enemy.isBoss) {
    addLog(`*** BOSS DEFEATED! +${goldGain} Gold ***`);
    STATE.hero.floor++;
    STATE.hero.room = 1;
    STATE.enemy.isBoss = false;
    STATE.enemy.hp = 40 + STATE.hero.floor * 10;
    STATE.enemy.dmg = 3 + STATE.hero.floor * 2;
    STATE.enemy.maxHp = STATE.enemy.hp;
  } else {
    addLog(`Enemy defeated! +${goldGain} Gold.`);
  }
  addLog("Moving to next encounter...");
  spawnNextEnemy();
  STATE.turnPhase = 'player';
  STATE.hero.defense = 0;
  STATE.hero.energy = Math.min(STATE.hero.maxEnergy, STATE.hero.energy + 1);
  drawHand();
  renderHand();
  updateUI();
  openShop(); // Auto open shop after combat
}

function spawnNextEnemy() {
  // Random enemy based on floor
  const floor = STATE.hero.floor;
  if (floor === 1) {
    STATE.enemy = { name: 'Goblin', hp: 20, maxHp: 20, dmg: 3, defense: 0, stun: 0, burn: 0, poison: 0, isBoss: false, floor: 1 };
    document.getElementById('boss-tag').style.display = 'none';
  } else if (floor === 2) {
    STATE.enemy = { name: 'Vampire Knight', hp: 30, maxHp: 30, dmg: 5, defense: 0, stun: 0, burn: 0, poison: 0, isBoss: false, floor: 2 };
    document.getElementById('boss-tag').style.display = 'none';
  } else if (floor === 3) {
    if (STATE.hero.room === 3 || STATE.hero.room === 6 || STATE.hero.room === 9) {
      // Bosses at end of floors
      if (STATE.hero.room === 3) STATE.enemy = { name: 'The Gatekeeper', hp: 80, maxHp: 80, dmg: 15, defense: 5, stun: 0, burn: 0, poison: 0, isBoss: true, floor: 1 };
      if (STATE.hero.room === 6) STATE.enemy = { name: 'The Corrupted', hp: 80, maxHp: 80, dmg: 20, defense: 0, stun: 0, burn: 0, poison: 0, isBoss: true, floor: 2 };
      if (STATE.hero.room === 9) STATE.enemy = { name: 'The Void Lord', hp: 80, maxHp: 80, dmg: 15, defense: 0, stun: 0, burn: 0, poison: 0, isBoss: true, floor: 3 };
      document.getElementById('boss-tag').style.display = 'inline-block';
    } else {
      STATE.enemy = { name: 'Void Warrior', hp: 40, maxHp: 40, dmg: 8, defense: 0, stun: 0, burn: 0, poison: 0, isBoss: false, floor: 3 };
      document.getElementById('boss-tag').style.display = 'none';
    }
  }
  // Ensure floor label is correct for boss mechanics tracking
  STATE.enemy.floor = STATE.hero.floor;
}

function endTurn() {
  if (STATE.turnPhase !== 'player') return;
  STATE.hero.defense = 0;
  STATE.hero.stunned = false;
  STATE.enemy.stun = Math.max(0, STATE.enemy.stun - 1);
  STATE.hero.energy = Math.min(STATE.hero.maxEnergy, STATE.hero.energy + 1);
  STATE.turnPhase = 'enemy';
  setTimeout(() => {
    resolveEnemyTurn();
    STATE.turnPhase = 'player';
    if (STATE.enemy.hp <= 0) { defeatEnemy(); return; }
    drawHand();
    renderHand();
    updateUI();
    addLog("Your turn begins.");
  }, 400);
  drawHand();
  renderHand();
  updateUI();
  addLog("You end your turn.");
}

function openShop() {
  document.getElementById('shop-overlay').classList.add('active');
  renderShop();
}

function closeShop(e) {
  document.getElementById('shop-overlay').classList.remove('active');
}

function renderShop() {
  const grid = document.getElementById('shop-grid');
  grid.innerHTML = '';
  const cards = Object.values(CARDS);
  for (const card of cards) {
    if (card.class !== STATE.hero.class) continue; // For simplicity, only show class cards (prototype scope)
    const count = STATE.hero.inventory[card.id] || 0;
    if (count >= STATE.hero.maxCopy) continue;
    const cost = count >= 3 ? 10 : 1; // Scaling simplified: 1 each, 4th = 10
    const btn = document.createElement('div');
    btn.className = 'shop-card';
    btn.innerHTML = `
      <div style="display:flex; justify-content:space-between;">
        <span style="font-size:10px; text-transform:uppercase; color:#888;">${card.type}</span>
        <span class="card-cost">${card.cost}</span>
      </div>
      <h4>${card.name}</h4>
      <div class="ability">${card.desc}</div>
      <div class="price-tag">${cost} Gold <span style="font-size:10px; color:#777;">(Owned: ${count}/5)</span></div>
    `;
    btn.onclick = () => buyCard(card);
    if (STATE.hero.gold < cost) btn.classList.add('disabled');
    grid.appendChild(btn);
  }
}

function buyCard(card) {
  const count = STATE.hero.inventory[card.id] || 0;
  const cost = count >= 3 ? 10 : 1;
  if (STATE.hero.gold < cost) {
    addLog("Not enough gold to buy " + card.name);
    return;
  }
  STATE.hero.gold -= cost;
  STATE.hero.inventory[card.id] = (STATE.hero.inventory[card.id] || 0) + 1;
  STATE.hero.deck.push(card.id);
  addLog(`Bought ${card.name} for ${cost} Gold!`);
  renderShop();
  updateUI();
}

function addLog(msg) {
  STATE.log.push(msg);
  const logEl = document.getElementById('log');
  logEl.innerHTML = STATE.log.slice(-12).map(m => `<div class="entry">${m}</div>`).join('');
  logEl.scrollTop = logEl.scrollHeight;
}

function updateUI() {
  document.getElementById('hud-gold').textContent = STATE.hero.gold;
  document.getElementById('hud-floor').textContent = STATE.hero.floor + ' / ' + STATE.hero.room;
  document.getElementById('hero-hp').textContent = STATE.hero.hp;
  document.getElementById('hero-max-hp').textContent = STATE.hero.maxHp;
  document.getElementById('hero-energy').textContent = STATE.hero.energy;
  document.getElementById('hero-max-energy').textContent = STATE.hero.maxEnergy;
  document.getElementById('hero-defense').textContent = STATE.hero.defense;
  document.getElementById('hero-handsize').textContent = STATE.hero.handSize;
  document.getElementById('hero-class').textContent = 'The ' + STATE.hero.class.charAt(0).toUpperCase() + STATE.hero.class.slice(1);

  const energyContainer = document.getElementById('energy-meter');
  energyContainer.innerHTML = '';
  for (let i = 0; i < STATE.hero.maxEnergy; i++) {
    const orb = document.createElement('div');
    orb.className = 'energy-orb' + (i < STATE.hero.energy ? '' : ' empty');
    orb.textContent = i + 1;
    energyContainer.appendChild(orb);
  }

  document.getElementById('enemy-name').textContent = STATE.enemy.name;
  document.getElementById('enemy-hp-display').textContent = STATE.enemy.hp + ' / ' + STATE.enemy.maxHp;
  document.getElementById('enemy-dmg').textContent = STATE.enemy.dmg;
  document.getElementById('enemy-def').textContent = STATE.enemy.defense;
  document.getElementById('shop-floor').textContent = STATE.hero.floor;
  document.getElementById('shop-enemy-type').textContent = STATE.enemy.isBoss ? 'Boss Room' : (STATE.hero.room % 3 === 0 ? 'Boss Room' : 'Enemy Room');

  if (STATE.enemy.hp < STATE.enemy.maxHp * 0.25 && STATE.enemy.isBoss && STATE.enemy.floor === 1) {
    document.getElementById('enemy-def').textContent = '0';
    addLog("Boss 1 defense broken!");
  }

  document.getElementById('hud-boss-hp').textContent = STATE.enemy.hp;
}

function gameOver() {
  document.getElementById('hand-container').innerHTML = `<div style="color:#e85555; font-size:18px; text-align:center;">GAME OVER</div>`;
  document.getElementById('log').innerHTML = `<div class="entry dmg">Hero defeated. The shadows consume all.</div>`;
}

window.addEventListener('load', () => {
  initGame();
});
</script>
</body>
</html>
<!-- agent-meta {"model":"thinkingmachines/inkling","provider":"openrouter","persona":"basic","sessionId":"3d89977d-970d-495a-b00c-12b18965e288","tokensIn":3572,"tokensOut":15886,"tokensTotal":19458,"turns":1,"toolCalls":0,"failedToolCalls":0,"timestamp":"2026-07-18T20:43:50.825Z"} -->