# Report design

Aesthetic guidance for the HTML you author before uploading it to LeafPage. This is principles, not a template — there is deliberately no boilerplate to paste in below. Match these to the content; don't force content to fit a fixed shape.

## Why self-contained, precisely

LeafPage does not technically block external resources — a `<script src="https://cdn…">` or a remote `<img>` will load. Self-contained HTML (inline CSS, inline `<script>`, images as `data:` URIs) is a strong recommendation for a different reason: **the pinned URL is a promise**. `/{code}/` is meant to render identically years from now, offline-capable, with nothing to fetch and nothing that can go missing, get rate-limited, or change out from under the snapshot. A CDN dependency quietly breaks that promise the day the CDN link rots. On the free plan it's also the only option — a single `index.html` is all that ships — but even on pro, where sibling asset files are allowed, prefer inlining unless the asset is large enough that inlining meaningfully bloats the page.

## Design principles

**Readable measure.** Body text wants roughly 60–80 characters per line. Constrain prose with a `max-width` (around `65ch` or `680–760px`) rather than letting it stretch edge-to-edge on a wide viewport.

**Type hierarchy.** Establish 3–4 clear size/weight steps (e.g. page title, section heading, body, caption) and use them consistently. A report with one size of bold and one size of regular text reads as flat and undifferentiated.

**Dual theme.** Ship both a light and a dark palette; don't assume the reader's background. At minimum:

```css
:root { --bg: #fff; --fg: #111; }
@media (prefers-color-scheme: dark) { :root { --bg: #0b0b0c; --fg: #eee; } }
body { background: var(--bg); color: var(--fg); }
```

Check contrast in both modes, not just one. Don't hard-code white cards or black text outside variables — they'll invert badly.

**Responsive layout.** Reports get opened on phones as often as desktops. Use relative units and flex/grid layouts that reflow; give wide elements (tables, code blocks, wide diagrams) their own `overflow-x: auto` container so they scroll internally instead of blowing out the page width.

**Charts without a CDN.** Build charts as inline SVG (hand-written or generated by inline `<script>` at load time) or plain-JS canvas drawing. No chart-library CDN link — see "Why self-contained" above. A few clean SVG bars or a line path is usually enough; it doesn't need to be a full charting engine.

**Icons.** When the page calls for icons and the user hasn't specified a set, default to Lucide-style inline SVG (24×24 viewBox, `fill="none"`, `stroke="currentColor"`, `stroke-width="2"`, ISC-licensed) — each icon is just a few lines of `<svg>` pasted inline, never via npm, CDN, or icon fonts. `currentColor` keeps icons matched to the surrounding text color in both light and dark themes. For an icon used repeatedly, define it once in a hidden `<svg><symbol id="…">` block and reference it with `<use href="#…">`. Emoji are acceptable for casual pages; keep icon count low either way.

**Restrained color.** One accent color, used deliberately (links, key data points, emphasis) — not five competing hues. Let hierarchy come from type and spacing before it comes from color.

**Whitespace.** Generous margins and section spacing read as considered; cramped content reads as unfinished. When in doubt, add space before adding another visual device (border, background tint, icon).

## Before you publish: a quick self-check

- Does the page render correctly with no network access at all (open the file locally, offline)?
- Does it hold up in both light and dark system themes?
- Does the layout survive a narrow (~375px) viewport, and does anything wide (tables, code) scroll inside itself instead of overflowing the page?
- Is there a clear visual hierarchy — can you tell what matters most at a glance?
- Any remaining external `<script src>`, `<link href>`, or remote `<img src>` that should be inlined instead?

## When the user has opinions

All of the above is a default, not a mandate. If the user specifies a style, a brand, an existing template, or particular colors/fonts, follow what they asked for — these principles fill the gap only when nothing else was specified.
