# @zakkster/lite-fireworks

> Zero-GC SoA fireworks engine. Two render modes: bloom trails (dark) and vector-comets (light). OKLCH colors. One dependency.

## Install
npm i @zakkster/lite-fireworks

## Dependencies
@zakkster/lite-color (OKLCH → CSS string conversion)

## Import
import { FireworksEngine } from '@zakkster/lite-fireworks';

## Key Facts
- SoA Float32Arrays: x, y, vx, vy, life + Uint8Array state, colorIndex
- Two-phase particles: shell (state=1) rises → apex triggers explode → stars (state=2) fade
- Shell velocity from physics: -√(2 × gravity × distance) for correct ballistic arcs
- Pre-parsed OKLCH colors in constructor — zero allocation in updateAndDraw
- Two render modes: bloom (dark, additive blending) and vector-comet (light, stroke trails)
- Config is live-mutable: change gravity/friction/starCount between frames
- RNG injectable: config.rng defaults to Math.random, inject rng.next.bind(rng) for determinism
- No canvas ownership: engine takes (ctx, dt, w, h) — caller handles resize
- destroy() nulls all typed arrays

## API
- new FireworksEngine(maxParticles?, config?)
- .launch(startX, startY, targetY, colorId?) — fire a shell
- .explode(originX, originY, colorId) — manual burst (auto-called at apex)
- .updateAndDraw(ctx, dt, w, h) — physics + render, call once per frame
- .clear() — kill all particles
- .destroy() — release all arrays

## Config
gravity (250), friction (0.96), starCount (60), transparentBackground (false),
fadeColor ('rgba(10,10,10,0.25)'), colors (7 OKLCH), rng (Math.random)

## Usage
const sky = new FireworksEngine(5000);
sky.launch(w/2, h, h * 0.3); // launch from bottom, explode at 30% height
sky.updateAndDraw(ctx, dt, w, h); // in RAF loop

## Seeded Random (deterministic)
import { Random } from '@zakkster/lite-random';
const rng = new Random(42);
const sky = new FireworksEngine(5000, { rng: () => rng.next() });

## Part of the @zakkster ecosystem
Zero-GC, deterministic, tree-shakeable micro-libraries for high-performance web presentation.
