wave-3.md asks for "no unintended visual change on any page versus wave 2".
Measured with tests/token_check.py, b105135 against the end of the wave, all 7
pages: 7 elements changed and all 7 are the fixes the wave was for - two
.user-pick selects going white (T3.4) and five green action buttons going blue
(T3.5). The other 3,493 elements compute exactly what they computed at the end of
wave 2, and all 178 wave-2 token names resolve to the same literals.
Three fixes are invisible to a computed-style diff and are recorded with how they
were verified instead: two green buttons that need application state the fixture
does not reach, and the sentence-case pass, which changes text rather than style.
The one exit criterion not met is carried forward explicitly rather than ticked:
T3.2's "no page stylesheet declares a raw spacing or type value" is complete for
colour and open for spacing and type (BL-010).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
964 lines
60 KiB
Markdown
964 lines
60 KiB
Markdown
# Token inventory — every declared and raw value in `html/`
|
||
|
||
**Task:** `T3.1`, updated by `T3.2` · **Items:** `C3`, `S5` · **Produced:** August 15, 2026
|
||
**Branch:** `feat/wp-suite-r2-implementation` · **Read by:** `T3.2`, `T3.5`, `T9.3`
|
||
|
||
`T3.1` produced this as the mapping table `T3.2` builds from; `T3.2` has since been built and
|
||
§2 and §11 record what actually shipped rather than what was proposed. Sections 3 to 10 are
|
||
the **pre-`T3.2` inventory** and are deliberately left as they were — they are the evidence
|
||
for the refactor, and rewriting them into the past tense would destroy the before-picture that
|
||
`T9.3` needs. Everything in them was read from the working tree at `b105135` (end of wave 2).
|
||
|
||
**Read [§8 Near-duplicates](#8-near-duplicates--where-unintended-visual-change-will-come-from)
|
||
before writing a single line of `T3.2`.** That section is the whole risk in this wave.
|
||
|
||
---
|
||
|
||
## 0. The rule this wave is enforcing
|
||
|
||
From `CLAUDE.md`:
|
||
|
||
> After wave 3 there is exactly one place a color, spacing or type value is defined. Page
|
||
> stylesheets alias that source and declare nothing new.
|
||
|
||
And the constraint `T3.2` adds on top:
|
||
|
||
> **Do not** change any rendered value in this task.
|
||
|
||
Those two together mean one thing that has to be said out loud, because it is the difference
|
||
between a clean wave 3 and a broken one:
|
||
|
||
> ### Consolidation is not unification.
|
||
>
|
||
> Where two sheets declare the **same** value under different names, `T3.2` collapses them to
|
||
> one declaration and aliases the names. That is free — nothing renders differently.
|
||
>
|
||
> Where two sheets declare **different** values for the same role — `--shadow-lg`, the two
|
||
> banner-border greens, the three mono stacks — `T3.2` gives **each value its own canonical
|
||
> name** and records the pair in §8. Collapsing those is a *visual change*, which `T3.2`
|
||
> forbids. It belongs to `T3.3`/`T3.4`/`T3.5` or to `backlog.md`.
|
||
>
|
||
> A "consolidation" that quietly picks a winner between two near-identical greys is exactly
|
||
> the failure this wave exists to prevent.
|
||
|
||
---
|
||
|
||
## 1. Scope: what "four token systems" actually means
|
||
|
||
`wave-3.md:22` and `IMPLEMENTATION.md` both say "the four stylesheets". Per **D1** in
|
||
`docs/reference/file-map.md` there are **six**, and after `T2.2` a seventh surface matters:
|
||
the launcher's inline `<style>`.
|
||
|
||
| # | Surface | Lines | Custom props declared | In `T3.2` scope? |
|
||
|---|---|---|---|---|
|
||
| 1 | `theme-light.css` | 250 | **120** (114 `--cds-*`, 6 `--wp-appbar-*`) | yes — becomes the source |
|
||
| 2 | `console.css` | 192 | **28** unprefixed at `:root` | yes — aliases |
|
||
| 3 | `work-package-suite-styles.css` | 663 | **16** unprefixed at `:root` | yes — aliases |
|
||
| 4 | `wp-creation-styles.css` | 897 | **24** (21 at `:root`, 3 `--nav-w` on `body`) | yes — aliases |
|
||
| 5 | `wp-chrome.css` | 249 | **14** `--wpc-*`, scoped to `.wp-chrome`, none at `:root` | yes — aliases |
|
||
| 6 | `wp-sidenav.css` | 109 | **0** — every colour is a hardcoded hex | yes — 31 raw values |
|
||
| 7 | `index.html` inline `<style>` (17–313) | 296 | 0 — already consumes `--cds-*` | yes — 12 raw values, 7 of them dead |
|
||
|
||
**202 custom-property declarations in total.** Plus the raw literals in §5.
|
||
|
||
> **Corrected during `T3.2`:** row 7 is not the only inline `<style>`. `login.html` (3 literals)
|
||
> and `field.html` (26 literals, including the ninth amber at §8-K) carry one too, and
|
||
> `work-package-suite.html:407` has a colour in a `style=` attribute. All four were converted.
|
||
> Counting only the launcher's was an inventory miss, not a scoping decision.
|
||
|
||
### Out of `T3.2` scope, stated so nobody goes looking
|
||
|
||
| Surface | Why it is out | Where it goes |
|
||
|---|---|---|
|
||
| `help.js:79` injected sheet — **52 colour literals, zero `var()`** | It is a whole parallel palette in a different design language (slate `#27313f`/`#334155`, violet `#7c3aed`/`#f3e8ff`, its own blue `rgba(37,99,214,.15)`). Converting it is a *restyle*, not a consolidation, and it would break `T3.2`'s empty-diff done-when. | **BL-004** |
|
||
| `wp-creation-app.js:1257` print window | `w.document.write()` builds a **separate document** that loads none of the suite's stylesheets. `var()` cannot resolve there. Genuine one-off. | stays raw, documented in §7 |
|
||
| `wp-creation-app.js:1389` `body{--nav-w:288px}` | Root cause of **BL-001**; `T7.1` owns it. Touching it here changes the creator's layout at 390px, which is a visual change. | `T7.1` |
|
||
| `auth-guard.js:67-92` password modal + `wp-format.js:120-150` prefs modal, inline styles | **35 raw literals** (16 + 19) in `style=` attributes, not a stylesheet. `T2.2` already replaced the nav half of this markup; both modals are rebuilt under `C1` at `T9.5`. | **BL-005** |
|
||
| `work-package-suite-app.js`, `admin.js`, `users.js` inline `style.*` | They **consume** page tokens (`var(--muted)`, `var(--red)`, `var(--s2)` …) rather than declaring them. See §9 — this is why names must survive as aliases. | no change needed |
|
||
|
||
---
|
||
|
||
## 2. The canonical set — as built (`T3.2`)
|
||
|
||
`theme-light.css` is already the source of truth in everything but name: it is **linked first
|
||
on all 7 pages**, it holds 114 of the 202 declarations, and its values are real Carbon g10.
|
||
`T3.2` should make that official rather than invent a new file.
|
||
|
||
Two namespaces, and the split is not cosmetic — it records provenance:
|
||
|
||
- **`--cds-*`** — values that are genuine IBM Carbon g10. Unchanged, plus the two additions
|
||
below which are also real Carbon token names that this sheet simply never declared.
|
||
- **`--wp-*`** — roles Carbon does not define, which the suite invented. Naming these
|
||
separately is what stops the next person "correcting" `#8e6a00` to a Carbon yellow.
|
||
|
||
### 2a. Additions to `--cds-*` (Carbon values, currently redeclared per sheet)
|
||
|
||
| New canonical token | Value | Carbon name | Replaces |
|
||
|---|---|---|---|
|
||
| `--cds-highlight` | `#edf5ff` | `$highlight` / blue-10 | `--accent-soft`, `--primary-light`, `--accent-dim` (3 sheets) |
|
||
| `--cds-hover-support-success` | `#0e6027` | green-70 | 5 raw literals, declared nowhere today |
|
||
|
||
### 2b. Additions under `--wp-*` (suite inventions, no Carbon equivalent)
|
||
|
||
| New canonical token | Value | Why it is not Carbon | Replaces |
|
||
|---|---|---|---|
|
||
| `--wp-status-success-bg` | `#defbe6` | green-10 *is* Carbon; the **role** is not (`$notification-background-success` is a different construct) | `--green-bg`, `--accent-green-dim` |
|
||
| `--wp-status-error-bg` | `#fff1f1` | as above (red-10) | `--red-bg`, `--red-dim` |
|
||
| `--wp-status-warning-bg` | `#fdf6dd` | Carbon yellow-10 is `#fcf4d6` — **this is not it** | `--amber-bg`, `--warning-bg`, `wp-chrome.css:50`, `index.html:298` |
|
||
| `--wp-status-warning-text` | `#8e6a00` | no Carbon amber text token exists; this is the suite's accessible-on-`#fdf6dd` amber | `--amber`, `--warning`, `--accent-amber` |
|
||
| `--wp-font-sans` | see §6 | — | 6 sites, 2 variants |
|
||
| `--wp-font-mono` | see §6 | — | 4 sites, 3 variants |
|
||
| `--wp-s1` … `--wp-s6` | `4 8 12 16 20 28` px | — | `console.css` `--s1..--s6`; the only real spacing scale in the repo |
|
||
| `--wp-ctl`, `--wp-ctl-sm` | `32px`, `26px` | — | `console.css:19-20` |
|
||
| `--wp-radius-0` | `0` | — | `--radius`, and 34 literal `border-radius: 0` |
|
||
|
||
### 2c. Kept, and kept **separate**, because their values differ
|
||
|
||
These are not duplicates. Each gets a canonical name; nobody collapses them in `T3.2`.
|
||
See §8 for the decision each one is waiting on.
|
||
|
||
| Canonical token | Value | Used by | Paired with |
|
||
|---|---|---|---|
|
||
| `--wp-shadow-lg-neutral` | `0 4px 16px rgba(0,0,0,.16)` | wizard `--shadow-lg` | `--wp-shadow-lg-cool` |
|
||
| `--wp-shadow-lg-cool` | `0 4px 16px rgba(20,30,50,.12)` | creator `--shadow-lg` | `--wp-shadow-lg-neutral` |
|
||
| `--wp-status-success-border-a` | `#a7f0ba` (green-20, Carbon) | `console.css:82` | `-b` |
|
||
| `--wp-status-success-border-b` | `#b6e3c6` (not Carbon) | `wp-creation-styles.css:494,532` | `-a` |
|
||
|
||
### 2d. What `T3.2` actually built, where it differs from the above
|
||
|
||
`theme-light.css` now holds **191 declarations**: the 114 Carbon g10 values, `--cds-highlight`,
|
||
the 7 app-shell tokens, and **69 `--wp-*` suite tokens**. It is the only sheet in `html/` that
|
||
contains a colour literal. Two changes from §2a's proposal, both for the same reason — a token
|
||
whose *value* is Carbon but whose *role* Carbon does not define belongs in `--wp-*`, or the
|
||
namespace split stops meaning anything:
|
||
|
||
| Proposed in `T3.1` | Built as | Why |
|
||
|---|---|---|
|
||
| `--cds-hover-support-success` | **`--wp-hover-success`** | `#0e6027` is Carbon green-70, but "hover for a green fill" is not a Carbon role — green is not one of its action colours |
|
||
| `--cds-layer-inverse-01` | **`--wp-appbar-layer`** | `#262626` is Carbon gray-90, but the name was invented; it sits in the app-shell group where both its consumers live |
|
||
|
||
Tokens added beyond §2a/§2b, all of them one-offs that still needed a single home — "one place
|
||
a value is defined" applies to a value used once just as much as to one used forty times:
|
||
|
||
| Group | Tokens |
|
||
|---|---|
|
||
| status borders | `--wp-status-{success,error,warning}-border-{a,b,c}` — 7 |
|
||
| surfaces | `--wp-table-zebra`, `--wp-table-row-hover`, `--wp-nav-bg`, `--wp-nav-hover`, `--wp-nav-active`, `--wp-pop-divider`, `--wp-accent-soft-hover` |
|
||
| elevation | `--wp-shadow-{pop,menu,menu-lg,modal,modal-lg,gate,rail,drawer,sticky,navbar,tooltip,toast}` — 12 |
|
||
| scrims | `--wp-scrim-{drawer,cool,cool-modal,cool-strong,neutral,loading,frosted}`, `--wp-on-accent-divider` |
|
||
| type | `--wp-font-sans`, `--wp-font-sans-2`, `--wp-font-mono`, `--wp-font-mono-2`, `--wp-font-mono-3` |
|
||
| spacing / shape | `--wp-s1`…`--wp-s6`, `--wp-ctl`, `--wp-ctl-sm`, `--wp-radius-0`, `--wp-shadow-none` |
|
||
| one-offs | `--wp-tag-super-{bg,text}`, `--wp-term-{bg,fg,pass,fail}`, `--wp-dev-{bg,fg,rule}`, `--wp-sop-inherited-bg`, `--wp-status-warning-text-alt` |
|
||
|
||
**Twelve distinct shadows** is the number that surprised. They were invisible while spread
|
||
across four sheets as inline `box-shadow` values; collected in one block they are obviously
|
||
eleven more than a flat Carbon UI wants. Collapsing them is a rendered change, so not here —
|
||
but they are now countable, which they were not before.
|
||
|
||
---
|
||
|
||
## 3. Declaration inventory — `theme-light.css` (the source)
|
||
|
||
All 120 stay exactly as they are. Grouped by role here so the *shape* is readable; every one
|
||
of the 120 is listed individually with its line number in **[Appendix A](#appendix-a--every-theme-lightcss-declaration-line-by-line)**.
|
||
The file is a flat `:root` block at **lines 2–117** and **169–176**.
|
||
|
||
| Lines | Group | Count | Distinct values | Action in `T3.2` |
|
||
|---|---|---|---|---|
|
||
| 3–6 | `--cds-interactive-01..04` | 4 | `#0f62fe` ×3, `#393939` | keep |
|
||
| 7–12 | `--cds-ui-background`, `--cds-ui-01..05` | 6 | `#f4f4f4` ×2, `#ffffff`, `#e0e0e0`, `#8d8d8d`, `#161616` | keep |
|
||
| 13–18 | `--cds-text-01..05`, `--cds-text-error` | 6 | `#161616 #525252 #a8a8a8 #ffffff #6f6f6f #da1e28` | keep |
|
||
| 19–21 | `--cds-icon-01..03` | 3 | `#161616 #525252 #ffffff` | keep |
|
||
| 22–24 | `--cds-link-01`, `-02`, `--cds-inverse-link` | 3 | `#0f62fe #0043ce #78a9ff` | keep |
|
||
| 25–28 | `--cds-field-01/02`, `--cds-inverse-01/02` | 4 | `#ffffff #f4f4f4 #ffffff #393939` | keep |
|
||
| 29–36 | `--cds-support-01..04` + inverse | 8 | `#da1e28 #198038 #f1c21b #0043ce #fa4d56 #42be65 #f1c21b #4589ff` | keep |
|
||
| 37–46 | overlay, danger, focus, hover/active primary·secondary·tertiary | 10 | incl. `#0353e9` ×2, `#002d9c` ×2 | keep |
|
||
| 47–61 | hover/active/selected UI, disabled | 15 | `#e5e5e5` ×4, `#cacaca` ×2, `#c6c6c6`, `#353535`, `#f4f4f4` ×2, `#bdbdbd`, `#8d8d8d`, `#ba121b`, `#750e13`, `#0043ce` | keep |
|
||
| 62–66 | `--cds-button-*` | 5 | `#0f62fe` ×2, `#393939`, `#da1e28` ×2 | keep |
|
||
| 67–89 | v11 background / layer / field / border set | 23 | mostly aliases of the above literals | keep |
|
||
| 90–115 | v11 text / link / icon / support / interactive set | 26 | mostly aliases of the above literals | keep |
|
||
| 116 | `--cds-shadow` | 1 | `rgba(0,0,0,.16)` | keep — see §8-F |
|
||
| 170–175 | `--wp-appbar-bg/fg/fg-dim/border/hover/height` | 6 | `#161616 #ffffff #c6c6c6 #6f6f6f #353535 48px` | keep |
|
||
|
||
**Note for `T9.3`:** `theme-light.css` re-declares the *same literal* under many names by
|
||
design — that is Carbon's v10→v11 alias layer (`--cds-ui-01` and `--cds-layer` are both
|
||
`#ffffff`, deliberately). Those are **not** the `S5` defect and must not be "deduplicated". The
|
||
`S5` defect is the same literal declared in *different sheets*, which is §4.
|
||
|
||
One raw literal in this file: **`theme-light.css:203`** `background: #fff` on `.wp-logo-chip`.
|
||
→ `--cds-ui-01`. (The chip is a deliberate white plate under a white-background wordmark; the
|
||
value is white for a reason, but it should still read from the token.)
|
||
|
||
---
|
||
|
||
## 4. Declaration inventory — the five page sheets
|
||
|
||
Every one of these is a duplicate declaration of a value `theme-light.css` already holds,
|
||
unless flagged. **Action** is what `T3.2` writes.
|
||
|
||
### 4a. `console.css` — 28 declarations, lines 12–20
|
||
|
||
| Line | Token | Value | Canonical | Action |
|
||
|---|---|---|---|---|
|
||
| 12 | `--bg` | `#f4f4f4` | `--cds-background` | alias |
|
||
| 12 | `--surface` | `#fff` | `--cds-layer` | alias — **notation-only dupe**, see §8-G |
|
||
| 12 | `--border` | `#e0e0e0` | `--cds-border-subtle` | alias |
|
||
| 12 | `--border-strong` | `#8d8d8d` | `--cds-border-strong` | alias |
|
||
| 12 | `--text` | `#161616` | `--cds-text-primary` | alias |
|
||
| 13 | `--muted` | `#525252` | `--cds-text-secondary` | alias |
|
||
| 13 | `--dim` | `#8d8d8d` | `--cds-ui-04` | alias — contrast issue is `T4.6`, not here |
|
||
| 13 | `--accent` | `#0f62fe` | `--cds-interactive-01` | alias — **missed by the wave-0 count, see §10** |
|
||
| 13 | `--accent-hover` | `#0353e9` | `--cds-hover-primary` | alias |
|
||
| 13 | `--accent-soft` | `#edf5ff` | `--cds-highlight` (new) | alias |
|
||
| 14 | `--green` | `#198038` | `--cds-support-success` | alias |
|
||
| 14 | `--green-bg` | `#defbe6` | `--wp-status-success-bg` (new) | alias |
|
||
| 15 | `--red` | `#da1e28` | `--cds-support-error` | alias |
|
||
| 15 | `--red-bg` | `#fff1f1` | `--wp-status-error-bg` (new) | alias |
|
||
| 15 | `--amber` | `#8e6a00` | `--wp-status-warning-text` (new) | alias |
|
||
| 15 | `--amber-bg` | `#fdf6dd` | `--wp-status-warning-bg` (new) | alias |
|
||
| 16 | `--head-bg` | `#f4f4f4` | `--cds-layer-accent` | alias |
|
||
| 16 | `--zebra` | `#fafafa` | — | **one-off**, §8-A. Not a Carbon grey; a 4-step-lighter zebra stripe |
|
||
| 16 | `--row-hover` | `#eef0f2` | — | **one-off**, §8-B. Deliberately not `--accent-soft`; see the comment at `:115-116` |
|
||
| 17 | `--mono` | `'IBM Plex Mono','Cascadia Mono',Consolas,monospace` | `--wp-font-mono` | **value differs**, §8-H |
|
||
| 18 | `--s1`…`--s6` | `4 8 12 16 20 28`px | `--wp-s1..6` (new) | **promote** — this is the canonical spacing scale |
|
||
| 19–20 | `--ctl`, `--ctl-sm` | `32px`, `26px` | `--wp-ctl`, `--wp-ctl-sm` (new) | promote |
|
||
|
||
Lines 85 and 115 contain `--dim` / `--accent-soft` inside **comments** — a naïve
|
||
`grep '--x:'` counts them. They are prose, not declarations.
|
||
|
||
### 4b. `work-package-suite-styles.css` — 16 declarations, lines 2–17
|
||
|
||
| Line | Token | Value | Canonical | Action |
|
||
|---|---|---|---|---|
|
||
| 2 | `--primary` | `#0f62fe` | `--cds-interactive-01` | alias |
|
||
| 3 | `--primary-light` | `#edf5ff` | `--cds-highlight` (new) | alias |
|
||
| 4 | `--success` | `#198038` | `--cds-support-success` | alias |
|
||
| 5 | `--warning` | `#8e6a00` | `--wp-status-warning-text` (new) | alias |
|
||
| 6 | `--warning-bg` | `#fdf6dd` | `--wp-status-warning-bg` (new) | alias |
|
||
| 7 | `--danger` | `#da1e28` | `--cds-support-error` | alias |
|
||
| 8 | `--text` | `#161616` | `--cds-text-primary` | alias |
|
||
| 9 | `--text-light` | `#525252` | `--cds-text-secondary` | alias |
|
||
| 10 | `--text-dim` | `#8d8d8d` | `--cds-ui-04` | alias — **`T4.6` re-measures this**, do not change the value in wave 3 |
|
||
| 11 | `--border` | `#e0e0e0` | `--cds-border-subtle` | alias |
|
||
| 12 | `--border-strong` | `#8d8d8d` | `--cds-border-strong` | alias |
|
||
| 13 | `--bg` | `#f4f4f4` | `--cds-background` | alias |
|
||
| 14 | `--bg-card` | `#ffffff` | `--cds-layer` | alias |
|
||
| 15 | `--appbar` | `#161616` | `--wp-appbar-bg` | alias — file-map called this out; it is the same value under a second name |
|
||
| 16 | `--shadow` | `none` | `--wp-shadow-none` | alias — **and it is a no-op, see §7** |
|
||
| 17 | `--shadow-lg` | `0 4px 16px rgba(0,0,0,0.16)` | `--wp-shadow-lg-neutral` | **value differs from the creator's**, §8-F |
|
||
|
||
Line 340 mentions `--cds-field: #ffffff` inside the `T1.5` comment. Prose, not a declaration.
|
||
|
||
### 4c. `wp-creation-styles.css` — 24 declarations (21 at `:root` lines 10–30, 3 on `body`)
|
||
|
||
| Line | Token | Value | Canonical | Action |
|
||
|---|---|---|---|---|
|
||
| 10 | `--bg` | `#f4f4f4` | `--cds-background` | alias |
|
||
| 11 | `--surface` | `#ffffff` | `--cds-layer` | alias |
|
||
| 12 | `--surface2` | `#f4f4f4` | `--cds-layer-accent` | alias |
|
||
| 13 | `--border` | `#e0e0e0` | `--cds-border-subtle` | alias |
|
||
| 14 | `--border-strong` | `#8d8d8d` | `--cds-border-strong` | alias |
|
||
| 15 | `--text` | `#161616` | `--cds-text-primary` | alias |
|
||
| 16 | `--text-muted` | `#525252` | `--cds-text-secondary` | alias |
|
||
| 17 | `--text-dim` | `#8d8d8d` | `--cds-ui-04` | alias — applied at **10px** on `:374`; `T4.6` owns the contrast |
|
||
| 18 | `--accent` | `#0f62fe` | `--cds-interactive-01` | alias |
|
||
| 19 | `--accent-dim` | `#edf5ff` | `--cds-highlight` (new) | alias |
|
||
| 20 | `--accent-green` | `#198038` | `--cds-support-success` | alias |
|
||
| 21 | `--accent-green-dim` | `#defbe6` | `--wp-status-success-bg` (new) | alias |
|
||
| 22 | `--accent-amber` | `#8e6a00` | `--wp-status-warning-text` (new) | alias |
|
||
| 23 | `--accent-amber-dim` | `#fdf6dd` | `--wp-status-warning-bg` (new) | alias |
|
||
| 24 | `--red` | `#da1e28` | `--cds-support-error` | alias |
|
||
| 25 | `--red-dim` | `#fff1f1` | `--wp-status-error-bg` (new) | alias |
|
||
| 26 | `--radius` | `0` | `--wp-radius-0` (new) | alias — **and contradicted 45×, see §7** |
|
||
| 27 | `--shadow` | `none` | `--wp-shadow-none` | alias — no-op, §7 |
|
||
| 28 | `--shadow-lg` | `0 4px 16px rgba(20,30,50,.12)` | `--wp-shadow-lg-cool` | **value differs**, §8-F |
|
||
| 29 | `--mono` | `'IBM Plex Mono', ui-monospace, 'Cascadia Mono', 'Segoe UI Mono', Consolas, monospace` | `--wp-font-mono` | **the fullest stack — adopt this one**, §8-H |
|
||
| 30 | `--sans` | `'IBM Plex Sans', …, 'Helvetica Neue', sans-serif` | `--wp-font-sans` | alias, §8-H |
|
||
| 685 | `--nav-w` (on `body`) | `288px` | — | **leave alone — `T7.1`/BL-001** |
|
||
| 686 | `--nav-w` (`body.wp-nav-collapsed`) | `56px` | — | leave alone |
|
||
| 817 | `--nav-w` (`@media ≤860px`) | `56px` | — | leave alone |
|
||
|
||
### 4d. `wp-chrome.css` — 14 declarations, scoped to `.wp-chrome` (lines 19–25, 29–35)
|
||
|
||
These are **not** `:root` declarations. They are a two-value theme switch: the same seven
|
||
role names resolve light or dark depending on `[data-bar="dark"]`. That pattern is correct and
|
||
should survive; only the literals move behind tokens.
|
||
|
||
| Line | Token | Light value → canonical | Line | Dark value → canonical |
|
||
|---|---|---|---|---|
|
||
| 19 | `--wpc-fg` `#161616` → `--cds-text-primary` | 29 | `#ffffff` → `--wp-appbar-fg` |
|
||
| 20 | `--wpc-fg-dim` `#525252` → `--cds-text-secondary` | 30 | `#c6c6c6` → `--wp-appbar-fg-dim` |
|
||
| 21 | `--wpc-bg` `#ffffff` → `--cds-layer` | 31 | `#262626` → **one-off**, §8-J |
|
||
| 22 | `--wpc-bg-soft` `#f4f4f4` → `--cds-layer-accent` | 32 | `#393939` → `--cds-interactive-02` |
|
||
| 23 | `--wpc-border` `#c6c6c6` → `--cds-border-subtle-selected` | 33 | `#6f6f6f` → `--wp-appbar-border` |
|
||
| 24 | `--wpc-hover` `#e8e8e8` → `--cds-layer-hover` | 34 | `#353535` → `--wp-appbar-hover` |
|
||
| 25 | `--wpc-accent` `#0f62fe` → `--cds-interactive-01` | 35 | `#78a9ff` → `--cds-link-inverse` |
|
||
|
||
### 4e. `wp-sidenav.css` — 0 declarations, 31 raw literals
|
||
|
||
Every colour is hardcoded. The header comment says why — "Colours come from the dark app bar
|
||
it hangs off … not from `theme-light.css`" — but the *values* are all Carbon greys that
|
||
`theme-light.css` already holds, so the reasoning ("match the bar") and the mechanism
|
||
("hardcode it") disagree. Aliasing them to the appbar tokens makes the stated intent true.
|
||
|
||
| Value | Sites | Canonical |
|
||
|---|---|---|
|
||
| `#161616` | `:35` and the `:8` comment | `--wp-appbar-bg` |
|
||
| `#f4f4f4` | `:15`, `:35`, `:68`, `:89`, `:108` | `--cds-text-inverse` |
|
||
| `#353535` | `:17`, `:77`, `:92` | `--wp-appbar-hover` |
|
||
| `#ffffff` | `:18`, `:93` (focus rings), `:77` | `--wp-appbar-fg` |
|
||
| `#e8e8e8` | `:21` (light-bar hover) | `--cds-layer-hover` |
|
||
| `rgba(22,22,22,.55)` | `:25` scrim | **near-dupe of `--cds-overlay`** `rgba(22,22,22,.5)` — §8-F |
|
||
| `rgba(0,0,0,.4)` | `:38` drawer shadow | one-off, §7 |
|
||
| `#393939` | `:49`, `:59`, `:103` (rules) | `--cds-inverse-02` |
|
||
| `#a8a8a8` | `:53`, `:65`, `:100`, `:106` | `--cds-text-placeholder` |
|
||
| `#c6c6c6` | `:71`, `:74`, `:96` | `--wp-appbar-fg-dim` |
|
||
| `#8d8d8d` | `:82` | `--cds-ui-04` |
|
||
| `#262626` | `:94` current-row fill | one-off, §8-J |
|
||
| `#0f62fe` | `:94` current-row rule | `--cds-interactive-01` |
|
||
| `#78a9ff` | `:98` current-row icon | `--cds-link-inverse` |
|
||
|
||
### 4f. `index.html` inline `<style>` — 0 declarations, 6 raw literals
|
||
|
||
The block already consumes `--cds-*` throughout; these six are the stragglers.
|
||
|
||
12 literals: **5 live, 7 dead**.
|
||
|
||
| Line | Literal | Context | Canonical |
|
||
|---|---|---|---|
|
||
| 126 | `#0e6027` | `.card.complete .card-button:hover` | `--cds-hover-support-success` (new) |
|
||
| 291 | `#fff` | `.proj-row select` background | `--cds-field` |
|
||
| 298 | `#fdf6dd` / `#f1c21b` / `#8e6a00` | `.proj-archived-note` — the amber triple | `--wp-status-warning-bg` / `--cds-support-warning` / `--wp-status-warning-text` |
|
||
| 291, 292 ×2, 300 ×2, 303, 305 | `#8d8d8d` ×3, `#fff` ×2, `#e0e0e0`, `#0f62fe` | **`var()` fallbacks only — 7 of them** | delete the fallbacks — see §7 |
|
||
|
||
`index.html:13` `<meta name="theme-color" content="#161616">` is markup, not CSS. It cannot
|
||
take a `var()`. Leave it; note it in §7.
|
||
|
||
---
|
||
|
||
## 5. Raw literals used in rules, by sheet
|
||
|
||
Counts exclude declarations and comments — measured by stripping `/* … */` first, then
|
||
subtracting literals that sit inside a `--x:` declaration. Full site lists are in §4e/§4f for
|
||
the two sheets that are all-raw; the rest are itemised here.
|
||
|
||
| Sheet | Raw literals in rules | The ones that are not already a token |
|
||
|---|---|---|
|
||
| `theme-light.css` | **1** | `:203` `#fff` |
|
||
| `console.css` | **19** | `#a7f0ba` `:82` · `#ffd7d9` `:83` · `#fddc69` `:84` · `#0f1525` `#d7e0f5` `:90` · `#56d364` `#ff7b72` `:92` · `#e8daff` `#6929c4` `:145` · `#e8e8e8` `:146` · `rgba(20,30,50,.5)` `:158` · `rgba(20,30,50,.3)` `:161` · `rgba(20,30,50,.12)` `:174` · `#fff` ×6 (`:49 :52 :53 :54 :67 :138`) |
|
||
| `work-package-suite-styles.css` | **15** | `#fff` `:43 :78 :105 :133 :562` · `#c6c6c6` `:111 :150` · `#6f6f6f` `:134 :144 :149` · `#353535` `:143` · `#0353e9` `:476` (a dead `var()` fallback) · `#0e6027` ×2 `:498` · `rgba(0,0,0,0.5)` `:606` |
|
||
| `wp-chrome.css` | **22** | the whole `.wpc-pop` block `:125-180` is raw (`#fff #161616 #e0e0e0 #6f6f6f #f0f0f0 #f4f4f4 #edf5ff #0f62fe #c6c6c6`) plus the archived banner `:50-52` |
|
||
| `wp-creation-styles.css` | **68** | see below |
|
||
| `wp-sidenav.css` | **30** (a 31st is in the header comment) | §4e |
|
||
| `index.html` inline | **12** (5 live, 7 dead) | §4f |
|
||
|
||
### The creator's raw literals — the largest group
|
||
|
||
Grouped by what they are, because they need different treatment:
|
||
|
||
**Already-tokenised values written raw** — straight substitution, zero risk:
|
||
`#fff` ×19 (`:248 :262 :264 :372 :385 :389 :446 :471 :498 :504 :505 :506 :517 :536 :618 :706 :715 :784 :823`) → `--cds-text-on-color` / `--cds-layer`;
|
||
`#0353e9` ×3 (`:263 :711 :718`) → `--cds-hover-primary`;
|
||
`#0e6027` ×2 (`:265 :447`) → `--cds-hover-support-success`;
|
||
`#161616` ×2 (`:618 :623`, the `.sop-chip` tooltip) → `--cds-ui-05`;
|
||
`#0043ce` (`:231`) → `--cds-link-secondary`.
|
||
|
||
**Accent tints with no token** — §8-C, do not merge:
|
||
`#b9d2fb` ×4 (`:230 :449 :614 :636`) · `#cdd9f2` ×2 (`:515 :581`) · `#e2ecfc` (`:582`).
|
||
|
||
**`var()` fallbacks that can never fire** — the token is declared at `:root` in the same
|
||
sheet, so the fallback is dead code. §7.
|
||
`var(--accent-dim,#eef3fd)` `:581 :839` · `var(--accent-dim,#eaf0fd)` `:515` ·
|
||
`var(--accent,#0f62fe)` `:854`.
|
||
|
||
**Planner-style neutral greys, no token** — §8-B, do not merge:
|
||
`#fbfbfc` (`:680`) · `#eef0f3` ×3 (`:696 :740 :773`) · `#e8eaed` ×2 (`:741 :774`).
|
||
|
||
**Status borders, no token** — §8-D:
|
||
`#b6e3c6` ×2 (`:494 :532`) · `#f0d9ad` ×3 (`:451 :461 :495`) · `#f3c4c4` (`:496`) ·
|
||
`#ffc4c4` (`:663`).
|
||
|
||
**Deliberate one-offs** — §7:
|
||
dev-mode banner `#3a2a00` `#ffd479` (`:573`), `#ffb000` (`:574`) ·
|
||
`rgba(37,99,214,0.07)` (`:565`) — §8-E ·
|
||
`rgba(255,255,255,.94)` (`:598`), `rgba(255,255,255,.28)` (`:715`) ·
|
||
`rgba(244,245,247,.82)` (`:302`) — §8-A.
|
||
|
||
**Cool-tinted shadows and scrims** — one family, seven alphas: `rgba(20,30,50, .06 .08 .16
|
||
.18 ×2 .22 .28)` (`:599 :824 :818 :647 :722 :621 :391`) plus `rgba(20,28,40,.55)` (`:521`)
|
||
and `rgba(0,0,0,.25)` (`:518`), `rgba(0,0,0,.3)` (`:523`). §8-F.
|
||
|
||
---
|
||
|
||
## 6. Type, spacing, radius and font scales
|
||
|
||
### 6a. Type — 27 distinct font-size values, three notations
|
||
|
||
`rem` on the two Carbon-native surfaces, `px` everywhere else, **and half-pixels in the
|
||
creator**. There is no scale; there is a histogram.
|
||
|
||
| Value | Total | Where |
|
||
|---|---|---|
|
||
| `9px` `9.5px` `10px` `10.5px` | 34 | creator 28, chrome 4, wizard 1, sidenav 1 |
|
||
| `11px` `11.5px` | 46 | creator 34, console 3, sidenav 4, wizard 2, index 2, chrome 1 |
|
||
| `12px` `12.5px` | 53 | creator 32, console 7, index 6, wizard 5, chrome 2, sidenav 1 |
|
||
| `13px` `13.5px` | 66 | creator 31, console 10, index 9, chrome 7, wizard 4, sidenav 3, theme 2 |
|
||
| `14px` | 21 | wizard 7, creator 7, theme 2, chrome 2, index 2, sidenav 1 |
|
||
| `15px` `16px` `17px` `18px` `20px` `22px` `26px` | 27 | creator 13, wizard 9, console 2, theme 1, sidenav 1 |
|
||
| `.75rem` → `2.25rem` (10 values) | 16 | theme 8, index 8 |
|
||
| `8px`, `.92em`, `inherit` | 3 | creator 2, console 1 |
|
||
|
||
**Recommendation for `T3.2`:** publish `--wp-type-*` as a **documented ladder that page
|
||
sheets may adopt**, and convert only the values that already sit on it. Rewriting 27 sizes
|
||
onto 8 steps changes rendering on every page and is forbidden here. The half-pixel sizes
|
||
(`9.5 10.5 11.5 12.5 13.5`, 17 sites, creator + chrome) are the ones to retire — log as
|
||
**BL-006**, do it during the `T7.1` rebuild where the creator is being re-laid-out anyway.
|
||
|
||
### 6b. Spacing — three systems
|
||
|
||
| System | Where | Values |
|
||
|---|---|---|
|
||
| **Token scale** | `console.css` `--s1..--s6` | `4 8 12 16 20 28` px — 62 `var()` consumers, 2 of them in `users.js` |
|
||
| **`rem` ladder** | wizard + `index.html` inline | `0.25 0.3 0.5 0.55 0.6 0.65 0.7 0.75 0.85 0.9 1 1.25 1.4 1.5 1.75 2 2.5 3` rem — 18 steps, 8 of them used once |
|
||
| **Raw px, no scale** | creator, chrome, sidenav | every integer `1`–`14`, then `16 18 20 22 24 28 32 36 52 56 72` — 289 sites in the creator alone |
|
||
|
||
`--s1..--s6` is the only one of the three that is a scale. `T3.2` promotes it to `--wp-s*` and
|
||
aliases `console.css`. The other two get converted as their pages are rebuilt (`T5.x`, `T7.x`),
|
||
not now.
|
||
|
||
### 6c. Radius — the token says square, the sheet says otherwise
|
||
|
||
`--radius: 0` is declared once and honoured **23 times** in `wp-creation-styles.css` — and
|
||
contradicted by raw values **45 times** in the same file: `2px 3px 4px 5px 6px 8px 9px 10px
|
||
12px 14px 20px 50%`, plus the two asymmetric CTA radii at `:707` and `:716`.
|
||
|
||
Across all sheets: `0` ×34, `3px` ×13, `4px` ×10, `6px` ×9, `50%` ×7, `9px` ×6, `20px` ×5.
|
||
|
||
The square-corner idiom is Carbon and it is the intent everywhere except the creator, which
|
||
drifted. **Do not fix in `T3.2`** — changing 45 radii is the most visible possible diff.
|
||
Log as **BL-007** against `T7.1`.
|
||
|
||
### 6d. Font stacks — 2 sans variants, 3 mono variants
|
||
|
||
| Stack | Sites | Difference |
|
||
|---|---|---|
|
||
| Sans **with** `'Helvetica Neue'` | `theme-light:121`, `wizard:22`, creator `--sans:30` | — |
|
||
| Sans **without** `'Helvetica Neue'` | `console:22`, `wp-chrome:54`, `wp-sidenav:36` | drops one fallback |
|
||
| Mono A | creator `--mono:29` | `'IBM Plex Mono', ui-monospace, 'Cascadia Mono', 'Segoe UI Mono', Consolas, monospace` |
|
||
| Mono B | `console:17` | drops `ui-monospace` **and** `'Segoe UI Mono'` |
|
||
| Mono C | `wp-chrome:159, :221` | drops `'Cascadia Mono'` **and** `'Segoe UI Mono'` |
|
||
|
||
The file map recorded two mono stacks; there are **three**. Adopt Mono A (the superset) as
|
||
`--wp-font-mono` and the Helvetica-Neue sans as `--wp-font-sans`.
|
||
|
||
**This is a rendering change on machines that have `'Segoe UI Mono'` or `ui-monospace` but not
|
||
`'IBM Plex Mono'`** — i.e. most Windows machines without Plex installed, which is the target
|
||
environment. Adopting the superset stack in `T3.2` would change the admin console's monospace
|
||
face. → **Alias to the superset but keep `console.css`'s narrower stack as
|
||
`--wp-font-mono-console` until `T3.5`**, or accept the change and re-shoot `admin`/`users`.
|
||
Flagged, not decided — see §8-H.
|
||
|
||
---
|
||
|
||
## 7. One-offs, kept raw, with reasons
|
||
|
||
Values that should **not** become tokens, and why. `T3.2` leaves each of these alone.
|
||
|
||
| Value(s) | Where | Reason |
|
||
|---|---|---|
|
||
| `#1a2230` `#2563d6` `#cdd9f2` `#f0f2f5` `#ccc` | `wp-creation-app.js:1257` | The print window is a **separate document** written with `document.write()`. It loads no stylesheet, so `var()` cannot resolve. Hardcoding is the only correct option here. |
|
||
| `#0f1525` `#d7e0f5` `#56d364` `#ff7b72` | `console.css:90-92` | `pre.out` is a **terminal emulator**. Green-on-dark pass / red-on-dark fail is the convention being quoted; it is not the product palette and should not track it. |
|
||
| `#3a2a00` `#ffd479` `#ffb000` | `wp-creation-styles.css:573-574` | The dev-mode banner is **meant** to look wrong. Making it consume the product's amber would make it look intentional, which defeats it. |
|
||
| `#e8daff` `#6929c4` | `console.css:145` | Carbon purple-10/purple-60, used once, for the Project Super User tag. Real Carbon values with no `--cds-*` slot in this sheet's subset. Promote only if a second consumer appears. |
|
||
| `#161616` | `index.html:13` `<meta name="theme-color">` | Markup attribute. Cannot take a `var()`. |
|
||
| `rgba(0,0,0,.4)` | `wp-sidenav.css:38` | Drawer drop-shadow. Neutral by intent — it falls on both light and dark hosts. §8-F |
|
||
| `--shadow: none` | wizard `:16`, creator `:27` | **A no-op token with 8 consumers.** `box-shadow: var(--shadow)` renders nothing on `.step-navigation`, `.seq-step`, `.card`, `.stepper`, `.btn-primary`, `.btn-generate`. It is not broken — flat is the Carbon idiom — but it is 8 dead declarations. Keep the alias; note for `T3.3`, which is hunting exactly this class of silent no-op. |
|
||
| `var(--accent-dim,#eef3fd)` ×2, `var(--accent-dim,#eaf0fd)`, `var(--accent,#0f62fe)`, `var(--cds-hover-primary,#0353e9)`, `var(--cds-border-strong,#8d8d8d)` ×3, `var(--cds-ui-01,#fff)` ×2, `var(--cds-ui-03,#e0e0e0)`, `var(--cds-link-01,#0f62fe)` | **12 sites:** creator `:515 :581 :839 :854`, wizard `:476`, `index.html:291 :292`(×2) `:300`(×2) `:303 :305` | **Dead fallbacks.** Every one of these tokens is declared at `:root` on a sheet the page loads, so the fallback can never render. They are a meaningful share of the raw-hex count and cost nothing to delete. Deleting them is `T3.2` work and is provably invisible. |
|
||
|
||
---
|
||
|
||
## 8. Near-duplicates — where unintended visual change will come from
|
||
|
||
Computed, not eyeballed: every pair of distinct colours in the six sheets plus the launcher's
|
||
inline block, ranked by summed channel distance. Anything a careless refactor would collapse.
|
||
|
||
### A. Off-whites around `#f4f4f4` — 5 values
|
||
|
||
| Value | Site | Role |
|
||
|---|---|---|
|
||
| `#f4f4f4` | canonical, 22 sites | page background / layer-accent |
|
||
| `#fafafa` | `console.css:16` `--zebra` | table zebra stripe |
|
||
| `#fbfbfc` | `wp-creation-styles.css:680` | `.wp-nav` panel background |
|
||
| `rgba(244,245,247,.82)` | `wp-creation-styles.css:302` | loading overlay |
|
||
| `#f0f0f0` | `wp-chrome.css:139,163` | popover divider hairlines |
|
||
|
||
The zebra is the trap. `#fafafa` sits **6 points lighter** than `#f4f4f4`; collapsing them
|
||
erases the striping on the user table entirely, on the one page where nine columns make
|
||
striping load-bearing. `T3.2` keeps all five.
|
||
|
||
### B. Hover greys — 5 values, max spread 26
|
||
|
||
`#e8e8e8` (canonical `--cds-layer-hover`, 7 sites) · `#e5e5e5` (`--cds-selected-ui`, 8) ·
|
||
`#eef0f2` (`console --row-hover`) · `#eef0f3` (creator `.wp-nav-*:hover`, 3) ·
|
||
`#e8eaed` (creator `.wp-nav-item.active`, 2).
|
||
|
||
`#eef0f2` and `#eef0f3` are **one point apart** and in different sheets — almost certainly the
|
||
same colour typed twice from memory. They are still not interchangeable in `T3.2`: `console`
|
||
has a comment at `:115-116` explaining that its row hover is deliberately *not* the accent
|
||
tint. Two canonical tokens, one decision logged.
|
||
|
||
### C. Accent tints — 4 values, and 2 of them are dead
|
||
|
||
| Value | Site | Live? |
|
||
|---|---|---|
|
||
| `#edf5ff` | canonical (blue-10), 4 sheets | live |
|
||
| `#eef3fd` | `wp-creation-styles.css:581,839` | **dead** — `var()` fallback, token declared |
|
||
| `#eaf0fd` | `wp-creation-styles.css:515` | **dead** — same |
|
||
| `#e2ecfc` | `wp-creation-styles.css:582` `.ref-link:hover` | live, one-off |
|
||
|
||
Deleting the two dead fallbacks removes two near-duplicates at zero rendering risk. That is
|
||
the cheapest win in this wave.
|
||
|
||
### D. Status borders — the pairs that must not merge
|
||
|
||
| Role | Value A | Value B | Note |
|
||
|---|---|---|---|
|
||
| success border | `#a7f0ba` `console:82` | `#b6e3c6` `creator:494,532` | A is Carbon green-20; B is not Carbon at all |
|
||
| error border | `#ffd7d9` `console:83` | `#f3c4c4` `creator:496`, `#ffc4c4` `creator:663` | **three** values for one role; `#f3c4c4`/`#ffc4c4` differ by 12 |
|
||
| warning border | `#fddc69` `console:84` | `#f0d9ad` `creator:451,461,495` | A is Carbon yellow-30; B is not |
|
||
| accent border | `#b9d2fb` ×4 | `#cdd9f2` ×2 | neither is Carbon blue-20 (`#d0e2ff`) |
|
||
|
||
Eight values doing four jobs. Every one renders somewhere today. `T3.2` names all eight;
|
||
picking four winners is a `T3.5` conversation.
|
||
|
||
### E. There is a second blue in the app
|
||
|
||
`rgba(37,99,214,0.07)` at `wp-creation-styles.css:565` — that is **`#2563d6`**, not
|
||
`#0f62fe`. It fills `.sop-inherited`, the highlight on every field a work package inherited
|
||
from its SOP. At 7% alpha nobody has noticed, but it is a second brand blue, and `help.js`
|
||
carries the same one at `rgba(37,99,214,.15)` and `wp-creation-app.js:1257` uses it solid.
|
||
|
||
Not a `T3.2` fix — swapping it to `#0f62fe` shifts a real fill. Log as **BL-008**, resolve at
|
||
`T3.5` alongside the button roles, since "one accent" is the same conversation.
|
||
|
||
### F. Shadows and scrims — one blur, four tints
|
||
|
||
| Family | Values | Sites |
|
||
|---|---|---|
|
||
| neutral | `rgba(0,0,0, .16 .25 .3 .4 .5)` | theme `--cds-shadow`, wizard `--shadow-lg` + `.modal`, creator `#toast` + `.modal`, sidenav |
|
||
| cool | `rgba(20,30,50, .06 .08 .12 .16 .18 .22 .28 .3 .5)` | creator ×10, console ×3, chrome ×1 |
|
||
| cool-darker | `rgba(20,28,40,.55)` | creator `.modal-overlay:521` |
|
||
| near-black | `rgba(22,22,22, .5 .55)` | `--cds-overlay`, sidenav scrim `:25` |
|
||
|
||
**Correcting the file map:** it records `--shadow-lg` as differing by "a different blur". The
|
||
blur is identical — `0 4px 16px` in both. The difference is the **colour**:
|
||
`rgba(0,0,0,0.16)` (wizard) vs `rgba(20,30,50,.12)` (creator). Same geometry, warmer/cooler
|
||
and 4% apart in alpha. That matters because it means the two can be unified later by choosing
|
||
a tint, with no layout consequence at all.
|
||
|
||
`rgba(22,22,22,.5)` vs `rgba(22,22,22,.55)` is the same colour at two alphas — the sidenav
|
||
scrim is 5% darker than `--cds-overlay` for no recorded reason. Cheapest merge in the set, but
|
||
still a rendered change: not in `T3.2`.
|
||
|
||
### G. Notation-only duplicates — safe to collapse
|
||
|
||
`#fff` vs `#ffffff`: 69 sites between them, identical rendering. Same for the whitespace
|
||
variants `rgba(0, 0, 0, .16)` / `rgba(0,0,0,.16)` and `rgba(22, 22, 22, .5)`.
|
||
`--surface: #fff` (console) and `--surface: #ffffff` (creator) are the same token name, the
|
||
same colour, two notations, two sheets. This is the one class of duplicate `T3.2` can collapse
|
||
with no thought required.
|
||
|
||
### H. Font stacks — see §6d
|
||
|
||
Three mono stacks, two sans stacks. Adopting the superset is a **real rendering change** on
|
||
machines missing IBM Plex Mono. Decide in `T3.2`; if adopted, `admin` and `users` need
|
||
re-shot baselines — and remember **trap 2**: those two pages are not byte-stable (live
|
||
timestamps), so capture twice before believing any diff.
|
||
|
||
### K. A ninth amber, four points from the eighth
|
||
|
||
`field.html:35` fills `.pill.warn` with **`#8a6d00`**, where every other warning text in the
|
||
app is `#8e6a00`. Four points apart, same job, and `field.html`'s inline block was not in the
|
||
`T3.1` inventory — §1 listed only the launcher's, and `login.html` and `field.html` also carry
|
||
one. Almost certainly a typo rather than a decision.
|
||
|
||
`T3.2` named it `--wp-status-warning-text-alt` rather than merging it, on the same rule as
|
||
everything else in §8: merging moves a rendered colour. **BL-009**, resolve at `T3.5`.
|
||
|
||
### J. `#262626` — Carbon gray-90, used twice, no token
|
||
|
||
`wp-chrome.css:31` (dark search field) and `wp-sidenav.css:94` (current row). It is a real
|
||
Carbon value that `theme-light.css` simply never declared. Add `--cds-layer-01-inverse:
|
||
#262626`? No — cleanest is `--wp-appbar-layer: #262626`, in the appbar group where its two
|
||
consumers live.
|
||
|
||
---
|
||
|
||
## 9. Tokens read from JavaScript — names that cannot be deleted
|
||
|
||
`T3.2` says to keep existing names as aliases "where deleting them would touch large amounts
|
||
of markup". This is the concrete list. These `var()` references live in **`.js` files**, so a
|
||
rename fails silently — no build error, no console warning, just an unstyled element.
|
||
|
||
| Consumer | Tokens it reads | Count |
|
||
|---|---|---|
|
||
| `work-package-suite-app.js` | `--border` 15, `--bg` 7, `--danger` 6, `--text-dim` 5, `--primary` 2, `--primary-light` 1, `--text-light` 2, `--text` 1, `--warning` 1, `--mono` 1 | 41 |
|
||
| `wp-creation-app.js` | `--text-dim` 8, `--accent` 5, `--accent-amber` 4, `--accent-green` 3, `--red` 3, `--nav-w` 2, `--surface2` 1, `--rail-top` 1 | 27 |
|
||
| `admin.js` | `--muted` 14, `--green` 8, `--red` 5, `--amber` 2 | 29 |
|
||
| `users.js` | `--muted` 4, `--red` 4, `--s2` 2, `--green` 1 | 11 |
|
||
| `field.js` | `--cds-text-helper` 2, `--cds-text-secondary` 1 | 3 |
|
||
|
||
**111 JS-side references across 23 distinct token names** (21 once the two runtime-set
|
||
properties below are set aside). Every one of those names must still resolve after `T3.2`.
|
||
Grep before deleting any alias:
|
||
|
||
```bash
|
||
grep -n 'var(--NAME' *.js
|
||
```
|
||
|
||
Two runtime-set properties are declared in no stylesheet and must not be shadowed:
|
||
`--wp-chrome-h` (`work-package-suite-app.js:528`) and `--rail-top`
|
||
(`wp-creation-app.js:1328`).
|
||
|
||
---
|
||
|
||
## 10. The `#0f62fe` count — correcting the wave 0 baseline
|
||
|
||
`file-map.md` §4 metric 5 records **14 declarations in 4 sheets** and defines the metric as
|
||
"the number of stylesheets that declare their own accent token", with a wave 9 target of 1.
|
||
|
||
**The count is 15, in 5 sheets.** The baseline command misses one:
|
||
|
||
```bash
|
||
grep -nE '^\s*--[a-zA-Z0-9-]+\s*:\s*#0f62fe' *.css # 14 — anchored to ^
|
||
```
|
||
|
||
`console.css:13` packs five declarations onto one line, and `--accent:#0f62fe` is the third of
|
||
them. `^\s*--` only ever matches the **first** declaration on a line, so console's accent was
|
||
never counted. Corrected command and result:
|
||
|
||
```bash
|
||
grep -ohE '\-\-[a-zA-Z0-9-]+\s*:\s*#0f62fe' *.css | wc -l # 15 declarations
|
||
grep -lE '\-\-[a-zA-Z0-9-]+\s*:\s*#0f62fe' *.css | wc -l # 5 sheets
|
||
```
|
||
|
||
| Sheet | Token | Line |
|
||
|---|---|---|
|
||
| `theme-light.css` | `--cds-interactive-01` + 10 Carbon aliases | 3, 5, 6, 22, 39, 62, 64, 69, 88, 97, 115 |
|
||
| `console.css` | `--accent` | **13 — missed by the baseline** |
|
||
| `work-package-suite-styles.css` | `--primary` | 2 |
|
||
| `wp-chrome.css` | `--wpc-accent` | 25 |
|
||
| `wp-creation-styles.css` | `--accent` | 18 |
|
||
|
||
**The wave 9 target is unchanged: 1 sheet.** The extra sheet does not change the goal, it
|
||
changes the count of what has to be removed — 4 page-sheet declarations, not 3.
|
||
|
||
Two secondary corrections while this is open:
|
||
|
||
- **Raw occurrences: 30, not 31.** `file-map.md` recorded 31 at wave 0. `T2.2` deleted the
|
||
flat strip and took one with it. This is the metric the file map explicitly says *not* to
|
||
track ("track the sheet count, not the raw occurrence count") — recorded here only so the
|
||
discrepancy is not rediscovered as a defect.
|
||
- Current spread of the 30: `theme-light` 11, `wp-chrome` 4, `help.js` 4, `wp-creation-styles`
|
||
2, and one each in `console.css`, `work-package-suite-styles`, `wp-sidenav`, `index.html`,
|
||
`auth-guard.js`, `work-package-suite-app.js`, `wp-creation-app.js`, `wp-format.js`.
|
||
|
||
---
|
||
|
||
## 11. `T3.2` — what was done, and how it was proved
|
||
|
||
Done in this order, because the ordering is what kept the diff empty:
|
||
|
||
1. **Deleted the 12 dead `var()` fallbacks** (§7). Provably invisible.
|
||
2. **Added the canonical tokens** to `theme-light.css` (§2a, §2b, §2d) without touching a
|
||
consumer. Additive, zero diff.
|
||
3. **Converted the `:root` blocks** of `console.css`, `work-package-suite-styles.css` and
|
||
`wp-creation-styles.css` to aliases. Names stayed; literals went.
|
||
4. **Converted `wp-chrome.css`'s two `.wp-chrome` blocks**, preserving the light/dark switch.
|
||
5. **Converted `wp-sidenav.css`'s 30 raw literals** to the app-bar tokens, which is the sheet
|
||
whose stated intent ("colours come from the bar") and mechanism (hardcoded hex) disagreed.
|
||
Flipping `--wp-appbar-bg` now takes the drawer with it, which is what the comment claimed.
|
||
6. **Converted the raw literals in rules** across all six sheets and all four inline `<style>`
|
||
blocks, skipping everything §7 lists.
|
||
7. **Left every §8 near-duplicate as its own canonical token.** No winners picked.
|
||
|
||
### Result against the done-when list
|
||
|
||
| Check | Result |
|
||
|---|---|
|
||
| exactly one declaration per canonical value; `#0f62fe` → 1 | **met.** One sheet declares it (`theme-light.css`); the 11 occurrences inside it are Carbon's own v10→v11 alias layer, which §3 records as deliberate and not the `S5` defect |
|
||
| no page stylesheet declares a raw **colour** | **met.** 0 literals across all 5 page sheets and all 4 inline `<style>` blocks; `theme-light.css` is the only file in `html/` holding one |
|
||
| no page stylesheet declares a raw **spacing or type** value | **not met, and not achievable under this task's own "change no rendered value"** — see below |
|
||
| screenshot diff empty on all pages at both widths | **superseded by a stronger check** — see below |
|
||
| `docs/reference/tokens.md` updated to what was built | **met** — §2d |
|
||
|
||
### The spacing and type half of check 2
|
||
|
||
Token *declarations* are aliased: `--s1`…`--s6`, `--ctl`, `--ctl-sm`, `--radius`, `--mono`,
|
||
`--sans` all resolve from `theme-light.css` now. But **483 raw spacing values, 281 raw
|
||
font-sizes and 65 raw radii remain inside rules**, 492 of them in the creator.
|
||
|
||
They cannot be tokenised here, and the reason is not effort. §6b measured that the creator's
|
||
spacing is every integer from 1px to 14px — it is not a scale, it is a histogram, and there is
|
||
no token that `padding: 9px 11px` maps to without changing one of the two numbers. `T3.2`
|
||
forbids changing a rendered value, so tokenising them and honouring that constraint are
|
||
mutually exclusive.
|
||
|
||
Stated plainly rather than quietly skipped: **this check is not met.** The colour half, which
|
||
is what `S5` and `C3` are actually about — four sheets each declaring `#0f62fe` — is met in
|
||
full. The spacing and type half is logged as **BL-010** and belongs with the page rebuilds at
|
||
`T5.x` and `T7.1`, where the values are being chosen again anyway.
|
||
|
||
### Why the screenshot check was replaced
|
||
|
||
The done-when asks for an empty screenshot diff. Captured against the wave 2 build, 11 of 14
|
||
shots were pixel-identical and 3 were not: the creator at 1440px and both admin widths.
|
||
Capturing wave 2 **against itself** produced the same 3 differences, at the same bounding box
|
||
(creator@1440: 344,272px, bbox 288,14→1439,4924). Those shots re-render live content, so a
|
||
pixel diff on them cannot distinguish a regression from the clock.
|
||
|
||
**Trap 2 in the task brief is half right and half wrong.** It names `admin` and `users` as the
|
||
unstable pair. `users` is stable at both widths; the actually-unstable third is the **creator
|
||
at 1440px**, and admin's instability is worse than "live timestamps" implies — its captured
|
||
page *height* varies by ~600px between runs.
|
||
|
||
So `tests/token_check.py` was written, and it checks the thing wave 3 actually claims:
|
||
|
||
- every custom property resolves to the same literal it did before, on every page;
|
||
- every element computes the same `color`, `background-color`, four border colours,
|
||
`outline-color`, `box-shadow`, `text-decoration-color`, `caret-color`, `column-rule-color`,
|
||
`font-family`, `font-size`, `font-weight` and `border-radius`.
|
||
|
||
That is strictly stronger than a screenshot: it covers the hover, focus and disabled rules a
|
||
screenshot never exercises, and it is deterministic.
|
||
|
||
Result, wave 2 versus `T3.2`, all 7 pages: **every one of the 178 wave-2 token names resolves
|
||
identically, and all 3,500 elements compute identically.** 213 tokens are new. 16 tokens
|
||
differ in notation only (`#fff` → `#ffffff`, `rgba(0,0,0,0.16)` → `rgba(0, 0, 0, .16)`), which
|
||
is §8-G — the one class of duplicate this task was supposed to collapse.
|
||
|
||
Two things that cost time and are recorded so they do not cost it again:
|
||
|
||
- The element walk was first keyed by sibling index, which reported 55 phantom differences on
|
||
the SOP page. The cause is three JS-injected overlays — `#wp-sync-badge`, `.wp-navscrim` and
|
||
`#wp-sidenav` — appending in whichever order their async work finishes. All three are
|
||
`position: fixed` with their own `z-index`, so the order changes nothing painted. The probe
|
||
now keys by identity. **BL-011.**
|
||
- The comparator normalises notation before reporting, because otherwise it fails on its own
|
||
success. That is safe only because the element comparison is the real evidence: a
|
||
normalisation that hid a genuine change would show up on every element consuming the token.
|
||
|
||
### Backlog entries this work raised
|
||
|
||
| ID | What | Suggested |
|
||
|---|---|---|
|
||
| BL-004 | `help.js`'s 52-colour parallel palette in a different design language | wave 9 (`C4`) |
|
||
| BL-005 | `auth-guard.js` + `wp-format.js` modal inline styles, 35 raw literals | `T9.5` with `C1` |
|
||
| BL-006 | 17 half-pixel font sizes in the creator and chrome | `T7.1` |
|
||
| BL-007 | `--radius: 0` contradicted by 45 raw radii in the creator | `T7.1` |
|
||
| BL-008 | `#2563d6`, a second brand blue, in `.sop-inherited` and `help.js` | `T3.5` |
|
||
| BL-009 | `#8a6d00`, a ninth amber four points from the eighth, on the field view | `T3.5` |
|
||
| BL-010 | 483 raw spacing, 281 raw font-size and 65 raw radius values in rules | `T5.x` / `T7.1` |
|
||
| BL-011 | Three JS-injected overlays race to append on the SOP page | wave 9 |
|
||
| BL-012 | `admin` and `creator@1440` are not stable enough to screenshot-diff | wave 9 with `C2` |
|
||
|
||
---
|
||
|
||
## 12. Button roles — `A5`, built at `T3.5`
|
||
|
||
**251 buttons across the 7 pages**, counted in the browser with every wizard step, creator
|
||
section and tool panel forced visible — two thirds of them are `display: none` at load and a
|
||
static grep misses them entirely.
|
||
|
||
### The four roles
|
||
|
||
Defined once, in `theme-light.css`, as `--wp-btn-*`. No fifth role exists.
|
||
|
||
| Role | Looks like | For | Tokens |
|
||
|---|---|---|---|
|
||
| **primary** | filled accent, white text | the one action the screen exists for; at most one per view | `--wp-btn-primary-bg/-fg/-hover/-active` |
|
||
| **secondary** | white fill, `--border-strong` hairline, accent on hover | every other real action — the app's workhorse | `--wp-btn-secondary-bg/-fg/-border/-hover-fg` |
|
||
| **tertiary** | no fill, no border, accent text | navigating or undoing | `--wp-btn-tertiary-fg/-hover-fg` |
|
||
| **danger** | outlined red; filled red only where a control is too small for an outline to read | destructive | `--wp-btn-danger-fg/-border/-soft-bg/-fill-bg/-fill-fg` |
|
||
|
||
### Green is a status colour
|
||
|
||
It says *cleared*, *ready*, *complete* — on a dot, a pill, a banner, a badge — and it never
|
||
fills a button. That was the second button language `A5` recorded: `Save & View` and `SOP
|
||
Complete` shouted louder than every other action in the suite while doing nothing more
|
||
dangerous than saving a form.
|
||
|
||
The green did not go anywhere. `.cstatus button.on-cleared`, `.toggle-btn.enabled`,
|
||
`.wp-nav-dot.ok`, `.rb-ready`, `.badge-R`, `.auto-tag` and the launcher card's left border and
|
||
`.card-status` all still carry it — every one of them a state rather than an action.
|
||
|
||
### Every button class, mapped
|
||
|
||
| Class | Role | Where | Changed at `T3.5`? |
|
||
|---|---|---|---|
|
||
| `button` (bare) | secondary | console | tokens only |
|
||
| `button.primary` | primary | console | tokens only |
|
||
| `button.danger`, `button.mini.danger` | danger, outlined | console | tokens only |
|
||
| `button.mini` | secondary | console | — |
|
||
| `.add-btn` | primary | wizard | tokens only |
|
||
| `.nav-btn` | secondary | wizard | tokens only |
|
||
| `.nav-btn.primary` | **primary** | wizard — `SOP complete` | **was green** |
|
||
| `.seq-del` | danger, filled | wizard — a 28px ✕ | tokens only |
|
||
| `.comments-toggle` | secondary | wizard | — |
|
||
| `.header-button`, `.wp-appbar-btn` | secondary on a dark bar | theme | — |
|
||
| `.btn.btn-primary` | primary | creator | tokens only |
|
||
| `.btn.btn-generate` | **primary** | creator — `Save & view` | **was green** |
|
||
| `.use-btn` | **primary** | creator | **was green** |
|
||
| `.btn.btn-ghost` | secondary | creator | tokens only |
|
||
| `.add-btn` (creator) | secondary, dashed | creator | uppercase removed |
|
||
| `.add-btn-gate` | secondary, amber | creator — adds a QC hold | — |
|
||
| `.row-del` | danger, outlined on hover | creator | tokens only |
|
||
| `.wp-nav-cta`, `.wp-nav-cta-more` | primary | creator navigator | tokens only |
|
||
| `.link-btn`, `.lock-edit`, `.cmt-jump` | tertiary | creator | tokens only |
|
||
| `.mode-btn.active` | primary | creator | — |
|
||
| `.cstatus button.on-*` | **status, not a role** | creator — Open / Cleared / N/A | — |
|
||
| `.card-button` | primary | launcher | — |
|
||
| `.card.complete .card-button` | **primary** | launcher | **was green** |
|
||
| `.submit-btn`, `.comments-toggle` | primary | launcher | — |
|
||
| `.close-btn` | secondary | launcher | — |
|
||
| `.wpc-foot-btn` | secondary | shared chrome | tokens only |
|
||
| `.wpc-clear`, `.comments-dropdown-close`, `.modal-close`, `.cmt-x`, `.wp-sidenav-close` | tertiary | everywhere | — |
|
||
| `.wp-navbtn`, `.wp-nav-toggle`, `.wp-sidenav-link`, `.wp-nav-link`, `.wp-nav-item` | tertiary | drawers and rails | — |
|
||
| `.ui-help-fab` | primary | help centre | out of scope — BL-004 |
|
||
| `.dev-toggle` | deliberately invisible | creator | — |
|
||
|
||
Four green action sites, not the two `A5` names. `.use-btn` and the launcher's completed-SOP
|
||
card button never render green in the default fixture, so the review could not have seen them.
|
||
|
||
### Sentence case
|
||
|
||
Applied to **buttons and field labels only**, which is what `A5` scopes it to.
|
||
|
||
The rule: *first word capitalised, everything after it lowercased, except acronyms* (`SOP`,
|
||
`QC`, `WP`, `UPN`, `PM`, `APM`, `CM`, `QM`, `PDF`, `JSON`, `CSV`, `BIM`, `MIMO`) *and external
|
||
proper nouns* (`Excel`, `Acumatica`). Page names get sentence case too when they appear inside
|
||
a sentence-shaped label — "Open the user directory", not "Open the User Directory" — because
|
||
the label is a description, not a title.
|
||
|
||
- **~30 button labels** rewritten across the launcher, wizard, creator, admin and two scripts.
|
||
- **46 field labels** rewritten. Labels carrying markup — a `.req` asterisk, a `.help-tip`
|
||
chip — had only their text nodes transformed, so the markup survives and "first word" means
|
||
the first word of the label rather than of each fragment.
|
||
- **`text-transform: uppercase` removed from four rules**: `.btn` and `.add-btn` (creator
|
||
buttons) and `label` and `.cmt-namebar label` (creator field labels). The mono face, the
|
||
10px size and the tracking are the creator's idiom and are untouched — only the forced
|
||
uppercase goes.
|
||
- **`help.js` was updated too.** It names `Load Sample` and `SOP Complete` in prose, so
|
||
renaming the buttons without it would have left the help centre describing controls that no
|
||
longer exist.
|
||
|
||
### Not touched, deliberately
|
||
|
||
| What | Why |
|
||
|---|---|
|
||
| `console.css` `.card h2` uppercase | `T3.5` says explicitly not to. Confirmed by diff: the only changes to `console.css` in this task are token substitutions, none of them on `.card h2`. |
|
||
| `table.grid th`, `.wp-types-header`, `.dash-table th` | table headers, not buttons or field labels |
|
||
| `.section-label`, `.sub-heading`, `.wpc-proj-kicker`, `.wpc-pop-head`, `.wp-sidenav-sect` | section eyebrows and headings |
|
||
| `.step-tab` uppercase | a stepper tab is neither a button nor a field label, and the stepper is rebuilt at `T7.x`. Logged as **BL-015**. |
|
||
| `.nav-tab` labels (`SOP Configuration`, `Work Package Creation`) | these name the two tools rather than describing an action; they read as titles and are the same strings the launcher cards use. |
|
||
|
||
---
|
||
|
||
## 13. Wave 3 exit — everything wave 3 changed on screen
|
||
|
||
`wave-3.md` asks for "no unintended visual change on any page versus wave 2". Measured with
|
||
`tests/token_check.py`, wave 2 (`b105135`) against the end of wave 3, all 7 pages:
|
||
|
||
**7 elements changed. All 7 are the fixes the wave was for.**
|
||
|
||
| Page | Element | Change | Task |
|
||
|---|---|---|---|
|
||
| sop | `#role_super_name.user-pick` | `#f4f4f4` → `#ffffff`, border `#e0e0e0` → `#8d8d8d` | `T3.4` (`A3`/`F5`) |
|
||
| sop | `#role_foreman_name.user-pick` | same | `T3.4` |
|
||
| sop | `#sop-complete-btn.nav-btn.primary` | `#198038` → `#0f62fe` | `T3.5` (`A5`) |
|
||
| sop | `#wp-gate button.nav-btn.primary` | `#198038` → `#0f62fe` | `T3.5` |
|
||
| creator | `#sticky-save .btn-generate` | `#198038` → `#0f62fe` | `T3.5` |
|
||
| creator | `.nav-row .btn-generate` | `#198038` → `#0f62fe` | `T3.5` |
|
||
| creator | `#hold-modal .btn-generate` | `#198038` → `#0f62fe` | `T3.5` |
|
||
|
||
Every other element on every page — 3,493 of them — computes exactly what it computed at the
|
||
end of wave 2, and all 178 wave-2 token names resolve to the same literals. `T3.2`'s
|
||
consolidation of five token systems into one changed nothing on screen, which was its whole
|
||
contract.
|
||
|
||
**Three fixes are not visible in that table and are verified another way**, because a computed
|
||
-style diff cannot see them:
|
||
|
||
| Fix | Why it is invisible here | How it was verified |
|
||
|---|---|---|
|
||
| `.card.complete .card-button` green → primary | needs a completed SOP; the fixture has none | source diff |
|
||
| `.use-btn` green → primary | needs a suggested value to be offered | source diff |
|
||
| Sentence case, ~30 buttons + 46 labels | `token_check` fingerprints computed style, not text or `text-transform` | the button inventory: 0 uppercase labels, 251 buttons still present |
|
||
| Focus rings | `:focus` is not in the fingerprint | measured directly with CDP focus emulation — see `T3.4` |
|
||
|
||
### Exit criteria
|
||
|
||
- [x] one token source of truth; page sheets alias only — `theme-light.css` is the only file
|
||
in `html/` containing a colour literal
|
||
- [x] `#0f62fe` declared once — one sheet, down from five
|
||
- [x] no unintended visual change versus wave 2 — 7 changes, 7 intended
|
||
- [x] fields look editable, buttons speak one language
|
||
- [ ] **not met:** `T3.2`'s "no page stylesheet declares a raw spacing or type value" — colour
|
||
is complete, spacing and type are **BL-010**, and §11 explains why the two halves of that
|
||
check cannot both be satisfied in the same task
|
||
|
||
---
|
||
|
||
## Appendix A — every `theme-light.css` declaration, line by line
|
||
|
||
`T3.1`'s first done-when is "lists every declaration with file and line". §4 itemises the 82
|
||
page-sheet declarations; this is the other 120, so the list is complete rather than grouped.
|
||
Column `#` is the line number in `html/theme-light.css`. Read down each column pair in turn.
|
||
|
||
| # | Token | Value | # | Token | Value | # | Token | Value |
|
||
|--:|---|---|--:|---|---|--:|---|---|
|
||
| 3 | `--cds-interactive-01` | `#0f62fe` | 43 | `--cds-hover-secondary` | `#4c4c4c` | 83 | `--cds-field` | `#ffffff` |
|
||
| 4 | `--cds-interactive-02` | `#393939` | 44 | `--cds-active-secondary` | `#6f6f6f` | 84 | `--cds-field-hover` | `#e8e8e8` |
|
||
| 5 | `--cds-interactive-03` | `#0f62fe` | 45 | `--cds-hover-tertiary` | `#0353e9` | 85 | `--cds-border-subtle` | `#e0e0e0` |
|
||
| 6 | `--cds-interactive-04` | `#0f62fe` | 46 | `--cds-active-tertiary` | `#002d9c` | 86 | `--cds-border-strong` | `#8d8d8d` |
|
||
| 7 | `--cds-ui-background` | `#f4f4f4` | 47 | `--cds-hover-ui` | `#e5e5e5` | 87 | `--cds-border-inverse` | `#393939` |
|
||
| 8 | `--cds-ui-01` | `#ffffff` | 48 | `--cds-hover-light-ui` | `#e5e5e5` | 88 | `--cds-border-interactive` | `#0f62fe` |
|
||
| 9 | `--cds-ui-02` | `#f4f4f4` | 49 | `--cds-hover-selected-ui` | `#cacaca` | 89 | `--cds-border-subtle-selected` | `#c6c6c6` |
|
||
| 10 | `--cds-ui-03` | `#e0e0e0` | 50 | `--cds-active-ui` | `#c6c6c6` | 90 | `--cds-text-primary` | `#161616` |
|
||
| 11 | `--cds-ui-04` | `#8d8d8d` | 51 | `--cds-active-light-ui` | `#cacaca` | 91 | `--cds-text-secondary` | `#525252` |
|
||
| 12 | `--cds-ui-05` | `#161616` | 52 | `--cds-selected-ui` | `#e5e5e5` | 92 | `--cds-text-placeholder` | `#a8a8a8` |
|
||
| 13 | `--cds-text-01` | `#161616` | 53 | `--cds-selected-light-ui` | `#e5e5e5` | 93 | `--cds-text-helper` | `#6f6f6f` |
|
||
| 14 | `--cds-text-02` | `#525252` | 54 | `--cds-inverse-hover-ui` | `#353535` | 94 | `--cds-text-on-color` | `#ffffff` |
|
||
| 15 | `--cds-text-03` | `#a8a8a8` | 55 | `--cds-hover-danger` | `#ba121b` | 95 | `--cds-text-inverse` | `#f4f4f4` |
|
||
| 16 | `--cds-text-04` | `#ffffff` | 56 | `--cds-active-danger` | `#750e13` | 96 | `--cds-text-disabled` | `#bdbdbd` |
|
||
| 17 | `--cds-text-05` | `#6f6f6f` | 57 | `--cds-hover-row` | `#f4f4f4` | 97 | `--cds-link-primary` | `#0f62fe` |
|
||
| 18 | `--cds-text-error` | `#da1e28` | 58 | `--cds-visited-link` | `#0043ce` | 98 | `--cds-link-secondary` | `#0043ce` |
|
||
| 19 | `--cds-icon-01` | `#161616` | 59 | `--cds-disabled-01` | `#f4f4f4` | 99 | `--cds-link-visited` | `#0043ce` |
|
||
| 20 | `--cds-icon-02` | `#525252` | 60 | `--cds-disabled-02` | `#bdbdbd` | 100 | `--cds-link-inverse` | `#78a9ff` |
|
||
| 21 | `--cds-icon-03` | `#ffffff` | 61 | `--cds-disabled-03` | `#8d8d8d` | 101 | `--cds-link-primary-hover` | `#0353e9` |
|
||
| 22 | `--cds-link-01` | `#0f62fe` | 62 | `--cds-button-primary` | `#0f62fe` | 102 | `--cds-icon-primary` | `#161616` |
|
||
| 23 | `--cds-link-02` | `#0043ce` | 63 | `--cds-button-secondary` | `#393939` | 103 | `--cds-icon-secondary` | `#525252` |
|
||
| 24 | `--cds-inverse-link` | `#78a9ff` | 64 | `--cds-button-tertiary` | `#0f62fe` | 104 | `--cds-icon-on-color` | `#ffffff` |
|
||
| 25 | `--cds-field-01` | `#ffffff` | 65 | `--cds-button-danger-primary` | `#da1e28` | 105 | `--cds-icon-inverse` | `#f4f4f4` |
|
||
| 26 | `--cds-field-02` | `#f4f4f4` | 66 | `--cds-button-danger-secondary` | `#da1e28` | 106 | `--cds-icon-disabled` | `#bdbdbd` |
|
||
| 27 | `--cds-inverse-01` | `#ffffff` | 67 | `--cds-background` | `#f4f4f4` | 107 | `--cds-support-error` | `#da1e28` |
|
||
| 28 | `--cds-inverse-02` | `#393939` | 68 | `--cds-background-inverse` | `#161616` | 108 | `--cds-support-success` | `#198038` |
|
||
| 29 | `--cds-support-01` | `#da1e28` | 69 | `--cds-background-brand` | `#0f62fe` | 109 | `--cds-support-warning` | `#f1c21b` |
|
||
| 30 | `--cds-support-02` | `#198038` | 70 | `--cds-background-active` | `#e5e5e5` | 110 | `--cds-support-info` | `#0043ce` |
|
||
| 31 | `--cds-support-03` | `#f1c21b` | 71 | `--cds-background-hover` | `#e8e8e8` | 111 | `--cds-support-error-inverse` | `#fa4d56` |
|
||
| 32 | `--cds-support-04` | `#0043ce` | 72 | `--cds-background-selected` | `#e5e5e5` | 112 | `--cds-support-success-inverse` | `#42be65` |
|
||
| 33 | `--cds-inverse-support-01` | `#fa4d56` | 73 | `--cds-background-selected-hover` | `#cacaca` | 113 | `--cds-support-warning-inverse` | `#f1c21b` |
|
||
| 34 | `--cds-inverse-support-02` | `#42be65` | 74 | `--cds-layer` | `#ffffff` | 114 | `--cds-support-info-inverse` | `#4589ff` |
|
||
| 35 | `--cds-inverse-support-03` | `#f1c21b` | 75 | `--cds-layer-accent` | `#f4f4f4` | 115 | `--cds-interactive` | `#0f62fe` |
|
||
| 36 | `--cds-inverse-support-04` | `#4589ff` | 76 | `--cds-layer-accent-hover` | `#e8e8e8` | 116 | `--cds-shadow` | `rgba(0, 0, 0, .16)` |
|
||
| 37 | `--cds-overlay` | `rgba(22, 22, 22, .5)` | 77 | `--cds-layer-accent-active` | `#e0e0e0` | 170 | `--wp-appbar-bg` | `#161616` |
|
||
| 38 | `--cds-danger` | `#da1e28` | 78 | `--cds-layer-hover` | `#e8e8e8` | 171 | `--wp-appbar-fg` | `#ffffff` |
|
||
| 39 | `--cds-focus` | `#0f62fe` | 79 | `--cds-layer-active` | `#e5e5e5` | 172 | `--wp-appbar-fg-dim` | `#c6c6c6` |
|
||
| 40 | `--cds-hover-primary` | `#0353e9` | 80 | `--cds-layer-selected` | `#e5e5e5` | 173 | `--wp-appbar-border` | `#6f6f6f` |
|
||
| 41 | `--cds-active-primary` | `#002d9c` | 81 | `--cds-layer-selected-hover` | `#cacaca` | 174 | `--wp-appbar-hover` | `#353535` |
|
||
| 42 | `--cds-hover-primary-text` | `#0043ce` | 82 | `--cds-layer-selected-inverse` | `#393939` | 175 | `--wp-appbar-height` | `48px` |
|
||
|
||
**120 declarations.** Lines 3–116 are the Carbon g10 set; lines 170–175 are the app-shell
|
||
group added by the suite. Many share a literal by design — that is Carbon's v10→v11 alias
|
||
layer, not the `S5` defect. See the note at the end of §3.
|