paper-poster-html skill (ARIS)
- Install
- SKILL.md (verbatim)
- Why this skill exists (the failure it prevents)
- Mental model
- Constants
- Workflow
- Phase 0 — Resume, dependencies, venue spec
- Phase 0.5 — Design discovery (one AskUserQuestion batch)
- Phase 1 — Paper ingest, content plan, claim audit
- Phase 2 — Real paper figures (provenance-gated)
- Phase 3 — Scaffold + tokens
- Phase 4 — Layout hard loop
- Phase 5 — Claude visual review (gated aesthetics)
- Phase 6 — Codex final review (fresh thread, cross-model)
- Phase 7 — Final verification + report
- State persistence
- Key rules
- Review tracing
- Output contract
- When NOT to use
- Other files in this skill
- DESIGNFINAL.md (verbatim)
- 0. 定位
- 1. 目录布局
- 2. 设计 token 纪律
- 3. stylecheck.py 源门规则(codex 定稿,逐条实现)
- 4. assetcheck.py 真图门
- 5. 公式门(半硬)
- 6. MathJax 本地化
- 7. rungates.py + GATEREPORT.json
- 8. Workflow phases(SKILL.md 主结构)
- 9. Claude 视觉 rubric(Phase 5)
- 10. Fix 词汇表(反补丁循环核心)
- 11. COMPONENTS.md 契约
- 12. 已知失败模式防御(codex round 1 §7)
- 12.5 Round-3 ACK nits(已采纳)
- 13. 验收
- IMPLEMENTATIONCONVENTIONS.md (verbatim)
- A. CSS Token 契约(templates + tokens/.json + stylecheck 三方共享)
- B. HTML 属性契约
- C. CLI 契约(scripts/)
- stylecheck.py
- assetcheck.py
- rungates.py
- extractpdffigures.py
- preprocessfigures.py
- D. FIGUREMANIFEST.json schema
- E. 模板改造配方(posterly → ARIS fork)
- F. tokens/.json schema
- G. 测试基线
- templates/README.md (verbatim)
- Picking a template
- Scaffolds, not finished posters
- Applying a token pack (tokens/.json → :root)
- Retargeting the canvas
- Zero inline-style + utility-class policy
- Adding a new template
What it does. DEFAULT poster pipeline — build an academic conference poster (ICML/NeurIPS/ICLR/CVPR/...) as a single HTML/CSS file with measurement-driven hard gates, real paper figures, a two-hue design-token system, and print-ready PDF via headless Chromium. Use when the user says "做海报", "poster", "conference poster", "paper poster", or asks to design/redo a research poster. Supersedes the retired LaTeX /paper-poster. Part of ARIS: Auto-claude-code-research-in-sleep (wanshuiyin/Auto-claude-code-research-in-sleep).
| Upstream | wanshuiyin/Auto-claude-code-research-in-sleep |
| Skill file | skills/paper-poster-html/SKILL.md |
| License | MIT |
| Author | wanshuiyin |
| Fetched | 2026-09-10 |
Install
- Clone the repo and run
bash tools/install_aris.sh, or copyskills/paper-poster-html/into~/.claude/skills/paper-poster-html/;npx skills add wanshuiyin/Auto-claude-code-research-in-sleep --skill paper-poster-htmlalso works. - Raw file:
curl -sL https://raw.githubusercontent.com/wanshuiyin/Auto-claude-code-research-in-sleep/HEAD/skills/paper-poster-html/SKILL.md
SKILL.md (verbatim)
name: paper-poster-html
description: "DEFAULT poster pipeline — build an academic conference poster (ICML/NeurIPS/ICLR/CVPR/...) as a single HTML/CSS file with measurement-driven hard gates, real paper figures, a two-hue design-token system, and print-ready PDF via headless Chromium. Use when the user says \"做海报\", \"poster\", \"conference poster\", \"paper poster\", or asks to design/redo a research poster. Supersedes the retired LaTeX /paper-poster."
argument-hint: "[paper-dir-or-pdf] [— venue: ICLR, canvas: 185x90cm landscape, venue-colors: true]"
allowed-tools: Bash(*), Read, Write, Edit, Grep, Glob, WebFetch, WebSearch, AskUserQuestion, mcp__codex__codex
Paper Poster (HTML): measurement-gated poster generation
One HTML file styled for an exact print canvas (@page { size: W H }), rendered to PDF
via Playwright print emulation. Iterate by measuring, not eyeballing — the screen
preview lies; only print emulation at the correct viewport tells the truth. Core gate
machinery is adapted from posterly (MIT, ©
2026 Ruishuo Chen — see NOTICE.md and LICENSES/posterly-MIT.txt); ARIS adds style
discipline gates, figure-provenance gates, the cross-model review loop, and the
anti-patch-loop fix vocabulary.
Why this skill exists (the failure it prevents)
A predecessor pipeline produced a poster with 30+ colors, zero real paper figures, a screen-pixel canvas, and tiny formulas floating in oversized boxes, then spent 12+ review rounds making it worse — each round added a new badge color or bespoke SVG patch. The cure is structural, not exhortative:
- Hard gates run before any aesthetic opinion (alignment, style, assets must PASS first — a reviewer never sees an unmeasured poster).
- A closed fix vocabulary — visual-review fixes can only touch design tokens, whole catalogued components, content rebalance, assets, or canvas choice. New inline styles / new hex values / bespoke decorations are structurally forbidden.
- Two-hue discipline as a machine check, not a style suggestion.
- Real paper figures with provenance manifest, or the gate fails.
Mental model
paper (.tex / PDF) ──► content plan + claim→evidence audit (codex, fresh)
│
figures extracted ─────────┤ FIGURE_MANIFEST.json (provenance, sha256)
(real paper figures ONLY) ▼
template scaffold ──► fill ──► run_gates.py ◄─── HARD, loop here
preflight → style → asset → measure → polish
│ all hard gates PASS
▼
Claude visual review (≤3 issues × ≤3 rounds, fix-vocabulary only)
│ score ≥ 9
▼
codex final cross-model review (fresh thread, full HTML+PDF)
│ pass
▼
verify-final → poster.pdf + GATE_REPORT.json
Constants
- SKILL_SCRIPTS =
${CLAUDE_SKILL_DIR}/scripts— all helpers are single-owner and ship inside this skill (Arch C). If the directory is missing the install is broken: abort and tell the user to re-install the skill (Policy A — the gates ARE the skill; never improvise replacements). - REVIEWER_MODEL =
gpt-6-astra, reasoningxhigh, fresh thread per review call (mcp__codex__codex, nevercodex-replyacross review boundaries). - CANVAS — from the venue's official spec, looked up live in Phase 0. Never assume. (Known anchor: ICLR 2026 main = 185×90 cm landscape per its official printing service; ICML/NeurIPS commonly 60×36 in landscape; workshop posters often 61×91 cm portrait. Specs change yearly — verify.)
- PALETTE — default =
templates/tokens/generic.json(slate-blue#2D5F8Baccent- gold
#C9A24Ahighlight + neutrals) for all venues. Venue packs are opt-in via— venue-colors: true. Purple-dominant accents (hue 250–285) are banned unless the user passes— allow-purple: true.
- gold
- AUTO_PROCEED = false — wait for explicit confirmation at every 🚦 checkpoint.
- OUTPUT_DIR =
poster_html/in the working directory.
Workflow
Phase 0 — Resume, dependencies, venue spec
- Resume: if
poster_html/POSTER_STATE.jsonexists withstatus: in_progress(< 24 h), resume from the saved phase. - Dependencies (degradation chain, in order):
- Playwright + bundled Chromium → if missing,
python3 -m playwright install chromium→ if install fails but system Chrome exists, scripts fall back tochannel="chrome"→ if all fail: you may produce the content plan and scaffold only, label everything "not print verified", and must NOT emit a final PDF. pdfinfomissing → PyMuPDF reads PDF dimensions. At least one of pdftoppm / PyMuPDF must exist for PNG review renders.- MathJax: download
tex-svg.jsonce intoposter_html/assets/mathjax/and reference it locally in the HTML. CDN is acceptable only for drafts; the measure gate hard-fails on unrendered MathJax either way.
- Playwright + bundled Chromium → if missing,
- Venue spec lookup (live): consult the venue's official poster-instructions page
(search + fetch). Extract dimensions, orientation, font floor, logo policy,
anonymity rules, file format. Record
{spec, source_url, retrieved}intoPOSTER_STATE.json— specs change yearly; never reuse a cached spec silently.
🚦 Checkpoint: echo the venue spec table (canvas, orientation, source URL) and the chosen template. Wait.
Phase 0.5 — Design discovery (one AskUserQuestion batch)
Ask once, ≤4 questions: layout template (from templates/README.md), palette
(default generic pack / venue pack / custom within constraints), logos + venue mark
(paths or "none" — never fabricate; check the venue's logo policy), QR target (paper /
code / project page / none — generate offline with qrencode or python-qrcode;
never a remote QR-service URL). Persist answers in POSTER_STATE.json as
design_decisions — re-read before any later "improvement" so deliberate choices are
never reverted.
Phase 1 — Paper ingest, content plan, claim audit
- Read the paper source (
.texideal; PDF otherwise). Extract: title/authors/affils, the 3–5 headline numbers, core method (equations verbatim), main results (tables/figures and what they show), takeaways. Buildposter_html/POSTER_CONTENT_PLAN.md— what goes in which column, word budget per card. Target density (excluding table cells, captions, author line, footer): standard poster 550–850 words; dense theory+empirical poster 750–1050 words, allowed only when ≥2 compact components are used (eqn-anatomy,flow-strip,derived-col,claim-pills,keybox--4). Warn yourself below 500 words on a 4-column landscape (it will read as sparse next to professionally dense posters) unless the template is hero/visual-first; warn above 1100 unless the user asked for dense mode. Bullets ≤ 8 words when possible — density comes from structure, not long prose. Prefer compact structure over prose: if the paper contains an explicit objective, algorithm, theorem mechanism, or baseline comparison, extract at least two of: (1) empirical objective / loss stack; (2) term-by-term equation anatomy; (3) a method-flow strip grounded in paper variables; (4) a derived-Δ column for method-vs-baseline rows; (5) a 4-up implementation/theory keybox; (6) a claim/evidence pill table for numeric-heavy posters. Do not invent an algorithm. If the paper has only an objective, label the component "objective flow" or "loss anatomy", never "algorithm". - Cross-model content audit (fresh codex thread,
xhigh): give it the content plan path + paper source path(s) — paths only, no summaries — and ask for a claim→evidence table:| claim on poster | paper file:line | paper says (verbatim) | match? |with match ∈ {OK, NUMERIC-MISMATCH, OVERCLAIM, MISSING-PRECONDITION, NOT-IN-PAPER, SCOPE-NARROWED}. Save toposter_html/CLAIM_EVIDENCE.md. - Fix every non-OK row or record it as a user-acknowledged tradeoff.
🚦 Checkpoint: content plan + audit summary. Wait.
Phase 2 — Real paper figures (provenance-gated)
Source preference chain:
- Paper source
figures/(vector SVG/PDF → convert to SVG viainkscape/pdf2svgif available, else rasterize ≥ 2× rendered px). - PDF-only:
extract_pdf_figures.py contact-sheet+autoto list candidate regions → pick crops (🚦 human confirms crop choices) →cropat 300–450 DPI. - Last resort: user supplies explicit
page,x0,y0,x1,y1bboxes.
Then preprocess_figures.py --autocrop every asset. Every paper-derived image gets a
FIGURE_MANIFEST.json entry (source hash, page, bbox, dpi, sha256, natural_px) and is
embedded as <img data-source="paper" data-asset-id="...">.
Hard rule: ≥ 2 paper-derived visuals or the asset gate fails. Theory-only papers
may waive the total-area rule (--waive-total-area) at a human checkpoint — never
silently. Never draw bespoke decorative SVG "figures" as substitutes.
Figure-area bands (asset gate, fractions of body): total target 14–22 % (warn < 12 % / > 24 %, hard < 10 % / > 28 %); per ordinary figure target 4–8 % (warn
10 %, hard > 13 %);
figure--duocombined 8–12 %. Hero templates pass--hero(centerpiece may take 30–40 %). The failure mode is symmetric: too small reads as decoration, too big crowds out content. Sibling figures that share axes or tell a before→after story belong in onefigure--duocard, not two cards.
Phase 3 — Scaffold + tokens
cp templates/<chosen>.html poster_html/poster.html; retarget @page + .poster
dims to the venue canvas (two edits, same values); apply the chosen token pack onto the
:root DESIGN TOKENS block; fill content per the plan; embed manifest figures.
Run preflight + style_check — both must PASS before any layout iteration. (A fresh
scaffold is expected to fail measure — that gate judges a filled poster.)
Phase 4 — Layout hard loop
After every layout change:
python3 "$SKILL_SCRIPTS/run_gates.py" poster_html/poster.html \
--tokens <pack.json> --manifest poster_html/FIGURE_MANIFEST.json \
--report poster_html/GATE_REPORT.json
Canonical order: preflight → style → asset → measure → polish. Targets: column-bottom
spread < 5 px (aim < 3), footer gap ∈ [30, 50] px, intercard gap ∈ [12, 50] px,
canvas-fill ∈ [95, 101] %, poster bbox aligned to page within ±2 px. Fix guidance for
each failure mode lives in the gate output and templates/COMPONENTS.md. Do not
proceed while any hard gate fails. Do not let a reviewer see an unmeasured poster.
Balance under-filled columns with content from the paper (Gate C), never with
whitespace, space-between, or stretched cards.
Phase 5 — Claude visual review (gated aesthetics)
Render and read the result yourself:
python3 "$SKILL_SCRIPTS/render_preview.py" poster_html/poster.html
pdftoppm -r 100 poster_html/poster_preview.pdf poster_html/review_full -png -f 1 -l 1
# plus 2-4 region crops at higher res (header / one column / equations) via PIL
Calibrate first (../shared-references/taste-calibration.md): if
human-curated references/good/ + references/bad/ exist under this skill
dir (or the project supplies its own pair), score those 3+3 reference posters
on the axes below BEFORE the target, anchoring the scale. Never select, search
for, or generate anchors yourself; if no reference sets exist, proceed
uncalibrated and mark CALIBRATION: none — never fabricate anchor scores.
Axes (weights sum 1.0): Design 0.35 · Craft 0.30 · Functionality 0.20 ·
Originality 0.15. Mapping: SCORE = min(round(1 + 9 × COMPOSITE), lowest triggered cap) — caps apply AFTER the mapping, and the loop's Score ≥ 9
threshold below always reads this final capped SCORE, never the raw
composite.
Score strictly 1–10. Critical caps (hard floors — a calibrated composite never overrides them): < 2 real paper figures → ≤ 3; broken canvas / clipped content / unreadable math → ≤ 4; ≥ 4 visible hue families or gradient-heavy header → ≤ 4; large blank cards or columns → ≤ 5; fabricated visual claim → ≤ 3. Checks: posterly-showcase gestalt (would this hang next to a professionally designed poster without looking like a patched dashboard?), single-accent discipline, real figures readable and central, print hierarchy (title → headline stats → figures → detail), column fill, equation prominence (no tiny math in oversized boxes), serif-body/sans-display pairing, no gradient kitsch, component consistency, 60-second narrative. Output format:
SCORE: N/10 (= min(round(1 + 9 × COMPOSITE), lowest cap); drives the loop)
COMPOSITE: 0.xx (weighted; list the four per-axis scores)
CALIBRATION: anchored | none
GAP: <which reference poster the target falls short of / exceeds, on which axis, and why — one paragraph; omit only when CALIBRATION: none>
CAPS_TRIGGERED: ...
TOP_ISSUES: (max 3)
ALLOWED_FIX_TYPE per issue: token | component | rebalance | asset | template/canvas
PATCH_LOOP_RISK: low | medium | high
Loop: fix (fix vocabulary below) → re-run Phase 4 gates → re-score. ≤ 3 issues per round, ≤ 3 rounds. Score ≥ 9 → Phase 6. Still < 9 after 3 rounds → STOP patching; escalate to template / canvas / content re-choice (back to Phase 3) or a human decision. Never enter round 4 of cosmetic patching.
Fix vocabulary (closed set — the anti-patch-loop core)
Allowed: (a) edit a :root token value; (b) swap/remove/add a whole component
instance from templates/COMPONENTS.md; (c) content rebalance (move a card across
columns, trim/grow text from the paper, resize a figure within its AR band);
(d) template/canvas re-choice; (e) global edits to an existing component's CSS
that reference only tokens; (f) switching predefined variants (.eqn--large,
.card--compact, .figure--wide, .nowrap, …); (g) asset fixes (re-crop, swap
for a clearer figure from the same paper, re-preprocess).
Forbidden: new inline styles, new hex values anywhere, bespoke decorative SVG,
per-element font-size overrides. A new component may not be born inside the visual
loop — stop, get a human checkpoint, add it to COMPONENTS.md, re-run from Phase 3.
Phase 6 — Codex final review (fresh thread, cross-model)
All hard gates PASS + polish warnings zero-or-waived + visual ≥ 9 first. Then a fresh
codex thread (xhigh) reviews the final artifacts (not the content plan):
poster.html, the rendered PDF/PNG, the paper source, GATE_REPORT.json,
CLAIM_EVIDENCE.md — paths only, no executor framing. It checks: (1) fidelity &
overclaims re-checked on final text (polish introduces new claims), (2) residue
(\ref{, TODO, raw < in math, missing images, remote URLs), (3) visual rhetoric
(headline numbers prominent, banner readable from 2 m), (4) gate-log coherence. The
reviewer recommends; it does not edit. Any fix → back through Phase 4/5 gates — never
straight to re-review.
Phase 7 — Final verification + report
python3 "$SKILL_SCRIPTS/poster_check.py" verify-final poster_html/poster_preview.pdf \
--from-html poster_html/poster.html --max-size-mb 20
Page count 1, dimensions match @page, size ≤ 20 MB, no TODO/residue, no remote
assets. Report: PDF path, final spread px, footer-gap range, gate summary table,
unresolved waivers, codex verdict. Update POSTER_STATE.json → done.
State persistence
poster_html/POSTER_STATE.json: {phase, venue, canvas{w,h,orientation,source_url, retrieved}, template, token_pack, design_decisions{...}, figures_selected[], visual_rounds, codex_threads{audit, final}, status, timestamp} — written after every
phase; enables compact-recovery resume.
Key rules
- Measure, don't eyeball. No layout claim without
run_gates.pyoutput. - Gates before aesthetics. Claude/codex review only ever sees a poster whose hard gates PASS. This ordering is what kills the patch-loop death spiral.
- Never invent paper numbers or figures. Numbers come from the paper source; visuals carry manifest provenance. Fabrication = critical cap ≤ 3.
- Two hues, one system. Accent + gold + neutrals. The style gate enforces it; don't negotiate with the gate.
- Real figures are the poster. A poster without the paper's own figures is a dashboard, not a poster.
- Fix vocabulary is closed. If a fix isn't expressible as token / component / rebalance / asset / canvas, it's the wrong fix.
- Cross-model verdicts. Claude drives the loop and scores visuals; acceptance of content fidelity comes from the fresh codex thread (a loop can drive, never acquit).
- Preserve user decisions. Re-read
design_decisionsbefore "improving" anything. - Vendor boundary.
poster_check.py,render_preview.py,_posterly/are vendored from posterly — keep diffs minimal; ARIS-side logic goes in the new scripts, not in vendored files.
Review tracing
Save every codex reviewer call's trace per shared-references/review-tracing.md to
.aris/traces/paper-poster-html/<date>_run<NN>/ (audit + final threads, raw responses).
Output contract
poster_html/
├── poster.html # single-file source of truth
├── poster_preview.pdf # print-emulated, verify-final-checked
├── poster_preview.png # thumbnail
├── POSTER_STATE.json # resume state
├── GATE_REPORT.json # canonical gate ledger (schema v1)
├── POSTER_CONTENT_PLAN.md # what-goes-where + word budgets
├── CLAIM_EVIDENCE.md # codex claim→evidence audit
├── FIGURE_MANIFEST.json # figure provenance (sha256, page, bbox, dpi)
└── assets/{paper_figures,logos,qr,mathjax}/
When NOT to use
- Slides, not a poster →
/paper-talk//slides-polish. - The paper's headline isn't stable yet — fix the paper first; a poster amplifies whatever story it's given.
Other files in this skill
- DESIGN_FINAL.md
- IMPLEMENTATION_CONVENTIONS.md
- LICENSES/posterly-MIT.txt
- NOTICE.md
- scripts/_posterly/init.py
- scripts/_posterly/canvas.py
- scripts/_posterly/measure.py
- scripts/_posterly/polish.py
- scripts/_posterly/preflight.py
- scripts/_posterly/render.py
- scripts/_posterly/textutil.py
- scripts/_posterly/verify_final.py
- scripts/asset_check.py
- scripts/extract_pdf_figures.py
- scripts/poster_check.py
- scripts/preprocess_figures.py
- scripts/render_preview.py
- scripts/run_gates.py
- scripts/style_check.py
- templates/COMPONENTS.md
- templates/README.md
- templates/landscape_4col.html
- templates/landscape_hero.html
- templates/portrait_2col.html
- templates/tokens/acl.json
- templates/tokens/cvpr.json
- templates/tokens/generic.json
- templates/tokens/iclr.json
- templates/tokens/icml.json
- templates/tokens/neurips.json
DESIGN_FINAL.md (verbatim)
paper-poster-html — 收敛后的最终设计(codex 3 轮讨论产物)
日期:2026-06-05。讨论 thread:019e96dc-8350-70f0-a595-c1ad15919aa8(gpt-5.5 xhigh)。 状态:Round 2 全点收敛,本文档为实现规格。
0. 定位
- HTML+CSS 是新的默认 poster 路径;旧
/paper-poster(LaTeX tcbposter)已退役为 重定向 stub(2026-06-07 落库决定,较本规格的 legacy 共存方案更进一步; 旧实现仅存于 git history)。 - posterly(MIT, github.com/Chenruishuo/posterly)的 tools vendor 进 skill,不外部依赖
不重写;
LICENSES/posterly-MIT.txt+NOTICE.md注明来源与 ARIS 修改。
1. 目录布局
skills/paper-poster-html/
├── SKILL.md
├── LICENSES/posterly-MIT.txt
├── NOTICE.md
├── templates/
│ ├── README.md
│ ├── COMPONENTS.md # 组件契约目录(Q6)
│ ├── landscape_4col.html # fork 自 posterly,de-gradient + token 化
│ ├── landscape_hero.html
│ ├── portrait_2col.html
│ └── tokens/
│ ├── generic.json # 默认:slate-blue #2D5F8B + gold #C9A24A
│ ├── iclr.json … cvpr.json # opt-in venue 包
└── scripts/
├── poster_check.py # vendored(measure/preflight/polish/verify-final)
├── render_preview.py # vendored(Playwright print render)
├── _posterly/… # vendored 内部模块
├── style_check.py # 新:风格硬门(12 条规则)
├── asset_check.py # 新:真图溯源门
├── run_gates.py # 新:canonical 顺序跑全门,写 GATE_REPORT.json
├── extract_pdf_figures.py # 新:PDF→contact sheet→候选裁剪
└── preprocess_figures.py # 新:autocrop/转格式/分辨率检查
工作目录输出:
poster_html/
├── poster.html / poster.pdf / poster_preview.png
├── POSTER_STATE.json / GATE_REPORT.json
├── CLAIM_EVIDENCE.md / FIGURE_MANIFEST.json
└── assets/{paper_figures,logos,qr,mathjax}/
2. 设计 token 纪律
- 默认色卡 = generic(所有 venue):accent #2D5F8B 族 + gold #C9A24A 族 + 中性色。
venue 色卡 opt-in(
— venue-colors: true),约束:accent S≤0.55、L∈[0.25,0.45]; gold 族固定 H∈[38,48]、S≤0.65、L∈[0.42,0.65];主 accent 禁紫(H 250–285), 除非— allow-purple: true。venue identity 默认文字 badge。 - 字号必须走
--fs-*token scale(≤9 档,超出 warn)。 - serif 正文(Charter/Source Serif Pro/Georgia/Times New Roman)+ sans 标题(Inter/Aptos/Helvetica Neue/Arial);mono 仅代码(Menlo/Consolas)。
3. style_check.py 源门规则(codex 定稿,逐条实现)
| # | 严重度 | 规则 |
|---|---|---|
| 1 | HARD | 颜色字面量只许出现在 token 文件 / :root token block;例外:data-color-exempt="logo" 的 SVG 内部 |
| 2 | HARD | 禁 inline style 含颜色/字体/字号/布局关键值(豁免同上 + paper asset 内部) |
| 3 | HARD | 组件 CSS 颜色必须 var(--…) |
| 4 | HARD | 渲染后非中性色相聚类 ≤2(聚类半径 18°,须落在 accent/gold hue ±22°;非中性=alpha≥0.10 且 S≥0.18;豁免 <img>、logo、data-source="paper"、QR) |
| 5 | HARD | 禁 linear-gradient;radial-gradient 仅许 .poster 背景且所有 color stop alpha≤0.06 |
| 6 | HARD | 字体配对:正文 serif 栈、标题/表头 sans 栈 |
| 7 | HARD | 字体白名单(§2) |
| 8 | HARD | 字号必须用 --fs-* token 或组件 class,禁任意 px 漂移 |
| 9 | WARN | 字号 token >9 档 |
| 10 | HARD | 契约属性:论文图必须 data-source="paper" + data-asset-id;logo 豁免必须显式标注 |
| 11 | HARD | 禁自造装饰 SVG;inline SVG 仅许 logo / QR fallback / COMPONENTS.md 已收录的结构图 |
| 12 | WARN | 大面积深色(L<0.18 且 >8% poster 面积)→ 土嗨预警 |
4. asset_check.py 真图门
- ≥2 张
data-source="paper"图;每张面积 ≥ poster 1.5%;paper-image 总面积 ≥ body 12%。 - raster natural size ≥ rendered size 1.5×(目标 2×)。
- FIGURE_MANIFEST.json 必填:source PDF hash、page、bbox、crop dpi、asset sha256、是否来自论文。
- 真图获取链:论文源 figures/(SVG/PDF→SVG 转换优先)→ PDF-only 时 PyMuPDF 300–450 DPI
渲染 contact sheet → 自动候选 + 人工选 → 用户给
page,x0,y0,x1,y1bbox → 不足 2 张硬失败 (除非 human checkpoint 显式 waiver)。
5. 公式门(半硬)
EQN/BROKEN(MathJax 没渲染出来)= HARD(vendored measure 已有)。EQN/UNDERSIZED:.eqn inner box >80px 高且 math bbox 面积 <15% → HARD; <25% 或底部空白 >35% → WARN(final 前必须修复或记录 waiver)。
6. MathJax 本地化
Phase 0 下载 tex-svg.js 到 poster_html/assets/mathjax/(缓存复用),HTML 引本地路径;
下载失败 → 询问后 CDN 仅供草稿;final 的 measure 门对 MathJax 失败保持硬失败。
7. run_gates.py + GATE_REPORT.json
- canonical order:
preflight → style_check → asset_check → measure → polish。 - 默认 accumulate(一次给全修复面),
--fail-fast可选。 - style/asset 保持独立 CLI(vendor diff 干净),run_gates.py 做编排。
- GATE_REPORT.json schema:schema_version/skill/timestamp/poster_html/canvas{source,width_cm, height_cm,orientation,source_url}/overall/hard_failures/warnings/gates[{name,severity,status, command,summary,artifacts}]。
- polish 的 WARN 在 Phase 6 前必须清零或显式 waiver。
8. Workflow phases(SKILL.md 主结构)
| Phase | 内容 | 门 | Checkpoint |
|---|---|---|---|
| 0 | resume + deps(Playwright 链)+ venue spec 实时调研(WebSearch/WebFetch 官方页,URL+date 入 state) | — | 🚦确认 venue/canvas |
| 0.5 | 设计问卷(layout/palette/logo/QR/source 一轮 AskUserQuestion) | — | 🚦确认设计输入 |
| 1 | paper ingest + content plan + claim→evidence 表 | codex fresh xhigh 内容审计 | 🚦全 claim OK 或用户接受 tradeoff |
| 2 | 真图提取/预处理 | asset_check + FIGURE_MANIFEST | 🚦PDF-only 时人工选裁剪 |
| 3 | scaffold + token patch | preflight + style_check | — |
| 4 | 布局硬循环 | preflight+style+asset+measure(spread<5 aim<3;footer gap 30–50;intercard 12–50;fill 95–101%;position≤2px) | — |
| 5 | 渲染 + Claude 视觉审(rubric §9) | ≤3 issue×≤3 轮;fix 限定词汇表 §10 | — |
| 6 | codex 终审(fresh xhigh,审 final HTML+PDF 不是 plan;fidelity/overclaim/residue/叙事/gate logs;不直接改文件) | 任何 fix 回 Phase 4/5 | — |
| 7 | verify-final + 报告 | PDF 1 页/尺寸/≤20MB/无 TODO/无 remote asset | 完成 |
Playwright 降级链:bundled Chromium → python -m playwright install chromium →
channel="chrome" → 仍失败则只产 content plan/scaffold,标注 "not print verified",
不许产出最终 PDF。pdfinfo 缺 → PyMuPDF 读尺寸;pdftoppm/PyMuPDF 至少一个用于 PNG。
9. Claude 视觉 rubric(Phase 5)
1–10 分;critical cap:无真图或 <2 张 →≤3;画布坏/裁切/公式不可读 →≤4;
≥4 个色相家族或重渐变 header →≤4;大空白卡/列 →≤5;捏造视觉 claim →≤3。
检查项:posterly-showcase gestalt / 单 accent 纪律 / 真图居中可读 / 打印层级
(title→headline→figures→details)/ 列底对齐无半空卡 / 公式占框 / serif+sans 配对 /
无渐变 kitsch / 组件一体感 / 60 秒叙事。
输出格式:SCORE: N/10、CAPS_TRIGGERED、TOP_ISSUES(≤3)、
ALLOWED_FIX_TYPE: token|component|rebalance|asset|template/canvas、PATCH_LOOP_RISK。
校准:旧 poster ≤3 分;posterly showcase ≥9 分。
10. Fix 词汇表(反补丁循环核心)
视觉审循环内只允许:
(a) 改 :root token 值;
(b) 整组件实例的换/删/加(组件集来自 COMPONENTS.md);
(c) 内容再平衡(卡片跨列移动 / 从论文取材增删文字 / AR 门带宽内调图);
(d) 画布/模板重选(升级路径);
(e) 组件 stylesheet 的全局改动(只许引用 token,禁新 hex);
(f) 预定义 variant 切换(.figure--wide、.card--compact、.eqn--large、.nowrap 等,
必须已录入 COMPONENTS.md);
(g) asset fix(重裁剪/换同论文更清晰图/重跑 preprocess)。
禁止:新 inline style、新 hex、自造装饰 SVG、单元素字号 override。
新组件禁止在视觉循环内诞生——需要新组件 → 停,human checkpoint 录入 COMPONENTS.md,
从 Phase 3 重跑。
11. COMPONENTS.md 契约
每组件:purpose / allowed variants / required data attributes / token usage / which gates inspect it / allowed fix operations / anti-patterns。 首发组件:card、numbered-card、figure-card、hero-figure、eqn、result-table、 claim-evidence、keybox、takeaways、qr-block、venue-badge、footer。
12. 已知失败模式防御(codex round 1 §7)
remote 资源 networkidle 假死→本地化;logo 豁免走私颜色→显式 data-color-exempt; 低清裁剪→1.5×/2× 检查;截图导致 PDF 爆体积→verify-final 20MB; 视觉审诱发新组件/新色→fix 词汇表;venue 规格过期→每次实时查+记录 URL/date; 改写引入新 claim→Phase 6 审 final HTML 不是 content plan。
12.5 Round-3 ACK nits(已采纳)
- style_check 规则 8:
calc(var(--fs-*) * …)仅许预定义组件 variant 使用,否则成漏洞。 - asset_check 的"paper-image 总面积 ≥ body 12%"对纯理论论文可 waiver——但首个验收案例不许 waiver。
- Phase 0 的 venue 调研在 skill 文案里写成泛化的 "official venue page lookup"(跨工具栈映射,codex 镜像兼容)。
13. 验收
首个验收案例:为一篇公开的 ICLR 2026 OpenReview 论文(理论+实验混合型)重做 poster: 画布 185×90cm 横版(ICLR 官方打印服务规格),generic 色卡, 真图来自 OpenReview PDF,目标执行方视觉 rubric ≥9 + 跨模型终审通过。 (已达成:全 gate PASS、列底 spread <1px、两轮跨模型终审 PRINT-READY。)
IMPLEMENTATION_CONVENTIONS.md (verbatim)
paper-poster-html 实现约定(所有实现 agent 必读)
配合 DESIGN_FINAL.md(规格)使用。本文档定死跨文件契约——实现时逐字遵守, 有疑问按本文档,不要自由发挥。
A. CSS Token 契约(templates + tokens/*.json + style_check 三方共享)
:root 中的 token block 必须被注释 /* ===== DESIGN TOKENS ===== */ 和
/* ===== END DESIGN TOKENS ===== */ 包围(style_check 靠这对注释定位 token block)。
颜色 token(只有这些地方允许出现颜色字面量):
--accent: #2D5F8B; --accent-deep: #1F4566; --accent-light: #E8F1F8; --accent-soft: #D7E5F0;
--gold: #C9A24A; --gold-soft: #FFF7E0;
--text-primary: #1A1A1A; --text-secondary: #555555; --text-muted: #888888;
--bg-page: #F6F2F0; --bg-card: #FFFFFF; --bg-card-tint: #FAFAFB; --bg-emphasis: var(--accent-light);
--border-soft: #D8D8D8; --border-strong: var(--accent);
字号 scale(9 档,模板内所有 font-size 必须引用之一;calc(var(--fs-N) * k) 仅许
COMPONENTS.md 预定义 variant 使用):
--fs-1: calc(9 * var(--u)); /* 微标签 */ --fs-2: calc(10 * var(--u)); /* 小 caption */
--fs-3: calc(11 * var(--u)); /* caption/表格 */ --fs-4: calc(12 * var(--u)); /* 正文 */
--fs-5: calc(13 * var(--u)); /* 公式/强调 */ --fs-6: calc(15 * var(--u)); /* 副标题 */
--fs-7: calc(16 * var(--u)); /* 节标题 */ --fs-8: calc(22 * var(--u)); /* banner 数字 */
--fs-9: calc(32 * var(--u)); /* 主标题 */
单位:--u: 1.6px(screen)/ @media print { :root { --u: 1mm } }。其余尺寸一律
calc(N * var(--u)),hairline 可用裸 px(≤2px)。
B. HTML 属性契约
| 属性 | 用途 | 谁检查 |
|---|---|---|
| `data-measure-role="poster | header | banner |
data-source="paper" + data-asset-id="<manifest id>" |
标记来自论文的图 | asset_check + style_check 豁免 |
data-color-exempt="logo" |
logo/印章 SVG 的调色豁免 | style_check |
data-fig-layout="beside-text" |
图文并排的 AR 门 opt-out(vendored) | poster_check polish |
模板和最终 poster 中禁止任何 style= 属性(零容忍,style_check 规则 2 实现成这样,
简单可靠)。例外:data-color-exempt="logo" 元素的内部 SVG 标记、data-source="paper"
的 <img> 上仅允许 style="width: NN%"(AR 调宽)。
为此模板必须自带 utility classes(替代 posterly 模板里的 inline style):
.fs-1 … .fs-9 /* font-size: var(--fs-N) */
.mt-1 … .mt-6 /* margin-top: calc(N * var(--u)) */
.mb-1 … .mb-4 /* margin-bottom */
.w-45 .w-50 … .w-100 /* 图宽 45%…100%,步长 5 */
.text-secondary .text-muted .nowrap .text-center
C. CLI 契约(scripts/)
全部 Python 3.10+,只用 stdlib + 已确认可用的 PyMuPDF(fitz)/PIL/playwright(lazy import,
缺失时给可读错误+降级指引)。每个脚本 --help 完整。exit code:0=pass,1=hard fail,2=用法/环境错误。
style_check.py
python3 style_check.py POSTER.html [--tokens TOKENS.json] [--json OUT.json]
[--no-render] # 跳过渲染门(规则4、12 标 SKIPPED)
实现 DESIGN_FINAL §3 的 12 条规则 + §12.5 nit 1。源门(规则 1-3,5-11)纯静态解析
(html.parser + 正则提 CSS);渲染门(规则 4、12)用 playwright 取 computed style。
色相聚类:rgba→HSL;非中性= alpha≥0.10 且 S≥0.18;greedy 聚类半径 18°(色环距离);
聚类数 ≤2 且每类中心落在 tokens 的 accent/gold hue ±22°(hue_centers 来自 --tokens JSON,
缺省从 :root 解析 --accent/--gold 算)。
JSON 输出:{"gate":"style","status":"PASS|FAIL|WARN","rules":[{"id":1,"severity":"hard","status":"PASS","detail":"..."}]}
asset_check.py
python3 asset_check.py POSTER.html --manifest FIGURE_MANIFEST.json [--json OUT.json]
[--min-paper-figs 2] [--min-fig-area 0.015] [--min-total-area 0.12]
[--waive-total-area] # 纯理论论文 waiver(DESIGN_FINAL §12.5 nit 2)
[--no-render] # 面积检查降级为 natural-size 估算
检查:≥N 张 data-source="paper" 且 manifest 里 from_paper=true;每张渲染面积 ≥ poster 1.5%; 总面积 ≥ body 12%(可 waive);natural_px ≥ rendered px 1.5×(WARN 在 <2×); manifest 必填字段齐全(见 D);文件存在且 sha256 匹配。
run_gates.py
python3 run_gates.py POSTER.html [--report GATE_REPORT.json] [--fail-fast]
[--strict-polish] [--tokens TOKENS.json] [--manifest FIGURE_MANIFEST.json]
[--waive-total-area] [--no-render]
canonical order:preflight → style → asset → measure → polish。默认 accumulate。 子门以 subprocess 调同目录脚本(sys.executable;poster_check.py 子命令用其 CLI)。 GATE_REPORT.json 严格按 DESIGN_FINAL §7 schema(canvas 信息从 POSTER_STATE.json 读, 读不到则从 @page 解析,source 标 "page-rule")。汇总 overall=PASS/FAIL + hard_failures + warnings。
extract_pdf_figures.py
python3 extract_pdf_figures.py PAPER.pdf --out DIR [--dpi 350]
contact-sheet # 整页缩略 contact sheet + 自动候选框
crop --page P --bbox x0,y0,x1,y1 --name ID [--caption-hint "..."]
auto # 自动检测大图块候选(图/表),输出候选列表
bbox 单位 = PDF points(72dpi 坐标,fitz 默认)。crop 模式渲染该区域至 --dpi,写 PNG 到 DIR,并 upsert FIGURE_MANIFEST.json(同目录上级)。contact-sheet 写 DIR/contact_sheet_pNN.png。
preprocess_figures.py
python3 preprocess_figures.py IMG... [--autocrop] [--pad 6] [--min-px 1200 700] [--manifest M.json]
PIL autocrop 白边(ImageChops.difference vs 白底,留 --pad px),报告 natural size, 低于 --min-px 给 WARN;改动后同步更新 manifest 的 natural_px/sha256。
D. FIGURE_MANIFEST.json schema
{
"schema_version": 1,
"source_pdf": {"path": "…", "sha256": "…"},
"figures": [
{"asset_id": "fig_method", "file": "assets/paper_figures/fig_method.png",
"from_paper": true, "page": 3, "bbox": [72.0, 100.0, 520.0, 380.0], "dpi": 350,
"sha256": "…", "natural_px": [2178, 1362], "caption_hint": "Figure 2: …"}
]
}
E. 模板改造配方(posterly → ARIS fork)
对 3 个模板各做(以上游 posterly 仓库的 templates/*.html 为底):
- 文件头注释:保留原说明,追加 "Adapted from posterly (MIT, © 2026 Ruishuo Chen) — see LICENSES/ & NOTICE.md; ARIS modifications: flat de-gradient, --fs token scale, zero-inline-style utilities, data-source/data-color-exempt contracts."
- 去渐变:
.poster::before顶条 → 纯色var(--accent);.framework-banner、.takeaways-strip背景 → 纯var(--bg-emphasis);.callout.gold→ 纯var(--gold)。.poster的 radial tint(alpha≤0.06)保留。 - token block:按 §A 注释包围;加 --fs-1..9;所有 font-size 改 var(--fs-N)。
- 消灭 inline style:模板正文里所有
style="…"换成 §B utility classes(在 CSS 段新增)。 - 图组件:
.figure img的 TODO 注释里写明契约:<img src="assets/paper_figures/x.png" data-source="paper" data-asset-id="x" class="w-95">。 - logo 槽注释写明
data-color-exempt="logo"。 data-measure-role一律保留。- @page 默认值保留(60×36in / 24×36in),在头注释加"画布重定位:同步改 @page 与 .poster 的 width/height(各一处),ICLR 2026 main = 185cm 90cm landscape 示例"。
- eqn 组件加 variant
.eqn--large(font-size: calc(var(--fs-5) * 1.25),预定义 calc 豁免)。 - 自检:改完后模板里 grep 不到
linear-gradient、style="(除 §B 两个例外注释示例)、 裸#hex(token block 与 logo SVG 例外)。
F. tokens/*.json schema
{"name": "generic",
"accent": {"base": "#2D5F8B", "deep": "#1F4566", "light": "#E8F1F8", "soft": "#D7E5F0"},
"gold": {"base": "#C9A24A", "soft": "#FFF7E0"},
"neutrals": {"text_primary": "#1A1A1A", "text_secondary": "#555555", "text_muted": "#888888",
"bg_page": "#F6F2F0", "bg_card": "#FFFFFF", "bg_card_tint": "#FAFAFB",
"border_soft": "#D8D8D8"},
"hue_centers": {"accent": 210, "gold": 43}}
venue 包约束:accent S≤0.55、L∈[0.25,0.45]、禁 H 250–285;gold 全包固定 generic 值; light/soft 从 base 推(同 hue 低饱和高亮度)。bg_page 可随 accent 微调暖/冷但 ΔE 要小。
G. 测试基线
上游 posterly 仓库的 examples/hello_world/poster.html 是全门 PASS 的参照(vendored 四门)。 新脚本写完后:style_check 对 hello_world 允许 FAIL(它有 inline style——posterly 原版风格), 但对我们改造后的模板(填充前)源门必须 PASS;run_gates 对脚手架预期 measure FAIL(未填充), 这是正常的(模板=脚手架)。
templates/README.md (verbatim)
Template gallery — paper-poster-html
Three neutral HTML scaffolds, forked from the posterly templates (MIT, © 2026 Ruishuo Chen —
see ../NOTICE.md) and adapted for ARIS: flat de-gradient, --fs-* token scale, zero
inline-style utility classes, and the data-source / data-color-exempt contracts. Class
names are unchanged, so COMPONENTS.md (the component contract catalog) applies to all three.
Each template is self-contained and neutral: no lab branding, no paper content — only
TODO placeholders. The authoring loop is: copy one to your working dir as poster.html →
apply a token pack → fill TODOs with paper content + real figures → run the gates
(run_gates.py) and balance until they pass.
Every layout-critical element carries data-measure-role so the measurement gate can locate
columns / hero / footer regions across templates. Do not remove these attributes — the
measure gate depends on them.
Picking a template
| Template | Canvas | Layout | Use when |
|---|---|---|---|
| landscape_4col.html | 60 × 36 in landscape | header → optional banner → 4 columns → optional takeaways → footer | The default. Standard ML conference poster (ICML / NeurIPS / generic landscape) with ~3–5 content cards per column; mix of figures, equations, and tables. |
| landscape_hero.html | 60 × 36 in landscape | header → hero panel (~60%) + supporting column (~40%) → takeaways → footer | ONE figure / table / system diagram is the main message. One big illustration left, 3–4 short cards right. No framework banner — the hero is the banner. |
| portrait_2col.html | 24 × 36 in portrait | header → 2 columns → footer (no banner, no takeaways strip) | Portrait venues / sub-A0 sizes. Vertical space is precious, so banner + takeaways are dropped; the final card in the right column carries the conclusion/takeaways. |
(File names follow DESIGN_FINAL §1: the ARIS forks drop the posterly _neutral suffix.)
Scaffolds, not finished posters
A template is a scaffold, not a poster. Figures are commented out and copy is TODO
stubs, so each column only fills the top of the canvas. That has gate consequences you should
expect — do not "fix" them on a fresh scaffold:
preflightpasses out of the box. It checks structure (validdata-measure-rolevalues, no LaTeX residue, no bare<inside$…$math, the rootdata-measure-role="poster"), which the scaffold already satisfies.style_checksource rules (1–3, 5–11) pass on the forked scaffold. The ARIS fork has no inline styles, nolinear-gradient, no stray hex outside the token block — so the static source gate is green on the empty template. (The upstream posterly originals keep inline styles and would FAILstyle_check— that is expected; the fork exists precisely to fix that.)measureandpolishare gates for your finished poster. They check that columns bottom-align to within 5 px, that the gap to the footer sits in a tight band (30–50), that intercard gaps stay in [12, 50], and that the canvas fills 95–101% — properties only a filled poster can have. An unfilled scaffold is expected to fail them (huge column-bottom spread, a large gap to the footer). That is the gate telling you the poster is not finished, not a bug in the template.asset_checkfails until you embed ≥2 real paper figures. A scaffold has none.
So the loop is: copy → apply token pack → fill content + drop in real figures → run
run_gates.py and balance until measure/polish/asset go green. See DESIGN_FINAL §8 for
the full phase structure and the worked ICLR 2026 acceptance case (§13).
Applying a token pack (tokens/*.json → :root)
The palette lives in two synchronized places: the tokens/*.json packs (machine-readable, what
style_check/run_gates read for the accent/gold hue_centers) and the :root DESIGN TOKENS
block in each template's <style> (what the browser renders). generic.json is the default
for every venue. Venue packs are opt-in (— venue-colors: true).
To apply a pack, manually copy its values into the template's :root token block (the
block fenced by /* ===== DESIGN TOKENS ===== */ … /* ===== END DESIGN TOKENS ===== */ —
style_check locates the token block by exactly this comment pair, so keep it intact). The
JSON-to-CSS field mapping:
| JSON path | CSS token |
|---|---|
accent.base |
--accent |
accent.deep |
--accent-deep |
accent.light |
--accent-light |
accent.soft |
--accent-soft |
gold.base |
--gold |
gold.soft |
--gold-soft |
neutrals.text_primary / text_secondary / text_muted |
--text-primary / --text-secondary / --text-muted |
neutrals.bg_page / bg_card / bg_card_tint |
--bg-page / --bg-card / --bg-card-tint |
neutrals.border_soft |
--border-soft |
--bg-emphasis: var(--accent-light) and --border-strong: var(--accent) are derived tokens —
leave them as var(--…) references; they follow the accent automatically.
When you pass a pack to the gates (run_gates.py --tokens tokens/<venue>.json,
style_check.py --tokens …), the hue_centers in the JSON are the source of truth for the
hue-cluster check (style rule 4): the two allowed non-neutral hue families are
hue_centers.accent ± 22° and hue_centers.gold ± 22°. If you copied the JSON values into
:root correctly, the rendered hues will land inside those windows. (If you omit --tokens,
style_check derives the centers from the :root --accent / --gold instead.)
Available packs (all share the generic gold family #C9A24A / #FFF7E0; all venue accents
satisfy S ≤ 0.55, L ∈ [0.25, 0.45], hue ∉ [250, 285]):
| Pack | Accent identity | accent hue center |
|---|---|---|
generic.json |
slate-blue #2D5F8B (the default for every venue) |
210 |
iclr.json |
deep green #2E6048 |
151 |
icml.json |
deep maroon #8B3A4A |
348 |
neurips.json |
steel/slate blue #3A5A7A |
210 |
cvpr.json |
deep azure/indigo #27407A |
222 |
acl.json |
deep teal #256E72 |
183 |
Venue packs are opt-in identity, not a license to deviate from the discipline: a single
accent family + the shared gold, deep and desaturated, never purple. The default text
venue-badge (COMPONENTS.md) is the primary venue cue; the color pack is secondary.
Retargeting the canvas
A template ships with a default @page size and a matching .poster size. To change the
canvas you must edit both in the template (each in exactly one place), keeping them
identical — measure's canvas-fill / position-align gate compares the rendered .poster
bounding box against the @page viewport, so a mismatch fails the gate.
@pagein the<style>block — e.g.@page { size: 185cm 90cm; margin: 0; }..posterprint dimensions in@media print { .poster { … width: 185cm; height: 90cm; } }. (The screen.posterusescalc(N * var(--u))with--u: 1.6px; print uses--u: 1mm, so the screen preview scales automatically — you only hardcode the printwidth/height.)
The canvas parser accepts in / mm / cm / pt units. ICLR 2026 main conference example
(the §13 acceptance case): the official print service spec is 185 × 90 cm landscape, so
start from landscape_4col.html and set both @page and the print .poster to
185cm 90cm / width: 185cm; height: 90cm;.
Safe-area / margin design belongs as internal padding on a full-bleed .poster, never as a
smaller poster — a smaller poster fails the position-align gate (the .poster bbox must align
to (0,0)–(viewport_w, viewport_h)).
Zero inline-style + utility-class policy
The templates and any finished poster carry no style= attribute (zero tolerance —
style_check rule 2; IMPLEMENTATION_CONVENTIONS §B). To make that possible the templates ship
their own utility classes in the <style> block, replacing every inline style the posterly
originals used:
.fs-1 … .fs-9 font-size: var(--fs-N)
.mt-1 … .mt-6 margin-top: calc(N * var(--u))
.mb-1 … .mb-4 margin-bottom: calc(N * var(--u))
.w-45 .w-50 … .w-100 figure <img> width 45%…100% (5% steps)
.text-secondary .text-muted .nowrap .text-center
The only sanctioned style= survivors:
- the internal markup of a
data-color-exempt="logo"element (a logo / seal SVG), and style="width: NN%"on adata-source="paper"<img>for aspect-ratio width tuning when the value is off the 5% grid (prefer the.w-NNclass when it lands on a step).
Likewise: no linear-gradient anywhere; the only gradient allowed is the .poster
background radial-gradient tint with all color stops at alpha ≤ 0.06 (style rule 5). All
font-sizes go through the --fs-* scale; calc(var(--fs-N) * k) is allowed only for the
predefined component variants catalogued in COMPONENTS.md (e.g. .eqn--large). All colors
are tokens — no hex literal outside the :root token block (and the exempted logo SVG).
Adding a new template
A new template MUST:
- Set
@page { size: <W> <H> }(in/mm/cm/pt) inside a<style>block — the canvas parser fails if absent — and a matching print.postersize. - Carry
data-measure-role="poster"on the root poster element. - Use the roles consistently:
header,banner(optional),body,column,card,hero(mutually exclusive withbanner),footer-strip(optional),footer. - Use the
--uunit system (1.6pxscreen,1mmprint) for ALL sizing viacalc(N * var(--u))— never bare px except hairlines (≤ 2px). - Carry the
:rootDESIGN TOKENS block fenced by the/* ===== DESIGN TOKENS ===== */…/* ===== END DESIGN TOKENS ===== */comment pair, the full--fs-1 … --fs-9scale, and the §B utility classes. - Use only components from
COMPONENTS.md; no inlinestyle=, nolinear-gradient, no hex outside the token block. - Keep all paper-specific content as
TODOplaceholders — neutral templates only.
Then add a row to the gallery table above, a catalog note if it introduces any new component
(which requires the COMPONENTS.md new-component checkpoint), and link it in SKILL.md Phase 3.
Back to ARIS: Auto-claude-code-research-in-sleep or Agent skills.