# WebUI Theme Contract GovOPlaN supports `system`, `light`, and `dark` as persisted user preferences. `system` follows `prefers-color-scheme` live; it is not resolved permanently at save time. Core applies the resolved mode through `data-theme` on the document root and exposes the selected preference through `data-theme-preference`. Each user may also choose a validated `default`, `civic_blue`, `forest`, or `plum` accent palette. Core applies it through `data-palette`; every module inherits the result through semantic tokens without module-specific CSS. ## Ownership - Core owns semantic CSS tokens, native `color-scheme`, preference persistence, the Settings selector, and the shared shell. - Modules consume semantic tokens such as `--surface`, `--text`, `--line`, and the status token families. They may define domain aliases whose values resolve to shared tokens. - Palette defaults form a provenance chain: system, tenant, then an explicit user choice. Invalid stored values are ignored. Reset means inheritance and does not copy the current parent value into the child scope. - A policy lock is separate from the default. A system lock wins over every child scope; otherwise a tenant lock suppresses a personal override. The authenticated profile reports the effective palette, source, inherited palette, and lock state. - Tenant branding is a separate policy surface and must preserve contrast and status semantics in both modes. ## Palette safety and scope The Settings preview shows the chosen or inherited accent in every applicable light/dark preview before Save. Presets are checked for WCAG AA contrast in the theme contract. Arbitrary token overrides and branding import/export are not inferred from this preference and require their own governed follow-up. Do not introduce fixed foreground/background colors in a module merely to make one mode look correct. Add or reuse a semantic Core token, then define both light and dark values. Bitmap content and externally authored HTML are exempt, but their surrounding controls must still use the shared tokens. `npm run test:theme-contract` verifies root mode/palette behavior, preset contrast, and representative Campaign, Calendar, Files, and Mail token consumption. The check runs before a production WebUI build.