# Quick Reference — SVS MSP CALC

## Stack
Vanilla HTML5/CSS3/JS (ES5-compatible). No frameworks, no npm, no build tools. Open HTML in browser to run.

## Project Status
**Design & Sales Optimization: COMPLETE** (2026-03-16)
- 22 tasks executed across 5 chunks
- 3 themes: Dark (flagship), Light, Glass — Retro removed
- 254 engine tests passing
- All responsive breakpoints verified

## File Map

### JS Runtime
| File | Purpose | Key Functions |
|------|---------|---------------|
| `SVS-MSP-Calculator.js` | Orchestration, event binding | `update()`, `calcQuote()`, `stepInput()`, `initQuote()`, `toggleSection()` |
| `quote-engine.js` | Pure math (DO NOT TOUCH without tests) | `calculateQuote(state, pricing)`, `readFormState()`, `getPricingConfig()` |
| `quote-pricing.js` | Pricing defaults (34 keys), JSON loader | `getSnapshot()`, globals |
| `quote-render.js` | DOM rendering + animated counters | `renderSidebar()`, `animateValue()`, `setSummary()`, `renderNudge()`, `buildNudges()` |
| `quote-persistence.js` | localStorage save/restore | `saveState()`, `restoreState()`, `resetState()` |
| `quote-export.js` | Print/PDF + JSON export | Respects HST toggle, schema v1.0 |
| `quote-import.js` | JSON import + schema migration | Additive migrations only |
| `theme-manager.js` | 3-theme cycle + persistence | `toggleTheme()`, `applyTheme()`, `initTheme()` — cycle: Dark → Light → Glass |
| `mobile-sync.js` | Mobile panel dual-render | Clones sidebar, wraps `update()` for `_m` ID sync |
| `package-prices-data.js` | Pricing source (DO NOT MOVE) | Single source of truth for all rates |

### CSS (load order via manifest SVS-MSP-Calculator.css)
| File | Purpose | Key Tokens/Classes |
|------|---------|-------------------|
| `*-tokens.css` | Design tokens — colors, spacing, radii, typography, shadows | `--shadow-card/hover/open`, `--sidebar-zone-*`, `--text-money-hero` |
| `*-base.css` | Resets, top bar chrome | Global typography |
| `*-layout.css` | Grid: `.outer`, `.main-col`, `.side-col` | Section gap: `clamp(12px, 1.2vw, 20px)` |
| `*-components.css` | Sections, steppers, badges, sidebar, VS table, pitch bar | `.sec-active`, `.suffix-mo`, stepper-pulse keyframe, tabular-nums |
| `*-responsive.css` | Breakpoints: 1920+, ≤1350, ≤1100, ≤900, ≤600, 780L | Mobile: sidebar hidden, floating MRR badge |
| `*-print.css` | Print overrides | Strips shadows, animations, forces expand |
| `*-light.css` | Light theme token overrides | Softer shadows, inverted zone tints |
| `*-glass.css` | Glass theme (frosted blur) | Stronger shadows, translucent backgrounds |

### HTML Structure (section display order)
| Order | ID | Numeral | Title | Has Stepper |
|-------|----|---------|-------|-------------|
| 1 | sec-02 | I | User Package | userCount |
| 2 | sec-03 | II | Endpoint Package | endpointCount |
| 3 | sec-01 | III | Site Management | — (badges only) |
| 4 | sec-04 | IV | Server Management | serverCount |
| 5 | sec-05 | V | Zero Trust Networking (HaaS) | ztNetSeats |
| 6 | sec-06 | VI | VoIP / Unified Communications (UCaaS) | voipSeats |

### Key DOM IDs (do not rename — mobile sync depends on these)
- Inputs: `userCount`, `endpointCount`, `serverCount`, `ztNetSeats`, `ztNetRouters`, `voipSeats`
- Summaries: `sec01-summary` through `sec06-summary`
- Admin: `adminFeeDisplay`, `adminWaived`, `feeBreakdown`
- Sidebar values: `sl-users-val`, `sl-endpoints-val`, `sl-servers-val`, `sl-zt-val`, `sl-voip-val`
- Hero: `mrrDisplay`, `annualDisplay`, `sl-monthly-total-val`
- Progress: `floorBar`, `floorNote`

## Design System (post-optimization)

### Animations
| Animation | Duration | Trigger | Implementation |
|-----------|----------|---------|----------------|
| Number counter (sidebar + badges) | 350ms ease-out | Value change | `animateValue()` in quote-render.js |
| Stepper pulse | 150ms ease-out | +/- click | CSS `@keyframes stepper-pulse` + `.pulse` class in JS |
| Section expand/collapse | ~250ms | Click header | JS `animateSection()` + CSS height/opacity |
| Chevron rotate | `--transition-medium` | Section toggle | CSS `transform: rotate(180deg)` on `.sec-open` |
| Sidebar line hover | `--transition-fast` | Mouse hover | CSS border-left accent + padding shift |
| Progress bar | 300ms ease-out | Value change | CSS `transition: width` on `.progress-fill` |
| Term tile selection | 200ms ease | Click tile | CSS transitions on `.tier-seg` |

### Typography Hierarchy
- **Bold (700-800):** Section titles, hero MRI number, monthly total value
- **Semi-bold (600):** Sidebar `.val` amounts, line item labels
- **Medium (500):** `.sidebar-group-title`, uppercase labels
- **Regular (400):** Descriptions, subtitles, meta text

### Shadow Tokens (per theme)
- `--shadow-card` — base elevation on `.section`
- `--shadow-card-hover` — combined with `--section-hover-shadow` (left accent glow)
- `--shadow-card-open` — combined with `--section-open-shadow` (stronger glow)

### Active Section System
- `.sec-active` class toggled in `update()` based on section count > 0
- CSS: 3px left accent border via `color-mix(in srgb, var(--accent) 50%, transparent)`
- `.sec-active .section-num` — numeral turns accent-blue

### Sidebar Zones
- `.sidebar-group--monthly` — rounded container, `--sidebar-zone-services` tint
- `.sidebar-group--invoice` — `--sidebar-zone-invoice` tint
- `.sidebar-group--value` — green-tinted `--sidebar-zone-value`
- `.sidebar-line:hover` — accent border slides in left, background tints blue

## Pricing Defaults (from quote-pricing.js)
```
Users:     M365 $140 (m2m) / $130 (annual) | BYOL $110 | ExtHrs +$25 | 1PWM +$9 | INKY +$8 | ZT +$55
Endpoints: $35/ea | USB +$4 | BMB +$25
Servers:   $120/ea
ZT Net:    $25/seat | $100/router
Admin:     Floor $150 | Threshold $650 | ZT +$250 | 1PWM 10%
VoIP:      Basic $28 | Standard $35 | Premium $45 | Phone +$15 | Fax +$10
Discounts: m2m 0% | 12mo 3% + 50% off onboarding | 24mo 5% + complimentary onboarding
HST:       13% (Ontario)
```

## Tests
```
node svsmspcalc/tests/test-quote-engine.js
```
254 tests, zero dependencies. Run after any pricing/engine/render changes.

## Danger Zones
- DOM IDs → mobile sync breaks silently if renamed
- `quote-engine.js` math → run tests after any change
- Print CSS → sensitive to component class changes
- `update()` call chain → side effects cascade (calcQuote → render → sidebar → nudges → summaries → sec-active toggle → save)
- localStorage key: `svs-msp-quote-v1`
- `animateValue()` targets both desktop element AND `_m` mobile clone
- `.suffix-mo` span inside monthly total value — set via `innerHTML` not `textContent`

## Directory Layout
```
svsmspcalc/
├── SVS-MSP-Calculator.html          # Main HTML shell
├── SVS-MSP-Calculator.css           # CSS import manifest
├── SVS-MSP-Calculator.js            # Orchestration + event binding
├── SVS-MSP-Calculator-tokens.css    # Design tokens (shadows, zones, colors)
├── SVS-MSP-Calculator-base.css      # Resets, typography
├── SVS-MSP-Calculator-layout.css    # Grid system, section gap
├── SVS-MSP-Calculator-components.css # All UI components (~2100 lines)
├── SVS-MSP-Calculator-responsive.css # Breakpoints
├── SVS-MSP-Calculator-print.css     # Print overrides
├── SVS-MSP-Calculator-light.css     # Light theme overrides
├── SVS-MSP-Calculator-glass.css     # Glass theme overrides
├── quote-engine.js                  # Pure math (254 tests)
├── quote-render.js                  # Rendering + animateValue()
├── quote-pricing.js                 # Pricing config
├── quote-persistence.js             # localStorage
├── quote-export.js                  # Print/PDF + JSON export
├── quote-import.js                  # JSON import + migration
├── theme-manager.js                 # 3-theme cycle
├── mobile-sync.js                   # Mobile dual-render
├── package-prices-data.js           # PRICING SOURCE
├── M365icons/                       # Microsoft 365 icons
├── fontawesomekit/                  # Font Awesome icons
├── pre-alpha/                       # READ-ONLY archived reference
├── tests/
│   └── test-quote-engine.js         # 254 engine tests
└── docs/
    ├── QUICK-REF.md                 # THIS FILE — architecture + file map
    ├── SESSION-HANDOFF.md           # Current status + next steps
    ├── CHECKPOINT.md                # Historical checkpoint
    ├── MASTER-SESSION-PROMPT.md     # Master rebuild prompt
    ├── DECISION-LOG.md              # Decision history
    ├── KNOWN-ISSUES.md              # Tracked bugs
    ├── quote-rules.md               # Business logic rules
    ├── regression-checklist.md      # QA checklist
    └── README.md                    # Project overview
```
