/* ============================================================================
 * 仓储运营平台 · 统一 UI 规范（可执行版）
 *
 * **这一份是全站唯一的样式源**。门户在 /static/ui-kit.css 托管它，各模块用
 * **绝对路径**引用：<link rel="stylesheet" href="/static/ui-kit.css">
 * 模块本来就只能经门户访问，所以不存在"门户挂了拿不到样式"这种新风险；
 * 换来的是改一处全站生效、永不漂移。
 *
 * 配套文档：docs/UI-规范.md（讲"为什么"和"新功能怎么落地"）。
 * 改这个文件 = 改全站，改之前先看那份文档里的「不要做什么」。
 *
 * ---------------------------------------------------------------------------
 * 三条总原则
 *
 * 1. **深色是基准，浅色是覆盖，都没选时跟随系统。** 门户把用户选的主题
 *    写进 <html data-theme>；子模块由代理经 X-Portal-Theme 头拿到后同样写进去。
 * 2. **颜色只从下面的变量取，不写死。** 要新颜色就在这里加一个变量，
 *    别在页面里写 #xxx —— 那是主题切换失效的唯一原因。
 * 3. **按钮位置有固定语义**（见 .toolbar）：主操作最左、次要跟随、
 *    危险操作推到最右并与其他按钮拉开距离。误点代价越大，离手越远。
 * ========================================================================= */

/* ---------------------------------------------------------------------------
 * 1. 设计令牌
 * ------------------------------------------------------------------------ */

/* 深色 = 基准主题 */
:root {
  --bg: #0f172a; --card: #1e293b; --line: #263449;
  --text: #f1f5f9; --muted: #94a3b8; --dim: #64748b;
  --accent: #0284c7; --accent-hover: #0369a1; --focus: #38bdf8;
  --ok: #4ade80; --warn: #fcd34d; --err: #fca5a5;
  --ok-bg: rgba(74,222,128,.1);  --ok-bd: rgba(74,222,128,.35);
  --warn-bg: rgba(251,191,36,.1); --warn-bd: rgba(251,191,36,.32);
  --err-bg: rgba(239,68,68,.12);  --err-bd: rgba(239,68,68,.35);
  --info: #7dd3fc; --info-bg: rgba(56,189,248,.1); --info-bd: rgba(56,189,248,.3);
  --shadow: 0 20px 50px rgba(0,0,0,.4); --input-bd: #334155;
  --zebra: rgba(255,255,255,.035);   /* 表格隔行 */
  --paper: #f8fafc;                  /* 打印预览的"纸"，两个主题下都是浅的 */
  /* 数据密集页面的派生色。放在这里而不是让每个看板自己造一套 ——
     动销看板原本就有一份紫色系的 th-bg/row-hover，与全站对不上。 */
  --th-bg: #1b212b;                  /* 表头底 */
  --row-alt: rgba(255,255,255,.028); /* 隔行 */
  --row-hover: rgba(56,189,248,.09); /* 悬停行 */
  --line-soft: #1c222b;              /* 比 --line 更淡的分隔 */
  --ring: rgba(56,189,248,.3);       /* 聚焦光环 */
  --shadow-sm: 0 1px 2px rgba(0,0,0,.4);
  --surface2: #172032;               /* 次级面（卡片里再嵌一层的小块） */
  --accent-soft: rgba(2,132,199,.16);/* 主色的淡底，用于"选中/命中"的行或块 */
  --chip: #3b82f6;                   /* 序号/批次这类中性标记的底色 */
  /* 图表色阶。**看板专用，但定义在这里** —— 人效看板原本自带一套
     (--gap0/1/2 等)，2026-07-27 接入 ui-kit 时那段 :root 被整块删掉，
     而这里没有对应令牌，于是时间轴的间隔色块、异常段、图例全部
     解析失败不显色（生产 bug，2026-08-11 修）。
     scale 是「强度三级」：0=可忽略 1=需留意 2=最严重。 */
  --chart-scale-0: #334155;          /* 深色下用中性深灰，不抢眼 */
  --chart-scale-1: #6b5bb5;
  --chart-scale-2: #8b6fe0;          /* 配白字仍可读 */
  --chart-neutral: #334155;          /* 「其他/未分类」的斜纹 */
  --chart-anomaly: rgba(252,165,165,.22); /* 异常段底，配 --err 虚线边框 */
  /* 分类色：并列的几个 KPI/类别，彼此要区分但都不表示"好坏"
     （表示好坏的用 --ok/--warn/--err）。库存指标页的四张 KPI 卡在用。 */
  --chart-cat-1: #818cf8;            /* 靛 */
  --chart-cat-2: #22d3ee;            /* 青 */
  --chart-cat-3: #a78bfa;            /* 紫 */
}
:root[data-theme="light"] {
  --bg: #f1f5f9; --card: #ffffff; --line: #e2e8f0;
  --text: #0f172a; --muted: #475569; --dim: #94a3b8;
  --accent: #0284c7; --accent-hover: #0369a1; --focus: #0284c7;
  --ok: #15803d; --warn: #b45309; --err: #b91c1c;
  --ok-bg: rgba(21,128,61,.07);   --ok-bd: rgba(21,128,61,.3);
  --warn-bg: rgba(180,83,9,.07);  --warn-bd: rgba(180,83,9,.28);
  --err-bg: rgba(220,38,38,.06);  --err-bd: rgba(220,38,38,.3);
  --info: #075985; --info-bg: rgba(2,132,199,.07); --info-bd: rgba(2,132,199,.25);
  --shadow: 0 10px 30px rgba(15,23,42,.1); --input-bd: #cbd5e1;
  --zebra: rgba(15,23,42,.025);
  --paper: #e9eaee;
  --th-bg: #f7f9fc;
  --row-alt: rgba(15,23,42,.02);
  --row-hover: rgba(2,132,199,.07);
  --line-soft: #eef2f7;
  --ring: rgba(2,132,199,.25);
  --shadow-sm: 0 1px 2px rgba(15,23,42,.06);
  --surface2: #f8fafc;
  --accent-soft: rgba(2,132,199,.09);
  --chip: #3b82f6;
  --chart-scale-0: #e2e8f0;
  --chart-scale-1: #b8abe8;
  --chart-scale-2: #4a3aa7;
  --chart-neutral: #e2e8f0;
  --chart-anomaly: #f3d9d9;
  --chart-cat-1: #6366f1;
  --chart-cat-2: #06b6d4;
  --chart-cat-3: #8b5cf6;
}
@media (prefers-color-scheme: light) {
  :root:not([data-theme]) {
    --bg: #f1f5f9; --card: #ffffff; --line: #e2e8f0;
    --text: #0f172a; --muted: #475569; --dim: #94a3b8;
    --accent: #0284c7; --accent-hover: #0369a1; --focus: #0284c7;
    --ok: #15803d; --warn: #b45309; --err: #b91c1c;
    --ok-bg: rgba(21,128,61,.07);   --ok-bd: rgba(21,128,61,.3);
    --warn-bg: rgba(180,83,9,.07);  --warn-bd: rgba(180,83,9,.28);
    --err-bg: rgba(220,38,38,.06);  --err-bd: rgba(220,38,38,.3);
    --info: #075985; --info-bg: rgba(2,132,199,.07); --info-bd: rgba(2,132,199,.25);
    --shadow: 0 10px 30px rgba(15,23,42,.1); --input-bd: #cbd5e1;
    --zebra: rgba(15,23,42,.025);
    --paper: #e9eaee;
    --th-bg: #f7f9fc;
    --row-alt: rgba(15,23,42,.02);
    --row-hover: rgba(2,132,199,.07);
    --line-soft: #eef2f7;
    --ring: rgba(2,132,199,.25);
    --shadow-sm: 0 1px 2px rgba(15,23,42,.06);
    --surface2: #f8fafc;
    --accent-soft: rgba(2,132,199,.09);
    --chip: #3b82f6;
    --chart-scale-0: #e2e8f0;
    --chart-scale-1: #b8abe8;
    --chart-scale-2: #4a3aa7;
    --chart-neutral: #e2e8f0;
    --chart-anomaly: #f3d9d9;
    --chart-cat-1: #6366f1;
    --chart-cat-2: #06b6d4;
    --chart-cat-3: #8b5cf6;
  }
}

/* 历史别名 —— 人力看板的页面样式与 JS 里写了几十处 var(--surface)/var(--link)。
   逐处改名的收益是零、回归风险是实打实的，所以在这里把旧名指向新名。
   **新代码一律用上面的规范名**，这几行只为存量兜底。 */
:root {
  --surface: var(--card);
  --ink: var(--text);
  --ink2: var(--muted);
  --grid: var(--line);
  --border: var(--line);
  --link: var(--accent);
  --track: var(--bg);
  --bad: var(--err);
  --slow: var(--warn);
}

/* ---------------------------------------------------------------------------
 * 2. 基础排版
 * ------------------------------------------------------------------------ */

* { box-sizing: border-box; margin: 0; padding: 0; }

body {
  font-family: system-ui, -apple-system, "Segoe UI", "Microsoft YaHei",
               "PingFang SC", Roboto, sans-serif;
  font-size: 14px; line-height: 1.55;
  min-height: 100vh; background: var(--bg); color: var(--text);
}
a { color: var(--muted); text-decoration: none; }
a:hover { color: var(--text); }

/* ---------------------------------------------------------------------------
 * 3. 顶栏 —— 每个页面都要有，长得都一样
 *
 * 左边"我是谁"，右边"我是谁的谁 + 怎么回去"。子模块**必须**给出「返回门户」，
 * 否则用户点进去就出不来（人力看板此前正是如此）。
 * ------------------------------------------------------------------------ */

.topbar {
  display: flex; justify-content: space-between; align-items: center;
  gap: 12px; padding: 14px 24px;
  border-bottom: 1px solid var(--line); font-size: 13px;
}
/* 17px 而不是 15px：15px 在数据密集的看板上被满屏数字压住，读不出"我在哪个功能里"。
   顶栏是全站唯一的定位锚点，宁可略大。 */
.topbar .brand { font-size: 17px; font-weight: 600; color: var(--text); }
.topbar .brand-logo { width: 26px; height: 26px; display: block;
                      border-radius: 6px; flex: none; }
.topbar .brand small { color: var(--dim); font-weight: 400; margin-left: 8px;
                       font-size: 12.5px; }
.topbar .right { display: flex; gap: 14px; align-items: center; color: var(--dim); }
.topbar .chip,
.topbar .lang-switch,
.topbar .back {
  border: 1px solid var(--line); padding: 4px 10px; border-radius: 6px;
  color: var(--muted); white-space: nowrap;
}
.topbar .back:hover,
.topbar .lang-switch:hover { border-color: var(--focus); color: var(--text); }

/* ---------------------------------------------------------------------------
 * 4. 页面容器与分区
 * ------------------------------------------------------------------------ */

.page { max-width: 1080px; margin: 28px auto 72px; padding: 0 20px;
        display: flex; flex-direction: column; gap: 16px; }
/* 数据密集的看板要更宽 —— 表格挤在 1080px 里读不了 */
.page.wide { max-width: 1500px; }

.card { background: var(--card); border: 1px solid var(--line);
        border-radius: 12px; padding: 22px 24px; box-shadow: var(--shadow); }

/* 分区标题两种写法，按场景选：
   .section-title  卡片之间的小标题（管理页常用）
   .card > h2      卡片内部带序号的步骤标题（分步操作的页面用） */
.section-title { font-size: 13px; color: var(--dim); text-transform: uppercase;
                 letter-spacing: .06em; margin: 12px 0 0; }
.card > h2 { font-size: 14px; font-weight: 600; margin-bottom: 16px;
             display: flex; align-items: center; gap: 9px; }
.card > h2 .n { display: inline-flex; align-items: center; justify-content: center;
                width: 21px; height: 21px; border-radius: 50%;
                background: var(--accent); color: #fff; font-size: 12px;
                font-weight: 600; flex: 0 0 auto; }
.card > h2 .sub { font-weight: 400; color: var(--dim); font-size: 12px; }

/* ---- 认证页（登录 / 改密码）：屏幕正中一张卡，没有顶栏 ----
   这类页面用户还没进系统，不该出现"返回门户"和用户名。 */
.auth {
  min-height: 100vh; display: flex; align-items: center; justify-content: center;
  padding: 24px;
  /* 一点点纵深：主色的极淡光晕从上方压下来，避免整屏一块死板的纯色。
     用 radial-gradient 而不是图片 —— 不引外部资源，两个主题下都成立。 */
  background:
    radial-gradient(1100px 520px at 50% -10%, var(--accent-soft), transparent 70%),
    var(--bg);
}
.auth .card { width: 100%; max-width: 400px; padding: 34px 32px; border-radius: 14px; }

/* 语言/主题切换挪到卡片外的右上角 —— 它们跟登录本身无关，
   挤在标题旁边会让第一眼看到两组不相干的东西。 */
.auth .switches { position: fixed; top: 18px; right: 20px;
                  display: flex; gap: 8px; z-index: 5; }
.auth .switches a { border: 1px solid var(--line); padding: 4px 10px;
                    border-radius: 6px; color: var(--muted); font-size: 12.5px; }
.auth .switches a:hover { border-color: var(--focus); color: var(--text); }

.auth h1 { font-size: 21px; font-weight: 600; line-height: 1.3; letter-spacing: -.2px; }
.auth .lead { color: var(--dim); font-size: 12.5px; margin-top: 6px; margin-bottom: 26px; }

/* 字段之间留够呼吸；label 与 input 贴紧，字段与字段拉开 */
.auth .field { margin-bottom: 15px; }
.auth .field > label { margin-bottom: 6px; }
.auth .field input { padding: 10px 12px; font-size: 14px; }
.auth .btn.block { margin-top: 22px; padding: 11px 15px; font-weight: 500; }
.auth .msg { margin-top: 14px; }
.auth .foot { margin-top: 18px; text-align: center; font-size: 13px; }

/* ---------------------------------------------------------------------------
 * 5. 表单控件 —— 全站同一套，别再各写各的圆角和内边距
 * ------------------------------------------------------------------------ */

/* 默认竖排：标题在上、输入框在下。这是**录入表单**的排法。 */
label { display: flex; flex-direction: column; gap: 5px;
        color: var(--muted); font-size: 12px; }
label.inline { flex-direction: row; align-items: center; gap: 8px; }

/* 但**含复选/单选的 label 一律横排**：勾选框在前、文字在后。
   没有人会想把复选框摞在文字上面 —— 上面那条竖排是给"标题+输入框"用的，
   套到复选框上就是 2026-07-28 用户连提三处的那个丑（动销的渠道、
   拣选热力图的拣选/订单类型、用户管理的权限清单，全是同一个根因）。
   横排还顺带省地方：一行能放下四五个选项，竖排一个占一行。 */
label:has(> input[type="checkbox"]),
label:has(> input[type="radio"]) {
  flex-direction: row; align-items: center; gap: 6px;
  color: var(--text); cursor: pointer; white-space: nowrap;
}
/* 勾选框自身不参与"输入框整宽"那条规则，也不要被 flex 拉伸 */
input[type="checkbox"], input[type="radio"] {
  width: auto; min-width: 0; flex: 0 0 auto; margin: 0; padding: 0;
  accent-color: var(--accent);
}
/* 一排复选框（周一~周日、拣选类型…）：横向铺开、自动换行。
   别用"文字在上、勾选框在下"那种竖排小格子 —— 看着像日历表头，
   实际是复选，两种含义混在一起。 */
.checkrow { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.checkrow > label { font-size: 12px; }

/* ---- 开关 .switch ----
 *
 * 用在**二值状态**上（启用/停用、开/关）。与复选框的区别是语义：
 * 复选框是"我要选它"（提交表单时才生效），开关是"它现在是开还是关"
 * —— 状态本身就是内容，看一眼就知道，不必再配一列文字说明。
 *
 * 底层仍是真的 <input type=checkbox>：键盘可达、表单语义不变、
 * 读屏软件认得。视觉全靠 ::before/::after，没有额外标签。
 *
 * 用法：
 *   <label class="switch"><input type="checkbox" checked><span>启用</span></label>
 * 要「一拨就生效」（不用再点保存）时加 data-submit，由 ui-kit.js 提交所在表单：
 *   <form method="post" action="…">
 *     <input type="hidden" name="status" value="…">
 *     <label class="switch"><input type="checkbox" data-submit checked></label>
 *   </form>
 */
.switch { display: inline-flex; align-items: center; gap: 8px;
          cursor: pointer; font-size: 12px; color: var(--muted); }
.switch > input[type="checkbox"] {
  appearance: none; -webkit-appearance: none;
  position: relative; flex: 0 0 auto;
  width: 34px; height: 19px; border-radius: 19px;
  background: var(--input-bd); border: 1px solid var(--line);
  cursor: pointer; transition: background .16s;
}
.switch > input[type="checkbox"]::after {
  content: ""; position: absolute; top: 2px; left: 2px;
  width: 13px; height: 13px; border-radius: 50%;
  background: var(--card); transition: transform .16s;
}
.switch > input[type="checkbox"]:checked { background: var(--accent); border-color: var(--accent); }
.switch > input[type="checkbox"]:checked::after { transform: translateX(15px); background: #fff; }
.switch > input[type="checkbox"]:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.switch > input[type="checkbox"]:disabled { opacity: .45; cursor: not-allowed; }
.switch:has(> input:disabled) { cursor: not-allowed; }
/* 开着的时候文字跟着亮起来，一眼能扫出哪几行是启用的 */
.switch:has(> input:checked) { color: var(--text); }

/* ---- 锁定态 .switch.locked ----
 *
 * 用在**状态是真的、但拨不动**的地方：管理员账号不允许停用、
 * 已停用的令牌不能再启用。
 *
 * 关键是**仍然显示真实状态**（开着就是蓝的），只是加一把锁说明"别试了"。
 * 不要退化成一个灰扑扑的关着的开关 —— 那会让人误以为管理员账号是停用的。
 * 也不要换成纯文字标签：同一列里有的是开关有的是文字，扫一眼分不清哪些能点。
 */
.switch.locked { cursor: not-allowed; }
.switch.locked > input[type="checkbox"] { opacity: .7; cursor: not-allowed; }
.switch.locked::before {
  content: "🔒"; font-size: 11px; line-height: 1; opacity: .8;
  filter: grayscale(1);            /* 别在一片蓝里冒出个黄挂锁 */
}
/* 上方留白的独立复选项（表单末尾那种"启用"） */
label.mt { margin-top: 14px; }

input, select, textarea {
  width: 100%; padding: 8px 10px; border-radius: 8px;
  border: 1px solid var(--input-bd); background: var(--bg); color: var(--text);
  font-size: 13px; font-family: inherit; outline: none;
}
input:focus, select:focus, textarea:focus {
  border-color: var(--focus); box-shadow: 0 0 0 3px var(--ring);
}

/* 浏览器自动填充：Chrome 会强行把输入框刷成浅蓝底黑字，深色主题下极刺眼，
   而且它优先级高到普通 background 盖不住 —— 只能靠超长的内阴影顶掉。 */
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus {
  -webkit-text-fill-color: var(--text);
  -webkit-box-shadow: 0 0 0 1000px var(--bg) inset;
  caret-color: var(--text);
  transition: background-color 9999s ease-out 0s;   /* 拖住它的过渡动画 */
}
input[type="file"] { padding: 7px 10px; color: var(--muted); }
input[type="file"]::file-selector-button {
  border: 1px solid var(--input-bd); background: var(--card); color: var(--text);
  padding: 4px 12px; border-radius: 6px; margin-right: 10px;
  cursor: pointer; font: inherit;
}
textarea { font-family: ui-monospace, Consolas, "Courier New", monospace;
           font-size: 12.5px; line-height: 1.6; resize: vertical; }
select[multiple] { padding: 4px; min-height: 78px; }

/* 表单栅格：一行排满自动换行，窄屏自动堆叠 */
.grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
        gap: 12px; }
/* `.row` 是个太常见的类名，两次咬人都出在它身上：
   1) 2026-07-29：TT 动销的表格行叫 <tr class="row">，被 display:flex 劈成
      flex 容器，整张表塌掉 → 加 :not(tr) 排除表格行；
   2) 2026-08-03：人力看板自己的 .row{display:grid} 是时间轴那一行的栅格，
      结果被上面那个 :not(tr) 反盖 —— **修 1) 的时候把优先级从 (0,1,0) 抬到
      了 (0,1,1)**，共享样式从此压过模块样式，191 行时间轴全塌成 0 宽。

   所以用 :where()：它的优先级恒为 0，整条选择器仍是 (0,1,0)。表格行照样排除，
   但模块自己的 .row（后加载）又能正常盖回来 —— 共享样式该是**底座**，
   不该压过模块。改共享样式里的短类名时，先问一句"这会不会压过谁"。 */
.row:where(:not(tr)) { display: flex; align-items: flex-end; gap: 10px; flex-wrap: wrap; }
.row:where(:not(tr)) > label { flex: 1 1 220px; }
.inline-form { display: inline-flex; gap: 4px; align-items: center; }

/* ---- 筛选条 .filterbar ----
 *
 * **筛选器不是页面主角。** 它是"选完就不管"的东西，主角是它下面的数据
 * （KPI 数字、热力图、表格）。所以一律做小、做淡：控件透明底、边框比正文淡、
 * 字号降一档。用户 2026-07-28 连着四个页面提同一个意见——仓库/日期/搜索框
 * 太显眼——就是因为最初把它们按"录入表单"的规格画了。
 *
 * 用法：外层 `<div class="filterbar">`，里面 `<label class="inline">标签 控件</label>`，
 * 主按钮照常 `.btn.primary.sm`。要把右侧信息推开就插一个 `<span class="spacer">`。
 * ------------------------------------------------------------------------ */

.filterbar {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 8px 0 10px;
}
.filterbar > label,
.filterbar label.inline {
  flex-direction: row; align-items: center; gap: 5px;
  font-size: 11.5px; color: var(--dim); margin: 0;
}
.filterbar select,
.filterbar input {
  width: auto; min-width: 110px; max-width: 300px;
  padding: 3px 7px; font-size: 12px; border-radius: 6px;
  color: var(--muted); background: transparent; border-color: var(--line);
}
.filterbar input[type="checkbox"],
.filterbar input[type="radio"] { width: auto; min-width: 0; }
/* 一组相关控件：「渠道 ☑ToC ☑ToB」「拣选类型 ☑大波次 ☑普通」。
   组内横排贴紧，组与组之间靠 .filterbar 的 gap 拉开 —— 这样一眼能看出
   哪几个选项是一伙的。没有这条的话整组会竖着堆（div 默认是块级）。 */
.filterbar .grp { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.filterbar .grp > span:not([class]),
.filterbar .grp > label:not(:has(> input[type="checkbox"])):not(:has(> input[type="radio"])) {
  font-size: 11.5px; color: var(--dim); white-space: nowrap;
}
.filterbar input[type="date"] { min-width: 0; }
.filterbar select:hover, .filterbar input:hover { border-color: var(--muted); }
/* **原生下拉的弹层是浏览器画的，它取 select 的 background/color。**
   上面把 .filterbar select 设成了 transparent + --muted：深色主题下弹层就成了
   灰字灰底，选项几乎看不见（2026-08-18 用户在云端同步入口的数据集下拉上撞到，
   但凡用 .filterbar select 的页面都一样）。
   给 option 一个实心底色与正文色，别让它继承那个为"融进筛选条"而设的透明背景。
   注意这条要放在全局，不能只放 .filterbar 下面 —— 表格里的 select 同理。 */
select option {
  background: var(--card);
  color: var(--text);
}

.filterbar select:focus, .filterbar input:focus {
  box-shadow: none; border-color: var(--focus); color: var(--text);
}
.filterbar .btn { padding: 4px 11px; font-size: 12px; }
.filterbar .spacer { flex: 1 1 auto; }
/* 筛选条右侧那串"当前口径"说明（日期范围、SKU 数…）：给人看一眼确认用的，
   同样压到最低对比度 */
.filterbar .meta { font-size: 11.5px; color: var(--dim); }
/* 搜索框：同属筛选，别做成整宽的大输入框 */
.filterbar input[type="search"], .filterbar input.search { min-width: 200px; }
/* 只填个数字的小格子（周数、天数、半径…）—— 给它整整 110px 是浪费 */
.filterbar input.narrow { min-width: 0; width: 52px; }

/* ---------------------------------------------------------------------------
 * 6. 按钮 —— 样式与**位置**都是规范的一部分
 * ------------------------------------------------------------------------ */

.btn, button.btn {
  padding: 8px 15px; border: 1px solid var(--input-bd); border-radius: 8px;
  background: var(--card); color: var(--text); font: inherit; font-size: 13px;
  cursor: pointer; white-space: nowrap;
  transition: border-color .15s, background .15s;
}
.btn:hover:not(:disabled) { border-color: var(--focus); }
.btn:disabled { opacity: .45; cursor: not-allowed; }
.btn.primary { background: var(--accent); border-color: var(--accent); color: #fff; }
.btn.primary:hover:not(:disabled) { background: var(--accent-hover);
                                    border-color: var(--accent-hover); }
.btn.ghost { background: transparent; color: var(--muted); }
.btn.ghost:hover:not(:disabled) { background: var(--bg); color: var(--text); }
/* 危险操作：不是红底大按钮（太扎眼、反而容易误点），是红字描边 + 位置隔离 */
.btn.danger { color: var(--err); border-color: var(--err-bd); background: transparent; }
.btn.danger:hover:not(:disabled) { background: var(--err-bg); border-color: var(--err); }
.btn.sm { padding: 5px 10px; font-size: 12.5px; }
/* 整宽按钮：表单里"提交"这类唯一出口用它（登录、改密码） */
.btn.block { display: block; width: 100%; padding: 10px 15px; font-size: 14px; }

/* 兜底：表单里漏写 class 的 <button> 至少不掉回浏览器默认的灰方块。
   **不是让你少写 class** —— 这只是防止一次疏忽把页面变丑（2026-07-28 把
   base.html 的裸 button 规则搬进 ui-kit 时只保留了 .btn，登录按钮当场裸奔）。
   单测 test_模板里的按钮都带类 会盯着这件事。 */
form button:not([class]) {
  padding: 8px 15px; border: 1px solid var(--accent); border-radius: 8px;
  background: var(--accent); color: #fff; font: inherit; font-size: 13px;
  cursor: pointer;
}

/* 兼容旧类名（门户存量模板用的是 btn-sm / btn-ghost） */
.btn-sm { width: auto; margin: 0; padding: 5px 10px; font-size: 13px; }
.btn-ghost { background: transparent; border: 1px solid var(--line); color: var(--muted); }
.btn-ghost:hover { background: var(--bg); color: var(--text); }

/* **按钮位置规范**：主操作在最左（视线起点、最好点），次要操作紧随其后，
   计数/状态文字用 .spacer 顶到右侧，危险操作放最右且拉开 —— 误点代价越大，
   离手越远。同一个页面里主操作永远只有一个。 */
.toolbar { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.toolbar .spacer { flex: 1 1 auto; }
.toolbar .danger-zone { margin-left: 18px; padding-left: 18px;
                        border-left: 1px solid var(--line); }

/* ---------------------------------------------------------------------------
 * 7. 表格
 * ------------------------------------------------------------------------ */

table.data, table.users { width: 100%; border-collapse: collapse; font-size: 14px; }
table.data th, table.data td,
table.users th, table.users td {
  text-align: left; padding: 10px 8px; border-bottom: 1px solid var(--line);
}
table.data th, table.users th { color: var(--muted); font-weight: 500; font-size: 12px; }
table.data tbody tr:nth-child(even) { background: var(--zebra); }
/* 数字右对齐 —— 一列数字左对齐是最影响可读性的排版错误 */
table.data td.num, table.data th.num { text-align: right;
                                       font-variant-numeric: tabular-nums; }
table.data select, table.data input,
table.users select, table.users input {
  width: auto; display: inline-block; padding: 5px 8px; font-size: 13px;
}

/* ---------------------------------------------------------------------------
 * 8. 反馈：提示条、状态标签
 *
 * 语义固定：ok=成功 / info=中性说明 / warn=能继续但要注意 / err=做不了。
 * 别拿颜色当装饰用。
 * ------------------------------------------------------------------------ */

.msg { padding: 9px 12px; border-radius: 8px; font-size: 12.5px;
       border: 1px solid transparent; }
.msg:empty { display: none; }
.msg.ok   { background: var(--ok-bg);   border-color: var(--ok-bd);   color: var(--ok); }
.msg.info { background: var(--info-bg); border-color: var(--info-bd); color: var(--info); }
.msg.warn { background: var(--warn-bg); border-color: var(--warn-bd); color: var(--warn); }
.msg.err, .msg.error { background: var(--err-bg); border-color: var(--err-bd);
                       color: var(--err); }

.hint { font-size: 12px; color: var(--dim); }
.empty-hint { color: var(--dim); font-size: 13px; padding: 10px 2px; }

.tag { display: inline-block; padding: 1px 8px; border-radius: 20px;
       font-size: 11px; border: 1px solid var(--line); color: var(--muted); }
.tag.ok   { color: var(--ok);   border-color: var(--ok-bd); }
.tag.warn { color: var(--warn); border-color: var(--warn-bd); }
.tag.err  { color: var(--err);  border-color: var(--err-bd); }

/* ---------------------------------------------------------------------------
 * 9. 标签页（看板类页面的二级导航）
 * ------------------------------------------------------------------------ */

nav.tabs { display: flex; gap: 4px; flex-wrap: wrap;
           border-bottom: 1px solid var(--line); }
nav.tabs a, .tabs .tab {
  color: var(--muted); text-decoration: none; padding: 8px 16px;
  border-radius: 8px 8px 0 0; font-size: 13px; cursor: pointer;
  border: 1px solid transparent; border-bottom: none;
  background: transparent; font-family: inherit;
}
nav.tabs a:hover, .tabs .tab:hover { background: var(--card); color: var(--text); }
nav.tabs a.on, .tabs .tab.on {
  background: var(--card); color: var(--text);
  border-color: var(--line); margin-bottom: -1px;
}

/* ---------------------------------------------------------------------------
 * 10. 模态框
 * ------------------------------------------------------------------------ */

.modal-overlay { display: none; position: fixed; inset: 0; z-index: 50;
                 background: rgba(0,0,0,.55); padding: 60px 20px; overflow-y: auto;
                 justify-content: center; align-items: flex-start; }
.modal-overlay.open { display: flex; }
.modal-panel { background: var(--card); border: 1px solid var(--line);
               border-radius: 14px; box-shadow: var(--shadow);
               width: 100%; max-width: 760px; padding: 24px; }
.modal-head { display: flex; justify-content: space-between; align-items: center;
              margin-bottom: 18px; font-size: 17px; font-weight: 600; }
.modal-x { width: 32px; height: 32px; padding: 0; margin: 0; background: transparent;
           color: var(--muted); border: 1px solid var(--line); border-radius: 8px;
           font-size: 14px; cursor: pointer; }
.modal-x:hover { background: var(--bg); color: var(--text); }

/* ---------------------------------------------------------------------------
 * 11. 下拉式复选
 *
 * 用 <details>/<summary> 而不是 <select multiple> —— 后者要按住 Ctrl 点选，
 * 运营用不来。面板绝对定位，展开时浮在上层而不撑高表格行。
 * ------------------------------------------------------------------------ */

.ms { position: relative; display: inline-block; }
.ms > summary {
  list-style: none; cursor: pointer; user-select: none;
  border: 1px solid var(--input-bd); border-radius: 6px;
  padding: 4px 26px 4px 9px; font-size: 12px; background: var(--card);
  color: var(--text); white-space: nowrap; position: relative; min-width: 108px;
}
.ms > summary::-webkit-details-marker { display: none; }
.ms > summary::after { content: "▾"; position: absolute; right: 9px; top: 50%;
                       transform: translateY(-50%); color: var(--dim); font-size: 10px; }
.ms[open] > summary { border-color: var(--focus); }
.ms[open] > summary::after { content: "▴"; }
.ms-panel { position: absolute; z-index: 40; top: calc(100% + 4px); left: 0;
            min-width: 210px; max-height: 260px; overflow: auto;
            background: var(--card); border: 1px solid var(--line);
            border-radius: 8px; box-shadow: var(--shadow); padding: 8px; }
/* 靠近页面底部时向上翻（由 ui-kit.js 在打开的瞬间量一次决定加不加这个类）。
   不翻的话面板会伸出视口，里面的「保存」够不着。 */
.ms-panel.up { top: auto; bottom: calc(100% + 4px); }
.ms-panel .ms-group { color: var(--dim); font-size: 11px; margin: 6px 0 3px; }
.ms-panel .ms-group:first-child { margin-top: 0; }
.ms-panel label { display: flex; align-items: center; gap: 6px; font-size: 12.5px;
                  padding: 3px 2px; cursor: pointer; white-space: nowrap; margin: 0; }
.ms-panel label:hover { background: rgba(127,127,127,.08); border-radius: 4px; }
/* 「保存」钉在面板底部：选项一多（权限有 18 条）面板就滚动，按钮会被滚出视野，
   用户以为没有保存按钮。sticky 让它始终贴在可视区底部。
   负的左右外边距 + 同色底，是为了盖住下面滚过去的选项，不然文字会透出来。 */
.ms-actions { position: sticky; bottom: -8px; z-index: 1;
              display: flex; gap: 6px; margin: 8px -8px -8px; padding: 7px 8px 8px;
              border-top: 1px solid var(--line); background: var(--card); }
.ms-count { color: var(--dim); font-size: 11px; margin-left: 6px; }

/* ---------------------------------------------------------------------------
 * 12. 窄屏
 * ------------------------------------------------------------------------ */

@media (max-width: 640px) {
  .topbar { padding: 12px 14px; }
  .page { margin: 16px auto 48px; padding: 0 12px; }
  .card { padding: 18px 16px; }
  .toolbar .spacer { flex-basis: 100%; }
  .toolbar .danger-zone { margin-left: 0; padding-left: 0; border-left: 0; }
}

/* 主题切换按钮（ui-kit.js 提供行为，各页只放 <button data-theme-toggle> 即可） */
[data-theme-toggle]{cursor:pointer;background:transparent;border:1px solid var(--line);
  border-radius:8px;color:var(--text);padding:2px 10px;font-size:13px;line-height:1.6}
[data-theme-toggle]:hover{border-color:var(--accent)}
