/* ============================================================
   设计系统层 ds.css（v157）
   ------------------------------------------------------------
   定位：只做「新增 + 覆盖」，不改 app.css 一行。加载顺序在 app.css 之后。
   目标：
     1) 把散落的 33 种字号 / 66% 脱轨间距 / 18 种圆角收敛成可枚举的尺度
     2) 提供工具类，终止「每要一个间距就写内联 style」的循环
     3) 统一按钮 / 卡片 / 表格 / 表单 / 空态 / 徽章 的视觉契约
     4) 提供移动端表格→卡片降级（配合 ds.js 的 data-label 注入）
   原则：不重命名任何现有 token；不为统一而破坏已形成肌肉记忆的交互。
   ============================================================ */

:root {
  /* ---------- 1. 字号阶梯（原 33 种 → 9 级） ---------- */
  --fs-1: 10px;    /* 极小：角标、单位 */
  --fs-2: 11px;    /* 小：辅助说明 */
  --fs-3: 12px;    /* 正文小：表格、次要信息 */
  --fs-4: 13px;    /* 正文：默认 */
  --fs-5: 14px;    /* 强调正文 */
  --fs-6: 16px;    /* 小标题 */
  --fs-7: 18px;    /* 卡片标题 */
  --fs-8: 22px;    /* KPI 数值 */
  --fs-9: 28px;    /* 页面大标题 */

  /* ---------- 2. 间距阶梯（4px 网格，8 档） ---------- */
  --sp-1: 4px;
  --sp-2: 8px;
  --sp-3: 12px;
  --sp-4: 16px;
  --sp-5: 20px;
  --sp-6: 24px;
  --sp-7: 32px;
  --sp-8: 40px;

  /* ---------- 3. 圆角（原 18 种 → 4 档） ---------- */
  --r-xs: 6px;
  --r-sm: 8px;
  --r-md: 12px;
  --r-full: 999px;

  /* ---------- 4. 语义色别名（指向现有 token，避免同义异值） ---------- */
  --ds-danger: var(--danger, #C0392C);
  --ds-ok: var(--ok, #0E7A50);
  --ds-warn: #A34F05;
  --ds-brand: var(--brand, #EF7F17);
  --ds-surface: #fff;
  --ds-surface-2: var(--bg-2, #FAFBFC);
  --ds-border: var(--line, #E7E2DA);
  --ds-border-warm: #F3D7B7;
  --ds-ink: var(--ink, #1D2228);
  --ds-ink-2: var(--ink-2, #44403C);
  --ds-muted: var(--muted, #7A736A);

  /* ---------- 5. 层叠（原 13 个 token 全废 → 5 档真正启用） ---------- */
  --z-nav: 50;
  --z-sticky: 100;
  --z-pop: 300;
  --z-modal: 500;
  --z-toast: 900;
}

/* ============================================================
   工具类（终止内联 style 的唯一手段）
   ------------------------------------------------------------
   命名：u- 前缀，避免与现有 .mt-* / .flex 等潜在类名冲突。
   只做「单属性、可组合」的原子类。
   ============================================================ */

/* 外边距：8 档 × 5 方向 */
.u-mt-1 { margin-top: var(--sp-1) !important; }
.u-mt-2 { margin-top: var(--sp-2) !important; }
.u-mt-3 { margin-top: var(--sp-3) !important; }
.u-mt-4 { margin-top: var(--sp-4) !important; }
.u-mt-5 { margin-top: var(--sp-5) !important; }
.u-mt-6 { margin-top: var(--sp-6) !important; }
.u-mt-7 { margin-top: var(--sp-7) !important; }
.u-mt-8 { margin-top: var(--sp-8) !important; }

.u-mb-1 { margin-bottom: var(--sp-1) !important; }
.u-mb-2 { margin-bottom: var(--sp-2) !important; }
.u-mb-3 { margin-bottom: var(--sp-3) !important; }
.u-mb-4 { margin-bottom: var(--sp-4) !important; }
.u-mb-5 { margin-bottom: var(--sp-5) !important; }
.u-mb-6 { margin-bottom: var(--sp-6) !important; }
.u-mb-7 { margin-bottom: var(--sp-7) !important; }
.u-mb-8 { margin-bottom: var(--sp-8) !important; }

.u-ml-1 { margin-left: var(--sp-1) !important; }
.u-ml-2 { margin-left: var(--sp-2) !important; }
.u-ml-3 { margin-left: var(--sp-3) !important; }
.u-ml-4 { margin-left: var(--sp-4) !important; }

.u-mr-1 { margin-right: var(--sp-1) !important; }
.u-mr-2 { margin-right: var(--sp-2) !important; }
.u-mr-3 { margin-right: var(--sp-3) !important; }
.u-mr-4 { margin-right: var(--sp-4) !important; }

.u-mx-auto { margin-left: auto !important; margin-right: auto !important; }

/* 内边距 */
.u-p-1 { padding: var(--sp-1) !important; }
.u-p-2 { padding: var(--sp-2) !important; }
.u-p-3 { padding: var(--sp-3) !important; }
.u-p-4 { padding: var(--sp-4) !important; }
.u-py-2 { padding-top: var(--sp-2) !important; padding-bottom: var(--sp-2) !important; }
.u-py-3 { padding-top: var(--sp-3) !important; padding-bottom: var(--sp-3) !important; }
.u-px-3 { padding-left: var(--sp-3) !important; padding-right: var(--sp-3) !important; }
.u-px-4 { padding-left: var(--sp-4) !important; padding-right: var(--sp-4) !important; }

/* 排版 */
.u-ta-l { text-align: left !important; }
.u-ta-c { text-align: center !important; }
.u-ta-r { text-align: right !important; }
.u-nowrap { white-space: nowrap !important; }
.u-truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.u-fs-1 { font-size: var(--fs-1) !important; }
.u-fs-2 { font-size: var(--fs-2) !important; }
.u-fs-3 { font-size: var(--fs-3) !important; }
.u-fs-4 { font-size: var(--fs-4) !important; }
.u-bold { font-weight: 650 !important; }
.u-muted { color: var(--ds-muted) !important; }
.u-danger { color: var(--ds-danger) !important; }
.u-ok { color: var(--ds-ok) !important; }
.u-num { font-variant-numeric: tabular-nums; }

/* 布局 */
.u-flex { display: flex !important; }
.u-flex-col { display: flex !important; flex-direction: column; }
.u-items-c { align-items: center !important; }
.u-justify-b { justify-content: space-between !important; }
.u-gap-1 { gap: var(--sp-1) !important; }
.u-gap-2 { gap: var(--sp-2) !important; }
.u-gap-3 { gap: var(--sp-3) !important; }
.u-gap-4 { gap: var(--sp-4) !important; }
.u-sp { flex: 1 1 auto; }
.u-w-full { width: 100% !important; }
.u-hide { display: none !important; }

/* ============================================================
   组件契约（只做收敛，不重画）
   ============================================================ */

/* 按钮：合并 .btn-sm 与 .btn-mini（两者字号本就相同，仅圆角/内边距差 1px） */
.btn-sm,
.btn-mini {
  font-size: var(--fs-3) !important;
  border-radius: var(--r-xs) !important;
  padding: 5px 11px !important;
  line-height: 1.4 !important;
}
/* 危险按钮补上缺失的样式（原先 class="btn btn-primary danger" 无任何定义） */
.btn.danger,
.btn.btn-danger {
  background: var(--ds-danger) !important;
  border-color: var(--ds-danger) !important;
  color: #fff !important;
}
.btn.danger:hover,
.btn.btn-danger:hover { filter: brightness(.94); }

/* 卡片：统一内边距（.kpi 原本 17px/19px，与 .card-bd 的 18px 差 1px 导致并排错位） */
.card-bd,
.kpi { padding: var(--sp-4) !important; }
.card,
.tw-card { border-radius: var(--r-md); }

/* 表格：表头底色统一为 --ds-surface-2（原 5 种近似值） */
.tbl thead th,
.tw-tbl thead th {
  background: var(--ds-surface-2) !important;
  font-size: var(--fs-2) !important;
  font-weight: 700 !important;
  color: var(--ds-muted) !important;
  white-space: nowrap;
}
/* 表格密度只保留 2 档（紧凑 / 常规），其余一次性表格类不再改行高 */
.tbl-sm td { padding-top: 7px !important; padding-bottom: 7px !important; }
.tbl td { padding-top: var(--sp-3) !important; padding-bottom: var(--sp-3) !important; }

/* 徽章：合并 .badge / .chip / .tag / .pill 四种语义 */
.badge,
.chip,
.tag,
.pill { border-radius: var(--r-full); font-size: var(--fs-1); font-weight: 700; }

/* 表单控件统一高度 */
.input,
.select,
textarea.input { min-height: 36px; font-size: var(--fs-4); }
.field .label { font-size: var(--fs-3); font-weight: 600; color: var(--ds-ink-2); }

/* 空态：统一形态（一句说明 + 一个主行动） */
.ds-empty {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--sp-3); padding: var(--sp-8) var(--sp-4); text-align: center;
}
.ds-empty .t { font-size: var(--fs-4); font-weight: 650; color: var(--ds-ink-2); }
.ds-empty .d { font-size: var(--fs-3); color: var(--ds-muted); max-width: 420px; line-height: 1.6; }

/* ============================================================
   移动端：表格 → 卡片降级（配 ds.js 注入的 data-label）
   ------------------------------------------------------------
   触发条件 ≤760px。带 .ds-cardable 的表格转为卡片流：
   每行成为一张卡，单元格以「标签：值」堆叠。
   ============================================================ */
@media (max-width: 760px) {
  table.ds-cardable { display: block; width: 100%; }
  table.ds-cardable thead { display: none; }
  table.ds-cardable tbody { display: block; }
  table.ds-cardable tr {
    display: block;
    background: var(--ds-surface);
    border: 1px solid var(--ds-border);
    border-radius: var(--r-sm);
    padding: var(--sp-3);
    margin-bottom: var(--sp-3);
  }
  table.ds-cardable td {
    display: flex;
    gap: var(--sp-2);
    align-items: flex-start;
    padding: 3px 0 !important;
    border: 0 !important;
    font-size: var(--fs-3);
  }
  table.ds-cardable td::before {
    content: attr(data-label);
    flex: 0 0 84px;
    color: var(--ds-muted);
    font-size: var(--fs-2);
    line-height: 1.7;
  }
  table.ds-cardable td[data-label=""]::before { display: none; }
  /* 移动端按钮加大触摸区 */
  .btn,
  .btn-sm,
  .btn-mini { min-height: 36px; }
}

/* 移动端：页面级留白收紧，避免横向溢出 */
@media (max-width: 760px) {
  .card-bd,
  .kpi { padding: var(--sp-3) !important; }
  .tw-toolbar { flex-wrap: wrap; row-gap: var(--sp-2); }
}

/* 轻主按钮：行内动作用它，避免一屏十几个橙色主按钮抢焦点。
   仍保留品牌色识别，但视觉权重低于工具栏真主按钮。 */
.btn-ghost.ds-act {
  color: var(--ds-brand) !important;
  border-color: var(--brand-200) !important;
  font-weight: 650 !important;
  background: #FFFBF6 !important;
}
.btn-ghost.ds-act:hover {
  background: var(--brand-50) !important;
  border-color: var(--ds-brand) !important;
}

/* ============================================================
   系统配置页：板块分组 + 通用参数表（v158）
   ============================================================ */
.set-tabs-grp { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 6px; }
.set-grp { display: inline-flex; align-items: center; gap: 4px; flex-wrap: wrap; }
.set-grp + .set-grp { padding-left: 10px; border-left: 1px solid var(--ds-border); }
.set-grp-t {
  font: 700 10px/1 var(--mono, monospace); color: #A9A196;
  letter-spacing: .6px; margin-right: 2px; white-space: nowrap;
}

/* 通用参数：分组标题 */
.pm-grp { margin: 4px 0 10px; }
.pm-grp-t {
  font: 700 10.5px/1 var(--mono, monospace); color: var(--ds-muted);
  letter-spacing: .6px; padding-bottom: 6px; border-bottom: 1px solid var(--ds-border);
  margin-bottom: 4px;
}
/* 通用参数：一行一个参数 —— 左标签右控件 */
.pm-row {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
  gap: var(--sp-3); align-items: start;
  padding: 10px 0; border-bottom: 1px dashed var(--line-2);
}
.pm-row:last-child { border-bottom: 0; }
.pm-name { font-size: var(--fs-4); font-weight: 650; color: var(--ds-ink); }
.pm-key { font: var(--fs-1)/1.5 var(--mono, monospace); color: var(--muted, #7A736A); margin-top: 3px; }
.pm-switch { display: inline-flex; gap: var(--sp-2); align-items: center; font-size: var(--fs-4); cursor: pointer; }
.pm-switch input { width: 16px; height: 16px; }

@media (max-width: 760px) {
  .pm-row { grid-template-columns: minmax(0, 1fr); gap: var(--sp-2); }
}

/* 工作台待办行可点（v159）：原先点了没反应 */
.wb-li-click { cursor: pointer; border-radius: var(--r-xs); transition: background .12s; }
.wb-li-click:hover { background: var(--brand-50); box-shadow: inset 3px 0 0 var(--ds-brand); }

/* 采购 KPI 触顶告警（v161）：数据可能不完整时显式提示，不静默 */
.pr-warn { border-left: 3px solid var(--ds-danger); }
.ds-empty-icon { font-size: 24px; line-height: 1; }

/* ============================================================
   v159 · 表单字段隐藏 / 只读（由 hr_form_fields.hidden / readonly 驱动）
   ------------------------------------------------------------
   fields.js 在装饰阶段给字段所在 .field 打上这两个类，
   业务表单无需任何改动即可生效。
   ============================================================ */
.fc-hidden { display: none !important; }
.fc-ro-box input,
.fc-ro-box select,
.fc-ro-box textarea {
  background: var(--line-2) !important;
  color: var(--ds-ink-2) !important;
  cursor: default !important;
}
.fc-ro-box .label { color: var(--ds-muted); }

/* ============================================================
   v159 · 工资条（完整明细 + 打印）
   ------------------------------------------------------------
   .pay-slip 是弹窗内容根节点；打印时由 #print-root 单独承载，
   隐藏页面上其余所有节点，不引入任何 PDF 库。
   ============================================================ */
.pay-slip { font-size: var(--fs-4); color: var(--ds-ink); }
.pay-slip.ps-body { max-height: 62vh; overflow-y: auto; padding-right: var(--sp-2); }

.ps-hd { display: flex; align-items: baseline; gap: var(--sp-3); flex-wrap: wrap;
  padding-bottom: var(--sp-3); border-bottom: 2px solid var(--ds-ink); margin-bottom: var(--sp-4); }
.ps-hd-t { font-size: var(--fs-7); font-weight: 750; letter-spacing: -.01em; }
.ps-hd-sub { font-size: var(--fs-3); color: var(--ds-muted); }
.ps-hd-badge { margin-left: auto; }

.ps-sec { margin-bottom: var(--sp-4); break-inside: avoid; page-break-inside: avoid; }
.ps-sec-t { font-size: var(--fs-2); font-weight: 750; letter-spacing: .1em; text-transform: uppercase;
  color: var(--ds-muted); padding-bottom: var(--sp-1); border-bottom: 1px solid var(--ds-border);
  margin-bottom: var(--sp-2); display: flex; gap: var(--sp-2); align-items: baseline; }
.ps-sec-n { font-weight: 500; letter-spacing: 0; text-transform: none; opacity: .75; }

.ps-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 var(--sp-5); }
.ps-kv { display: flex; align-items: baseline; gap: var(--sp-2); padding: 3px 0;
  border-bottom: 1px dotted var(--ds-border); min-width: 0; }
.ps-k { color: var(--ds-muted); font-size: var(--fs-3); flex: 0 0 auto; }
.ps-v { margin-left: auto; text-align: right; font-weight: 600; font-size: var(--fs-3);
  overflow-wrap: anywhere; }

.ps-line { display: flex; align-items: baseline; gap: var(--sp-2); padding: 3.5px 0;
  border-bottom: 1px dotted var(--ds-border); }
.ps-line .ps-k { display: flex; align-items: baseline; gap: var(--sp-2); min-width: 0; }
.ps-line .ps-v { font-size: var(--fs-4); font-variant-numeric: tabular-nums; }
.ps-sub { font-style: normal; font-size: var(--fs-2); color: var(--ds-muted); font-weight: 400; }
.ps-mut { color: var(--ds-muted); font-size: var(--fs-2); }

.ps-total { border-bottom: 0; border-top: 1px solid var(--ds-ink); margin-top: var(--sp-1);
  padding-top: var(--sp-2); }
.ps-total .ps-k { color: var(--ds-ink); font-weight: 750; font-size: var(--fs-4); }
.ps-total .ps-v { font-weight: 750; font-size: var(--fs-5); }
.ps-neg .ps-v { color: var(--ds-danger); }

.ps-tax { border: 1px solid var(--ds-border); border-radius: var(--r-sm);
  padding: var(--sp-2) var(--sp-3); background: var(--ds-surface-2); }
.ps-tax > summary { cursor: pointer; font-size: var(--fs-3); color: var(--ds-muted); font-weight: 650; }
.ps-tax > summary::marker { color: var(--ds-muted); }

.ps-net { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-3);
  margin-top: var(--sp-4); padding: var(--sp-4); border-radius: var(--r-md);
  background: var(--brand-50); border: 1px solid var(--brand-200); }
.ps-net-item { display: flex; flex-direction: column; gap: 2px; }
.ps-net-k { font-size: var(--fs-2); color: var(--ds-muted); }
.ps-net-v { font-size: var(--fs-8); font-weight: 780; letter-spacing: -.02em;
  font-variant-numeric: tabular-nums; line-height: 1.15; }
.ps-net-v.ps-strong { color: var(--ds-ink); }
.ps-words { grid-column: 1 / -1; font-size: var(--fs-2); color: var(--ds-muted); }

.ps-emp { margin-top: var(--sp-4); border-top: 1px dashed var(--ds-border); padding-top: var(--sp-2); }
.ps-emp > summary { cursor: pointer; font-size: var(--fs-3); color: var(--ds-muted); font-weight: 650; }
.ps-emp-note { font-size: var(--fs-2); color: var(--ds-muted); margin: var(--sp-1) 0 var(--sp-2); }

/* 打印专用容器：屏幕上永远不可见 */
.print-root { display: none; }

@media (max-width: 760px) {
  .ps-grid, .ps-net { grid-template-columns: minmax(0, 1fr); }
}

@media print {
  @page { size: A4 portrait; margin: 12mm 10mm; }
  body > *:not(.print-root) { display: none !important; }
  .print-root { display: block !important; }
  .print-root .pay-slip,
  .print-root .pay-slip.ps-body {
    max-height: none !important; overflow: visible !important;
    padding: 0 !important; font-size: 11px !important; color: var(--ds-ink) !important;
  }
  .print-root .ps-net { background: none !important; border: 1px solid var(--ds-ink) !important; }
  .print-root .ps-tax { background: none !important; }
  .print-root .ps-sec { margin-bottom: 10px; break-inside: avoid; page-break-inside: avoid; }
  .print-root .ps-net-v { font-size: 20px !important; }
  .print-root .ps-k,
  .print-root .ps-v,
  .print-root .ps-sub,
  .print-root .ps-mut,
  .print-root .ps-words,
  .print-root .ps-sec-t { font-size: 10px !important; color: var(--ds-ink-2) !important; }
  .print-root .ps-line .ps-v,
  .print-root .ps-total .ps-v { font-size: 11px !important; color: var(--ds-ink) !important; }
  .no-print { display: none !important; }
}

/* ============================================================
   v159 · 请假附件（上传控件 + 详情链接）
   ============================================================ */
.sv-att-bar { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; }
.sv-att-file { display: none; }
.sv-att-list { display: flex; flex-direction: column; gap: var(--sp-1); margin-top: var(--sp-2); }
.sv-att-list:empty { margin-top: 0; }
.sv-att-row {
  display: flex; align-items: center; gap: var(--sp-2);
  padding: 5px var(--sp-2); border: 1px solid var(--ds-border); border-radius: var(--r-xs);
  background: var(--ds-surface-2); font-size: var(--fs-3);
}
.sv-att-ico { width: 14px; height: 14px; flex: 0 0 auto; color: var(--ds-muted); }
.sv-att-name {
  flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  color: var(--ds-ink);
}
.sv-att-link { color: var(--ds-brand); text-decoration: underline; cursor: pointer; }
.sv-att-link:hover { text-decoration: none; }
.sv-att-size { color: var(--ds-muted); font-size: var(--fs-2); font-variant-numeric: tabular-nums; flex: 0 0 auto; }
.sv-att-x {
  border: 0; background: none; cursor: pointer; padding: 0 2px; line-height: 1;
  color: var(--ds-muted); font-size: var(--fs-5); flex: 0 0 auto;
}
.sv-att-x:hover { color: var(--ds-danger); }
.sv-att-hint { font-size: var(--fs-2); color: var(--ds-muted); margin-top: var(--sp-1); line-height: 1.5; }
.sv-att-sec { margin-top: var(--sp-3); }
.sv-att-cap { font-size: var(--fs-2); font-weight: 650; color: var(--ds-muted); margin-bottom: var(--sp-1); }

/* ============================================================
   考勤矩阵配色归一（v162）
   ------------------------------------------------------------
   问题：.mx-* 那 500 行 CSS 自成一套"暖米色"（#faf7f1/#f6f1e8/#f4f2ec/
        #eceae4/#d8d2c8/#b9b2a8/#c9c2b8/#a59e93），与全站冷灰系
        （#F4F6F9/#E5E9EE/#1D2228）零交集 —— 点开考勤矩阵像进了另一个产品。
   做法：只把"中性灰"从暖转到冷，**不动橙色状态色**（橙色是语义，不是装饰），
        也不动布局。全部靠覆盖，不修改 app.css 原规则。
   语义保持：浅灰=未填/空位，中灰=统一（uni），深灰=否认（den）。
   ============================================================ */
:root {
  --mx-head:      #F7F9FB;   /* 表头（原 #faf7f1） */
  --mx-head-2:    #F1F4F8;   /* 分组表头（原 #f6f1e8） */
  --mx-na-bg:     #F4F6F9;   /* 未填（原 #f4f2ec） */
  --mx-na-fg:     #B4BCC6;   /* 原 #c9c2b8 */
  --mx-den-bg:    #E5E9EE;   /* 否认（原 #eceae4） */
  --mx-den-fg:    #8C96A1;   /* 原 #a59e93 */
  --mx-uni-bg:    #F7F9FB;   /* 统一（原 #f7f5f0） */
  --mx-uni-fg:    #AEB6C0;   /* 原 #b8b1a6 */
  --mx-slot-bd:   #D3D9E0;   /* 空位虚线（原 #d8d2c8） */
}

table.mx-table thead th { background: var(--mx-head) !important; }
table.mx-table tr.mx-ghd th { background: var(--mx-head-2) !important; }
table.mx-table thead th.mx-sticky { background: var(--mx-head) !important; }
table.mx-table tr.mx-ghd th.mx-sticky { background: var(--mx-head-2) !important; }

td.mx-td .mx-box { border-color: var(--mx-slot-bd) !important; color: var(--mx-uni-fg) !important; }
td.mx-c-add .mx-box { border-color: var(--mx-slot-bd) !important; color: var(--mx-uni-fg) !important; }
td.mx-c-uni .mx-box { background: var(--mx-uni-bg) !important; color: var(--mx-uni-fg) !important; border-color: var(--mx-den-bg) !important; }
td.mx-c-na  .mx-box { background: var(--mx-na-bg)  !important; color: var(--mx-na-fg)  !important; }
td.mx-c-den .mx-box { background: var(--mx-den-bg) !important; color: var(--mx-den-fg) !important; }

.mx-lg .s-na  { background: var(--mx-na-bg)  !important; color: var(--mx-na-fg)  !important; }
.mx-lg .s-den { background: var(--mx-den-bg) !important; color: var(--mx-den-fg) !important; }
.mx-lg .s-add { color: var(--mx-uni-fg) !important; border-color: var(--mx-slot-bd) !important; }

/* 行悬停：原 #f7f3ec（暖）→ 统一为全站的浅橙品牌色，与其它表格一致 */
.mx-acc:hover { background: var(--brand-50, #FEF3E7) !important; }

/* v159：审批路径的小 spinner / 链进度小标题（从内联 style 收编） */
.sv-spin-xs { width: 14px; height: 14px; display: inline-block; vertical-align: -2px; }
.sv-chain-cap { margin: 8px 0 2px; font-size: var(--fs-3); color: var(--faint, var(--ds-muted)); }

/* ============================================================
   v163 · .hide-s 补真样式
   ------------------------------------------------------------
   9 处用例想表达"移动端隐藏次要列"，但这个类此前**从未定义**，
   等于从未生效（评估报告把它列在"死类"里）。这里补上。
   ============================================================ */
@media (max-width: 760px) {
  .hide-s { display: none !important; }
}

/* ============================================================
   v163.2 · 进度条行（.bar-row）类名与布局归一
   ------------------------------------------------------------
   问题：app.css 里 `.bar-row` 被定义了 3 次，互相覆盖 ——
     · 528 行：flex + .bl/.bt/.bf/.bv（宽 108 / 46）
     · 1247 行：grid 116px 1fr 74px
     · 2360 行：flex + .nm/.tr/.vv（宽 170 / 96）  ← 最终生效的一条
   而各视图用的类名不一致（.bl / .nm / .bar-name 三种写法），
   导致部分页面的标签宽度不受控、进度条把右侧金额挤出可视区。

   做法：统一成一套 grid，并让三种类名都指向同一套样式。
   ============================================================ */
.bar-row {
  display: grid !important;
  grid-template-columns: 150px minmax(60px, 1fr) 96px;
  gap: var(--sp-3) !important;
  align-items: center !important;
  margin: 6px 0 !important;
}
.bar-row > .bl,
.bar-row > .nm,
.bar-row > .bar-name {
  width: auto !important;
  flex: none !important;
  min-width: 0;
  font-size: var(--fs-3) !important;
  color: var(--ds-ink-2);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.bar-row > .bt,
.bar-row > .tr {
  width: auto !important;
  flex: none !important;
  height: 9px !important;
  background: var(--line-2) !important;
  border-radius: 6px !important;
  overflow: hidden;
}
.bar-row > .bt > .bf,
.bar-row > .tr > i {
  display: block !important;
  height: 100% !important;
  border-radius: 6px !important;
  background: var(--brand) !important;
}
.bar-row > .bv,
.bar-row > .vv {
  width: auto !important;
  flex: none !important;
  text-align: right !important;
  font-size: var(--fs-3) !important;
  font-weight: 650 !important;
  color: var(--ds-ink) !important;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* ============================================================
   v164 · 左侧导航分组小标题（.nav-sep）
   ------------------------------------------------------------
   设置页 13 个页签下沉为二级项后，按「权限与账号 / 业务规则 / 个人偏好 / 数据与运维」
   四组加小标题，避免 13 项平铺看不出层次。不可点击。
   左内边距对齐 .nav-item 的 14px。
   ============================================================ */
.nav-sep {
  padding: 12px 14px 4px;
  font-size: var(--fs-2) !important;
  font-weight: 600;
  color: var(--ds-muted);
  letter-spacing: .04em;
  cursor: default;
  user-select: none;
}
.nav-sep:first-child { padding-top: 4px; }

/* ============================================================
   v165 · 设置页「角色与权限」合并页的内部分段
   ------------------------------------------------------------
   原来「角色」「权限总览」是两个页签，用户要在两者间来回跳；
   合并为一页后，用这两个分段按钮切换（样式与页签区分开，避免与横向页签混淆）。
   ============================================================ */
.rp-seg {
  display: inline-flex;
  gap: 4px;
  padding: 4px;
  margin-bottom: 14px;
  background: var(--ds-surface-2);
  border-radius: 10px;
}
.rp-b {
  border: 0;
  background: none;
  cursor: pointer;
  padding: 7px 16px;
  border-radius: 8px;
  font-family: inherit;
  font-size: var(--fs-3);
  font-weight: 650;
  color: var(--ds-muted);
  transition: background var(--t-fast) var(--ease-io), color var(--t-fast) var(--ease-io);
}
.rp-b:hover { color: var(--ink); }
.rp-b.on { background: var(--card); color: var(--ink); box-shadow: 0 1px 2px rgba(0, 0, 0, .08); }


/* ============================================================
   v167 · 团队工作管理（teamwork）样式并入设计系统
   ------------------------------------------------------------
   【上一轮的误判，这里更正】
   v166 曾判断"tw-* 这套 CSS 丢失了"——错的。它一直在，只是以
   `<style>' + css() + '</style>` 的形式**在 JS 里运行时注入**（view-teamwork.js:197-477，
   267 条规则、24KB），所以 grep app.css 自然找不到。

   【真正的问题有两个】
   1) 这套规则自成体系、覆盖在 ds.css 之上，导致该模块永远与其它模块观感不同；
   2) 里面把设计系统已有的色值**硬编码**了一遍（var(--warn) 就是 --warn、var(--brand) 就是 --brand、
      var(--ok) 就是 --ok），字号也混了 12.2/12.5/12.8/13.5 等脱轨值；
      加上 `.tw-kpi` 用 `--bg-2` 灰底（其它模块的 KPI 卡是白卡），整页就显得"灰且不一样"。

   【本次做法】
   · 267 条规则原样搬入本文件（不再运行时注入），视觉不变；
   · 硬编码色 → 语义 token，脱轨字号 → --fs-*，`--mono` → `--font-mono`；
   · 仅一处观感调整：`.tw-kpi` 灰底 → 白卡（与其它模块 KPI 一致，这是"全灰"的主因）。
   · 新增 `--danger-50` 供浅红底使用。
   ============================================================ */

:root { --danger-50: var(--danger-50); }

.tw-shell{display:flex;flex-direction:column;gap:12px}
.tw-head{display:flex;justify-content:space-between;align-items:flex-end;gap:12px;flex-wrap:wrap}
.tw-head h2{margin:2px 0 0;font-size:var(--fs-8);letter-spacing:-.3px}
.tw-kicker{font-size:var(--fs-1);letter-spacing:2px;color:var(--brand);font-weight:700}
.tw-head-tools{display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.tw-tabs{display:flex;gap:4px;flex-wrap:wrap;border-bottom:1px solid var(--line);padding-bottom:6px}
.tw-tab{border:0;background:transparent;padding:7px 11px;border-radius:8px;cursor:pointer;color:var(--muted);font-size:var(--fs-3)}
.tw-tab.active{background:var(--brand);color:var(--card);font-weight:700}
.tw-kpis{display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:8px}
.tw-kpi{background:var(--card);border:1px solid var(--line);border-radius:10px;padding:10px 12px;position:relative}
.tw-kpi b{display:block;font-size:var(--fs-8);line-height:1.15;font-variant-numeric:tabular-nums}
.tw-kpi span{font-size:var(--fs-1);color:var(--muted);display:block;margin-top:2px}
.tw-kpi.alert b{color:var(--danger)}
.tw-grid2{display:grid;grid-template-columns:minmax(0,1.55fr) minmax(0,1fr);gap:10px}
.tw-card{border:1px solid var(--line);border-radius:12px;padding:16px;background:var(--card)}
.tw-card h4{margin:0 0 8px;font-size:var(--fs-5);display:flex;align-items:center;gap:8px}
.tw-muted{font-size:var(--fs-2);color:var(--muted)}
.tw-empty{padding:22px;text-align:center;color:var(--muted);font-size:var(--fs-3)}
.tw-toolbar{display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin-bottom:8px}
.tw-toolbar .sp{flex:1}
.tw-chip{border:1px solid var(--line);background:var(--bg);border-radius:999px;padding:5px 11px;font-size:var(--fs-3);cursor:pointer;color:var(--muted)}
.tw-chip.risk{border-color:var(--brand-200);background:var(--card);color:var(--warn)}
.tw-chip.active.risk{border-color:var(--brand);background:var(--brand);color:var(--card)}
.tw-mini{border:1px solid var(--line);background:var(--bg);border-radius:6px;padding:4px 8px;font:600 var(--fs-2)/1.2 inherit;color:var(--muted);cursor:pointer;white-space:nowrap}
.tw-mini:hover{border-color:var(--brand);color:var(--brand-ink,var(--brand-700))}
.tw-mini.on{background:var(--brand);border-color:var(--brand);color:var(--card);font-weight:700}
.tw-kpi.link{cursor:pointer;transition:border-color .15s,box-shadow .15s}
.tw-kpi.link:hover{border-color:var(--brand);box-shadow:0 0 0 3px rgba(239,127,23,.12)}
.tw-sbwrap{overflow-x:auto;margin:2px -2px 0}
.tw-sb{width:100%;border-collapse:separate;border-spacing:3px;font-size:var(--fs-3)}
.tw-sb th{background:none;border:0;font:700 var(--fs-1)/1.4 var(--font-mono);color:var(--muted);padding:3px 2px;text-align:center;white-space:nowrap}
.tw-sb th.l{text-align:left}
.tw-sb td{border:0;text-align:center;padding:9px 4px;border-radius:7px;background:var(--card);color:var(--muted);font-variant-numeric:tabular-nums;white-space:nowrap}
.tw-sb td.who{text-align:left;background:none;color:var(--ink);font-weight:600;padding-left:0;white-space:nowrap}
.tw-sb td.val{font:700 var(--fs-5)/1 var(--font-mono);cursor:pointer}
.tw-sb td.val:hover{box-shadow:0 0 0 2px var(--brand)}
.tw-sb td.yr{background:var(--ink);color:var(--card);font:700 13.4px/1 var(--font-mono)}
.tw-sb td.empty{background:repeating-linear-gradient(45deg,var(--card),var(--card) 5px,var(--card) 5px,var(--card) 10px);color:var(--line)}
.tw-sblg{display:flex;gap:11px;flex-wrap:wrap;align-items:center;margin-top:9px;font-size:var(--fs-2);color:var(--muted)}
.tw-sblg i{width:15px;height:9px;border-radius:3px;display:inline-block;margin-right:4px;vertical-align:-1px}
.tw-sblg i.em{background:repeating-linear-gradient(45deg,var(--card),var(--card) 2px,var(--card) 2px,var(--card) 4px)}
.tw-cin{display:flex;gap:5px;align-items:center}
.tw-cin input{flex:1;min-width:0}
.tw-tr{flex:none;font:700 var(--fs-1)/1 var(--font-mono);border:1px solid var(--brand-200);background:var(--brand-50);color:var(--brand-700);border-radius:5px;padding:6px 5px;cursor:pointer}
.tw-tr:hover{background:var(--brand-100)}
.tw-wlab{font:700 var(--fs-1)/1.4 var(--font-mono);color:var(--muted);letter-spacing:.02em}
.tw-chip.off{opacity:.42}
.tw-chiprow{display:flex;gap:6px;flex-wrap:wrap}
.tw-chiprow::-webkit-scrollbar{height:0}
.tw-vsep{width:1px;height:16px;background:var(--line);margin:0 4px;flex:none}
.tw-cdot{width:7px;height:7px;border-radius:50%;display:inline-block;margin-right:4px}
.tw-fn{display:inline-flex;align-items:center;gap:4px;font:700 var(--fs-1)/1 var(--font-mono);padding:3px 6px;border-radius:4px;background:var(--card);color:var(--ink2)}
.tw-fn i{width:6px;height:6px;border-radius:50%;background:var(--c);display:inline-block}
.tw-click{cursor:pointer}
.tw-click:hover{color:var(--brand-ink,var(--brand-700))}
.tw-kcard-p{cursor:pointer}
.tw-kcard-p:hover{border-color:var(--brand);box-shadow:0 2px 8px rgba(0,0,0,.07)}
.tw-dwwrap{position:fixed;inset:0;background:rgba(20,18,15,.34);z-index:62;display:flex;align-items:center;justify-content:center;padding:28px 18px}
.tw-dw{width:min(620px,96vw);max-height:min(84vh,780px);background:var(--bg);overflow:auto;padding:22px 24px;border-radius:14px;box-shadow:0 20px 56px rgba(0,0,0,.22);display:flex;flex-direction:column;gap:13px;animation:twDwIn .16s ease-out}
@keyframes twDwIn{from{opacity:0;transform:translateY(8px) scale(.99)}to{opacity:1;transform:none}}
.tw-dw-h{display:flex;gap:10px;align-items:flex-start}.tw-dw-h h3{margin:3px 0 0;font-size:var(--fs-6);line-height:1.35}
.tw-dw-meta{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px 16px;font-size:var(--fs-3)}
.tw-dw-meta .k{font:700 var(--fs-1)/1.4 var(--font-mono);color:var(--muted);display:block;margin-bottom:2px}
.tw-dw-sec{border-top:1px solid var(--line);padding-top:10px}
.tw-dw-sec>b{font-size:var(--fs-3);display:block;margin-bottom:7px}
.tw-rec{padding:6px 0;border-bottom:1px dashed var(--line-2);font-size:var(--fs-3);line-height:1.5}
.tw-rec .k{font:700 var(--fs-1)/1 var(--font-mono);color:var(--muted);margin-right:6px}
.tw-dw-foot{display:flex;gap:8px;flex-wrap:wrap;justify-content:flex-end;padding-top:13px;margin-top:2px;border-top:1px solid var(--line)}
.tw-badge{font:800 var(--fs-2)/1 var(--font-mono);background:var(--brand);color:var(--card);border-radius:999px;padding:3px 7px;margin-left:6px}
.tw-focus{display:grid;grid-template-columns:78px minmax(0,1fr) 84px 56px;gap:9px;align-items:center;padding:7px 0;border-bottom:1px dashed var(--line-2)}
.tw-focus:last-child{border-bottom:0}
.tw-focus-t{font-size:var(--fs-3);font-weight:600;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tw-focus-o{text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tw-fl{font:700 var(--fs-1)/1 var(--font-mono);padding:4px 6px;border-radius:5px;text-align:center;white-space:nowrap}
.tw-fl.bl-no{background:var(--danger-50);color:var(--danger)}
.tw-fl.bl-bl{background:var(--brand-50);color:var(--warn)}
.tw-fl.bl-so{background:var(--brand-50);color:var(--brand-700)}
.tw-mdet{margin-top:9px;border-top:1px solid var(--line);padding-top:6px}
.tw-mdet-row{display:grid;grid-template-columns:minmax(0,1fr) 66px 44px 52px;gap:8px;align-items:center;padding:4px 0;font-size:var(--fs-3)}
.tw-mdet-t{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tw-mdet-s{font:700 var(--fs-3)/1 var(--font-mono);text-align:right}
.tw-mdet-s em{color:var(--muted);font-style:normal;font-weight:600}
.tw-mrow{display:grid;grid-template-columns:minmax(0,1fr) 74px 42px;gap:9px;align-items:center;padding:6px 0;border-bottom:1px dashed var(--line-2);cursor:pointer}
.tw-mrow:last-child{border-bottom:0}
.tw-mrow:hover .tw-mrow-n{color:var(--brand-ink,var(--brand-700))}
.tw-mrow-n{font-size:var(--fs-3);font-weight:600;display:flex;align-items:center;min-width:0;overflow:hidden}
.tw-mrow-b{height:5px;border-radius:3px;background:var(--line-2);overflow:hidden}
.tw-mrow-b i{display:block;height:100%;border-radius:3px}
.tw-mrow-v{font:700 var(--fs-2)/1 var(--font-mono);color:var(--muted);text-align:right}
.tw-kpi.link::after{content:"›";position:absolute;right:10px;bottom:7px;color:var(--brand);font-weight:800;font-size:var(--fs-5);line-height:1}
.tw-lg{display:inline-block;width:9px;height:9px;border-radius:3px;vertical-align:-1px;margin:0 2px}
.tw-lg[data-s="done"]{background:var(--ok)}.tw-lg[data-s="in_progress"]{background:var(--info)}.tw-lg[data-s="blocked"]{background:var(--warn)}
.tw-wk .now{font:700 var(--fs-1)/1 var(--font-mono);color:var(--card);background:var(--brand);border-radius:3px;padding:2px 4px;margin-left:5px}
.tw-chip.active{background:var(--brand);border-color:var(--brand);color:var(--card);font-weight:700}
.tw-seg{display:flex;border:1px solid var(--line);border-radius:8px;overflow:hidden}
.tw-seg button{border:0;background:var(--bg);padding:6px 11px;font-size:var(--fs-3);cursor:pointer;color:var(--muted)}
.tw-seg button.active{background:var(--brand);color:var(--card);font-weight:700}
.tw-row{display:grid;grid-template-columns:minmax(0,1.7fr) 92px 100px 110px 100px 76px 88px 108px;gap:10px;align-items:start;padding:10px 12px;border-bottom:1px solid var(--line-2)}
.tw-obj{font-size:var(--fs-3);line-height:1.5;color:var(--muted);margin-top:2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tw-obj .ob-k{font:700 var(--fs-1)/1 var(--font-mono);color:var(--line);letter-spacing:.06em;margin-right:5px;vertical-align:1px}
.tw-obj .ob-k.dim{color:var(--line)}
.tw-upd{font-size:var(--fs-2);line-height:1.55;color:var(--muted);min-width:0}
.tw-upd .tw-ul-l{display:flex;gap:5px;align-items:baseline;padding:.5px 0;overflow:hidden}
.tw-upd .tw-ul-l.cur{color:var(--ink);font-weight:600}
.tw-upd .tw-ul-t{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tw-upd .tw-ul-m{color:var(--muted);font-size:var(--fs-1);margin-top:2px}
.tw-hist{display:flex;flex-direction:column;gap:2px;margin-bottom:4px}
.tw-hist:empty{display:none}
.tw-hl{display:flex;gap:5px;align-items:baseline;font-size:var(--fs-1);line-height:1.45;color:var(--muted);overflow:hidden}
.tw-hl .k{flex:none;font:700 var(--fs-1)/1 var(--font-mono);background:var(--bg-2);border-radius:3px;padding:2px 4px}
.tw-hl .t{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tw-hl-more{color:var(--muted);font-style:italic}
.rt-2col{display:grid;grid-template-columns:minmax(0,1fr) 320px;gap:14px;align-items:start}
@media(max-width:1180px){.rt-2col{grid-template-columns:minmax(0,1fr)}}
.rt-board{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px;align-items:start}
@media(max-width:1100px){.rt-board{grid-template-columns:repeat(2,minmax(0,1fr))}}
.rt-bcol{background:var(--bg-2);border-radius:9px;padding:8px;min-height:90px}
.rt-bhd{display:flex;align-items:center;gap:6px;font:700 var(--fs-1)/1.4 var(--font-mono);color:var(--muted);padding:2px 3px 8px}
.rt-bhd i{width:8px;height:8px;border-radius:50%;display:block;flex:none}
.rt-bhd .n{margin-left:auto;background:var(--card);border-radius:9px;padding:1px 6px;font-size:var(--fs-1);color:var(--ink-2)}
.rt-bcard{background:var(--card);border:1px solid var(--line-2);border-radius:7px;padding:8px;margin-bottom:7px;cursor:pointer;transition:box-shadow .12s}
.rt-bcard:hover{box-shadow:0 2px 8px rgba(0,0,0,.06)}
.rt-bcard .t{font:600 var(--fs-3)/1.45 var(--sans,sans-serif);margin-bottom:5px}
.rt-bcard .m{display:flex;gap:8px;font-size:var(--fs-1);color:var(--muted);margin-bottom:5px}
.rt-bcard .f{display:flex;gap:5px;align-items:center;flex-wrap:wrap}
.rt-bcard.done{opacity:.6}
.rt-bempty{font-size:var(--fs-2);color:var(--line);text-align:center;padding:10px 0}
.tw-alerts{display:flex;flex-direction:column;gap:8px;margin-top:6px}
.tw-alert-row{display:grid;grid-template-columns:120px 130px 1fr;gap:10px;align-items:center;padding:6px 0;border-bottom:1px dashed var(--line-2)}
.tw-alert-row:last-child{border-bottom:0}
.tw-alert-name{font-weight:650;font-size:var(--fs-3)}
.tw-alert-tags{display:flex;gap:5px;flex-wrap:wrap}
.tw-alert-items{display:flex;gap:10px;flex-wrap:wrap;font-size:var(--fs-2);color:var(--muted)}
.tw-tbl-wrap{overflow-x:auto}
.tw-tbl{width:100%;border-collapse:collapse;font-size:var(--fs-3)}
.tw-tbl th{text-align:left;padding:8px 12px;font:700 var(--fs-1)/1.5 var(--font-mono);color:var(--muted);background:var(--bg-2);white-space:nowrap}
.tw-tbl td{padding:9px 12px;border-top:1px solid var(--line-2);vertical-align:middle}
.tw-msum{display:flex;flex-direction:column;gap:6px;margin-top:6px}
.tw-msum-row{display:grid;grid-template-columns:110px 62px 1fr 46px 46px;gap:10px;align-items:center;font-size:var(--fs-3)}
.tw-msum-row .n{font-weight:600}
.tw-msum-row .v{color:var(--muted);font-variant-numeric:tabular-nums}
.tw-msum-row .p{text-align:right;font-variant-numeric:tabular-nums}
.tw-msum-row .o{text-align:right;font-variant-numeric:tabular-nums;color:var(--brand-700,var(--brand-700));font-weight:650}
.tw-bar{height:6px;background:var(--line-2);border-radius:3px;overflow:hidden}
.tw-bar i{display:block;height:100%;background:var(--ok);border-radius:3px}
.tw-main{display:grid;grid-template-columns:minmax(0,1fr) minmax(150px,40%);gap:12px;align-items:start}
.tw-rw-work > div:not(.tw-main){align-self:center}
.tw-main-l{min-width:0}
.tw-main-r{display:flex;flex-direction:column;gap:3px;min-width:0;padding-left:12px;border-left:1px dashed var(--line-2)}
.tw-main-r .tw-hl{display:flex;gap:5px;align-items:baseline;font-size:var(--fs-1);line-height:1.45;color:var(--muted);overflow:hidden}
.tw-main-r .tw-hl .k{flex:none;font:700 var(--fs-1)/1 var(--font-mono);background:var(--bg-2);border-radius:3px;padding:2px 4px}
.tw-main-r .tw-hl .t{white-space:normal;word-break:break-word;line-height:1.45}
.tw-row .tw-upd{display:flex;gap:5px;align-items:baseline;font-size:var(--fs-1);color:var(--muted);margin-top:3px;overflow:hidden}
.tw-row .tw-upd .k{flex:none;font:700 var(--fs-1)/1 var(--font-mono);background:var(--bg-2);border-radius:3px;padding:2px 4px}
.tw-stars{display:inline-flex;gap:1px;font-size:var(--fs-2);line-height:1;letter-spacing:-1px}
.tw-star{color:var(--line-2)}
.tw-star.on{color:var(--brand)}
.tw-star{cursor:pointer;transition:transform .1s}
.tw-stars:hover .tw-star{color:var(--line-2)}
.tw-stars:hover .tw-star.on{color:var(--brand)}
.tw-stars .tw-star:hover{transform:scale(1.25);color:var(--brand)!important}
.tw-age{display:inline-block;font:700 var(--fs-1)/1 var(--font-mono);padding:3px 5px;border-radius:4px;vertical-align:2px;margin-left:4px}
.tw-age.new{background:var(--ok-50);color:var(--ok)}
.tw-age.carry{background:var(--brand-50);color:var(--warn)}
.tw-rrow{display:grid;grid-template-columns:44px minmax(0,1fr) 84px 78px;gap:8px;align-items:center;padding:5px 0;border-bottom:1px dashed var(--line-2);font-size:var(--fs-3)}
.tw-rrow:last-child{border-bottom:0}
.tw-rrow .due{color:var(--muted);font-variant-numeric:tabular-nums;font-size:var(--fs-2)}
.tw-rrow .tt{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tw-rrow .ow{color:var(--muted);font-size:var(--fs-2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tw-mx{display:flex;flex-direction:column;gap:2px}
.tw-mx-h,.tw-mx-r{display:grid;grid-template-columns:minmax(0,1.2fr) 72px 72px 72px 78px;gap:8px;align-items:center}
.tw-mx-h{font:700 var(--fs-1)/1.6 var(--font-mono);color:var(--muted);padding-bottom:4px;border-bottom:1px solid var(--line-2)}
.tw-mx-r{padding:4px 0;font-size:var(--fs-3);cursor:pointer}
.tw-mx-r:hover{background:var(--bg-2)}
.tw-mx-r .nm{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tw-mc{display:flex;flex-direction:column;gap:2px}
.tw-mc b{font:650 var(--fs-2)/1 var(--font-mono);font-variant-numeric:tabular-nums}
.tw-mc i{display:block;height:3px;background:var(--line-2);border-radius:2px;overflow:hidden}
.tw-mc u{display:block;height:100%;text-decoration:none;border-radius:2px;background:var(--ok)}
.tw-mc.mid u{background:var(--brand)}.tw-mc.low u{background:var(--danger)}
.tw-mc.dim b{color:var(--line)}
.tw-mc.tot b{color:var(--ink)}
.tw-noacct{font:700 var(--fs-1)/1 var(--font-mono);background:var(--danger-50);color:var(--danger);border-radius:3px;padding:2px 4px;margin-left:3px}
.tw-focus{display:grid;grid-template-columns:4px 86px minmax(0,1fr) 88px 74px;gap:9px;align-items:center;padding:7px 0;border-bottom:1px dashed var(--line-2)}
.tw-focus:last-child{border-bottom:0}
.tw-focus .tw-fl{display:block;width:4px;height:22px;border-radius:2px;background:var(--line)}
.tw-fl.bl-no{background:var(--danger)}.tw-fl.bl-bl{background:var(--warn)}.tw-fl.bl-so{background:var(--brand)}
.tw-focus .fn{min-width:0;overflow:hidden}
.tw-focus .tt{font-weight:600;font-size:var(--fs-3);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tw-focus .ow{font-size:var(--fs-2);color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tw-focus .tag2{font-size:var(--fs-1);text-align:right;color:var(--danger);font-weight:650}
.tw-focus .fx{display:flex;gap:8px;align-items:baseline;min-width:0}
.tw-focus .fx b{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tw-focus .fx .tw-muted{flex:none;font-size:var(--fs-2)}
.tw-upd .k{font:700 var(--fs-1)/1 var(--font-mono);background:var(--bg-2);border-radius:3px;padding:2px 4px;margin-right:5px;color:var(--muted);vertical-align:1px}
.tw-upd .k.warn{background:var(--danger-50);color:var(--danger)}
.tw-upd .m{color:var(--muted)}
.tw-wt{font:700 var(--fs-2)/1 var(--font-mono);color:var(--ink2);font-variant-numeric:tabular-nums}
.tw-sc{font:700 var(--fs-1)/1 var(--font-mono);color:var(--ok);display:block;margin-top:3px;text-align:center}
.tw-row.tw-row-head{background:var(--bg-2);font:700 var(--fs-1)/1.5 var(--font-mono);color:var(--muted);position:sticky;top:0;z-index:3;border-bottom:1px solid var(--line)}
.tw-row:hover{background:var(--bg-2)}
.tw-row .t{font-weight:600;font-size:var(--fs-4);line-height:1.35}
.tw-row .s{font-size:var(--fs-1);color:var(--muted);margin-top:3px;display:flex;gap:6px;align-items:center;flex-wrap:wrap}
.tw-tag{font-size:var(--fs-1);font-weight:700;padding:2px 5px;border-radius:4px;background:var(--bg-2);color:var(--muted)}
.tw-tag.k{background:var(--brand-50);color:var(--brand-700)}
.tw-wds{display:flex;gap:3px}
.tw-wd{width:20px;height:20px;border-radius:4px;border:1px solid var(--line);background:var(--bg);font-size:var(--fs-1);line-height:18px;text-align:center;color:var(--muted)}
.tw-wd[data-s="done"]{background:var(--ok-50);border-color:var(--ok-50);color:var(--ok);font-weight:700}
.tw-wd[data-s="in_progress"]{background:var(--info-50);border-color:var(--brand-200);color:var(--info);font-weight:700}
.tw-wd[data-s="blocked"]{background:var(--brand-50);border-color:var(--brand-200);color:var(--warn);font-weight:700}
.tw-wd[data-s="not_started"]{background:var(--card);border-color:var(--line-2)}
.tw-wd.cur{box-shadow:0 0 0 2px var(--brand)}
.tw-dot{width:7px;height:7px;border-radius:50%;background:var(--line-2);display:inline-block}
.tw-dot[data-s="done"]{background:var(--ok)}
.tw-dot[data-s="in_progress"]{background:var(--info)}
.tw-dot[data-s="blocked"]{background:var(--warn)}
.tw-dot[data-s="not_started"]{background:var(--line)}
.tw-st{appearance:none;-webkit-appearance:none;border:1px solid var(--line);border-radius:7px;padding:5px 8px;font-size:var(--fs-2);font-weight:700;background:var(--bg);color:var(--muted);cursor:pointer}
.tw-st[data-s="in_progress"]{background:var(--info-50);border-color:var(--brand-200);color:var(--info)}
.tw-st[data-s="done"]{background:var(--ok-50);border-color:var(--ok-50);color:var(--ok)}
.tw-st[data-s="blocked"]{background:var(--brand-50);border-color:var(--brand-200);color:var(--warn)}
.tw-st[data-s="wait"]{background:var(--brand-50);border-color:var(--brand-200);color:var(--brand-700)}
.tw-col{display:flex;flex-direction:column;gap:8px;min-width:0}
.tw-cols{display:grid;grid-auto-flow:column;grid-auto-columns:minmax(252px,1fr);gap:10px;overflow-x:auto;padding-bottom:4px}
.tw-col-h{display:flex;align-items:center;gap:6px;font-size:var(--fs-3);font-weight:700;padding:6px 8px;background:var(--bg-2);border-radius:8px}
.tw-col-h .n{font-variant-numeric:tabular-nums;color:var(--muted);font-weight:600}
.tw-kcard{border:1px solid var(--line);border-radius:9px;padding:8px 9px;background:var(--bg)}
.tw-kcard .t{font-size:var(--fs-3);font-weight:600;line-height:1.35}
.tw-kcard .m{font-size:var(--fs-1);color:var(--muted);margin-top:4px;display:flex;gap:6px;flex-wrap:wrap;align-items:center}
.tw-week{display:grid;grid-template-columns:minmax(0,1fr) 268px;gap:10px}
.tw-wkbar{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:8px;margin-bottom:10px}
.tw-wk{border:1px solid var(--line);border-radius:9px;padding:8px 10px;background:var(--bg);cursor:pointer}
.tw-wk.active{border-color:var(--brand);box-shadow:0 0 0 2px rgba(239,127,23,.16)}
.tw-wk .d{font-size:var(--fs-1);color:var(--muted);display:flex;align-items:center;gap:6px}
.tw-wk .v{font-size:var(--fs-6);font-weight:800;font-variant-numeric:tabular-nums;margin-top:2px}
.tw-wk .p{height:4px;border-radius:3px;background:var(--line-2);margin-top:5px;overflow:hidden}
.tw-wk .p i{display:block;height:100%;background:var(--brand)}
.tw-wkrow,.tw-rw-week{display:grid;grid-template-columns:20px minmax(0,1.1fr) 104px minmax(0,1.2fr) 96px;gap:10px;align-items:center;padding:10px 12px;border-bottom:1px solid var(--line-2)}
.tw-wkrow{background:var(--bg-2);font:700 var(--fs-1)/1.5 var(--font-mono)!important;color:var(--muted);position:sticky;top:0;z-index:3;border-bottom:1px solid var(--line)}
.tw-rw-week.blank{background:var(--card)}
.tw-rw-work.sel,.tw-rw-week.sel{background:var(--brand-50)!important;box-shadow:inset 3px 0 0 var(--brand)}
.tw-rw-week .mk{font:800 var(--fs-3)/1 var(--font-mono);text-align:center;color:var(--ok)}
.tw-rw-week.blank .mk{color:var(--danger)}
.tw-rw-week .ttl{font-weight:600;font-size:var(--fs-3);line-height:1.35}
.tw-wkrow input,.tw-rw-week input{width:100%;border:1px solid transparent;background:var(--bg-2);border-radius:7px;padding:6px 8px;font-size:var(--fs-3);color:inherit}
.tw-wkrow input:focus,.tw-rw-week input:focus{outline:0;border-color:var(--brand);background:var(--bg)}
.tw-rw-week select.tw-st{width:100%;border:1px solid var(--line);background-color:var(--card);padding:6px 18px 6px 8px;background-image:linear-gradient(45deg,transparent 50%,var(--muted) 50%),linear-gradient(135deg,var(--muted) 50%,transparent 50%);background-position:calc(100% - 11px) 50%,calc(100% - 7px) 50%;background-size:4px 4px,4px 4px;background-repeat:no-repeat}
.tw-draft{white-space:pre-wrap;font-size:var(--fs-3);line-height:1.7;color:var(--muted)}
.tw-mcards{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}
.tw-mcard{border:1px solid var(--line);border-radius:12px;padding:12px;background:var(--bg)}
.tw-mcard .h{display:flex;align-items:center;gap:8px;margin-bottom:8px}
.tw-mcard .h b{font-size:var(--fs-5)}
.tw-num{display:grid;grid-template-columns:repeat(3,1fr);gap:6px;margin-bottom:8px}
.tw-num div{background:var(--bg-2);border-radius:8px;padding:6px 8px}
.tw-num b{display:block;font-size:var(--fs-6);font-variant-numeric:tabular-nums}
.tw-num span{font-size:var(--fs-1);color:var(--muted)}
.tw-mgwrap{position:fixed;inset:0;background:rgba(20,18,15,.28);z-index:60;display:flex;justify-content:flex-end}
.tw-mg{width:min(460px,94vw);height:100%;background:var(--bg);overflow:auto;padding:18px;box-shadow:-8px 0 28px rgba(0,0,0,.12)}
.tw-mg h3{margin:0 0 4px;font-size:var(--fs-6)}
.tw-mg .sec{border-top:1px solid var(--line);padding:13px 0}
.tw-mg .sec b{font-size:var(--fs-3);display:block;margin-bottom:4px}
.tw-mg .sec .tw-muted{margin-bottom:7px;line-height:1.6}
.tw-mg-row{display:flex;align-items:center;gap:8px;padding:5px 0;font-size:var(--fs-3)}
@media(max-width:1280px){.tw-row{grid-template-columns:minmax(0,1.5fr) 88px 94px 104px 96px 72px 84px 104px}}
@media(max-width:1100px){.tw-row{grid-template-columns:minmax(0,1.15fr) minmax(0,0.85fr) 84px 80px 92px 66px 100px}.tw-row .hide-lg{display:none}}
@media(max-width:1080px){.tw-kpis{grid-template-columns:repeat(3,minmax(0,1fr))}.tw-grid2{grid-template-columns:minmax(0,1fr)}.tw-week{grid-template-columns:minmax(0,1fr)}.tw-cols{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(max-width:760px){.tw-kpis{grid-template-columns:repeat(2,minmax(0,1fr))}.tw-mcards{grid-template-columns:minmax(0,1fr)}.tw-col{min-width:0}.tw-row.tw-row-head{display:none}.tw-row{display:flex;flex-wrap:wrap;row-gap:8px;align-items:center}.tw-row>div:first-child{flex:1 1 100%}.tw-row>div:last-child{margin-left:auto}.tw-row .hide-s{display:none}.tw-wkbar{grid-auto-flow:column;grid-auto-columns:minmax(104px,1fr);grid-template-columns:none;overflow-x:auto;padding-bottom:2px}.tw-wkrow{display:none}.tw-rw-week{grid-template-columns:minmax(0,1fr)!important;row-gap:7px;padding:10px}.tw-rw-week .mk{display:none}.tw-wkrow .hide-s,.tw-rw-week .hide-s{display:none}.tw-chiprow{flex-wrap:nowrap;overflow-x:auto;padding-bottom:2px}.tw-chiprow .tw-chip{flex:none}.tw-head h2{font-size:var(--fs-7)}}

/* ============================================================
   v168 · KPI 卡统一（解决"看板卡片大小不一"）
   ------------------------------------------------------------
   现状盘点：
     .kpis    minmax(184px,1fr)  gap 无
     .wb-kpis minmax(148px,1fr)  gap 12px   ← 列宽比 .kpis 窄 36px
     .tw-kpis repeat(6,...)      gap 8px
     .ast-kpis 没有 grid，卡片块级堆叠
     .pf-grid4 是表单网格（S/A/B/C 阈值输入），不属于 KPI，不动
   且 .kpi 没有 min-height、标签不固定行高 ——
   标签一长（"招聘计划完成率"）就换行，把数值顶下去，
   同组里数值高低不齐，这就是"大小不一"的直接观感来源。

   做法：统一间距 + 卡片等高 + 标签固定两行高度（数值落在同一基线上）。
   列数不动 —— 各视图 KPI 数量不同（4/6/8），强改列数会挤出孤块。
   ============================================================ */
.kpis,
.wb-kpis,
.ast-kpis,
.tw-kpis {
  gap: var(--sp-3) !important;
  align-items: stretch !important;
  margin-bottom: var(--sp-4) !important;
}
.kpis > .kpi,
.wb-kpis > .kpi,
.ast-kpis > .kpi,
.tw-kpis > .tw-kpi {
  min-height: 96px;
  display: flex;
  flex-direction: column;
  justify-content: center;
}
/* 标签固定两行高：单行标签与两行标签的数值落在同一条基线上 */
.kpis > .kpi .k-label,
.wb-kpis > .kpi .kl,
.ast-kpis > .kpi .k-label {
  min-height: 2.6em;
  display: flex;
  align-items: flex-end;
  margin-bottom: 4px;
}
.tw-kpis > .tw-kpi > span {
  min-height: 2.2em;
  display: flex;
  align-items: flex-end;
}
/* 数值不换行、不因长数字压扁 */
.kpis > .kpi .k-val,
.wb-kpis > .kpi .kv,
.tw-kpis > .tw-kpi b {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ============================================================
   v168 · 团队工作管理 · 概览页「需要你处理」行动条
   ------------------------------------------------------------
   一进页面先看到"有几件事等我"，点数字直接筛到工作清单。
   红色（risk）用于逾期，其余用中性；整条只在有事项时出现。
   ============================================================ */
.tw-action {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  padding: 10px 14px;
  margin-bottom: var(--sp-3);
  background: var(--brand-50);
  border: 1px solid var(--brand-200);
  border-radius: var(--r-md);
  font-size: var(--fs-3);
}
.tw-action b { font-weight: 700; color: var(--brand-800); }
.tw-act-b {
  border: 1px solid var(--brand-200);
  background: var(--card);
  color: var(--brand-800);
  font-family: inherit;
  font-size: var(--fs-2);
  font-weight: 650;
  padding: 3px 10px;
  border-radius: 999px;
  cursor: pointer;
  white-space: nowrap;
}
.tw-act-b:hover { background: var(--brand-100); }
.tw-act-b.risk {
  background: var(--danger-50);
  border-color: var(--danger);
  color: var(--danger);
}
.tw-act-b.risk:hover { background: var(--danger); color: var(--card); }
