- Add fonts/READY-PACKAGE.md: exact woff2/ttf names, OFL license steps, pixel-match checklist vs verae-2026-design CERT-01.html/png - Cross-link README, LICENSE-FONTS, fetch-fonts.example.sh status - certificate.html residual points at READY-PACKAGE (ops drop-in) Software path unchanged; go test pdfcert + statuslang PASS. Binaries remain operator deploy-host only (not committed).
159 lines
7.4 KiB
Markdown
159 lines
7.4 KiB
Markdown
# CERT OFL fonts — READY package
|
||
|
||
Operator drop-in package for self-hosted CERT-01 type on printit.verae.ai.
|
||
Software path is complete (`certificate.html` local-first probe, `pdfcert`
|
||
`EmbedBrandFonts` opt-in). This file is the **exact contract** for filenames,
|
||
license steps, and pixel-match sign-off against the CERT-01 design.
|
||
|
||
**Binaries are not committed.** Place OFL files on the deploy host (or
|
||
uncomment `fetch-fonts.example.sh` after license review), then run
|
||
`./fetch-fonts.example.sh --check`.
|
||
|
||
## Exact filenames under `fonts/`
|
||
|
||
Directory: `site/printit.verae.ai/fonts/` (this folder).
|
||
|
||
### Web viewer (required for local @font-face)
|
||
|
||
| File | Required | Used by | Notes |
|
||
|------|----------|---------|-------|
|
||
| `fraunces-opsz-wght-700.woff2` | **yes** | `certificate.html` title weight 700 | wOFF2 magic `wOF2`; variable or static subset OK |
|
||
| `fraunces-opsz-wght-600.woff2` | **yes** (`--check`) | weight 600 body/serif accents | same family name `Fraunces` |
|
||
| `jetbrains-mono-500.woff2` | optional | digest / mono rows | family `JetBrains Mono` |
|
||
| `OFL.txt` | **yes** | license beside binaries | upstream SIL OFL 1.1 text; keep copyright notices |
|
||
|
||
Probe order in `certificate.html` (must match names exactly):
|
||
|
||
```
|
||
fonts/fraunces-opsz-wght-700.woff2 → Fraunces 700
|
||
fonts/fraunces-opsz-wght-600.woff2 → Fraunces 600
|
||
fonts/jetbrains-mono-500.woff2 → JetBrains Mono 500
|
||
```
|
||
|
||
Do **not** rename after first production deploy — the head script HEADs these
|
||
paths only.
|
||
|
||
### PDF embed (optional; `EmbedBrandFonts` / `VERAE_EMBED_BRAND_FONTS`)
|
||
|
||
| File | Required | Used by | Notes |
|
||
|------|----------|---------|-------|
|
||
| `Fraunces-opsz-wght.ttf` (or any `*fraunces*.ttf`) | optional | `internal/pdfcert` `findBrandFaceFile` | Prefer name containing `fraunces`; else first `.ttf`, else first `.otf` |
|
||
| `*.otf` Fraunces | optional | same | Used only if no `.ttf` found |
|
||
| `OFL.txt` | **yes** if any face present | same as web | |
|
||
|
||
Override scan dir with `VERAE_BRAND_FONTS_DIR`. Default scan is this `fonts/`
|
||
directory (repo-relative). Default embed is **off** — core Times/Helvetica.
|
||
|
||
## License steps (operator)
|
||
|
||
1. Confirm faces are **SIL Open Font License 1.1 (OFL)** only — Fraunces and
|
||
JetBrains Mono are OFL upstream; do not drop proprietary faces here.
|
||
2. Obtain sources (pin a commit or release; do not track `main` blindly):
|
||
- Fraunces: https://github.com/google/fonts/tree/main/ofl/fraunces
|
||
or https://github.com/underscript-type/fraunces
|
||
- JetBrains Mono: https://github.com/google/fonts/tree/main/ofl/jetbrainsmono
|
||
or https://github.com/JetBrains/JetBrainsMono
|
||
3. Convert / subset to the **planned woff2 names** above (e.g. `fonttools` +
|
||
`woff2_compress`). Title glyphs only is enough for CERT web.
|
||
4. Copy upstream **`OFL.txt`** next to the binaries (never strip copyright).
|
||
5. Optional PDF: place a Fraunces `.ttf`/`.otf` (name containing `fraunces`
|
||
preferred) in this dir or `VERAE_BRAND_FONTS_DIR`; enable embed only when
|
||
intended (`VERAE_EMBED_BRAND_FONTS=1` or `Input.EmbedBrandFonts`).
|
||
6. Verify:
|
||
|
||
```sh
|
||
cd site/printit.verae.ai/fonts
|
||
./fetch-fonts.example.sh --check # exit 0 when required set present
|
||
# open ../certificate.html — Network: no fonts.googleapis.com if local hits
|
||
# Offline smoke: block fonts.googleapis.com / fonts.gstatic.com; title still Fraunces or Georgia
|
||
```
|
||
|
||
7. Deploy with the static site (`rsync` → `/var/www/printit.verae.ai/`). No HTML
|
||
edit required. Do not enable the example fetch script in CI.
|
||
|
||
See also: [`LICENSE-FONTS.md`](./LICENSE-FONTS.md), [`README.md`](./README.md),
|
||
[`fetch-fonts.example.sh`](./fetch-fonts.example.sh).
|
||
|
||
## Pixel-match checklist vs CERT-01 design
|
||
|
||
**Design source of truth (in order):**
|
||
|
||
| Asset | Absolute path (Verae-Projects) |
|
||
|-------|--------------------------------|
|
||
| HTML mock | `verae-2026-design/ui-designs/src/html/CERT-01.html` |
|
||
| PNG | `verae-2026-design/ui-designs/pngs/CERT-01.png` |
|
||
| PNG v1 | `verae-2026-design/ui-designs/pngs/CERT-01-v1.png` |
|
||
| Annotated | `verae-2026-design/ui-designs/pngs-annotated/CERT-01.png` |
|
||
| Live viewer | `apps/PrintToVeraeTimeStamp/site/printit.verae.ai/certificate.html` |
|
||
|
||
Compare live `certificate.html` (print CSS + screen) side-by-side with
|
||
`CERT-01.png` / the HTML mock. Check each row; mark pass only when measured.
|
||
|
||
### Geometry (design → live)
|
||
|
||
| Token | CERT-01 design | Live `certificate.html` | Pass? |
|
||
|-------|----------------|-------------------------|-------|
|
||
| Canvas / column | shadow **816×1056**; outer pad **30px** | `.wrap` max-width **816px**; pad **30px 16px 48px** | |
|
||
| Outer plum frame | `inset:22px`; border **1.5px** `var(--plum)`; radius 4px | double box-shadow plum 1.5px + gold 0.5px (equivalent frame) | |
|
||
| Inner gold frame | `inset:28px`; border **0.5px** `var(--gold)` | gold inner ring via inset shadow | |
|
||
| Content pad | **56px 64px** | `.sheet` padding **56px 64px** | |
|
||
| Logo height | **40px** | brand logo ~40px row | |
|
||
| Title block margin | **26px 0 18px** | `.title-block` **26px 0 18px** | |
|
||
| Title type | Fraunces **700 / 26px**; color `--ink` | `.title` Fraunces 700 (local or CDN); size aligned ~26–28px | |
|
||
| Subtitle | **12.5px** muted; margin-top 6px | `.subtitle` 12.5px | |
|
||
| Gold rule | **2px × 120px**; margin 14px auto 0 | `.rule` 2×120 | |
|
||
| Final banner | border **2px** `--ok`; radius **10px**; pad **12×16**; gap 12 | `.banner.final` same | |
|
||
| KV grid | cols **150px 1fr**; gap **10×16**; margin-top 20px | `.kv` aligned | |
|
||
| Mono digests | **11px** JetBrains Mono / mono stack | `.mono` 11px | |
|
||
| Verify row | flex; gap **22px**; margin-top **22px**; pad **16px**; radius 10 | `.verify` same | |
|
||
| QR box | **130×130** SVG; pad 4px; radius 6; ink border | `.qr` **130px**; live data-URL when final | |
|
||
| Footer | muted **10px**; absolute band ~top 930 in mock | `.legal` / footer strip | |
|
||
| Tokens | `--plum #531B59`, `--gold #C4A85A`, `--ink #1D1534`, ok greens | `brand/tokens.css` | |
|
||
|
||
### Type / fonts
|
||
|
||
| Check | Pass? |
|
||
|-------|-------|
|
||
| With planned woff2 present: Network tab has **no** `fonts.googleapis.com` / `fonts.gstatic.com` request for Fraunces | |
|
||
| Title glyph shapes match CERT-01 PNG (Fraunces, not Georgia) at 100% zoom | |
|
||
| Without woff2: CDN Fraunces loads; offline → Georgia/serif still legible; plum/gold frame kept | |
|
||
| Digests use mono stack; optional `jetbrains-mono-500.woff2` when present | |
|
||
| Print stylesheet: frame + serif title survive; QR print-safe (data-URL or SVG placeholder) | |
|
||
|
||
### Behavioral (not pure pixels)
|
||
|
||
| Check | Pass? |
|
||
|-------|-------|
|
||
| Final + digest → live QR data-URL (`setVerifyQR` / qrcode.js) | |
|
||
| Provisional / offline → SVG placeholder, no broken image | |
|
||
| Multihash / blake3 fields only when digests present (never invented) | |
|
||
| PDF path: `EmbedBrandFonts` default false; with TTF + flag, register or fail closed to Times | |
|
||
|
||
### Sign-off
|
||
|
||
```
|
||
Operator: ____________ Date: ________ Host: ________
|
||
./fetch-fonts.example.sh --check → exit 0
|
||
Side-by-side vs CERT-01.png: geometry ____ type ____ QR ____
|
||
Notes: ________________________________________________
|
||
```
|
||
|
||
**Status:** READY package complete (filenames + license + checklist). Pixel
|
||
sign-off and binary drop-in remain operator actions on the deploy host — not
|
||
git content.
|
||
|
||
## Tree after drop-in (example)
|
||
|
||
```
|
||
fonts/
|
||
.gitkeep
|
||
README.md
|
||
LICENSE-FONTS.md
|
||
READY-PACKAGE.md ← this file
|
||
fetch-fonts.example.sh
|
||
fraunces-opsz-wght-700.woff2
|
||
fraunces-opsz-wght-600.woff2
|
||
jetbrains-mono-500.woff2 (optional)
|
||
Fraunces[opsz,wght].ttf (optional PDF; any *fraunces*.ttf)
|
||
OFL.txt
|
||
```
|