/* ============================================================
Airshelf · Restraint V2.1 · Firecrawl-aligned · 纯净版
============================================================
严格遵循 DESIGN_SPEC_V2.md V2.1 · 不含任何 V1/V2 legacy alias
============================================================ */
/* ============ Web font · Alibaba PuHuiTi 3.0 ============ */
@font-face {
font-family: 'Alibaba PuHuiTi';
font-weight: 400;
font-style: normal;
font-display: swap;
src: local('Alibaba PuHuiTi 3.0'),
local('AlibabaPuHuiTi-3-55-Regular'),
local('Alibaba PuHuiTi 2.0'),
local('AlibabaPuHuiTi-2-55-Regular'),
url('/fonts/AlibabaPuHuiTi-3-55-Regular.woff2') format('woff2');
}
@font-face {
font-family: 'Alibaba PuHuiTi';
font-weight: 500;
font-style: normal;
font-display: swap;
src: local('Alibaba PuHuiTi 3.0 Medium'),
local('AlibabaPuHuiTi-3-65-Medium'),
local('AlibabaPuHuiTi-2-65-Medium'),
url('/fonts/AlibabaPuHuiTi-3-65-Medium.woff2') format('woff2');
}
@font-face {
font-family: 'Alibaba PuHuiTi';
font-weight: 600;
font-style: normal;
font-display: swap;
src: local('AlibabaPuHuiTi-3-75-SemiBold'),
local('AlibabaPuHuiTi-2-75-SemiBold'),
url('/fonts/AlibabaPuHuiTi-3-75-SemiBold.woff2') format('woff2');
}
@font-face {
font-family: 'Alibaba PuHuiTi';
font-weight: 700;
font-style: normal;
font-display: swap;
src: local('Alibaba PuHuiTi 3.0 Bold'),
local('AlibabaPuHuiTi-3-85-Bold'),
local('AlibabaPuHuiTi-2-85-Bold'),
url('/fonts/AlibabaPuHuiTi-3-85-Bold.woff2') format('woff2');
}
* { box-sizing: border-box; margin: 0; padding: 0; }
:root {
/* ===== Backgrounds (冷灰) ===== */
--background-base: #f9f9f9;
--background-lighter: #fbfbfb;
--surface: #ffffff;
--surface-raised: #ffffff;
/* ===== Borders (冷灰 3 档,语义优先) ===== */
--border-faint: #ededed;
--border-muted: #e8e8e8;
--border-loud: #e6e6e6;
/* ===== Accent multi-color (5 色信号) ===== */
--accent-black: #262626;
--accent-white: #ffffff;
--accent-amethyst: #9061ff;
--accent-bluetron: #2a6dfb;
--accent-crimson: #eb3424;
--accent-forest: #42c366;
--accent-honey: #ecb730;
/* status 配套底/边 */
--forest-bg: rgba(66, 195, 102, .08);
--forest-bd: rgba(66, 195, 102, .20);
--crimson-bg: rgba(235, 52, 36, .08);
--crimson-bd: rgba(235, 52, 36, .20);
--honey-bg: rgba(236, 183, 48, .08);
--honey-bd: rgba(236, 183, 48, .20);
/* ===== Heat · 单 hue + 8 档 alpha ===== */
--heat: #fa5d19;
--heat-90: rgba(250, 93, 25, .90);
--heat-40: rgba(250, 93, 25, .40);
--heat-20: rgba(250, 93, 25, .20);
--heat-16: rgba(250, 93, 25, .16);
--heat-12: rgba(250, 93, 25, .12);
--heat-8: rgba(250, 93, 25, .08);
--heat-4: rgba(250, 93, 25, .04);
/* ===== Black-alpha 阶梯 (20 档) ===== */
--black-alpha-1: rgba(0, 0, 0, .01);
--black-alpha-2: rgba(0, 0, 0, .02);
--black-alpha-3: rgba(0, 0, 0, .03);
--black-alpha-4: rgba(0, 0, 0, .04);
--black-alpha-5: rgba(0, 0, 0, .05);
--black-alpha-6: rgba(0, 0, 0, .06);
--black-alpha-7: rgba(0, 0, 0, .07);
--black-alpha-8: rgba(0, 0, 0, .08);
--black-alpha-10: rgba(0, 0, 0, .10);
--black-alpha-12: rgba(0, 0, 0, .12);
--black-alpha-16: rgba(0, 0, 0, .16);
--black-alpha-20: rgba(0, 0, 0, .20);
--black-alpha-24: rgba(0, 0, 0, .24);
--black-alpha-32: rgba(38, 38, 38, .32);
--black-alpha-40: rgba(38, 38, 38, .40);
--black-alpha-48: rgba(38, 38, 38, .48);
--black-alpha-56: rgba(38, 38, 38, .56);
--black-alpha-64: rgba(38, 38, 38, .64);
--black-alpha-72: rgba(38, 38, 38, .72);
--black-alpha-88: rgba(38, 38, 38, .88);
/* ===== Radius ===== */
--r-sm: 4px;
--r-md: 8px;
--r-pill: 999px;
/* ===== Font · 关键:--font-mono 必须含 PuHuiTi 中文 fallback ===== */
/* Inter 不含 CJK 字形。
字体链按字符级 fallthrough,中文字符会找下一个候选 —— 必须包含 PuHuiTi。 */
--font-sans: 'Inter', 'Alibaba PuHuiTi', 'PingFang SC', 'Microsoft YaHei', system-ui, sans-serif;
--font-inter: 'Inter', system-ui, sans-serif;
--font-mono: 'Inter', 'Alibaba PuHuiTi', 'PingFang SC', 'Microsoft YaHei', system-ui, sans-serif;
/* ===== Transition ===== */
--t-fast: 100ms ease;
--t-base: 200ms ease;
--t-slow: 300ms cubic-bezier(0.34, 1.56, 0.64, 1);
/* ===== Shadows ===== */
--shadow-cta:
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-cta-hover:
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);
--shadow-cta-active:
inset 0 -4px 8px rgba(250, 93, 25, .28),
0 1px 2px rgba(250, 93, 25, .16);
--shadow-floating: 0 4px 20px rgba(21, 20, 15, .06);
}
::selection { background: var(--heat-20); color: var(--heat); }
html, body {
background: var(--background-base);
color: var(--accent-black);
font-family: var(--font-sans);
font-size: 14px;
line-height: 1.65;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-rendering: optimizeLegibility;
}
a { color: inherit; text-decoration: none; }
button { font: inherit; cursor: pointer; border: 0; background: none; color: inherit; }
input, textarea, select { font: inherit; color: inherit; outline: none; }
img, svg, video { display: block; max-width: 100%; }
/* ─── Icon system · Lucide-line only ─── */
:root {
--icon-stroke: 1.5;
--icon-xs: 12px;
--icon-s: 14px;
--icon-m: 16px;
--icon-l: 20px;
--icon-xl: 24px;
}
.ui-icon {
width: var(--icon-m);
height: var(--icon-m);
flex: 0 0 auto;
display: block;
fill: none;
stroke: currentColor;
stroke-width: var(--icon-stroke);
stroke-linecap: round;
stroke-linejoin: round;
}
.ui-icon * { vector-effect: non-scaling-stroke; }
.ui-icon [stroke="none"] {
fill: currentColor;
stroke: none;
}
:where(nav a, .search-box, .balance-chip, .queue-chip, .icon-btn, .btn, .chip, .toolbar, .page-head, .toast, .modal, .drawer, .card-del-btn, .row-more, .gen-img-btn, .shortcut, .empty-state) svg:not(.corner):not(.quote-icon) {
flex: 0 0 auto;
fill: none;
stroke: currentColor;
stroke-width: var(--icon-stroke);
stroke-linecap: round;
stroke-linejoin: round;
}
:where(nav a, .search-box, .balance-chip, .queue-chip, .icon-btn, .btn, .chip, .toolbar, .page-head, .toast, .modal, .drawer, .card-del-btn, .row-more, .gen-img-btn, .shortcut, .empty-state) svg:not(.corner):not(.quote-icon) [fill="currentColor"] {
fill: none;
stroke: currentColor;
}
:where(nav a, .search-box, .balance-chip, .queue-chip, .icon-btn, .btn, .chip, .toolbar, .page-head, .toast, .modal, .drawer, .card-del-btn, .row-more, .gen-img-btn, .shortcut, .empty-state) svg:not(.corner):not(.quote-icon) [stroke="none"] {
fill: currentColor;
stroke: none;
}
.row-more svg circle {
fill: currentColor !important;
stroke: none !important;
}
.num, .tnum { font-variant-numeric: tabular-nums; }
.mono { font-family: var(--font-mono); }
.muted { color: var(--black-alpha-56); }
.muted-2 { color: var(--black-alpha-48); }
.spacer { flex: 1; }
.hstack { display: flex; align-items: center; gap: 8px; }
.hstack[hidden], .vstack[hidden] { display: none; }
.vstack { display: flex; flex-direction: column; gap: 8px; }
.divider { height: 1px; background: var(--border-faint); margin: 16px 0; }
/* ─── App shell ─── */
.app {
display: grid;
grid-template-columns: 248px 1fr;
min-height: 100vh;
transition: grid-template-columns var(--t-base);
}
body.sidebar-collapsed .app { grid-template-columns: 96px 1fr; }
/* ─── Sidebar ─── */
aside.sidebar {
padding: 22px 16px;
border-right: 1px solid var(--border-faint);
background: var(--background-base);
position: sticky;
top: 0;
height: 100vh;
overflow-y: auto;
transition: padding var(--t-base);
}
.sidebar-head {
display: flex;
align-items: center;
padding: 2px 8px 16px;
min-height: 44px;
}
.brand { display: flex; align-items: center; min-width: 0; color: var(--accent-black); }
.brand-clip {
display: block;
width: 142px;
overflow: hidden;
transition: width var(--t-base);
}
.brand-logo { display: block; width: 142px; max-width: none; height: auto; margin: -8px 0 -6px -8px; object-fit: contain; }
.brand-mark, .flame { width: 22px; height: 22px; color: var(--heat); }
.brand-mark svg, .flame svg { width: 100%; height: 100%; }
.brand .name { font-weight: 600; font-size: 18px; letter-spacing: -.012em; color: var(--accent-black); }
.sidebar-toggle {
position: fixed;
top: 0;
left: 220px;
z-index: 70;
width: 28px;
height: 100vh;
border: 0;
border-radius: 0;
background: transparent;
color: var(--black-alpha-48);
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
opacity: 1;
pointer-events: auto;
transition: color var(--t-base), background var(--t-base);
}
.sidebar-toggle:hover,
.sidebar-toggle:focus-visible {
background: var(--black-alpha-4);
backdrop-filter: blur(4px);
-webkit-backdrop-filter: blur(4px);
color: var(--accent-black);
outline: none;
}
.sidebar-toggle-icon {
display: block;
opacity: 0;
line-height: 1;
transition: opacity var(--t-base);
}
.sidebar-toggle:hover .sidebar-toggle-icon,
.sidebar-toggle:focus-visible .sidebar-toggle-icon { opacity: 1; }
.sidebar-toggle-icon--expand { display: none; }
/* sidebar search · Ctrl K Inter Bold 平铺 */
.search-box {
display: flex; align-items: center; gap: 10px;
padding: 9px 12px;
background: var(--surface);
border: 1px solid var(--border-faint);
border-radius: var(--r-md);
color: var(--black-alpha-48);
margin-bottom: 18px;
cursor: text;
transition: border-color var(--t-base);
}
.search-box:hover { border-color: var(--black-alpha-24); }
.search-box:focus-within { border-color: var(--heat-40); box-shadow: inset 0 0 0 1px var(--heat-40); }
.search-box svg { width: var(--icon-m); height: var(--icon-m); flex-shrink: 0; color: var(--ink-3); }
.search-box input {
flex: 1; min-width: 0;
border: 0; background: transparent;
font-size: 14px; color: var(--accent-black);
padding: 0;
}
.search-box input::placeholder { color: var(--black-alpha-48); }
.search-box .kbd {
margin-left: auto;
flex-shrink: 0;
white-space: nowrap;
font-family: var(--font-inter);
font-weight: 700;
font-size: 12px;
color: var(--black-alpha-48);
letter-spacing: .02em;
}
.nav-section {
font-size: 12px; color: var(--black-alpha-48);
padding: 16px 12px 8px;
letter-spacing: .04em;
font-weight: 500;
/* 中文标签用 sans 字体,不用 mono + uppercase */
}
nav { display: flex; flex-direction: column; gap: 2px; }
nav a {
display: flex; align-items: center; gap: 11px;
padding: 9px 12px;
color: var(--black-alpha-56);
font-size: 14px; font-weight: 500;
border-radius: var(--r-md);
cursor: pointer;
user-select: none;
transition: background var(--t-base), color var(--t-base);
}
nav a:hover { background: var(--black-alpha-4); color: var(--accent-black); }
nav a.active { background: var(--heat-12); color: var(--heat); }
nav a svg { width: var(--icon-m); height: var(--icon-m); color: var(--ink-3); }
nav a.active svg { color: var(--orange); }
nav a .pill-mini {
margin-left: auto;
font-family: var(--font-mono);
font-size: 12px; font-weight: 600;
padding: 2px 7px;
background: var(--surface);
color: var(--black-alpha-48);
border: 1px solid var(--border-faint);
border-radius: var(--r-pill);
letter-spacing: .04em;
}
nav a.disabled { color: var(--black-alpha-32); cursor: not-allowed; }
nav a.disabled:hover { background: transparent; color: var(--black-alpha-32); }
.aside-foot { margin-top: 20px; padding-top: 16px; border-top: 1px solid var(--border-faint); }
.user {
display: flex; align-items: center; gap: 10px;
padding: 8px 10px;
border-radius: var(--r-md);
cursor: pointer;
transition: background var(--t-base);
}
.user:hover { background: var(--black-alpha-4); }
.user .av {
width: 26px; height: 26px;
border-radius: 6px;
background: var(--accent-black);
color: var(--accent-white);
display: flex; align-items: center; justify-content: center;
font-weight: 600; font-size: 12px;
overflow: hidden;
}
.user .av img { width: 100%; height: 100%; object-fit: cover; display: block; }
.user .em { font-size: 13px; color: var(--accent-black); }
body.sidebar-collapsed aside.sidebar { padding: 22px 12px; }
body.sidebar-collapsed .sidebar-head { gap: 6px; padding: 2px 0 16px; }
body.sidebar-collapsed .brand-clip {
width: 34px;
height: 34px;
display: flex;
align-items: center;
}
body.sidebar-collapsed .sidebar-toggle { left: 68px; }
body.sidebar-collapsed .sidebar-toggle-icon--collapse { display: none; }
body.sidebar-collapsed .sidebar-toggle-icon--expand { display: block; }
body.sidebar-collapsed .search-box {
justify-content: center;
gap: 0;
padding: 9px 0;
cursor: pointer;
}
body.sidebar-collapsed .search-box input,
body.sidebar-collapsed .search-box .kbd,
body.sidebar-collapsed aside.sidebar nav a span,
body.sidebar-collapsed aside.sidebar nav a .pill-mini,
body.sidebar-collapsed .user .em { display: none; }
body.sidebar-collapsed .nav-section {
height: 1px;
margin: 10px 0 8px;
padding: 0;
overflow: hidden;
color: transparent;
background: var(--border-faint);
}
body.sidebar-collapsed aside.sidebar nav a {
justify-content: center;
gap: 0;
padding: 10px 0;
}
body.sidebar-collapsed .aside-foot { padding-top: 12px; }
body.sidebar-collapsed .user {
justify-content: center;
padding: 8px 0;
}
/* ─── Main + grid background ─── */
main { position: relative; background: var(--background-base); min-width: 0; }
.grid-bg {
position: absolute; inset: 0; pointer-events: none;
background-image:
url("data:image/svg+xml;utf8,"),
url("data:image/svg+xml;utf8,"),
url("data:image/svg+xml;utf8,");
background-size: 240px 240px, 60px 60px, 240px 240px;
mask-image: radial-gradient(ellipse 95% 80% at 50% 35%, #000 25%, transparent 95%);
-webkit-mask-image: radial-gradient(ellipse 95% 80% at 50% 35%, #000 25%, transparent 95%);
}
.scatter {
position: absolute;
font-family: var(--font-mono); font-size: 12px; line-height: 1.05;
color: var(--black-alpha-20); white-space: pre; pointer-events: none;
opacity: .85; letter-spacing: .04em;
}
.tag-corner {
position: absolute;
color: var(--black-alpha-48);
font-family: var(--font-mono);
font-size: 12px; letter-spacing: .06em;
pointer-events: none; opacity: .85; z-index: 1;
}
.sq-mark { position: absolute; width: 5px; height: 5px; background: var(--black-alpha-24); pointer-events: none; }
/* ─── Topbar ─── */
.topbar {
display: flex; align-items: center; gap: 12px;
padding: 14px 28px;
border-bottom: 1px solid var(--border-faint);
background: var(--background-base);
position: sticky; top: 0; z-index: 50;
}
.crumbs { display: flex; align-items: center; gap: 8px; font-size: 14px; color: var(--black-alpha-48); }
.crumbs .sep { color: var(--black-alpha-32); }
.crumbs .here { color: var(--accent-black); font-weight: 500; }
.crumbs a:hover { color: var(--accent-black); }
.topbar .right { margin-left: auto; display: flex; align-items: center; gap: 10px; }
.balance-chip {
display: inline-flex; align-items: center; gap: 7px;
height: 36px;
padding: 0 14px 0 12px;
background: var(--surface);
border: 1px solid var(--border-faint);
border-radius: var(--r-pill);
font-size: 13px;
color: var(--black-alpha-56);
cursor: pointer;
transition: background var(--t-base), border-color var(--t-base);
}
.balance-chip:hover { background: var(--black-alpha-4); border-color: var(--black-alpha-24); }
.balance-chip strong { color: var(--accent-black); font-weight: 600; font-variant-numeric: tabular-nums; }
.balance-chip svg { width: var(--icon-m); height: var(--icon-m); color: var(--heat); }
.icon-btn {
width: 36px; height: 36px;
display: flex; align-items: center; justify-content: center;
background: var(--surface);
border: 1px solid var(--border-faint);
border-radius: var(--r-pill);
color: var(--black-alpha-56);
cursor: pointer;
position: relative;
transition: background var(--t-base), border-color var(--t-base), color var(--t-base);
}
.icon-btn:hover { background: var(--background-lighter); color: var(--accent-black); border-color: var(--border-loud); }
.icon-btn svg { width: var(--icon-m); height: var(--icon-m); }
.icon-btn .dot-noti {
position: absolute; top: 8px; right: 9px;
width: 7px; height: 7px; border-radius: 50%;
background: var(--heat); border: 1.5px solid var(--surface);
}
.icon-btn .count-noti {
position: absolute; top: -4px; right: -4px;
min-width: 16px; height: 16px; padding: 0 4px;
display: inline-flex; align-items: center; justify-content: center;
background: var(--accent-crimson); color: var(--accent-white);
border: 1.5px solid var(--surface);
border-radius: var(--r-pill);
font-family: var(--font-mono); font-size: 12px; font-weight: 600;
letter-spacing: .02em; line-height: 1;
pointer-events: none;
}
/* ─── Topbar · 任务队列 chip ─── */
.queue-chip {
display: inline-flex; align-items: center; gap: 7px;
height: 36px;
padding: 0 8px 0 12px;
background: var(--surface);
border: 1px solid var(--border-faint);
border-radius: var(--r-pill);
font-size: 13px;
color: var(--accent-black);
cursor: pointer;
transition: background var(--t-base), border-color var(--t-base);
}
.queue-chip:hover { background: var(--black-alpha-4); border-color: var(--black-alpha-24); }
.queue-chip[hidden] { display: none; }
.queue-chip svg { width: var(--icon-m); height: var(--icon-m); color: var(--black-alpha-56); }
.queue-chip .count {
display: inline-flex; align-items: center; justify-content: center;
height: 20px; min-width: 20px; padding: 0 6px;
background: var(--heat-12); color: var(--heat);
border: 1px solid var(--heat-20);
border-radius: var(--r-pill);
font-family: var(--font-mono); font-size: 12px; font-weight: 600;
letter-spacing: .02em;
}
/* ─── Topbar · 头像 ─── */
.topbar-avatar {
width: 36px; height: 36px;
border-radius: var(--r-pill);
background: var(--accent-black);
color: var(--accent-white);
display: inline-flex; align-items: center; justify-content: center;
font-size: 13px; font-weight: 600;
cursor: pointer;
border: 1px solid var(--border-faint);
transition: transform var(--t-fast), box-shadow var(--t-base);
flex-shrink: 0;
overflow: hidden;
}
.topbar-avatar:hover {
transform: scale(1.04);
box-shadow: 0 0 0 3px var(--heat-12);
}
.topbar-avatar img {
width: 100%; height: 100%; object-fit: cover;
}
/* ─── Content ─── */
.content {
/* 对齐 HTML 设计稿 #page-content(24px 28px 60px):原 48px 顶距使全站标题整体偏低 24px */
padding: 24px 28px 60px;
position: relative;
z-index: 1;
min-height: calc(100vh - 64px);
}
.content > .corner-mark { display: none; }
.page-head {
display: flex; align-items: flex-start; justify-content: space-between;
margin-bottom: 36px; gap: 16px; flex-wrap: wrap;
}
.page-head h1 {
font-size: 28px; font-weight: 600; letter-spacing: -.02em; line-height: 1.25;
color: var(--accent-black);
}
.page-head .sub {
font-size: 14px; color: var(--black-alpha-56);
margin-top: 10px;
display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
}
.page-head .sub .mono { font-family: var(--font-mono); font-size: 12px; color: var(--black-alpha-48); letter-spacing: .04em; }
.page-head .actions { display: flex; gap: 10px; align-items: center; }
/* page-head 右上角主操作按钮 · 统一尺寸(对齐 .btn-lg),覆盖各页里 btn / btn-sm / btn-lg 混用 */
.page-head .actions > .btn,
.page-head .actions > a.btn,
.page-head .actions > button.btn {
height: 40px;
padding: 0 20px;
font-size: 14px;
}
.page-head .actions > .btn svg { width: var(--icon-s); height: var(--icon-s); }
.page-head .actions > .btn.btn-create svg { width: var(--icon-m); height: var(--icon-m); }
.section-h { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: 14px; }
.section-h h2 { font-size: 16px; font-weight: 600; letter-spacing: -.01em; color: var(--accent-black); }
.section-h .more {
font-family: var(--font-mono); font-size: 12px;
color: var(--black-alpha-48); letter-spacing: .04em;
cursor: pointer;
transition: color var(--t-base);
}
.section-h .more:hover { color: var(--heat); }
/* ─── Buttons · 统一高度 36 / 8 px 圆角 / 真 1px border / hover bg 切换 ─── */
.btn {
display: inline-flex; align-items: center; justify-content: center; gap: 6px;
height: 36px;
padding: 0 16px;
border-radius: var(--r-md);
font-size: 13px; font-weight: 500;
background: var(--surface);
color: var(--accent-black);
cursor: pointer;
white-space: nowrap;
font-family: inherit;
border: 1px solid var(--black-alpha-12);
transition: background var(--t-base), border-color var(--t-base), transform var(--t-fast);
}
.btn:hover { background: var(--black-alpha-4); border-color: var(--black-alpha-24); }
.btn:active { background: var(--black-alpha-7); transform: scale(.99); }
.btn:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--background-base), 0 0 0 4px var(--heat-40); }
.btn:disabled, .btn.disabled {
color: var(--black-alpha-32);
background: var(--black-alpha-5);
border-color: var(--black-alpha-12);
cursor: not-allowed;
transform: none;
}
.btn:disabled:hover, .btn.disabled:hover {
background: var(--black-alpha-5);
border-color: var(--black-alpha-12);
}
.btn svg { width: var(--icon-s); height: var(--icon-s); }
.btn[hidden] { display: none; }
.btn-primary {
background: var(--heat);
color: var(--accent-white);
border-color: var(--heat);
font-weight: 600;
/* 继承 .btn 的 height: 36px / padding: 0 16px */
box-shadow: var(--shadow-cta);
}
.btn-primary:hover {
background: var(--heat);
border-color: var(--heat);
box-shadow: var(--shadow-cta-hover);
}
.btn-primary:active {
background: var(--heat);
transform: scale(.995);
box-shadow: var(--shadow-cta-active);
}
.btn-primary:disabled, .btn-primary.disabled {
background: var(--heat-40);
color: var(--accent-white);
border-color: var(--heat-40);
box-shadow: none;
}
.btn-ghost {
background: transparent;
border-color: transparent;
color: var(--black-alpha-56);
}
.btn-ghost:hover { background: var(--black-alpha-4); border-color: transparent; color: var(--accent-black); }
.btn-ghost:active { background: var(--black-alpha-7); }
.btn-sm { height: 28px; padding: 0 12px; font-size: 12px; border-radius: var(--r-md); }
.btn-lg { height: 40px; padding: 0 20px; font-size: 14px; }
/* ─── Pills ─── */
.pill {
display: inline-flex; align-items: center; gap: 6px;
padding: 4px 10px;
border-radius: var(--r-pill);
font-size: 12px; font-weight: 500;
border: 1px solid var(--border-faint);
background: var(--surface);
color: var(--black-alpha-56);
white-space: nowrap;
}
.pill.info { background: var(--heat-12); color: var(--heat); border-color: var(--heat-20); }
.pill.ok { background: var(--forest-bg); color: var(--accent-forest); border-color: var(--forest-bd); }
.pill.err { background: var(--crimson-bg); color: var(--accent-crimson); border-color: var(--crimson-bd); }
.pill.neutral { background: var(--black-alpha-4); color: var(--black-alpha-56); border-color: var(--border-faint); }
.pill .dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
/* ─── Cards / containers · V2.1 统一 8 px 圆角 ─── */
.card-hard {
background: var(--surface);
border: 1px solid var(--border-faint);
border-radius: var(--r-md);
position: relative;
}
/* V2.1 spec §5.3 · 容器四角准星 · SVG 圆弧内凹(22×21 viewBox) */
.card-hard.with-corners::before, .card-hard.with-corners::after,
.with-corners .corner-tr, .with-corners .corner-bl {
content: ''; position: absolute;
width: 14px; height: 14px;
background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 22 21' fill='%23e8e8e8'%3E%3Cpath 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'/%3E%3C/svg%3E") no-repeat center;
background-size: contain;
pointer-events: none;
}
.card-hard.with-corners::before { top: -7px; left: -7px; }
.card-hard.with-corners::after { bottom: -7px; right: -7px; }
.with-corners .corner-tr { top: -7px; right: -7px; }
.with-corners .corner-bl { bottom: -7px; left: -7px; }
/* ─── Stats (KPI bar) ─── */
.stats {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 0;
background: var(--surface);
border: 1px solid var(--border-faint);
border-radius: var(--r-md);
position: relative;
margin-bottom: 36px;
overflow: hidden;
}
.stat {
padding: 24px 28px;
border-right: 1px solid var(--border-faint);
position: relative;
cursor: pointer;
transition: background var(--t-base);
/* 余额是