# PRINT-DOC — the standard for one-file documents that print to PDF

> Read this before building any document whose end form is **a single HTML file a person opens, reads on
> screen, and prints to PDF** — an SOP, a manual, a policy, a checklist, any working document handed to other
> people. This file holds only what's common to *every* such document. A skill that produces one specific kind
> of document (an SOP, a manual) still owns its own section list, its own JSON schema fields, and its own
> content rules — write those in that skill's own `references/document.md`, and cite this file for everything
> below rather than repeating it.

---

## 1. Fully self-contained — no exceptions

- **Single HTML file.** No CDN, no external font, no external image, no external script or stylesheet
  reference of any kind. Must open correctly by double-click with the network disconnected — this is not a
  nice-to-have, it's the reason the format was chosen.
- **Fonts:** a system font stack with Thai-capable fallbacks, e.g.
  `font-family: -apple-system, "Segoe UI", "Noto Sans Thai", "Sarabun", system-ui, sans-serif;` — every
  browser/OS combination already has one of these installed; none needs to be downloaded.
- Any icon or illustration must be inline SVG or CSS, never an `<img src="http...">` or icon-font CDN.

## 2. Language and tone

- All visible document text in Thai. No emoji anywhere, in any view.
- **The document's tone must read more neutral than a chat reply** — per `CONVENTIONS.md` section 4, this
  file gets handed to people with no chat context around it (staff, auditors, new hires, customers). No trace
  of AI-generated phrasing ("ในฐานะ AI...", "หวังว่าจะเป็นประโยชน์", conversational filler, first-person
  self-reference). Write it the way a working document already in use at a real company reads.

## 3. The embedded data block — what makes the file re-editable

Every document built to this standard embeds its own source data, so a future session can reopen the same
file, read the data instead of re-interviewing the person, and regenerate the file with changes.

```html
<script type="application/json" id="doc-data">
{
  "docType": "doc-sop",
  "docCode": "...",
  "title": "...",
  "version": "1.0",
  "effectiveDate": "2026-08-25",
  "owner": "...",
  "approver": "...",
  "nextReview": "...",
  "revisionHistory": [
    { "version": "1.0", "date": "2026-08-25", "change": "สร้างเอกสารครั้งแรก", "by": "..." }
  ]
}
</script>
```

- The block id is always `doc-data` — never `sop-data`, `manual-data`, or any other per-skill name, so any
  document built to this standard can be recognized the same way regardless of which skill made it.
- `docType` is mandatory and states which producing skill's schema this document follows, using that skill's
  own name (e.g. `"doc-sop"`, `"doc-manual"`) — this is how a re-invoked skill knows what schema to expect
  before it even reads the rest of the block. A skill that covers several sub-kinds of the same document type
  (e.g. `doc-manual`'s tool guide / onboarding guide / customer guide) adds its own extra field to distinguish
  them — `docType` itself stays the producing skill's name.
- The fields shown above (`docType`, `docCode`, `title`, `version`, `effectiveDate`, `owner`, `approver`,
  `nextReview`, `revisionHistory`) are the shared minimum every document carries. The producing skill adds
  whatever fields hold its own content (steps, sections, FAQ, glossary — whatever that document type needs) in
  the same JSON object.
- Fields genuinely not collected can be an empty array/string, not omitted — the shape stays predictable for a
  future re-read.

**Mandatory rule for every skill that produces documents to this standard:** if the user hands back a file
this standard produced (recognizable by the `id="doc-data"` script block), **read that JSON block first**
before asking anything — every field already answered lives there. Ask only about what's changing. When
writing the new file: bump the version number, add one new row to the revision history table with today's
date and what changed, and keep everything not discussed this round exactly as it was.

## 4. Standard header block

Every full document opens with this block — a compact info table or labeled row, not prose:

| Field | Thai label |
|---|---|
| Document code | รหัสเอกสาร |
| Title | ชื่อเอกสาร |
| Version | เวอร์ชัน |
| Effective date | วันที่เริ่มใช้ |
| Owner | ผู้ดูแล |
| Approver | ผู้อนุมัติ |
| Next review | ทบทวนครั้งถัดไป |

## 5. Revision history table

Every full document ends with a revision history table: version, date, what changed, who changed it. Pick
oldest-first or newest-first and state which — never leave the order ambiguous.

## 6. Two views in one file

Every document built to this standard ships **two views from the same data**, toggled by a class on the
document root (e.g. `<body class="view-full">` / `<body class="view-card">`):

- **The full document** — read at a desk, complete detail.
- **A one-page card** — glanced at in the moment, large type, essentials only. What belongs on the card
  differs by document type (a wall-card of steps for an SOP, a getting-started card for a manual) — the
  producing skill's own reference defines the content; this standard only fixes the mechanism.

**The print buttons set the view class themselves before printing** — never rely on the user having manually
switched the on-screen toggle first. Each button: set the class, then call `window.print()`.

## 7. On-screen chrome (`no-print`)

- A `no-print` button bar with the print actions for both views, plus a way to switch which view shows on
  screen.
- One short `no-print` line explaining PDF export: "กด Cmd+P (แมค) หรือ Ctrl+P (วินโดวส์) แล้วเลือกปลายทางเป็น
  Save as PDF"
- Both must vanish completely under `@media print`.

## 8. Print rules

```css
@page {
  size: A4;
  margin: 18mm 16mm;
}

@media print {
  .no-print { display: none !important; }
}
```

- Printing one view must produce only that view — never both mixed together.
- **No step, table row, or checklist line may split across a page break.** Apply `break-inside: avoid;` (and
  `page-break-inside: avoid;` for older engines) to each such block.
- **Table headers repeat on a new page** — use `<thead>` properly so the browser's own repeat-on-break-page
  behavior applies; do not fake header rows with plain `<div>`s that lose this behavior.
- Checkboxes (`<input type="checkbox">`) must still render as an empty tickable box in print — not disappear,
  not collapse to plain text.
- **Never rely on color alone to carry meaning.** Anything distinguished by color on screen (e.g. a warning
  callout) needs a textual marker too (bold label, border, or the word itself) so it still reads correctly in
  black-and-white print.

## 9. The one-page card must actually fit one page

**If content doesn't compress to one A4 page, compress it further until it does — never let it spill to a
second page.** A second-page "one-page card" defeats the format entirely.

**If anything had to be merged or cut to make it fit, say so plainly to the user in the chat reply** (not
buried only inside the document) — name exactly what was compressed and why. E.g. "การ์ดหน้าเดียวย่อรวมขั้นตอน
ที่ 3-5 เป็นข้อเดียว เพราะใส่ครบไม่พอหน้า."

Add `break-inside: avoid` framing to the card's blocks too — content that fits by character count can still
drift onto a phantom second page from margin/line-height rounding, so don't rely on length alone.

## 10. Illustrations — never fabricate

**The producing skill cannot generate real screenshots or photos of anything.** If the document should
contain one (a screenshot of a screen, a photo of a physical setup):

- Place a visible bordered placeholder box with the caption stating exactly what belongs there, e.g.
  `[ใส่ภาพหน้าจอ: หน้าจอตอนกดปุ่มยืนยันออเดอร์]`.
- **Never invent, fake, or imply an image already exists.** No generated mock, no stock photo standing in for
  a real one.
- At the end of the chat reply, tell the user plainly how many image slots need filling and what each one is,
  so nothing gets missed.

## 11. Checklist — every producing skill's own checklist must include these

- [ ] File opens by double-click with no network connection; grep confirms zero `http://`/`https://`/CDN
      reference anywhere in the file
- [ ] `id="doc-data"` present, with `docType` set correctly, holding every field this document type defines
- [ ] Both views present, switchable on screen, each printing without the other and without `.no-print`
      elements
- [ ] The one-page card fits one real A4 page — if content was compressed to make it fit, the chat reply says
      exactly what and why
- [ ] No table row, step, or checklist line splits across a page break when printed
- [ ] Readable in black and white — no meaning carried by color alone
- [ ] Zero emoji, zero AI-sounding phrasing, all visible text in Thai
- [ ] Every image slot is a labeled placeholder, never a fabricated image — and the chat reply lists how many
      need filling
