/** * Chart colour roles — all CSS custom properties so light/dark swap without re-render. * Categorical slots are assigned in FIXED order (dataviz rule: colour follows the entity, never its rank; * never cycle past 8 — fold to "Other" or facet). */ export const SERIES_MAX = 8; export function seriesVar(index: number): string { const i = Math.min(Math.max(index, 0), SERIES_MAX - 1) + 1; return `var(--series-${i})`; } /** Sequential (choropleth) class fill, k ∈ 1..7 light→dark. */ export function seqVar(step: number): string { const i = Math.min(Math.max(step, 1), 7); return `var(--seq-${i})`; } export const CHART = { ink: 'var(--ink)', ink2: 'var(--ink-2)', ink3: 'var(--ink-3)', rule: 'var(--rule)', ruleStrong: 'var(--rule-strong)', surface: 'var(--surface)', accent: 'var(--accent)', accentSoft: 'var(--accent-soft)', up: 'var(--up)', down: 'var(--down)', nodata: 'var(--nodata)', forecast: 'var(--forecast)', } as const; /** Mark specs (dataviz marks-and-anatomy): thin marks, 2px lines, ≥8px end dots, 24px max bar thickness. */ export const MARK = { line: 2, dotR: 4, ringW: 2, barMax: 24, barRadius: 4, gap: 2, areaOpacity: 0.12, } as const;