Purpose
Emit a burst of small particle shapes from a focal point at a specific beat (typically a music hit or scene climax). Communicates "celebration" / "yes!" / "win" without explicit text.
Params
{
"emit_position": { "x": 540, "y": 960 },
"emit_frame": 36, // when the burst fires
"particle_count": 24,
"particle_size_range_px": [6, 14],
"particle_colors": ["#FF7BB6", "#0F0F0F", "#FFCC33"],
"spread_angle_deg": 90,
"spread_origin_deg": -90, // 0 = right, -90 = up
"initial_velocity_px_per_frame": 12, "gravity_px_per_frame_squared": 0.5,
"duration_frames": 36, // how long particles render before fading out "fade_out_starts_at_frames_remaining": 12,
"rotation_range_rps": [-2, 2], // revolutions per second "shapes": ["rect", "circle", "triangle"] }
## Behaviour
1. At `emit_frame`, instantiate `particle_count` particles at `emit_position`.
2. Each particle has random:
- velocity (initial, plus gravity per frame)
- direction (within `spread_angle_deg` of `spread_origin_deg`)
- color (from `particle_colors`)
- shape (from `shapes`)
- size (from `particle_size_range_px`)
- rotation rate
3. Render each particle's position + rotation per frame.
4. Fade out in the last `fade_out_starts_at_frames_remaining`.
## Style pack overrides
- **SP-G (riso-illustration)** — primary use case. "GOAL!" celebration.
- **SP-E (chaos-card)** — occasional accent on logo lockup.
## Quality Checks
- Particle count 16-32 (not too few = sparse, not too many = visual noise).
- Particles emit from a SINGLE source point (not the full canvas).
- Gravity applied (particles fall, not float).
- Particles fade out before scene end.
## Failure Modes
- **Burst looks like a screensaver (particles float forever).** Add gravity.
- **Burst is too sparse.** Bump count to 24+.
- **Particles overlap text/logo.** Constrain emit zone to outside the hero element bbox.