/* =============================================================================
   ds.css —— 后台管理系统 UI/UX 设计系统（antd-admin-design-system 落地层）
   -----------------------------------------------------------------------------
   三站（客服售后助手 / 云计算管理下载 / 临时聊天室）共用的**设计系统层**，
   实现规范里的：三档主题 token / 72px 图标轨道骨架 / 卡片·表格·表单·按钮·标签·
   KPI·抽屉·命令面板组件 / 768px 主断点双端适配 / 无障碍三条 / 等宽数字。

   用法（必须放在站点自身样式**之后**加载）：
       <link rel="stylesheet" href="assets/style.css">
       <link rel="stylesheet" href="assets/ds.css">
   原因：ds.css 里 `html[data-theme=*]`(0,1,1) 要盖过站点样式里的 `:root`(0,1,0)，
        同名组件规则靠后加载取胜。

   主题切换由 ds.js 负责：在 <html> 上写 data-theme="light|dark|ultra-dark"，
   同时在 <body> 上写 class="light|dark"（兼容 antd 惯例）。
   缺省（无属性）＝ 暗色，保证老用户观感不跳变。
   ========================================================================== */

/* =============================================================================
   1. 三档主题 token（规范 §2.1）
   ============================================================================= */

/* ---- 暗色：antd darkAlgorithm + 页面级变量。
        同时是「无 JS」时的兜底默认档 —— 这三站原本就是暗色，默认值不能跳变 ---- */
:root,
html[data-theme="dark"] {
  --bg-page:        #1a1b1f;
  --bg-card:        #23252b;
  --bg-card-solid:  #1c1e22;
  --bg-elevated:    #2d2f37;
  --bg-inset:       #1a1c20;
  --bg-deep:        #14161a;

  --text:           rgba(255, 255, 255, .85);
  --text-2:         rgba(255, 255, 255, .65);
  --text-3:         rgba(255, 255, 255, .45);
  --border:         #50566e;
  --border-2:       #414659;

  --primary:        #1668dc;
  --primary-hover:  #3c89e8;
  --primary-deep:   #14539f;
  --success:        #49aa19;
  --warning:        #d89614;
  --danger:         #dc4446;
  --danger-hover:   #e56b6d;
  --info:           #1668dc;

  /* 语义色的「文字档」：填充档在深底上当文字偏暗，文字统一走这一档 */
  --success-text:   #49aa19;
  --warning-text:   #d89614;
  --danger-text:    #dc4446;
  --info-text:      #3c89e8;

  /* 暗色层级靠描边 + 内高光，不靠外阴影（规范 §2.4） */
  --shadow-card:    0 1px 2px rgba(0, 0, 0, .40), inset 0 1px 0 rgba(255, 255, 255, .03);
  --shadow-pop:     0 8px 24px rgba(0, 0, 0, .55);
  --grid-color:     rgba(255, 255, 255, .06);
  --hairline:       1px solid var(--border-2);
}

/* ---- 亮色：antd defaultAlgorithm + 页面级变量 ---- */
html[data-theme="light"] {
  --bg-page:        #e6e8ec;
  --bg-card:        #ffffff;
  --bg-card-solid:  #ffffff;
  --bg-elevated:    #ffffff;
  --bg-inset:       #f5f6f8;
  --bg-deep:        #ffffff;

  --text:           rgba(0, 0, 0, .88);
  --text-2:         rgba(0, 0, 0, .65);
  --text-3:         rgba(0, 0, 0, .45);
  --border:         #d9d9d9;
  --border-2:       #f0f0f0;

  --primary:        #1677ff;
  --primary-hover:  #4096ff;
  --primary-deep:   #0958d9;
  --success:        #52c41a;
  --warning:        #faad14;
  --danger:         #cf1322;
  --danger-hover:   #e0413f;
  --info:           #1677ff;

  /* 填充档（#52c41a / #faad14）在白底上做文字对比度不够，
     文字统一改用 antd 的 color*Text 档 —— 语义不变，只是分档 */
  --success-text:   #389e0d;
  --warning-text:   #d48806;
  --danger-text:    #cf1322;
  --info-text:      #0958d9;

  --shadow-card:    0 1px 2px rgba(0, 0, 0, .06), 0 0 0 1px rgba(0, 0, 0, .02);
  --shadow-pop:     0 6px 16px rgba(0, 0, 0, .12);
  --grid-color:     rgba(99, 102, 241, .06);
  --hairline:       1px solid var(--border-2);
}

/* ---- 超暗（纯黑 OLED：省电 + 夜间）---- */
html[data-theme="ultra-dark"] {
  --rail-bg-drawer: #050507;   /* 超暗档抽屉再压一档，与纯黑页面拉开层次 */
  --bg-page:        #000000;
  --bg-card:        #101013;
  --bg-card-solid:  #101013;
  --bg-elevated:    #1a1a1e;
  --bg-inset:       #08080a;
  --bg-deep:        #050507;

  --text:           rgba(255, 255, 255, .85);
  --text-2:         rgba(255, 255, 255, .65);
  --text-3:         rgba(255, 255, 255, .45);
  --border:         #43485c;
  --border-2:       #33384a;

  --primary:        #1668dc;
  --primary-hover:  #3c89e8;
  --primary-deep:   #14539f;
  --success:        #49aa19;
  --warning:        #d89614;
  --danger:         #dc4446;
  --danger-hover:   #e56b6d;
  --info:           #1668dc;

  --success-text:   #49aa19;
  --warning-text:   #d89614;
  --danger-text:    #dc4446;
  --info-text:      #3c89e8;

  --shadow-card:    0 1px 2px rgba(0, 0, 0, .75), inset 0 1px 0 rgba(255, 255, 255, .04);
  --shadow-pop:     0 8px 24px rgba(0, 0, 0, .85);
  --grid-color:     rgba(255, 255, 255, .05);
  --hairline:       1px solid var(--border-2);
}

/* ---- 侧边栏轨道：三档主题下都保持深色（规范 §2.1 决策 2，性价比最高的一招）---- */
:root,
html[data-theme="light"],
html[data-theme="dark"],
html[data-theme="ultra-dark"] {
  --rail-bg:        #15161a;
  --rail-bg-drawer: #15161a;
  --rail-text:      rgba(255, 255, 255, .85);
  --rail-muted:     rgba(255, 255, 255, .45);
  --rail-border:    rgba(255, 255, 255, .08);
  --rail-hover:     rgba(255, 255, 255, .06);
}

/* ---- 形状 / 字号 / 尺寸（规范 §2.2）---- */
:root {
  --radius-sm:   4px;
  --radius:      6px;
  --radius-lg:   8px;
  --radius-card: 12px;
  --radius-pill: 999px;

  --fs:          14px;
  --fs-sm:       13px;
  --fs-xs:       12px;
  --control-h:   32px;

  --sider-rail:  72px;   /* 图标轨道宽度（规范 §3.1）*/
  --sider-w:     72px;   /* 当前实际宽度：默认收起成轨道 */
  --sider-expanded: 220px;
  --topbar-h:    32px;   /* 桌面状态条高度 */
  --tap-min:     40px;   /* 触控目标最小边（规范 §6.3）*/

  /* 间距阶梯：只用 4 的倍数（规范 §2.3）*/
  --gap-1: 4px;  --gap-2: 8px;  --gap-3: 12px;
  --gap-4: 16px; --gap-5: 24px; --gap-6: 32px;

  --pad-page:        var(--gap-5);      /* 桌面内容区 padding 24 */
  --gap-card:        var(--gap-3);      /* 桌面卡片间距 12 */
  /* 手机内容区 padding。
     规范原文是 `64px 12px 12px` —— 那 64px 是给「悬空汉堡」不遮住首屏内容留的。
     这里的状态条是 sticky 且自带标题行，汉堡落在状态条里（靠 .topbar.has-handle
     让出 60px 左内边距），内容区不再需要额外顶部留白，所以给 12px。 */
  --pad-page-mobile: var(--gap-3);
  --gap-card-mobile: var(--gap-2);      /* 手机卡片间距 8 */

  --mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace;
  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei",
          "Helvetica Neue", Arial, sans-serif;

  --dur: .2s;
}

/* =============================================================================
   2. 历史 token 别名 —— 让三站原有样式不加改动就跟随三档主题
   （别名落在 html[data-theme=*] 上，特异性高于站点自己的 :root）
   ============================================================================= */
html[data-theme="light"], html[data-theme="dark"], html[data-theme="ultra-dark"] {
  /* —— 客服售后助手 kf —— */
  --bg:            var(--bg-page);
  --sidebar:       var(--rail-bg);
  --card:          var(--bg-card);
  --card-head:     var(--bg-card-solid);
  --border-soft:   var(--border-2);
  --muted:         var(--text-2);
  --sidebar-w:     var(--sider-w);

  /* —— 云计算管理下载 swp —— */
  --bg2:           var(--bg-deep);
  --panel:         var(--bg-card);
  --panel2:        var(--bg-card-solid);
  --border2:       var(--border);
  --accent:        var(--primary);
  --accent2:       var(--primary-deep);
  --green:         var(--success);
  --red:           var(--danger);
  --yellow:        var(--warning);
  --radius-md:     10px;
  --radius-lg:     var(--radius-card);
  --radius-xl:     16px;

  /* —— 临时聊天室 talk —— */
  --brand:         var(--primary);
  --brand-dark:    var(--primary-deep);
  --warn:          var(--warning);
  --bubble:        color-mix(in srgb, var(--primary) 10%, var(--bg-card));
}

/* =============================================================================
   3. 基础层
   ============================================================================= */
* { box-sizing: border-box; }

html, body { height: 100%; }

body {
  margin: 0;
  padding: 0;
  font-family: var(--font);
  font-size: var(--fs);
  line-height: 1.6;
  background: var(--bg-page);
  color: var(--text);
  -webkit-text-size-adjust: 100%;
  touch-action: manipulation;
  transition: background-color var(--dur), color var(--dur);
}

a { color: var(--primary); text-decoration: none; }
a:hover { color: var(--primary-hover); }

/* hover 与 focus-visible 必须成对（规范 §5.1 / §8） */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
summary:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}
#main-content:focus { outline: none; }

.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 2000;
  padding: 8px 14px; background: var(--primary); color: #fff; border-radius: 0 0 var(--radius) 0;
}
.skip-link:focus { left: 0; }

/* 等宽数字：版本号 / 端口 / 流量 / 大小 / 时间（规范 §2.2） */
.mono, .num, code, pre, kbd, samp { font-family: var(--mono); }
.num { font-variant-numeric: tabular-nums; }

.muted { color: var(--text-2); }
.small, .sm { font-size: var(--fs-xs); }
.tc { text-align: center; }
.tr { text-align: right; }
.ellipsis { max-width: 220px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.hidden { display: none !important; }
[hidden] { display: none !important; }

/* 在线呼吸点（规范 §6.1 / §6.2） */
.online-dot, .dot-online {
  display: inline-block; width: 7px; height: 7px; border-radius: 50%;
  background: var(--success); flex-shrink: 0;
  animation: ds-online-blink 1.1s ease-in-out infinite;
}
@keyframes ds-online-blink {
  0%, to { opacity: 1;  box-shadow: 0 0 0 0 color-mix(in srgb, var(--success) 55%, transparent); }
  50%    { opacity: .35; box-shadow: 0 0 0 4px transparent; }
}

/* =============================================================================
   4. 骨架层（规范 §3）
   同时覆盖两套既有类名：kf 的 .app-shell/.page、swp 的 .layout/.content
   ============================================================================= */
.app-shell,
.layout {
  display: flex;
  min-height: 100vh;
  min-height: 100dvh;
  /* 老站点用 --sidebar-w 当作「侧栏宽度」的引用；在这里重算一次，
     这样 .rail-open 改 --sider-w 时，子元素继承到的 --sidebar-w 也跟着变
     （自定义属性在声明处求值，光在 html 上声明是不跟随的）。 */
  --sidebar-w: var(--sider-w);
}

/* ---- 侧边栏 → 72px 图标轨道 ---- */
.sidebar {
  width: var(--sider-w);
  flex: 0 0 var(--sider-w);
  min-width: 0;
  height: 100vh;
  height: 100dvh;
  /* 覆盖站点老样式里的 position:fixed + left/bottom（改 sticky 后它们会残留） */
  position: sticky;
  top: 0;
  left: auto; right: auto; bottom: auto;
  z-index: 100;
  display: flex;
  flex-direction: column;
  background: var(--rail-bg);
  border-right: 1px solid var(--rail-border);
  transition: width var(--dur), flex-basis var(--dur);
  overflow: hidden;
}

/* 品牌区：58px（规范 §5.1） */
.brand {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  height: 58px;
  flex: 0 0 58px;
  padding: 0 var(--gap-2);
  border-bottom: 1px solid var(--rail-border);
  color: var(--rail-text);
}
.rail-open .brand { justify-content: flex-start; padding-left: var(--gap-3); }
.brand-logo {
  width: 34px; height: 34px; flex-shrink: 0;
  border-radius: var(--radius-lg);
  background: linear-gradient(135deg, var(--primary), var(--primary-deep));
  color: #fff;
  font-weight: 700; font-size: 15px;
  display: flex; align-items: center; justify-content: center;
  letter-spacing: .5px;
}
.brand-logo.lg { width: 42px; height: 42px; font-size: 18px; border-radius: var(--radius-card); }
.brand-text { display: none; flex-direction: column; line-height: 1.3; min-width: 0; }
.rail-open .brand-text { display: flex; }
.brand-name {
  font-weight: 600; font-size: 18px; letter-spacing: .5px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.brand-sub { color: var(--rail-muted); font-size: var(--fs-xs); white-space: nowrap; }

/* ---- 图标尺寸统一兜底（很重要，别删）----
   CSS 里内联 <svg> 若没写 width/height，会按替换元素的默认尺寸 300×150 渲染，
   直接把 16px 的图标槽撑爆。2026-09-28 真实问题：主题按钮的图标槽被整段替换后，
   月亮图标渲染成 64×64，在 72px 轨道里占掉两格、看着像「一个巨大的方块」。
   这里统一钉死 16px；汉堡那类需要 20px 的另行声明（在后面，优先级更高）。 */
.nav-item svg, .nav-ico svg, .nav-icon svg, .cmd-trigger svg,
.icon-btn-sq svg, .ds-theme-fab svg, .sider-pin svg, .sidebar-theme-cycle svg,
.brand-acts svg, .cmdk-ico svg {
  width: 16px; height: 16px; flex-shrink: 0; display: block;
}

/* 品牌区小圆钮 30×30（规范 §5.1） */
.brand-acts { margin-left: auto; display: flex; align-items: center; gap: 2px; flex-shrink: 0; }
.icon-btn-sq, .sidebar-theme-cycle, .sider-pin {
  width: 30px; height: 30px; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  background: transparent; border: none; border-radius: 50%;
  color: var(--rail-muted); cursor: pointer; padding: 0;
  transition: background-color var(--dur), transform .15s, color var(--dur);
}
.icon-btn-sq:hover, .icon-btn-sq:focus-visible,
.sidebar-theme-cycle:hover, .sidebar-theme-cycle:focus-visible,
.sider-pin:hover, .sider-pin:focus-visible {
  background-color: color-mix(in srgb, var(--primary) 12%, transparent);
  color: var(--primary);
  transform: scale(1.08);
  outline: none;
}
.icon-btn-sq svg, .sidebar-theme-cycle svg, .sider-pin svg { width: 16px; height: 16px; }

/* 命令面板触发条：36px（规范 §3.1 ②）
   轨道收起时它是 56×36 的「只有放大镜」方块（规范 §5.1 明写）；
   文字与 Ctrl K 提示只在展开态出现，否则 72px 轨道里文字会被压成竖排。 */
.cmd-trigger {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  height: 36px; flex: 0 0 36px;
  margin: var(--gap-2) auto 0;
  padding: 0;
  width: 56px;
  border-radius: var(--radius-lg);
  border: 1px solid var(--rail-border);
  background: transparent;
  color: var(--rail-muted);
  font-size: var(--fs-xs); font-family: var(--font);
  cursor: pointer;
  transition: background-color var(--dur), color var(--dur), width var(--dur);
}
.cmd-trigger:hover, .cmd-trigger:focus-visible {
  background: var(--rail-hover); color: var(--rail-text); outline: none;
}
.cmd-trigger svg { width: 15px; height: 15px; flex-shrink: 0; }
.cmd-trigger > span { display: none; }
.cmd-trigger .cmd-kbd { margin-left: auto; gap: 3px; }
.rail-open .cmd-trigger { width: calc(100% - 16px); margin-inline: var(--gap-2); padding: 0 12px; justify-content: flex-start; }
.rail-open .cmd-trigger > span { display: inline-flex; }
.cmd-kbd kbd {
  font-size: 10px; line-height: 1;
  padding: 3px 5px; border-radius: var(--radius-sm);
  background: color-mix(in srgb, #fff 8%, transparent);
  border: 1px solid var(--rail-border);
  color: var(--rail-muted);
}

/* 主导航（可滚动，flex:auto） */
.nav { flex: 1; padding: var(--gap-2) 0; overflow-y: auto; overflow-x: hidden; }

/* 导航项：64×40、圆角 8、图标 16（规范 §3.1 / §5.1）
   background/border 显式置空：侧栏里的「轨道控制」是两个 <button class="nav-item">，
   不清掉的话会带上浏览器默认的 button 底色（buttonface）与 2px outset 边框，
   在深色轨道上会变成两块突兀的灰方块。 */
.nav-item {
  display: flex; align-items: center; gap: 11px;
  width: 64px; height: 40px;
  margin: 2px var(--gap-1);
  padding: 0;
  justify-content: center;
  border: 0;
  background: transparent;
  border-radius: var(--radius-lg);
  color: var(--rail-muted);
  font-size: var(--fs-sm);
  font-family: var(--font);
  text-align: left;
  cursor: pointer;
  white-space: nowrap;
  transition: background-color var(--dur), color var(--dur);
}
.nav-item:hover, .nav-item:focus-visible {
  background: var(--rail-hover); color: var(--rail-text); outline: none;
}
.nav-item.active {
  background: color-mix(in srgb, var(--primary) 20%, transparent);
  color: var(--primary);
}
.nav-item .nav-icon, .nav-item .nav-ico {
  width: 16px; height: 16px; flex-shrink: 0;
  font-size: 16px; line-height: 1; text-align: center;
  display: inline-flex; align-items: center; justify-content: center;
}
.nav-item .nav-label, .nav-item > span:not(.nav-ico):not(.nav-icon) { display: none; }

/* 展开态（点 pin）：显示文字，宽度回 220 */
.app-shell.rail-open, .layout.rail-open { --sider-w: var(--sider-expanded); }
.rail-open .nav-item {
  width: auto; justify-content: flex-start;
  padding: 0 12px; margin-inline: var(--gap-2);
}
.rail-open .brand-name { font-size: 15px; }
.rail-open .nav-item .nav-label,
.rail-open .nav-item > span:not(.nav-ico):not(.nav-icon) { display: inline; }
.rail-open .cmd-trigger { padding: 0 12px; }

/* 工具组（轨道收起/主题切换）—— 与主导航同款式，但单列一组，
   保证在 72px 轨道下也永远可见可点（品牌区只有 52px 可用宽，塞不下两枚按钮） */
.sidebar-tools {
  border-top: 1px solid var(--rail-border);
  padding: var(--gap-1) 0;
  flex: 0 0 auto;
}
.sidebar-tools button.nav-item {
  border: none; background: transparent; font-family: var(--font); cursor: pointer;
}

/* 工具组 + 页脚版本条（规范 §3.1） */
.sidebar-foot, .sider-utility {
  border-top: 1px solid var(--rail-border);
  padding: var(--gap-2);
  color: var(--rail-muted);
  /* 轨道只有 72px 宽，工具组必须竖排居中；展开后改回左对齐 */
  display: flex; flex-direction: column; align-items: center;
  justify-content: center; gap: 6px;
}
.rail-open .sidebar-foot, .rail-open .sider-utility { align-items: stretch; justify-content: flex-start; }
.sider-foot-ver {
  display: flex; align-items: center; justify-content: center; gap: 6px;
  height: 30px; font-family: var(--mono); font-size: var(--fs-xs);
  color: var(--rail-muted); border-top: 1px solid var(--rail-border);
}
.rail-open .sider-foot-ver { justify-content: flex-start; padding-left: var(--gap-3); }

.user-mini { display: flex; align-items: center; gap: 9px; justify-content: center; }
.rail-open .user-mini { justify-content: flex-start; }
.user-mini-meta { display: none; flex-direction: column; line-height: 1.3; min-width: 0; }
.rail-open .user-mini-meta { display: flex; }
.u-name { font-size: var(--fs-sm); color: var(--rail-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.u-role { font-size: var(--fs-xs); color: var(--rail-muted); }

.avatar {
  width: 30px; height: 30px; flex-shrink: 0;
  border-radius: 50%;
  background: var(--primary-deep); color: #fff;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: var(--fs-sm); font-weight: 600;
}

/* ---- 主内容区 ---- */
.main, .main-area {
  flex: 1; min-width: 0;
  /* 覆盖站点老样式的 margin-left: var(--sidebar-w)（改成 flex + sticky 后不需要它）*/
  margin-left: 0;
  display: flex; flex-direction: column;
}

/* 顶部状态条：桌面 32px（规范 §3.1 ①） */
.topbar {
  min-height: var(--topbar-h);
  height: auto;
  flex: 0 0 auto;
  display: flex; align-items: center; gap: var(--gap-3);
  padding: 0 var(--gap-5);
  position: sticky; top: 0; z-index: 50;
  background: var(--bg-deep);
  border-bottom: 1px solid var(--border-2);
}
.topbar-title, .topbar h1 {
  font-weight: 600; font-size: var(--fs);
  flex: 1; min-width: 0; margin: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.topbar-right { display: flex; align-items: center; gap: var(--gap-2); justify-content: flex-end; }
/* 右侧组的每个控件都不许被压窄：宽度不够时应该由**标题**去截断，
   而不是把头像/退出按钮挤成 0 宽（390px 下曾出现「头像整个消失」）。
   注意 flex 子项默认 flex-shrink:1，不显式写就会互相挤压。 */
.topbar-right > * { flex-shrink: 0; }

.status-pill {
  display: inline-flex; align-items: center; gap: 6px;
  height: 22px; padding: 0 10px;
  border-radius: var(--radius-pill);
  font-size: var(--fs-xs);
  background: color-mix(in srgb, var(--success) 14%, transparent);
  color: var(--success-text);
  white-space: nowrap;
}
.topbar .ver { font-family: var(--mono); font-size: var(--fs-xs); color: var(--text-2); white-space: nowrap; }

/* 内容区：桌面 padding 24 */
.page, .content { flex: 1; min-width: 0; padding: var(--pad-page); }
/* 内容区里直接子级的纵向间距也走设计系统阶梯（swp 的 .content 原本是 gap:20，收到 12） */
.content { display: flex; flex-direction: column; gap: var(--gap-card); }

/* ---- 浮动汉堡（仅 ≤768px，规范 §3.2）----
   只有显式带 .drawer-handle 的按钮才变成「左上角浮动圆钮」。
   .menu-toggle / .menu-btn 是站点既有的汉堡（内联在状态条里），位置交给站点自己，
   ds.css 只负责「桌面隐藏、手机出现」。 */
.drawer-handle {
  display: none;
  width: 40px; height: 40px;
  border-radius: 50%;
  background: rgba(0, 0, 0, .55);
  color: #fff;
  border: none;
  align-items: center; justify-content: center;
  position: fixed; top: 12px; left: 12px; z-index: 1100;
  cursor: pointer; padding: 0;
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
}
.drawer-handle svg { width: 20px; height: 20px; }

.menu-toggle, .menu-btn {
  display: none;
  align-items: center; justify-content: center;
  cursor: pointer;
  touch-action: manipulation;
}
.menu-toggle svg, .menu-btn svg { width: 20px; height: 20px; }
.menu-icon { width: 16px; height: 2px; background: currentColor; position: relative; display: block; }
.menu-icon::before, .menu-icon::after {
  content: ''; position: absolute; left: 0; width: 16px; height: 2px; background: currentColor;
}
.menu-icon::before { top: -5px; }
.menu-icon::after  { top: 5px; }

/* ---- 移动端抽屉（规范 §5.6）---- */
.drawer {
  position: fixed; top: 0; left: 0; bottom: 0; z-index: var(--z-drawer, 1200);
  width: 80%; max-width: 300px;
  background: var(--rail-bg-drawer);
  color: var(--rail-text);
  display: flex; flex-direction: column;
  transform: translateX(-100%);
  transition: transform var(--dur);
  overflow-y: auto;
  border-right: 1px solid var(--rail-border);
}
.drawer.open { transform: translateX(0); box-shadow: 0 0 32px rgba(0, 0, 0, .42); }
.drawer .nav { padding: var(--gap-2) 0; }
/* 抽屉菜单项高 48、圆角 0、贴边（规范 §5.6） */
.drawer .nav-item {
  width: auto; height: 48px;
  justify-content: flex-start;
  margin: 0; padding: 0 var(--gap-4);
  border-radius: 0;
  font-size: var(--fs);
}
.drawer .nav-item .nav-label,
.drawer .nav-item > span:not(.nav-ico):not(.nav-icon) { display: inline; }
.drawer-head {
  display: flex; align-items: center; gap: var(--gap-2);
  height: 58px; flex: 0 0 58px;
  padding: 0 var(--gap-2) 0 var(--gap-4);
  border-bottom: 1px solid var(--rail-border);
  font-weight: 600; font-size: var(--fs);
}
.drawer-foot { border-top: 1px solid var(--rail-border); padding: var(--gap-3) var(--gap-4); }
.drawer-mask, .mask {
  position: fixed; inset: 0;
  /* 站点若自带 z-index 体系（swp 的 --z-mask）就跟随它，否则用设计系统的档位。
     这里不写 opacity/visibility：kf 靠 .show 类、swp 靠 hidden 属性，
     两套开关方式不同，ds.css 插手显隐会把其中一套弄坏。 */
  z-index: var(--z-mask, 1150);
  background: rgba(0, 0, 0, .45);
}
body.drawer-open { overflow: hidden; }

/* =============================================================================
   5. 组件层（规范 §5）
   ============================================================================= */

/* ---- 卡片：圆角 12 + 1px 半透明描边 + 内高光（规范 §5.2）---- */
.card, .panel {
  background: var(--bg-card);
  border: var(--hairline);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  margin-bottom: var(--gap-card);
  overflow: hidden;
}
.card-head, .panel-head {
  display: flex; align-items: center; gap: var(--gap-2);
  padding: 13px var(--gap-4);
  font-weight: 600; font-size: var(--fs);
  background: var(--bg-card-solid);
  border-bottom: var(--hairline);
  flex-wrap: wrap;
}
.card-body, .panel-body { padding: var(--gap-4); }
.form-card { max-width: 860px; }
.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: var(--gap-card); }

/* ---- KPI / 指标 tile（规范 §5.3）---- */
.stat-grid, .stats {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--gap-card);
  margin-bottom: var(--gap-card);
}
.stat-card, .stat {
  background: var(--bg-card);
  border: var(--hairline);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  padding: var(--gap-4);
}
.stat-label, .stat-card .stat-label { color: var(--text-2); font-size: var(--fs-sm); }
.stat-value {
  font-size: 28px; font-weight: 700; line-height: 1.2;
  margin: 4px 0 2px;
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
}
.stat-foot, .stat-hint { color: var(--text-2); font-size: var(--fs-xs); }

/* ---- 表格（规范 §5.4）---- */
.table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.table { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); }
.table th, .table td {
  padding: 10px 14px; text-align: left;
  border-bottom: var(--hairline);
  white-space: nowrap;
}
.table th {
  color: var(--text-2); font-weight: 500; font-size: var(--fs-xs);
  background: var(--bg-card-solid);
  position: sticky; top: 0; z-index: 1;
}
.table tbody tr:hover { background: color-mix(in srgb, var(--primary) 5%, transparent); }
.table tbody tr:last-child td { border-bottom: none; }
.table td.num, .table th.num { text-align: right; font-family: var(--mono); font-variant-numeric: tabular-nums; }
.kv-table th { color: var(--text-2); font-weight: 500; width: 120px; }

/* ---- 按钮（规范 §2.2：高度 32、圆角 6）---- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  min-height: var(--control-h);
  padding: 5px 14px;
  border-radius: var(--radius);
  border: 1px solid transparent;
  font-size: var(--fs-sm); font-family: var(--font); line-height: 1.4;
  cursor: pointer;
  transition: background-color var(--dur), border-color var(--dur), color var(--dur), transform .15s;
}
.btn:disabled, .btn[disabled] { opacity: .45; cursor: not-allowed; }
.btn-primary { background: var(--primary); color: #fff; }
.btn-primary:hover:not(:disabled) { background: var(--primary-hover); color: #fff; }
.btn-ghost { background: transparent; border-color: var(--border); color: var(--text); }
.btn-ghost:hover:not(:disabled) { border-color: var(--primary); color: var(--primary-hover); }
.btn-danger { background: var(--danger); color: #fff; }
.btn-danger:hover:not(:disabled) { background: var(--danger-hover); color: #fff; }
.btn-warning { background: var(--warning); border-color: var(--warning); color: #fff; }
.btn-success { background: var(--success); border-color: var(--success); color: #fff; }
.btn-info { background: transparent; border-color: var(--info); color: var(--info-text); }
.btn-info:hover:not(:disabled) { background: color-mix(in srgb, var(--info) 12%, transparent); }
.btn-sm { min-height: 26px; padding: 2px 10px; font-size: var(--fs-xs); }
.btn-lg { min-height: 40px; padding: 8px 20px; font-size: var(--fs); }
.btn-block { width: 100%; }
.btn-icon { width: var(--control-h); padding: 0; }
.btn:active:not(:disabled) { transform: translateY(1px); }

/* ---- 表单 ---- */
.form { display: flex; flex-direction: column; gap: var(--gap-4); }
.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: var(--gap-4); }
.field { display: flex; flex-direction: column; gap: 6px; }
.field-label, .field > span:first-child { color: var(--text-2); font-size: var(--fs-sm); }

/* ---------------------------------------------------------------------------
   🔴 表单控件一律用 :where() 包起来 —— 让本层的特异性归零。

   为什么（2026-09-28 真实故障）：本层原先写成 `input[type=text], … , select,
   textarea { width: 100% }`，特异性是 (0,1,1)；而老站点里有大量「用 class 给
   控件定尺寸」的规则，例如 kf 的 `.wb-pick-cb { width: 18px; height: 18px }`
   是 (0,1,0)。ds.css 又在 app.css 之后加载 —— 结果 18px 被 width:auto 覆盖，
   自绘的取号勾选框塌缩成一根 3px 的细线，用户反馈「取号的时候选择框不见了」。
   同类：`.toolbar-form input { width: auto }`（分页/搜索框被撑满）也是这样被压掉的。

   :where() 的匹配行为不变，但特异性为 0 —— 于是：
     · 老站点自己的规则永远优先（本层只做「没有样式时的兜底」）
     · 站点没写过的控件，仍然吃到这里的统一外观
   ========================================================================= */
:where(input[type=text], input[type=password], input[type=email], input[type=number],
       input[type=search], input[type=file], select, textarea) {
  width: 100%;
  min-height: var(--control-h);
  padding: 5px 11px;
  background: var(--bg-inset);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: var(--text);
  font-size: var(--fs);
  font-family: inherit;
  outline: none;
  transition: border-color var(--dur), box-shadow var(--dur);
}
:where(input, select, textarea):focus {
  border-color: var(--primary);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--primary) 18%, transparent);
}
:where(input, textarea)::placeholder { color: var(--text-3); }
:where(input, select, textarea):disabled { opacity: .6; cursor: not-allowed; }
:where(textarea) { padding: 8px 11px; resize: vertical; min-height: 76px; }
:where(select) { cursor: pointer; }

/* 勾选框 / 单选框：只统一配色，**绝不去定尺寸** ——
   尺寸属于站点的自绘控件（kf 的取号勾选框、swp 的表头选择框都由 class 给）。
   accent-color 也让原生控件在暗底上不再是一片看不清的灰。 */
:where(input[type=checkbox], input[type=radio]) {
  accent-color: var(--primary);
  cursor: pointer;
}

/* 老内核（Chrome < 88 / Safari < 14）不认 :where()，上面整组规则会被丢弃。
   这里用普通选择器补一遍最要紧的兜底外观（尺寸仍然交给站点）。 */
@supports not (selector(:where(a))) {
  input[type=text], input[type=password], input[type=email], input[type=number],
  input[type=search], input[type=file], select, textarea {
    background: var(--bg-inset);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    color: var(--text);
    font-family: inherit;
  }
  input::placeholder, textarea::placeholder { color: var(--text-3); }
  input[type=checkbox], input[type=radio] { accent-color: var(--primary); }
}

/* ---- 标签 / 徽标 ---- */
.tag {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 1px 8px;
  border-radius: var(--radius-sm);
  font-size: var(--fs-xs);
  line-height: 18px;
  white-space: nowrap;
}
.tag-ok,   .tag-success { background: color-mix(in srgb, var(--success) 16%, transparent); color: var(--success-text); }
.tag-err,  .tag-danger  { background: color-mix(in srgb, var(--danger)  16%, transparent); color: var(--danger-text); }
.tag-info              { background: color-mix(in srgb, var(--info)    16%, transparent); color: var(--info-text); }
.tag-warn, .tag-warning { background: color-mix(in srgb, var(--warning) 16%, transparent); color: var(--warning-text); }
.tag-role              { background: color-mix(in srgb, var(--warning) 16%, transparent); color: var(--warning-text); }
.tag-muted             { background: color-mix(in srgb, var(--text-2)   14%, transparent); color: var(--text-2); }

/* ---- 提示条 ---- */
.alert {
  display: flex; align-items: center; gap: 8px;
  padding: 9px 14px;
  border: 1px solid transparent;
  border-radius: var(--radius);
  margin-bottom: var(--gap-3);
  font-size: var(--fs-sm);
  line-height: 1.6;
}
.alert-success { background: color-mix(in srgb, var(--success) 12%, transparent); border-color: color-mix(in srgb, var(--success) 40%, transparent); color: var(--success-text); }
.alert-error, .alert-danger { background: color-mix(in srgb, var(--danger) 12%, transparent); border-color: color-mix(in srgb, var(--danger) 40%, transparent); color: var(--danger-text); }
.alert-warning { background: color-mix(in srgb, var(--warning) 12%, transparent); border-color: color-mix(in srgb, var(--warning) 40%, transparent); color: var(--warning-text); }
.alert-info { background: color-mix(in srgb, var(--info) 12%, transparent); border-color: color-mix(in srgb, var(--info) 40%, transparent); color: var(--info-text); }
.notice {
  display: flex; align-items: center; gap: 8px;
  padding: 9px 14px; margin-bottom: var(--gap-4);
  background: color-mix(in srgb, var(--info) 10%, transparent);
  border: 1px solid color-mix(in srgb, var(--info) 30%, transparent);
  border-radius: var(--radius);
  color: var(--info-text);
}

/* ---- 工具栏 / 分页 / 空态 ---- */
.toolbar { display: flex; align-items: center; gap: var(--gap-3); flex-wrap: wrap; margin-bottom: var(--gap-3); }
.toolbar-form { display: flex; align-items: center; gap: var(--gap-2); flex-wrap: wrap; flex: 1; }
.toolbar-form input[type=text] { max-width: 280px; }

.pagination { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; padding: var(--gap-3) var(--gap-4); }
.pg-item {
  min-width: var(--control-h); height: var(--control-h);
  display: inline-flex; align-items: center; justify-content: center;
  padding: 0 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: var(--text);
  font-family: var(--mono); font-size: var(--fs-sm);
}
.pg-item:hover { border-color: var(--primary); color: var(--primary); }
.pg-item.active { background: var(--primary); border-color: var(--primary); color: #fff; }
.pg-gap { color: var(--text-3); padding: 0 2px; }
.pg-total { margin-left: auto; color: var(--text-2); font-size: var(--fs-xs); }

.empty, .empty-sm, .wb-empty { padding: var(--gap-5); text-align: center; color: var(--text-2); font-size: var(--fs-sm); }

/* ---- 模态（规范 §5.5：桌面 780，手机 96vw）----
   ⚠️ 这些规则**故意用 :where() 降到 0 特异性**：
      凡是站点自己已有 .modal / .modal-card 的（swp 就有完整一套：
      90%/560px、modal-card-wide 96vw/1240px、右上下角 padding 22px…），
      一律以站点为准 —— 设计系统只负责「站点没定义时兜底」。
      2026-09-28：ds 的 width:780px 曾把 swp 的 1240px 宽弹窗压成 780，
                  .modal-head 的 padding 又把标题栏顶高 17px。 */
/* ---- 模态（规范 §5.5：桌面 780，手机 96vw）---- */
:where(.modal) { position: fixed; inset: 0; z-index: var(--z-modal, 1300); display: flex; align-items: center; justify-content: center; padding: var(--gap-4); }
:where(.modal-mask) { position: absolute; inset: 0; background: rgba(0, 0, 0, .5); }
:where(.modal-card) {
  position: relative;
  width: 780px; max-width: 100%;
  max-height: 88vh; overflow: auto;
  background: var(--bg-elevated);
  border: var(--hairline);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-pop);
}
:where(.modal-head) { display: flex; align-items: center; gap: var(--gap-2); padding: 13px var(--gap-4); border-bottom: var(--hairline); }
:where(.modal-head h3) { margin: 0; font-size: var(--fs); font-weight: 600; flex: 1; }
:where(.modal-x) {
  width: 30px; height: 30px; border: none; background: transparent; border-radius: 50%;
  color: var(--text-2); cursor: pointer; font-size: 15px;
}
:where(.modal-x:hover) { background: color-mix(in srgb, var(--primary) 12%, transparent); color: var(--primary); }

/* ---- Toast：设计系统层「不」提供 .toast ----
   ----------------------------------------------------------------------------
   🔴 2026-09-28 踩坑（真实线上事故）：
      这里原来按规范写了一套「底部居中」的 toast
        .toast { left: 50%; bottom: 28px; transform: translateX(-50%) ... }
      swp 站点自己那套是「右上角」
        .toast { top: 20px; right: 24px; transform: translateX(120%) ... }
      两者特异性相同、ds.css 后加载。问题在于**层叠只按「同一属性」比较**：
      站点定义了 top/right，ds 定义了 left/bottom，互不冲突 → 四个边全部生效，
      元素被死死拉伸成 1440-720-24=696 宽 × 900-20-28=852 高，
      于是一次「保存成功」的提示就是一个铺满右半屏的巨大绿色方块。

   ⚠️ 这类「站点未定义、设计系统补上」的定位属性，用 :where() 降权也救不了
      （降权只影响同一属性的胜负，补上的 left/bottom 照样生效）。
      所以定位/尺寸这类「必须整组一致」的声明，要么整套给、要么整套不给。

   结论：.toast 的定位与尺寸一律交给站点自己（swp 有完整实现，
   kf 用的是另一套 .wb-toast，talk 没有 toast）。设计系统层不掺和。
   仅保留下面 forced-colors 里对 .toast 的高对比度增强（正常模式不影响）。 */

/* ---- 登录页 ---- */
.auth-body, .login-body {
  display: flex; align-items: center; justify-content: center;
  min-height: 100vh; min-height: 100dvh;
  background: var(--bg-page);
  padding: var(--gap-5) var(--gap-4);
}
.auth-wrap, .login-wrap { width: 100%; max-width: 420px; }
.auth-card, .login-card {
  background: var(--bg-card);
  border: var(--hairline);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  padding: 28px var(--gap-5);
}
.auth-brand, .login-brand { display: flex; align-items: center; gap: var(--gap-3); margin-bottom: var(--gap-5); }
.auth-brand h1, .login-brand h1 { margin: 0; font-size: 19px; font-weight: 650; }
.auth-brand p { margin: 2px 0 0; color: var(--text-2); font-size: var(--fs-xs); }
.auth-form { display: flex; flex-direction: column; gap: var(--gap-4); }
.auth-foot { margin-top: var(--gap-4); color: var(--text-2); font-size: var(--fs-xs); line-height: 1.7; }
.auth-back { margin-top: var(--gap-3); text-align: center; font-size: var(--fs-xs); }
.login-err {
  padding: 8px 12px; margin-bottom: var(--gap-3);
  background: color-mix(in srgb, var(--danger) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--danger) 40%, transparent);
  border-radius: var(--radius);
  color: var(--danger-text); font-size: var(--fs-sm);
}

/* 主题切换浮钮：登录页 / 门户共用（右上角） */
.ds-theme-fab {
  position: fixed; top: 12px; right: 12px; z-index: 1100;
  width: 36px; height: 36px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--bg-card); border: var(--hairline); color: var(--text-2);
  cursor: pointer; padding: 0; box-shadow: var(--shadow-card);
  transition: transform .15s, color var(--dur), background-color var(--dur);
}
.ds-theme-fab:hover, .ds-theme-fab:focus-visible { color: var(--primary); transform: scale(1.08); outline: none; }
.ds-theme-fab svg { width: 18px; height: 18px; }

/* =============================================================================
   6. 命令面板（规范 §5.7）
   ============================================================================= */
.cmdk { position: fixed; inset: 0; z-index: 1500; display: none; }
.cmdk.open { display: block; }
.cmdk-mask { position: absolute; inset: 0; background: rgba(0, 0, 0, .5); }
.cmdk-box {
  position: relative;
  width: 680px; max-width: calc(100vw - 32px);
  max-height: 638px;
  margin: 12vh auto 0;
  background: var(--bg-elevated);
  border: var(--hairline);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-pop);
  display: flex; flex-direction: column;
  overflow: hidden;
}
.cmdk-input {
  width: 100%; border: none; border-bottom: var(--hairline);
  background: transparent; color: var(--text);
  padding: 14px 18px; font-size: 15px; font-family: var(--font);
  min-height: 0; border-radius: 0;
}
.cmdk-input:focus { box-shadow: none; border-color: var(--border-2); }
.cmdk-list { overflow-y: auto; padding: 6px; flex: 1; }
.cmdk-group {
  padding: 8px 12px 4px;
  font-size: var(--fs-xs); color: var(--text-3);
  text-transform: uppercase; letter-spacing: .5px;
}
.cmdk-item {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 12px;
  border-radius: var(--radius-lg);
  color: var(--text); cursor: pointer;
  font-size: var(--fs-sm);
}
.cmdk-item:hover, .cmdk-item.on {
  background: color-mix(in srgb, var(--primary) 14%, transparent);
  color: var(--primary);
}
.cmdk-item .cmdk-ico { width: 16px; height: 16px; flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center; }
.cmdk-item .cmdk-hint { margin-left: auto; font-size: var(--fs-xs); color: var(--text-3); font-family: var(--mono); }
.cmdk-foot {
  display: flex; align-items: center; gap: 14px;
  padding: 9px 16px;
  border-top: var(--hairline);
  font-size: var(--fs-xs); color: var(--text-3);
}
.cmdk-foot .cmdk-foot-right { margin-left: auto; font-weight: 600; }

/* =============================================================================
   7. 响应式（规范 §4.1：主断点只有一个 —— 768px）
   ============================================================================= */
@media (max-width: 1100px) {
  .stat-grid, .stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .grid-2 { grid-template-columns: 1fr; }
}

@media (max-width: 768px) {
  /* 侧栏整体宽度归零（不是 display:none —— 内部子元素仍可参与布局计算），
     导航迁到抽屉。visibility:hidden 是为了键盘 Tab 不会跑进一个 0 宽的侧栏。 */
  .sidebar {
    flex: 0 0 0;
    width: 0; min-width: 0; max-width: 0;
    border-right: none;
    overflow: hidden;
    visibility: hidden;
  }

  /* 站点自带的「侧栏即抽屉」模式（kf 的 #sidebar.open）：
     展开时把同一个元素恢复成 80% 宽的抽屉，不额外复制一份 DOM */
  .sidebar.open {
    position: fixed; top: 0; left: 0; bottom: 0;
    z-index: 1200;
    flex: 0 0 auto;
    width: 80%; max-width: 300px; min-width: 0;
    visibility: visible;
    background: var(--rail-bg-drawer);
    border-right: 1px solid var(--rail-border);
    box-shadow: 0 0 32px rgba(0, 0, 0, .42);
    overflow-y: auto;
  }
  /* 抽屉里导航项高 48、圆角 0、贴边（规范 §5.6） */
  .sidebar.open .nav-item {
    width: auto; height: 48px;
    justify-content: flex-start;
    margin: 0; padding: 0 var(--gap-4);
    border-radius: 0;
    font-size: var(--fs);
  }
  .sidebar.open .nav-item .nav-label,
  .sidebar.open .nav-item > span:not(.nav-ico):not(.nav-icon) { display: inline; }
  .sidebar.open .brand-name { font-size: 15px; }
  .sidebar.open .user-mini { justify-content: flex-start; }
  .sidebar.open .user-mini-meta { display: flex; }
  .sidebar.open .cmd-trigger { display: none; }
  .sidebar.open .brand-acts { display: none; }

  .drawer-handle, .menu-toggle, .menu-btn { display: inline-flex; }

  .topbar {
    /* 手机状态条**保持单行**：左边 60px 让位给浮动汉堡，中间标题截断，右侧组钉在右边。
       历史坑：这里原本是 flex-wrap:wrap + 子项 flex:1 1 100%，
       结果是「标题独占一行、账号与退出换行后从左排起」——
       视觉上就像账户信息和退出按钮跑到了左边。 */
    padding: 6px var(--gap-3);
    padding-top: calc(6px + var(--sa-top, 0px));
    flex-wrap: nowrap;
    gap: var(--gap-2);
    min-height: 52px;
  }
  /* 浮动汉堡要占住左上角，状态条左侧让出 60px */
  .topbar.has-handle { padding-left: 60px; }
  .topbar-title, .topbar h1 { flex: 1 1 auto; min-width: 0; font-size: 15px; }
  .topbar-right { flex: 0 0 auto; flex-wrap: nowrap; justify-content: flex-end; }
  /* 状态胶囊与版本号在手机上省掉（时间/版本不是这里要看的东西），
     省下来的宽度留给「标题 + 退出 + 头像」 */
  .topbar .status-pill, .topbar .ver { display: none; }
  /* 用户名与下拉箭头收起，只留头像 —— 免得把「退出」挤到看不见 */
  .topbar .user-btn .u-name, .topbar .user-btn .chev { display: none; }
  .topbar .user-btn { padding: 4px; }
  /* 🔴 账号入口在手机上**保留**（只是收成头像）：
     站点自己有一条 ≤560px 的 `.user-dropdown { display: none }`，
     理由是「给退出按钮让位」。但主题切换按钮已经下线、位置腾出来了，
     而用户明确要求「账户信息不要消失 / 不要跑到左边」——
     所以这里用更高特异性把它显示回来，与「退出」并排、一起钉在右侧。
     （特异性 .topbar .user-dropdown = 0,2,0 > 站点那条 0,1,0，无需 !important） */
  .topbar .user-dropdown { display: block; }
  /* 🔴 「退出」在手机上**保留文字**：只留图标会变成一个认不出来的小方块
     （用户 2026-09-28 反馈原话：「退出登录的按钮也是不知名方框」） */
  .topbar-exit { padding: 0 10px; font-size: var(--fs-xs); }
  .topbar-exit svg { width: 14px; height: 14px; }

  .page, .content { padding: var(--pad-page-mobile); }

  .card, .panel { margin-bottom: var(--gap-card-mobile); }
  .card-body, .panel-body { padding: var(--gap-3); }
  .stat-grid, .stats { grid-template-columns: 1fr; gap: var(--gap-card-mobile); }
  .grid-2 { grid-template-columns: 1fr; gap: var(--gap-card-mobile); }

  /* 表格 → 卡片流（同一份 DOM，用 data-label 渲染字段名）。
     服务端渲染站点没有 React 条件渲染这一层，改为 CSS 卡片化；
     站点只要给主要表格加 .cardify 类即可（别用 display:none 藏表格）。 */
  .table-wrap { overflow-x: visible; }
  table.cardify { border-collapse: separate; }
  table.cardify thead { display: none; }
  table.cardify tbody, table.cardify tr, table.cardify td { display: block; width: 100%; }
  table.cardify tr {
    background: var(--bg-card);
    border: var(--hairline);
    border-radius: var(--radius-card);
    box-shadow: var(--shadow-card);
    margin-bottom: var(--gap-card-mobile);
    padding: var(--gap-2) var(--gap-3);
  }
  table.cardify td {
    display: flex; align-items: center; gap: var(--gap-3);
    border-bottom: none; padding: 7px 0;
    white-space: normal; text-align: right;
  }
  table.cardify td::before {
    content: attr(data-label);
    flex: 0 0 84px;
    text-align: left;
    color: var(--text-2);
    font-size: var(--fs-xs);
    white-space: nowrap;
  }
  table.cardify td:not([data-label])::before { content: none; }
  table.cardify td .btn { min-height: 30px; }
  table.cardify td[data-label="操作"] { flex-wrap: wrap; justify-content: flex-end; }
  table.cardify .hide-mobile { display: none !important; }

  .form-row { grid-template-columns: 1fr; }
  .toolbar { flex-direction: column; align-items: stretch; }
  .toolbar-form input[type=text] { max-width: none; }

  /* 弹窗近全宽（规范 §4.3） */
  :where(.modal) { padding: var(--gap-2); align-items: flex-end; }
  :where(.modal-card) { width: 100%; max-height: 92vh; border-radius: var(--radius-card) var(--radius-card) 0 0; }

  .cmdk-box { margin-top: 6vh; max-height: 80vh; }

  /* iOS 一聚焦就放大整页：输入控件字号必须 ≥16px */
  input, select, textarea { font-size: 16px !important; }
}

@media (max-width: 560px) {
  .stat-value { font-size: 24px; }
  .pagination .pg-total { margin-left: 0; flex: 1 1 100%; }
}

/* ---- 无障碍降级（规范 §6.3）---- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
  .nav-item:hover, .icon-btn-sq:hover, .sidebar-theme-cycle:hover,
  .sider-pin:hover, .btn:active, .ds-theme-fab:hover { transform: none !important; }
}

/* Windows 高对比度模式 */
@media (forced-colors: active) {
  .card, .panel, .stat-card, .stat, .modal-card, .cmdk-box, .toast {
    border: 1px solid CanvasText; box-shadow: none;
  }
  .btn, .nav-item, .tag, .pg-item { forced-color-adjust: auto; }
  .brand-logo, .avatar { background: Highlight; color: HighlightText; }
  .online-dot { background: CanvasText; animation: none; }
  .nav-item.active { outline: 2px solid Highlight; }
  .sidebar { border-right: 1px solid CanvasText; }
}

/* ---- 打印 ---- */
@media print {
  .sidebar, .drawer, .drawer-mask, .mask, .topbar, .cmdk, .drawer-handle,
  .menu-toggle, .menu-btn, .toolbar { display: none !important; }
  body { background: #fff; color: #000; }
  .card, .panel { break-inside: avoid; box-shadow: none; }
}

/* =============================================================================
   8. 旧浏览器兜底：不支持 color-mix() 时的降级配色
   -----------------------------------------------------------------------------
   color-mix() 需要 Chrome 111+ / Safari 16.2+ / Firefox 113+。客服、客户那边
   仍可能跑在旧版 360/WebView 内核上 —— 那里 color-mix 会让整条声明失效，
   于是「选中态没有底色」「状态标签没有底色」这类问题会静默出现。
   @supports not 包住一组固定色兜底值：现代浏览器直接跳过这一整块。
   ========================================================================== */
@supports not (color: color-mix(in srgb, red, blue)) {
  .nav-item:hover, .nav-item:focus-visible { background: rgba(255, 255, 255, .06); }
  .nav-item.active { background: rgba(22, 104, 220, .20); }
  .icon-btn-sq:hover, .icon-btn-sq:focus-visible,
  .sidebar-theme-cycle:hover, .sidebar-theme-cycle:focus-visible,
  .sider-pin:hover, .sider-pin:focus-visible { background: rgba(22, 104, 220, .12); }
  .cmdk-item:hover, .cmdk-item.on { background: rgba(22, 104, 220, .14); }
  input:focus, select:focus, textarea:focus { box-shadow: 0 0 0 2px rgba(22, 104, 220, .18); }
  .table tbody tr:hover { background: rgba(22, 104, 220, .05); }
  .status-pill { background: rgba(73, 170, 25, .14); }
  .tag-ok, .tag-success { background: rgba(73, 170, 25, .16); }
  .tag-err, .tag-danger { background: rgba(220, 68, 70, .16); }
  .tag-info { background: rgba(22, 104, 220, .16); }
  .tag-warn, .tag-warning, .tag-role { background: rgba(216, 150, 20, .16); }
  .tag-muted { background: rgba(136, 136, 136, .14); }
  .alert-success { background: rgba(73, 170, 25, .12); border-color: rgba(73, 170, 25, .40); }
  .alert-error, .alert-danger { background: rgba(220, 68, 70, .12); border-color: rgba(220, 68, 70, .40); }
  .alert-warning { background: rgba(216, 150, 20, .12); border-color: rgba(216, 150, 20, .40); }
  .alert-info, .notice { background: rgba(22, 104, 220, .12); border-color: rgba(22, 104, 220, .40); }
  .login-err { background: rgba(220, 68, 70, .12); border-color: rgba(220, 68, 70, .40); }
  .btn-info:hover:not(:disabled), .modal-x:hover { background: rgba(22, 104, 220, .12); }
  .cmd-kbd kbd { background: rgba(255, 255, 255, .08); }
  .cmdk-box, .modal-card { box-shadow: 0 8px 24px rgba(0, 0, 0, .5); }
}
