You are CONTINUING a build that was killed by a session cap. The user's budget is fragile — DO NOT cap out before a playable slice exists. Playable slice > complete game. Commit early, refine later. Be efficient.

WHAT EXISTS IN THIS DIR (you started it, then died):
- `index.html` — set up with "IRON FIST HARBOR" title and styling
- `package.json` — vite + typescript + playwright deps
- `vite.config.ts` — base: './'
- `tsconfig.json`
- `scripts/gen-sprites.ts` — FULL Toro + Kage character design constants + STYLE + CHROMA key spec + 7 SpriteSpec entries already defined. Read this first — it has all your prior art direction work and shouldn't be rewritten.
- NO `src/` yet. NO sprites generated yet (cache is empty).

YOUR JOB — minimum viable fighting game, prioritized as a SHIPPING STACK:

**STAGE 1 — must reach (don't stop until done):**
1. `npm install`
2. `node scripts/gen-sprites.ts` — generate the 7 sprites via gpt-image-2 (OPENAI_API_KEY in env). ~$0.28 total. ONE SHOT each — do not regenerate if not perfect, accept the first result. Then exit the sprite step.
3. Write `src/main.ts`, `src/game.ts`, `src/assets.ts`, `src/input.ts` for a **single-round, single-stage 1v1 fight**:
   - 2 characters loaded from generated sprites (Toro left side, Kage right side)
   - Use ONE sprite per character (e.g. their idle/portrait) and animate via canvas transforms (squash/stretch/slide/rotate) for attack frames. **Do NOT try to switch between attack/idle sprites — gpt-image-2 can't keep characters consistent.**
   - 2 attacks per character: light (jab/kick) and heavy (special). Bind to J/K for P1.
   - Hitbox/hurtbox per attack. Light = fast startup, low damage. Heavy = slow startup, high damage.
   - Movement: A/D walk, W jump, S crouch (block).
   - Health bars top of screen, P1 left P2 right (mirrored), 100 HP each.
   - CPU AI for P2: simple — when in range randomly attacks/blocks; when far walks toward player. Make it BEATABLE.
   - Win condition: KO at 0 HP → "K.O." screen → rematch button.
4. `npm run build` — dist/ must populate.
5. Single playwright e2e test: load, click rematch from KO screen, verify match starts, P1 attack reduces P2 hp.

**STAGE 1 IS THE SHIPPING TARGET. If you have any doubt about cap, COMMIT THE BUILD AND STOP HERE.**

**STAGE 2 — only if stage 1 fully done AND ≥30 turns remaining in your budget:**
- Add super meter that fills on hits taken/dealt
- Add 1 super move per character (triggered with L when meter full)
- Add block (hold A while opponent attacks = block, chip dmg only)

**STAGE 3 — only if stages 1+2 done AND ≥20 turns remaining:**
- Best of 3 rounds with round counter
- Character select screen

OUT OF SCOPE — do NOT attempt:
- Multi-stage backgrounds
- Throws / parries / combos beyond cancel-on-hit
- More than 2 characters
- Online multiplayer
- Replay mode
- Audio overhaul (basic Web Audio synth pew sounds OK, no music)
- Per-frame sprite animation switching across multiple sprites

BUDGET HARD CAP: **50 turns total.** If you're approaching 40 turns and stage 1 isn't shipped, stop polishing and commit. Bias toward shipping over perfecting.

WHEN DONE: print one-line summary of what shipped. Result event closes session.
