import { config } from '../config/Config.js'; import { toColor } from './Color.js'; /** * Helpers for the shared visual theme (data/theme.json). * * The theme is the game's UI language — fonts, palette, and CRT/glitch * tuning — so every scene reads from here instead of hardcoding looks: * * import { fontStack, themeColor } from '../utils/Theme.js'; * const titleStyle = { fontFamily: fontStack('header'), ... }; * const neon = themeColor('neon', 0x00e5ff); */ /** * Canvas-ready CSS font stack for a theme font kind ('header' | 'body'). * * fontStack('header') → "'Ethnocentric', 'Arial Black', 'Impact', sans-serif" * * Falls back to a plain system stack if the theme section is missing * (e.g. a config that predates theme.json). */ export function fontStack(kind = 'body') { const f = config.get(`theme.fonts.${kind}`); if (f && typeof f.family === 'string' && f.family.length > 0) { const family = /[^a-z0-9-]/i.test(f.family) ? `'${f.family}'` : f.family; const fallbacks = Array.isArray(f.cssFallbacks) ? f.cssFallbacks : []; return [family, ...fallbacks, 'sans-serif'].join(', '); } return "'Segoe UI', 'Helvetica Neue', Arial, sans-serif"; } /** A theme palette color as an int: themeColor('neon', 0x00e5ff) */ export function themeColor(name, fallback = 0xffffff) { return toColor(config.get(`theme.colors.${name}`, undefined), fallback); }