feat(correspondance): le format de lettre commerciale devient un gabarit réutilisable
Fixé avec le dossier KissMetrics du 24/08 et validé par l'opérateur : « on peut se souvenir de ce format pour les communications avec KM et futurs prospects/clients ». Il ne servira à rien s'il faut le reconstituer à chaque fois — d'où un gabarit, un script, et les raisons écrites. LE TEST DU GABARIT : la lettre du 24/08 s'en régénère à l'identique, au mot près, vérifié par diff du texte extrait. Un gabarit qui ne reproduit pas son propre exemple n'est pas un gabarit. LES CHOIX, ET POURQUOI. Charter pour le texte — dessinée par Matthew Carter pour tenir le petit corps là où d'autres se délitent — et Optima pour les titres. Les deux incorporées au PDF : le rendu est le même chez le destinataire. Chiffres elzéviriens, pour que les montants s'alignent au lieu de faire des bâtons. Deux encadrés, deux usages : le gris porte une question, le rouge sourd ce qui doit être lu en diagonale — UN SEUL par lettre, deux et plus rien ne ressort. Les tableaux portent un <thead>, sans quoi ils perdent leur en-tête en se coupant entre deux pages. LE PIÈGE, consigné parce qu'il coûte une heure à qui le redécouvre : weasyprint NE SAIT PAS rendre Apple Color Emoji. C'est un format bitmap sbix qu'il ignore, et les trois emblèmes 🏹💻🪽 sortent en carrés vides — sans erreur, sans avertissement. D'où correspondance/emblemes/*.png, rendus une fois pour toutes par test/emoji2png.ts, qui passe par Chromium : lui lit la police système. Les PNG sont incorporés en base64 À LA GÉNÉRATION, pas dans le gabarit : un gabarit de 400 Ko dont 97 % de charabia ne se relit pas. Le PDF produit reste autonome. Les trois emblèmes viennent du site — « Gabriel 🪽 Radureau, pour 🏹 réussir vos projets 💻 ». L'arc et l'ange sont dans le nom lui-même. lettre.py proteste au-delà de deux pages : une lettre d'affaires qui déborde ne se lit pas, et la tentation est alors de rétrécir la typographie plutôt que le propos. C'est le propos qu'il faut resserrer. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8">
|
||||
<title>{{TITRE}} — Arcodange</title>
|
||||
<style>
|
||||
@page { size: A4; margin: 15mm 18mm 13mm 18mm;
|
||||
@bottom-center { content: "{{PIED}} — page " counter(page) " / " counter(pages);
|
||||
font-family: "Optima", "Seravek", sans-serif; font-size: 7.8pt;
|
||||
letter-spacing: .4px; color: #8a8a8a; } }
|
||||
body { font-family: "Charter", "Bitstream Charter", "Iowan Old Style", Georgia, serif;
|
||||
font-size: 9.9pt; line-height: 1.44; color: #14161a;
|
||||
font-feature-settings: "kern" 1, "liga" 1, "onum" 1; }
|
||||
.entete { border-bottom: 1.5px solid #14161a; padding-bottom: 8px; margin-bottom: 16px;
|
||||
display: flex; justify-content: space-between; align-items: flex-end; }
|
||||
.entete .nom { font-family: "Optima", "Seravek", sans-serif; font-size: 17pt;
|
||||
font-weight: 600; letter-spacing: 3.5px; }
|
||||
.marque { margin-top: 7px; }
|
||||
.marque img { height: 16px; vertical-align: -3px; margin-right: 7px; }
|
||||
.signature .qui img { height: 13px; vertical-align: -2px; margin: 0 1px; }
|
||||
.entete .mentions { font-family: "Optima", "Seravek", sans-serif; font-size: 8pt; color: #4a4a4a; line-height: 1.45; text-align: right; }
|
||||
.dest { margin-bottom: 16px; font-size: 10pt; }
|
||||
.dest .a { font-family: "Optima", "Seravek", sans-serif; color: #8a8a8a; font-size: 7.8pt; letter-spacing: .6px; text-transform: uppercase; }
|
||||
h1 { font-family: "Optima", "Seravek", sans-serif; font-size: 14pt; font-weight: 600;
|
||||
margin: 0 0 3px; letter-spacing: .2px; }
|
||||
h1 + .sous { font-style: italic; color: #4a4a4a; margin: 0 0 16px; font-size: 10pt; }
|
||||
h2 { font-family: "Optima", "Seravek", sans-serif; font-size: 10.2pt; font-weight: 600;
|
||||
page-break-after: avoid; margin: 14px 0 5px; padding-bottom: 3px; border-bottom: 1px solid #d8d8d8;
|
||||
letter-spacing: .4px; }
|
||||
p { margin: 0 0 7px; text-align: justify; }
|
||||
strong { font-weight: bold; }
|
||||
em { font-style: italic; }
|
||||
table { width: 100%; border-collapse: collapse; margin: 9px 0 10px; font-size: 8.7pt; }
|
||||
th, td { border-bottom: 1px solid #dcdcdc; padding: 3.5px 8px; text-align: left; }
|
||||
thead { display: table-header-group; }
|
||||
th { font-family: "Optima", "Seravek", sans-serif;
|
||||
background: #f4f4f2; border-bottom: 1px solid #999; font-weight: 600; font-size: 8.2pt;
|
||||
letter-spacing: .5px; text-transform: uppercase; color: #333; }
|
||||
td.n { text-align: right; white-space: nowrap; }
|
||||
tr.due td { background: #fdf6f2; font-weight: bold; }
|
||||
.encart { border-left: 3px solid #8a1c1c; background: #fbf6f5; padding: 8px 12px; margin: 11px 0;
|
||||
font-size: 9.4pt; }
|
||||
.calme { border-left: 3px solid #b8b8b0; background: #f8f8f6; padding: 8px 12px; margin: 11px 0;
|
||||
font-size: 9.4pt; }
|
||||
.signature { margin-top: 17px; page-break-inside: avoid; }
|
||||
.signature .qui { font-family: "Optima", "Seravek", sans-serif; font-weight: 600; font-size: 11pt; }
|
||||
.signature .role { font-family: "Optima", "Seravek", sans-serif; font-size: 9pt; color: #555; }
|
||||
</style></head><body>
|
||||
|
||||
<div class="entete">
|
||||
<div><div class="nom">ARCODANGE</div>
|
||||
<div class="marque"><img src="{{ARC}}" alt=""><img src="{{LAPTOP}}" alt=""><img src="{{AILE}}" alt=""></div></div>
|
||||
<div class="mentions">
|
||||
SARL au capital de 1 000 € — SIREN 999 657 455 R.C.S. Évry<br>
|
||||
73 boulevard de l'Yerres, 91000 Évry-Courcouronnes, France<br>
|
||||
VAT FR00 999 657 455 — [email protected]
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="dest">
|
||||
<span class="a">To</span><br>
|
||||
<strong>{{DESTINATAIRE}}</strong> — {{FONCTION}}, {{SOCIETE}}<br>
|
||||
{{ADRESSE}}<br>
|
||||
<span class="a" style="font-size:7.4pt">cc</span> {{COPIE}}
|
||||
</div>
|
||||
|
||||
<h1>{{TITRE}}</h1>
|
||||
<p class="sous">{{DATE}}</p>
|
||||
|
||||
<p>Dear {{PRENOM}},</p>
|
||||
|
||||
<!-- ═══ CORPS ═══════════════════════════════════════════════════════════════
|
||||
Le contenu, et rien d'autre, change d'une lettre à l'autre. Ce qui suit
|
||||
est l'exemple du 24/08/2026 (dossier KissMetrics), gardé pour montrer les
|
||||
éléments disponibles. Le remplacer intégralement.
|
||||
|
||||
<h2>1 — Titre de section</h2> numérotées, c'est une lettre d'affaires
|
||||
<p>…</p>
|
||||
<div class="calme">…</div> encadré gris : une question, une demande
|
||||
<div class="encart">…</div> encadré rouge sourd : ce qui doit être vu
|
||||
<table>…</table> <thead> obligatoire : l'en-tête se répète
|
||||
<tr class="due">…</tr> ligne mise en avant dans un tableau
|
||||
════════════════════════════════════════════════════════════════════════════ -->
|
||||
|
||||
<h2>1 — Une section</h2>
|
||||
|
||||
<p>Corps de texte en Charter. Les <strong>montants</strong> et les points qui
|
||||
portent la décision se mettent en gras ; les citations en <em>italique</em>.</p>
|
||||
|
||||
<div class="calme">
|
||||
<p style="margin:0"><strong>Une question posée franchement</strong> se met dans
|
||||
un encadré gris — elle ne doit pas se noyer dans un paragraphe.</p>
|
||||
</div>
|
||||
|
||||
<div class="encart">
|
||||
<p style="margin:0">L'encadré rouge sourd est réservé à ce qui doit être lu
|
||||
même en diagonale. <strong>Un par lettre, pas deux.</strong></p>
|
||||
</div>
|
||||
|
||||
<div class="signature">
|
||||
<p class="qui">Gabriel <img src="{{AILE}}" alt=""> Radureau</p>
|
||||
<p class="role">Gérant — Arcodange</p>
|
||||
</div>
|
||||
|
||||
</body></html>
|
||||
Reference in New Issue
Block a user