Foundations
Document layout
Everything the company issues as a document sits on the same geometry, so an invoice and a memo line up when they are stacked. Word measures in dxa, where 1440 units is one inch.
Source of truth: varick-docs/SKILL.md · varick-docs/references/template.js
Page geometry
US Letter with a 6.7in content column. The wordmark scales to exactly that width, which is what makes the masthead identical across every document type.
| Token | dxa | Inches | Note |
|---|---|---|---|
PAGE_W × PAGE_H | 12240 × 15840 | 8.5in × 11in | US Letter. |
MARGIN_X | 1296 | 0.9in | Left and right. |
MARGIN_TOP | 1900 | 1.32in | Clears the masthead by ~0.3in. |
MARGIN_BOTTOM | 1080 | 0.75in | n/a |
CONTENT_W | 9648 | 6.7in | The wordmark scales to exactly this. |
HEADER_DIST | 720 | 0.5in | n/a |
FOOTER_DIST | 620 | 0.43in | n/a |
LINE | 276 | 1.15 | Line height, all body copy. |
SP_BEFORE / SP_AFTER | 200 / 140 | n/a | Fixed for every block. Do not tune per block. |
Percentage widths break in Google Docs. Keep every measurement in dxa, and let fitWidths() split the remainder rather than doing the arithmetic yourself.
Page anatomy
Four zones, and only one of them is yours to fill.
masthead, every page
CONFIDENTIAL · Page X of Y
8.5in × 11in · 0.9in side margins · 6.7in content column
- Masthead sits in the page header so it repeats. Never call it in the body.
- The first line of every page clears the masthead rule by about 0.3in. That is what MARGIN_TOP 1900 buys.
- The footer is three parts, all grey: CONFIDENTIAL, Varick Agents, and a live Page X of Y field.
- Nothing is centred. The whole system is left-aligned.
Spacing is fixed
Every block sits on the same before/after pair, so the rhythm down the page is even without anyone tuning it.
SP_BEFORE: 200, // dxa
SP_AFTER: 140,
LINE: 276, // 1.15 line heightIf a document runs long, cut copy
What goes wrong
Four failure modes that have actually happened.
| Symptom | Cause | Fix |
|---|---|---|
| A table split into two blocks with a "(continued)" header | Someone assumed a long table needs manual pagination. | One table() call, however long. It flows across the break and the navy header row repeats itself. |
| A heading stranded at the bottom of a page | The content it introduces moved to the next page. | section() and subhead() already carry keepNext. If a page still ends awkwardly, cut copy rather than inserting a pagebreak. |
| Page X of Y shows the wrong total | The reader has not recalculated fields. | Nothing to fix. The PDF is always right, and Google Docs updates on open. Never replace the field with a literal number. |
| A cell fill renders black | ShadingType.SOLID. | Always ShadingType.CLEAR. |
Editing a document that already exists
There is one source of truth and it is not the .docx.
Reconstruct the content in buildDoc() and rebuild. Patching the .docx directly means the next change starts from a file nobody can regenerate.
# Recover an issued document
pandoc -t markdown old.docx
# If all you have is the PDF
pdftotext -layout old.pdf -