AirShelf/电商AI平台/_archive/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

1731 lines
103 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 · 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">
<style>
/* ============================================================
Alibaba PuHuiTi 3.0 · 阿里巴巴普惠体 · 中文 web 字体
优先用 chinese-fonts-cdn 上的 woff2(已切片优化加载快)
失败回退到本地安装 → 系统 PingFang SC / Microsoft YaHei
============================================================ */
@font-face {
font-family: 'Alibaba PuHuiTi';
font-weight: 400;
font-style: normal;
font-display: swap;
src: local('Alibaba PuHuiTi 3.0'),
local('AlibabaPuHuiTi-3-55-Regular'),
local('Alibaba PuHuiTi 2.0'),
local('AlibabaPuHuiTi-2-55-Regular'),
url('https://chinese-fonts-cdn.deno.dev/packages/alibaba_puhuiti/dist/AlibabaPuHuiTi-3-55-Regular/AlibabaPuHuiTi-3-55-Regular.woff2') format('woff2');
}
@font-face {
font-family: 'Alibaba PuHuiTi';
font-weight: 500;
font-style: normal;
font-display: swap;
src: local('Alibaba PuHuiTi 3.0 Medium'),
local('AlibabaPuHuiTi-3-65-Medium'),
local('AlibabaPuHuiTi-2-65-Medium'),
url('https://chinese-fonts-cdn.deno.dev/packages/alibaba_puhuiti/dist/AlibabaPuHuiTi-3-65-Medium/AlibabaPuHuiTi-3-65-Medium.woff2') format('woff2');
}
@font-face {
font-family: 'Alibaba PuHuiTi';
font-weight: 600;
font-style: normal;
font-display: swap;
src: local('AlibabaPuHuiTi-3-75-SemiBold'),
local('AlibabaPuHuiTi-2-75-SemiBold'),
url('https://chinese-fonts-cdn.deno.dev/packages/alibaba_puhuiti/dist/AlibabaPuHuiTi-3-75-SemiBold/AlibabaPuHuiTi-3-75-SemiBold.woff2') format('woff2');
}
@font-face {
font-family: 'Alibaba PuHuiTi';
font-weight: 700;
font-style: normal;
font-display: swap;
src: local('Alibaba PuHuiTi 3.0 Bold'),
local('AlibabaPuHuiTi-3-85-Bold'),
local('AlibabaPuHuiTi-2-85-Bold'),
url('https://chinese-fonts-cdn.deno.dev/packages/alibaba_puhuiti/dist/AlibabaPuHuiTi-3-85-Bold/AlibabaPuHuiTi-3-85-Bold.woff2') format('woff2');
}
:root{
/* ============================================================
Color system V2.1 · Firecrawl-aligned
Reference: _design_src/firecrawl_playground_spec.md
============================================================ */
/* ===== Backgrounds (cold gray, no warm tint) ===== */
--background-base: #f9f9f9; /* page bg */
--background-lighter: #fbfbfb; /* container bg / hover plate */
--surface: #ffffff; /* card */
--surface-raised: #ffffff; /* modal / popover */
/* ===== Borders (3 levels, near-identical, semantic only) ===== */
--border-faint: #ededed; /* default 1px */
--border-muted: #e8e8e8;
--border-loud: #e6e6e6;
/* ===== Accent multi-color (Firecrawl 5-color signal palette) ===== */
--accent-black: #262626; /* primary foreground (not pure black) */
--accent-white: #ffffff;
--accent-amethyst: #9061ff; /* code / property */
--accent-bluetron: #2a6dfb; /* info */
--accent-crimson: #eb3424; /* error */
--accent-forest: #42c366; /* success */
--accent-honey: #ecb730; /* warning */
/* ===== Heat · single hue + 8 alpha levels (no hue shift on hover) ===== */
--heat: #fa5d19; /* 100% · main CTA */
--heat-90: rgba(250, 93, 25, .90);
--heat-40: rgba(250, 93, 25, .40); /* ring / edge */
--heat-20: rgba(250, 93, 25, .20); /* pill border / selection */
--heat-16: rgba(250, 93, 25, .16);
--heat-12: rgba(250, 93, 25, .12); /* tint bg */
--heat-8: rgba(250, 93, 25, .08);
--heat-4: rgba(250, 93, 25, .04);
/* ===== Black-alpha (20 levels · 024 uses #000, 32+ uses accent-black) ===== */
--black-alpha-1: rgba(0, 0, 0, .01);
--black-alpha-2: rgba(0, 0, 0, .02);
--black-alpha-3: rgba(0, 0, 0, .03);
--black-alpha-4: rgba(0, 0, 0, .04); /* hover bg */
--black-alpha-5: rgba(0, 0, 0, .05);
--black-alpha-6: rgba(0, 0, 0, .06);
--black-alpha-7: rgba(0, 0, 0, .07); /* active bg */
--black-alpha-8: rgba(0, 0, 0, .08);
--black-alpha-10: rgba(0, 0, 0, .10);
--black-alpha-12: rgba(0, 0, 0, .12); /* inside-border / disabled fg */
--black-alpha-16: rgba(0, 0, 0, .16);
--black-alpha-20: rgba(0, 0, 0, .20);
--black-alpha-24: rgba(0, 0, 0, .24);
--black-alpha-32: rgba(38, 38, 38, .32);
--black-alpha-40: rgba(38, 38, 38, .40);
--black-alpha-48: rgba(38, 38, 38, .48); /* placeholder */
--black-alpha-56: rgba(38, 38, 38, .56); /* secondary / inactive tab */
--black-alpha-64: rgba(38, 38, 38, .64); /* description */
--black-alpha-72: rgba(38, 38, 38, .72);
--black-alpha-88: rgba(38, 38, 38, .88);
/* ===== Legacy aliases (V2 names → V2.1 tokens, for backward compat) ===== */
--bg: var(--background-base);
--bg-soft: var(--background-lighter);
--card: var(--surface);
--ink: var(--accent-black);
--green: var(--accent-forest);
--red: var(--accent-crimson);
--green-bg: rgba(66, 195, 102, .08);
--green-bd: rgba(66, 195, 102, .20);
--red-bg: rgba(235, 52, 36, .08);
--red-bd: rgba(235, 52, 36, .20);
--ink-alpha-4: var(--black-alpha-4);
--ink-alpha-7: var(--black-alpha-7);
--ink-alpha-12: var(--black-alpha-12);
--ink-alpha-24: var(--black-alpha-24);
--ink-alpha-32: var(--black-alpha-32);
--ink-alpha-48: var(--black-alpha-48);
--ink-alpha-56: var(--black-alpha-56);
--ink-alpha-64: var(--black-alpha-64);
--ink-alpha-72: var(--black-alpha-72);
--ink-alpha-88: var(--black-alpha-88);
/* ===== Radius ===== */
--r-sm: 4px;
--r-md: 8px;
--r-pill: 999px;
/* ===== Font ===== */
/* 混排策略:Inter 列首 → 英文/数字/符号用 Inter(Inter 不含 CJK)
→ 中文自动 fallthrough 到 Alibaba PuHuiTi → 兜底系统中文 */
--font-sans: 'Inter', 'Alibaba PuHuiTi', 'PingFang SC', 'Microsoft YaHei', system-ui, sans-serif;
--font-mono: 'JetBrains Mono', 'Geist Mono', ui-monospace, monospace;
/* Inter 系列 · 独立 token,给 Ctrl K / 全英文徽标这种"强制纯英文"场景用 */
--font-inter: 'Inter', system-ui, sans-serif;
/* ===== Transition ===== */
--t-fast: 100ms ease;
--t-base: 200ms ease;
--t-slow: 300ms cubic-bezier(0.34, 1.56, 0.64, 1);
}
::selection{ background: var(--heat-20); color: var(--heat); }
*,*::before,*::after{box-sizing:border-box}
html,body{margin:0;padding:0}
body{
font-family:var(--font-sans);
font-size:14px;
color:var(--ink);
background:var(--bg);
line-height:1.65;
-webkit-font-smoothing:antialiased;
-moz-osx-font-smoothing:grayscale;
text-rendering:optimizeLegibility;
}
/* === Layout: sidebar + main === */
.layout{display:grid;grid-template-columns:248px 1fr;min-height:100vh}
.sidebar{
position:sticky;top:0;height:100vh;
border-right:1px solid var(--border-faint);
background:var(--card);
padding:40px 28px;
overflow-y:auto;
}
.sidebar h1{
font-size:17px;font-weight:600;letter-spacing:-.01em;
margin:0 0 6px;line-height:1.4;
}
.sidebar .mono-sub{
font-family:var(--font-mono);font-size:10.5px;color:var(--ink-alpha-48);
letter-spacing:.04em;margin-bottom:32px;
}
.nav-list{list-style:none;padding:0;margin:0}
.nav-list li{margin:0}
.nav-list a{
display:block;padding:8px 12px;
font-size:13px;color:var(--ink-alpha-64);
text-decoration:none;border-radius:var(--r-md);
transition:background var(--t-base),color var(--t-base);
}
.nav-list a:hover{background:var(--ink-alpha-4);color:var(--ink)}
.nav-list a.active{background:var(--heat-12);color:var(--heat)}
.nav-list .nav-group{
font-family:var(--font-mono);font-size:10px;
letter-spacing:.06em;color:var(--ink-alpha-32);
margin:24px 0 8px;padding:0 12px;text-transform:uppercase;
}
.main{padding:72px 80px 120px;max-width:1280px}
.main > section{margin-bottom:104px;scroll-margin-top:32px}
.main > section:last-child{margin-bottom:0}
.section-head{margin-bottom:44px;border-bottom:1px solid var(--border-faint);padding-bottom:28px}
.section-head .mono-tag{
display:inline-block;font-family:var(--font-mono);font-size:11px;
color:var(--ink-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;
}
.section-head p{
font-size:14px;color:var(--ink-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;
}
.subsection h3 .mono-num{
font-family:var(--font-mono);font-size:11px;color:var(--ink-alpha-32);
font-weight:400;letter-spacing:.04em;
}
.subsection p.lead{
font-size:13px;color:var(--ink-alpha-56);margin:0 0 22px;line-height:1.8;max-width:720px;
}
/* === Mono helper === */
.mono{font-family:var(--font-mono);font-size:11.5px;letter-spacing:.04em;color:var(--ink-alpha-56)}
.kbd{
display:inline-flex;align-items:center;gap:3px;
font-family:var(--font-mono);font-size:10.5px;line-height:1;
background:var(--background-lighter);border:1px solid var(--border-faint);
border-radius:var(--r-sm);padding:3px 6px;color:var(--black-alpha-64);
letter-spacing:.04em;
}
.kbd svg{display:block;width:10px;height:10px;flex-shrink:0}
/* === Hero === */
.hero{
position:relative;
border:1px solid var(--border-faint);
background:var(--card);
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}
.hero p{font-size:15px;color:var(--ink-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(--ink-alpha-48);letter-spacing:.04em}
/* === Inside-border core utility === */
.inside-border{position:relative}
.inside-border::before{
content:'';position:absolute;inset:0;
border:1px solid var(--ink-alpha-12);
border-radius:inherit;pointer-events:none;
transition:opacity var(--t-base),border-color var(--t-base);
}
/* === Color tokens grid === */
.swatch-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(190px,1fr));gap:14px}
.swatch{
background:var(--card);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 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(--ink);font-weight:500;letter-spacing:.02em;line-height:1.5}
.swatch .val{font-family:var(--font-mono);font-size:10.5px;color:var(--ink-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 sample === */
.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(--ink-alpha-48);letter-spacing:.04em;line-height:1.65}
.type-row .meta-col strong{display:block;color:var(--ink);font-family:var(--font-sans);font-size:13px;font-weight:500;margin-bottom:6px;letter-spacing:0}
.type-row .sample{color:var(--ink)}
/* === Radius scale === */
.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(--card);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(--ink-alpha-48);letter-spacing:.04em}
.radius-box .px{font-family:var(--font-mono);font-size:13px;color:var(--ink);font-weight:500}
/* === 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(--ink-alpha-64);background:var(--card);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(--ink-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(--card);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(--ink-alpha-12)}
.icon-box{width:32px;height:32px;border-radius:var(--r-md);background:var(--heat-12);display:grid;place-items:center}
.icon-box svg{stroke:var(--heat);width:16px;height:16px}
/* === Buttons === */
.btn{
display:inline-flex;align-items:center;justify-content:center;gap:6px;
height:32px;padding:0 14px;
background:var(--card);color:var(--ink);
font-family:inherit;font-size:13px;font-weight:500;line-height:1;
border:0;cursor:pointer;
border-radius:var(--r-md);
position:relative;outline:none;
transition:background var(--t-base),transform var(--t-fast),box-shadow var(--t-fast);
}
.btn::before{
content:'';position:absolute;inset:0;
border:1px solid var(--ink-alpha-12);
border-radius:inherit;pointer-events:none;
transition:opacity var(--t-base),border-color var(--t-base);
}
.btn:hover{background:var(--ink-alpha-4)}
.btn:hover::before{opacity:0}
.btn:active{background:var(--ink-alpha-7);transform:scale(.99)}
.btn:focus-visible::before{opacity:0}
.btn:focus-visible{box-shadow:0 0 0 2px var(--bg),0 0 0 4px var(--heat-40)}
.btn[disabled],.btn.is-disabled{
background:var(--black-alpha-5);color:var(--black-alpha-32);
cursor:not-allowed;transform:none;
}
.btn[disabled]:hover,.btn.is-disabled:hover{background:var(--black-alpha-5)}
.btn[disabled]::before,.btn.is-disabled::before,
.btn[disabled]:hover::before,.btn.is-disabled:hover::before{opacity:1;border-color:var(--black-alpha-12)}
.btn-primary{
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 0.5px 0.5px rgba(250,93,25,.16);
}
.btn-primary::before{display:none}
.btn-primary:hover{
background:var(--heat);
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 0.5px 0.5px rgba(250,93,25,.16);
}
.btn-primary:active{transform:scale(.995);box-shadow:inset 0 -4px 8px rgba(250,93,25,.28),0 1px 2px rgba(250,93,25,.16)}
.btn-primary[disabled],.btn-primary.is-disabled{
background:var(--heat-40);color:#fff;box-shadow:none;cursor:not-allowed;
}
.btn-ghost{background:transparent;color:var(--ink-alpha-56)}
.btn-ghost::before{display:none}
.btn-ghost:hover{background:var(--ink-alpha-4);color:var(--ink)}
.btn-ghost:active{background:var(--ink-alpha-7)}
.btn-sm{height:28px;padding:0 10px;font-size:12px}
.btn-lg{height:40px;padding:0 18px;font-size:14px}
.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(--ink-alpha-48);
letter-spacing:.04em;width:96px;flex-shrink:0;
}
/* Force visual states for demo */
.btn.demo-hover{background:var(--ink-alpha-4)}
.btn.demo-hover::before{opacity:0}
.btn.demo-active{background:var(--ink-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 0.5px 0.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(--ink-alpha-4);color:var(--ink)}
.btn-ghost.demo-active{background:var(--ink-alpha-7)}
.btn.demo-focus{box-shadow:0 0 0 2px var(--bg),0 0 0 4px var(--heat-40)}
.btn.demo-focus::before{opacity:0}
/* === Pills === */
.pill{
display:inline-flex;align-items:center;gap:6px;
font-weight:500;border-radius:var(--r-pill);
position:relative;
}
.pill .dot{display:block;border-radius:50%;background:currentColor}
.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-info{color:var(--heat);background:var(--heat-12);border:1px solid var(--heat-20)}
.pill-ok{color:var(--green);background:var(--green-bg);border:1px solid var(--green-bd)}
.pill-err{color:var(--red);background:var(--red-bg);border:1px solid var(--red-bd)}
.pill-row{display:flex;gap:14px;flex-wrap:wrap;align-items:center}
/* === Inputs === */
.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(--ink-alpha-48);letter-spacing:.04em}
.input{
width:100%;max-width:380px;height:36px;
padding:0 14px;background:var(--card);color:var(--ink);
font-family:inherit;font-size:14px;
border:0;border-radius:var(--r-md);
position:relative;outline:none;
transition:background var(--t-base);
}
.input-wrap{position:relative;display:inline-block;max-width:380px;width:100%}
.input-wrap::before{
content:'';position:absolute;inset:0;
border:1px solid var(--ink-alpha-12);
border-radius:var(--r-md);pointer-events:none;
transition:border-color var(--t-base),box-shadow var(--t-base);
}
.input-wrap:hover::before{border-color:var(--ink-alpha-24)}
.input-wrap.is-focus::before{border-color:var(--heat-40);box-shadow:inset 0 0 0 1px var(--heat-40)}
.input-wrap.is-error::before{border-color:var(--red);box-shadow:inset 0 0 0 1px var(--red-bd)}
.input-wrap.is-error .input{background:var(--red-bg)}
.input-wrap.is-disabled::before{border-color:var(--black-alpha-12)}
.input-wrap.is-disabled .input{background:var(--black-alpha-5);color:var(--black-alpha-32);cursor:not-allowed}
.input-wrap.is-disabled .input::placeholder{color:var(--black-alpha-24)}
.input::placeholder{color:var(--ink-alpha-48)}
.search-wrap{position:relative;max-width:440px}
.search-wrap .ic-left{
position:absolute;left:14px;top:50%;transform:translateY(-50%);
color:var(--black-alpha-56);
pointer-events:none;
z-index:2; /* 关键:压在 input bg 之上,否则被白底盖住 */
display:flex; /* 防止 SVG 行高继承导致偏移 */
}
.search-wrap .input{padding-left:42px;padding-right:64px}
.search-wrap .k{
position:absolute;right:14px;top:50%;transform:translateY(-50%);
font-family:var(--font-inter); /* Inter Bold,不再用 mono */
font-weight:700;
font-size:11.5px;
color:var(--black-alpha-56);
letter-spacing:.02em;
pointer-events:none;z-index:2;
line-height:1;
}
/* === Checkbox / Radio / Switch === */
.ck-row{display:flex;gap:24px;align-items:center;flex-wrap:wrap}
.ck{display:inline-flex;align-items:center;gap:10px;cursor:pointer;user-select:none;font-size:14px}
.ck input{display:none}
.ck .ck-box{
width:16px;height:16px;border-radius:var(--r-sm);
background:var(--card);position:relative;flex-shrink:0;
transition:background var(--t-base),box-shadow var(--t-base);
box-shadow:inset 0 0 0 1px var(--ink-alpha-24);
}
.ck:hover .ck-box{box-shadow:inset 0 0 0 1px var(--ink-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(--bg-soft);box-shadow:inset 0 0 0 1px var(--ink-alpha-12)}
.rd{display:inline-flex;align-items:center;gap:10px;cursor:pointer;user-select:none;font-size:14px}
.rd input{display:none}
.rd .rd-box{
width:16px;height:16px;border-radius:50%;
background:var(--card);position:relative;flex-shrink:0;
box-shadow:inset 0 0 0 1px var(--ink-alpha-24);
transition:box-shadow var(--t-base);
}
.rd:hover .rd-box{box-shadow:inset 0 0 0 1px var(--ink-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{display:inline-flex;align-items:center;gap:12px;cursor:pointer;user-select:none;font-size:14px}
.sw input{display:none}
.sw .sw-box{
width:28px;height:16px;border-radius:var(--r-pill);
background:var(--ink-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 === */
.tabs{border-bottom:1px solid var(--border-faint);display:flex;gap:0;margin-bottom:16px}
.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(--ink-alpha-56);
transition:color var(--t-base),background var(--t-base);
border-radius:var(--r-md) var(--r-md) 0 0;
}
.tab:hover{color:var(--ink);background:var(--ink-alpha-4)}
.tab.is-active{color:var(--ink)}
.tab.is-active::after{
content:'';position:absolute;left:0;right:0;bottom:-1px;
height:2px;background:var(--heat);
}
.subtabs{display:flex;gap:0;margin-bottom:24px}
.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(--ink-alpha-56);
transition:color var(--t-base);
border-radius:var(--r-md);
}
.subtab svg{opacity:.6;transition:opacity var(--t-base)}
.subtab:hover{color:var(--ink)}
.subtab.is-active{color:var(--ink)}
.subtab.is-active svg{opacity:1;color:var(--heat)}
.subtab-divider{width:1px;height:12px;background:var(--ink-alpha-7);margin:0 4px;align-self:center}
/* === Card / Shortcut / Tip / Stats === */
.card{
background:var(--card);border:1px solid var(--border-faint);
border-radius:var(--r-md);padding:28px 30px;
}
.shortcut{
display:flex;align-items:center;gap:16px;
background:var(--card);border:1px solid var(--border-faint);
border-radius:var(--r-md);padding:18px 20px;
cursor:pointer;text-decoration:none;color:inherit;
transition:background var(--t-base);
}
.shortcut:hover{background:var(--ink-alpha-4)}
.shortcut:active{transform:scale(.99)}
.shortcut .meta{flex:1;min-width:0}
.shortcut .title{font-size:14px;font-weight:500;color:var(--ink);margin-bottom:4px;line-height:1.4}
.shortcut .desc{font-family:var(--font-mono);font-size:11.5px;color:var(--ink-alpha-48);letter-spacing:.04em;line-height:1.5}
.tip{
background:var(--card);border:1px dashed var(--border-loud);
border-radius:var(--r-md);padding:20px 24px;
}
.tip .head{font-size:14px;font-weight:500;margin-bottom:10px;color:var(--ink);line-height:1.4}
.tip .body{font-size:13px;color:var(--ink-alpha-64);line-height:1.8}
.tip .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}
.stats{
background:var(--card);border:1px solid var(--border-faint);
border-radius:var(--r-md);
display:grid;grid-template-columns:repeat(4,1fr);
position:relative;
}
.stats .cell{padding:28px 30px;border-right:1px solid var(--border-faint)}
.stats .cell:last-child{border-right:0}
.stats .lbl-row{display:flex;align-items:center;gap:10px;margin-bottom:14px}
.stats .lbl{font-family:var(--font-mono);font-size:11px;color:var(--ink-alpha-48);letter-spacing:.06em;text-transform:uppercase}
.stats .num{font-size:32px;font-weight:500;letter-spacing:-.02em;font-variant-numeric:tabular-nums;line-height:1.1;color:var(--ink)}
.stats .num small{font-size:15px;color:var(--ink-alpha-48);font-weight:400}
.stats .delta{font-family:var(--font-mono);font-size:11.5px;color:var(--ink-alpha-48);margin-top:10px}
.stats .delta .up{color:var(--green)}
/* progress bar segments · 语义色 */
.prog{display:flex;gap:3px;margin-top:8px}
.prog span{
width:18px;height:5px;border-radius:2px;
background:var(--black-alpha-8);
display:inline-block;
transition:background var(--t-base);
}
.prog span.done{background:var(--accent-forest)} /* 已完成 = 绿 */
.prog span.now{
background:var(--heat); /* 进行中 = 橙 + 脉动 */
animation:prog-pulse 1.4s ease-in-out infinite;
}
.prog span.err{background:var(--accent-crimson)} /* 失败 = 红 */
@keyframes prog-pulse{
0%,100%{opacity:1;transform:scaleY(1)}
50%{opacity:.55;transform:scaleY(.7)}
}
/* === List row === */
.list-card{background:var(--card);border:1px solid var(--border-faint);border-radius:var(--r-md);overflow:hidden}
.list-row{
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:last-child{border-bottom:0}
.list-row:hover{background:var(--ink-alpha-4)}
.list-row .thumb{
width:56px;height:72px;background:var(--bg-soft);
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(--ink-alpha-48);letter-spacing:.04em;
}
.list-row .meta .ti{font-size:14px;font-weight:500;color:var(--ink);margin-bottom:6px;line-height:1.4}
.list-row .meta .sub{font-family:var(--font-mono);font-size:11.5px;color:var(--ink-alpha-48);letter-spacing:.02em;line-height:1.5}
/* === Toast === */
.toast-stack{position:fixed;right:24px;bottom:24px;display:flex;flex-direction:column;gap:10px;z-index:1000;pointer-events:none}
.toast{
pointer-events:auto;
display:flex;align-items:center;gap:14px;
background:var(--card);border:1px solid var(--border-faint);
border-radius:var(--r-md);padding:16px 20px;min-width:300px;max-width:400px;
box-shadow:0 4px 20px rgba(21,20,15,.06);
animation:toastIn var(--t-slow) both;
}
.toast.is-leave{animation:toastOut 200ms forwards}
.toast .ic-box{width:28px;height:28px;border-radius:var(--r-md);background:var(--heat-12);display:grid;place-items:center;flex-shrink:0}
.toast .ic-box svg{stroke:var(--heat);width:14px;height:14px}
.toast .ti{font-size:14px;font-weight:500;color:var(--ink);line-height:1.4}
.toast .sub{font-family:var(--font-mono);font-size:11px;color:var(--ink-alpha-48);letter-spacing:.04em;margin-top:3px}
@keyframes toastIn{from{transform:translateX(420px);opacity:0}to{transform:translateX(0);opacity:1}}
@keyframes toastOut{to{transform:translateX(420px);opacity:0}}
/* === Modal === */
.modal-mask{
position:fixed;inset:0;background:rgba(21,20,15,.42);backdrop-filter:blur(8px);
display:none;align-items:center;justify-content:center;z-index:900;
animation:fadeIn 200ms both;
}
.modal-mask.is-open{display:flex}
.modal{
background:var(--card);border:1px solid var(--border-faint);
border-radius:var(--r-md);width:460px;position:relative;
animation:modalIn 250ms cubic-bezier(0.34,1.56,0.64,1) both;
}
.modal .corner{position:absolute;width:22px;height:21px;color:var(--border-muted)}
.modal .corner.tl{top:-10.5px;left:-11px}
.modal .corner.tr{top:-10.5px;right:-11px;transform:scaleX(-1)}
.modal .corner.bl{bottom:-10.5px;left:-11px;transform:scaleY(-1)}
.modal .corner.br{bottom:-10.5px;right:-11px;transform:scale(-1,-1)}
.modal .head{display:flex;align-items:center;gap:16px;padding:24px 28px;border-bottom:1px solid var(--border-faint)}
.modal .head .ic-box{width:36px;height:36px;border-radius:var(--r-md);background:var(--heat-12);display:grid;place-items:center;flex-shrink:0}
.modal .head .ic-box svg{stroke:var(--heat);width:18px;height:18px}
.modal .head .ti{font-size:16px;font-weight:500;color:var(--ink);letter-spacing:-.01em;line-height:1.4}
.modal .head .sub{font-family:var(--font-mono);font-size:11px;color:var(--ink-alpha-48);letter-spacing:.04em;margin-top:4px}
.modal .body{padding:24px 28px;font-size:14px;color:var(--ink-alpha-72);line-height:1.8}
.modal .foot{display:flex;justify-content:flex-end;gap:12px;padding:18px 28px;border-top:1px solid var(--border-faint)}
@keyframes fadeIn{from{opacity:0}to{opacity:1}}
@keyframes modalIn{from{opacity:0;transform:scale(.96)}to{opacity:1;transform:scale(1)}}
/* === Container border-x demo === */
.container-demo{
position:relative;margin:36px auto 24px;
max-width:720px;padding:48px 56px;
background:var(--bg);
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(--card);border:1px solid var(--border-faint);
border-radius:var(--r-md);padding:24px;
font-size:13px;color:var(--ink-alpha-72);text-align:center;
}
/* === Mono decoration samples === */
.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(--ink-alpha-48);background:var(--bg-soft);
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)}
/* === Don't / Do === */
.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)}
.dodont.do{border-color:var(--green-bd);background:var(--green-bg)}
.dodont.do .head{background:var(--green);color:#fff}
.dodont.dont{border-color:var(--red-bd);background:var(--red-bg)}
.dodont.dont .head{background:var(--red);color:#fff}
.dodont .body{font-size:12.5px;line-height:1.7;color:var(--ink-alpha-72)}
.dont-list-item{
display:flex;align-items:flex-start;gap:10px;
font-size:12.5px;line-height:1.7;color:var(--ink-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(--red);font-family:var(--font-mono);flex-shrink:0;margin-top:2px}
/* Codebox */
.codebox{
background:var(--bg-soft);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(--ink-alpha-88);overflow-x:auto;letter-spacing:.02em;
white-space:pre;
}
.codebox .c-key{color:var(--heat)}
.codebox .c-val{color:var(--ink-alpha-64)}
.codebox .c-comment{color:var(--ink-alpha-32)}
/* responsive */
@media(max-width:980px){
.layout{grid-template-columns:1fr}
.sidebar{position:relative;height:auto;border-right:0;border-bottom:1px solid var(--border-faint)}
.main{padding:32px 24px 64px}
.stats{grid-template-columns:repeat(2,1fr)}
.stats .cell:nth-child(2){border-right:0}
.stats .cell:nth-child(1),.stats .cell:nth-child(2){border-bottom:1px solid var(--border-faint)}
}
</style>
</head>
<body>
<div class="layout">
<!-- ============ SIDEBAR ============ -->
<aside class="sidebar">
<h1>流·Studio<br>设计系统</h1>
<div class="mono-sub">// V2 · 2026-05-15 · INTERACTIVE</div>
<ul class="nav-list">
<li class="nav-group">// FOUNDATION</li>
<li><a href="#tokens">色彩 Tokens</a></li>
<li><a href="#type">字体系统</a></li>
<li><a href="#radius">圆角阶梯</a></li>
<li><a href="#icons">Icon 系统</a></li>
<li class="nav-group">// COMPONENTS</li>
<li><a href="#buttons">按钮</a></li>
<li><a href="#pills">胶囊 Pills</a></li>
<li><a href="#inputs">输入框</a></li>
<li><a href="#form-controls">表单控件</a></li>
<li><a href="#tabs">Tab</a></li>
<li><a href="#cards">卡片 / 快捷入口</a></li>
<li><a href="#stats">KPI 统计</a></li>
<li><a href="#list">列表行</a></li>
<li><a href="#tip">提示框 / 进度</a></li>
<li><a href="#modal">Modal · 弹窗</a></li>
<li><a href="#toast">Toast · 通知</a></li>
<li class="nav-group">// SIGNATURE</li>
<li><a href="#container">主容器装订线</a></li>
<li><a href="#mono-decor">Mono 装饰元素</a></li>
<li class="nav-group">// GUARDRAILS</li>
<li><a href="#dont">Don't List</a></li>
</ul>
</aside>
<!-- ============ MAIN ============ -->
<main class="main">
<!-- HERO -->
<div class="hero">
<span class="badge">// V2 · INTERACTIVE</span>
<h1>流·Studio 设计系统</h1>
<p>所有 token、组件、状态的可交互参照。基于 Firecrawl Playground 实测规范校准。 hover / 点击下方组件可看到真实交互反馈。</p>
<div class="meta">
<span>[ Restraint · v2.0 ]</span>
<span>·</span>
<span>// based on DESIGN_SPEC_V2.md</span>
</div>
</div>
<!-- =========================================== -->
<!-- §1 COLOR TOKENS -->
<!-- =========================================== -->
<section id="tokens">
<div class="section-head">
<span class="mono-tag">// §1 · COLOR TOKENS · V2.1 · FIRECRAWL-ALIGNED</span>
<h2>色彩系统</h2>
<p>V2.1 全面对齐 Firecrawl Playground 实测色板:**冷灰底**(非米白)· **#FA5D19 主橙**(更亮一档)· **20 档 black-alpha 阶梯**(替代 11 档 ink-alpha)· **5 色 accent 多彩点**(amethyst / bluetron / crimson / forest / honey)。点击任何色块复制值。</p>
</div>
<div class="subsection">
<h3>表面 / 背景 <span class="mono-num">// 4 档 · 冷灰无色相</span></h3>
<p class="lead">告别 V2 的暖米白(#FAF9F5),全面切换 Firecrawl 的纯冷灰。<code class="mono" style="background:var(--background-lighter);padding:1px 6px;border-radius:4px">--bg/--bg-soft/--card</code> 作为 legacy 别名仍可用。</p>
<div class="swatch-grid" data-copy-grid>
<div class="swatch" data-hex="#f9f9f9"><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="#fbfbfb"><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="#ffffff"><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="#ffffff"><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 个色阶,肉眼几乎看不出。**用语义,不用视觉对比**——80% 场景用 <code class="mono" style="background:var(--background-lighter);padding:1px 6px;border-radius:4px">--border-faint</code></p>
<div class="swatch-grid" data-copy-grid>
<div class="swatch" data-hex="#ededed"><div class="chip" style="background:#ededed"></div><div class="meta-row"><div class="name">--border-faint</div><div class="val">#ededed · 默认 ★</div><div class="copy">copied</div></div></div>
<div class="swatch" data-hex="#e8e8e8"><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="#e6e6e6"><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">从 V2 砖红 <code class="mono" style="background:var(--background-lighter);padding:1px 6px;border-radius:4px">#E55B26</code> 调亮到 Firecrawl 实测 <code class="mono" style="background:var(--heat-12);color:var(--heat);padding:1px 6px;border-radius:4px">#FA5D19</code>(更红更饱和)。**全靠 alpha 叠加,绝不换 hue。** hover 不再切换到更深的橙,而是用 90% / 16% 这些档位组合。</p>
<div class="swatch-grid" data-copy-grid>
<div class="swatch" data-hex="#fa5d19"><div class="chip" style="background:#fa5d19"></div><div class="meta-row"><div class="name">--heat</div><div class="val">#fa5d19 · 100% · CTA ★</div><div class="copy">copied</div></div></div>
<div class="swatch" data-hex="rgba(250,93,25,.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="rgba(250,93,25,.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="rgba(250,93,25,.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="rgba(250,93,25,.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="rgba(250,93,25,.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="rgba(250,93,25,.08)"><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="rgba(250,93,25,.04)"><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">**新增章节 · 取自 Firecrawl 实测**。这 5 色只用于**语义信号**(代码高亮 / info / 状态色),**禁止做大面积装饰**——全场依然只有橙色一个 accent。<code class="mono" style="background:var(--heat-12);color:var(--heat);padding:1px 6px;border-radius:4px">--accent-black</code> 替代 V2 的 <code class="mono" style="background:var(--background-lighter);padding:1px 6px;border-radius:4px">--ink #15140F</code>(更柔和的灰黑)。</p>
<div class="swatch-grid" data-copy-grid>
<div class="swatch" data-hex="#262626"><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="#ffffff"><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="#9061ff"><div class="chip" style="background:#9061ff"></div><div class="meta-row"><div class="name">--accent-amethyst</div><div class="val">#9061ff · 紫 / code property</div><div class="copy">copied</div></div></div>
<div class="swatch" data-hex="#2a6dfb"><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="#eb3424"><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="#42c366"><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="#ecb730"><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>Black-Alpha 阶梯 <span class="mono-num">// 20 档 · 替代 V2 的 11 档 ink-alpha</span></h3>
<p class="lead">**核心工具尺。** 024% 用 <code class="mono">rgba(0,0,0,...)</code> 纯黑透明;**32% 起换 <code class="mono">rgba(38,38,38,...)</code>**(即 accent-black 作底)避免叠出"灰中带蓝"——这是 Firecrawl 的细节技巧,我们 1:1 复刻。dark mode 时这套 token 自动翻转为 white-alpha。原 <code class="mono">--ink-alpha-*</code> 全部作为 legacy 别名映射到对应 black-alpha。</p>
<div class="swatch-grid" data-copy-grid>
<div class="swatch" data-hex="rgba(0,0,0,.01)"><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="rgba(0,0,0,.02)"><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="rgba(0,0,0,.03)"><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="rgba(0,0,0,.04)"><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="rgba(0,0,0,.05)"><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% · tab 分隔</div><div class="copy">copied</div></div></div>
<div class="swatch" data-hex="rgba(0,0,0,.06)"><div class="chip with-grid"><div style="position:absolute;inset:0;background:rgba(0,0,0,.06)"></div></div><div class="meta-row"><div class="name">--black-alpha-6</div><div class="val">6%</div><div class="copy">copied</div></div></div>
<div class="swatch" data-hex="rgba(0,0,0,.07)"><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="rgba(0,0,0,.08)"><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%</div><div class="copy">copied</div></div></div>
<div class="swatch" data-hex="rgba(0,0,0,.10)"><div class="chip with-grid"><div style="position:absolute;inset:0;background:rgba(0,0,0,.10)"></div></div><div class="meta-row"><div class="name">--black-alpha-10</div><div class="val">10%</div><div class="copy">copied</div></div></div>
<div class="swatch" data-hex="rgba(0,0,0,.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="rgba(0,0,0,.16)"><div class="chip with-grid"><div style="position:absolute;inset:0;background:rgba(0,0,0,.16)"></div></div><div class="meta-row"><div class="name">--black-alpha-16</div><div class="val">16%</div><div class="copy">copied</div></div></div>
<div class="swatch" data-hex="rgba(0,0,0,.20)"><div class="chip with-grid"><div style="position:absolute;inset:0;background:rgba(0,0,0,.20)"></div></div><div class="meta-row"><div class="name">--black-alpha-20</div><div class="val">20%</div><div class="copy">copied</div></div></div>
<div class="swatch" data-hex="rgba(0,0,0,.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%</div><div class="copy">copied</div></div></div>
<div class="swatch" data-hex="rgba(38,38,38,.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="rgba(38,38,38,.40)"><div class="chip" style="background:rgba(38,38,38,.40)"></div><div class="meta-row"><div class="name">--black-alpha-40</div><div class="val">40%</div><div class="copy">copied</div></div></div>
<div class="swatch" data-hex="rgba(38,38,38,.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="rgba(38,38,38,.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="rgba(38,38,38,.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="rgba(38,38,38,.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="rgba(38,38,38,.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>
<div class="subsection">
<h3>状态色 <span class="mono-num">// 用 accent-forest / crimson 作语义</span></h3>
<p class="lead">V2 的 <code class="mono">--green #3F6B3F</code>(深森林绿)与 <code class="mono">--red #B33A2A</code>(暗砖红)替换为 Firecrawl 的 <code class="mono">--accent-forest #42c366</code><code class="mono">--accent-crimson #eb3424</code>——更明亮、更接近真实"信号灯"颜色,但仍保持非荧光。</p>
<div class="swatch-grid" data-copy-grid>
<div class="swatch" data-hex="#42c366"><div class="chip" style="background:#42c366"></div><div class="meta-row"><div class="name">--green</div><div class="val">#42c366 · 成功(=forest)</div><div class="copy">copied</div></div></div>
<div class="swatch" data-hex="rgba(66,195,102,.08)"><div class="chip" style="background:rgba(66,195,102,.08)"></div><div class="meta-row"><div class="name">--green-bg</div><div class="val">8% · 配套底</div><div class="copy">copied</div></div></div>
<div class="swatch" data-hex="rgba(66,195,102,.20)"><div class="chip" style="background:rgba(66,195,102,.20)"></div><div class="meta-row"><div class="name">--green-bd</div><div class="val">20% · 配套边</div><div class="copy">copied</div></div></div>
<div class="swatch" data-hex="#eb3424"><div class="chip" style="background:#eb3424"></div><div class="meta-row"><div class="name">--red</div><div class="val">#eb3424 · 失败(=crimson)</div><div class="copy">copied</div></div></div>
<div class="swatch" data-hex="rgba(235,52,36,.08)"><div class="chip" style="background:rgba(235,52,36,.08)"></div><div class="meta-row"><div class="name">--red-bg</div><div class="val">8% · 配套底</div><div class="copy">copied</div></div></div>
<div class="swatch" data-hex="rgba(235,52,36,.20)"><div class="chip" style="background:rgba(235,52,36,.20)"></div><div class="meta-row"><div class="name">--red-bd</div><div class="val">20% · 配套边</div><div class="copy">copied</div></div></div>
</div>
</div>
<div class="subsection">
<h3>Selection 选中色 <span class="mono-num">// Firecrawl 签名细节</span></h3>
<p class="lead">页面内任何文字选中时,底色 <code class="mono" style="background:var(--heat-20);color:var(--heat);padding:1px 6px;border-radius:4px">--heat-20</code> + 字色 <code class="mono" style="color:var(--heat);padding:1px 6px;border-radius:4px">--heat</code>。**试着选中下面这行字看效果:**</p>
<p style="font-size:14px;line-height:1.7;padding:14px;border:1px solid var(--border-faint);border-radius:8px;background:var(--surface)">本月营收 ¥327,400 较上月增长 33%,有 5 个项目处于"生成中"状态。其中 2 个需要重新调整模特模板。</p>
</div>
</section>
<!-- =========================================== -->
<!-- §2 TYPOGRAPHY -->
<!-- =========================================== -->
<section id="type">
<div class="section-head">
<span class="mono-tag">// §2 · TYPE · V2.1 MIXED STRATEGY</span>
<h2>字体系统 · 中英协作</h2>
<p>V2.1 改为**中英双字体协作** —— <code class="mono" style="background:var(--background-lighter);padding:2px 8px;border-radius:4px;color:var(--ink)">Inter</code> 处理英文/数字,<code class="mono" style="background:var(--background-lighter);padding:2px 8px;border-radius:4px;color:var(--ink)">Alibaba PuHuiTi</code> 处理中文,装饰用 <code class="mono" style="background:var(--background-lighter);padding:2px 8px;border-radius:4px;color:var(--ink)">JetBrains Mono</code>。浏览器按字符级 fallthrough,Inter 不含 CJK 字形 → 中文自动跳到普惠体。**不需要 JS,中英自然分工。**</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(--ink-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(--ink);margin-bottom:8px">Inter</div>
<div style="font-family:'Inter',sans-serif;font-size:13px;color:var(--ink-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(--ink-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(--ink);margin-bottom:8px">阿里普惠体</div>
<div style="font-family:'Alibaba PuHuiTi','PingFang SC',sans-serif;font-size:13px;color:var(--ink-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(--ink-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(--ink);margin-bottom:8px">JetBrains</div>
<div style="font-family:var(--font-mono);font-size:12px;color:var(--ink-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(--ink);line-height:1.5">本月营收 ¥327,400 较上月 +33%,共 5 个 AI 项目处于 "生成中" 状态</div>
<div style="font-family:var(--font-mono);font-size:11px;color:var(--ink-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">// 11 档</span></h3>
<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(--ink-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 张满意的头图,选 1 张。</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 / --ink-alpha-64 / 1.8</div>
<div class="sample" style="font-size:13px;color:var(--ink-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:var(--font-inter);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(--ink-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(--ink-alpha-12)">· · + · +XX+ +XXXX· +X·</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(--ink-alpha-48);letter-spacing:.04em;margin-bottom:10px">// REGULAR · 400</div>
<div style="font-size:18px;font-weight:400">流·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(--ink-alpha-48);letter-spacing:.04em;margin-bottom:10px">// MEDIUM · 500 ★ 默认强调</div>
<div style="font-size:18px;font-weight:500">流·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(--ink-alpha-48);letter-spacing:.04em;margin-bottom:10px">// SEMIBOLD · 600</div>
<div style="font-size:18px;font-weight:600">流·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(--ink-alpha-48);letter-spacing:.04em;margin-bottom:10px">// BOLD · 700 · 限徽标</div>
<div style="font-size:18px;font-weight:700">流·Studio · Aa Bb 123</div>
</div>
</div>
<p class="mono" style="margin-top:14px">// Bold 700 仅用于 Ctrl K 这种纯英文徽标场景,**正文严禁 700**(中英字重错位会暴露)</p>
</div>
</section>
<!-- =========================================== -->
<!-- §3 RADIUS -->
<!-- =========================================== -->
<section id="radius">
<div class="section-head">
<span class="mono-tag">// §3 · RADIUS</span>
<h2>圆角阶梯</h2>
<p>V2 核心变化:统一 <strong style="color:var(--ink)">8 px</strong> 作为默认主圆角。完全圆 999 px 仅用于 pill 和 dot。微元素降到 46 px。</p>
</div>
<div class="radius-row">
<div class="radius-box"><div class="box" style="border-radius:0"><span class="mono">x</span></div><div class="lbl">禁用 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>
<!-- =========================================== -->
<!-- §4 ICONS -->
<!-- =========================================== -->
<section id="icons">
<div class="section-head">
<span class="mono-tag">// §4 · ICONS</span>
<h2>Icon 系统</h2>
<p>统一 SVG line icon · stroke 1.5 · linecap round · 颜色通过 <code class="mono" style="background:var(--bg-soft);padding:1px 6px;border-radius:4px">currentColor</code> 继承。禁用 emoji / filled icon。</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">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" style="color:var(--ink-alpha-56)"><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>默认 ink-56</span>
</div>
<div class="demo" style="background:var(--ink-alpha-4);color:var(--ink)">
<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 · ink</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 class="icon-box"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" 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 class="icon-box"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" 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 class="icon-box"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" 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>
<!-- =========================================== -->
<!-- §5 BUTTONS -->
<!-- =========================================== -->
<section id="buttons">
<div class="section-head">
<span class="mono-tag">// §5 · BUTTONS</span>
<h2>按钮 · 3 类型 × 5 状态 × 3 尺寸</h2>
<p>所有按钮:<strong style="color:var(--ink)">高 32 / 圆角 8 / 字号 13 / 字重 500</strong>。默认按钮用 <code class="mono" style="background:var(--bg-soft);padding:1px 6px;border-radius:4px">::before inside-border</code>,hover 时边框淡出底色淡入,无布局抖动。</p>
</div>
<div class="subsection">
<h3>类型 1 · 默认 <span class="mono-num">// .btn</span></h3>
<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>类型 2 · 主 CTA <span class="mono-num">// .btn-primary</span></h3>
<p class="lead">唯一允许阴影的按钮 —— 4 层橙色多重阴影,hover 时阴影向上抬起。</p>
<div class="btn-row"><span class="state-label">// default</span><button class="btn btn-primary">查看 Demo</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">查看 Demo</button></div>
<div class="btn-row"><span class="state-label">// active</span><button class="btn btn-primary demo-active">查看 Demo</button></div>
<div class="btn-row"><span class="state-label">// focused</span><button class="btn btn-primary demo-focus">查看 Demo</button></div>
<div class="btn-row"><span class="state-label">// disabled</span><button class="btn btn-primary" disabled>查看 Demo</button></div>
</div>
<div class="subsection">
<h3>类型 3 · 无框 <span class="mono-num">// .btn-ghost</span></h3>
<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">// -sm / 默认 / -lg</span></h3>
<div class="btn-row">
<button class="btn btn-sm">Small · 28h</button>
<button class="btn">Default · 32h</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>
</div>
</section>
<!-- =========================================== -->
<!-- §6 PILLS -->
<!-- =========================================== -->
<section id="pills">
<div class="section-head">
<span class="mono-tag">// §6 · PILLS</span>
<h2>胶囊 · 严格 3 级分层</h2>
<p><strong style="color:var(--ink)">同级别尺寸必须完全一致。</strong>不允许混用。pill 永远是 <code class="mono" style="background:var(--bg-soft);padding:1px 6px;border-radius:4px">999 px</code>(完全圆),靠 dot 体现状态。</p>
</div>
<div class="subsection">
<h3>L1 · 大胶囊 <span class="mono-num">// h:28 / fs:13 / dot:8</span></h3>
<p class="lead">用于项目状态、列表行主标签。</p>
<div class="pill-row">
<span class="pill pill-l1 pill-info"><span class="dot"></span>生成中</span>
<span class="pill pill-l1 pill-ok"><span class="dot"></span>已完成</span>
<span class="pill pill-l1 pill-err"><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 pill-info"><span class="dot"></span>生成中</span>
<span class="pill pill-l2 pill-ok"><span class="dot"></span>200 OK</span>
<span class="pill pill-l2 pill-err"><span class="dot"></span>超时</span>
</div>
</div>
<div class="subsection">
<h3>L3 · 小胶囊 <span class="mono-num">// h:18 / fs:10.5 / dot:5</span></h3>
<p class="lead">KPI 角标 / 行内 Mono 标签场景。</p>
<div class="pill-row">
<span class="pill pill-l3 pill-info"><span class="dot"></span>NEW</span>
<span class="pill pill-l3 pill-ok"><span class="dot"></span>+33%</span>
<span class="pill pill-l3 pill-err"><span class="dot"></span>-1.2%</span>
</div>
</div>
<div class="subsection">
<h3>对比展示 <span class="mono-num">// 同色 3 级并列看大小差距</span></h3>
<div class="card" style="display:flex;gap:14px;align-items:center;flex-wrap:wrap">
<span class="pill pill-l1 pill-info"><span class="dot"></span>L1 · 生成中</span>
<span class="pill pill-l2 pill-info"><span class="dot"></span>L2 · 生成中</span>
<span class="pill pill-l3 pill-info"><span class="dot"></span>L3 · 生成中</span>
</div>
</div>
</section>
<!-- =========================================== -->
<!-- §7 INPUTS -->
<!-- =========================================== -->
<section id="inputs">
<div class="section-head">
<span class="mono-tag">// §7 · INPUTS</span>
<h2>输入框 · 5 状态</h2>
<p>同样用 inside-border。focused 时橙色 ring 2 px,error 时红色边框 + 红色软底。点击下方各字段可看到真实 focus 反馈。</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">// hover</span><div class="input-wrap" style="--hover:1" onmouseenter="this.classList.add('is-hover-demo')" onmouseleave="this.classList.remove('is-hover-demo')"><input class="input" placeholder="hover 我看效果"/></div></div>
<div class="field-row"><span class="lbl">// focused</span><div class="input-wrap is-focus"><input class="input" value="已聚焦"/></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 is-disabled"><input class="input" placeholder="不可编辑" disabled/></div></div>
</div>
<div class="subsection">
<h3>带图标 / 搜索 <span class="mono-num">// 含 Ctrl+K 提示</span></h3>
<div class="search-wrap input-wrap">
<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>
</div>
</section>
<!-- =========================================== -->
<!-- §8 FORM CONTROLS -->
<!-- =========================================== -->
<section id="form-controls">
<div class="section-head">
<span class="mono-tag">// §8 · FORM CONTROLS</span>
<h2>表单控件</h2>
<p>Checkbox / Radio / Switch 全部可点击。disabled 状态也可演示。</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>
<!-- =========================================== -->
<!-- §9 TABS -->
<!-- =========================================== -->
<section id="tabs">
<div class="section-head">
<span class="mono-tag">// §9 · TABS</span>
<h2>Tab · 双层结构</h2>
<p>主 Tab 在区块顶部,带橙色下划线指示;副 Tab 用于过滤,带灰度→彩色 icon 反馈。点击切换。</p>
</div>
<div class="subsection">
<h3>主 Tab</h3>
<div class="tabs" data-tabs>
<button class="tab is-active" data-tab="all">全部</button>
<button class="tab" data-tab="img">商品图</button>
<button class="tab" data-tab="vid">短视频</button>
<button class="tab" data-tab="ad">投放素材</button>
</div>
<div class="card">当前显示:<span data-tab-content style="color:var(--heat)">全部</span></div>
</div>
<div class="subsection">
<h3>副 Tab · 灰度→彩色</h3>
<div class="subtabs" data-subtabs>
<button class="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="subtab-divider"></div>
<button class="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="subtab-divider"></div>
<button class="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="subtab-divider"></div>
<button class="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>
<!-- =========================================== -->
<!-- §10 CARDS / SHORTCUT -->
<!-- =========================================== -->
<section id="cards">
<div class="section-head">
<span class="mono-tag">// §10 · CARDS</span>
<h2>卡片 / 快捷入口</h2>
<p>所有卡片统一 8 px 圆角、1 px 边框、无阴影。快捷入口含 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 class="shortcut" href="#">
<div class="icon-box"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5v14M5 12h14"/></svg></div>
<div class="meta"><div class="title">新建商品</div><div class="desc">// AI 生成 / 上传图</div></div>
</a>
<a class="shortcut" href="#">
<div class="icon-box"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" 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 class="meta"><div class="title">短视频工坊</div><div class="desc">// 9:16 · MP4</div></div>
</a>
<a class="shortcut" href="#">
<div class="icon-box"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" 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 class="meta"><div class="title">投放话术库</div><div class="desc">// /v2 · 模板</div></div>
</a>
</div>
</div>
</section>
<!-- =========================================== -->
<!-- §11 KPI STATS -->
<!-- =========================================== -->
<section id="stats">
<div class="section-head">
<span class="mono-tag">// §11 · KPI</span>
<h2>统计行 · 4 格 stats</h2>
</div>
<div class="stats">
<div class="cell">
<div class="lbl-row"><span class="lbl">本月营收</span><span class="pill pill-l3 pill-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 pill-info"><span class="dot"></span>RUNNING</span></div>
<div class="num">5</div>
<div class="prog"><span class="done"></span><span class="done"></span><span class="now"></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>
<!-- =========================================== -->
<!-- §12 LIST ROW -->
<!-- =========================================== -->
<section id="list">
<div class="section-head">
<span class="mono-tag">// §12 · LIST</span>
<h2>列表行</h2>
<p>hover 我看整行底色变化。</p>
</div>
<div class="list-card">
<div class="list-row">
<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="now"></span><span></span></div>
<span class="pill pill-l2 pill-info"><span class="dot"></span>生成中</span>
<button class="btn btn-sm">查看</button>
</div>
<div class="list-row">
<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 pill-ok"><span class="dot"></span>已完成</span>
<button class="btn btn-sm">导出</button>
</div>
<div class="list-row">
<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="err"></span><span></span><span></span><span></span></div>
<span class="pill pill-l2 pill-err"><span class="dot"></span>生成失败</span>
<button class="btn btn-sm">重试</button>
</div>
</div>
</section>
<!-- =========================================== -->
<!-- §13 TIP / PROGRESS -->
<!-- =========================================== -->
<section id="tip">
<div class="section-head">
<span class="mono-tag">// §13 · TIP</span>
<h2>提示框 / 进度</h2>
</div>
<div class="subsection">
<div class="tip" style="max-width:560px">
<div class="head">小提示</div>
<div class="body">使用 <span class="mono-code">Ctrl+K</span> 快速搜索任意项目、商品或资产。Tab 切换不同维度,Enter 直达。</div>
</div>
</div>
<div class="subsection">
<h3>进度条段位 <span class="mono-num">// 5 段 · 流水线专用</span></h3>
<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="now"></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="err"></span><span></span><span></span><span></span></div><div class="mono" style="margin-top:6px">失败</div></div>
</div>
</div>
</section>
<!-- =========================================== -->
<!-- §14 MODAL -->
<!-- =========================================== -->
<section id="modal">
<div class="section-head">
<span class="mono-tag">// §14 · MODAL</span>
<h2>弹窗 Modal</h2>
<p>点击下方按钮打开。ESC / 点击遮罩关闭。带 4 角 SVG 准星 + 8 px 圆角 + 半透明遮罩 + 弹性入场。</p>
</div>
<button class="btn btn-primary" id="open-modal">打开 Modal Demo</button>
</section>
<!-- =========================================== -->
<!-- §15 TOAST -->
<!-- =========================================== -->
<section id="toast">
<div class="section-head">
<span class="mono-tag">// §15 · TOAST</span>
<h2>Toast 通知</h2>
<p>右下角浮出。300ms 弹性入场,2400ms 自动消失。</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>
<!-- =========================================== -->
<!-- §16 CONTAINER -->
<!-- =========================================== -->
<section id="container">
<div class="section-head">
<span class="mono-tag">// §16 · SIGNATURE</span>
<h2>主容器装订线</h2>
<p>整个工作区被左右两条 1 px 边线包夹,四角放圆弧内凹的 SVG 准星。这是流·Studio 视觉的"图纸"签名。Modal 内不必加。</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>
<!-- =========================================== -->
<!-- §17 MONO DECOR -->
<!-- =========================================== -->
<section id="mono-decor">
<div class="section-head">
<span class="mono-tag">// §17 · DECOR</span>
<h2>Mono 装饰元素 · 品牌签名</h2>
<p>方括号标签 / 双斜杠注释 / 中点连接 —— 这些是流·Studio 独有的"调试视图感",Firecrawl 没有,绝对保留。</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(--ink-alpha-64)">/sidebar collapse · /toast dismiss · /modal open</div>
</div>
<div class="subsection">
<h3>ASCII 散点(背景装饰)</h3>
<div style="font-family:var(--font-mono);font-size:11px;color:var(--ink-alpha-12);line-height:1.4;letter-spacing:.04em;background:var(--card);border:1px solid var(--border-faint);border-radius:var(--r-md);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(--ink-alpha-72);max-width:680px;line-height:1.7">
本月营收较上月增长 <b style="color:var(--ink)">+33%</b>,有 <b style="color:var(--ink)">5 个项目</b>处于"生成中"状态。其中 <b style="color:var(--ink)">2 个</b>需要重新调整模特模板。
</p>
<p class="mono" style="margin-top:8px">// 关键名词加深一档(不变橙),橙色只留给 CTA</p>
</div>
</section>
<!-- =========================================== -->
<!-- §18 DON'T LIST -->
<!-- =========================================== -->
<section id="dont">
<div class="section-head">
<span class="mono-tag">// §18 · GUARDRAILS</span>
<h2>Don't List · 绝对禁止</h2>
<p>任何 mockup / 代码 review 时,对照此清单。每一条违反都判错。</p>
</div>
<div class="dodont-grid">
<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="mono" style="background:var(--card);padding:1px 5px;border-radius:3px;color:var(--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 class="card" style="margin-top:18px;padding:18px 22px">
<div class="dont-list-item"><span class="x">×</span><span><strong style="color:var(--ink)">渐变背景</strong> —— 只有 hero 区可考虑,首选纯色。绝禁多色渐变。</span></div>
<div class="dont-list-item"><span class="x">×</span><span><strong style="color:var(--ink)">玻璃拟态</strong> —— <code class="mono" style="background:var(--bg-soft);padding:1px 5px;border-radius:3px">backdrop-filter</code> 只用于 modal 遮罩。</span></div>
<div class="dont-list-item"><span class="x">×</span><span><strong style="color:var(--ink)">彩色 emoji</strong> —— 所有图标必须 SVG line(stroke 1.5)。</span></div>
<div class="dont-list-item"><span class="x">×</span><span><strong style="color:var(--ink)">多 accent 色</strong> —— 全场只有橙色一个 accent。</span></div>
<div class="dont-list-item"><span class="x">×</span><span><strong style="color:var(--ink)">大圆角容器</strong>(&gt;12 px)—— 直接判错。</span></div>
<div class="dont-list-item"><span class="x">×</span><span><strong style="color:var(--ink)">鲜艳荧光状态色</strong> —— 避免霓虹绿、电光蓝、霓虹粉。</span></div>
<div class="dont-list-item"><span class="x">×</span><span><strong style="color:var(--ink)">居中对齐大段正文</strong> —— 全部左对齐。</span></div>
<div class="dont-list-item"><span class="x">×</span><span><strong style="color:var(--ink)">装饰当主角</strong> —— 场记板 / 丝绒 / 霓虹灯都不要。</span></div>
<div class="dont-list-item"><span class="x">×</span><span><strong style="color:var(--ink)">无意义微动效</strong> —— hover 旋转、缩放、彩虹流光,禁。</span></div>
<div class="dont-list-item"><span class="x">×</span><span><strong style="color:var(--ink)">同行混用直角+圆角</strong> —— 用户原话:"不要有些是直角,胶囊又是圆角"。</span></div>
</div>
</section>
</main>
</div>
<!-- ===== Modal HTML ===== -->
<div class="modal-mask" id="modal-mask">
<div class="modal" role="dialog">
<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="head">
<div class="ic-box"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" 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>
<div class="ti">确认删除此商品?</div>
<div class="sub">// /products/dlt · IRREVERSIBLE</div>
</div>
</div>
<div class="body">
该操作不可撤销。商品「夏季新款蕾丝连衣裙」及其关联的 <b style="color:var(--ink)">4 张候选图</b><b style="color:var(--ink)">2 段短视频</b>将一并删除。
</div>
<div class="foot">
<button class="btn" data-close-modal>取消</button>
<button class="btn btn-primary">确认删除</button>
</div>
</div>
</div>
<!-- ===== Toast container ===== -->
<div class="toast-stack" id="toast-stack"></div>
<script>
// ---- Copy hex on click ----
document.querySelectorAll('[data-copy-grid] .swatch').forEach(sw => {
sw.addEventListener('click', () => {
const hex = sw.dataset.hex;
navigator.clipboard?.writeText(hex);
sw.classList.add('copied');
setTimeout(() => sw.classList.remove('copied'), 1200);
});
});
// ---- Input wrapper focus state ----
document.querySelectorAll('.input').forEach(inp => {
const wrap = inp.closest('.input-wrap');
if (!wrap || wrap.classList.contains('is-focus') || wrap.classList.contains('is-error') || wrap.classList.contains('is-disabled')) return;
inp.addEventListener('focus', () => wrap.classList.add('is-focus'));
inp.addEventListener('blur', () => wrap.classList.remove('is-focus'));
});
// ---- Checkbox indeterminate visual toggle on click ----
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('.tab');
if (!btn) return;
group.querySelectorAll('.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('.subtab');
if (!btn) return;
group.querySelectorAll('.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('is-open'));
mask.addEventListener('click', e => {
if (e.target === mask || e.target.matches('[data-close-modal]')) mask.classList.remove('is-open');
});
document.addEventListener('keydown', e => { if (e.key === 'Escape') mask.classList.remove('is-open') });
// ---- 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';
t.innerHTML = `
<div class="ic-box"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg></div>
<div><div class="ti">${data.ti}</div><div class="sub">${data.sub}</div></div>
`;
stack.appendChild(t);
setTimeout(() => { t.classList.add('is-leave'); setTimeout(() => t.remove(), 220) }, 2400);
});
});
// ---- Nav active on scroll ----
const navLinks = document.querySelectorAll('.nav-list a');
const sections = [...document.querySelectorAll('.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>