# CAREER-002 CV Builder redesign

Updated: 2026-08-24

Status: `IMPLEMENTED — NOT VERIFIED`. Repository, automated and pathological Chromium/PDF gates are complete; authenticated application-browser and production gates remain.

## 2026-08-24 professional-builder increment

- Split the editor into Content, Template, Design, Layout, AI and History workspaces under a compact
  document toolbar with editable name, autosave/retry state, undo/redo, duplicate, public link and PDF.
- Added normalized print-safe colour, typography, spacing, A4/Letter, language/date, skills and
  one/two-column controls. The same settings and renderer drive live preview, public output and PDF.
- Replaced the infinite preview with labelled measured page sheets, mobile Edit/Preview switching,
  fit/zoom/page navigation and horizontal-overflow reporting.
- Added real rendered demo thumbnails for all eight templates. Demo content is constructed in memory
  by a read-only endpoint and is never stored in a user's master profile or CV.
- Expanded structured contacts with GitHub and validated custom links; added Norwegian default labels,
  `nå` and configurable date formats.
- Hardened CV/job association so a foreign tenant's numeric job ID is rejected by the service and API.
  Dashboard cards now show the authorized associated role/company instead of only an internal ID.
- Added explicit Original/Suggested AI review with Accept/Reject/Edit and a measurable-impact action
  that asks for placeholders rather than inventing metrics.
- Frontend gates after this increment: TypeScript pass, optimized production build pass, 61/61 Jest
  suites and 246/246 tests. Backend/migration/PDF reruns are blocked locally by the missing .NET 9 SDK;
  the new backend paths have focused tests ready for the normal SDK/CI gate.

## Revalidated capability matrix

| Requirement | Existing implementation | Current status |
|---|---|---|
| Ordered section list | Default plus persisted section order | Implemented; browser pending |
| Expand/collapse | Entry-based sections use explicit collapse controls | Implemented; deeper tests pending |
| Inline editing | Section title and per-entry title/subtitle/bullets overrides | Implemented; validation depth pending |
| Add entries | Explicit custom-section entries; master entries remain profile-owned | Implemented; browser pending |
| Delete entries/sections | Confirmed deletion for populated custom entries/sections; profile entries hide instead of mutating the profile | Implemented; browser pending |
| Reorder sections/entries | Native drag plus named up/down keyboard buttons | Implemented and persistence-tested |
| Visibility | Named section/entry/custom-section hide/show controls | Implemented and persistence-tested |
| Save feedback | Unsaved/Saving/Saved/failed badge existed | Hardened in `b58cc19` |
| Navigation safety | Debounced/failed state could be abandoned silently | Hardened in `b58cc19` |
| Preview | Debounced live server render beside editor; visible failure/retry; below editor on narrow layout | Implemented; responsive/browser review pending |
| Versions/public/PDF | Existing history/restore, public toggle/link and PDF export | Preserved; regression/production gates remain |

## Multi-page/rendering increment

- Removed page-level clipping and added wrapping/min-width protections for names, titles, employers, contact values, URLs, tags and two-column content.
- Short entries remain intact. Large entries and large list items flow at safe internal boundaries instead of becoming unsplittable blocks taller than a page.
- The legacy job-specific CV templates receive the same wrapping/pagination rules; sidebar values are now HTML-encoded consistently.
- Preview measures both document/body height, uses the selected A4 or Letter dimensions, applies ceiling-based page counts, exposes real Fit/percentage controls, and reports horizontal overflow.
- Three-page and longer CVs receive content-density guidance. Text size is not silently reduced.
- Custom sections now participate in the same section order as master-profile sections.
- Autosaves are serialized; stale preview responses are ignored; export/public actions save pending edits first.
- CV deletion and version restore use the shared application dialog system.
- The non-functional page-number switch is no longer advertised; `ShowPageNumbers` remains a backward-compatible exporter extension point until the Chromium CLI path supports controlled PDF footers.
- Header-band contact/headline text now owns a computed black-or-white foreground chosen for the stronger WCAG contrast against both theme and custom accents. Sidebar contact/headline text owns `SidebarInk` instead of inheriting the main-page muted colour.
- Accent overrides are restricted to six-digit hex colours and font overrides to the six editor-supported stacks before CSS generation, preventing malformed/public settings from escaping the generated stylesheet.

## Save-integrity increment

- Latest settings/name are retained independently of render closures.
- Monotonic save revisions prevent an older overlapping request from changing a newer edit to `Saved` or `Save failed`.
- Blank names show inline validation and are not sent as misleading no-op renames.
- Unsaved and failed states expose **Save now**; failed saves retry the latest settings.
- Data-router navigation is blocked until the user explicitly confirms discarding pending/failed changes. Reload/tab close uses the browser's before-unload warning.
- The debounce timer is cleared on intentional unmount. Existing version creation and API payloads are unchanged.

## Interaction and error increments

- Custom sections retain the existing `string[]` storage model but expose entries individually: add, multiline edit, inline empty validation, arrow reorder and confirmation before destructive deletion.
- Custom sections can be reordered and hidden without changing the Career Profile. Deleting an original profile-backed entry is intentionally not offered; variant-specific hide/override preserves source-of-truth ownership.
- Profile-backed section and entry controls include the affected section/entry name. Expand controls expose `aria-expanded`.
- Preview failure no longer silently preserves stale output without explanation; an error state and in-context retry are available.

## Verification to date

- Focused Builder list/helper/deep-link/save/navigation: 3 suites, 21/21 tests; editor deep-link/interaction 9/9.
- Focused renderer/template backend: 25/25 tests, including header/sidebar contrast ownership and visual-override sanitization.
- Full frontend: 49/49 suites, 184/184 tests.
- Production build/TypeScript and `git diff --check`: pass.
- Pathological Chromium render: 14 long roles, 75 long skills, oversized name/email/URL, zero horizontal-overflow elements, nine-page PDF (173,196 bytes) with extractable final-page content.
- Contrast rerun in real Chromium: Modern default computed white on `rgb(37, 99, 235)`, light custom accent computed black on `rgb(248, 250, 252)`, Technical sidebar computed white on `rgb(15, 76, 92)`, and all three reported zero element overflow at a 1400px viewport. The harder 14-role/75-skill fixture exported a 17-page A4 PDF (259,447 bytes) with 1,685 extractable characters on the final page.
- Implementation commits: `b58cc19`, `a5b74e0`, `2043349` plus the V-165 checkpoint.

## Product research

Public current material for Reactive Resume, Resume.io, Enhancv, Novorésumé, FlowCV and Canva was reviewed. Repeated patterns and adopted/rejected decisions are recorded in `docs/research/cv-builder-patterns.md`. No authenticated/private competitor session was used or claimed.

## Remaining verification

- Run 375/768/1440, Light/Dark, keyboard/focus, empty/error and production synthetic-variant checks.
- Recheck DOCX status honestly: the current architecture documents it as an extension point, while PDF/public rendering are implemented.

## Rollback

Revert `2043349`, `a5b74e0` and `b58cc19` in reverse order. No schema, dependency, configuration, CV data rewrite or version migration is involved.
