`.btn-primary` was defined five times in five scoped stylesheets and all five
had drifted: three paddings, three font sizes, three disabled opacities — and
ProjectListView had no disabled style at all, so a disabled button there looked
enabled. Nothing detected any of it. A scoped duplicate is not a rule
violation, not a broken reference, and not a recorded snippet, so no existing
check could see it (#2273).
assets/components.css is now the single definition of the core four —
primary, secondary, ghost, danger — plus the small modifier, in design-system
tokens throughout. Operator's call to align to the system rather than to the
majority of current values, so buttons move to the 8px radius and 12px label
the system specifies, from the app's 4px/14.4px.
Class names are unchanged, so there are no template edits: the existing surface
is repurposed, not rebuilt.
STAGING PROPERTY that makes this safe to land ahead of the rest: a Vue
`<style scoped>` rule compiles to `.btn-primary[data-v-…]` (specificity 0,2,0)
and beats a plain global selector (0,1,0). So the shared sheet changes nothing
for a view still carrying its own copy, and every intermediate state of the
remaining migration is coherent rather than half-applied.
Two divergences corrected on the way, both worth naming:
- SnippetEditorView's `.btn-secondary` was a GHOST in disguise — outline
styling under the secondary name, while the house style says secondary is
filled bronze. It now looks like what it is called.
- SnippetDetailView and SnippetListView tinted a ghost button's label with the
ACCENT on hover. The house style reserves the accent for identity and active
state, never general chrome.
DesignView reported "no shared button exists" as an honest gap and declined to
draw a look-alike. That gap is closed, so it now renders the app's real
classes — the specimens cannot drift from the app without drifting the app.
Net -177 lines. Follows: the ~20 semantic one-offs (.btn-save, .btn-delete,
.btn-toggle …) and the compound overrides in ProjectView, one of which puts the
accent on a primary action button.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UaYUaouG9jjhATyuxCKrQs