# 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. - User preference selects the mode and palette. Invalid stored palette values fail safely to `default`; the profile API accepts only the supported preset identifiers. Tenant and system policy may provide a future default, but must not silently replace an explicit user choice. - Tenant branding is a separate policy surface and must preserve contrast and status semantics in both modes. ## Palette safety and scope The current slice is intentionally user-level. The Settings preview shows the chosen accent in every applicable light/dark preview before Save, and Reset palette returns the draft to the GovOPlaN default before persistence. Presets are checked for WCAG AA contrast in the theme contract. Arbitrary token overrides, tenant/system defaults, branding import/export, and policy locks 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.