T-APNC-design-language-agentpants-palette-burndown
State: open/ready · Impact: low · Complexity: medium
apps/agentpants carries the ring’s largest literal debt: raw Tailwind
palette classes and dark: variants (bun scripts/guard-raw-palette.ts --counts reports the current figure). Its adoption PR extended the layer
but deliberately left the debt. Burn it down to --d-* tokens so theming
actually reaches the app.
| Location | Role today |
|---|---|
apps/agentpants/src-nuxt/app/ | Raw palette classes and dark: variants throughout components and pages; the layer’s tokens available but unused there. |
Proposed
Section titled “Proposed”Literals replaced by token-backed styling, directory by directory, with visual parity at each step. The T-J04U-design-language-no-raw-palette-check baseline for this app ratchets toward zero.
Approach
Section titled “Approach”- Rank directories by literal count; sweep one per commit.
- Map each literal to its token (
--d-*or bridge-provided--ui-*semantics); drop the paireddark:variant — tokens carry mode. - Screenshot parity per sweep (light + dark).
- Lower the guard baseline as counts fall.
| Area | Note |
|---|---|
apps/agentpants/src-nuxt/app/ | literal → token sweeps |
Acceptance criteria
Section titled “Acceptance criteria”- AC-1: Raw-palette count for the app reaches 0 (guard baseline 0).
- AC-2: Visual parity screenshot pairs accompany each sweep PR.
- AC-3: Theme switching (platinum ↔ others, light/dark) restyles the swept surfaces.
Out of scope
Section titled “Out of scope”- Component restructuring; behavior changes.
Dependencies
Section titled “Dependencies”- The agentpants adoption PR merges first; T-J04U-design-language-no-raw-palette-check provides the ratchet.
Discovery context
Section titled “Discovery context”docs/planning/notes/N-R926-design-language-plan.mdPhase 3 (“burn down opportunistically, not big-bang”).
Findings from the first capture
Section titled “Findings from the first capture”The app is now capturable in a plain browser, and
apps/agentpants/docs/screenshots/ holds eight light/dark route pairs with
real data in them. These are the first images of the app in dark mode with
content, so they are the first direct evidence of what the raw palette
classes actually do. Three findings, each with a citation.
- The accent never follows the theme.
bg-blue-500andbg-blue-600occur 87 times between them. They render as the same hard blue in light and in dark, and they ignore the Platinum II default entirely. Visible on “New Skill”, “New Workflow”, “Publish”, the Appearance segmented control, and every checked checkbox. This is the most visible single class of debt and the one a reader notices first. The evidence that it is not theme-aware at all is that the accent is pixel-identical between the two members of every pair: compareskills-default-light.pngagainstskills-default-dark.pngfor the “New Skill” button,workflows-default-*.pngfor “New Workflow”, andsettings-default-*.pngfor the Appearance segmented control and the checked checkboxes. A theme-aware accent would shift between the two; these do not move. - Native checkboxes are effectively unstyled in dark mode.
apps/agentpants/src-nuxt/app/pages/settings/index.vue:373gives themrounded border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-900 text-blue-600, but a native<input type="checkbox">ignoresbg-*on its control surface. The classes look like dark-mode support and provide none. Unchecked boxes render as pale squares on a near-black page. There are five such inputs in that file. The fix isaccent-color, or the layer’s own checkbox component. - Most greys are paired, so they survive the mode switch.
text-gray-800/dark:text-gray-200anddark:bg-gray-900appear in matched numbers. Unpaired mid-tones liketext-gray-500(399) andborder-gray-500(127) read acceptably in both modes. So the grey debt is a tokenization cost, not a visible dark-mode defect — unlike the two findings above.
Literal counts by file, highest first, as a suggested sweep order:
| File | Literals |
|---|---|
app/pages/settings/index.vue | 571 |
app/pages/packs/[id]/export.vue | 157 |
app/components/skills/SkillDetail.vue | 95 |
app/pages/model-profiles/index.vue | 93 |
app/components/destinations/TargetDetail.vue | 91 |
app/components/model-profiles/ModelProfileDetail.vue | 90 |
app/pages/packs/index.vue | 74 |
app/pages/hooks/index.vue | 71 |
Settings is both the largest offender and the screen where the debt is most visible, so it is the natural first sweep.
One defect the capture found that is NOT palette debt: the list tables squeeze the Name column down to a few pixels and truncate every row to one or two characters, while the rest of the frame sits empty. Visible in the workflows and skills pairs. It now has its own entry with measurements — B-K3TQ-agentpants-list-name-column-starved-by-fixed-columns — and is out of scope here.
A second non-palette defect surfaced by the same capture:
B-R7VM-agentpants-hooks-packs-model-profiles-render-below-the-fold. The
/hooks, /packs and /model-profiles pages render their content below the
fold because they never adopted the shell’s teleport pattern. Those three
routes are therefore absent from the screenshot set, which is why the sweep
order table above cites literal counts for pages/model-profiles/index.vue,
pages/packs/index.vue and pages/hooks/index.vue that no screenshot yet
shows.