| name | html-document-style |
| description | Claude Warm Academic Humanism genre — the safe warm default. Use when: guide, manual, handbook, tutorial, proposal, kickoff, whitepaper, thought-leadership, memo, announcement, changelog, or postmortem. Trigger: guide / manual / handbook / how-to / tutorial / documentation / reference / spec / onboarding / proposal / kickoff / whitepaper / vision / manifesto / memo / newsletter / changelog / release notes / postmortem / 指南 / 手册 / 文档 / 提案 / 白皮书 / 说明. Inherits typography-system. NOT for: data dashboards (bloomberg), strategy decks (mckinsey), research briefs (economist). |
name: html-document-style
description: "Use when generating a standalone single-file HTML deliverable: whitepaper, guide, proposal, kickoff doc, manual, spec, tutorial, or poster. NOT for research reports or data-dense analyses (use html-economist-style). NOT for React components or inline HTML."
combo-tags: [html-rendering]
HTML Document Style -- Warm Academic Humanism
Typography base (inherited): this skill composes ON TOP of the shared
typography-system foundation — link/inline
tokens/typography.css FIRST, then layer this skill for color + accent +
brand font-family ONLY. Never re-declare the type scale, vertical rhythm,
measure, page frame, or CJK rules; keep mixed CJK+Latin stacks Latin-first.
Verify: python3 scripts/audit-genre-typography.py.
This is the canonical default style for all standalone HTML documents produced
by AI-Fleet workflows. It implements an "Anthropic/Claude-inspired" warm academic
humanism aesthetic that conveys authority, clarity, and approachability.
When generating any single-file HTML deliverable (whitepaper, project kickoff,
report, proposal, poster, dashboard printout), apply this design system unless
the user explicitly requests an alternative style.
Universal Layout Frame (MUST inject before any other CSS)
Non-negotiable. Satisfies pre-tool-style-router-gate.py dual-verify (identifier +
canonical token signature --claude-) AND prevents the hero/body misalignment
bug at wide viewports by sharing one reference frame across cover and body.
:root{
--claude-page-max:1100px;
--claude-page-gutter-total:clamp(32px,6vw,96px);
}
.frame{
width:min(var(--claude-page-max),calc(100% - var(--claude-page-gutter-total)));
margin-inline:auto;
}
.cover, .hero{padding-block:64px 40px;padding-inline:0;}
main.frame{padding-block:32px 80px;}
.cover{margin-bottom:0;}
main.frame > section{margin-bottom:72px;}
<section class="cover">
<div class="frame">
<h1>Document Title</h1>
<p class="subtitle">…</p>
<div class="herostats">…</div>
</div>
</section>
<main class="frame">…</main>
Hero must anchor its bottom edge. A cover holding only badge + h1 + short
left-aligned subtitle leaves a hollow band of cream before the first section on
tall/wide viewports — the content stops high while the padding keeps going. End
the hero with a content element that spans the frame width (a stat strip, a mini
table-of-contents, or the document's first visual pulled up into the cover) so
the cover→body transition is a deliberate edge, not empty padding. Keep the
subtitle wide enough (max-width ≥ 860px or unset) so it uses the frame instead
of stranding a void on the right.
Anti-pattern: .cover { padding-inline: 8vw } combined with
main { max-width: 1100px; margin: 0 auto } breaks alignment on wide screens
(>1480px) — cover sits at 8vw of viewport while body centers in 1100px. Always
wrap cover children in .frame and use <main class="frame">.
Design Philosophy
- Warm, not cold: Cream/paper backgrounds replace sterile white or dark themes
- Academic, not corporate: Serif titles convey authority; sans-serif body ensures readability
- Humanist, not mechanical: Terracotta and mustard tones feel organic, not neon
- Restrained, not flashy: Paper-like shadows replace glassmorphism; motion is purposeful
Color Palette (CSS Custom Properties)
:root {
--bg-primary: #F3F0E9;
--bg-card: #FFFFFF;
--bg-card-hover: #FAF8F4;
--bg-warm: #EDE8DD;
--border: rgba(44,44,46,0.08);
--border-strong: rgba(44,44,46,0.15);
--text-primary: #2C2C2E;
--text-secondary: #5C5C5E;
--text-muted: #9B9B9D;
--accent: #D67052;
--accent-glow: rgba(214,112,82,0.08);
--accent-light: rgba(214,112,82,0.06);
--mustard: #F0B857;
--mustard-light: rgba(240,184,87,0.10);
--green: #4A9D6E;
--green-light: rgba(74,157,110,0.08);
--amber: #D4943A;
--red: #C44536;
--purple: #6B5B8D;
--navy: #1B3A5C;
--navy-light: rgba(27,58,92,0.06);
--cyan: #1B3A5C;
--font-serif: 'Crimson Pro', 'Noto Serif SC', 'Songti SC', 'SimSun', 'STSong', serif;
--font: 'Source Sans 3', 'Noto Sans SC', 'PingFang SC', 'Microsoft YaHei', sans-serif;
--mono: 'JetBrains Mono', 'SF Mono', 'Fira Code', monospace;
--radius: 10px;
--radius-sm: 6px;
--shadow-sm: 0 1px 3px rgba(44,44,46,0.04), 0 1px 2px rgba(44,44,46,0.02);
--shadow-md: 0 2px 8px rgba(44,44,46,0.06), 0 4px 16px rgba(44,44,46,0.04);
--shadow-lg: 0 4px 12px rgba(44,44,46,0.08), 0 8px 32px rgba(44,44,46,0.06);
}
Typography Rules
Font Loading (Google Fonts)
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Crimson+Pro:wght@400;600;700;800&family=Noto+Serif+SC:wght@400;700&family=Source+Sans+3:wght@400;600;700&display=swap" rel="stylesheet">
Hierarchy
| Element | Font | Weight | Size | Usage |
|---|
| Page title (h1) | var(--font-serif) | 800 | 3.2rem | Document title, hero |
| Section title (h2) | var(--font-serif) | 700 | 1.85rem | Section headings |
| Subsection (h3) | var(--font-serif) | 700 | 1.25rem | Card titles, sub-headings |
| Body text | var(--font) | 400 | 1rem (16px) | Paragraphs, descriptions |
| Labels / meta | var(--font) | 600 | 0.8rem | Section numbers, badges |
| Code / mono | var(--mono) | 400 | 0.85rem | Code blocks, technical IDs |
| Stat numbers | var(--font-serif) | 700 | 2.5rem+ | Key metrics, pricing |
CJK Optimization
body {
-webkit-font-smoothing: antialiased;
font-feature-settings: 'palt' 1;
}
Component Patterns
Nav (Sticky, Frosted)
position: sticky; top: 0; z-index: 100
- Background:
rgba(243,240,233,0.92) with backdrop-filter: blur(12px)
- Brand name in serif font, terracotta color
- Links:
font-weight: 600, hover shows terracotta tint background
Cards (Paper Shadow)
- Background:
var(--bg-card) (white)
- Border:
1px solid var(--border)
- Shadow:
var(--shadow-sm) default, var(--shadow-md) on hover
- Border-radius:
var(--radius) (10px)
- Transition:
all 0.25s ease
- Hover: lift with
transform: translateY(-2px) + stronger shadow
Section Dividers (Gradient)
Replace hard borders with centered gradient pseudo-elements:
section::before {
content: '';
display: block;
width: 120px;
height: 2px;
margin: 0 auto 60px;
background: linear-gradient(90deg, transparent, var(--accent), transparent);
opacity: 0.3;
}
Blockquotes (Left Border Accent)
blockquote {
background: var(--bg-card);
border-left: 3px solid var(--accent);
padding: 28px 32px;
border-radius: 0 var(--radius) var(--radius) 0;
box-shadow: var(--shadow-sm);
font-size: 0.98rem;
line-height: 1.9;
}
Badges / Tags
.badge {
display: inline-block;
background: var(--accent-glow);
color: var(--accent);
padding: 8px 24px;
border-radius: 20px;
font-size: 12px;
font-weight: 700;
letter-spacing: 2px;
text-transform: uppercase;
font-family: var(--mono);
}
Pricing Cards (Recommended Highlight)
The recommended tier uses:
- Border:
2px solid var(--accent) (terracotta)
::after pseudo-element badge at top center:
.pricing-recommended {
position: relative;
border: 2px solid var(--accent);
}
.pricing-recommended::after {
content: 'RECOMMENDED';
position: absolute;
top: -1px; left: 50%; transform: translateX(-50%);
background: var(--accent);
color: #fff;
font-size: 10px; font-weight: 700;
letter-spacing: 1.5px;
padding: 4px 16px;
border-radius: 0 0 6px 6px;
}
Timeline (Vertical Line + Colored Dots)
- Vertical connector: 2px line in
var(--border-strong) via ::before on container
- Dots: 12px circles, colored per track/phase
- Left padding: 32px for text offset from dot
Metric Bars (Flat Minimal)
- Container:
height: 6px; background: var(--bg-warm); border-radius: 3px
- Fill: colored with respective accent (green/mustard/accent)
- No borders, no 3D effects
Layout Principles
- Max-width: 1100px centered container
- Padding: 36px horizontal on container
- Section spacing: 80-100px between sections
- Grid: CSS Grid with explicit column counts (see Grid Rules below)
- Two-column scope: Flexbox with gap, equal columns
- Responsive: Stack to fewer columns at 768px, single column at 640px
Grid Rules (Fixed Column Count)
Use explicit repeat(N, 1fr) for named grid classes. Never use auto-fit/auto-fill
when the class name implies a fixed column count:
.card-grid { display: grid; gap: 20px; }
.card-grid-2 { grid-template-columns: repeat(2, 1fr); }
.card-grid-3 { grid-template-columns: repeat(3, 1fr); }
.card-grid-4 { grid-template-columns: repeat(4, 1fr); }
.card-grid-2 { grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); }
Responsive fallback via media queries:
@media (max-width: 768px) {
.card-grid-3 { grid-template-columns: repeat(2, 1fr); }
.card-grid-4 { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 640px) {
.card-grid-2 { grid-template-columns: 1fr; }
.card-grid-3 { grid-template-columns: 1fr; }
.card-grid-4 { grid-template-columns: repeat(2, 1fr); }
}
When to use auto-fit: Only for truly fluid grids where the column count is
intentionally unknown (e.g., a photo gallery, tag cloud). Never for named -N classes.
Footer
<footer style="text-align:center; padding:60px 20px 40px; color:var(--text-muted); font-size:13px; line-height:2.2;">
<p>[ProjectName] v[X.Y] -- [Document Type]</p>
<p>Your Name | your@email.com</p>
<p style="font-size:12px; margin-top:8px;">[Generation date and data source attribution]</p>
</footer>
Definition Lists / Field Templates
When displaying structured field definitions (API schemas, data templates, config references),
never use fixed-width columns for monospace field names. Monospace names like
typical_input_categories (24+ chars) will overflow narrow columns.
Use a stacked layout instead:
.field-row {
padding: 18px 0;
border-bottom: 1px solid var(--border);
}
.field-name {
display: inline;
font-family: var(--mono);
font-size: 0.92rem;
font-weight: 600;
color: var(--accent);
margin-right: 12px;
}
.field-type {
display: inline;
font-size: 0.82rem;
color: var(--text-muted);
background: var(--bg-warm);
padding: 2px 10px;
border-radius: 4px;
}
.field-desc {
display: block;
margin-top: 8px;
font-size: 0.92rem;
color: var(--text-primary);
line-height: 1.85;
}
For table headers (field name / type / description column titles), use a separate
.field-row-header class with a 3-column grid since headers are short labels.
Minimum Font Sizes
- Body text: >= 0.92rem (14.7px)
- Labels / meta: >= 0.82rem (13.1px)
- Footer attribution: >= 12px
- Never go below 12px for any user-visible text
- Code blocks: >= 0.84rem for readability on screens
Muted Text Contrast
--text-muted must pass WCAG AA contrast ratio against --bg-primary (#F3F0E9).
- Default:
#9B9B9D (3.0:1) -- FAILS AA for normal text
- Corrected:
#858587 (3.8:1) -- passes AA for large text, acceptable for meta/captions
- For important labels, use
--text-secondary (#5C5C5E, 5.5:1) instead of --text-muted
Gotchas
-
Google Fonts Crimson Pro fails silently in China — always include CJK fallbacks first. The @import or <link> to Google Fonts is blocked by GFW. Without local fallbacks, headings render in the browser's default serif (Times New Roman) which looks broken. The font stack already has Noto Serif SC / Songti SC as fallbacks — verify they're listed BEFORE any web-only font, and add font-display: swap to prevent FOIT.
-
--bg-primary: #F3F0E9 (cream) makes --text-muted: #9B9B9D fail WCAG AA. The warm cream background reduces contrast for muted text to ~3.0:1 (AA requires 4.5:1 for normal text). Use #858587 or darker for any text smaller than 18px on cream backgrounds. This is already documented in the Muted Text Contrast section but gets forgotten when copy-pasting card styles.
-
Card hover translateY(-2px) causes layout shift in grid containers. When cards lift on hover, adjacent cards in a CSS Grid row don't move — but the row height can change if the card has margin-bottom: auto or is the tallest in the row. Fix: add will-change: transform and explicit min-height to card containers to prevent reflow.
-
var(--radius): 10px on very small elements (badges, tags) looks disproportionate. A 10px radius on a 24px-tall badge makes it nearly circular. Always use var(--radius-sm): 6px for elements smaller than 40px height. The badge example in this doc correctly uses border-radius: 20px (pill shape), but custom small components often inherit the wrong radius.
-
Section ::before gradient divider conflicts with padding-top on the section. The divider uses margin: 0 auto 60px which combines with the section's own padding. The visual gap between sections becomes 60px (margin) + section padding, often 120px+ total. Either use the gradient divider OR section padding, not both. When using dividers, set padding-top: 0 on the section.
-
Hero/banner text uses opacity and becomes unreadable on dark backgrounds. Never use opacity for text contrast control — it affects the entire element tree. Use explicit color: rgba(255,255,255,0.85) minimum for subtitle text and rgba(255,255,255,0.85) for meta text on any dark hero/banner. This applies to ALL four HTML style systems.
-
Code/diagram blocks need generous internal padding (>=20px). Content touching container borders looks unprofessional. Minimum: padding: 20px 24px for pre blocks, padding: 36px 40px 28px for diagram containers with floating label badges. This is a cross-style-system rule.
-
Container max-width: 960px is too narrow for CJK documents with tables. Use max-width: 1100px as the default for all four style systems. Apply consistently to .container, .section, .toc, and all max-width-constrained elements. Mismatched widths between elements cause visual misalignment.
-
.cover is a <section> — a generic section{margin-bottom} rule leaks onto the hero and creates a large dead gap before the first body section. Measured on a real deliverable (2026-05-30, viewport 1253×1233): cover padding-bottom:64px + inherited section{margin-bottom:72px} + main{padding-top:56px} stacked into 192px of pure empty cream between the hero meta line and the first section heading. On a tall window this reads as the page being "broken" with a giant hole. Three-part fix: (a) scope the rule to main.frame > section{}, never bare section{}, so the cover is excluded; (b) set .cover{margin-bottom:0} explicitly as a belt-and-suspenders guard; (c) keep the cover→body seam tight (cover padding-bottom ≤ 44px, main padding-top ≤ 32px). Combined with the hero-anchor rule above, the dead gap dropped to 72px and the first section pulled into the same viewport as the hero. Always re-measure the seam with getBoundingClientRect (cover bottom → first section top) after building a cover — do not eyeball it.
Anti-Patterns (Never Do)
- No bare
section{margin-bottom} rule — it leaks onto .cover (Gotcha 9). Scope to main.frame > section{}
- No cover that ends on bare padding — anchor the hero bottom with content (stat strip / TOC / first visual)
- No
auto-fit/auto-fill for named column grids (see Grid Rules above)
- No fixed-width columns for monospace field names (use stacked layout, see above)
- No font-size below 12px for any visible text
- No
--text-muted for important labels (use --text-secondary)
- No glassmorphism blur on cards (use paper shadows instead)
- No neon/saturated accent colors (terracotta, not electric orange)
- No pure black (#000000) -- use warm dark (#2C2C2E)
- No pure white background -- use warm cream (#F3F0E9)
- No generic fonts (Inter, Roboto, Arial) -- use Crimson Pro + Source Sans 3
- No emoji in content (per project rules)
- No heavy animations -- only subtle hover transitions (0.25s ease)
- No dark theme -- this is a warm light theme by design
Print Styles
@media print {
nav { display: none; }
body { background: #fff; }
section { break-inside: avoid; }
.card { box-shadow: none; border: 1px solid #ddd; }
}
Reference Implementation
See /Users/mauricewen/Projects/17-tax-claw/public/project-kickoff-zh.html
as the canonical reference for this design system (1165 lines, 14 sections,
full warm academic style).