# PDF Parity Checklist

## Header

| Area | Expectation | Status |
| --- | --- | --- |
| Company block | Static company branding and contact text render from template | Partial |
| Customer block | `customer_name`, `customer_addr`, `customer_tel`, `customer_email`, `customer_att` render from mapping registry | Match |
| Document references | `quotation_code`, `quotation_date`, `project_name`, `site_location` render from live quotation data | Match |

## Commercial Body

| Area | Expectation | Status |
| --- | --- | --- |
| Items | `items_table` columns stay aligned with quotation item rows and totals | Match |
| Topics | Dynamic topic engine expands `topic_*` / `item_topic_*` in order | Match |
| Exclusion block | `exclusion_data` renders as `string[][]` table payload | Match |
| Price summary | `quotation_price` and `currency` use formatted runtime values | Match |

## Approval / Footer

| Area | Expectation | Status |
| --- | --- | --- |
| Signatures | `app1/app2/app3` map to prepared/approved/authorized blocks | Match |
| Signature placement | Closing block stays together after dynamic topic pagination | Partial |
| Footer copy | Static footer text and closing statement remain template-owned | Match |

## Visual Parity Rules

- `Match` means the current PDF runtime has a verified mapping path and auditable payload.
- `Partial` means the business data path is correct but final pixel-perfect comparison still needs manual screenshot review against the legacy CRM PDF.
- `Missing` should only be used when a field or section has no runtime path.

## Integrity Freeze

- `npm run audit:pdf` is the integrity gate for template, placeholder, payload, topic runtime, and snapshot parity.
- `QT-H5-AUDIT` is the preferred fixture for repeatable PDF audits.
