/** * Print stylesheet generator. * * Source of truth: .context/designs/make-pdf-print-reference.html and siblings. * Mirror those CSS rules here. The HTML references were approved via * /plan-design-review with explicit design decisions locked in the plan: * * - Helvetica first, with Liberation Sans as a metric-compatible Linux * fallback (Helvetica and Arial aren't installed on most Linux distros; * Liberation Sans ships via the fonts-liberation package and Playwright's * install-deps). No bundled webfonts — dodges the per-glyph Tj bug that * breaks copy-paste extraction. * - All paragraphs flush-left. No first-line indent, no justify, no * p+p indent. text-align: left everywhere. 12pt margin-bottom. * - Cover page (v1.58.0.0 poster revision, user-directed): 56pt title, * 13pt meta, padding-top 1.4in for poster placement. Still no flexbox * and no vertical centering; the inset is a deliberate top-third drop. * (Supersedes the original "no inset padding" lock from the first * /plan-design-review — the 32pt cover read as too small in print.) * - `@page :first` suppresses running header/footer but does NOT override * the 1in margin. * - No , no external CSS/fonts — everything inlined. * - CJK fallback: Helvetica, Liberation Sans, Arial, Hiragino Kaku Gothic * ProN, Noto Sans CJK JP, Microsoft YaHei, sans-serif. * - Emoji fallback: the body and @top-center running-header stacks end in an * emoji family group ("Apple Color Emoji", "Segoe UI Emoji", "Noto Color * Emoji"), placed BEFORE the generic `sans-serif` so Chromium has a glyph * source for emoji code points instead of emitting .notdef tofu (▯). The * @bottom-* margin boxes hold only counters / a fixed "CONFIDENTIAL" * string, so they get no emoji families. On Linux this requires an * installed color-emoji font — `setup` installs fonts-noto-color-emoji. * * Font stacks are composed from the constants below so each family list has a * single source of truth (DRY) and every stack stays in sync. */ // Metric-compatible sans stack: Helvetica (macOS), Liberation Sans (Linux, // ships via fonts-liberation), Arial (Windows). Shared by every text surface. const SANS_STACK = `Helvetica, "Liberation Sans", Arial`; // CJK fallback families, appended to the body stack only. const CJK_STACK = `"Hiragino Kaku Gothic ProN", "Noto Sans CJK JP", "Microsoft YaHei"`; // Color-emoji families: Apple (macOS), Segoe (Windows), Noto (Linux). const EMOJI_FAMILIES = `"Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji"`; export interface PrintCssOptions { // Document structure cover?: boolean; toc?: boolean; noChapterBreaks?: boolean; // Branding watermark?: string; confidential?: boolean; // Header (running title, top of page) runningHeader?: string; // Page size (in CSS `@page size:` terms) pageSize?: "letter" | "a4" | "legal" | "tabloid"; // Margins (default 1in) margins?: string; // Whether to render "N of M" page numbers in the @page @bottom-center rule. // Default true. Set false to suppress CSS numbering (used when the caller // supplies a custom Chromium footerTemplate, or when --no-page-numbers). pageNumbers?: boolean; } /** * Produce a CSS block (no