Metadata-Version: 2.4
Name: fullbleed
Version: 2.2.5
Classifier: Development Status :: 5 - Production/Stable
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: MacOS
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Rust
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Topic :: Printing
Classifier: Topic :: Text Processing :: Markup :: HTML
Provides-Extra: api
License-File: LICENSE
License-File: COPYRIGHT
License-File: LICENSING.md
License-File: THIRD_PARTY_LICENSES.md
License-File: FONT_LICENSE_AUDIT.md
License-File: FONT_LICENSE_AUDIT.json
Summary: Deterministic static HTML/CSS-to-PDF renderer built in Rust
Keywords: pdf,html,css,rust,static-pdf,document-generation
Home-Page: https://fullbleed.dev
License-Expression: MIT
Requires-Python: >=3.10
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
Project-URL: Documentation, https://github.com/fullbleed-engine/fullbleed-official#readme
Project-URL: Homepage, https://fullbleed.dev
Project-URL: Issues, https://github.com/fullbleed-engine/fullbleed-official/issues
Project-URL: Repository, https://github.com/fullbleed-engine/fullbleed-official

<!-- SPDX-License-Identifier: MIT -->
# Fullbleed

Deterministic, self-contained HTML/CSS-to-PDF generation in Rust, with a Python-first CLI and Python engine bindings.


License: MIT.



- **Install:** `pip install fullbleed`
- **Try:** `fullbleed init . && python report.py`
- **Outputs:** `output/report.pdf` 
- Deterministic + reproducible (`--repro-record` / `--repro-check`)
- Agent-safe JSON schemas (`--json-only`, `--schema`)

## Positioning

Fullbleed is a deterministic, offline-first document rendering engine for transactional/VDP pipelines (not a browser, not a hosted web-to-print SaaS).

HTML and CSS are used as a familiar DSL for layout, styling, and data placement in transactional documents.


This README is the canonical usage guide for:

- `fullbleed` CLI (human workflows + machine/agent automation)
- `fullbleed` Python bindings (`PdfEngine`, `AssetBundle`, batch APIs)

Additional focused references are in `docs/`:

- `docs/install-non-technical.md` (step-by-step setup for non-technical users)
- `docs/css-coverage.md` (validated CSS coverage, parity status, and active gaps)
- `docs/README.md`
- `docs/engine.md`
- `docs/performance-architecture.md`
- `docs/performance-pass-2026-08-04.md`
- `docs/python-api.md`
- `docs/ui-accessibility.md`
- `docs/cli.md`
- `docs/pdf-templates.md`

## What You Get

- No headless browser requirement for PDF generation.
- Deterministic render pipeline with optional SHA256 output hashing.
- Reproducibility workflow via `--repro-record` and `--repro-check`.
- PDF `1.7` as the production-stable default target.
- Rust-native PDF template composition for VDP/transactional overlays.
- Native Rust image emission for overlay and finalized compose outputs (`--emit-image`) without external PDF raster runtime dependencies.
- Feature-driven page-to-template binding with per-page deterministic compose plans.
- Structured JSON result schemas for CI and AI agents.
- Offline-first asset model with explicit remote opt-in.
- Remote project template registry workflows (`new list`, `new search`, `new remote`).
- Python-first extension surface for hackability and custom workflows.
- Python render calls release the GIL while Rust rendering executes.
- Ordered standard-library worker pools for batch rendering and selected internal workloads.
- A deliberately small, license-audited Rust dependency graph and no required third-party Python
  runtime or build packages.

## Concurrency Model

- Python binding render methods release the GIL during Rust execution through the Stable ABI bridge.
- Parallel batch APIs use Fullbleed's ordered standard-library worker pool (`render_pdf_batch_parallel(...)` and parallel-to-file variants).
- The same bounded worker implementation serves selected internal hotspots such as table layout and JIT paint paths.
- Do not assume every single-document render path will fully saturate all cores end-to-end.

## Performance in 2.2

Fullbleed 2.2 retains exact TrueType glyph subsetting and adds compiled fixed-geometry variable-data
binding. Across the five independent benchmark fixtures, PDFs are 95.5-97.3% smaller and ordinary
warm rendering is 2.90x faster by geometric mean than released 2.0.0.

The new compile-once API freezes an immutable Q32.32 display document and can link it repeatedly
without rerunning HTML parsing, selector matching, layout, pagination, or command planning. For
identical untagged copies in one ordered PDF, `CompiledDocument.render_pdf_batch(...)` shares each
source page's content stream across the copied page dictionaries. The measured 20-copy lane is
200.7x faster per page by geometric mean than the released 2.0.0 warm renderer; a 1,000-page stress
run sustained 304,479-666,622 pages/s.

The 2.2 compiler includes a genuine fixed-geometry variable-data lane. A compiled invoice
with six bound fields rendered 100,000 distinct records in a five-run median of 283.807 ms to
memory (**352,352 pages/s**) and 295.999 ms directly to a flushed 88.1 MB PDF
(**337,839 pages/s**). Including the one-time 4.168 ms compile gives 333,147 direct-file pages/s.
The harness verified all 100,000 unique invoice IDs in page order, exact page count, resolved
markers, deterministic bytes, and equal buffer/file SHA-256. Reproduce it with:

```bash
python tools/benchmark_fullbleed_vdp.py --records 100000 --repeats 5
```

Fixed-geometry slots may remain inside immutable page-space transforms and clips. The compiler
captures that active coordinate-state program once and replays it in each compact record overlay;
it does not rerun layout or clone the complete page display list.

The fixed-copy result remains scoped to identical content; the variable-data result is scoped to
paint-only text whose geometry does not reflow. Neither is a claim that arbitrary new HTML or
size-changing records render 200x faster. See
[`docs/performance-pass-2026-08-04.md`](docs/performance-pass-2026-08-04.md) for measurements and
[`docs/performance-architecture.md`](docs/performance-architecture.md) for the packed vector IR,
typed-binding, virtual-linker, and shader roadmap.

Fullbleed 2.2.5 hardens the third compiler lane introduced in 2.2.4 for
size-changing records: `CompiledDocument.render_pdf_reflow_bindings(...)`. It parses and recovers
the template DOM once and compiles encountered structural flow variants into guarded fixed-point
display programs. Matching records bind directly into those programs; workers execute pre-shaped
text/TJ paint slots, cached static PDF page segments, page-local Deflate, and one ordered linker.
Explicit trusted structural slots use `data-fb-bind-html="slot"`. A value that no compiled variant
can safely place runs ordinary fixed-point layout once to add another variant.

On the independent 1,000-distinct-record case study, the 29-sample hot direct-file median was
216.160 ms: **4,626 records/s and 8,096 pages/s**. The 168.995 ms best sample reached **5,917
records/s and 10,355 pages/s**. It produced
the exact 1,750-page 500/300/150/50 reflow distribution and verified all 24,900 markers. The
throughput-tuned 6,870,320-byte PDF was deterministic across all samples. With the compact
compression setting, compiled output was also byte-for-byte identical to ordinary rendering:
5,298,961 bytes and SHA-256 `bb3c441313a08fb00d3bd15f23a567981f3bbbd550908e3a9fe7a07ca5d7f138`.
This is a hot compiled-variant result, not a claim for previously unseen structure. The first
variant-discovery render measured 0.509 s (3,437 pages/s), and the fully cold job including setup,
bindings, compilation, discovery, and write measured 0.588 s (2,975 pages/s). The independently
observed hot-median speedup over the ordinary path was 43.8x.

## Install

New to Python or setting up on a fresh machine? Start with `docs/install-non-technical.md`.

```bash
python -m pip install fullbleed
```

From a local wheel:

```bash
python -m pip install C:\path\to\fullbleed-2.2.5-cp310-abi3-win_amd64.whl
```

From a source checkout with Rust installed, no Python build package is needed:

```bash
python -m pip install --no-build-isolation --no-deps --editable .
```

To create deterministic release artifacts directly:

```bash
python build_backend/fullbleed_build_backend.py wheel --out dist
python build_backend/fullbleed_build_backend.py sdist --out dist
```

Platform artifact policy:

- Linux wheels cover `manylinux2014` on x86-64, x86, ARM64, ARMv7, s390x,
  and ppc64le, plus `musllinux_1_2` on x86-64, x86, ARM64, and ARMv7.
- Windows wheels cover x86-64, x86, and ARM64; macOS wheels cover Intel and
  Apple silicon.
- The CPython stable ABI allows each platform wheel to support Python 3.10
  through 3.14.
- CI installs and exercises every built wheel on its target architecture,
  using native runners or QEMU as appropriate. The x86-64 manylinux wheel is
  additionally tested on every supported Python version before publication.

Verify command surface:

```bash
fullbleed --help
fullbleed capabilities --json
fullbleed doctor --json
```

## 60-Second Quick Start (Project Happy Path)

Initialize project scaffold:

```bash
fullbleed init .
```

`fullbleed init` now vendors Bootstrap (`5.0.0`) into `vendor/css/bootstrap.min.css`,
vendors Bootstrap Icons (`1.11.3`) into `vendor/icons/bootstrap-icons.svg`,
vendors `inter` into `vendor/fonts/Inter-Variable.ttf`, writes license notices
(`vendor/css/LICENSE.bootstrap.txt`, `vendor/icons/LICENSE.bootstrap-icons.txt`, `vendor/fonts/LICENSE.inter.txt`),
and seeds `assets.lock.json` with pinned hashes.
The scaffolded `report.py` also runs a component mount smoke validation before
main render and writes `output/component_mount_validation.json` (fails fast on
missing glyphs, actual pagination overflow, or CSS miss signals). On current engines,
render-time pagination is authoritative for overflow; conservative JIT placement bounds
remain the compatibility fallback for older engines.
Scaffolded components now include `components/primitives.py` with reusable
layout/content helpers (`Stack`, `Row`, `Text`, table/list helpers, key/value rows, etc.).
Each scaffolded project also includes `SCAFFOLDING.md`, which should be your
first read before restructuring components.

Install additional project assets (defaults to `./vendor/...` in project context):

```bash
fullbleed assets install inter --json
```

Bootstrap baseline note:
- We target Bootstrap (`5.0.0`) as the default styling baseline for project workflows.
- Re-run `fullbleed assets install bootstrap --json` only if you want to explicitly refresh/bootstrap-manage outside `init`.

Render using the scaffolded component pipeline:

```bash
python report.py
```

Expected artifacts from scaffolded `report.py`:
- `output/report.pdf`
- `output/report_page1.png` (or equivalent page preview from engine image APIs)
- `output/component_mount_validation.json`
- `output/css_layers.json`

Canonical static PDF reference:

```bash
python examples/canonical_reference/report.py
```

`examples/canonical_reference/` is the exhaustive scaffold-shaped reference for
component composition, layered CSS, bundled fonts/SVG, inline SVG, raster data
URIs, linked and standalone HTML artifacts, PDF output, PNG previews, and
validation reports.

## Project Bootstrap Templates (`fullbleed new`)

Use local starters:

```bash
fullbleed new local invoice ./my-invoice
fullbleed new local statement ./my-statement
fullbleed new local accessible ./my-accessible-doc
fullbleed new local reference ./my-reference-doc
```

Discover remote starters from registry:

```bash
fullbleed new list --json
fullbleed new search i9 --tag vdp --json
fullbleed new remote i9-stamped-vdp ./i9-job --json
```

`fullbleed new local accessible` is the verbose accessibility-first starter and
demonstrates the `fullbleed.accessibility` runtime surface (engine verifier,
PMR, PDF/UA-targeted seed checks, and non-visual trace artifacts).
`fullbleed new local reference` vendors the canonical static PDF reference shape
as a scaffolded project with component layers, assets, PDF/PNG outputs, page data,
and validation reports.

Optional registry override (for private/canary registries):

```bash
fullbleed new list --registry https://example.com/manifest.json --json
```

or:

```bash
set FULLBLEED_TEMPLATE_REGISTRY=https://example.com/manifest.json
fullbleed new search statement --json
```

## Scaffold-First Workflow (Recommended)

`fullbleed init` is designed for component-first authoring rather than a single large HTML template.

Typical scaffold layout:

```text
.
|-- SCAFFOLDING.md
|-- COMPLIANCE.md
|-- report.py
|-- components/
|   |-- fb_ui.py
|   |-- primitives.py
|   |-- header.py
|   |-- body.py
|   |-- footer.py
|   `-- styles/
|       |-- primitives.css
|       |-- header.css
|       |-- body.css
|       `-- footer.css
|-- styles/
|   |-- tokens.css
|   `-- report.css
|-- vendor/
|   |-- css/
|   |-- fonts/
|   `-- icons/
`-- output/
```

Best-practice authoring model:
1. Read `SCAFFOLDING.md` first for project conventions.
2. Keep composition and data loading in `report.py`.
3. Keep reusable component building blocks in `components/primitives.py`.
4. Keep section markup in `components/header.py`, `components/body.py`, `components/footer.py`.
5. Keep component-local styles in `components/styles/*.css`.
6. Keep page tokens/composition styles in `styles/tokens.css` and `styles/report.css`.

Recommended CSS layer order:
1. `styles/tokens.css`
2. `components/styles/primitives.css`
3. `components/styles/header.css`
4. `components/styles/body.css`
5. `components/styles/footer.css`
6. `styles/report.css`

Recommended iteration loop:
1. Edit data loading + component props in `report.py`.
2. Edit component markup in `components/*.py`.
3. Edit styles in `components/styles/*.css` and `styles/*.css`.
4. Run `python report.py`.
5. Review `output/report_page1.png`, `output/component_mount_validation.json`, and `output/css_layers.json`.

Optional scaffold diagnostics:
- `FULLBLEED_DEBUG=1` to emit JIT traces.
- `FULLBLEED_PERF=1` to emit perf traces.
- `FULLBLEED_EMIT_PAGE_DATA=1` to persist page data JSON.
- `FULLBLEED_IMAGE_DPI=144` (or higher) for preview resolution.
- `FULLBLEED_VALIDATE_STRICT=1` for stricter validation gates in CI.

## One-off Quick Render (No Project Scaffold)

Render inline HTML/CSS with reproducibility artifacts:

```bash
fullbleed --json render \
  --html-str "<html><body><h1>Hello</h1></body></html>" \
  --css-str "body{font-family:sans-serif}" \
  --emit-manifest build/render.manifest.json \
  --emit-jit build/render.jit.jsonl \
  --emit-perf build/render.perf.jsonl \
  --deterministic-hash build/render.sha256 \
  --repro-record build/render.repro.json \
  --out output/hello.pdf
```

`--deterministic-hash` writes the output PDF SHA-256 by default; when `--emit-image` is enabled, it writes an artifact-set digest (`fullbleed.artifact_digest.v1`) over PDF SHA-256 plus ordered page-image SHA-256 hashes. JSON outputs expose `outputs.deterministic_hash_mode` (`pdf_only` or `artifact_set_v1`), with `outputs.artifact_sha256` and `outputs.image_sha256` when images are emitted.

Re-run and enforce reproducibility against a stored record:

```bash
fullbleed --json render \
  --html templates/report.html \
  --css templates/report.css \
  --repro-check build/render.repro.json \
  --out output/report.rerun.pdf
```

Generate PNG page artifacts from an existing validation render:

```bash
fullbleed --json verify \
  --html templates/report.html \
  --css templates/report.css \
  --emit-pdf output/report.verify.pdf \
  --emit-image output/report_verify_pages \
  --image-dpi 200
```

Compile-only plan (no render):

```bash
fullbleed --json plan \
  --html templates/report.html \
  --css templates/report.css
```

Template compose planning (no finalize write):

```bash
fullbleed --json plan \
  --html templates/overlay.html \
  --css templates/overlay.css \
  --template-binding config/template_binding.json \
  --templates config/template_catalog.json \
  --emit-compose-plan output/compose_plan.json
```

## PDF Template Composition (VDP / Transactional)

When overlaying variable data onto a source PDF, use the built-in Rust template compose path.

Minimal CLI auto-compose flow:

```bash
fullbleed --json render \
  --html templates/overlay.html \
  --css templates/overlay.css \
  --asset templates/source.pdf --asset-kind pdf --asset-name source-template \
  --template-binding config/template_binding.json \
  --templates config/template_catalog.json \
  --out output/composed.pdf
```

Compose image semantics:
- In template auto-compose mode, `--emit-image` PNGs are rasterized from finalized composed pages and report `outputs.image_mode=composed_pdf`.
- In non-compose `render`/`verify` runs, `--emit-image` reports `outputs.image_mode=overlay_document`.

Minimal `template_binding` example:

```json
{
  "default_template_id": "source-template",
  "feature_prefix": "fb.feature.",
  "by_feature": {
    "front": "source-template",
    "back_blank": "source-template"
  }
}
```

Python API compose flow:

```python
import fullbleed

engine = fullbleed.PdfEngine(template_binding=binding_spec)
overlay_bytes, _page_data, _bindings = engine.render_pdf_with_page_data_and_template_bindings(html, css)
open("output/overlay.pdf", "wb").write(overlay_bytes)
plan_result = engine.plan_template_compose(
    html,
    css,
    [("source-template", "templates/source.pdf")],
    0.0,
    0.0,
)
plan = [
    (
        row["template_id"],
        row["template_page"],
        row["overlay_page"],
        row["dx"],
        row["dy"],
    )
    for row in plan_result["plan"]
]
fullbleed.finalize_compose_pdf(
    [("source-template", "templates/source.pdf")],
    plan,
    "output/overlay.pdf",
    "output/composed.pdf",
    annotation_mode="link_only",  # optional: link_only | none | carry_widgets
)
```

See `docs/pdf-templates.md` and `examples/template-flagging-smoke/` for full production examples.

## CLI Command Map

| Command | Purpose | JSON Schema |
| --- | --- | --- |
| `render` | Render HTML/CSS to PDF with optional PNG page artifacts | `fullbleed.render_result.v1` |
| `verify` | Validation render path with optional PDF and PNG emits | `fullbleed.verify_result.v1` |
| `plan` | Compile/normalize inputs into manifest + warnings | `fullbleed.plan_result.v1` |
| `run` | Render using Python module/file engine factory | `fullbleed.run_result.v1` |
| `inspect pdf` | Inspect PDF metadata and composition compatibility | `fullbleed.inspect_pdf.v1` |
| `inspect pdf-batch` | Inspect multiple PDFs with per-file status | `fullbleed.inspect_pdf_batch.v1` |
| `inspect templates` | Inspect template catalog metadata/compatibility | `fullbleed.inspect_templates.v1` |
| `compliance` | License/compliance report for legal/procurement | `fullbleed.compliance.v1` |
| `debug-perf` | Summarize perf JSONL logs | `fullbleed.debug_perf.v1` |
| `debug-jit` | Filter/inspect JIT JSONL logs | `fullbleed.debug_jit.v1` |
| `doctor` | Runtime capability and health checks | `fullbleed.doctor.v1` |
| `capabilities` | Machine-readable command/engine capabilities | `fullbleed.capabilities.v1` |
| `assets list` | Installed and optional remote packages | `fullbleed.assets_list.v1` |
| `assets info` | Package details + hashes/sizes | `fullbleed.assets_info.v1` |
| `assets install` | Install builtin/remote package | `fullbleed.assets_install.v1` |
| `assets verify` | Validate package and optional lock constraints | `fullbleed.assets_verify.v1` |
| `assets lock` | Write/update `assets.lock.json` | `fullbleed.assets_lock.v1` |
| `cache dir` | Cache location | `fullbleed.cache_dir.v1` |
| `cache prune` | Remove old cached packages | `fullbleed.cache_prune.v1` |
| `init` | Initialize project scaffold | `fullbleed.init.v1` |
| `new` | Create starter template files or query/install remote templates | `fullbleed.new_template.v1`, `fullbleed.new_list.v1`, `fullbleed.new_search.v1`, `fullbleed.new_remote.v1` |

Schema discovery for any command/subcommand:

```bash
fullbleed --schema render
fullbleed --schema assets verify
fullbleed --schema inspect pdf
fullbleed --schema inspect templates
```

## CLI Flags That Matter Most

Global machine flags:

- `--json`: structured result payload to stdout
- `--json-only`: implies `--json` and `--no-prompts`
- `--schema`: emit schema definition and exit
- `--no-prompts`: disable interactive prompts
- `--config`: load defaults from a config file
- `--log-level error|warn|info|debug`: control CLI log verbosity
- `--no-color`: disable ANSI color output
- `--version`: print CLI version and exit

Render/verify/plan key flags:

- Inputs: `--html`, `--html-str`, `--css`, `--css-str`
  `--html` accepts `.svg` files for direct SVG-document rendering; `--html-str` accepts inline SVG markup.
- Page setup: `--page-size`, `--page-width`, `--page-height`, `--margin`, `--page-margins`
- Engine toggles: `--reuse-xobjects`, `--svg-form-xobjects`, `--svg-raster-fallback`, `--shape-text`, `--unicode-support`, `--unicode-metrics`
- PDF/compliance: `--pdf-version`, `--pdf-profile`, `--color-space`, `--document-lang`, `--document-title`
  Stable default is `--pdf-version 1.7` for shipping workflows.
  Profile targets: `none`, `pdfa1a`, `pdfa1b`, `pdfa2a`, `pdfa2b`, `pdfa2u`, `pdfa3a`, `pdfa3b`, `pdfa3u`, `pdfa4`, `pdfa4e`, `pdfa4f`, `pdfx4`, `pdfua1`, `pdfua2`, `pdfvt1`, `wtpdf1r`, `wtpdf1a`, `tagged`.
  Aliases: `a`, `ua`, `vt`, `wt1r`, `wt1a`, `pdf/a`, `pdf/ua`, `pdf/vt`.
  Output intent metadata (`--output-intent-identifier|--output-intent-info|--output-intent-components`) requires `--output-intent-icc`.
  Run `python tools/validate_pdf_profiles.py --download-verapdf --install-pdf-oxide --strict-external`
  to regenerate profile specimens, capture inspect/JIT evidence, replay
  deterministic hashes, validate PDF/A and PDF/UA with veraPDF, and validate
  PDF/X-4 with `pdf_oxide`. WTPDF profiles are validated with veraPDF
  `wt1r`/`wt1a` and include PDF Declaration evidence. `pdfa4f` emits and
  checks an associated `EmbeddedFiles` name tree. `pdfvt1` also emits and checks a parsed
  DPart graph (`DPartRoot`, `DPartRootNode`, one-level `NodeNameList`, leaf page range,
  and page `/DPart` references), including a supplemental multipage specimen
  for `/Start` and `/End`, reported as granular booleans plus
  `pdfvt_dpart_graph_valid`; use a dedicated PDF/VT preflight tool
  for third-party PDF/VT certification, or wire one into the same harness with
  `--pdfvt-cmd "tool --input {pdf}" --require-dedicated-pdfvt`.
- Watermarking: `--watermark-text`, `--watermark-html`, `--watermark-image`, `--watermark-layer`, `--watermark-semantics`, `--watermark-opacity`, `--watermark-rotation`
- Artifacts: `--emit-jit`, `--emit-perf`, `--emit-glyph-report`, `--emit-page-data`, `--emit-compose-plan`, `--emit-image`, `--image-dpi`, `--deterministic-hash`
- Assets: `--asset`, `--asset-kind`, `--asset-name`, `--asset-trusted`, `--allow-remote-assets`
- Profiles: `--profile dev|preflight|prod`
- Fail policy: `--fail-on overflow|missing-glyphs|font-subst|budget`
- Fallback policy: `--allow-fallbacks` (keeps fallback diagnostics, but does not fail `missing-glyphs` / `font-subst` gates)
- Reproducibility: `--repro-record <path>`, `--repro-check <path>`
- Budget thresholds: `--budget-max-pages`, `--budget-max-bytes`, `--budget-max-ms`
- Release gates: `doctor --strict`, `compliance --strict --max-audit-age-days <n>`

## SVG Workflows

Fullbleed supports SVG in three practical CLI paths:

- Direct SVG document render via `--html <file.svg>`
- Inline SVG markup via `--html-str "<svg ...>...</svg>"`
- Referenced SVG assets via `--asset <file.svg>` (kind auto-infers to `svg`)

Standalone SVG file to PDF:

```bash
fullbleed --json render \
  --html artwork/badge.svg \
  --out output/badge.pdf
```

Inline SVG markup to PDF:

```bash
fullbleed --json render \
  --html-str "<svg xmlns='http://www.w3.org/2000/svg' width='200' height='80'><rect width='200' height='80' fill='#0d6efd'/><text x='16' y='48' fill='white'>Hello SVG</text></svg>" \
  --out output/inline-svg.pdf
```

HTML template with explicit SVG asset registration:

```bash
fullbleed --json render \
  --html templates/report.html \
  --css templates/report.css \
  --asset assets/logo.svg \
  --asset-kind svg \
  --out output/report.pdf
```

SVG render behavior flags:

- `--svg-form-xobjects` / `--no-svg-form-xobjects`
- `--svg-raster-fallback` / `--no-svg-raster-fallback`

Distributed Python wheels enable the `svg_raster` engine feature, so
`--svg-raster-fallback` can rasterize unsupported SVG constructs such as SVG
text, filters, masks, and `foreignObject` into deterministic image content.
Custom source builds must include `--features python,svg_raster` to advertise
and use that fallback path.

Machine discovery:

```bash
fullbleed capabilities --json
```

Inspect the `svg` object in `fullbleed.capabilities.v1` for SVG support metadata. The `engine`
object also reports compiled-document/reflow availability and supported per-call compression modes.
It reports the compiled `svg_raster` build feature plus a feature matrix for
native-vector SVG, raster-fallback-required SVG, and unsupported/known-loss SVG
features.

## Image Support Matrix

Launch-safe image claims:

- Supported direct raster inputs: PNG and JPEG.
- SVG is handled by the SVG pipeline described above, with native-vector output
  where supported and raster fallback for fallback-only features when
  `svg_raster` is enabled.
- Supported references include filesystem paths, registered bundle assets,
  file/data URIs, `<img>`, CSS `background-image: url(...)`, list-style images,
  and watermark images.
- Unsupported or not launch-claimed as direct inputs: WebP, GIF, TIFF, AVIF,
  BMP, animated images, `<picture>`, `srcset`, `sizes`, density descriptors,
  and browser-style responsive image selection.
- For deterministic builds, prefer vendored local assets or registered
  `AssetBundle` inputs; remote assets must be explicitly allowed.

## Per-Page Templates (`page_1`, `page_2`, `page_n`)

Fullbleed uses ordered page templates internally. In docs, this is easiest to think of as:

- `page_1`: first page template
- `page_2`: second page template
- `page_n`: repeating template for later pages

Configuration mapping:

- CLI `--page-margins` keys: `1`, `2`, ... and optional `"n"` (or `"each"` alias).
- Python `PdfEngine(page_margins=...)`: same key model.
- Missing numeric pages fall back to the base `margin`.
- The last configured template repeats for remaining pages.

Minimal CLI example:

```json
{
  "1": {"top": "12mm", "right": "12mm", "bottom": "12mm", "left": "12mm"},
  "2": {"top": "24mm", "right": "12mm", "bottom": "12mm", "left": "12mm"},
  "n": {"top": "30mm", "right": "12mm", "bottom": "12mm", "left": "12mm"}
}
```

```bash
fullbleed --json render \
  --html templates/report.html \
  --css templates/report.css \
  --page-margins page_margins.json \
  --header-each "Statement continued - Page {page} of {pages}" \
  --out output/report.pdf
```

Minimal Python example:

```python
import fullbleed

engine = fullbleed.PdfEngine(
    page_width="8.5in",
    page_height="11in",
    margin="12mm",
    page_margins={
        1: {"top": "12mm", "right": "12mm", "bottom": "12mm", "left": "12mm"},  # page_1
        2: {"top": "24mm", "right": "12mm", "bottom": "12mm", "left": "12mm"},  # page_2
        "n": {"top": "30mm", "right": "12mm", "bottom": "12mm", "left": "12mm"} # page_n
    },
    header_first="Account Statement",
    header_each="Statement continued - Page {page} of {pages}",
    footer_last="Final page",
)
```

Note:
- CLI currently exposes `--header-each` / `--footer-each` (and `--header-html-each` / `--footer-html-each`).
- For `first/last` header/footer variants (`header_first`, `header_last`, `footer_first`, `footer_last`), use the Python API.

## Asset Workflow (CLI)

List installed + available packages:

```bash
fullbleed assets list --available --json
```

Install builtin assets:

```bash
fullbleed assets install bootstrap
fullbleed assets install bootstrap-icons
# `@bootstrap` / `@bootstrap-icons` are also supported aliases
```

PowerShell note:
- Quote `@` aliases (for example `"@bootstrap"`) to avoid shell parsing surprises.

Install remote asset package:

```bash
fullbleed assets install inter
```

Install broad Unicode fallback package (larger font payload):

```bash
fullbleed assets install noto-sans
```

Install to a custom vendor directory:

```bash
fullbleed assets install bootstrap --vendor ./vendor
```

Install to global cache:

```bash
fullbleed assets install inter --global
```

Install common barcode fonts (license-safe defaults):

```bash
fullbleed assets install libre-barcode-128
fullbleed assets install libre-barcode-39
fullbleed assets install libre-barcode-ean13-text
```

Verify against lock file with strict failure:

```bash
fullbleed assets verify inter --lock --strict --json
```

Preview cache cleanup without deleting files:

```bash
fullbleed cache prune --max-age-days 30 --dry-run --json
```

Notes:

- Builtin packages accept both plain and `@` references (`bootstrap` == `@bootstrap`, `bootstrap-icons` == `@bootstrap-icons`, `noto-sans` == `@noto-sans`).
- `noto-sans` is available as a builtin fallback package, but it is intentionally larger than `inter`; use it when your document requires broader glyph coverage.
- Project installs default to `./vendor/` when project markers are present (`assets.lock.json`, `report.py`, or `fullbleed.toml` in CWD).
- If no project markers are found, `assets install` defaults to global cache unless `--vendor` is explicitly set.
- Do not hardcode cache paths like `%LOCALAPPDATA%/fullbleed/cache/...`; use `assets install --json` and consume `installed_to`.
- Installed assets include license files in typed vendor directories (for example `vendor/fonts/`, `vendor/css/`).
- `assets lock --add` is currently aimed at builtin package additions.
- Barcode packages in the remote registry are currently OFL-1.1 families from Google Fonts (`Libre Barcode`).
- USPS IMB fonts are not currently auto-installable via `assets install`; use local vetted font files and track licensing separately.

## Bootstrap Vendoring

Bootstrap builtin package details:

- Package: `bootstrap` (alias: `@bootstrap`)
- Bundled version: `5.0.0`
- Asset kind: CSS (`bootstrap.min.css`)
- Default install location: `vendor/css/bootstrap.min.css` (project mode)
- License: `MIT`
- License source: `https://raw.githubusercontent.com/twbs/bootstrap/v5.0.0/LICENSE`

Bootstrap Icons builtin package details:

- Package: `bootstrap-icons` (alias: `@bootstrap-icons`)
- Bundled version: `1.11.3`
- Asset kind: SVG sprite (`bootstrap-icons.svg`)
- Default install location: `vendor/icons/bootstrap-icons.svg` (project mode)
- License: `MIT`
- License source: `https://raw.githubusercontent.com/twbs/icons/v1.11.3/LICENSE`

Bootstrap notes:

- Bootstrap is vendored and installable through the asset pipeline.
- Bootstrap CSS is consumed as an explicit local asset (`--asset @bootstrap` or `AssetBundle`); external HTML `<link rel="stylesheet">` is not an execution path.
- Bootstrap preflight examples remain useful smoke examples, but they are not the canonical source of CSS parity claims.

## Validated CSS Coverage

For the full, maintained coverage statement, see `docs/css-coverage.md`.

Summary as of May 19, 2026:

- Tracked CSS modules: `22`
- Module state: `22/22 in_progress`
- Full CSS fixture lane: `86/86` fixtures passing with `603` assertion/paint checks
- Parity status check: green (`tools/generate_css_parity_status.py --check --json`)
- Canonical validation artifact: `_css_working/css_parity_status.json`
- Canonical validation artifact: `_css_working/tmp/fixture_full_latest.json`
- Canonical validation artifact: `_css_working/css_broad_coverage_sprint_s14.md`

The complete pinned independent Wheel265 gate closed on August 9, 2026 with `1,642 PASS`,
`0 FAIL`, and `20 REFERENCE-DISPUTED` across 1,662 fixtures. That is strict `100%` parity for
every adjudicable fixture in this named corpus; disputed references remain visible and are not
relabeled as implementation passes. Broader web-platform coverage remains bounded by the module
and known-gap contract in `docs/css-coverage.md`.

Flow/reflow hardening validated on August 5, 2026 adds fixed-height block,
one-column grid, and column-flex continuation slicing; avoids content
duplication; retains empty styled captions inside avoided figures; preserves
`display: contents` grid paint phase; and keeps positioned containing blocks
atomic. The independent review's targeted 18-case regression cluster passes
`18/18` (13 pixel-exact, maximum above-floor difference `0.97030199%`). This
targeted diagnostic does not replace the full external-corpus report.

Current validated behavior includes first-class parser -> evaluator -> calculator -> layout/paint coverage across broad static-document CSS domains (values math, layout primitives, pagination/fragmentation baselines, transforms phase-1, gradient/effects subsets including color-first and interleaved-color `filter: drop-shadow(...)` with computed lengths, modern `rgb()` shadow colors with `mm` lengths, duplicate `drop-shadow(...)` color rejection, empty optional filter-function defaults, explicit/currentColor `backdrop-filter: drop-shadow(...)` raster paint, strict `box-shadow` length/color grammar with modern `rgb()` plus `mm` paint coverage, softened blurred inset edge paint, and directional inset offset edge paint, overflow-gated `text-overflow: ellipsis`, physical min/max box constraints, horizontal-tb RTL `direction` inline inset/margin/padding/border mapping, vertical writing-mode `direction: rtl` inline inset remapping, vertical-rl logical sizing/insets/margin/padding/border/min-max constraints, vertical-lr logical sizing/min-max/insets/margin/padding/border remapping, basic vertical text columns with `vertical-rl` leftward and `vertical-lr` rightward line progression, and deterministic diagnostics).

Known gap categories are explicitly tracked for the final parity push:

- remaining filter/backdrop-filter function breadth beyond current subset, including SVG `url()` filters, advanced `drop-shadow()` forms beyond the current flexible-color-order foreground and baseline backdrop coverage, and PDF-native foreground filters
- advanced `clip-path` grammar beyond the current basic-shape subset, including SVG clip sources, SVG-specific geometry boxes, and deeper edge grammar
- plus-lighter PDF-native parity and deeper nested compositing/isolation breadth
- deeper blurred inset shadow edge fidelity
- remaining multi-layer background image edge semantics beyond the current sized gradient-layer repeat-x/space/round and PNG `url(...)` explicit-size/auto-auto-intrinsic/negative-size-invalid/contain/cover/auto-dimension-size/single-value-size/alpha-stack/default-repeat-repeat/repeat-y/repeat/repeat-no-repeat/no-repeat-repeat/space-space/round-round/round-space/space-round/round-repeat/round-no-repeat/no-repeat-round/no-repeat-space/space-no-repeat/repeat-space/repeat-round/space-repeat/logical-repeat-aliases/multi-layer-repeat-axis/background-list-repetition/percentage-position/edge-offset-position/logical-position-aliases/shorthand-position-size-repeat/content-box-origin-clip/multi-layer-origin-clip/background-blend-normal/background-blend-multiply/screen-mode/overlay-mode/exclusion-mode/hard-light-mode/darken-mode/lighten-mode/color-dodge-mode/color-burn-mode/soft-light-mode/hue-mode/saturation-mode/color-mode/luminosity-mode/plus-lighter-mode/list-repetition/truncation/raster-blend/raster-layer-mapping/mixed-raster-gradient-mapping/mixed-gradient-raster-mapping subset, including broader mixed raster stack combinations
- table layout edge semantics hardening beyond the current fixed-layout width-hint, auto-width, caption-side placement, and invalid caption-side inheritance lanes
- full vertical text/layout flow beyond the current vertical static-layout and basic wrapped text-column baseline

## `run` Command (Python Factory Interop)

`run` lets the CLI use a Python-created engine instance.

`report.py`:

```python
import fullbleed

def create_engine():
    return fullbleed.PdfEngine(page_width="8.5in", page_height="11in", margin="0.5in")
```

CLI invocation:

```bash
fullbleed --json run report:create_engine \
  --html-str "<h1>From run</h1>" \
  --css templates/report.css \
  --out output/report.pdf
```

Entrypoint formats:

- `module_name:factory_or_engine`
- `path/to/file.py:factory_or_engine`

## Python API Quick Start

```python
import fullbleed

engine = fullbleed.PdfEngine(
    page_width="8.5in",
    page_height="11in",
    margin="0.5in",
    pdf_version="1.7",
    pdf_profile="none",
    color_space="rgb",
)

html = "<html><body><h1>Invoice</h1><p>Hello.</p></body></html>"
css = "body { font-family: sans-serif; }"

bytes_written = engine.render_pdf_to_file(html, css, "output/invoice.pdf")
print(bytes_written)
```

Register local assets with `AssetBundle`:

```python
import fullbleed

bundle = fullbleed.AssetBundle()
bundle.add_file("vendor/css/bootstrap.min.css", "css", name="bootstrap")
bundle.add_file("vendor/fonts/Inter-Variable.ttf", "font", name="inter")

engine = fullbleed.PdfEngine(page_width="8.5in", page_height="11in")
engine.register_bundle(bundle)
engine.render_pdf_to_file("<h1>Styled</h1>", "", "output/styled.pdf")
```

## Python API Signatures (Runtime-Verified)

These signatures are verified from the installed package via `inspect.signature(...)`.

`PdfEngine` constructor:

```python
PdfEngine(
    page_width=None,
    page_height=None,
    margin=None,
    page_margins=None,
    font_dirs=None,
    font_files=None,
    reuse_xobjects=True,
    svg_form_xobjects=False,
    svg_raster_fallback=False,
    unicode_support=True,
    shape_text=True,
    unicode_metrics=True,
    pdf_version=None,
    pdf_profile=None,
    output_intent_icc=None,
    output_intent_identifier=None,
    output_intent_info=None,
    output_intent_components=None,
    color_space=None,
    document_lang=None,
    document_title=None,
    header_first=None,
    header_each=None,
    header_last=None,
    header_x=None,
    header_y_from_top=None,
    header_font_name=None,
    header_font_size=None,
    header_color=None,
    header_html_first=None,
    header_html_each=None,
    header_html_last=None,
    header_html_x=None,
    header_html_y_from_top=None,
    header_html_width=None,
    header_html_height=None,
    footer_first=None,
    footer_each=None,
    footer_last=None,
    footer_x=None,
    footer_y_from_bottom=None,
    footer_font_name=None,
    footer_font_size=None,
    footer_color=None,
    watermark=None,
    watermark_text=None,
    watermark_html=None,
    watermark_image=None,
    watermark_layer="overlay",
    watermark_semantics="artifact",
    watermark_opacity=0.15,
    watermark_rotation=0.0,
    watermark_font_name=None,
    watermark_font_size=None,
    watermark_color=None,
    paginated_context=None,
    jit_mode=None,
    debug=False,
    debug_out=None,
    perf=False,
    perf_out=None,
)
```

Module exports:

- `PdfEngine`
- `CompiledDocument`
- `CompiledFlowCompression`
- `AssetBundle`
- `Asset`
- `AssetKind`
- `WatermarkSpec(kind, value, layer='overlay', semantics=None, opacity=0.15, rotation_deg=0.0, font_name=None, font_size=None, color=None)`
- `concat_css(parts)`
- `vendored_asset(source, kind, name=None, trusted=False, remote=False)`
- `inspect_pdf(path)`
- `inspect_template_catalog(templates)`
- `finalize_stamp_pdf(template, overlay, out, page_map=None, dx=0.0, dy=0.0)`
- `finalize_compose_pdf(templates, plan, overlay, out, annotation_mode='link_only')`
- `fetch_asset(url)`

`PdfEngine` methods:

| Method | Return shape |
| --- | --- |
| `register_bundle(bundle)` | `None` |
| `compile_pdf(html, css)` | `CompiledDocument` |
| `render_pdf(html, css, deterministic_hash=None)` | `bytes` |
| `render_pdf_to_file(html, css, path, deterministic_hash=None)` | `int` (bytes written) |
| `render_image_pages(html, css, dpi=150)` | `list[bytes]` |
| `render_image_pages_to_dir(html, css, out_dir, dpi=150, stem=None)` | `list[str]` |
| `render_finalized_pdf_image_pages(pdf_path, dpi=150)` | `list[bytes]` |
| `render_finalized_pdf_image_pages_to_dir(pdf_path, out_dir, dpi=150, stem=None)` | `list[str]` |
| `render_pdf_with_glyph_report(html, css)` | `(bytes, list)` |
| `render_pdf_with_page_data(html, css)` | `(bytes, page_data_or_none)` |
| `render_pdf_with_page_data_and_glyph_report(html, css)` | `(bytes, page_data_or_none, glyph_report_list)` |
| `render_pdf_with_page_data_and_template_bindings(html, css)` | `(bytes, page_data_or_none, template_bindings_or_none)` |
| `render_pdf_with_page_data_and_template_bindings_and_glyph_report(html, css)` | `(bytes, page_data_or_none, template_bindings_or_none, glyph_report_list)` |
| `plan_template_compose(html, css, templates, dx=0.0, dy=0.0)` | `dict` |
| `render_pdf_batch(html_list, css, deterministic_hash=None)` | `bytes` |
| `render_pdf_batch_parallel(html_list, css, deterministic_hash=None)` | `bytes` |
| `render_pdf_batch_to_file(html_list, css, path, deterministic_hash=None)` | `int` |
| `render_pdf_batch_to_file_parallel(html_list, css, path, deterministic_hash=None)` | `int` |
| `render_pdf_batch_to_file_parallel_with_page_data(html_list, css, path, deterministic_hash=None)` | `(bytes_written, page_data_list)` |
| `render_pdf_batch_with_css(jobs, deterministic_hash=None)` | `bytes` |
| `render_pdf_batch_with_css_to_file(jobs, path, deterministic_hash=None)` | `int` |

`CompiledDocument` methods:

| Method | Return shape |
| --- | --- |
| `stats()` | `dict` |
| `render_pdf(deterministic_hash=None)` | `bytes` |
| `render_pdf_to_file(path, deterministic_hash=None)` | `int` |
| `render_pdf_batch(copies, deterministic_hash=None)` | `bytes` |
| `render_pdf_bindings(bindings, deterministic_hash=None)` | `bytes` |
| `render_pdf_bindings_to_file(bindings, path, deterministic_hash=None)` | `int` |
| `render_pdf_reflow_bindings(bindings, deterministic_hash=None, *, compression="throughput")` | `bytes` |
| `render_pdf_reflow_bindings_to_file(bindings, path, deterministic_hash=None, *, compression="throughput")` | `int` |

The compiled lane runs parsing/layout once. `render_pdf_batch` virtualizes identical untagged page
content. The fixed binding methods accept columnar `dict[str, list[str]]` data and emit distinct
fixed-geometry text overlays per record while sharing static paint. They require exact slot keys,
equal non-zero column lengths, page-local WinAnsi-compatible text, and an untagged profile; bound
values do not trigger reflow.

The reflow binding methods use the same exact-column contract but execute the compiled parsed-DOM
program. `{{slot}}` values are literal text and may reshape, wrap, resize blocks, and change page
counts. Empty elements can opt into trusted generated markup with
`data-fb-bind-html="slot"`; those values replace the element's children. One DOM is reused per
native worker and record output is linked in input order through a bounded queue. Structural slot
values are parsed as trusted markup: sanitize untrusted input or use scalar `{{slot}}` bindings,
which remain literal text. Choose `CompiledFlowCompression.Throughput` (default) or
`CompiledFlowCompression.Compact` per render; modes can be mixed safely in one process. See
[`docs/python-api.md`](docs/python-api.md) for the trust boundary and current limitations.

When `deterministic_hash` is set, engine writes PDF SHA-256 to the provided file path.

`AssetBundle` methods:

- `add_file(path, kind, name=None, trusted=False, remote=False)`
- `add(asset)`
- `assets_info()`
- `css()`

## Python Examples (Smoke-Checked)

Canonical scaffold reference:

```bash
python examples/canonical_reference/report.py
```

Text watermark + diagnostics:

```python
import fullbleed

engine = fullbleed.PdfEngine(
    page_width="8.5in",
    page_height="11in",
    margin="0.5in",
    pdf_version="1.7",
    watermark_text="INTERNAL",
    watermark_layer="overlay",
    watermark_semantics="artifact",
    watermark_opacity=0.12,
    watermark_rotation=-32.0,
    debug=True,
    debug_out="build/invoice.jit.jsonl",
    perf=True,
    perf_out="build/invoice.perf.jsonl",
)

html = "<h1>Invoice</h1><p>Status: Ready</p>"
css = "h1{margin:0 0 8px 0} p{margin:0}"

written = engine.render_pdf_to_file(html, css, "output/invoice_watermarked.pdf")
print("bytes:", written)
```

Batch render + glyph/page-data checks:

```python
import fullbleed

engine = fullbleed.PdfEngine(page_width="8.5in", page_height="11in", margin="0.5in")

jobs = [
    ("<h1>Batch A</h1><p>Alpha</p>", "h1{color:#0d6efd}"),
    ("<h1>Batch B</h1><p>Beta</p>", "h1{color:#198754}"),
]

written = engine.render_pdf_batch_with_css_to_file(jobs, "output/batch.pdf")
print("batch bytes:", written)

pdf_bytes, glyph_report = engine.render_pdf_with_glyph_report("<p>Hello</p>", "")
print("glyph entries:", len(glyph_report))

pdf_bytes, page_data = engine.render_pdf_with_page_data("<p>Hello</p>", "")
print("page data available:", page_data is not None)
```

## Transactional Header/Footer + Totals

Minimal, self-contained Python example (no external template files) showing:

- Continued headers on page 2+.
- Per-page subtotal footer expansion via `{sum:items.amount}`.
- Final-page grand total footer expansion via `{total:items.amount}`.
- Structured `page_data` totals for automation and reconciliation checks.

```python
from pathlib import Path
import fullbleed

rows = []
for i in range(1, 121):  # enough rows to force multiple pages
    amount = 10.00 + ((i * 7) % 23) + 0.25
    rows.append(
        f'<tr data-fb="items.amount={amount:.2f}">'
        f"<td>2026-01-{(i % 28) + 1:02d}</td>"
        f"<td>Txn {i:03d}</td>"
        f'<td class="num">${amount:.2f}</td>'
        "</tr>"
    )

html = f"""<!doctype html>
<html>
<body>
  <h1>Monthly Statement</h1>
  <table>
    <thead>
      <tr><th>Date</th><th>Description</th><th class="num">Amount</th></tr>
    </thead>
    <tbody>
      {''.join(rows)}
    </tbody>
  </table>
</body>
</html>
"""

css = """
body { font-family: sans-serif; font-size: 10pt; color: #111; }
h1 { margin: 0 0 8pt 0; }
table { width: 100%; border-collapse: collapse; }
th, td { padding: 4pt; border-bottom: 1pt solid #e1e1e1; }
thead th { background: #f3f6fa; text-transform: uppercase; font-size: 9pt; }
.num { text-align: right; }
"""

engine = fullbleed.PdfEngine(
    page_width="8.5in",
    page_height="11in",
    margin="12mm",
    page_margins={
        1: {"top": "12mm", "right": "12mm", "bottom": "12mm", "left": "12mm"},
        2: {"top": "28mm", "right": "12mm", "bottom": "12mm", "left": "12mm"},
        "n": {"top": "28mm", "right": "12mm", "bottom": "12mm", "left": "12mm"},
    },
    header_html_each=(
        '<div style="display:flex;justify-content:space-between;border-bottom:1pt solid #d9d9d9;">'
        '<div style="font-weight:bold;">Acme Ledger</div>'
        '<div style="font-size:9pt;color:#444;">Statement Continued - Page {page} of {pages}</div>'
        "</div>"
    ),
    header_html_x="12mm",
    header_html_y_from_top="6mm",
    header_html_width="186mm",
    header_html_height="10mm",
    paginated_context={"items.amount": "sum"},
    footer_each="Subtotal (Page {page}): ${sum:items.amount}",
    footer_last="Grand Total: ${total:items.amount}",
    footer_x="12mm",
    footer_y_from_bottom="8mm",
)

pdf_bytes, page_data = engine.render_pdf_with_page_data(html, css)
Path("output_transactional_minimal.pdf").write_bytes(pdf_bytes)

assert page_data["page_count"] >= 2
assert page_data["totals"]["items.amount"]["value"] == sum(
    p["items.amount"]["value"] for p in page_data["pages"]
)
print("Wrote output_transactional_minimal.pdf")
print("Page count:", page_data["page_count"])
print("Grand total:", page_data["totals"]["items.amount"]["formatted"])
```

API note:
- For transactional running totals (`paginated_context`) and HTML header/footer placement (`header_html_*`, `footer_html_*`), use the Python `PdfEngine` API path.
- The CLI currently exposes direct text header/footer flags (`--header-each`, `--footer-each`) for simpler cases.

CLI watermark parity example:

```bash
fullbleed --json render \
  --html-str "<h1>Watermark probe</h1><p>hello</p>" \
  --css-str "body{font-family:sans-serif}" \
  --watermark-text "INTERNAL" \
  --watermark-layer overlay \
  --watermark-opacity 0.12 \
  --watermark-rotation -32 \
  --out output/watermark_probe.pdf
```

## Reference-Image Parity Workflow (Practical)

When targeting a design reference image (for example reference image exports), this loop has worked well:

1. Start from `fullbleed init` so CSS/font/icon baselines are vendored and pinned.
2. For scaffolded projects, run `python report.py` and set `FULLBLEED_IMAGE_DPI` as needed for sharper previews.
3. For direct CLI template rendering, register assets through the CLI (`--asset ...`) or `AssetBundle`.
4. Iterate with image artifacts enabled:

```bash
fullbleed --json render \
  --profile preflight \
  --html templates/invoice.html \
  --css templates/invoice.css \
  --asset vendor/css/bootstrap.min.css --asset-kind css --asset-name bootstrap \
  --asset vendor/icons/bootstrap-icons.svg --asset-kind svg --asset-name bootstrap-icons \
  --asset vendor/fonts/Inter-Variable.ttf --asset-kind font --asset-name inter \
  --emit-image output/pages_png \
  --emit-jit output/render.jit.jsonl \
  --emit-perf output/render.perf.jsonl \
  --out output/render.pdf
```

5. Use `--repro-record` / `--repro-check` once your layout stabilizes.

Practical tips:
- Compare against full-page exports when available.
- Keep a fixed preview DPI (for example `144` or `200`) across iterations.
- Commit PNG baselines for repeatable visual checks.

## Public Golden Regression Suite

Launch-grade render regression coverage is available under `goldens/` with three fixtures:

- `invoice`
- `statement`
- `menu`

Golden contract assets:

- Expected hashes: `goldens/expected/golden_suite.expected.json`
- Expected PNG baselines: `goldens/expected/png/<case>/<case>_page1.png`

Run against committed expectations:

```bash
python goldens/run_golden_suite.py verify
```

Refresh baselines intentionally:

```bash
python goldens/run_golden_suite.py generate
```

## Human + AI Operating Mode

Recommended automation defaults:

```bash
fullbleed --json-only render ...
```

Why this is agent-safe:

- For command-execution JSON payloads, `schema` is always present.
- Parser usage errors (`exit=2`) are emitted by argparse as usage text, not JSON payloads.
- `ok` indicates success/failure without parsing text.
- Optional artifacts are explicitly named in `outputs`.
- Schema introspection is available at runtime (`--schema`).

Example parse loop:

```python
import json, subprocess

proc = subprocess.run(
    [
        "fullbleed", "--json-only", "render",
        "--html", "templates/report.html",
        "--css", "templates/report.css",
        "--out", "output/report.pdf",
    ],
    capture_output=True,
    text=True,
    check=False,
)

payload = json.loads(proc.stdout)
assert payload["schema"] == "fullbleed.render_result.v1"
assert payload["ok"] is True
print(payload["outputs"]["pdf"])
```

## MACHINE_CONTRACT.v1

```json
{
  "schema": "fullbleed.readme_contract.v1",
  "package": "fullbleed",
  "cli_entrypoint": "fullbleed",
  "dev_cli_entrypoint": "python -m fullbleed_cli.cli",
  "python_module": "fullbleed",
  "json_discriminator": "schema",
  "core_commands": [
    "render",
    "verify",
    "plan",
    "debug-perf",
    "debug-jit",
    "run",
    "finalize",
    "inspect",
    "compliance",
    "doctor",
    "capabilities",
    "assets",
    "cache",
    "init",
    "new"
  ],
  "result_schemas": [
    "fullbleed.render_result.v1",
    "fullbleed.verify_result.v1",
    "fullbleed.plan_result.v1",
    "fullbleed.run_result.v1",
    "fullbleed.inspect_pdf.v1",
    "fullbleed.inspect_pdf_batch.v1",
    "fullbleed.inspect_templates.v1",
    "fullbleed.compose_plan.v1",
    "fullbleed.compliance.v1",
    "fullbleed.capabilities.v1",
    "fullbleed.doctor.v1",
    "fullbleed.assets_list.v1",
    "fullbleed.assets_info.v1",
    "fullbleed.assets_install.v1",
    "fullbleed.assets_verify.v1",
    "fullbleed.assets_lock.v1",
    "fullbleed.cache_dir.v1",
    "fullbleed.cache_prune.v1",
    "fullbleed.init.v1",
    "fullbleed.new_template.v1",
    "fullbleed.new_list.v1",
    "fullbleed.new_search.v1",
    "fullbleed.new_remote.v1",
    "fullbleed.debug_perf.v1",
    "fullbleed.debug_jit.v1",
    "fullbleed.repro_record.v1",
    "fullbleed.error.v1"
  ],
  "artifact_flags": [
    "--emit-manifest",
    "--emit-jit",
    "--emit-perf",
    "--emit-glyph-report",
    "--emit-page-data",
    "--emit-compose-plan",
    "--emit-image",
    "--image-dpi",
    "--deterministic-hash",
    "--repro-record",
    "--repro-check"
  ],
  "fail_on": ["overflow", "missing-glyphs", "font-subst", "budget"],
  "budget_flags": ["--budget-max-pages", "--budget-max-bytes", "--budget-max-ms"],
  "profiles": ["dev", "preflight", "prod"],
  "pdf_version_default": "1.7",
  "known_exit_codes": {
    "0": "success",
    "1": "command-level validation/operational failure",
    "2": "argparse usage error",
    "3": "CLI runtime/input error wrapper"
  }
}
```

## Important Behavior Notes

- `render --json` cannot be combined with `--out -` (stdout PDF bytes).
- `verify` defaults to stdout PDF unless `--emit-pdf` is provided; for machine mode, use `--emit-pdf <path>`.
- `--emit-image <dir>` writes per-page PNGs as `<stem>_pageN.png` (stem comes from `--out`/`--emit-pdf`, or `render` when streaming PDF to stdout).
- In template auto-compose runs, `--emit-image` artifacts are rasterized from finalized composed pages and report `outputs.image_mode=composed_pdf`; otherwise `image_mode=overlay_document`.
- `outputs.deterministic_hash_mode` is `pdf_only` by default and `artifact_set_v1` when image artifacts are emitted.
- If both `--emit-page-data` and `--emit-glyph-report` are set, current engines use a combined API and render once; older engines without that API fall back to a double render.
- Production target is PDF `1.7`.
- `run` accepts `--html-str` without requiring `--html`.
- `init` now scaffolds `COMPLIANCE.md` for project-level release review.
- `compliance --json` emits machine-readable legal/procurement diagnostics.
- `--watermark-layer underlay` is accepted as a legacy alias and normalized to `background`.
- `--emit-manifest` includes a `watermark` object with `text|html|image|layer|semantics|opacity|rotation|enabled`.
- `--fail-on overflow` is enforced from placement data and may auto-enable internal JIT planning.
- `--fail-on font-subst` is enforced using missing glyph and fallback diagnostics.
- `--allow-fallbacks` allows fallback diagnostics to remain informational for `missing-glyphs` / `font-subst` gates while still reporting them in JSON output.
- `--fail-on budget` requires at least one budget threshold flag.
- `--repro-check` fails on input/hash drift and lock hash mismatches when lock data is available.
- PDF/A and PDF/X/VT profiles require output intent metadata; `pdfa4`, `pdfa4e`, and `pdfa4f` emit PDF 2.0 automatically. PDF/A, PDF/X/VT, PDF/UA, and WTPDF text output enforces embedded-font constraints, and CLI errors include an actionable hint to add an embeddable font asset.
- `--pdf-profile pdfua1` enables tagged output and PDF/UA-1 identification metadata. Treat verifier/seed traces as machine evidence before making external conformance claims.
- `argparse` usage errors exit with code `2` and emit usage text (not JSON), even when `--json` is present.

## Related Docs

- Agent workflow guide: `llm.txt`
- CLI JSON contract quick reference: `cli_schema.md`
- CLI epoch/spec: `CLI_EPOCH.md`
- PDF template/XObject composition guide: `docs/pdf-templates.md`
- Licensing guide: `LICENSING.md`
- Third-party notices: `THIRD_PARTY_LICENSES.md`
- Living docs example project: `examples/living_docs_atlas/README.md`
- Roofing invoice parity example: `examples/roofing_invoice/README.md`
- Iconography smoke example: `examples/iconography_test/README.md`
- Public golden regression suite: `goldens/README.md`

## License

Fullbleed is licensed under the MIT License (`MIT`). Commercial use,
modification, distribution, and use in proprietary software are permitted
subject to the notice-preservation requirement in `LICENSE`.

Cargo and PyPI metadata both declare `MIT`.

- Copyright notice: `COPYRIGHT`
- Third-party notices: `THIRD_PARTY_LICENSES.md`
- Practical licensing guide: `LICENSING.md`

For license information, please visit `fullbleed.dev` or email `info@fullbleed.dev`.

License integrity gate (CI-friendly, no build required):

```bash
python tools/check_license_integrity.py --json
```
