s3://rustfs-brand/agents/Resources · AI agents

DESIGN.md 与 SkillFor AI agents

供 AI agent 使用的设计规范与技能。
DESIGN.md alpha · lint 0 / 0Skill rustfs-brand适用 Claude Code · Claude.ai · Agent SDK

DESIGN.mdDESIGN.md

Google design.md 格式:YAML 令牌加规则正文。

01放入项目

放在仓库根目录。

02在说明中引用

在 AGENTS.md 中引用。

03校验与导出

用 CLI 校验或导出。

DESIGN.md下载当前版本
命令
npx @google/design.md lint DESIGN.md
npx @google/design.md export --format css-tailwind DESIGN.md
npx @google/design.md export --format dtcg DESIGN.md
AGENTS.md
## Design

All UI, marketing and visual work must follow DESIGN.md
(RustFS design system). Use the tokens in tokens/tailwind.css;
do not introduce colours, radii or fonts outside it.
DESIGN.md
---
version: alpha
name: RustFS
description: Design system for RustFS, the Rust-native, S3-compatible distributed object storage. Square, exact and structural; Signal Blue carries the brand, Oxide marks parity and the single focal point.
colors:
  primary: "#0062FF"
  primary-hover: "#014FDD"
  on-primary: "#FFFFFF"
  primary-on-dark: "#5C99FF"
  parity: "#FF5E14"
  on-parity: "#0B0E14"
  parity-text: "#B33A10"
  parity-text-on-dark: "#FE8F5D"
  ink: "#0B0E14"
  paper: "#F4F6F9"
  surface: "#FFFFFF"
  surface-alt: "#F4F6F9"
  surface-sunken: "#EAEDF2"
  on-surface: "#0B0E14"
  on-surface-subtle: "#424853"
  on-surface-muted: "#5A616D"
  outline: "#DCE0E6"
  outline-strong: "#C4C9D2"
  surface-dark: "#0B0E14"
  surface-dark-alt: "#13171E"
  on-surface-dark: "#F4F6F9"
  on-surface-dark-muted: "#9AA0AC"
  outline-dark: "#2B313A"
  success: "#037E3F"
  warning: "#A06604"
  error: "#C51B32"
  info: "#014FDD"
  status-online: "#02A855"
  status-degraded: "#F7AE0C"
  status-offline: "#E42E41"
  chart-1: "#0062FF"
  chart-2: "#FF5E14"
  chart-3: "#00AEAE"
  chart-4: "#7D5BE6"
  chart-5: "#F7AE0C"
  chart-6: "#61C3F9"
  chart-7: "#02A855"
  chart-8: "#9AA0AC"
typography:
  display-xl:
    fontFamily: Archivo
    fontSize: 96px
    fontWeight: 800
    lineHeight: 0.94
    letterSpacing: -0.025em
    fontVariation: "'wdth' 125"
  display-lg:
    fontFamily: Archivo
    fontSize: 72px
    fontWeight: 800
    lineHeight: 0.96
    letterSpacing: -0.02em
    fontVariation: "'wdth' 125"
  display-md:
    fontFamily: Archivo
    fontSize: 56px
    fontWeight: 800
    lineHeight: 1
    letterSpacing: -0.02em
    fontVariation: "'wdth' 125"
  headline-lg:
    fontFamily: Archivo
    fontSize: 40px
    fontWeight: 750
    lineHeight: 1.08
    letterSpacing: -0.01em
    fontVariation: "'wdth' 112"
  headline-md:
    fontFamily: Archivo
    fontSize: 30px
    fontWeight: 700
    lineHeight: 1.15
    letterSpacing: -0.01em
    fontVariation: "'wdth' 112"
  headline-sm:
    fontFamily: Geist
    fontSize: 22px
    fontWeight: 600
    lineHeight: 1.3
    letterSpacing: -0.005em
  title:
    fontFamily: Geist
    fontSize: 18px
    fontWeight: 600
    lineHeight: 1.4
  body-lg:
    fontFamily: Geist
    fontSize: 18px
    fontWeight: 400
    lineHeight: 1.7
  body-md:
    fontFamily: Geist
    fontSize: 16px
    fontWeight: 400
    lineHeight: 1.7
  body-sm:
    fontFamily: Geist
    fontSize: 14px
    fontWeight: 400
    lineHeight: 1.6
  caption:
    fontFamily: Geist
    fontSize: 12px
    fontWeight: 400
    lineHeight: 1.5
  button:
    fontFamily: Geist
    fontSize: 14px
    fontWeight: 500
    lineHeight: 1
  label-md:
    fontFamily: Geist Mono
    fontSize: 12px
    fontWeight: 500
    lineHeight: 1.3
    letterSpacing: 0.08em
  label-sm:
    fontFamily: Geist Mono
    fontSize: 11px
    fontWeight: 500
    lineHeight: 1.3
    letterSpacing: 0.08em
  code:
    fontFamily: Geist Mono
    fontSize: 14px
    fontWeight: 400
    lineHeight: 1.65
  numeral:
    fontFamily: Archivo
    fontSize: 48px
    fontWeight: 800
    lineHeight: 1
    letterSpacing: -0.02em
    fontFeature: "'tnum' 1"
    fontVariation: "'wdth' 125"
rounded:
  none: 0px
  full: 9999px
spacing:
  unit: 4px
  xs: 4px
  sm: 8px
  md: 16px
  lg: 24px
  xl: 32px
  2xl: 48px
  3xl: 64px
  4xl: 96px
  gutter: 16px
  container: 1240px
  columns: 12
components:
  button-primary:
    backgroundColor: "{colors.primary}"
    textColor: "{colors.on-primary}"
    typography: "{typography.button}"
    rounded: "{rounded.none}"
    height: 40px
    padding: 0 16px
  button-primary-hover:
    backgroundColor: "{colors.primary-hover}"
    textColor: "{colors.on-primary}"
  button-secondary:
    backgroundColor: "{colors.surface-sunken}"
    textColor: "{colors.on-surface}"
    typography: "{typography.button}"
    rounded: "{rounded.none}"
    height: 40px
    padding: 0 16px
  button-outline:
    backgroundColor: "{colors.surface}"
    textColor: "{colors.on-surface}"
    typography: "{typography.button}"
    rounded: "{rounded.none}"
    height: 40px
    padding: 0 16px
  button-on-dark:
    backgroundColor: "{colors.surface}"
    textColor: "{colors.ink}"
    typography: "{typography.button}"
    rounded: "{rounded.none}"
    height: 40px
  input:
    backgroundColor: "{colors.surface}"
    textColor: "{colors.on-surface}"
    typography: "{typography.body-sm}"
    rounded: "{rounded.none}"
    height: 40px
    padding: 0 12px
  card:
    backgroundColor: "{colors.surface}"
    textColor: "{colors.on-surface}"
    rounded: "{rounded.none}"
    padding: 24px
  card-dark:
    backgroundColor: "{colors.surface-dark-alt}"
    textColor: "{colors.on-surface-dark}"
    rounded: "{rounded.none}"
    padding: 24px
  label:
    textColor: "{colors.on-surface-muted}"
    typography: "{typography.label-md}"
  code-block:
    backgroundColor: "{colors.ink}"
    textColor: "{colors.on-surface-dark}"
    typography: "{typography.code}"
    rounded: "{rounded.none}"
    padding: 16px
  status-chip:
    backgroundColor: "{colors.surface}"
    textColor: "{colors.on-surface}"
    typography: "{typography.label-sm}"
    rounded: "{rounded.none}"
    height: 24px
    padding: 0 8px
  link:
    textColor: "{colors.primary-hover}"
    typography: "{typography.body-md}"
  link-on-dark:
    backgroundColor: "{colors.surface-dark}"
    textColor: "{colors.primary-on-dark}"
  parity-marker:
    backgroundColor: "{colors.parity}"
    textColor: "{colors.on-parity}"
    rounded: "{rounded.none}"
    size: 10px
  alert-error:
    backgroundColor: "{colors.surface}"
    textColor: "{colors.error}"
    typography: "{typography.body-sm}"
    rounded: "{rounded.none}"
  alert-success:
    backgroundColor: "{colors.surface}"
    textColor: "{colors.success}"
    typography: "{typography.body-sm}"
    rounded: "{rounded.none}"
  alert-warning:
    backgroundColor: "{colors.surface}"
    textColor: "{colors.warning}"
    typography: "{typography.body-sm}"
    rounded: "{rounded.none}"
  alert-info:
    backgroundColor: "{colors.surface}"
    textColor: "{colors.info}"
    typography: "{typography.body-sm}"
    rounded: "{rounded.none}"
  section-alt:
    backgroundColor: "{colors.surface-alt}"
    textColor: "{colors.on-surface-subtle}"
  artboard-paper:
    backgroundColor: "{colors.paper}"
    textColor: "{colors.ink}"
  artboard-signal:
    backgroundColor: "{colors.primary}"
    textColor: "{colors.on-primary}"
  artboard-ink:
    backgroundColor: "{colors.ink}"
    textColor: "{colors.on-surface-dark}"
  caption-on-dark:
    backgroundColor: "{colors.surface-dark}"
    textColor: "{colors.on-surface-dark-muted}"
    typography: "{typography.label-sm}"
  parity-label:
    backgroundColor: "{colors.surface}"
    textColor: "{colors.parity-text}"
    typography: "{typography.label-sm}"
  parity-label-on-dark:
    backgroundColor: "{colors.surface-dark}"
    textColor: "{colors.parity-text-on-dark}"
    typography: "{typography.label-sm}"
  divider:
    backgroundColor: "{colors.outline}"
    height: 1px
  divider-strong:
    backgroundColor: "{colors.outline-strong}"
    height: 1px
  divider-dark:
    backgroundColor: "{colors.outline-dark}"
    height: 1px
  status-marker-online:
    backgroundColor: "{colors.status-online}"
    rounded: "{rounded.none}"
    size: 10px
  status-marker-healing:
    backgroundColor: "{colors.primary}"
    rounded: "{rounded.none}"
    size: 10px
  status-marker-degraded:
    backgroundColor: "{colors.status-degraded}"
    rounded: "{rounded.none}"
    size: 10px
  status-marker-offline:
    backgroundColor: "{colors.status-offline}"
    rounded: "{rounded.none}"
    size: 10px
  chart-series-1:
    backgroundColor: "{colors.chart-1}"
  chart-series-2:
    backgroundColor: "{colors.chart-2}"
  chart-series-3:
    backgroundColor: "{colors.chart-3}"
  chart-series-4:
    backgroundColor: "{colors.chart-4}"
  chart-series-5:
    backgroundColor: "{colors.chart-5}"
  chart-series-6:
    backgroundColor: "{colors.chart-6}"
  chart-series-7:
    backgroundColor: "{colors.chart-7}"
  chart-series-8:
    backgroundColor: "{colors.chart-8}"
---

# RustFS Design System

The full, illustrated guidelines are published at the RustFS design site (`/en/` and `/zh/`). Tokens in this file mirror `tokens/tokens.json`; when they disagree, `tokens/tokens.json` wins. Tailwind v4 projects should import `tokens/tailwind.css`, whose semantic variable names match shadcn/ui (`--background`, `--primary`, `--muted-foreground`, `--ring`, …) plus RustFS roles (`--brand`, `--parity`, `--subtle`, `--faint`, `--surface`, `--stage`).

## Overview

RustFS is a distributed object storage system built in Rust: S3-compatible, Apache 2.0 licensed, self-hosted, with erasure coding, bitrot protection and healing. The brand line is "AI infrastructure, accounted for byte by byte." (Chinese: 「AI 时代的基建,从每一个字节算起。」).

The audience is platform, SRE and AI-infrastructure engineers who hand RustFS the data they cannot lose. The interface and every marketing surface must feel **exact, candid, engineered and open**: like a carefully set system diagram, never like hype. Personality limits: exact but not cold, candid but not alarmist, engineered but not jargon-heavy, open but not sloppy.

Four principles decide every layout:

1. **Show the structure.** Organise with grids, shards, stripes and mono labels. Brand graphics come from the real structure of erasure coding.
2. **Exact over loud.** Real numbers with units, sources and dates replace adjectives.
3. **Blue carries, Oxide checks.** Neutrals ~60%, Signal Blue ~30%, Oxide ≤10% and only one Oxide focal point per screen.
4. **Square, flat, predictable.** Square corners, 1px rules, no drop shadows or glows, motion in steps without bounce.

## Colors

- **Signal Blue `primary` (#0062FF)** is the logo colour and the only brand blue. It carries primary actions, links, selected states, data shards and RustFS in charts. Never substitute another blue. Small text and links on white use `primary-hover` (#014FDD, 6.6:1); text on dark surfaces uses `primary-on-dark` (#5C99FF).
- **Oxide `parity` (#FF5E14)** is the parity colour. It marks parity shards, preview features and the single thing to see first. It is never used for errors or warnings, never floods large areas, and never sits on a Signal Blue surface (parity turns Ink there). Oxide text uses `parity-text` (#B33A10) on light and `parity-text-on-dark` (#FE8F5D) on dark.
- **Neutrals** are a cool grey with a slight blue bias (hue 262). `ink` (#0B0E14) is the dark surface and primary text colour; `paper` (#F4F6F9) is the light alternate surface. Supporting text on light surfaces is never lighter than `on-surface-muted` (#5A616D, 6.2:1).
- **Status colours** describe drive and cluster health and always pair with a text label and a square marker: online (green), healing (blue), degraded (amber), offline (red).
- **Charts** use `chart-1` … `chart-8` in order. RustFS is always series 1 (Signal Blue); comparison series use neutrals; Oxide highlights one point.
- **Surface modes** for fixed artboards (covers, ads, slides): Ink (default stage), Paper (technical content), White, and Signal (announcements). On Signal, data shards are white and parity is Ink.
- Body text must reach 4.5:1 contrast; large text 3:1. The dark theme mirrors the light one through the semantic roles in `tokens/tailwind.css`.

## Typography

- **Archivo** (variable, SIL OFL) at **125% width** (`font-stretch: 125%` or `'wdth' 125`) for display, numerals and version numbers; **112% width** for headlines. Weights 700–800. It echoes the wide, heavy construction of the RUSTFS wordmark. Never use Archivo below 100% width.
- **Geist** for body and interface text (400/500/600).
- **Geist Mono** for labels, data, paths, code and eyebrows. Labels are uppercase with 0.08em tracking.
- **Chinese**: HarmonyOS Sans SC or Source Han Sans SC (web fallback PingFang SC, Microsoft YaHei). Chinese headings use zero tracking (never negative), line-height ≥ 1.15, Bold/Heavy weights, no synthetic bold or italics. Put a half-width space between Chinese and Latin letters or numbers. Chinese quotes use 「」.
- Numbers: tabular figures in data; ISO dates (2026-10-14); versions without a "v" prefix (1.0.1); binary sizes in KiB/MiB/GiB; erasure layouts written `EC 4+2`.
- A block uses four levels at most: mono eyebrow → Archivo headline → Geist body → data.
- Tailwind exposes each style as a `type-*` utility (`type-display-xl`, `type-headline-md`, `type-label-md`, `type-numeral`).

## Layout

- Web: 12-column grid, content max 1240px, side gutter ≥ 16px (4 columns < 640px, 8 columns 640–1023px, 12 columns ≥ 1024px). Spacing on a 4px base (Tailwind's default `--spacing`).
- Sections: a mono eyebrow, a headline on the left (5/12) and the lede on the right (7/12), specimens full width below. Generous vertical rhythm (72–128px between sections).
- Fixed artboards measure in **u = 1/100 of the short side**; the safe margin is **7u**. The wordmark sits top-left at 4.25u tall, a single mono category label top-right at 2.25u, the title in the left ~64%, and the brand graphic on the right ~36% or along the bottom edge.
- Left-align by default. Centre only symmetric formats (stickers, avatars, square posts with a single figure).

## Elevation & Depth

The design is flat. Separate layers with 1px borders (`outline` #DCE0E6 light, #2B313A dark) and tonal surfaces (`surface` → `surface-alt` → `surface-sunken`). The only shadow is for overlays (popovers, dialogs, menus): `0 24px 48px -16px rgba(11,14,20,0.28)`. No glows, gradients, glassmorphism or blurred backgrounds.

## Shapes

All corners are square (`rounded.none`): buttons, inputs, cards, images, charts, badges, app icon masters and stickers. `rounded.full` exists only where a platform forces a circular crop (social avatars). Status markers are squares, never dots or pills. The shard (a filled square) is the basic shape of the brand.

## Components

- **Buttons**: square, 40px tall (32 small, 48 large), Geist Medium 14px. Primary = Signal Blue with white text; secondary = sunken neutral; outline = 1px border; on dark surfaces, a white button with Ink text. Labels start with a verb that names the result ("Download RustFS", "Create bucket"). Hover lifts 1px and a light sheen sweeps across (420ms emphasized); press returns and scales to 98.5% (80ms).
- **Inputs**: square, 1px `outline-strong` border, 40px tall; focus shows a 2px Signal ring with 2px offset; errors show red text below with the cause and fix.
- **Cards**: 1px border, 24px padding, no shadow, no coloured side rail. Hover turns the border to the foreground colour and nudges the arrow icon 2px (240ms).
- **Status chips**: square marker + mono label; online green, healing blue (animated heal), degraded amber, offline red, preview Oxide.
- **Code blocks**: always Ink background in both themes, Geist Mono 13–14px, with a copy button. Syntax colours: foreground #EAEDF2, comment #757C88, punctuation #9AA0AC, keyword/tag/command #5C99FF, function/type/selector #96BFFF, property/attribute/key #C3DBFE, string #6BDFCA, number/unit/constant #FE8F5D (tokens `color.syntax.*`).
- **Tables**: mono uppercase header labels on `surface-alt`; numbers right-aligned with tabular figures.
- **Icons**: 24px grid, 1.5px stroke, square caps, miter joins, `currentColor`; fills only for a written/current shard.
- **Brand graphics** — the only two allowed:
  - *Stripe signature*: 4 Signal Blue squares + 2 Oxide squares (an EC 4+2 stripe), gap 32% of the square, used once per layout as a sign-off, divider or corner mark.
  - *Shard matrix*: columns = drives, rows = stripes; each stripe has k data shards and m parity shards, and parity shifts one drive to the right per stripe (diagonal Oxide bands). Variants: solid, tone (three data shades), outline, sparse, dissolve toward a corner, dead drive columns (dashed), missing shards. Generate it by the rule; never arrange squares by hand.
- **Logo**: the RUSTFS wordmark is the primary logo (Signal Blue on light, white on Ink/Signal, Ink for one colour). The Flow S (the wordmark's final S with two arrows) is the standalone symbol for avatars, favicons and app icons. Clear space ½ of the wordmark height; minimum 72px / 18mm wide. In text the name is always "RustFS".
- **Motion**: easings `standard` cubic-bezier(0.2,0,0,1), `emphasized` cubic-bezier(0.16,1,0.3,1), `exit` cubic-bezier(0.4,0,1,1); durations 80 / 150 / 240 / 420 / 720ms; stagger 40–60ms. Brand moves: **write** (shards appear stripe by stripe, stepped) and **heal** (a shard drops to a dashed outline, parity flashes, the shard is rebuilt). No springs, bounce or parallax. Respect `prefers-reduced-motion`.
- **Copy**: verifiable claims with conditions and sources; no superlatives ("fastest", "100% compatible", "military-grade"); preview features labelled Preview; errors say what happened, why and how to fix it.

## Do's and Don'ts

- Do use Signal Blue #0062FF exactly; don't introduce other blues, purple-to-blue gradients or neon glows.
- Do keep Oxide to parity and one focal point; don't use Oxide for errors or large floods.
- Do keep every corner square; don't use rounded cards, pill badges, circular status dots or rounded app-icon masters.
- Do draw the shard matrix by the erasure rule; don't scatter random squares, dots or abstract light effects.
- Do use real product screenshots, real hardware and event photos; don't use stock imagery or AI-generated illustrations.
- Do label sample data as sample data and cite sources and dates; don't publish single-run peaks, truncated axes, 3D or pie charts.
- Do set Archivo at 112–125% width; don't retype the wordmark in any font, stretch, outline, rotate or recolour it.
- Do put one message, one proof line and one call to action in an ad; don't stack multiple messages, emoji or hashtags in graphics.
- Do write bilingual copy that carries the same meaning; don't translate word by word or translate the product name.
- Do respect reduced-motion preferences; don't flash more than three times per second.

Skillrustfs-brand Skill

制作 RustFS 品牌物料时自动加载,按规范出图并自检。

安装到 Claude Code
# personal, all projects
unzip rustfs-brand.skill -d ~/.claude/skills/

# one project, shared with the team
unzip rustfs-brand.skill -d .claude/skills/
目录结构
rustfs-brand/
  SKILL.md                 workflow and key rules
  references/
    DESIGN.md              tokens and full rules
    formats.md             sizes and layout recipes per channel
    copy.md                voice, terminology, approved lines, facts
    graphics.md            logo, stripe, shard matrix, icons, charts
  assets/
    artboard.html          single-file starter for static graphics
    tailwind.css           Tailwind v4 tokens
    tokens.css             CSS variables
    logo/*.svg             wordmark, symbol, app icon
  scripts/
    render.mjs             HTML → PNG with headless Chrome
    matrix.mjs             shard-matrix SVG generator
示例请求Skill 的处理方式
「给 1.0.2 发布做一张公众号头图和分享图」按规格出两张 PNG
“Design a 1080×1080 post announcing S3 Tables preview”标注 Preview 并注明来源
「把控制台的按钮和卡片改成品牌规范」引入 tailwind.css,去圆角与投影
“A slide comparing RustFS throughput before and after the release”按比例绘制,标注示例数据
SKILL.md
---
name: rustfs-brand
description: Apply the official RustFS brand and design system (Signal Blue #0062FF, Oxide parity accent, Archivo Expanded / Geist / Geist Mono, square corners, shard-matrix graphics, bilingual zh/en copy rules) to anything RustFS-branded. Use this skill whenever the user asks for RustFS marketing or product visuals or copy — blog/OG covers, WeChat or social posts, ads and banners, slide decks, video thumbnails and title cards, posters, stickers, event materials, website sections, Console/UI components, diagrams, charts or release announcements — or asks to make something "on-brand", "in RustFS style", or to use RustFS colours, fonts, logo or tokens, even if they do not say "brand" or "design system".
---

# RustFS brand

RustFS is a Rust-native, S3-compatible distributed object store (Apache 2.0, self-hosted, erasure coding, bitrot protection, healing). Its identity turns the structure of erasure coding into a visual language: data shards in Signal Blue, a few parity shards in Oxide, everything square, exact and labelled. Brand line: "AI infrastructure, accounted for byte by byte." / 「AI 时代的基建,从每一个字节算起。」

The full rules live in `references/DESIGN.md` (machine-readable tokens + prose, the Google DESIGN.md format). Read it once per task before designing anything. The other references are loaded only when the task needs them.

## Workflow

1. **Pin down the deliverable.** Channel, exact pixel size, language(s), and the one message it carries. If the user gives no size, take it from `references/formats.md`.
2. **Get the words right first.** Check `references/copy.md` for tone, terminology, the approved campaign lines and brand facts (every figure needs its source and date). Claims must be verifiable; no superlatives; label sample data as sample data. Never invent quotes, customers, metrics or program output.
3. **Choose the build path.**
   - *Static graphic* (cover, post, ad, slide, thumbnail, poster): copy `assets/artboard.html`, set the size, compose with the recipe from `references/formats.md`, then render with `node scripts/render.mjs <file.html> <out.png>`. Look at the PNG and fix problems before delivering.
   - *Web or product UI* in a Tailwind v4 project: import `assets/tailwind.css` (semantic names match shadcn/ui) and follow the Components section of `references/DESIGN.md`.
   - *Anything else* (Figma, Keynote, docs): use the hex values, type styles and spacing from `references/DESIGN.md`.
4. **Use only the brand graphics.** The stripe signature and the shard matrix (`references/graphics.md`; `scripts/matrix.mjs` emits a matrix SVG). Logos come from `assets/logo/` — never retype or redraw the wordmark.
5. **Check before you hand over** (list below), then tell the user what you made, its size and any assumption you had to make.

## The rules that matter most

- **Colour ratio** — neutrals ~60%, Signal Blue ~30%, Oxide ≤10% with one Oxide focal point at most. Oxide means parity or "look here first"; it never signals errors and never sits on a Signal Blue surface (parity turns Ink there). No other blues, no gradients, no glows.
- **Square everything** — radius 0 for cards, buttons, images, badges, status markers and app-icon masters. Only platform-imposed avatar crops are round.
- **Type** — Archivo at 125% width (`font-stretch:125%`) for display and numerals, 112% for headlines; Geist for text; Geist Mono uppercase with 0.08em tracking for labels. Chinese headings: zero tracking, line-height ≥ 1.15, a half-width space between Chinese and Latin/numbers, product name always `RustFS`.
- **Layout for artboards** — measure in u (1/100 of the short side); 7u safe margin; wordmark top-left at 4.25u; one mono label top-right; title in the left ~64%; the matrix on the right ~36% or along the bottom. Left-aligned. One message, one proof line, one call to action.
- **Surfaces** — Ink #0B0E14 (default stage), Paper #F4F6F9 (technical), White, Signal #0062FF (announcements). Wordmark is white on Ink/Signal and Signal Blue on light surfaces.
- **Motion** — write (shards appear in order, stepped) and heal (a shard drops to a dashed outline, parity flashes, it is rebuilt). Standard/emphasized/exit easings, 80–720ms, no bounce, honour reduced motion.

## Before you hand over

- The wordmark is an official SVG, unmodified, with clear space of half its height.
- Text sits inside the 7u margin; nothing overlaps unintentionally; the smallest text is readable at the size it will be seen (feeds shrink 1080px posts to ~320px).
- Oxide appears at most once as a focal point; no colours outside the palette.
- Every number has a unit; quoted figures have a source and a date; sample data says so.
- Both languages say the same thing when the piece is bilingual.
- You rendered the final file and actually looked at it.

## Files

- `references/DESIGN.md` — tokens and full rules (read first).
- `references/formats.md` — sizes, safe zones and layout recipes per channel.
- `references/copy.md` — voice, terminology (zh/en), approved lines, brand facts.
- `references/graphics.md` — logo usage, stripe signature, shard-matrix algorithm, icons, charts.
- `assets/artboard.html` — single-file starter for static graphics (fonts, tokens, wordmark, matrix generator).
- `assets/tailwind.css`, `assets/tokens.css` — generated design tokens.
- `assets/logo/*.svg` — wordmark, Flow S symbol and app icon in Signal, White and Ink.
- `scripts/render.mjs` — render an HTML artboard to PNG with headless Chrome (Node ≥ 22, no npm packages).
- `scripts/matrix.mjs` — print a shard-matrix SVG for any size and erasure layout.
规范更新后请重新下载。