/* ============================================================================
 * 中流智舟云平台-ZLZZCloud — 主题令牌 + 主题切换组件
 * ----------------------------------------------------------------------------
 * 约定：<html> 上带 data-theme="light"|"dark" 表示「用户强制选择」；
 *       不带 data-theme 表示「跟随系统」，由 @media (prefers-color-scheme) 自动切换。
 * 暗色值 = 现有门户配色，亮色值为新增，两者收敛到同一套 CSS 变量。
 * 承重色值（--bg/--bg2/--card/--line/--txt/--mut + 暗色 --glass）与**桌面客户端
 * 品牌皮肤**逐字对齐（apps/desktop/src/brand-theme.css 的 :root / :root.dark）——
 * 客户端内嵌窗口里两侧因此是同一套表面/描边/文字色，不会『一个偏灰一个偏紫』。
 * 各静态页首屏已内联一小段脚本按 localStorage 提前设定 data-theme，避免闪烁。
 * ========================================================================== */

:root {
  color-scheme: dark;
  /* 背景 / 卡片 / 边框 */
  --bg: #0a0416;
  --bg2: #0d0720;
  --card: #130b26;
  --card2: #1a1428;
  --line: #2b1b55;
  --line2: #382a5c;
  /* 文字 */
  --txt: #ece5fc;
  --mut: #bcaee6;
  --mut2: #7d70a8;
  --body-txt: #d9d1ef;
  /* 强调 / 语义色 */
  --pri: #6F4AF4;
  --pri2: #4A2ACB;
  --acc: #38bdf8;
  --ok: #34d399;
  --warn: #fbbf24;
  --bad: #f87171;
  --ok2: #22c55e;
  --bad2: #ef4444;
  --warn2: #f59e0b;
  /* 渐变 */
  --grad: linear-gradient(135deg, #6F4AF4, #4A2ACB);
  --grad2: linear-gradient(135deg, #6F4AF4 0%, #4A2ACB 50%, #38bdf8 100%);
  --danger-grad: linear-gradient(135deg, #ef4444, #b91c1c);
  /* 输入 / 代码块 */
  --inp: #0f0a1d;
  --inp-ro: #0b0716;
  --pre: #07040e;
  /* 毛玻璃 / 遮罩 */
  --glass: rgba(10, 4, 22, .72);
  --glass-side: rgba(10, 6, 20, .7);
  --overlay: rgba(4, 2, 10, .74);
  --overlay2: rgba(4, 2, 10, .7);
  /* 分隔线 / 表面洗白 */
  --row-bd: rgba(255, 255, 255, .05);
  --row-bd2: rgba(255, 255, 255, .06);
  --surface-wash: rgba(255, 255, 255, .02);
  --surface-wash2: rgba(255, 255, 255, .07);
  --row-hover: rgba(111, 74, 244, .05);
  /* 滚动条 / 占位符 / 代码字 / 开关 */
  --thumb: #2b2145;
  --thumb-h: #3d2f61;
  --ph: #5b5183;
  --code-txt: #d8c8ff;
  --switch-off: #241b3c;
  /* 背景光斑 —— 暗色下压低调到接近客户端真图底纹的柔和度，减少长时间阅读的眩光累眼 */
  --glow-a: rgba(111, 74, 244, .16);
  --glow-b: rgba(56, 189, 248, .10);
  --glow-c: rgba(74, 42, 203, .12);
  --r: 8px;   /* 旧页面的容器圆角（index.html 的 .card/.feat、admin.html 的 .card 用 var(--r)）。
                 扁平口径下容器圆角上限就是 8px，新页一律用下面的 --r-flat / --r-flat-sm。 */
}

/* 亮色主题（用户强制选择亮色时） */
:root[data-theme="light"] {
  color-scheme: light;
  --bg: #f6f3fc;
  --bg2: #efeaf9;
  --card: #ffffff;
  --card2: #f7f6fb;
  --line: #ddd1f2;
  --line2: #d9d5e6;   /* 亮色柔化（2026-09-26）：#cfcbe0 偏中性灰、又比 --line 更「硬」，
                         而它恰好是唯一一个**不在桌面客户端皮肤里**的描边令牌（客户端亮色
                         --dt-border/--color-border 只对齐 --line = #ddd1f2），所以只柔化它，
                         --line / --bg2 保持与客户端逐字一致。它管的是 pill 边、次要按钮边、
                         金额块与支付卡边这几处亮色下最扎眼的小控件描边。 */
  --txt: #251a44;
  --mut: #6f6287;
  --mut2: #8b859b;
  --body-txt: #2b2840;
  --pri: #6F4AF4;
  --pri2: #4A2ACB;
  --acc: #0284c7;
  --ok: #059669;
  --warn: #b45309;
  --bad: #dc2626;
  --ok2: #16a34a;
  --bad2: #dc2626;
  --warn2: #d97706;
  --grad: linear-gradient(135deg, #6F4AF4, #4A2ACB);
  --grad2: linear-gradient(135deg, #6F4AF4 0%, #4A2ACB 50%, #0284c7 100%);
  --danger-grad: linear-gradient(135deg, #dc2626, #b91c1c);
  --inp: #ffffff;
  --inp-ro: #f1eff6;
  --pre: #f1eff6;
  --glass: rgba(255, 255, 255, .78);
  --glass-side: rgba(255, 255, 255, .82);
  --overlay: rgba(23, 19, 40, .42);
  --overlay2: rgba(23, 19, 40, .42);
  --row-bd: rgba(28, 22, 54, .08);
  --row-bd2: rgba(28, 22, 54, .10);
  --surface-wash: rgba(111, 74, 244, .035);
  --surface-wash2: rgba(111, 74, 244, .08);   /* 亮色柔化：原本是中性灰 rgba(28,22,54,.06)，
                        于是白卡上的 pill（状态标签 / 模型 slug / 类别标签）是一块「灰芯片」，
                        与整页的淡紫底不是一个色系。改成品牌淡紫洗白后，pill / 悬停面 /
                        选中面都归到同一族色里（暗色值不动）。 */
  --row-hover: rgba(111, 74, 244, .06);
  --thumb: #c9c5da;
  --thumb-h: #b3aed0;
  --ph: #9a94a8;
  --code-txt: #4c1d95;
  --switch-off: #d6d2e4;
  --glow-a: rgba(111, 74, 244, .14);
  --glow-b: rgba(2, 132, 199, .10);
  --glow-c: rgba(74, 42, 203, .10);
}

/* 跟随系统且系统偏好亮色（无 data-theme 时）。无 JS 兜底：靠浏览器原生 media query。 */
@media (prefers-color-scheme: light) {
  :root:not([data-theme]) {
    color-scheme: light;
    --bg: #f6f3fc;
    --bg2: #efeaf9;
    --card: #ffffff;
    --card2: #f7f6fb;
    --line: #ddd1f2;
    --line2: #d9d5e6;   /* 亮色柔化（2026-09-26）：#cfcbe0 偏中性灰、又比 --line 更「硬」，
                         而它恰好是唯一一个**不在桌面客户端皮肤里**的描边令牌（客户端亮色
                         --dt-border/--color-border 只对齐 --line = #ddd1f2），所以只柔化它，
                         --line / --bg2 保持与客户端逐字一致。它管的是 pill 边、次要按钮边、
                         金额块与支付卡边这几处亮色下最扎眼的小控件描边。 */
    --txt: #251a44;
    --mut: #6f6287;
    --mut2: #8b859b;
    --body-txt: #2b2840;
    --pri: #6F4AF4;
    --pri2: #4A2ACB;
    --acc: #0284c7;
    --ok: #059669;
    --warn: #b45309;
    --bad: #dc2626;
    --ok2: #16a34a;
    --bad2: #dc2626;
    --warn2: #d97706;
    --grad: linear-gradient(135deg, #6F4AF4, #4A2ACB);
    --grad2: linear-gradient(135deg, #6F4AF4 0%, #4A2ACB 50%, #0284c7 100%);
    --danger-grad: linear-gradient(135deg, #dc2626, #b91c1c);
    --inp: #ffffff;
    --inp-ro: #f1eff6;
    --pre: #f1eff6;
    --glass: rgba(255, 255, 255, .78);
    --glass-side: rgba(255, 255, 255, .82);
    --overlay: rgba(23, 19, 40, .42);
    --overlay2: rgba(23, 19, 40, .42);
    --row-bd: rgba(28, 22, 54, .08);
    --row-bd2: rgba(28, 22, 54, .10);
    --surface-wash: rgba(111, 74, 244, .035);
    --surface-wash2: rgba(111, 74, 244, .08);   /* 亮色柔化：原本是中性灰 rgba(28,22,54,.06)，
                        于是白卡上的 pill（状态标签 / 模型 slug / 类别标签）是一块「灰芯片」，
                        与整页的淡紫底不是一个色系。改成品牌淡紫洗白后，pill / 悬停面 /
                        选中面都归到同一族色里（暗色值不动）。 */
    --row-hover: rgba(111, 74, 244, .06);
    --thumb: #c9c5da;
    --thumb-h: #b3aed0;
    --ph: #9a94a8;
    --code-txt: #4c1d95;
    --switch-off: #d6d2e4;
    --glow-a: rgba(111, 74, 244, .14);
    --glow-b: rgba(2, 132, 199, .10);
    --glow-c: rgba(74, 42, 203, .10);
  }
}

/* ============================================================================
 * 主题切换按钮 + 下拉菜单（右上角）
 * ----------------------------------------------------------------------------
 * 2026-09-25 重做：原来这里是 38×38 / 10px 圆角 + 16px 模糊的大投影下拉菜单，
 * 与页面上的普通图标按钮（32×32 / 2.4px 圆角 / 1px 描边）不是一套语言，看起来
 * 「格格不入」。现在几何全部走下面那套扁平令牌：32×32、--r-flat-sm、1px 描边，
 * hover 是换面（--surface-wash2）而不是发光/描边变色；
 * 下拉菜单去大投影，改成 1px 描边 + 表面换色（--card2）区分，项高走 --ctl-h，
 * 选中项用 inset 主色细描边而不是加粗（client 的选中态口径）。
 * 类名一个没改：.theme-sw / .theme-btn / .theme-menu / .theme-ic / .t-ic /
 * .t-chk / .on / .open —— theme.js 的 querySelector 与 classList.toggle 全部照旧。
 * ========================================================================== */
.theme-sw { position: relative; display: inline-flex; }
/* z-index 定在弹窗层（.zf-modal = 1000）之下：弹出遮罩时不该有按钮浮在遮罩上面。
   999 仍高于页面内所有普通内容（下拉菜单自身在其内部层叠，不受影响）。 */
.theme-sw.fixed { position: fixed; top: var(--sp-4); right: var(--sp-4); z-index: 999; }
.theme-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: var(--ctl-h); height: var(--ctl-h); min-height: var(--ctl-h); padding: 0;
  background: transparent; border: 1px solid var(--line2); border-radius: var(--r-flat-sm);
  color: var(--mut); font-size: 15px; line-height: 1; cursor: pointer;
  font-family: inherit;
  transition: background .12s, color .12s, border-color .12s;
}
.theme-btn:hover { background: var(--surface-wash2); color: var(--txt); filter: none; }
.theme-btn:focus-visible { outline: none; border-color: var(--pri); box-shadow: var(--zf-sel); }
.theme-sw.open .theme-btn { background: var(--surface-wash2); color: var(--txt); }
.theme-ic { line-height: 1; }
/* 主题图标的字形由 theme.js 写入（ICONS = {auto:'◐', light:'☀️', dark:'🌙'}）——
   彩色 emoji 自带字号/行高与高饱和填色：亮色下那枚橙色实心圆与相邻文字按钮不是一套语言，
   内边距看着也与别处大小不一。这里隐藏 emoji 字形，改成与文字同色的单色字形按主题画（JS 一字未改）。 */
.theme-btn .theme-ic { font-size: 0; line-height: 0; }
.theme-btn .theme-ic::before { content: "\25D0"; font-size: 14px; line-height: 1; }
:root[data-theme="light"] .theme-btn .theme-ic::before { content: "\2600\FE0E"; }
:root[data-theme="dark"] .theme-btn .theme-ic::before { content: "\263E"; }
.theme-menu {
  position: absolute; top: calc(100% + var(--sp-2)); right: 0; min-width: 168px;
  background: var(--card2); border: 1px solid var(--line); border-radius: var(--r-flat);
  padding: var(--sp-1); box-shadow: none;
  opacity: 0; visibility: hidden; transform: translateY(-2px);
  transition: opacity .12s, transform .12s, visibility .12s; z-index: 400;
}
.theme-sw.open .theme-menu { opacity: 1; visibility: visible; transform: none; }
.theme-menu button {
  display: flex; align-items: center; gap: var(--sp-2); width: 100%; text-align: left;
  background: transparent; border: 0; border-radius: var(--r-flat-sm);
  padding: 0 var(--sp-2); min-height: var(--ctl-h);
  color: var(--mut); font-size: 13.5px; font-weight: 600; cursor: pointer;
  font-family: inherit; transition: background .12s, color .12s;
}
.theme-menu button:hover { background: var(--row-hover); color: var(--txt); filter: none; }
.theme-menu button:focus-visible { outline: none; background: var(--row-hover); color: var(--txt); box-shadow: var(--zf-sel); }
.theme-menu button .t-ic { width: var(--sp-5); text-align: center; font-style: normal; font-size: 14px; }
.theme-menu button .t-chk { margin-left: auto; color: var(--pri); font-weight: 700; opacity: 0; }
.theme-menu button.on {
  background: var(--surface-wash2); color: var(--txt);
  box-shadow: var(--zf-sel);   /* 选中 = 换面 + inset 主色细描边，不加粗 */
}
.theme-menu button.on:hover { background: var(--surface-wash2); }
.theme-menu button.on .t-chk { opacity: 1; }

/* ============================================================================
 * 扁平设计系统层（zf-*）—— 2026-09-25
 * ----------------------------------------------------------------------------
 * 为什么有这一层：云平台各页（index / admin / 登录 / 协议）此前各自内联了一套
 * 立体写法（大圆角、发光、大投影、14px 容器圆角），与桌面客户端的扁平口径对不上。
 * 这一层把「口径」收敛成一份可复用的共用件：间距刻度、圆角刻度、控件高、以及
 * zf- 前缀的组件类。以后各页只写结构与 zf- 类名，几何与表面色不用再各写一遍。
 *
 * 口径出处（与桌面客户端逐条对齐，别凭感觉改）：
 *   圆角  面板 3.2px / 容器 2.4px / 输入框按钮 2.5px（= 客户端 --radius-scalar:.2）
 *   深度  唯一的深度是输入框静息的 inset 一线；面板、按钮、下拉菜单一律无投影
 *   描边  统一 1px
 *   选中  换面 + inset 0 0 0 1px 主色细描边（不用渐变、不用投影、不加粗）
 *   发散  只有主按钮保留客户端同款 135 度紫渐变，其余一律纯色面
 *
 * 前缀用 zf- 而不是复用各页已有的类名：既有页面（含内联样式）本轮由各自的
 * 任务改，这里只提供新件，避免与既有类名互相踩。
 * 承重色值（--bg/--card/--line/--txt/--pri …）保持原样，一个都没动；
 * 这里新增的令牌只在上面的色板上做「浅底/细线」派生。
 * 主题判定沿用本文件的三段式：:root（暗） + :root[data-theme="light"]（亮）
 * + @media prefers-color-scheme:light（跟随系统且无 data-theme）。
 * ========================================================================== */

/* ---- 1) 刻度与派生色 ---------------------------------------------------- */
:root {
  /* 间距刻度：所有 margin/padding/gap 只从这七个里挑，别再写 13px/18px 这类散值 */
  --sp-1: 4px;
  --sp-2: 8px;
  --sp-3: 12px;
  --sp-4: 16px;
  --sp-5: 24px;
  --sp-6: 32px;
  --sp-7: 48px;
  /* 圆角刻度 */
  --r-flat: 3.2px;      /* 面板 / 卡片 / 弹窗 */
  --r-flat-sm: 2.4px;   /* 容器 / 控件 / 图标按钮 / 下拉项 */
  --r-flat-lg: 6px;     /* 极少数大件（空态插画框等），慎用 */
  /* 控件高：按钮、输入框、下拉项、导航项统一这个高度 */
  --ctl-h: 32px;
  /* 派生色：亮暗各自一套，组件里不出现写死的 rgb() */
  --zf-sel: inset 0 0 0 1px var(--pri);          /* 选中态细描边 */
  --zf-inset: inset 0 1px 1px rgba(167, 139, 250, .14);  /* 输入框静息唯一深度（暗） */
  --zf-ring: rgba(111, 74, 244, .26);            /* 输入框静息描边（暗） */
  --zf-pri-soft: rgba(111, 74, 244, .15);
  --zf-pri-line: rgba(111, 74, 244, .40);
  --zf-ok-soft: rgba(52, 211, 153, .15);
  --zf-ok-line: rgba(52, 211, 153, .40);
  --zf-warn-soft: rgba(251, 191, 36, .15);
  --zf-warn-line: rgba(251, 191, 36, .40);
  --zf-bad-soft: rgba(248, 113, 113, .15);
  --zf-bad-line: rgba(248, 113, 113, .42);
}
:root[data-theme="light"] {
  --zf-inset: inset 0 1px 1px rgba(111, 74, 244, .10);
  --zf-ring: rgba(111, 74, 244, .26);
  --zf-pri-soft: rgba(111, 74, 244, .10);
  --zf-pri-line: rgba(111, 74, 244, .42);
  --zf-ok-soft: rgba(5, 150, 105, .12);
  --zf-ok-line: rgba(5, 150, 105, .42);
  --zf-warn-soft: rgba(180, 83, 9, .12);
  --zf-warn-line: rgba(180, 83, 9, .42);
  --zf-bad-soft: rgba(220, 38, 38, .10);
  --zf-bad-line: rgba(220, 38, 38, .42);
}
@media (prefers-color-scheme: light) {
  :root:not([data-theme]) {
    --zf-inset: inset 0 1px 1px rgba(111, 74, 244, .10);
    --zf-ring: rgba(111, 74, 244, .26);
    --zf-pri-soft: rgba(111, 74, 244, .10);
    --zf-pri-line: rgba(111, 74, 244, .42);
    --zf-ok-soft: rgba(5, 150, 105, .12);
    --zf-ok-line: rgba(5, 150, 105, .42);
    --zf-warn-soft: rgba(180, 83, 9, .12);
    --zf-warn-line: rgba(180, 83, 9, .42);
    --zf-bad-soft: rgba(220, 38, 38, .10);
    --zf-bad-line: rgba(220, 38, 38, .42);
  }
}

/* ---- 2) 页面骨架 -------------------------------------------------------- */
/* 页面外壳：<body class="zf-body"> + 一个 .zf-shell（或 .zf-page 自带容器）。
   把「页面底色/文字色/字体栈/内容居中/最大宽度」一次定死，新页不要再各写一遍 body 样式。 */
.zf-body { background: var(--bg); color: var(--txt); min-height: 100vh; -webkit-text-size-adjust: 100%; }
.zf-body, .zf-body * { box-sizing: border-box; }
.zf-shell {
  width: 100%; max-width: 1080px; margin: 0 auto;
  padding: var(--sp-6) var(--sp-5) var(--sp-7);
  font-family: "Segoe UI", "PingFang SC", "Microsoft YaHei", system-ui, sans-serif;
  font-size: 14px; line-height: 1.6; color: var(--txt);
}
/* 页面根：所有直接子块之间自动 24px，页面不再靠 margin 东拼西凑 */
.zf-page { display: flex; flex-direction: column; gap: var(--sp-5); }
.zf-page > * { margin-top: 0; margin-bottom: 0; }
/* 浏览器默认的标题/段落外边距在设计系统里一律归零（间距只由 --sp-* 决定） */
.zf-page h1, .zf-page h2, .zf-page h3, .zf-page h4, .zf-page h5,
.zf-page p, .zf-page dl, .zf-page dt, .zf-page dd, .zf-page figure, .zf-page pre { margin: 0; }
.zf-page, .zf-page * { box-sizing: border-box; }
/* 页头：解释性文字与下方内容同宽（不要给副标题单独设 max-width，会被截断换行） */
.zf-page-hd { display: flex; flex-direction: column; gap: var(--sp-1); }
.zf-page-hd h1 { font-size: 18px; font-weight: 700; color: var(--txt); line-height: 1.35; }
.zf-page-hd h2 { font-size: 15.5px; font-weight: 700; color: var(--txt); line-height: 1.4; }
.zf-page-sub { font-size: 13px; color: var(--mut); line-height: 1.6; }
/* 右上角有固定切换器（.theme-sw.fixed 挂在 body 下）时，页头右侧自动让出一格，
   标题/说明不会钻到按钮下面；没有固定切换器的页面完全不受影响（:has 不匹配即整条失效）。 */
body:has(> .theme-sw.fixed) .zf-page-hd { padding-right: calc(var(--ctl-h) + var(--sp-3)); }

/* ---- 3) 容器 ------------------------------------------------------------ */
.zf-card {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r-flat);
  box-shadow: none; overflow: hidden;
}
.zf-card-hd {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border-bottom: 1px solid var(--line); background: var(--card);
  font-size: 13.5px; font-weight: 700; color: var(--txt);
}
.zf-card-hd .zf-page-sub { font-weight: 400; }
.zf-card-bd { padding: var(--sp-5); }
.zf-card-ft {
  display: flex; align-items: center; justify-content: flex-end; gap: var(--sp-2);
  padding: var(--sp-3) var(--sp-4); border-top: 1px solid var(--line);
}

/* 工具条：一排控件，统一对齐与间距 */
.zf-toolbar { display: flex; align-items: center; flex-wrap: wrap; gap: var(--sp-2); }
/* 撑开条：把后面的控件推到右边（等价 space-between，但可多次使用） */
.zf-spacer { flex: 1 1 auto; min-width: 0; }
.zf-toolbar > .zf-spacer { flex: 1 1 auto; }

/* 行 / 栈 */
.zf-row { display: flex; align-items: center; gap: var(--sp-3); min-width: 0; }
.zf-row--top { align-items: flex-start; }
.zf-row--between { justify-content: space-between; }
.zf-stack { display: flex; flex-direction: column; gap: var(--sp-3); min-width: 0; }
.zf-stack--tight { gap: var(--sp-2); }

/* 栅格：桌面自动多列，<=640 单列。
   align-items:start = 每张卡片按自己的内容高度收，不互相拉平（否则内容少的那张会空出半张）。
   需要等高的卡片行，页面自己写 align-items:stretch。 */
.zf-grid {
  display: grid; gap: var(--sp-4); align-items: start;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
}
.zf-grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.zf-grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }

/* ---- 4) 按钮 ------------------------------------------------------------ */
.zf-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-2);
  height: var(--ctl-h); min-height: var(--ctl-h); padding: 0 var(--sp-3);
  background: var(--card2); border: 1px solid var(--line2); border-radius: var(--r-flat-sm);
  color: var(--txt); font-family: inherit; font-size: 13.5px; font-weight: 600;
  line-height: 1; text-decoration: none; white-space: nowrap; cursor: pointer;
  box-shadow: none; transition: background .12s, color .12s, border-color .12s;
}
.zf-btn:hover { background: var(--surface-wash2); filter: none; }
.zf-btn:focus-visible { outline: none; border-color: var(--pri); box-shadow: var(--zf-sel); }
.zf-btn:disabled, .zf-btn[aria-disabled="true"] { opacity: .45; cursor: not-allowed; }
/* 主按钮：保留客户端同款 135 度紫渐变（这不属于「立体」，是品牌动作色） */
.zf-btn--pri { background: var(--grad); border-color: transparent; color: #fff; }
.zf-btn--pri:hover { background: var(--grad); filter: brightness(1.08); }
/* 幽灵按钮：只留 1px 描边 */
.zf-btn--ghost { background: transparent; border-color: var(--line2); color: var(--mut); }
.zf-btn--ghost:hover { background: var(--surface-wash2); color: var(--txt); }
/* 危险按钮 */
.zf-btn--danger { background: var(--zf-bad-soft); border-color: var(--zf-bad-line); color: var(--bad); }
.zf-btn--danger:hover { background: var(--zf-bad-soft); filter: brightness(1.06); }
.zf-btn--danger-solid { background: var(--danger-grad); border-color: transparent; color: #fff; }
/* 实心渐变按钮上的 focus：主色细描边在紫底/红底上看不清，改用 1px 白色 inset 细线
   （仍是 1px 细线，不引入投影）。 */
.zf-btn--pri:focus-visible, .zf-btn--danger-solid:focus-visible { border-color: transparent; box-shadow: inset 0 0 0 1px currentColor; }
/* 小号 */
.zf-btn--sm { height: 26px; min-height: 26px; padding: 0 var(--sp-2); font-size: 12.5px; border-radius: var(--r-flat-sm); }
/* 图标按钮：32x32，页面右上角那些小图标都用它，与主题切换按钮同一套几何 */
.zf-icon-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: var(--ctl-h); height: var(--ctl-h); min-height: var(--ctl-h); padding: 0;
  background: transparent; border: 1px solid var(--line2); border-radius: var(--r-flat-sm);
  color: var(--mut); font-size: 15px; line-height: 1; cursor: pointer;
  font-family: inherit; box-shadow: none;
  transition: background .12s, color .12s, border-color .12s;
}
.zf-icon-btn:hover { background: var(--surface-wash2); color: var(--txt); }
.zf-icon-btn:focus-visible { outline: none; border-color: var(--pri); box-shadow: var(--zf-sel); }

/* ---- 5) 表单控件 -------------------------------------------------------- */
.zf-label { display: block; font-size: 12.5px; font-weight: 600; color: var(--mut); margin-bottom: var(--sp-1); }
.zf-input, .zf-select, .zf-textarea {
  display: block; width: 100%; height: var(--ctl-h); min-height: var(--ctl-h);
  padding: 0 var(--sp-3);
  background: var(--inp); border: 1px solid var(--zf-ring); border-radius: var(--r-flat-sm);
  color: var(--txt); font-family: inherit; font-size: 13.5px; line-height: 1.5;
  box-shadow: var(--zf-inset);   /* 静息唯一的深度 */
  transition: border-color .12s, background .12s;
}
.zf-input::placeholder, .zf-textarea::placeholder { color: var(--ph); }
.zf-input:focus, .zf-select:focus, .zf-textarea:focus {
  outline: none; border-color: var(--pri); box-shadow: none;   /* focus 连描边环都不要 */
}
.zf-input:disabled, .zf-select:disabled, .zf-textarea:disabled,
.zf-input[readonly], .zf-textarea[readonly] {
  background: var(--inp-ro); color: var(--mut); box-shadow: none; cursor: not-allowed;
}
.zf-textarea { height: auto; min-height: 88px; padding: var(--sp-2) var(--sp-3); resize: vertical; }
.zf-field { display: flex; flex-direction: column; min-width: 0; }
.zf-hint { font-size: 12px; color: var(--mut2); line-height: 1.5; margin-top: var(--sp-1); }

/* ---- 6) 表格（.zf-tbl 是横向滚动包裹层，table 写在里面） ----------------- */
.zf-tbl {
  overflow-x: auto; -webkit-overflow-scrolling: touch;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r-flat);
}
.zf-tbl table { width: 100%; border-collapse: collapse; font-size: 13.5px; }
.zf-tbl th {
  text-align: left; white-space: nowrap; padding: var(--sp-2) var(--sp-3);
  background: var(--bg2); border-bottom: 1px solid var(--line);
  color: var(--mut); font-size: 12.5px; font-weight: 700;
}
.zf-tbl td {
  padding: var(--sp-2) var(--sp-3); border-bottom: 1px solid var(--row-bd);
  color: var(--body-txt); vertical-align: middle;
}
.zf-tbl tr:last-child td { border-bottom: 0; }
.zf-tbl tbody tr:hover td { background: var(--row-hover); }

/* ---- 7) 状态标签 -------------------------------------------------------- */
.zf-pill {
  display: inline-flex; align-items: center; gap: var(--sp-1);
  height: 20px; padding: 0 var(--sp-2);
  background: var(--surface-wash2); border: 1px solid transparent; border-radius: var(--r-flat-sm);
  color: var(--mut); font-size: 12px; font-weight: 600; white-space: nowrap;
}
.zf-pill--pri { background: var(--zf-pri-soft); border-color: var(--zf-pri-line); color: var(--pri); }
.zf-pill--ok { background: var(--zf-ok-soft); border-color: var(--zf-ok-line); color: var(--ok); }
.zf-pill--warn { background: var(--zf-warn-soft); border-color: var(--zf-warn-line); color: var(--warn); }
.zf-pill--bad { background: var(--zf-bad-soft); border-color: var(--zf-bad-line); color: var(--bad); }

/* ---- 8) 导航（侧栏默认竖排；<=900 收起成一条可横滑的条） ---------------- */
.zf-nav { display: flex; flex-direction: column; gap: 2px; padding: var(--sp-2); min-width: 0; }
.zf-nav-item {
  display: flex; align-items: center; gap: var(--sp-3);
  min-height: var(--ctl-h); padding: 0 var(--sp-3);
  background: transparent; border: 0; border-radius: var(--r-flat-sm);
  color: var(--mut); font-family: inherit; font-size: 13.5px; font-weight: 600;
  text-align: left; text-decoration: none; white-space: nowrap; cursor: pointer;
  box-shadow: none; transition: background .12s, color .12s;
}
.zf-nav-item:hover { background: var(--row-hover); color: var(--txt); }
.zf-nav-item.on, .zf-nav-item[aria-current="page"] {
  background: var(--surface-wash2); color: var(--txt); box-shadow: var(--zf-sel);
}
.zf-nav--row { flex-direction: row; flex-wrap: nowrap; overflow-x: auto; -webkit-overflow-scrolling: touch; }

/* ---- 9) 空态 ------------------------------------------------------------ */
.zf-empty { padding: var(--sp-7) var(--sp-4); text-align: center; color: var(--mut2); font-size: 13px; line-height: 1.6; }
.zf-empty strong { display: block; margin-bottom: var(--sp-1); color: var(--mut); font-size: 14px; font-weight: 700; }

/* ---- 10) 弹窗（.zf-modal 是遮罩层；面板用 .zf-modal-box） ---------------- */
.zf-modal {
  position: fixed; inset: 0; z-index: 1000;
  display: flex; align-items: center; justify-content: center; padding: var(--sp-4);
  background: var(--overlay);
}
.zf-modal[hidden] { display: none !important; }   /* 别让 display:flex 盖掉 hidden */
.zf-modal-box {
  width: min(560px, 100%); max-height: 88vh; overflow: auto;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r-flat);
  box-shadow: none;
}
.zf-modal-hd {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-4) var(--sp-5); border-bottom: 1px solid var(--line);
  font-size: 14px; font-weight: 700; color: var(--txt);
}
.zf-modal-bd { padding: var(--sp-5); color: var(--body-txt); font-size: 13.5px; line-height: 1.7; }
.zf-modal-ft {
  display: flex; align-items: center; justify-content: flex-end; gap: var(--sp-2);
  padding: var(--sp-4) var(--sp-5); border-top: 1px solid var(--line);
}

/* ---- 11) 键值行 --------------------------------------------------------- */
.zf-kv { display: grid; grid-template-columns: minmax(88px, auto) minmax(0, 1fr); gap: var(--sp-2) var(--sp-4); font-size: 13.5px; }
.zf-kv > dt, .zf-kv > .zf-k { color: var(--mut); }
.zf-kv > dd, .zf-kv > .zf-v { color: var(--txt); min-width: 0; word-break: break-word; }

/* ---- 12) 断点 ----------------------------------------------------------- */

/* <=900：导航 / 侧栏收起成一条（要保留竖排的加 .zf-nav--keep） */
@media (max-width: 900px) {
  .zf-nav {
    flex-direction: row; flex-wrap: nowrap; overflow-x: auto;
    -webkit-overflow-scrolling: touch; padding: var(--sp-2);
  }
  .zf-nav.zf-nav--keep { flex-direction: column; overflow: visible; }
  .zf-grid--2, .zf-grid--3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* <=640：单列、控件放宽到手指可用、表格横向滚 */
@media (max-width: 640px) {
  :root { --ctl-h: 44px; }   /* 手机端控件高 44px（触控目标下限） */
  .zf-shell { padding: var(--sp-4); }
  .zf-page { gap: var(--sp-4); }
  .zf-grid, .zf-grid--2, .zf-grid--3 { grid-template-columns: minmax(0, 1fr); }
  .zf-card-bd { padding: var(--sp-4); }
  .zf-card-hd, .zf-card-ft, .zf-modal-hd, .zf-modal-ft { padding: var(--sp-3) var(--sp-4); }
  .zf-modal-bd { padding: var(--sp-4); }
  .zf-empty { padding: var(--sp-6) var(--sp-3); }
  .zf-row { flex-wrap: wrap; }
  /* 一次性推开的撑开条在单列里没有意义，留着只会占一行空白 */
  .zf-toolbar > .zf-spacer { display: none; }
  /* 单列：工具条按钮、卡片/弹窗底部按钮一律整行（手指好按） */
  .zf-toolbar > .zf-btn { flex: 1 1 100%; }
  .zf-card-ft, .zf-modal-ft { flex-wrap: wrap; }
  .zf-card-ft > .zf-btn, .zf-modal-ft > .zf-btn, .zf-stack > .zf-btn { width: 100%; }
  /* 小号按钮在触屏上放到标准控件高：26px 高按不准，也是「点击区 >= 44px」的下限 */
  .zf-btn--sm { height: var(--ctl-h); min-height: var(--ctl-h); padding: 0 var(--sp-3); font-size: 13.5px; }
  /* 输入框 16px 防止 iOS 聚焦缩放（本页其余控件仍 13.5px） */
  .zf-input, .zf-select, .zf-textarea { font-size: 16px; }
  .zf-tbl table { min-width: 560px; }   /* 宁可横向滚，也不挤成一团 */
  .zf-kv { grid-template-columns: minmax(0, 1fr); gap: var(--sp-1); }
  .zf-kv > dt, .zf-kv > .zf-k { font-size: 12.5px; }
  /* 右上角挂着固定切换器时，页面整体下沉到按钮下沿（按钮高 + 上边距），
     标题与首个卡片不会钻到按钮下面 —— 只在真的有固定切换器时生效。 */
  body:has(> .theme-sw.fixed) .zf-page,
  body:has(> .theme-sw.fixed) .zf-shell { padding-top: calc(var(--ctl-h) + var(--sp-4)); }
}
