Files
guizang-social-card-skill/references/screenshot-treatment.md
T
郭浩andClaude Opus 4.7 82d221bb90 v0.13 baseline · git 初始化 + 仓库瘦身
把所有本地 demo / 测试 / 上传图 / 调试脚本搬入 local-tests/,写
.gitignore 忽略整个测试目录与 node_modules/。本次起 skill 仓库
只跟踪:SKILL.md / HANDOFF.md / PRODUCT.md / assets/(3 模板)/
references/(15 规则文档)/ agents/openai.yaml / validate-social-deck.mjs
/ package.json + lock。

历次版本(v0.1-v0.12)的全部实质改动已包含在当前文件状态中——
HANDOFF.md 的版本历史段保留作为时间轴文字记录,但代码层面以
此 commit 为唯一基线,后续逐次 commit 对应 HANDOFF.md 新增段落。

HANDOFF/PRODUCT/category-cookbook/components/style-system 中的
demo 路径引用已加 local-tests/ 前缀。SKILL.md Step 5 line 190 的
'social-card-<slug>/' 是下游用户工作区的命名约定,未改动。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-27 22:00:55 +08:00

149 lines
6.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Screenshot Treatment
When the user supplies an app / web / code / dashboard screenshot, **do not** drop it raw into a `.frame-img`. The aspect ratio mismatch crops UI and the harsh edge looks SaaS-y. Use `.frame-shot` instead — a sibling class added to both seed templates.
## When to reach for it
- App / Web UI capture — anything with a status bar, tab bar, toolbar, or window chrome.
- Code / terminal screenshots.
- Dashboard / chart screenshots that need to keep every label readable.
- IDE captures where text density matters more than composition.
For **photographic** content (people, scenery, products) — keep using `.frame-img`. The treatments below assume a pixel-perfect UI source where contain-fit is non-negotiable.
## Anatomy
```
.frame-shot.r-{ratio}.corners-{sq|sm|md}.shadow-{none|soft|ed}.bg-{paper|grid|dot|grey-1|ink}.inset-{none|sub|bal}
└─ <img src="…"> (object-fit: contain by default)
```
Optional wrapping:
```
.device-browser
└─ .frame-shot.r-16x10.bg-paper
└─ <img>
.device-phone
└─ .frame-shot.r-3x4.bg-paper
└─ <img>
```
## Parameters
Pick six values before writing the markup. Treat this like the M16 cover decision tree — pick once, don't fiddle mid-build.
### 1. `r-*` ratio (required, matches slot)
| Class | Use |
| ---------- | --------------------------------------------------------- |
| `r-16x10` | Default for app / web shots, looks like a real window |
| `r-16x9` | Landscape video / dashboard / wide chart |
| `r-4x3` | Classic desktop window, legacy app |
| `r-3x2` | DSLR-style — only if the source is photographic UI mockup |
| `r-1x1` | App icon / square widget |
| `r-3x4` | Mobile portrait shot (pair with `.device-phone`) |
| `r-21x9` | Multi-monitor / ultra-wide / WeChat hero |
### 2. `corners-*` (style-locked default)
- **Swiss** default: `corners-sq`. Use `corners-sm` only if the slot has surrounding shadow or chrome.
- **Editorial** default: `corners-sm` (6 px). Bump to `corners-md` (14 px) for "cutout" feel on paper.
Never go above 14 px — anything bigger reads as iOS marketing.
### 3. `shadow-*` (style-locked default)
- Swiss → `shadow-none` 90% of the time. `shadow-soft` only on screenshots that float on `bg-grid` / `bg-dot`. `shadow-ed` adds a `1px` outline as part of the shadow — reserve for hero shots.
- Editorial → `shadow-soft` on `bg-paper-2` is the warm default. `shadow-ed` for hero shots.
### 4. `bg-*` (the screenshot "stage")
| Token | Swiss role | Editorial role |
| ------------ | ------------------- | ---------------------- |
| `bg-paper` | Default plain stage | Same |
| `bg-paper-2` | n/a | Default warm stage |
| `bg-grey-1` | Default plain stage | n/a |
| `bg-grid` | Engineering / data | Field-notes engineering |
| `bg-dot` | Subtle structure | Subtle structure |
| `bg-ink` | Dark-mode UI shot | Dark-mode UI shot |
Backgrounds are **never** accent-coloured. If the screenshot needs an accent emphasis, add a `.t-cat` chip or `.kicker` next to it — don't tint the stage.
### 5. `inset-*` (padding between shot and stage)
- `inset-none` — image fills the frame. Use when the screenshot itself already has window chrome.
- `inset-sub` (Swiss 20 px / Editorial 24 px) — default. Lets the stage breathe.
- `inset-bal` (Swiss 48 px / Editorial 56 px) — when the shot is busy and needs to feel calm.
### 6. `fit-cover` (override)
Default is `object-fit: contain` — this is the whole point of `.frame-shot`. **Only** add `.fit-cover` when:
- The slot is a hero where exact pixels of the source don't matter (e.g. a code shot used as a background pattern).
- The user explicitly says they want the shot cropped.
## Device chrome
Two wrapper classes ship with the seeds. They wrap a `.frame-shot`:
### `.device-browser`
Adds a 32–36 px chrome bar with traffic-light dots. Use for web / desktop app captures.
```html
<div class="device-browser">
<div class="frame-shot r-16x10 bg-paper inset-none">
<img src="assets/website.png" alt="Linear inbox">
</div>
</div>
```
Pair with `shadow-soft` on the screenshot itself for a desk-photo feel.
### `.device-phone`
Wraps a 3:4 or 16:10 shot in an ink-coloured bezel with 18-24 px rounded inner corners. Use for mobile captures.
```html
<div class="device-phone">
<div class="frame-shot r-3x4 bg-paper inset-none">
<img src="assets/app.png" alt="WeChat detail">
</div>
</div>
```
Don't stack `corners-md` on top of `.device-phone` — the bezel already rounds the inner shot.
## Safe-area cropping
When the user delivers a full-screen capture (1290×2796 iOS / 1080×2400 Android / 1920×1080 desktop), do **not** show the status bar, dock, or browser tab strip unless that chrome is the subject. Crop before importing:
1. Trim the iOS / Android status bar (top 47-59 px on retina).
2. Trim the home indicator / nav gesture bar (bottom 34 px on iOS).
3. For desktop: trim everything above the page content unless wrapped in `.device-browser`.
If you can't crop ahead of time, use `object-position: center 6%` to bias the visible region downward — but this is a workaround, not the preferred path.
## Style cheat-sheet
Two recipes that cover 80% of cases.
**Swiss product demo** — pure stage, no shadow:
```
.frame-shot.r-16x10.corners-sq.shadow-none.bg-grey-1.inset-bal
```
**Editorial deep-dive** — desk-photo warmth:
```
.frame-shot.r-16x10.corners-sm.shadow-soft.bg-paper-2.inset-sub
```
For comparison shots (before / after), use **the same parameters** on both — different treatment between cells reads as inconsistency, not contrast.
## Validator
`validate-social-deck.mjs` doesn't have a screenshot-specific rule (yet). The existing R1 / R2 / R5 still apply: a `.frame-shot` that overflows or pushes the footer is still a fail.
If a deck mixes `.frame-img` and `.frame-shot` on the same poster, that's usually a smell — pick one approach per poster.