6.9 KiB
Spacing Token Consolidation — Design Spec
Date: 2026-03-16 Status: Approved Scope: Phases 1-3 (~183 instances across 5 CSS files) Approach: Phase-by-phase across all files, one commit per phase
Context
The SVS MSP Calculator CSS has ~420 hardcoded px values across 75+ unique values. About half already have tokens defined in SVS-MSP-Calculator-tokens.css but aren't being used. This consolidation pass addresses the highest-ROI phases: border widths, existing token adoption, and border-radius scale.
Why now: The project is moving from alpha to beta. Consolidating magic numbers improves maintainability, makes theme adjustments easier, and reduces regression risk from future CSS changes.
What's NOT in scope: Icon/button sizing tokens (Phase 4), typography scale (Phase 5), breakpoint tokens (Phase 6 — CSS vars can't be used in @media queries anyway).
Phase 1: Border Width Tokens (~124 instances)
New tokens (add to SVS-MSP-Calculator-tokens.css)
--border-thin: 1px; /* structural borders */
--border-medium: 2px; /* accent borders, summary badges */
--border-thick: 3px; /* sidebar decorators, group strips */
Replacement rules
| Pattern | Replacement |
|---|---|
border: 1px solid ... |
border: var(--border-thin) solid ... |
border-top: 1px solid ... |
border-top: var(--border-thin) solid ... |
border-bottom: 1px solid ... |
border-bottom: var(--border-thin) solid ... |
border-left: 1px solid ... |
border-left: var(--border-thin) solid ... |
border-right: 1px solid ... |
border-right: var(--border-thin) solid ... |
border-width: 1px |
border-width: var(--border-thin) |
Same patterns for 2px |
Use var(--border-medium) |
border: 1px dashed ... |
border: var(--border-thin) dashed ... |
border: 1px dotted ... |
border: var(--border-thin) dotted ... |
border-*-width: 1px |
border-*-width: var(--border-thin) |
Same patterns for 2px |
Use var(--border-medium) |
Same patterns for 3px |
Use var(--border-thick) |
Files affected
SVS-MSP-Calculator-components.css(~86 instances)SVS-MSP-Calculator-responsive.css(~19 instances)SVS-MSP-Calculator-layout.css(~12 instances)SVS-MSP-Calculator-print.css(~7 instances)SVS-MSP-Calculator-base.css(~2 instances)SVS-MSP-Calculator-glass.css(~1 instance)
Global exclusions
pre-alpha/directory — archived reference, do not modify1pxincalc()expressions — visual micro-adjustments1pxinbox-shadowoffsets — shadow geometry, not borders1pxinoutline— separate concern2pxin non-border contexts (e.g.,padding: 2px) — that's spacing, not border width
Commit message
css: tokenize border widths — consolidate 1px/2px/3px to --border-thin/medium/thick
Phase 2: Adopt Existing Spacing Tokens (~37 instances)
No new tokens — use what already exists
| Hardcoded | Token | Count |
|---|---|---|
4px (spacing) |
var(--space-xs) |
~12 |
8px (spacing) |
var(--space-sm) |
~11 |
10px (spacing) |
var(--space-stack-tight) |
~5 |
12px (spacing) |
var(--space-md) |
~2 |
16px (spacing) |
var(--space-stack-roomy) |
~2 |
18px (spacing) |
var(--space-lg) |
~2 |
20px (spacing) |
var(--space-xl) |
~3 |
Replacement rules
Only replace margin, padding, and gap properties. Do NOT replace:
border-radiusvalues (Phase 3)font-sizevalues (out of scope)width/heightvalues (out of scope)- Values in
clamp()orcalc()expressions - Intentional off-grid values (
5px,9px,7px) — these are deliberate tweaks
Files affected
SVS-MSP-Calculator-components.css(~30 instances)SVS-MSP-Calculator-layout.css(~4 instances)SVS-MSP-Calculator-responsive.css(~2 instances)SVS-MSP-Calculator-print.css(~1 instance)
Commit message
css: adopt existing spacing tokens — replace hardcoded 4-20px with var(--space-*)
Phase 3: Border-Radius Scale (~20 instances)
New tokens (add to SVS-MSP-Calculator-tokens.css)
--radius-sm: 4px; /* small corners: pills, badges, small buttons */
--radius-md: 8px; /* medium corners: cards, modals, containers */
--radius-lg: 10px; /* large corners: pill buttons, modal dialogs */
--radius-pill: 999px; /* perfect pill shape */
Existing tokens remain unchanged:
--radius-control: 6px— input controls--radius-card: 12px— section cards
Replacement rules
| Hardcoded | Token | Count |
|---|---|---|
border-radius: 4px |
var(--radius-sm) |
~12 |
border-radius: 8px |
var(--radius-md) |
~8 |
border-radius: 10px |
var(--radius-lg) |
~4 |
border-radius: 999px |
var(--radius-pill) |
~1 |
Exclusions
border-radiusvalues insideclamp()orcalc()- Outlier values (
2px,3px,7px) — keep as hardcoded, too unique to tokenize
Files affected
SVS-MSP-Calculator-components.css(~18 instances)SVS-MSP-Calculator-responsive.css(~2 instances)SVS-MSP-Calculator-base.css(~1 instance)
Commit message
css: tokenize border-radius — consolidate to --radius-sm/md/lg/pill scale
Verification (per phase)
- Tests:
node tests/test-quote-engine.js— 254/254 must pass - Visual: Playwright screenshots at 1920px — Dark, Light, Glass themes
- Mobile: Playwright at 375px — floating MRR pill, bottom sheet, sync
- Print: Playwright print media emulation — no regressions
- Diff: Pixel-compare screenshots before/after — changes should be zero (pure refactor)
Risk Assessment
| Risk | Mitigation |
|---|---|
| Accidental visual change | Playwright pixel-diff before/after each phase |
| Theme-specific breakage | Light/Glass only override colors/shadows, not border-widths or spacing — low risk |
| Mobile sync breakage | No DOM ID changes — zero risk |
| Print regression | Print CSS uses same tokens — verify with print emulation |
| Token name collision | Checked: no existing --border-thin/medium/thick or --radius-sm/md/lg/pill tokens |
!important in theme overrides |
Tokenizing 1px !important in glass.css is valid CSS; border widths don't vary by theme so low risk |
Token Summary (final state after all 3 phases)
New tokens added to SVS-MSP-Calculator-tokens.css
/* Border widths */
--border-thin: 1px;
--border-medium: 2px;
--border-thick: 3px;
/* Border radius (additions to existing scale) */
--radius-sm: 4px;
--radius-md: 8px;
--radius-lg: 10px;
--radius-pill: 999px;
Existing tokens (no changes)
/* Spacing (already defined, now actually used) */
--space-xs: 4px;
--space-sm: 8px;
--space-stack-tight: 10px;
--space-md: 12px;
--space-stack-roomy: 16px;
--space-lg: 18px;
--space-xl: 20px;
/* Radius (already defined, unchanged) */
--radius-control: 6px;
--radius-card: 12px;