Audit & Drift
Mechanically-scanned CSS drift metrics (hardcoded radii, raw z-index, duplicate token values) plus hand-verified bugs and consolidation findings.
A standing audit of CSS-system drift in BuilderStudio-main. The metrics below are scanned mechanically from source by the generator (so they stay accurate and refreshable); the findings are hand-verified judgement calls. Most were fixed by the CSS token sweep on main; this page tracks what was done and what remains.
- 11Findings resolved
- 1Findings open
- 1By design
- 19Pill radii (50% only)
- 35Hardcoded radii
- 80Raw z-index (by contract)
- 18Hardcoded shadows
- 12Dup token values
Open
Still actionable — not yet addressed.
- DriftOpenHardcoded box-shadows bypass the shadow tokenscomponents/canvas/sidebars/CanvasAssetsList.module.css + ~18 sites
About 18 hardcoded box-shadows use literal rgba() instead of the --ui-shadow-* tokens. Some (e.g. CanvasAssetsList’s `0 1px 2px rgb(0 0 0 / 8–12%)`) closely match --ui-shadow-soft; others are genuinely context-specific depth.
By design
Investigated and intentionally left as-is (a contract or constraint makes the “drift” correct).
- DriftBy designSplit z-index system: tokens for primitives, literals for canvasrepo-wide
Portaled UI primitives (Tooltip/Toast/Select) use the --ui-z-* tokens; canvas overlays and node chrome use raw z-index integers.
By design: Intentional, not drift. scripts/validate-canvas-layer-contract.ts deliberately pins canvas selectors (.sheet=35, .toolbar=36, .promptHud=37, .root/.quickZoomDock=40, …) to LITERAL z-index values so the stacking order is statically verifiable. A --canvas-z-* token scale was tried during the sweep and reverted because it broke that contract. Leave canvas z-index as literals.
Resolved by the token sweep
Fixed on BuilderStudio-main main. Kept here for history; each notes how and where it was addressed.
- BugResolved`var(--ui-shadow-md)` is never definedcomponents/canvas/nodes/EasyConnectNode/EasyConnectNode.module.css
`box-shadow: var(--ui-shadow-md)` was used with no fallback, but tokens.css only defines --ui-shadow-panel / -popover / -tooltip / -toast / -soft. There was no -md, so the shadow silently resolved to nothing and the node rendered with no elevation.
Fix: Changed to var(--ui-shadow-soft) — CSS token sweep (main @ d84f8332c). This is the one intentional visual change in the sweep (the node now shows its intended elevation).
- BugResolved`.input` border color is set then immediately overriddencomponents/canvas/nodes/base/properties/properties.module.css
`.input` declared `border: 1px solid rgb(115 115 115 / 0.5)` then a later `border-color: rgb(0 0 0 / 0.12)` that overrode the color, so the 115-grey never rendered.
Fix: Collapsed to a single `border: 1px solid rgb(0 0 0 / 0.12)` (the value that actually rendered) — CSS token sweep (main @ d84f8332c). Pixel-identical.
- WarningResolvedDead `@keyframes loading-bar-slide` + misleading commentstyles/animations.css
The keyframe had zero consumers anywhere in the repo. Its comment claimed it was "used by CanvasLoadingScreen", but that component uses its own keyframes (rootReveal, loaderLogoEnter, textEnter).
Fix: Deleted the keyframe and the stale comment — CSS token sweep (main @ d84f8332c). The generated dead-keyframes scan is now 0.
- WarningResolvedglobals.css comment says `.animate-*` (plural)app/globals.css
The comment implied multiple animation utility classes live in animations.css, but exactly one exists (.animate-canvas-card-exit).
Fix: Comment corrected to name the single class — CSS token sweep (main @ d84f8332c).
- WarningResolvedNode-param dropdown z-index (1200) sat above toasts (1100)components/canvas/nodes/base/ModelParamsEditor/ModelParamsEditor.module.css + workspace-settings/DatePicker.module.css
`.paramSelectContent` hard-set z-index:1200 on a portaled Select dropdown. The Select primitive uses var(--ui-z-overlay)=1000 and toasts are --ui-z-toast=1100, so a node-param (and the date-picker) dropdown rendered on top of toasts.
Fix: Both dropdowns now use var(--ui-z-overlay) so toasts sit above them — CSS token sweep (main @ d84f8332c).
- WarningResolved`.secondaryToolbarButton` declared as two adjacent blockscomponents/canvas/overlays/CanvasFloatingToolbar.module.css
Two back-to-back rule blocks for the same selector (both set `border: 0`; the second added height/place-items/gap/radius/padding). Harmless but read as an incomplete refactor.
Fix: Merged into one block (and deduped a doubled :focus selector) — CSS token sweep (main @ d84f8332c).
- DriftResolved8 `--node-property-*` theming hooks were never setcomponents/canvas/nodes/base/properties/properties.module.css
Eight custom properties (--node-property-label-font-size, -help-font-size, -section-gap, -description-line-clamp, etc.) were read only with fallbacks and never assigned in any CSS or TS — dead indirection. Contrast with --bs-select-* and --canvas-viewport-* which ARE set at runtime (see cleared list).
Fix: All 8 reads inlined to their fallback values — CSS token sweep (main @ d84f8332c). Pixel-identical.
- DriftResolvedThree identical scroll-thumb tokens implied a state change that never happenedcomponents/canvas/nodes/base/PromptInput/PromptInput.module.css
--tone-scroll-thumb, -hover and -focus were byte-identical (rgba(0,0,0,0.2)) yet wired to 3 call sites (default / :hover / :focus) as if the thumb changed color on interaction — it did not.
Fix: Collapsed to one --tone-scroll-thumb token; the 3 call sites point at it — CSS token sweep (main @ d84f8332c). Pixel-identical.
- DriftResolvedNo pill/full radius tokenstyles/tokens.css + repo-wide
There was no --ui-radius-full token, so full/pill radius was hardcoded as 999px / 9999px (and 50% circles) across the codebase.
Fix: Added --ui-radius-full (and --ui-radius-2xs for 2px); ~120 border-radius literals tokenized (999px/9999px→full, 2px/0.125rem→2xs, plus exact-match px→token), pixel-identical — CSS token sweep (main @ d84f8332c). The pill-scan dropped 76→19; the remaining 19 are intentional 50% circles left as a documented idiom.
- DriftResolvedDuplicate-value tokens under many namesstyles/tokens.css
Pure white was defined under 6+ token names; #111827 under 3; plus error-shell ≡ error-bg/border, auth-text-muted ≡ public-text-muted, the node-header colour pair, and text-caption ≡ ui-text-xs.
Fix: Duplicates redefined as var() aliases of a canonical token (white→--color-background, fg→--color-foreground, error-shell→base, auth-text-muted→public, node-header icon→label, text-caption→--ui-text-xs) — CSS token sweep (main @ d84f8332c). One source of truth; zero visual change. (Genuinely-distinct values like --text-micro / --text-node-label were left alone.)
- DriftResolvedTwo overlapping type scalesstyles/tokens.css
--ui-text-xs/sm/md/lg coexisted with --text-caption/micro/node-label/label, with --text-caption byte-identical to --ui-text-xs.
Fix: The overlapping --text-caption is now an alias of --ui-text-xs (and --text-label was already an alias of --ui-text-md) — CSS token sweep (main @ d84f8332c). --text-micro (10px) and --text-node-label (9px) are unique canvas values with no scale-A equivalent, so they stay as-is by design.
Cleared (false positives)
Suspected issues that were investigated and found to be fine — recorded so they don't get re-raised (a few were subagent or stale-snapshot false positives).
- Cleared`--radius-full` "broken references"repo-wide
An earlier pass suspected ~11 broken var(--radius-full) refs. Verified: --radius-full existed nowhere and was referenced nowhere. A stale-snapshot artifact, not a real token. (Note: the sweep later ADDED a real --ui-radius-full token — different name, deliberate.)
- Cleared`--ui-selection-bg` driftapp/globals.css
Suspected the ::selection rule hardcoded the color instead of using the token. Verified: it correctly uses var(--ui-selection-bg). Not a bug.
- Cleared`--port-color` undefinedcomponents/canvas/nodes/base/NodeHandles/NodeHandles.module.css
Flagged by a pure-CSS scan as used-but-undefined. Verified: it is injected at runtime via inline style in PortHandle.tsx (getPortAccentColor). Correct pattern; allowlisted in the drift scan.
- Cleared`--canvas-viewport-floating-chrome-gap` (badge-position gap)components/canvas/nodes/base/badge-position.module.css
Looked like a never-set fallback var. Verified: viewportTransform.ts builds a CSS-vars map that sets it, zoom-reactively (test asserts it computes to 32px / 2px). Live, not dead.
- Cleared`--bs-select-*` "dead hooks"components/ui/primitives/Select.module.css
The Select primitive consumes ~20 --bs-select-* vars, all with sensible token fallbacks; node modules override a subset and -trigger-width is JS-measured. This is the correct themeable-contract pattern (the model the now-removed --node-property-* hooks should have followed).
- ClearedCanvasSidebarSheet "font-size used as border-radius" bugcomponents/canvas/sidebars/CanvasSidebarSheet.module.css
A subagent reported `border-radius: var(--text-micro)` at line 145. Verified false: line 145 is `justify-content: center;` and no border-radius uses a font token anywhere in that file. A hallucinated finding — recorded here so it is not re-raised.
Hardcoded border-radius
35 non-pill hardcoded radius values remain (1 exact-match a radius token; 34 are off-scale and left as documented literals). Plus 19 pill radii — all now the intentional 50% circle idiom after 999px/9999px were tokenized to --ui-radius-full. By value:
- 7px11
- 5px4
- 14px3
- 0.625rem3
- 03
- 9px3
- 10px2
- 1.5px1
- 0.5rem1
- 3px1
- 18px1
- 1px1
- 15px1
Raw z-index values
80 raw z-index integers across 27 distinct values. Canvas chrome keeps literals on purpose — validate-canvas-layer-contract.ts pins them for static stacking verification (see the “by design” finding).
- 99991
- 10001
- 1202
- 1001
- 602
- 505
- 405
- 391
- 372
- 361
- 351
- 341
- 303
- 281
- 204
- 182
- 151
- 142
- 104
- 81
- 51
- 31
- 23
- 123
- 08
- -12
- -21
Duplicate token values
12 literal values are each defined under more than one token name. After the sweep most colour duplicates are var() aliases of a canonical token; the remainder are cross-category coincidences (e.g. a spacing value equal to a radius value) that are not real duplication.
| Value | Defined under these token names |
|---|---|
| 0.5rem | --ui-radius-sm--ui-space-2--node-drag-header-height |
| 0.75rem | --ui-radius-md--ui-space-3--ui-text-sm |
| 1.25rem | --ui-radius-xl--ui-space-5--node-header-icon-size |
| rgba(255, 255, 255, 1) | --ui-surface-0--ui-surface-node--ui-surface-tab-active |
| rgba(243, 244, 246, 1) | --ui-surface-2--ui-border-subtle--ui-surface-subtle-hover |
| #f3f3f3 | --canvas-chrome-surface-subtle--canvas-chrome-row-active--canvas-chrome-row-hover |
| 0.25rem | --ui-radius-xxs--ui-space-1 |
| 1rem | --ui-radius-lg--ui-space-4 |
| 3rem | --ui-space-12--task-control-height |
| rgba(249, 250, 251, 1) | --ui-surface-1--ui-surface-subtle |
| 260px | --canvas-sidebar-primary-width--canvas-sidebar-secondary-width |
| rgba(229, 231, 235, 1) | --ui-border-soft--ui-border-subtle-hover |
Was this page helpful?