8.8 KiB
CLAUDE.md — SVS MSP Calculator
What This Is
SVS MSP Calculator — a live pricing and quote tool used by the sales team on screen during prospect calls.
HTML5 / CSS3 / JS. No frameworks, no build tools. Open SVS-MSP-Calculator.html in a browser — it runs.
Status: Active development — current focus is GUI / UI improvement. Quote logic and pricing engine are stable. Do not touch without explicit approval.
How It Works
The Update Loop
Every input change triggers this pipeline:
Input event → readFormState() → calculateQuote(state, pricing) → renderQuote(quote) → mobileSync()
SVS-MSP-Calculator.js orchestrates this via update(). The engine is a pure function — state in, quote out. Render writes to DOM. Mobile sync clones to the mobile panel. Any change that touches this chain affects the entire app.
CSS Cascade
9 modular CSS files loaded via SVS-MSP-Calculator.css (master import):
tokens.css → base.css → layout.css → components.css → responsive.css
↕
light.css / glass.css (theme overrides)
↕
print.css
Tokens are the source of truth. 60+ semantic variables (--ink, --paper, --accent, --surface-*, --print-*). Changing a token ripples through all 3 themes, all components, and print output.
Themes are pure CSS variable overrides on :root — no HTML changes, no JS logic. theme-manager.js toggles a class; the cascade does the rest.
Mobile Sync
mobile-sync.js physically clones the sidebar DOM into a bottom-sheet panel (#mobileQuotePanel) and appends _m to every cloned ID. It then syncs content, classes, styles, and checkbox states from desktop → mobile after each update().
If you add a new sidebar element, mobile-sync must know about it or mobile breaks silently.
The Sidebar Is the Product
The right column (.sidebar) is what the prospect stares at during the call. Hero numbers: MRR, per-user cost, annual total. Every UI change should be evaluated from: does this make the sidebar clearer?
Print / PDF
SVS-MSP-Calculator-print.css is a parallel rendering target with its own token set (--print-*). At @media print it hides all interactive controls, forces sections open, and outputs a clean A4 document. Print is not an afterthought — it's a sales deliverable.
localStorage
3 keys: quote state (full form data as JSON), quote reference ID, theme preference. Save/load via quote-persistence.js. Ctrl+S / Ctrl+L shortcuts.
Invariants
Things that must be true before and after every session. Each has a verification step.
| Invariant | Verify |
|---|---|
| All unit tests pass | node tests/test-quote-engine.js — 254/254 |
| All 3 themes render correctly | Playwright-check Dark, Light, Glass after any CSS change |
| DOM IDs unchanged | Never rename — mobile-sync.js maps 100+ desktop↔mobile pairs silently |
| localStorage round-trip | Save → reload → confirm all values restore |
| Print output clean | Verify after any CSS change — print has its own cascade |
| Mobile panel matches sidebar | Check mobile bottom-sheet after any sidebar change |
Working Rules
How Claude behaves while working. Not testable — behavioral.
- Read before editing — always inspect current code first
- Quote engine is locked — no changes to
quote-engine.js,quote-pricing.js, orpackage-prices-data.jswithout explicit approval - No frameworks, no build tools — vanilla JS by design
- No broad rewrites — surgical, approved changes only
- Ask before assuming — when requirements are unclear, ask
Do Not Touch
| Thing | Why |
|---|---|
fontawesomekit/ |
Huge vendor directory. Reference known FA icons by name when needed — never scan this directory |
pre-alpha/ |
Legacy/experimental files. Ignore unless explicitly asked |
| Quote engine files | quote-engine.js, quote-pricing.js, package-prices-data.js — stable, tested, locked |
Design Principles
- Sales clarity over visual novelty — prospects read numbers at a glance
- The sidebar is the hero — treat it like a financial summary
- Dark theme is flagship — Light and Glass must meet the same bar
- Copy is UX — every label and nudge is a design decision
- Mobile is first-class — a sales rep on a tablet must run a full quote
Architecture
HTML Structure
6 collapsible sections in the main column, sticky sidebar in the right column:
| Section | ID | Content |
|---|---|---|
| I — Site Management | #sec-01 |
Admin fee, floor $650 |
| II — User Package | #sec-02 |
Per-user pricing, M365/BYOL |
| III — Endpoint Package | #sec-03 |
Device count |
| IV — Server Management | #sec-04 |
Server count |
| V — Zero Trust HaaS | #sec-05 |
Seats, routers |
| VI — VoIP UCaaS | #sec-06 |
Seats, tiers |
Layout: CSS Grid — 3fr | 2fr (main | sidebar). Collapses to single column at 1100px. Mobile pill + bottom-sheet panel below 1100px.
Z-index stack: 400 (modals) → 300 (mobile panel) → 200 (mobile pill) → 100 (top bar) → 10 (sidebar)
JS Files
| File | Role |
|---|---|
SVS-MSP-Calculator.js |
Orchestrator — update() loop, form reading, event wiring |
quote-engine.js |
Pure calculation — calculateQuote(state, pricing) → quote object |
quote-pricing.js |
Pricing defaults (32 rates/fees) — SVSQuotePricing.getSnapshot() |
package-prices-data.js |
External pricing data (optional override) |
quote-render.js |
Writes calculated quote to DOM elements |
quote-persistence.js |
localStorage save/load + Ctrl+S/Ctrl+L |
quote-export.js |
Printable/exportable quote HTML generation |
quote-import.js |
Load saved quotes from JSON |
mobile-sync.js |
Clones sidebar → mobile panel, syncs on every update() |
theme-manager.js |
Dark/Light/Glass toggle, persists preference |
CSS Files
| File | Role |
|---|---|
SVS-MSP-Calculator.css |
Master import — loads all modules |
*-tokens.css |
Design tokens — 60+ semantic variables, source of truth |
*-base.css |
Body, top bar, theme toggle |
*-layout.css |
Grid, page layout, sidebar, modals |
*-components.css |
Section cards, buttons, icons, form controls |
*-responsive.css |
Media queries — 1100px and 600px breakpoints |
*-light.css |
Light theme — :root variable overrides only |
*-glass.css |
Glass theme — gradients, blur, color-scheme: dark |
*-print.css |
Print/PDF — own token set, aggressive cleanup, A4-ready |
Tests
254 tests across 47 groups. Custom minimal harness (no framework). Covers: pricing, discounts, add-ons, VoIP tiers, HST, contract terms, edge cases, admin fees.
Run: node tests/test-quote-engine.js
Tools & When to Use Them
| Tool | Use when |
|---|---|
| Playwright | Visual verification — viewing HTML/CSS across themes |
| ui-ux-pro-max | Any design decision — invoke before touching CSS |
| superpowers | Planning, parallel agents, debugging, TDD, branch/commit |
| frontend-design | Building or modifying UI components |
| code-review | Before marking any task complete |
| code-simplifier | After implementation — clean up without changing behavior |
| context-mode | Large output (>20 lines) — routes through sandbox to protect context window. Use ctx_batch_execute for multi-command research, ctx_search for follow-up queries, ctx_execute/ctx_execute_file for data processing, ctx_fetch_and_index for URL fetching |
| accesslint | Accessibility and colour contrast checking. Use contrast-checker for WCAG ratio checks on hex pairs, use-of-color to flag colour-only indicators, reviewer for full component audits. Minimum standard: WCAG 2.1 AA (4.5:1 normal text, 3:1 large text). Suggest replacement hex values on failure. |
Session Start
- Read
docs/SESSION-HANDOFF.md— current state of the project - Run
node tests/test-quote-engine.js— confirm 254/254 - Ask the user what they want — do not assume, do not start changing things
Read other docs only when the task requires them:
docs/QUICK-REF.md— file map, DOM IDs, pricing constantsdocs/quote-rules.md— pricing / business logicdocs/DECISION-LOG.md— has this decision already been made?docs/KNOWN-ISSUES.md— is this bug already tracked?
Session End
- Run
node tests/test-quote-engine.js— all 254 must pass - Update
docs/SESSION-HANDOFF.mdas a current state snapshot:- What is the state of the project right now (not a history log)
- What files are in what state
- What is next
- Commit if approved by user — one concern per commit