Initial commit

This commit is contained in:
Z User
2026-06-06 05:21:10 +00:00
Unverified
commit 6664758a6d
493 changed files with 135653 additions and 0 deletions

153
skills/pdf/configs/components.md Executable file
View File

@@ -0,0 +1,153 @@
# Components — Art Direction JSON Lexicon
This file defines the strict component vocabulary for the Creative pipeline.
**CRITICAL RULE: DO NOT OUTPUT HTML OR CSS.**
You are an Art Director. You only output JSON. To use these components, insert their corresponding JSON objects into the `components` array of your page blueprint. The `design_engine.py` will automatically compile them into gallery-grade visual assets.
---
## 1. Glass_Canvas
The primary container for readable body text. Simulates printed text on frosted acrylic.
**JSON Blueprint Structure:**
```json
{
"type": "Glass_Canvas",
"markdown_content": "### The Divide\nYour text goes here. Supports standard Markdown.",
"tension_score": 0.8
}
```
**Parameters:**
- `markdown_content`: (Required) The actual text. **Recommended under 150 words; absolute max 250 words.**
- `tension_score`: (Optional, 0.0 to 1.0) Semantic tension. Drives dynamic font weight (300 to 900). Use `0.1` for calm/light text, `0.9` for crisis/heavy text. Do NOT use on data-heavy pages.
---
## 2. Hero_Typography
Massive, page-dominating title text that physically interacts with the background via blend modes.
**JSON Blueprint Structure:**
```json
{
"type": "Hero_Typography",
"content": "THE WEIGHT<br>OF SILENCE",
"weight": "black",
"variant": "standard",
"scale": 6
}
```
**Parameters:**
- `content`: (Required) The text. Use `<br>` for deliberate typographic line breaks.
- `weight`: (Required) `"black"` (900 weight, dominating) or `"thin"` (100 weight, whisper-quiet/elegant).
- `variant`: (Optional) `"standard"` (default) only. ~~`"vertical_accent"`~~ is **NOT implemented** in `design_engine.py` — the engine silently ignores this parameter. Use `Floating_Meta` component instead for rotated/vertical decorative text.
- `scale`: (Optional, integer 16) Typographic scale level. The engine maps this to fluid CSS `clamp()` sizes:
- `6``clamp(64px, 12vw, 150px)` — Hero/Display, maximum impact
- `5``clamp(48px, 8vw, 96px)` — Primary Title
- `4``clamp(32px, 5vw, 56px)` — Subheadline
- `3``clamp(20px, 3vw, 32px)` — Lead Paragraph
- `2``16px` — Body
- `1``10px` — Meta/Caption
If omitted, the engine uses the default hero font size from CSS.
---
## 3. Floating_Meta
Small-text metadata positioned vertically in corners, mimicking art monograph indexes.
**JSON Blueprint Structure:**
```json
{
"type": "Floating_Meta",
"position": "bottom-right",
"items": [
"CATALOG NO. 2026.031",
"EDITION 1/500"
]
}
```
**Parameters:**
- `position`: (Required) `"top-left"`, `"top-right"`, `"bottom-left"`, or `"bottom-right"`.
- `items`: (Required) Array of short strings (dates, edition numbers, refs).
---
## 4. Stat_Block
Data sculpture. Transforms boring numbers into massive visual objects.
**JSON Blueprint Structure:**
```json
{
"type": "Stat_Block",
"number": "97.3",
"unit": "%",
"label": "COMPLETION RATE"
}
```
**Parameters:**
- `number`: The core massive digit.
- `unit`: Tiny unit attached to the number.
- `label`: Metadata label below the number.
---
## 5. Hairline_Divider
Ultra-thin separator lines. Structural, like fold lines in print.
**JSON Blueprint Structure:**
```json
{
"type": "Hairline_Divider",
"style": "accent"
}
```
**Parameters:**
- `style`: `"bleed"` (full width edge-to-edge) or `"accent"` (short centered 30% line).
---
## 6. Page_Ghost_Number
Giant, 4% opacity watermark numbers that become part of the page's atmosphere.
**JSON Blueprint Structure:**
```json
{
"type": "Page_Ghost_Number",
"number": "03"
}
```
---
## 7. Shaped_Canvas (Advanced Semantic Shape-Wrapping)
A container where text flows around a non-rectangular shape. The empty space created by the shape IS the visual design.
**JSON Blueprint Structure:**
```json
{
"type": "Shaped_Canvas",
"shape_keyword": "wave",
"markdown_content": "The ocean stretched endlessly... (recommended under 150 words, absolute max 250)"
}
```
**Parameters & Shape Presets:**
- `shape_keyword`: MUST be one of the following:
- `"circle"`: Unity, spotlight, focus.
- `"wave"`: Ocean, flow, fluidity.
- `"diagonal_slash"`: Disruption, change, energy.
- `"diamond"`: Luxury, precision, crystalline.
- `"wedge_right"`: Direction, progress, forward motion.
- `markdown_content`: Text to wrap around the shape.
**CRITICAL Layout Constraint:**
If a page contains a `Shaped_Canvas`, that page's `archetype` MUST be set to `"shaped_editorial"` in the JSON. Never mix `Shaped_Canvas` and `Glass_Canvas` on the same page.
---
## Blueprint Assembly Guidelines
When constructing the JSON `pages` array, keep these layering and composition rules in mind:
1. **Backgrounds**: Do NOT try to place background SVGs as components. Backgrounds are declared globally in the `art_direction.background_svg` field (`"flow"`, `"grid"`, `"noise"`, or `"continuous_flow"`).
2. **Layering**: The order of objects in the `components` array roughly dictates their top-to-bottom rendering.
3. **Breathing Room**: Less is more. A page with just one `Hero_Typography` and one `Floating_Meta` is highly sophisticated. Cramming 5 components on a page communicates desperation.

93
skills/pdf/configs/fonts.md Executable file
View File

@@ -0,0 +1,93 @@
# Font System
## Font Stacks (by pipeline)
### Creative Pipeline (Playwright / HTML)
Fonts are loaded via Google Fonts CDN in the HTML `<head>`:
```html
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;900&family=Noto+Sans+SC:wght@300;400;500;700;900&family=Playfair+Display:ital,wght@0,400;0,700;0,900;1,400&display=swap" rel="stylesheet">
```
#### Variable Font (for Tension Typesetting)
When `tension_score` is used on `Glass_Canvas`, the engine switches to **Inter Variable** for continuous weight interpolation (100900):
```html
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@100..900&display=swap" rel="stylesheet">
```
This enables `font-variation-settings: 'wght' <value>` for smooth, non-discrete weight transitions. The standard discrete-weight URL is still used when tension is not active.
| Variable | Stack | Usage |
|----------|-------|-------|
| `--font-sans` | Inter, Noto Sans SC, Helvetica Neue, Apple Color Emoji, Segoe UI Emoji, sans-serif | Body text, UI elements, stats |
| `--font-serif` | Playfair Display, Noto Serif SC, Cormorant Garamond, Apple Color Emoji, serif | Hero text, editorial headlines |
| `--font-mono` | SF Mono, Consolas, Apple Color Emoji, monospace | Floating meta, timestamps, codes |
### Report Pipeline (ReportLab)
ReportLab requires registered fonts. CJK support via `UniSong` / `UniHei` (built into reportlab.lib.fonts):
```python
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.cidfonts import UnicodeCIDFont
pdfmetrics.registerFont(UnicodeCIDFont('STSong-Light')) # Song-ti (serif-like)
# Use 'STSong-Light' for body, headings
```
> **⚠️ ReportLab CANNOT render emoji.** If content has emoji, route to Creative pipeline.
### Academic Pipeline (Tectonic / LaTeX)
CJK support via `ctex` package:
```latex
\usepackage{ctex} % Auto-selects appropriate CJK fonts
```
For manual font selection:
```latex
\setCJKmainfont{Noto Serif CJK SC}
\setCJKsansfont{Noto Sans CJK SC}
```
> **⚠️ LaTeX silently drops emoji characters.** If content has emoji, route to Creative pipeline.
## Emoji Font Fallback
All Creative pipeline font stacks include emoji fallback:
- **macOS**: `Apple Color Emoji` (system default, full color emoji)
- **Windows**: `Segoe UI Emoji`
- **Linux**: `Noto Color Emoji` (install: `apt install fonts-noto-color-emoji`)
Chromium (used by Playwright) on macOS renders emoji natively — no extra configuration needed.
## CJK Font Weight Guide
| Weight Value | Inter Equivalent | Noto Sans SC Name | Usage |
|-------------|------------------|-------------------|-------|
| 300 | Light | Light | Subtitles, captions, meta text |
| 400 | Regular | Regular | Body text |
| 500 | Medium | Medium | Semi-emphasis |
| 700 | Bold | Bold | Headlines, emphasis |
| 900 | Black | Black | Hero text, stat numbers |
> **Tip**: Noto Sans SC weights 300900 cover most use cases. Always load at least 400 and 700 via Google Fonts.
## Font Size Scale
Recommended type scale (base: 16px body):
| Role | Size | Weight | Line-Height |
|------|------|--------|-------------|
| Page Ghost Number | 240px | 900 | 1.0 |
| Hero (large) | clamp(48px, 10vw, 110px) | 900 | 0.88 |
| Hero (serif thin) | clamp(48px, 10vw, 110px) | 100 | 0.88 |
| Stat Number | clamp(32px, 5vw, 56px) | 900 | 0.9 |
| Section Title | 24px | 800 | 1.2 |
| Subsection | 20px | 700 | 1.3 |
| Body | 16px | 400 | 1.61.7 |
| Caption | 14px | 400 | 1.5 |
| Floating Meta | 10px | 400 (mono) | 1.4 |
| Stat Label | 11px | 400 | 1.2 |

View File

@@ -0,0 +1,263 @@
# Visual Framework — Aesthetic Axioms
Non-template design system. This file is the LLM's thinking framework — not a list of styles to pick from, but a set of immutable laws that govern every design decision.
---
## The Three Absolutes
1. **Restraint** — Remove until it hurts. Then remove one more thing.
2. **Contrast** — Hierarchy through scale and weight, never through color multiplication.
3. **Space Metaphor** — Every page has physical energy: gravity, tension, breathing.
### The Anti-Gaudy Imperative
> **When in doubt, remove. Never add.**
A document looks "cheap" or "土" when it has too many competing visual elements. The cure is always subtraction, never rearrangement.
**Red flags that a design is gaudy:**
- More than 3 decorative elements on a single body page
- Icons or emoji used as section header decoration (use typography instead)
- Decorative borders or frames around body content
- Pattern/texture backgrounds on body pages
- 3+ different hue families visible simultaneously
- Elements added "because there's empty space" rather than for function
**The fix is always:** Delete the decorative element. If the page still communicates its message clearly, it didn't need the decoration. If it doesn't, fix the typography hierarchy — not by adding more visual noise.
### 🚫 The Stock Image / Clipart / AI-Generated Decoration Ban
> **ABSOLUTE PROHIBITION: Do NOT embed stock photos, clipart, watercolor illustrations, AI-generated images (flowers, patterns, borders, frames, ornaments), or any decorative raster/vector artwork into PDF documents.**
This is the #1 source of "cheap" / "土" / "婚庆风" design. Examples of what is BANNED:
- ✘ Watercolor flowers / roses / floral corners / vine borders
- ✘ Gold/metallic decorative frames or borders
- ✘ Stock photo backgrounds (landscapes, textures, marble)
- ✘ Clipart illustrations (ribbons, bows, hearts, stars)
- ✘ AI-generated decorative artwork (DALL-E flowers, Midjourney patterns)
- ✘ Any `<img>` tag used for purely decorative (non-informational) purposes
- ✘ Unsplash/Pexels/Pixabay stock photos used as background or decoration
**What IS allowed:**
- ✔ Geometric shapes rendered in CSS/SVG (circles, lines, rectangles — from `geometry.md`)
- ✔ Typography-based decoration (oversized letters, watermark text, letter-spacing effects)
- ✔ Color blocks and gradients (within palette rules)
- ✔ User-provided photos/logos that are CONTENT (not decoration)
- ✔ Charts and data visualizations
- ✔ Diagrams that convey information
**The principle:** If removing an image doesn't reduce the information content of the document, that image is decoration and should be replaced with typography or geometric elements.
**Wedding invitations, event cards, certificates:** Use elegant typography + geometric accents (thin lines, minimal shapes) + generous whitespace. A beautifully typeset name in 48pt serif with 6pt letter-spacing is infinitely more elegant than watercolor roses.
---
## Color Axioms
### The 60-30-10 Law
Every design consists of exactly three tonal zones:
| Zone | Coverage | Role | Generated by |
|------|----------|------|-------------|
| **60% — Ground** | Background, margins, empty space | Sets mood; the viewer doesn't "see" it consciously | `--c-bg` from `design_engine.py` |
| **30% — Structure** | Cards, dividers, secondary areas | Provides architecture; same hue family as ground, different lightness | `--c-mid` |
| **10% — Emphasis** | Headlines, key numbers, one accent element | Draws the eye; the only place "color" lives | `--c-accent` |
### Saturation Discipline (HARD RULE)
All colors pass through `design_engine.py` which enforces:
- **Saturation range**: 0.05 0.25 (HSL). This is non-negotiable.
- **No pure primaries**: Pure red (#ff0000), blue (#0000ff), yellow (#ffff00) are forbidden.
- **Max 3 hues** in the entire document. Variations in lightness/saturation don't count as separate hues.
### Lightness Polarity
Only two lightness regimes exist. The middle is forbidden.
| Mode | Background L | Text L | Forbidden Zone |
|------|-------------|--------|----------------|
| **Dark** (Cinematic) | < 0.10 | > 0.85 | L between 0.300.70 for backgrounds |
| **Light** (Editorial) | > 0.95 | < 0.15 | L between 0.300.70 for backgrounds |
Muddy mid-tones (L 0.300.70) for backgrounds produce the "cheap web app" look. Never.
### What Color is NOT For
Color does not create hierarchy. Size and weight do.
| ❌ Wrong | ✅ Right |
|----------|---------|
| Blue heading, grey subheading, black body | All same hue; heading 900 weight 48px, sub 600 36px, body 400 16px |
| Colored tags/badges for categories | Monochrome tags with border weight variation |
| Gradient text on everything | Gradient text on exactly ONE hero element, nowhere else |
---
## Typography Axioms
### Weight is the New Color
Hierarchy comes from the contrast between extremes of weight:
| Element | Weight | Size Relative to Body |
|---------|--------|----------------------|
| Hero title | 100 (Thin) OR 900 (Black) | 46× body |
| Section heading | 700 | 2× body |
| Body | 400 | 1× (baseline) |
| Caption / metadata | 300 | 0.7× body |
The gap between hero and body must be **dramatic** — at least 4× size ratio. Anything less feels timid.
### Font Rules
- **Max 2 families per page**. One serif, one sans (or one display, one text). Never three.
- **Every `font-family` must end with a generic**: `sans-serif`, `serif`, or `monospace`.
- **For physical print (>500mm)**: Use `pt`/`mm` for font sizes, never `px`.
### Line-Height by Density
| Content Type | Line-Height | Why |
|-------------|------------|-----|
| Body text, paragraphs | 1.61.8 | Comfortable reading |
| Headings | 0.851.0 | Tight, sculptural — headings are visual objects, not sentences |
| Captions, metadata | 1.4 | Compact but readable |
---
## Space Axioms
### The Breathing Margin Rule (MANDATORY)
Every page must have **1012% clear margin** on all edges. Nothing — no text, no decoration, no card — may enter this zone.
The exact percentage depends on content density:
- **Sparse content** (hero pages, covers): 15% is fine — lots of air
- **Standard content** (editorial, data): **12%** is the sweet spot
- **Dense content** (tables, stat grids): 10% minimum — tighter but still breathable
Default in `design_engine.py`: `inset: 10% 12%` (vertical 10%, horizontal 12%).
```
┌──────────────────────────────┐
│ 10-12% margin (breathing) │
│ ┌────────────────────────┐ │
│ │ │ │
│ │ Content lives here │ │
│ │ (76-80% of canvas) │ │
│ │ │ │
│ └────────────────────────┘ │
│ 10-12% margin (breathing) │
└──────────────────────────────┘
```
Decorative SVG backgrounds may extend into the margin zone (they're atmospheric, not content). But all readable elements respect it.
### Negative Space is Content
Empty space is not "wasted space." It's a compositional element:
- A poster with 50% whitespace communicates **confidence**
- A poster crammed to 90% communicates **desperation**
- The ratio of content to void sets the emotional tone
### Proximity Rule
Related items are close. Unrelated items are far. The gap between unrelated elements should be **at least 3× the gap between related ones**.
---
## Intent → Visual Translation
Five design intents. Each describes an **atmosphere** — the emotional field the viewer should feel. Intents do NOT prescribe specific parameters (font weight, line-height, SVG type, etc.). All concrete parameter mappings live in `briefs/creative.md` § Intent Mapping Table and `design_engine.py` INTENT_HUES/INTENT_HARMONY_MAP.
### Calm
Stillness. The viewers breathing slows. Vast open space, restrained palette, nothing competes for attention. Covers healthcare, wellness, meditation, and minimalist aesthetics. The design communicates through what it *removes*.
### Tension
Conflict. Sharp angles, dramatic contrast, elements that push against each other. Urgency, crisis, disruption. The page has physical energy — something is about to break or has already broken.
### Energy
Motion. Dense composition, slight rotations, warmth. Marketing, launches, social campaigns. The design vibrates — it wants to move off the page. Nothing is perfectly centered.
### Authority
Gravitas. Formal, deliberate, symmetrical. Government, finance, luxury, high-end corporate. Every element is placed with surgical precision. The design commands respect through restraint and weight.
### Warmth
Comfort. Rounded edges, generous spacing, earth tones. Food, lifestyle, home. The design feels like a warm room — inviting, soft, human.
---
> **Legacy mapping:** Serenity → Calm, Minimalism → Calm, Elegance → Authority. Old intent names are accepted as aliases in `design_engine.py` for backward compatibility.
---
## Advanced Visual Techniques
### Semantic-Topological Typesetting (Tension Score)
Text is not visually flat — its "weight" should mirror its emotional intensity. When a document has narrative arc (calm introduction → crisis → resolution), font weight should breathe with it.
**The Principle**: Assign a `tension_score` (0.01.0) to `Glass_Canvas` components. The engine maps this to a continuous font weight via Inter Variable font (300900 axis).
**When it matters**:
- Documents with 3+ pages and clear emotional shifts
- Storytelling: case studies, pitch decks, manifestos
- The reader may not consciously notice, but the subconscious weight variation creates "texture" in the reading experience — the same way a film score operates below awareness
**When to skip**:
- Single-page posters (no arc to express)
- Data-heavy reports (numbers don't have "feelings")
- Short documents where all paragraphs share the same tone
### Cross-Page Visual Continuity (Continuous Flow)
Multi-page documents are not a collection of isolated posters — they're a journey. The background should reflect this.
**The Principle**: Instead of generating independent SVGs per page, generate ONE continuous bezier curve spanning the entire document height, then slice it per-page via SVG `viewBox`. The result: curves that exit one page's bottom edge seamlessly enter the next page's top.
**When to use `continuous_flow`**:
- Multi-page (2+) documents with narrative structure
- Journey/timeline documents
- Brand pieces where seamless sophistication matters
- Best paired with: `Warmth`, `Elegance`, `Serenity` intents
**When to use regular `flow` instead**:
- Single-page documents (continuous has no meaning)
- Each page is conceptually independent (not a story)
### Semantic Shape-Wrapping (Shaped_Canvas)
The most dramatic of the three techniques. Text wraps around invisible geometric shapes, and the negative space itself becomes the illustration.
**The Principle**: A floating `<div>` with CSS `shape-outside` creates a non-rectangular boundary for text flow. The empty void left by the shape is the design element.
**The key insight**: We're not adding an image — we're sculpting the TEXT into a shape. This is extreme minimalism: zero visual assets, maximum visual impact.
**When to use**:
- Pages that need a "wow" without images
- Section openers, cover alternatives
- Content that thematically connects to a shape (ocean → wave, progress → wedge)
- Pages with moderate text density (100200 words) — the shape needs room
**When NOT to use**:
- Dense content pages (shape eats 3040% of text area → overflow risk)
- Together with `Glass_Canvas` on the same page (backdrop-filter conflicts)
- More than one per page (visual chaos)
---
## Quality Litmus Tests
Before delivering, every page must pass these:
| Test | Method |
|------|--------|
| **3-meter test** | Can you read the headline from 3 meters away? (size hierarchy) |
| **Squint test** | Squint at the page — do you see clear dark/light zones? (contrast) |
| **Magazine test** | Could this be a page in Monocle, Kinfolk, or Cereal magazine? (taste) |
| **Removal test** | Can you remove any element without losing meaning? If not, you have too little. If yes, remove it. |
| **Color count** | Count distinct hues. If > 3, you've failed the color axiom. |
| **Saturation check** | Run `design_engine.py audit` — any S > 0.25 on non-accent = violation |
| **Breathing check** | Is there 15% clear margin on all edges? |
| **Consistency** | Do all pages share the same font pairing, color tokens, line thickness, and corner radius? |