Mechanize UI color token enforcement check
Problem and behavior
UI colors must be defined as design tokens in :root to ensure consistency across light and dark themes. However, this rule was not mechanized, allowing hardcoded color literals (Hex/RGB/HSL) to slip into web/styles.css, web/task.css, and web/recording/recording.css.
This PR converts all existing out-of-scope literals into semantic variables within :root and adds a strict mechanical checker (scripts/check-css-tokens.py) to prevent future violations.
Notes
The checker script parses scopes like [data-theme="light"] and @media (prefers-color-scheme: light) identically to :root, recognizing them as valid token definition blocks where color literals are permitted. Standard CSS keywords (like black) and var(...) usages are ignored.
Instead of creating an allowlist for the existing technical debt, all 17 prior violations were resolved in the same change. Literals like #d7f7e5 on .agent-pill.ready, #1e1e1e on .editor-panel, and hardcoded mask or box-shadow values were extracted into new semantic tokens. This allows the checker to operate with a strict zero-tolerance baseline.
Testing
tests/scripts/test_check_css_tokens.py adds coverage for valid token definitions, permitted comments, and exact interception of prohibited literal formats. Integrated the checker into scripts/test.sh as css_tokens_gate. The tests fail if a hardcoded literal is introduced outside a definition block. ./scripts/test.sh passes; cargo-audit, cargo-deny, actionlint, and GitHub CLI-dependent tests were skipped locally or deferred to CI.
Close #578
Summary by cubic
Mechanizes UI color definitions so hardcoded Hex/RGB/HSL literals can't reappear in the CSS files under web/.
Adds scripts/check-css-tokens.py with unit tests in tests/test_check_css_tokens.py, wired into scripts/test.sh as css-tokens-tests and css-tokens gates. Replaces existing literals in web/styles.css, web/task.css, and web/recording/recording.css with semantic tokens in :root, except two .turn-ring mask gradients in web/styles.css that now use the black keyword. Also swaps the cube's hardcoded #11110f stroke and fill in web/cube-view.js for var(--cube-ink).
Closes #578.