Files
svsmspcalc/docs/superpowers/specs/2026-03-16-spacing-token-consolidation-design.md

203 lines
6.9 KiB
Markdown

# 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`)
```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
1. `SVS-MSP-Calculator-components.css` (~86 instances)
2. `SVS-MSP-Calculator-responsive.css` (~19 instances)
3. `SVS-MSP-Calculator-layout.css` (~12 instances)
4. `SVS-MSP-Calculator-print.css` (~7 instances)
5. `SVS-MSP-Calculator-base.css` (~2 instances)
6. `SVS-MSP-Calculator-glass.css` (~1 instance)
### Global exclusions
- `pre-alpha/` directory — archived reference, do not modify
- `1px` in `calc()` expressions — visual micro-adjustments
- `1px` in `box-shadow` offsets — shadow geometry, not borders
- `1px` in `outline` — separate concern
- `2px` in 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-radius` values (Phase 3)
- `font-size` values (out of scope)
- `width`/`height` values (out of scope)
- Values in `clamp()` or `calc()` expressions
- Intentional off-grid values (`5px`, `9px`, `7px`) — these are deliberate tweaks
### Files affected
1. `SVS-MSP-Calculator-components.css` (~30 instances)
2. `SVS-MSP-Calculator-layout.css` (~4 instances)
3. `SVS-MSP-Calculator-responsive.css` (~2 instances)
4. `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`)
```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-radius` values inside `clamp()` or `calc()`
- Outlier values (`2px`, `3px`, `7px`) — keep as hardcoded, too unique to tokenize
### Files affected
1. `SVS-MSP-Calculator-components.css` (~18 instances)
2. `SVS-MSP-Calculator-responsive.css` (~2 instances)
3. `SVS-MSP-Calculator-base.css` (~1 instance)
### Commit message
`css: tokenize border-radius — consolidate to --radius-sm/md/lg/pill scale`
---
## Verification (per phase)
1. **Tests:** `node tests/test-quote-engine.js` — 254/254 must pass
2. **Visual:** Playwright screenshots at 1920px — Dark, Light, Glass themes
3. **Mobile:** Playwright at 375px — floating MRR pill, bottom sheet, sync
4. **Print:** Playwright print media emulation — no regressions
5. **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`
```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)
```css
/* 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;
```