Follow-up to #384. That PR moved every neutral colour behind a token — five surface levels, hairlines, control edges, a seven-step text ramp — and the migration is complete: one deliberate literal remains in src (ConnectionModal.tsx:829, a spinner inside a solid blue button). Accents were left out of scope, so they still carry the value that was tuned for a near-black ground.
What that costs in light
Measured in Chrome against a production build, resolving lab()/oklab() through a canvas so the numbers are the ones actually painted:
| where |
classes |
ratio on its own ground |
agent rail, active mode and workflow pills (AgentRail.tsx:1028, :1056) |
bg-blue-500/15 text-blue-300 |
1.46 : 1 |
agent rail Start / action buttons (:1098, :1222, :1305) |
text-blue-300 |
1.46 – 2.4 : 1 |
agent rail warnings (:457, :498, :1211, :1445) |
text-amber-300 |
~2.0 : 1 |
results tab strip, active (BottomPanel.tsx:204) |
text-blue-400 |
2.26 : 1 |
query pill (QueryToolbar.tsx:60-61) |
text-blue-400 |
2.38 : 1 |
| Explain affordance |
amber-500 on #fafafa |
2.05 : 1 |
bg-blue-500/15 over #0a0a0a lands near #1a2233, and blue-300 over that is comfortable. The same tint over white lands near #dbe8fb, and blue-300 over that is 1.46:1 — a chip you can see and a word you cannot read.
Calibration, so this is not read as a regression
I ran the same sweep in both themes over the whole studio surface. Light returns 33 text nodes below WCAG AA; dark returns 57. Low text contrast is this app's existing character rather than something the light theme introduced, and the bottom of the neutral ramp is symmetric by design — --studio-fg-subtle is #a1a1aa in light and #52525b in dark, both around 2.5:1, documented as the step for "decoration and hints".
So this issue is not "light mode is inaccessible". It is narrower: accent-on-accent-tint is the one failure class that light has and dark does not, because the accent values were selected against one ground and are now being asked to serve two.
Note this is separate from the chart series palette, which #384 did validate in both modes and which explicitly forbids using series colours as text.
Direction
The token layer already has the right shape; accents just need to join it. Something like an --studio-accent / --studio-accent-quiet pair selected per mode (blue-300 in dark, roughly blue-700 in light, with the tint adjusted to match), plus the amber equivalent for the warning slot, would let text-accent replace the literals the same way text-fg-muted replaced text-zinc-500.
Worth resisting the shortcut of sprinkling dark: variants at each call site — that is the state the neutral ramp was just rescued from, and it puts the decision back in 40 files.
Acceptance
cc @omerfarukbolat — context is freshest with you, but this is genuinely optional follow-up work, not a correction to what you shipped.
Follow-up to #384. That PR moved every neutral colour behind a token — five surface levels, hairlines, control edges, a seven-step text ramp — and the migration is complete: one deliberate literal remains in
src(ConnectionModal.tsx:829, a spinner inside a solid blue button). Accents were left out of scope, so they still carry the value that was tuned for a near-black ground.What that costs in light
Measured in Chrome against a production build, resolving
lab()/oklab()through a canvas so the numbers are the ones actually painted:AgentRail.tsx:1028,:1056)bg-blue-500/15 text-blue-300:1098,:1222,:1305)text-blue-300:457,:498,:1211,:1445)text-amber-300BottomPanel.tsx:204)text-blue-400QueryToolbar.tsx:60-61)text-blue-400#fafafabg-blue-500/15over#0a0a0alands near#1a2233, and blue-300 over that is comfortable. The same tint over white lands near#dbe8fb, and blue-300 over that is 1.46:1 — a chip you can see and a word you cannot read.Calibration, so this is not read as a regression
I ran the same sweep in both themes over the whole studio surface. Light returns 33 text nodes below WCAG AA; dark returns 57. Low text contrast is this app's existing character rather than something the light theme introduced, and the bottom of the neutral ramp is symmetric by design —
--studio-fg-subtleis#a1a1aain light and#52525bin dark, both around 2.5:1, documented as the step for "decoration and hints".So this issue is not "light mode is inaccessible". It is narrower: accent-on-accent-tint is the one failure class that light has and dark does not, because the accent values were selected against one ground and are now being asked to serve two.
Note this is separate from the chart series palette, which #384 did validate in both modes and which explicitly forbids using series colours as text.
Direction
The token layer already has the right shape; accents just need to join it. Something like an
--studio-accent/--studio-accent-quietpair selected per mode (blue-300 in dark, roughly blue-700 in light, with the tint adjusted to match), plus the amber equivalent for the warning slot, would lettext-accentreplace the literals the same waytext-fg-mutedreplacedtext-zinc-500.Worth resisting the shortcut of sprinkling
dark:variants at each call site — that is the state the neutral ramp was just rescued from, and it puts the decision back in 40 files.Acceptance
@libredb/studio/styles.cssgets them too.cc @omerfarukbolat — context is freshest with you, but this is genuinely optional follow-up work, not a correction to what you shipped.