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