/// Per-parameter help, surfaced by ParamSlider. Texts mirror the web app's
/// `src/ui/paramHelp.ts`, keyed by the native `ParamDescriptor.label` (which
/// differs from the web label for several params). Matrix cells share one text.
enum ParamHelp {
static let byLabel: [String: String] = [
// Global
"Agents": "How many particles run the simulation. Higher = denser trails and slower frame rate.",
"Exposure": "Overall image brightness, applied before tone-mapping. Push higher for glowy / blown-out highlights.",
"Sim speed": "How many physics steps run per rendered frame. 1× is real time; 8× evolves the pattern much faster but costs ~8× GPU.",
// Species
"Population": "Relative fraction of agents that belong to this species. Set one to 0 to hide that species entirely.",
"Sensor angle": "Spread of the left/right antennae relative to the agent's heading. Wider = sees more of the surroundings.",
"Sensor distance": "How far ahead the antennae sample the pheromone field. Larger = thicker, more cohesive structures.",
"Turn speed": "How sharply agents can change direction per step. Low = smooth curves; high = nervous zig-zag.",
"Move speed": "How far agents step each frame. Higher = faster pattern evolution but less coherent trails.",
"Deposit": "How much pheromone each agent drops every frame. Higher = brighter, more dominant trails.",
// Pheromone
"Decay": "How much of the trail survives each diffusion pass (0.97 = 3 % fades per pass). Higher = persistent ghosts.",
"Diffusion": "Diffuse (blur) the pheromone field every N frames. 1 = constant blur (soft), 12 = sharp trails that rarely smear.",
"Fade": "Extra decay applied on top of decay rate. Useful for thinning persistent bright spots.",
"Trail cap": "Pheromone cap before the renderer clips. Lower = brighter trails saturate faster (washes out highlights).",
// Dynamics
"Chaos interval": "Frames between random kicks to every agent's heading. 0 disables. Lower = more frequent jolts.",
"Chaos strength": "How violent each chaos kick is. Pairs with Chaos interval: rare strong kicks vs frequent gentle ones.",
"Rhythm": "A per-agent sine-wander layered on top of the steering. Adds a subtle wobble — set to 0 for clean trails.",
// Effects
"Head glow": "Bright stamp at each agent's current position, on top of the persistent trail. 0 = trail only; 1 ≈ matches trail brightness; 2-3 = comet head. Combine with high Decay rate for long-exposure photography feel.",
"Kaleidoscope": "Folds the image into N mirror axes (1-6). 0 disables. Higher values give more symmetry — 6 looks like a snowflake.",
"Feedback": "How much of the previous rendered frame leaks into the current one. Creates a soft, smeary echo — not a directional trail. For an actual moving-comet effect, raise Decay rate in the Pheromone section instead (those trails are intrinsic to the agents).",
"Bloom threshold": "Brightness above which pixels start to bloom. Lower = even mid-bright trails glow; higher = only the brightest peaks.",
"Bloom": "How strongly the bloom halo adds back into the scene. 0 disables bloom; high values make everything pulse.",
"Vignette": "Edge darkening — frames the image like a lens. 0 disables.",
"Saturation": "Colour intensity. 0 = greyscale, 1 = neutral, 2 = ultra-saturated.",
"Contrast": "Stretch around mid-grey. 0 = flat grey, 1 = neutral, 2 = punchy.",
// Non-scalar controls
"Spawn pattern": "How agents are placed when the simulation seeds. Affects only the initial frames — patterns emerge from the dynamics.",
"Blend mode": "How agents compose over the background. Additive: agents emit light (works on dark bg, saturates with bright bg). Paint: agents are ink on paper (works at any bg, no glow).",
"Background color": "Colour of the empty void. Trails are added on top — pick something dark for high contrast, bright for soft pastels.",
"Species color": "The colour this species deposits into its pheromone channel. Where two species overlap, colours add.",
"Audio reactive": "Master switch for audio modulation. When off, routes below are ignored and factors stay at 1.",
"Auto-gain": "Scales the overall reaction to loudness: quiet is gentle, loud is full, silence stays calm. Disable for a constant, always-full response.",
"Input gain": "Manual master multiplier on the reaction strength. Raise it for more punch; works with Auto-gain on or off.",
]
/// Matrix cells (`M[r,c]`) have no web entry — they share one explanation.
static let matrix = "How strongly the row species senses the column species' trail. Positive attracts, negative repels; the diagonal is a species' response to its own trail (cohesion)."
static func text(for label: String) -> String {
if label.hasPrefix("M[") { return matrix }
return byLabel[label] ?? ""
}
}