AirShelf/电商AI平台/design-system.html
iye 04335f3269
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 7s
feat(workbench): 三工序图片区视觉对齐 + 任务中心聚合 + 工具台头部筛选
- model-photo / platform-cover · 头部 toolbar 落地: 时间 / 模特(平台) chip 下拉 + 折叠搜索
- model-photo / platform-cover · 图片卡片样式同步图片创作 (.io-cell): bg / hover / .gen 脉冲 / .err 红框
- model-photo / platform-cover · 单图 hover overlay: 再次生成 + 下载 + 更多(加入资产库/删除)
- model-photo / platform-cover · 批次底栏: 再次生成图标统一 + 更多 menu(全部加入资产库/删除该批)
- model-photo · 修 TDZ bug: renderModelMini 调用挪到 MODELS 声明后, 解决整页崩溃
- model-photo · 去掉冗余 pv-summary, 商品自动选最近编辑, task 写入 name 字段
- image-optimize · 单图右上加再次生成图标, 加入 fs-image-tasks-image 与任务中心打通
- image-optimize · 输入区拆 3 行: + 在顶 / textarea 满宽 / 发送在底栏右; 参考图缩略与加号同 64×64
- asset-factory · 任务中心加时间 chip + image 类型 + 跳转表; 删冗余类型列
- pipeline · stage2 商品卡换商品库风格 + AI 生成三视图主 CTA + .tri-missing-badge[hidden] CSS 修复
2026-05-22 19:35:36 +08:00

2035 lines
129 KiB
HTML
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.

<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>流·Studio 设计系统 · V2.1 · Interactive</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
<!-- 引入项目共享 CSS · token + 100+ 组件类(1592 行) -->
<link rel="stylesheet" href="assets/restraint.css">
<style>
/* ============================================================
design-system.html · 演示辅助样式
============================================================
规则:
- token / 组件主类全部来自 restraint.css(看到的 = 生产用的)
- 本文件只补充"样板间专用"的展示工具类
- 任何在这里 inline 的样式都不应进入业务页面
============================================================ */
/* === 顶层布局 === */
.ds-layout { display: grid; grid-template-columns: 248px 1fr; min-height: 100vh; }
.ds-sidebar {
position: sticky; top: 0; height: 100vh;
padding: 40px 28px;
border-right: 1px solid var(--border-faint);
background: var(--surface);
overflow-y: auto;
}
.ds-sidebar h1 {
font-size: 17px; font-weight: 600; letter-spacing: -.01em;
margin: 0 0 6px; line-height: 1.4;
color: var(--accent-black);
}
.ds-sidebar .mono-sub {
font-family: var(--font-mono); font-size: 10.5px;
color: var(--black-alpha-48); letter-spacing: .04em;
margin-bottom: 32px;
}
.ds-nav { list-style: none; padding: 0; margin: 0; }
.ds-nav li { margin: 0; }
.ds-nav a {
display: block; padding: 8px 12px;
font-size: 13px; color: var(--black-alpha-64);
text-decoration: none; border-radius: var(--r-md);
transition: background var(--t-base), color var(--t-base);
}
.ds-nav a:hover { background: var(--black-alpha-4); color: var(--accent-black); }
.ds-nav a.active { background: var(--heat-12); color: var(--heat); }
.ds-nav .nav-group {
font-family: var(--font-mono); font-size: 10px;
letter-spacing: .06em; color: var(--black-alpha-32);
margin: 24px 0 8px; padding: 0 12px; text-transform: uppercase;
}
.ds-main { padding: 72px 80px 120px; max-width: 1280px; }
.ds-main > section { margin-bottom: 104px; scroll-margin-top: 32px; }
.ds-main > section:last-child { margin-bottom: 0; }
.section-head { margin-bottom: 44px; padding-bottom: 28px; border-bottom: 1px solid var(--border-faint); }
.section-head .mono-tag {
display: inline-block; font-family: var(--font-mono); font-size: 11px;
color: var(--black-alpha-48); letter-spacing: .06em; margin-bottom: 14px;
}
.section-head h2 {
font-size: 28px; font-weight: 500; letter-spacing: -.02em;
margin: 0 0 12px; line-height: 1.25;
color: var(--accent-black);
}
.section-head p {
font-size: 14px; color: var(--black-alpha-64);
margin: 0; max-width: 720px; line-height: 1.75;
}
.subsection { margin-bottom: 64px; }
.subsection h3 {
font-size: 16px; font-weight: 500; letter-spacing: -.01em;
margin: 0 0 22px; display: flex; align-items: center; gap: 12px;
line-height: 1.4; color: var(--accent-black);
}
.subsection h3 .mono-num {
font-family: var(--font-mono); font-size: 11px;
color: var(--black-alpha-32); font-weight: 400; letter-spacing: .04em;
}
.subsection p.lead {
font-size: 13px; color: var(--black-alpha-56);
margin: 0 0 22px; line-height: 1.8; max-width: 720px;
}
/* === Hero === */
.hero {
position: relative;
border: 1px solid var(--border-faint);
background: var(--surface);
border-radius: var(--r-md);
padding: 52px 56px; margin-bottom: 72px; overflow: hidden;
}
.hero .badge {
display: inline-flex; align-items: center; gap: 6px;
font-family: var(--font-mono); font-size: 11px; color: var(--heat);
background: var(--heat-12); border: 1px solid var(--heat-20);
border-radius: var(--r-pill); padding: 4px 11px; letter-spacing: .04em;
margin-bottom: 20px;
}
.hero h1 {
font-size: 36px; font-weight: 500; letter-spacing: -.024em;
margin: 0 0 14px; line-height: 1.2; color: var(--accent-black);
}
.hero p {
font-size: 15px; color: var(--black-alpha-64);
margin: 0; line-height: 1.75; max-width: 680px;
}
.hero .meta {
display: flex; gap: 16px; margin-top: 24px;
font-family: var(--font-mono); font-size: 11px;
color: var(--black-alpha-48); letter-spacing: .04em;
}
/* === 共用工具 === */
.mono { font-family: var(--font-mono); font-size: 11.5px; letter-spacing: .04em; color: var(--black-alpha-56); }
code.tk { font-family: var(--font-mono); font-size: 11.5px; padding: 1px 6px; border-radius: 4px; background: var(--background-lighter); color: var(--accent-black); border: 1px solid var(--border-faint); }
code.tk.heat { background: var(--heat-12); color: var(--heat); border-color: var(--heat-20); }
/* === Swatch grid (色块) === */
.swatch-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 14px; }
.swatch {
background: var(--surface); border-radius: var(--r-md); overflow: hidden;
cursor: pointer; transition: transform var(--t-fast);
}
.swatch:hover { transform: translateY(-1px); }
.swatch .chip { height: 76px; position: relative; border-bottom: 1px solid var(--border-faint); }
.swatch .chip.with-grid {
background-image:
linear-gradient(45deg, #dcdcdc 25%, transparent 25%),
linear-gradient(-45deg, #dcdcdc 25%, transparent 25%),
linear-gradient(45deg, transparent 75%, #dcdcdc 75%),
linear-gradient(-45deg, transparent 75%, #dcdcdc 75%);
background-color: #f5f5f5;
background-size: 12px 12px;
background-position: 0 0, 0 6px, 6px -6px, -6px 0;
}
.swatch .meta-row {
padding: 14px;
border: 1px solid var(--border-faint);
border-top: 0;
border-radius: 0 0 var(--r-md) var(--r-md);
}
.swatch .name { font-family: var(--font-mono); font-size: 11.5px; color: var(--accent-black); font-weight: 500; letter-spacing: .02em; line-height: 1.5; }
.swatch .val { font-family: var(--font-mono); font-size: 10.5px; color: var(--black-alpha-48); margin-top: 4px; letter-spacing: .04em; line-height: 1.5; }
.swatch .copy { font-family: var(--font-mono); font-size: 10px; color: var(--heat); display: none; margin-top: 3px; }
.swatch.copied .copy { display: block; }
/* === 字体 / 字号 / 字重展示 === */
.type-row {
display: grid; grid-template-columns: 220px 1fr; gap: 28px;
align-items: baseline; padding: 24px 0;
border-bottom: 1px solid var(--border-faint);
}
.type-row:last-child { border: 0; }
.type-row .meta-col {
font-family: var(--font-mono); font-size: 11px;
color: var(--black-alpha-48); letter-spacing: .04em; line-height: 1.65;
}
.type-row .meta-col strong {
display: block; color: var(--accent-black);
font-family: var(--font-sans); font-size: 13px; font-weight: 500;
margin-bottom: 6px; letter-spacing: 0;
}
.type-row .sample { color: var(--accent-black); }
/* === 圆角阶梯 === */
.radius-row { display: flex; gap: 16px; flex-wrap: wrap; align-items: flex-end; }
.radius-box { display: flex; flex-direction: column; align-items: center; gap: 6px; }
.radius-box .box {
background: var(--surface);
border: 1px solid var(--border-faint);
width: 88px; height: 88px;
display: grid; place-items: center;
}
.radius-box .lbl { font-family: var(--font-mono); font-size: 10.5px; color: var(--black-alpha-48); letter-spacing: .04em; }
.radius-box .px { font-family: var(--font-mono); font-size: 13px; color: var(--accent-black); font-weight: 500; }
/* === 间距示例 === */
.spacing-row { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 14px; }
.spacing-box {
display: flex; flex-direction: column; align-items: center; gap: 8px;
}
.spacing-bar {
background: var(--heat-12);
border-radius: 2px;
}
.spacing-box .lbl {
font-family: var(--font-mono); font-size: 10.5px;
color: var(--black-alpha-48); letter-spacing: .04em;
}
/* === 阴影 === */
.shadow-row { display: flex; gap: 24px; flex-wrap: wrap; margin-top: 14px; }
.shadow-box {
width: 200px; height: 80px;
background: var(--surface);
border-radius: var(--r-md);
display: grid; place-items: center;
font-family: var(--font-mono); font-size: 11px;
color: var(--black-alpha-56); letter-spacing: .04em;
}
.shadow-cta-demo {
background: var(--heat); color: #fff;
box-shadow:
inset 0 -4px 8px rgba(250, 93, 25, .20),
0 1px 1px rgba(250, 93, 25, .12),
0 2px 4px rgba(250, 93, 25, .10),
0 .5px .5px rgba(250, 93, 25, .16);
}
.shadow-floating-demo {
box-shadow: 0 4px 20px rgba(21, 20, 15, .06);
}
/* === Inside-border 演示 === */
.ib-demo {
display: flex; gap: 18px; flex-wrap: wrap;
}
.ib-box {
padding: 22px 26px; background: var(--surface);
border-radius: var(--r-md); position: relative;
font-family: var(--font-mono); font-size: 11px;
color: var(--black-alpha-56); letter-spacing: .04em;
width: 200px; text-align: center;
}
.ib-box::before {
content: ''; position: absolute; inset: 0;
border: 1px solid var(--black-alpha-12);
border-radius: inherit; pointer-events: none;
transition: opacity .2s, border-color .2s;
}
.ib-box:hover::before { opacity: 0; }
.ib-box:hover { background: var(--black-alpha-4); }
/* === Icons === */
.icon-row { display: flex; gap: 24px; align-items: flex-end; flex-wrap: wrap; }
.icon-cell { display: flex; flex-direction: column; align-items: center; gap: 8px; }
.icon-cell .ic {
display: grid; place-items: center;
color: var(--black-alpha-64);
background: var(--surface);
border: 1px solid var(--border-faint);
border-radius: var(--r-md);
}
.icon-cell svg { display: block; }
.icon-cell .lbl { font-family: var(--font-mono); font-size: 10px; color: var(--black-alpha-48); letter-spacing: .04em; }
.icon-color-row { display: flex; gap: 14px; align-items: center; flex-wrap: wrap; }
.icon-color-row .demo {
display: inline-flex; align-items: center; gap: 8px;
padding: 8px 14px; border-radius: var(--r-md);
border: 1px solid var(--border-faint);
background: var(--surface); font-size: 12.5px;
}
.icon-color-row .demo.primary { background: var(--heat); color: #fff; border-color: var(--heat); }
.icon-color-row .demo.disabled { color: var(--black-alpha-12); }
/* === 按钮演示状态 (覆盖 hover/active 视觉) === */
.btn-row { display: flex; gap: 14px; flex-wrap: wrap; align-items: center; margin-bottom: 20px; }
.btn-row .state-label {
font-family: var(--font-mono); font-size: 11px; color: var(--black-alpha-48);
letter-spacing: .04em; width: 96px; flex-shrink: 0;
}
.btn.demo-hover { background: var(--black-alpha-4); border-color: var(--black-alpha-24); }
.btn.demo-active { background: var(--black-alpha-7); transform: scale(.99); }
.btn-primary.demo-hover {
box-shadow:
inset 0 -4px 8px rgba(250, 93, 25, .20),
0 1px 1px rgba(250, 93, 25, .16),
0 4px 8px rgba(250, 93, 25, .20),
0 .5px .5px rgba(250, 93, 25, .16);
}
.btn-primary.demo-active {
transform: scale(.995);
box-shadow: inset 0 -4px 8px rgba(250, 93, 25, .28), 0 1px 2px rgba(250, 93, 25, .16);
}
.btn-ghost.demo-hover { background: var(--black-alpha-4); border-color: transparent; color: var(--accent-black); }
.btn-ghost.demo-active { background: var(--black-alpha-7); }
.btn.demo-focus { box-shadow: 0 0 0 2px var(--background-base), 0 0 0 4px var(--heat-40); }
/* === Pills 三级演示(原 restraint.css 只一档 · 这里展示分级) === */
.pill-l1 { height: 28px; padding: 0 12px; font-size: 13px; gap: 8px; }
.pill-l1 .dot { width: 8px; height: 8px; }
.pill-l2 { height: 22px; padding: 0 10px; font-size: 11.5px; gap: 6px; }
.pill-l2 .dot { width: 6px; height: 6px; }
.pill-l3 { height: 18px; padding: 0 8px; font-size: 10.5px; gap: 5px; }
.pill-l3 .dot { width: 5px; height: 5px; }
.pill-row { display: flex; gap: 14px; flex-wrap: wrap; align-items: center; }
/* === Inputs 包装 (focus / error 状态演示) === */
.field-row {
display: grid; grid-template-columns: 120px 1fr; gap: 20px;
align-items: center; margin-bottom: 18px;
}
.field-row .lbl { font-family: var(--font-mono); font-size: 11px; color: var(--black-alpha-48); letter-spacing: .04em; }
.input-wrap { position: relative; display: inline-block; max-width: 380px; width: 100%; }
.input-wrap .input { width: 100%; max-width: none; }
.input-wrap.is-error .input { background: var(--crimson-bg); border-color: var(--accent-crimson); box-shadow: inset 0 0 0 1px var(--crimson-bd); }
/* search wrap 复用 toolbar 的搜索风格 */
.search-demo { position: relative; max-width: 440px; }
.search-demo svg.ic-left {
position: absolute; left: 14px; top: 50%; transform: translateY(-50%);
color: var(--black-alpha-56);
pointer-events: none; z-index: 2; display: flex;
}
.search-demo .input { padding-left: 42px; padding-right: 64px; }
.search-demo .k {
position: absolute; right: 14px; top: 50%; transform: translateY(-50%);
font-family: var(--font-inter, 'Inter', sans-serif); font-weight: 700;
font-size: 11.5px; color: var(--black-alpha-56);
letter-spacing: .02em; pointer-events: none; z-index: 2; line-height: 1;
}
/* === Form controls (Checkbox/Radio/Switch) === */
.ck-row { display: flex; gap: 24px; align-items: center; flex-wrap: wrap; }
.ck, .rd, .sw { display: inline-flex; align-items: center; gap: 10px; cursor: pointer; user-select: none; font-size: 14px; color: var(--accent-black); }
.ck input, .rd input, .sw input { display: none; }
.ck .ck-box {
width: 16px; height: 16px; border-radius: var(--r-sm);
background: var(--surface); position: relative; flex-shrink: 0;
transition: background var(--t-base), box-shadow var(--t-base);
box-shadow: inset 0 0 0 1px var(--black-alpha-24);
}
.ck:hover .ck-box { box-shadow: inset 0 0 0 1px var(--black-alpha-48); }
.ck input:checked + .ck-box {
background: var(--heat); box-shadow: inset 0 0 0 1px var(--heat);
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E");
background-repeat: no-repeat; background-position: center; background-size: 12px 12px;
}
.ck.is-indeterminate .ck-box {
background: var(--heat); box-shadow: inset 0 0 0 1px var(--heat);
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h14'/%3E%3C/svg%3E");
background-repeat: no-repeat; background-position: center; background-size: 12px 12px;
}
.ck.is-disabled { opacity: .6; cursor: not-allowed; }
.ck.is-disabled .ck-box { background: var(--background-lighter); box-shadow: inset 0 0 0 1px var(--black-alpha-12); }
.rd .rd-box {
width: 16px; height: 16px; border-radius: 50%;
background: var(--surface); position: relative; flex-shrink: 0;
box-shadow: inset 0 0 0 1px var(--black-alpha-24);
transition: box-shadow var(--t-base);
}
.rd:hover .rd-box { box-shadow: inset 0 0 0 1px var(--black-alpha-48); }
.rd input:checked + .rd-box { box-shadow: inset 0 0 0 1px var(--heat); }
.rd input:checked + .rd-box::after { content: ''; position: absolute; inset: 4px; border-radius: 50%; background: var(--heat); }
.sw .sw-box {
width: 28px; height: 16px; border-radius: var(--r-pill);
background: var(--black-alpha-12); position: relative; flex-shrink: 0;
transition: background var(--t-base);
}
.sw .sw-box::after {
content: ''; position: absolute; left: 2px; top: 2px;
width: 12px; height: 12px; border-radius: 50%; background: #fff;
transition: left var(--t-base);
box-shadow: 0 1px 2px rgba(21, 20, 15, .12);
}
.sw input:checked + .sw-box { background: var(--heat); }
.sw input:checked + .sw-box::after { left: 14px; }
.sw.is-disabled { opacity: .5; cursor: not-allowed; }
/* === Tabs (sub) === */
.ds-tabs { border-bottom: 1px solid var(--border-faint); display: flex; gap: 0; margin-bottom: 16px; }
.ds-tab {
position: relative; background: none; border: 0; cursor: pointer;
height: 36px; padding: 0 14px;
font-family: inherit; font-size: 13px; font-weight: 500;
color: var(--black-alpha-56);
transition: color var(--t-base), background var(--t-base);
border-radius: var(--r-md) var(--r-md) 0 0;
}
.ds-tab:hover { color: var(--accent-black); background: var(--black-alpha-4); }
.ds-tab.is-active { color: var(--accent-black); }
.ds-tab.is-active::after {
content: ''; position: absolute; left: 0; right: 0; bottom: -1px;
height: 2px; background: var(--heat);
}
.ds-subtabs { display: flex; gap: 0; margin-bottom: 24px; }
.ds-subtab {
display: inline-flex; align-items: center; gap: 6px;
background: none; border: 0; cursor: pointer;
height: 28px; padding: 0 10px;
font-family: inherit; font-size: 12px; font-weight: 500;
color: var(--black-alpha-56);
transition: color var(--t-base); border-radius: var(--r-md);
}
.ds-subtab svg { opacity: .6; transition: opacity var(--t-base); }
.ds-subtab:hover { color: var(--accent-black); }
.ds-subtab.is-active { color: var(--accent-black); }
.ds-subtab.is-active svg { opacity: 1; color: var(--heat); }
.ds-subtab-divider { width: 1px; height: 12px; background: var(--black-alpha-7); margin: 0 4px; align-self: center; }
/* === KPI stats demo === */
.demo-stats {
background: var(--surface); border: 1px solid var(--border-faint);
border-radius: var(--r-md);
display: grid; grid-template-columns: repeat(4, 1fr);
position: relative;
}
.demo-stats .cell { padding: 28px 30px; border-right: 1px solid var(--border-faint); }
.demo-stats .cell:last-child { border-right: 0; }
.demo-stats .lbl-row { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; }
.demo-stats .lbl { font-family: var(--font-mono); font-size: 11px; color: var(--black-alpha-48); letter-spacing: .06em; text-transform: uppercase; }
.demo-stats .num { font-size: 32px; font-weight: 500; letter-spacing: -.02em; font-variant-numeric: tabular-nums; line-height: 1.1; color: var(--accent-black); }
.demo-stats .num small { font-size: 15px; color: var(--black-alpha-48); font-weight: 400; }
.demo-stats .delta { font-family: var(--font-mono); font-size: 11.5px; color: var(--black-alpha-48); margin-top: 10px; }
.demo-stats .delta .up { color: var(--accent-forest); }
/* === List row demo (复用 restraint.css 的 .list-row 但 inline 一些 demo) === */
.list-card-demo {
background: var(--surface); border: 1px solid var(--border-faint);
border-radius: var(--r-md); overflow: hidden;
}
.list-row-demo {
display: grid; grid-template-columns: 56px 1fr auto auto auto; gap: 22px;
align-items: center; padding: 20px 24px;
border-bottom: 1px solid var(--border-faint);
transition: background var(--t-base);
}
.list-row-demo:last-child { border-bottom: 0; }
.list-row-demo:hover { background: var(--black-alpha-4); }
.list-row-demo .thumb {
width: 56px; height: 72px; background: var(--background-lighter);
border: 1px solid var(--border-faint); border-radius: var(--r-md);
display: grid; place-items: center;
font-family: var(--font-mono); font-size: 10.5px; color: var(--black-alpha-48); letter-spacing: .04em;
}
.list-row-demo .meta .ti { font-size: 14px; font-weight: 500; color: var(--accent-black); margin-bottom: 6px; line-height: 1.4; }
.list-row-demo .meta .sub { font-family: var(--font-mono); font-size: 11.5px; color: var(--black-alpha-48); letter-spacing: .02em; line-height: 1.5; }
/* === Tip === */
.tip-demo {
background: var(--surface);
border: 1px dashed var(--border-loud);
border-radius: var(--r-md);
padding: 20px 24px;
max-width: 560px;
}
.tip-demo .head { font-size: 14px; font-weight: 500; margin-bottom: 10px; color: var(--accent-black); line-height: 1.4; }
.tip-demo .body { font-size: 13px; color: var(--black-alpha-64); line-height: 1.8; }
.tip-demo .mono-code {
display: inline-block; padding: 2px 8px;
background: var(--heat-12); color: var(--heat);
font-family: var(--font-mono); font-size: 11.5px;
border-radius: var(--r-sm); letter-spacing: .04em;
}
/* === Container demo (装订线) === */
.container-demo {
position: relative; margin: 36px auto 24px;
max-width: 720px; padding: 48px 56px;
background: var(--background-base);
border-left: 1px solid var(--border-faint);
border-right: 1px solid var(--border-faint);
}
.container-demo .corner { position: absolute; width: 22px; height: 21px; color: var(--border-muted); }
.container-demo .corner.tl { top: -10.5px; left: -11px; }
.container-demo .corner.tr { top: -10.5px; right: -11px; transform: scaleX(-1); }
.container-demo .corner.bl { bottom: -10.5px; left: -11px; transform: scaleY(-1); }
.container-demo .corner.br { bottom: -10.5px; right: -11px; transform: scale(-1, -1); }
.container-demo .inner {
background: var(--surface); border: 1px solid var(--border-faint);
border-radius: var(--r-md); padding: 24px;
font-size: 13px; color: var(--black-alpha-72); text-align: center;
}
/* === Mono decor === */
.mono-sample-row { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; margin-bottom: 10px; }
.mono-tag-sample {
font-family: var(--font-mono); font-size: 11px;
color: var(--black-alpha-48); background: var(--background-lighter);
border: 1px solid var(--border-faint);
border-radius: var(--r-sm); padding: 3px 8px; letter-spacing: .04em;
}
.mono-tag-sample.heat { color: var(--heat); background: var(--heat-12); border-color: var(--heat-20); }
/* === Page layouts (§6 · ASCII art) === */
.layout-card {
background: var(--surface); border: 1px solid var(--border-faint);
border-radius: var(--r-md); padding: 24px 28px;
margin-bottom: 18px;
}
.layout-card .h {
display: flex; align-items: center; gap: 10px; margin-bottom: 12px;
}
.layout-card .h .tag {
font-family: var(--font-mono); font-size: 10.5px;
color: var(--heat); background: var(--heat-12);
border: 1px solid var(--heat-20);
border-radius: var(--r-sm); padding: 2px 8px; letter-spacing: .04em;
font-weight: 500;
}
.layout-card .h .ti { font-size: 14px; font-weight: 500; color: var(--accent-black); }
.layout-card .desc { font-size: 13px; color: var(--black-alpha-64); line-height: 1.7; margin-bottom: 14px; }
.layout-card pre.ascii {
background: var(--background-lighter);
border: 1px solid var(--border-faint);
border-radius: var(--r-sm);
padding: 14px 18px;
font-family: var(--font-mono); font-size: 11.5px;
color: var(--black-alpha-72); line-height: 1.55;
letter-spacing: .02em; overflow-x: auto; white-space: pre;
margin: 0 0 12px;
}
.layout-card .pages {
font-family: var(--font-mono); font-size: 11px;
color: var(--black-alpha-48); letter-spacing: .04em;
}
.layout-card .pages strong { color: var(--accent-black); font-weight: 500; font-family: var(--font-sans); }
/* === Do/Don't grid === */
.dodont-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.dodont { padding: 16px 18px; border-radius: var(--r-md); border: 1px solid; }
.dodont .head {
font-family: var(--font-mono); font-size: 10.5px; letter-spacing: .04em;
margin-bottom: 10px; display: inline-block; padding: 1px 8px;
border-radius: var(--r-sm); color: #fff;
}
.dodont.do { border-color: var(--forest-bd); background: var(--forest-bg); }
.dodont.do .head { background: var(--accent-forest); }
.dodont.dont { border-color: var(--crimson-bd); background: var(--crimson-bg); }
.dodont.dont .head { background: var(--accent-crimson); }
.dodont .body { font-size: 12.5px; line-height: 1.7; color: var(--black-alpha-72); }
.dont-list-item {
display: flex; align-items: flex-start; gap: 10px;
font-size: 12.5px; line-height: 1.7; color: var(--black-alpha-72);
padding: 8px 0; border-bottom: 1px solid var(--border-faint);
}
.dont-list-item:last-child { border-bottom: 0; }
.dont-list-item .x { color: var(--accent-crimson); font-family: var(--font-mono); flex-shrink: 0; margin-top: 2px; }
/* === Audit table (§7 待统一清单) === */
.audit-table {
width: 100%; border-collapse: collapse;
background: var(--surface);
border: 1px solid var(--border-faint);
border-radius: var(--r-md); overflow: hidden;
margin-bottom: 22px;
}
.audit-table th, .audit-table td {
padding: 12px 16px; text-align: left;
font-size: 12.5px; color: var(--accent-black);
border-bottom: 1px solid var(--border-faint);
vertical-align: top;
}
.audit-table th {
font-family: var(--font-mono); font-size: 11px;
font-weight: 500; color: var(--black-alpha-56);
letter-spacing: .04em; text-transform: uppercase;
background: var(--black-alpha-3);
}
.audit-table tbody tr:last-child td { border-bottom: 0; }
.audit-table td:first-child { font-family: var(--font-mono); font-size: 12px; color: var(--heat); width: 32px; }
.audit-table td.problem { color: var(--accent-crimson); font-weight: 500; }
.audit-table td.now { font-family: var(--font-mono); font-size: 11.5px; color: var(--black-alpha-64); }
.audit-table td.should { font-weight: 500; color: var(--accent-forest); }
.audit-section-label {
display: inline-block;
font-family: var(--font-mono); font-size: 11px;
padding: 3px 10px; border-radius: var(--r-sm);
letter-spacing: .04em; margin-bottom: 10px;
}
.audit-section-label.hi { background: var(--crimson-bg); color: var(--accent-crimson); border: 1px solid var(--crimson-bd); }
.audit-section-label.mid { background: var(--honey-bg); color: var(--accent-honey); border: 1px solid var(--honey-bd); }
.audit-section-label.lo { background: var(--background-lighter); color: var(--black-alpha-56); border: 1px solid var(--border-faint); }
/* === Checklist === */
.cl-card {
background: var(--surface); border: 1px solid var(--border-faint);
border-radius: var(--r-md); padding: 22px 26px;
margin-bottom: 16px;
}
.cl-card .ch {
display: flex; align-items: center; gap: 10px; margin-bottom: 14px;
}
.cl-card .ch .ti { font-size: 14px; font-weight: 500; color: var(--accent-black); }
.cl-card .ch .stage {
font-family: var(--font-mono); font-size: 10.5px;
color: var(--heat); background: var(--heat-12);
border: 1px solid var(--heat-20);
border-radius: var(--r-sm); padding: 2px 8px; letter-spacing: .04em;
font-weight: 500;
}
.cl-list { list-style: none; padding: 0; margin: 0; }
.cl-list li {
display: flex; align-items: flex-start; gap: 10px;
padding: 7px 0; font-size: 13px; color: var(--accent-black); line-height: 1.6;
}
.cl-list li .mk {
width: 16px; height: 16px; border-radius: var(--r-sm);
border: 1px solid var(--black-alpha-24);
background: var(--surface); flex-shrink: 0; margin-top: 2px;
display: grid; place-items: center;
}
.cl-list li .mk svg { width: 10px; height: 10px; color: var(--heat); opacity: 0; }
/* === Toast container === */
.toast-stack { position: fixed; right: 24px; bottom: 24px; display: flex; flex-direction: column; gap: 10px; z-index: 1000; pointer-events: none; }
.toast-stack .toast { pointer-events: auto; animation: toastIn 300ms cubic-bezier(0.34,1.56,0.64,1) both; transform: translateX(0); }
.toast-stack .toast.is-leave { animation: toastOut 200ms forwards; }
@keyframes toastIn { from { transform: translateX(420px); opacity: 0; } to { transform: translateX(0); opacity: 1; } }
@keyframes toastOut { to { transform: translateX(420px); opacity: 0; } }
/* === Codebox === */
.codebox {
background: var(--background-lighter);
border: 1px solid var(--border-faint);
border-radius: var(--r-md);
padding: 12px 14px; font-family: var(--font-mono);
font-size: 11.5px; line-height: 1.65;
color: var(--black-alpha-88); overflow-x: auto;
letter-spacing: .02em; white-space: pre; margin: 0;
}
/* === Responsive === */
@media (max-width: 980px) {
.ds-layout { grid-template-columns: 1fr; }
.ds-sidebar { position: relative; height: auto; border-right: 0; border-bottom: 1px solid var(--border-faint); }
.ds-main { padding: 32px 24px 64px; }
.demo-stats { grid-template-columns: repeat(2, 1fr); }
.demo-stats .cell:nth-child(2) { border-right: 0; }
.demo-stats .cell:nth-child(1), .demo-stats .cell:nth-child(2) { border-bottom: 1px solid var(--border-faint); }
.dodont-grid { grid-template-columns: 1fr; }
}
</style>
</head>
<body>
<div class="ds-layout">
<!-- ============ SIDEBAR ============ -->
<aside class="ds-sidebar">
<h1>流·Studio<br>设计系统</h1>
<div class="mono-sub">// V2.1 · 2026-05-22 · INTERACTIVE</div>
<ul class="ds-nav">
<li class="nav-group">// FOUNDATION</li>
<li><a href="#philosophy">§1 设计哲学</a></li>
<li><a href="#tokens">§2.1 色彩 Tokens</a></li>
<li><a href="#alpha">§2.2 Black-Alpha</a></li>
<li><a href="#type">§2.5 字体系统</a></li>
<li><a href="#typescale">§2.6 字号阶梯</a></li>
<li><a href="#radius">§2.7 圆角</a></li>
<li><a href="#spacing">§2.8 间距</a></li>
<li><a href="#shadow">§2.9 阴影</a></li>
<li><a href="#inside-border">§2.10 inside-border</a></li>
<li class="nav-group">// SKELETON</li>
<li><a href="#skeleton">§3 页面骨架</a></li>
<li><a href="#container">§3.4 主容器装订线</a></li>
<li class="nav-group">// COMPONENTS</li>
<li><a href="#icons">§4.12 Icon 系统</a></li>
<li><a href="#buttons">§4.1 按钮</a></li>
<li><a href="#pills">§4.2 胶囊 Pills</a></li>
<li><a href="#inputs">§4.3 输入框</a></li>
<li><a href="#form-controls">§4.4 表单控件</a></li>
<li><a href="#stats">§4.5 KPI 统计</a></li>
<li><a href="#progress">§4.6 进度条</a></li>
<li><a href="#list">§4.7 列表行</a></li>
<li><a href="#tabs">§4.8 Tab</a></li>
<li><a href="#cards">§4.10 卡片</a></li>
<li><a href="#tip">§4.10 提示框</a></li>
<li><a href="#modal">§4.11 Modal</a></li>
<li><a href="#toast">§4.11 Toast</a></li>
<li class="nav-group">// SIGNATURE</li>
<li><a href="#mono-decor">§5 Mono 装饰</a></li>
<li class="nav-group">// LAYOUT</li>
<li><a href="#layouts">§6 五种布局模式</a></li>
<li class="nav-group">// GOVERNANCE</li>
<li><a href="#audit">§7 待统一清单 ★</a></li>
<li><a href="#dont">§8 Don't List</a></li>
<li><a href="#checklist">§9 Checklist</a></li>
</ul>
</aside>
<!-- ============ MAIN ============ -->
<main class="ds-main">
<!-- HERO -->
<div class="hero">
<span class="badge">// V2.1 · INTERACTIVE · 2026-05-22</span>
<h1>流·Studio 设计系统</h1>
<p>本页是 <code class="tk">design.md</code> 的可视化样板间。所有 token / 组件均来自 <code class="tk">assets/restraint.css</code> —— <strong style="color:var(--accent-black)">看到的就是页面用的</strong>。点击色块复制 token,hover / 点击组件看真实交互反馈。</p>
<div class="meta">
<span>[ Restraint · V2.1 ]</span>
<span>·</span>
<span>// 基于 design.md 整合定稿</span>
</div>
</div>
<!-- =========================================== §1 设计哲学 =========================================== -->
<section id="philosophy">
<div class="section-head">
<span class="mono-tag">// §1 · PHILOSOPHY</span>
<h2>设计哲学</h2>
<p>一句话:<strong style="color:var(--accent-black)">一台精密设备的工作面板</strong>。克制 + 单橙锚点 + 图纸装订线 + Mono 装饰。</p>
</div>
<div class="subsection">
<h3>三条铁律 <span class="mono-num">// 不可妥协</span></h3>
<div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:14px">
<div style="padding:22px 26px;border:1px solid var(--border-faint);border-radius:8px;background:var(--surface)">
<div style="font-family:var(--font-mono);font-size:10.5px;color:var(--heat);letter-spacing:.04em;margin-bottom:10px">// RULE 1</div>
<div style="font-size:16px;font-weight:500;color:var(--accent-black);margin-bottom:8px">克制大于装饰</div>
<div style="font-size:13px;color:var(--black-alpha-64);line-height:1.7">留白 &gt; 容器 &gt; 内容,大量空气感。padding 不确定选 24,margin 不确定选 64。</div>
</div>
<div style="padding:22px 26px;border:1px solid var(--border-faint);border-radius:8px;background:var(--surface)">
<div style="font-family:var(--font-mono);font-size:10.5px;color:var(--heat);letter-spacing:.04em;margin-bottom:10px">// RULE 2</div>
<div style="font-size:16px;font-weight:500;color:var(--accent-black);margin-bottom:8px">单色锚点</div>
<div style="font-size:13px;color:var(--black-alpha-64);line-height:1.7">全场只有一个 accent(橙)· 只用于 CTA / 关键状态 / 强调单词。其他颜色仅做语义信号。</div>
</div>
<div style="padding:22px 26px;border:1px solid var(--border-faint);border-radius:8px;background:var(--surface)">
<div style="font-family:var(--font-mono);font-size:10.5px;color:var(--heat);letter-spacing:.04em;margin-bottom:10px">// RULE 3</div>
<div style="font-size:16px;font-weight:500;color:var(--accent-black);margin-bottom:8px">结构清晰可见</div>
<div style="font-size:13px;color:var(--black-alpha-64);line-height:1.7">用 1 px 边框 + 8 px 圆角 + 准星 + 装订线 + mono 标签暴露"图纸感",而非阴影/渐变隐藏结构。</div>
</div>
</div>
</div>
<div class="subsection">
<h3>核心签名 <span class="mono-num">// 4 个不能丢</span></h3>
<ul class="cl-list">
<li><span class="mk" style="background:var(--heat);border-color:var(--heat)"><svg viewBox="0 0 24 24" fill="none" stroke="#fff" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" style="opacity:1"><path d="M20 6 9 17l-5-5"/></svg></span>主橙 <code class="tk heat">#fa5d19</code>(Firecrawl 实测)+ 单 hue alpha 阶梯</li>
<li><span class="mk" style="background:var(--heat);border-color:var(--heat)"><svg viewBox="0 0 24 24" fill="none" stroke="#fff" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" style="opacity:1"><path d="M20 6 9 17l-5-5"/></svg></span>全场 8 px 圆角(Pill 999 例外)</li>
<li><span class="mk" style="background:var(--heat);border-color:var(--heat)"><svg viewBox="0 0 24 24" fill="none" stroke="#fff" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" style="opacity:1"><path d="M20 6 9 17l-5-5"/></svg></span>主容器左右装订线 + 四角准星</li>
<li><span class="mk" style="background:var(--heat);border-color:var(--heat)"><svg viewBox="0 0 24 24" fill="none" stroke="#fff" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" style="opacity:1"><path d="M20 6 9 17l-5-5"/></svg></span>Mono 装饰 <code class="tk">[ 200 OK ]</code> <code class="tk">// 05.14</code> <code class="tk">[ /v2 ]</code>(品牌签名 · Firecrawl 没有)</li>
</ul>
</div>
</section>
<!-- =========================================== §2.1 色彩 Tokens =========================================== -->
<section id="tokens">
<div class="section-head">
<span class="mono-tag">// §2.1 · COLOR TOKENS · FIRECRAWL-ALIGNED</span>
<h2>色彩系统</h2>
<p>冷灰底 · 单 hue 橙 · 5 色信号点。<strong style="color:var(--accent-black)">点击色块复制 token 名。</strong>禁止创建新色值,所有颜色必须用以下 token。</p>
</div>
<div class="subsection">
<h3>表面 / 背景 <span class="mono-num">// 4 档 · 冷灰无色相</span></h3>
<div class="swatch-grid" data-copy-grid>
<div class="swatch" data-hex="--background-base"><div class="chip" style="background:#f9f9f9"></div><div class="meta-row"><div class="name">--background-base</div><div class="val">#f9f9f9 · 页面底 ★</div><div class="copy">copied</div></div></div>
<div class="swatch" data-hex="--background-lighter"><div class="chip" style="background:#fbfbfb"></div><div class="meta-row"><div class="name">--background-lighter</div><div class="val">#fbfbfb · 容器底</div><div class="copy">copied</div></div></div>
<div class="swatch" data-hex="--surface"><div class="chip with-grid" style="background:#ffffff"></div><div class="meta-row"><div class="name">--surface</div><div class="val">#ffffff · 卡片 ★</div><div class="copy">copied</div></div></div>
<div class="swatch" data-hex="--surface-raised"><div class="chip with-grid" style="background:#ffffff"></div><div class="meta-row"><div class="name">--surface-raised</div><div class="val">#ffffff · Modal</div><div class="copy">copied</div></div></div>
</div>
</div>
<div class="subsection">
<h3>边框 <span class="mono-num">// 3 档 · 差距极小靠语义</span></h3>
<p class="lead">3 档相差只 12 色阶,肉眼几乎看不出。<strong>用语义,不用视觉对比</strong> —— 80% 场景用 <code class="tk">--border-faint</code></p>
<div class="swatch-grid" data-copy-grid>
<div class="swatch" data-hex="--border-faint"><div class="chip" style="background:#ededed"></div><div class="meta-row"><div class="name">--border-faint</div><div class="val">#ededed · 默认 ★ 80%</div><div class="copy">copied</div></div></div>
<div class="swatch" data-hex="--border-muted"><div class="chip" style="background:#e8e8e8"></div><div class="meta-row"><div class="name">--border-muted</div><div class="val">#e8e8e8 · 略深</div><div class="copy">copied</div></div></div>
<div class="swatch" data-hex="--border-loud"><div class="chip" style="background:#e6e6e6"></div><div class="meta-row"><div class="name">--border-loud</div><div class="val">#e6e6e6 · 强分隔</div><div class="copy">copied</div></div></div>
</div>
</div>
<div class="subsection">
<h3>主橙 Heat <span class="mono-num">// 单 hue #fa5d19 + 8 档 alpha</span></h3>
<p class="lead"><strong>全靠 alpha 叠加,绝不换 hue。</strong>hover 不切换深橙,而是用 90% / 16% 这些档位组合。</p>
<div class="swatch-grid" data-copy-grid>
<div class="swatch" data-hex="--heat"><div class="chip" style="background:#fa5d19"></div><div class="meta-row"><div class="name">--heat</div><div class="val">100% · CTA ★</div><div class="copy">copied</div></div></div>
<div class="swatch" data-hex="--heat-90"><div class="chip" style="background:rgba(250,93,25,.90)"></div><div class="meta-row"><div class="name">--heat-90</div><div class="val">90% · hover</div><div class="copy">copied</div></div></div>
<div class="swatch" data-hex="--heat-40"><div class="chip" style="background:rgba(250,93,25,.40)"></div><div class="meta-row"><div class="name">--heat-40</div><div class="val">40% · ring / edge</div><div class="copy">copied</div></div></div>
<div class="swatch" data-hex="--heat-20"><div class="chip" style="background:rgba(250,93,25,.20)"></div><div class="meta-row"><div class="name">--heat-20</div><div class="val">20% · pill border / selection</div><div class="copy">copied</div></div></div>
<div class="swatch" data-hex="--heat-16"><div class="chip" style="background:rgba(250,93,25,.16)"></div><div class="meta-row"><div class="name">--heat-16</div><div class="val">16% · hover bg</div><div class="copy">copied</div></div></div>
<div class="swatch" data-hex="--heat-12"><div class="chip" style="background:rgba(250,93,25,.12)"></div><div class="meta-row"><div class="name">--heat-12</div><div class="val">12% · tint bg ★</div><div class="copy">copied</div></div></div>
<div class="swatch" data-hex="--heat-8"><div class="chip" style="background:rgba(250,93,25,.08)"></div><div class="meta-row"><div class="name">--heat-8</div><div class="val">8%</div><div class="copy">copied</div></div></div>
<div class="swatch" data-hex="--heat-4"><div class="chip" style="background:rgba(250,93,25,.04)"></div><div class="meta-row"><div class="name">--heat-4</div><div class="val">4% · 极弱</div><div class="copy">copied</div></div></div>
</div>
</div>
<div class="subsection">
<h3>Accent 多彩点 <span class="mono-num">// 5 色信号 · 限定语义场景</span></h3>
<p class="lead"><strong>只用于语义信号</strong>(代码高亮 / info / 状态色),<strong>禁止做大面积装饰</strong> —— 全场依然只有橙色一个 accent。</p>
<div class="swatch-grid" data-copy-grid>
<div class="swatch" data-hex="--accent-black"><div class="chip" style="background:#262626"></div><div class="meta-row"><div class="name">--accent-black</div><div class="val">#262626 · 主前景 ★</div><div class="copy">copied</div></div></div>
<div class="swatch" data-hex="--accent-white"><div class="chip with-grid" style="background:#ffffff"></div><div class="meta-row"><div class="name">--accent-white</div><div class="val">#ffffff · 反色文字</div><div class="copy">copied</div></div></div>
<div class="swatch" data-hex="--accent-amethyst"><div class="chip" style="background:#9061ff"></div><div class="meta-row"><div class="name">--accent-amethyst</div><div class="val">#9061ff · 紫 / code</div><div class="copy">copied</div></div></div>
<div class="swatch" data-hex="--accent-bluetron"><div class="chip" style="background:#2a6dfb"></div><div class="meta-row"><div class="name">--accent-bluetron</div><div class="val">#2a6dfb · 蓝 / info</div><div class="copy">copied</div></div></div>
<div class="swatch" data-hex="--accent-crimson"><div class="chip" style="background:#eb3424"></div><div class="meta-row"><div class="name">--accent-crimson</div><div class="val">#eb3424 · 红 / error ★</div><div class="copy">copied</div></div></div>
<div class="swatch" data-hex="--accent-forest"><div class="chip" style="background:#42c366"></div><div class="meta-row"><div class="name">--accent-forest</div><div class="val">#42c366 · 绿 / success ★</div><div class="copy">copied</div></div></div>
<div class="swatch" data-hex="--accent-honey"><div class="chip" style="background:#ecb730"></div><div class="meta-row"><div class="name">--accent-honey</div><div class="val">#ecb730 · 黄 / warning</div><div class="copy">copied</div></div></div>
</div>
</div>
<div class="subsection">
<h3>状态色配套(底 / 边) <span class="mono-num">// 8% / 20% alpha</span></h3>
<div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:14px">
<div style="padding:16px 18px;background:var(--forest-bg);border:1px solid var(--forest-bd);border-radius:8px;color:var(--accent-forest);font-size:13px;font-weight:500"><span class="dot" style="display:inline-block;width:6px;height:6px;border-radius:50%;background:currentColor;margin-right:8px"></span>成功 · forest</div>
<div style="padding:16px 18px;background:var(--crimson-bg);border:1px solid var(--crimson-bd);border-radius:8px;color:var(--accent-crimson);font-size:13px;font-weight:500"><span class="dot" style="display:inline-block;width:6px;height:6px;border-radius:50%;background:currentColor;margin-right:8px"></span>失败 · crimson</div>
<div style="padding:16px 18px;background:var(--heat-12);border:1px solid var(--heat-20);border-radius:8px;color:var(--heat);font-size:13px;font-weight:500"><span class="dot" style="display:inline-block;width:6px;height:6px;border-radius:50%;background:currentColor;margin-right:8px"></span>信息 · heat</div>
<div style="padding:16px 18px;background:var(--honey-bg);border:1px solid var(--honey-bd);border-radius:8px;color:var(--accent-honey);font-size:13px;font-weight:500"><span class="dot" style="display:inline-block;width:6px;height:6px;border-radius:50%;background:currentColor;margin-right:8px"></span>警告 · honey</div>
</div>
</div>
<div class="subsection">
<h3>Selection · Firecrawl 签名细节</h3>
<p class="lead">页面任何文字选中时,底色 <code class="tk heat">--heat-20</code> + 字色 <code class="tk heat">--heat</code><strong>试选下面这行字看效果:</strong></p>
<p style="font-size:14px;line-height:1.7;padding:14px 18px;border:1px solid var(--border-faint);border-radius:8px;background:var(--surface);color:var(--accent-black)">本月营收 ¥327,400 较上月增长 33%,有 5 个项目处于"生成中"状态。其中 2 个需要重新调整模特模板。</p>
</div>
</section>
<!-- =========================================== §2.2 Black-Alpha =========================================== -->
<section id="alpha">
<div class="section-head">
<span class="mono-tag">// §2.2 · BLACK-ALPHA · 20 档核心工具尺</span>
<h2>Black-Alpha 阶梯</h2>
<p><strong>日常用得最多的 token。</strong>024% 用 <code class="tk">rgba(0,0,0,...)</code>;32% 起换 <code class="tk">rgba(38,38,38,...)</code>(避免叠出"灰中带蓝")。</p>
</div>
<div class="subsection">
<div class="swatch-grid" data-copy-grid>
<div class="swatch" data-hex="--black-alpha-1"><div class="chip with-grid"><div style="position:absolute;inset:0;background:rgba(0,0,0,.01)"></div></div><div class="meta-row"><div class="name">--black-alpha-1</div><div class="val">1%</div><div class="copy">copied</div></div></div>
<div class="swatch" data-hex="--black-alpha-2"><div class="chip with-grid"><div style="position:absolute;inset:0;background:rgba(0,0,0,.02)"></div></div><div class="meta-row"><div class="name">--black-alpha-2</div><div class="val">2%</div><div class="copy">copied</div></div></div>
<div class="swatch" data-hex="--black-alpha-3"><div class="chip with-grid"><div style="position:absolute;inset:0;background:rgba(0,0,0,.03)"></div></div><div class="meta-row"><div class="name">--black-alpha-3</div><div class="val">3%</div><div class="copy">copied</div></div></div>
<div class="swatch" data-hex="--black-alpha-4"><div class="chip with-grid"><div style="position:absolute;inset:0;background:rgba(0,0,0,.04)"></div></div><div class="meta-row"><div class="name">--black-alpha-4</div><div class="val">4% · hover bg ★</div><div class="copy">copied</div></div></div>
<div class="swatch" data-hex="--black-alpha-5"><div class="chip with-grid"><div style="position:absolute;inset:0;background:rgba(0,0,0,.05)"></div></div><div class="meta-row"><div class="name">--black-alpha-5</div><div class="val">5% · disabled bg</div><div class="copy">copied</div></div></div>
<div class="swatch" data-hex="--black-alpha-7"><div class="chip with-grid"><div style="position:absolute;inset:0;background:rgba(0,0,0,.07)"></div></div><div class="meta-row"><div class="name">--black-alpha-7</div><div class="val">7% · active bg ★</div><div class="copy">copied</div></div></div>
<div class="swatch" data-hex="--black-alpha-8"><div class="chip with-grid"><div style="position:absolute;inset:0;background:rgba(0,0,0,.08)"></div></div><div class="meta-row"><div class="name">--black-alpha-8</div><div class="val">8% · prog 未开始</div><div class="copy">copied</div></div></div>
<div class="swatch" data-hex="--black-alpha-12"><div class="chip with-grid"><div style="position:absolute;inset:0;background:rgba(0,0,0,.12)"></div></div><div class="meta-row"><div class="name">--black-alpha-12</div><div class="val">12% · inside-border ★</div><div class="copy">copied</div></div></div>
<div class="swatch" data-hex="--black-alpha-24"><div class="chip with-grid"><div style="position:absolute;inset:0;background:rgba(0,0,0,.24)"></div></div><div class="meta-row"><div class="name">--black-alpha-24</div><div class="val">24% · input hover</div><div class="copy">copied</div></div></div>
<div class="swatch" data-hex="--black-alpha-32"><div class="chip" style="background:rgba(38,38,38,.32)"></div><div class="meta-row"><div class="name">--black-alpha-32</div><div class="val">32% · base 切换 →</div><div class="copy">copied</div></div></div>
<div class="swatch" data-hex="--black-alpha-48"><div class="chip" style="background:rgba(38,38,38,.48)"></div><div class="meta-row"><div class="name">--black-alpha-48</div><div class="val">48% · 占位字色 ★</div><div class="copy">copied</div></div></div>
<div class="swatch" data-hex="--black-alpha-56"><div class="chip" style="background:rgba(38,38,38,.56)"></div><div class="meta-row"><div class="name">--black-alpha-56</div><div class="val">56% · 次级文字 ★</div><div class="copy">copied</div></div></div>
<div class="swatch" data-hex="--black-alpha-64"><div class="chip" style="background:rgba(38,38,38,.64)"></div><div class="meta-row"><div class="name">--black-alpha-64</div><div class="val">64% · 描述</div><div class="copy">copied</div></div></div>
<div class="swatch" data-hex="--black-alpha-72"><div class="chip" style="background:rgba(38,38,38,.72)"></div><div class="meta-row"><div class="name">--black-alpha-72</div><div class="val">72%</div><div class="copy">copied</div></div></div>
<div class="swatch" data-hex="--black-alpha-88"><div class="chip" style="background:rgba(38,38,38,.88)"></div><div class="meta-row"><div class="name">--black-alpha-88</div><div class="val">88% · 近主前景</div><div class="copy">copied</div></div></div>
</div>
</div>
</section>
<!-- =========================================== §2.5 字体系统 =========================================== -->
<section id="type">
<div class="section-head">
<span class="mono-tag">// §2.5 · TYPE · MIXED STRATEGY</span>
<h2>字体系统 · 中英协作</h2>
<p><code class="tk">Inter</code>(英文/数字)+ <code class="tk">Alibaba PuHuiTi</code>(中文)+ <code class="tk">JetBrains Mono</code>(装饰)。浏览器按字符级 fallthrough,<strong>不需要 JS,中英自然分工</strong></p>
</div>
<div class="subsection">
<h3>字体族原理 <span class="mono-num">// browser-level character fallthrough</span></h3>
<div style="display:grid;grid-template-columns:1fr 1fr 1fr;gap:14px;margin-bottom:24px">
<div style="padding:24px 26px;border:1px solid var(--border-faint);border-radius:8px;background:var(--surface)">
<div style="font-family:var(--font-mono);font-size:10.5px;color:var(--black-alpha-48);letter-spacing:.06em;margin-bottom:14px">// 01 · ENGLISH</div>
<div style="font-family:'Inter',sans-serif;font-size:24px;font-weight:500;letter-spacing:-.01em;color:var(--accent-black);margin-bottom:8px">Inter</div>
<div style="font-family:'Inter',sans-serif;font-size:13px;color:var(--black-alpha-64);line-height:1.6">The quick brown fox jumps. 0123456789 — Vercel / Linear / Stripe 御用,屏幕 UI 优化。</div>
</div>
<div style="padding:24px 26px;border:1px solid var(--border-faint);border-radius:8px;background:var(--surface)">
<div style="font-family:var(--font-mono);font-size:10.5px;color:var(--black-alpha-48);letter-spacing:.06em;margin-bottom:14px">// 02 · 中文</div>
<div style="font-family:'Alibaba PuHuiTi','PingFang SC',sans-serif;font-size:24px;font-weight:500;letter-spacing:-.01em;color:var(--accent-black);margin-bottom:8px">阿里普惠体</div>
<div style="font-family:'Alibaba PuHuiTi','PingFang SC',sans-serif;font-size:13px;color:var(--black-alpha-64);line-height:1.6">为中英混排专门设计的笔画粗细配比,与 Inter 视觉重量贴近。</div>
</div>
<div style="padding:24px 26px;border:1px solid var(--border-faint);border-radius:8px;background:var(--surface)">
<div style="font-family:var(--font-mono);font-size:10.5px;color:var(--black-alpha-48);letter-spacing:.06em;margin-bottom:14px">// 03 · 装饰 MONO</div>
<div style="font-family:var(--font-mono);font-size:22px;font-weight:500;color:var(--accent-black);margin-bottom:8px">JetBrains</div>
<div style="font-family:var(--font-mono);font-size:12px;color:var(--black-alpha-64);line-height:1.6;letter-spacing:.02em">[ 200 OK ] · // 05.14 · /v2 — 仅装饰,不参与正文。</div>
</div>
</div>
<div style="padding:22px 26px;background:var(--heat-8);border:1px solid var(--heat-20);border-radius:8px">
<div style="font-family:var(--font-mono);font-size:10.5px;color:var(--heat);letter-spacing:.06em;margin-bottom:10px">// 混排实测 · MIXED RENDERING</div>
<div style="font-size:18px;font-weight:500;color:var(--accent-black);line-height:1.5">本月营收 ¥327,400 较上月 +33%,共 5 个 AI 项目处于 "生成中" 状态</div>
<div style="font-family:var(--font-mono);font-size:11px;color:var(--black-alpha-48);margin-top:10px;letter-spacing:.04em">↑ 中文走 PuHuiTi · "¥" "327,400" "+33%" "5" "AI" 走 Inter · 字重视觉匀质,无错位</div>
</div>
</div>
<div class="subsection">
<h3>字重档位 <span class="mono-num">// 400 / 500 / 600 · 700 仅徽标</span></h3>
<div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:14px">
<div style="padding:20px 22px;border:1px solid var(--border-faint);border-radius:8px;background:var(--surface)">
<div style="font-family:var(--font-mono);font-size:10.5px;color:var(--black-alpha-48);letter-spacing:.04em;margin-bottom:10px">// REGULAR · 400</div>
<div style="font-size:18px;font-weight:400;color:var(--accent-black)">流·Studio · Aa Bb 123</div>
</div>
<div style="padding:20px 22px;border:1px solid var(--heat-20);border-radius:8px;background:var(--heat-8)">
<div style="font-family:var(--font-mono);font-size:10.5px;color:var(--heat);letter-spacing:.04em;margin-bottom:10px">// MEDIUM · 500 ★ 默认</div>
<div style="font-size:18px;font-weight:500;color:var(--accent-black)">流·Studio · Aa Bb 123</div>
</div>
<div style="padding:20px 22px;border:1px solid var(--border-faint);border-radius:8px;background:var(--surface)">
<div style="font-family:var(--font-mono);font-size:10.5px;color:var(--black-alpha-48);letter-spacing:.04em;margin-bottom:10px">// SEMIBOLD · 600</div>
<div style="font-size:18px;font-weight:600;color:var(--accent-black)">流·Studio · Aa Bb 123</div>
</div>
<div style="padding:20px 22px;border:1px solid var(--border-faint);border-radius:8px;background:var(--surface)">
<div style="font-family:var(--font-mono);font-size:10.5px;color:var(--black-alpha-48);letter-spacing:.04em;margin-bottom:10px">// BOLD · 700 · 限徽标</div>
<div style="font-size:18px;font-weight:700;color:var(--accent-black)">流·Studio · Aa Bb 123</div>
</div>
</div>
<p class="mono" style="margin-top:14px">// Bold 700 仅用于 Ctrl K 这种纯英文徽标场景 · 正文严禁 700(中英字重错位会暴露)</p>
</div>
</section>
<!-- =========================================== §2.6 字号阶梯 =========================================== -->
<section id="typescale">
<div class="section-head">
<span class="mono-tag">// §2.6 · TYPE SCALE</span>
<h2>字号 / 字重 / 行高(11 档)</h2>
<p>数值类必须加 <code class="tk">tabular-nums</code><code class="tk">.num</code>。中文正文行高 1.651.8。</p>
</div>
<div class="subsection">
<div class="type-row">
<div class="meta-col"><strong>H1 / Hero</strong>36 / 500 / -0.024em / 1.2</div>
<div class="sample" style="font-size:36px;font-weight:500;letter-spacing:-.024em;line-height:1.2">早上好,大莱</div>
</div>
<div class="type-row">
<div class="meta-col"><strong>区块 H2</strong>28 / 500 / -0.02em / 1.25</div>
<div class="sample" style="font-size:28px;font-weight:500;letter-spacing:-.02em;line-height:1.25">设计系统总览</div>
</div>
<div class="type-row">
<div class="meta-col"><strong>KPI 数值</strong>32 / 500 / -0.02em / tabular-nums</div>
<div class="sample" style="font-size:32px;font-weight:500;letter-spacing:-.02em;font-variant-numeric:tabular-nums">¥327<small style="font-size:15px;color:var(--black-alpha-48)">.40 K</small></div>
</div>
<div class="type-row">
<div class="meta-col"><strong>子区 H3</strong>16 / 500 / -0.01em / 1.4</div>
<div class="sample" style="font-size:16px;font-weight:500;letter-spacing:-.01em">最近项目</div>
</div>
<div class="type-row">
<div class="meta-col"><strong>卡片标题</strong>14 / 500 / normal / 1.4</div>
<div class="sample" style="font-size:14px;font-weight:500">夏季新款蕾丝连衣裙 · 蓝色 / M</div>
</div>
<div class="type-row">
<div class="meta-col"><strong>正文 body</strong>14 / 400 / normal / 1.65</div>
<div class="sample" style="font-size:14px;line-height:1.65">商家可能没有现成的商品图,需要新增一种「AI 生成」模式 —— 上传一张随手拍的原图,AI 生成 4 张满意的头图。</div>
</div>
<div class="type-row">
<div class="meta-col"><strong>Label · 按钮 / Tab</strong>13 / 500 / normal</div>
<div class="sample" style="font-size:13px;font-weight:500">查看 Demo</div>
</div>
<div class="type-row">
<div class="meta-col"><strong>描述次级</strong>13 / 400 / black-alpha-64 / 1.8</div>
<div class="sample" style="font-size:13px;color:var(--black-alpha-64);line-height:1.8">本月营收较上月增长 33%,5 个项目处于"生成中"状态,2 个需要重新调整模特模板</div>
</div>
<div class="type-row">
<div class="meta-col"><strong>Pill 文字</strong>11.5 / 500 / normal</div>
<div class="sample" style="font-size:11.5px;font-weight:500">生成中</div>
</div>
<div class="type-row">
<div class="meta-col"><strong>Inter Bold 徽标</strong>11.5 / 700 / Inter only</div>
<div class="sample" style="font-family:'Inter',sans-serif;font-size:11.5px;font-weight:700;color:var(--black-alpha-56);letter-spacing:.02em">Ctrl K · ESC · Enter · ⇧+Tab</div>
</div>
<div class="type-row">
<div class="meta-col"><strong>Mono 标签</strong>11 / 400 / 0.04em · JetBrains</div>
<div class="sample" style="font-family:var(--font-mono);font-size:11px;letter-spacing:.04em;color:var(--black-alpha-48)">[ 200 OK ] [ .MP4 · 9:16 ] [ /v2 ]</div>
</div>
<div class="type-row">
<div class="meta-col"><strong>Mono 散点装饰</strong>8.5 / 400 / 0.04em</div>
<div class="sample" style="font-family:var(--font-mono);font-size:8.5px;letter-spacing:.04em;color:var(--black-alpha-12)">· · &nbsp;+ · &nbsp;+XX+ +XXXX· +X·</div>
</div>
</div>
</section>
<!-- =========================================== §2.7 圆角 =========================================== -->
<section id="radius">
<div class="section-head">
<span class="mono-tag">// §2.7 · RADIUS</span>
<h2>圆角阶梯</h2>
<p>统一 <strong style="color:var(--accent-black)">8 px</strong> 作为默认主圆角。完全圆 999 px 仅用于 pill / dot。<strong>不确定就选 8 · &gt;12 px 直接判错。</strong></p>
</div>
<div class="radius-row">
<div class="radius-box"><div class="box" style="border-radius:0;background:var(--crimson-bg);border-color:var(--crimson-bd)"><span class="mono" style="color:var(--accent-crimson)"></span></div><div class="lbl" style="color:var(--accent-crimson)">禁用 V1</div><div class="px">0 px</div></div>
<div class="radius-box"><div class="box" style="border-radius:2px"></div><div class="lbl">progress</div><div class="px">2 px</div></div>
<div class="radius-box"><div class="box" style="border-radius:4px"></div><div class="lbl">kbd / badge</div><div class="px">4 px</div></div>
<div class="radius-box"><div class="box" style="border-radius:6px"></div><div class="lbl">小色块</div><div class="px">6 px</div></div>
<div class="radius-box"><div class="box" style="border-radius:8px;border-color:var(--heat);background:var(--heat-8)"></div><div class="lbl" style="color:var(--heat);font-weight:500">主默认</div><div class="px" style="color:var(--heat)">8 px ★</div></div>
<div class="radius-box"><div class="box" style="border-radius:999px;width:160px;height:48px"><span class="mono">pill</span></div><div class="lbl">pill / dot</div><div class="px">999 px</div></div>
</div>
</section>
<!-- =========================================== §2.8 间距 =========================================== -->
<section id="spacing">
<div class="section-head">
<span class="mono-tag">// §2.8 · SPACING</span>
<h2>间距阶梯</h2>
<p>基础栅格 4 px。<strong>当不确定 padding 是 16 还是 24 时,选 24。</strong>当不确定 margin 是 48 还是 64 时,选 64。</p>
</div>
<div class="subsection">
<h3>常用阶梯</h3>
<div class="spacing-row">
<div class="spacing-box"><div class="spacing-bar" style="width:4px;height:36px"></div><div class="lbl">4</div></div>
<div class="spacing-box"><div class="spacing-bar" style="width:8px;height:36px"></div><div class="lbl">8</div></div>
<div class="spacing-box"><div class="spacing-bar" style="width:12px;height:36px"></div><div class="lbl">12</div></div>
<div class="spacing-box"><div class="spacing-bar" style="width:16px;height:36px"></div><div class="lbl">16</div></div>
<div class="spacing-box"><div class="spacing-bar" style="width:20px;height:36px"></div><div class="lbl">20</div></div>
<div class="spacing-box"><div class="spacing-bar" style="width:24px;height:36px"></div><div class="lbl">24 ★</div></div>
<div class="spacing-box"><div class="spacing-bar" style="width:32px;height:36px"></div><div class="lbl">32</div></div>
<div class="spacing-box"><div class="spacing-bar" style="width:40px;height:36px"></div><div class="lbl">40</div></div>
<div class="spacing-box"><div class="spacing-bar" style="width:48px;height:36px"></div><div class="lbl">48</div></div>
<div class="spacing-box"><div class="spacing-bar" style="width:64px;height:36px"></div><div class="lbl">64 ★</div></div>
<div class="spacing-box"><div class="spacing-bar" style="width:80px;height:36px"></div><div class="lbl">80</div></div>
<div class="spacing-box"><div class="spacing-bar" style="width:104px;height:36px"></div><div class="lbl">104</div></div>
</div>
</div>
<div class="subsection">
<h3>典型场景</h3>
<table class="audit-table">
<thead><tr><th>场景</th><th></th></tr></thead>
<tbody>
<tr><td colspan="1" style="color:var(--accent-black)">Sidebar 宽度</td><td class="now">248 px</td></tr>
<tr><td colspan="1" style="color:var(--accent-black)">Topbar 高度</td><td class="now">64 px</td></tr>
<tr><td colspan="1" style="color:var(--accent-black)">Content padding</td><td class="now">48 · 28 · 72</td></tr>
<tr><td colspan="1" style="color:var(--accent-black)">卡片内 padding(大)</td><td class="now">28 · 30 或 24 · 28</td></tr>
<tr><td colspan="1" style="color:var(--accent-black)">列表行 padding</td><td class="now">14 · 18 ~ 20 · 24</td></tr>
<tr><td colspan="1" style="color:var(--accent-black)">KPI cell padding</td><td class="now">24 · 28</td></tr>
<tr><td colspan="1" style="color:var(--accent-black)">主区块 margin</td><td class="now">64104 px</td></tr>
<tr><td colspan="1" style="color:var(--accent-black)">子区块 margin</td><td class="now">3648 px</td></tr>
<tr><td colspan="1" style="color:var(--accent-black)">卡片网格 gap</td><td class="now">14(子区)/ 24(主区)</td></tr>
</tbody>
</table>
</div>
</section>
<!-- =========================================== §2.9 阴影 =========================================== -->
<section id="shadow">
<div class="section-head">
<span class="mono-tag">// §2.9 · SHADOW</span>
<h2>阴影 · 只 3 个允许场景</h2>
<p>主 CTA(4 层橙色发光)+ Toast/Dropdown 浮层(白色 6%)。其他场景<strong style="color:var(--accent-crimson)">一律禁阴影</strong></p>
</div>
<div class="shadow-row">
<div class="shadow-box shadow-cta-demo">主 CTA · 4 层橙阴影</div>
<div class="shadow-box shadow-cta-demo" style="box-shadow:inset 0 -4px 8px rgba(250,93,25,.20),0 1px 1px rgba(250,93,25,.16),0 4px 8px rgba(250,93,25,.20),0 .5px .5px rgba(250,93,25,.16)">主 CTA · hover 抬升</div>
<div class="shadow-box shadow-floating-demo">Toast / Dropdown · 白阴影</div>
</div>
</section>
<!-- =========================================== §2.10 inside-border =========================================== -->
<section id="inside-border">
<div class="section-head">
<span class="mono-tag">// §2.10 · INSIDE-BORDER</span>
<h2>边框策略 · inside-border</h2>
<p>默认边框用 <code class="tk">::before</code> 伪元素绘制(而非真 <code class="tk">border</code>),hover 时让 <code class="tk">::before</code> 透明度 → 0,<strong>不触发布局抖动</strong><strong>hover 下面的卡看效果。</strong></p>
</div>
<div class="ib-demo">
<div class="ib-box">// 默认</div>
<div class="ib-box">// hover 我看</div>
<div class="ib-box">// hover 我看</div>
</div>
</section>
<!-- =========================================== §3 页面骨架 =========================================== -->
<section id="skeleton">
<div class="section-head">
<span class="mono-tag">// §3 · SKELETON</span>
<h2>页面骨架(全站统一)</h2>
<p>每个新页面都用同一套 HTML 骨架。<code class="tk">shell.js</code> 自动注入 sidebar + topbar,<strong>页面只写 <code class="tk">&lt;main&gt;</code> 内的 <code class="tk">.content</code> 内容</strong></p>
</div>
<div class="subsection">
<h3>HTML 模板</h3>
<pre class="codebox">&lt;link rel="stylesheet" href="assets/restraint.css"&gt;
&lt;link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700
&amp;family=JetBrains+Mono:wght@400;500&amp;display=swap" rel="stylesheet"&gt;
&lt;div class="app"&gt;
&lt;aside class="sidebar"&gt;&lt;!-- shell.js 注入 --&gt;&lt;/aside&gt;
&lt;main&gt;
&lt;div class="topbar"&gt;&lt;!-- shell.js 注入:crumbs · right --&gt;&lt;/div&gt;
&lt;div class="content"&gt;
&lt;div class="page-head"&gt;
&lt;div&gt;
&lt;h1&gt;商品库&lt;/h1&gt;
&lt;div class="sub"&gt;&lt;span class="mono"&gt;// 12 个商品&lt;/span&gt; · 描述&lt;/div&gt;
&lt;/div&gt;
&lt;div class="actions"&gt;
&lt;button class="btn"&gt;导入&lt;/button&gt;
&lt;button class="btn btn-primary"&gt;+ 新建商品&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section-h"&gt;
&lt;h2&gt;最近项目&lt;/h2&gt;
&lt;a class="more"&gt;[ ALL · 12 ] →&lt;/a&gt;
&lt;/div&gt;
&lt;!-- 内容 --&gt;
&lt;/div&gt;
&lt;/main&gt;
&lt;/div&gt;
&lt;script src="assets/shell.js" defer&gt;&lt;/script&gt;</pre>
</div>
</section>
<!-- =========================================== §3.4 主容器装订线 =========================================== -->
<section id="container">
<div class="section-head">
<span class="mono-tag">// §3.4 · SIGNATURE · CONTAINER GUTTER</span>
<h2>主容器装订线</h2>
<p>工作台 / 项目列表 / 商品库 / 流水线主区:左右两条 1 px 边线 + 4 角圆弧内凹 SVG 准星。Modal / 编辑器全屏画布<strong>不必加</strong></p>
</div>
<div class="container-demo">
<svg class="corner tl" viewBox="0 0 22 21" fill="currentColor"><path d="M10.5 4C10.5 7.31371 7.81371 10 4.5 10H0.5V11H4.5C7.81371 11 10.5 13.6863 10.5 17V21H11.5V17C11.5 13.6863 14.1863 11 17.5 11H21.5V10H17.5C14.1863 10 11.5 7.31371 11.5 4V0H10.5V4Z"/></svg>
<svg class="corner tr" viewBox="0 0 22 21" fill="currentColor"><path d="M10.5 4C10.5 7.31371 7.81371 10 4.5 10H0.5V11H4.5C7.81371 11 10.5 13.6863 10.5 17V21H11.5V17C11.5 13.6863 14.1863 11 17.5 11H21.5V10H17.5C14.1863 10 11.5 7.31371 11.5 4V0H10.5V4Z"/></svg>
<svg class="corner bl" viewBox="0 0 22 21" fill="currentColor"><path d="M10.5 4C10.5 7.31371 7.81371 10 4.5 10H0.5V11H4.5C7.81371 11 10.5 13.6863 10.5 17V21H11.5V17C11.5 13.6863 14.1863 11 17.5 11H21.5V10H17.5C14.1863 10 11.5 7.31371 11.5 4V0H10.5V4Z"/></svg>
<svg class="corner br" viewBox="0 0 22 21" fill="currentColor"><path d="M10.5 4C10.5 7.31371 7.81371 10 4.5 10H0.5V11H4.5C7.81371 11 10.5 13.6863 10.5 17V21H11.5V17C11.5 13.6863 14.1863 11 17.5 11H21.5V10H17.5C14.1863 10 11.5 7.31371 11.5 4V0H10.5V4Z"/></svg>
<div class="inner">
这块容器左右贯穿两条 1 px 边线,四角带圆弧内凹的 SVG 准星<br>
<span class="mono">// container-demo · max-width: 720 · border-x only</span>
</div>
</div>
</section>
<!-- =========================================== §4.12 Icon 系统 =========================================== -->
<section id="icons">
<div class="section-head">
<span class="mono-tag">// §4.12 · ICONS</span>
<h2>Icon 系统</h2>
<p>统一 SVG line icon · <code class="tk">stroke 1.5</code> · <code class="tk">linecap round</code> · 颜色通过 <code class="tk">currentColor</code> 继承。<strong>禁用 emoji / filled icon</strong></p>
</div>
<div class="subsection">
<h3>尺寸阶梯 <span class="mono-num">// 5 档</span></h3>
<div class="icon-row">
<div class="icon-cell">
<div class="ic" style="width:32px;height:32px"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5v14M5 12h14"/></svg></div>
<div class="lbl">S · 14 px</div>
</div>
<div class="icon-cell">
<div class="ic" style="width:36px;height:36px"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5v14M5 12h14"/></svg></div>
<div class="lbl">M · 16 px ★</div>
</div>
<div class="icon-cell">
<div class="ic" style="width:40px;height:40px"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5v14M5 12h14"/></svg></div>
<div class="lbl">L · 20 px</div>
</div>
<div class="icon-cell">
<div class="ic" style="width:48px;height:48px"><svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5v14M5 12h14"/></svg></div>
<div class="lbl">XL · 24 px</div>
</div>
<div class="icon-cell">
<div class="ic" style="width:64px;height:64px"><svg width="36" height="36" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5v14M5 12h14"/></svg></div>
<div class="lbl">Hero · 36 px</div>
</div>
</div>
</div>
<div class="subsection">
<h3>颜色场景 <span class="mono-num">// 通过 currentColor 继承</span></h3>
<div class="icon-color-row">
<div class="demo" style="color:var(--black-alpha-56)">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>
<span>默认 alpha-56</span>
</div>
<div class="demo" style="background:var(--black-alpha-4);color:var(--accent-black)">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>
<span>hover · 主前景</span>
</div>
<div class="demo" style="color:var(--heat);background:var(--heat-12);border-color:var(--heat-20)">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>
<span>active · heat</span>
</div>
<div class="demo primary">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14M12 5l7 7-7 7"/></svg>
<span>在主 CTA 内</span>
</div>
<div class="demo disabled">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>
<span>disabled</span>
</div>
</div>
</div>
<div class="subsection">
<h3>Icon Box <span class="mono-num">// 快捷入口 / Modal 头部用</span></h3>
<div style="display:flex;gap:14px;align-items:center;flex-wrap:wrap">
<div style="width:32px;height:32px;border-radius:8px;background:var(--heat-12);display:grid;place-items:center"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="var(--heat)" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><path d="m9 11 3 3L22 4"/></svg></div>
<div style="width:32px;height:32px;border-radius:8px;background:var(--heat-12);display:grid;place-items:center"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="var(--heat)" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2"/><path d="m9 9 6 6m0-6-6 6"/></svg></div>
<div style="width:32px;height:32px;border-radius:8px;background:var(--heat-12);display:grid;place-items:center"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="var(--heat)" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83"/></svg></div>
<span class="mono">32×32 · 8 px 圆角 · --heat-12 底 · 16 px line icon</span>
</div>
</div>
</section>
<!-- =========================================== §4.1 按钮 · 三级体系 =========================================== -->
<section id="buttons">
<div class="section-head">
<span class="mono-tag">// §4.1 · BUTTONS · 三级体系(按功能重要性)</span>
<h2>按钮 · 按功能重要性分 3 级</h2>
<p><strong style="color:var(--accent-black)">视觉强度 = 操作重要程度。</strong>一个区域只能有<strong style="color:var(--heat)">一个</strong>一级按钮(像航海图上只能有一个北极星)。<strong style="color:var(--accent-crimson)">视觉等级混乱比按钮不好看更致命</strong></p>
</div>
<div class="subsection">
<h3>三级体系总览 <span class="mono-num">// 视觉 / 语义 / 数量约束</span></h3>
<table class="audit-table">
<thead><tr><th>等级</th><th>类名</th><th>视觉</th><th>语义</th><th>数量约束</th></tr></thead>
<tbody>
<tr>
<td><span class="pill pill-l3 info"><span class="dot"></span>L1</span></td>
<td class="now">.btn.btn-primary</td>
<td>橙底 + 4 层橙阴影 + 字重 600</td>
<td style="color:var(--accent-black);font-weight:500">页面/弹窗最重要动作 · 主动作</td>
<td class="should">一个区域只 1 个 ★</td>
</tr>
<tr>
<td><span class="pill pill-l3 neutral"><span class="dot"></span>L2</span></td>
<td class="now">.btn</td>
<td>白底 + inside-border + 主前景字</td>
<td style="color:var(--accent-black);font-weight:500">跟主操作并列的重要动作</td>
<td class="should">可多个</td>
</tr>
<tr>
<td><span class="pill pill-l3 neutral"><span class="dot"></span>L3</span></td>
<td class="now">.btn.btn-ghost</td>
<td>透明底 + 无框 + alpha-56 字</td>
<td style="color:var(--accent-black);font-weight:500">辅助 / 链接式弱化操作</td>
<td class="should">不限</td>
</tr>
</tbody>
</table>
</div>
<div class="subsection">
<h3>选谁?决策表 <span class="mono-num">// 操作类型 → 等级</span></h3>
<table class="audit-table">
<thead><tr><th>操作类型</th><th>等级</th><th>例子</th></tr></thead>
<tbody>
<tr><td style="color:var(--accent-black)">提交 / 确认 / 创建 / 下一步 / 保存 / 生成</td><td><span class="pill pill-l3 info"><span class="dot"></span>L1 一级</span></td><td class="now">创建商品 · 确认删除 · 开始生成</td></tr>
<tr><td style="color:var(--accent-black)">取消 / 重置 / 导出 / 导入 / 上一步 / 关闭</td><td><span class="pill pill-l3 neutral"><span class="dot"></span>L2 二级</span></td><td class="now">取消 · 重置 · 导出 CSV</td></tr>
<tr><td style="color:var(--accent-black)">跳过 / 了解更多 / 查看详情 / 行内动作</td><td><span class="pill pill-l3 neutral"><span class="dot"></span>L3 三级</span></td><td class="now">跳过 · 了解更多 → · [查看] [编辑] [删除] 行内</td></tr>
<tr><td style="color:var(--accent-black)">破坏性(删除 / 危险)</td><td><span class="pill pill-l3 err"><span class="dot"></span>L1 in Modal</span></td><td class="now">列表里的"删除"用二级 → 弹 modal,modal 里的"确认删除"才是一级</td></tr>
</tbody>
</table>
</div>
<div class="subsection">
<h3>一级按钮 · Primary <span class="mono-num">// .btn-primary · 一个区域只 1 个</span></h3>
<p class="lead"><strong>语义:</strong>用户在当前页面/弹窗最希望完成的<strong>那一个</strong>动作。视觉上需要"被看到"。</p>
<div class="btn-row"><span class="state-label">// default</span><button class="btn btn-primary">创建商品</button><button class="btn btn-primary">下一步<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14M12 5l7 7-7 7"/></svg></button></div>
<div class="btn-row"><span class="state-label">// hover</span><button class="btn btn-primary demo-hover">创建商品</button></div>
<div class="btn-row"><span class="state-label">// active</span><button class="btn btn-primary demo-active">创建商品</button></div>
<div class="btn-row"><span class="state-label">// focused</span><button class="btn btn-primary demo-focus">创建商品</button></div>
<div class="btn-row"><span class="state-label">// disabled</span><button class="btn btn-primary" disabled>创建商品</button></div>
</div>
<div class="subsection">
<h3>二级按钮 · Secondary <span class="mono-num">// .btn · 并列动作 · 可多个</span></h3>
<p class="lead"><strong>语义:</strong>跟主操作并列出现的动作,但不是首要焦点 —— 取消、重置、导出、上一步、关闭。</p>
<div class="btn-row"><span class="state-label">// default</span><button class="btn">取消</button><button class="btn"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4M7 10l5 5 5-5M12 15V3"/></svg>导出</button></div>
<div class="btn-row"><span class="state-label">// hover</span><button class="btn demo-hover">取消</button></div>
<div class="btn-row"><span class="state-label">// active</span><button class="btn demo-active">取消</button></div>
<div class="btn-row"><span class="state-label">// focused</span><button class="btn demo-focus">取消</button></div>
<div class="btn-row"><span class="state-label">// disabled</span><button class="btn" disabled>取消</button></div>
</div>
<div class="subsection">
<h3>三级按钮 · Tertiary <span class="mono-num">// .btn-ghost · 弱化辅助 · 不限</span></h3>
<p class="lead"><strong>语义:</strong>视觉降级的辅助动作 —— 跳过、了解更多、行内 [查看]/[编辑]/[删除]。<strong>不抢夺主流程注意力</strong></p>
<div class="btn-row"><span class="state-label">// default</span><button class="btn btn-ghost">跳过</button><button class="btn btn-ghost">了解更多 →</button></div>
<div class="btn-row"><span class="state-label">// hover</span><button class="btn btn-ghost demo-hover">跳过</button></div>
<div class="btn-row"><span class="state-label">// active</span><button class="btn btn-ghost demo-active">跳过</button></div>
<div class="btn-row"><span class="state-label">// disabled</span><button class="btn btn-ghost" disabled>跳过</button></div>
</div>
<div class="subsection">
<h3>典型组合 <span class="mono-num">// 一个区域如何摆放 4 种场景</span></h3>
<p class="lead">// 1 · <strong>page-head 标题区</strong> · 模式 <code class="tk">[L2] + [L1]</code></p>
<div style="background:var(--surface);border:1px solid var(--border-faint);border-radius:8px;padding:18px 22px;margin-bottom:18px;display:flex;justify-content:space-between;align-items:center;gap:16px;flex-wrap:wrap">
<div><div style="font-size:18px;color:var(--accent-black);font-weight:500;margin-bottom:6px">商品库</div><div class="mono">// 12 个商品 · 你的所有商品和卖点</div></div>
<div style="display:flex;gap:10px"><button class="btn btn-lg">导入</button><button class="btn btn-primary btn-lg">+ 新建商品</button></div>
</div>
<p class="lead">// 2 · <strong>Modal 底栏</strong> · 模式 <code class="tk">[L2 取消] + [L1 确认]</code> · <strong style="color:var(--accent-black)">主操作永远在右</strong></p>
<div style="background:var(--surface);border:1px solid var(--border-faint);border-radius:8px;padding:18px 22px;margin-bottom:18px;display:flex;justify-content:flex-end;align-items:center;gap:10px">
<button class="btn">取消</button>
<button class="btn btn-primary">确认删除</button>
</div>
<p class="lead">// 3 · <strong>卡片 / 列表行内</strong> · 模式 <code class="tk">[L3] × N</code> · 弱化避免抢戏</p>
<div style="background:var(--surface);border:1px solid var(--border-faint);border-radius:8px;padding:18px 22px;margin-bottom:18px;display:flex;justify-content:space-between;align-items:center;gap:16px">
<div style="min-width:0;flex:1"><div style="font-size:14px;color:var(--accent-black);font-weight:500;margin-bottom:4px">夏季新款蕾丝连衣裙</div><div class="mono">// 05.14 · 蓝色 / M</div></div>
<div style="display:flex;gap:2px"><button class="btn btn-ghost btn-sm">查看</button><button class="btn btn-ghost btn-sm">编辑</button><button class="btn btn-ghost btn-sm">删除</button></div>
</div>
<p class="lead">// 4 · <strong>表单 / 向导底部</strong> · 模式 <code class="tk">[L3] + spacer + [L2] + [L1]</code></p>
<div style="background:var(--surface);border:1px solid var(--border-faint);border-radius:8px;padding:18px 22px;display:flex;align-items:center;gap:10px;flex-wrap:wrap">
<button class="btn btn-ghost">← 上一步</button>
<div style="flex:1"></div>
<button class="btn">保存草稿</button>
<button class="btn btn-primary">提交</button>
</div>
</div>
<div class="subsection">
<h3>尺寸阶梯 <span class="mono-num">// 独立于等级 · 按上下文密度选</span></h3>
<p class="lead">尺寸跟等级<strong>正交</strong> — 一级可以是 sm/默认/lg,二级三级同理。按上下文密度选尺寸。</p>
<div class="btn-row">
<button class="btn btn-sm">Small · 28h</button>
<button class="btn">Default · 36h ★</button>
<button class="btn btn-lg">Large · 40h</button>
</div>
<div class="btn-row" style="margin-top:12px">
<button class="btn btn-primary btn-sm">Small</button>
<button class="btn btn-primary">Default</button>
<button class="btn btn-primary btn-lg">Large</button>
</div>
<p class="mono" style="margin-top:14px">// sm 用于:行内/列表行末/表格内/紧凑工具栏 · lg 用于:hero CTA / page-head 主操作(已全局覆盖)</p>
</div>
<div class="subsection">
<h3>常见错误 <span class="mono-num">// Do / Don't 对照</span></h3>
<div class="dodont-grid">
<div class="dodont dont">
<span class="head">DON'T</span>
<div class="body"><strong>一个区域两个一级橙按钮并列</strong> — 用户视线分散,不知道该点哪个</div>
</div>
<div class="dodont do">
<span class="head">DO</span>
<div class="body">[二级] + [一级] · 永远只有一个真正的主动作</div>
</div>
<div class="dodont dont">
<span class="head">DON'T</span>
<div class="body"><strong>"取消"做成橙色 primary</strong> — 取消是退出动作,不应该是焦点</div>
</div>
<div class="dodont do">
<span class="head">DO</span>
<div class="body">"取消" 永远是二级 .btn,放在主操作的<strong>左边</strong></div>
</div>
<div class="dodont dont">
<span class="head">DON'T</span>
<div class="body"><strong>重要操作用 ghost 三级</strong> — 弱化了主流程,用户找不到入口</div>
</div>
<div class="dodont do">
<span class="head">DO</span>
<div class="body">按重要性分级:主动作橙 · 次重要白 · 弱化 ghost</div>
</div>
<div class="dodont dont">
<span class="head">DON'T</span>
<div class="body"><strong>三级按钮 inline 加边框</strong> — 加了边框就退化成二级了</div>
</div>
<div class="dodont do">
<span class="head">DO</span>
<div class="body">三级保持 ghost 无框,只 hover 时出 4% 浅底</div>
</div>
<div class="dodont dont">
<span class="head">DON'T</span>
<div class="body"><strong>页面 inline 改 .btn 高度/字号</strong> — 用 .btn-sm / .btn-lg,不要 inline</div>
</div>
<div class="dodont do">
<span class="head">DO</span>
<div class="body">需要新尺寸 → 先回 restraint.css 加,不污染页面 inline</div>
</div>
</div>
</div>
</section>
<!-- =========================================== §4.2 Pills =========================================== -->
<section id="pills">
<div class="section-head">
<span class="mono-tag">// §4.2 · PILLS</span>
<h2>胶囊 · 严格 3 级分层</h2>
<p><strong style="color:var(--accent-black)">同级别尺寸必须完全一致。</strong>pill 永远是 <code class="tk">999 px</code>(完全圆),靠 dot 体现状态。</p>
</div>
<div class="subsection">
<h3>L1 · 大胶囊 <span class="mono-num">// h:28 / fs:13 / dot:8 · 项目状态 / 列表行主标签</span></h3>
<div class="pill-row">
<span class="pill pill-l1 info"><span class="dot"></span>生成中</span>
<span class="pill pill-l1 ok"><span class="dot"></span>已完成</span>
<span class="pill pill-l1 err"><span class="dot"></span>失败</span>
<span class="pill pill-l1 neutral"><span class="dot"></span>已归档</span>
</div>
</div>
<div class="subsection">
<h3>L2 · 中胶囊 <span class="mono-num">// h:22 / fs:11.5 / dot:6 ★ 默认</span></h3>
<p class="lead">最常用尺寸。卡片内 / 表格内默认。</p>
<div class="pill-row">
<span class="pill pill-l2 info"><span class="dot"></span>生成中</span>
<span class="pill pill-l2 ok"><span class="dot"></span>200 OK</span>
<span class="pill pill-l2 err"><span class="dot"></span>超时</span>
<span class="pill pill-l2 neutral"><span class="dot"></span>已归档</span>
</div>
</div>
<div class="subsection">
<h3>L3 · 小胶囊 <span class="mono-num">// h:18 / fs:10.5 / dot:5 · KPI 角标</span></h3>
<div class="pill-row">
<span class="pill pill-l3 info"><span class="dot"></span>NEW</span>
<span class="pill pill-l3 ok"><span class="dot"></span>+33%</span>
<span class="pill pill-l3 err"><span class="dot"></span>-1.2%</span>
</div>
</div>
<div class="subsection">
<h3>对比 <span class="mono-num">// 同色 3 级并列</span></h3>
<div style="display:flex;gap:14px;align-items:center;flex-wrap:wrap;padding:24px;background:var(--surface);border:1px solid var(--border-faint);border-radius:8px">
<span class="pill pill-l1 info"><span class="dot"></span>L1 · 生成中</span>
<span class="pill pill-l2 info"><span class="dot"></span>L2 · 生成中</span>
<span class="pill pill-l3 info"><span class="dot"></span>L3 · 生成中</span>
</div>
</div>
</section>
<!-- =========================================== §4.3 输入框 =========================================== -->
<section id="inputs">
<div class="section-head">
<span class="mono-tag">// §4.3 · INPUTS</span>
<h2>输入框 · 5 状态</h2>
<p>高 36 px / 圆角 8 / inside-border。focused 时橙色 ring 内嵌 1 px,error 时红边 + 红软底。<strong>点击下面字段看真实 focus 反馈。</strong></p>
</div>
<div class="subsection">
<div class="field-row"><span class="lbl">// default</span><div class="input-wrap"><input class="input" placeholder="搜索商品 / 项目..."/></div></div>
<div class="field-row"><span class="lbl">// focused</span><div class="input-wrap"><input class="input" value="已聚焦" style="border-color:var(--heat-40);box-shadow:inset 0 0 0 1px var(--heat-40)"/></div></div>
<div class="field-row"><span class="lbl">// error</span><div class="input-wrap is-error"><input class="input" value="invalid@example"/></div></div>
<div class="field-row"><span class="lbl">// disabled</span><div class="input-wrap"><input class="input" placeholder="不可编辑" disabled/></div></div>
</div>
<div class="subsection">
<h3>带图标 / 搜索 <span class="mono-num">// 含 Ctrl K 提示</span></h3>
<div class="search-demo">
<svg class="ic-left" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/></svg>
<input class="input" placeholder="搜索任意内容..."/>
<span class="k">Ctrl K</span>
</div>
<p class="mono" style="margin-top:12px">// 关键坑:左侧 icon 必须 z-index: 2(否则被 input 白底盖住)· Ctrl K 用纯文本不用 ⌘(JetBrains Mono 不带该字形)</p>
</div>
</section>
<!-- =========================================== §4.4 表单控件 =========================================== -->
<section id="form-controls">
<div class="section-head">
<span class="mono-tag">// §4.4 · FORM CONTROLS</span>
<h2>表单控件 · Checkbox / Radio / Switch</h2>
<p>全部用真 SVG indicator,<strong>禁止 border-width / rotate(45deg) 凑对勾</strong>(在缩放/字体渲染下会变形)。<strong>点击下面控件试试。</strong></p>
</div>
<div class="subsection">
<h3>Checkbox</h3>
<div class="ck-row">
<label class="ck"><input type="checkbox"/><span class="ck-box"></span>未选中</label>
<label class="ck"><input type="checkbox" checked/><span class="ck-box"></span>已选中</label>
<label class="ck is-indeterminate"><input type="checkbox"/><span class="ck-box"></span>半选中</label>
<label class="ck is-disabled"><input type="checkbox" disabled/><span class="ck-box"></span>Disabled</label>
</div>
</div>
<div class="subsection">
<h3>Radio</h3>
<div class="ck-row">
<label class="rd"><input type="radio" name="rdemo"/><span class="rd-box"></span>选项 A</label>
<label class="rd"><input type="radio" name="rdemo" checked/><span class="rd-box"></span>选项 B(已选)</label>
<label class="rd"><input type="radio" name="rdemo"/><span class="rd-box"></span>选项 C</label>
<label class="rd" style="opacity:.5;cursor:not-allowed"><input type="radio" disabled/><span class="rd-box"></span>Disabled</label>
</div>
</div>
<div class="subsection">
<h3>Switch</h3>
<div class="ck-row">
<label class="sw"><input type="checkbox"/><span class="sw-box"></span></label>
<label class="sw"><input type="checkbox" checked/><span class="sw-box"></span></label>
<label class="sw is-disabled"><input type="checkbox" disabled/><span class="sw-box"></span>Disabled</label>
</div>
</div>
</section>
<!-- =========================================== §4.5 KPI 统计行 =========================================== -->
<section id="stats">
<div class="section-head">
<span class="mono-tag">// §4.5 · KPI STATS</span>
<h2>KPI 统计行 · 4 格</h2>
<p>1 行 4 格 grid · 共用一个 inside-border 容器 · <strong>无 gap</strong>。列与列之间用 1 px 分隔线。</p>
</div>
<div class="demo-stats">
<div class="cell">
<div class="lbl-row"><span class="lbl">本月营收</span><span class="pill pill-l3 ok"><span class="dot"></span>+33%</span></div>
<div class="num">¥327<small>.40 K</small></div>
<div class="delta"><span class="up">↑ 较上月 +33%</span></div>
</div>
<div class="cell">
<div class="lbl-row"><span class="lbl">活跃项目</span></div>
<div class="num">12</div>
<div class="delta">↑ 本月 +3</div>
</div>
<div class="cell">
<div class="lbl-row"><span class="lbl">生成中</span><span class="pill pill-l3 info"><span class="dot"></span>RUN</span></div>
<div class="num">5</div>
<div class="prog" style="margin-top:8px"><span class="done"></span><span class="done"></span><span class="cur"></span><span></span><span></span></div>
</div>
<div class="cell">
<div class="lbl-row"><span class="lbl">资产总数</span></div>
<div class="num">847</div>
<div class="delta">· MP4 · JPG · PNG</div>
</div>
</div>
</section>
<!-- =========================================== §4.6 进度条 =========================================== -->
<section id="progress">
<div class="section-head">
<span class="mono-tag">// §4.6 · PROGRESS · 5 段流水线专用</span>
<h2>进度条段位</h2>
<p><strong>动 = 在运行,静 = 完成/失败。</strong>脉动只给"进行中"(橙)。已完成绿、失败红、未开始灰。</p>
</div>
<div style="display:flex;gap:24px;flex-wrap:wrap">
<div><div class="prog"><span></span><span></span><span></span><span></span><span></span></div><div class="mono" style="margin-top:6px">未开始</div></div>
<div><div class="prog"><span class="done"></span><span class="done"></span><span class="cur"></span><span></span><span></span></div><div class="mono" style="margin-top:6px">进行中(2/5)· 脉动</div></div>
<div><div class="prog"><span class="done"></span><span class="done"></span><span class="done"></span><span class="done"></span><span class="done"></span></div><div class="mono" style="margin-top:6px">已完成</div></div>
<div><div class="prog"><span class="done"></span><span class="fail"></span><span></span><span></span><span></span></div><div class="mono" style="margin-top:6px">失败</div></div>
</div>
</section>
<!-- =========================================== §4.7 列表行 =========================================== -->
<section id="list">
<div class="section-head">
<span class="mono-tag">// §4.7 · LIST ROW</span>
<h2>列表行</h2>
<p>grid: <code class="tk">56px 1fr auto auto auto</code> · gap 22 · padding 20·24。<strong>hover 我看整行底色变化。</strong></p>
</div>
<div class="list-card-demo">
<div class="list-row-demo">
<div class="thumb">9:16</div>
<div class="meta"><div class="ti">夏季新款蕾丝连衣裙</div><div class="sub">// 创建于 05.14 · 蓝色 / M</div></div>
<div class="prog"><span class="done"></span><span class="done"></span><span class="done"></span><span class="cur"></span><span></span></div>
<span class="pill pill-l2 info"><span class="dot"></span>生成中</span>
<button class="btn btn-sm">查看</button>
</div>
<div class="list-row-demo">
<div class="thumb">4:5</div>
<div class="meta"><div class="ti">秋季风衣 · 卡其色</div><div class="sub">// 创建于 05.12 · M / L</div></div>
<div class="prog"><span class="done"></span><span class="done"></span><span class="done"></span><span class="done"></span><span class="done"></span></div>
<span class="pill pill-l2 ok"><span class="dot"></span>已完成</span>
<button class="btn btn-sm">导出</button>
</div>
<div class="list-row-demo">
<div class="thumb">1:1</div>
<div class="meta"><div class="ti">运动 T 恤 · 黑白款</div><div class="sub">// 创建于 05.10 · 全色系</div></div>
<div class="prog"><span class="done"></span><span class="fail"></span><span></span><span></span><span></span></div>
<span class="pill pill-l2 err"><span class="dot"></span>生成失败</span>
<button class="btn btn-sm">重试</button>
</div>
</div>
</section>
<!-- =========================================== §4.8 Tab =========================================== -->
<section id="tabs">
<div class="section-head">
<span class="mono-tag">// §4.8 · TABS</span>
<h2>Tab · 双层结构</h2>
<p>主 Tab 用<strong>下划线激活</strong>(2 px <code class="tk heat">--heat</code> 横线)。副 Tab 用灰度→彩色 icon 反馈。<strong>点击切换。</strong></p>
</div>
<div class="subsection">
<h3>主 Tab</h3>
<div class="ds-tabs" data-tabs>
<button class="ds-tab is-active" data-tab="all">全部</button>
<button class="ds-tab" data-tab="img">商品图</button>
<button class="ds-tab" data-tab="vid">短视频</button>
<button class="ds-tab" data-tab="ad">投放素材</button>
</div>
<div style="padding:20px 24px;background:var(--surface);border:1px solid var(--border-faint);border-radius:8px">当前显示:<span data-tab-content style="color:var(--heat);font-weight:500">全部</span></div>
</div>
<div class="subsection">
<h3>副 Tab · 灰度→彩色</h3>
<div class="ds-subtabs" data-subtabs>
<button class="ds-subtab is-active"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/></svg>Search</button>
<div class="ds-subtab-divider"></div>
<button class="ds-subtab"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2"/><path d="M3 9h18M9 21V9"/></svg>Scrape</button>
<div class="ds-subtab-divider"></div>
<button class="ds-subtab"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><path d="M14 2v6h6"/></svg>Parse</button>
<div class="ds-subtab-divider"></div>
<button class="ds-subtab"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><polygon points="3 6 9 3 15 6 21 3 21 18 15 21 9 18 3 21 3 6"/></svg>Map</button>
</div>
</div>
</section>
<!-- =========================================== §4.10 卡片 =========================================== -->
<section id="cards">
<div class="section-head">
<span class="mono-tag">// §4.10 · CARDS</span>
<h2>卡片 / 快捷入口</h2>
<p>所有卡片统一 <code class="tk">8 px 圆角 · 1 px 边框 · 无阴影</code>。快捷入口含 hover / active 状态。</p>
</div>
<div class="subsection">
<h3>快捷入口 <span class="mono-num">// hover 我</span></h3>
<div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:12px">
<a href="#" style="display:flex;align-items:center;gap:16px;background:var(--surface);border:1px solid var(--border-faint);border-radius:8px;padding:18px 20px;cursor:pointer;text-decoration:none;color:inherit;transition:background var(--t-base)" onmouseenter="this.style.background='var(--black-alpha-4)'" onmouseleave="this.style.background='var(--surface)'">
<div style="width:32px;height:32px;border-radius:8px;background:var(--heat-12);display:grid;place-items:center;flex-shrink:0"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="var(--heat)" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5v14M5 12h14"/></svg></div>
<div style="flex:1;min-width:0"><div style="font-size:14px;font-weight:500;color:var(--accent-black);margin-bottom:4px;line-height:1.4">新建商品</div><div class="mono">// AI 生成 / 上传图</div></div>
</a>
<a href="#" style="display:flex;align-items:center;gap:16px;background:var(--surface);border:1px solid var(--border-faint);border-radius:8px;padding:18px 20px;cursor:pointer;text-decoration:none;color:inherit;transition:background var(--t-base)" onmouseenter="this.style.background='var(--black-alpha-4)'" onmouseleave="this.style.background='var(--surface)'">
<div style="width:32px;height:32px;border-radius:8px;background:var(--heat-12);display:grid;place-items:center;flex-shrink:0"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="var(--heat)" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="6" width="20" height="12" rx="2"/><path d="m10 9 5 3-5 3z" fill="currentColor"/></svg></div>
<div style="flex:1;min-width:0"><div style="font-size:14px;font-weight:500;color:var(--accent-black);margin-bottom:4px;line-height:1.4">短视频工坊</div><div class="mono">// 9:16 · MP4</div></div>
</a>
<a href="#" style="display:flex;align-items:center;gap:16px;background:var(--surface);border:1px solid var(--border-faint);border-radius:8px;padding:18px 20px;cursor:pointer;text-decoration:none;color:inherit;transition:background var(--t-base)" onmouseenter="this.style.background='var(--black-alpha-4)'" onmouseleave="this.style.background='var(--surface)'">
<div style="width:32px;height:32px;border-radius:8px;background:var(--heat-12);display:grid;place-items:center;flex-shrink:0"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="var(--heat)" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg></div>
<div style="flex:1;min-width:0"><div style="font-size:14px;font-weight:500;color:var(--accent-black);margin-bottom:4px;line-height:1.4">投放话术库</div><div class="mono">// /v2 · 模板</div></div>
</a>
</div>
</div>
</section>
<!-- =========================================== §4.10 提示框 =========================================== -->
<section id="tip">
<div class="section-head">
<span class="mono-tag">// §4.10 · TIP</span>
<h2>提示框</h2>
<p>白底 · 1 px 虚线边框(<code class="tk">dashed</code>)· 8 px 圆角 · 加粗标题 + 正文。</p>
</div>
<div class="tip-demo">
<div class="head">小提示</div>
<div class="body">使用 <span class="mono-code">Ctrl K</span> 快速搜索任意项目、商品或资产。Tab 切换不同维度,Enter 直达。</div>
</div>
</section>
<!-- =========================================== §4.11 Modal =========================================== -->
<section id="modal">
<div class="section-head">
<span class="mono-tag">// §4.11 · MODAL</span>
<h2>弹窗 Modal</h2>
<p>居中 460480 px · 4 角 SVG 准星 · 8 px 圆角 · <code class="tk">backdrop-filter: blur(8px)</code> · 弹性入场。<strong>点击下方按钮打开 · ESC / 点击遮罩关闭。</strong></p>
</div>
<button class="btn btn-primary" id="open-modal">打开 Modal Demo</button>
</section>
<!-- =========================================== §4.11 Toast =========================================== -->
<section id="toast">
<div class="section-head">
<span class="mono-tag">// §4.11 · TOAST</span>
<h2>Toast 通知</h2>
<p>右下角浮出 · 300ms 弹性入场 · 2400ms 自动消失。<strong>触发演示:</strong></p>
</div>
<div style="display:flex;gap:10px;flex-wrap:wrap">
<button class="btn" data-toast='{"ti":"项目已保存","sub":"// 200 OK · /projects/12"}'>触发默认 Toast</button>
<button class="btn btn-primary" data-toast='{"ti":"商品生成完成","sub":"// 4 张待审核 · 02:34"}'>主 CTA Toast</button>
</div>
</section>
<!-- =========================================== §5 Mono 装饰 =========================================== -->
<section id="mono-decor">
<div class="section-head">
<span class="mono-tag">// §5 · MONO DECOR · 品牌签名</span>
<h2>Mono 装饰元素</h2>
<p>方括号标签 / 双斜杠注释 / 中点连接 —— 这些是流·Studio 独有的"调试视图感",<strong>Firecrawl 没有,绝对保留</strong></p>
</div>
<div class="subsection">
<h3>方括号标签</h3>
<div class="mono-sample-row">
<span class="mono-tag-sample">[ 200 OK ]</span>
<span class="mono-tag-sample">[ /v2 ]</span>
<span class="mono-tag-sample">[ .MP4 · 9:16 ]</span>
<span class="mono-tag-sample heat">[ STUDIO ]</span>
<span class="mono-tag-sample">[ ALL · 12 ] →</span>
</div>
</div>
<div class="subsection">
<h3>注释样式时间戳</h3>
<div class="mono" style="font-size:13px">// 05.14 · 周五 · 14:32</div>
</div>
<div class="subsection">
<h3>命令路径</h3>
<div class="mono" style="font-size:13px;color:var(--black-alpha-64)">/sidebar collapse · /toast dismiss · /modal open</div>
</div>
<div class="subsection">
<h3>数值后缀</h3>
<div style="font-size:32px;font-weight:500;letter-spacing:-.02em;font-variant-numeric:tabular-nums;color:var(--accent-black)">¥327<small style="font-size:15px;color:var(--black-alpha-48);font-weight:400">.40 K</small></div>
<p class="mono" style="margin-top:8px">// 主体大字 + 小字次级用 &lt;small&gt;</p>
</div>
<div class="subsection">
<h3>ASCII 散点(背景装饰)</h3>
<div style="font-family:var(--font-mono);font-size:11px;color:var(--black-alpha-12);line-height:1.4;letter-spacing:.04em;background:var(--surface);border:1px solid var(--border-faint);border-radius:8px;padding:18px 22px">
· · &nbsp;+<br>
·&nbsp; +XX+<br>
&nbsp;+XXXX·<br>
&nbsp;&nbsp; +X·
</div>
</div>
<div class="subsection">
<h3>强调单词上色</h3>
<p style="font-size:13.5px;color:var(--black-alpha-72);max-width:680px;line-height:1.7">
本月营收较上月增长 <b style="color:var(--accent-black)">+33%</b>,有 <b style="color:var(--accent-black)">5 个项目</b>处于"生成中"状态。其中 <b style="color:var(--accent-black)">2 个</b>需要重新调整模特模板。
</p>
<p class="mono" style="margin-top:8px">// 关键名词加深一档(不变橙),橙色只留给 CTA</p>
</div>
</section>
<!-- =========================================== §6 五种页面布局 =========================================== -->
<section id="layouts">
<div class="section-head">
<span class="mono-tag">// §6 · LAYOUT MODES · 5 种</span>
<h2>五种页面级布局模式</h2>
<p>页面骨架统一,<strong>内容区布局按用途分 5 类</strong>。新页面归类后选对应模式。</p>
</div>
<div class="subsection">
<div class="layout-card">
<div class="h"><span class="tag">A</span><span class="ti">看板型 · Dashboard</span></div>
<div class="desc">KPI 行 + 多个 section + 列表行 / shortcut 网格。</div>
<pre class="ascii">[ stats.with-corners · KPI 4 列 ]
[ section-h ]
[ ░░ recent-row × N ░░ ] [ shortcut × N ]
[ tip · 虚线提示 ]</pre>
<div class="pages">代表页:<strong>index.html · projects.html(列表)· library.html</strong></div>
</div>
<div class="layout-card">
<div class="h"><span class="tag">B</span><span class="ti">列表 + 筛选型 · List + Filter</span></div>
<div class="desc">Toolbar(搜索 + chip 筛选 + 视图切换)+ 卡片网格 + 分页 + 批量栏。</div>
<pre class="ascii">[ toolbar: search-inline + chip-wrap × n + view-toggle ] sticky top
[ result-meta · 共 N 条 ]
[ ░░ 卡片网格 / 列表 ░░ ]
[ pagination ] sticky bottom
[ bulk-bar(选中后显示) ] 吸底浮动</pre>
<div class="pages">代表页:<strong>products.html · projects.html · library.html · team.html</strong></div>
</div>
<div class="layout-card">
<div class="h"><span class="tag">C</span><span class="ti">编辑器型 · Editor / IDE</span></div>
<div class="desc">锁视口高度 · 多栏内部滚 · 大量页面级独有样式。<strong style="color:var(--accent-crimson)">⚠️ 这类定制最多 · 改之前先确认 restraint.css 没现成组件</strong></div>
<pre class="ascii">[ 左栏 · 资产/导航 sticky ] [ 中央 · 画布/参数 ] [ 右栏 · 预览/AI 助手 ]
└───────── 整页 viewport 高度锁定 · 不滚 main ────────┘</pre>
<div class="pages">代表页:<strong>pipeline.html · model-photo.html · image-optimize.html · studio.html</strong></div>
</div>
<div class="layout-card">
<div class="h"><span class="tag">D</span><span class="ti">表单 / 向导型 · Wizard / Form</span></div>
<div class="desc">左侧 sticky 步数条 + 右侧多 pane 同时显示(非 Tab 切换)。</div>
<pre class="ascii">[ .wizard ]
├─ .steps · 200 px sticky ← 左步数条
└─ .panes · 1fr ← 右滚
├─ .wiz-pane #step-1
├─ .wiz-pane #step-2
└─ .wiz-pane #step-3</pre>
<div class="pages">代表页:<strong>projects-new.html · products.html drawer · account.html · settings.html</strong></div>
</div>
<div class="layout-card">
<div class="h"><span class="tag">E</span><span class="ti">单卡型 · Single Screen</span></div>
<div class="desc">不渲染 sidebar/topbar · 全屏灰底 + 中心白卡。</div>
<pre class="ascii"> ┌─────────────────┐
│ │
│ .input × N │
│ .btn-primary │
│ │
└─────────────────┘</pre>
<div class="pages">代表页:<strong>login.html · register.html</strong></div>
</div>
</div>
</section>
<!-- =========================================== §7 待统一清单 =========================================== -->
<section id="audit">
<div class="section-head">
<span class="mono-tag">// §7 · AUDIT · V2.1 落地待统一清单 ★</span>
<h2>待统一清单</h2>
<p>扫完 18 个 HTML 发现的偏离点。按影响视觉一致性程度排序。<strong>改页面时遇到这些点,顺手改正。</strong></p>
</div>
<div class="subsection">
<span class="audit-section-label hi">// 高优先级 · 影响视觉对齐</span>
<table class="audit-table">
<thead><tr><th>#</th><th>问题</th><th>现状</th><th>应改为</th></tr></thead>
<tbody>
<tr><td>1</td><td class="problem">按钮等级混乱 ★</td><td class="now">各页随意选 .btn / .btn-primary / .btn-ghost,部分页面 2 个一级橙并列,"取消"被做成主橙;尺寸也乱(38/32/44 混)</td><td class="should">按 §4.1 三级体系:一个区域只 1 个一级(主动作) · 二级(并列动作) · 三级(辅助) · 尺寸默认 36 / lg 40 / sm 28</td></tr>
<tr><td>2</td><td class="problem">输入框高度</td><td class="now">products 38 / projects search 32 / login 36</td><td class="should">统一 36</td></tr>
<tr><td>3</td><td class="problem">Tab 激活样式</td><td class="now">product-detail 下划线 / library 底色填充</td><td class="should">统一下划线 + bottom 2 px heat</td></tr>
<tr><td>4</td><td class="problem">Hover 底色</td><td class="now">多数 bg-lighter / 部分 black-alpha-4</td><td class="should">统一 black-alpha-4</td></tr>
<tr><td>5</td><td class="problem">卡片标题字号</td><td class="now">projects 13.5 / products 14</td><td class="should">统一 14 / 500</td></tr>
<tr><td>6</td><td class="problem">卡片网格列宽</td><td class="now">products 240 / library auto 180 / projects-new 4 列</td><td class="should">商品 240 · 资产 180 · 通用 auto-fill 220</td></tr>
</tbody>
</table>
</div>
<div class="subsection">
<span class="audit-section-label mid">// 中优先级 · 语义偏离</span>
<table class="audit-table">
<thead><tr><th>#</th><th>问题</th><th>现状</th><th>应改为</th></tr></thead>
<tbody>
<tr><td>7</td><td class="problem">Pill 变体不全</td><td class="now">restraint.css 4 种 / library 用了 .pill.archive 没定义</td><td class="should">补 .pill.archive(灰)/ .pill.warn(honey)</td></tr>
<tr><td>8</td><td class="problem">X 关闭按钮</td><td class="now">drawer 30 / modal 32 / toast 28</td><td class="should">统一 32×32 / 8 px 圆角</td></tr>
<tr><td>9</td><td class="problem">label 字重</td><td class="now">products 500 / product-detail 600</td><td class="should">统一 500</td></tr>
<tr><td>10</td><td class="problem">mono 装饰</td><td class="now">部分页有 4 角 [ 200 OK ],部分没</td><td class="should">主工作台型必有 · 编辑器型可省</td></tr>
<tr><td>11</td><td class="problem">section-h 分隔</td><td class="now">部分 border-bottom / 部分没</td><td class="should">统一不用(留白即分隔)</td></tr>
</tbody>
</table>
</div>
<div class="subsection">
<span class="audit-section-label lo">// 低优先级 · 架构清理</span>
<table class="audit-table">
<thead><tr><th>#</th><th>问题</th><th>现状</th><th>应改为</th></tr></thead>
<tbody>
<tr><td>12</td><td class="problem">编辑器页 inline style 过大</td><td class="now">pipeline 795 / model-photo 1393 / platform-cover 1003 行</td><td class="should">抽 .stepper / .shot-card 到 restraint.css 或 editor.css</td></tr>
<tr><td>13</td><td class="problem">四角准星重复 SVG</td><td class="now">部分页定义自己的 SVG 背景</td><td class="should">全部改用 .with-corners + .corner-tr/.corner-bl</td></tr>
<tr><td>14</td><td class="problem">滚动条样式残留</td><td class="now">部分页 inline scrollbar-width: thin</td><td class="should">restraint.css 已全局隐藏 · 清理 inline</td></tr>
<tr><td>15</td><td class="problem">mono 字体里的中文</td><td class="now">部分页直接写 font-family: monospace</td><td class="should">全部换 var(--font-mono)</td></tr>
</tbody>
</table>
</div>
</section>
<!-- =========================================== §8 Don't List =========================================== -->
<section id="dont">
<div class="section-head">
<span class="mono-tag">// §8 · GUARDRAILS</span>
<h2>Don't List · 绝对禁止</h2>
<p>任何 mockup / 代码 review 时,对照此清单。<strong style="color:var(--accent-crimson)">每一条违反都判错</strong></p>
</div>
<div class="dodont-grid" style="margin-bottom:18px">
<div class="dodont do">
<span class="head">DO</span>
<div class="body">用 8 px 统一圆角 + 准星 + 装订线 + mono 装饰做"图纸感"</div>
</div>
<div class="dodont dont">
<span class="head">DON'T</span>
<div class="body">用 0 px 硬切角的卡片 —— V1 的做法,V2 起判错</div>
</div>
<div class="dodont do">
<span class="head">DO</span>
<div class="body">橙色 hover 用 <code class="tk heat">--heat-90</code> 等 alpha 阶梯</div>
</div>
<div class="dodont dont">
<span class="head">DON'T</span>
<div class="body">hover 时切换到更深的橙 hex(如 #D04E1F)</div>
</div>
<div class="dodont do">
<span class="head">DO</span>
<div class="body">主 CTA 用多层橙色阴影(4 层)制造发光感</div>
</div>
<div class="dodont dont">
<span class="head">DON'T</span>
<div class="body">用灰色阴影 / 文字阴影 / 通用 box-shadow 装饰</div>
</div>
</div>
<div style="background:var(--surface);border:1px solid var(--border-faint);border-radius:8px;padding:18px 22px">
<div class="dont-list-item"><span class="x">×</span><span><strong style="color:var(--accent-black)">渐变背景</strong> · 只有 hero 区可考虑,首选纯色。绝禁多色渐变。</span></div>
<div class="dont-list-item"><span class="x">×</span><span><strong style="color:var(--accent-black)">玻璃拟态</strong> · <code class="tk">backdrop-filter</code> 只用于 modal 遮罩</span></div>
<div class="dont-list-item"><span class="x">×</span><span><strong style="color:var(--accent-black)">彩色 emoji / filled icon</strong> · 一律 SVG line(stroke 1.5)</span></div>
<div class="dont-list-item"><span class="x">×</span><span><strong style="color:var(--accent-black)">多 accent 色</strong> · 全场只有橙色一个 accent</span></div>
<div class="dont-list-item"><span class="x">×</span><span><strong style="color:var(--accent-black)">大圆角容器(&gt;12 px)</strong> · 直接判错</span></div>
<div class="dont-list-item"><span class="x">×</span><span><strong style="color:var(--accent-black)">真 border + hover 边框消失</strong> · 用 inside-border ::before</span></div>
<div class="dont-list-item"><span class="x">×</span><span><strong style="color:var(--accent-black)">荧光鲜艳状态色</strong> · 避免霓虹绿、电光蓝、霓虹粉</span></div>
<div class="dont-list-item"><span class="x">×</span><span><strong style="color:var(--accent-black)">居中对齐大段正文</strong> · 全部左对齐</span></div>
<div class="dont-list-item"><span class="x">×</span><span><strong style="color:var(--accent-black)">装饰当主角</strong> · 场记板 / 丝绒 / 霓虹灯都不要</span></div>
<div class="dont-list-item"><span class="x">×</span><span><strong style="color:var(--accent-black)">无意义微动效</strong> · hover 旋转、缩放、彩虹流光,禁</span></div>
<div class="dont-list-item"><span class="x">×</span><span><strong style="color:var(--accent-black)">同一行混用直角和圆角</strong> · 用户原话:"不要有些是直角,胶囊又是圆角"</span></div>
<div class="dont-list-item"><span class="x">×</span><span><strong style="color:var(--accent-black)">页面 inline style 重写共享类</strong> · 要变体先改 restraint.css</span></div>
<div class="dont-list-item"><span class="x">×</span><span><strong style="color:var(--accent-black)">新建色值</strong> · 必须复用现有 token</span></div>
<div class="dont-list-item"><span class="x">×</span><span><strong style="color:var(--accent-black)">⌘ Unicode 字符</strong> · JetBrains Mono 不带该字形 · 用 "Ctrl K" 纯文本</span></div>
</div>
</section>
<!-- =========================================== §9 Checklist =========================================== -->
<section id="checklist">
<div class="section-head">
<span class="mono-tag">// §9 · CHECKLIST</span>
<h2>新页面 / 改页面 checklist</h2>
<p>每次开工前过一遍。<strong style="color:var(--accent-black)">3 个阶段都不能跳。</strong></p>
</div>
<div class="cl-card">
<div class="ch"><span class="stage">// STAGE 01</span><span class="ti">写代码前</span></div>
<ul class="cl-list">
<li><span class="mk"></span>已 Read [电商AI平台/design.md](design.md) §1 §3 §8(至少)</li>
<li><span class="mk"></span>用 Grep 查 restraint.css 是否已有该组件</li>
<li><span class="mk"></span>看本 design-system.html 找视觉参考</li>
<li><span class="mk"></span>不确定的设计点 → <strong>先问用户</strong>,不要凭感觉</li>
</ul>
</div>
<div class="cl-card">
<div class="ch"><span class="stage">// STAGE 02</span><span class="ti">写代码时</span></div>
<ul class="cl-list">
<li><span class="mk"></span>HTML 用 <code class="tk">app &gt; sidebar + main &gt; topbar + content</code> 骨架</li>
<li><span class="mk"></span>head 含 <code class="tk">assets/restraint.css</code> + Inter + JetBrains Mono</li>
<li><span class="mk"></span>body 末尾 <code class="tk">assets/shell.js</code></li>
<li><span class="mk"></span>标题区用 <code class="tk">.page-head &gt; h1 + .sub</code></li>
<li><span class="mk"></span>主操作按钮放 <code class="tk">.page-head &gt; .actions</code>(自动 40 px 高)</li>
<li><span class="mk"></span>子区块用 <code class="tk">.section-h &gt; h2 + .more</code></li>
<li><span class="mk"></span>按钮全 <code class="tk">.btn</code> 系列 · 不要自己写</li>
<li><span class="mk"></span>状态徽标全 <code class="tk">.pill.info/.ok/.err/.neutral</code></li>
<li><span class="mk"></span>输入框全 <code class="tk">.input / .select / .textarea</code> · 字段用 <code class="tk">.field</code></li>
<li><span class="mk"></span>浮层全用现成 Modal / Drawer / Toast</li>
<li><span class="mk"></span>图标 SVG line · stroke 1.5 · linecap round · <code class="tk">stroke="currentColor"</code></li>
<li><span class="mk"></span>时间戳 mono 注释 <code class="tk">// 05.22 · 周四</code></li>
<li><span class="mk"></span>强调单词加深(不变橙)<code class="tk">&lt;b style="color:var(--accent-black)"&gt;3 个&lt;/b&gt;</code></li>
<li><span class="mk"></span>数字加 <code class="tk">.num</code><code class="tk">tabular-nums</code></li>
<li><span class="mk"></span>状态色按语义选 <code class="tk">--heat / --accent-forest / --accent-crimson / --accent-honey</code></li>
</ul>
</div>
<div class="cl-card">
<div class="ch"><span class="stage">// STAGE 03</span><span class="ti">写完自检</span></div>
<ul class="cl-list">
<li><span class="mk"></span>对照 §8 Don't List 逐条过</li>
<li><span class="mk"></span>浏览器打开页面 · 截图 + 跟本 design-system.html 对比</li>
<li><span class="mk"></span>测 hover / focus / active / disabled 状态都正确</li>
<li><span class="mk"></span>测 dark mode(给 body 加 <code class="tk">.dark</code> class 看是否破)</li>
<li><span class="mk"></span>移动端缩到 1100 px 以下看响应式</li>
<li><span class="mk"></span>不在 master/main 上,在 dev 分支</li>
<li><span class="mk"></span>不带 <code class="tk">--no-verify</code>,不跳过 hook</li>
</ul>
</div>
</section>
</main>
</div>
<!-- ===== Modal HTML ===== -->
<div class="modal-bg" id="modal-mask">
<div class="modal" role="dialog">
<span class="corner-tr" aria-hidden></span>
<span class="corner-bl" aria-hidden></span>
<div class="modal-h">
<div class="ic-m"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 8v4M12 16h.01"/></svg></div>
<div class="ti">确认删除此商品?<span>// /products/dlt · IRREVERSIBLE</span></div>
</div>
<div class="modal-b">
该操作不可撤销。商品「夏季新款蕾丝连衣裙」及其关联的 <b style="color:var(--accent-black)">4 张候选图</b><b style="color:var(--accent-black)">2 段短视频</b>将一并删除。
</div>
<div class="modal-f">
<button class="btn" data-close-modal>取消</button>
<button class="btn btn-primary" data-close-modal>确认删除</button>
</div>
</div>
</div>
<!-- ===== Toast container ===== -->
<div class="toast-stack" id="toast-stack"></div>
<script>
/* ====== 复制色值 token 名 ====== */
document.querySelectorAll('[data-copy-grid] .swatch').forEach(sw => {
sw.addEventListener('click', () => {
const tk = sw.dataset.hex;
navigator.clipboard?.writeText(tk);
sw.classList.add('copied');
setTimeout(() => sw.classList.remove('copied'), 1200);
});
});
/* ====== Checkbox indeterminate click toggle ====== */
document.querySelectorAll('.ck.is-indeterminate input').forEach(cb => {
cb.addEventListener('change', e => {
e.target.closest('.ck').classList.remove('is-indeterminate');
});
});
/* ====== Tabs ====== */
document.querySelectorAll('[data-tabs]').forEach(group => {
const out = document.querySelector('[data-tab-content]');
group.addEventListener('click', e => {
const btn = e.target.closest('.ds-tab');
if (!btn) return;
group.querySelectorAll('.ds-tab').forEach(b => b.classList.remove('is-active'));
btn.classList.add('is-active');
if (out) out.textContent = btn.textContent;
});
});
/* ====== Subtabs ====== */
document.querySelectorAll('[data-subtabs]').forEach(group => {
group.addEventListener('click', e => {
const btn = e.target.closest('.ds-subtab');
if (!btn) return;
group.querySelectorAll('.ds-subtab').forEach(b => b.classList.remove('is-active'));
btn.classList.add('is-active');
});
});
/* ====== Modal ====== */
const mask = document.getElementById('modal-mask');
document.getElementById('open-modal').addEventListener('click', () => mask.classList.add('show'));
mask.addEventListener('click', e => {
if (e.target === mask || e.target.matches('[data-close-modal]')) mask.classList.remove('show');
});
document.addEventListener('keydown', e => { if (e.key === 'Escape') mask.classList.remove('show'); });
/* ====== Toast ====== */
const stack = document.getElementById('toast-stack');
document.querySelectorAll('[data-toast]').forEach(btn => {
btn.addEventListener('click', () => {
const data = JSON.parse(btn.dataset.toast);
const t = document.createElement('div');
t.className = 'toast show';
t.innerHTML = `
<div class="ic-t"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg></div>
<div class="txt">${data.ti}<span class="mono">${data.sub}</span></div>
`;
stack.appendChild(t);
setTimeout(() => { t.classList.add('is-leave'); setTimeout(() => t.remove(), 240); }, 2400);
});
});
/* ====== Nav active on scroll ====== */
const navLinks = document.querySelectorAll('.ds-nav a');
const sections = [...document.querySelectorAll('.ds-main > section')];
function syncNav() {
const y = window.scrollY + 100;
let cur = sections[0]?.id;
sections.forEach(s => { if (s.offsetTop <= y) cur = s.id; });
navLinks.forEach(a => a.classList.toggle('active', a.getAttribute('href') === '#' + cur));
}
window.addEventListener('scroll', syncNav, { passive: true });
syncNav();
</script>
</body>
</html>