---
status: reconciled-partial
coverage_depth: representative
last_reconciled: 2026-07-18
specs:
  - apps/oshun/web/e2e/wcag-aa-signoff-v1-p2-3510.spec.ts
  - apps/oshun/web/e2e/wcag-aa-signoff-v1-p2-3511.spec.ts
  - apps/oshun/web/e2e/lilith-public-routes.spec.ts
source: apps/oshun/web/e2e/wcag-aa-signoff-v1-p2-3510.spec.ts
---

# Accessibility result: customer contrast-token handoff

- **Walked**: 2026-05-30–31 during the customer accessibility repair campaign.
  The dated sweep reduced 402 recorded contrast nodes to a 25-node floor
  classified as intentional specimens or invalid-parameter skeletons.
- **Reconciled**: 2026-07-18 against the current Lilith tokens, `readableInk`
  helper, stylesheet contract tests, system-specimen policy, and canonical
  desktop/mobile customer accessibility matrices. This was a source
  reconciliation, not a fresh all-route contrast sweep.
- **Verdict**: **partial** — the historical record explains a substantial and
  traceable token repair campaign, and the key fixes remain present in current
  source. Current automation guards representative customer surfaces and
  explicitly treats diagnostic specimen pages as render-only. It does not
  reproduce the dated 181-route inventory or justify carrying “every real
  customer surface is AA” forward as a current universal claim.
- **Current signoff specs**: `wcag-aa-signoff-v1-p2-3510.spec.ts`,
  `wcag-aa-signoff-v1-p2-3511.spec.ts`, and `lilith-public-routes.spec.ts`.

## Result at a glance

| Evidence lane                   | Recorded or current result                                                                                        | Authority limit                                           |
| ------------------------------- | ----------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------- |
| 2026-05-30 starting sweep       | 402 customer `color-contrast` nodes                                                                               | Historical build, route manifest, runner, and raw JSONL   |
| 2026-05-31 recorded floor       | 25 nodes: 17 intentional specimen/showcase cases and 8 invalid-parameter skeleton cases                           | Dated classification, not a current scan                  |
| Current semantic token repairs  | Cream `--l-muted`, `--l-warn`, and `--l-accent-2-text` values remain in the Lilith stylesheet                     | Source presence, not rendered coverage                    |
| Current data-color repair       | `readableInk` darkens six-digit hex text colors toward the cream-surface target and leaves other inputs unchanged | Helper contract; callers and backgrounds still matter     |
| Current customer signoff matrix | Eleven primary/domain surfaces run WCAG 2.1 A/AA at desktop and 390 × 844                                         | Serious/critical release threshold, representative routes |
| Current specimen policy         | Five `/system*` diagnostic pages render publicly with axe skipped for intentional sub-AA demonstrations           | Exclusion needs continued ownership and clear semantics   |

## Evidence map

The useful outcome is not the original count alone. The campaign moved repeated
component literals into semantic text tokens and a reusable data-color helper,
then retained a smaller portable accessibility matrix.

```mermaid
flowchart LR
    A[402 dated contrast nodes] --> B[Trace actual foreground and background]
    B --> C[Component literal repairs]
    B --> D[readableInk for data colors]
    B --> E[Semantic text tokens]
    C --> F[25-node dated floor]
    D --> F
    E --> F
    F --> G[17 intentional specimens]
    F --> H[8 invalid-param skeletons]
    I[Current desktop matrix: 11 surfaces] --> J[Serious and critical gate]
    K[Current mobile matrix: same 11] --> J
    L[System specimen routes] --> M[Render-only policy]
    F -. historical only .-> N[Current posture]
    J --> N
    M --> N
```

## Proven observations

### Historical remediation trail

- The repair record documents a descent from 402 customer contrast nodes to 25
  through repeated scan, node-level foreground/background tracing, component
  fixes, shared-token changes, and cross-surface regression checks.
- Data-driven category and domain colors moved through `readableInk` where a
  literal six-digit hex was used as text on the cream surface. The helper
  preserves hue while darkening and intentionally leaves CSS variables,
  gradients, and rgba inputs unchanged.
- Text usages that could not safely reuse brighter fill/icon colors gained
  semantic variants, including `--l-accent-2-text`. The current cream token is
  `#8f4a1e`; the original accent remains distinct at `#c97247`.
- The cream warning token remains at the repaired `#6f5220`, and cream muted
  text remains `#574d3f`. The stylesheet contract maps the TypeScript token
  variants back to the CSS custom properties so later theme drift is testable.

### Corrections preserved from the dated investigation

- The apparent `#637b4f` token transformation was a stale probe, not a runtime
  color-transform layer. The later trace established that the named tokens
  resolved to their CSS definitions.
- The final plan-review diagnosis also superseded the earlier opacity theory.
  Actual axe nodes showed `--l-warn` at full opacity on warmer card backgrounds;
  darkening the cream warning token, rather than removing animation, closed the
  measured near-misses.
- The final historical note therefore classified the remaining 25 nodes as 17
  intentional demonstrations and eight invalid-parameter skeletons, with no
  remaining real-content defect in that dated manifest.

### Current durable contract

- The canonical desktop and mobile signoff specs each cover Home, Library,
  Search, notifications, Profile, and the Tara, Veritas, Nyx, Arete, Nisaba, and
  Metis domain entries. They run the WCAG 2.1 A/AA rule set and fail serious or
  critical findings.
- `lilith-public-routes.spec.ts` keeps the system galleries public and
  renderable while documenting why their contrast scan is skipped: the pages
  display palette, ratio, faded-preview, and edge-state specimens, including
  deliberately sub-AA examples.
- This current matrix is portable repository evidence. The original parallel
  `/tmp/walk` runner and JSONL report are historical provenance only.

## Boundaries and gaps

- **The 402-to-25 sequence is historical.** It belongs to the 2026-05 route
  manifest and build. This reconciliation did not rerun that temporary
  all-customer scanner against today's tree.
- **A source token value is not rendered conformance.** Backgrounds, opacity,
  font size/weight, state, animation, blending, nested themes, and user content
  determine the actual axe result.
- **`readableInk` has a narrow contract.** It handles six-digit hex inputs for
  cream-surface text. CSS variables and non-hex colors pass through unchanged,
  so callers must choose a semantic text token for those cases.
- **Specimen exclusions are scoped, not global waivers.** The current policy
  skips contrast on named diagnostic galleries because low contrast is the
  demonstrated subject. The same token pairing on a task surface remains a
  defect.
- **Invalid-parameter skeletons are not valid dynamic-route evidence.** Their
  faded states explained dated findings but do not certify real ids, empty
  states, error copy, or every current dynamic route.
- **The current release gate is representative.** Eleven desktop/mobile surfaces
  fail serious/critical findings; moderate/minor findings and the rest of the
  customer route/state inventory need separate coverage.
- **Automated contrast is not full accessibility.** Forced colors, zoom/reflow,
  user theme overrides, display calibration, cognition, and assistive-
  technology task completion remain outside this record.

## Re-run evidence

The current portable browser evidence can be run serially with:

```bash
PW_BROWSER_CHANNEL=chrome pnpm exec playwright test \
  -c apps/oshun/web/playwright.config.ts \
  apps/oshun/web/e2e/wcag-aa-signoff-v1-p2-3510.spec.ts \
  apps/oshun/web/e2e/wcag-aa-signoff-v1-p2-3511.spec.ts \
  apps/oshun/web/e2e/lilith-public-routes.spec.ts \
  --workers=1
```

That command verifies the maintained representative matrix and specimen render
policy. It does not recreate the historical 181-route contrast sweep or its
25-node floor.

## Source trail

- [Desktop customer accessibility matrix](../../apps/oshun/web/e2e/wcag-aa-signoff-v1-p2-3510.spec.ts)
- [Mobile customer accessibility matrix](../../apps/oshun/web/e2e/wcag-aa-signoff-v1-p2-3511.spec.ts)
- [Public and system-specimen policy](../../apps/oshun/web/e2e/lilith-public-routes.spec.ts)
- [Lilith theme tokens](../../apps/oshun/web/src/design-system/lilith/lilith.css)
- [Stylesheet/token contract](../../apps/oshun/web/src/design-system/__tests__/lilith-css-contract.test.ts)
- [Cream-surface data-color helper](../../apps/oshun/web/src/lib/a11y/readable-ink.ts)
- [Current key-route accessibility result](./at-pass-2026-05-29.md)

## Cross-references

- [System contrast specimen view](../customer/13-system/system-verify.md)
- [System overview](../customer/13-system/system.md)
- [Customer route coverage matrix](../matrix/coverage.md)
- [Studio and Operator accessibility result](./at-pass-studio-operator-2026-05-29.md)
- [Walkthrough result registry](./README.md)

## Open questions

- What generated route/state inventory should replace the dated 181-route
  manifest for a safe, repeatable customer contrast sweep?
- Should current CI retain serious/critical as the release threshold while a
  scheduled job records every axe severity and node-level trend?
- How will diagnostic specimen exclusions be identified semantically so a
  route-name allowlist cannot hide ordinary product content?
- Which tests should pin contrast for semantic text tokens across cream,
  cream-high-contrast, dusk, warmer cards, disabled states, and motion frames?
- Where should versioned JSON axe artifacts live so future claims can be
  compared to this repair history rather than reconstructed from prose?
