Semantic Palettes and Action States

Status: Canonical (v1.0)
Last updated: 2026-08-10 Taxonomy placement: D0. Color (Emotional Palette)
Audience: Design Systems, Product Design, Front-End Engineering


CEM uses color as the primary channel for communicating, using a branded palette to express:

Companion specs:

Table of contents

  1. Scope
  2. Design principles
  3. Token taxonomy
  4. Base branded color family
  5. Emotional palette
  6. Theme modes
  7. Action intent and state tokens
  8. Zebra outline colors
  9. System colors and forced-colors
  10. Component mapping checklist
  11. Accessibility and QA
  12. Implementation guidance
  13. Governance and versioning
  14. Canonical token summary
  15. References

1. Scope

1.1 What D0 controls (and what it does not define)

D0 (Color) defines:

D0 (Color) does not define:

This spec defines consumer-semantic color tokens for CEM:

Non-goals:


2. Design principles

2.1 Consumer-semantic meaning first

Tokens are named for what the user experiences (comfort, danger, trust) and for flow semantics (primary, destructive, selected, pending), rather than for RGB/hex values.

2.2 State separation is multi-channel

CEM intentionally separates meaning across channels:

This avoids overloading color fill and improves accessibility in compact/dense UIs.

2.3 Forced-colors is first-class

2.4 Bounded variation (governance by design)

To avoid “palette explosion”, D0 constrains variation intentionally:

2.5 Cross-dimension coupling (informative)

When forced-colors is active, system colors win. CEM must preserve semantics using Canvas, CanvasText, Highlight, SelectedItem, etc., and avoid losing meaning when shadows/glows are dropped by the UA.


3. Token taxonomy

3.1 Consumer color vocabulary (informative)

Emotional terms (what the interface wants the user to feel):

cem-palette-emotion
TermPrimary palette tokenTypical usage
comfort--cem-palette-comfortcanvas/surfaces, low-salience backgrounds
calm--cem-palette-calmsubtle affordances, secondary emphasis
trust--cem-palette-trustexplicit emphasis, strong call-to-action
enthusiasm--cem-palette-enthusiasmalternate emphasis, “positive energy”
creativity--cem-palette-creativityprimary emphasis, “go forward” actions
danger--cem-palette-dangererrors, destructive affordances
conservative--cem-palette-conservativeneutral/disabled, “quiet UI”

Action terms (what an action will do):

cem-action-kind
TermIntent token prefixTypical usage
primary--cem-action-primary-*default “go forward” action
explicit--cem-action-explicit-*strong call-to-action
contextual--cem-action-contextual-*within-context action
alternate--cem-action-alternate-*secondary/alternate action
destructive--cem-action-destructive-*deletion, irreversible change

State terms (how condition changes):

StateChannelNotes
disabled/readonly/editablebackground + textsubdued progression (see §7.2)
hover/active/pendingbackground + textformulaic color-mix() progression (see §7.2)
focus/selected/targetoutline (zebra)do not rely on fill alone (see §8)

3.2 Token model: branded → emotional → action

Branded hues (implementation substrate)
  --cem-color-{hue}-{variant}
        │
        ▼
Emotional palette (semantic contract)
  --cem-palette-{emotion} (+ -x / -text / -text-x)
        │
        ▼
Action intents (consumer-facing API)
  --cem-action-{intent}-{state}-{attribute}

3.3 Why three layers?

CEM color endpoints are layered:

  1. Base branded family (implementation): --cem-color-{hue}-{variant}
  2. Emotional palette (semantic): --cem-palette-{emotion} and --cem-palette-{emotion}-text
  3. Action tokens (flow semantic): --cem-action-{intent}-{state}-{attribute}
  4. Zebra outline colors (state channel): --cem-zebra-color-0..3 + strip size

Rule: consumers should theme primarily by adjusting palette and (optionally) base colors; product code should depend on palette/action/zebra endpoints.


4. Base branded color family

4.1 Brightness variants (selection guidance)

Branded hues are provided in a small, repeatable set of brightness variants:

VariantMeaning (relative)Typical role
xllightestlarge surface fills in light schemes; extreme contrast partner in dark
llightstandard surface/intent fill in light schemes
ddarkstandard surface/intent fill in dark schemes
xddarkestextreme contrast partner in light schemes; deep surfaces in dark

4.2 Contrast pairing rule of thumb

When selecting a safe pairing (especially for text and outlines), prefer opposite ends:

4.3 Neutral (grey) exception

The neutral/grey family is intentionally smaller (typically l + d) and is used primarily via the conservative palette.

The base family is a small set of named hues with a few variants. These are reference values (from theme-data.xhtml) and may be overridden by a brand, as long as the semantic palette mappings remain coherent.

4.4 Branded color tokens

cem-color-hue-variant
TokenHueVariantValueLabelIntended useTier
--cem-color-blue-xlbluexl#e0e8ffLightest blueTrust palette (light scene surface)recommended
--cem-color-blue-lbluel#d7e3ffLight blueTrust palette, attention semanticrecommended
--cem-color-blue-dblued#002f65Dark blueTrust palette (dark theme)recommended
--cem-color-blue-xdbluexd#001b3fDarkest blueTrust palette (dark scene surface)recommended
--cem-color-brown-xlbrownxl#d7ccc8Extra light brownConservative palette (light theme)recommended
--cem-color-brown-lbrownl#a1887fLight brownConservative emotion, brand-3recommended
--cem-color-brown-dbrownd#4e342eDark brownConservative palette (dark theme)recommended
--cem-color-brown-xdbrownxd#3e2723Extra dark brownConservative palette (dark theme, extreme)recommended
--cem-color-cyan-xlcyanxl#f1fefeExtra light cyanUsed for comfort palette (light scenes)recommended
--cem-color-cyan-lcyanl#00fbfbLight cyanCalm palette, creativity accentrecommended
--cem-color-cyan-dcyand#006a6aDark cyanCalm palette (dark theme)recommended
--cem-color-cyan-xdcyanxd#001010Extra dark cyanUsed for comfort palette (dark scenes)recommended
--cem-color-grey-lgreyl#f1f1ebLight greyConservative palette, neutral backgroundsrecommended
--cem-color-grey-dgreyd#1a1c18Dark greyConservative palette (dark theme)recommended
--cem-color-orange-xlorangexl#f0f070Extra light yellowEnthusiasm palette (light theme)recommended
--cem-color-orange-lorangel#ffe082Light orangeEnthusiasm emotion, brand-2recommended
--cem-color-orange-doranged#723600Dark orangeEnthusiasm hype (dark theme)recommended
--cem-color-orange-xdorangexd#502400Extra dark orangeEnthusiasm palette (dark theme, extreme)recommended
--cem-color-purple-xlpurplexl#f3e5f5Extra light purpleCreativity palette (light theme)recommended
--cem-color-purple-lpurplel#e1bee7Light purpleCreativity emotion, brand-1recommended
--cem-color-purple-dpurpled#6a1b9aDark purpleCreativity palette (dark theme)recommended
--cem-color-purple-xdpurplexd#4a148cExtra dark purpleCreativity palette (dark theme, extreme)recommended
--cem-color-red-xlredxl#ffb4abExtra light redDanger palette (light theme)recommended
--cem-color-red-lredl#ba1a1aLight redDanger emotion, alert semanticrecommended
--cem-color-red-dredd#690005Dark redDanger palette (dark theme)recommended
--cem-color-red-xdredxd#410002Extra dark redDanger palette (dark theme, extreme)recommended
--cem-color-visitedtext-30-blacknatdcolor-mix(in srgb, VisitedText 30%, black)light trust-xNative palette Trust extreme variantrecommended
--cem-color-visitedtext-30-whitenatlcolor-mix(in srgb, VisitedText 30%, white)dark trust-xNative palette Trust extreme variantrecommended
--cem-color-mark-30-blacknatdcolor-mix(in srgb, Mark 30%, black)light enthusiasm-xNative palette Enthusiasm extreme variantrecommended
--cem-color-mark-30-whitenatlcolor-mix(in srgb, Mark 30%, white)dark enthusiasm-xNative palette Enthusiasm extreme variantrecommended
--cem-color-canvastext-30-purplenatdcolor-mix(in srgb, CanvasText 30%, purple )light creativity-xNative palette Creativity extreme variantrecommended
--cem-color-canvastext-30-lightpinknatlcolor-mix(in srgb, CanvasText 30%, lightpink)dark creativity-xNative palette Creativity extreme variantrecommended
--cem-color-red-30-blacknatdcolor-mix(in srgb, red 30%, black)light danger-xNative palette Danger extreme variantrecommended
--cem-color-red-30-whitenatlcolor-mix(in srgb, red 30%, white)dark danger-xNative palette Danger extreme variantrecommended
--cem-color-whitenatlwhitedark trust textTrust and Extreme palette dark mode textrecommended

Variant semantics:

4.5 Native browser colors

cem-color-native

CSS system colors adapt automatically to the user's OS color scheme. In native mode, CEM maps palette endpoints directly to these values (see §9).

ColorText pairDescription
AccentColorAccentColorTextBackground of accented user interface controls
AccentColorTextAccentColorText of accented user interface controls
ActiveTextCanvasText of active links
ButtonBorderCanvasBase border color of controls
ButtonFaceCanvasTextBackground color of controls
ButtonTextCanvasText color of controls
CanvasCanvasTextBackground of application content or documents
CanvasTextCanvasText color in application content or documents
FieldCanvasTextBackground of input fields
FieldTextCanvasText in input fields
GrayTextCanvasText color for disabled items
HighlightHighlightTextBackground of selected items
HighlightTextHighlightText color of selected items
LinkTextCanvasText of non-active, non-visited links
MarkMarkTextBackground of specially marked text (e.g. <mark>)
MarkTextMarkText of specially marked text
SelectedItemSelectedItemTextBackground of selected items (e.g. checkbox)
SelectedItemTextSelectedItemText of selected items
VisitedTextCanvasText of visited links

5. Emotional palette

The emotional palette is the primary semantic contract for color.

Reference mappings (from theme-data.xhtml) use light-dark() so a single token resolves appropriately for light vs dark schemes.

cem-palette-emotion-shift
TokenRoleLightdarkNative LightNative DarkUsageEmotionShifttier
--cem-palette-comfortBase comfort colorcyan-xlcyan-xdCanvasMain canvas/backgroundcomfortrequired
--cem-palette-comfort-xComfort extreme variantcyan-xdcyan-xlCanvasTextUsed in color-mix for state variationscomfortxrecommended
--cem-palette-comfort-textComfort text colorcyan-xdcyan-xlCanvasTextPrimary text on comfort backgroundscomforttextrequired
--cem-palette-comfort-text-xComfort extreme textcyan-xlcyan-xdCanvasText on extreme variant backgroundscomforttext-xrecommended
--cem-palette-calmBase calm colorcyan-lcyan-dcyanForeground elementscalmrecommended
--cem-palette-calm-xCalm extreme variantcyan-dcyan-lrgb(0, 120, 120)Inverted calm color ( darked darkcyan )calmxrecommended
--cem-palette-calm-textCalm text colorcomfort-textcomfort-textblackText on calm backgroundscalmtextrecommended
--cem-palette-calm-text-xCalm extreme textcomfort-text-xcomfort-text-xwhiteText on extreme calm backgroundscalmtext-xrecommended
--cem-palette-trustBase trust colorblue-lblue-dcolor-mix(in srgb, Highlight 70%, black)Explicit actions, highlightstrustrequired
--cem-palette-trust-xTrust extreme variantblue-dblue-l--cem-color-visitedtext-30-black--cem-color-visitedtext-30-whiteDarker/lighter trust variationtrustxrecommended
--cem-palette-trust-textTrust text colorcomfort-textwhiteHighlightTextText on trust backgroundstrusttextrequired
--cem-palette-trust-text-xTrust extreme textcomfort-text-xcomfort-text-xCanvasCanvasText on extreme trust backgroundstrusttext-xrecommended
--cem-palette-enthusiasmBase enthusiasm colororange-lorange-dMarkBrand-2, alternate actionsenthusiasmrecommended
--cem-palette-enthusiasm-xEnthusiasm extreme variantorange-xdorange-xl--cem-color-mark-30-black--cem-color-mark-30-whiteDarker/lighter enthusiasm variationenthusiasmxrecommended
--cem-palette-enthusiasm-textEnthusiasm text colorcomfort-textwhiteMarkTextText on enthusiasm backgroundsenthusiasmtextrecommended
--cem-palette-enthusiasm-text-xEnthusiasm extreme textcomfort-text-xcomfort-text-xCanvasText on extreme enthusiasm backgroundsenthusiasmtext-xrecommended
--cem-palette-creativityBase creativity colorpurple-lpurple-dButtonFaceBrand-1, primary actionscreativityrecommended
--cem-palette-creativity-xCreativity extreme variantpurple-dpurple-l--cem-color-canvastext-30-purple--cem-color-canvastext-30-lightpinkDarker/lighter creativity variationcreativityxrecommended
--cem-palette-creativity-textCreativity text colorcomfort-textcomfort-textCanvasTextText on creativity backgroundscreativitytextrecommended
--cem-palette-creativity-text-xCreativity extreme textcomfort-text-xcomfort-text-xCanvasText on extreme creativity backgroundscreativitytext-xrecommended
--cem-palette-dangerBase danger colorred-lred-d--cem-color-red-l--cem-color-red-dError messages, destructive actionsdangerrequired
--cem-palette-danger-xDanger extreme variantred-dred-l--cem-color-red-30-black--cem-color-red-30-whiteDarker/lighter danger variationdangerxrecommended
--cem-palette-danger-textDanger text colorcomfort-text-xcomfort-textCanvasCanvasTextText on danger backgroundsdangertextrequired
--cem-palette-danger-text-xDanger extreme textorange-xlorange-xlCanvasHigh contrast text on extreme danger backgroundsdangertext-xrecommended
--cem-palette-conservativeBase conservative colorgrey-lgrey-dButtonFaceBrand-3, disabled statesconservativerequired
--cem-palette-conservative-xConservative extreme variantgrey-dgrey-lCanvasTextDarker/lighter conservative variationconservativexrecommended
--cem-palette-conservative-textConservative text colorcomfort-textcomfort-textCanvasTextText on conservative backgroundsconservativetextrequired
--cem-palette-conservative-text-xConservative extreme textcomfort-text-xcomfort-text-xCanvasText on extreme conservative backgroundsconservativetext-xrecommended

5.1 Semantics of the core emotions


6. Theme modes

CEM defines 5 operational modes for color behavior:

cem-theme-mode
ModeColor schemeDescription
nativesystemRely on system colors (Canvas, CanvasText, etc.)
lightlightBranded palette in light scheme
darkdarkBranded palette in dark scheme
contrast-lightlightMinimize fill differences; emphasize outlines/markers
contrast-darkdarkSame, in dark scheme

Normative expectations:


7. Action intent and state tokens

Action tokens encode user-flow intent (primary, explicit, destructive, etc.) and interaction/state.

7.0 Visual reference: emotional palette gradations (light theme)

action-colors.png

Supplemental title: Light theme — Emotional palette gradations across interaction states (action intents).

Notes (interpretation):

7.1 Action intent mapping (reference)

cem-action-intent-emotion
Action intentEmotional paletteBranded (light)Branded (dark)Primary token
explicittrustblue-l (#d7e3ff)blue-d (#002f65)--cem-action-explicit-default-background
primarycreativitypurple-l (#e1bee7)purple-d (#6a1b9a)--cem-action-primary-default-background
contextualcomfortcyan-xl (#f1fefe)cyan-xd (#001010)--cem-action-contextual-default-background
alternateenthusiasmorange-l (#ffe082)orange-d (#723600)--cem-action-alternate-default-background
destructivedangerred-l (#ba1a1a)red-d (#690005)--cem-action-destructive-default-background

7.2 Canonical state model

CEM action states (union of form/action semantics and interaction semantics):

State progression is defined as a formulaic movement from “least emphasized” to “most emphasized”, using color-mix() against the emotion’s extreme variant (--cem-palette-{emotion}-x).

7.2.1 Background-driven states

disabled → readonly → editable → default → indeterminate → hover → active → pending
 (30%)      (80%)      (90%)      (base)   (90%)          (70%)   (25%)   (5%)

7.2.2 State formulas (normative)

cem-action-state-color
StateBackground formula (palette-level)Text tokenContrast backgroundContrast texttier
disabledcolor-mix(in srgb, var(--cem-palette-[emotion]) 30%, var(--cem-palette-conservative-x))var(--cem-palette-conservative-text-x)var(--cem-palette-comfort)color-mix(in srgb, var(--cem-palette-comfort-text) 38%, var(--cem-palette-comfort))required
readonlycolor-mix(in srgb, var(--cem-palette-[emotion]) 80%, var(--cem-palette-[emotion]-x))var(--cem-palette-[emotion]-text)var(--cem-palette-comfort)var(--cem-palette-comfort-text)recommended
editablecolor-mix(in srgb, var(--cem-palette-[emotion]) 90%, var(--cem-palette-[emotion]-x))var(--cem-palette-[emotion]-text)var(--cem-palette-comfort)var(--cem-palette-comfort-text)recommended
defaultvar(--cem-palette-[emotion])var(--cem-palette-[emotion]-text)var(--cem-palette-comfort)var(--cem-palette-comfort-text)required
indeterminatecolor-mix(in srgb, var(--cem-palette-[emotion]) 90%, var(--cem-palette-[emotion]-x))var(--cem-palette-[emotion]-text)var(--cem-palette-comfort)var(--cem-palette-comfort-text)recommended
hovercolor-mix(in srgb, var(--cem-palette-[emotion]) 70%, var(--cem-palette-[emotion]-x))var(--cem-palette-[emotion]-text)var(--cem-palette-comfort)var(--cem-palette-comfort-text)required
activecolor-mix(in srgb, var(--cem-palette-[emotion]) 25%, var(--cem-palette-[emotion]-x))var(--cem-palette-[emotion]-text-x)var(--cem-palette-comfort)var(--cem-palette-comfort-text)required
pendingcolor-mix(in srgb, var(--cem-palette-[emotion]) 5%, var(--cem-palette-[emotion]-x))var(--cem-palette-[emotion]-text-x)var(--cem-palette-comfort)var(--cem-palette-comfort-text)recommended

Applying this to action intents: substitute [emotion] with the emotional palette mapped by the intent (see §7.1). The resulting values populate --cem-action-{intent}-{state}-background and --cem-action-{intent}-{state}-text.

Pending gradient and continuous motion

Outside contrast modes, pending actions MUST show a repeating 45-degree background gradient while their busy source is true. A one-shot color fade is not the pending-motion contract. Use the intent's pending background and dedicated pending stripe background as its two gradient colors, with pending text throughout. Primary, explicit, contextual and alternate use one shared adjustment: mix the active endpoint with 12% white in light schemes and 20% black in dark schemes. Destructive keeps 25% white / 50% black because its yellow foreground has a different contrast range. The default endpoints must exceed 1.8:1 stripe separation and preserve at least 4.5:1 text contrast across the gradient. Dark contrast contours share these endpoints. Light contrast contours use a brighter stripe (40% white, or extra-light red for destructive) as specified in §7.5. Active button paint is unchanged; the pending background remains a color, including as the solid fallback.

cem-pending-colors
TokenValueDescriptiontier
--cem-pending-color-1var(--cem-action-primary-pending-background)First gradient color; bind to the current intent's pending backgroundrecommended
--cem-pending-color-2var(--cem-action-primary-pending-stripe-background)Second gradient color; bind to the current intent's pending stripe backgroundrecommended
--cem-action-primary-pending-stripe-backgroundlight-dark(color-mix(in srgb, var(--cem-action-primary-active-background) 88%, var(--cem-color-white)), color-mix(in srgb, var(--cem-action-primary-active-background) 80%, black))Pending stripe: 12% white in light schemes; 20% black in dark schemesrecommended
--cem-action-explicit-pending-stripe-backgroundlight-dark(color-mix(in srgb, var(--cem-action-explicit-active-background) 88%, var(--cem-color-white)), color-mix(in srgb, var(--cem-action-explicit-active-background) 80%, black))Pending stripe: 12% white in light schemes; 20% black in dark schemesrecommended
--cem-action-contextual-pending-stripe-backgroundlight-dark(color-mix(in srgb, var(--cem-action-contextual-active-background) 88%, var(--cem-color-white)), color-mix(in srgb, var(--cem-action-contextual-active-background) 80%, black))Pending stripe: 12% white in light schemes; 20% black in dark schemesrecommended
--cem-action-alternate-pending-stripe-backgroundlight-dark(color-mix(in srgb, var(--cem-action-alternate-active-background) 88%, var(--cem-color-white)), color-mix(in srgb, var(--cem-action-alternate-active-background) 80%, black))Pending stripe: 12% white in light schemes; 20% black in dark schemesrecommended
--cem-action-destructive-pending-stripe-backgroundlight-dark(color-mix(in srgb, var(--cem-action-destructive-active-background) 75%, var(--cem-color-white)), color-mix(in srgb, var(--cem-action-destructive-active-background) 50%, black))Destructive pending stripe: lighten the active endpoint with 25% white in light schemes; darken it with 50% black in dark schemesrecommended
--cem-action-primary-pending-imagelinear-gradient(var(--cem-pending-angle), color-mix(in srgb, var(--cem-palette-creativity) 5%, var(--cem-palette-creativity-x)) 0% 5%, light-dark(color-mix(in srgb, color-mix(in srgb, var(--cem-palette-creativity) 25%, var(--cem-palette-creativity-x)) 60%, var(--cem-color-white)), color-mix(in srgb, color-mix(in srgb, var(--cem-palette-creativity) 25%, var(--cem-palette-creativity-x)) 80%, black)) 20% 30%, color-mix(in srgb, var(--cem-palette-creativity) 5%, var(--cem-palette-creativity-x)) 45% 55%, light-dark(color-mix(in srgb, color-mix(in srgb, var(--cem-palette-creativity) 25%, var(--cem-palette-creativity-x)) 60%, var(--cem-color-white)), color-mix(in srgb, color-mix(in srgb, var(--cem-palette-creativity) 25%, var(--cem-palette-creativity-x)) 80%, black)) 70% 80%, color-mix(in srgb, var(--cem-palette-creativity) 5%, var(--cem-palette-creativity-x)) 95% 100%)Primary pending recipe; 40% white stripe in light contrast; ordinary dark endpointrecommended
--cem-action-explicit-pending-imagelinear-gradient(var(--cem-pending-angle), color-mix(in srgb, var(--cem-palette-trust) 5%, var(--cem-palette-trust-x)) 0% 5%, light-dark(color-mix(in srgb, color-mix(in srgb, var(--cem-palette-trust) 25%, var(--cem-palette-trust-x)) 60%, var(--cem-color-white)), color-mix(in srgb, color-mix(in srgb, var(--cem-palette-trust) 25%, var(--cem-palette-trust-x)) 80%, black)) 20% 30%, color-mix(in srgb, var(--cem-palette-trust) 5%, var(--cem-palette-trust-x)) 45% 55%, light-dark(color-mix(in srgb, color-mix(in srgb, var(--cem-palette-trust) 25%, var(--cem-palette-trust-x)) 60%, var(--cem-color-white)), color-mix(in srgb, color-mix(in srgb, var(--cem-palette-trust) 25%, var(--cem-palette-trust-x)) 80%, black)) 70% 80%, color-mix(in srgb, var(--cem-palette-trust) 5%, var(--cem-palette-trust-x)) 95% 100%)Explicit pending recipe; 40% white stripe in light contrast; ordinary dark endpointrecommended
--cem-action-contextual-pending-imagelinear-gradient(var(--cem-pending-angle), color-mix(in srgb, var(--cem-palette-comfort) 5%, var(--cem-palette-comfort-x)) 0% 5%, light-dark(color-mix(in srgb, color-mix(in srgb, var(--cem-palette-comfort) 25%, var(--cem-palette-comfort-x)) 60%, var(--cem-color-white)), color-mix(in srgb, color-mix(in srgb, var(--cem-palette-comfort) 25%, var(--cem-palette-comfort-x)) 80%, black)) 20% 30%, color-mix(in srgb, var(--cem-palette-comfort) 5%, var(--cem-palette-comfort-x)) 45% 55%, light-dark(color-mix(in srgb, color-mix(in srgb, var(--cem-palette-comfort) 25%, var(--cem-palette-comfort-x)) 60%, var(--cem-color-white)), color-mix(in srgb, color-mix(in srgb, var(--cem-palette-comfort) 25%, var(--cem-palette-comfort-x)) 80%, black)) 70% 80%, color-mix(in srgb, var(--cem-palette-comfort) 5%, var(--cem-palette-comfort-x)) 95% 100%)Contextual pending recipe; 40% white stripe in light contrast; ordinary dark endpointrecommended
--cem-action-alternate-pending-imagelinear-gradient(var(--cem-pending-angle), color-mix(in srgb, var(--cem-palette-enthusiasm) 5%, var(--cem-palette-enthusiasm-x)) 0% 5%, light-dark(color-mix(in srgb, color-mix(in srgb, var(--cem-palette-enthusiasm) 25%, var(--cem-palette-enthusiasm-x)) 60%, var(--cem-color-white)), color-mix(in srgb, color-mix(in srgb, var(--cem-palette-enthusiasm) 25%, var(--cem-palette-enthusiasm-x)) 80%, black)) 20% 30%, color-mix(in srgb, var(--cem-palette-enthusiasm) 5%, var(--cem-palette-enthusiasm-x)) 45% 55%, light-dark(color-mix(in srgb, color-mix(in srgb, var(--cem-palette-enthusiasm) 25%, var(--cem-palette-enthusiasm-x)) 60%, var(--cem-color-white)), color-mix(in srgb, color-mix(in srgb, var(--cem-palette-enthusiasm) 25%, var(--cem-palette-enthusiasm-x)) 80%, black)) 70% 80%, color-mix(in srgb, var(--cem-palette-enthusiasm) 5%, var(--cem-palette-enthusiasm-x)) 95% 100%)Alternate pending recipe; 40% white stripe in light contrast; ordinary dark endpointrecommended
--cem-action-destructive-pending-imagelinear-gradient(var(--cem-pending-angle), color-mix(in srgb, var(--cem-palette-danger) 5%, var(--cem-palette-danger-x)) 0% 5%, light-dark(var(--cem-color-red-xl), color-mix(in srgb, color-mix(in srgb, var(--cem-palette-danger) 25%, var(--cem-palette-danger-x)) 50%, black)) 20% 30%, color-mix(in srgb, var(--cem-palette-danger) 5%, var(--cem-palette-danger-x)) 45% 55%, light-dark(var(--cem-color-red-xl), color-mix(in srgb, color-mix(in srgb, var(--cem-palette-danger) 25%, var(--cem-palette-danger-x)) 50%, black)) 70% 80%, color-mix(in srgb, var(--cem-palette-danger) 5%, var(--cem-palette-danger-x)) 95% 100%)Destructive pending recipe; Extra-light red stripe in light contrast; ordinary dark endpointrecommended

The intent image recipes use the pending (5%) and active (25%) palette formulas directly so contrast fill overrides cannot erase their colors. Dark contours match normal fill endpoints. Light contours mix the active palette endpoint with 40% white; destructive uses --cem-color-red-xl. The ordinary fill keeps its text-safe stripe. Existing per-control fill color overrides remain independent.

Native themes retain their system-palette active stripe endpoints for the four ordinary intents; mixing them with fixed white/black can reduce text contrast. Destructive retains its existing native recipe.

cem-action-native-overrides
TokenValue
--cem-action-primary-pending-stripe-backgroundvar(--cem-action-primary-active-background)
--cem-action-explicit-pending-stripe-backgroundvar(--cem-action-explicit-active-background)
--cem-action-contextual-pending-stripe-backgroundvar(--cem-action-contextual-active-background)
--cem-action-alternate-pending-stripe-backgroundvar(--cem-action-alternate-active-background)

D5 owns --cem-pending-angle (45deg) and --cem-pending-tile-size (2rem). D7 owns --cem-duration-pending-cycle (2000ms). Use uniform easing and infinite iteration. Translate the background by one square tile along the x axis per cycle. Each transition holds its initial color for 20%, blends for 60%, then holds the final color for 20%. The alternating color ranges are 0–5%, 20–30%, 45–55%, 70–80% and 95–100%; the gaps blend continuously. At 45 degrees, opposite tile edges match and translating one tile closes the loop without a jump. Freeze the pattern under reduced motion. Under forced colors, suppress the gradient and motion and use system button colors with a persistent pending-width boundary. Keep zebra focus rings independent of background motion.

The generated .cem-pending theme utility demonstrates this recipe. Consumers bind the two color inputs and pending foreground for their intent. Canonical components own the same recipe in their embedded scoped CSS. cem-action activates it for pending="true", including disabled buttons. Pending paint takes precedence over disabled paint while pending; native disabled semantics still block activation and focus. Clearing pending while disabled restores the disabled colors. Pending does not itself disable activation. Hover and focus do not restart or replace the continuous animation. Clearing pending removes the gradient and motion and restores current interaction paint.

7.2.3 Outline-driven states

focus, selected, and target are primarily expressed through the zebra outline channel (§8). Background tokens MAY remain at default for these states; do not rely on fill alone. Selection is a first-class persistent state. cem-action[selected] MUST paint selected zebra even when unfocused, disabled or pending. Focus and selected stripes remain independent, and hover/held press do not clear selection. The container owns the selected attribute; the action does not infer it from a click or from disclosure expansion.

7.3 Attribute channels

Action state can affect these channels (the set varies by state):

7.4 Minimal required action endpoints

To render functional UIs, the following endpoints are REQUIRED per action intent:

Other states (focus, target, pending, required, indeterminate, readonly, editable) are RECOMMENDED, and may be implemented through zebra/markers rather than fill.

7.5 Contrast themes: collapse fills, keep semantics

In contrast-light and contrast-dark, all action background tokens MUST resolve to the base surface (--cem-palette-comfort). Text uses surface ink, including for destructive actions; disabled ink is subdued. The contrast columns in the state table are canonical. There is no intent or state fill progression.

Intent moves to a contour, colored by the intent's extreme palette endpoint. D5 defines its resting/hover/active thickness; keyboard focus retains its independent zebra rings. Pending, including disabled pending, uses an animated 45-degree zebra contour instead of the background gradient. Motion parameters match the normal gradient. Dark contours also retain the normal gradient colors. Light contours brighten the second endpoint with 40% white for primary, explicit, contextual and alternate. Destructive uses the extra-light red endpoint (--cem-color-red-xl, #ffb4ab). All five intents exceed 3:1 stripe separation. This stronger light stripe is confined to the outline; ordinary fills retain their readable text contrast. This explicitly supersedes light-mode fill/contour color parity. Reduced motion freezes the contour. Forced colors uses the existing static system-color pending boundary. Changing back to light/dark/native restores the ordinary gradient. This is the explicit contrast exception to the pending background contract in §7.2.2.

cem-action-outline-colors
TokenValueDescriptiontier
--cem-action-primary-outline-colorvar(--cem-palette-creativity-x)Primary intent contourrequired
--cem-action-explicit-outline-colorvar(--cem-palette-trust-x)Explicit intent contourrequired
--cem-action-contextual-outline-colorvar(--cem-palette-comfort-x)Contextual intent contourrequired
--cem-action-alternate-outline-colorvar(--cem-palette-enthusiasm-x)Alternate intent contourrequired
--cem-action-destructive-outline-colorvar(--cem-palette-danger-x)Destructive intent contourrequired
--cem-action-pending-outline-imagevar(--cem-action-primary-pending-image)Default primary pending zebra contour; bind the current intent image; D5 masks the centerrecommended
cem-action-contrast-overrides
TokenValue
--cem-action-primary-pending-stripe-backgroundvar(--cem-palette-comfort)
--cem-action-explicit-pending-stripe-backgroundvar(--cem-palette-comfort)
--cem-action-contextual-pending-stripe-backgroundvar(--cem-palette-comfort)
--cem-action-alternate-pending-stripe-backgroundvar(--cem-palette-comfort)
--cem-action-destructive-pending-stripe-backgroundvar(--cem-palette-comfort)
--cem-slider-thumb-hover-colorvar(--cem-palette-creativity-x)
--cem-slider-thumb-active-colorvar(--cem-palette-comfort-text)

This override table declares no new tokens; it suppresses all intent pending fill stripes in contrast modes. Slider thumbs are foreground markers, so their hover/active ink must not inherit collapsed action backgrounds. Preserve all ordinary-mode endpoints.


7.6 Implementation guidance (non-normative)

Deriving state backgrounds from palette (example):

/* Example: primary intent is mapped to creativity */
:root {
  --cem-action-primary-default-background: var(--cem-palette-creativity);
  --cem-action-primary-default-text:       var(--cem-palette-creativity-text);

  --cem-action-primary-hover-background:   color-mix(in srgb, var(--cem-palette-creativity) 70%, var(--cem-palette-creativity-x));
  --cem-action-primary-hover-text:         var(--cem-palette-creativity-text);

  --cem-action-primary-active-background:  color-mix(in srgb, var(--cem-palette-creativity) 25%, var(--cem-palette-creativity-x));
  --cem-action-primary-active-text:        var(--cem-palette-creativity-text-x);
}

/* Focus should be expressed via zebra outlines (D5), not by fill alone */
.button:focus-visible { outline-color: var(--cem-zebra-color-1); }

Framework adapters (illustrative, not normative):

CEM semanticMUI (conceptual)Angular Material (conceptual)
--cem-action-primary-*palette.primary.* (creativity)primary (creativity)
--cem-action-destructive-*palette.error.*warn
--cem-action-alternate-*palette.secondary.* (or custom)accent (or custom)
zebra focus/selected/targetfocus ring / outline stylesfocus indicator / ripple-outline styles

7.7 Input indicator stripe colors

Ordinary fields, closed selects and unselected choices have no extra resting shadow stack. Native boundaries remain. Choice feedback belongs to the native input, never to its enclosing text label. Hover alone does not add a shadow.

Input controls use a state-composed stripe stack rather than assigning one physical stripe to every possible state. The stack has three physical classes:

  1. an anchor/state stripe, absent at rest and activated for pending or invalid states;
  2. a focus stripe, activated by :focus-visible and colored by --cem-zebra-color-1;
  3. a selection stripe, activated by checked, selected, or indeterminate state.

Invalidity activates the anchor/state stripe at boundary width; pending uses pending width. These outside indicators do not change layout. Focus and selection therefore remain independently visible when an input is also invalid. Required state remains a marker/text concern and does not acquire an indicator stripe. A component with an explicit, truthful busy source binds loading to the pending anchor color and the D5 --cem-stroke-pending width so pending does not rely on hue alone. A custom select or editable autocomplete owns a truthful aria-expanded source and activates the existing selection stripe while its popup is open.

cem-input-indicator-colors
Tokenvalue-typedefault-formulanotestier
--cem-input-background-color<color>color-mix(in srgb, var(--cem-palette-comfort-text) 4%, var(--cem-palette-comfort))Subtle filled text-input surface; outlined controls override locally to transparentrequired
--cem-input-indicator-anchor-color<color>color-mix(in srgb, var(--cem-palette-comfort-text) 62%, transparent)Resting boundary/anchor striperequired
--cem-input-indicator-anchor-hover-color<color>var(--cem-palette-comfort-text)Enabled native-control hoverrequired
--cem-input-indicator-anchor-disabled-color<color>color-mix(in srgb, var(--cem-palette-conservative-text-x) 38%, transparent)Unavailable control; wins over pointer interactionrequired
--cem-input-indicator-anchor-readonly-color<color>color-mix(in srgb, var(--cem-palette-comfort-text) 50%, transparent)Readonly field; wins over hoverrecommended
--cem-input-indicator-anchor-pending-color<color>var(--cem-palette-enthusiasm-x)Reserved loading/pending anchorrecommended
--cem-input-indicator-anchor-invalid-color<color>var(--cem-palette-danger)Invalid anchor; wins over ordinary hoverrequired
--cem-input-indicator-anchor-invalid-hover-color<color>var(--cem-palette-danger-x)Invalid enabled control under native hoverrequired
--cem-input-indicator-selection-color<color>var(--cem-palette-creativity-x)Checked or selected striperequired
--cem-input-indicator-indeterminate-color<color>var(--cem-palette-enthusiasm-x)Mixed-selection striperecommended

--cem-input-background-color is the theme-owned fill for text inputs. Default underline controls consume it; indicator="outline" sets a local transparent override at the native control so the surrounding surface remains visible. This variant override does not change ancestor or sibling palette tokens. Required markers, focus and validation indicators retain their independent channels.

The anchor precedence is disabled > invalid-hover > invalid > pending > readonly > hover > default. Focus and selection do not participate in that precedence chain because they occupy independent stripes. If invalid and indeterminate coexist, invalid controls the anchor while indeterminate controls the selection stripe.

D5 owns the outline/underline geometry transform and stripe widths. Component libraries may expose a public adapter property that selects that transform, but the adapter is not a replacement for these D0 semantic color endpoints.

7.8 Choice popup and option state colors

Custom selects and editable autocompletes share semantic fill/text pairs for their choice popup and HTML-rendered options. These endpoints are component-family semantics, not raw palette aliases: themes may remap them while preserving the distinction between pointer hover, composite active-descendant, committed selection, and disabled content. Focus and open-state geometry continue to use the input indicator/zebra contract. The historical --cem-select-* prefix remains stable; it names this shared choice-popup state category rather than limiting its use to a button-triggered select.

cem-select-state-colors
Tokenvalue-typedefault-formulanotestier
--cem-select-popup-background<color>var(--cem-palette-comfort)Select/autocomplete popup and listbox surfacerequired
--cem-select-popup-text<color>var(--cem-palette-comfort-text)Default option textrequired
--cem-select-popup-border-color<color>var(--cem-input-indicator-anchor-color)Popup boundaryrequired
--cem-select-option-hover-background<color>var(--cem-action-contextual-hover-background)Enabled option under pointer hoverrequired
--cem-select-option-hover-text<color>var(--cem-action-contextual-hover-text)Enabled option text under pointer hoverrequired
--cem-select-option-active-background<color>var(--cem-palette-trust)Keyboard/typeahead active descendantrequired
--cem-select-option-active-text<color>var(--cem-palette-trust-text)Active-descendant textrequired
--cem-select-option-selected-background<color>var(--cem-palette-creativity)Committed selectionrequired
--cem-select-option-selected-text<color>var(--cem-palette-creativity-text)Committed-selection textrequired
--cem-select-option-disabled-background<color>var(--cem-action-contextual-disabled-background)Unavailable option fillrequired
--cem-select-option-disabled-text<color>var(--cem-action-contextual-disabled-text)Unavailable option textrequired
--cem-select-group-text<color>var(--cem-palette-conservative-text-x)Option-group headingrecommended

7.9 Navigation item state colors

Navigation items move between locations or switch the current local view. They are not action-intent controls: a theme must be able to change navigation styling without also changing primary/contextual commands. Current links and selected tabs share one semantic state, including distinct hover and active pairs so transient input feedback does not erase the current/selected meaning. The default formulas align with contextual/primary action progression, but the navigation endpoints remain independently themeable. Disabled wins over current, hover, and active.

cem-navigation-item-state-colors
Tokenvalue-typedefault-formulanotestier
--cem-navigation-item-default-background<color>transparentResting navigation item fillrequired
--cem-navigation-item-default-text<color>var(--cem-palette-comfort-text)Resting navigation item textrequired
--cem-navigation-item-hover-background<color>var(--cem-action-contextual-hover-background)Enabled unselected item under pointer hoverrequired
--cem-navigation-item-hover-text<color>var(--cem-action-contextual-hover-text)Enabled unselected hover textrequired
--cem-navigation-item-active-background<color>var(--cem-action-contextual-active-background)Enabled unselected item while native activation input is heldrequired
--cem-navigation-item-active-text<color>var(--cem-action-contextual-active-text)Enabled unselected active textrequired
--cem-navigation-item-current-background<color>var(--cem-action-primary-default-background)Current link or selected tab fillrequired
--cem-navigation-item-current-text<color>var(--cem-action-primary-default-text)Current link or selected tab textrequired
--cem-navigation-item-current-hover-background<color>var(--cem-action-primary-hover-background)Current/selected item under pointer hoverrequired
--cem-navigation-item-current-hover-text<color>var(--cem-action-primary-hover-text)Current/selected hover textrequired
--cem-navigation-item-current-active-background<color>var(--cem-action-primary-active-background)Current/selected item while native activation input is heldrequired
--cem-navigation-item-current-active-text<color>var(--cem-action-primary-active-text)Current/selected active textrequired
--cem-navigation-item-disabled-background<color>var(--cem-action-contextual-disabled-background)Unavailable navigation item fill; wins over hover/active/currentrequired
--cem-navigation-item-disabled-text<color>var(--cem-action-contextual-disabled-text)Unavailable navigation item textrequired

7.10 Interactive content state colors

Interactive content controls expose content selection or filtering without becoming action-intent, navigation, or form-input components. Their state colors therefore need an independently themeable category even when the reference formulas align with existing action or palette endpoints. Active endpoints preserve held native-input feedback, while selected-hover and selected-active keep the selected/checked meaning visible during transient input. Disabled wins over selected, hover, and active. Focus remains a separate D5/zebra geometry channel. A current contextual datum is not necessarily selected: for example, today's date remains current while a user previews or commits another calendar date. Its indicator therefore has an independent D0 endpoint whose geometry remains D5-owned.

cem-content-interaction-state-colors
Tokenvalue-typedefault-formulanotestier
--cem-content-interaction-default-background<color>transparentResting interactive-content owner fillrequired
--cem-content-interaction-default-text<color>var(--cem-palette-comfort-text)Resting interactive-content owner textrequired
--cem-content-interaction-hover-background<color>var(--cem-action-contextual-hover-background)Enabled unselected content owner under pointer hoverrequired
--cem-content-interaction-hover-text<color>var(--cem-action-contextual-hover-text)Enabled unselected hover textrequired
--cem-content-interaction-active-background<color>var(--cem-action-contextual-active-background)Enabled unselected content owner while native activation input is heldrequired
--cem-content-interaction-active-text<color>var(--cem-action-contextual-active-text)Enabled unselected held-active textrequired
--cem-content-interaction-selected-background<color>var(--cem-palette-creativity)Selected or checked content owner fillrequired
--cem-content-interaction-selected-text<color>var(--cem-palette-creativity-text)Selected or checked content owner textrequired
--cem-content-interaction-selected-hover-background<color>color-mix(in srgb, var(--cem-palette-creativity) 70%, var(--cem-palette-creativity-x))Enabled selected or checked owner under pointer hoverrequired
--cem-content-interaction-selected-hover-text<color>var(--cem-palette-creativity-text)Selected or checked hover textrequired
--cem-content-interaction-selected-active-background<color>color-mix(in srgb, var(--cem-palette-creativity) 45%, var(--cem-palette-creativity-x))Enabled selected or checked owner while native activation input is heldrequired
--cem-content-interaction-selected-active-text<color>var(--cem-palette-creativity-text)Enabled selected or checked held-active textrequired
--cem-content-interaction-disabled-background<color>var(--cem-action-contextual-disabled-background)Disabled content owner fill; wins over selected and hoverrequired
--cem-content-interaction-disabled-text<color>var(--cem-action-contextual-disabled-text)Disabled content owner textrequired
--cem-content-interaction-current-indicator-color<color>var(--cem-zebra-color-2)Current contextual datum such as today's date; independent of committed selectionrecommended

7.11 Separator color

A separator is not readable content and SHOULD NOT normally use the full-strength text color. It nevertheless belongs to the same D0 surface/text relationship so it remains legible when the surface changes. The canonical endpoint is therefore derived from --cem-palette-comfort-text at reduced salience rather than copied from it verbatim.

D0 owns only the color. D5 owns divider thickness and placement, while D1 and D2 determine the space surrounding the line. A component boundary with its own state semantics must use the corresponding component-family color instead of silently reusing this sibling-separation endpoint.

cem-separator-colors
Tokenvalue-typedefault-formulaforced-colorsnotestier
--cem-separator-color<color>color-mix(in srgb, var(--cem-palette-comfort-text) 38%, transparent)CanvasTextReduced-salience line between sibling regions; forced colors restores a solid system contourrequired

7.12 Progress indicator colors

A progress indicator is status graphics, not readable text, an action, an input stripe, or a sibling separator. Its completed/current arc therefore needs a dedicated semantic color, and its remaining-range track needs an independently themeable reduced-salience color. Components MUST NOT reuse --cem-separator-color: the track represents the value range rather than a relationship between siblings.

Both determinate and indeterminate progress use the same two endpoints. Mode is communicated by geometry, programmatic value semantics, and—when motion is allowed—D7 motion, so color is not the only distinction. In forced colors the track maps to GrayText and the indicator maps to Highlight, preserving the remaining/current distinction with system-owned colors.

cem-progress-indicator-colors
Tokenvalue-typedefault-formulaforced-colorsnotestier
--cem-progress-track-color<color>color-mix(in srgb, var(--cem-palette-comfort-text) 24%, transparent)GrayTextRemaining progress range at reduced saliencerequired
--cem-progress-indicator-color<color>var(--cem-palette-enthusiasm-x)HighlightCurrent or indeterminate work indicatorrequired

7.13 Workflow step colors

Workflow steppers combine navigation with durable process facts. Header default/current/hover/active/disabled paint uses the navigation-item family, but completion and error markers must remain independently visible when a current or focused header coexists with those facts. Connector graphics represent process progress, not sibling separation or a numeric progress indicator, and therefore must not reuse --cem-separator-color or --cem-progress-*.

Text labels and marker shapes keep workflow meaning redundant with color. In forced colors remaining connectors map to GrayText, completed progress maps to Highlight, and invalidity maps to Mark.

cem-workflow-step-colors
Tokenvalue-typedefault-formulaforced-colorsnotestier
--cem-workflow-step-completed-indicator-color<color>var(--cem-palette-trust)HighlightCompleted-step marker independent of current/focus paintrequired
--cem-workflow-step-invalid-indicator-color<color>var(--cem-palette-danger)MarkInvalid-step marker independent of current/focus paintrequired
--cem-workflow-connector-default-color<color>color-mix(in srgb, var(--cem-palette-comfort-text) 24%, transparent)GrayTextRemaining workflow pathrequired
--cem-workflow-connector-completed-color<color>var(--cem-palette-trust)HighlightCompleted workflow pathrequired

7.14 Slider input colors

A slider is an interactive value input. Its remaining track, selected range, thumb, and step ticks therefore form one dedicated D0 family. These endpoints MUST NOT reuse sibling-separator color or progress status color merely because the rendered graphics contain a line: position along the line is the input value, and the thumb has hover, active, focus, and disabled states.

The default track is reduced-salience surface text, while the active track and thumb derive from the enthusiasm endpoint. Hover and active thumb endpoints are separate so a theme can preserve pointer feedback without changing geometry. In forced colors, geometry plus system colors preserves remaining/selected, enabled/disabled, and thumb/tick distinctions.

cem-slider-colors
Tokenvalue-typedefault-formulaforced-colorsnotestier
--cem-slider-track-color<color>color-mix(in srgb, var(--cem-palette-comfort-text) 24%, transparent)GrayTextRemaining value range at reduced saliencerequired
--cem-slider-active-track-color<color>var(--cem-palette-enthusiasm-x)HighlightSelected single-value or range segmentrequired
--cem-slider-thumb-color<color>var(--cem-palette-enthusiasm-x)CanvasTextResting enabled thumbrequired
--cem-slider-thumb-hover-color<color>var(--cem-action-primary-hover-background)HighlightEnabled thumb under pointer hoverrequired
--cem-slider-thumb-active-color<color>var(--cem-action-primary-active-background)HighlightEnabled thumb during native activationrequired
--cem-slider-disabled-track-color<color>color-mix(in srgb, var(--cem-palette-comfort-text) 14%, transparent)GrayTextRemaining and selected range when globally disabledrequired
--cem-slider-disabled-thumb-color<color>var(--cem-action-contextual-disabled-text)GrayTextGlobally disabled thumbrequired
--cem-slider-tick-color<color>var(--cem-palette-comfort-text)CanvasTextStep tick graphics; position remains a redundant cuerequired

8. Zebra outline colors

8.1 Outline-driven state mapping (zebra)

StateZebra stripeRecommended meaning
focus--cem-zebra-color-1keyboard focus visibility
target--cem-zebra-color-2navigation target / guided attention
selected--cem-zebra-color-3selection / checked / chosen

See D5 Stroke for zebra geometry (stripe order, offsets, and ring widths).

Zebra is a striped outline (implemented in D5 Stroke) with four semantic strips.

Color endpoints:

cem-zebra-tokens
Tokenvalue-typedefault-formulatiernotes
--cem-zebra-color-0<color>var(--cem-palette-comfort)requiredBase stripe; state selectors override per §8.2
--cem-zebra-color-1<color>var(--cem-palette-comfort)requiredFocus stripe; :focus override = CanvasText
--cem-zebra-color-2<color>var(--cem-palette-comfort)requiredTarget stripe; :target override = Mark
--cem-zebra-color-3<color>var(--cem-palette-comfort)requiredSelected stripe; .selected override = SelectedItem
--cem-zebra-strip-size<length>2pxrequiredStripe thickness basis; D5 geometry references this

Why target occupies the middle ring (color-2): Target is the least-used state — typically once per page. When inactive it collapses to --cem-palette-comfort, so its ring acts as a neutral visual gap. When active the target color is always hue-distinct from both the focus ring (color-1) and the selection ring (color-3), providing clear three-way separability without competing for attention alongside the two more common states. In light and contrast-light modes a warm orange (orange-l) serves this role; in dark mode a mid-tone purple (creativity) does; in native mode the OS Mark color (typically yellow) is used.

8.2 Theme-mode mapping

Focus, selected, and target MUST always resolve to different hues so that combined states (e.g., a focused-and-selected item) remain distinguishable. --cem-zebra-color-0 anchors the ring to the base surface; the remaining stripes are state indicators.

cem-zebra-mode-mapping
Theme mode--cem-zebra-color-0 (base)--cem-zebra-color-1 (focus)--cem-zebra-color-2 (target)--cem-zebra-color-3 (selected)
nativeCanvasCanvasTextMarkSelectedItem
light--cem-palette-comfort--cem-palette-trust-x--cem-color-orange-l--cem-palette-creativity-x
dark--cem-palette-comfort--cem-palette-comfort-x--cem-palette-creativity--cem-palette-calm-x
contrast-light--cem-palette-comfort--cem-palette-trust-x--cem-color-orange-l--cem-palette-creativity-x
contrast-dark--cem-palette-comfort--cem-palette-comfort-x--cem-palette-enthusiasm-x--cem-palette-trust

Rationale:

Zebra colors MUST NOT reuse the same tone as action border/box-shadow indicators in the same theme variation.

8.3 Rules


9. System colors and forced-colors

9.1 Native/system palette mapping

In native mode, palette endpoints SHOULD map to system colors:

9.2 Forced colors

When @media (forced-colors: active) is true:


10. Component mapping checklist

Use this as a quick “did we wire tokens correctly?” checklist.

10.1 Actions

10.2 Inputs and selection controls

10.3 Informational semantics

10.4 Separation


11. Accessibility and QA

11.1 Contrast requirements (normative)

ElementMinimum ratio
Body text on background≥4.5:1
Large text (≥18pt or ≥14pt bold)≥3:1
UI components and graphical objects≥3:1
Focus indicators≥3:1 against adjacent colors

11.2 QA checklist (done-ness)

Minimum QA expectations:


11.3 Color-blind resilience and redundancy (normative)

11.4 Motion sensitivity (normative)

12. Implementation guidance

Implementations SHOULD preserve the three-layer model:

  1. Branded hues (--cem-color-*) — implementation substrate (brand-controlled)
  2. Emotional palette (--cem-palette-*) — semantic contract (theme-adaptive via light-dark())
  3. Action intents (--cem-action-*) — product-facing API (derived state progression via color-mix())

12.2 Derivation pattern (illustrative CSS)

:root {
  /* Emotional palette (example) */
  --cem-palette-creativity:        light-dark(var(--cem-color-purple-l), var(--cem-color-purple-d));
  --cem-palette-creativity-x:      light-dark(var(--cem-color-purple-d), var(--cem-color-purple-l));
  --cem-palette-creativity-text:   light-dark(var(--cem-palette-comfort-text), var(--cem-palette-comfort-text));
  --cem-palette-creativity-text-x: light-dark(var(--cem-palette-comfort-text-x), var(--cem-palette-comfort-text-x));

  /* Primary intent mapped to creativity */
  --cem-action-primary-default-background: var(--cem-palette-creativity);
  --cem-action-primary-default-text:       var(--cem-palette-creativity-text);

  --cem-action-primary-hover-background: color-mix(in srgb, var(--cem-palette-creativity) 70%, var(--cem-palette-creativity-x));
  --cem-action-primary-hover-text:       var(--cem-palette-creativity-text);

  --cem-action-primary-active-background: color-mix(in srgb, var(--cem-palette-creativity) 25%, var(--cem-palette-creativity-x));
  --cem-action-primary-active-text:       var(--cem-palette-creativity-text-x);
}

@media (forced-colors: active) {
  :root {
    --cem-palette-comfort: Canvas;
    --cem-palette-comfort-text: CanvasText;
    --cem-palette-trust: color-mix(in srgb, Highlight 70%, black);
    --cem-palette-trust-text: HighlightText;
  }
}

12.3 Framework mapping (conceptual)

CEM semanticMaterial Design 3 (concept)Angular Material (concept)MUI (concept)
--cem-palette-comfortmd-sys-color-surface--mat-sys-surfacetheme.palette.background.default
--cem-palette-comfort-textmd-sys-color-on-surface--mat-sys-on-surfacetheme.palette.text.primary
--cem-palette-trustmd-sys-color-primary--mat-sys-primarytheme.palette.primary.main
--cem-palette-dangermd-sys-color-error--mat-sys-errortheme.palette.error.main
zebra focus/selected/targetfocus indicator guidancefocus indicator stylesfocus ring / outline styles

12.4 Test focus: “semantic survives adapters”

In addition to contrast, validate that semantic meaning remains stable across:

13. Governance and versioning

Treat as breaking (major):

Treat as non-breaking (minor/patch):


14. Canonical token summary

14.1 Required (product contract)

Emotional palette (minimum set):

Zebra (outline/pattern channel):

Actions (per shipped intent):

For each shipped intent (primary, explicit, contextual, alternate, destructive), the implementation MUST provide at least:

Navigation items:

Interactive content:

Separation:

Workflow steps:

14.3 Token manifest index

Token tier is encoded in the tier column of each source table. The manifest validator derives expected token names from these tables using the same logic as cem-colors.html.

Source table h6 idTokens coveredValidator derivation
cem-color-hue-variant--cem-color-* (35 tokens)one token per row
cem-palette-emotion-shift--cem-palette-* (28 tokens)one token per row
cem-pending-colorsTwo color inputs, five stripe endpoints and five intent contour images (12 tokens)one token per row
cem-action-outline-colorsFive intent contours and pending contour image (6 tokens)one token per row
cem-action-native-overridesExisting stripe tokens retain native system colorsno new tokens
cem-action-contrast-overridesExisting destructive stripe and slider marker endpointsoverrides only; no new tokens
cem-zebra-tokens--cem-zebra-* (5 tokens)one token per row
cem-input-indicator-colors--cem-input-background-color + --cem-input-indicator-* (10 tokens)one token per row
cem-progress-indicator-colors--cem-progress-* (2 tokens)one token per row
cem-slider-colors--cem-slider-* (8 tokens)one token per row
cem-select-state-colors--cem-select-* (12 tokens)one token per row
cem-navigation-item-state-colors--cem-navigation-item-* (14 tokens)one token per row
cem-content-interaction-state-colors--cem-content-interaction-* (15 tokens)one token per row
cem-separator-colors--cem-separator-* (1 token)one token per row
cem-workflow-step-colors--cem-workflow-* (4 tokens)one token per row
cem-action-intent-emotion × cem-action-state-color--cem-action-* (80 tokens)intent × state × {background, text}
The contrast columns in cem-action-state-color generate mode overrides of
existing intent × state background/text tokens; they declare no additional tokens.

15. References

Internal

External


This spec is the canonical D0 contract for CEM color semantics.