Repository navigation
UI Consistency: 3 issues found
The switch from a root filter to semantic token mixing resolves the earlier chrome-wide filter concern, but the new token math and its ownership introduce three issues.
apps/web/src/index.css(L163-L172, L236-L240): dark mode's--border/--input/--sidebar-borderare translucent, so mixing them with opaque--background/--sidebarand opaque black/white changes alpha rather than contrast. At 70% a border becomes ~34% opaque near-black (a more visible dark hairline on cards, popovers and glass); at 135% a 6% white border becomes ~39%, anddark:bg-input/32jumps from ~2.6% to ~13% fill.apps/web/src/index.css(L205-L209): the mix lives only in the@theme inlinebridge, so raw-token consumers in the same stylesheet keep default contrast —.chat-markdownheadings/h6/blockquote and table borders,--sidebar-icon-color(L93), the--toolbar-*tokens, andcontextMenuFallback.tsinline styles. A single chat message will shift its body text while its headings and rules stay put.apps/web/src/appearanceContrast.ts(L6):data-appearance-contrastis toggled and asserted in tests but has no CSS or TS consumer — dead DOM state that reads like a styling hook.
Three inline comments were posted. The slider duplication in SettingsPanels.tsx was already flagged in a prior run and is not repeated.
Details
Note
Your check run agent prompt is: .macroscope/check-run-agents/ui-consistency.md
More information about how Check Run Agents work can be found in our Help Center.
Methodology:
- Confirmed the previously flagged
filteron:rootis gone and replaced withcolor-mixon@theme inlinecolor tokens; verified@theme inlineinlines values sovar(--appearance-contrast-*),var(--background)andvar(--sidebar)resolve at the consuming element (correct for the[data-app-sidebar]andhtml[data-theme-id]scoped palettes). - Verified
.darkis only ever toggled ondocument.documentElement(hooks/useTheme.tsL314,themePalette.tsL1847), so--appearance-contrast-targetunder@variant dark(:root:is(.dark, .dark *)) always matches the element where the tokens are consumed. No scoped-subtree inversion risk. - Read the dark palette definitions (
index.cssL1517-L1518, L1569-L1570) to compute the alpha behaviour of the nested mix for translucent--border/--input, and cross-checked consumers such asborder-border/60anddark:bg-input/32incomponents/ui/button.tsx. - Grepped repo-wide for
appearance-contrast: the only references are the new module, its test, the CSS variables and the settings control; nothing reads thedata-appearance-contrastattribute. - Grepped for raw
var(--foreground|border|muted-foreground|input|sidebar-*)consumers to establish which surfaces bypass the new contrast layer (.chat-markdownblock L2040-L2291,--sidebar-icon-colorL93,--toolbar-*L1433-L1436,contextMenuFallback.ts). - Confirmed the settings row,
ContrastAppearanceSync, and the contracts schema follow the existing glass-opacity/font-sync patterns; no new accessibility or interaction regressions found in the control itself. The slider duplication was already reported on this PR.
🔍 Agent activity — 13 tool calls
💭 The PR moved from using a filter on :root to color-mix on semantic tokens, so that concern is resolved. The slider duplication issue in SettingsPanels.tsx is still present though, so I shouldn't flag it again since it was already noted in a prior review pass—just focus on what's new. Now I'm examining the nested color-mix expressions for correctness, checking whether these tokens live in a
@themeversus@theme inlineblock since that affects how Tailwind resolves them at build time. The critical issue is that--color-*tokens get emitted at:root, but if the dark mode variant overrides these custom properties elsewhere, the theme-level tokens may not pick up that override correctly. I'm reasoning through how CSS custom property resolution works here:--color-foregrounddeclared at:rootresolves itsvar()references based on where that declaration lives, so a.darkclass on the same root element would apply, but a scoped.darkclass on a subtree wouldn't affect the root-level resolution -- unless@theme inlineis being used, which inlines resolution to the consuming element instead, making scoped theming work correctly. I need to verify which of these two behaviors applies to this specific setup. I'm also questioning whether thedata-appearance-contrastattribute set byapplyAppearanceContrastis actually consumed anywhere in the CSS, since the test checks for it but I haven't confirmed any selector relies on it -- that would make it dead code if unused. Separately, I'm noting that contrast adjustments were applied to foreground, muted-foreground, border, input, placeholder, and some sidebar/icon tokens, but not to card-foreground, popover-foreground, or accent-foreground, which could create inconsistent contrast behavior on cards and popovers -- though this might be an intentional semantic choice rather than an oversight. I want to open index.css to confirm these details.
1. git_tools — @theme
2. git_tools — appearance-contrast
💭 The data-appearance-contrast attribute seems to have no CSS consumer, just an attribute tests assert against — a minor dead-attribute finding, low severity though. I want to check index.css lines 70-260 to see the structure better.
3. browse_code — apps/web/src/index.css
💭 I'm tracing how the contrast target variable resolves — since inline theming pushes color-mix resolution to the consuming element, it should inherit correctly from whichever ancestor sets the dark variant, whether that's :root or a scoped subtree.
4. git_tools — custom-variant
5. git_tools — --secondary-label|--icon-muted|--placeholder:
💭 I'm checking whether theme palettes are applied via classes on the html element or scoped to subtrees, so I want to look at the lines around 1400-1500 to see how theme colors like
--backgroundare defined.
6. browse_code — apps/web/src/index.css
💭 I'm working through how the translucent white border color-mixes with the opaque background — mixing a 6% alpha white border with a solid background at less than 100% contrast base actually increases the border's apparent opacity and pulls it toward the background's hue, which seems counter to the original intent. At base=100% though, the boost term drops out entirely and the inner mix just collapses back to the original border color unchanged. But when contrast is reduced or the target is white for boosting, the alpha shifts toward opaque — meaning over non-background surfaces like cards or popovers, the translucent border effectively paints a solid background-colored line instead of softening, which is a visible regression at extreme contrast settings. Now I realize boosting contrast by 35% turns a 6% white border into roughly 39% white — a 6.5x jump in alpha, way more drastic than a subtle contrast boost, and the same happens with the input token going from 8% to 40%. This nonlinear, disproportionate scaling on translucent tokens is a real concern, especially on glass surfaces, though solid tokens like muted remain unaffected. I'm also noting that mixing foreground toward background works as an approximation even though many surfaces actually use card or popover backgrounds instead, and now checking whether the placeholder color token has the same issue. I also spot an inconsistency: the sidebar icon color at :root still references the raw
--sidebar-muted-foregroundvariable instead of the new contrast-adjusted token, meaning sidebar icons won't shift with the contrast setting while sidebar text will — even though the feature claims to affect colors and borders across the whole interface. This creates a tonal mismatch between icons and text that seems like a gap introduced by this PR, since the icon token bypasses the new contrast logic entirely. Given that, I suspect other tokens like toolbar, terminal, and code surface colors similarly reference raw foreground/border variables directly rather than going through the contrast-adjusted layer, so those surfaces would also miss out on the contrast setting even though Tailwind utilities like border-border and text-foreground pick it up. I want to search for any places in the codebase using the raw variables directly in arbitrary Tailwind values to confirm how widespread this bypass is.
7. git_tools — var(--(foreground|border|muted-foreground|input|sidebar-border|sidebar-foreground))
💭 I notice there are many raw-variable consumers beyond Tailwind utilities—markdown CSS, the context menu's imperative DOM styling, glass effects, terminal styling—that won't automatically pick up the new contrast setting since it derives from semantic tokens. This is inherent partial coverage rather than a clear violation, though the markdown CSS consumer stands out as particularly worth flagging. I'm narrowing toward two higher-signal findings: the sidebar icon color still derives from the raw muted-foreground variable while the sidebar label color is now contrast-adjusted, so at high contrast icons would look washed out relative to text—a real, fixable inconsistency the patch introduces even though the specific line wasn't touched. I'm also starting to consider a second finding related to translucent dark-mode elements. Now I'm tracing through the alpha math for the border/input tokens in dark mode. Mixing the near-black translucent border color with an opaque contrast target at boosted percentages pushes the alpha from around 6% up to roughly 34-39%, meaning borders drawn over cards or popovers would render as a visible dark line instead of a subtle translucent one—this is the strongest concrete regression I've found, since it changes the actual visual semantics of the alpha-based tokens rather than just being a minor drift. I'm now thinking through the fix: rather than mixing translucent tokens with an opaque surface color, the token should preserve its alpha character, perhaps by scaling opacity directly through something like an alpha-adjustment function, or mixing toward transparent instead of an opaque contrast target. I also notice a
data-appearance-contrastattribute gets set and tested but nothing in the CSS or TypeScript actually reads it — that's dead code worth flagging with a brief inline comment. Checking whether the contrast variable applied at the document root properly cascades into the theme utilities, and it does inherit correctly, so that part checks out. Now I'm looking at whether the@theme inlineblock's references to the contrast and background variables are consistent. I want to double-check how Tailwind's opacity modifiers interact with these inline theme values — since@theme inlineresolves opacity modifiers using color-mix against the resolved value, nested color-mix values like these should still work fine, and other variable references in the theme also look consistent. The other flagged spots — like the slider duplication in SettingsPanels and the border/opacity combinations — I've already noted, so I'll move on and check how the glass opacity slider handles its labeling for consistency with the other sliders.
8. browse_code — apps/web/src/components/settings/SettingsPanels.tsx
💭 I'm checking whether dark theme and custom theme palettes also use these same low-opacity border and input values, confirming the dark mode alpha percentages match at 6% and 8%, and noting that the sidebar border variable inherits from the general border variable.
9. browse_code — apps/web/src/index.css
💭 I've confirmed the alpha border values differ in dark mode for the sidebar scope. I'm also verifying that scoped CSS variables like
--backgroundand--foregroundset within[data-app-sidebar]correctly cascade into the@theme inlinecolor mixing, since these resolve at the consuming element rather than globally. But I realize there's a subtler issue:--appearance-contrast-targetis defined at:rootunder the dark variant, so it only actually applies when.darksits on the root element. If a subtree — like a theme preview card — carries its own.darkclass while the rest of the app stays light, that scoped selector won't match, and the preview would end up using the light-mode contrast target instead. Since other tokens like--app-scrollbar-thumbshare this same pattern and are pre-existing, this isn't new, but--appearance-contrast-targetnow feeds every foreground/border token, so the effect could actually invert contrast in a dark-scoped preview inside a light app. I need to check whether ThemeLibrary or any other component actually applies a.darkclass to a subtree like that.
10. git_tools — "dark"|'dark'|classList.*dark|\bdark\b.*className
💭 I confirm the dark class is only applied to documentElement, so that subtree concern doesn't apply. My key finding is that mixing translucent border/input tokens with opaque background/sidebar colors in dark mode breaks alpha semantics — I'll flag this around index.css line 168. Working through the contrast math: at contrast=70, the border ends up 34% opaque near-black instead of softer, rendering a stronger, wrong-toned outline on lighter surfaces. At contrast=135, the border alpha jumps to ~39% white (6.5x default) and the input token goes from 2.6% to 12.8% effective opacity, causing subtle fills to become drastically more visible. The smallest fix seems to be scaling alpha directly for translucent chrome tokens rather than mixing them against an opaque surface — keeping the base mix against transparent instead. Trying to work out a clean CSS expression for this: mixing the border/input toward transparent at varying percentages controls alpha scaling, but combining two translucent colors via color-mix still just averages alpha rather than truly reducing or boosting it multiplicatively, so this approach doesn't cleanly solve the problem. I'm weighing whether the
--alpha()approach actually fixes the alpha-scaling issue, but it doesn't cleanly multiply per-theme alpha values. I think the cleanest note is just to flag that the current approach breaks for translucent tokens and needs one of these alternate paths instead of trying to force a perfect formula. Now I'm turning to the sidebar icon color issue:--sidebar-icon-colorpulls straight from raw sidebar tokens rather than the contrast-aware ones, so icons don't track the contrast setting the way labels do. Switching it to reference the themed muted-foreground variable seems right, but I need to double check how@theme inlinevariables get emitted since that affects whether this reference will actually resolve at:root. Sidebar icons staying static while labels shift contrast could read as a legit inconsistency, but flagging just that one raw-var consumer feels arbitrary given how many others exist (markdown prose, terminal, toolbar). I think the stronger approach is a single consolidated finding: the contrast layer only applies to the@theme inlineTailwind tokens, leaving all the rawvar(--foreground)/var(--border)consumers elsewhere in the file unaffected. That means chat markdown, code blocks, toolbar chrome, and native context menus keep default contrast while the rest of the UI adapts — a genuine gap against the stated "colors and borders across the interface" scope. The deeper design issue is that the contrast mix is applied at the Tailwind bridge instead of at the source semantic variables in:root, so only Tailwind utility consumers benefit; fixing this at the true ownership location would need a two-tier raw-to-adjusted token structure since the foreground variable can't reference itself directly. I feel good about this as one high-value consolidated finding. Now I'm deciding where to anchor comments in the diff: one near the alpha/translucent mix around lines 163-172, and another near the partial-coverage/ownership issue at the--color-foregrounddefinition around lines 205-209, confirming both fall on added lines so inline comments will attach correctly. I also want to flag thedata-appearance-contrastattribute as dead API since I confirmed via a repo-wide grep that nothing outside the web src consumes it, including checking whether other appearance-sync components mount similarly inside the providers in__root.tsx.
11. browse_code — apps/web/src/routes/__root.tsx
💭 This mirrors GlassAppearanceSync's pattern — ContrastAppearanceSync only mounts in the authenticated branch, so loading/auth-gate states render without it, consistent with how glass and fonts behave. I'm now checking whether contrast gets applied during boot to prevent a flash, similar to glass. Custom themes generate opaque border colors while the default dark theme keeps translucent borders, so the alpha concern is mostly limited to that default path, which is acceptable. I'm also verifying that glass surfaces reference the border color variable correctly, and double-checking that color-mix() with a percentage supplied via a custom property resolves properly at computed-value time since the default is set at the root level. Now I'm working through Tailwind's
@theme inlinemechanics — how opacity modifiers wrap values in their own color-mix, meaning our two-level mix gets nested inside a third layer, which should still work fine. I'm also confirming that percentage splits in nested color-mix calls behave as expected, like a 50/50 contrast split producing washed-out text, and that black/white keywords mix correctly within the oklab color space. I'm settling on which findings to raise: the translucent alpha semantics breaking in dark mode for the border/input/sidebar-border tokens, and the fact that the contrast data attribute has no actual consumer wired up anywhere. I'm also weighing whether to flag the broader issue of partial token coverage across raw-var consumers like markdown prose, the toolbar, scrollbar, and context menu — it's a legitimate concern tied to the rule that contrast settings must derive from semantic tokens, even though it risks looking like I'm asking for a large rework. I found it — the markdown prose CSS sets color directly on--foregroundaround line 2055, so chat message text stays at default contrast while the rest of the interface shifts. That confirms a real, concrete inconsistency worth naming precisely, so I want to check the surrounding lines to describe it accurately.
12. browse_code — apps/web/src/index.css
💭 I'm confirming that markdown headings, blockquotes, and table borders reference raw color variables directly, so they ignore the contrast setting even while surrounding UI adapts. This creates inconsistency within a single message—body text inherits adjusted foreground colors from its Tailwind parent, but headings don't get that same treatment. Now I'm drafting three review comments to post on the diff. The first flags that dark mode's border and input tokens are translucent rather than opaque, so mixing them with a surface color at reduced contrast actually shifts their alpha value instead of their perceived contrast, producing unexpected visual results like a darker, more visible line instead of a subtler one. The second comment notes that this contrast-mixing logic only lives in the theme bridge, so raw token consumers elsewhere in the same file — like chat markdown headings, sidebar icon colors, and toolbar tokens — never pick up the contrast adjustment and stay at default values. I'm considering suggesting computing adjusted values once as shared custom properties near the palette so both the theme bridge and raw consumers can read them, since
@theme inlinevars can't be referenced from plain CSS. I'm also noting thatdata-appearance-contrastappears to be dead DOM state since nothing reads it besides the test, and thinking about whether to drop it or use it to scope when the color-mix actually runs. Fixing that third issue would require editing the test too, so I can't just offer an inline suggestion — I'll present it as a plain observation instead. I double-checked by grepping the repo for "appearance-contrast" and confirmed there's no CSS consumer, and verified thatdark:bg-input/32does exist in button.tsx. Since there are real findings here, I should mark this review as failure and post it now.
13. modify_pr — Contrast is now derived from semantic tokens instead of a root filter, which resolves the earlier concern about glass backdrops, previews, and view-transition snapshots. Three issues remain in the new token math and its ownership.
Agent Credits: 121 credits