From 4a896e72e31c57a0d8b8ea38e9f65b47dc0e9e1d Mon Sep 17 00:00:00 2001 From: Thomas Hackner Date: Fri, 3 Jul 2026 18:04:52 +0200 Subject: [PATCH] Restyle cover letter to match the CV as one application set MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bring the Anschreiben into the résumé's visual language: navy name, tracked role line, the shared hairline-plus-accent-bar rule under the letterhead, and a navy bold subject line as the letter's headline. Keep strict DIN-5008 structure (recipient block, right-aligned date, subject, salutation/closing, signature space, enclosures) and near-black body for readability. Co-Authored-By: Claude Opus 4.8 --- lib/documents.js | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/lib/documents.js b/lib/documents.js index 5cb04b4..49e9ce9 100644 --- a/lib/documents.js +++ b/lib/documents.js @@ -850,11 +850,13 @@ const LET = { mx: 25, mr: 20, top: 24, bottom: 18 }; // DIN-ish margins const LET_R = PAGE.w - LET.mr; // 190 const LET_W = LET_R - LET.mx; // 165 -// Restrained grayscale palette — no accent colours. +// Grayscale body with the same deep navy-slate accent as the résumé, so the +// cover letter and CV read as one deliberately designed application set. const LC = { ink: [26, 26, 26], muted: [92, 98, 106], hair: [206, 208, 212], + accent: [31, 64, 104], }; // Extract just the town from a possibly-full address ("Feldstraße 76, 45968 @@ -874,10 +876,10 @@ function composeLetter(doc, S, dry, cur, { letter, header, job, anlagen, signatu const betreff = letter.betreff || (job.stelle ? `Bewerbung als ${job.stelle}` : 'Bewerbung'); const stadt = cityName(header); // just the town for the date line ("Ort, den …") - // --- Letterhead: name (left) + contact (right), thin rule --- + // --- Letterhead: name (left) + contact (right), accented rule --- const top = cur.y; - write(doc, S, dry, cur, header.name, { pt: 16, style: 'bold', color: LC.ink, x, width: width * 0.55, factor: 1.15 }); - if (header.headline) write(doc, S, dry, cur, header.headline, { pt: 9.5, color: LC.muted, x, width: width * 0.55, factor: 1.2 }); + write(doc, S, dry, cur, header.name, { pt: 17, style: 'bold', color: LC.accent, x, width: width * 0.55, factor: 1.15 }); + if (header.headline) write(doc, S, dry, cur, header.headline, { pt: 10, color: LC.muted, x, width: width * 0.55, factor: 1.25, charSpace: 0.2 }); const leftBottom = cur.y; const contactLines = []; @@ -887,8 +889,17 @@ function composeLetter(doc, S, dry, cur, { letter, header, job, anlagen, signatu const rc = { y: top }; contactLines.forEach((line) => write(doc, S, dry, rc, line, { pt: 9, color: LC.muted, x, width, align: 'right', right, factor: 1.32 })); + // Hairline across, with a short heavier accent segment at the start — the + // same motif that anchors every section of the résumé. cur.y = Math.max(leftBottom, rc.y) + 3 * S; - rule(doc, S, dry, cur.y, x, right, LC.hair, 0.3); + if (!dry) { + doc.setDrawColor(LC.hair[0], LC.hair[1], LC.hair[2]); + doc.setLineWidth(0.3 * S); + doc.line(x, cur.y, right, cur.y); + doc.setDrawColor(LC.accent[0], LC.accent[1], LC.accent[2]); + doc.setLineWidth(1.0 * S); + doc.line(x, cur.y, x + 15 * S, cur.y); + } cur.y += 13 * S; // --- Recipient (Anschriftfeld) — from the LLM's empfaenger, falling back to job --- @@ -905,9 +916,9 @@ function composeLetter(doc, S, dry, cur, { letter, header, job, anlagen, signatu const dateLine = stadt ? `${stadt}, den ${today}` : today; write(doc, S, dry, cur, dateLine, { pt: 10, color: LC.ink, x, width, align: 'right', right, factor: 1.2 }); - // --- Subject (bold, no "Betreff:" label) --- + // --- Subject (bold navy, no "Betreff:" label) — the letter's headline --- cur.y += 7 * S; - write(doc, S, dry, cur, betreff, { pt: 11, style: 'bold', color: LC.ink, x, width, factor: 1.3 }); + write(doc, S, dry, cur, betreff, { pt: 11, style: 'bold', color: LC.accent, x, width, factor: 1.3 }); // --- Salutation + body --- cur.y += 6 * S;