//! GPU-accelerated particle system.
//!
//! Provides real-time particle effects simulated on the GPU:
//!
//! - [`ParticleEmitter`]: Configurable emitter with shape, velocity, color, and lifetime
//! - [`EmitterShape`]: Point, sphere, cone, or box emission volumes
//! - [`EmitterType`]: Effect presets (Firework, Fire, Smoke, Sparks, Trail)
//! - [`ColorGradient`]: Color and alpha over particle lifetime
//!
//! Particles are rendered as camera-facing billboards with additive blending
//! for emissive effects or alpha blending for smoke.
//!
//! # Using Built-in Presets
//!
//! [`ParticleEmitter`] provides many ready-to-use effect presets:
//!
//! ```ignore
//! // Continuous fire effect
//! let emitter = ParticleEmitter::fire(Vec3::new(0.0, 0.0, 0.0));
//!
//! // Rising smoke plume
//! let emitter = ParticleEmitter::smoke(Vec3::new(0.0, 1.0, 0.0));
//!
//! // Spark fountain
//! let emitter = ParticleEmitter::sparks(Vec3::zeros());
//!
//! // One-shot firework explosion (red, 300 particles)
//! let emitter = ParticleEmitter::firework_explosion(
//!     Vec3::new(0.0, 10.0, 0.0),
//!     Vec3::new(1.0, 0.2, 0.2),  // color
//!     300,                        // particle count
//! );
//! ```
//!
//! # Spawning Particle Emitters
//!
//! ```ignore
//! let entity = world.spawn_entities(
//!     PARTICLE_EMITTER | LOCAL_TRANSFORM | GLOBAL_TRANSFORM | LOCAL_TRANSFORM_DIRTY,
//!     1
//! )[0];
//! world.set_particle_emitter(entity, ParticleEmitter::fire(Vec3::zeros()));
//! world.set_local_transform(entity, LocalTransform {
//!     translation: Vec3::new(5.0, 0.0, 0.0),
//!     ..Default::default()
//! });
//! ```
//!
//! # Firework Presets
//!
//! | Preset | Description |
//! |--------|-------------|
//! | `firework_shell()` | Rising shell with trailing sparks |
//! | `firework_explosion()` | Spherical burst |
//! | `firework_willow()` | Long-lived drooping trails |
//! | `firework_chrysanthemum()` | Dense spherical burst with slow drag |
//! | `firework_ring()` | Flat ring expansion |
//! | `firework_glitter()` | Twinkling scattered particles |
//! | `firework_crackle()` | Fast crackling sparks |
//! | `palm_explosion()` | Upward-biased palm tree shape |
//! | `flash_burst()` | Brief bright flash |
//! | `strobe_effect()` | Sustained bright particles |
//!
//! # Color Gradients
//!
//! Control particle color over lifetime with [`ColorGradient`]:
//!
//! ```ignore
//! // Custom gradient: white -> orange -> red -> transparent
//! let gradient = ColorGradient {
//!     colors: vec![
//!         (0.0, Vec4::new(1.0, 1.0, 1.0, 1.0)),
//!         (0.3, Vec4::new(1.0, 0.5, 0.0, 1.0)),
//!         (0.7, Vec4::new(1.0, 0.2, 0.0, 0.5)),
//!         (1.0, Vec4::new(0.5, 0.0, 0.0, 0.0)),
//!     ],
//! };
//!
//! // Or use built-in gradients
//! let fire_colors = ColorGradient::fire();
//! let smoke_colors = ColorGradient::smoke();
//! ```
//!
//! # Emitter Properties
//!
//! | Property | Unit | Description |
//! |----------|------|-------------|
//! | `spawn_rate` | particles/sec | Continuous emission rate (0 for burst-only) |
//! | `burst_count` | count | Immediate spawn count |
//! | `particle_lifetime_min/max` | seconds | Random lifetime range |
//! | `initial_velocity_min/max` | m/s | Random speed range |
//! | `velocity_spread` | radians | Cone angle from direction |
//! | `gravity` | m/s² | Acceleration vector |
//! | `drag` | 0-1 | Velocity damping per frame |
//! | `size_start/end` | world units | Particle scale over lifetime |
//! | `emissive_strength` | multiplier | HDR bloom intensity |
//! | `one_shot` | bool | Disable after first burst |
//!
//! [`ParticleEmitter`]: components::ParticleEmitter
//! [`EmitterShape`]: components::EmitterShape
//! [`EmitterType`]: components::EmitterType
//! [`ColorGradient`]: components::ColorGradient

pub mod components;
pub mod systems;
