---
version: alpha
name: zzm-v4
description: |
  赵子民设计系统 v4「纸 · 墨 · 朱」。纸白画布、墨色文字、一枚哑光朱砂红只标「你在这里 / 下一步」；
  8pt 间距梯与 4pt 基线；每个可交互控件都是一枚光从正上方照下的微拟物键（凸面、顶部反光、贴地投影、反光光晕、按压内陷）。
  文字按钮一律圆角矩形，999 胶囊只给不可点的徽章。系统字体，无网络字体，只有浅色。
  所有样式在 .zzm-v4 作用域内生效。源：https://ui.zhaozimin.com · 同步自 edu.zhaozimin v23.5.1 (086937d)。

colors:
  accent: "#A6402F"
  paper: "#F6F6F4"
  surface: "#FFFFFF"
  ink: "#161616"
  ink-strong: "#1D1D1B"
  text-1: "#26261F"
  text-2: "#3F3F3B"
  text-3: "#4A4A46"
  text-4: "#6E6E6A"
  text-5: "#72726E"
  muted: "#8B8B85"
  muted-2: "#A2A29C"
  muted-3: "#B0B0AA"
  faint: "#C6C6C0"
  dark-card: "#131316"
  dark-poster: "#0E0E10"
  dark-pay: "#0B0B0C"
  hairline: "rgba(0, 0, 0, 0.07)"
  hairline-2: "rgba(0, 0, 0, 0.09)"
  hairline-strong: "rgba(0, 0, 0, 0.14)"
  tier-free: "#16A34A"
  tier-free-bg: "rgba(22, 163, 74, 0.12)"
  tier-free-ink: "#157F3C"
  tier-member: "#E0920A"
  tier-member-bg: "rgba(224, 146, 10, 0.18)"
  tier-member-ink: "#8A5606"
  tier-ext: "#A6402F"
  tier-ext-bg: "rgba(166, 64, 47, 0.11)"
  tier-ext-ink: "#A6402F"

typography:
  display:
    fontFamily: "-apple-system, BlinkMacSystemFont, \"PingFang SC\", \"Hiragino Sans GB\", \"Microsoft YaHei\", sans-serif"
    fontSize: "40px"
    fontWeight: 750
    lineHeight: "48px"
    letterSpacing: "-0.5px"
  title:
    fontFamily: "-apple-system, BlinkMacSystemFont, \"PingFang SC\", \"Hiragino Sans GB\", \"Microsoft YaHei\", sans-serif"
    fontSize: "26px"
    fontWeight: 700
    lineHeight: "32px"
  card-title:
    fontFamily: "-apple-system, BlinkMacSystemFont, \"PingFang SC\", \"Hiragino Sans GB\", \"Microsoft YaHei\", sans-serif"
    fontSize: "16px"
    fontWeight: 650
    lineHeight: "24px"
  body:
    fontFamily: "-apple-system, BlinkMacSystemFont, \"PingFang SC\", \"Hiragino Sans GB\", \"Microsoft YaHei\", sans-serif"
    fontSize: "14px"
    fontWeight: 400
    lineHeight: "24px"
  body-sm:
    fontFamily: "-apple-system, BlinkMacSystemFont, \"PingFang SC\", \"Hiragino Sans GB\", \"Microsoft YaHei\", sans-serif"
    fontSize: "13px"
    fontWeight: 400
    lineHeight: "20px"
  caption:
    fontFamily: "-apple-system, BlinkMacSystemFont, \"PingFang SC\", \"Hiragino Sans GB\", \"Microsoft YaHei\", sans-serif"
    fontSize: "12.5px"
    fontWeight: 400
    lineHeight: "20px"
  label:
    fontFamily: "ui-monospace, \"SF Mono\", Menlo, monospace"
    fontSize: "10px"
    fontWeight: 400
    letterSpacing: "1.5px"
  meta:
    fontFamily: "ui-monospace, \"SF Mono\", Menlo, monospace"
    fontSize: "11px"
    fontWeight: 400
  button-sm:
    fontFamily: "-apple-system, BlinkMacSystemFont, \"PingFang SC\", \"Hiragino Sans GB\", \"Microsoft YaHei\", sans-serif"
    fontSize: "12px"
    fontWeight: 600
  button-md:
    fontFamily: "-apple-system, BlinkMacSystemFont, \"PingFang SC\", \"Hiragino Sans GB\", \"Microsoft YaHei\", sans-serif"
    fontSize: "13px"
    fontWeight: 600
    letterSpacing: "0.2px"
  button-lg:
    fontFamily: "-apple-system, BlinkMacSystemFont, \"PingFang SC\", \"Hiragino Sans GB\", \"Microsoft YaHei\", sans-serif"
    fontSize: "14px"
    fontWeight: 600

rounded:
  r-1: "4px"
  r-2: "8px"
  r-3: "12px"
  r-4: "16px"
  r-pill: "999px"

spacing:
  s-1: "4px"
  s-2: "8px"
  s-3: "12px"
  s-4: "16px"
  s-5: "20px"
  s-6: "24px"
  s-8: "32px"
  s-10: "40px"
  s-12: "48px"
  s-16: "64px"

components:
  button-paper:
    -webkit-appearance: "none"
    appearance: "none"
    display: "inline-flex"
    align-items: "center"
    justify-content: "center"
    gap: "8px"
    height: "36px"
    padding: "0 16px"
    font-family: "inherit"
    font-size: "13px"
    font-weight: "600"
    letter-spacing: ".2px"
    white-space: "nowrap"
    cursor: "pointer"
    user-select: "none"
    border-radius: "8px"
    border: "1px solid rgba(0, 0, 0, .14)"
    color: "#3F3F3B"
    background: "linear-gradient(180deg, #FFFFFF 0%, #F2F2EF 100%)"
    box-shadow: "0 0 0 3px rgba(255, 255, 255, .55), 0 1px 2px rgba(0, 0, 0, .09), 0 2px 6px rgba(0, 0, 0, .06), inset 0 1px 0 rgba(255, 255, 255, .92), inset 0 -1px 0 rgba(0, 0, 0, .05)"
    transition: "box-shadow .16s ease, transform .16s ease, background .16s ease, border-color .16s ease, filter .16s ease, opacity .16s ease"
  button-paper-hover:
    transform: "translateY(-1px)"
    border-color: "rgba(0, 0, 0, .18)"
    box-shadow: "0 0 0 4px rgba(255, 255, 255, .8), 0 2px 4px rgba(0, 0, 0, .10), 0 4px 12px rgba(0, 0, 0, .09), inset 0 1px 0 rgba(255, 255, 255, .95), inset 0 -1px 0 rgba(0, 0, 0, .05)"
  button-paper-active:
    transform: "translateY(0)"
    background: "linear-gradient(180deg, #ECECE9 0%, #F4F4F1 100%)"
    box-shadow: "0 0 0 3px rgba(255, 255, 255, .45), 0 1px 0 rgba(255, 255, 255, .65), inset 0 2px 4px rgba(0, 0, 0, .13), inset 0 1px 2px rgba(0, 0, 0, .09)"
  button-focus:
    outline: "none"
    box-shadow: "0 0 0 3px rgba(166, 64, 47, .20), 0 1px 2px rgba(0, 0, 0, .09), 0 2px 6px rgba(0, 0, 0, .06), inset 0 1px 0 rgba(255, 255, 255, .92)"
  button-disabled:
    color: "#A2A29C"
    background: "#F2F2EF"
    border-color: "rgba(0, 0, 0, .08)"
    box-shadow: "inset 0 1px 0 rgba(255, 255, 255, .7), 0 1px 2px rgba(0, 0, 0, .04)"
  button-busy:
    position: "relative"
    overflow: "hidden"
    pointer-events: "none"
    opacity: ".92"
    filter: "saturate(.72)"
    transform: "none"
  button-primary:
    color: "#FFFFFF"
    border-color: "rgba(0, 0, 0, .85)"
    background: "linear-gradient(180deg, #3A3A36 0%, #1D1D1B 58%, #141412 100%)"
    box-shadow: "0 0 0 3px rgba(22, 22, 22, .06), 0 1px 2px rgba(0, 0, 0, .18), 0 3px 10px rgba(22, 22, 22, .24), inset 0 1px 0 rgba(255, 255, 255, .20), inset 0 -1px 0 rgba(0, 0, 0, .38)"
  button-primary-active:
    filter: "none"
    background: "linear-gradient(180deg, #101010 0%, #22221F 100%)"
    box-shadow: "0 0 0 3px rgba(22, 22, 22, .06), inset 0 2px 5px rgba(0, 0, 0, .55), inset 0 1px 2px rgba(0, 0, 0, .4)"
  button-accent:
    color: "#FFFFFF"
    border-color: "rgba(122, 42, 29, .9)"
    background: "linear-gradient(180deg, #C25743 0%, #A6402F 56%, #99392A 100%)"
    box-shadow: "0 0 0 3px rgba(166, 64, 47, .10), 0 1px 2px rgba(0, 0, 0, .14), 0 3px 10px rgba(166, 64, 47, .28), inset 0 1px 0 rgba(255, 255, 255, .32), inset 0 -1px 0 rgba(0, 0, 0, .20)"
  button-accent-active:
    filter: "none"
    background: "linear-gradient(180deg, #8E3425 0%, #A03D2C 100%)"
    box-shadow: "0 0 0 3px rgba(166, 64, 47, .10), inset 0 2px 5px rgba(0, 0, 0, .34), inset 0 1px 2px rgba(0, 0, 0, .24)"
  button-ghost:
    border-color: "transparent"
    background: "transparent"
    box-shadow: "none"
    color: "#4A4A46"
  button-ghost-hover:
    transform: "translateY(-1px)"
    border-color: "rgba(0, 0, 0, .14)"
    background: "linear-gradient(180deg, #FFFFFF 0%, #F2F2EF 100%)"
    box-shadow: "0 0 0 3px rgba(255, 255, 255, .55), 0 1px 2px rgba(0, 0, 0, .09), 0 2px 6px rgba(0, 0, 0, .06), inset 0 1px 0 rgba(255, 255, 255, .92)"
  button-ondark:
    color: "#FFFFFF"
    border-color: "rgba(255, 255, 255, .28)"
    background: "linear-gradient(180deg, rgba(255, 255, 255, .16) 0%, rgba(255, 255, 255, .06) 100%)"
    box-shadow: "0 0 0 3px rgba(255, 255, 255, .05), 0 2px 8px rgba(0, 0, 0, .4), inset 0 1px 0 rgba(255, 255, 255, .28), inset 0 -1px 0 rgba(0, 0, 0, .3)"
  button-sm:
    height: "28px"
    padding: "0 12px"
    font-size: "12px"
    gap: "4px"
  button-lg:
    height: "44px"
    padding: "0 24px"
    font-size: "14px"
    border-radius: "12px"
    gap: "8px"
  button-icon:
    width: "36px"
    padding: "0"
  video-play:
    display: "grid"
    place-items: "center"
    width: "72px"
    height: "72px"
    padding: "0"
    border: "1px solid rgba(0, 0, 0, .16)"
    border-radius: "50%"
    cursor: "pointer"
    color: "#1D1D1B"
    background: "linear-gradient(180deg, #FFFFFF 0%, #F2F2EF 100%)"
    box-shadow: "0 0 0 4px rgba(255, 255, 255, .24), 0 2px 4px rgba(0, 0, 0, .16), 0 6px 16px rgba(0, 0, 0, .22), inset 0 1px 0 rgba(255, 255, 255, .96), inset 0 -1px 0 rgba(0, 0, 0, .08)"
    transition: "transform .16s ease, box-shadow .16s ease, border-color .16s ease"
  input:
    background: "#FDFDFC"
    box-shadow: "inset 0 1.5px 3px rgba(0, 0, 0, .06), inset 0 1px 1px rgba(0, 0, 0, .04)"
  input-focused:
    border-color: "#161616"
    box-shadow: "inset 0 1.5px 3px rgba(0, 0, 0, .06), 0 0 0 3px rgba(22, 22, 22, .07)"
  card:
    background: "#FFFFFF"
    border: "1px solid rgba(0, 0, 0, .09)"
    border-radius: "16px"
    box-shadow: "0 1px 2px rgba(0, 0, 0, .04), 0 6px 18px rgba(0, 0, 0, .05), inset 0 1px 0 rgba(255, 255, 255, .85)"
  cardlink:
    background: "#FFFFFF"
    border: "1px solid rgba(0, 0, 0, .09)"
    border-radius: "16px"
    padding: "12px"
    cursor: "pointer"
    box-shadow: "0 1px 2px rgba(0, 0, 0, .04)"
    transition: "transform .16s ease, box-shadow .16s ease, border-color .16s ease"
  cardlink-hover:
    transform: "translateY(-3px)"
    border-color: "rgba(0, 0, 0, .3)"
    box-shadow: "0 10px 30px rgba(0, 0, 0, .09), 0 1px 2px rgba(0, 0, 0, .04)"
  cardlink-done:
    background: "rgba(166, 64, 47, .04)"
    border-color: "rgba(166, 64, 47, .35)"
  dialog-overlay:
    background: "rgba(22, 22, 22, .46)"
    position: "fixed"
    inset: "0"
    z-index: "50"
    animation: "zzmFade .2s ease both"
  dialog-panel:
    width: "min(calc(100% - 32px), 440px)"
    max-width: "440px"
    gap: "16px"
    padding: "24px"
    border: "1px solid rgba(0, 0, 0, .14)"
    border-radius: "16px"
    background: "#FFFFFF"
    box-shadow: "0 1px 2px rgba(0, 0, 0, .10), 0 18px 48px rgba(0, 0, 0, .22), inset 0 1px 0 rgba(255, 255, 255, .92)"
    position: "fixed"
    top: "50%"
    left: "50%"
    z-index: "51"
    display: "grid"
    transform: "translate(-50%, -50%)"
    animation: "zzmDialogIn .2s cubic-bezier(.2, .7, .2, 1) both"
  dialog-title:
    color: "#1D1D1B"
    font-size: "17px"
    font-weight: "700"
    line-height: "24px"
    margin: "0"
  dialog-description:
    color: "#6E6E68"
    font-size: "13px"
    line-height: "20px"
    margin: "0"
  toast:
    display: "inline-block"
    background: "#1D1D1B"
    color: "#FFFFFF"
    font-size: "12px"
    padding: "9px 18px"
    border-radius: "999px"
    white-space: "nowrap"
    box-shadow: "0 8px 24px rgba(0, 0, 0, .3)"
    animation: "zzmUp .25s ease both"
  skeleton:
    position: "relative"
    overflow: "hidden"
    background: "#EFEFEC"
    border-radius: "8px"
  tier-pill:
    fontSize: "10px"
    fontWeight: 600
    letterSpacing: "0.5px"
    padding: "2px 7px"
    borderRadius: "4px"
    free: "var(--zzm-tier-free-bg) / var(--zzm-tier-free-ink)"
    member: "var(--zzm-tier-member-bg) / var(--zzm-tier-member-ink)"
    ext: "var(--zzm-tier-ext-bg) / var(--zzm-tier-ext-ink)"
  tag:
    fontSize: "9.5px"
    fontWeight: 600
    letterSpacing: "1px"
    padding: "3px 8px"
    borderRadius: "4px"
    accent: "rgba(166,64,47,.08) / var(--zzm-accent)"
    neutral: "#EFEFEC / #8B8B85"
  breadcrumb:
    fontSize: "12px"
    lineHeight: "20px"
    gap: "8px"
    item: "#8B8B85 → hover #161616"
    separator: "\"/\" #C6C6C0"
    current: "#161616 / 600"
  tabs:
    fontSize: "13px"
    padding: "8px 2px 10px"
    gap: "24px"
    active: "#161616 / 600 + 2px solid var(--zzm-accent)"
    inactive: "#8B8B85 / 450"
    divider: "1px solid rgba(0,0,0,.09)"
  course-card:
    border: "1px solid rgba(0,0,0,.09)"
    borderRadius: "16px"
    header: "aspect-ratio 16/9 · #131316"
    body: "padding 16px 18px 17px"
    title: "16px / 650"
    intro: "13px / 1.65 / #72726E"
  lesson-card:
    container: ".zzm-cardlink"
    thumb: "aspect-ratio 16/9 · radius 12 · #131316"
    corner: "mono 9.5–10.5 · padding 3px 6px · radius 4 · rgba(0,0,0,.55)"
    locked: "rgba(8,8,10,.7) 遮罩 + 居中锁头"
  sidebar:
    width: "266px"
    background: "var(--zzm-paper)"
    borderRight: "1px solid rgba(0,0,0,.07)"
    row: "padding 9px 10px · radius 8 · 13.5px"
    active: "rgba(0,0,0,.07) · 600"
---

# 赵子民设计系统 · zzm v4「纸 · 墨 · 朱」

> 站点 v0.1.1 · 2026-09-23 · https://ui.zhaozimin.com

## Overview

高级、克制、好上手。进来就安静下来，觉得「这很简单，我马上能开始」。整个界面看起来要像**一块材料切出来的**：每个板块共用同一套视觉词汇，所有尺寸取自同一把梯子，所有光影来自同一个光源。

使用要点：

- 引入 https://ui.zhaozimin.com/zzm.css，并在根节点加 class="zzm-v4"——所有样式只在这个作用域内生效（不想加类名就用 https://ui.zhaozimin.com/zzm.global.css）
- 颜色只用 var(--zzm-*)；间距、高度、行高、圆角只取 4 的倍数（优先 8 的倍数）
- 按钮用 .zzm-btn 家族：圆角矩形（sm/md 8px · lg 12px），高 28/36/44，禁止 999 胶囊
- 阴影只从 .zzm-btn / .zzm-card / .zzm-cardlink / .zzm-input 取，不要自己写 box-shadow、backdrop-filter
- 一屏只出现一次朱砂红 --zzm-accent，标「你在这里 / 下一步」
- 系统字体栈，不引入网络字体；只有浅色，没有暗色主题
- 禁用＝灰面灰字（不用 opacity 淡化）；等待中的按钮用 busy

## Colors

黑、白、朱砂红。灰带一点黄绿偏，与纸面同一个色温。朱色一屏只出现一次。

### 品牌与底面
| 令牌 | 值 | 用途 |
|---|---|---|
| `--zzm-accent` | `#A6402F` |  |
| `--zzm-paper` | `#F6F6F4` | 应用画布 / 侧栏底 |
| `--zzm-surface` | `#FFFFFF` | 主内容面 / 卡片 |
| `--zzm-ink` | `#161616` | 主文字墨色 |
| `--zzm-ink-strong` | `#1D1D1B` | 深墨（黑胶囊 CTA） |

### 文字灰阶
| 令牌 | 值 | 用途 |
|---|---|---|
| `--zzm-text-1` | `#26261F` |  |
| `--zzm-text-2` | `#3F3F3B` |  |
| `--zzm-text-3` | `#4A4A46` |  |
| `--zzm-text-4` | `#6E6E6A` |  |
| `--zzm-text-5` | `#72726E` |  |
| `--zzm-muted` | `#8B8B85` |  |
| `--zzm-muted-2` | `#A2A29C` |  |
| `--zzm-muted-3` | `#B0B0AA` |  |
| `--zzm-faint` | `#C6C6C0` |  |

### 暗底（只给封面、播放器、付款页）
| 令牌 | 值 | 用途 |
|---|---|---|
| `--zzm-dark-card` | `#131316` |  |
| `--zzm-dark-poster` | `#0E0E10` |  |
| `--zzm-dark-pay` | `#0B0B0C` |  |

### 细线三档
| 令牌 | 值 | 用途 |
|---|---|---|
| `--zzm-hairline` | `rgba(0, 0, 0, 0.07)` |  |
| `--zzm-hairline-2` | `rgba(0, 0, 0, 0.09)` |  |
| `--zzm-hairline-strong` | `rgba(0, 0, 0, 0.14)` |  |

### 课时档位信号色（只用在档位胶囊上）
| 令牌 | 值 | 用途 |
|---|---|---|
| `--zzm-tier-free` | `#16A34A` | 免费 · 绿 |
| `--zzm-tier-free-bg` | `rgba(22, 163, 74, 0.12)` |  |
| `--zzm-tier-free-ink` | `#157F3C` |  |
| `--zzm-tier-member` | `#E0920A` | 会员 · 黄金 |
| `--zzm-tier-member-bg` | `rgba(224, 146, 10, 0.18)` |  |
| `--zzm-tier-member-ink` | `#8A5606` |  |
| `--zzm-tier-ext` | `#A6402F` | 拓展 · 红（品牌朱同族） |
| `--zzm-tier-ext-bg` | `rgba(166, 64, 47, 0.11)` |  |
| `--zzm-tier-ext-ink` | `#A6402F` |  |

## Typography

字体栈 `-apple-system, BlinkMacSystemFont, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif`；等宽 `ui-monospace, "SF Mono", Menlo, monospace`。字号沿用 0.5 步进字阶（9.5 / 10.5 / 11.5 / 12.5 / 13.5 / 14.5 / 16 / 22 / 26 / 40+），不发明新字号。显式行高一律写 px 且为 4 的倍数（13px→20px，16px→24px，22–26px→32px，40–48px→48/56px）；无单位行高只允许 1。元数据、编号、节标签用 mono。

## Layout

- 间距梯：4 · 8 · 12 · 16 · 20 · 24 · 32 · 40 · 48 · 56 · 64 · 72 · 80 · 88（只取 4 的倍数，优先 8 的倍数）。
- 控件高度：28（工具条键）/ 36（表单键与输入框）/ 44（主操作键）。容器与头部：32 / 40 / 48 / 56 / 64。
- 主内容区 max-width 1080 + 左右内距 48；窄文档流 820；侧栏 266；面包屑顶栏钉顶。
- 节标题骨架：mono 编号 + 标题 + 右侧注记 + 底部 .09 细线。
- 卡片语法：白卡 + 1px .09 细线 + 圆角 16 + 内距 16–24 + .zzm-card 浮起光影。

## Elevation & Depth

光从正上方来。每个可交互控件都是一枚真实的键，五层缺一不可：

1. 凸面：竖向微渐变（顶亮底沉）。
2. 顶部反光：`inset 0 1px 0` 高光线。
3. 贴地投影：近影 1px 锐 + 远影 2–6px 柔。
4. 反光光晕：外圈 `0 0 0 3px` 白环，悬停变亮变宽。
5. 按压内陷：`:active` 翻转渐变 + inset 阴影。

凸的是键，凹的是输入槽（.zzm-input），浮起的是卡片（.zzm-card）。阴影只从这些质感类取；backdrop-filter 全域禁用。深色面上要重标：顶部反光降到 .055 左右、投影加深——直接用 .zzm-btn--ondark。

## Shapes

圆角梯 4（微件、徽章）/ 8（按钮、输入框）/ 12（内嵌卡、大按钮）/ 16（卡片、面板）/ 20–24（大容器）/ 999（非交互胶囊）/ 50%（圆）。同层级同档：外层卡片 16，卡内嵌套 12。唯一可为圆形的交互键是视频播放键（.zzm-video-play，72px）。

## Components

### 按钮 Btn

光从正上方来——每个按钮都是一枚真实的键：凸面渐变、顶部反光、贴地投影、反光光晕、按压内陷。文字按钮一律圆角矩形，禁胶囊。

- 要：圆角矩形：`sm`/`md` 圆角 8，`lg` 圆角 12
- 不要：把文字按钮做成 999 胶囊——胶囊只留给不可点的徽章
- 要：光影只从 `.zzm-btn` 取，调用方 `style` 只写 margin / flex / width
- 不要：在 `style` 里散写 `box-shadow`、渐变或 `border-radius` 盖掉质感
- 要：点击后要等待的操作用 `busy`
- 不要：用 `opacity` 淡化来表示禁用
- 要：一屏只有一个墨键或朱键做主操作
- 不要：朱键当装饰色——它只标「下一步」或危险动作

完整样张与代码：https://ui.zhaozimin.com/components/button.md

### 视频播放键 VideoPlay

全站唯一允许为圆形的交互键。圆形不是装饰例外，而是「点按即开始播放」这个媒体语义的通用符号——导学封面与所有课时海报共用这一个原件。

- 要：只用于「点按即开始播放」
- 不要：借它的圆形去做别的按钮——文字按钮仍然是圆角矩形
- 要：导学封面与课时海报用同一个原件
- 不要：在不同页面给同一个动作画不同的播放键

完整样张与代码：https://ui.zhaozimin.com/components/video-play.md

### 输入槽 Input

键是凸的，槽是凹的。.zzm-input 给输入框一层内凹阴影和近白底色；几何（高 36、圆角 8、.14 描边、内距 12）由调用方写在 style 里。

- 要：高 36（与 md 按钮同高，放一行能对齐）
- 不要：输入框做成胶囊
- 要：错误用朱色描边 + 文字说明怎么改
- 不要：只变红不说原因

完整样张与代码：https://ui.zhaozimin.com/components/input.md

### 开关 Switch

墨色开关：关闭是浅灰轨道，开启是墨色轨道，白色滑块沿标准缓动滑过去。

完整样张与代码：https://ui.zhaozimin.com/components/switch.md

### 复选框 Checkbox

16px 方框、圆角 4。选中是墨底白勾，未选是 1.5px 描边；文字随状态从灰变深。

完整样张与代码：https://ui.zhaozimin.com/components/checkbox.md

### 徽章与档位 Badge

一切不可点的标识。圆＝徽章不可点，方角＝控件可点——这条信号让用户看形状就知道能不能点。

- 要：徽章、标签、状态不可点
- 不要：给徽章加点击事件——要能点就改成按钮
- 要：档位色只出现在档位胶囊上
- 不要：用档位绿、黄去表达别的意思

完整样张与代码：https://ui.zhaozimin.com/components/badge.md

### 面包屑 Breadcrumb

层级轨迹：灰字可点、悬停变墨，末项是墨色加粗的当前页，斜杠分隔。全站课程页把它钉在顶栏。

- 要：颜色交给容器继承
- 不要：在项上写内联 `color`——它会压死 :hover
- 要：轨迹由页面自己组，组件只管长相

完整样张与代码：https://ui.zhaozimin.com/components/breadcrumb.md

### 标签页 Tabs

下划线标签页。当前项墨色 600 加 2px 朱色下划线，其余灰字 450。那条朱线就是这一屏的「你在这里」。

- 要：同屏用了朱色下划线，就不再用第二处朱色做装饰
- 不要：做成胶囊分段控件——需要分段时用 sm 按钮组（当前项墨键）

完整样张与代码：https://ui.zhaozimin.com/components/tabs.md

### 分页 Pagination

26px 方格：当前页墨底白字，其余 .14 描边，省略号不加框。页数多时只留首页、末页和当前页前后各一页。

完整样张与代码：https://ui.zhaozimin.com/components/pagination.md

### 确认窗 Dialog

纸面卡片、宽 440、圆角 16，遮罩只降亮不模糊——背景仍能认出正在操作什么。朱键只用于破坏性确认。

- 要：朱键只给「删除、作废、注销」这类破坏性确认
- 不要：用 `window.confirm()` 原生灰框
- 要：遮罩 `rgba(22,22,22,.46)`，只降亮
- 不要：给遮罩加模糊

完整样张与代码：https://ui.zhaozimin.com/components/dialog.md

### 轻提示 Toast

深墨胶囊，从下方浮起，1.8 秒后消失。它不可点，所以可以是胶囊。文案说结果，不说过程：「已保存到你的笔记库」。

- 要：说结果：「已保存」「已复制」「已删除」
- 不要：说过程或道歉：「操作成功！」「抱歉，出错了」
- 要：1.8 秒自动消失；出错要让人处理时用确认窗或内联错误

完整样张与代码：https://ui.zhaozimin.com/components/toast.md

### 进度条 Progress

4px 细轨，.09 灰底，朱色填充。高度 ≤ 8px 的微件允许 2px 端帽圆角。

- 要：朱色填充表示「你走到了这里」
- 不要：同屏多条朱色进度条——只有当前关注的那条用朱色，其余用墨色

完整样张与代码：https://ui.zhaozimin.com/components/progress.md

### 骨架屏 Skeleton

纸灰底块，一道微光 1.4 秒扫过。取代「LOADING…」文字。卡片不另写骨架——同一个组件传 loading，骨架与真实态共用同一段布局。

- 要：骨架与真实态同源（loading prop）
- 不要：单独手写一份「看起来差不多」的骨架组件
- 不要：用「加载中…」文字或转圈占位整块内容

完整样张与代码：https://ui.zhaozimin.com/components/skeleton.md

### 卡片与卡链 Card

两种容器：.zzm-card 是浮在纸上的白面板；.zzm-cardlink 是可点的内容卡——悬停时描边加深、上浮 3px、落下柔影。

- 要：卡 16、卡内嵌图 12
- 不要：在卡上内联写 `box-shadow` 或 `borderColor`
- 要：完成态用容器级朱染
- 不要：在角落放一个 18px 小勾让人去找

完整样张与代码：https://ui.zhaozimin.com/components/card.md

### 课程卡 CourseCard

综合首页与落地页共用的课程卡：16:9 暗底头图（封面或星座线稿）+ 名称、简介、适合人群、元数据与脚注动作。

- 要：封面按上传原图呈现，不叠蒙层
- 不要：为了一行小字压暗整幅封面
- 要：编号用深色小底自持可读性
- 不要：用 textShadow 救浅字——白底海报上一样糊

完整样张与代码：https://ui.zhaozimin.com/components/course-card.md

### 系列卡 SeriesCard

课程总览里的一个系列：头图、名称、两行简介、节数与总时长，再加一排每课一格的进度方块——完成的格子是朱色打勾。

完整样张与代码：https://ui.zhaozimin.com/components/series-card.md

### 课节卡 LessonCard

一节课：16:9 暗底缩略图，四角是编号、档位角标、时长；未解锁时整卡压暗并居中一把锁；看完后整卡朱染。

- 要：四角元素（编号、时长、角标）各自带深色小底
- 不要：给整张封面加暗色蒙层
- 要：有封面就不叠短标题——封面图自己写着课名
- 不要：锁定用 backdrop 模糊（同屏几十张卡，GPU 吃不消）

完整样张与代码：https://ui.zhaozimin.com/components/lesson-card.md

### 封面图 CoverImage

封面三态：加载中只露父容器的暗底，就绪后 350ms 淡入，失败回退到线稿。杜绝「先画线稿、封面到了再跳变盖上」的闪跳。

- 要：封面按上传原图呈现
- 不要：提供「蒙层」参数——叠字可读性由那颗字自己解决

完整样张与代码：https://ui.zhaozimin.com/components/cover-image.md

### 神秘卡 MysteryCard

尚未揭晓的课：3D 绸缎遮罩、朱印封蜡、一道流光，悬停时微微掀起。不显示名称和价格，也不能购买。

- 要：只用于尚未上线的课程
- 不要：把 3D、流光这类效果搬到普通卡片上

完整样张与代码：https://ui.zhaozimin.com/components/mystery-card.md

### 星图 StarMap

学习地图：一条折线穿过五个站点。走过的站墨色实心、实线相连；当前站朱色，外圈一道脉冲光晕；还没到的站白底灰边、虚线相连。

- 要：朱色只给当前站：它就是「你在这里」
- 不要：给已完成的站也上朱色
- 要：脉冲光晕只挂在当前站（zzmPulse 2.6s）

完整样张与代码：https://ui.zhaozimin.com/components/star-map.md

### 侧栏导航 Sidebar

纸色侧栏，宽 266。导航行是扁平的，不是键——当前行只加一层 .07 灰底和 600 字重；真正的操作（收起、退出）才用微拟物键。

- 要：导航行扁平，当前行灰底
- 不要：把导航行做成一排凸键
- 要：收起键展开态与收起态同一坐标，零位移
- 不要：用朱色标当前导航项——朱色留给内容里的「下一步」

完整样张与代码：https://ui.zhaozimin.com/patterns/sidebar.md

### 数据表格 DataTable

同名但用途不同的数据先用一排小键分区，再进表格。浅灰 mono 表头、可排序列、细线分行；窄屏只横向滚动，不折行。

完整样张与代码：https://ui.zhaozimin.com/patterns/data-table.md

### 安全验证外壳 VerifyShell

第三方人机验证（Cloudflare Turnstile、阿里云验证码）的外围壳：始终可见、占位固定，底下三种反馈态——通过、冷却、限流。

- 要：单次 token：每次发送验证码前重新验证
- 要：发送后 60 秒冷却，冷却中显示倒计时
- 要：被限流时明确说「请求过多 · 暂时拦截」
- 不要：验证失败时只让按钮变灰、不说原因

完整样张与代码：https://ui.zhaozimin.com/patterns/verify-shell.md

### 笔记标注块 Callouts

课程笔记用 Obsidian 的语法和官方色板：老用户零学习成本，一眼分清提示、警告和完成。这是刻意的边界——笔记区是内容，不是产品界面。

- 要：笔记区（内容）用 Obsidian 官方色
- 不要：把这些颜色带进按钮、卡片、徽章等产品界面
- 要：链接没通过白名单（safeHref）时降级为纯文本

完整样张与代码：https://ui.zhaozimin.com/patterns/callouts.md

## Do's and Don'ts

- 要：**光影铁律**：阴影只从质感类（`.zzm-btn` `.zzm-card` `.zzm-input`）取，组件里禁止散写 `box-shadow`。一体感来自全站共用同一个光照模型
- 要：**按钮禁胶囊**：文字按钮一律圆角矩形（sm/md 8 · lg 12），999 胶囊只留给不可点的徽章
- 不要：鲜艳纯红。红必须是哑光的朱砂 / 印泥色，而且用量极少
- 不要：营销优先的首屏：大 Hero、多个 CTA、社交证明横幅。第一眼必须是学习内容本身
- 不要：奶油色、米色暖纸底。白就是中性白，不偏暖
- 不要：打卡中断、红点焦虑这类胁迫式活跃机制。地图只照亮位置，不制造焦虑
- 不要：模糊背景（backdrop-filter）。性能代价大，全域禁用
- 不要：网络字体。系统字体就是这套系统的一部分

## Agent Prompt Guide

- 目录：https://ui.zhaozimin.com/llms.txt · 全文：https://ui.zhaozimin.com/llms-full.txt · 令牌：https://ui.zhaozimin.com/tokens.json · 样式：https://ui.zhaozimin.com/zzm.css
- 任一组件：https://ui.zhaozimin.com/components/<名字>.md，其中的 HTML 由 React 源码在构建时渲染，可原样粘贴。
- 复刻完与站内样张同机截图比对；最常见的偏差依次是：漏了 .zzm-v4、字体被换成网络字体、缺 box-sizing、自己写了 box-shadow、同屏朱色超过一处。
