Files
2026-08-21 16:00:13 +08:00

801 lines
16 KiB
CSS
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* ============================================================
* design/_chrome.css — 原型共享组件层(AppShell chrome)
* ============================================================
*
* 用途:供所有 AppShell / NarrowShell 原型 <link> 引用。集中此前
* 每个原型 <style> 里字面重复的 sidebar / 导航 / 卡片 / 按钮 /
* 标签 / 页头 等组件样式,消除 25 份副本与已出现的写法分叉
* (如角标写法分叉:部分页用 class,部分页内联)。
*
* 依赖:<link href="tokens.css"> 与 <link href="_base.css"> 必须在本
* 文件之前——组件样式引用 token 变量,_base.css 提供 reset/body。
*
* 层次:tokens.css(变量)→ _base.css(reset/body/极光)→ _chrome.css
* (共享组件)→ 页面 <style>(仅页面特异样式)。
*
* sidebar 注入:侧栏 DOM 由 _theme.js 从 _nav.html fetch 注入
* 到 .sidebar-mount;本文件提供 .sidebar-* 样式。
* ============================================================ */
/* ── AppShell 布局骨架 ── */
.app-shell {
display: flex;
min-height: 100vh;
}
.sidebar-mount {
display: flex;
} /* 让注入的 .sidebar-wrap 拉伸填满本列全高 */
.main-area {
flex: 1;
min-width: 0;
display: flex;
flex-direction: column;
}
/* ── 侧栏(可折叠:默认 220 展开 / .collapsed 60 图标态)──
DOM 由 _theme.js 从 _nav.html 注入;align-self + sticky 让长页面下贴顶滚动。
折叠由 #sidebar-fold 触发,_theme.js 持久化到 localStorage。
背景在 .sidebar-wrap 上(填满 flex 列高)而非 .sidebar(仅 100vh sticky)。
border-right 同层,确保全高发丝线不断。 */
.sidebar-wrap {
display: flex;
width: 220px;
flex-shrink: 0;
z-index: 30;
transition:
width 0.28s cubic-bezier(0.4, 0, 0.2, 1),
box-shadow 0.28s;
background: linear-gradient(
180deg,
color-mix(in srgb, var(--night-bronze) 92%, var(--patina) 4%),
var(--night-bronze)
);
border-right: 1px solid var(--rule);
}
.sidebar-wrap.collapsed {
width: 60px;
box-shadow: 8px 0 36px -10px rgba(0, 0, 0, 0.55);
}
.sidebar {
width: 100%;
height: 100vh;
overflow-y: auto;
overflow-x: hidden;
display: flex;
flex-direction: column;
padding: 12px 0 8px;
position: sticky;
top: 0;
align-self: flex-start;
}
/* 顶栏:logo + 折叠按钮 */
.sidebar-topbar {
display: flex;
align-items: center;
justify-content: space-between;
gap: 4px;
padding: 6px 12px;
}
.sidebar-wrap.collapsed .sidebar-topbar {
justify-content: center;
padding: 6px 4px;
}
.sidebar .logo {
font-family: "Songti SC", serif;
font-size: 18px;
font-weight: 700;
letter-spacing: 0.1em;
color: var(--fg);
background: none;
border: none;
cursor: pointer;
display: flex;
align-items: center;
gap: 7px;
padding: 4px;
}
.sidebar .logo:hover {
opacity: 0.85;
}
.sidebar .logo .logo-mark {
width: 18px;
height: 18px;
flex-shrink: 0;
}
.sidebar .logo .logo-mark .knob {
fill: var(--gilt);
}
.sidebar-wrap.collapsed .sidebar .logo {
font-size: 0;
justify-content: center;
}
.sidebar-wrap.collapsed .sidebar .logo .logo-mark {
width: 22px;
height: 22px;
}
/* logo 彩蛋:tick(单击敲门)+ egg-pulse(1.2s 连点 5 次,金光 + 谶语) */
@keyframes logoTick {
0%,
100% {
transform: scale(1);
}
50% {
transform: scale(1.07);
}
}
.logo.tick .logo-mark {
animation: logoTick 0.3s ease;
}
@keyframes logoEggPulse {
0% {
transform: scale(1);
filter: drop-shadow(0 0 0 transparent);
}
40% {
transform: scale(1.2);
filter: drop-shadow(0 0 7px var(--gilt));
}
100% {
transform: scale(1);
filter: drop-shadow(0 0 0 transparent);
}
}
.logo.egg-pulse .logo-mark {
animation: logoEggPulse 1.4s ease;
color: var(--gilt);
}
/* 折叠按钮(折叠态旋转 180,箭头指向展开) */
.sidebar-foldbtn {
display: flex;
align-items: center;
justify-content: center;
width: 28px;
height: 28px;
border-radius: 8px;
color: var(--muted);
background: none;
border: none;
cursor: pointer;
flex-shrink: 0;
transition:
background 0.12s,
color 0.12s,
transform 0.28s;
}
.sidebar-foldbtn:hover {
background: var(--overlay-hover);
color: var(--fg);
}
.sidebar-wrap.collapsed .sidebar-foldbtn {
transform: rotate(180deg);
}
/* 图标默认(Lucide 风:stroke currentColor、fill none) */
.sidebar .ico {
width: 16px;
height: 16px;
fill: none;
stroke: currentColor;
stroke-width: 2;
stroke-linecap: round;
stroke-linejoin: round;
flex-shrink: 0;
}
/* ── 导航组与条目 ── */
.nav-group {
margin-top: 14px;
}
.nav-group:first-of-type {
margin-top: 6px;
}
.nav-group-title {
font-size: 12px;
font-weight: 600;
letter-spacing: 0.1em;
text-transform: uppercase;
color: var(--muted);
padding: 0 18px;
margin-bottom: 4px;
opacity: 0.7;
max-height: 22px;
overflow: hidden;
transition:
opacity 0.18s,
max-height 0.2s;
display: flex;
align-items: center;
gap: 6px;
}
/* 载入组:新功能视觉区分(顶边鎏金淡线) */
.nav-group.tavern {
border-top: 1px solid var(--gilt-faint);
padding-top: 14px;
}
.sidebar-wrap.collapsed .nav-group-title {
opacity: 0;
max-height: 0;
padding: 0;
margin: 0;
}
.nav-item {
display: flex;
align-items: center;
padding: 7px 18px;
border-radius: 10px;
font-size: 13.5px;
font-weight: 500;
color: var(--muted);
text-decoration: none;
transition:
background var(--duration-fast),
color var(--duration-fast),
padding var(--duration-fast),
box-shadow var(--duration-fast);
cursor: pointer;
gap: 10px;
position: relative;
}
.nav-item:hover {
background: var(--overlay-hover);
color: var(--fg);
}
.nav-item.active {
background: var(--patina-wash);
color: var(--patina);
box-shadow: inset 2px 0 0 var(--patina);
}
.nav-item .ico {
opacity: 0.65;
}
.nav-item.active .ico {
opacity: 1;
}
/* 司命台 · 朱漆语义(设计语言:朱漆仅司命/朱批/告警) */
.nav-item.siming {
color: var(--cinnabar);
}
.nav-item.siming:hover {
background: var(--cinnabar-wash);
color: var(--cinnabar);
}
.nav-item.siming.active {
background: var(--cinnabar-wash);
color: var(--cinnabar);
}
/* ── 心智分层:灵枢(总览)↔ 维度(五行/人格/内驱力/演化)之间的分隔线
.nav-item--overview 暂为语义标记(无额外样式),视觉分层仅靠 .nav-divider
一条发丝线,不靠底色/字重——克制,避免总览项与 active 态混淆。 ── */
.nav-divider {
height: 1px;
margin: 6px 18px;
background: var(--rule);
opacity: 0.8;
flex-shrink: 0;
}
.sidebar-wrap.collapsed .nav-item {
padding: 9px 0;
font-size: 0;
gap: 0;
justify-content: center;
}
.sidebar-wrap.collapsed .nav-item .ico {
width: 18px;
height: 18px;
opacity: 1;
}
.sidebar .spacer {
flex: 1;
min-height: 8px;
}
/* ── 底栏:用户卡 + foot-btn + 主题 ── */
.sidebar .user-card {
display: flex;
align-items: center;
gap: 10px;
padding: 10px 12px;
margin-top: 8px;
border-top: 1px solid var(--rule);
}
.sidebar .user-card .avatar {
width: 32px;
height: 32px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
background: var(--patina);
color: var(--ink);
font-size: 13px;
font-weight: 600;
flex-shrink: 0;
}
.sidebar .user-card .info {
min-width: 0;
flex: 1;
}
.sidebar .user-card .name {
font-size: 13px;
font-weight: 500;
color: var(--fg);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.sidebar .user-card .role {
font-size: 12px;
color: var(--muted);
}
.sidebar-wrap.collapsed .user-card {
padding: 10px 0;
gap: 0;
justify-content: center;
}
.sidebar-wrap.collapsed .user-card .info {
display: none;
}
.foot-btn {
display: flex;
align-items: center;
gap: 10px;
padding: 7px 18px;
border-radius: 10px;
font-size: 12px;
color: var(--muted);
text-decoration: none;
cursor: pointer;
background: none;
border: none;
width: 100%;
font-family: inherit;
transition:
background 0.12s,
color 0.12s,
padding 0.2s;
}
.foot-btn:hover {
background: var(--overlay-hover);
color: var(--fg);
}
.sidebar-wrap.collapsed .foot-btn {
padding: 7px 0;
font-size: 0;
gap: 0;
justify-content: center;
}
.nav-item.nav-theme {
margin: 0 8px;
}
.sidebar-wrap.collapsed .nav-item.nav-theme {
margin: 0;
padding: 9px 0;
justify-content: center;
}
/* ── 页头与标题 ──
通用 .page-title/.page-sub 是默认(NarrowShell 22px);.page-header .page-title
特异性更高、覆盖为 AppShell 19px。无 .page-head 容器的页直接用通用默认。 */
.page-title {
font-family: "Songti SC", serif;
font-size: 22px;
font-weight: 700;
letter-spacing: 0.04em;
color: var(--fg);
margin: 0;
}
.page-sub {
font-size: 13px;
color: var(--fg-dim);
margin-top: 3px;
}
.page-header {
display: flex;
align-items: center;
gap: 12px;
padding: 14px 28px;
border-bottom: 1px solid var(--rule);
background: var(--surface);
backdrop-filter: blur(8px);
flex-shrink: 0;
flex-wrap: wrap;
}
.page-header .page-title {
font-family: "Songti SC", serif;
font-size: 19px;
font-weight: 700;
letter-spacing: 0.04em;
color: var(--fg);
}
.page-header .page-sub {
font-family: "JetBrains Mono", monospace;
font-size: 12px;
color: var(--fg-faint);
letter-spacing: 0.06em;
}
.page-header .spacer {
flex: 1;
}
/* ── 页体 ── */
.page-body {
flex: 1;
padding: 24px 28px 56px;
display: flex;
flex-direction: column;
gap: 22px;
max-width: 1180px;
width: 100%;
}
.section-label {
font-family: "JetBrains Mono", monospace;
font-size: 12px;
letter-spacing: 0.1em;
color: var(--fg-faint);
margin-bottom: 12px;
display: flex;
align-items: center;
gap: 8px;
}
.section-label .glyph {
color: var(--gilt);
opacity: 0.85;
font-family: "Songti SC", serif;
font-size: 14px;
}
.section-label .sub {
color: var(--fg-dim);
opacity: 0.7;
letter-spacing: 0.04em;
}
.section-label .count {
font-size: 11px;
color: var(--fg-dim);
font-weight: 400;
}
/* ── NarrowShell 主区(窄流程页:card-import / lorebook / character-*)
AppShell 壳 + 窄主区;.app-main 居中限宽,配 .back-link 面包屑。 ── */
.app-main {
flex: 1;
padding: 24px 28px 56px;
max-width: 920px;
width: 100%;
margin: 0 auto;
}
.app-main.narrow {
max-width: 760px;
} /* 更窄:导入流程等 */
.page-head {
display: flex;
align-items: flex-end;
justify-content: space-between;
gap: 16px;
margin-bottom: 18px;
}
.page-head .page-title {
font-family: "Songti SC", serif;
font-size: 22px;
font-weight: 700;
letter-spacing: 0.04em;
color: var(--fg);
margin: 0;
}
.page-head .page-sub {
font-size: 13px;
color: var(--fg-dim);
margin-top: 3px;
}
.back-link {
display: inline-flex;
align-items: center;
gap: 5px;
margin-bottom: 14px;
font-size: 13px;
color: var(--muted);
text-decoration: none;
cursor: pointer;
}
.back-link:hover {
color: var(--patina);
}
/* ── 卡片 ── */
.card {
border: 1px solid var(--rule);
border-radius: 14px;
background: var(--surface);
overflow: hidden;
margin-bottom: 16px;
}
.card-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 16px 20px 0;
}
.card-title {
font-family: "Songti SC", serif;
font-size: 15px;
font-weight: 600;
color: var(--fg);
display: flex;
align-items: center;
gap: 7px;
}
.card-title .glyph {
color: var(--patina);
opacity: 0.8;
}
.card-body {
padding: 16px 20px 20px;
}
/* ── 按钮 ── */
.btn {
display: inline-flex;
align-items: center;
gap: 5px;
padding: 7px 16px;
border-radius: 10px;
font-size: 12px;
font-weight: 500;
font-family: inherit;
cursor: pointer;
transition:
background 0.12s,
border-color 0.12s,
color 0.12s;
border: 1px solid transparent;
text-decoration: none;
}
.btn-primary {
background: var(--patina);
color: var(--ink);
border-color: var(--patina-dim);
}
.btn-primary:hover {
background: var(--patina-bright);
}
.btn-outline {
background: transparent;
color: var(--fg-dim);
border-color: var(--rule);
}
.btn-outline:hover {
background: var(--surface-hi);
color: var(--fg);
}
.btn-sm {
padding: 4px 11px;
font-size: 11px;
border-radius: 8px;
}
.btn-ghost {
background: transparent;
color: var(--muted);
border: none;
padding: 4px 8px;
}
.btn-ghost:hover {
color: var(--fg);
background: var(--overlay-hover);
}
.btn-danger {
background: transparent;
color: var(--cinnabar);
border-color: var(--cinnabar-dim);
}
.btn-danger:hover {
background: var(--cinnabar-wash);
color: var(--cinnabar);
}
.btn-icon {
display: inline-flex;
align-items: center;
justify-content: center;
width: 32px;
height: 32px;
padding: 0;
border-radius: 8px;
background: transparent;
color: var(--muted);
border: none;
cursor: pointer;
transition:
background var(--duration-fast),
color var(--duration-fast);
}
.btn-icon:hover {
background: var(--overlay-hover);
color: var(--fg);
}
/* ── 表单元素(统一 input / textarea / select / switch)── */
.input,
.textarea,
.select {
width: 100%;
padding: 8px 12px;
border: 1px solid var(--rule);
border-radius: 10px;
background: var(--glass);
color: var(--fg);
font-family: inherit;
font-size: 13px;
transition: border-color var(--duration-fast);
}
.input:focus,
.textarea:focus,
.select:focus {
outline: none;
border-color: var(--patina-dim);
}
.textarea {
min-height: 80px;
resize: vertical;
line-height: 1.6;
}
.select {
cursor: pointer;
}
.switch {
position: relative;
width: 32px;
height: 18px;
border-radius: 999px;
background: var(--rule);
cursor: pointer;
transition: background var(--duration-fast);
flex-shrink: 0;
}
.switch::after {
content: "";
position: absolute;
top: 2px;
left: 2px;
width: 14px;
height: 14px;
border-radius: 50%;
background: var(--fg-dim);
transition:
transform var(--duration-fast),
background var(--duration-fast);
}
.switch.on {
background: var(--patina-dim);
}
.switch.on::after {
transform: translateX(14px);
background: var(--patina);
}
.field-label {
display: block;
font-family: "JetBrains Mono", monospace;
font-size: 11px;
letter-spacing: 0.04em;
color: var(--muted);
margin-bottom: 4px;
}
/* ── 标签(通用胶囊)── */
.tag {
display: inline-flex;
align-items: center;
padding: 2px 9px;
border-radius: 999px;
font-family: "JetBrains Mono", monospace;
font-size: 10.5px;
border: 1px solid;
}
.tag-gilt {
border-color: var(--gilt-dim);
color: var(--gilt);
background: var(--gilt-faint);
}
.tag-patina {
border-color: var(--patina-dim);
color: var(--patina);
background: var(--patina-wash);
}
/* ── 状态药丸 ── */
.stat-pill {
display: inline-flex;
align-items: center;
gap: 6px;
font-family: "JetBrains Mono", monospace;
font-size: 11.5px;
color: var(--patina);
padding: 4px 12px;
border: 1px solid var(--patina-dim);
border-radius: 999px;
background: var(--patina-wash);
}
/* ── 滚动条 ── */
::-webkit-scrollbar {
width: 6px;
}
::-webkit-scrollbar-thumb {
background: var(--rule);
border-radius: 3px;
}
/* ── 响应式:中屏折叠侧栏为图标态,窄屏隐藏 ── */
@media (max-width: 1200px) and (min-width: 901px) {
.sidebar-wrap {
width: 60px;
}
.sidebar-wrap .nav-group-title {
opacity: 0;
max-height: 0;
padding: 0;
margin: 0;
}
.sidebar-wrap .nav-item {
padding: 9px 0;
font-size: 0;
gap: 0;
justify-content: center;
}
.sidebar-wrap .nav-item .ico {
width: 18px;
height: 18px;
opacity: 1;
}
.sidebar-wrap .sidebar-topbar {
justify-content: center;
padding: 6px 4px;
}
.sidebar-wrap .sidebar .logo {
font-size: 0;
justify-content: center;
}
.sidebar-wrap .sidebar .logo .logo-mark {
width: 22px;
height: 22px;
}
.sidebar-wrap .user-card {
padding: 10px 0;
gap: 0;
justify-content: center;
}
.sidebar-wrap .user-card .info {
display: none;
}
.sidebar-wrap .foot-btn {
padding: 7px 0;
font-size: 0;
gap: 0;
justify-content: center;
}
.sidebar-wrap .nav-item.nav-theme {
margin: 0;
padding: 9px 0;
justify-content: center;
}
}
@media (max-width: 900px) {
.sidebar-wrap {
display: none;
}
.page-body {
padding: 18px 16px 40px;
}
.app-main {
padding: 18px 16px 40px;
}
}