PURPOSE

Canonical registry of named palette presets and the biome-to-preset preference map. Each preset is a small parameter tuple (temperature, brightness, saturation, optional hue_bias) that the palette generator expands into a full cohesive palette. Adding a new look costs 3–4 numbers, not 7 hex picks. Also resolves a biome id (plus an optional mission seed) to a chosen preset id.

OWNS

  • PRESETS: the canonical list of PalettePreset rows (id, displayName, temperature, brightness, saturation, optional hue_bias, optional overrides).
  • _presetById: an internal Map<string, PalettePreset> for id lookup, built once from PRESETS.
  • BIOME_PREFERRED_PALETTES: a Record<string, string[]> mapping biome id to an ordered list of preferred preset ids.
  • Three preset families documented in source: near-greyscale/reference (pure_grey, noir, ice_seed); cool atmospherics (voidmilk, deep_frost, cold_ember, amethyst_drift); pastel/jade/pink/light-blue (rose_quartz, dusty_rose, mint_jade, seafoam, cotton_sky, periwinkle, peach_cream, lavender_haze).
  • Biome entries: landing_site, sunrise_city, the_voidstar, obsidian_spire, jungle_canopy, crystal_cavern, delphi, old_earth.
  • Curation history: presets ember_drift, solar_flare, blood_furnace, sunlit_moss, monochrome_hot were explicitly dropped (Nate 2026-04-22) for being too warm/saturated.

READS FROM

  • ./palette-types: Palette, PalettePreset type imports.
  • ./palette-generator: generatePalette(presetId, preset) — called by getPaletteByPresetId to expand a preset into a full palette.

PUSHES TO

  • getPaletteByPresetId(id): returns a fully-generated Palette, with hand-tuned preset.overrides (if present) applied on top via Object.assign. Throws on unknown id.
  • getAllPresetIds(): returns all preset ids in declared order.
  • getPresetMeta(id): returns the raw PalettePreset row for debug UIs. Throws on unknown id.
  • BIOME_PREFERRED_PALETTES: exported record consumed by anything that needs the raw biome-to-preset table.
  • pickPresetForBiome(biomeId, seed?): returns a single preset id chosen from the biome’s preferred list. With no seed, returns the first preferred. With a seed, indexes the preferred list by Math.abs(Math.floor(seed)) % prefs.length. Falls back to 'voidmilk' for biomes without an entry.

DOES NOT

  • Does not generate palette colors itself — delegates all expansion to generatePalette in palette-generator.
  • Does not cache generated palettes — each getPaletteByPresetId call re-runs the generator and re-applies overrides.
  • Does not register or query biomes from the biome system — the biome-to-preset table is a literal in this file.
  • Does not handle daily/boss/event override paths — the source note says those runs may force an off-preset palette for variety, but that selection lives elsewhere.
  • Does not validate that overrides are well-formed — they are blindly Object.assign’d onto the generated palette.
  • Does not coerce or wrap seeds in any RNG abstraction — uses Math.abs(Math.floor(seed)) directly on the raw number.

Signals

None. This module exposes pure functions and exported constants only; it raises no events and runs no side effects beyond the one-time _presetById map construction at import.

Entry points

  • getPaletteByPresetId(id: string): Palette — primary resolution path used when a preset id is already known.
  • pickPresetForBiome(biomeId: string, seed?: number): string — primary mission-seed entry point; picks the preset id for a biome+seed pair.
  • getAllPresetIds(): string[] — used by debug UIs and tooling that need to enumerate presets.
  • getPresetMeta(id: string): PalettePreset — used by debug UIs that need to display raw preset parameters.
  • BIOME_PREFERRED_PALETTES — direct read access for code that needs the full table.

Pattern notes

  • Data-table-in-code: presets and biome preferences are literal arrays/records in this file rather than JSON, so types are checked at compile time and renames flow through TypeScript references.
  • Crash-on-unknown: both getPaletteByPresetId and getPresetMeta throw on missing ids rather than returning a default — consistent with the project’s no-silent-fallbacks rule for internal lookups.
  • Soft fallback only at the biome edge: pickPresetForBiome defaults to ['voidmilk'] for biomes with no entry, treating biome ids as a softer boundary than preset ids.
  • Overrides as escape hatch: preset.overrides exist for the rare case where the generator produces a slot that reads flat or clashes with art direction — the source comment marks them as deliberately sparing.
  • Seed indexing is deterministic and symmetric around zero: negative seeds map to the same index as their absolute value.
  • Preset rows are aligned column-style in source for readability; new rows should follow the same column layout.
  • Three documented preset families act as informal categories; the source comments serve as the design rationale for each family’s parameter range.