QA #1110 — Polish visuel du PDF de contrat Sortie réelle du builder PUR contract-html.builder.ts (rendu Chromium/Paged.js). Comparaison AVANT (origin/master) vs APRÈS (feat/1110-contract-pdf-polish), même contrat de test. Améliorations vérifiées (cf. QA-proof-1110.png, 1110-before.png, 1110-after.png) : 1. Champs société vides masqués — les lignes « Adresse du siège social : », « N° SIRET : », « Code APE : » sans valeur (bloc PRODUCTEUR) sont retirées du rendu (AVANT: visibles/inachevé). 2. Blocs de signature en encarts légers bordés (#f9fafb / bordure #d1d5db, coins arrondis, libellés en capitales d'accent) aux 3 placements. 3. Titre principal centré souligné d'un filet d'accent ; titres d'article à filet d'accent. 4. Corps justifié + césure ; tableau à en-tête tramé (#f1f5f9) + bordures fines. 5. Hygiène : paragraphes/items vidés par la substitution masqués (:empty) ; veuves/orphelines + pas de titre seul en bas de page (break-after: avoid). Robustesse champs vides : liste curée de libellés connus (SIRET, APE, Adresse, IBAN, BIC, Représentant, TVA, …) — zéro faux positif sur de la prose ; un champ AVEC valeur est conservé ; les titres (h1/h2/h3) ne sont jamais retirés. Gate de tests (Node 24) : - Unitaires builder : test/contract-html.builder.test.ts → 19 passed (dont 9 nouveaux #1110). - Suite unit complète (CI) : 131 passed ; typecheck vert. - Non-régression : generateContractPdf (zéro balise brute) + e2e contrat OK. Aucun secret dans les preuves (données synthétiques).