Reading all eight files for an independent review across the listed defect categories.
Searching for em dashes, side-stripe patterns, and verifying assets exist.
## Verdict

**[OK] Ship-ready demo with one real handoff gap and a few UX/mobile nits.** Nav/`aria-current` are correct per page, calculator math matches published rates, assets resolve, and the normal left-click estimate flow works. I found no broken internal links and no user-facing em dashes or side-stripe accent borders.

**Confidence: high** on nav/math/links; **medium** on narrow-mobile layout (CSS-only inference, not browser-tested).

---

## 1. Cross-page header / footer / nav

**[OK] Header structure is consistent** across all six pages: same brand, six nav links, phone, theme toggle, mobile menu (`navLinks`, `navToggle`, `themeToggle`).

**[OK] `aria-current="page"` is correct** on every page:

| Page | Active link |
|------|-------------|
| `index.html:38` | Home |
| `services.html:26` | Services |
| `pricing.html:27` | Pricing |
| `calculator.html:28` | Estimate |
| `about.html:29` | About |
| `contact.html:33` | Contact |

**[WARN] Footer disclaimer copy drifts** (not broken, but inconsistent):

- `index.html:152` — longest (estimator + tailored quote)
- `about.html:112` — no pricing disclaimer at all
- `contact.html:106` — form-not-wired note only

**[INFO] Cosmetic head-script formatting** differs (`index.html` expanded vs minified on other pages). No functional impact.

---

## 2. Calculator → contact estimate handoff

**[OK] Normal left-click path works.** Flow:

```140:153:D:\ClaudeTools\projects\acg-website-showcase\multipage\js\app.js
    var sendBtn = $("#sendEstimate");
    if (sendBtn) {
      sendBtn.addEventListener("click", function () {
        // ... builds summary from #ledgerLines ...
        try { sessionStorage.setItem("acg-estimate", summary); } catch (e) {}
      });
    }
```

```192:201:D:\ClaudeTools\projects\acg-website-showcase\multipage\js\app.js
    var msg = $("#cf-msg");
    if (msg) {
      try {
        var est = sessionStorage.getItem("acg-estimate");
        if (est) {
          msg.value = est;
          sessionStorage.removeItem("acg-estimate");
```

- `#sendEstimate` is an `<a href="contact.html#contact">` (`calculator.html:124`)
- Click handler is synchronous before navigation — `sessionStorage` is set in time
- `app.js` is at end of `<body>` on `contact.html:109`, so `#cf-msg` exists before prefill runs
- Anchor target `#contact` exists (`contact.html:43`)

**[OK] JS-before/after hash jump is not a data bug.** Script runs after DOM parse; hash scroll does not block prefill.

**[ERROR] Middle-click / “Open in new tab” drops the estimate.** `#sendEstimate` is a plain link; middle-click and some modifier opens navigate without firing the `click` listener, so `acg-estimate` is never written. Left-click only.

**[WARN] Hash lands on section top, not the form.** `contact.html#contact` scrolls to the section (`id="contact"`), not `#cf-msg` / `#contactForm`. On desktop two-column layout, the prefilled textarea can be off-screen right; user may not see the handoff without scrolling.

**[WARN] No focus management after prefill** — textarea is filled but never focused/scrolled into view.

**[INFO] One-shot storage** — reload clears the estimate (`removeItem` on read). Intentional, but worth knowing.

---

## 3. Calculator math and stepper clamp

**[OK] Math matches pricing page rates:**

| Input | Rate | Source |
|-------|------|--------|
| GPS tiers | $19 / $26 / $39 | `app.js:99`, `pricing.html:56-82` |
| Equipment | $25 flat | `app.js:78`, `pricing.html:94` |
| Support | $200–$850 | `app.js:94`, `pricing.html:108-111` |
| M365 | $14/user | `app.js:78`, `pricing.html:154` |
| VoIP | $28/user | `app.js:78`, `pricing.html:166` |
| Hosting | $15 / $35 / $65 | `app.js:97`, `pricing.html:141-143` |

Default (22 endpoints, Pro, Standard support): **$952/mo** — arithmetic checks out.

**[OK] Stepper clamp** — `clampInt` 0–500 (`app.js:80`), HTML `min="0" max="500"`, buttons use clamp + `recalc()`.

**[WARN] Typing invalid numbers** — `recalc()` uses clamped value on `input`, but the visible field can still show garbage until `change` blur clamp (`app.js:136`). Totals can disagree with displayed digits briefly.

---

## 4. Links, assets, duplicate IDs

**[OK] All internal page links resolve** — `index`, `services`, `pricing`, `calculator`, `about`, `contact`, `tel:`, `mailto:`.

**[OK] Referenced images exist** under `assets/images/`: `hero.png`, `about.png`, `services.png`, `story.png`, `contact.png`.

**[WARN] Duplicate `id="cta-h"`** on four pages (`index.html:137`, `services.html:88`, `pricing.html:179`, `about.html:97`). Harmless in multipage navigation; invalid if pages were ever combined.

**[WARN] Shared IDs across pages** (`year`, `navLinks`, `themeToggle`, etc.) — same note; one page at a time so no runtime collision.

---

## 5. Light + dark contrast (new components)

**[OK] Token design is deliberate** — `--ink-3` annotated AA-safe on light paper (`styles.css:14`); dark tokens mirrored (`styles.css:32-44`).

**[OK] New multipage components** (active nav underline, page-head eyebrow, contact labels, CTA band, office figure) use `--ink`, `--ink-2`, `--ink-3`, `--accent-ink` — consistent with the system.

**[WARN] `.calc__foot` at 0.78rem / `--ink-3`** (`styles.css:374`) — likely fine in light mode; dark-mode small muted text is the usual borderline case. Worth a quick contrast pass in browser, not a confirmed fail.

**[OK] Primary buttons** — `--on-accent` on `--accent` is an intentional pairing (`styles.css:18-19, 118`).

---

## 6. Em dashes and side-stripe accents

**[OK] No em dashes in user-facing HTML** across any of the six pages.

**[WARN] Em dashes only in CSS comments** (`styles.css:2, 17`) — violates house style in source, not visible to visitors.

**[OK] No forbidden side-stripe accent borders.** Only structural rules: `.calc__inputs { border-right: 1px solid var(--rule) }` (`styles.css:310`), `.tier--pop` top inset accent (`styles.css:263`). Matches DESIGN intent (no colored left/right accent stripes).

---

## 7. Mobile

**[OK] Major breakpoints covered** — nav drawer @880px, hero/story/calc/contact/CTA stack @760–820px, trust 2-col @720px, tables scroll via `.table-wrap`.

**[WARN] Calculator rows stay two-column on all widths** — `.calc__row { grid-template-columns: 1fr auto }` (`styles.css:311-312`) with no narrow override. Stepper is ~152px fixed; on ~320px viewports labels + controls may crush or overflow.

**[WARN] `.svc__meta { white-space: nowrap }`** (`styles.css:251`) — on very narrow screens, right-aligned meta could overflow when not yet in stacked mobile layout.

**[OK] Mobile nav** — `aria-expanded` toggles, Escape closes, link click closes drawer (`app.js:57-69`).

**[ERROR] Progressive enhancement gap** — `.reveal { opacity: 0 }` (`styles.css:427`) until `app.js` adds `.in`. If JS fails, large sections stay invisible sitewide.

---

## Ranked top fixes

| Rank | Severity | Issue | Where |
|------|----------|-------|-------|
| **1** | **[ERROR]** | Estimate handoff fails on middle-click / open-in-new-tab because storage write is click-only on an `<a>` | `calculator.html:124`, `app.js:140-153` |
| **2** | **[ERROR]** | Content hidden without JS (`.reveal` starts at `opacity: 0`) | `styles.css:427-428`, all pages |
| **3** | **[WARN]** | After handoff, user may not see prefilled message (hash → section, not form; no focus/scroll) | `calculator.html:124`, `contact.html:43-76`, `app.js:192-201` |
| **4** | **[WARN]** | Calculator input rows don’t stack on very narrow phones | `styles.css:311-312, 375-378` |
| **5** | **[WARN]** | Invalid stepper text vs calculated total until blur | `app.js:136-137, 156-157` |
| **6** | **[INFO]** | Footer disclaimer text inconsistent | all footers |
| **7** | **[INFO]** | Duplicate `id="cta-h"` across four pages | see §4 |
| **8** | **[INFO]** | Em dashes in CSS comments only | `styles.css:2, 17` |

---

**Bottom line:** The multipage shell is coherent and the primary estimate workflow is sound. Fix **#1** (handoff reliability) and **#2** (no-JS visibility) first; the rest are polish. I did not modify any files per your instruction.
