Theme system is runtime-configurable and user-overridable from config. Source of truth lives in:
spurwechsel/Models/ConfigModels.swiftspurwechsel/Models/ConfigFileModels.swiftspurwechsel/State/ConfigResolver.swiftspurwechsel/DesignSystem/AppTheme.swiftspurwechsel/DesignSystem/ViewStyles.swift
Each palette uses ThemeToken -> ThemeColor.
Supported tokens:
backgroundbackgroundSecondarypanelpanelRaisedpanelMutedborderborderStrongforegroundforegroundMutedforegroundDimaccentaccentForegroundselectionterminalterminalForegroundsuccesswarningerrorinfooverlayoverlayStrongshadow
Hex values accept #RRGGBB or #RRGGBBAA.
ThemeSet: light + dark palettesThemePalette: concrete token mapSpurTheme: SwiftUI-ready colorsTerminalTheme: Ghostty terminal colors
SpurwechselConfig.theme stores effective theme after validation and fallback merge.
- user may override only subset of tokens
- missing tokens fall back to app defaults
- invalid token names are ignored
- invalid hex values produce diagnostics and fall back to defaults
- shell uses
layout.themeModeto choose light or dark palette ShellStore.themeSetupdates after config reload- terminal surfaces use
projectConfig.theme.terminalTheme
- add token to
ThemeToken - add default values to both palettes
- update resolver if validation rules change
- confirm
SpurThemeand terminal mapping both expose token