/* ============================================================
   设计 token（阶段1 打底）
   决策层 10 个基础色 → 代码层展开为派生档。本阶段先"只定义、不改旧值"，
   除顶部通栏外不产生任何视觉变化。
   ============================================================ */
:root {
  /* 品牌主色（换肤：皮肤3 · 沉稳深侧栏 · 主色 #2563eb） */
  --color-primary: #2563eb;
  --color-primary-hover: #1d4ed8;
  --color-primary-weak: #eef4ff;
  --color-primary-on-tint: #1e40af;
  /* 语义状态色 */
  --color-success: #389e0d;
  --color-success-text: #157347;
  --color-success-bright: #52c41a;
  --color-warning: #d48806;
  --color-warning-bright: #fa8c16;
  --color-danger: #cf1322;
  --color-info-purple: #722ed1;
  --color-info-cyan: #13c2c2;
  /* 状态灰（S1 立项 / S7 关闭 分档，不合并） */
  --color-status-idle: #6c757d;
  --color-status-closed: #343a40;
  /* 状态徽章（换肤：胶囊形） */
  --badge-radius: 999px;
  --badge-pad-y: .3em;
  --badge-pad-x: .65em;
  --badge-font-weight: 500;
  /* 文本中性色 */
  --color-text: #333333;
  --color-text-strong: #25292e;
  --color-text-secondary: #595959;
  --color-text-muted: #8c8c8c;
  --color-text-placeholder: #b0b0b0;
  /* 背景 / 表面 / 边框 */
  --color-bg: #f4f6fb;
  --color-surface: #ffffff;
  --color-border: #eef0f4;
  --color-border-light: #f4f6fb;
  /* 布局（换肤：深色侧边栏 #0f172a） */
  --color-sidebar: #0f172a;
  --color-sidebar-text: #cbd5e1;
  /* 侧栏（深色化） */
  --color-sidebar-border: #1e293b;
  --color-sidebar-hover-bg: #1e293b;
  --color-sidebar-active-bg: #2563eb;
  --color-sidebar-active-text: #ffffff;
  --color-sidebar-submenu-bg: #0b1526;
  --color-sidebar-arrow: #64748b;
  --color-sidebar-disabled: #64748b;
  /* 功能卡（阶段4：克制风格 —— 细边框 + 浅色 tint 图标） */
  --card-icon-blue-bg: #eef4ff;
  --card-icon-blue-fg: #2563eb;
  --card-icon-blue-bd: #dbeafe;
  --card-icon-purple-bg: #f4edff;
  --card-icon-purple-fg: #722ed1;
  --card-icon-purple-bd: #e2d3fb;
  --card-icon-green-bg: #eef8e6;
  --card-icon-green-fg: #389e0d;
  --card-icon-green-bd: #d5ebc2;
  --card-icon-teal-bg: #e6f7f5;
  --card-icon-teal-fg: #0d9488;
  --card-icon-teal-bd: #c5e9e4;
  --card-icon-off-bg: #f2f4f7;
  --card-icon-off-fg: #b6bcc6;
  --card-icon-off-bd: #e6e9ee;
  /* 顶部通栏 */
  --topbar-bg: #ffffff;
  --topbar-fg: #25292e;
  --topbar-icon: #5b636d;
  --topbar-avatar-bg: #eef4ff;
  --topbar-avatar-fg: #2563eb;
  --topbar-border: #eef0f4;
  /* 阶梯（换肤：圆角加大） */
  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 12px;
  --radius-pill: 999px;
  --shadow-surface: 0 1px 3px rgba(16, 24, 40, .06), 0 1px 2px rgba(16, 24, 40, .04);
  --shadow-overlay: 0 8px 24px rgba(0, 0, 0, .10);
  /* 表格冻结（吸顶表头/固定列）背景 —— 换肤统一令牌 */
  --tbl-head-bg: #f8f9fa;
  --tbl-frozen-bg: #ffffff;
  --tbl-hover-bg: #f5f5f5;
  --tbl-border: #e9ecef;
  --font-size-xs: 12px;
  --font-size-sm: 13px;
  --font-size-base: 14px;
  --font-size-lg: 16px;
  --font-size-xl: 20px;
  --font-size-2xl: 26px;
}

/* ============================================================
   全局样式：极简工业风（参考简道云后台 / 黑湖小工单）
   布局：顶部 56px 蓝色通栏 + 左侧 220px 深色侧边栏 + 右侧内容区
   ============================================================ */

body {
  background-color: var(--color-bg);
  font-size: 14px;
  color: var(--color-text);
}

/* ============================================================
   阶段6b：全站链接色归并到主色
   背景：Bootstrap 内置的裸链接色是另一个偏紫的蓝（非主色 #2563eb），全站"裸链接"此前一直用它。
   只覆盖"裸链接"；带类的链接（.nav-link / .dropdown-item / .btn / .alert-link /
   .page-link 等）靠类选择器更高特异性保持原样，不受影响。
   ============================================================ */
a { color: var(--color-primary); }
a:hover { color: var(--color-primary-hover); }

/* ============ 布局骨架 ============ */
.app-body { min-height: 100vh; }

/* ---------- 顶部蓝色通栏（56px，fixed 全宽） ---------- */
.topbar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 56px;
  background: var(--topbar-bg);
  color: var(--topbar-fg);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 16px;
  z-index: 1030;
  border-bottom: 1px solid var(--topbar-border);
}
.topbar-left { display: flex; align-items: center; gap: 10px; }
.topbar-logo { display: inline-flex; width: 28px; height: 28px; color: var(--color-primary); }
.topbar-logo svg { width: 28px; height: 28px; }
.topbar-brand { font-size: 17px; font-weight: 600; letter-spacing: .5px; color: var(--topbar-fg); }
.topbar-right { display: flex; align-items: center; gap: 14px; }
.topbar-bell { color: var(--topbar-icon); display: inline-flex; width: 22px; height: 22px; opacity: .92; }
.topbar-bell:hover { opacity: 1; }
.topbar-bell svg { width: 22px; height: 22px; }
.topbar-user {
  color: var(--topbar-fg);
  text-decoration: none;
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 14px;
}
.topbar-user:hover { color: var(--topbar-fg); }
.topbar-avatar {
  display: inline-flex;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: var(--topbar-avatar-bg);
  color: var(--topbar-avatar-fg);
  align-items: center;
  justify-content: center;
  font-weight: 600;
}

/* ---------- 左侧深色侧边栏（220px，fixed） ---------- */
.sidebar {
  position: fixed;
  top: 56px;
  left: 0;
  bottom: 0;
  width: 220px;
  background: var(--color-sidebar);
  border-right: 1px solid var(--color-sidebar-border);
  overflow-y: auto;
  z-index: 1020;
}
.sidebar-nav { padding: 10px 0; }
.sidebar-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 20px;
  color: var(--color-sidebar-text);
  text-decoration: none;
  font-size: 14px;
  border-left: 3px solid transparent;
  transition: background .15s, color .15s;
}
.sidebar-item:hover { background: var(--color-sidebar-hover-bg); color: #e2e8f0; }
.sidebar-item.active {
  background: var(--color-sidebar-active-bg);
  color: var(--color-sidebar-active-text);
  border-left-color: var(--color-primary);
  font-weight: 600;
}
.sidebar-item.disabled { color: var(--color-sidebar-disabled); cursor: not-allowed; }
.sidebar-item.disabled:hover { background: transparent; color: var(--color-sidebar-disabled); }
.sidebar-icon { display: inline-flex; width: 18px; height: 18px; flex: none; }
.sidebar-icon svg { width: 18px; height: 18px; }
.sidebar-arrow { margin-left: auto; font-size: 11px; color: var(--color-sidebar-arrow); }
.sidebar-submenu { background: var(--color-sidebar-submenu-bg); }
.sidebar-sub { padding-left: 48px; padding-top: 10px; padding-bottom: 10px; font-size: 13.5px; }
.sidebar-sub.active { border-left-color: var(--color-primary); color: var(--color-sidebar-active-text); }

/* ---------- 主内容区 ---------- */
.main-content {
  margin-left: 220px;
  margin-top: 56px;
  padding: 1.25rem 1.5rem 2rem;
}

/* ---------- 卡片 ---------- */
.card { border: 1px solid var(--color-border); box-shadow: var(--shadow-surface); border-radius: var(--radius-lg); }
.card-header { font-size: 15px; font-weight: 600; }

/* ============ 工作台：功能大卡片 ============ */
.func-cards { margin-bottom: 1.25rem; }
.func-card {
  display: block;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 1.15rem 1.15rem .95rem;
  text-decoration: none;
  color: var(--color-text);
  height: 100%;
  transition: box-shadow .15s, transform .15s, border-color .15s;
}
.func-card:hover { box-shadow: 0 6px 20px rgba(16, 24, 40, .08); transform: translateY(-2px); color: var(--color-text); border-color: #bcd7ff; }
.func-card .func-icon {
  display: inline-flex;
  width: 42px;
  height: 42px;
  border-radius: var(--radius-md);
  align-items: center;
  justify-content: center;
  margin-bottom: 10px;
  background: var(--card-icon-blue-bg);
  color: var(--card-icon-blue-fg);
  border: 1px solid var(--card-icon-blue-bd);
}
.func-card.card-blue .func-icon { background: var(--card-icon-blue-bg); color: var(--card-icon-blue-fg); border-color: var(--card-icon-blue-bd); }
.func-card.card-purple .func-icon { background: var(--card-icon-purple-bg); color: var(--card-icon-purple-fg); border-color: var(--card-icon-purple-bd); }
.func-card.card-green .func-icon { background: var(--card-icon-green-bg); color: var(--card-icon-green-fg); border-color: var(--card-icon-green-bd); }
.func-card.card-teal .func-icon { background: var(--card-icon-teal-bg); color: var(--card-icon-teal-fg); border-color: var(--card-icon-teal-bd); }
.func-card .func-icon svg { width: 22px; height: 22px; }
.func-card .func-title { font-size: 16px; font-weight: 600; margin-bottom: 4px; }
.func-card .func-desc { font-size: 13px; color: var(--color-text-muted); margin-bottom: 0; }
.func-card .func-tag { font-size: 12px; color: #bbb; }
/* 禁用卡：真正灰化（置于彩色图标规则之后，保证同特异性下"灰化"优先于 card-green/blue/purple） */
.func-card.card-disabled {
  cursor: not-allowed;
  opacity: 1;
  background: #fbfcfd;
  border-style: dashed;
  border-color: #e4e7ec;
}
.func-card.card-disabled .func-icon {
  background: var(--card-icon-off-bg);
  color: var(--card-icon-off-fg);
  border-color: var(--card-icon-off-bd);
}
.func-card.card-disabled .func-title { color: #9aa2ae; }
.func-card.card-disabled .func-desc { color: #b6bcc6; }
.func-card.card-disabled:hover { box-shadow: none; transform: none; border-color: #e4e7ec; }

/* ============ 待办任务 ============ */
.todo-list { margin: 0; }
.todo-empty { text-align: center; color: #9aa3ac; padding: 2rem 0; }

/* ============ 状态颜色规范（待办/通用） ============ */
.badge-todo { font-weight: var(--badge-font-weight); padding: var(--badge-pad-y) var(--badge-pad-x); border-radius: var(--badge-radius); font-size: 12.5px; }
.badge-todo-processing { background: var(--color-primary-weak); color: var(--color-primary); }  /* 进行中：蓝 */
.badge-todo-waiting    { background: #fff7e6; color: var(--color-warning); }  /* 待处理：黄 */
.badge-todo-overdue    { background: #fff1f0; color: var(--color-danger); }  /* 逾期：红 */
.badge-todo-done       { background: #f0f9eb; color: var(--color-success); }  /* 已完成：绿 */

/* ============ 按钮（做大，工业风） ============ */
.btn { font-size: 14px; }
.btn-primary { background: #2563eb; border-color: #2563eb; }
.btn-primary:hover { background: #1d4ed8; border-color: #1d4ed8; }
.btn-lg { padding: .55rem 1.5rem; font-size: 15px; }
.btn-sm { padding: .3rem .7rem; }

/* ============ 表格（行高放大，不挤） ============ */
.table { font-size: 14px; }
.table th {
  font-weight: 600;
  white-space: nowrap;
  color: #595959;
  background: #fafbfc;
  padding: .75rem .75rem;
  vertical-align: middle;
}
.table td { vertical-align: middle; padding: .75rem .75rem; }

/* ============ 登录页（居中卡片） ============ */
.login-body {
  background-color: #eef1f5;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  padding: 1rem;
}
.login-card { width: 430px; max-width: 94vw; border-radius: 10px; }
.error-code { font-size: 3.2rem; font-weight: 700; letter-spacing: 2px; }

/* ============ 右上角 toast 提示 ============ */
#toast-area {
  position: fixed;
  top: 66px;
  right: 16px;
  z-index: 2100;
  width: 340px;
  max-width: 90vw;
}
#toast-area .alert { margin-bottom: .5rem; padding: .55rem .9rem; font-size: 13.5px; }
#toast-area .alert.fade-out { opacity: 0; transition: opacity .3s; }

/* ============ 分页条 ============ */
.pagination-bar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: .5rem;
  font-size: 13px;
  color: #666;
}
.pagination-bar .page-btn { min-width: 60px; }

/* ============ 样品状态徽章配色（7 态，详情/列表复用） ============ */
.badge-status { font-weight: var(--badge-font-weight); padding: var(--badge-pad-y) var(--badge-pad-x); border-radius: var(--badge-radius); display: inline-block; }
/* S1-S7 各自携带形状属性：部分页面（如 user_admin.js）单独使用子类而不带 .badge-status 基类，
   此处内联同一套 token 取值，保证"带/不带基类"两种用法形状完全一致（与基类叠加为幂等，值相同） */
.badge-status-S1 { background: var(--color-status-idle); color: #fff; border-radius: var(--badge-radius); padding: var(--badge-pad-y) var(--badge-pad-x); display: inline-block; font-weight: var(--badge-font-weight); }  /* 立项：灰 */
.badge-status-S2 { background: var(--color-primary); color: #fff; border-radius: var(--badge-radius); padding: var(--badge-pad-y) var(--badge-pad-x); display: inline-block; font-weight: var(--badge-font-weight); }  /* 建模中：蓝 */
.badge-status-S3 { background: var(--color-info-purple); color: #fff; border-radius: var(--badge-radius); padding: var(--badge-pad-y) var(--badge-pad-x); display: inline-block; font-weight: var(--badge-font-weight); }  /* BOM中：紫 */
.badge-status-S4 { background: var(--color-warning); color: #fff; border-radius: var(--badge-radius); padding: var(--badge-pad-y) var(--badge-pad-x); display: inline-block; font-weight: var(--badge-font-weight); }  /* 工艺中：橙 */
.badge-status-S5 { background: var(--color-info-cyan); color: #fff; border-radius: var(--badge-radius); padding: var(--badge-pad-y) var(--badge-pad-x); display: inline-block; font-weight: var(--badge-font-weight); }  /* 制作中：青 */
.badge-status-S6 { background: var(--color-success); color: #fff; border-radius: var(--badge-radius); padding: var(--badge-pad-y) var(--badge-pad-x); display: inline-block; font-weight: var(--badge-font-weight); }  /* 定型：绿 */
.badge-status-S7 { background: var(--color-status-closed); color: #fff; border-radius: var(--badge-radius); padding: var(--badge-pad-y) var(--badge-pad-x); display: inline-block; font-weight: var(--badge-font-weight); }  /* 关闭：深灰 */

/* ============ 样品行状态表达（仅靠 6 步回字形流程点；整行底色已于阶段6移除） ============ */
/* 阶段6：已移除「整行底色 + 整行文字色」（tr.sample-row-done / -progress）。
   理由：状态徽章 + 6 步流程点已完整表达状态，整行底色属第三重冗余编码，
   且把行内文字对比度从 11.4:1 压到 5.88:1。JS 仍会给行加类，无 CSS 匹配即无效，故 JS 零改动。 */

/* ============ 状态列流程推进条（7 环节箭头推进） ============ */
.status-steps { display: inline-flex; align-items: center; white-space: nowrap; }
.status-steps .st-node { display: inline-flex; align-items: center; gap: 4px; }
.status-steps .st-dot {
  width: 16px; height: 16px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 11px; line-height: 1; flex: none;
}
.status-steps .st-label { font-size: 12px; }
.status-steps .st-arrow { width: 16px; height: 1px; flex: none; }

.status-steps .st-done .st-dot { background: #52c41a; color: #fff; }
.status-steps .st-done .st-label { color: #389e0d; }

.status-steps .st-current .st-dot {
  background: #fff; border: 2px solid #2563eb;
  box-sizing: border-box;
}
.status-steps .st-current .st-label { color: #2563eb; font-weight: 500; }
/* 完成且当前：绿底 + 蓝框 */
.status-steps .st-done.st-current .st-dot {
  background: #52c41a; border-color: #2563eb; color: #fff;
}
.status-steps .st-done.st-current .st-label { color: #2563eb; font-weight: 500; }

.status-steps .st-future .st-dot { background: #f0f0f0; border: 1px solid #d9d9d9; box-sizing: border-box; }
.status-steps .st-future .st-label { color: #b0b0b0; }

.status-steps .st-arrow.st-line { background: #e0e0e0; }
.status-steps .st-arrow.st-line-done { background: #52c41a; }

/* ---- 回字形两行布局：上排 4 步横排（行尾下折 ─┐），下排 3 步右对齐回折 ---- */
.status-steps.status-flow {
  display: inline-flex; flex-direction: column; gap: 2px;
  align-items: stretch;   /* 覆盖旧规则 center：两行拉伸同宽，下排 flex-end 才能右对齐 */
}
.status-flow .sf-row { display: flex; align-items: center; white-space: nowrap; }
.status-flow .sf-row-bottom { justify-content: flex-end; }
.status-flow .sf-turn {
  width: 10px; height: 17px; flex: none; box-sizing: border-box;
  border-top: 1px solid #e0e0e0; border-right: 1px solid #e0e0e0;
  align-self: flex-start; margin-top: 7px;
}
.status-flow .sf-turn.st-line-done { border-top-color: #52c41a; border-right-color: #52c41a; }
.status-flow .sf-turn-pad { width: 10px; height: 1px; flex: none; }

/* 样品名称列保底宽度：状态列改回字形收窄后，保证名称列拿到足够可读宽度 */
.fixed-th[data-fix="sample_name"] { min-width: 180px; }

/* ---- 负责人列：各环节负责人横排流式展示（环节名 + 人名，2 行内排完，保证一屏 ≥10 行） ---- */
.owner-steps { display: flex; flex-direction: row; flex-wrap: wrap; gap: 1px 14px; }
.owner-line { display: inline-flex; align-items: center; gap: 4px; white-space: nowrap;
              font-size: 11.5px; line-height: 1.4; }
.owner-stage { color: #8c8c8c; flex: none; }
.owner-name { color: #333; }
.fixed-th[data-fix="owner"] { min-width: 300px; }

/* ---- 状态列回字形紧凑化（配合列表密度：点 13px / 字 11px / 折线缩小） ---- */
.status-steps .st-dot { width: 13px; height: 13px; font-size: 10px; }
.status-steps .st-label { font-size: 11px; }
.status-steps .st-arrow { width: 12px; }
.status-steps.status-flow { gap: 1px; }
.status-flow .sf-turn { width: 8px; height: 13px; margin-top: 5px; }
.status-flow .sf-turn-pad { width: 8px; }

/* ============ 样品列表（行距加大 1/3、字体放大，缓解阅读费劲） ============ */
#sample-table { font-size: 14px; }
#sample-table th { padding: .53rem .5rem; font-size: 13px; }
#sample-table td { padding: .3rem .5rem; line-height: 1.4; }
#sample-table .btn-sm { padding: .16rem .5rem; font-size: 12.5px; }

/* 产品项目台账：完全沿用样品台账表格样式（冻结窗格/列头吸顶/排序交互一致） */
#project-table { font-size: 14px; }
#project-table th { padding: .53rem .5rem; font-size: 13px; white-space: nowrap; }
#project-table td { padding: .3rem .5rem; line-height: 1.4; }
#project-table .th-title { cursor: pointer; user-select: none; }
#project-table .sort-arrow { font-size: 11px; margin-left: 2px; }

/* ============ 全局弹窗拖拽缩放（common.js 自动注入，md- 前缀；八方向：四边 + 四角） ============ */
/* min-height:0 覆盖 .modal-dialog-centered 自带的 min-height:calc(100% - …)，
   否则带 modal-dialog-centered 的弹窗高度被钉死、顶部/底部手柄拖不动（内容由 .modal-body 滚动承接）。 */
.md-floating .modal-dialog { margin: 0 !important; min-height: 0 !important; }
.md-floating .modal-content { height: 100%; min-height: 0; display: flex; flex-direction: column; }
.md-floating .modal-body { overflow: auto; flex: 1 1 auto; min-height: 0; }
.md-resize-handle { position: absolute; z-index: 6; touch-action: none; }
.md-resize-handle::after { content: ''; position: absolute; width: 9px; height: 9px; transition: .15s; }
/* 四边：细长热区 */
.md-rz-n { top: 0; left: 0; right: 0; height: 6px; }
.md-rz-s { bottom: 0; left: 0; right: 0; height: 6px; }
.md-rz-w { top: 0; bottom: 0; left: 0; width: 6px; }
.md-rz-e { top: 0; bottom: 0; right: 0; width: 6px; }
/* 四角：略大热区 + 小三角视觉提示（互不重叠） */
.md-rz-nw { top: 0; left: 0; width: 16px; height: 20px; }
.md-rz-ne { top: 0; right: 0; width: 16px; height: 20px; }
.md-rz-sw { bottom: 0; left: 0; width: 16px; height: 20px; }
.md-rz-se { bottom: 0; right: 0; width: 16px; height: 20px; }
.md-rz-nw::after { left: 4px; top: 4px; border-left: 2px solid #c7ccd4; border-top: 2px solid #c7ccd4; border-top-left-radius: 2px; }
.md-rz-ne::after { right: 4px; top: 4px; border-right: 2px solid #c7ccd4; border-top: 2px solid #c7ccd4; border-top-right-radius: 2px; }
.md-rz-sw::after { left: 4px; bottom: 4px; border-left: 2px solid #c7ccd4; border-bottom: 2px solid #c7ccd4; border-bottom-left-radius: 2px; }
.md-rz-se::after { right: 4px; bottom: 4px; border-right: 2px solid #c7ccd4; border-bottom: 2px solid #c7ccd4; border-bottom-right-radius: 2px; }
.md-resize-handle:hover::after { border-color: #2563eb; }
/* 光标：各手柄方向在 common.js 内联设置（按拖拽方向）；拖动中全页统一为该方向光标 */
body.md-dragging, body.md-dragging * { user-select: none !important; cursor: move !important; }
body.md-resizing, body.md-resizing * { user-select: none !important; cursor: inherit !important; }

/* ============ Excel 式冻结窗格：标题+筛选区自然常驻，表格行在固定高度盒内滚动，列头吸顶 ============ */
/* 盒高 = 视口 - 顶栏56 - 标题/筛选区约128 - 底部分页约76（不足时兜底 240px） */
.table-scroll-box { max-height: calc(100vh - 260px); min-height: 240px; overflow: auto; }
/* separate + spacing 0：修复 collapse 模式下吸顶列头底边透出行内容的穿透问题 */
.table-scroll-box table { border-collapse: separate; border-spacing: 0; }
/* ★ thead 行组整体吸顶（z=5）：Chrome 对 table 内 sticky 单元格的 z-index 比较存在缺陷
   （某些版本下 sticky td 会反压吸顶 th，行内容/按钮浮到表头上）。
   thead 作为行组 sticky 时绘制层级天然高于 tbody（W3C 标准行为），从根上杜绝穿透；
   th 自身的 sticky top/right 保留作为老浏览器兜底，两者同轴不冲突。 */
.table-scroll-box thead { position: sticky; top: 0; z-index: 5; }
.table-scroll-box thead th {
  position: sticky; top: 0; z-index: 3;
  background: var(--tbl-head-bg);                 /* 显式不透明背景，防吸顶时文字穿透 */
  transform: translateZ(0);                       /* 强制提升合成层：修复 Chrome 下 tbody 行内容穿透 sticky 表头的绘制缺陷 */
  box-shadow: inset 0 -1px 0 var(--tbl-border);   /* 列头底边线，行滚动时保持分隔视觉 */
}

/* ============ 末列「操作」固定在右侧（Excel 式冻结列） ============
   背景：列多的表（8~15 列）总宽超过滚动容器可视宽 → 最右的「操作」列被推到
   水平滚动区之外，用户看不见按钮、以为「点了删除没反应」。
   用法（二选一，无需逐列加类）：
     ① 操作列就是最后一列 → <table class="... tbl-sticky-last">，走 :last-child
     ② 操作列不是最后一列（后面还有「+新建列」等尾巴列）
        → <table class="... tbl-sticky-last"> 且给该列 th/td 加 .col-op
   做法：只对「操作单元格」生效 → 任何列宽变化、增删中间列都不用改 CSS，
   也不动 JS 渲染逻辑（仅在渲染模板里补一个类名）。
   与 .table-scroll-box 配合：操作列表头 z-index 需高于吸顶列头的 3。 */
.tbl-sticky-last thead th:last-child,
.tbl-sticky-last tbody td:last-child,
.tbl-sticky-last thead th.col-op,
.tbl-sticky-last tbody td.col-op {
  position: sticky; right: 0;
  background: var(--tbl-frozen-bg);
  box-shadow: -6px 0 8px -6px rgba(20, 30, 50, .12);   /* 与滚动区分隔 */
  white-space: nowrap;
  vertical-align: middle;
}
.tbl-sticky-last thead th:last-child,
.tbl-sticky-last thead th.col-op { background: var(--tbl-head-bg); z-index: 4; }
.tbl-sticky-last tbody td:last-child,
.tbl-sticky-last tbody td.col-op { z-index: 2; }
/* hover 行跟随高亮，避免固定列在白底上"脱节" */
.tbl-sticky-last tbody tr:hover td:last-child,
.tbl-sticky-last tbody tr:hover td.col-op { background: var(--tbl-hover-bg); }

/* ============ 末列「操作」抽屉式（默认完全收起，鼠标移到表格右边缘才滑出） ============
   背景：操作列常驻右固定会占去 100~180px 常显宽度；对「信息为主、操作为辅」的台账，
   用户希望操作列**默认收起**，需要时再把鼠标移到表格右边缘把它抽出来。
   范式来源：/proc-design 技术参数页（已验证）→ 此处抽成**公用类**，各表只加类名即可复用。
   用法：<table class="... tbl-drawer-last">（操作列须是末列，或加 .col-op 标记）；
        外层再包一层 <div class="tbl-drawer-zone">（热区/把手挂它上面）；
        JS 侧调用全局函数 window.TableDrawer.init(zoneEl[, tableEl]) 初始化（见 JS 段注释）。
   ★只改 CSS 位移量 + 容器状态类，**完全不动单元格渲染逻辑与列宽**。
   ★--tbl-drawer-x：抽屉整体右移量。展开 = 0px；收起 = 操作列实测宽度（JS 写入）。
   收起时把该列沿 right 轴推出滚动容器可视区，由 .table-scroll-box 的 overflow 裁掉 → 视觉上完全不见。 */
.tbl-drawer-last { --tbl-drawer-x: 0px; }
.tbl-drawer-last thead th:last-child,
.tbl-drawer-last tbody td:last-child,
.tbl-drawer-last thead th.col-op,
.tbl-drawer-last tbody td.col-op {
  position: sticky; right: calc(-1 * var(--tbl-drawer-x));
  transition: right .18s ease;
  background: var(--tbl-frozen-bg);
  box-shadow: -6px 0 8px -6px rgba(20, 30, 50, .12);
  white-space: nowrap;
  vertical-align: middle;
}
.tbl-drawer-last thead th:last-child,
.tbl-drawer-last thead th.col-op { background: var(--tbl-head-bg); z-index: 4; }
.tbl-drawer-last tbody td:last-child,
.tbl-drawer-last tbody td.col-op { z-index: 2; }
.tbl-drawer-last tbody tr:hover td:last-child,
.tbl-drawer-last tbody tr:hover td.col-op { background: var(--tbl-hover-bg); }

/* 抽屉热区 + 常驻把手（贴表格右边缘、垂直居中、竖排三小圆点）：
   热区/把手本身 pointer-events:none，不挡单元格里的按钮点击；触发判定由 JS 在
   共同外层容器上监听 mousemove（指针进入右边缘 20px 内即展开）。 */
.tbl-drawer-zone { position: relative; }
.tbl-drawer-hot { position: absolute; right: 0; top: 0; bottom: 0; width: 20px;
                  pointer-events: none; z-index: 5; }
.tbl-drawer-handle { position: absolute; right: 0; top: 50%; transform: translateY(-50%);
                     display: flex; flex-direction: column; align-items: center; justify-content: center;
                     gap: 3px; width: 8px; padding: 9px 0; border-radius: 5px 0 0 5px;
                     background: #e9eef6; border: 1px solid #dbe3ee; border-right: 0;
                     box-shadow: -2px 0 5px -2px rgba(20, 30, 50, .14);
                     transition: background .18s ease, opacity .18s ease; }
.tbl-drawer-handle i { display: block; width: 3px; height: 3px; border-radius: 50%;
                       background: #8a95a5; }
.tbl-drawer-zone.is-open .tbl-drawer-handle { opacity: 0; }

/* 表格不溢出（总宽 <= 容器可视宽）时：横向没有滚动，操作列无需 sticky 固定，
   否则会「半露」在右缘（sticky 贴住但无滚动空间）→ 降级为普通流式列。
   由 JS 检测 scrollWidth <= clientWidth 时给容器加 .drawer-static。 */
.tbl-drawer-zone.drawer-static .tbl-drawer-last thead th:last-child,
.tbl-drawer-zone.drawer-static .tbl-drawer-last tbody td:last-child,
.tbl-drawer-zone.drawer-static .tbl-drawer-last thead th.col-op,
.tbl-drawer-zone.drawer-static .tbl-drawer-last tbody td.col-op {
  position: static; right: auto; transition: none;
}
/* 该情形下拖动条/把手无意义，一并隐藏 */
.tbl-drawer-zone.drawer-static .tbl-drawer-hot { display: none; }

/* ============ 强制抽屉（.tbl-drawer-force）：表格不溢出也收起操作列 ============
   常规抽屉靠 sticky 负偏移把操作列推出可视区——依赖横向滚动空间；
   不溢出的表没有滚动空间，right 负偏移推不动（sticky 受包含块限制）→ 仍会常显。
   故 force 表收起态改用 display 整列隐藏（腾出宽度），展开态走原有 sticky 贴右缘机制。
   由 JS 侧 syncOverflow 对带此类的容器恒判溢出、不降级 drawer-static 配合。 */
.tbl-drawer-force:not(.is-open) .tbl-drawer-last thead th:last-child,
.tbl-drawer-force:not(.is-open) .tbl-drawer-last tbody td:last-child,
.tbl-drawer-force:not(.is-open) .tbl-drawer-last thead th.col-op,
.tbl-drawer-force:not(.is-open) .tbl-drawer-last tbody td.col-op { display: none; }

/* ============ 用户状态徽章 ============ */
.badge-enabled  { background: var(--color-success); color: #fff; font-weight: var(--badge-font-weight); border-radius: var(--badge-radius); padding: var(--badge-pad-y) var(--badge-pad-x); display: inline-block; }
.badge-disabled { background: #adb5bd; color: #fff; font-weight: var(--badge-font-weight); border-radius: var(--badge-radius); padding: var(--badge-pad-y) var(--badge-pad-x); display: inline-block; }

/* 已停用用户：整行灰显，一眼分辨；操作列保持清晰，便于直接点「启用」 */
tr.user-row-off > td { opacity: .45; }
tr.user-row-off > td:last-child { opacity: 1; }

/* ============ 7 态横向步骤条（样品详情页） ============ */
.flow-steps { display: flex; width: 100%; }
.flow-steps .flow-step {
  flex: 1;
  text-align: center;
  position: relative;
  padding-top: 4px;
  min-width: 0;
}
.flow-steps .flow-step::before {
  content: '';
  position: absolute;
  top: 14px;
  left: -50%;
  width: 100%;
  height: 2px;
  background: #dee2e6;
  z-index: 0;
}
.flow-steps .flow-step:first-child::before { display: none; }
.flow-steps .flow-step.done::before { background: #389e0d; }
.flow-steps .flow-step.current::before { background: #fa8c16; }
.flow-steps .step-dot {
  position: relative;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: #fff;
  border: 2px solid #ced4da;
  color: #8a939b;
  font-size: 13px;
  font-weight: 600;
}
.flow-steps .flow-step.done .step-dot {
  border-color: #389e0d;
  background: #389e0d;
  color: #fff;
}
.flow-steps .flow-step.current .step-dot {
  border-color: #fa8c16;
  color: #fa8c16;
  box-shadow: 0 0 0 3px rgba(250, 140, 22, .18);
}
/* 完成且当前：绿底 + 橙框 */
.flow-steps .flow-step.done.current .step-dot {
  border-color: #fa8c16;
  background: #389e0d;
  color: #fff;
  box-shadow: 0 0 0 3px rgba(250, 140, 22, .18);
}
.flow-steps .step-name { font-size: 12.5px; margin-top: 4px; color: #666; }
.flow-steps .flow-step.done .step-name { color: #389e0d; }
.flow-steps .flow-step.current .step-name { color: #fa8c16; font-weight: 600; }
.flow-steps .step-meta { font-size: 11.5px; color: #999; }

/* ============ 样品列表：自定义列模式 ============ */
.custom-th, .fixed-th { cursor: grab; user-select: none; white-space: nowrap; position: relative; }
.custom-th:active, .fixed-th:active { cursor: grabbing; }
.custom-th.dragging, .fixed-th.dragging { opacity: .5; }
.custom-th.drag-over, .fixed-th.drag-over { background: #e6f0ff; outline: 2px dashed #2563eb; }
.th-title { margin-right: 6px; cursor: pointer; user-select: none; }
.th-title:hover { color: var(--color-primary); }
.sort-ind { font-size: 10px; margin-left: 2px; color: var(--color-primary); }
.sort-ind.sort-idle { color: #b8c2cf; }

/* 整行拖动手动排序（企微多维表同款：左侧手柄 + 蓝线落点） */
.th-handle { width: 34px; min-width: 34px; }
.td-handle { width: 34px; min-width: 34px; padding: 0; text-align: center; }
.row-handle { cursor: grab; color: #adb5bd; opacity: 0; user-select: none; }
tr:hover .row-handle { opacity: 1; }
.row-handle.disabled { opacity: .25; cursor: not-allowed; }
tr.row-dragging { opacity: .4; }
tr.drop-before td { border-top: 2px solid var(--color-primary); }
tr.drop-after td { border-bottom: 2px solid var(--color-primary); }
.th-drag {
  color: #c0c6cd;
  font-size: 13px;
  line-height: 1;
  cursor: grab;
  margin-left: 2px;
  vertical-align: -1px;
  user-select: none;
}
.th-drag:active { cursor: grabbing; }
.th-menu {
  cursor: pointer;
  color: #a0a8b2;
  font-size: 11px;
  padding: 0 4px;
  border-radius: 3px;
  line-height: 1;
}
.th-menu:hover { color: #2563eb; background: #eef3fb; }
.th-add { text-align: center; }
.btn-add-field {
  border: none;
  background: transparent;
  color: #9aa3ac;
  font-size: 18px;
  line-height: 1;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  cursor: pointer;
}
.btn-add-field:hover { background: #eef1f4; color: #555; }

/* 表格底部通栏「新增一行」虚线按钮（企微智能表格加行样式） */
.btn-add-row {
  display: block;
  width: 100%;
  padding: 9px 0;
  border: 1px dashed #c5cdd6;
  background: transparent;
  color: #6b7684;
  font-size: 13.5px;
  border-radius: 6px;
  cursor: pointer;
  transition: all .15s;
}
.btn-add-row:hover {
  border-color: #2563eb;
  color: #2563eb;
  background: #f5f9ff;
}

/* 行内新增行（企微智能表格式） */
.inline-new-row td { vertical-align: middle; }
.inline-new-row .form-control-sm,
.inline-new-row .form-select-sm { min-width: 90px; }
.inline-new-row .btn-inline-save { min-width: 52px; }

/* 列头下拉菜单 */
.field-menu {
  background: #fff;
  border: 1px solid #e5e7eb;
  border-radius: 6px;
  box-shadow: 0 4px 14px rgba(0, 0, 0, .12);
  padding: 4px 0;
  min-width: 120px;
  z-index: 2200;
}
.field-menu .fm-item {
  padding: 8px 16px;
  font-size: 13.5px;
  cursor: pointer;
  white-space: nowrap;
}
.field-menu .fm-item:hover { background: #f2f4f7; }
.field-menu .fm-danger { color: #cf1322; }
.field-menu .fm-danger:hover { background: #fff1f0; }

/* ---------- 配置中心：目录选择器条目 ---------- */
.dir-item { cursor: pointer; user-select: none; }
.dir-item:hover { background: #e6f4ff; }

/* ---------- 制造应用工具：工具箱卡片 ---------- */
.tool-card {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  padding: 20px 22px;
  min-height: 180px;
  text-decoration: none;
  color: inherit;
  transition: transform .15s ease, box-shadow .15s ease;
}
.tool-card:hover {
  transform: translateY(-3px);
  box-shadow: 0 10px 24px rgba(0, 0, 0, .10);
  text-decoration: none;
  color: inherit;
}
/* 文字图标（1~2 个汉字/字母），默认 func-icon 为 44px 圆角方块 */
.tool-badge {
  font-size: 22px;
  font-weight: 600;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
}
/* 打开提示 */
.tool-open {
  margin-top: auto;
  font-size: 13px;
  color: #2563eb;
  font-weight: 500;
}
/* 筹备中角标 */
.tool-tag {
  margin-top: auto;
  display: inline-block;
  padding: 3px 10px;
  font-size: 12px;
  line-height: 1;
  color: #8c8c8c;
  background: #f0f0f0;
  border-radius: 999px;
  white-space: nowrap;
}
/* 更多工具占位卡 */
.tool-soon {
  cursor: default;
  border-style: dashed;
  background: #fafafa;
}
.tool-soon .tool-badge,
.tool-soon .func-title,
.tool-soon .func-desc { color: #bfbfbf; }

/* ============ 样品详情页：一行信息卡 + 负责人嵌流程 + 卡位式文件区 ============ */
.info-row { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.info-no { font-size: 20px; font-weight: 800; letter-spacing: .3px; }
.info-name { font-size: 15.5px; font-weight: 700; }
.info-meta { margin-left: auto; display: flex; gap: 20px; flex-wrap: wrap; font-size: 12.5px; color: #5b636d; }
.info-meta b { color: #25292e; font-weight: 600; margin-left: 2px; }

/* 步骤条：负责人下拉嵌环节下方 */
.flow-steps .step-owner { margin-top: 5px; }
.flow-steps .owner-sel { width: 104px; height: 26px; font-size: 12px; color: #25292e;
  border: 1px solid #d7dbe2; border-radius: 6px; background: #fff; padding: 0 4px; }
.flow-steps .owner-sel:focus { outline: none; border-color: #2563eb; }
.flow-steps .owner-name { font-size: 12px; color: #4a5568; background: #f4f6f9;
  border-radius: 6px; padding: 2px 10px; white-space: nowrap; }

/* 环节文件：卡位式 */
.folder-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; }
@media (max-width: 1200px) { .folder-grid { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 900px) { .folder-grid { grid-template-columns: repeat(2, 1fr); } }
.fcard { border: 1px solid #e8ebf0; border-radius: 8px; background: #fff; overflow: hidden;
  display: flex; flex-direction: column; }
.fcard:hover { box-shadow: 0 3px 8px rgba(16,24,40,.09); }
.fcard-hd { padding: 7px 10px; border-bottom: 1px solid #f0f2f5;
  display: flex; align-items: center; gap: 5px; flex-wrap: wrap; }
.fcard-hd .fname { font-weight: 700; font-size: 12.5px; }
.chip-stage { font-size: 10px; background: #eef4ff; color: #2563eb; border-radius: var(--badge-radius); padding: 0 5px; line-height: 16px; }
.chip-state { font-size: 10px; border-radius: var(--badge-radius); padding: 0 6px; margin-left: auto; font-weight: 600; line-height: 16px; white-space: nowrap; }
.st-ok  { background: #e6f7ee; color: #157347; }
.st-has { background: #e8f1fe; color: #1a5fbd; }
.st-none{ background: #f0f2f5; color: #8b9099; }
.fcard-bd { padding: 5px 10px; flex: 1; }
.fitem { display: flex; align-items: center; gap: 5px; padding: 4px 0;
  border-bottom: 1px dashed #f0f2f5; font-size: 12px; }
.fitem:last-child { border-bottom: 0; }
.fitem .fico { color: #2563eb; flex: none; font-size: 12px; }
.fitem .fn { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  color: #25292e; text-decoration: none; }
.fitem .fn:hover { color: #2563eb; text-decoration: underline; }
.fitem .fv { color: #9aa0a8; font-size: 11px; flex: none; }
.fitem .foff { color: #d48806; font-size: 10px; flex: none; background: #fff7e8;
  border-radius: 3px; padding: 0 4px; }
.fitem .fic { flex: none; display: flex; gap: 3px; }
.icobtn { width: 20px; height: 20px; border-radius: 5px; border: 1px solid #e3e6eb; background: #fff;
  display: inline-flex; align-items: center; justify-content: center; cursor: pointer;
  color: #5b636d; font-size: 11px; text-decoration: none; line-height: 1; }
.icobtn:hover { border-color: #2563eb; color: #2563eb; }
.fempty { color: #b9bfc7; font-size: 11.5px; text-align: center; padding: 10px 0 8px; }
/* 文件卡状态色（依据：绿=齐全 / 橙黄=缺料提醒，配文字不只靠颜色） */
.fcard-ok { background: #f4fbf6; border-color: #a8dcbe; border-left: 4px solid #52c41a; }
.fcard-miss { background: #fffaef; border-color: #ffd77a; border-left: 4px solid #faad14; }
.fcard-miss .fcard-hd { border-bottom-color: #ffedb8; }
.fcard-miss .fempty { color: #d48806; font-weight: 600; }
.chip-state.st-miss { background: #ffeccb; color: #d48806; }
.fcard-ft { padding: 5px 10px; border-top: 1px solid #f0f2f5; background: #fafbfc;
  display: flex; align-items: center; gap: 6px; }
.up-btn { flex: 1; border: 1px dashed #c9d4e3; background: transparent; color: #2563eb;
  font-size: 12px; font-weight: 600; padding: 4px; border-radius: 6px; cursor: pointer; }
.up-btn:hover { border-color: #2563eb; background: #f0f6ff; }
.major-lbl { font-size: 11px; color: #8b9099; display: inline-flex; align-items: center;
  gap: 3px; white-space: nowrap; cursor: pointer; }
.major-lbl input { margin: 0; }

/* 项目立项需求同步区（样品「需求文档」卡片内，单向只读） */
.proj-demand { background: #f5f8ff; border: 1px solid #d8e4fb; border-radius: 6px; padding: 6px 8px; margin-bottom: 6px; }
.proj-demand-hd { font-size: 11px; font-weight: 600; color: #2563eb; margin-bottom: 4px; }
.proj-demand-desc { font-size: 12px; color: #30363f; margin-bottom: 5px; white-space: pre-wrap; word-break: break-word; }
.proj-demand-files { display: flex; flex-direction: column; gap: 3px; }
.proj-demand-file { display: flex; align-items: center; gap: 6px; font-size: 11.5px; flex-wrap: wrap; }
.proj-demand-file .fname { color: #2563eb; text-decoration: none; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.proj-demand-file .fname:hover { text-decoration: underline; }
.proj-demand-file .fnote { color: #5b636d; }
.proj-demand-file .ftime { color: #9aa0a8; font-size: 10.5px; margin-left: auto; }

/* 流转记录：时间线（折叠） */
.tline { position: relative; padding-left: 16px; }
.tline::before { content: ''; position: absolute; left: 4px; top: 5px; bottom: 5px; width: 2px; background: #e8ebf0; }
.titem { position: relative; padding: 0 0 9px 12px; font-size: 12.5px; }
.titem::before { content: ''; position: absolute; left: -2px; top: 5px; width: 9px; height: 9px;
  border-radius: 50%; background: #2563eb; border: 2px solid #fff; box-shadow: 0 0 0 1px #d7dbe2; }
.titem .tmeta { color: #9aa0a8; font-size: 11.5px; margin-left: 6px; }
.tline-reason { color: #9aa0a8; font-size: 11.5px; margin-top: 1px; }

/* ============ 样品统计看板 ============ */
.dash-card { background: #f7f9fb; border: 1px solid #eef1f5; border-radius: 8px; padding: 14px 16px; }
.dash-label { font-size: 13px; color: #6b7280; }
.dash-num { font-size: 26px; font-weight: 500; line-height: 1.2; margin-top: 6px; color: #1f2937; }
.dash-num.dash-blue   { color: #2563eb; }
.dash-num.dash-green  { color: #389e0d; }
.dash-num.dash-orange { color: #d48806; }
.dash-num.dash-red    { color: #cf1322; }
.dash-title { font-size: 14px; font-weight: 500; margin-bottom: 12px; }
.dash-chart { width: 100%; height: 280px; }
.dash-note { font-size: 10px; color: #9aa3ad; line-height: 1.3; margin-top: 4px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* ---- 自由布局画布（CSS Grid 12 列；行高/间距与 JS 中 COLS/CELL_H/GAP 保持同步） ---- */
.dash-canvas { display: grid; grid-template-columns: repeat(12, 1fr);
  grid-auto-rows: 108px; gap: 12px; position: relative; }
.dash-canvas.grid-on {
  background-image:
    linear-gradient(to right, rgba(22,119,255,.16) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(22,119,255,.16) 1px, transparent 1px);
  background-size: calc((100% + 12px) / 12) 100%, 100% 120px;
}
.dash-item { position: relative; min-width: 0; min-height: 0; user-select: none; cursor: grab; }
.dash-item:active { cursor: grabbing; }
.dash-item > .dash-card { height: 100%; }
.dash-item > .card { height: 100%; display: flex; flex-direction: column; }
.dash-item > .card > .card-body { flex: 1 1 auto; display: flex; flex-direction: column; min-height: 0; }
.dash-item .dash-title { flex: 0 0 auto; }
.dash-item .dash-chart { flex: 1 1 auto; width: 100%; height: auto; min-height: 120px; }
.dash-item.dash-moving { opacity: .45; z-index: 2; box-shadow: 0 8px 24px rgba(0,0,0,.18); }

/* 缩放手柄（右下角 ⌟） */
.dash-resize { position: absolute; right: 3px; bottom: 3px; width: 14px; height: 14px;
  color: #2563eb; cursor: nwse-resize; opacity: .45; z-index: 3; }
.dash-resize:hover { opacity: 1; }

/* 对齐参考线（绝对定位，贯穿画布） */
.dash-guides { position: absolute; inset: 0; pointer-events: none; z-index: 5; }
.dash-guide-v { position: absolute; top: 0; bottom: 0; width: 1px; background: #2563eb; }
.dash-guide-h { position: absolute; left: 0; right: 0; height: 1px; background: #2563eb; }

/* ============================================================
   阶段2：按钮三色收敛
   目标：一屏内按钮最多出现 蓝(操作) / 灰(次要) / 红(危险) 三色。
   做法：把 info / warning / success 三个彩色族的实心与描边按钮统一降为中性灰，
        保留 primary / outline-primary / secondary / danger / outline-danger。
   说明：纯 CSS 覆盖 Bootstrap 变体类，JS 与模板零改动。
   ============================================================ */

/* 次要描边按钮：info / warning / success → 中性描边 */
.btn-outline-info,
.btn-outline-warning,
.btn-outline-success {
  color: var(--color-text-secondary);
  border-color: #d0d5dd;
  background-color: transparent;
}
.btn-outline-info:hover,
.btn-outline-warning:hover,
.btn-outline-success:hover,
.btn-outline-info:focus,
.btn-outline-warning:focus,
.btn-outline-success:focus,
.btn-outline-info:active,
.btn-outline-warning:active,
.btn-outline-success:active,
.btn-outline-info.active,
.btn-outline-warning.active,
.btn-outline-success.active {
  color: var(--color-text-strong);
  background-color: #f2f4f7;
  border-color: #b9c0ca;
}
.btn-outline-info:focus-visible,
.btn-outline-warning:focus-visible,
.btn-outline-success:focus-visible {
  box-shadow: 0 0 0 .2rem rgba(37, 41, 46, .12);
}

/* 实心次要按钮：info / warning / success → 中性实心灰 */
.btn-info,
.btn-warning,
.btn-success {
  color: #fff;
  background-color: #6b7280;
  border-color: #6b7280;
}
.btn-info:hover,
.btn-warning:hover,
.btn-success:hover,
.btn-info:focus,
.btn-warning:focus,
.btn-success:focus,
.btn-info:active,
.btn-warning:active,
.btn-success:active,
.btn-info.active,
.btn-warning.active,
.btn-success.active {
  color: #fff;
  background-color: #5b6270;
  border-color: #5b6270;
}
.btn-info:focus-visible,
.btn-warning:focus-visible,
.btn-success:focus-visible {
  box-shadow: 0 0 0 .2rem rgba(107, 114, 128, .3);
}

/* 危险按钮统一到 token 红 */
.btn-outline-danger {
  color: var(--color-danger);
  border-color: #f0b7bc;
}
.btn-outline-danger:hover,
.btn-outline-danger:focus,
.btn-outline-danger:active,
.btn-outline-danger.active {
  color: #fff;
  background-color: var(--color-danger);
  border-color: var(--color-danger);
}
.btn-danger {
  background-color: var(--color-danger);
  border-color: var(--color-danger);
}
.btn-danger:hover,
.btn-danger:focus,
.btn-danger:active,
.btn-danger.active {
  background-color: #a50f1c;
  border-color: #a50f1c;
}

/* disabled 态也纳入三色制：禁用按钮不带任何语义色，一律中性 */
.btn-outline-info:disabled,
.btn-outline-warning:disabled,
.btn-outline-success:disabled,
.btn-outline-info.disabled,
.btn-outline-warning.disabled,
.btn-outline-success.disabled {
  color: var(--color-text-secondary);
  border-color: #d0d5dd;
  background-color: transparent;
}
.btn-info:disabled,
.btn-warning:disabled,
.btn-success:disabled,
.btn-info.disabled,
.btn-warning.disabled,
.btn-success.disabled {
  color: #fff;
  background-color: #9ca3af;
  border-color: #9ca3af;
}

/* ============ 顶栏站内通知（P1） ============ */
.topbar-bell { position: relative; }
.bell-badge {
  position: absolute;
  top: -7px;
  right: -9px;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  border-radius: 999px;
  background: var(--color-danger);
  color: #fff;
  font-size: 10px;
  line-height: 16px;
  text-align: center;
  font-weight: 600;
  box-shadow: 0 0 0 2px var(--topbar-bg);
}

/* 通知下拉面板（fixed 定位，铃铛下方） */
.notify-panel {
  position: fixed;
  top: 62px;
  right: 16px;
  width: 340px;
  max-width: calc(100vw - 24px);
  max-height: 480px;
  background: #fff;
  border: 1px solid #e5e7eb;
  border-radius: 10px;
  box-shadow: 0 10px 30px rgba(16, 24, 40, .16);
  z-index: 2000;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.notify-panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 14px;
  border-bottom: 1px solid #f0f2f5;
  font-weight: 600;
  font-size: 14px;
  color: #1f2937;
}
.notify-panel-body { overflow-y: auto; flex: 1 1 auto; }
.notify-item {
  display: block;
  padding: 10px 14px;
  border-bottom: 1px solid #f5f6f8;
  color: inherit;
  text-decoration: none;
  cursor: pointer;
}
.notify-item:hover { background: #f6f9ff; }
.notify-item:last-child { border-bottom: 0; }
.notify-item.unread { background: #f0f7ff; }
.notify-item .nt-title { font-size: 13px; color: #1f2937; margin-bottom: 2px; }
.notify-item.unread .nt-title { font-weight: 600; }
.notify-item .nt-body { font-size: 12px; color: var(--color-text-muted); }
.notify-item .nt-time { font-size: 11px; color: #b0b6bf; margin-top: 2px; }
.notify-panel-foot {
  padding: 8px 14px;
  border-top: 1px solid #f0f2f5;
  text-align: center;
}
.notify-empty { padding: 28px 14px; text-align: center; color: var(--color-text-muted); font-size: 13px; }


/* ============ 通用列宽拖拽（共享能力，window.ColResize 配套样式） ============ */
.wh-colresize th { position: relative; }
.wh-colresize th .colresize-handle { position: absolute; top: 0; right: 0; bottom: 0; width: 8px; cursor: col-resize; z-index: 6; user-select: none; touch-action: none; }
.wh-colresize th .colresize-handle::after { content: ''; position: absolute; top: 0; right: 3px; bottom: 0; width: 2px; background: transparent; transition: background .15s ease; }
.wh-colresize th:hover .colresize-handle::after { background: #1677ff; }
.wh-colresize th .colresize-handle:active::after { background: #0958d9; }
body.wh-col-resizing, body.wh-col-resizing * { user-select: none !important; cursor: col-resize !important; }

/* ============ 可搜索下拉（SearchSelect 通用组件配套样式） ============ */
.ss-wrap { position: relative; display: inline-block; }
.ss-wrap > select.ss-hidden { display: none; }
.ss-box { display: flex; align-items: center; gap: 2px; height: 26px; padding: 0 6px;
  border: 1px solid #d7dbe2; border-radius: 6px; background: #fff; cursor: pointer; box-sizing: border-box; }
.ss-box:hover { border-color: #2563eb; }
.ss-wrap.ss-open .ss-box { border-color: #2563eb; }
.ss-val { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px; color: #25292e; }
.ss-input { flex: 1; min-width: 0; border: none; outline: none; background: transparent; font-size: 12px; color: #25292e; padding: 0; display: none; }
.ss-wrap.ss-open .ss-input { display: block; }
.ss-wrap.ss-open .ss-val { display: none; }
.ss-caret { color: #6c757d; font-size: 10px; line-height: 1; flex: none; }
.ss-list { position: absolute; top: 100%; left: 0; z-index: 1200; min-width: 160px;
  max-height: 240px; overflow: auto; background: #fff; border: 1px solid #dee2e6; border-radius: 6px;
  box-shadow: 0 6px 16px rgba(0, 0, 0, .12); margin-top: 3px; padding: 4px 0; display: none; }
.ss-wrap.ss-open .ss-list { display: block; }
.ss-opt { padding: 6px 12px; font-size: 13px; cursor: pointer; white-space: nowrap; }
.ss-opt:hover { background: #eaf1ff; }
.ss-opt.ss-sel { color: #2563eb; font-weight: 500; }
.ss-empty { padding: 8px 12px; font-size: 12px; color: #98a1ab; }
/* 样品流程步骤条里的负责人下拉保持紧凑宽度 */
.flow-steps .ss-wrap { width: 104px; }
.flow-steps .ss-box { width: 100%; }
