Add the Northline template family: Purple Pop and Citrus Split

Purple Pop (cream page, purple pills, asterisk and dome decor, opt-in
logo) and Citrus Split (grey split panel, halftone chevrons, icon
contacts, logo in the measured slot) are rebuilt from the Canva PDFs on
the engine with A4/Letter support, GST slots and zero audit errors. Adds
static DM Sans, Jost and Poppins 800 as look-alikes for the commercial
fonts. The picker now lists ten templates.
This commit is contained in:
2026-10-04 09:56:56 +05:30
parent 06976df55c
commit 5ea62a9be8
36 changed files with 3033 additions and 56 deletions
+19
View File
@@ -216,3 +216,22 @@ US Letter is 612 × 792.
Sibling of 13.pdf. They are from the same Canva family, with the same placeholder data ('Northline Group', 'Amy Fletcher', 'Intelligent Bank'), the same DM Sans plus Gotham type system, the same raster 30% shadow effects, and the same SERVICE/QTY/RATE/AMOUNT table with SUBTOTAL/TAX/TOTAL.
The composition is different: pills and asterisks on cream here, versus a split grey column on blush in 13. Keep both and share the data-mapping code. Not similar to 1–11, format.pdf or the in-app template.
## Implementation notes
Built as `src/pdf/templates/northline/` (the family component shared with Citrus Split: `Layout.tsx` dispatches to `PurpleLayout.tsx`, the plans live in `plan.ts`, tokens in `purple.tsx` and `variant.ts`) on the decor primitives in `src/pdf/decor/` (`Asterisk`, `Underlay`, `CircledIcon`). Measured against `12.pdf` with `npm run templates:compare -- purple-pop` (`/tmp/invoice-c5/compare-purple-pop.png`, left Canva, right ours; `--numbers` prints both sets of baselines).
**Matches the design (measured, A4):** wordmark x 238.8 and 291.6 pt wide (Canva 238.2 / 292.2), right edge on the design's 530.4; INVOICE NO pill right edge 530.9, grey, text tracked 0.13 em; client label, pill and lines at x 67.1; AMOUNT DUE at 71.8; table pills, 46.6 pt header (radius 23.3), 32.7 pt rows (radius 16.35), alternating #EDEDE8 / #FFD80B, flush; SUBTOTAL / TOTAL labels at x 192 and values ending at 522 / 529; the TOTAL pill 369.4 x 41 at x 173.4; rule 1 at 64.8..533.4; footer columns at x 67.4 / 218.5 / 380.7.
**Intentional deviations, and why:**
- **Fonts.** Open Sauce One is not bundled: the wordmark is Poppins 800 at -0.08 em. Gotham is Montserrat with every size multiplied by 0.96 at token definition (`gotham()` in `variant.ts`; a real Gotham imported over the licensed name would need the tokens at factor 1). DM Sans is bundled 400/700 and has the rupee sign; Montserrat and Poppins carry it too, so no amount depends on the Plex fallback.
- **Wordmark and 'Tax'.** The wordmark always reads "Invoice". A tax invoice adds a tracked 14 pt "TAX" above it (right-aligned), not a 61 pt "Tax Invoice". Negative tracking leaves the last glyph's ink 7.5 pt past the line end, so the wordmark Text carries that much right padding; the ink then ends on the design's edge and the overflow audit stays quiet.
- **Vertical rhythm.** The design is generous and a Voiced invoice has more lines (GSTIN, place of supply, tax rows, amount in words, signature, bank lines), so the gaps between blocks are elastic (client 35 to 10, rules 18 to 6, amount band 18 to 6, table 20 to 8, totals 14 to 6; Letter gives back its 49.9 pt from them first). A one-page invoice of two or three plain items fits A4; a tax invoice with a signature and notes puts items and totals on page 1 and the closing block (terms, signature, footer) alone at the foot of page 2, which is how the other families behave too. When the gaps can give back the whole overflow only to keep the totals with the items, the plan does exactly that.
- **Table width.** The narrow table beside the asterisk (x 176.9, the design) is used only for up to three items whose descriptions take at most two lines in its ~100 pt column; everything else uses the full width (x 59.5..539.4) on every page and drops the asterisk, as the spec recommends. The 71.5 pt asterisk is page 1 only and a child of `FirstPageHeader`, positioned from the plan; the dome sits in the left gutter of the totals block and travels with it.
- **Pills.** Header and rows are Views with a flat fill and a radius, laid out through `TableRows`'s `pill` option (cells inset 15 pt inside the pill, the pill indented from the container's left edge). No opacity, so text is never faded.
- **Watermarks.** The two pale asterisks are `decor.underlay` items (fixed, painted before the flow, anchored to the page corners; the off-page part is cut away by the Svg's viewBox so the box always lies on the page, Letter included). No keep-outs: nothing printed over them needs a clear ground. Canva's drop-shadow rasters are dropped.
- **Dates.** "INVOICE DATE : ..." and "DUE DATE : ..." are explicit right-aligned lines (a PO line is added when present); the size shrinks to 10 pt before the amount (32.74 pt, shrinking to 20) loses its 150 pt.
- **Supplier lines.** GSTIN and PAN sit under the vendor name (9 pt, through `Slot.Gstin`); phone, e-mail and address are footer columns B and C with icons (solid discs for phone and e-mail, a ring for the address). The website column has no Voiced data and is dropped; UPI is a bank line.
- **Signature and terms.** The signature takes the 29 pt asterisk's place at the right of the terms row (190 pt wide, so the computer-generated line fits in one line). Terms are one bullet per note line; with more than the signature's height they flow as their own block before the closing block, each bullet unbreakable and the label held with the first.
- **Logo.** No Canva placeholder: opt-in (picker toggle, `prefs.logo.show`), off by default, in the area left of the vendor name (at most 200 x 34 from `slots.optin.ts`). A mark shifts the name right; a wordmark replaces it. The no-logo fallback is the vendor name in DM Sans Bold.
- **Margins.** Top 70 (the design's pill starts at 77; 7 pt go to the page-2+ continuation band), bottom 40 plus the footer reserve, 54.8 left, 52.48 right; floors 36 / 36 / 24 / 36.