theme.ts
Theme, color palette, rarity colors, and composable VFX trait table. Ported 1:1 from the legacy 01-config.js. Pure data module — no runtime side effects. Holds the single source of truth for raw color tokens (SP), semantic UI tokens (THEME), item rarity colors (RARITY_COLORS), and visual-effect trait recipes (VFX_TRAITS), plus one formatNum utility.
River of Hate (Styx) — Color governance
SPis raw tokens. Do not consumeSP.*directly from UI; route throughTHEME.*semantic roles so palette swaps don’t require grepping the codebase.THEME.bgisSP.navywhich is'transparent'— the canvas/nebula background is what shows through, not a solid color. Setting an opaque background anywhere upstream breaks the nebula reveal.THEME.accentis teal (was green pre-port). Anywhere that still expects “green accent” is stale.THEME.accentOrangeis reserved for action CTAs (LAUNCH-class buttons). Don’t bleed orange into informational UI.THEME.danger(#ff3344) is hardcoded — the only non-SPcolor inTHEME. If a second danger shade is needed, lift it intoSPfirst.- Rarity colors are exported as both RGB triplets and hex. Canvas particle code uses
r/g/b; CSS useshex. Keep both in sync if changing a rarity color. VFX_TRAITSis a sparse heterogeneous record —VfxTraitdeclares every possible field as optional. Adding a new trait type with a new field requires extending the interface, not just the table.colorKey: nullin a VFX trait signals “inherit from caller” (rarity, faction, etc).colorKeyas a string is a named lookup the consumer must resolve.formatNumthresholds are asymmetric:<10Kshows one decimal (“1.5K”),>=10Kshows none (“12K”),>=1Mshows one decimal (“1.2M”). Do not “normalize” — the bands are deliberate for HUD density.
Exports
SP (const)
Raw color token bag. Four families:
| Family | Keys | Notes |
|---|---|---|
| Teal | teal, tealBright, tealDim, tealGlow, tealTrack | Primary brand accent. tealGlow/tealTrack are pre-baked rgba. |
| Orange | orange, orangeHot, orangeGlow, peach | Action/focus/LAUNCH. orangeGlow is pre-baked rgba at 0.30 alpha. |
| Navy | navy, navyCard, navyMid, navyBorder | navy is 'transparent', not a color — nebula bg shows through. |
| Text | starlight, white, dim, dimMore | starlight (#fff8d0) is the primary warm text; white (#e4f4ff) is cool secondary. |
THEME (const)
Semantic design tokens — UI roles mapped onto SP. Keys: bg, surface, surfaceLight, border, text, textDim, accent, accentDim, accentOrange, gold, danger, heading, font, mono. Font stacks live here too: heading uses Cal Sans / Impact; body and mono both use Space Grotesk (mono falls back to Georgia).
RarityColor (interface)
{ r: number; g: number; b: number; hex: string; name: string }. RGB for canvas, hex for CSS, name for UI labels.
RARITY_COLORS (const)
| Key | Hex | RGB | Display name |
|---|---|---|---|
green | #50ff78 | 80, 255, 120 | Common |
blue | #50a0ff | 80, 160, 255 | Rare |
epic | #b450ff | 180, 80, 255 | Epic |
legend | #ffd228 | 255, 210, 40 | Legendary |
Note key green maps to display name Common and legend maps to Legendary — internal keys are color-coded, not tier-named.
VfxTrait (interface)
Single shape covering all VFX trait variants. All fields except type are optional. Possible fields: radiusMult, alpha, colorKey, pulse, freq, amp, slots, color, width, rate, spread, heatMod, buildTime, burstRadiusMult, count, duration, symbol, radius.
VFX_TRAITS (const)
Recipe table for composable visual effects. 16 entries:
| Key | type | Notable params |
|---|---|---|
glow | glow | radiusMult 1.5, alpha 0.40, colorKey inherits |
ring | ring | radiusMult 2.0, alpha 0.30, pulsing |
wiggle | wiggle | freq 8, amp 3 |
engine_trail | trail | 5 slots, color #44aaff, width 3 |
exhaust | exhaust | rate 20, color #88aaff |
spark_emit | sparks | rate 8, spread 30, color #ffcc44 |
heat_glow | glow | radiusMult 2.0, colorKey heat, heatMod: true |
distortion | distortion | radiusMult 1.2 |
charge_up | charge | buildTime 1.5s, burstRadiusMult 3, color #ff4444 |
death_burst | burst | count 20, spread 120, inherited color |
shield_pulse | shield | alpha 0.25, pulsing, color #44aaff |
crit_flash | flash | duration 0.08s, white |
boss_aura | aura | radiusMult 3.0, pulsing, color #aa00ff |
elite_mark | mark | symbol ◆ (◆), color #ffcc44 |
warp_ripple | ripple | radius 80, duration 0.4s, color #44ffaa |
pickup_glow | glow | radiusMult 1.8, alpha 0.50, pulsing, inherited color |
formatNum(n: number): string
Compact number formatter for HUD/labels:
n < 1000→ bare integer string1000 ≤ n < 10000→1.5K(one decimal)10000 ≤ n < 1_000_000→12K(zero decimal)n ≥ 1_000_000→1.2M(one decimal)
Negatives and floats below 1000 are passed through String(n) without truncation.
Dependencies
None. Pure constants + one pure function. Consumed broadly across UI, canvas, VFX, and HUD code.
EXTRACT-CANDIDATE
- VFX trait table (
VFX_TRAITS) likely belongs in its owndata/vfx-traits.tsmodule — it has its own interface (VfxTrait), its own shape, and is logically separate from color/theme concerns. Co-located here only because of the legacy 1:1 port. formatNumis a utility, not theme data. Move tosrc/starship-survivors/util/format.ts(or wherever autilbarrel lives) — its presence intheme.tsis incidental.RARITY_COLORScould move todata/rarity.tsif rarity metadata grows beyond color (drop weights, naming overrides, sort order). Today it’s small enough to stay.- The double representation (
r/g/b+hex) inRarityColorinvites drift. Consider deriving one from the other at module load instead of hand-maintaining both.