feat(campaigns): apply real TARGO brand + auto-route FR/EN by Customer.language
Brand audit against the official guide (Feb 2026 v1.0) caught several
inconsistencies in the email template:
- Wrong primary green: was #019547, should be #00C853 (Targo Green from
brand palette). Globally replaced.
- Wrong gradient: was #019547→#06a04d, should be 135deg #00C853→#005026
(the official Gradient Targo from the brand). Now using Outlook-safe
background-image + bgcolor fallback for solid green on Outlook desktop.
- Wrong contact info: facturation@targointernet.com / 514 242-1500 →
support@targo.ca / 514 448-0773 / 1 855 888-2746 (per §11 of guide).
- Wrong website: targointernet.com + gigafibre.ca → www.targo.ca.
- Missing slogan + green dot: footer now ends with the trademark
tagline "Services de confiance, tout-en-un, près de chez vous." with
the obligatory green period (always FR — it's the trademark, not a
marketing line, so stays untranslated in EN template too).
- Missing brand fonts: added Space Grotesk (display) + Plus Jakarta
Sans (body) via Google Fonts. Wrapped in MSO conditional comments so
Outlook desktop skips the request and falls back to Helvetica via
the explicit font-family stack on every element.
- Wrong body bg / text colors: now #F5FAF7 (Muted) / #1B2E24
(Foreground) per brand semantic palette.
- Wrong info-pill bg: was #f3f4f3 → #F5FAF7 (Muted).
- Added official dark footer band #1C1E26 (Targo Dark) with white
inverted wordmark, slogan, address, copyright.
Multilang routing (FR/EN):
- lib/campaigns.js matchCustomer now fetches Customer.language
(14k FR / 1k EN distribution confirmed on prod). Default 'fr' for
unmatched contacts.
- New templateForLanguage(lang) helper picks gift-email-<lang>.html,
falls back to FR. Resolves 'fr-CA' → 'fr' etc.
- sendCampaignAsync pre-loads templates per recipient with an in-memory
cache to avoid re-reading from disk on every send.
- gift-email-en.html created — English translation of the full FR
template, keeping the slogan in French (it's the trademark tagline).
- year variable now injected (replaces hardcoded © year).
UI (CampaignNewPage):
- New "Langue" column in the Step 2 recipient table. Shows a clickable
chip (FR primary green / EN blue-grey) that toggles language inline,
so a campaign manager can override the ERPNext-resolved language
per recipient.
- Step 3 recap now shows "Répartition par langue: 145 × FR, 12 × EN"
before confirming the send.
Spell-check:
- TemplateEditorPage HTML mode now has spellcheck="true" + dynamic
lang attribute on the textarea, picked from the template name suffix
(gift-email-fr → fr, gift-email-en → en). Browser's native dictionary
flags typos in real time. AI-grade rewrites deferred to the future
/campaigns/ai/rewrite endpoint discussed previously.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>