Repository navigation
UI Consistency: 2 issues found
Two role reads escaped the contrast audit, leaving adjusted and unadjusted colors side by side.
apps/web/src/index.css(L1826) — the t3-chat light override for.chat-markdown :not(pre) > codestill reads rawvar(--message-foreground), so inline code text stays at stock contrast while its own border (--contrast-border) and the surrounding markdown text (--contrast-foreground) follow the setting. Suggestedvar(--contrast-message-foreground), which is already mixed against--message-surface.apps/web/src/index.css(L1727) —#theme-inspector-hover [data-theme-inspector-hover-label]now derives its border from--contrast-border(changed line L1723) but keepscolor: var(--popover-foreground), painting an adjusted border around unadjusted text. Suggestedvar(--contrast-popover-foreground).
Both were posted as inline review comments with suggested fixes.
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.
What was verified
- No document-level filter: the
filterapproach from the first revision is gone; contrast is derived entirely from semantic tokens. - Token ownership:
--contrast-*are ordinary custom properties declared at:root, [data-app-sidebar](index.css L1874-1963) and consumed by the@theme inlinebridge, global CSS, and imperative style strings alike. The sidebar redeclaration is required and correct, sincehtml[data-theme-id] [data-app-sidebar](L1836) and[data-app-sidebar](L1500) own a local semantic palette; substitution happens on the element carrying the declaration, so descendants inherit the right adjusted values. - Alpha and surface ownership:
--contrast-border/--contrast-input/--contrast-sidebar-bordersoften towardtransparent(preserving translucent hairlines in dark themes,--border: --alpha(var(--color-white) / 6%),--input: … / 8%,rgb(255 255 255 / 18%)under the sidebar) and strengthen with a modest ≤12.5% semantic-foreground mix. Card, popover, accent, secondary, message, and sidebar foregrounds are each mixed against their own surface. - Identity behavior at defaults: at
appearanceContrast: 100every mix is an identity (base: 100%,boost: 0%), so stock themes are unchanged. - Audit coverage: grepped every remaining
var(--foreground|border|input|muted-foreground|card-foreground|popover-foreground|accent-foreground|secondary-foreground|sidebar-*|placeholder|icon-muted|secondary-label|message-foreground)read inapps/web/src(CSS, TS, TSX, Tailwind arbitrary values). Everything user-facing is converted except the two reported lines; remaining reads are token definitions, or--code-*/--terminal-*/--app-theme-*roles, which are intentionally left on their own palettes (code and terminal surfaces own syntax colors). - Theme inspector probes still work:
applyThemeTokenProbesets--app-theme-*ondocumentElement, which propagates through the semantic role into--contrast-*. - Settings wiring parity with the existing
glassOpacitycontrol: schema + patch + decoding default, restore/reset labels and dependency array, search entry, desktop settings fixture, and a root-level sync component matchingGlassAppearanceSync/FontAppearanceSync.
Not re-reported
The duplicated inline range-slider treatment in SettingsPanels.tsx (ratio math, --settings-slider-progress / --settings-slider-fill-offset, output badge, clamping onChange) is unchanged from the earlier revision and was already flagged; no duplicate comment was posted.
🔍 Agent activity — 30 tool calls
💭 I'm tracing how the PR has evolved across commits, noting the filter approach was dropped in favor of ordinary custom properties, with foreground colors, borders, and the contrast attribute all adjusted. Now I want to check this latest version for real issues, starting with whether any leftover references to the old variable naming still exist in the code. I'm also thinking through the cascade behavior of the new
--contrast-*properties — since they're computed at the root using values like--foreground, they should inherit correctly through normal custom property inheritance, but I'm wondering whether nested scopes that redefine--foregroundlocally (like message surfaces) would fail to recompute the contrast variables since those inherit the already-computed root value rather than recalculating. Since ordering of custom property definitions doesn't affect var() resolution, and both:rootand[data-app-sidebar]have equal specificity but apply to different scopes, this should resolve correctly within the sidebar subtree. I also want to verify where the dark mode override for--appearance-contrast-targetlives, check that--message-surfaceis defined, and confirm the sidebar icon and toolbar color variables are properly updated. Now I'm scanning index.css and the TS/TSX files for lingering direct references tovar(--foreground),var(--border), orvar(--muted-foreground)that might have been missed and could cause inconsistent contrast. I want to actually open the files to check. I'm also verifying the border-boost math in appearanceContrast.ts—boost divided by four should give 8.75% for a boost of 135, which matches the test expectation, and the softening logic for values below 100% correctly blends the border color toward transparent using color-mix. The foreground softening also checks out, blending toward the background color via oklab mixing. For boosting above 100%, the base stays at full foreground opacity before mixing with the target color, and I traced through the alpha math for the border boost case—mixing translucent border with opaque foreground at 8.75% raises the alpha as intended, giving the "stronger border" effect the spec calls for. Now I want to check whether the contrast block sits properly inside the layer, so let me pull up the relevant section of the CSS file.
1. browse_code — apps/web/src/index.css
2. browse_code — apps/web/src/index.css
💭 I'm tracing where the semantic tokens like
--foregroundand--borderget defined -- likely within theme-specific selectors such ashtml[data-theme-id]and[data-app-sidebar], and checking how the:rootblock computes contrast values from these variables. I still need to check if anything overrides--card,--popover, or--message-foregrounddeeper in the component tree rather than at the root, since that would break the contrast calculation. I'll grep for these variable names across index.css and component files to see if any local scopes redefine them.
3. git_tools — --message-foreground|--message-surface
4. git_tools — ^\s*--(foreground|border|input|card|popover|accent|secondary|muted-foreground|placeholder|icon-muted|secondary-label):
💭 I'm checking how the sidebar element locally redefines its own color variables, and confirming the new root block re-declares the contrast variables so the sidebar recalculates properly, but I need to verify the specificity of these overrides against the sidebar selector. Now I'm scanning index.css for remaining direct uses of the foreground, border, muted-foreground, card-foreground, popover-foreground, accent-foreground, sidebar-foreground, input, and placeholder variables outside the token definition blocks to make sure none were missed.
5. git_tools — var(--(foreground|border|input|muted-foreground|card-foreground|popover-foreground|accent-foreground|secondary-foreground|sidebar-foreground|sidebar-muted-foreground|sidebar-border|placeholder|icon-muted|secondary-label|message-foreground))
💭 I still have two more consumer reads to check: one near line 1727 referencing popover-foreground color, likely in the same block as the recently updated ring border, and another at line 1826 using message-foreground inside a theme-scoped block. Let me view lines 1700-1835 to see the surrounding context.
6. browse_code — apps/web/src/index.css
💭 Line 1727 is minor dev inspector chrome, but line 1826 catches my attention more — it's a theme-specific inline code color in t3-chat light that would stay unadjusted while other markdown text colors get adjusted, which conflicts with the rule that headings, markdown chrome, menus, and utilities shouldn't split into adjusted versus unadjusted colors. Digging further, I find
--message-foregroundresolves tovar(--app-theme-message-foreground), and since a--contrast-message-foregroundvariable already exists, the fix is trivial — just swap in that contrast variable. Separately,--code-foregroundmapping straight tovar(--foreground)seems intentional since code/terminal surfaces are meant to stay unadjusted for syntax highlighting, so that's fine as-is. Now I want to grep across apps/web/src for remaining literal role reads in TS/TSX files to check whether the audit missed other menus or headings.
7. git_tools — var(--(foreground|border|input|muted-foreground|card-foreground|popover-foreground|accent-foreground|secondary-foreground|sidebar-foreground|sidebar-muted-foreground|sidebar-border|placeholder|icon-muted|secondary-label|message-foreground))
💭 That one's fine since it's in a code preview intentionally. Now I should check other CSS files beyond index.css, and consider whether my grep for
var(--foreground)would also catch instances embedded in Tailwind arbitrary value class strings like color-mix expressions.
8. browse_code — apps/web/src/**/*.css
9. git_tools — contrast-foreground|contrast-border|contrast-input|contrast-muted-foreground
💭 The audit looks solid, so now I'm checking for functional issues—specifically whether the contrast variables declared at root and sidebar selectors are sitting outside Tailwind v4's layer system, which could cause specificity or cascade problems since top-level rules in index.css might not be wrapped in @layer. Actually, tracing through it,
@theme inlinemeans utilities like text-foreground resolve directly to the local contrast variable at the element, so sidebar redeclarations should correctly override. I'm also weighing whether the dark-mode contrast target (boosting toward white) could backfire in edge cases where the sidebar itself is a light surface within a dark theme, though that feels like a speculative edge case rather than a confirmed bug. Now I'm looking more closely at how the sidebar's local redeclaration references the underlying foreground variable to see if there's a subtle mismatch there. That color-mix nesting should work fine at runtime. I want to check whether there are other local palette scopes beyond the sidebar that redefine foreground/card variables, so I'm tracing which selectors the other root theme blocks belong to. I'm also spotting a potential issue with--contrast-card-foreground: it mixes--card-foregroundtoward--card, but I need to check whether--card-foregroundis actually defined in the default light theme's root block. If it's undefined there, referencing it insidecolor-mixcould make the whole declaration invalid at computed-value time, which would be a real bug worth flagging.
10. browse_code — apps/web/src/index.css
💭 I notice the
[data-app-sidebar]block already redefines the foreground, card, muted, border, input, and sidebar variables for the default theme, which the new contrast redeclaration should handle. But I'm now catching a specificity conflict since both:rootand[data-app-sidebar]selectors carry the same specificity weight, which could cause unpredictable override behavior. I'm also tracing whether any dependency cycles exist between the contrast tokens and sidebar-derived variables — so far each contrast token traces back cleanly to foreground/background without looping, though I'm still checking whether--sidebar-icon-color's dependency chain closes safely. I'm now noticing that toolbar foreground was previously just--foreground, but is now contrast-adjusted only for the default theme, while custom themes still use their own unadjusted--app-theme-toolbar-foreground. That creates an inconsistency where themed toolbars won't respond to contrast settings even though the default theme's does, and I'm weighing whether this counts as a role split worth flagging given it falls outside the audited semantic roles. I'm treating the entire app-theme layer, including code, terminal, and toolbar variants, as intentionally out of scope since the instructions call for excluding terminals and previews, and fully adjusting every app-theme role would be a much larger change than intended. Moving on to look for real defects in this pass, I'm flagging two concerns: placeholder, secondary-label, icon-muted, and muted-foreground colors mixed against background (likely minor since these often sit on inputs or popovers), and how the black/white boost target is chosen by the dark variant only at the root level. Now I'm confirming the sidebar's contrast target correctly inherits from root since the dark variant applies as a class or media condition on the html element, and I'm verifying that using color-mix with black or white as valid target colors resolves correctly. At the default contrast level of 100, the mixes are all identity operations, so this is just a performance consideration rather than a correctness bug, though I want to double check one more important color-mix detail. At 100% base contrast, the mix with transparent resolves cleanly to the original value since there's no alpha multiplier applied. But I'm now noticing that border colors computed via mixing in srgb could shift slightly when the source palette uses oklch, since the mix would convert those values into srgb space, potentially altering the resulting color. I'm trying to recall whether@theme inlinestill emits variables into:rootor purely inlines them into utilities — either way, the substituted value should resolve correctly since it's just a variable reference chain. I'm checking whether the theme token probe or inspector reads computed values in a way that would be affected, but that seems unrelated to the actual bug. Given the PR seems to comply with all three stated rules, I'm now looking more closely at the sidebar redeclaration under:root, [data-app-sidebar]for a subtler issue. I'm checking whether the muted foreground roles on[data-app-sidebar]correctly inherit and recompute against the sidebar's own overridden background rather than the root background, since the sidebar redefines--backgroundlocally — that mixing looks intentional but worth double-checking for a subtle bug. I also want to verify the SettingsPanels slider duplication issue from the earlier review round; the diff still shows the same inline third slider that I already flagged at line 997, so I shouldn't repeat that comment. Instead I should look for whether a shared slider primitive now exists elsewhere in SettingsPanels, particularly around the contrast and glass opacity rows.
11. git_tools — settings-slider|--settings-slider-progress
💭 I only find two settings-slider call sites, contrast and glass opacity, not the third one I thought existed—maybe the volume slider lives elsewhere. I'll move on and check the SettingsPanels region around lines 960-1110 to look at the new contrast row for consistency and accessibility issues.
12. browse_code — apps/web/src/components/settings/SettingsPanels.tsx
💭 That duplicated slider was already flagged in a prior comment, so I won't re-post it since the code hasn't changed. Checking the searchableSetting id naming — "setting-appearance-contrast" versus the input's "appearance-contrast" — and it looks consistent with other rows like "setting-glass-opacity", plus there's a matching entry in settingsSearch. I want to double check the ordering of items in SETTINGS_SEARCH_ITEMS matches the panel layout, though that's minor. More importantly, I should look for a real functional regression — the contrast variables are only defined on :root and the sidebar selector, but other components might locally override semantic role variables like --popover or --card via inline styles, so I need to grep the TSX files for local overrides of those role variables.
13. git_tools — "--(foreground|background|card|popover|accent|secondary|border|input|muted-foreground|sidebar|sidebar-foreground|message-surface)"
14. git_tools — [--(foreground|card|popover|accent|border|input|muted-foreground|sidebar-foreground):
💭 No local role overrides found, so I'm now checking whether theme preview components in settings might scope
--app-theme-*variables locally on a container, which could cause preview swatches to show root-computed contrast values instead of their own local ones.
15. git_tools — --app-theme-text|--app-theme-border
💭 I'm tracing where themePalette.ts's mappings get applied—likely via applyThemePalette on the document root—and checking whether preview cards in the theme library set their own local CSS variables instead.
16. browse_code — In apps/web/src, how are the --app-theme-* CSS variables applied? Is there any component (theme preview card, theme library swatch, theme editor) that sets --app-theme-* or semantic role variables (--foreground, --card, --border) on a local DOM element/subtree rather than on document.documentElement? Show the code and target elements.
💭 I'm checking whether the theme inspector probe still works when it sets
--borderon the root with!important—since--contrast-borderreferencesvar(--border), the recomputation should cascade correctly and the probe should still detect the affected tokens.
17. browse_code — apps/web/src/index.css
18. browse_code — apps/web/src/components/settings/themeInspector.ts
💭 I'm considering whether the probe's sentinel color propagates correctly through the oklab color-mix calculation—since contrast values derive from the theme role variables at root, even a color-space conversion should still register as a detectable change between snapshots. Checking the sidebar's foreground/border boosts, those look consistent with the semantic-mix pattern. Now I want to verify whether the glass surface tokens also pull from
--bordervia color-mix, so I need to trace through that section of the stylesheet. I'm also considering whether other Tailwind theme colors reading raw tokens create a mismatch—secondary, accent, and ring stay unadjusted since they're surfaces, which seems correct. But status foreground colors like destructive, error, warning, success, and info also stay unadjusted at higher contrast levels while body text does adjust, which could be an intentional split since those are meant to be theme-independent identity colors. Now I'm tracing how--sidebar-icon-colorgets computed—it's declared at root and references--contrast-sidebar-muted-foreground, but since the sidebar element redeclares that variable, I need to work out whether descendants actually get the sidebar's override or the root's value, since custom property substitution happens at computed-value time per element. Comparing to the pre-PR version, the same root-resolution pattern already existed with--sidebar-muted-foreground, so the sidebar's local override never influenced this variable before either — meaning this isn't a newly introduced bug, just the same unchanged behavior now applied to the renamed contrast variable. Turning to--toolbar-foreground, this also resolves the same way at root level, so that's fine too. Now I want to check something more concrete: whether--contrast-foregroundmixing towardvar(--background)at contrast levels below 100 creates a real problem in the sidebar context, since the sidebar's background color differs from the main surface. I'm checking whethercolor-mix()with the transparent keyword behaves correctly for border softening — since transparent is effectively rgba(0,0,0,0), premultiplied alpha mixing in srgb should just scale down the alpha while preserving hue, which is the intended softening effect. Then I'm working through the math for the contrast-border boost, mixing a low-alpha border color with an opaque foreground color to see what resulting alpha value comes out. I move on to check other Tailwind utilities like ring-border, divide-border, and outline-border, confirming they all correctly reference the same border color variable. I also check the fallback context menu component, verifying that since it's likely appended to the document body, it should still properly inherit the contrast CSS variables from the root. Now I'm tracing how the contrast popover foreground variable derives from the popover variable within the sidebar's variable block. Since neither popover nor popover-foreground seem overridden there, that looks fine, so I shift to reviewing the settings restore and reset logic for correctness across schema and desktop settings, noting the restore hook includes a contrast label and reset entry with the desktop test updated. I want to check other places that list appearance settings for consistency, like sync or serialization logic or a reset function, so I plan to search the codebase for every reference to glassOpacity to see if appearanceContrast is wired up the same way everywhere, since a mismatch between web and desktop settings handling would be a genuine consistency gap worth flagging.
19. git_tools — glassOpacity
20. git_tools — appearanceContrast
💭 Wiring parity looks good, but I notice glass opacity is applied inline via an effect in __root.tsx, while contrast uses a separate ContrastAppearanceSync component and module. Let me check __root.tsx around lines 130-180 to see if the structure is consistent.
21. browse_code — apps/web/src/routes/__root.tsx
💭 I notice contrast is only applied in an effect, meaning there could be a flash of unadjusted contrast on load, similar to fonts. I want to check index.html to see if there's an inline boot script applying appearance settings like fonts or glass opacity before hydration, to see if that same gap exists there too.
22. git_tools — glass-opacity|appearance-font|font-size-interface|appearance-contrast
💭 Nothing else looks like a genuine regression here since the contrast variables inherit properly through the sidebar scope. Let me check the actual diff hunks around lines 316, 349, and 769-829 in index.css to see what changed there. I should compare against the previous commit to isolate exactly what's newly introduced versus carried forward, since any real bug would be in the fresh changes responding to earlier feedback.
23. git_tools — 5c8db7a..4b52a03
💭 The history was force-pushed, so I should look at the PR's commit list to see what changed.
24. github_api_read_only — repos/{owner}/{repo}/pulls/{pull_number}/commits?per_page=100
💭 I want to check the diffs of the last two commits to see what changes were introduced around contrast token ownership and shared chrome roles.
25. git_tools — 0249d3a
26. git_tools — 4b52a03
💭 I want to check the full diff of the last commit to index.css for any newly introduced issue, particularly around the
:root, [data-app-sidebar]block that may have been added in 0249d3a. I should also look at 4b52a03's index.css diff.
27. git_tools — apps/web/src/index.css 0249d3a..4b52a03
💭 I notice the
--contrast-*variables are defined in a plain rule at the root/sidebar scope, outside the layered origin, while@theme inlinesubstitutes values directly into utility classes—so I'm working through whethertext-foregroundactually resolves to referencing--contrast-foregroundgiven how Tailwind v4's inline theme mode handles substitution. Checking thatbg-cardsimilarly gets inlined to reference the card variable directly, matching the existing sidebar override pattern in the repo. I'm also verifying opacity modifiers liketext-foreground/70compile correctly using color-mix, then tracing through the sidebar and toolbar variable declarations to rule out any circular reference between--contrast-foregroundand dependent tokens like--toolbar-foreground. I don't see any actual cycles so far—each variable resolves cleanly to a definition in a different scope. The remaining question is whether the boosted alpha values for--contrast-input/--contrast-borderstay within the "modest" range intended for dark themes, and whether[data-app-sidebar]scoping behaves consistently when portaled elements like dialogs and dropdowns fall back to root-level contrast tokens. Now I want to check the diff around lines 300-360 to see which glass-surface rules changed and whether the dark variant override is light-only, plus look at the new.chat-markdown :not(pre) > codestyling that adds contrast-based color and border. Comparing that against the t3-chat light theme override at line 1825, which sets the code color from an unadjusted message-foreground variable instead of the contrast one — this looks like exactly the kind of split the audit is meant to catch, and since--contrast-message-foregroundalready exists, it's a simple, scoped fix within index.css affecting inline code styling in markdown chrome. I'm also checking whether the code-block coloring changes are intentional, since code surfaces reasonably keep their own palette separate from the contrast border variables. Tracing precedence for the t3-chat theme, the theme-specific light override for inline code wins out over the general contrast-foreground rule, confirming the inconsistency actually surfaces in that theme. The fix is to swap in--contrast-message-foreground, since the inline code chip's background uses--message-surface, and that's exactly the surface the contrast token should be mixed against. I confirm there's no other place referencing the raw--message-foregroundvariable that needs the same treatment. I'm now checking other color usages — the color-selector's palette and the usage provider's chart colors — to see if their contrast-adjusted foreground defaults are appropriate for how those colors are actually rendered as content. I'm working through whether using--contrast-inputas an indicator's fill color causes a problem: at 50% contrast it becomes 50% alpha, turning what should be a solid surface into something translucent that lets the parent show through — potentially breaking the intended surface ownership even though it might look acceptably "softer."
28. browse_code — apps/web/src/components/chat/ProviderModelPicker.tsx
💭 I'm tracing where
indicatorBackgroundgets used inProviderInstanceIcon— it seems meant to act as a knockout color matching the surrounding surface, so switching it from the input token to the contrast-input token could make it translucent and break that effect at low contrast settings.
29. git_tools — indicatorBackground
💭 I'm noting that
indicatorBackgroundacts as a backing/knockout color for the badge's border, meant to match surrounding surface tokens like card, muted, or background — but here it's using the input token, which now maps tovar(--contrast-input), so I'm tracing what happens to that border color at lower contrast levels. At contrast values like 50, that token becomes 50% alpha, making the badge's separating ring translucent so the icon bleeds through and the badge loses its distinct chip appearance — a real regression, since--inputwas previously opaque in light themes. This seems like a genuine case of a border-role contrast token being misapplied to a knockout-fill role, and the cleanest fix is either keeping the original input token or swapping in an opaque surface token, though I want to consider the counterargument that softening everything at low contrast might be the intended behavior. Weighing which findings to actually report: the t3-chat light inline code issue (unadjusted markdown foreground color while surrounding text adjusts) is strong and well-supported by the check's own naming conventions, with a straightforward fix. The theme-inspector-hover label color issue is weaker and more of a dev-tool nitpick, but it touches a line already in the diff, so I could fold a mention of it into that same line's comment rather than raising it separately. I'm also confirming the ProviderModelPicker knockout ring issue holds up as a concrete, changed-line finding, and double-checking that the t3-chat light theme is actually reachable in practice and that--contrast-message-foregroundis indeed the correct token to swap in, since the rule's own design intent (translucent secondary surface layered over the light chat canvas using--message-surfaceand--message-foreground) confirms that's the right variable to mix against. Now I need to check whether the lines I want to flag actually appear within the PR's diff hunks, since GitHub only allows inline comments on lines shown in the diff context. Line 1826 falls outside any hunk boundary, so I can't attach a comment there directly and need to find an alternative approach. I'm weighing whether the theme-inspector label color issue is significant enough to flag, and decide it's a minor but genuine inconsistency worth mentioning briefly. I'll combine it into a single comment anchored at line 1723, referencing both the label and the t3-chat inline-code issue together for conciseness. I'm also considering a separate comment for ProviderModelPicker.tsx around line 169 regarding the knockout ring alpha value, though I'm still unsure if that one is solid enough to include. Given the guidance not to fail for optional aesthetic preferences, and that this is a borderColor application, I'll drop point C. That leaves findings A and B, both cases where the audit missed a role read tied to the very rule the PR added — B being the more significant one, since it's a real user-visible split in a shipped light-mode theme where inline code text won't respond to the contrast setting, while A is more minor. I want to verify the exact line numbers for both against the head file: A anchors cleanly at the border rule using color-mix with the ring and contrast-border variables, and now I need to pin down B's location precisely. I'll anchor B near the added line referencing--appearance-contrast-basefor the message foreground. For the comment body, I'm noting that the label's border now tracks the contrast setting but its text still reads the raw role, so the label keeps stock contrast while its border and surrounding chrome adjust — suggesting the adjusted role be read there too. Since the target line isn't in the diff, I can't do a multi-line inline suggestion, so I'm drafting a unified diff instead. Writing diff suggestion... Finishing the diff for the inline code color fix... Now I'm also considering whether portaled mobile sheet sidebars need separate verification for the--contrast-*token propagation. I want to check whether any JS code reads CSS custom properties directly for terminal or canvas rendering, but that seems fine since the terminal color is meant to remain unadjusted. Then I'm tracing a potential circular dependency in the dark sidebar block where--sidebar-row-hovermixes with--contrast-foreground, which itself might depend on the same variable it's feeding into. I'll finalize the review with two findings and mark it as a failure since real inconsistencies exist, keeping the write-up concise and titled around UI consistency issues, then post it.
30. modify_pr — Reviewed the contrast token derivation, the Tailwind bridge, and the converted global/imperative role reads. The token ownership (ordinary --contrast-* custom properties, redeclared on [data-app-sidebar], alpha-preserving softening for --border/--input, per-surface foreground mixes) looks right. Two role reads were missed by the audit, so they stay at stock contrast while the chrome around them moves with the setting.
Agent Credits: 513 credits