diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 0000000..b492b4a --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,5 @@ +{ + "enabledPlugins": { + "context-mode@context-mode": true + } +} diff --git a/.claude/settings.local.json b/.claude/settings.local.json index a153a67..2a2d532 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -13,7 +13,22 @@ "Bash(git checkout*)", "Read(//c/Users/JohnOReilly/OneDrive - Silicon Valley Services/Documents/Projects VS CODE/SVS MSP Calculator/**)", "mcp__plugin_playwright_playwright__browser_evaluate", - "mcp__plugin_playwright_playwright__browser_run_code" + "mcp__plugin_playwright_playwright__browser_run_code", + "Bash(node:*)", + "Bash(bun --version)", + "Read(//c/Users/JohnOReilly/AppData/Roaming/npm/node_modules/bun/**)", + "Read(//c/Users/JohnOReilly/**)", + "mcp__plugin_context-mode_context-mode__ctx_batch_execute", + "mcp__plugin_context-mode_context-mode__ctx_doctor", + "mcp__plugin_context-mode_context-mode__ctx_fetch_and_index", + "mcp__plugin_context-mode_context-mode__ctx_execute_file", + "mcp__plugin_context-mode_context-mode__ctx_execute", + "mcp__plugin_playwright_playwright__browser_take_screenshot", + "mcp__plugin_playwright_playwright__browser_click", + "mcp__plugin_accesslint_accesslint__analyze_color_pair" ] + }, + "enabledPlugins": { + "context-mode@context-mode": true } } diff --git a/.claude/skills/ui-ux-pro-max b/.claude/skills/ui-ux-pro-max new file mode 160000 index 0000000..07f4ef3 --- /dev/null +++ b/.claude/skills/ui-ux-pro-max @@ -0,0 +1 @@ +Subproject commit 07f4ef3ac2568c25a3b0c8ef5165a86abc3e56e4 diff --git a/.mcp.json b/.mcp.json new file mode 100644 index 0000000..333eea1 --- /dev/null +++ b/.mcp.json @@ -0,0 +1,8 @@ +{ + "mcpServers": { + "accesslint": { + "command": "npx", + "args": ["-y", "@accesslint/mcp"] + } + } +} diff --git a/.playwright-mcp/console-2026-03-18T20-08-48-067Z.log b/.playwright-mcp/console-2026-03-18T20-08-48-067Z.log new file mode 100644 index 0000000..1d2befd --- /dev/null +++ b/.playwright-mcp/console-2026-03-18T20-08-48-067Z.log @@ -0,0 +1 @@ +[ 816ms] [ERROR] Failed to load resource: the server responded with a status of 404 (Not Found) @ http://localhost:8765/favicon.ico:0 diff --git a/.playwright-mcp/console-2026-03-18T20-27-17-867Z.log b/.playwright-mcp/console-2026-03-18T20-27-17-867Z.log new file mode 100644 index 0000000..dfb674b --- /dev/null +++ b/.playwright-mcp/console-2026-03-18T20-27-17-867Z.log @@ -0,0 +1 @@ +[ 442ms] [ERROR] Failed to load resource: the server responded with a status of 404 (Not Found) @ http://localhost:8766/favicon.ico:0 diff --git a/.playwright-mcp/console-2026-03-18T20-43-11-414Z.log b/.playwright-mcp/console-2026-03-18T20-43-11-414Z.log new file mode 100644 index 0000000..e8b1344 --- /dev/null +++ b/.playwright-mcp/console-2026-03-18T20-43-11-414Z.log @@ -0,0 +1 @@ +[ 254ms] [ERROR] Failed to load resource: the server responded with a status of 404 (File not found) @ http://localhost:8765/favicon.ico:0 diff --git a/.playwright-mcp/console-2026-03-18T20-53-05-347Z.log b/.playwright-mcp/console-2026-03-18T20-53-05-347Z.log new file mode 100644 index 0000000..8037678 --- /dev/null +++ b/.playwright-mcp/console-2026-03-18T20-53-05-347Z.log @@ -0,0 +1 @@ +[ 433ms] [ERROR] Failed to load resource: the server responded with a status of 404 (File not found) @ http://localhost:8765/favicon.ico:0 diff --git a/.playwright-mcp/console-2026-03-18T21-06-29-639Z.log b/.playwright-mcp/console-2026-03-18T21-06-29-639Z.log new file mode 100644 index 0000000..2d59ece --- /dev/null +++ b/.playwright-mcp/console-2026-03-18T21-06-29-639Z.log @@ -0,0 +1 @@ +[ 557ms] [ERROR] Failed to load resource: the server responded with a status of 404 (File not found) @ http://localhost:8766/favicon.ico:0 diff --git a/CLAUDE-beta.md b/CLAUDE-beta.md new file mode 100644 index 0000000..dc87b5b --- /dev/null +++ b/CLAUDE-beta.md @@ -0,0 +1,203 @@ +# 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. + +1. **Read before editing** — always inspect current code first +2. **Quote engine is locked** — no changes to `quote-engine.js`, `quote-pricing.js`, or `package-prices-data.js` without explicit approval +3. **No frameworks, no build tools** — vanilla JS by design +4. **No broad rewrites** — surgical, approved changes only +5. **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 + +1. **Sales clarity over visual novelty** — prospects read numbers at a glance +2. **The sidebar is the hero** — treat it like a financial summary +3. **Dark theme is flagship** — Light and Glass must meet the same bar +4. **Copy is UX** — every label and nudge is a design decision +5. **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 + +1. Read `docs/SESSION-HANDOFF.md` — current state of the project +2. Run `node tests/test-quote-engine.js` — confirm 254/254 +3. 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 constants +- `docs/quote-rules.md` — pricing / business logic +- `docs/DECISION-LOG.md` — has this decision already been made? +- `docs/KNOWN-ISSUES.md` — is this bug already tracked? + +--- + +## Session End + +1. Run `node tests/test-quote-engine.js` — all 254 must pass +2. Update `docs/SESSION-HANDOFF.md` as 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 +3. Commit if approved by user — one concern per commit diff --git a/CLAUDE-nextsteps.md b/CLAUDE-nextsteps.md new file mode 100644 index 0000000..0d93448 --- /dev/null +++ b/CLAUDE-nextsteps.md @@ -0,0 +1,59 @@ +# Next Steps — SVS MSP Calculator + +**Updated:** 2026-03-18 +**Purpose:** Resume guide for next session. + +--- + +## Just Completed (2026-03-18, committed as 4c53af9) + +Sidebar UX polish pass: +- Unified dividers → one `--sidebar-rule` token, dashed everywhere +- Letter-spacing → `--text-spacing-money: 0.05em` token +- Font floor → 11px minimum (6 locations bumped) +- Contrast → muted colors darkened to 6.5:1+ on all themes +- Opacity → removed from 9 double-muted text elements +- Total line border → scoped to monthly breakdown only + +--- + +## Next Session: Google Fonts + GUI Polish + +### Step 1: Google Fonts Selection +- **Approved:** up to 3 fonts (preferred), 4 hard cap +- **Currently loaded:** Poppins (hero numbers), DM Mono (monospace values) +- **Need:** A clean sans-serif for body text, labels, and UI copy +- **Candidates to evaluate:** Inter, IBM Plex Sans, Source Sans 3, Outfit, or similar +- **Approach:** Pick font → load from Google Fonts CDN → apply to body/labels → verify all 3 themes + +### Step 2: GUI Polish List A +- Contract Term pills — more vertical padding on unselected +- Section card collapsed headers — slightly tight vertically +- "MANAGED IT SERVICES (SECTIONS I, II, III)" label — low contrast +- Insight carousel text — more line-height +- "QUOTE NOTES" label spacing — inconsistent with other section labels + +### Step 3: Typography Token Pass +- Tokenize remaining hardcoded letter-spacing (~20 locations) +- Tokenize hardcoded font-sizes +- Move sidebar typography tokens from components.css → tokens.css +- Phase 4: icon/button sizing tokens +- Phase 6: responsive breakpoint font-sizes (optional) + +--- + +## Tools Available — USE THEM + +| Tool | When | +|------|------| +| **Playwright MCP** | Visual verification across Dark/Light/Glass | +| **accesslint** | Contrast checking on any color changes | +| **superpowers** | Planning, parallel agents, TDD, debugging | +| **context-mode** | Large output processing (>20 lines) | + +--- + +## Resume Prompt + +Tell Claude: +> "Read docs/SESSION-HANDOFF.md. Pick up at Google Fonts selection, then GUI polish list A." diff --git a/CLAUDE.md b/CLAUDE.md index 1245ab4..dc87b5b 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,248 +1,203 @@ # CLAUDE.md — SVS MSP Calculator -> Master instruction set for Claude Code. This is the SINGLE file to read on session start. -> It references deeper docs — do not duplicate them here. +--- -## Project Identity +## What This Is -**App:** SVS MSP Calculator — a live quote/pricing calculator for SVS Managed Services. -**Used by:** Sales team, live on screen with prospects during discovery calls. -**Tech:** Vanilla HTML5 / CSS3 / JS (ES5-compatible). No frameworks, no npm, no build tools. Open `SVS-MSP-Calculator.html` in a browser — it runs. -**Status:** Alpha-ready, pushing to Beta. -**Tests:** 254 passing (`node tests/test-quote-engine.js`) -**Themes:** 3 — Dark (flagship), Light, Glass +**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. -For full architecture, file maps, DOM IDs, and pricing constants see `docs/QUICK-REF.md`. -For business logic and pricing rules see `docs/quote-rules.md`. -For the complete architecture brief see `docs/MASTER-SESSION-PROMPT.md`. +**Status:** Active development — current focus is GUI / UI improvement. +Quote logic and pricing engine are stable. Do not touch without explicit approval. --- -## Session Start Protocol +## How It Works -On every new conversation, execute in order: +### The Update Loop -1. **Read context** (parallel): - - `docs/SESSION-HANDOFF.md` — what happened last, what is next - - `docs/QUICK-REF.md` — file map, DOM IDs, pricing, danger zones -2. **Run baseline tests:** `node tests/test-quote-engine.js` — confirm 254/254 pass -3. **Ask the user** what they want to work on. Do not assume. Do not start changing things. -4. **Read task-specific docs only when needed:** - - `docs/quote-rules.md` — pricing or business logic work - - `docs/regression-checklist.md` — validation work - - `docs/MASTER-SESSION-PROMPT.md` — unfamiliar areas, full architecture - - `docs/DECISION-LOG.md` — check if a relevant decision was already made - - `docs/KNOWN-ISSUES.md` — check if the issue is already tracked - ---- - -## Session End Protocol - -Before ending any session: - -1. **Run full test suite:** `node tests/test-quote-engine.js` — all 254 must pass -2. **Update `docs/SESSION-HANDOFF.md`** with: - - What was done (brief, specific) - - Files modified (table format) - - Test status (pass count) - - What is next (prioritized) -3. **Update `docs/CHECKPOINT.md`** if structural work was completed -4. **Update `docs/DECISION-LOG.md`** if any decisions were made -5. **Use `superpowers:finishing-a-development-branch`** for commit and cleanup - ---- - -## Orchestration Engine — Superpowers - -Use the **superpowers** plugin as the execution backbone for all non-trivial work. - -### Workflow Selection - -| Situation | Superpowers Skill to Use | -|-----------|--------------------------| -| Planning any feature or multi-step work | `superpowers:writing-plans` | -| Executing a plan with review gates | `superpowers:subagent-driven-development` | -| 2+ independent tasks (e.g., fix CSS in all 3 themes) | `superpowers:dispatching-parallel-agents` | -| Investigating a bug or failure | `superpowers:systematic-debugging` | -| Writing or modifying quote engine logic | `superpowers:test-driven-development` | -| Final checks before marking work done | `superpowers:verification-before-completion` | -| Committing, branch cleanup, merge prep | `superpowers:finishing-a-development-branch` | -| Visual brainstorming for design or UX | `superpowers:brainstorming` | - -### Subagent-Driven Development Flow - -For any plan with 2+ tasks, use `superpowers:subagent-driven-development`: +Every input change triggers this pipeline: ``` -Per task: - 1. Dispatch implementer subagent (with role-specific model — see below) - 2. Spec compliance review (did it match requirements?) - 3. Code quality review (is it well-built?) - 4. Mark task complete -After all tasks: - Final code review → superpowers:finishing-a-development-branch +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.** -## Agent Roles & Model Routing +### CSS Cascade -When dispatching subagents (via superpowers or directly), route to the right role and model. - -### Frontend Coder — Opus (default) -**When:** JS logic, CSS changes, HTML structure, bug fixes, refactoring. -**How:** Surgical precision. Read the file first, make the minimal change. -**Post-change:** Run the full validation pipeline. - -### UI/UX Designer — Opus + ui-ux-pro-max Skill -**When:** Design decisions — palettes, typography, spacing, layout, visual hierarchy, component styling. -**How:** Invoke the ui-ux-pro-max skill BEFORE implementation. Feed design system output to the implementer subagent. -**Sub-skills:** banner-design, brand, design-system, design, slides, ui-styling -**Constraint:** Translate all output to vanilla CSS — this project has no framework. - -### Copywriter — Sonnet Model -**When:** ALL user-facing text — button labels, section descriptions, nudge messages, tooltip copy, sidebar labels, sales language, feature descriptions, comparison text, pitch bar copy. -**How:** Dispatch Agent with `model: "sonnet"`. Provide context about: - - The sales use case (live on calls with prospects) - - The specific UI element being written for - - The current text (if revising) -**Tone:** Confident, concise, client-facing. Not marketing fluff. This is a tool used live. -**Rule:** Copy is UX. Every label guides behavior. Every nudge drives a decision. - -### Calculation Validator — Opus -**When:** After ANY change to `quote-engine.js`, `quote-pricing.js`, `package-prices-data.js`, or sidebar render values. -**How:** - 1. Run `node tests/test-quote-engine.js` — all 254 must pass - 2. Manually verify 2+ quote configs against the verification matrix in `docs/MASTER-SESSION-PROMPT.md` (Priority 4) - 3. Cross-check sidebar display values against engine output - 4. Verify admin fee floor/threshold logic at edge cases (0 users, 1 endpoint) - -### QA / Regression Tester — Opus -**When:** After any visual, structural, or behavioral change. -**How:** Run the validation pipeline below. Use Playwright MCP for visual verification. -**Reference:** `docs/regression-checklist.md` for full manual QA procedures. - ---- - -## Validation Pipeline - -After every change, validate in order. Stop and fix at the first failure. +9 modular CSS files loaded via `SVS-MSP-Calculator.css` (master import): ``` -1. TESTS node tests/test-quote-engine.js (254/254 must pass) -2. SYNTAX No console errors on fresh browser load -3. THEMES Playwright: verify Dark, Light, Glass all render correctly -4. MOBILE Playwright: verify at 375px — floating MRR pill, bottom sheet, sync -5. PRINT If CSS touched: verify print output is unaffected -6. PERSISTENCE If state/form touched: save → reload → verify all values restore -7. EXPORT If export touched: JSON export valid, version field present +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. -## Hard Constraints +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. -These are inviolable. Every change must preserve them. +### Mobile Sync -| # | Constraint | -|---|-----------| -| 1 | **DOM IDs are a contract.** `mobile-sync.js` maps 100+ ID pairs (desktop ↔ `_m` suffix). Renaming breaks sync silently. | -| 2 | **Quote math is sacred.** Any `quote-engine.js` or `quote-pricing.js` change requires test validation. | -| 3 | **localStorage round-trip must work.** Key: `svs-msp-quote-v1`. Verify after form/state changes. | -| 4 | **All 3 themes must work.** Dark (flagship), Light, Glass. Token/component changes cascade to all. | -| 5 | **Mobile parity maintained.** Sidebar clone in mobile panel must stay in sync. Usable at 375px. | -| 6 | **Print/PDF tested after CSS changes.** Print CSS is sensitive to component class changes. | -| 7 | **No framework or build-tool migration.** Vanilla JS by design. | -| 8 | **No broad rewrites.** Surgical, approved changes only. | -| 9 | **Read before editing.** Always inspect current code before making changes. | -| 10 | **Ask before assuming.** When requirements are ambiguous, ask the user. | +`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. --- -## Regression Hotspots +## Invariants -| Area | Risk | Why | -|------|------|-----| -| `quote-engine.js` math | Critical | Wrong quotes in real sales calls | -| localStorage round-trip | High | Silent failures lose configured quotes | -| Mobile sync ID map | High | 100+ pairs desync silently if IDs change | -| Print/PDF CSS | Medium | Separate cascade, sensitive to class changes | -| Theme switching | Medium | All 3 themes affected by token changes | -| `update()` call chain | Medium | Side effects cascade: calc → render → sidebar → nudges → summaries → save | +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 | --- -## Installed Plugins & Skills +## Working Rules -### Plugins (use when applicable) +How Claude behaves while working. Not testable — behavioral. -| Plugin | When to Use | -|--------|-------------| -| `superpowers` | Orchestration: planning, agents, reviews, TDD, debugging, branch mgmt | -| `frontend-design` | Frontend design patterns and implementation | -| `code-review` | Structured code review | -| `code-simplifier` | Simplification and cleanup passes | -| `playwright` | Browser automation, visual verification, screenshot comparison | -| `claude-md-management` | Maintaining this CLAUDE.md file | -| `skill-creator` | Creating new custom skills for this project | - -### Skills (ui-ux-pro-max) - -| Skill | When to Use | -|-------|-------------| -| `ui-ux-pro-max` | Main design intelligence — styles, colors, typography, UX rules | -| `design-system` | Token architecture, component specs | -| `brand` | Voice, visual identity, messaging consistency | -| `ui-styling` | Component styling (translate to vanilla CSS) | -| `design` | Logo, icons, visual assets | -| `banner-design` | Marketing banners and heroes | -| `slides` | HTML presentations | - -**Search command** (requires Python 3): -```bash -python3 .claude/skills/ui-ux-pro-max/src/ui-ux-pro-max/scripts/search.py "" --domain -``` -Domains: `style`, `color`, `typography`, `product`, `landing`, `chart`, `ux` +1. **Read before editing** — always inspect current code first +2. **Quote engine is locked** — no changes to `quote-engine.js`, `quote-pricing.js`, or `package-prices-data.js` without explicit approval +3. **No frameworks, no build tools** — vanilla JS by design +4. **No broad rewrites** — surgical, approved changes only +5. **Ask before assuming** — when requirements are unclear, ask --- -## Commit Protocol +## Do Not Touch -- One concern per commit. Do not bundle unrelated changes. -- Message format: `: ` -- Examples: `css: fix glass theme sidebar blur — backdrop-filter not applying at 900px` -- Examples: `engine: correct admin fee at zero users — floor logic was bypassed` -- Do not commit temp files or `.bak-focusmode` files. -- Run validation pipeline before committing. -- Use `superpowers:finishing-a-development-branch` for final commit + cleanup. +| 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 -1. **Sales clarity over visual novelty.** Prospects must read numbers at a glance. -2. **Trust through polish.** Misaligned inputs erode prospect confidence. -3. **Progressive disclosure.** Lead with MRR total. Detail unfolds on demand. -4. **Feedback immediacy.** Every input change updates sidebar within 1 frame. -5. **Dark theme is the flagship.** Light and Glass must meet the same bar. -6. **The sidebar is the hero.** Design it like a financial summary, not a DOM dump. -7. **Copy is UX.** Labels, nudges, and button text are design decisions. -8. **Mobile is first-class.** A sales rep on a tablet must run a full quote. +1. **Sales clarity over visual novelty** — prospects read numbers at a glance +2. **The sidebar is the hero** — treat it like a financial summary +3. **Dark theme is flagship** — Light and Glass must meet the same bar +4. **Copy is UX** — every label and nudge is a design decision +5. **Mobile is first-class** — a sales rep on a tablet must run a full quote --- -## File Reference +## Architecture -See `docs/QUICK-REF.md` for the complete file map, DOM IDs, and pricing constants. +### HTML Structure -| Category | Key Files | -|----------|-----------| -| Orchestration | `SVS-MSP-Calculator.js`, `SVS-MSP-Calculator.html` | -| Quote Engine | `quote-engine.js`, `quote-pricing.js`, `package-prices-data.js` | -| Rendering | `quote-render.js`, `mobile-sync.js`, `theme-manager.js` | -| Persistence | `quote-persistence.js`, `quote-export.js`, `quote-import.js` | -| CSS Tokens | `SVS-MSP-Calculator-tokens.css` (source of truth for design tokens) | -| CSS Themes | `*-light.css`, `*-glass.css` | -| CSS Layout | `*-layout.css`, `*-components.css`, `*-responsive.css`, `*-print.css` | -| Tests | `tests/test-quote-engine.js` (254 tests, zero deps) | -| Docs | `docs/QUICK-REF.md`, `docs/SESSION-HANDOFF.md`, `docs/MASTER-SESSION-PROMPT.md`, `docs/quote-rules.md`, `docs/DECISION-LOG.md`, `docs/KNOWN-ISSUES.md` | +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 + +1. Read `docs/SESSION-HANDOFF.md` — current state of the project +2. Run `node tests/test-quote-engine.js` — confirm 254/254 +3. 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 constants +- `docs/quote-rules.md` — pricing / business logic +- `docs/DECISION-LOG.md` — has this decision already been made? +- `docs/KNOWN-ISSUES.md` — is this bug already tracked? + +--- + +## Session End + +1. Run `node tests/test-quote-engine.js` — all 254 must pass +2. Update `docs/SESSION-HANDOFF.md` as 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 +3. Commit if approved by user — one concern per commit diff --git a/dark-footnote-after.png b/dark-footnote-after.png new file mode 100644 index 0000000..4560773 Binary files /dev/null and b/dark-footnote-after.png differ diff --git a/dark-sidebar-after.png b/dark-sidebar-after.png new file mode 100644 index 0000000..03c29e4 Binary files /dev/null and b/dark-sidebar-after.png differ diff --git a/dark-theme-full.png b/dark-theme-full.png new file mode 100644 index 0000000..3314f25 Binary files /dev/null and b/dark-theme-full.png differ diff --git a/docs/CHECKPOINT.md b/docs/CHECKPOINT.md deleted file mode 100644 index 9081ddf..0000000 --- a/docs/CHECKPOINT.md +++ /dev/null @@ -1,400 +0,0 @@ -# SVS MSP CALC — Beta Build Checkpoint - -**Date:** 2026-03-15 -**Status:** Phases 1–8 + Stage 8 complete. Beta + a11y/perf audit + code quality passes I & II + test expansion + print enhancements done. -**Tests:** 254/254 passing -**Build Prompt:** .claude/plans/STAGE2-BUILD-PROMPT.md -**Previous Stage Prompt:** docs/STAGE3-SESSION-PROMPT.md -**Previous Stage Prompt:** docs/STAGE5-SESSION-PROMPT.md -**Previous Stage Prompt:** docs/STAGE6-SESSION-PROMPT.md -**Previous Stage Prompt:** docs/STAGE7-SESSION-PROMPT.md -**Previous Stage Prompt:** docs/STAGE8-SESSION-PROMPT.md - ---- - -## Completed - -### Phase 1: Bug Fixes (6/6) - -| # | Issue | File | Change | -|---|-------|------|--------| -| 1.1 | ADDON_INKY default $5 → $8 | quote-pricing.js:12 | `ADDON_INKY: 5` → `8` | -| 1.2 | Onboarding fee loses manual override on term switch | SVS-MSP-Calculator.js:41-70 | Store manual value in `data-manual-value` before 24mo clears it; restore on switch back to m2m/12mo | -| 1.3 | VoIP fax CSV comment misleading | package-prices.csv:18 | "Flat/mo" → "Per seat/mo" | -| 1.4 | Print forces HST on regardless of user toggle | quote-export.js:12 | Removed `state.hstEnabled = true;` — print now respects user's HST toggle | -| 1.5 | JSON export missing schema version | quote-export.js:229 | Added `version: '1.0'` as first field in payload | -| 1.6 | ZT admin supplement triggers with no warning | quote-render.js:494-499 | New amber nudge when `ztActive` warns about $250 admin supplement | - -Test expectations updated in test-quote-engine.js for INKY $8 (4 values changed). - -### Phase 2: Visual Polish (Sections I–III) - -| # | Issue | File | Change | -|---|-------|------|--------| -| 2.1a | Hardcoded `#e06070` danger icon | components.css:41 | → `var(--text-danger)` — adapts per theme | -| 2.1b | Hardcoded `#86efac` pill-savings on checked state | components.css:442 | → `var(--text-pill-savings-active)` — new token | -| — | Token added to all 4 themes | tokens.css, light.css, glass.css, 70retro.css | Dark: `#86efac`, Light: `#d4f5e0`, Glass: `#a8f0c8`, Retro: `#e0f0d0` | -| 2.1c | QUICK-REF.md outdated | docs/QUICK-REF.md | Updated INKY $8, export desc, theme list, test count | - -**Audit findings (no action needed):** -- All 4 themes fully token-covered for Sections I–III -- Glass theme uses `!important` selector overrides (valid for glassmorphism effects) -- Sidebar focus-toggle white rgba values sit on colored header — correct everywhere -- No remaining hardcoded colors in Sections I–III component CSS -- Sidebar renders correctly across all 4 themes at all breakpoints - -### Phase 3: UX Hardening (Sections I–III) - -#### 3.1 Interaction Refinements - -| # | Change | Files | Details | -|---|--------|-------|---------| -| 3.1a | Smooth theme-switch transition | tokens.css, theme-manager.js | `body.theme-transitioning` class enables 0.25s color/bg/border fade; applied for 300ms during `toggleTheme()` | -| 3.1b | Nudge crossfade on rotation/nav | components.css, quote-render.js | `.nudge-fading` class fades opacity to 0; `cycleNudge()` does fade-out → swap → fade-in (180ms); auto-rotation now uses `cycleNudge(1)` for consistency | -| 3.1c | Summary badge fade-in on collapse | components.css | `@keyframes badgeFadeIn` — 0.25s opacity + translateY animation on `.sec-summary-badge` | -| 3.1d | Addon toggle micro-feedback | components.css | `@keyframes addonPulse` — 0.2s scale(1.015) pulse on `.addon-row.selected` | - -#### 3.2 Responsive Edge Cases - -| # | Change | Files | Details | -|---|--------|-------|---------| -| 3.2a | Touch targets ≥44px on mobile | responsive.css | `.mobile-panel-close-btn` 36→44px, `.nudge-nav-btn` 34→44px at ≤1100px; `.collapsible-header` and `.section-toggle` min-height 44px at ≤600px | -| 3.2b | Container query fallback verified | — | `@container (max-width: 760px)` for addon rows has adequate fallback via ≤600px media query; no change needed | - -#### 3.3 Mobile Experience Completeness - -| # | Change | Files | Details | -|---|--------|-------|---------| -| 3.3a | Focus trap in mobile panel | mobile-sync.js | `trapFocus()` function keeps Tab cycling within open panel; focus moves to close button on open, returns to pill on close | -| 3.3b | Safe-area insets for notch phones | responsive.css | `padding-bottom: env(safe-area-inset-bottom)` on `.mobile-panel-sheet`; `right: max(14px, env(safe-area-inset-right))` on `.mobile-quote-pill` | - -**GATE: 88/88 tests pass. All JS syntax-checked. CSS brace balance verified.** - ---- - -### Phase 4: Documentation & QA - -| # | Task | Status | -|---|------|--------| -| 4.1 | Update all docs (README, code-verification, quote-rules, phase-roadmap, QUICK-REF, MASTER-SESSION-PROMPT, ai-session-brief) | COMPLETE | -| 4.2 | Full regression checklist walkthrough | COMPLETE — 88/88 automated, 15/15 manual items verified in code | -| 4.3 | Beta definition of done verification | COMPLETE — all 13 criteria pass | - -**Docs updated:** -- README.md — phase status, 88 tests, 4 themes, export description, file map (70retro.css added) -- code-verification.md — date, test count, all Phase 1-3 changes as known-good baseline -- quote-rules.md — onboarding manual override persistence, HST print behavior, JSON export rules, admin nudge -- phase-roadmap.md — Phases 1-4 status, 88 tests -- QUICK-REF.md — test count in "Remind User", 70retro.css in CSS file map -- MASTER-SESSION-PROMPT.md — 88 tests (3 occurrences), 4 themes (6 occurrences), 70retro.css in tree, 4 theme override layers -- ai-session-brief.md — test count updated - -**Regression checklist results:** -- Automated: 88/88 pass -- Manual: All 15 items verified via source code review (admin waive displays, term/onboarding logic, manual override persistence, sidebar sync, mobile panel sync, persistence round-trip, reset behavior, print HST, JSON export, section headers, theme transitions, nudge crossfade, focus trap, safe-area insets, touch targets) - -**Beta Definition of Done: ALL 13 CRITERIA PASS** - -**GATE: PASSED — Beta build for Sections I–III is complete.** - ---- - -### Phase 5: Performance & Accessibility Audit - -| # | Fix | File(s) | Details | -|---|-----|---------|---------| -| A2 | `aria-expanded` on section & collapsible toggles | HTML, SVS-MSP-Calculator.js | Added `aria-expanded="false"` to 12 toggle elements; JS updates dynamically on toggle | -| A3 | Focus trap on reset confirm modal | quote-persistence.js | `trapFocusInModal()` — Tab cycles within modal when open | -| A4 | `aria-label` on stepper buttons | HTML | All 12 step-btn elements have descriptive labels (e.g. "Decrease users") | -| P1 | Glass theme scroll jank on mobile | glass.css | `background-attachment: scroll` at ≤1100px — avoids fixed-bg repaint on iOS | -| P2 | Skip mobile sync on desktop | mobile-sync.js | Guard skips 35+ element sync when panel closed on desktop; forces full sync on `openMobilePanel()` | -| M1 | `sidebarFocusClientName` not in sync map | mobile-sync.js | Added to html sync list — client name now updates in mobile panel | -| M2 | `sl-discount-detail` + `sl-value-onboarding-label` not in sync map | mobile-sync.js | Added to html sync list — contract term label and onboarding label now sync | - -**Not flagged (clean):** Token coverage, `:focus-visible`, mobile focus trap, escape handling, touch targets, `will-change` usage, print CSS isolation, no unused JS. - -**GATE: 88/88 tests pass. All fixes verified.** - -### Font Awesome Icon Fix - -| # | Fix | File | Details | -|---|-----|------|---------| -| FA1 | Icons invisible on `file://` protocol | components.css:44-79 | All 36 FA Sharp Solid SVG file references converted to inline `data:image/svg+xml` URIs — eliminates CORS/`file://` restriction on `mask-image: url()` | - -**Root cause:** CSS `mask-image: url("fontawesomekit/svgs/...")` is blocked by browser security on the `file://` protocol. Inline data URIs bypass this completely. - -**GATE: 88/88 tests pass. Icons render on local file open.** - ---- - -### Phase 6: Code Quality Pass (Stage 3) - -| # | Fix | File(s) | Details | -|---|-----|---------|---------| -| CQ1 | New `--sky` color token | tokens.css, light.css, glass.css, 70retro.css | Per-theme sky/info accent: Dark `#38bdf8`, Light `#0e7490`, Glass `#7dd3fc`, Retro `#a34a14` | -| CQ2 | New `--transition-fast` token | tokens.css | `0.15s` — replaces hardcoded timing in layout.css button transitions | -| CQ3 | Consolidated duplicate button CSS | layout.css:25-47 | `.btn-reset-quote` and `.btn-import-quote` shared 10 identical properties → merged into grouped selector | -| CQ4 | Hardcoded amber hover → token-derived | layout.css:43-46 | `rgba(232,146,15,…)` → `color-mix(in srgb, var(--amber) …%, transparent)` | -| CQ5 | Hardcoded sky blue hover → token-derived | layout.css:47-50, light.css, glass.css, 70retro.css | All `rgba(56,189,248,…)` / `#38bdf8` / `#7dd3fc` / `#a34a14` → `var(--sky)` + `color-mix()` | -| CQ6 | Dead null-check removed | quote-render.js:533 | `nudgeIndex == null ||` removed — `nudgeIndex` is always initialized to `0` | - -**Audit findings (no action taken — documented for future):** -- `fmt()` duplicated in quote-render.js and quote-export.js (both inside IIFEs — intentional isolation, one-liner) -- Spacing magic numbers (14px/16px/20px) used 95+ times — too many touchpoints for surgical migration -- `console.warn()` statements in pricing/persistence/import are intentional error reporting -- No dead functions, no unreachable code, no unused exports across all 8 JS modules - -**GATE: 88/88 tests pass. All 4 themes verified tokenized.** - ---- - -### Phase 7: Test Coverage Expansion (Stage 4) - -| # | Test Group | Count | Details | -|---|-----------|-------|---------| -| T1 | Pricing DEFAULTS integrity | 34 | All required keys exist, types correct, values match spec, frozen, ordering invariants | -| T2 | Engine edge cases & boundaries | 55 | Admin fee thresholds, large counts (100u/100ep), string coercion, invalid inputs (NaN/null/empty), servers-only, VoIP-only, VoIP edge cases, ZT without user addon, admin waived, all addons combined, BYOL term independence, discount rounding | -| T3 | Export JSON schema validation | 18 | Payload structure, field types, version field, contract term labels, licensing labels, pricing sub-object, voip tier null handling | -| T4 | Persistence state shape | 6 | JSON round-trip for strings/numbers/booleans, engine compatibility, zero-state | -| T5 | Import payload mapping | 12 | Contract term reverse-map, full export→import→engine round-trip (MRR, effectiveMrr, mrrWithHst, userTotal, endpointTotal, voipTotal, adminFeeNet, effectiveAnnual) | -| T6 | Quote output invariants | 24 | 6 configs × 4 invariants (effectiveMrr, effectiveAnnual, mrrWithHst, non-negative values) | - -**Total: 88 → 250 tests (162 new). All passing.** - -**GATE: 250/250 tests pass.** - ---- - -### Phase 8: Enhanced Print/PDF (Stage 4) - -| # | Enhancement | File(s) | Details | -|---|------------|---------|---------| -| P1 | Quote notes field | HTML:920, components.css, quote-persistence.js, quote-export.js, quote-import.js | `