Forced colors / high contrast
How Koder UIs respond when the OS forces a high-contrast color palette (Windows High Contrast / `forced-colors: active`, and equivalent platform modes): defer to the user's system colors, keep every shape and focus ring visible via borders + system-color keywords, and degrade the Verge token layer gracefully. The OS-driven counterpart to the opt-in low-vision mode in a11y-modes.kmd. Fluent 2 + WCAG parity.
Status: v0.1.0 — Draft. Promoted from the Microsoft Fluent 2 parity scan (metadocsstack #081); fills the "Windows high-contrast bridge / forced-colors (separate spec)" deferred by
specs/themes/a11y-modes.kmd. Sources: CSSforced-colorsmedia feature; Windows High Contrast; Fluent 2 high-contrast guidance.
R1 — Two distinct things
- Forced colors (this spec, OS-driven): the OS replaces the palette
(Windows High Contrast,
forced-colors: active). Koder does NOT pick the colors — it defers to the user's system palette. - Low-vision mode (a11y-modes.kmd, Koder opt-in): a Koder-chosen
AAA-contrast theme the user enables in Settings. Independent; both can be active.
Detection is via the forced-colors: active media query (and the platform equivalent on Flutter — highContrast/accessibility flags).
R2 — Defer to system colors
Under forced colors, map UI to the system color keywords rather than brand tokens: CanvasCanvasText (surfacetext), LinkText, ButtonFaceButtonText, HighlightHighlightText (selection), GrayText (disabled), Field/FieldText. Let the OS resolve them; do not hard-code hex in this mode.
R3 — Shapes survive (borders, not fills)
- Decorative backgrounds, shadows, and tonal elevation are typically
flattened by the OS — so components MUST stay legible by border / outline, not fill alone. Add a 1px system-color border to surfaces that relied on background contrast (cards, inputs, buttons, menus).
- Never
forced-color-adjust: noneto "preserve branding" except forgenuine content (e.g. a photo, a brand logo swatch) — never for chrome.
R4 — Focus and state always visible
- The focus ring uses a system color (
Highlight) and stays visible (it isthe primary navigation cue when fills vanish).
- Selected / checked / disabled states are conveyed by system-color +
shape/icon, never by a brand fill that the OS will strip (pairs with the color-is-not-the-only-signal rule, WCAG 1.4.1).
R5 — Icons & images
- Symbolic UI icons (
specs/icons/ui-symbols.kmd) usecurrentColorsothey inherit the system text color and remain visible.
- Purely decorative images may be hidden under forced colors; meaningful
images keep a text alternative.
R6 — Token-layer degradation
The Verge token layer (specs/themes/verge.kmd) defines forced-colors fallbacks centrally so components inherit correct behavior without per-component overrides; lightdark (`specsthemes/light-dark.kmd) is
orthogonal (forced colors overrides both). Verification ties into the BR
conformance matrix (specsaccessibilityconformance-br.kmd`).
Não-escopo
- The opt-in low-vision / color-blind modes (
specs/themes/a11y-modes.kmd). - The base lightdark contract (`specsthemes/light-dark.kmd`).
- Per-component visual specs (each owns its forced-colors border per R3).