/* ============================================================
   考勤统计系统 — 视觉设计系统 v4
   风格：蓝色主色 + 冷调中性色 + 琥珀强调 + 统一字体 + 规范间距
   ============================================================ */

:root {
  /* 冷调中性灰（文字/边框，轻微蓝灰更显专业） */
  --ink-50: #f7f8fa;
  --ink-100: #f1f2f5;
  --ink-150: #e3e5ea;
  --ink-200: #cfd2d9;
  --ink-300: #9fa4ad;
  --ink-400: #6f7681;
  --ink-500: #525a66;
  --ink-600: #3d444f;
  --ink-700: #2a303a;
  --ink-800: #1a1f27;
  --ink-900: #0d1117;

  /* 蓝色主色（主题蓝 rgb(0, 113, 227)，Apple 蓝） */
  --accent-50: #eaf4ff;
  --accent-100: #d5e9ff;
  --accent-200: #bfdcff;
  --accent-300: #7ab8f5;
  --accent-500: #0071e3;
  --accent-600: #0066cc;
  --accent-700: #005bb8;
  --accent-glow: 0, 113, 227;

  /* 琥珀强调色（比旧亮黄更柔和专业） */
  --yellow-50: #fffbeb;
  --yellow-100: #fef0c9;
  --yellow-200: #fce3a1;
  --yellow-300: #f6cd6e;
  --yellow-400: #eeb92f;
  --yellow-500: #d99316;
  --yellow-glow: 238, 185, 47;
  /* 旧 peach 别名 → 黄色（兼容旧引用） */
  --peach-300: var(--yellow-300);
  --peach-400: var(--yellow-400);
  --peach-500: var(--yellow-500);
  --peach-glow: var(--yellow-glow);

  /* 状态色 */
  --success: #16a34a;
  --success-glow: 22, 163, 74;
  --warning: #d97706;
  --warning-glow: 245, 166, 35;
  --danger: #dc2626;
  --danger-glow: 220, 38, 38;
  --info: #0071e3;
  --info-glow: 0, 113, 227;

  /* 表面（浅灰底 + 白色卡片/表单） */
  --bg-canvas: #eef1f6;
  --bg-paper: #ffffff;
  --bg-paper-2: #f5f6f9;
  --bg-tinted: #f8f9fc;

  /* 边框 */
  --border-subtle: rgba(100, 116, 139, 0.12);
  --border-default: rgba(100, 116, 139, 0.22);
  --border-strong: rgba(71, 85, 105, 0.34);
  /* 考勤数据表格边框（用户要求统一为 #aaaaaa） */
  --border-table: #aaaaaa;
  /* 深色模式适配变量（20260928n 补丁）：浅色值与原硬编码一致，深色块内重定义 */
  --bg-hover: #e8ebf1;        /* 菜单项 hover / 默认灰格（比面板底深一档的灰蓝） */
  --bg-panel: #f5f6f9;        /* 侧栏 / 顶栏面板底 */
  --bg-panel-2: #f7f8fa;      /* 更浅面板底 */
  --border-hairline: #cccccc; /* 表格单元格细线（grid-full #cccccc） */
  --border-line: #dddddd;     /* 标题描边线等分隔线 */
  --danger-line: #fca5a5;     /* 删除按钮浅红边（--bg-card/--danger-soft 复用既有别名，见下方「兼容旧组件别名」） */

  /* 阴影 */
  --shadow-xs: 0 1px 2px rgba(15,15,15,0.05);
  --shadow-sm: 0 2px 4px rgba(15,15,15,0.05), 0 1px 2px rgba(15,15,15,0.05);
  --shadow-md: 0 4px 12px rgba(15,15,15,0.08), 0 1px 3px rgba(15,15,15,0.05);
  --shadow-lg: 0 12px 32px rgba(15,15,15,0.10), 0 4px 8px rgba(15,15,15,0.06);

  /* 圆角 */
  --radius-sm: 6px;
  --radius-md: 8px;
  --radius-lg: 14px;
  --radius-xl: 20px;

  /* 间距（4px 基准，规范统一） */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 20px;
  --space-6: 24px;
  --space-8: 32px;

  /* 字体（苹果中国官网字体栈；数字等宽对齐） */
  --font-sans: "SF Pro SC", "SF Pro Display", "SF Pro Icons", "PingFang SC", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --font-serif: var(--font-sans);
  --font-mono: "SF Mono", "Cascadia Code", Consolas, monospace;

  --ease-out-quart: cubic-bezier(0.25, 1, 0.5, 1);

  /* 兼容旧组件别名（内部仍在使用） */
  --brand: var(--accent-500);
  --brand-soft: var(--accent-50);
  --brand-hover: var(--accent-600);
  --brand-softer: #f7faff;
  --brand-line: var(--accent-100);
  --text-1: var(--ink-700);
  --text-2: var(--ink-500);
  --text-3: var(--ink-400);
  --text-4: var(--ink-300);
  --bg-page: var(--bg-canvas);
  --bg-card: var(--bg-paper);
  --bg-soft: var(--ink-100);
  --border-soft: var(--border-subtle);
  --border: var(--border-default);
  --border-dark: var(--border-strong);
  --success-soft: #e9f7ef;
  --warning-soft: #fdf6e3;
  --danger-soft: #fdecec;
  --info-soft: #eaf1fe;

  /* 20260928o：旧组件 fallback 变量 --line（此前未定义，全走 #e2e8f0 fallback；
     显式定义后深色模式才有机会反转——tpl-card/tpl-thumb/fmt-remember 等描边） */
  --line: #e2e8f0;

  /* 表格（蓝灰底 + 黄色合计/节假日强调） */
  --row-a: #f8f9fc;
  --row-b: #ffffff;
  --col-name-bg: #eef1f6;
  --col-dept-bg: #f3f5f9;
  --col-metric-bg: #f1f3f8;
  --col-total-bg: #fbf5e3;
  --col-rest-bg: #eaf1fe;
  --col-holiday-bg: #fdf3d4;
}

* { box-sizing: border-box; margin: 0; padding: 0; }
html, body { height: 100%; }
body {
  font-family: var(--font-sans);
  color: var(--ink-700);
  /* 20260922a：右侧内容区改纯白（参照 macOS 系统设置）。
     原来的「浅灰画布 + 白卡」两层结构取消，直接「白底 → 内容」。
     ⚠️ --bg-canvas 这个变量本身不改（.list-item:hover / 登录页渐变仍在用），
     只把 body 这一层换成白。 */
  background: var(--bg-paper);
  font-size: 16px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
a { color: var(--accent-600); text-decoration: none; }
a:hover { color: var(--accent-700); }

/* ============================================================
   布局骨架
   ============================================================ */
.app-shell {
  display: flex; flex-direction: column;
  height: 100vh; width: 100vw;
  overflow: hidden;
}

/* 顶栏 navtop（20260923a 整块移除）：原顶栏条与其状态胶囊样式的规则一并删除，
   订阅信息改由左侧菜单左下角承载（.sb-trial / .btn-sub-blue）。 */

/* 主体 */
.main-layout {
  flex: 1; min-height: 0;
  display: flex; flex-direction: row;
}

/* ============================================================
   侧栏
   ============================================================ */
.sidebar {
  width: 216px; flex-shrink: 0;
  /* 20260922a：左侧菜单底 #f5f6f9（参照 macOS 系统设置）。
     右侧已是纯白，左右边界靠底色差异体现，故去掉分隔描边线。 */
  background: var(--bg-panel);
  border-right: none;
  display: flex; flex-direction: column;
  overflow: hidden;
}
.sidebar-brand {
  display: flex; align-items: center; gap: 10px;
  padding: 20px 20px 16px; flex-shrink: 0;
}
/* 20260922m：logo 换为横版组合图（圆形树懒 + excelin.top 已含在图内），
   不再裁圆、去掉右侧标题/域名文字，只控高度等比缩放 */
.sidebar-brand .logo {
  flex-shrink: 0; background: transparent; line-height: 0;
}
.sidebar-brand .logo img {
  height: 40px; width: auto; max-width: 100%; display: block;
}

/* logo 深浅双图（20260928r）：默认只显示浅色图，html.dark 下对调（防闪烁脚本在 head 先加 dark，无闪烁） */
.sidebar-brand .logo img.logo-dark { display: none; }
html.dark .sidebar-brand .logo img.logo-light { display: none; }
html.dark .sidebar-brand .logo img.logo-dark { display: block; }

.sidebar-nav { flex: 1; padding: 4px 14px; overflow-y: auto; }
/* 20260922d：用户要求去掉侧栏「工作台 / 洞察」两个一级分组标题，
   原分组标题的样式规则已无任何元素使用，一并删除（见 verify_20260921a.py N14）。 */
.side-item {
  display: flex; align-items: center; gap: 9px;
  /* 20261011s：图标改为 24px 圆角色块后行高 +6px，纵向内边距 8→7px 收回一部分；
     横向 12→10px（配合 gap 10→9px），把「邀请好友 + 可获积分返利」的说明小字放回一行 */
  padding: 7px 10px; border-radius: 8px;
  cursor: pointer; font-size: 15px; font-weight: 500;
  /* 20260922g：①默认态字体改黑（原 --ink-500 灰）②模块间距 2px → 4px */
  color: var(--ink-900); margin-bottom: 4px;
  user-select: none; transition: all .18s var(--ease-out-quart);
  position: relative;
}
/* 默认已是黑色，hover 只靠底色区分，不再把字色变浅。
   20260923c：hover 底色原来是 --bg-paper-2(#f5f6f9)，与侧栏底色 #f5f6f9 完全相同
   → 鼠标经过没有任何视觉反馈。改为写死 #e8ebf1（比侧栏底深一档的灰蓝）。 */
.side-item:hover { background: var(--bg-hover); color: var(--ink-900); }
/* 选中态（20260923c）：原「蓝底白字」→ 浅蓝底 + 黑字加粗（用户口径）
   20260923d：用户反馈蓝太浅 → 底色整体加深一档（accent-50 → accent-100），
   hover 选中项随之用新补的 accent-200，保证 hover 反馈仍能区分 */
.side-item.active { background: var(--accent-100); color: var(--ink-900); font-weight: 600; }
.side-item.active:hover { background: var(--accent-200); color: var(--ink-900); }
/* ============================================================================
   侧栏菜单图标（20261011s 用户口径）：借鉴 macOS 系统设置的「圆角彩色图标」
   —— 24×24 圆角方块（radius 7px）+ 纯白线性图形 + 顶部微渐变。
   （20261011u：**去掉 box-shadow 投影**，改成纯扁平色块）
   配色规则（20261011t 收紧为五色）：**只用 蓝 / 浅蓝 / 灰 / 红 / 绿**
   —— 蓝=业务主链路与工具类（考勤、历史、统计、渠道、定制、反馈、发票、后台）
   —— 浅蓝=人员/用户列表（users）、邀请好友（invite）
   —— 灰=操作日志（logs）、深灰=管理后台入口
   —— 红=仅规则设置（config）；绿=员工管理（employees）与返利订阅（subs）
   其它色相一律归到蓝，靠「蓝 vs 浅蓝」的明度差做出层次，整体更克制统一。
   ============================================================================ */
.side-item .icon {
  width: 24px; height: 24px; border-radius: 7px; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  color: #fff;
  background-color: var(--si-bg, #8e8e93);
  background-image: linear-gradient(180deg, rgba(255, 255, 255, .18), rgba(255, 255, 255, 0) 62%);
  transition: transform .18s var(--ease-out-quart);
}
/* 内嵌 SVG 声明的是 18px（旧版尺寸），在色块内统一缩到 14px 并略加粗描边 */
.side-item .icon svg { width: 14px; height: 14px; stroke-width: 2.1; }
.side-item:hover .icon { transform: scale(1.06); }

/* ---- 逐项配色（20261011t：仅 蓝 / 浅蓝 / 灰 / 红 / 绿）---- */
.side-item[data-page="attendance"] .icon,          /* 计算考勤 */
.side-item[data-page="dash"] .icon { --si-bg: #3478f6; }        /* 主入口：蓝 */
.side-item[data-page="config"] .icon { --si-bg: #ff3b30; }      /* 规则设置：红 */
.side-item[data-page="logs"] .icon { --si-bg: #8e8e93; }        /* 操作日志：灰 */
.side-item[data-page="history"] .icon,             /* 历史数据 */
.side-item[data-page="channels"] .icon { --si-bg: #3478f6; }    /* 归档 / 渠道：蓝 */
.side-item[data-page="employees"] .icon { --si-bg: #34c759; }   /* 员工管理：绿 */
.side-item[data-page="groups"] .icon { --si-bg: #3478f6; }      /* 考勤组管理：蓝（20261023g 升一级入口，用户定版改蓝） */
.side-item[data-page="users"] .icon { --si-bg: #5ac8fa; }       /* 人员 / 用户列表：浅蓝 */
.side-item[data-page="stats"] .icon,               /* 统计分析 */
.side-item[data-page="settlement"] .icon,          /* 渠道结算 */
.side-item[data-page="settle"] .icon { --si-bg: #3478f6; }      /* 统计 / 结算：蓝 */
.side-item[data-page="custom"] .icon { --si-bg: #3478f6; }      /* 我要定制：蓝 */
.side-item[data-page="feedback"] .icon { --si-bg: #3478f6; }    /* 问题反馈：蓝 */
.side-item[data-page="invoices"] .icon { --si-bg: #3478f6; }    /* 发票管理：蓝 */
.side-item[data-page="invite"] .icon { --si-bg: #5ac8fa; }      /* 邀请好友：浅蓝 */
.side-item[data-page="subs"] .icon { --si-bg: #34c759; }        /* 返利 / 订阅：绿 */
#agent-link .icon { --si-bg: #3478f6; }                         /* 渠道后台：蓝 */
#admin-link .icon { --si-bg: #6e6e73; }                         /* 管理后台：深灰 */
.side-item .badge { margin-left: auto; }
/* 20260922f：侧栏分上下两组——「统计分析」及以上为「考勤业务」组，
   其下「我要定制」为「服务」组，用一段留白替代原来的分组标题做视觉切分
   （用 data-page 锚定，插入新菜单项不会错位） */
.sidebar-nav .side-item[data-page="stats"] { margin-top: 16px; }
/* 管理后台入口（20260923a）：作为独立一组放在最底部，与「我要定制」留出间隔。
   <a> 复用 .side-item 外观，需补回链接的默认下划线/配色重置。 */
.side-item-admin { margin-top: 16px; text-decoration: none; }
.side-item-admin:hover { text-decoration: none; }

/* 邀请好友（20260924k）：与上方「问题反馈」拉开一组留白独立成组；
   20260924m：用户反馈不要默认浅蓝底 —— 撤掉 accent-50 底与图标主色，
   外观与其他菜单项一致（选中/hover 态走 .side-item 通用规则） */
.sidebar-nav .side-item[data-page="invite"] { margin-top: 16px; }

.sidebar-bottom { border-top: 1px solid var(--border-subtle); padding: 12px 14px; flex-shrink: 0; }
/* 菜单文字恒单行（20261011s）：图标改成 24px 色块后横向空间少 6px，
   「邀请好友 + 可获积分返利」正好卡在临界，浏览器会把 4 字标题折成两行（行高 38→59）。
   标签 nowrap 保证单行，右侧说明小字空间不足时省略号收尾。 */
.side-item > span:not(.icon) { white-space: nowrap; }
.side-item .side-note { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.sidebar-user { display: flex; align-items: center; gap: 10px; padding: 8px 0; border-radius: 8px; cursor: pointer; }
.sidebar-user:hover { background: var(--bg-paper-2); }
.sidebar-user .avatar {
  width: 30px; height: 30px; border-radius: 50%;
  background: linear-gradient(135deg, var(--accent-500), var(--accent-700));
  color: #fff; display: flex; align-items: center; justify-content: center;
  font-weight: 600; font-size: 14px;
}
.sidebar-user .u-info { flex: 1; min-width: 0; display: flex; align-items: center; gap: 8px; }
.sidebar-user .u-name { flex: 1 1 auto; min-width: 0; font-size: 14.5px; font-weight: 600; color: var(--ink-800); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* 账号状态徽章（20260920e）：由「用户名 → 账号状态 → 到期日期」三层堆叠改成「用户名 + 状态」同一行 */
.sidebar-user .u-info .sub-ver { flex: none; font-size: 12.5px; padding: 1px 8px; }

/* ============================================================
   内容区
   ============================================================ */
.content {
  flex: 1; min-width: 0; min-height: 0;
  display: flex; flex-direction: column;
  padding: 24px 28px;
  overflow: hidden;
}
.page { flex: 1; min-height: 0; display: flex; flex-direction: column; min-width: 0; }
.page-header {
  /* --ph-pad-bottom：唯一 padding-bottom 来源。
     二级导航 .hist-head .seg-tabs 是绝对定位，top:50% 相对的是「padding box」，
     加了 padding-bottom 后会把导航整体下推「一半 padding」，与左侧标题不在同一
     水平线上（20260922d 用户反馈）。故用变量统一，导航侧反向补偿。 */
  --ph-pad-bottom: 16px;
  display: flex; align-items: center; gap: 12px;
  border-bottom: 1px solid var(--border-line);
  padding: 0 0 var(--ph-pad-bottom) 0;
  margin-bottom: 16px;
  flex-shrink: 0;
}
/* 20260922f：页面标题字号 15px → 24px（用户要求） */
.page-title { font-size: 24px; font-weight: 600; color: var(--ink-900); letter-spacing: -0.01em; }
.page-sub { font-size: 15px; color: var(--ink-400); margin-top: 2px; }
.page-actions { margin-left: auto; display: flex; gap: 8px; }
.page-header .grow { flex: 1; }

/* ============================================================
   卡片
   ============================================================ */
.card {
  background: var(--bg-paper);
  border: none;
  /* 20260922d：去掉 padding 与 border-radius（内容直接贴白底、无圆角） */
  border-radius: 0;
  padding: 0;
  margin-bottom: 16px;
  box-shadow: none;
}
.card-head { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
/* 20260922f：卡片标题左侧留 5px（与卡片左边线拉开） */
.card-title { font-size: 17px; font-weight: 600; color: var(--ink-800); margin: 0 0 0 5px; }
.card-sub { font-size: 14px; color: var(--ink-400); margin-left: 8px; }
.card-actions { margin-left: auto; display: flex; gap: 8px; }

/* 工作台/历史数据：这些容器需填满页面并内部滚动（高度链） */
.app-shell #view-projects,
.app-shell #view-project {
  flex: 1; min-height: 0;
  display: flex; flex-direction: column;
  overflow: hidden;
}
.app-shell #view-projects .card,
.app-shell #view-project .card,
.app-shell #page-history .card,
.app-shell #page-history-detail .card {
  flex: 1; min-height: 0;
  display: flex; flex-direction: column;
  overflow: hidden;
  margin-bottom: 0;
}

/* ============================================================
   统计看板
   ============================================================ */
.stat-grid {
  display: grid; gap: 12px;
  grid-template-columns: repeat(4, 1fr);
  /* 20260922h：上 10 / 左右 0 / 下 20（原 margin: 20px 0px） */
  margin: 10px 0 20px 0; flex-shrink: 0;
}
.stat-card {
  background: var(--bg-panel);
  border: none;
  border-radius: var(--radius-md);
  padding: 16px 18px;
  display: flex; flex-direction: column; gap: 5px;
  position: relative; overflow: hidden;
}
.stat-card .stat-label { font-size: 14px; color: var(--ink-500); }
.stat-card .stat-value { font-family: var(--font-mono); font-size: 26px; font-weight: 600; color: var(--ink-800); line-height: 1.15; }
.stat-card .stat-extra { font-size: 13px; color: var(--ink-400); }
.stat-card .stat-icon {
  position: absolute; top: 16px; right: 16px;
  width: 30px; height: 30px; border-radius: 8px;
  background: var(--yellow-100); color: var(--yellow-500);
  display: flex; align-items: center; justify-content: center;
}
.stat-card.green .stat-icon { background: var(--success-soft); color: var(--success); }
.stat-card.blue .stat-icon { background: var(--info-soft); color: var(--info); }
.stat-card.yellow .stat-icon { background: var(--yellow-100); color: var(--yellow-500); }

/* ============================================================
   按钮
   ============================================================ */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  border: 1px solid var(--accent-100); background: var(--accent-50);
  color: var(--accent-700);
  padding: 8px 14px; border-radius: var(--radius-md); cursor: pointer;
  font-size: 15px; font-family: inherit; line-height: 1.2;
  transition: all .18s var(--ease-out-quart);
  white-space: nowrap;
}
/* 用户要求（20260910o，口径最终纠正）：按钮上保留手指光标；
   user-select:none 禁止选中按钮文字，消除按钮内出现的文字竖线光标（I-beam） */
.btn, button { cursor: pointer; user-select: none; -webkit-user-select: none; }
/* 导出等耗时操作的按钮加载态（20260921i）：
   用户感知不到「点了在跑」会以为按钮坏了 —— 置灰 + 转圈 + 禁点 */
.btn.is-busy, button.is-busy {
  opacity: .75; cursor: default !important; pointer-events: none;
}
.btn.is-busy:hover { transform: none !important; box-shadow: none !important; }
.btn-spin {
  display: inline-block; width: 12px; height: 12px; flex: 0 0 auto;
  border: 2px solid currentColor; border-top-color: transparent;
  border-radius: 50%; animation: btn-spin .7s linear infinite;
}
@keyframes btn-spin { to { transform: rotate(360deg); } }
/* 全局兜底（20260910o-2）：所有按钮/可点击元素一律禁止文字竖线光标——
   [onclick] 覆盖 div/span/a/label 充当按钮的元素（chip、模板卡片、年月数值、
   面包屑链接、下载示例、整行勾选等），类名逐个兜住已知按钮样式 */
.btn, button, [onclick], .chip, .tpl-card, .tpl-dl, .page-num,
.crumb-link, .crumb-cur, .ym-year-val, .ym-nav, .fmt-remember,
.modal-close, .tpl-preview-btn, a.btn, .emp-row-btn, .row-btn {
  user-select: none; -webkit-user-select: none;
}
/* 默认按钮即浅蓝风格（与请假管理按钮统一）；白底按钮样式已全局废弃 */
.btn:not(:disabled):hover { background: var(--accent-100); border-color: var(--accent-300); color: var(--accent-700); }
.btn-primary { background: var(--accent-600); border-color: var(--accent-700); color: #fff; }
.btn-primary:not(:disabled):hover { background: var(--accent-700); border-color: var(--accent-700); color: #fff; transform: translateY(-1px); box-shadow: 0 8px 22px rgba(var(--accent-glow), 0.42); }
/* 例外：计算考勤右上角归档/导出按钮保留默认阴影 */
#btn-archive { box-shadow: none; }
/* 绿色描边按钮：白底绿字（考勤统计右上角「预览」「归档」），hover 浅绿底 */
.btn-greenline { background: var(--bg-card); border-color: var(--ink-200); color: var(--success); }
.btn-greenline:not(:disabled):hover {
  background: #bbf7d0; border-color: #4ade80; color: var(--success);
}
.btn-greenline:active { transform: translateY(0); box-shadow: none; }
/* 蓝色描边按钮：白底蓝边蓝字 */
.btn-outline { background: var(--bg-paper); border: 1px solid var(--accent-500); color: var(--accent-600); }
.btn-outline:not(:disabled):hover { background: var(--accent-50); border-color: var(--accent-600); color: var(--accent-700); }
.btn-success { background: var(--success); border-color: var(--success); color: #fff; }
.btn-success:not(:disabled):hover { background: var(--success); border-color: var(--success); }
.btn-danger { background: var(--danger); border-color: var(--danger); color: #fff; }
.btn-danger:not(:disabled):hover { background: var(--danger); border-color: var(--danger); }
.btn-accent { background: var(--accent-500); border-color: var(--accent-600); color: #fff; }
.btn-accent:not(:disabled):hover { background: var(--accent-600); border-color: var(--accent-600); color: #fff; transform: translateY(-1px); box-shadow: 0 6px 18px rgba(var(--accent-glow), 0.30); }
.btn-yellow { background: var(--yellow-400); border-color: var(--yellow-400); color: var(--yellow-500); }
.btn-yellow:not(:disabled):hover { background: var(--yellow-300); border-color: var(--yellow-300); color: var(--yellow-500); transform: translateY(-1px); box-shadow: 0 6px 18px rgba(var(--yellow-glow), 0.35); }
/* 中性幽灵按钮：跟随浅蓝基调和（弹窗 ✕ 关闭、清空输入等） */
.btn-ghost { background: var(--accent-50); border-color: var(--accent-100); color: var(--accent-700); }
.btn-ghost:not(:disabled):hover { background: var(--accent-100); border-color: var(--accent-300); color: var(--accent-700); }
.btn-sm { padding: 5px 10px; font-size: 14px; border-radius: 6px; }
.btn-lg { padding: 11px 20px; font-size: 16px; border-radius: 10px; }
.btn-xl { padding: 13px 44px; font-size: 17px; border-radius: 10px; font-weight: 600; }

/* 规则设置底部固定保存栏（位于滚动区之外，卡片底部固定行，绝无透底） */
.cfg-save-bar {
  flex-shrink: 0;
  display: flex; justify-content: center;
  /* 20260922a：去掉上边线（页面已无任何分隔描边） */
  margin-top: 12px; padding: 14px 0 2px;
}
.cfg-save-bar .btn { min-width: 220px; }

/* 绿色保存按钮（var(--success)）+ 同色投影增强立体感 */
.btn-green { background: var(--success); border-color: var(--success); color: #fff; }
.btn-green:not(:disabled):hover { background: var(--success); border-color: #166534; color: #fff; transform: translateY(-1px); box-shadow: 0 8px 22px rgba(22, 163, 74, 0.45); }
.btn-green:active { transform: translateY(0); box-shadow: 0 4px 12px rgba(22, 163, 74, 0.35); }
/* 例外：规则设置「保存规则」（btn-xl 绿色）保留默认阴影 */
.btn-green.btn-xl { box-shadow: 0 6px 18px rgba(22, 163, 74, 0.38); }
.btn[disabled] { opacity: .5; cursor: not-allowed; }
/* 浅蓝色按钮（20260914l）：原规则设置-显示与导出标题右侧的表格配置入口（20260920c 起
   改挂在计算考勤页「我的项目」卡片标题右侧；20260920d 起规则设置区已无入口） */
.btn-blue { background: #e8f2ff; border-color: #b9d7fa; color: #1667d9; }
.btn-blue:not(:disabled):hover { background: #d7e9ff; border-color: #9cc6f8; color: #0f5cc4; transform: translateY(-1px); box-shadow: 0 6px 16px rgba(22, 103, 217, 0.22); }
.btn-blue:active { transform: translateY(0); box-shadow: 0 3px 10px rgba(22, 103, 217, 0.18); }
/* 全局兜底：任何禁用按钮（含未挂 .btn 类的原生按钮）一律显示禁止光标 */
button:disabled, .btn:disabled { cursor: not-allowed !important; }

/* 项目页头操作按钮：预览/归档已改用 .btn-greenline 白底绿字；导出=主蓝 */
#btn-export {
  background: var(--accent-600); border-color: var(--accent-700); color: #fff;
  box-shadow: var(--shadow-sm);
}
#btn-export:not(:disabled):hover {
  background: var(--accent-700); border-color: var(--accent-700); color: #fff;
  transform: translateY(-1px); box-shadow: 0 6px 18px rgba(var(--accent-glow), 0.35);
}

input, select, textarea {
  border: 1px solid var(--ink-200); border-radius: var(--radius-md);
  padding: 8px 11px; font-size: 15.5px; font-family: inherit;
  background: var(--bg-paper); color: var(--ink-800); outline: none;
  transition: border-color .18s, box-shadow .18s;
}
input:focus, select:focus, textarea:focus {
  border-color: var(--accent-500);
  box-shadow: 0 0 0 4px rgba(var(--accent-glow), 0.10);
}

/* ============================================================
   标签 / 徽章 / 横幅
   ============================================================ */
.badge { display: inline-flex; align-items: center; gap: 3px; padding: 2px 8px; border-radius: 4px; font-size: 14px; }
.badge-ok { background: var(--success-soft); color: var(--success); }
.badge-off { background: var(--danger-soft); color: var(--danger); }
.badge-warn { background: var(--warning-soft); color: var(--warning); }
.badge-gray { background: var(--bg-paper-2); color: var(--ink-400); }
.badge-brand { background: var(--accent-50); color: var(--accent-700); }

.banner {
  padding: 10px 14px; border-radius: 8px; margin-bottom: 14px; font-size: 15px;
  display: flex; align-items: center; gap: 8px;
}
.banner-warn { background: var(--warning-soft); color: var(--yellow-500); border: 1px solid #ebd4a3; }
.banner-err { background: var(--danger-soft); color: var(--danger); border: 1px solid #f0c8c8; }
.banner-ok { background: var(--success-soft); color: var(--success); border: 1px solid #c4e2cc; }
.banner-info { background: var(--info-soft); color: #1e5690; border: 1px solid #c2d8ee; }

/* 顶部提醒浮层：固定定位不占文档流（显示/隐藏不再顶动页面内容，杜绝抖动）；
   三档语义：成功=绿 / 中性告知=琥珀 / 报错=红，带浮入动画
   20261044b：底色从「8% 透明色 + 毛玻璃」改成**不透明浅底 + 深色文字**。
   原来半透明浮层叠在表格/看板上，毛玻璃又没遮住下面的字，正文和底色糊成一片看不清；
   现在实底 + 描边 + 深字，任何背景下都读得清（暗色主题另给深底浅字）。
   z-index 2000：必须高于 .de-overlay(1000) / .de-pop-mask(1090) / .de-pop(1100)，
   否则在「配置考勤明细表格格式 / 配置考勤汇总表格格式」这类全屏子页面上提示会被盖住看不见（20260914u） */
#msg.banner {
  position: fixed; top: 16px; left: 50%; transform: translateX(-50%);
  z-index: 2000; margin: 0;
  width: max-content; max-width: min(560px, calc(100vw - 32px));
  border-radius: 10px;
  padding: 11px 18px 11px 15px; font-size: 14.5px; line-height: 1.5;
  font-weight: 500; letter-spacing: .1px;
  animation: msg-in .18s ease-out;
}
#msg.banner::before {
  content: ''; width: 8px; height: 8px; border-radius: 50%;
  flex-shrink: 0; box-shadow: 0 0 0 3px rgba(255, 255, 255, .72);
}
/* 成功（保存/导入/下载/复制…）：绿 */
#msg.msg-success {
  background: #e9f7ef; border: 1px solid #79c795; color: #14663a;
  box-shadow: 0 10px 28px rgba(15, 15, 15, .16), 0 2px 6px rgba(22, 163, 74, .14);
}
#msg.msg-success::before { background: #16a34a; }
/* 中性告知（「当前没有…」「无需…」）：琥珀，不再和报错共用红色 */
#msg.msg-info {
  background: #fdf6e3; border: 1px solid #e8ca8c; color: #83540a;
  box-shadow: 0 10px 28px rgba(15, 15, 15, .16), 0 2px 6px rgba(217, 119, 6, .14);
}
#msg.msg-info::before { background: #d97706; }
/* 报错：红 */
#msg.msg-error {
  background: #fdecec; border: 1px solid #ef9f9f; color: #a81d1d;
  box-shadow: 0 10px 28px rgba(15, 15, 15, .16), 0 2px 6px rgba(220, 38, 38, .14);
}
#msg.msg-error::before { background: #dc2626; }
/* 暗色主题：同语义换深底浅字 */
html.dark #msg.banner::before { box-shadow: 0 0 0 3px rgba(0, 0, 0, .38); }
html.dark #msg.msg-success { background: #11331f; border-color: #2e7d4d; color: #86e3a8; }
html.dark #msg.msg-info { background: #3a2b0d; border-color: #8a6820; color: #f5cd80; }
html.dark #msg.msg-error { background: #3b1717; border-color: #8f3b3b; color: #ff9f9f; }
@keyframes msg-in {
  from { opacity: 0; transform: translate(-50%, -8px); }
  to   { opacity: 1; transform: translate(-50%, 0); }
}

/* ============================================================
   工具栏 / 列表卡片
   ============================================================ */
.toolbar { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 12px; flex-shrink: 0; position: relative; z-index: 20; }
.toolbar .grow { flex: 1; }
.toolbar select { min-width: 96px; }
.muted { color: var(--ink-400); font-size: 14.5px; }

.list-card {
  background: var(--bg-paper);
  border: none;
  border-radius: var(--radius-lg);
  padding: 6px;
  margin-bottom: 12px; flex-shrink: 0;
}
.list-item {
  display: flex; align-items: center; gap: 14px;
  padding: 16px 18px;
  background: var(--bg-paper-2);
  border-radius: 12px;
  margin-bottom: 8px;
  cursor: pointer; transition: background .15s, box-shadow .15s;
}
.list-item:last-child { margin-bottom: 0; }
.list-item:hover { background: var(--bg-canvas); }
.list-icon {
  width: 44px; height: 44px; border-radius: 10px;
  background: var(--accent-50); color: var(--accent-600);
  display: flex; align-items: center; justify-content: center; flex-shrink: 0;
}
.list-icon.green { background: var(--success-soft); color: var(--success); }
.list-icon.blue { background: var(--info-soft); color: var(--info); }
.list-body { flex: 1; min-width: 0; }
.list-title { font-size: 17px; font-weight: 600; color: var(--ink-800); display: flex; align-items: center; gap: 8px; }
/* 项目列表：标题右侧统计年月徽章（醒目，沿用主色） */
.proj-period {
  display: inline-flex; align-items: center; flex-shrink: 0;
  font-size: 13px; font-weight: 700; letter-spacing: 0.01em;
  color: var(--accent-700); background: var(--accent-50);
  border: 1px solid rgba(var(--accent-glow), 0.28);
  border-radius: 999px; padding: 2px 10px;
}
.list-meta { font-size: 14px; color: var(--ink-400); margin-top: 4px; display: flex; gap: 12px; flex-wrap: wrap; }
.list-actions { display: flex; gap: 8px; flex-shrink: 0; }
.empty-state {
  text-align: center; padding: 60px 20px; color: var(--ink-400);
  border: 1px dashed var(--border-default); border-radius: var(--radius-md);
}
/* 20260923z：空态图标由彩色 emoji 改为扁平线性 SVG —— 尺寸走 CSS（宽高），颜色跟随文字色
   ⚠️ emoji 是行内文本（靠 text-align:center 居中），换 SVG 后 .empty-icon 变成块级 → 必须 margin:0 auto 自己居中 */
.empty-state .empty-icon { width: 46px; height: 46px; color: var(--ink-300); margin: 0 auto 10px; }
.empty-state .empty-icon svg { width: 100%; height: 100%; display: block; }

/* ============================================================
   个人信息
   ============================================================ */
.profile-hero {
  background: linear-gradient(160deg, #005bb8 0%, #0071e3 100%);
  border-radius: var(--radius-lg);
  padding: 28px 32px;
  display: flex; align-items: center; gap: 20px;
  color: #fff; margin-bottom: 16px;
  position: relative; overflow: hidden;
}
.profile-hero::before {
  content: ''; position: absolute; top: -30%; right: -15%;
  width: 220px; height: 220px;
  background: radial-gradient(circle, rgba(238, 185, 47, 0.26), transparent 70%);
}
.profile-hero .avatar-lg {
  width: 72px; height: 72px; border-radius: 50%;
  background: linear-gradient(135deg, var(--accent-500), var(--accent-700));
  display: flex; align-items: center; justify-content: center;
  font-size: 32px; font-weight: 700; flex-shrink: 0;
  border: 3px solid rgba(255,255,255,0.15);
}
.profile-hero .p-name { font-size: 24px; font-weight: 600; position: relative; }
.profile-hero .p-role { font-size: 15px; opacity: 0.85; margin-top: 4px; position: relative; }
.profile-hero .p-id { font-family: var(--font-mono); font-size: 14px; opacity: 0.7; margin-top: 2px; position: relative; }
/* 20261015o：横幅/头像按订阅档位配色 —— 免费版蓝色系（默认）/ 标准版金色系 / 专业版（含试用）靛色系 */
.profile-hero.tier-basic { background: linear-gradient(160deg, #925e00 0%, #bb8700 100%); }
.profile-hero.tier-basic::before { background: radial-gradient(circle, rgba(255, 255, 255, 0.22), transparent 70%); }
.profile-hero.tier-pro { background: linear-gradient(160deg, #3b3a9e 0%, #5e5ce6 100%); }
.profile-hero.tier-pro::before { background: radial-gradient(circle, rgba(255, 255, 255, 0.18), transparent 70%); }
.profile-hero.tier-basic .avatar-lg { background: linear-gradient(135deg, #d9a521, #8a5a00); }
.profile-hero.tier-pro .avatar-lg { background: linear-gradient(135deg, #7a78f2, #34339c); }
/* 档位版本徽章（订阅状态行）：与横幅同色系 */
.badge-tier-free { background: #e3effb; color: #005bb8; }
.badge-tier-basic { background: #f6ecc9; color: #8a5f00; }
.badge-tier-pro { background: #e7e6fb; color: #4543b8; }

.info-list { display: flex; flex-direction: column; }
.info-row {
  display: flex; align-items: center; padding: 14px 0;
  border-bottom: 1px solid var(--border-subtle); font-size: 16px;
}
.info-row:last-child { border-bottom: none; }
.info-row .k { width: 110px; color: var(--ink-400); flex-shrink: 0; }
.info-row .v { flex: 1; color: var(--ink-800); font-weight: 500; }

/* ============================================================
   全员总览大表
   ============================================================ */
.grid-wrap {
  flex: 1 1 0; min-height: 0; height: 0;
  overflow: auto;
  /* 20260922h：外框描边统一 var(--border-hairline)（原 --border-table #aaaaaa） */
  border: 1px solid var(--border-hairline);
  /* 20260922e：表格上级外框去掉圆角（单元格线/表头线同步改为 var(--border-hairline)） */
  border-radius: 0;
  background: var(--bg-paper);
}
/* 考勤结果：表格可滚动区 + 分页（分页在表格外、固定在底部，不随表格滚动） */
.summary-wrap {
  flex: 1 1 0; min-height: 0; height: 0;
  display: flex; flex-direction: column; overflow: hidden;
}
.summary-wrap > .grid-wrap { flex: 1 1 0; }
table.grid-full {
  border-collapse: separate; border-spacing: 0;
  width: max-content; min-width: 100%;
  table-layout: fixed; font-size: 15px;
}
table.grid-full th, table.grid-full td {
  /* 20260922e：单元格线统一 var(--border-hairline)（原 --border-table #aaaaaa） */
  border-right: 1px solid var(--border-hairline);
  border-bottom: 1px solid var(--border-hairline);
  padding: 4px 6px; text-align: center; white-space: nowrap; height: 28px;
  color: var(--ink-900); font-weight: 400;
}
table.grid-full thead th {
  background: var(--bg-paper-2); font-weight: 700; color: var(--ink-900);
  /* 20260922e：标题下边线统一 var(--border-hairline)（原 #aaaaaa） */
  position: sticky; top: 0; z-index: 3; border-bottom: 1px solid var(--border-hairline);
}
table.grid-full thead .sub { font-weight: 400; font-size: 13px; color: var(--ink-900); }
table.grid-full th.col-seq, table.grid-full td.col-seq {
  width: 44px; min-width: 44px;
  position: sticky; left: 0; z-index: 2; font-weight: 400; color: var(--ink-900);
  background: var(--col-name-bg);
}
table.grid-full th.col-name, table.grid-full td.col-name {
  width: 86px; min-width: 86px;
  position: sticky; left: 44px; z-index: 2; background: var(--col-name-bg);
  white-space: normal; word-break: break-all; line-height: 1.35;
}
table.grid-full th.col-dept, table.grid-full td.col-dept {
  width: 86px; min-width: 86px;
  position: sticky; left: 130px; z-index: 2; background: var(--col-dept-bg);
  white-space: normal; word-break: break-all; line-height: 1.35;
}
/* 指标列（20261016c 用户口径）：宽 86 → **76px** —— 够「原始打卡记录」等 6 字指标名
   折 2 行显示完整（内容已 normal 折行 + 居中），左侧偏移仍为前三列之和 216px 不变 */
table.grid-full th.col-metric, table.grid-full td.col-metric {
  width: 76px; min-width: 76px;
  position: sticky; left: 216px; z-index: 2; background: var(--col-metric-bg);
}
table.grid-full.view-detail th.col-metric, table.grid-full.view-detail td.col-metric { left: 0 !important; }
table.grid-full thead th.col-seq, table.grid-full thead th.col-name, table.grid-full thead th.col-dept, table.grid-full thead th.col-metric { z-index: 4; }
table.grid-full th.col-day, table.grid-full td.col-day { width: 52px; min-width: 52px; }
table.grid-full th.col-total, table.grid-full td.col-total {
  width: 78px; min-width: 78px; background: var(--col-total-bg);
  position: sticky; right: 0; z-index: 2;
}
table.grid-full thead th.col-total { z-index: 4; }
/* 汇总列（20260914v）：字段与顺序来自「配置考勤明细表格格式」，非固定列；
   每名员工纵向合并居中。20260914w：列宽收窄（86→60px），标题文字折行。
   20260916a：不再填充黄色 —— 与整行底色一致（白底黑字），表头与其它列表头同色 */
table.grid-full th.col-summary, table.grid-full td.col-summary {
  width: 60px; min-width: 60px; white-space: normal; line-height: 1.35;
  color: var(--ink-900);
}
/* ---------- 列宽硬锁（20261007t）----------
   ⚠️ 背景：`table.grid-full` 是 `width: max-content` + `table-layout: fixed`。
   fixed 布局下浏览器先按各列声明宽排出min 宽度；若表格最终宽度（max-content）
   大于「各列声明宽之和」，**多出来的余量会被分配到列上**。
   原本只有 `min-width` 的列在 fixed 布局里 `width` 不生效，于是
   `col-metric`（指标列）成了唯一「自由列」，**独自吸收全部余量**：
       结果页tableW=2413 → col-metric 86 被撑到 97（+11）
       预览页  tableW=2419 → col-metric 86 被撑到 103（+17）
   两页余量不同 → 指标列宽度不同 → 后面所有日列的起始位置被挤偏，
   用户看到「3 号列宽度和其他日期不一样」。

   修法：给所有固定宽列补 `max-width`（与已有 `min-width` 同值），
   使任一列都不能突破声明宽 —— 余量无处可去，表格宽度自然收敛到「列宽之和」。
   实测：两页 tableW 齐平为 2402、col-metric 齐平为 86、日列恒 52。
   （只给 col-day 加 max-width 无效：30 个日列本来就是精确 52px×30，
     余量仍然全被 metric 吃掉 —— **必须同时锁住「自由列」**。） */

/* ---------- 单元格内容溢出时折行（20261007t）----------
   列宽被max-width 硬锁死后，内容比列宽长时**不能再撑宽列**，
   必须让文字在格内换行，否则会溢出到相邻格（视觉上像"那列变宽了"）。
   规则：
     · 汇总/吸附/指标列 → normal + break-word（中文长值如「外3h 事3.9h」可断）
     · 每日列 col-day→ normal（原始打卡记录已按卡换行；数字类值本来很短）
   ⚠️ 不能用 `overflow: hidden`：那会**裁掉**内容（缺卡/旷工等标记被切掉），
      必须靠折行让内容完整可见。 */
table.grid-full th.col-metric, table.grid-full td.col-metric,
table.grid-full th.col-summary, table.grid-full td.col-summary,
table.grid-full th.col-total, table.grid-full td.col-total {
  white-space: normal; overflow-wrap: anywhere; word-break: break-word;
}
table.grid-full th.col-day, table.grid-full td.col-day {
  white-space: normal; overflow-wrap: anywhere;
}
/* 表头同理：标题较长时折行而不是撑宽列 */
table.grid-full thead th { white-space: normal; overflow-wrap: anywhere; }
table.grid-full th.col-seq, table.grid-full td.col-seq { max-width: 44px; }
table.grid-full th.col-name, table.grid-full td.col-name,
table.grid-full th.col-dept, table.grid-full td.col-dept { max-width: 86px; }
table.grid-full th.col-metric, table.grid-full td.col-metric { max-width: 76px; }
table.grid-full th.col-day, table.grid-full td.col-day { max-width: 52px; }
table.grid-full th.col-total, table.grid-full td.col-total { max-width: 78px; }
table.grid-full th.col-summary, table.grid-full td.col-summary { max-width: 60px; }

/* 原始打卡记录（20261007q）：每日列宽最多容纳一个「xx:xx」（.col-day 固定 52px），
   因此每张卡独占一行——放开 nowrap 改逐卡换行；行高由 JS 按实际卡数写在 <tr> 上。
   字号略缩到 13px 以保证「xx:xx」在 52px 内不被折成两行（结果页/归档页/导出预览页同源）。 */
table.grid-full td.c-rawpunch {
  white-space: normal; line-height: 21px; word-break: keep-all;
  font-size: 13px; font-variant-numeric: tabular-nums;
  padding: 4px 2px; vertical-align: middle;
}
/* 超出上限折叠的「+N」提示（20261007q） */
table.grid-full td.c-rawpunch .rp-more {
  font-size: 11px; color: var(--ink-500); letter-spacing: -.2px;
}
/* 结果页原始打卡单元格可点（20261009a）：点击弹出「原始打卡记录」编辑对话框。
   只给结果页那一份加 .c-rawpunch-edit（归档页 / 导出预览页仍为只读）。
   ⚠️ hover 必须与其它可编辑格**完全同款**（蓝色描边 + 浅蓝底）——不要另写一套，
      统一挂在下方 `.editable:hover` 那条共用规则上（20261009b）。 */
table.grid-full td.c-rawpunch-edit { cursor: pointer; }
table.grid-full tr.block-a td { background-color: var(--row-a); }
table.grid-full tr.block-b td { background-color: var(--row-b); }
table.grid-full td.rest { background-color: var(--col-rest-bg) !important; }
table.grid-full td.holiday { background-color: var(--col-holiday-bg) !important; }
table.grid-full thead th.rest { background: var(--col-rest-bg); }
table.grid-full thead th.holiday { background: var(--col-holiday-bg); }
table.grid-full td.editable { cursor: pointer; color: var(--ink-800); }
/* 表格内容格 hover 统一口径（蓝色描边 + 浅蓝底）：可编辑格、结果页原始打卡格共用。
   新增「可点单元格」一律并进这里，别再单独写 background/outline。 */
table.grid-full td.editable:hover,
table.grid-full td.c-rawpunch-edit:hover { outline: 2px solid var(--accent-500); outline-offset: -2px; background: var(--accent-50) !important; }
table.grid-full td.editable input { width: 64px; padding: 2px 4px; text-align: center; font-size: 14px; }
/* 人工修改过的单元格：右上角红色角标（20261019u 用户定版：蓝改红；悬停显示原值/新值） */
table.grid-full td.edited { position: relative; }
table.grid-full td.edited::after {
  content: ''; position: absolute; top: 0; right: 0;
  width: 0; height: 0; border-style: solid;
  border-width: 0 8px 8px 0; border-color: transparent var(--danger) transparent transparent;
}

/* 状态配色（20260925i 与异常检查模式色系对齐）：
   迟到=浅紫（ck 紫 #7c3aed）/ 早退=浅蓝（#0066cc）/ 缺卡=浅红（var(--danger)）/ 旷工=浅黄（ck 黄 #f9c716）
   — 迟到标记在「上班」卡、早退标记在「下班」卡；导出预览页单独钉回导出配色（见 preview-grid 段） */
table.grid-full td.c-late { background: #ede9fe !important; color: #6d28d9; }
/* 免罚分钟（20261019g 用户定版）：命中免罚的迟到/早退分钟 —— 灰字 + 删除线（默认口径）。
   「显示方式=不显示」由前端直接留空（不走 CSS）。
   🔴 底色仍走 c-late / c-early（迟到/早退着色不变），只压文字颜色 + 删除线；不改字号。 */
table.grid-full td.is-free-minute,
table.grid-full td.is-free-minute.c-late,
table.grid-full td.is-free-minute.c-early {
  color: var(--ink-400) !important;
  text-decoration: line-through;
  text-decoration-thickness: 1px;
  text-decoration-color: var(--ink-300);
}
html.dark table.grid-full td.is-free-minute,
html.dark table.grid-full td.is-free-minute.c-late,
html.dark table.grid-full td.is-free-minute.c-early {
  color: var(--ink-500) !important;
  text-decoration-color: var(--ink-500);
}
/* 扣时长命中（20261020e）：迟到/早退已被「按分钟次数扣时长」处罚（正班起算点
   推迟/提前，分钟/次数不进合计）——单元格红描边 + 悬停提示处罚结果。用内阴影
   描边（border 会挤动列宽，outline 在 collapse 表格上不显示）。 */
table.grid-full td.is-ct-hit {
  /* 20261020f：1px 内阴影 → 20261020g（用户定版）：改右上角红色角标
     （与人工修改角标同形；同时叠加 is-free-minute 灰字删除线展示分钟值） */
  position: relative;
  font-weight: 600;
}
table.grid-full td.is-ct-hit::after {
  content: ''; position: absolute; top: 0; right: 0;
  width: 0; height: 0; border-style: solid;
  border-width: 0 8px 8px 0; border-color: transparent var(--danger, #e5484d) transparent transparent;
}
table.grid-full td.c-early { background: #e5f1ff !important; color: #0066cc; }
table.grid-full td.c-missing { background: #ffdada !important; color: var(--danger); font-weight: 600; }

/* 表格右上角颜色图例 */
.table-legend {
  display: flex; gap: 14px; justify-content: flex-end;
  margin-bottom: 0; font-size: 13px; color: var(--ink-500);
  flex-wrap: wrap; flex-shrink: 0;
}
.lg-item { display: inline-flex; align-items: center; gap: 5px; }
.lg-dot { width: 12px; height: 12px; border-radius: 3px; display: inline-block; border: 1px solid rgba(71,85,105,0.25); }
.lg-dot.c-late { background: #ede9fe; }
.lg-dot.c-early { background: #e5f1ff; }
.lg-dot.c-missing { background: #ffdada; }
.lg-dot.c-absent { background: #fef9c3; }

/* 请假导入：模板格式选择弹窗 */
.tpl-grid {
  display: grid; grid-template-columns: repeat(2, 1fr); gap: 16px;
}
.tpl-card {
  border: 1.5px solid var(--line, #e2e8f0); border-radius: 10px;
  padding: 12px 12px 14px; text-align: center; cursor: pointer;
  display: flex; flex-direction: column; align-items: center; gap: 10px;
  transition: border-color .15s, box-shadow .15s;
}
/* 20260928u：去掉 hover 抬升 translateY —— 鼠标停在卡片下边缘时抬起/落回循环触发抖动 */
.tpl-card:hover {
  border-color: var(--accent-500, #2563eb);
  box-shadow: 0 4px 14px rgba(37, 99, 235, .12);
}
.tpl-thumb {
  position: relative; width: 100%; height: 190px; border-radius: 6px; overflow: hidden;
  background: #f8fafc; border: 1px solid var(--line, #e2e8f0);
  display: flex; align-items: center; justify-content: center;
}
.tpl-thumb img { max-width: 100%; max-height: 100%; object-fit: contain; }
/* 鼠标经过缩略图出现「预览大图」按钮 */
.tpl-preview-btn {
  position: absolute; left: 50%; bottom: 10px; transform: translateX(-50%);
  display: inline-flex; align-items: center; gap: 4px;
  padding: 5px 12px; border-radius: 6px; border: none; cursor: pointer;
  font-size: 12.5px; color: #fff; background: rgba(15, 23, 42, .68);
  opacity: 0; pointer-events: none; transition: opacity .15s;
  white-space: nowrap;
}
.tpl-card:hover .tpl-preview-btn { opacity: 1; pointer-events: auto; }
.tpl-preview-btn:hover { background: rgba(15, 23, 42, .88); }
/* 标题固定两行高度，下载按钮贴底对齐 */
.tpl-name {
  font-size: 13.5px; font-weight: 600; color: var(--ink-900, #0f172a);
  min-height: 20px; line-height: 20px;
}
/* 格式要求备注：左对齐浅底说明块（20260910h）；文字允许复制（20260910s 放行 user-select） */
.tpl-req {
  width: 100%; text-align: left;
  font-size: 12px; line-height: 1.65; color: #64748b;
  background: var(--bg-soft, #f8fafc);
  border: 1px solid var(--line, #e2e8f0); border-radius: 7px;
  padding: 8px 10px;
  user-select: text !important; -webkit-user-select: text !important;
}
.tpl-dl {
  font-size: 12.5px; color: var(--accent-600, #2563eb);
  text-decoration: none; padding: 2px 8px; border-radius: 5px;
  margin-top: auto;
}
.tpl-dl:hover { background: var(--accent-50, #eff6ff); }
/* 缩略图大图预览（点击遮罩关闭） */
.img-preview-mask {
  position: fixed; inset: 0; z-index: 1000;
  background: rgba(15, 23, 42, .78);
  display: flex; align-items: center; justify-content: center;
  cursor: zoom-out;
}

/* ---------- 拖拽导入遮罩（20261020h）：拖文件到页面全屏显示，松开即导入 ---------- */
.drop-overlay {
  position: fixed; inset: 0; z-index: 2000;
  background: rgba(15, 23, 42, .78);
  backdrop-filter: blur(2px);
  display: flex; align-items: center; justify-content: center;
  pointer-events: none;             /* 🔴 不拦截拖拽事件（dragover/drop 由 document 接管） */
}
.drop-inner {
  display: flex; flex-direction: column; align-items: center;
  padding: 44px 64px;
  border: 2px dashed rgba(255, 255, 255, .55);
  border-radius: 16px;
  color: #fff;
  background: rgba(255, 255, 255, .06);
}
.drop-ico { color: #fff; opacity: .92; margin-bottom: 14px; }
.drop-title { font-size: 20px; font-weight: 600; letter-spacing: .5px; }
.drop-sub { margin-top: 8px; font-size: 13px; color: rgba(255, 255, 255, .72); }
/* 20261020j：确认年月弹窗内「已自动识别格式」提示（拖拽导入自动确认格式）
   位于年月选择器上方；浅绿样式；🔴 max-width:100% + box-sizing 防 360px 定宽
   在窄弹窗撑出横向滚动条 */
.drop-fmt-hint {
  margin: 0 auto 10px;
  max-width: 100%;
  box-sizing: border-box;
  font-size: 12px;
  line-height: 1.6;
  color: var(--success);
  background: var(--success-soft);
  border: 1px solid #c4e2cc;
  border-radius: 8px;
  padding: 7px 12px;
  text-align: center;
}
.drop-fmt-hint.hidden { display: none; }   /* 🔴 隐藏态必须 display:none（不占 scrollWidth） */
.img-preview-mask img {
  max-width: 92vw; max-height: 92vh; border-radius: 8px;
  box-shadow: 0 12px 48px rgba(0, 0, 0, .5);
  background: var(--bg-card);
}
.tpl-note { font-size: 12.5px; margin-top: 14px; line-height: 1.7; }
.tpl-note a { color: var(--accent-600, #2563eb); margin-left: 4px; }
/* 20261009o：假勤导入弹框改「2×2 紧凑分组」
   ① 去掉「第X类」徽章 → 组标题前的扁平图标（.tpl-group-ico）区分四类
   ② 卡片加「格式要求」块（.tpl-req），组描述不再承载格式要求
   ③ 缩略图 190px → 86px、卡片宽度固定 160px ⇒ 弹框整体高度减半，不出现滚动条 */
/* 20261009q：左右两列宽度随内容（左列 2 卡 / 右列 3 卡），去掉两列之间的等分留白。
   ⚠️ 组内必须用 flex 而非 repeat(auto-fit)：auto-fit 在「auto 列宽」下轨道数退化成 1、
   卡片全部竖排（09q 实测溢出 170px）；flex 的 max-content 才是「所有卡排一行」。 */
.tpl-groups {
  display: grid; grid-template-columns: auto auto;
  gap: 12px 22px; align-items: start; justify-content: flex-start;
}
.tpl-group { min-width: 0; }
.tpl-groups .tpl-grid { display: flex; flex-wrap: wrap; gap: 10px; }
/* flex 下没有 grid 轨道给宽度 ⇒ 卡片必须显式定宽（与轨道时代的 185px 一致） */
.tpl-groups .tpl-card { flex: 0 0 185px; width: 185px; }
.tpl-group-head {
  display: flex; align-items: center; gap: 7px; flex-wrap: wrap;
  margin-bottom: 8px;
}
.tpl-group-ico {
  flex-shrink: 0; width: 22px; height: 22px; border-radius: 6px;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--accent-600, #2563eb); background: var(--accent-50, #eff6ff);
}
.tpl-group-ico svg { width: 14px; height: 14px; }
.tpl-group-title { font-size: 14px; font-weight: 600; color: var(--ink-900, #0f172a); }
.tpl-group-desc { font-size: 12px; color: var(--ink-400, #94a3b8); }

.tpl-groups .tpl-card { padding: 8px 8px 10px; gap: 7px; border-radius: 8px; }
.tpl-groups .tpl-thumb { height: 86px; }
.tpl-groups .tpl-preview-btn { bottom: 6px; padding: 4px 9px; font-size: 11.5px; }
.tpl-groups .tpl-name { font-size: 13px; min-height: 0; line-height: 1.35; }
.tpl-groups .tpl-req {
  font-size: 11px; line-height: 1.5; padding: 6px 7px; border-radius: 6px;
}
.tpl-groups .tpl-dl { font-size: 12px; padding: 2px 6px; }

/* ⚠️ 弹框限高：正常内容（2 行分组）应完全放得下；万一视口极矮仍可滚，且
   「✕ 关闭」永远固定在头部不被顶出可点区域。 */
#leave-import-format-modal .modal-box {
  display: flex; flex-direction: column;
  max-height: calc(100vh - 40px);   /* 20261020c：与通用 .modal-box 统一（mask padding 20×2） */
  width: min(1034px, calc(100vw - 32px)); max-width: 1034px;
}
#leave-import-format-modal .modal-head { flex-shrink: 0; margin-bottom: 10px; }
#leave-import-format-modal .modal-body { overflow-y: auto; min-height: 0; }
#leave-import-format-modal .modal-title .link-btn { font-size: 12.5px; font-weight: 500; }
/* 20261010：标题右侧提示文字（取代「导入说明」按钮） */
#leave-import-format-modal .modal-tip {
  font-size: 12.5px; font-weight: 400; color: var(--ink-400, #94a3b8); white-space: nowrap;
}
/* 提示里的拖拽引导片段（20261020q）：绿色强调，与考勤页拖拽提示同色 */
#leave-import-format-modal .modal-tip .tip-green {
  color: var(--success); font-weight: 600;
}

/* 「导入说明」弹窗里的小节标题：左侧蓝色竖条区分四类（不再写「第X类」） */
.ih-sec {
  font-size: 13px; font-weight: 600; color: var(--ink-900, #0f172a);
  line-height: 1.5; margin: 12px 0 6px; padding-left: 8px;
  border-left: 3px solid var(--accent-500, #2563eb);
}
.ih-sec:first-child { margin-top: 0; }

/* 考勤格式弹窗（20260910k）：备注块内文字黑色 14px，下载示例内联在文字末尾 */
#att-import-format-modal .tpl-req {
  font-size: 14px; line-height: 1.7; color: var(--ink-900, #0f172a);
}
#att-import-format-modal .tpl-req .tpl-dl {
  font-size: 14px; font-weight: 600; margin-top: 0; white-space: nowrap;
  transition: background .15s, color .15s;
}
#att-import-format-modal .tpl-req .tpl-dl:hover {
  background: var(--accent-100, #dbeafe); color: var(--accent-700, #1d4ed8);
}
#att-import-format-modal .tpl-name { font-size: 14px; text-align: center; min-height: auto; }
/* 考勤格式卡片一行四列（20261039h，用户定版：原三列 → 四列，卡片高度整体降低、描述大幅精简；
   请假导入弹窗仍用 .tpl-grid 两列不受影响）。
   🔴 这一组全部带 `#att-import-format-modal #att-tpl-grid` 双 id 前缀（特异性 2,2,0），
      才能压过下面那条通用 `#att-import-format-modal .tpl-req{font-size:14px}`(1,1,0)
      和 `#att-tpl-grid .tpl-card.selected`(1,2,0)。 */
#att-import-format-modal #att-tpl-grid {
  grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px;
}
#att-import-format-modal #att-tpl-grid .tpl-card {
  padding: 9px 9px 10px; gap: 7px; border-radius: 8px;
}
#att-import-format-modal #att-tpl-grid .tpl-thumb { height: 88px; }
#att-import-format-modal #att-tpl-grid .tpl-preview-btn {
  bottom: 5px; padding: 3px 8px; font-size: 11px;
}
#att-import-format-modal #att-tpl-grid .tpl-name {
  font-size: 12.5px; line-height: 1.4; min-height: 0;
}
#att-import-format-modal #att-tpl-grid .tpl-req {
  font-size: 12px; line-height: 1.6; padding: 5px 7px; border-radius: 6px;
}
/* 「下载示例」独占一行：inline 时描述短就会与文字同行（出现「列 下载示例」这种混排） */
#att-import-format-modal #att-tpl-grid .tpl-req .tpl-dl {
  display: block; width: fit-content; margin-top: 3px;
  font-size: 12px; padding: 1px 5px;
}
/* 选中态：2px 描边替代 1.5px，padding 同步减 0.5 保持卡片外框尺寸不变 */
#att-import-format-modal #att-tpl-grid .tpl-card.selected {
  padding: 7.5px 7.5px 8.5px;
}

/* 20261039h：弹框上方「拖拽考勤文件 / 点击上传」区（云朵 + 上箭头，按用户截图还原） */
.att-drop {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  padding: 14px 16px 16px; margin-bottom: 12px; gap: 2px;
  border: 1.5px dashed var(--ink-200, #e2e8f0); border-radius: 12px;
  background: var(--bg-soft, #f8fafc);
  text-align: center; cursor: pointer;
  transition: border-color .15s, background .15s;
}
.att-drop:hover, .att-drop:focus-visible, .att-drop.drag-on {
  border-color: var(--accent-500, #2563eb);
  background: var(--accent-50, #eff6ff);
  outline: none;
}
.att-drop-ico {
  /* 云朵填充色：底色是 --bg-soft(极浅灰)，图标必须比背景明显深一档才看得见
     （20261039h 首版用 #e4e6e9 几乎与底同色，实测只剩一个白箭头） */
  color: var(--ink-300, #cfd2d9); line-height: 0; margin-bottom: 7px; transition: color .15s;
}
.att-drop:hover .att-drop-ico, .att-drop.drag-on .att-drop-ico { color: #a9c8f0; }
.att-drop-t1 { font-size: 15px; font-weight: 600; color: var(--ink-900, #0f172a); }
.att-drop-t2 {
  font-size: 12.5px; color: var(--ink-500, #64748b); line-height: 1.6; margin-top: 3px;
}
html.dark .att-drop { background: var(--bg-paper-2); border-color: var(--border-strong); }
html.dark .att-drop:hover, html.dark .att-drop.drag-on {
  border-color: var(--accent-500); background: rgba(10, 132, 255, .10);
}
html.dark .att-drop-ico { color: #4b4f57; }
html.dark .att-drop:hover .att-drop-ico, html.dark .att-drop.drag-on .att-drop-ico { color: #33587f; }
/* 扣款阶梯行（20260913b）：一格 = 标签 + 输入 + 单位；标签用深色（20260913d 设置内容黑字，备注仍灰）
   20260913e：阶梯区域内文字统一 14px（输入框文字与「迟到≤」等标签一致） */
.ladder-cell { display: inline-flex; align-items: center; gap: 4px; }
.ladder-lbl { font-size: 14px; color: var(--ink-700); white-space: nowrap; }
.ladder-row .interval-input,
.ladder-cap-line .input { width: 76px; font-size: 14px; padding: 6px 8px; }
.ladder-cap-line .input { width: 96px; }
.ladder-row .interval-unit { font-size: 14px; }
.ladder-grace-lbl { font-size: 14px; }
/* 每周期免罚额度（20261019c）：一个字段里两个数字输入 ——「每周期免罚 [N] 次 / 单次≤ [M] 分钟」。
   20261019s（用户定版）：整行 6 栏、本字段占 **1 栏**（≈163px，与上下行栏边界对齐）——
   110px 输入框保留，两段在段间折成两行（19d 设计），底对齐不受影响。 */
.free-quota-row { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 5px; }
.free-quota-row .fq-txt {
  color: var(--ink-500); font-size: 14px; white-space: nowrap; user-select: none;
}
.free-quota-row .fq-input {
  width: 110px; flex: 0 0 110px; min-width: 0; text-align: center;
  background: var(--bg-paper); border: 1px solid var(--ink-200);
  border-radius: var(--radius-md); padding: 9px 4px;
  font-size: 16px; font-family: var(--font-mono); color: var(--ink-800);
  outline: none; transition: all .18s;
}
.free-quota-row .fq-input:hover { border-color: var(--ink-300); }
.free-quota-row .fq-input:focus {
  border-color: var(--accent-500); box-shadow: 0 0 0 4px rgba(var(--accent-glow), 0.10);
}
/* 免罚行底对齐（20261019h）：本字段不是 .input-wrap 结构，cols-8 / cfg-time-grid 的
   「输入区 margin-top:auto 压到格底」选不中它 ⇒ 单独补一条，否则同排只有它悬在上方 */
.field-grid.cfg-time-grid .field > .free-quota-row { margin-top: auto; }
/* 免罚额度两段分组（20261019d）：[N]次 / 单次≤[M]分钟 各自内部不拆行，
   窄栏（1/6 行宽 ≈163px）时在两段之间整齐折成两行，不会出现「分钟」单独掉行 */
.free-quota-row .fq-grp {
  display: inline-flex; align-items: center; gap: 4px; flex: 0 0 auto; white-space: nowrap;
}
/* 单日封顶 / 减去宽限独立设置行（20260913c/d）：阶梯下方统一一行；窄列时允许换行 */
.ladder-cap-line { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; margin: 8px 0; }
.ladder-cap-line .muted { font-size: 12px; }
/* 字段标题右侧蓝色文字按钮（20260913c）：无背景填充 */
.link-btn {
  background: none; border: none; padding: 0; margin-left: 8px;
  color: var(--accent-600, #2563eb); font-size: 15px; font-weight: 500;
  font-family: inherit;   /* 20260923y：button 默认字体是 Arial，与相邻文字字体不一致 → 与「附件」标题视觉对不齐 */
  /* 20261037m：去掉 vertical-align: middle —— 与标题文字同基线即可，middle 会让按钮相对文字上浮 */
  cursor: pointer;
}
.link-btn:hover { text-decoration: underline; }
/* 卡片选中态：仅蓝色描边 2px，不填充 */
#att-tpl-grid .tpl-card.selected {
  border: 2px solid var(--accent-500, #2563eb);
  padding: 11.5px 11.5px 13.5px;
}
/* 卡片过多时弹框不超出屏幕（20260912g）：弹框限高 + 内部纵向布局，
   卡片区域（modal-body）竖向滚动，标题与底部按钮始终可见可点 */
#att-import-format-modal .modal-box.fmt-wide {
  max-height: calc(100vh - 40px);
  display: flex; flex-direction: column;
  overflow: hidden;
}
#att-import-format-modal .modal-title {
  flex-shrink: 0;
  /* 20260928t：标题 + 右上角「选择其他格式」按钮一行；20260928v：右上角 ✕ 关闭（margin-left:auto 推到最右） */
  display: flex; align-items: center; justify-content: flex-start; gap: 10px;
}
#att-import-format-modal .modal-title .link-btn { font-size: 13.5px; }
#att-import-format-modal .modal-title .modal-close { margin-left: auto; }
#att-import-format-modal .modal-body {
  flex: 1 1 auto; min-height: 0;
  overflow-y: auto;
  padding-right: 6px;              /* 给滚动条留位，避免卡片贴条 */
  overscroll-behavior: contain;    /* 滚到边界不带动页面 */
}
#att-import-format-modal .modal-body::-webkit-scrollbar { width: 8px; }
#att-import-format-modal .modal-body::-webkit-scrollbar-thumb {
  background: rgba(100, 116, 139, .35); border-radius: 4px;
}
#att-import-format-modal .modal-body::-webkit-scrollbar-thumb:hover {
  background: rgba(100, 116, 139, .55);
}
#att-import-format-modal .modal-actions { flex-shrink: 0; margin-top: 14px; }
/* 底部「记住我的选择」：带底色块的明显样式，贴最左 */
.fmt-remember {
  margin-right: auto; display: inline-flex; align-items: center; gap: 7px;
  font-size: 14.5px; font-weight: 500; color: var(--ink-900, #0f172a);
  background: var(--bg-soft, #f8fafc);
  border: 1px solid var(--line, #e2e8f0); border-radius: 7px;
  padding: 7px 12px; cursor: pointer; user-select: none;
  transition: border-color .15s, background .15s;
}
.fmt-remember:hover { border-color: var(--accent-500, #2563eb); }
.fmt-remember:has(input:checked) {
  border-color: var(--accent-500, #2563eb);
  background: var(--accent-50, #eff6ff);
}
.fmt-remember input {
  width: 16px; height: 16px; margin: 0;
  accent-color: var(--accent-500, #2563eb); cursor: pointer;
}

/* 后台列表通用表格（20260924j）：样式与用户端「员工管理」表（.emp-table）统一 ——
   ① 边框：去掉满格网格线与外框，只留行分隔线（表头线稍深、正文行浅）；
   ② 对齐：表头与正文一律左对齐（原居中）；
   ③ 字号：14px → 15px；
   ④ 行内按钮：改灰底黑字（hover 浅蓝底蓝字，见下方 .btn 覆盖），与 .emp-row-btn 一致。 */
table.grid { border-collapse: collapse; width: 100%; font-size: 15px; }
table.grid th, table.grid td {
  border: none; border-bottom: 1px solid var(--border-subtle);
  padding: 10px 12px; text-align: left; white-space: nowrap;
  color: var(--ink-900); font-weight: 400; font-size: 15px;
}
table.grid thead th {
  background: var(--bg-paper-2); font-weight: 700; color: var(--ink-900);
  border-bottom: 1px solid var(--border-default);
  position: sticky; top: 0; z-index: 2;
}
table.grid tbody tr:hover { background: var(--bg-tinted); }
table.grid tbody tr:last-child td { border-bottom: none; }
/* 行内操作按钮（开通订阅 / 试用 / 重置密码 / 详情 / 回复 / 已沟通 / 停用…）：
   与员工管理操作列的 .emp-row-btn 同款 —— 灰底黑字、无边框，hover 浅蓝 */
table.grid td .btn:not(:disabled) {
  background: var(--ink-100); border: none; color: var(--ink-900);
  font-size: 15px; padding: 4px 8px; border-radius: 6px; transition: all .15s;
}
table.grid td .btn:not(:disabled):hover { background: var(--accent-50); color: var(--accent-700); }
/* 危险操作（停用）：与员工管理「删除」同款 —— 默认黑字，hover 才变红 */
table.grid td .btn.btn-danger:not(:disabled):hover { background: var(--danger-soft); color: var(--danger); }

/* ============================================================
   Tabs
   ============================================================ */
.tabs {
  display: flex; gap: 4px; padding: 5px;
  background: var(--bg-paper-2); border-radius: 11px;
  margin-bottom: 14px; flex-shrink: 0; width: fit-content;
}
.tabs button {
  border: none; background: transparent; padding: 7px 14px;
  font-size: 15px; font-weight: 500; cursor: pointer;
  color: var(--ink-500); border-radius: 8px; font-family: inherit;
  transition: all .18s;
}
.tabs button:hover { color: var(--ink-800); }
.tabs button.active {
  background: var(--bg-paper); color: var(--ink-900);
  box-shadow: var(--shadow-sm); font-weight: 600;
}
/* 二级导航行：左侧 tabs + 右侧颜色图例水平对齐 */
.tabs-row {
  display: flex; align-items: center; gap: 12px;
  flex-shrink: 0; margin-bottom: 14px;
}
.tabs-row .tabs { margin-bottom: 0; }
.tabs-row .table-legend { margin-left: auto; margin-bottom: 0; }

/* 全局规则设置视图：card 与滚动区撑满可用高度，避免内容被裁切 */
#view-config { flex: 1 1 0; min-height: 0; display: flex; flex-direction: column; overflow: hidden; }
#view-config > .card { flex: 1 1 0; min-height: 0; display: flex; flex-direction: column; overflow: hidden; }
#view-config #global-config-body { flex: 1 1 0; min-height: 0; overflow: auto; }
/* 20260922a：规则设置页去掉「第 2 层」白卡。
   右侧内容区已是纯白，外层 .card 不再有底色 / 投影 / 圆角 / 内边距
   （flex 高度链那三条继续生效，滚动不受影响），内容直接铺在白底上；
   10 个模块靠 #f5f6f9 浅灰圆角块区分，本身不带任何描边线。 */
#view-config > .card {
  background: transparent;
  box-shadow: none;
  border-radius: 0;
  padding: 0;
}

/* 考勤结果：姓名/部门多选筛选 + 分页 */
.filter-bar { display: flex; align-items: center; gap: 10px; flex-shrink: 0; }
.filter-dd { position: relative; }
.filter-btn {
  display: inline-flex; align-items: center; gap: 4px;
  background: var(--bg-paper); border: 1px solid var(--ink-200);
  border-radius: 8px; padding: 6px 12px; font-size: 14px;
  color: var(--ink-800); cursor: pointer; font-family: inherit;
  min-width: 96px;
}
.filter-btn:hover { border-color: var(--ink-300); }
.filter-btn .muted { color: var(--ink-400); font-size: 12.5px; }
.filter-panel {
  position: fixed; left: 0; top: 0; z-index: 200;
  background: var(--bg-paper); border: 1px solid var(--border-default);
  border-radius: 10px; box-shadow: var(--shadow-lg);
  min-width: 240px; max-width: 320px; min-height: 300px; max-height: 640px;
  display: flex; flex-direction: column; overflow: hidden;
}
.filter-panel-head {
  display: flex; gap: 6px; padding: 8px 10px;
  border-bottom: 1px solid var(--border-default);
  background: var(--bg-paper-2);
}
.filter-list { overflow: auto; padding: 4px 4px 8px; flex: 1 1 auto; min-height: 0; }
.filter-search-wrap { padding: 8px 10px 4px; border-bottom: 1px solid var(--border-default); flex-shrink: 0; }
.filter-search {
  width: 100%; box-sizing: border-box; padding: 7px 10px; font-size: 14px;
  border: 1px solid var(--ink-200); border-radius: 7px;
  background: var(--bg-paper); color: var(--ink-800); outline: none;
  transition: border-color .18s, box-shadow .18s;
}
.filter-search:focus { border-color: var(--accent-500); box-shadow: 0 0 0 3px rgba(var(--accent-glow), 0.10); }
.filter-item {
  display: flex; align-items: center; gap: 8px;
  padding: 7px 12px; min-height: 36px; box-sizing: border-box;
  border-radius: 6px; cursor: pointer;
  font-size: 14px; color: var(--ink-800);
}
.filter-item:hover { background: var(--bg-tinted); }
.filter-item input[type="checkbox"] { margin: 0; width: 15px; height: 15px; flex-shrink: 0; cursor: pointer; }

/* 考勤结果分页 */
.summary-pagination {
  display: flex; align-items: center; gap: 8px; justify-content: flex-end;
  padding-top: 10px; flex-shrink: 0; font-size: 14px;
}
.summary-pagination .page-info { color: var(--ink-500); margin-right: 8px; }
.summary-pagination button:disabled { opacity: 0.45; cursor: not-allowed; }

/* 归档详情页二级 tab（20260915d：mac 卡片切换 / 分段控件风格，与标题行齐平居中）
   20260916a：容器背景改白色，选中段 = 蓝色背景 + 白色字体 */
.page-header.hist-head { position: relative; }
.hist-head .seg-tabs {
  position: absolute; left: 50%;
  /* 20260922d：top:50% 相对 padding box → 必须减去 padding-bottom 的一半，
     才能与左侧「返回 + 标题」处于同一水平线。用变量与 .page-header 联动，
     以后改 padding 不会再错位。 */
  top: calc(50% - var(--ph-pad-bottom, 16px) / 2);
  transform: translate(-50%, -50%);
}
.seg-tabs {
  display: inline-flex; align-items: center; gap: 2px;
  padding: 3px; flex-shrink: 0;
  background: var(--bg-paper);
  border: 1px solid var(--border-default);
  border-radius: 10px;
}
.seg-btn {
  appearance: none; -webkit-appearance: none;
  border: none; background: transparent; font-family: inherit;
  font-size: 13.5px; color: var(--ink-600); cursor: pointer;
  padding: 5px 16px; border-radius: 7px; white-space: nowrap;
  transition: background .16s, color .16s, box-shadow .16s;
}
.seg-btn:hover { color: var(--ink-900); }
.seg-btn.active {
  background: var(--accent-500); color: #fff; font-weight: 600;
  box-shadow: 0 1px 2px rgba(0, 113, 227, 0.28);
}
.seg-btn.active:hover { color: #fff; }
/* 窄屏：分段控件回落为常规流并居中，避免与标题/返回按钮重叠 */
@media (max-width: 1080px) {
  .page-header.hist-head { flex-wrap: wrap; }
  .hist-head .seg-tabs { position: static; transform: none; margin: 0 auto; }
}
.hist-empty {
  padding: 64px 0; display: flex; flex-direction: column;
  align-items: center; gap: 8px; color: var(--ink-400); font-size: 14px;
}

/* ---------- 自定义列录入（20260916a；20260916d 按钮左置 + 边框统一 var(--border-line) + 分页） ---------- */
.cc-head {
  display: flex; align-items: center; gap: 12px;
  flex-wrap: wrap; margin-bottom: 10px; flex-shrink: 0;
}
.cc-actions { display: flex; align-items: center; gap: 10px; }
.cc-actions .cc-dirty-tip { margin-left: 6px; }
.cc-dirty-tip { color: var(--warning); font-size: 13px; }
/* 20260922i：自定义列录入 / 补卡次数管理 —— 去掉容器外框。
   表格自身的 cc-table th/td 已是 1px var(--border-hairline)，容器再描一遍会与最外圈单元格线重叠
   （同色叠加视觉变深、看着像加粗），故容器不画线，外圈线完全交给表格。 */
.cc-wrap {
  overflow: auto; max-height: calc(100vh - 350px);
  border: none; border-radius: 0; background: var(--bg-paper);
}
table.cc-table { border-collapse: collapse; width: 100%; }
table.cc-table th, table.cc-table td {
  border: 1px solid var(--border-hairline); padding: 4px 8px;
  font-size: 14px; color: var(--ink-900); text-align: center; height: 34px;
}
table.cc-table thead th {
  background: var(--bg-paper-2); font-weight: 700; white-space: nowrap;
  position: sticky; top: 0; z-index: 2;
}
table.cc-table td.cc-seq { width: 52px; }
table.cc-table td.cc-name { width: 100px; font-weight: 600; }
table.cc-table td.cc-dept { width: 110px; }
table.cc-table thead th.cc-col { min-width: 110px; }
table.cc-table td.cc-cell { padding: 2px 4px; }
table.cc-table td.cc-dirty { background: var(--accent-50); }
/* 补卡次数管理（20260921b）：表格固定布局 + 表头列定义等宽，
   让「姓名 / 部门 / 补卡次数」三列平均分布（序号列仍保持 52px；
   table-layout:fixed 按第一行 th 定宽 → 宽度必须写在 thead th 上） */
table.cc-table.cc-eqcol { table-layout: fixed; }
table.cc-table.cc-eqcol th.cc-seq { width: 52px; }
table.cc-table.cc-eqcol td.cc-seq { width: 52px; }
table.cc-table.cc-eqcol td.cc-name,
table.cc-table.cc-eqcol td.cc-dept { width: auto; }
table.cc-table.cc-eqcol thead th.cc-col { min-width: 0; width: auto; }
table.cc-table.cc-eqcol th.cc-col, table.cc-table.cc-eqcol td.cc-cell { overflow: hidden; }
/* 输入框：无描边、无 hover 高亮（20260916d）；聚焦只给浅蓝底便于定位 */
.cc-input {
  width: 100%; min-width: 90px; height: 28px; text-align: center;
  border: none; border-radius: 6px;
  background: transparent; font-family: inherit; font-size: 14px; color: var(--ink-900);
  outline: none; box-shadow: none;
}
.cc-input:hover { background: transparent; }
.cc-input:focus { background: var(--accent-50); }
/* 分页（20260916d）：与请假管理一致 */
#cc-pagination { flex-shrink: 0; padding-top: 10px; }

/* ============================================================
   归档详情 · 统计分析（20260916f）：KPI 概览 + TOP10 排名 + 拓展分析
   数据全部来自归档快照（冻结口径），页面只读
   20260916f2：整页铺满视口（不出现页面级滚动，模块内部各自竖向滚动）；
   字号统一 ≥14px（数字可用 mono 字体）；本页去掉 .grid-wrap 描边
   ============================================================ */
/* 仅统计页去掉 #hist-detail-body(.grid-wrap) 描边，不影响其他页面 */
#hist-detail-body.astat-no-frame { border: none; }
/* 整页 = KPI 行（固定高）+ main（吃满剩余高度）；容器本身由 flexbox 撑满。
   窗口高度过小时（下面两行有 min-height 兜底）整页可竖向滚动，不会把图表压扁/裁切 */
.astat-wrap { height: 100%; display: flex; flex-direction: column; overflow: auto; padding: 2px 4px 12px 0; }
/* KPI 概览：2 行 × 每行 4 卡（20260916h） */
.astat-kpis { flex: none; display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; margin-bottom: 12px; }
.astat-kpi {
  border: 1px solid var(--border-line); border-radius: 10px; padding: 10px 12px;
  background: var(--bg-paper); border-left-width: 4px; min-width: 0;
}
.astat-kpi.blue { border-left-color: var(--accent-500); }
.astat-kpi.green { border-left-color: var(--success); }
.astat-kpi.yellow { border-left-color: var(--yellow-500, #d97706); }
.astat-kpi-label { font-size: 14px; color: var(--ink-500); white-space: nowrap; }
.astat-kpi-val { font-family: var(--font-mono); font-size: 20px; font-weight: 700; color: var(--ink-800); margin: 2px 0; white-space: nowrap; }
.astat-kpi-extra { font-size: 14px; color: var(--ink-400); }

/* 20260925t：main 改 flex:none（内容高度）——原 flex:1 1 0 可收缩，内容超高时
   main 被压扁、row1/row2 溢出压住后面的趋势行 row3；超高由 .astat-wrap 滚动承接 */
.astat-main { flex: none; min-height: 0; display: flex; flex-direction: column; gap: 12px; }
/* 20260925v：9 个图表模块（TOP10/部门对比/三张分布图/四张趋势卡）统一单一网格：
   每行 3 个、行高一致（grid-auto-rows 固定 340px）、竖向间距一致（gap 12px）；
   图表容器在卡内自适应填充（flex:1），≤900px 降单列 */
.astat-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; grid-auto-rows: 340px; }
.astat-grid .astat-card { min-height: 0; }
/* 网格内含 ECharts 的卡片体改为填充剩余高度（行高固定，flex:1 才有确定高度可量） */
.astat-grid .astat-card-body:has(> .astat-echart) { flex: 1 1 0; overflow: hidden; display: flex; flex-direction: column; }
.astat-grid .astat-echart { flex: 1 1 0; height: auto; min-height: 0; min-width: 0; }
.astat-echart { height: 240px; min-width: 0; }
/* 20260925t：含 ECharts 的卡片体改内容高度——原 .astat-card-body{flex:1 1 0}
   在 auto 高卡片里假设主尺寸=0，卡片塌掉后 canvas 被 .astat-card overflow:hidden
   裁掉（图表空白）；行高改 auto 后必须让图卡体按内容撑起 */
.astat-card-body:has(> .astat-echart) { flex: 0 0 auto; overflow: hidden; }
@media (max-width: 900px) { .astat-grid { grid-template-columns: 1fr; } }
/* 卡片：占满分配高度，内容超出时在卡片内竖向滚动 */
.astat-card {
  border: 1px solid var(--border-line); border-radius: 10px; background: var(--bg-paper); padding: 12px 14px;
  display: flex; flex-direction: column; min-height: 0; min-width: 0; overflow: hidden;
}
.astat-card-head { flex: none; display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; margin-bottom: 8px; }
.astat-title { font-size: 15px; font-weight: 700; color: var(--ink-800); }
.astat-sub { font-size: 14px; color: var(--ink-400); }
/* 卡头统计行（20260916k / 20260916l 改版）：合计放标题下方、图表上方；
   灰底圆角块 + 大号数字 —— 与下方图表形成明显区分 */
.astat-head-stat {
  flex: none; display: flex; align-items: baseline; gap: 6px;
  margin: 0 0 12px; padding: 8px 12px; border-radius: 8px;
  background: #f1f3f5; border: 1px solid #e5e7eb;
  font-size: 14px; color: var(--ink-500);
}
.astat-head-stat-num {
  font-family: var(--font-mono); font-size: 22px; font-weight: 700;
  color: var(--ink-800); line-height: 1;
}
.astat-head-stat-unit { font-size: 14px; color: var(--ink-500); }
.astat-head-stat-sub { margin-left: auto; font-size: 14px; color: var(--ink-400); }
.astat-card-body { flex: 1 1 0; min-height: 0; overflow: auto; }
/* TOP10 类型切换（chip 横向） */
.astat-chips { flex: none; display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 10px; }
.astat-chip {
  border: 1px solid var(--border-line); background: var(--bg-paper); border-radius: 999px;
  padding: 4px 14px; font-size: 14px; color: var(--ink-500); cursor: pointer;
}
.astat-chip:hover { border-color: var(--ink-200); color: var(--ink-800); }
.astat-chip.active { background: var(--accent-500); border-color: var(--accent-500); color: #fff; }
.astat-unit-seg { display: inline-flex; border: 1px solid var(--border-line); border-radius: 8px; overflow: hidden; }
.astat-unit-seg .seg-btn { border-radius: 0; border: none; box-shadow: none; }
/* TOP10 排名行 */
.astat-rank-list { display: flex; flex-direction: column; gap: 6px; }
.astat-rank-row { display: flex; align-items: center; gap: 10px; }
.astat-rank-no {
  width: 26px; height: 26px; border-radius: 6px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  font-size: 14px; font-weight: 700; background: var(--bg-paper-2); color: var(--ink-500);
}
.astat-rank-no.top1 { background: #fbbf24; color: #7c2d12; }
.astat-rank-no.top2 { background: #d1d5db; color: #374151; }
.astat-rank-no.top3 { background: #fcd9b8; color: #92400e; }
.astat-rank-name { width: 205px; flex-shrink: 0; font-size: 14px; color: var(--ink-800); display: flex; align-items: center; gap: 8px; overflow: hidden; }
/* 20260922k：姓名不可压缩（不换行）；部门占剩余空间、超出省略号
   —— 之前姓名是裸文本节点，会被 nowrap 的部门挤成一个字一行 */
.astat-rank-emp { flex: none; white-space: nowrap; }
.astat-rank-bar { flex: 1; height: 14px; border-radius: 4px; background: var(--bg-paper-2); overflow: hidden; }
.astat-rank-bar-in { height: 100%; border-radius: 4px; background: var(--accent-500); opacity: .85; }
.astat-rank-val { width: 120px; flex-shrink: 0; text-align: right; font-family: var(--font-mono); font-size: 14px; font-weight: 600; color: var(--ink-800); }
.astat-empty { padding: 18px 0; text-align: center; font-size: 14px; color: var(--ink-400); }
/* 分布横条 */
.astat-dist { display: flex; flex-direction: column; gap: 8px; }
.astat-dist-row { display: flex; align-items: center; gap: 10px; }
.astat-dist-name { width: 130px; flex-shrink: 0; font-size: 14px; color: var(--ink-600, #374151); }
.astat-dist-bar { flex: 1; height: 14px; border-radius: 4px; background: var(--bg-paper-2); overflow: hidden; }
.astat-dist-bar-in { height: 100%; border-radius: 4px; background: var(--accent-300, #7cb3f0); }
.astat-dist-val { flex: none; text-align: right; font-family: var(--font-mono); font-size: 14px; color: var(--ink-500); white-space: nowrap; }
/* 三分布卡三种图表（20260916h/l）：环形图 / 半圆仪表盘 / 胶囊柱状图 */
/* 卡片变矮时用 safe center（溢出时不向上裁切，改为向下可滚动） */
.astat-donut-flex { display: flex; align-items: safe center; gap: 16px; height: 100%; min-height: 0; }
.astat-donut { width: 172px; height: 172px; flex: none; max-width: 100%; max-height: 100%; }
.astat-donut-num { font-family: var(--font-mono); font-size: 26px; font-weight: 700; fill: var(--ink-800, #111827); }
.astat-donut-unit { font-size: 14px; fill: var(--ink-400, #9ca3af); }
.astat-legend { display: flex; flex-direction: column; gap: 9px; min-width: 0; flex: 1; }
.astat-legend-row { display: flex; align-items: center; gap: 8px; font-size: 14px; min-width: 0; }
.astat-legend-dot { width: 12px; height: 12px; border-radius: 3px; flex: none; }
.astat-legend-name { color: var(--ink-600, #374151); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.astat-legend-val { margin-left: auto; font-family: var(--font-mono); font-size: 14px; color: var(--ink-500); white-space: nowrap; }
/* 半圆仪表盘（20260916l，加班构成）：三类并排铺满卡片宽度、垂直居中；
   环身按可用高度缩放（min-height:0 + flex），卡片变矮时不会被裁掉 */
.astat-gauges { display: flex; align-items: stretch; gap: 10px; height: 100%; min-height: 0; }
.astat-gauge {
  flex: 1 1 0; min-width: 0; min-height: 0; display: flex; flex-direction: column;
  align-items: center; justify-content: safe center; gap: 4px;
}
.astat-gauge-box {
  position: relative; flex: 1 1 0; min-height: 0; width: 100%; max-width: 168px;
  display: flex; align-items: flex-end; justify-content: center;
}
.astat-gauge-svg { display: block; height: 100%; width: auto; max-width: 100%; }
.astat-gauge-pct {
  position: absolute; left: 0; right: 0; bottom: 1px; text-align: center;
  font-family: var(--font-mono); font-size: 18px; font-weight: 700; color: var(--ink-800);
  line-height: 1;
}
.astat-gauge-pctu { font-size: 14px; font-weight: 600; color: var(--ink-400); margin-left: 1px; }
.astat-gauge-name { flex: none; font-size: 14px; color: var(--ink-600, #374151); white-space: nowrap; }
.astat-gauge-val { flex: none; font-family: var(--font-mono); font-size: 14px; color: var(--ink-500); white-space: nowrap; }
/* 柱状图（出勤率分布）：柱高按可用高度自适应（轨道百分比），柱身胶囊形（四角圆角取最大 = 半圆） */
.astat-cols { display: flex; gap: 12px; align-items: stretch; height: 100%; min-height: 0; padding-top: 4px; }
.astat-col { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 6px; min-width: 0; min-height: 0; }
.astat-col-val { flex: none; font-family: var(--font-mono); font-size: 14px; font-weight: 600; color: var(--ink-600, #374151); white-space: nowrap; }
.astat-col-track { flex: 1 1 0; min-height: 0; width: 100%; display: flex; align-items: flex-end; justify-content: center; }
.astat-col-bar { width: 34%; max-width: 30px; min-width: 14px; border-radius: 999px; background: var(--accent-300, #7cb3f0); }
.astat-col-bar.empty { background: var(--bg-paper-2); }
.astat-col-name { flex: none; font-size: 14px; color: var(--ink-500); white-space: nowrap; }
/* 部门对比表 */
.astat-table { border-collapse: collapse; width: 100%; }
.astat-table th, .astat-table td { border-bottom: 1px solid var(--border-hairline); padding: 7px 10px; font-size: 14px; text-align: center; color: var(--ink-800); white-space: nowrap; }
.astat-table thead th { color: var(--ink-500); font-weight: 600; background: var(--bg-paper-2); white-space: nowrap; }
.astat-table .astat-td-name { text-align: left; font-weight: 600; }

/* ============================================================
   规则配置（分类卡片布局）
   ============================================================ */
.config-pane { flex: 1 1 0; min-height: 0; align-self: stretch; overflow: auto; padding: 2px 4px 16px 0; }
/* 规则设置：左侧快速切换菜单 + 右侧内容 */
.config-wrap { flex: 1; min-height: 0; display: flex; gap: 18px; align-items: stretch; }
.config-sidenav { width: 168px; flex: none; display: flex; flex-direction: column; gap: 4px; overflow: auto; padding: 2px 4px 16px 0; }
.config-nav-item { display: flex; align-items: center; gap: 8px; padding: 9px 12px; border: 1px solid transparent; background: transparent; border-radius: 8px; color: var(--ink-600); font-size: 13.5px; cursor: pointer; text-align: left; font-family: inherit; line-height: 1.4; transition: background .15s, color .15s; }
.config-nav-item:hover { background: var(--bg-paper-2); color: var(--ink-900); }
.config-nav-item.active { background: var(--bg-paper-2); border-color: transparent; color: var(--ink-900); font-weight: 600; }
.config-nav-num { font-family: var(--font-mono); font-size: 12px; color: var(--ink-400); flex: none; }
.config-nav-item.active .config-nav-num { color: var(--accent); }
#global-config-body { scroll-margin-top: 12px; }
.cfg-card { scroll-margin-top: 12px; }
/* 多班次+多类型：由考勤组设置的字段锁定 */
.cfg-locked { opacity: .6; }
.cfg-locked input, .cfg-locked select { cursor: not-allowed; }
.cfg-lock-badge { display: inline-flex; align-items: center; gap: 3px; margin-left: 7px; font-size: 11px; font-weight: 500; color: var(--accent); background: color-mix(in srgb, var(--accent) 10%, transparent); border: 1px solid color-mix(in srgb, var(--accent) 35%, transparent); border-radius: 999px; padding: 1px 8px; vertical-align: middle; line-height: 1.6; }
.chip-locked { opacity: .55; cursor: not-allowed; }
/* 20261025b：.cfg-group-mode-tip（「已选择多个班次…已锁定」提示条）随 DOM 一起下线 */

.cfg-hero {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 24px; margin-bottom: 20px;
}
.cfg-hero .eyebrow {
  font-size: 13.5px; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--ink-400); font-weight: 600; margin-bottom: 8px;
  display: flex; align-items: center; gap: 8px;
}
.cfg-hero .eyebrow::before { content: ''; width: 18px; height: 1px; background: var(--ink-300); }
.cfg-hero .title {
  font-size: 28px; line-height: 1.25;
  letter-spacing: -0.01em; color: var(--ink-900); font-weight: 700;
}
.cfg-hero .title .num { font-family: var(--font-mono); font-size: 0.85em; }
.cfg-hero .title .punct { color: var(--ink-300); margin: 0 6px; }
.cfg-hero .sub { color: var(--ink-500); font-size: 15px; max-width: 520px; margin-top: 8px; line-height: 1.6; }

/* 配置卡片 */
.cfg-card {
  background: var(--bg-paper);
  border: none;
  border-radius: var(--radius-lg);
  margin-bottom: 16px;
  overflow: hidden;
}
.cfg-card-head {
  padding: 20px 24px 16px;
  display: flex; justify-content: space-between; align-items: flex-start; gap: 16px;
  /* 20260922a：去掉标题下划线，模块内不再有任何分隔描边 */
}
.cfg-card-head-left { display: flex; gap: 14px; align-items: flex-start; flex: 1; min-width: 0; }
.cfg-card-num {
  width: 32px; height: 32px; border-radius: 8px;
  /* 20260922a：去掉描边，只留强调色底（macOS 图标块风格） */
  background: var(--accent-50);
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-mono); font-size: 17px;
  color: var(--accent-600); font-weight: 600; flex-shrink: 0;
}
.cfg-card-title { font-size: 17.5px; font-weight: 600; color: var(--ink-800); }
.cfg-card-sub { font-size: 14.5px; color: var(--ink-400); margin-top: 3px; }
.cfg-card-status {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 10px; border-radius: 999px; font-size: 13.5px; font-weight: 500;
  background: var(--success-soft); color: var(--success); white-space: nowrap;
}
.cfg-card-status.pending { background: var(--warning-soft); color: var(--warning); }
.cfg-card-status .dot { width: 5px; height: 5px; border-radius: 50%; background: currentColor; }

.cfg-card-body { padding: 20px 24px 22px; }
.cfg-card-foot {
  /* 20260922a：去掉上边线与灰底条，保持模块内部纯平 */
  padding: 12px 24px; display: flex; align-items: center; justify-content: space-between;
  font-size: 14.5px; color: var(--ink-500);
}

/* ---------- 规则设置各模块底色（20260921a 改灰底；20260922a 去描边） ----------
   01~10 统一为**浅灰底 #f5f6f9 圆角块**（与左侧菜单同色），不再有边框：
   去掉第 2 层白卡后，模块是页面上唯一的「面」，靠底色与间距区分边界。 */
.cfg-card[class*="cfg-tint-"] {
  background: var(--bg-paper-2);
  border: none;
}

/* 分区标题 */
.section-divider {
  display: flex; align-items: center; gap: 12px;
  margin: 16px 0 12px; color: var(--ink-500);
  font-size: 14px; letter-spacing: 0.06em; font-weight: 600;
}
.section-divider::before, .section-divider::after { content: ''; flex: 1; height: 1px; background: var(--border-default); }
.section-divider:first-child { margin-top: 0; }

/* 字段网格 */
.field-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 18px 22px; }
.field-grid.cols-3 { grid-template-columns: repeat(3, 1fr); }
.field-grid.cols-4 { grid-template-columns: repeat(4, 1fr); }
/* 五栏（20260914i：全勤规则「开关+奖金」+ 规则1~4 同一行）
   20260919e 按用户要求把本类改为 **6 个等宽轨（repeat(6, 2fr)）**：
   全勤规则 5 个字段各占 1 轨、末尾第 6 轨留空 —— 这样每栏宽度 = 行宽 1/6，
   与「07 补贴规则」的 cols-6 完全对齐（此前 5 等分与上下区块的 6 等分错位）。
   ⚠️ cols-5 目前仅「09 全勤规则」使用，故直接改本类不影响其它区块。 */
.field-grid.cols-5 { grid-template-columns: repeat(6, 2fr); }
/* 六栏（20260914b：补贴规则「夜宵三栏 + 夜班三栏」同一行） */
.field-grid.cols-6 { grid-template-columns: repeat(6, 1fr); }
/* 八栏（20260919d：02「上下班时间」一行放下 7 个时间字段 + 1 个空列）——
   整行按 **8 列等宽**分布（每列 = 行宽 1/8）：左 4 栏（上班/午休开始/午休结束/下班）
   占第 1~4 列，右 3 栏（晚间吃饭开始/结束/超过几点扣晚间吃饭时长）占第 5~7 列，
   第 8 列留空。20260919c 的 repeat(4,5fr) repeat(3,7fr) 是「7 列平均分布」，
   列宽与页面其它区块的节奏不一致（用户反馈「没对齐」），故按 8 列重写。
   ⚠️ 这里不再给 .field-label 设 min-height：标签换行高度参差改由「输入框 margin-top:auto」
   兜底（见下），既保证同排输入框纵向对齐，又不会把整行撑得比其它区块高。 */
.field-grid.cols-8 { grid-template-columns: repeat(8, 1fr); }
.field-grid.cols-8 .field-label {
  /* 标签允许换行（每列仅约 1/8 行宽，12 字标签会排到 2 行） */
  flex-wrap: wrap;
  align-items: flex-start;
  align-content: flex-start;
  row-gap: 3px;
}
/* 同排各列标签行数不等（1 行 / 2 行）→ 用 auto 外边距把输入框压到单元格底部：
   网格行内的格子被拉伸成等高、输入框自身高度一致，故底边与顶边自然对齐，无需写死 min-height */
.field-grid.cols-8 .field > .input-wrap { margin-top: auto; }
/* 八栏单列仅约 116px：「考勤组设置」徽章换到单独一行，否则标题会被挤成「上班时 / 间」 */
.field-grid.cols-8 .cfg-lock-badge { flex-basis: 100%; width: fit-content; margin-left: 0; }

/* 标题右侧提示图标（20260919c）：把较长的字段说明从字段下方移到标题行，
   鼠标经过（或键盘聚焦）时气泡显示。因 .cfg-card 是 overflow:hidden，
   气泡向下展开（覆盖在输入框上方），不会被卡片裁掉。
   20261013e：全部字段提示统一走本图标后，窄栏（cols-6 约 137px）里
   15px 图标 + 标题行 gap:6px + 图标 margin-left:5px 会吃掉 26px，
   把 8 字标题（如「规则1：出勤天数」「是否统计超时天数」）挤成「……天 / 数」两行
   ⇒ 只在该行存在提示图标时把间距收到 3px + 图标 margin 归零（合省 8px）。
   ⚠️ 只覆盖 .field-label 内的图标，其它位置（.ck-legend、选项 chip 等）保持原样。 */
.field-label:has(.cfg-tip) { gap: 2px; }
.field-label .cfg-tip { margin-left: 0; width: 14px; height: 14px; }
.field-label .cfg-tip svg { width: 14px; height: 14px; }
.cfg-tip {
  position: relative; display: inline-flex; align-items: center; justify-content: center;
  width: 15px; height: 15px; margin-left: 5px; flex: 0 0 auto;
  color: var(--ink-300); cursor: help; vertical-align: middle;
}
.cfg-tip:hover, .cfg-tip:focus-visible { color: var(--accent-500); outline: none; }
.cfg-tip svg { display: block; }
.cfg-tip-bubble {
  position: absolute; top: calc(100% + 8px); left: 50%; transform: translateX(-50%);
  width: max-content; max-width: 320px; padding: 8px 11px; border-radius: 8px;
  /* 20260928r：深浅模式统一黑底白字（原 --ink-800 深色下反转成白底刺眼） */
  background: #1d1f24; color: #fff;
  font-size: 12.5px; font-weight: 400; line-height: 1.6; letter-spacing: 0;
  text-align: left; white-space: pre-line;   /* 20260928c：支持 tip 内 \n 分行（如两种出勤规则各一行） */
  opacity: 0; visibility: hidden; transition: opacity .14s ease;
  pointer-events: none; z-index: 2100; box-shadow: 0 8px 24px rgba(13, 17, 23, .24);
  /* 20260929k：气泡提层到 2100——原 60 低于 modal-mask(1000)，异常检查等弹框内
     的提示图标气泡下半截被弹框盖住（表现为高度不对） */
}
.cfg-tip-bubble::before {
  content: ''; position: absolute; left: 50%; bottom: 100%; margin-left: -5px;
  border: 5px solid transparent; border-bottom-color: #1d1f24;
}
/* 20260925n：气泡改 fixed + JS 定位后，底部放不下时向上翻（箭头移到底部、指向下） */
.cfg-tip-bubble[data-arrow="up"]::before {
  bottom: auto; top: 100%;
  border-bottom-color: transparent; border-top-color: #1d1f24;
}
.cfg-tip:hover .cfg-tip-bubble, .cfg-tip:focus-visible .cfg-tip-bubble {
  opacity: 1; visibility: visible;
}
/* 20260925s：点击图标弹出（班次弹窗等场景）——再次点击/点空白关闭 */
.cfg-tip.cfg-tip-open { color: var(--accent-500); }
.cfg-tip.cfg-tip-open .cfg-tip-bubble { opacity: 1; visibility: visible; }
/* 分行配置（sec.rows）：行式布局下每行都是 field-grid，字段自带 12px 上下内距 +
   底部分割线 ⇒ 再加 20px 会让模块间距忽大忽小（用户 20261020v 定版：去掉，改为 0） */
.cfg-card-body .field-grid + .field-grid { margin-top: 0; }
/* 配置子集面板（20261019d）：给「只在父字段某个取值下才出现」的字段一个缩进容器
   （04 迟到早退规则：迟到/早退阶梯扣款 = 扣款类型的子集）。左侧 3px 竖线 + 浅底
   + 右侧圆角，与父行（扣款类型行）形成明确的从属层级；面板内相邻行间距收到 14px，
   与面板外的 20px 区分开。面板由 .cfg-subset 的显隐随内部字段整体收起。
   ⚠️ 只做间距/底色/描边，不碰字号（窄栏裁切一律不改字号）。 */
.cfg-subset {
  margin-top: 16px; padding: 14px 16px 16px;
  border: 1px solid var(--ink-100); border-left: 3px solid var(--ink-200);
  border-radius: 0 12px 12px 0; background: var(--bg-soft, #f8fafc);
}
.cfg-subset-title {
  flex: 1 1 auto; min-width: 0;
  font-size: 13.5px; font-weight: 500; color: var(--ink-400); line-height: 1.4;
  letter-spacing: .02em;
}
.cfg-subset .field-grid + .field-grid { margin-top: 14px; }
/* 子集面板标题行（20261019d）：标题靠左，父字段派生的行内小控件（04 的「扣除类型」）
   靠右同一行 —— 该控件只在父字段取特定值时才出现（syncDeductUI 控显隐）。
   控件里的 .field 改成横向：标签在左、下拉在右，整行高度与一行文本一致，不额外占高。 */
.cfg-subset-head {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  margin-bottom: 12px;
}
.cfg-subset-ctrl { flex: 0 0 auto; width: 258px; }
.cfg-subset-ctrl .field { flex-direction: row; align-items: center; gap: 8px; }
.cfg-subset-ctrl .field-label { white-space: nowrap; }
.cfg-subset-ctrl .field > select.input { flex: 1 1 auto; min-width: 0; }
/* 扣款类型只读反显（20261019e）：04 区块的扣款类型不再直接选，改为「反显当前值 + 标题右侧『配置』」
   （点配置弹窗里设置，见 .dm-box）。
   🔴 20261019e 用户口径：「不要用禁用状态样式」—— 故用**白底 + 正常文字色**（与只读文本一致），
   不做灰底/降透明度/灰字；只把边框压到最淡一档，提示「这里不是下拉，去右侧配置」。
   🔴 窄栏一律不改字号（本项目铁律）。 */
/* 🔴 20261019f 用户口径：本行 6 栏**均分**（扣款类型各自 1 栏 + 4 个旷工阈值各 1 栏），
   且**六个体框必须完全一致** ——
   ① 描边同色 --ink-200（与全局 .input-wrap 同色，原来只读框用 ink-100 显得更淡）；
   ② 同高：「按分钟次数扣时长/费用」在 1 栏（163px）里放不下 ⇒ 只读框折 2 行变高，
      故让数字字段的 .input-wrap 撑满字段剩余高度、内部 input 100% 高，跟着一起变高；
      绝不把只读框压成单行裁字（🔴 本项目禁止裁字 / 缩字号）。 */
.deduct-ro {
  display: flex; align-items: center; min-height: 39px;
  padding: 8px 11px;
  border: 1px solid var(--ink-200); border-radius: var(--radius-md);
  background: var(--bg-paper);
  font-size: 15.5px; line-height: 1.35; color: var(--ink-800);
}
.deduct-ro-val { min-width: 0; white-space: normal; word-break: break-word; }
/* 1 栏只有 163px：标题 90px + ⓘ 20 + 「配置」28 已接近满宽 ⇒ 允许标题行折行，
   按钮紧跟标题（margin-left 固定，不用 auto，避免窄栏被挤出容器）。 */
.cfg-deduct-types > .field > .field-label { flex-wrap: wrap; row-gap: 2px; }
.cfg-deduct-btn,
.deduct-cfg-btn { flex: 0 0 auto; margin-left: 6px; font-size: 13.5px; }
/* 同排数字输入框跟随只读框高度（体框一致的②） */
.cfg-deduct-types > .field > .input-wrap { flex: 1 1 auto; }
.cfg-deduct-types > .field > .input-wrap > .input { height: 100%; }
/* 影子容器（20261019e）：扣款配置弹窗的数据源 / 写回目标字段，整块不可见。
   🔴 只隐藏这一层，内部字段保持可见态（style.display 为 ''），否则 saveConfig
   会把它们当成「隐藏字段」跳过采集。 */
.cfg-shadow { display: none !important; }
.field { display: flex; flex-direction: column; gap: 7px; min-width: 0; }
.field.col-span-2 { grid-column: span 2; }
/* 跨 3 栏（20260914c：补贴规则「午餐补贴金额」占左半，右半放晚餐三栏） */
.field.col-span-3 { grid-column: span 3; }
/* 跨 4 栏（20261019f）：04 扣款类型行的「旷工阈值 4 小格」整体占右 4 栏，
   与左 2 栏的两个扣款类型合起来正好 6 栏均分（每栏 = 1 个字段 / 1 个小格）。 */
.field.col-span-4 { grid-column: span 4; }
/* 组合字段：同列内上下排列多个子字段（输入区与上下行等宽） */
.field-group-col { display: flex; flex-direction: column; gap: 16px; min-width: 0; }
/* 纵向内容居中（如开关列对齐左侧多字段组高度） */
.field-center { justify-content: center; }
.field-label { font-size: 15px; font-weight: 500; color: var(--ink-900); display: flex; align-items: center; gap: 6px; }
.field-label .req { color: var(--danger); font-weight: 700; }
.field-help { font-size: 13.5px; color: var(--ink-400); line-height: 1.5; }
/* 提示不折行（20260915a）：请假类型区下方两行的说明文字单行显示（文字已精简） */
.field.help-nowrap .field-help,
.field.help-nowrap .lt-days-hint,
.field.help-nowrap .switch-row .muted { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* 输入包装 */
.input-wrap {
  position: relative; display: flex; align-items: center;
  background: var(--bg-paper); border: 1px solid var(--ink-200);
  border-radius: var(--radius-md); transition: all .18s;
}
.input-wrap:hover { border-color: var(--ink-300); }
.input-wrap:focus-within { border-color: var(--accent-500); box-shadow: 0 0 0 4px rgba(var(--accent-glow), 0.10); }
.input-wrap .input {
  flex: 1; border: none; background-color: transparent; padding: 9px 13px;
  /* 🔴 20261017j：原为简写 `background: transparent` —— 会把全站 select 的自绘箭头
     background-image（文末「全站下拉选择框箭头统一」规则）一并清掉，凡 select.input
     出现在 .input-wrap 内就变成无箭头文本框（2885 行注释同坑复发）。改 background-color
     只清底色、保住箭头。 */
  font-size: 16px; font-family: inherit; color: var(--ink-800); outline: none; width: 100%;
}
.input-wrap .input.mono { font-family: var(--font-mono); }
.input-suffix {
  padding-right: 13px; color: var(--ink-400); font-size: 14px;
  font-family: var(--font-mono); user-select: none;
}
/* 考勤周期「开始和结束日期」合并字段（20260919e）：同一个带边框的容器里放两个数字输入
   （开始 / 结束），中间以「—」连接，末尾统一标「日」。两个输入等分容器宽度，
   整体宽度与同排其它单输入字段一致（都占 1 栏）。 */
.input-wrap.cyc-range .input { padding-left: 12px; padding-right: 8px; text-align: center; }
.input-wrap.cyc-range .cyc-sep {
  flex: 0 0 auto; padding: 0 1px; color: var(--ink-300); font-size: 14px; user-select: none;
}
/* 02 上下班时间「合并时段」组件（20261013d）：一个带边框容器内放两个 time 输入
   （如「上班-下班时间」= start_time — end_time），整体宽度与同排单输入字段一致
   （1 栏）。🔴 一栏 6 项时单栏仅约 137px，两个字（各 ≈60px）+ 分隔符刚好塞满，
   而原生 time 输入自带表头图标（≈13px）与内边距 —— 不处理会被裁成「08:0」。
   故本组件内：①隐藏原生选择器图标（🔴 20261013d 二次修正：先前靠「字号 13.5px」
   省宽度，用户反馈「设置时间后字体被调小了」——时间值就是这个框的主体内容，
   字号必须与其它输入框一致；改由「去掉图标 + 内边距归零」腾出宽度，实测
   '08:00' 在 16px 下约 48px，双框 96px + 分隔符，1 栏内完整显示不裁切）；
   ②去掉左侧时钟装饰（两个时间之间已有「—」，语义明确）；
   ③两个输入 flex:1 1 0 + min-width:0 等分容器。 */
.input-wrap.time-range .input {
  flex: 1 1 0; min-width: 0; width: auto;
  padding: 9px 0; font-size: 16px; text-align: center;
}
.input-wrap.time-range .input::-webkit-calendar-picker-indicator { display: none; }
.input-wrap.time-range .time-sep {
  flex: 0 0 auto; padding: 0; color: var(--ink-300); font-size: 15px; user-select: none;
}
/* 02 上下班时间两行（一栏 6 项）标签长短不一（「晚间吃饭开始/结束时间（选填）」
   会排到 2 行）→ 允许标签换行，并把控件压到单元格底部，保证同排控件纵向对齐
   （口径同 .field-grid.cols-8 的既有处理，作用域限定本行，不影响其它 cols-6 区块）。
   20261013e（用户反馈「自由打卡选项高度和右侧上下班时间高度不一致，没对齐」）：
   原规则只覆盖 .input-wrap，两处漏网 ⇒
     ①「是否自由打卡」是 select 字段，DOM 为 .field > select.input（没有 .input-wrap 外壳）
        ⇒ 拿不到 margin-top:auto，紧贴标签，而同排时间组件被压到底 ⇒ 垂直错位；
     ②同排控件自然高度本就参差：time_range 双框 39px（隐藏了原生表头图标）、
        带时钟图标的时间框 41px、下拉框 37px（全局 select padding 8px）⇒ 即便底对齐，顶边也参差。
   故本行统一：把 select / .select-wrap / .flex-inline-row 一并纳入底对齐，并给全部控件
   钉同一高度 42px（比原来最高的 43px 略收，视觉上与原尺寸一致）。 */
.field-grid.cfg-time-grid .field-label {
  flex-wrap: wrap; align-items: flex-start; align-content: flex-start; row-gap: 3px;
}
.field-grid.cfg-time-grid .field > .input-wrap,
.field-grid.cfg-time-grid .field > .select-wrap,
.field-grid.cfg-time-grid .field > select.input,
.field-grid.cfg-time-grid .field > .flex-inline-row { margin-top: auto; height: 42px; }
.field-grid.cfg-time-grid .field > .select-wrap select,
.field-grid.cfg-time-grid .field > .flex-inline-row .select-wrap,
.field-grid.cfg-time-grid .field > .flex-inline-row .select-wrap select,
.field-grid.cfg-time-grid .field > .flex-inline-row input[type="number"] { height: 100%; }

/* 下拉 */
.select-wrap { position: relative; }
.select-wrap select {
  appearance: none; width: 100%;
  border: 1px solid var(--ink-200); border-radius: var(--radius-md);
  padding: 9px 26px 9px 13px; font-size: 16px; font-family: inherit;
  color: var(--ink-800); background-color: var(--bg-paper); cursor: pointer;
}
.select-wrap select:hover { border-color: var(--ink-300); }
.select-wrap select:focus { border-color: var(--accent-500); box-shadow: 0 0 0 4px rgba(var(--accent-glow), 0.10); }

/* 开关 */
.switch { position: relative; display: inline-block; width: 40px; height: 22px; flex-shrink: 0; }
.switch input { opacity: 0; width: 0; height: 0; }
.switch .slider {
  position: absolute; inset: 0; background: var(--ink-200);
  border-radius: 999px; cursor: pointer; transition: background .2s;
}
.switch .slider::before {
  content: ''; position: absolute; width: 16px; height: 16px; border-radius: 50%;
  background: var(--bg-card); top: 3px; left: 3px; transition: transform .2s;
  box-shadow: var(--shadow-xs);
}
.switch input:checked + .slider { background: var(--accent-500); }
.switch input:checked + .slider::before { transform: translateX(18px); }
.switch-row { display: flex; align-items: center; gap: 10px; padding: 8px 0; flex-wrap: wrap; row-gap: 4px; }

/* 取整区间编辑器：两个区间编辑器左右并排（横向布局），区间内 7 元素一行横排 */
.interval-field { grid-column: span 1; }
.interval-list { display: flex; flex-direction: column; gap: 10px; }
.interval-row {
  display: flex !important;
  flex-direction: row !important;
  flex-wrap: nowrap;
  align-items: center;
  gap: 6px;
  padding: 4px 0;
}
.interval-input {
  width: 72px !important;
  min-width: 72px;
  max-width: 72px;
  flex: 0 0 72px !important;
  padding: 7px 4px;
  text-align: center;
  font-size: 15px;
  box-sizing: border-box;
}
.interval-sep, .interval-arrow, .interval-unit {
  color: var(--ink-400);
  font-size: 14px;
  white-space: nowrap;
  user-select: none;
  flex-shrink: 0;
}
.interval-unit { font-size: 13px; }
.interval-add { align-self: flex-start; margin-top: 4px; }
/* 一键应用正班时长取整规则（20260925k 改 .link-btn 蓝色文字无背景，与「一键应用迟到规则」同款，
   挂「加班时长取整区间」标题右侧，与标题留一点距离） */
.interval-apply { flex: 0 0 auto; margin-left: 10px; white-space: nowrap; }
.interval-del {
  width: 26px !important;
  min-width: 26px;
  height: 26px;
  padding: 0;
  border-radius: 6px;
  font-size: 15px;
  line-height: 1;
  flex: 0 0 26px;
}

/* 分类筛选 chips（tab 样式） */
.cat-tabs {
  display: flex; gap: 4px; padding: 4px;
  background: var(--bg-paper-2); border-radius: 9px; margin-bottom: 14px;
  width: fit-content; flex-wrap: wrap;
}
.cat-tab {
  padding: 6px 12px; font-size: 14.5px; font-weight: 500;
  border-radius: 6px; color: var(--ink-500); cursor: pointer;
  border: none; background: transparent; font-family: inherit;
  transition: all .18s; display: inline-flex; align-items: center; gap: 6px;
}
.cat-tab:hover { color: var(--ink-800); }
.cat-tab.active { background: var(--bg-paper); color: var(--ink-900); box-shadow: var(--shadow-xs); }
.cat-tab .count {
  font-family: var(--font-mono); font-size: 12px; padding: 1px 6px;
  border-radius: 3px; background: var(--bg-paper-2); color: var(--ink-500);
}
.cat-tab.active .count { background: var(--accent-50); color: var(--accent-700); }

/* 多选 chip */
.chip-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; }
.chip-grid.cols-3 { grid-template-columns: repeat(3, 1fr); }
.chip-grid.cols-6 { grid-template-columns: repeat(6, 1fr); }
.chip {
  display: flex; align-items: center; gap: 10px;
  padding: 11px 13px; border: 1px solid var(--border-default);
  border-radius: var(--radius-md); background: var(--bg-paper);
  cursor: pointer; transition: all .18s var(--ease-out-quart);
  user-select: none; position: relative;
}
.chip:hover { border-color: var(--ink-200); }
.chip.checked {
  /* 20260928r：选中不再变背景/描边（原蓝渐变+蓝描边），只留右侧打勾 —— 深浅模式一致 */
  background: var(--bg-paper); border-color: var(--border-default); box-shadow: none;
}
/* 20261035d（用户 2026-10-27）：多选框左侧小方块改为「未选灰 / 选中蓝」两态，
   原先恒为蓝色 ⇒ 未勾选的项看着也像已勾选，与右侧打勾框表达冲突。 */
.chip-dot {
  width: 10px; height: 10px; border-radius: 3px; flex-shrink: 0;
  background: var(--ink-300); transition: background .18s var(--ease-out-quart);
}
.chip.checked .chip-dot { background: var(--accent-500); }
.chip-label {
  flex: 1; min-width: 0; font-size: 15px; font-weight: 500; color: var(--ink-700);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.chip.checked .chip-label { color: var(--ink-900); }
.chip-check {
  width: 16px; height: 16px; border-radius: 4px;
  border: 1.5px solid var(--ink-200); display: flex; align-items: center; justify-content: center;
  flex-shrink: 0; background: var(--bg-paper); color: #fff; transition: all .18s;
}
.chip-check svg { opacity: 0; transition: opacity .12s; }
.chip.checked .chip-check { background: var(--accent-500); border-color: var(--accent-500); }
.chip.checked .chip-check svg { opacity: 1; }

/* 小 stat tile（卡片内） */
.tile-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; margin-top: 16px; }
.tile {
  padding: 14px 16px; background: var(--bg-paper-2);
  border: 1px solid var(--border-default); border-radius: var(--radius-md);
}
.tile.accent { background: var(--accent-50); border-color: rgba(var(--accent-glow), 0.20); }
.tile-label { font-size: 13px; color: var(--ink-500); margin-bottom: 5px; font-weight: 600; }
.tile-value { font-family: var(--font-mono); font-size: 22px; font-weight: 600; color: var(--ink-800); line-height: 1; }
.tile-value .unit { font-size: 13px; color: var(--ink-400); margin-left: 2px; font-weight: 400; }
.tile-foot { font-size: 13px; color: var(--ink-400); margin-top: 4px; }

/* 信息提示条 */
.tip-box {
  margin-top: 16px; padding: 12px 16px; border-radius: var(--radius-md);
  background: var(--accent-50); border: 1px solid rgba(var(--accent-glow), 0.18);
  display: flex; gap: 10px; align-items: flex-start;
}
.tip-box .tip-icon { color: var(--accent-600); margin-top: 1px; flex-shrink: 0; display: flex; }
.tip-box .tip-title { font-size: 15px; font-weight: 500; color: var(--ink-800); margin-bottom: 2px; }
.tip-box .tip-text { font-size: 14px; color: var(--ink-500); line-height: 1.5; }

/* 底部操作条（配置页） */
.cfg-actions {
  position: sticky; bottom: 0;
  margin: 4px -4px 0;
  padding: 14px 0 6px;
  background: linear-gradient(180deg, rgba(238,241,246,0) 0%, var(--bg-canvas) 30%);
  display: flex; align-items: center; gap: 10px;
}
.cfg-actions .grow { flex: 1; }

/* ============================================================
   占位页 / 其它
   ============================================================ */
.placeholder-page {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  flex: 1; color: var(--ink-400); font-size: 17px; gap: 10px;
  background: var(--bg-paper); border-radius: var(--radius-lg);
  border: 1px dashed var(--border-default);
}
.placeholder-page .big { font-size: 30px; font-weight: 700; color: var(--ink-300); letter-spacing: 3px; }
.placeholder-page .sub { font-size: 15px; }

.perms-box { display: flex; flex-wrap: wrap; gap: 8px 12px; }
.perms-box label { display: flex; align-items: center; gap: 5px; font-size: 15px; }
.scroll-x { overflow-x: auto; }
#proj-list, #hist-list { flex: 1; min-height: 0; overflow: auto; }

.hidden { display: none !important; }

/* ============================================================
   响应式
   ============================================================ */
@media (max-width: 1100px) {
  .field-grid.cols-3 { grid-template-columns: repeat(2, 1fr); }
  .field-grid.cols-4 { grid-template-columns: repeat(2, 1fr); }
  .field-grid.cols-5 { grid-template-columns: repeat(3, 1fr); }
  .field-grid.cols-6 { grid-template-columns: repeat(3, 1fr); }
  /* 20260919c：七栏行回落到两栏（左右各半 → 两列），标签恢复自然高度 */
  .field-grid.cols-8 { grid-template-columns: repeat(4, 1fr); }
  .chip-grid, .chip-grid.cols-6 { grid-template-columns: repeat(3, 1fr); }
  .tile-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 900px) {
  .stat-grid { grid-template-columns: repeat(2, 1fr); }
  .sidebar { width: 64px; }
  /* 窄屏（64px 侧栏）：横版 logo 放不下 → 裁出左侧圆形树懒部分当图标 */
  .sidebar-brand .logo img {
    width: 36px; height: 36px; object-fit: cover; object-position: left center;
  }
  .side-item span:not(.icon):not(.badge),
  .sidebar-user .u-info { display: none; }
  /* 窄屏侧栏（20260923a）：64px 放不下试用期文字与「我要订阅」按钮 →
     整块隐藏；订阅入口改从「点头像 → 个人信息页 → 订阅状态」进入（顶栏 pill 已移除）。 */
  .sub-user-row { display: none; }
  /* 窄屏侧栏（20260923g）：管理后台的「退出登录」是 4 个汉字 + .btn 默认 nowrap，
     在 64px 侧栏里会横向溢出到内容区 → 缩字号并允许折成两行 */
  .btn.adm-logout {
    width: 44px; margin: 0 auto 12px; padding: 6px 2px;
    font-size: 10.5px; line-height: 1.1; white-space: normal;
  }
  .side-item { justify-content: center; padding: 12px; }
  .field-grid, .field-grid.cols-3, .field-grid.cols-4,
  .field-grid.cols-5, .field-grid.cols-6, .field-grid.cols-8 { grid-template-columns: 1fr; }
  /* 单列时取消跨列，避免 span 撑出隐式列导致溢出 */
  .field.col-span-2, .field.col-span-3 { grid-column: span 1; }
  .group-form-2col { grid-template-columns: 1fr; }
  .group-form-4col { grid-template-columns: 1fr 1fr; }
  .chip-grid, .chip-grid.cols-6 { grid-template-columns: repeat(2, 1fr); }
}
/* 中屏（681~1100）4 列网格：04 行 20261019s 起为 6 栏 = 6 字段各 1 栏，
   4 列下自然换行（第 4~6 项落到第二行），无需跨列特判（旧 cols-8 规则随 19s 移除） */
@media (min-width: 681px) and (max-width: 1100px) {
  .field-grid.cfg-time-grid .field > .free-quota-row { gap: 3px 3px; }
}
@media (max-width: 600px) {
  .stat-grid { grid-template-columns: 1fr 1fr; }
  .content { padding: 14px; }
  .tile-grid { grid-template-columns: 1fr 1fr; }
}

/* 自定义滚动条 */
::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--ink-150); border-radius: 4px; }
::-webkit-scrollbar-thumb:hover { background: var(--ink-200); }

/* ============================================================
   员工管理
   ============================================================ */
.emp-table { width: 100%; border-collapse: collapse; }
.emp-table thead th {
  text-align: left; font-size: 15px; font-weight: 700; color: var(--ink-900);
  padding: 10px 12px; border-bottom: 1px solid var(--border-default);
  background: var(--bg-paper-2);
  position: sticky; top: 0; z-index: 2;   /* 竖向滚动时表头固定不动 */
}
.emp-table tbody td {
  padding: 10px 12px; font-size: 15px; border-bottom: 1px solid var(--border-subtle);
  color: var(--ink-900); font-weight: 400;
}
.emp-table tbody tr { cursor: pointer; }
.emp-table tbody tr.row-sel td { background: var(--bg-tinted); }
.emp-table tbody tr.row-sel:hover td { background: var(--bg-tinted); }
.emp-table tbody tr:hover td { background: var(--bg-tinted); }
.emp-table tbody tr:last-child td { border-bottom: none; }
.emp-table .chk { width: 40px; }
.emp-table .chk input[type="checkbox"],
.emp-table .emp-chk {
  width: 17px; height: 17px; cursor: pointer;
  accent-color: var(--accent-500);
}
.emp-table .seq { width: 60px; color: var(--ink-900); }   /* 序号与正文统一字体，不再用等宽体 */
.emp-table .ops { width: 250px; text-align: right; white-space: nowrap; }
.emp-table .ops .btn { margin-left: 4px; }
.group-times { display: flex; align-items: center; gap: 12px; white-space: nowrap; }
.group-time { font-size: 12.5px; color: var(--ink-500); line-height: 1.5; }
.group-times .group-time + .group-time::before { content: '|'; margin-right: 12px; color: var(--ink-200); }

/* 考勤组列表：班次设置列回显（多班次逐行：班次名 + 时间摘要 + 标签；单班次一行） */
.gshift-list { display: flex; flex-direction: column; gap: 7px; min-width: 300px; padding: 2px 0; }
.gshift-row { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.gshift-name { font-size: 14px; font-weight: 600; color: var(--ink-900); white-space: nowrap; }
.gshift-time { font-size: 12.5px; color: var(--ink-600); font-family: var(--font-mono); white-space: nowrap; }
.gshift-tags { display: inline-flex; flex-wrap: wrap; gap: 4px; }
.gshift-tags .shift-tag { font-size: 11px; padding: 3px 7px; }

/* 员工管理：卡片占满剩余高度，列表内部滚动，分页固定在底部可见 */
#page-employees .card {
  flex: 1; min-height: 0;
  display: flex; flex-direction: column;
  overflow: hidden;
  margin-bottom: 0;
}
#emp-list { flex: 1; min-height: 0; overflow: auto; }
#emp-pagination { flex-shrink: 0; }

/* 考勤组管理（20261046）：与员工管理同款 —— 卡片占满剩余高度，
   列表超高时内部滚动，翻页组件固定在卡片底部始终可见 */
#page-groups .card {
  flex: 1; min-height: 0;
  display: flex; flex-direction: column;
  overflow: hidden;
  margin-bottom: 0;
}
#group-list { flex: 1; min-height: 0; overflow: auto; }
#group-pagination { flex-shrink: 0; }

/* 弹窗 */
.modal-mask {
  position: fixed; inset: 0; z-index: 100;
  background: rgba(15, 15, 15, 0.45);
  display: flex; align-items: center; justify-content: center;
  padding: 20px;
}
.modal-box {
  background: var(--bg-paper); border-radius: var(--radius-lg);
  box-shadow: 0 20px 50px rgba(0,0,0,0.25);
  width: 100%; max-width: 480px; padding: 24px;
  /* 20261020c（用户定版）：屏幕高度小时弹框自适应——限高 = 视口 − 上下 20px；
     有 .modal-body 的弹窗由 body 竖向滚动（标题区/底部按钮常驻可点），
     无 .modal-body 的弹窗由 box 自身兜底滚动。 */
  max-height: calc(100vh - 40px);
  display: flex; flex-direction: column;
  overflow-y: auto; overscroll-behavior: contain;
}
.modal-title { font-size: 18px; font-weight: 600; color: var(--ink-900); margin-bottom: 14px; }
.modal-body {
  font-size: 15.5px; color: var(--ink-700); line-height: 1.7;
  /* 20261020c：内容超出限高 → body 竖向滚动，顶部标题/关闭按钮与底部操作区不动 */
  flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain;
}
.modal-list { margin: 0; padding-left: 20px; }
.modal-list li { margin-bottom: 8px; }
.modal-list li.warn { color: var(--danger); }
.modal-actions { display: flex; justify-content: flex-end; gap: 10px; margin-top: 20px; flex-shrink: 0; }
/* 导入类弹框底部的灰色补充说明（20261040b）：列表讲规则，这里指向「下载模板」 */
.modal-note { margin-top: 14px; font-size: 12.5px; color: var(--ink-500); line-height: 1.8; }
/* 导入提示框（20261040c）：一句话引导 → 下方蓝色下划线「下载模板」链接。
   链接不占底部按钮位，只保留「取消 / 选择文件导入」两个按钮。 */
.imp-hint-text { margin: 0; font-size: 14px; line-height: 1.75; color: var(--ink-700); }
.tpl-link {
  display: inline-block; margin-top: 10px;
  font-size: 14px; line-height: 1.6;
  color: var(--accent-600, #2563eb);
  text-decoration: underline; text-underline-offset: 3px;
  cursor: pointer; user-select: none; -webkit-user-select: none;
}
.tpl-link:hover { color: var(--accent-500, #0071e3); }
/* 下载中：只做视觉反馈，不撑宽（链接文字长度不变）*/
.tpl-link.is-busy { opacity: .6; pointer-events: none; }

/* 通用系统确认框（20261026a）：替代浏览器原生 confirm()。
   盒子略窄（440px）+ 正文可换行，深浅主题靠变量自动跟随。 */
.modal-box.sys-confirm-box { max-width: 460px; }
.sys-confirm-text { white-space: pre-line; word-break: break-word; }
.sys-confirm-list { margin-top: 12px; padding-left: 20px; }
.sys-confirm-list li { margin-bottom: 7px; font-size: 14.5px; line-height: 1.65; }
.sys-confirm-list li.warn { color: var(--danger); }
.sys-confirm-list li:last-child { margin-bottom: 0; }

/* 考勤记录格式说明：缩略图卡片（4:3 占位，悬停出现预览按钮） */
.modal-box.wide.fmt-wide { max-width: 1080px; }
/* 排班表模板弹窗：仅一个卡片 → 弹窗收窄为单卡片宽，提示语与卡片同宽、超行自动换行 */
.modal-box.wide.fmt-sched { max-width: 580px; }
#schedule-tpl-grid { grid-template-columns: 1fr; }
.tpl-sched-note { width: 100%; word-break: break-all; }
/* ============================================================
   扣款规则配置弹窗（20261019e）：04 迟到/早退扣款类型的「配置」
   限高 + body 滚动（口径同 #att-import-format-modal），标题与底部按钮常驻
   ============================================================ */
.dm-box {
  max-width: 620px;
  max-height: calc(100vh - 40px);
  display: flex; flex-direction: column; overflow: hidden;
}
.dm-box .modal-body {
  flex: 1 1 auto; min-height: 0; overflow-y: auto;
  padding-right: 6px; overscroll-behavior: contain;
}
.dm-box .modal-body::-webkit-scrollbar { width: 8px; }
.dm-box .modal-body::-webkit-scrollbar-thumb { background: rgba(100, 116, 139, .35); border-radius: 4px; }
.dm-box .modal-body::-webkit-scrollbar-thumb:hover { background: rgba(100, 116, 139, .55); }
.dm-box .modal-actions { flex-shrink: 0; margin-top: 14px; }
/* 顶部说明条 */
.dm-hint {
  font-size: 13.5px; line-height: 1.6; color: var(--ink-400);
  padding: 9px 12px; margin-bottom: 14px;
  background: var(--bg-soft, #f5f6f9); border-radius: 8px;
}
/* 区块卡片：每段规则一个浅描边块 */
.dm-sec {
  /* 20261021a：描边色由 --ink-100 提到 --ink-150 —— 与卡片内 .field 底边框、
     扣款阶梯盒的描边/行分隔线同色（用户要求「模块之间的分割线样式颜色统一」） */
  border: 1px solid var(--ink-150); border-radius: 10px;
  padding: 12px 14px; margin-bottom: 12px;
}
.dm-sec:last-child { margin-bottom: 0; }
.dm-sec-title {
  font-size: 13.5px; font-weight: 600; color: var(--ink-700);
  line-height: 1.4; padding-left: 8px; margin-bottom: 10px;
  border-left: 3px solid var(--accent-500);
}
/* 扣款类型 / 扣除类型：标签固定宽，下拉占满剩余 */
.dm-row { display: flex; align-items: center; gap: 12px; }
.dm-row + .dm-row { margin-top: 10px; }
.dm-label {
  flex: 0 0 88px; font-size: 14.5px; color: var(--ink-900);
  display: flex; align-items: center; gap: 4px;
}
.dm-row .dm-select { flex: 1 1 auto; min-width: 0; }
.dm-ladder { display: flex; flex-direction: column; gap: 8px; }
/* 20261020f（用户定版）：阶梯行内容宽度自适应当前弹框宽度——
   行铺满整行，两格 + 删除按钮在行内均匀铺开（窄屏放不下时仍可换行）。 */
.dm-ladder .ladder-row {
  flex-wrap: wrap; justify-content: space-between; gap: 6px 8px; width: 100%;
}
.dm-ladder .ladder-row .ladder-cell { flex: 0 1 auto; }
/* 每周期免罚（20261019e）：弹窗里一行 —— [N] 次 单次≤ [M] 分钟；输入框窄化，
   整体宽度收在 340px 内，避免在 620px 弹窗里被拉得很散。 */
.dm-free-row { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.dm-free-row .dm-free-input {
  width: 68px; flex: 0 0 68px; text-align: center;
  font-family: var(--font-mono); font-size: 15px; padding: 8px 6px;
}
.dm-free-txt { font-size: 14.5px; color: var(--ink-500); white-space: nowrap; user-select: none; }
.dm-help { font-size: 12.5px; line-height: 1.5; color: var(--ink-400); margin-top: 6px; }
.dm-off-tip { font-size: 13.5px; color: var(--ink-400); padding: 0 2px 12px; }
/* 20261022f（用户报 bug）：扣款类型=不扣款时，两侧阶梯块照样显示、整块置灰禁用 ——
   原来整块被清空，子页里只剩一个「扣款类型」下拉，用户以为页面坏了。 */
.dm-off-tip { line-height: 1.6; }
#deduct-modal-body [data-dsides].dm-off { opacity: .62; }
#deduct-modal-body [data-dsides].dm-off input,
#deduct-modal-body [data-dsides].dm-off button { cursor: not-allowed; }
#deduct-modal-body [data-dsides].dm-off .ladder-add { display: none; }
.modal-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; flex-shrink: 0; }
.modal-close { font-size: 15px; line-height: 1; padding: 6px 10px; }
.fmt-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 14px; }
.fmt-card { border: none; border-radius: 10px; overflow: hidden; background: var(--bg-paper); box-shadow: 0 1px 3px rgba(15,15,15,0.06); }
.fmt-thumb {
  position: relative; aspect-ratio: 4 / 3; width: 100%;
  background: linear-gradient(135deg, var(--accent-50), #d5e9ff);
  display: flex; align-items: center; justify-content: center;
  color: var(--accent-700); border-bottom: 1px solid var(--border-subtle);
  overflow: hidden;
}
.fmt-thumb-label { font-size: 15px; font-weight: 600; letter-spacing: 0.02em; position: relative; z-index: 1; }
.fmt-thumb::after {
  content: ''; position: absolute; inset: 0; background: rgba(15, 15, 15, 0.35);
  opacity: 0; transition: opacity .18s; z-index: 2;
}
.fmt-preview-btn {
  position: absolute; inset: 0; margin: auto;
  width: max-content; height: max-content;
  opacity: 0; transition: opacity .18s; z-index: 3;
}
.fmt-preview-btn:hover { transform: none; }
.fmt-thumb:hover::after { opacity: 1; }
.fmt-thumb:hover .fmt-preview-btn { opacity: 1; }
.fmt-card:nth-child(2) .fmt-thumb { background: linear-gradient(135deg, #eef4ff, #d5e9d5); color: var(--success); }
.fmt-card:nth-child(3) .fmt-thumb { background: linear-gradient(135deg, #fff8e6, #ffe7c2); color: #a85a0a; }
.fmt-card:nth-child(4) .fmt-thumb { background: linear-gradient(135deg, #fdf3f3, #ffdada); color: var(--danger); }
.fmt-actions { display: flex; align-items: center; gap: 8px; padding: 10px; }
.fmt-actions .btn { flex: 1; margin: 0; }
/* 格式预览大图（占位） */
.fmt-preview-img {
  width: 100%; aspect-ratio: 4 / 3; border-radius: 10px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px;
  font-size: 24px; font-weight: 700; border: 1px solid var(--border-default);
}
.fmt-preview-sub { font-size: 14px; font-weight: 400; opacity: 0.7; }

/* 导入考勤文件：确认统计年月（醒目大样式） */
.ym-pick { display: flex; align-items: center; justify-content: center; gap: 12px; padding: 10px 0 6px; }
.ym-year { display: flex; align-items: center; gap: 8px; }
.ym-nav {
  width: 46px; height: 54px; font-size: 26px; font-weight: 700; line-height: 1;
  border: 1.5px solid var(--border-strong); border-radius: 12px;
  background: var(--bg-paper); color: var(--ink-700); cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: all .15s;
}
.ym-nav:hover { border-color: var(--accent-500); color: var(--accent-600); background: var(--accent-50); }
.ym-year-val {
  min-width: 132px; font-size: 30px; font-weight: 700; color: var(--ink-900);
  text-align: center; padding: 8px 12px; cursor: pointer; border-radius: 12px;
  border: 1.5px solid transparent; font-family: var(--font-mono);
}
.ym-year-val:hover { border-color: var(--border-strong); background: var(--bg-paper-2); }
.ym-select {
  font-size: 22px; font-weight: 600; color: var(--ink-900);
  padding: 12px 16px; border: 1.5px solid var(--border-strong);
  border-radius: 12px; background-color: var(--bg-paper);
  /* 20261020j：min-width→width+可收缩。固定 130 常态视觉不变；年月行整体
     比弹窗宽 ~7px 曾撑出横向滚动条，允许下拉在窄弹窗时收缩（min-width:0） */
  width: 130px; min-width: 0; flex-shrink: 1;
  text-align: center; cursor: pointer;
  font-family: inherit;
}
.ym-select:hover { border-color: var(--accent-500); }
.ym-select:focus { outline: none; border-color: var(--accent-500); box-shadow: 0 0 0 4px rgba(var(--accent-glow), 0.12); }
.ym-sep { font-size: 20px; font-weight: 600; color: var(--ink-400); }

/* 考勤单元格编辑弹窗 */
.cell-edit-hint { margin-bottom: 14px; font-size: 14px; line-height: 1.6; }.cell-edit-grid { display: flex; gap: 12px; }
.cell-field {
  display: flex; flex-direction: column; gap: 7px; min-width: 0; flex: 1;
}
.cell-edit-grid .cell-field { max-width: 180px; }
.cell-field input {
  width: 100%; box-sizing: border-box; padding: 9px 12px; font-size: 15.5px;
}
.cell-field input[type="number"] { font-family: var(--font-mono); }
.cell-edit-limit {
  margin-top: 10px; padding: 7px 11px; font-size: 13px; line-height: 1.5;
  background: var(--warning-soft, rgba(251,191,36,.12)); color: var(--warning, #b7791f);
  border-radius: 8px;
}
.modal-box .modal-actions .btn-ghost { margin-right: auto; }


/* 考勤统计页顶部：考勤组未设置上下班时间常驻提示（红色系） */
.group-time-warn {
  margin: 0 0 12px; padding: 10px 14px;
  background: #fdeceb; border: 1px solid #f5b5b0; border-radius: 10px;
  color: #c0392b; font-size: 14px; line-height: 1.6;
}
.group-time-warn .gtw-inner { display: flex; flex-wrap: wrap; gap: 6px 24px; align-items: center; }
.group-time-warn .gtw-item { cursor: pointer; }
.group-time-warn .gtw-item:hover u { text-decoration-thickness: 2px; }
.group-time-warn u { color: #b3261e; }

/* 20261026c：未配置考勤组员工的行级提示层（renderSummary → applyRowMasks）。
   #summary-grid 是滚动容器，提示层绝对定位随内容滚动；z-index 压过吸顶列(z=2~4)，
   吸顶表头再提到 35 压过提示层——行段滚到表头下方时提示不会盖住表头。
   20261026e（用户定版）：**层背景全透明**（不再整段压暗），每个被遮员工各自出现一条
   提示文字，文字带黑色半透明圆角底（.eml-pill）——一眼看出「这个人算不出来是没配组」。 */
#summary-grid { position: relative; }
#summary-grid thead th { z-index: 35; }
/* 20261032a（用户报样式 bug）：吸顶表头统一提到 35 后，**左侧冻结列的表头**必须再高一层。
   否则横向滚动时日期表头（DOM 在后、同 z=35）会压住序号/姓名/工号/部门/岗位/指标的表头，
   表现为「滚到中间，左侧那几列的表头被日期盖住、整块变成日期」。数据格不受影响
   （td.col-* 是 z=2，日期 td 是 static）。
   用 ID 选择器保证特异性高于 `#summary-grid thead th`（1,0,2）—— 原
   `table.grid-full thead th.col-seq{...z-index:4}` 是 (0,2,3)，压不过 ID 规则。
   右侧 col-total 同理（sticky right）。 */
#summary-grid thead th.col-seq,
#summary-grid thead th.col-name,
#summary-grid thead th.col-empno,
#summary-grid thead th.col-pos,
#summary-grid thead th.col-dept,
#summary-grid thead th.col-metric,
#summary-grid thead th.col-total { z-index: 36; }
#summary-grid .emp-mask-layer {
  position: absolute; left: 0; z-index: 30;
  background: transparent; pointer-events: none;
}
#summary-grid .emp-mask-layer .eml-pill {
  position: absolute; left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  /* 20261026f：新文案约 50 字 + 「前往考勤组管理」按钮，760px 会被挤成两行 —— 放宽到
     940px 单行放得下（表格可视宽 1328px）；窄视口由 calc 兜底，wrap 兜底换行 */
  flex-wrap: wrap; max-width: min(940px, calc(100% - 40px));
  padding: 7px 16px; border-radius: 999px;
  background: rgba(0, 0, 0, .62);
  color: #fff; font-size: 13px; font-weight: 600; line-height: 1.5;
  text-align: center;
  /* 20261026f（用户定版）：文字与胶囊都不要任何阴影（box-shadow / text-shadow 全清） */
  text-shadow: none; box-shadow: none;
  pointer-events: auto;
}
#summary-grid .emp-mask-layer .eml-pill * { text-shadow: none; }
#summary-grid .emp-mask-layer .eml-ico { font-size: 15px; flex: none; }
#summary-grid .emp-mask-layer .eml-txt { white-space: normal; word-break: break-word; }
#summary-grid .emp-mask-layer .eml-link {
  flex: none; color: #fff; font-weight: 600; text-decoration: underline; cursor: pointer;
  padding: 2px 10px; border: 1px solid rgba(255, 255, 255, .7); border-radius: 999px;
  background: transparent;
}
#summary-grid .emp-mask-layer .eml-link:hover { background: rgba(255, 255, 255, .22); }
/* 单人行段高于网格可视区（竖版一天一行）：pill 吸附在可视位置，滚动时不会跑出屏幕 */
#summary-grid .emp-mask-layer.emp-mask-tall .eml-pill {
  position: sticky; display: flex; width: fit-content; margin: 0 auto;
  left: auto; transform: none;
}

/* 同步员工数据：项目选择列表 */
.emp-sync-list {
  display: flex; flex-direction: column; gap: 8px;
  max-height: 320px; overflow-y: auto; padding: 4px;
}
.emp-sync-item {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px; border: 1px solid var(--border-default);
  border-radius: 8px; cursor: pointer; font-size: 14.5px; transition: all .15s;
}
.emp-sync-item:hover { border-color: var(--accent-500); background: rgba(var(--accent-glow), .05); }
.emp-sync-item:has(input:checked) { border-color: var(--accent-500); background: rgba(var(--accent-glow), .08); }
.emp-sync-item input { accent-color: var(--accent-500); }

/* 节假日设置 */
.holiday-toolbar { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; }
.holiday-toolbar .muted { flex: 1; }
.holiday-group-title {
  margin: 14px 0 8px; font-size: 14px; font-weight: 600; color: var(--ink-700);
  padding-bottom: 4px; border-bottom: 1px solid var(--border-default);
}
.holiday-days { display: grid; grid-template-columns: repeat(8, 1fr); gap: 8px; }
/* 补班日期：5 个格子、每格更宽（20260916i） */
.holiday-days.makeup { grid-template-columns: repeat(5, 1fr); gap: 12px; }
.holiday-cell { display: flex; flex-direction: column; gap: 4px; }
.holiday-cell span {
  font-size: 12.5px; color: var(--ink-500); font-family: var(--font-mono);
  text-align: center;
}
.holiday-cell select {
  width: 100%; box-sizing: border-box; padding: 5px 18px 5px 6px; font-size: 14px;
  border: 1px solid var(--border-default); border-radius: var(--radius-md);
  background-color: var(--bg-paper); color: var(--ink-800); cursor: pointer;
  appearance: none; text-align: center;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 10 10'><path d='M1 3h8L5 8z' fill='black'/></svg>");
  background-repeat: no-repeat; background-position: right 4px center;
}
.holiday-cell select:focus { border-color: var(--accent-500); box-shadow: 0 0 0 3px rgba(var(--accent-glow), 0.10); }

/* 全屏预览（复刻导出 Excel 效果） */
.preview-overlay {
  position: fixed; inset: 0; z-index: 300;
  background: var(--bg-canvas);
  display: flex; flex-direction: column;
}
.preview-head {
  display: flex; align-items: center; gap: 14px;
  padding: 12px 20px; flex-shrink: 0;
  background: var(--bg-paper); border-bottom: 1px solid var(--border-default);
}
.preview-title { font-size: 16px; font-weight: 700; color: var(--ink-800); }
.preview-count { margin-left: auto; font-size: 14px; color: var(--ink-500); }
.preview-body {
  flex: 1 1 0; min-height: 0; display: flex; flex-direction: column;
  padding: 16px 20px 12px; overflow: hidden;
}
.preview-table-wrap {
  flex: 1 1 0; min-height: 0; overflow: auto;
  /* 20260922h：外框描边统一 var(--border-hairline)；20260922e：去掉圆角（与 .grid-wrap 一致） */
  border: 1px solid var(--border-hairline); border-radius: 0;
  background: var(--bg-paper);
}
.preview-pagination {
  flex-shrink: 0; padding-top: 10px;
  display: flex; align-items: center; justify-content: flex-end; gap: 8px;
  font-size: 14px; color: var(--ink-500);
}

/* 复刻导出配色：周末/2倍=浅红、3倍节假日=浅橙（20260916a：汇总列不再填充黄色，与导出 Excel 一致） */
table.grid-full.preview-grid th.rest,
table.grid-full.preview-grid td.rest { background: #FCE4D6 !important; }
table.grid-full.preview-grid th.holiday,
table.grid-full.preview-grid td.holiday { background: #F8CBAD !important; }
/* 20261013e（用户反馈）：预览网格的周末/节假日色是**写死的浅色**（刻意复刻导出 Excel
   配色，故不能改成变量，否则浅色模式也跟着变色）——深色模式必须单独覆盖，
   否则节假日日期单元格在深色下仍是浅橙。取值同 --col-rest-bg / --col-holiday-bg 的深色口径。 */
html.dark table.grid-full.preview-grid th.rest,
html.dark table.grid-full.preview-grid td.rest { background: rgba(10, 132, 255, 0.12) !important; }
html.dark table.grid-full.preview-grid th.holiday,
html.dark table.grid-full.preview-grid td.holiday { background: rgba(255, 159, 10, 0.14) !important; }
/* 20260929m：预览不再钉回旧导出配色——迟到/早退/缺卡/旷工直接走通用 c-* 规则，
   与计算结果页色系一致（迟到紫/早退蓝/缺卡红/旷工黄；导出 Excel 已同步改色）。
   原 preview-grid c-missing/c-late/c-absent 覆盖与无引用的 pv-late/pv-early 死规则一并移除 */

/* 员工表单 */
.form-field { margin-bottom: 14px; }
.form-field .field-label { display: block; margin-bottom: 6px; }
.form-field input,
.form-field select { width: 100%; box-sizing: border-box; }
.form-field input,
.form-field select {
  padding: 10px 26px 10px 12px; font-size: 14.5px; border-radius: var(--radius-md);
}
/* 弹窗选项行（单选/复选）：横排对齐 */
.opt-row { display: flex; align-items: center; gap: 8px; padding: 4px 0; cursor: pointer; font-size: 14.5px; color: var(--ink-700); }
.opt-row input[type="radio"], .opt-row input[type="checkbox"] { width: auto; margin: 0; accent-color: var(--accent-600); cursor: pointer; }
.form-field .field-help { margin: 2px 0 6px 22px; }
/* 考勤类型设置：两栏/三栏布局，chip 宽度随字段自适应，备注放每个选项下方 */
.cfg-att-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px 18px; }
.cfg-att-grid-3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px 10px; }
.cfg-att-item { display: flex; flex-direction: column; gap: 3px; }
.cfg-att-item .chip { width: 100%; }
.cfg-att-item .field-help { margin: 0; font-size: 12.5px; line-height: 1.45; }
/* 20260925d：01 区下拉框与规定打卡次数下拉等高（统一 padding 11px + 15px 字号） */
#cfg-sec-01 select.input, #cfg-sec-01 .msel-box { padding: 11px 11px; font-size: 15px; line-height: 1.5; }
/* 多选下拉（20260925d）：外层下拉框 + 面板内复用 chips（状态/联动/保存沿用 chips 链路） */
.msel { position: relative; }
.msel-box {
  display: flex; align-items: center; gap: 8px; width: 100%; cursor: pointer;
  background: var(--bg-paper); border: 1px solid var(--ink-200);
  border-radius: var(--radius-md); transition: border-color .18s, box-shadow .18s;
}
.msel-box:hover { border-color: var(--ink-300); }
.msel.open .msel-box { border-color: var(--accent-500); box-shadow: 0 0 0 4px rgba(var(--accent-glow), 0.10); }
/* 20260925e（截图口径）：框内=已选标签（可点 ✕ 移除），空=「请选择」占位 */
.msel-tags { flex: 1; min-width: 0; display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.msel-ph { font-size: 15px; color: var(--ink-400); }
.msel-tag {
  display: inline-flex; align-items: center; gap: 6px; max-width: 100%;
  padding: 2px 8px; border-radius: 6px;
  background: rgba(var(--accent-glow), 0.12);
  color: var(--accent-500); font-size: 14px; font-weight: 500; line-height: 1.4;
  white-space: nowrap;
}
.msel-tag-x {
  border: 0; background: transparent; cursor: pointer; padding: 0;
  color: var(--accent-500); font-size: 12px; line-height: 1;
  opacity: .75; transition: opacity .15s;
}
.msel-tag-x:hover { opacity: 1; }
.msel-arrow { flex: none; color: var(--ink-400); font-size: 12px; transition: transform .18s; }
.msel.open .msel-arrow { transform: rotate(180deg); }
/* 20260925g：position:fixed 脱离 .cfg-card 的 overflow:hidden 裁剪（原 absolute 会被卡片剪掉，
   面板只能显示第一行）；坐标由 JS 开面板时按 .msel-box 实时计算（mselPlace） */
.msel-pop {
  position: fixed; top: 0; left: 0; z-index: 60; width: max-content; min-width: 0;
  max-width: 320px; max-height: calc(100vh - 16px); overflow-y: auto;
  background: var(--bg-paper); border: 1px solid var(--border-default);
  border-radius: var(--radius-md); box-shadow: 0 10px 28px rgba(15, 23, 42, .14);
  padding: 10px;
}
.msel-pop.hidden { display: none; }
.msel.open .msel-pop { display: block; }
/* 20260925f（截图口径）：面板=纯选项行（抛弃原 chips 外观）——
   无框行、hover 浅底、选中行蓝字加粗 + 右侧 ✓；chips 隐藏容器仅作状态载体 */
.msel-rows { display: flex; flex-direction: column; padding: 4px 2px; }
.msel-row {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 14px; border-radius: 8px; cursor: pointer;
  transition: background .15s;
}
.msel-row:hover { background: var(--ink-50); }
.msel-row-label {
  flex: 1; min-width: 0; font-size: 15px; color: var(--ink-800);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.msel-row-check { flex: none; width: 16px; height: 16px; color: var(--accent-500); }
.msel-row-check svg { opacity: 0; transition: opacity .12s; }
.msel-row.on .msel-row-label { color: var(--accent-500); font-weight: 600; }
.msel-row.on .msel-row-check svg { opacity: 1; }
.msel-row[data-msel-chips], .msel [data-msel-chips] { display: none !important; }
.form-field input:focus,
.form-field select:focus {
  border-color: var(--accent-500);
  box-shadow: 0 0 0 4px rgba(var(--accent-glow), 0.10);
}

/* 分页 */
.pagination { display: flex; align-items: center; gap: 6px; justify-content: flex-end; padding-top: 14px; flex-wrap: wrap; }
.pagination .page-info { margin-right: auto; color: var(--ink-400); font-size: 14px; }
/* 翻页按钮：默认白底灰边，当前页浅蓝底蓝字（全局统一） */
.pagination .btn { background: var(--bg-card); border-color: var(--ink-200); color: var(--ink-600); }
.pagination .btn:not(:disabled):hover { background: var(--ink-50); border-color: var(--ink-300); color: var(--ink-900); }
.pagination .page-num { min-width: 32px; padding: 4px 8px; }
.pagination .page-num.active { background: var(--accent-100); border-color: var(--accent-300); color: var(--accent-700); }
/* 每页人数下拉（20261016c）：历史数据 → 考勤汇总翻页条，「每页 [10/20/50] 人」 */
.pagination .page-size { display: inline-flex; align-items: center; gap: 4px;
  margin-right: 8px; color: var(--ink-500); font-size: 13px; white-space: nowrap; }
.pagination .page-size select { height: 28px; padding: 0 6px; border: 1px solid var(--ink-200);
  border-radius: 6px; background: var(--bg-card); color: var(--ink-700);
  font-size: 13px; cursor: pointer; }
.pagination .page-ellipsis { color: var(--ink-400); padding: 0 2px; user-select: none; }
/* 员工管理页：#page-employees .btn ID 规则会盖掉上面的当前页浅蓝，同级覆盖恢复 */
#page-employees .pagination .btn.page-num.active {
  background: var(--accent-100); border-color: var(--accent-300); color: var(--accent-700);
}

/* ============================================================
   请假管理（独立子页面，类似规则设置）
   ============================================================ */
/* 页面容器：填满卡片剩余高度，内部滚动 */
.leave-pane {
  flex: 1 1 0; min-height: 0; height: 0;
  display: flex; flex-direction: column;
  overflow: hidden;
}
/* 页头：左侧四个动作按钮（更新/导入/导出/清空），中间三段 tab 居中，
   右侧「共 N 人」+ 提示文字（与左侧按钮水平对齐） */
.leave-page-head {
  display: flex; align-items: center; gap: 12px;
  padding-bottom: 14px; flex-shrink: 0;
  flex-wrap: nowrap;
}
/* 假勤管理页头（20261009k 三列；**20261024f 用户定版改两列**）：
   = [动作按钮] ......... [请假申请|加班申请|补卡申请]      ← tab 贴页面**最右**
   原第三列「共 N 人 · 点击任意日期单元格可修改当日 XX 结果」整块删除：
   ① 人数与分页条「共 N 人 · N 页」重复；
   ② 那句提示改成固定文案「点击任意日期单元格可修改当日结果」下沉到分页条左侧。
   ⚠️ 顺带退休 20261009l 的「第三列定宽 330px 防抖」补丁——右列没了，中间 1fr 的宽度
      不再随文案变化，切档时 tab 也不会横移，无需再定宽。
   ⚠️ 只加在 .lc-head 上，排班表管理页共用的 .leave-page-head 保持原 flex 布局不受影响。 */
.leave-page-head.lc-head {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  column-gap: 12px;
  align-items: center;
}
.leave-page-head.lc-head .lc-tabs { justify-self: end; }
/* 窄屏（一行放不下「按钮 + tab」）⇒ 回落为 flex 换行：按钮第 1 行、tab 第 2 行仍靠右。 */
@media (max-width: 1439px) {
  .leave-page-head.lc-head { display: flex; flex-wrap: wrap; }
  .leave-page-head.lc-head .lc-tabs { margin-left: auto; }
}
.leave-back-btn { flex-shrink: 0; }
.leave-page-actions { display: flex; align-items: center; gap: 12px; flex-shrink: 0; }
.leave-page-tip {
  margin-left: auto;
  font-size: 14.5px; color: var(--ink-500);
  display: flex; align-items: center;
  white-space: nowrap;
  min-width: 0;
}
.leave-page-tip b { color: var(--accent-700); font-weight: 700; margin: 0 2px; }
/* 姓名列在请假表格中贴左侧固定，不要有 44px 的空隙 */
table.grid-full.leave-grid th.col-name,
table.grid-full.leave-grid td.col-name { left: 0; }
/* 假勤管理：姓名表头「姓名 (全部) ▾」多选筛选按钮（20261024c 用户定版）
   🔴 表头 th 自带 4px 6px padding 与 28px 固定高 ⇒ 按钮必须撑满单元格并清零内边距，
      否则箭头会偏、点击热区只覆盖文字。姓名列适当加宽以容下「(已选 N)」。 */
table.grid-full.leave-grid th.col-name { padding: 0; width: 104px; min-width: 104px; }
.lc-th-btn {
  display: flex; align-items: center; justify-content: center; gap: 1px;
  width: 100%; height: 32px; padding: 4px 6px;
  background: transparent; border: 0; cursor: pointer;
  font: inherit; font-weight: 700; color: var(--ink-900); white-space: nowrap;
}
.lc-th-btn:hover { color: var(--accent-500); }
.lc-th-label { font-weight: 400; font-size: 11.5px; color: var(--ink-500); }
/* 20261024f：筛选箭头 9px → 18px（用户口径：看得见、点得准）；同时把与「姓名」的间距
   压到最小 —— gap 3→1px，再给箭头 -2px 左外边距抵消 ▾ 字形自身的左侧留白。 */
.lc-th-caret { font-size: 18px; line-height: 1; margin-left: -2px; opacity: .75; }
/* 假勤页首屏占位（20261010f）：没有缓存时先给即时反馈，避免点完空白几百毫秒 */
.lc-loading {
  display: flex; align-items: center; justify-content: center; gap: 10px;
  min-height: 180px; padding: 40px 0;
  font-size: 14px; color: var(--ink-400);
}
@keyframes lc-spin { to { transform: rotate(360deg); } }
.lc-spin {
  width: 18px; height: 18px; border-radius: 50%; flex: none;
  border: 2.5px solid var(--ink-150); border-top-color: var(--accent-500);
  animation: lc-spin .8s linear infinite;
}
html.dark .lc-spin { border-color: var(--ink-300); border-top-color: var(--accent-600); }
#leave-pagination { flex-shrink: 0; padding-top: 8px; }
/* 表格区域：提示文字在表格右上角，仅表格区域横向滚动（页面不动） */
.leave-table-area {
  flex: 1 1 0; min-height: 0;
  display: flex; flex-direction: column;
  overflow: hidden;
}
.leave-table-tip {
  text-align: right; font-size: 13.5px; color: var(--ink-400);
  padding: 0 2px 8px; flex-shrink: 0;
}
.leave-table-wrap {
  flex: 1 1 0; min-height: 0;
  overflow: auto;
  /* 20260922h：描边统一 var(--border-hairline)；20260922e：去掉圆角（请假管理 / 排班表管理共用） */
  border: 1px solid var(--border-hairline);
  border-radius: 0;
  background: var(--bg-paper);
}
.leave-table-wrap .empty-state { border: none; height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: center; }

table.grid-full.leave-grid td.leave-cell {
  cursor: pointer; position: relative; max-width: 48px; min-width: 42px;
  white-space: normal; line-height: 1.5; font-size: 13.5px; padding: 4px 3px;
}
/* 请假表格日期列收窄，全屏时尽量不出现横向滚动条 */
table.grid-full.leave-grid th.col-day { width: 44px; min-width: 44px; }
table.grid-full.leave-grid td.leave-cell:hover {
  outline: 2px solid var(--accent-500); outline-offset: -2px;
  background: var(--accent-50) !important; z-index: 1;
}
table.grid-full.leave-grid td.leave-cell.empty { color: var(--ink-400); }
/* 20261009m：加班 / 补卡的单元格是「12.5h」「08:00」这类 5 字符短标签，
   而日期列内容宽只有 ~42px（列 44-48px 减左右 padding 6px），比标签需要的 ~46px 窄
   ⇒ 标签内部被挤成两行（实测标签宽 39px、行高 51px，页面看是「08:0 / 0」）。
   这两个 tab 单独加宽日期列，并禁止标签**内部**折行（多个标签之间仍可换行）。 */
table.grid-full.leave-grid[data-kind="ot"] th.col-day,
table.grid-full.leave-grid[data-kind="ot"] td.col-day,
table.grid-full.leave-grid[data-kind="makeup"] th.col-day,
table.grid-full.leave-grid[data-kind="makeup"] td.col-day { width: 52px; min-width: 52px; }
table.grid-full.leave-grid[data-kind="ot"] td.leave-cell,
table.grid-full.leave-grid[data-kind="makeup"] td.leave-cell { min-width: 52px; max-width: 52px; }
table.grid-full.leave-grid[data-kind="ot"] td.leave-cell .leave-type-tag,
table.grid-full.leave-grid[data-kind="makeup"] td.leave-cell .leave-type-tag { white-space: nowrap; }
table.grid-full.leave-grid td.leave-total { min-width: 64px; }
.leave-type-tag { display: inline-block; background: var(--accent-50); color: var(--accent-600);
  border-radius: 5px; padding: 1px 5px; margin: 1px 2px 1px 0; font-size: 12.5px; }
.leave-emp-name { cursor: default; }

/* 请假修改弹窗 */
.modal-box.wide { max-width: 560px; }
/* 考勤组表单弹窗：加宽 + 3 个时间段占一行 */
.modal-box.wide.group-wide { max-width: 880px; }
/* 考勤组导入预览弹窗（20261040a） */
.grp-imp-box .modal-body { max-height: 66vh; overflow: auto; }
.grp-imp-sum { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 12px; }
.gi-chip {
  font-size: 13px; color: var(--ink-700); background: var(--bg-soft);
  border: 1px solid var(--border-hairline); border-radius: 999px;
  padding: 3px 11px; line-height: 20px;
}
.gi-chip b { color: var(--ink-900); font-weight: 600; }
.gi-chip.gi-new { background: rgba(34,197,94,.10); border-color: rgba(34,197,94,.35); }
.gi-chip.gi-new b { color: #15803d; }
.gi-chip.gi-upd { background: rgba(37,99,235,.09); border-color: rgba(37,99,235,.32); }
.gi-chip.gi-upd b { color: var(--accent-600); }
.gi-table { width: 100%; border-collapse: collapse; font-size: 13.5px; }
.gi-table th {
  text-align: left; font-weight: 500; color: var(--ink-600); background: var(--bg-soft);
  padding: 7px 10px; border-bottom: 1px solid var(--border-hairline); white-space: nowrap;
}
.gi-table td {
  padding: 7px 10px; border-bottom: 1px solid var(--border-hairline); color: var(--ink-800);
}
.gi-table th.r, .gi-table td.r { text-align: right; width: 62px; }
.gi-tag {
  display: inline-block; font-size: 12px; border-radius: 6px; padding: 1px 8px;
  background: var(--bg-soft); color: var(--ink-600);
}
.gi-tag.gi-tag-new { background: rgba(34,197,94,.12); color: #15803d; }
.gi-tag.gi-tag-upd { background: rgba(37,99,235,.10); color: var(--accent-600); }
.gi-block {
  margin-top: 12px; border-radius: 10px; padding: 10px 13px; font-size: 13px;
  border: 1px solid var(--border-default); background: var(--bg-paper-2);
}
.gi-block-h { font-weight: 600; margin-bottom: 6px; }
.gi-block ul { margin: 0; padding-left: 18px; }
.gi-block li { line-height: 1.7; color: var(--ink-700); }
.gi-block.gi-err { border-color: rgba(220,38,38,.35); background: rgba(220,38,38,.06); }
.gi-block.gi-err .gi-block-h { color: #b91c1c; }
.gi-block.gi-warn { border-color: rgba(217,119,6,.35); background: rgba(217,119,6,.06); }
.gi-block.gi-warn .gi-block-h { color: #b45309; }
.gi-note { margin-top: 12px; font-size: 12.5px; color: var(--ink-500); line-height: 1.8; }
html.dark .gi-chip.gi-new { background: rgba(34,197,94,.16); }
html.dark .gi-chip.gi-new b { color: #4ade80; }
html.dark .gi-tag.gi-tag-new { background: rgba(34,197,94,.18); color: #4ade80; }
html.dark .gi-block.gi-err .gi-block-h { color: #f87171; }
html.dark .gi-block.gi-warn .gi-block-h { color: #fbbf24; }
/* 午间连班（考勤组弹窗 + 规则设置 04 加班规则共用） */
.noon-box, .group-noon-box {
  border: 1px solid var(--border-default); border-radius: 10px;
  background: var(--bg-paper-2); padding: 13px 15px;
  display: flex; flex-direction: column; gap: 12px;
}
.noon-switch-line { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.noon-switch-text { font-size: 14.5px; font-weight: 500; color: var(--ink-800); }
.noon-detail { display: flex; flex-direction: column; gap: 11px;
  border-top: 1px dashed var(--border-default); padding-top: 11px; }
.noon-block-title { font-size: 12.5px; font-weight: 600; color: var(--ink-500); }
.noon-detail .cfg-att-grid { margin-top: 0; }
.noon-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.noon-row-label { flex: none; font-size: 14px; font-weight: 600; color: var(--ink-700); }
.noon-start-line { margin-top: 2px; }
.noon-note { font-size: 13px; line-height: 1.6; }
/* 规则设置 04 加班规则（20260914d）：午间/晚间连班改为左右各占一栏（半宽），
   box 内的规则 chip 改为纵向单列并允许换行，避免标题被省略号截断 */
#global-config-body .field[data-cfg-field="noon"] .cfg-att-grid,
#global-config-body .field[data-cfg-field="dinner"] .cfg-att-grid {
  grid-template-columns: 1fr;
}
#global-config-body .field[data-cfg-field="noon"] .chip,
#global-config-body .field[data-cfg-field="dinner"] .chip { align-items: flex-start; }
#global-config-body .field[data-cfg-field="noon"] .chip-label,
#global-config-body .field[data-cfg-field="dinner"] .chip-label {
  white-space: normal; overflow: visible; text-overflow: clip; line-height: 1.5;
}
#global-config-body .field[data-cfg-field="noon"] .noon-start-line .input-wrap,
#global-config-body .field[data-cfg-field="dinner"] .noon-start-line .input-wrap { width: 180px !important; }
/* 考勤组弹窗内规则 chips：纵向两行全宽可换行 */
.group-noon-rules { display: flex; flex-direction: column; gap: 8px; }
.group-noon-rules .chip { width: 100%; justify-content: flex-start; padding: 10px 12px; }
.group-noon-rules .chip .chip-label { white-space: normal; line-height: 1.5; font-size: 14px; }
#group-noon-wrap .field-label, #group-dinner-wrap .field-label { display: block; margin-bottom: 6px; }
#group-noon-wrap .noon-switch-line, #group-dinner-wrap .noon-switch-line { gap: 14px; }
/* 考勤组弹窗两栏行：名称+打卡次数、午间连班+晚间连班 */
.group-form-2col { display: grid; grid-template-columns: 1fr 1fr; gap: 18px 22px; align-items: start; }
/* 班次弹窗补贴 4 栏网格（20261017h）：夜班每天补贴 ~ 是否统计夜宵天数，
   每行 4 项；隐藏项（display:none）自动回流不留空位 */
.group-form-4col { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 18px 22px; align-items: start; }
/* 开关行（是否自由打卡/是否存在倒班/错位）行距收紧统一，列表块与上下字段留出舒适间距 */
#group-form-modal .form-field-row { margin-bottom: 12px; }
#group-shift-wrap, #group-time-wrap { margin: 2px 0 14px; }
/* 弹性打卡：下拉（是/否）+ 条件输入框同宽各占一半，风格与普通字段一致（无底色） */
.flex-inline-row { display: flex; align-items: center; gap: 12px; }
.flex-inline-row .select-wrap { flex: 1; min-width: 0; }
.flex-inline-row input[type="number"] { flex: 1; min-width: 0; width: auto; }
/* 规则设置 02 工作时间与班次：「弹性打卡」字段（20261013e 用户口径重定）——
   本字段不再占 2 栏：原先 colSpan:2 ⇒ 下拉 295px，比同排「重复打卡间隔」的输入框
   宽一倍，用户要求「宽度调整和其他选项宽度一致」。收成 1 栏（137px）后，选「是」
   要在同一栏内同时放下「是/否」下拉 + 「最大弹性时长」数字框 ⇒ 下拉收到 60px。 */
#global-config-body .field[data-cfg-field="flex"] .flex-inline-row { gap: 8px; }
#global-config-body .field[data-cfg-field="flex"] .flex-inline-row .select-wrap { flex: 1 1 auto; }
#global-config-body .field[data-cfg-field="flex"] .flex-inline-row.flex-max-on .select-wrap { flex: 0 0 60px; }
/* 60px 下拉内沿用全局 padding（右 26px 留给原生箭头）会把「是/否」挤出框，故收窄左右内边距 */
#global-config-body .field[data-cfg-field="flex"] .flex-inline-row.flex-max-on .select-wrap select {
  padding: 8px 20px 8px 8px;
}
#global-config-body .field[data-cfg-field="flex"] .flex-inline-row.flex-max-on input[type="number"] {
  flex: 1 1 auto; min-width: 0; padding: 8px 6px; text-align: center;
}
/* 规则设置 09 全勤规则（20260914g/h）：规则1 为固定规则，输入框只读（禁止输入状态）；
   外观沿用普通字段的正常描边线框（外包 .input-wrap 的 1px 实线），
   内层 input 不再自带边框，避免出现黑色虚线框 */
.input.is-locked, #global-config-body .input.is-locked {
  background: transparent; color: var(--ink-700);
  cursor: not-allowed; opacity: 1; border: none;
}
.input-wrap:has(.input.is-locked),
#global-config-body .input-wrap:has(.input.is-locked) {
  background: var(--bg-paper-2); cursor: not-allowed;
}
.input-wrap:has(.input.is-locked):hover { border-color: var(--border-default); }
/* 规则设置 09 全勤规则（20260914i）：启用开关与全勤奖金额整合为同一字段、五项并排一行；
   「是/否」下拉默认满宽，选「是」后收窄（flex-max-on）并露出金额输入框（交互同弹性打卡） */
#global-config-body .field[data-cfg-field="full_attendance"] .flex-inline-row { gap: 8px; }
#global-config-body .field[data-cfg-field="full_attendance"] .flex-inline-row .select-wrap { flex: 1 1 auto; min-width: 0; }
#global-config-body .field[data-cfg-field="full_attendance"] .flex-inline-row .input-wrap { flex: 1 1 auto; min-width: 0; }
#global-config-body .field[data-cfg-field="full_attendance"] .flex-inline-row.flex-max-on .select-wrap { flex: 0 0 88px; }
#global-config-body .field[data-cfg-field="full_attendance"] .flex-inline-row .input-suffix { padding-right: 9px; padding-left: 4px; }
/* 规则设置 08 补卡规则（20260919b，20260919d 改指「宽限外缺卡是否扣款」）：与上一条全勤规则同构 ——
   「是/否」下拉默认满宽（整行限宽 420px，避免窄栏下被拉成超宽下拉），
   选「是」后收窄到 92px，露出「每次扣款（元/次）」输入框
   （原字段 makeup_card_deduct「超补卡次数是否扣款」已整块移除） */
/* 20261020t：420 → 330，与其它单控件行左缘对齐（用户要求同类错位一起修） */
#global-config-body .field[data-cfg-field="missing_deduct_enabled"] .flex-inline-row { gap: 10px; max-width: 330px; }
#global-config-body .field[data-cfg-field="missing_deduct_enabled"] .flex-inline-row .select-wrap { flex: 1 1 auto; min-width: 0; }
#global-config-body .field[data-cfg-field="missing_deduct_enabled"] .flex-inline-row .input-wrap { flex: 1 1 auto; min-width: 0; }
#global-config-body .field[data-cfg-field="missing_deduct_enabled"] .flex-inline-row.flex-max-on .select-wrap { flex: 0 0 92px; }
#global-config-body .field[data-cfg-field="missing_deduct_enabled"] .flex-inline-row .input-suffix { padding-right: 9px; padding-left: 4px; }
/* 规则设置 04 早来计算加班（20260925j）：与全勤/补卡规则同构 ——
   「是/否」下拉默认满宽，选「是」后收窄（flex-max-on），露出「早来最少提前」输入框
   （.input-wrap 必须给 flex:1 1 auto，否则占位文字撑宽输入框、下拉被挤成细条） */
#global-config-body .field[data-cfg-field="early_ot"] .flex-inline-row { gap: 8px; }
#global-config-body .field[data-cfg-field="early_ot"] .flex-inline-row .select-wrap { flex: 1 1 auto; min-width: 0; }
#global-config-body .field[data-cfg-field="early_ot"] .flex-inline-row .input-wrap { flex: 1 1 auto; min-width: 0; }
#global-config-body .field[data-cfg-field="early_ot"] .flex-inline-row.flex-max-on .select-wrap { flex: 0 0 88px; }
#global-config-body .field[data-cfg-field="early_ot"] .flex-inline-row .input-suffix { padding-right: 9px; padding-left: 4px; }
/* 规则设置 09 全勤规则2~6（20261017j）：与「是否计算全勤/补卡扣款/早来加班」同构 ——
   不启用 = 「不启用/启用」下拉满宽；启用 = 下拉收窄 92px + 露出「次数」输入框。
   前缀选择器覆盖 规则2 max_late / 规则3 max_early / 规则4 max_late_early /
   规则5 max_missing / 规则6 max_leave（键名都以 full_attendance_max 开头）。
   🔴 旧实现（select.input 塞 .input-wrap）两个坑：简写 background 清箭头 + 78px
   死宽导致点外框空白无反应 → 本规则整体取代之 */
#global-config-body .field[data-cfg-field^="full_attendance_max"] .flex-inline-row { gap: 8px; }
#global-config-body .field[data-cfg-field^="full_attendance_max"] .flex-inline-row .select-wrap { flex: 1 1 auto; min-width: 0; }
#global-config-body .field[data-cfg-field^="full_attendance_max"] .flex-inline-row .input-wrap { flex: 1 1 auto; min-width: 0; }
#global-config-body .field[data-cfg-field^="full_attendance_max"] .flex-inline-row.flex-max-on .select-wrap { flex: 0 0 92px; }
#global-config-body .field[data-cfg-field^="full_attendance_max"] .flex-inline-row .input-suffix { padding-right: 9px; padding-left: 4px; }
/* 1/5 窄栏：只读规则1 的字号收到 14px，过长时省略显示（完整规则见下方提示文字） */
#global-config-body .field[data-cfg-field="full_attendance_rule1"] .input.is-locked {
  font-size: 14px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* 大小周设置弹窗：组行 + 逗号分隔日期输入框 */
.bsw-row { display: flex; align-items: center; gap: 16px; margin-bottom: 10px; }
.bsw-group-name { flex: none; min-width: 110px; max-width: 220px; font-weight: 600; font-size: 14px; color: var(--ink-800); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bsw-input { min-width: 0; }
.group-time-row { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; margin-bottom: 14px; }
.group-time-row.group-ot-row { grid-template-columns: repeat(3, 1fr); }
.group-time-row.group-ot-row .group-time-col:last-child { grid-column: span 1; }
.group-time-col { background: var(--bg-paper-2); border: 1px solid var(--border-default); border-radius: 10px; padding: 12px 14px; }

/* 倒班/自由打卡统一班次列表（横向一行一个班次，节省高度） */
.shift-list {
  background: var(--bg-paper-2); border: 1px solid var(--border-default);
  border-radius: 10px; padding: 12px 14px;
}
.shift-grid, .shift-grid-row {
  display: grid; grid-template-columns: 86px repeat(8, minmax(0, 1fr)) 30px;
  gap: 6px; align-items: center;
}
.shift-grid-head {
  font-size: 12px; font-weight: 600; color: var(--ink-500);
  padding: 0 0 6px; text-align: center; white-space: nowrap;
}
.shift-grid-head .head-sub { font-size: 11px; font-weight: 400; color: var(--ink-400); }
.shift-grid-row { margin-bottom: 6px; }
.shift-grid-row:last-of-type { margin-bottom: 0; }
.shift-row-name {
  font-size: 12.5px; font-weight: 600; color: var(--ink-700);
  text-align: center; white-space: nowrap;
}
.shift-cell {
  width: 100%; box-sizing: border-box; padding: 5px 4px !important;
  font-size: 13px !important; text-align: center; border-radius: 6px !important;
}
.shift-del-btn {
  width: 26px; height: 26px; border-radius: 6px; border: 1px solid var(--border-strong);
  background: var(--bg-paper); color: var(--ink-500); cursor: pointer;
  font-size: 15px; line-height: 1; padding: 0; flex-shrink: 0;
}
.shift-del-btn:hover { border-color: var(--danger); color: var(--danger); background: #fef2f2; }
.shift-add-btn { margin-top: 8px; }
.group-time-col-title { font-size: 13px; font-weight: 600; color: var(--ink-700); margin-bottom: 10px; padding-bottom: 6px; border-bottom: 1px solid var(--border-default); text-align: center; }
.group-time-col .cell-field { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.group-time-col .cell-field:last-child { margin-bottom: 0; }
.group-time-col .cell-field .field-label { flex: none; white-space: nowrap; font-size: 13px; font-weight: 600; color: var(--ink-800); }
.group-time-col .cell-field input { flex: 1; min-width: 0; }
/* 开关字段：文字 + 开关同一行（间距 20px，不贴最右） */
#group-form-modal .form-field-row { display: flex; align-items: center; gap: 20px; }
#group-form-modal .form-field-row .field-label { display: inline; margin: 0; font-weight: 600; color: var(--ink-800); }
/* 不固定休息：标题占一行，下方两栏（左选择休息类型、右月休输入框） */
.rest-type-row { display: flex; align-items: center; gap: 14px; }
.rest-type-row .select-wrap { flex: 1; min-width: 0; }
/* 双休/单休的「星期几」下拉（20261014k）：与休息类型下拉同排等分宽度，窄栏下允许
   收缩（考勤组弹窗为两列网格，三个下拉同排时不得撑破单元格） */
.rest-type-row .rest-wd-select { flex: 1 1 0; min-width: 0; }
.rest-type-row .group-rest-days-input { width: 150px; flex: none; }
/* 20260927h：是/否下拉与时长输入框 4:6（选「是」出现输入框后 .on 生效；
   未选时输入框 hidden，下拉仍占满整行）。on 态用 grid 4fr/6fr 严格比例
   （flex-grow 百分比 basis 在弹窗布局栈下分配不稳，实测偏移） */
.ratio-46 .group-rest-days-input { width: auto; min-width: 0; }
.ratio-46.on { display: grid; grid-template-columns: 4fr 6fr; gap: 10px; align-items: center; }
/* 跨凌晨班次开关行：与上方模块保持合适间距 */
/* 跨凌晨行（20260925p → 20260928h 四栏）：班次类型/存在情况/错位一行四栏，
   尾栏空着；display:none 的格子不占网格位，显隐自动补列 */
#shift-form-modal .shift-crossdawn-row { margin-top: 14px; grid-template-columns: repeat(4, 1fr); }
@media (max-width: 900px) {
  #shift-form-modal .shift-crossdawn-row { grid-template-columns: 1fr; }
}
/* 标准时长（20260928i）：占位符=自动计算的值，颜色与正常输入文字一致（用户口径：不要灰色「自动 X」） */
#shift-form-std-hours::placeholder { color: var(--ink-800); opacity: 1; }

/* 跨凌晨打卡记录是否错位：单选框行 + 下方独立备注行（不与选项重叠） */
.crossdawn-radio-row { display: flex; align-items: center; gap: 22px; }
.crossdawn-radio-row .radio-inline { display: inline-flex; align-items: center; gap: 6px; cursor: pointer; font-size: 14.5px; color: var(--ink-800); }
.crossdawn-radio-row .radio-inline input { width: 16px; height: 16px; margin: 0; accent-color: var(--accent-600); cursor: pointer; }

/* 考勤组弹窗：班次卡片列表（每个班次独立配置，点击编辑在二级弹窗中设置） */
.shift-cards { display: flex; flex-direction: column; gap: 8px; margin-bottom: 10px; }
.shift-card {
  display: flex; align-items: center; gap: 16px;
  background: var(--bg-paper-2); border-radius: 10px; padding: 12px 16px;
}
.shift-card-main { flex: 1; min-width: 0; }
.shift-card-name { font-size: 15px; font-weight: 600; color: var(--ink-900); margin-bottom: 2px; }
.shift-card-time { font-size: 13px; color: var(--ink-600); font-family: var(--font-mono); margin-bottom: 6px; }
.shift-card-tags { display: flex; flex-wrap: wrap; gap: 6px; }
.shift-tag {
  font-size: 11.5px; line-height: 1; padding: 4px 8px; border-radius: 6px;
  background: var(--accent-50); color: var(--accent-600); white-space: nowrap;
}
.shift-card-ops { display: flex; gap: 8px; flex-shrink: 0; }
.shift-cards-foot { display: flex; align-items: center; gap: 12px; }

/* 班次弹窗：时间设置网格（4 列，标签在上输入在下）。
   20261013i：标签字号不再单独压小 —— 原先 `.st-field .field-label` 被覆盖成 12.5px，
   比同弹窗「班次名称」「规定员工打卡次数」等 15px 标签小一圈（用户反馈「标题字体大小
   不统一」）⇒ 删掉该覆盖，7 个标签统一继承 .field-label 的 15px。同时删掉已无引用的
   `.st-field .head-sub`（「晚间吃饭开始/结束时间」后的「(可不填)」副标题 20261013i
   已按要求去掉，全站仅存的 .head-sub 是排班表表头 .shift-grid-head .head-sub）。
   ⚠️ 字号统一是用户明确要求，与「窄栏裁切优先去图标/内边距、不靠缩字号」的红线不冲突：
   此处是**放大到与其它字段一致**，不是缩字号省宽度（input 字号仍 14px 未动）。 */
.shift-time-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px 14px; }
.st-field { display: flex; flex-direction: column; gap: 5px; }
.st-field input { padding: 8px 10px; font-size: 14px; border: 1px solid var(--border-default); border-radius: 8px; background: var(--bg-paper); color: var(--ink-900); font-family: var(--font-mono); width: 100%; box-sizing: border-box; }
.st-field input:focus { outline: none; border-color: var(--accent-500); box-shadow: 0 0 0 3px rgba(var(--accent-glow), 0.12); }
/* 班次弹窗时间网格（20261013h）：3 个「双输入」时段组件（上下班时间 / 午休开始-结束 /
   晚间吃饭开始-结束）的连线容器 —— 与 02 区 .input-wrap.time-range 同口径（隐藏原生
   选择器图标 + 值居中 + 两框 flex 等分），但**不能**套 .input-wrap：.st-field input 自身
   已有边框圆角，再套一层会变双层边框。字号保持 14px 不变（不用缩字号省宽度）。 */
.shift-time-grid .st-range { display: flex; align-items: center; gap: 5px; }
.shift-time-grid .st-range input {
  flex: 1 1 0; min-width: 0; width: auto; padding: 8px 2px; text-align: center;
}
.shift-time-grid .st-range input::-webkit-calendar-picker-indicator { display: none; }
.shift-time-grid .st-range .st-range-sep {
  flex: 0 0 auto; color: var(--ink-300); font-size: 13px; user-select: none;
}
/* 同排底对齐（口径同 .field-grid.cfg-time-grid）：标签行数不一时（窄栏自动换行）把控件
   压到单元格底部，保证同排输入框底边齐平。20261013i 起 7 个标签字号统一 15px，正常
   宽度下均单行显示；该兜底规则保留，窄屏换行时仍保证底边齐平。 */
.shift-time-grid .st-field > input,
.shift-time-grid .st-field > .st-range { margin-top: auto; }
.group-rest-days-input { padding: 9px 12px; font-size: 14.5px; border: 1px solid var(--border-default); border-radius: var(--radius-md); background: var(--bg-paper); color: var(--ink-800); font-family: var(--font-mono); box-sizing: border-box; }

/* 排班表管理：列表（表格样式与员工管理 emp-table 一致，无外层边框包裹） */
.sched-list-area { flex: 1 1 0; min-height: 0; overflow: auto; }
.sched-list-table tbody tr { cursor: default; }
.sched-list-table .ops { width: 130px; }
/* 排班页与请假管理同布局：去掉 card 双层包裹后压缩页头下方间距 */
#tab-schedule .leave-page-head { padding-bottom: 10px; }
/* 排班表管理页：提示文字紧跟「更新排班数据至考勤」按钮右侧 10px（不推到最右） */
#tab-schedule .leave-page-tip { margin-left: 10px; }
/* 排班表详情页：提示文字推到最右侧（与列表页 10px 规则区分） */
#tab-schedule .sched-tip-end { margin-left: auto; }
/* 浅蓝操作按钮（与请假管理按钮同风格）：导入/导出类 */
.btn-lightblue {
  background: var(--accent-50); border-color: var(--accent-100); color: var(--accent-700);
}
.btn-lightblue:not(:disabled):hover {
  background: var(--accent-100); border-color: var(--accent-300); color: var(--accent-700);
}
/* 浅红危险操作按钮：清空数据 */
.btn-lightred {
  background: #fef2f2; border-color: #fecaca; color: var(--danger);
}
.btn-lightred:not(:disabled):hover {
  background: var(--danger-soft); border-color: var(--danger-line); color: var(--danger);
}
.sched-group-name { font-weight: 600; color: var(--ink-900); white-space: nowrap; }
.sched-shift-lines { display: flex; flex-direction: column; gap: 4px; }
.sched-shift-line { display: flex; align-items: baseline; gap: 10px; }
.sched-shift-name { font-size: 14px; font-weight: 600; color: var(--ink-900); }
.sched-shift-time { font-size: 12.5px; color: var(--ink-500); font-family: var(--font-mono); }
.sched-badge { display: inline-flex; align-items: center; padding: 4px 10px; border-radius: 999px; font-size: 12.5px; white-space: nowrap; }
.sched-badge.ok { background: rgba(22, 163, 74, 0.12); color: var(--success); }
.sched-badge.none { background: var(--bg-paper-2); color: var(--ink-500); }
.sched-badge.pending { background: rgba(234, 88, 12, 0.12); color: var(--warning); }
.leave-page-tip .tip-warn { color: var(--danger); font-weight: 600; }

/* 排班表详情：表格样式与请假管理 leave-grid 一致（姓名列固定，日期列收窄） */
table.grid-full.sched-detail td.col-day { min-width: 50px; padding: 2px 1px; }
table.grid-full.sched-detail th.sched-day-th { font-family: var(--font-mono); }
table.grid-full.sched-detail th.sched-day-th.sched-we { color: var(--danger); }
table.grid-full.sched-detail td.sched-cell-txt { font-size: 13px; text-align: center; }
.sched-member-name { font-weight: 600; }

/* 20261024e：排班格子与下拉统一白底 —— 取消隔行灰底，下拉去描边、去箭头，
   点击格子即弹出原生班次列表（select 本身保留，无障碍/键盘可用）。 */
table.grid-full.sched-detail tr.block-a td.col-day,
table.grid-full.sched-detail tr.block-b td.col-day { background-color: var(--bg-paper); }
.sched-sel {
  width: 100%; min-width: 0; height: 26px; padding: 0 2px;
  font-size: 12.5px; line-height: 26px;
  border: 0; border-radius: 0;
  background-color: var(--bg-paper); color: var(--ink-900);
  background-image: none;   /* 干掉全局 select 的下拉箭头（style.css 内侧 select 规则） */
  -webkit-appearance: none; -moz-appearance: none; appearance: none;
  box-sizing: border-box; text-align: center; text-align-last: center;
  cursor: pointer;
}
.sched-sel::-ms-expand { display: none; }
.sched-sel:hover { background-color: var(--accent-50); }
.sched-sel:focus { outline: none; background-color: var(--accent-50); box-shadow: inset 0 0 0 2px var(--accent-500); }
/* 深色模式下方「html.dark select」会把箭头加回来（特异性更高），这里再压一次 */
html.dark .sched-sel { background-image: none; }

/* 日期列头：上行日期数字，下行「星期 + 节假日/补班标记」 */
table.grid-full.sched-detail th.sched-day-th { padding: 3px 2px; line-height: 1.15; vertical-align: middle; }
.sched-dh-num { display: block; font-family: var(--font-mono); font-size: 13px; font-weight: 700; }
.sched-dh-sub { display: flex; align-items: center; justify-content: center; gap: 2px; font-size: 10.5px; font-weight: 400; color: var(--ink-500); }
.sched-dh-tag { font-style: normal; font-size: 10px; line-height: 1; padding: 1px 3px; border-radius: 3px; font-weight: 600; }
.sched-dh-tag { background: var(--bg-paper-2); color: var(--ink-500); }
th.sched-day-th.mk-makeup .sched-dh-tag { background: rgba(var(--accent-glow), 0.14); color: var(--accent-600); }
th.sched-day-th.mk-h3 .sched-dh-tag { background: rgba(var(--danger-glow), 0.14); color: var(--danger); }
th.sched-day-th.mk-h2 .sched-dh-tag { background: rgba(var(--warning-glow), 0.16); color: var(--warning); }
th.sched-day-th.mk-h3 .sched-dh-num { color: var(--danger); }

/* 导入时班次不一致被清空的单元格：1px 红色边框 + 右上角红色角标，悬停提示 */
td.sched-cell-invalid { position: relative; border: 1px solid var(--danger) !important; box-shadow: inset 0 0 0 1px rgba(220, 38, 38, 0.18); cursor: help; }
td.sched-cell-invalid::after {
  content: '';
  position: absolute;
  top: 0;
  right: 0;
  width: 0;
  height: 0;
  border-top: 9px solid var(--danger);
  border-left: 9px solid transparent;
  border-top-right-radius: 4px;
  z-index: 1;
  pointer-events: none;
}
/* 弹窗内警示文字（排班表格式选择） */
.tpl-warn-text { color: var(--danger); font-weight: 600; }

.leave-edit-hint { margin-bottom: 10px; font-size: 14px; }
.leave-edit-items { display: flex; flex-direction: column; gap: 8px; margin-bottom: 10px; }
.leave-edit-row { display: flex; align-items: center; gap: 8px; }
.leave-edit-row select { border: 1px solid var(--border-default);
  border-radius: 8px; background-color: var(--bg-paper); color: var(--ink-800); font-size: 14px; font-family: inherit; padding-right: 24px; }
.leave-edit-row .leave-type-select { flex: 1; min-width: 0; padding: 6px 8px; }
.leave-edit-row input[type="number"] { width: 84px; padding: 6px 8px; border: 1px solid var(--border-default);
  border-radius: 8px; background: var(--bg-paper); color: var(--ink-800); font-size: 14px; font-family: inherit; }
.leave-edit-row .leave-am-pm-select { width: 76px; padding: 6px 4px; flex-shrink: 0; }
.leave-edit-row .leave-unit-select { width: 72px; padding: 6px 4px; flex-shrink: 0; }
/* 20261009m：加班 / 补卡的单值编辑行（与请假行共用 .leave-edit-row，只多一个固定单位标签） */
/* 加班的时长输入沿用上面的 input[type=number] 样式（84px），这里只补补卡的「时刻」输入框 */
.leave-edit-row input[type="time"].leave-time-input { width: 140px; padding: 6px 8px; border: 1px solid var(--border-default);
  border-radius: 8px; background: var(--bg-paper); color: var(--ink-800); font-size: 14px; font-family: inherit; }
.leave-edit-fixed-unit { font-size: 13.5px; color: var(--ink-500, #64748b); flex-shrink: 0; }
.leave-edit-fixed-gap { flex: 1; min-width: 0; }
/* 20261009q：加班编辑 = 单输入框（无「添加/删除」行操作），输入框加宽 */
.leave-edit-row input.leave-ot-input { width: 240px; }
.leave-edit-empty { color: var(--ink-400); font-size: 14px; padding: 8px 0; }

/* 规则设置 → 请假类型：每个类型一张「请假规则」卡（20261023e 用户定版）
   布局口径：**一行五栏** —— 请假类型（类型名，文字栏，放在最左）/ 简称 / 汇总单位 /
   是否计出勤天数 / 请假时长处理；不再有卡片标题（23e 用户：「请假类型 建议放在简称左侧」）。
   🔴 三处不能改：
     ① 请假类型 / 简称 / 汇总单位的宽度**固定小尺寸**（110 / 90 / 92px，刚好显示完整），
        剩余宽度全部给「请假时长处理」——它的选项文字「计入正班（正班最大不超过标准时长）」
        ≈262px，与其它项等分就会被 ellipsis 裁断；
     ② 输入框/下拉框**不覆盖 padding 与 font-size** —— 全局 `input, select` 是
        `padding:8px 11px; font-size:15.5px`，覆盖成 6px/14px 会比其它模块矮一截；
     ③ 用 flex-wrap 而不是 grid：窄屏时最后一项整体掉到下一行占满宽度，永远不裁字。 */
.lt-rules-list { display: flex; flex-direction: column; gap: 10px; margin-top: 12px; }
.lt-rules-empty { font-size: 13.5px; color: var(--ink-400); padding: 2px 0 4px; }
.lt-rule-card {
  /* 20261023e 用户定版：去掉描边与自定义底色，**与上方「添加请假类型」卡同一套底色**
     （`.cfg-sub-body .cfg-card` 用的就是 --bg-paper-2），靠 10px 间距区分，不再画线 */
  border: 0;
  border-radius: 10px;
  background: var(--bg-paper-2, #f5f6f9);
  padding: 9px 14px 12px;
}
.lt-rule-grid { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 10px 12px; }
.lt-rule-item { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.lt-rule-item:nth-child(1) { flex: 0 1 110px; min-width: 72px; }
.lt-rule-item:nth-child(2) { flex: 0 0 90px; }
.lt-rule-item:nth-child(3) { flex: 0 0 92px; }
.lt-rule-item:nth-child(4) { flex: 0 0 108px; }
.lt-rule-item:nth-child(5) { flex: 1 1 262px; }
.lt-rule-lb {
  font-size: 13px; color: var(--ink-500); line-height: 1.35;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* 类型名（文字栏，加粗）：上面放一个**空的同款标签位**（.lt-rule-lb-ghost），
   再给文字补与控件相同的 8px 上下内距 ⇒ 文字与右侧输入框/下拉框**逐行垂直居中对齐**
   （不用 magin/padding 硬算固定值，标签行高或控件高变化时仍然对齐）。 */
.lt-rule-type {
  padding: 8px 0;
  font-size: 15.5px; font-weight: 700; color: var(--ink-800); line-height: 1.35;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.lt-rule-card .lt-days-short,
.lt-rule-card .lt-days-unit,
.lt-rule-card .lt-days-check-sel,
.lt-rule-card .lt-days-work { width: 100%; min-width: 0; }
/* 结尾提示（20260915c）：两段编号说明各占一行，行内不折行（避免半句换行） */
.lt-days-hint { font-size: 13px; color: var(--ink-400); margin-top: 6px; line-height: 1.7; }
.lt-days-hint > div { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* ============================================================
   登录页
   ============================================================ */
/* 背景图（static/img/bg-auth.jpg，20260928ac 用户定版换官方深蓝科技图）：
   深浅两模式统一使用此图，不加叠层（图自带低对比网格，卡片区域不受干扰）；
   图片缺失时回退到浅蓝渐变 */
.login-wrap {
  min-height: 100vh;
  display: flex; align-items: center; justify-content: center;
  padding: 24px;
  background:
    url('/static/img/bg-auth.jpg') center / cover no-repeat,
    linear-gradient(180deg, #eaf1fe 0%, var(--bg-canvas) 46%, var(--bg-canvas) 100%);
}
/* 登录页左上角 logo（20260928ad）：深蓝背景配深色版 logo（白字），固定尺寸（20260928ae 用户定版 50px/32/35） */
.login-logo {
  position: fixed; top: 32px; left: 35px;
  height: 50px; width: auto;
  z-index: 10; user-select: none; pointer-events: none;
}

.login-box {
  width: 100%; max-width: 400px;
  /* liquid-glass 磨砂（20260928ae，仅登录/注册页）：半透明 + 背景模糊提饱和；20260928ah 浅色透明度用户定版 0.7 */
  background: rgba(255, 255, 255, 0.7);
  backdrop-filter: blur(20px) saturate(1.5);
  -webkit-backdrop-filter: blur(20px) saturate(1.5);
  border: 1px solid rgba(255, 255, 255, 0.45);
  border-radius: 16px;
  box-shadow: 0 8px 32px rgba(15, 30, 60, 0.16);
  padding: 34px 32px 30px;
}
.login-box h2 {
  font-size: 21px; font-weight: 700; color: var(--ink-800);
  margin-bottom: 6px; letter-spacing: 0.01em;
}
.login-box .sub {
  font-size: 14px; color: var(--ink-400);
  margin-bottom: 22px; line-height: 1.5;
}
.login-box .field {
  display: flex; flex-direction: column; gap: 7px;
  margin-bottom: 16px;
}
.login-box .lb {
  font-size: 14px; font-weight: 500; color: var(--ink-600);
}
.login-box input {
  width: 100%; box-sizing: border-box;
  padding: 10px 12px; font-size: 15px;
  /* 磨砂适配（20260928af）：半透明输入框融入玻璃卡片，仅 .login-box 作用域 */
  background: rgba(255, 255, 255, 0.45);
  border: 1px solid rgba(255, 255, 255, 0.55);
  border-radius: 8px;
}
.login-box input:focus {
  background: rgba(255, 255, 255, 0.65);
  border-color: var(--accent-500);
  box-shadow: 0 0 0 3px rgba(10, 132, 255, 0.15);
}
html.dark .login-box input {
  background: rgba(255, 255, 255, 0.07);
  border-color: rgba(255, 255, 255, 0.16);
  color: var(--ink-800);
}
html.dark .login-box input:focus {
  background: rgba(255, 255, 255, 0.11);
  border-color: var(--accent-500);
  box-shadow: 0 0 0 3px rgba(94, 168, 255, 0.2);
}
.login-box .btn { width: 100%; padding: 10px 14px; margin-top: 4px; }
/* 下次自动登录勾选（20261011r） */
.login-remember { display: flex; align-items: center; gap: 7px; margin: 2px 2px 0;
  font-size: 13px; color: var(--ink-500); cursor: pointer; user-select: none; }
.login-remember input[type="checkbox"] { width: 15px; height: 15px; margin: 0;
  accent-color: var(--accent-600); cursor: pointer; flex-shrink: 0; }
/* 深色下卡片：深色磨砂玻璃 + 收黑阴影（20260928ae 随 liquid-glass 同步） */
html.dark .login-box {
  background: rgba(28, 28, 30, 0.55);
  border: 1px solid rgba(255, 255, 255, 0.14);
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.45);
}

/* ============================================================
   员工管理页 · 按钮配色方案（UI 分析 After 方案落地）
   层级：同步员工数据=唯一实心主按钮(btn-accent) > 次级白底描边
   > 行内文字按钮(ghost) > 删除红色仅在 hover/已勾选时出现
   ============================================================ */
/* 次级按钮：白底灰描边（分析 a-secondary），不与主按钮争夺视线 */
#page-employees .btn:not(.btn-accent):not(:disabled) {
  background: var(--bg-card); border-color: var(--ink-200); color: var(--ink-600);
}
#page-employees .btn:not(.btn-accent):not(:disabled):hover {
  background: var(--ink-50); border-color: var(--ink-300); color: var(--ink-900);
}
/* 未激活（未勾选）：灰色禁用态，不回落到浅蓝基础样式 */
#page-employees .btn:disabled {
  background: var(--ink-100); border-color: var(--ink-200); color: var(--ink-400);
  cursor: not-allowed;
}
/* 批量删除：未勾选=灰色禁用；勾选后=白底红字红边，hover 浅红底 */
#page-employees .emp-batch-del:not(:disabled) {
  background: var(--bg-card); border-color: var(--danger-line); color: var(--danger);
}
#page-employees .emp-batch-del:not(:disabled):hover {
  background: var(--danger-soft); border-color: var(--danger); color: var(--danger);
}
/* 行内操作（全站列表通用）：默认灰底 + 黑字，hover 变浅蓝 */
.emp-row-btn, .row-btn {
  background: var(--ink-100); border: none; color: var(--ink-900);
  font-size: 15px; padding: 4px 8px; border-radius: 6px; cursor: pointer;
  transition: all .15s; white-space: nowrap;
}
.emp-row-btn:hover, .row-btn:hover { background: var(--accent-50); color: var(--accent-700); }
/* 行内删除：默认黑字，hover 变红 + 浅红底 */
.emp-row-btn.emp-row-del, .row-btn.row-btn-del { color: var(--ink-900); }
.emp-row-btn.emp-row-del:hover, .row-btn.row-btn-del:hover { background: var(--danger-soft); color: var(--danger); }
/* 列表正文字号 +2px（仅员工列表正文，表头保持） */
#emp-list table.grid-full { font-size: 16px; }
/* 蓝字按钮（白底蓝字，hover 浅蓝底）：员工页部门/考勤组管理、考勤统计页大小周/节假日/排班/请假入口 */
.btn.btn-linkblue:not(:disabled) {
  background: var(--bg-card); border-color: var(--ink-200); color: var(--accent-700);
}
.btn.btn-linkblue:not(:disabled):hover {
  background: var(--accent-50); border-color: var(--accent-300); color: var(--accent-700);
}
/* 员工管理页：ID 级次级按钮规则(#page-employees .btn)优先级高于上面的全局类，需同级覆盖恢复蓝字 */
#page-employees .btn.btn-linkblue:not(:disabled) {
  background: var(--bg-card); border-color: var(--ink-200); color: var(--accent-700);
}
#page-employees .btn.btn-linkblue:not(:disabled):hover {
  background: var(--accent-50); border-color: var(--accent-300); color: var(--accent-700);
}
/* 返回按钮：白底灰字（区别于浅蓝动作按钮） */
.btn.btn-white:not(:disabled) {
  background: var(--bg-card); border-color: var(--ink-200); color: var(--ink-600);
}
.btn.btn-white:not(:disabled):hover {
  background: var(--ink-50); border-color: var(--ink-300); color: var(--ink-900);
}
/* 批量设置部门/考勤组（20260928p）：激活（勾选后可点）= 蓝底白字加粗，突出可操作性；
   禁用态维持上方灰底灰字。双 id 压过 #page-employees .btn 系列规则 */
#page-employees #emp-btn-batch-dept:not(:disabled), #page-employees #emp-btn-batch-group:not(:disabled) {
  background: var(--accent-500); border-color: var(--accent-600); color: #fff; font-weight: 600;
}
#page-employees #emp-btn-batch-dept:not(:disabled):hover, #page-employees #emp-btn-batch-group:not(:disabled):hover {
  background: var(--accent-600); border-color: var(--accent-600); color: #fff;
}
/* 规则设置页主题开关（20260928p）：图标与文字垂直居中对齐（原行内基线对不齐） */
#theme-toggle { display: inline-flex; align-items: center; gap: 6px; }
/* 20260928q：svg 行内坐在基线上，图标框底部多出降部空隙 → flex 居中后图标视觉偏高
   1~2px。svg 改块级 + 图标框行高压到 1，框高即图标高，居中后与文字严格水平对齐 */
#theme-toggle .ico { display: inline-flex; align-items: center; line-height: 1; }
#theme-toggle .ico svg { display: block; }

/* 考勤统计结果页字号保持 14px 不变（本轮统一 15px 的例外） */
#summary-grid table.grid-full { font-size: 14px; }
/* 绿色按钮禁用态（请假页「更新请假数据至考勤」无数据时） */
.btn-green:disabled { opacity: 0.45; cursor: not-allowed; box-shadow: none; }
.btn-green:disabled:hover { background: var(--success); border-color: var(--success); transform: none; }
/* 面包屑页面标题（请假管理/排班表管理）：不加粗，上一级可点击，当前页浅色 */
.proj-crumb { display: flex; align-items: center; gap: 8px; }
.proj-crumb .crumb-link {
  cursor: pointer; color: var(--ink-700); border-radius: 6px; padding: 2px 4px;
  transition: all .15s;
}
.proj-crumb .crumb-link:hover { color: var(--accent-600); background: var(--accent-50); }
.proj-crumb .crumb-sep { color: var(--ink-300); }
.proj-crumb .crumb-cur { color: var(--ink-400); }
/* 20260922h：计算考勤「内页」标题缩小到 16px（顶层页面标题仍是 .page-title 24px）。
   覆盖范围：#proj-title 本体 + 它的面包屑（如「考勤统计 > 请假管理」）。
   ID 选择器优先级高于 .page-title，故无需 !important。 */
#proj-title { font-size: 16px; }
/* 旷工（整天无打卡文字标记）：20260925i 浅黄底深黄字（与异常检查模式旷工黄 #f9c716 同色系），
   与缺卡浅红区分；图例圆点已随上方 .lg-dot 组统一 */
table.grid-full td.c-absent { background: #fef9c3 !important; color: #a16207; font-weight: 600; }
/* 旷工/休息行休息日显示值（20261022p，如「休」）：灰字（非异常，不加异常底色；
   不覆盖 td.rest 的周末列底色） */
table.grid-full td.c-rest-mark { color: var(--ink-300, #9fa4ad); font-weight: 400; }
/* 分页容器统一：考勤统计/预览的外层为 flex，内层 .pagination 需占满宽度使「共 N 人」靠左 */
.summary-pagination > .pagination, .preview-pagination > .pagination { width: 100%; }

/* ============================================================
   全站下拉选择框箭头统一：黑色实心小三角（与考勤统计页
   姓名/部门筛选按钮的 ▾ 一致）；各 select 规则的 background
   已改为 background-color，避免简写清掉本箭头
   ============================================================ */
select {
  -webkit-appearance: none; appearance: none;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 10 10'><path d='M1 3h8L5 8z' fill='black'/></svg>");
  background-repeat: no-repeat;
  background-position: right 8px center;
  padding-right: 26px;
}

/* ---------- 配置考勤明细表格格式（20260914k） ---------- */
/* 表格配置入口按钮：20260916c 从「模块标题右侧」移到「模块内容区顶部」，
   故用 .cfg-card-actions（挂在 .cfg-card-body 内，明细在前、汇总在后）。
   .cfg-head-actions 为 20260914k~20260916b 的旧位置样式，已不再使用。 */
.cfg-card-actions { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.cfg-card-actions + .field-grid,
.cfg-card-actions + .cfg-actions-note { margin-top: 18px; }

/* 全屏子页面 */
.de-overlay { position: fixed; inset: 0; z-index: 1000; background: #f2f4f8; display: flex; flex-direction: column;
  --de-hot: #e8f2ff;          /* 鼠标经过的高亮底色（20260914q：浅红 → 浅蓝） */
  --de-hot-line: #b9d7fa; }
.de-overlay.hidden { display: none; }
.de-topbar { display: flex; align-items: center; gap: 14px; padding: 12px 20px; background: var(--bg-card);
  border-bottom: 1px solid var(--border-default); flex-shrink: 0; }
.de-title { font-size: 16.5px; font-weight: 600; color: var(--ink-800); }
/* 20260920d：动作按钮从顶栏最右侧移到「标题名称」右侧（去掉 margin-left:auto 即可，
   靠 .de-topbar 自身的 14px gap 与标题留出间距）
   20261039f：动作组改为「撑满剩余宽度」（flex:1）—— 右侧跨页跳转按钮再靠
   margin-left:auto 顶到最右边，其余按钮位置一分不动（用户定版） */
.de-topbar-actions { display: flex; gap: 8px; flex: 1 1 auto; min-width: 0; }
/* 跨页跳转按钮（明细页 → 配置考勤汇总表格格式，20261039f 用户定版）：
   顶到顶栏最右侧 + 蓝色样式（.btn-blue：浅蓝底 / 蓝描边 / 蓝字，不与实心主按钮抢焦点） */
.de-jump-btn { margin-left: auto; }
/* 表格区高度自适应（20260914q：内容不足时贴合内容高度，避免表格与温馨提示之间出现空白；
   内容超高时收缩为可用高度，表内滚动 + 表头吸顶），下方紧跟「温馨提示」区域 */
.de-body { flex: 1 1 0; display: flex; flex-direction: column; gap: 12px;
  overflow: hidden; padding: 14px 20px 16px; }
.de-table-wrap { flex: 0 1 auto; min-height: 0; max-height: 100%; background: var(--bg-card);
  /* 20261039b：圆角 10px + 极浅投影，与「快捷格式」面板统一容器语言（明细页同样生效）
     20261039d：描边由 var(--border-hairline) 改为 var(--border-default) —— 与
     「快捷格式」面板、温馨提示三块描边统一（原 #ccc 比另两块深，看起来像两套容器） */
  border: 1px solid var(--border-default); border-radius: 10px; overflow: auto;
  box-shadow: var(--shadow-xs); }
/* 温馨提示（表格下方，每条独立一行，14px 黑色） */
.de-tips { flex: 0 0 auto; background: var(--bg-card); border: 1px solid var(--border-default);
  border-radius: 10px; padding: 12px 18px 13px; }
.de-tips-title { font-size: 14px; font-weight: 600; color: var(--ink-900); margin-bottom: 5px; }
.de-tips-list { margin: 0; padding: 0; list-style: none; counter-reset: de-tip; }
.de-tips-list li { counter-increment: de-tip; position: relative; padding-left: 22px;
  font-size: 14px; color: var(--ink-900); line-height: 1.95; }
.de-tips-list li::before { content: counter(de-tip) '、'; position: absolute; left: 0; top: 0;
  font-size: 14px; color: var(--ink-900); }
/* 20261039c：重点词蓝色（拖动行名 / 移除 / 添加 / 保存配置…）—— 不倾斜，只提亮 */
.de-tips-list em.de-tip-k { font-style: normal; font-weight: 600; color: var(--accent-600); }

/* 预览表：单元格内容统一 14px、水平垂直居中；表格宽度铺满容器，列窄时撑开滚动 */
.de-table { border-collapse: separate; border-spacing: 0; font-size: 14px; color: var(--ink-800);
  min-width: 100%; }
.de-table th, .de-table td { border-right: 1px solid var(--border-hairline); border-bottom: 1px solid var(--border-hairline);
  padding: 9px 6px; text-align: center; vertical-align: middle; white-space: nowrap; background: var(--bg-card); }
.de-table thead th { position: sticky; top: 0; z-index: 30; background: var(--bg-paper-2);
  font-weight: 600; color: var(--ink-800); white-space: normal; word-break: break-all; }
.de-table thead tr:first-child th { height: 46px; line-height: 1.32; }
.de-table .de-sticky { position: sticky; z-index: 20; }
.de-table thead .de-sticky { z-index: 40; }
/* 20261039c：汇总列收窄（52/48 → 46/44）—— 表头加高后 2 行折行放得下，
   一屏能多看几列；数值仍是 nowrap（不折行），不会数字断行 */
/* ⚠️ 必须写 `.de-table thead` 前缀：`.de-table th, .de-table td { padding: 9px 6px }` 的
   特异性(0,1,1)高于单类(0,1,0)，只写 .de-sum-head 的 padding 根本不会生效（实测踩过） */
.de-table thead .de-sum-head { min-width: 48px; padding: 5px 3px; }
.de-sum-head[draggable="true"] { cursor: grab; }
.de-sum-head .de-sum-label { white-space: normal; display: inline-block; line-height: 1.28;
  vertical-align: middle; font-size: 13px; }
.de-add-head { min-width: 84px; }
/* 20261039c（用户口径）：由虚线浅底改为**蓝底白字**实心按钮（明细页同样生效） */
.de-add-btn { display: inline-flex; align-items: center; gap: 4px; border: 1px solid var(--brand);
  color: #fff; background: var(--brand); border-radius: 6px; padding: 4px 10px;
  font-size: 12.5px; font-weight: 500; cursor: pointer;
  box-shadow: 0 1px 2px rgba(0, 113, 227, .18);
  transition: background .16s, border-color .16s; }
.de-add-btn:hover { background: var(--brand-hover); border-color: var(--brand-hover); }
/* 「＋ 添加」按钮固定可见（20261009i）：用户反馈表格宽/长时滚动后按钮被藏、找不到入口。
   · 纵列添加（表头最右 th.de-add-head）→ 吸附右侧（横向滚动时始终贴容器右缘）
   · 指标添加（表尾最左 td.de-add-cell）→ 吸附底部（纵向滚动时始终贴容器下缘）
   ⚠️ 吸附后会盖在相邻单元格之上（与冻结列同理）；用阴影与内容区分。
   ⚠️ z-index 45 高于表头吸附列的 40，避免被其它吸顶列盖住。 */
.de-table thead th.de-add-head { position: sticky; right: 0; z-index: 45;
  box-shadow: -6px 0 8px -6px rgba(15, 23, 42, .26); }
.de-table tfoot .de-add-cell { position: sticky; bottom: 0; z-index: 25;
  box-shadow: 6px -6px 8px -6px rgba(15, 23, 42, .26); }

/* 指标行：经过行内「指标项 / 日期格」→ 该行高亮（20260914r：改用
   .de-row-hot 类，由表级 mouseover 维护 —— 汇总列的合并单元格落在首行，
   CSS :hover 会让鼠标经过汇总列时连带点亮「上午上班」行）。
   20260920d：该行的「移除 / 编辑」按钮已收进标题单元格的悬停动作组，不再随行高亮出现。 */
.de-row .de-name { cursor: grab; user-select: none; }
.de-name .de-name-text { display: inline-block; max-width: 96px; white-space: normal; vertical-align: middle; line-height: 1.3; }
/* 行/列标题就地改名（20260920c）：双击行名/列头名出现输入框，Enter 确认 / Esc 取消 */
.de-rename-input { width: 96px; font: inherit; font-size: 12.5px; line-height: 1.3;
  padding: 2px 5px; border: 1px solid var(--brand); border-radius: 5px; outline: none;
  background: var(--bg-card); color: var(--ink-800); }
.de-rename-input:focus { box-shadow: 0 0 0 2px var(--brand-softer); }
.de-table .de-row.de-row-hot .de-name,
.de-table .de-row.de-row-hot .de-daycell { background: var(--de-hot, #e8f2ff); }
.de-name:active { cursor: grabbing; }
.de-dragging { opacity: .4; }
.de-drop-before { box-shadow: inset 0 2px 0 var(--brand); }
.de-drop-after { box-shadow: inset 0 -2px 0 var(--brand); }

/* 每日明细区域整块高亮（经过任一日期表头） */
.de-table.de-days-hot .de-daycell,
.de-table.de-days-hot .de-day-head { background: var(--de-hot, #e8f2ff); }
/* 汇总列整列高亮 */
.de-table .de-col-hot { background: var(--de-hot, #e8f2ff); }

/* 移除按钮：绝对定位居中悬浮在所属区域中心（不占布局 → 无抖动），黑色半透明底 + 白字。
   显隐由区域 hover 控制：横向=指标行经过任意位置；纵向=汇总列经过表头或内容格；
   每日明细=经过任一日期表头或日格（20260914p） */
.de-del { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  display: inline-flex; align-items: center; justify-content: center; z-index: 25;
  border: none; border-radius: 5px; padding: 2px 9px; font-size: 12px; line-height: 1.6;
  font-family: inherit; white-space: nowrap;
  cursor: pointer;
  opacity: 0; visibility: hidden; pointer-events: none;
  transition: opacity .12s, background .12s; }
/* 20260914q：背景/文字用 .de-table .de-del 提特异性，保证被列/行高亮（.de-col-hot 等）命中时
   仍然是黑色半透明底 + 白字（历史问题：纵列经过时按钮底被浅红高亮覆盖 → 白字看不清） */
.de-table .de-del { background: rgba(0, 0, 0, .62); color: #fff; }
.de-table .de-del:hover { background: rgba(0, 0, 0, .88); }
/* 20260920d：行内「移除」按钮改为与「编辑」一起收进标题单元格的悬停动作组（见下），
   不再随整行高亮出现 —— 否则鼠标一进单元格就把行名盖住并抢走点击 */
.de-table .de-col-hot .de-del-sum,
.de-table.de-days-hot .de-del-days { opacity: 1; visibility: visible; pointer-events: auto; }

/* ---------- 标题单元格的悬停动作组（20260920d）----------
   鼠标经过「行名 / 列名」所在的标题单元格时，在其中心横向排出按钮：
   行 =「编辑」+「移除」，列 =「编辑」（列的移除在内容格里，悬停整列出现，天然不冲突）。
     · 只有可改名的标题才有这组按钮 —— 序号 / 姓名 / 部门 / 日期 /「指标项」表头都没有，
       所以"不能编辑名称的模块不会出现编辑按钮"；
     · 绝对定位居中 → 不占布局，进出不会让表格列宽抖动；
     · 组内按钮是 flex 行内项、横向排开 → 编辑与移除不重叠；
     · 悬停时暂时隐藏标题文字，避免按钮压住文字（与 .de-ellipsis-txt 同一手法）；
       正在改名的输入框用 .de-renaming 保持可见。 */
.de-title-acts { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  display: flex; align-items: center; gap: 4px; z-index: 26; }
/* .de-del 默认是绝对居中（给日块 / 汇总列内容格用）—— 放进动作组后改回普通 flex 行内项 */
.de-table .de-title-acts .de-del { position: static; left: auto; top: auto; transform: none; }
.de-act { display: inline-flex; align-items: center; justify-content: center;
  border: none; border-radius: 5px; padding: 2px 9px; font-size: 12px; line-height: 1.6;
  font-family: inherit; white-space: nowrap; cursor: pointer;
  opacity: 0; visibility: hidden; pointer-events: none;
  transition: opacity .12s, background .12s; }
.de-table .de-act-edit { background: var(--brand); color: #fff; }
.de-table .de-act-edit:hover { background: var(--brand-hover); }
/* 指标项（行名 / 竖版指标列表头）的动作组有 3 个按钮（编辑/修改规则/移除）。
   20261016c：指标项列宽由 136 → 76 后，三按钮**横排**（实测 128px）放不下 →
   折成两行：第 1 行「编辑 移除」（62px），第 2 行「修改规则」（52px），组宽 64px。
   动作组本身是 position:absolute（不占布局）→ 折行不会撑高行/表头，只在竖直方向
   上下各溢出一行按钮高度（约 3px），不会盖住相邻内容。
   ⚠️ 只作用于指标项标题（.de-name，横向行名 + 竖版指标列表头都是它）；
      汇总列头的 de-acts-3（编辑 + 修改规则 = 84px）维持原横向排布，不受影响。 */
.de-table .de-name .de-title-acts.de-acts-3 {
  gap: 2px; flex-wrap: wrap; width: 64px; justify-content: center;
}
/* ⚠️「移除」按钮的类是 .de-del（不是 .de-act），基础样式带 padding 2px 9px（42px 宽）
   → 折行宽度必须把它一起收紧，否则「编辑 30 + 移除 42」> 组宽，会折成 3 行（20261016c 实测） */
.de-table .de-title-acts.de-acts-3 .de-act,
.de-table .de-title-acts.de-acts-3 .de-del { padding: 2px 4px; font-size: 11px; }
/* 折行顺序：编辑 + 移除 在第一行，修改规则 落到第二行（DOM 顺序不动） */
.de-table .de-name .de-title-acts .de-act[data-de="rename"] { order: 1; }
.de-table .de-name .de-title-acts .de-del[data-de="rowdel"] { order: 2; }
.de-table .de-name .de-title-acts .de-act[data-de="attrule"],
.de-table .de-name .de-title-acts .de-act[data-de="rawpunchrule"] { order: 3; }
.de-table .de-name:hover .de-title-acts .de-act,
.de-table .de-name:hover .de-title-acts .de-del,
.de-table .de-sum-head:hover .de-title-acts .de-act,
.de-table .de-sum-head:hover .de-title-acts .de-del { opacity: 1; visibility: visible; pointer-events: auto; }
.de-table .de-name:hover .de-name-text:not(.de-renaming),
.de-table .de-sum-head:hover .de-sum-label:not(.de-renaming) { visibility: hidden; }
.de-table .de-name-text.de-renaming,
.de-table .de-sum-label.de-renaming { visibility: visible; }
/* 改名进行中：动作组整体隐藏，避免压住输入框 */
.de-table.de-renaming .de-title-acts { display: none; }
/* 被移除按钮覆盖的单元格：hover 区域内容变暗，突出按钮 */
.de-table .de-daycell.de-col-hot, .de-table .de-day-head.de-col-hot { background: var(--de-hot, #e8f2ff); }

/* 单元格内容 */
.de-punch { font-family: var(--font-mono); font-size: 14px; min-width: 52px; }
.de-empty { color: var(--ink-400); }
.de-bad { color: var(--danger); font-weight: 600; }
.de-rest-mark { color: var(--ink-400); }
.de-emp { font-weight: 600; }
.de-sumcell { position: relative; z-index: 1; min-width: 44px;
  font-family: var(--font-mono); }

/* 每日一列（20260914m）：列头「9/1 + 周几」、周末列淡红底、中间省略列、汇总列纵向合并 */
.de-day-head { min-width: 52px; padding: 3px 5px; line-height: 1.25; }
.de-day-head .de-wd { font-weight: 400; color: var(--ink-400); }
.de-table .de-day-rest { background: #fdf0ef; }
.de-table .de-days-hot .de-day-rest { background: var(--de-hot, #e8f2ff); }
.de-ellipsis-head, .de-ellipsis-cell { min-width: 24px; padding: 3px 2px; color: var(--ink-400); }
/* 省略列表头承载「移除」按钮 → 留出按钮宽度；hover 时隐藏「…」避免透出 */
.de-ellipsis-head { min-width: 58px; }
.de-table.de-days-hot .de-ellipsis-txt { visibility: hidden; }
/* 汇总列整列合并为一个单元格：值垂直居中加粗 */
.de-table .de-sumcell { vertical-align: middle; font-weight: 600; font-size: 14px;
  padding-left: 3px; padding-right: 3px; }
.de-sum-val { display: inline-block; }
.de-blank { border-right: 1px solid var(--border-default); }
.de-add-cell { text-align: center; }

/* 弹框基类（20260914o：页面居中模态 + 遮罩；标题/底部固定，中间列表滚动）
   ⚠️「＋ 添加」已改为右侧抽屉，覆盖规则见下方 20261009j 那段；本基类服务于其余规则弹框 */
.de-pop-mask { position: fixed; inset: 0; z-index: 1090; background: rgba(15, 23, 42, .32); }
.de-pop-mask.hidden { display: none; }
.de-pop { position: fixed; left: 50%; top: 50%; transform: translate(-50%, -50%); z-index: 1100;
  background: var(--bg-card); border: 1px solid var(--border-default); border-radius: 10px;
  box-shadow: 0 14px 40px rgba(15, 23, 42, .22); padding: 12px 16px;
  width: 600px; max-width: calc(100vw - 48px); height: 580px; max-height: calc(100vh - 80px);
  display: flex; flex-direction: column; }
.de-pop.hidden { display: none; }
.de-pop-head { flex: 0 0 auto; padding: 2px 4px 10px; border-bottom: 1px solid var(--border-default); }
.de-pop-title { font-size: 16px; font-weight: 600; color: var(--ink-900); }
.de-pop-sub { font-size: 14px; color: var(--ink-400); margin-top: 3px; line-height: 1.4; }
.de-pop-list { flex: 1 1 0; overflow-y: auto; padding: 6px 4px; }
.de-pop-item { display: flex; align-items: flex-start; gap: 10px; padding: 8px 9px; border-radius: 8px;
  cursor: pointer; }
.de-pop-item:hover { background: var(--brand-softer); }
.de-pop-item.disabled { opacity: .55; cursor: not-allowed; }
.de-pop-item.disabled:hover { background: transparent; }
/* 勾选框 */
.de-check { flex: 0 0 auto; width: 16px; height: 16px; margin-top: 3px; border: 1.5px solid var(--ink-400);
  border-radius: 4px; background: var(--bg-card); position: relative; }
.de-pop-item.selected .de-check { background: var(--brand); border-color: var(--brand); }
.de-pop-item.selected .de-check::after { content: '✓'; position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center; color: #fff; font-size: 12px; }
/* 条目内容：标题（16px 加粗黑色）+ 描述（14px 灰色）换行显示 */
.de-it-body { display: flex; flex-direction: column; min-width: 0; flex: 1 1 auto; }
.de-it-title { font-size: 16px; font-weight: 600; color: var(--ink-900); line-height: 1.35; }
.de-it-desc { font-size: 14px; color: var(--ink-400); line-height: 1.4; margin-top: 2px; }
/* 出勤统计三行条目右侧「配置规则」文字按钮（20260921h）：
   主动点击才弹规则框；点它不改变勾选状态（handler 里 stopPropagation） */
.de-pop-item .de-it-rule { flex: 0 0 auto; align-self: center; margin-left: 8px; padding: 3px 8px;
  border: 1px solid var(--brand); border-radius: 6px; background: var(--bg-card); color: var(--brand);
  font-size: 13px; line-height: 1.3; cursor: pointer; white-space: nowrap; }
.de-pop-item .de-it-rule:hover { background: var(--brand); color: #fff; }
.de-pop-foot { flex: 0 0 auto; display: flex; justify-content: flex-end; gap: 8px; padding: 10px 4px 2px;
  border-top: 1px solid var(--border-default); }
/* 归档页面：弹框顶部「添加自定义列」（20260914r） */
.de-pop-custom { margin-top: 10px; padding: 10px 12px 11px; border-radius: 8px;
  background: var(--brand-softer); border: 1px dashed var(--brand-line); }
.de-pop-custom-title { font-size: 14px; font-weight: 600; color: var(--ink-900); margin-bottom: 7px; }
.de-pop-custom-row { display: flex; gap: 8px; align-items: center; }
.de-pop-custom-row .input { flex: 1 1 auto; min-width: 0; }
.de-pop-custom-row .btn { flex: 0 0 auto; padding: 7px 16px; font-size: 14px; }
.de-pop-custom-hint { margin-top: 7px; font-size: 12.5px; color: var(--ink-400); line-height: 1.5; }
.de-pop-custom-hint.de-pop-custom-warn { color: var(--danger); }
.de-pop-empty { padding: 26px 10px; text-align: center; font-size: 14px; color: var(--ink-400); }

/* ===== 「＋ 添加」抽屉（20261009i 分组 → 20261009j 右侧抽屉）=====
   用户要求：① 从该页面右侧浮出（保留遮罩层）、高度 = 当前屏幕高；② 去掉标题下方的
   提示文字；③ 去掉字段名称搜索（字段已按类型分组，一眼看全，无需再搜）。
   保留：头部/底部固定 + 中间列表滚动、分组网格（20261009i）、拖左边缘调宽 + 宽度记忆 +
   「重置宽度」。
   ⚠️ 定位/圆角等覆盖 .de-pop（居中模态）的规则 —— .de-pop-add 在文件更靠后，同特异性后来居上；
      其它 .de-pop 弹框（.de-att-rule / .de-raw-punch-rule / .de-leave-total-rule）不受影响。
   ⚠️ 高度固定 100vh（max-height 同步抬到 100vh，否则会被 .de-pop 的 calc(100vh - 80px) 卡住）。 */
.de-pop-add { left: auto; right: 0; top: 0; transform: none;
  width: 780px; height: 100vh; max-height: 100vh;
  min-width: 420px; max-width: calc(100vw - 56px);
  border-radius: 0; border-top: 0; border-right: 0; border-bottom: 0;
  box-shadow: -14px 0 40px rgba(15, 23, 42, .20);
  overflow: hidden;
  animation: dePopDrawerIn .22s cubic-bezier(.22, .61, .36, 1); }
/* 从右侧滑入（隐藏用 display:none，重新显示时动画重放） */
@keyframes dePopDrawerIn {
  from { transform: translateX(30px); opacity: .35; }
  to { transform: none; opacity: 1; }
}
/* 左边缘拖动调宽（自绘手柄：原生 resize 手柄在右下角、且右侧贴边时方向反直觉） */
.de-pop-grip { position: absolute; left: 0; top: 0; bottom: 0; width: 6px; z-index: 3;
  cursor: col-resize; background: transparent; border-left: 1px solid var(--border-hairline); }
.de-pop-grip:hover { background: var(--brand-softer); border-left-color: var(--brand); }
body.de-pop-resizing { cursor: col-resize; user-select: none; }
/* 头部：标题与「重置宽度」同一行（不再有副标题提示文字） */
.de-pop-head-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.de-pop-size-reset { flex: 0 0 auto; border: 1px solid var(--border-default); background: var(--bg-card);
  color: var(--ink-600); border-radius: 6px; padding: 5px 10px; font-size: 12.5px; cursor: pointer;
  white-space: nowrap; }
.de-pop-size-reset:hover { border-color: var(--brand); color: var(--brand); }
/* 分组：组标题（左色条 + 名称 + 数量）+ 组内自适应网格 */
.de-pop-group { padding: 3px 0 7px; }
.de-pop-group + .de-pop-group { border-top: 1px dashed var(--border-hairline); }
.de-pop-group-title { display: flex; align-items: center; gap: 7px; padding: 6px 4px 7px;
  font-size: 13px; font-weight: 600; color: var(--ink-600);
  /* 吸顶：滚动时始终知道当前在看哪一组（containing block = 自己的 .de-pop-group，
     故只在本组范围内吸附）；必须有不透明底色，否则会与滚过的条目文字重叠 */
  position: sticky; top: 0; z-index: 2; background: var(--bg-card); }
.de-pop-group-title::before { content: ''; width: 3px; height: 13px; border-radius: 2px;
  background: var(--brand); }
.de-pop-group-n { font-size: 11.5px; font-weight: 500; color: var(--ink-400);
  background: var(--brand-softer); border-radius: 9px; padding: 0 7px; line-height: 17px; }
.de-pop-group-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(232px, 1fr));
  gap: 6px; }
/* 网格里给条目加透明描边：hover 时才显色，避免出现/消失时抖动 */
.de-pop-group-grid .de-pop-item { border: 1px solid transparent; }
.de-pop-group-grid .de-pop-item:hover { border-color: var(--brand-line); }
.de-pop-group-grid .de-pop-item.disabled:hover { border-color: transparent; }

/* 出勤统计规则对话框（20260921d）：判定顺序 / 简称 / 请假显示 / 正常出勤文字
   注意：.de-pop-list 是 flex:1 1 0，父容器必须有确定高度，否则会被压成 0 → 这里给
   一个固定高度（内容超出时列表内滚动），不用 height:auto。 */
.de-att-rule { width: 680px; height: 660px; max-height: calc(100vh - 60px); }
.de-att-rule .de-pop-list { padding: 12px 6px 4px; }
/* 夜班打卡错位显示方式（20261008f）：只有两个单选项，弹框按内容收窄，不吃 600×580。
   ⚠️ .de-pop-list 是 flex:1 1 0，父容器改 height:auto 会把列表压成 0 → 这里改成 0 0 auto。 */
.de-raw-punch-rule { width: 460px; height: auto; }
.de-raw-punch-rule .de-pop-list { flex: 0 0 auto; padding: 12px 6px 4px; }
.de-raw-punch-rule .att-opt-list { gap: 2px; }
.de-raw-punch-rule .att-opt { padding: 5px 0; }
.de-raw-punch-rule .att-hint { margin-top: 1px; margin-left: 23px; padding-bottom: 6px; }
/* 原始打卡记录编辑对话框（20261009a，交互层）：标题 → 一个输入框 → 输入框下方提示 → 底部按钮。
   ⚠️ 同 .de-raw-punch-rule：.de-pop-list 是 flex:1 1 0，父容器 height:auto 会把列表压成 0
   → 这里改成 flex:0 0 auto 并按内容收窄宽度。 */
.de-raw-punch-edit { width: 480px; height: auto; }
.de-raw-punch-edit .de-pop-list { flex: 0 0 auto; padding: 14px 4px 6px; }
.de-raw-punch-edit .de-raw-punch-input {
  display: block; width: 100%; box-sizing: border-box;
  font-family: inherit; font-size: 14px; line-height: 1.5;
  padding: 9px 12px; color: var(--ink-800); background: var(--bg-paper);
  border: 1px solid var(--ink-200); border-radius: var(--radius-md);
  outline: none; transition: all .18s;
}
.de-raw-punch-edit .de-raw-punch-input:hover { border-color: var(--ink-300); }
.de-raw-punch-edit .de-raw-punch-input:focus {
  border-color: var(--accent-500); box-shadow: 0 0 0 4px rgba(var(--accent-glow), 0.10);
}
.de-raw-punch-edit .de-raw-punch-hint {
  margin-top: 8px; font-size: 12.5px; color: var(--ink-400); line-height: 1.55;
}
/* 「恢复为原始记录」靠左（其余按钮仍右对齐） */
.de-raw-punch-edit .de-pop-foot .de-rpe-restore { margin-right: auto; }
/* 请假合计规则对话框（20261009h）：合计单位 + 请假类型多选，内容不多 → 按内容收窄。
   ⚠️ 同 .de-raw-punch-rule：.de-pop-list 默认 flex:1 1 0，父容器 height:auto 会把列表
   压成 0 → 这里改成 flex:0 0 auto，并给一个可滚动的最大高度（请假类型多时能滚）。 */
.de-leave-total-rule { width: 520px; height: auto; max-height: calc(100vh - 80px); }
.de-leave-total-rule .de-pop-list { flex: 0 0 auto; padding: 12px 6px 4px; max-height: 58vh; overflow-y: auto; }
/* 应出勤统计规则弹框（20261015u）：内容固定且短，**不许出现横/竖滚动条** ——
   .de-pop-list 默认 overflow-y:auto（单轴设 auto 会把另一轴也算成 auto）时，
   第②条说明右侧的 cfg-tip ⓘ 绝对气泡（同 MEMORY「cfg-tip 绝对气泡恒超」）
   会同时撑出横向与竖向滚动条。此处只放行该弹框（用 id 精确命中，不影响
   请假合计等其它复用 .de-leave-total-rule 的弹框）。 */
#de-expected-days-rule .de-pop-list { flex: 0 0 auto; max-height: none; overflow: visible; }
.att-sec { padding: 0 6px 14px; margin-bottom: 14px; border-bottom: 1px dashed var(--border-default); }
.att-sec:last-of-type { border-bottom: none; margin-bottom: 0; padding-bottom: 0; }
.att-sec-title { font-size: 15px; font-weight: 600; color: var(--ink-900); margin-bottom: 9px; }
.att-sec-tip { font-size: 12.5px; font-weight: 400; color: var(--ink-400); margin-left: 6px; }
.att-hint { margin-top: 8px; font-size: 12.5px; color: var(--ink-400); line-height: 1.55; }
/* 应出勤「不减除节假日」下的 1、2、3 三句并列提示（20261015t/u）：
   纯提示、**无勾选框、无缩进从属**（三句平级并列），由「不减除」这一档必然产生 ——
   做成开关会破坏应出勤与出勤的配平 */
.att-note-list {
  margin: 8px 0 0 23px; display: flex; flex-direction: column; gap: 6px;
}
.att-note-item {
  display: flex; align-items: flex-start; font-size: 12.5px; color: var(--ink-400);
  line-height: 1.55;
}
.att-note-item .att-note-n { flex: 0 0 auto; }
.att-note-item > span:last-of-type { min-width: 0; }
.att-note-item .cfg-tip { width: 14px; height: 14px; margin-left: 2px; flex: 0 0 auto; }
/* 判定顺序 */
.att-order { display: flex; flex-direction: column; gap: 6px; }
.att-order-item { display: flex; align-items: center; gap: 10px; padding: 7px 10px;
  border: 1px solid var(--border-default); border-radius: 8px; background: var(--bg-paper-2, #fafafa); }
.att-idx { flex: 0 0 20px; height: 20px; line-height: 20px; text-align: center; font-size: 12px;
  font-weight: 600; color: var(--brand); background: var(--brand-softer); border-radius: 50%; }
.att-en-wrap { flex: 1 1 auto; display: flex; align-items: center; gap: 8px; cursor: pointer;
  min-width: 0; }
.att-en { flex: 0 0 auto; width: 15px; height: 15px; accent-color: var(--brand); cursor: pointer; }
.att-en-name { font-size: 14px; font-weight: 600; color: var(--ink-900); }
.att-move { flex: 0 0 auto; display: flex; gap: 4px; }
.att-mv { width: 26px; height: 24px; font-size: 11px; line-height: 1; color: var(--ink-500, #555);
  background: var(--bg-card); border: 1px solid var(--border-default); border-radius: 5px; cursor: pointer; }
.att-mv:hover { border-color: var(--brand); color: var(--brand); }
/* 简称 / 正常出勤文字 */
.att-short-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 9px 14px; }
.att-short-row { display: flex; align-items: center; gap: 9px; min-width: 0; }
.att-short-label { flex: 0 0 74px; font-size: 13.5px; color: var(--ink-500, #555); text-align: right; }
.att-short-input { flex: 1 1 auto; min-width: 0; padding: 6px 9px; font-size: 13.5px; }
/* 勾选项列表 */
.att-opt-list { display: flex; flex-direction: column; gap: 8px; }
.att-opt { display: flex; align-items: center; gap: 8px; font-size: 14px; color: var(--ink-900); cursor: pointer; }
.att-opt input { width: 15px; height: 15px; accent-color: var(--brand); cursor: pointer; }

/* ============================================================
   订阅（20260916m）
   左下角「当前用户版本」+ 订阅弹框（功能权益 / 按月 15 元 · 按年 156 元 / 积分输入 / 微信·支付宝扫码）
   ============================================================ */

/* ---------- 左下角订阅入口（20260923a：试用期 + 「我要订阅」按钮） ---------- */
/* 试用期文字在上、「我要订阅」按钮在下；仅试用 / 未订阅时出现，已订阅 / 管理员整块隐藏 */
.sub-user-row { display: flex; flex-direction: column; gap: 7px; padding: 2px 10px 10px; }
/* 试用期：浅绿底绿字（20260923b 由蓝系改回浅绿，与「已订阅」徽章同色系）
   20260923b：字号 12.5→14px、加粗 600、内边距 3/8→7/10 把高度抬起来，与下方「我要订阅」按钮更协调 */
.sb-trial {
  font-size: 14px; font-weight: 600; line-height: 1.5; text-align: center; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
  padding: 7px 10px; border-radius: 8px;
  background: var(--success-soft); color: var(--success); border: 1px solid rgba(var(--success-glow), 0.22);
}
/* 我要订阅：蓝底白字（用户指定），占满侧栏宽度。
   hover 必须显式写 color：#fff —— 否则会继承全局 .btn:hover 的 --accent-700 蓝字，
   深蓝底 + 蓝字会看不清；同时补上主按钮的上浮 + 蓝光阴影，与 .btn-primary 手感一致。 */
.btn.btn-sub-blue {
  width: 100%; font-weight: 600;
  background: var(--accent-500); border-color: var(--accent-500); color: #fff;
}
.btn.btn-sub-blue:not(:disabled):hover {
  background: var(--accent-600); border-color: var(--accent-600); color: #fff;
  transform: translateY(-1px); box-shadow: 0 8px 22px rgba(var(--accent-glow), 0.42);
}
.btn.btn-sub-blue:not(:disabled):active { transform: translateY(0); box-shadow: none; }
.sub-ver { flex: none; font-size: 14px; font-weight: 600; line-height: 1.45; padding: 1px 9px; border-radius: 999px;
  background: var(--bg-paper-2); color: var(--ink-500); border: 1px solid var(--border-subtle); }
.sub-ver.trial, .sub-ver.admin { background: var(--accent-50); color: var(--accent-700); border-color: var(--accent-100); }
.sub-ver.paid { background: var(--success-soft); color: var(--success); border-color: rgba(var(--success-glow), 0.22); }
.sub-ver.none { background: var(--danger-soft); color: var(--danger); border-color: rgba(var(--danger-glow), 0.20); }
/* 20261015p：侧栏左下角按档位配色（与个人信息页 15o 同套色系）——免费=蓝 / 标准=金 / 专业含试用=靛 */
.sub-ver.free { background: #e3effb; color: #005bb8; border-color: #c7dff7; }
.sub-ver.basic { background: #f6ecc9; color: #8a5f00; border-color: #e8d9a0; }
.sub-ver.pro { background: #e7e6fb; color: #4543b8; border-color: #d0cfae; }
.sidebar-user .avatar.tier-basic { background: linear-gradient(135deg, #d9a521, #8a5a00); }
.sidebar-user .avatar.tier-pro { background: linear-gradient(135deg, #7a78f2, #34339c); }
.btn.btn-xs { padding: 3px 10px; font-size: 14px; line-height: 1.5; border-radius: 6px; }
#expired-banner .btn { margin-left: 8px; vertical-align: middle; }

/* ---------- 订阅弹框 ---------- */
/* 宽度：宽屏 560px 单列（20260920e 定稿；早期 820px 双列布局已废弃）。 */
.modal-box.sub-modal-box { max-width: 560px; max-height: 92vh; display: flex; flex-direction: column; padding: 20px 24px 20px; }
.sub-modal-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; overflow-x: hidden; padding-right: 4px; }
.sub-loading, .sub-empty { padding: 30px 6px; text-align: center; font-size: 14px; color: var(--ink-400); }
.sub-step { display: flex; flex-direction: column; gap: 16px; }

/* 当前版本条 */
.sub-cur { display: flex; align-items: center; gap: 10px; padding: 10px 14px; border-radius: 10px;
  background: var(--brand-softer); border: 1px solid var(--accent-100); font-size: 14px; }
.sub-cur-label { flex: none; color: var(--ink-500); }
.sub-cur-val { font-weight: 600; color: var(--accent-700); }

/* 区块 */
.sub-sec { display: flex; flex-direction: column; gap: 9px; }
.sub-sec-title { font-size: 14px; font-weight: 600; color: var(--ink-800); }

/* 功能权益 */
.sub-benefits { list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px 12px; }
.sub-benefit { display: flex; gap: 8px; align-items: flex-start; padding: 9px 12px;
  border-radius: 8px; background: var(--bg-paper-2); border: 1px solid var(--border-subtle); }
.sub-benefit-ck { flex: none; width: 18px; height: 18px; border-radius: 50%; background: var(--success-soft);
  color: var(--success); font-size: 14px; font-weight: 700; line-height: 18px; text-align: center; }
.sub-benefit-tx { min-width: 0; }
.sub-benefit-tx b { display: block; font-size: 14px; font-weight: 600; color: var(--ink-800); }
.sub-benefit-tx i { display: block; font-style: normal; font-size: 14px; color: var(--ink-400); line-height: 1.5; margin-top: 2px; }

/* 方案（价格醒目） */
.sub-plans { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; padding-top: 4px; }
.sub-plan { position: relative; padding: 16px 18px; border-radius: 12px; border: 2px solid var(--border-default);
  background: var(--bg-paper); cursor: pointer; transition: border-color .15s, box-shadow .15s, transform .15s; }
.sub-plan:hover { border-color: var(--accent-300); transform: translateY(-1px); }
.sub-plan.selected { border-color: var(--accent-500); box-shadow: 0 8px 24px rgba(var(--accent-glow), 0.18); }
.sub-plan-tag { position: absolute; top: -11px; right: 14px; padding: 1px 10px; border-radius: 999px;
  background: var(--accent-500); color: #fff; font-size: 14px; font-weight: 600; }
.sub-plan-name { font-size: 15px; font-weight: 600; color: var(--ink-700); }
.sub-plan-price { display: flex; align-items: baseline; gap: 2px; margin: 6px 0 4px; color: var(--accent-600); }
.sub-plan-cur { font-size: 22px; font-weight: 700; }
.sub-plan-num { font-family: var(--font-mono); font-size: 44px; font-weight: 700; line-height: 1.05; letter-spacing: -1px; }
.sub-plan-unit { font-size: 16px; font-weight: 600; color: var(--ink-500); margin-left: 3px; }
.sub-plan-note { font-size: 14px; color: var(--ink-400); }
.sub-plan-save { display: inline-block; margin-top: 8px; padding: 2px 8px; border-radius: 6px;
  background: var(--yellow-50); border: 1px solid var(--yellow-200); color: var(--yellow-500); font-size: 14px; }

/* 积分输入（样式主体在 3746 起：20260924j 输入框通宽改造，旧窄版规则已删） */
.sub-points-unit { font-size: 14px; color: var(--ink-400); }

/* 支付方式 */
.sub-methods { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
.sub-method { display: flex; align-items: center; gap: 10px; padding: 10px 14px; border-radius: 10px;
  border: 2px solid var(--border-default); background: var(--bg-paper); cursor: pointer; text-align: left; }
.sub-method:hover { border-color: var(--accent-300); }
.sub-method.active { border-color: var(--accent-500); background: var(--brand-softer); }
/* 渠道未开通（20260917b）：置灰不可选，避免用户选到不可用渠道后点确认支付才报错 */
.sub-method.sub-method-off { opacity: .55; cursor: not-allowed; }
.sub-method.sub-method-off:hover { border-color: var(--border-default); }
.sub-method.sub-method-off .sub-method-tx i { color: var(--ink-300); }
.sub-method-ic { flex: none; width: 28px; height: 28px; border-radius: 8px; display: flex;
  align-items: center; justify-content: center; font-size: 14px; font-weight: 700; color: #fff; }
.sub-method-ic-wechat { background: #22ac38; }
.sub-method-ic-alipay { background: #1677ff; }
.sub-method-tx { display: flex; flex-direction: column; min-width: 0; }
.sub-method-tx b { font-size: 14.5px; font-weight: 600; color: var(--ink-800); }
.sub-method-tx i { font-style: normal; font-size: 14px; color: var(--ink-400); }
.sub-methods-hint { font-size: 14px; color: var(--ink-400); }

/* 应付金额条 */
.sub-pay-bar { display: flex; align-items: center; gap: 16px; padding: 13px 16px;
  border-radius: 12px; background: var(--bg-paper-2); border: 1px solid var(--border-subtle); }
.sub-pay-amt { flex: 1 1 auto; min-width: 0; display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.sub-pay-amt-label { font-size: 14px; color: var(--ink-500); }
.sub-pay-amt-val { font-family: var(--font-mono); font-size: 30px; font-weight: 700; color: var(--accent-600); line-height: 1; }
.sub-pay-amt-sub { flex-basis: 100%; font-size: 14px; color: var(--ink-400); }
.sub-pay-btn { flex: none; padding: 10px 26px; font-size: 15px; }

/* 第 2 步：扫码支付 */
.sub-order-head { display: flex; align-items: center; gap: 16px; padding: 12px 16px;
  border-radius: 10px; background: var(--brand-softer); border: 1px solid var(--accent-100); }
.sub-order-amt { font-family: var(--font-mono); font-size: 28px; font-weight: 700; color: var(--accent-600); line-height: 1; }
.sub-order-meta { font-size: 14px; color: var(--ink-500); line-height: 1.6; }

/* 20260920e：原「二维码 / 链接型支付」那整套样式（.sub-qr-* / .sub-link-*）已随
   支付区改为「去支付」按钮而整体下线。此处只保留 .sub-qr-text 作为一个
   纯文本兜底渲染类（正常情况下不会再被用到）。 */
.sub-qr-text { font-size: 14px; color: var(--ink-600); line-height: 1.7; word-break: break-all; }
.sub-link-btn { display: block; width: 100%; text-align: center; box-sizing: border-box; }
.sub-link-tip { font-size: 13px; color: var(--ink-400); line-height: 1.6; }
.sub-link-url { width: 100%; height: 62px; resize: none; box-sizing: border-box;
  font: 12px/1.5 ui-monospace, Consolas, monospace; color: var(--ink-500);
  background: #f8f9fb; border: 1px solid var(--border-default); border-radius: 8px;
  padding: 6px 8px; word-break: break-all; }

/* 20260919b：原「沙箱测试提示」样式块（20260917d）已随 UI 一起移除 */

/* 第 3 步：订阅成功 */
.sub-step.sub-ok { align-items: center; text-align: center; padding: 14px 0 4px; }
.sub-ok-ic { width: 56px; height: 56px; border-radius: 50%; background: var(--success-soft);
  color: var(--success); font-size: 30px; font-weight: 700; line-height: 56px; }
.sub-ok-title { font-size: 20px; font-weight: 700; color: var(--ink-900); }
.sub-ok-desc { font-size: 15px; color: var(--ink-600); }
.sub-ok-desc b { color: var(--accent-700); }
.sub-ok-list { width: 100%; max-width: 460px; border: 1px solid var(--border-default); border-radius: 10px; overflow: hidden; }
.sub-ok-row { display: flex; justify-content: space-between; gap: 12px; padding: 10px 14px; font-size: 14px; background: var(--bg-paper); }
.sub-ok-row + .sub-ok-row { border-top: 1px solid var(--border-default); }
.sub-ok-row span { color: var(--ink-400); }
.sub-ok-row b { font-weight: 600; color: var(--ink-800); }
.sub-ok-tip { font-size: 14px; color: var(--ink-400); }
.sub-ok .sub-pay-btn { min-width: 180px; }

@media (max-width: 760px) {
  .sub-benefits, .sub-plans { grid-template-columns: 1fr; }
  .sub-plan-num { font-size: 38px; }
  .sub-pay-bar { flex-wrap: wrap; }
  /* 20260920e：单列支付区在窄屏下收紧留白与字号，「去支付」按钮撑满可用宽度 */
  .sub-modal-body { padding: 16px 16px 20px; }
  .sub-methods { flex-direction: column; gap: 9px; padding: 12px 14px; }
  .sub-pay-main { padding: 22px 14px 18px; }
  .sub-pay-hero-amt { font-size: 40px; }
  .sub-pay-go { max-width: none; padding: 15px 18px; font-size: 16.5px; }
  .sub-pay-summary { max-width: none; }
  .sub-pay-broken { max-width: none; }
}

/* ============================================================
   订阅弹框（20260918e）：截图风格 — 蓝色头部 + 卡片式方案 + 支付区
   （20260920e：支付区已从「扫码」改为「去支付」按钮，宽度统一由上方基类给）
   ============================================================ */

/* 弹框整体：去上 padding，让蓝色头部顶到最上方（宽度交给基类，别在这里再写 max-width） */
.modal-box.sub-modal-box {
  max-height: 92vh; display: flex; flex-direction: column;
  padding: 0; overflow: hidden; background: var(--bg-card);
}
/* 暗色主题：订阅弹框背景回落面板色（20261011l：亮色定白底） */
html.dark .modal-box.sub-modal-box { background: var(--bg-panel-2); }
.sub-modal-body {
  flex: 1 1 auto; min-height: 0; overflow-y: auto; overflow-x: hidden;
  padding: 18px 22px 22px;
}

/* 蓝色头部 */
.sub-modal-head {
  position: relative; flex: none;
  background: linear-gradient(135deg, #2b8cfa 0%, #1767d9 100%);
  color: #fff; text-align: center; padding: 28px 20px 22px;
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
}
.sub-modal-icon {
  width: 52px; height: 52px; margin: 0 auto 10px;
  background: rgba(255,255,255,0.22); border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  backdrop-filter: blur(2px);
}
.sub-modal-icon svg { width: 28px; height: 28px; color: #fff; }
.sub-modal-title { font-size: 24px; font-weight: 700; color: #fff; letter-spacing: 0.02em; }
.sub-modal-subtitle { font-size: 14px; color: rgba(255,255,255,0.82); margin-top: 4px; }
.sub-modal-close {
  position: absolute; top: 14px; right: 14px; width: 32px; height: 32px;
  border: none; border-radius: 50%; background: rgba(255,255,255,0.18);
  color: #fff; font-size: 18px; line-height: 1; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: background .15s;
}
.sub-modal-close:hover { background: rgba(255,255,255,0.30); }

/* 步骤容器 */
.sub-step { display: flex; flex-direction: column; gap: 16px; }

/* 套餐卡片 */
.sub-plans-cards { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
.sub-plan-card {
  position: relative; display: flex; align-items: center; gap: 12px;
  padding: 16px 14px; border-radius: 14px;
  border: 1.5px solid var(--border-default); background: var(--bg-card);
  cursor: pointer; transition: all .15s;
}
.sub-plan-card:hover { border-color: var(--accent-300); }
.sub-plan-card.selected {
  border-color: #2b8cfa;
  box-shadow: 0 4px 16px rgba(43,140,250,0.14);
}
.sub-plan-card-readonly { cursor: default; }
.sub-plan-card-readonly:hover { border-color: var(--border-default); }
.sub-plan-radio {
  flex: none; width: 20px; height: 20px; border-radius: 50%;
  border: 2px solid var(--border-default); display: flex; align-items: center; justify-content: center;
}
.sub-plan-card.selected .sub-plan-radio { border-color: #2b8cfa; }
.sub-plan-radio-dot {
  width: 10px; height: 10px; border-radius: 50%; background: #2b8cfa;
}
.sub-plan-card-body { flex: 1 1 auto; min-width: 0; }
.sub-plan-card-name { font-size: 15px; font-weight: 700; color: var(--ink-800); }
.sub-plan-card-hint,
.sub-plan-card-save { font-size: 13px; line-height: 1.45; margin-top: 3px; }
.sub-plan-card-hint { color: var(--ink-400); }
.sub-plan-card-save { color: #10b981; font-weight: 600; }
.sub-plan-card-price {
  flex: none; display: flex; align-items: baseline; gap: 1px;
  color: #2b8cfa; font-weight: 700;
}
.sub-plan-card-cur { font-size: 16px; }
.sub-plan-card-num { font-size: 28px; letter-spacing: -1px; }
.sub-plan-card-unit { font-size: 13px; color: var(--ink-500); font-weight: 600; }

/* 支付卡片容器
   20260920e：原「左右两栏（二维码 + 信息）」的整套样式（.sub-pay-card-body /
   .sub-pay-card-left / .sub-pay-card-right / .sub-pay-card-qr* / .sub-pay-card-method /
   .sub-pay-card-amount* / .sub-method-pill*）已随支付区改为「去支付」单列形态而下线。
   现在只保留最外层的卡片容器；内部布局见下方 20260920e 段落。 */
.sub-pay-card {
  background: var(--bg-card); border-radius: 16px; border: 1px solid var(--border-default);
  overflow: hidden;
}

/* 底部按钮行 + 提示 */
.sub-pay-card-bar {
  display: flex; gap: 12px; padding: 0 2px;
}
.sub-pay-card-bar .btn { flex: 1; padding: 11px 18px; font-size: 15px; }
.sub-pay-footer {
  display: flex; align-items: flex-start; gap: 7px;
  font-size: 13px; color: var(--ink-400); line-height: 1.55; padding: 0 2px;
}
.sub-pay-footer-ic {
  flex: none; width: 18px; height: 18px; border-radius: 50%;
  border: 1px solid currentColor; display: flex; align-items: center; justify-content: center;
  font-size: 11px; line-height: 1; margin-top: 1px;
}

/* ============================================================
   订阅弹框（20260920e）：单页下单 · 「去支付」按钮形态
   —— 取消二维码与扫码文案；选好套餐/渠道后点「去支付」在新窗口打开收银台。
      布局由「左码右信息」的两栏改为**单列聚焦**：金额主角 → 主按钮 → 订单摘要。
   ============================================================ */

/* —— 弹框尺寸与留白 ——
   20260924k：整体收紧一档（头部/正文/卡片/支付区留白 -15~30%），弹框高度明显下降，
   视觉层次不变 —— 数值与配色全保留，只动间距与个别字号。 */
.modal-box.sub-modal-box { max-width: 1050px; }
.sub-modal-body { padding: 12px 20px 14px; }
.sub-step { gap: 10px; }

/* —— 左右两栏（20261011e）：左栏选套餐/周期/积分，右栏支付 —— */
/* 20261012m：左栏比例回落 1.2fr（下方三块已限宽，多余留白无用）；
   同步微调：卡 gap 10→8、卡内距 14→12，保证每卡 ~187px 仍容得下 161px 文字需求 */
.sub-two-col { display: grid; grid-template-columns: 1.2fr 1fr; gap: 18px; align-items: start; }
.sub-col { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.sub-col-right { border-left: 1px solid var(--border-default); padding-left: 18px; }
.sub-sec-title { font-size: 13px; font-weight: 700; color: var(--ink-500);
  letter-spacing: 0.04em; padding-left: 2px; margin-bottom: -6px; }

/* 蓝色头部：留白适度收紧（20260924k：30/24/24 → 20/24/18） */
.sub-modal-head { padding: 16px 24px 14px; }
.sub-modal-icon { width: 42px; height: 42px; margin-bottom: 6px; }
.sub-modal-icon svg { width: 22px; height: 22px; }
.sub-modal-title { font-size: 21px; }
.sub-modal-subtitle { font-size: 14px; margin-top: 3px; }

/* —— 套餐卡 —— */
/* 选中圆点恒存在，切套餐只切 class（不重建 DOM，避免闪烁） */
.sub-plan-card:not(.selected) .sub-plan-radio-dot { display: none; }
.sub-plans-cards { gap: 12px; }
.sub-plan-card { padding: 11px 13px; border-radius: 13px; gap: 11px; }
.sub-plan-card-name { font-size: 15px; }
.sub-plan-card-save { font-size: 13px; }

/* —— 套餐类型选择（20261011d：顶部先选档位卡，下方再选月/年价格）—— */
/* 20261012j：三栏布局；免费版卡仅作对比（置灰不可点）；feat 文字 nowrap 不折行；
   限宽 605px 与下方计费周期/积分抵扣对齐（20261012j/k）；
   20261012m：左栏回落 1.2fr 后栏宽 ~579px，卡 gap 10→8、内距 14→12 保证不折行 */
.sub-tier-cards { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; max-width: 605px; }
.sub-col-left .sub-plans-cards,
.sub-col-left .sub-points,
.sub-col-left .sub-sec-title-row { max-width: 605px; }
.sub-tier-card { border: 1.5px solid var(--border-default); border-radius: 14px;
  padding: 13px 12px; display: flex; flex-direction: column; gap: 9px;
  background: var(--surface, #fff); cursor: pointer; text-align: left;
  transition: border-color .13s, box-shadow .13s; }
.sub-tier-card:hover { border-color: var(--accent-300, #b9c9ff); }
.sub-tier-card.selected { border-color: var(--accent-500, #4a6cf7);
  box-shadow: 0 3px 14px rgba(74,108,247,.14); }
.sub-tier-card.sub-tier-free { cursor: default; background: var(--bg-subtle, #f7f8fa); }
.sub-tier-card.sub-tier-free:hover { border-color: var(--border-default); }
/* 20261014c：未到期的「当前版本」卡——置灰不可选（同档续费只延期、不恢复本月次数） */
.sub-tier-card.sub-tier-locked { cursor: not-allowed; background: var(--bg-subtle, #f7f8fa); }
.sub-tier-card.sub-tier-locked:hover { border-color: var(--border-default); }
.sub-tier-card.sub-tier-locked .sub-tier-name { color: var(--ink-500); }
.sub-tier-cur { font-size: 11px; font-weight: 700; color: var(--ink-600, #4b5563);
  background: var(--bg-subtle, #f7f8fa); border: 1px solid var(--border-default);
  border-radius: 999px; padding: 2px 8px; white-space: nowrap; }
.sub-tier-card-head { display: flex; align-items: center; gap: 8px; }
.sub-tier-name { font-size: 15px; font-weight: 700; color: var(--ink-900); }
.sub-tier-card.sub-tier-pro .sub-tier-name { color: var(--accent-600, #3556d4); }
.sub-tier-card.sub-tier-free .sub-tier-name { color: var(--ink-500); }
.sub-tier-tag { font-size: 11px; font-weight: 700; color: #fff;
  background: var(--accent-500, #4a6cf7); border-radius: 999px; padding: 2px 8px; }
.sub-tier-feats { display: flex; flex-direction: column; gap: 4px; }
.sub-tier-feat { display: flex; align-items: center; gap: 7px;
  font-size: 12.5px; color: var(--ink-600); }
.sub-tier-feat span { white-space: nowrap; }
.sub-tier-feat svg { color: var(--accent-500, #4a6cf7); flex: none; }
.sub-tier-feat-neg { color: var(--ink-400); }
.sub-tier-feat-neg svg { color: var(--ink-400); }

/* 专业版专属选项（标准版置灰，20261011a） */
.tier-locked { opacity: .45; cursor: not-allowed; filter: grayscale(.35); }
select option.pro-locked { color: var(--ink-300); }

/* 专业版升级提示弹框（20261011a 文案 / 20261011k 按用户截图重排：
   无标题无右上角关闭，底部「取消 / 去升级」左右布局居中，等宽圆角按钮） */
.tier-upgrade-box { max-width: 400px; /* padding-top: 8px; */ }
.tier-upgrade-box .modal-body { text-align: center; padding: 6px 24px 4px; }
.tier-upgrade-icon { width: 58px; height: 58px; margin: 2px auto 10px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--accent-50, #eef3ff); color: var(--accent-500, #4a6cf7); }
.tier-upgrade-text { font-size: 14.5px; color: var(--ink-800); line-height: 1.7; }
.tier-upgrade-feature { font-weight: 700; color: var(--accent-600, #3556d4); }
.tier-upgrade-actions { justify-content: center; gap: 16px; margin-top: 28px; padding: 0 6px 6px; }
.tier-upgrade-actions .btn { flex: 0 0 168px; height: 42px; border-radius: 10px; font-size: 15px; }
.tier-upgrade-actions .btn-ghost {
  background: var(--accent-50, #eef3ff); color: var(--accent-600, #3556d4);
  border-color: transparent; }

/* 标准版 300 人上限提示（20261011k）：导入被截取后在「计算考勤」标题右侧常驻 */
.emp-limit-tip { display: inline-block; margin-left: 12px; font-size: 13px; font-weight: 400;
  color: var(--danger); vertical-align: 3px; }
.emp-limit-tip.hidden { display: none; }
/* 结果页标题行：标题 + 300 人提示同行基线对齐（20261011l） */
.proj-title-wrap { display: flex; align-items: baseline; min-width: 0; }
.emp-limit-link { color: var(--accent-500, #4a6cf7); text-decoration: underline;
  cursor: pointer; font-weight: 600; margin-left: 2px; }
.emp-limit-link-red { color: #e5484d; }   /* 20261012r：「升级专业版」红色（用户定版） */

/* 20261012u：结果页超限提示——纯文字无背景，正文蓝色、「升级专业版」红色（用户定版） */
.trunc-tip { color: var(--accent-600, #3556d4); font-size: 13px; font-weight: 600; }
/* 20261014a：「我的项目」动作区左侧的本月导入次数用尽提示（红色常驻文字，点击打开订阅界面）。
   限制 max-width 让长文案在动作区左边换行，不去挤压按钮与标题。 */
.quota-alert { font-size: 13px; font-weight: 600; color: var(--danger);
  background: transparent;          /* 透明背景，只有红字 */
  white-space: nowrap;              /* 20261014b：整句不折行 */
  line-height: 1.45; max-width: 760px;
  align-self: center;               /* 20261014b：.card-actions 默认 stretch 会让文字贴顶，这里单独居中 */
  cursor: pointer; }
.quota-alert:hover { text-decoration: underline; }

/* 20261020p：「我的项目」标题右侧的拖拽导入绿色提示文字（常驻，与 card-sub 同排） */
.drop-hint-green { font-size: 13px; font-weight: 600; color: var(--success);
  margin-left: 8px; white-space: nowrap; line-height: 1.45; align-self: center; }
@media (max-width: 1100px) { .drop-hint-green { display: none; } }   /* 窄屏收起防挤压按钮 */
.btn-locked { opacity: 0.45; cursor: not-allowed; }

/* 假勤页姓名旁工号徽标（20261011a：重名区分） */
.lc-empno { display: inline-block; margin-left: 6px; padding: 0 6px;
  font-size: 11px; line-height: 17px; border-radius: 999px;
  background: var(--ink-100, #eef0f4); color: var(--ink-500); vertical-align: 1px; }
.sub-plan-card-num { font-size: 27px; }

/* —— 支付卡片 —— */
.sub-pay-card-head {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 10px 20px; border-bottom: 1px solid var(--border-default);
}
.sub-pay-card-title { font-size: 16px; font-weight: 700; color: var(--ink-800); }

/* 支付方式选择条：卡片内、支付区上方通栏 */
.sub-methods {
  display: flex; gap: 12px; padding: 8px 20px;
  border-bottom: 1px solid var(--border-default); background: #fbfcfe;
}
.sub-method.sub-method-pill {
  flex: 1; display: flex; align-items: center; justify-content: center; gap: 9px;
  padding: 8px 12px; border-radius: 11px; border: 1.5px solid var(--border-default);
  background: var(--bg-card); font-size: 14.5px; font-weight: 600; color: var(--ink-700);
  cursor: pointer; transition: all .13s;
}
.sub-method.sub-method-pill:hover { border-color: var(--accent-300); }
.sub-method.sub-method-pill.active {
  border-color: #2b8cfa; background: #f0f7ff; color: #2b8cfa;
  box-shadow: 0 2px 10px rgba(43,140,250,0.16);
}
.sub-method.sub-method-pill:disabled,
.sub-method.sub-method-pill.sub-method-pill-off { opacity: .55; cursor: not-allowed; }
.sub-method-pill-ic { flex: none; width: 24px; height: 24px; border-radius: 6px; background: transparent; }
.sub-method-pill-tx { display: flex; flex-direction: row; align-items: center; gap: 6px; min-width: 0; }
.sub-method-pill-tx b { font-size: 14.5px; font-weight: 600; white-space: nowrap; }
.sub-method-pill-tx i { font-style: normal; font-size: 11px; font-weight: 500;
  color: var(--ink-400); background: #eef1f5; border-radius: 4px; padding: 1px 5px; white-space: nowrap; }

/* 支付主体：单列居中，金额 → 主按钮 → 说明 → 摘要 */
.sub-pay-main {
  display: flex; flex-direction: column; align-items: center; gap: 0;
  padding: 14px 18px 12px;
}

/* 金额主角 */
.sub-pay-hero { display: flex; flex-direction: column; align-items: center; gap: 4px; }
.sub-pay-hero-label { font-size: 13.5px; color: var(--ink-500); }
.sub-pay-hero-amt {
  font-family: var(--font-mono); font-size: 38px; font-weight: 700; line-height: 1.05;
  letter-spacing: -1.5px; color: #2b8cfa;
}
.sub-pay-hero-sub { font-size: 13px; color: var(--ink-400); }
.sub-pay-hero-sub:empty { display: none; }

/* 「去支付」主按钮：大、圆、有图标，是全卡片唯一的强引导 */
.sub-pay-go {
  display: flex; align-items: center; justify-content: center; gap: 10px;
  width: 100%; max-width: 340px; margin-top: 13px;
  padding: 12px 24px; border-radius: 13px;
  font-size: 17px; font-weight: 700; letter-spacing: 0.02em;
  box-shadow: 0 6px 18px rgba(43,140,250,0.28);
  transition: transform .12s, box-shadow .12s, filter .12s;
}
.sub-pay-go:hover { transform: translateY(-1px); box-shadow: 0 9px 24px rgba(43,140,250,0.34); }
.sub-pay-go:active { transform: translateY(0); box-shadow: 0 3px 10px rgba(43,140,250,0.26); }
.sub-pay-go.clicked { filter: saturate(0.75); box-shadow: 0 3px 10px rgba(43,140,250,0.20); }
/* 20260923b：按钮内的渠道图标（.sub-pay-go-ic）已按用户要求去掉，对应样式一并删除。 */

/* 20260920h：原「将在新窗口打开收银台…」（.sub-pay-go-tip）与
   「支付完成后系统会自动确认到账…」（.sub-pay-card-note）两处提示文案
   已按用户要求删除，对应样式一并下线。 */

/* 订单摘要：底部三行细表，弱化但不隐藏 */
.sub-pay-summary {
  width: 100%; max-width: 380px; margin-top: 12px;
  border: 1px solid var(--border-default); border-radius: 11px; overflow: hidden;
  background: var(--bg-paper);
}
.sub-pay-summary-row {
  display: flex; align-items: baseline; justify-content: space-between; gap: 14px;
  padding: 6px 14px; font-size: 13.5px;
}
.sub-pay-summary-row + .sub-pay-summary-row { border-top: 1px solid var(--border-default); }
.sub-pay-summary-row > span { flex: none; color: var(--ink-400); }
.sub-pay-summary-row > b { font-weight: 600; color: var(--ink-800); text-align: right; }
.sub-pay-summary-no { font-family: var(--font-mono); font-size: 12.5px; letter-spacing: -0.2px; }

/* 下单进行中的占位 */
.sub-pay-loading {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 14px; min-height: 160px; color: #94a3b8; font-size: 13.5px;
}
.sub-qr-err { color: var(--danger); }
@keyframes sub-spin { to { transform: rotate(360deg); } }
.sub-spin { width: 22px; height: 22px; border-radius: 50%;
  border: 2.5px solid var(--border-default); border-top-color: #2b8cfa; animation: sub-spin .8s linear infinite; }

/* 「刷新订单」：从码框里搬到卡片标题右侧（链接有时效，给自助换单入口） */
.sub-pay-refresh {
  display: inline-flex; align-items: center; gap: 5px; white-space: nowrap;
  padding: 5px 11px; border-radius: 999px; cursor: pointer;
  border: 1px solid var(--border-default); background: var(--bg-card);
  font-size: 12.5px; font-weight: 600; color: var(--ink-500);
  transition: all .13s;
}
.sub-pay-refresh:hover { color: #2b8cfa; border-color: #2b8cfa; background: #f5faff; }
.sub-pay-refresh:disabled, .sub-pay-refresh.busy { opacity: .6; cursor: wait; }
.sub-pay-refresh svg { width: 14px; height: 14px; }
.sub-pay-refresh.busy svg { animation: sub-spin .8s linear infinite; }

/* 渠道不可用：说清楚原因，不把用户送进一个会报错的页面 */
.sub-pay-broken {
  width: 100%; max-width: 380px; margin-top: 22px; padding: 18px 16px;
  border-radius: 12px; background: var(--yellow-50); border: 1px solid var(--yellow-200);
  text-align: center;
}
.sub-pay-broken-title { font-size: 15px; font-weight: 700; color: var(--yellow-500); }
.sub-pay-broken-desc { margin-top: 6px; font-size: 13px; color: var(--yellow-500); line-height: 1.6; }
.sub-pay-broken-hint { margin-top: 10px; font-size: 12.5px; color: #a1750f; line-height: 1.6; }
.sub-pay-broken-hint b { font-family: var(--font-mono); color: var(--yellow-500); }

/* —— 底部按钮 + 居中提示 —— */
.sub-pay-card-bar { padding: 0; margin-top: 2px; }
.sub-pay-card-bar .btn { padding: 12px 20px; font-size: 15px; font-weight: 600; border-radius: 11px; }
.sub-pay-footer {
  display: flex; justify-content: center; align-items: center; gap: 8px;
  font-size: 13.5px; color: var(--ink-400); padding: 2px 0 0;
}
.sub-pay-footer-ic {
  flex: none; width: 17px; height: 17px; border: none; color: var(--ink-400);
}
.sub-pay-footer-ic svg { display: block; width: 100%; height: 100%; }

/* 第 3 步：订阅成功 */
.sub-step.sub-ok { align-items: center; text-align: center; padding: 14px 0 4px; }
.sub-ok-ic { width: 56px; height: 56px; border-radius: 50%; background: var(--success-soft);
  color: var(--success); font-size: 30px; font-weight: 700; line-height: 56px; }
.sub-ok-title { font-size: 20px; font-weight: 700; color: var(--ink-900); }
.sub-ok-desc { font-size: 15px; color: var(--ink-600); }
.sub-ok-desc b { color: var(--accent-700); }
.sub-ok-list { width: 100%; max-width: 460px; border: 1px solid var(--border-default); border-radius: 10px; overflow: hidden; }
.sub-ok-row { display: flex; justify-content: space-between; gap: 12px; padding: 10px 14px; font-size: 14px; background: var(--bg-paper); }
.sub-ok-row + .sub-ok-row { border-top: 1px solid var(--border-default); }
.sub-ok-row span { color: var(--ink-400); }
.sub-ok-row b { font-weight: 600; color: var(--ink-800); }
.sub-ok-tip { font-size: 14px; color: var(--ink-400); }
.sub-ok .sub-pay-btn { min-width: 180px; }

/* 旧兼容样式：保留以防其他位置引用 */
.sub-method-ic { width: 30px; height: 30px; border-radius: 8px; background: transparent; font-size: 0; }
.sub-method-ic svg { display: block; width: 100%; height: 100%; }
.sub-ver-left { white-space: nowrap; }
.sub-reason { display: block; padding: 10px 14px; border-radius: 10px; font-size: 14px; line-height: 1.6;
  background: var(--yellow-50); border: 1px solid var(--yellow-200); color: var(--yellow-500); }
.sub-pay-amt-sub:empty { display: none; }

@media (max-width: 760px) {
  .sub-two-col { grid-template-columns: 1fr; }
  .sub-col-right { border-left: none; padding-left: 0; }
}

@media (max-width: 560px) {
  .sub-plans-cards { grid-template-columns: 1fr; }
  .sub-tier-cards { grid-template-columns: 1fr; }
  /* 20260920e：支付区已是单列，旧的两栏折叠规则不再需要；
     这里只把套餐卡纵向堆叠，并在极窄屏再缩一档金额字号。 */
  .sub-pay-hero-amt { font-size: 36px; }
  .sub-pay-card-head { padding: 14px 16px; }
}

/* ============================================================
   统计分析 · 周期筛选（20260922k：年份下拉 + 自定义周期并到一行）
   ============================================================ */
.stats-filter { display: flex; flex-direction: column; gap: 10px; margin-bottom: 16px; }
.sf-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
/* 20260928y：标签去 min-width（随文字自适应，「按年份」不再被撑到 70px） */
.sf-label { font-size: 14px; color: var(--ink-500); flex-shrink: 0; }
.sf-input {
  height: 32px; padding: 0 8px; font-family: inherit; font-size: 14px;
  color: var(--ink-800);
  /* 20260928w：background 简写会清掉全局 select 箭头（深色下 html.dark select
     的灰白箭头图失去 repeat/position 平铺成整排三角，同 28k #inv-status / 28s
     .adm-select 一类坑），改用 background-color 保留箭头 */
  background-color: var(--bg-paper);
  border: 1px solid var(--ink-200); border-radius: 6px;
}
.sf-input:focus { outline: none; border-color: var(--accent-500); }
/* 发票状态筛选（20260928k）：恢复右侧下拉箭头（.sf-input 简写 background 清掉了全局 select 箭头） */
#inv-status {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 10 10'><path d='M1 3h8L5 8z' fill='black'/></svg>");
  background-repeat: no-repeat;
  background-position: right 9px center;
  padding-right: 26px; cursor: pointer; min-width: 132px;
}
/* 批量开票按钮（20260928k）：白底；未勾选=灰色禁用态（同员工管理页批量按钮口径） */
#inv-batch-btn:disabled {
  background: var(--ink-100); border-color: var(--ink-200); color: var(--ink-400);
  cursor: not-allowed;
}
/* 管理后台发票详情弹框（20260928k）：内容超高纵向滚动 */
/* 详情弹框（20260928l）：弹框整体限高，仅内容区（modal-body）竖向滚动，标题行固定 */
#inv-det-modal .modal-box {
  max-width: 640px; max-height: 86vh;
  display: flex; flex-direction: column; overflow: hidden;
}
#inv-det-modal .modal-head { flex-shrink: 0; }
#inv-det-modal .modal-body {
  flex: 1 1 auto; min-height: 0;
  overflow-y: auto; overscroll-behavior: contain;
  padding-right: 6px;              /* 给滚动条留位，避免卡片贴条 */
}
#inv-det-modal .modal-body::-webkit-scrollbar { width: 8px; }
/* 上传发票弹窗附件提示（20260928k 用户口径）：去掉蓝色底色，纯灰色文字 */
#inv-up-modal .adm-field-tip {
  background: transparent; border-color: transparent; padding-left: 0; padding-right: 0;
}
/* 20260928x：按年份下拉不设宽度上限（max-width:none 显式放开），宽度随内容自适应；
   补 padding-right:26px 让出箭头位（此前被 .sf-input 的 padding 简写覆盖成 8px，箭头压文字） */
.sf-select { min-width: 116px; max-width: none; width: auto; cursor: pointer; padding-right: 26px; }
.sf-divider { width: 1px; height: 20px; background: var(--border-default); margin: 0 6px; }
.sf-sep { font-size: 14px; color: var(--ink-400); }
.sf-tip { font-size: 13px; color: var(--ink-400); margin-left: 4px; }

/* 统计分析的图表区（20260922l；20260925u 改整页滚动）：
   标题/筛选区/KPI 卡/图表随 #page-stats 整体竖向滚动，
   .stats-charts 只做纵向排布容器（flex:none，不再内部滚动） */
.stats-filter { flex: none; }
#stats-cards { flex: none; margin-top: 16px; }
.stats-charts {
  flex: 1 1 auto; min-height: 320px; overflow-y: auto; overflow-x: hidden;
  display: flex; flex-direction: column; gap: 12px; margin-top: 16px; padding-right: 4px;
}
.stats-charts:empty { display: none; }
/* 20260925u：改整页滚动（用户要求竖向滚动含顶部统计部分一起滚）——
   原设计筛选区/KPI 固定顶部、仅 .stats-charts 内部滚；现 #page-stats 整体
   overflow-y:auto，标题/筛选/KPI/图表一起滚，.stats-charts 不再内部滚动 */
#page-stats { overflow-y: auto; }
#page-stats .stats-charts { flex: none; overflow: visible; min-height: 0; }
.stats-charts .astat-main { flex: none; min-height: 0; }
/* 部门对比等表格竖向滚动时表头固定（滚动容器是 .astat-card-body） */
.stats-charts .astat-table thead th { position: sticky; top: 0; z-index: 1; }
/* 出勤天数 TOP10 行距（20260922n 由 6px 加大到 14px；20260924h 收紧为 12px；
   仅统计分析页生效，归档页维持原 6px） */
.stats-charts .astat-rank-list { gap: 12px; }

/* ============================================================
   注册页（20260922o）
   与登录页同一套 .login-wrap / .login-box 骨架；注册页额外需要：
   方式切换（mac 分段控件）、验证码行（输入框 + 发送按钮）、密码安全等级条
   ============================================================ */
.reg-box { max-width: 420px; }
/* 注册页的提示条是「页内元素」而不是全局浮层：覆盖 #msg.banner 的 fixed 定位，
   否则验证码/错误提示会飘到屏幕顶部、与表单脱节 */
.reg-box #msg.banner {
  position: static; transform: none; width: auto; max-width: none;
  animation: none; box-shadow: none; backdrop-filter: none; -webkit-backdrop-filter: none;
  line-height: 1.55; word-break: break-all;
}
.reg-box #msg.banner::before { background: currentColor; }

.reg-tabs {
  display: flex; gap: 4px; padding: 3px; margin-bottom: 18px;
  background: rgba(255, 255, 255, 0.35);   /* 20260928ag 磨砂适配：半透明融入玻璃卡片 */
  border: 1px solid rgba(255, 255, 255, 0.45);
  border-radius: 10px;
}
.reg-tab {
  flex: 1 1 0; padding: 7px 0; border: none; border-radius: 7px;
  background: transparent; cursor: pointer;
  font-family: inherit; font-size: 14px; font-weight: 500; color: var(--ink-500);
}
.reg-tab:hover { color: var(--ink-700); }
.reg-tab.active {
  background: rgba(255, 255, 255, 0.78); color: var(--ink-800); font-weight: 600;
  box-shadow: 0 1px 2px rgba(15,15,15,.10), 0 0 0 .5px rgba(15,15,15,.06);
}
.reg-tab.is-disabled { color: var(--ink-300); cursor: not-allowed; }
html.dark .reg-tabs {
  background: rgba(255, 255, 255, 0.07);
  border-color: rgba(255, 255, 255, 0.14);
}
html.dark .reg-tab.active {
  background: rgba(255, 255, 255, 0.15);
  color: var(--ink-800);
  box-shadow: 0 1px 2px rgba(0,0,0,.35);
}

.reg-box .field { margin-bottom: 14px; }
.code-row { display: flex; gap: 8px; align-items: stretch; }
.code-row .code-input { flex: 1 1 auto; min-width: 0; letter-spacing: 2px; }
/* 注意：.login-box .btn 是 width:100%（登录按钮要满宽），验证码按钮在同一容器里
   会被撑满 → 把输入框挤成一小条。这里必须显式收回宽度。 */
.reg-box .code-row .btn-code,
#forgot-modal .btn-code {
  flex: 0 0 auto; width: auto; margin-top: 0; white-space: nowrap;
  padding: 10px 14px; font-size: 14px;
  /* 20260928ag 磨砂适配：获取验证码按钮半透明融入玻璃卡片（注册页 + 找回弹框共用 btn-code） */
  background: rgba(255, 255, 255, 0.4);
  border-color: rgba(255, 255, 255, 0.5);
}
html.dark .reg-box .code-row .btn-code,
html.dark #forgot-modal .btn-code {
  background: rgba(255, 255, 255, 0.08);
  border-color: rgba(255, 255, 255, 0.16);
  color: var(--ink-700);
}

/* 找回密码弹框液态玻璃（20260928ag，仅 #forgot-modal） */
#forgot-modal .modal-box {
  background: rgba(255, 255, 255, 0.72);
  backdrop-filter: blur(20px) saturate(1.5);
  -webkit-backdrop-filter: blur(20px) saturate(1.5);
  border: 1px solid rgba(255, 255, 255, 0.45);
}
#forgot-modal .pwd-modal-box input {
  background: rgba(255, 255, 255, 0.45);
  border: 1px solid rgba(255, 255, 255, 0.55);
  border-radius: 8px;
}
#forgot-modal .pwd-modal-box input:focus {
  background: rgba(255, 255, 255, 0.65);
  border-color: var(--accent-500);
  box-shadow: 0 0 0 3px rgba(10, 132, 255, 0.15);
}
html.dark #forgot-modal .modal-box {
  background: rgba(28, 28, 30, 0.72);
  border-color: rgba(255, 255, 255, 0.14);
}
html.dark #forgot-modal .pwd-modal-box input {
  background: rgba(255, 255, 255, 0.07);
  border-color: rgba(255, 255, 255, 0.16);
  color: var(--ink-800);
}
html.dark #forgot-modal .pwd-modal-box input:focus {
  background: rgba(255, 255, 255, 0.11);
  border-color: var(--accent-500);
  box-shadow: 0 0 0 3px rgba(94, 168, 255, 0.2);
}

/* 20261035g（用户定版）：找回密码弹框底部操作区不要独立白底。
   弹框本身是半透明液态玻璃（rgba(255,255,255,.72) + blur），而通用规则
   `.modal-body .modal-actions` 给操作区铺了不透明白底 ⇒ 盒子下方出现一条
   与玻璃不搭的白色横带。此弹框内容短、无需吸附遮罩，直接还原透明。 */
#forgot-modal .modal-body .modal-actions { background: none; }
html.dark #forgot-modal .modal-body .modal-actions { background: none; }

.pw-strength { display: flex; align-items: center; gap: 10px; margin-top: 2px; }
.pw-bar { display: flex; gap: 4px; flex: 0 0 auto; }
.pw-bar i { display: block; width: 34px; height: 4px; border-radius: 2px; background: var(--ink-150); }
.pw-bar.low i:nth-child(1) { background: var(--danger); }
.pw-bar.mid i:nth-child(1), .pw-bar.mid i:nth-child(2) { background: var(--yellow-400); }
.pw-bar.high i { background: var(--success); }
.pw-text { font-size: 12.5px; color: var(--ink-400); }
.pw-text.low { color: var(--danger); }
.pw-text.mid { color: #a06a00; }
.pw-text.high { color: var(--success); }
.pw-mismatch { color: var(--danger); }

.reg-foot { margin-top: 16px; text-align: center; font-size: 13.5px; color: var(--ink-400); }
.reg-foot a { color: var(--accent-600); text-decoration: none; font-weight: 500; }
.reg-foot a:hover { text-decoration: underline; }

/* ============================================================
   登录页「忘记密码」找回流程 + 个人信息「昵称 / 更换绑定」（20260922p）
   ============================================================ */
/* 登录标题下方没有副标题（原「请使用管理员分配的账号登录」已去掉），单独补底部间距 */
.login-box h2.title-only { margin-bottom: 22px; }

/* 「忘记密码？」：密码框下方右对齐，不抢登录按钮视线 */
.login-aux { text-align: right; margin: -4px 0 14px; font-size: 13.5px; }
.login-aux a { color: var(--accent-600); text-decoration: none; font-weight: 500; }
.login-aux a:hover { text-decoration: underline; }

/* 找回密码弹框 */
.modal-box.pwd-modal-box { max-width: 460px; }
.pwd-hint { font-size: 14px; color: var(--ink-500); line-height: 1.7; margin-bottom: 14px; }
.pwd-hint strong { color: var(--ink-800); font-weight: 600; }

/* 多通道选择（邮箱 / 手机号都可用时才出现） */
.pwd-channels { margin-bottom: 2px; }
.pwd-ch-label { font-size: 13.5px; color: var(--ink-400); margin-bottom: 8px; }
.pwd-ch {
  display: flex; align-items: baseline; gap: 8px; width: 100%; box-sizing: border-box;
  padding: 11px 14px; margin-bottom: 8px; text-align: left;
  border: 1.5px solid var(--border-default); border-radius: 10px;
  background: var(--bg-paper); cursor: pointer;
  font-family: inherit; font-size: 15px; color: var(--ink-800);
}
.pwd-ch:hover { border-color: var(--accent-300); background: var(--brand-softer); }
.pwd-ch i { font-style: normal; font-size: 13.5px; color: var(--ink-400); }

/* 无法自助找回 → 管理员微信二维码 */
.pwd-qr { display: flex; flex-direction: column; align-items: center; gap: 8px; padding: 6px 0 2px; }
.pwd-qr img { width: 230px; height: auto; border-radius: 10px; display: block; }
.pwd-qr-tip { font-size: 14.5px; font-weight: 600; color: var(--ink-800); }
.pwd-qr-note { margin-top: 8px; font-size: 13.5px; color: var(--ink-400); line-height: 1.65; }

/* 重置成功 */
.pwd-ok { display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 12px 0 4px; text-align: center; }
.pwd-ok-ic {
  width: 54px; height: 54px; border-radius: 50%;
  background: var(--success-soft); color: var(--success);
  display: flex; align-items: center; justify-content: center;
  font-size: 28px; font-weight: 700;
}
.pwd-ok-title { font-size: 19px; font-weight: 700; color: var(--ink-900); }
.pwd-ok-desc { font-size: 14.5px; color: var(--ink-500); }
.pwd-ok-desc strong { color: var(--ink-800); font-weight: 600; }

/* 验证码行里的「获取验证码」按钮：收回宽度（.login-box .btn 满宽会把它挤爆） */
.code-row .btn-code { flex: 0 0 auto; width: auto; margin-top: 0; white-space: nowrap; }

/* 个人信息：账户信息行内的操作按钮（修改 / 绑定 / 更改） */
.info-row .pf-act { flex: none; margin-left: 12px; }
.info-row .v .muted { font-weight: 400; }

/* 个人信息：修改昵称 / 更换绑定 弹框 */
.modal-box.pf-modal-box { max-width: 450px; }
.pf-modal-tip { font-size: 14px; color: var(--ink-500); line-height: 1.65; margin-bottom: 14px; }
.pf-modal-tip b { color: var(--ink-800); font-weight: 600; }
.pf-modal-tip strong { color: var(--accent-700); font-weight: 600; }
.pf-modal-warn { color: var(--yellow-500); }

/* ============================================================
   登录页「忘记密码」并入注册行 + 找回弹框「忘记账号？」（20260922q）
   ============================================================ */
/* 忘记密码挪到「还没有账号？立即注册」同一行的最右侧（原独立 .login-aux 行已去掉） */
.reg-foot.login-foot {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; text-align: left;
}
.reg-foot.login-foot .reg-foot-forgot { margin-left: auto; white-space: nowrap; }

/* 找回密码第一步提示末尾的「忘记账号？」 */
.pwd-acc-link { margin-left: 6px; color: var(--accent-600); font-weight: 500; white-space: nowrap; }
.pwd-acc-link:hover { text-decoration: underline; }

/* ============================================================
   个人信息页：分块灰底 + 800px 居中（20260922q）
   ============================================================ */
/* 内容整体居中并限宽：原来铺满整个内容区，左右距离过大看着累 */
#page-profile {
  width: 100%; max-width: 800px;
  margin-left: auto; margin-right: auto;
  align-self: center;
}
/* 限宽后可能出现纵向溢出（.content 是 overflow:hidden）→ 本页自己滚 */
#page-profile .pf-scroll { flex: 1; min-height: 0; overflow-y: auto; padding-right: 4px; }

/* 每一块一个灰底（原 .card 是白底无边界，与页面融在一起） */
.pf-block {
  background: var(--bg-paper-2);
  border-radius: var(--radius-lg);
  padding: 16px 20px 6px;
  margin-bottom: 16px;
}
.pf-block-head { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.pf-block-title { font-size: 16px; font-weight: 600; color: var(--ink-800); }
.pf-block .info-row { border-bottom-color: rgba(100, 116, 139, 0.16); }
.pf-block .info-row:last-child { border-bottom: none; }
.pf-block .info-row .v.mono { font-family: var(--font-mono); font-weight: 500; }
/* 账号安全右侧说明文字（20260923a）：.v.muted 需盖过 .info-row .v 的字色 → 提高一级特异性 */
.info-row .v.muted { color: var(--ink-400); font-weight: 400; }

/* 退出登录（20260923a）：整宽浅红按钮（原顶栏「退出」入口）。
   20260923b：本按钮不套 .pf-block 分块（用户要求移到 section 外）→ 上下留白由自身 margin 提供 */
.pf-logout-btn {
  display: flex; align-items: center; justify-content: center; gap: 6px;
  width: 100%; margin: 0 0 18px;
  background: var(--danger-soft); border-color: rgba(var(--danger-glow), 0.30); color: var(--danger);
  font-weight: 500;
}
.pf-logout-btn:hover { background: #fbdede; border-color: rgba(var(--danger-glow), 0.45); color: var(--danger); }

/* 账号安全行：右侧「修改密码」按钮与其它行按钮对齐 */
.info-row .pf-act.pf-act-accent { color: var(--accent-600); }
/* 修改密码弹框：表单内的强度条/不一致提示（沿用注册页 .pw-* 类，只补间距） */
.form-field .pw-strength { margin-top: 6px; }
.form-field .pw-mismatch { margin-top: 6px; }
/* 「忘记旧密码？」左对齐小链接 */
.pf-forgot-row { margin: -2px 0 14px; font-size: 13.5px; }
.pf-forgot-row a { color: var(--accent-600); font-weight: 500; }
.pf-forgot-row a:hover { text-decoration: underline; }

/* ============================================================
   管理后台（20260923e）
   页面骨架与用户端工作台完全一致（.main-layout / .sidebar / .content），
   这里只补管理后台独有的零件：可滚动页面、KPI 下的图表卡、日志表、弹框提示。
   ============================================================ */
/* 每个管理页自带滚动区：.content 是 overflow:hidden，长内容必须自己滚（历史踩坑） */
.adm-scroll {
  flex: 1 1 auto; min-height: 0; overflow-y: auto; overflow-x: hidden;
  padding-right: 2px;
}
/* ---- 20261008r：表格页「表内滚动」 ----
   问题：.adm-scroll 自己 overflow-y:auto，表格一长就**整页一起滚** ——
        筛选栏、汇总数字、分页、底部说明全被推走，读表时得回头滚。
   方案：.adm-scroll 改成 flex 列（表格区吃掉全部剩余高度），
        只有 .scroll-x 表格容器竖向滚动，表头 position:sticky 天然吸顶。
   ⚠️ 保留 overflow-y:auto（不改成 hidden）：视口极矮、非表格区就撑满时
      退化成整页滚动，而不是把底部分页/说明**裁掉看不见**。
   用法：<div class="adm-scroll col"> + tab 主体加 class="adm-fill"。 */
.adm-scroll.col { display: flex; flex-direction: column; }
/* 直接子元素默认按内容高度（页头 / 筛选 / 汇总 / 分页 / 说明），一律不参与伸缩 */
.adm-scroll.col > * { flex: none; }
/* tab 主体等中间层容器必须自己也是 flex 列并吃掉剩余高度，
   否则里面的 .scroll-x 拿到的是 auto 高度 → 表格撑开外层又变成整页滚 */
.adm-scroll.col > .adm-fill { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.adm-scroll.col > .adm-fill > * { flex: none; }
/* 表格区：横向 + 竖向都在这里滚。min-height 兜底：剩余空间小于它时
   外层退化为整页滚动（内容不会消失） */
.adm-scroll.col > .scroll-x,
.adm-scroll.col > .adm-fill > .scroll-x { flex: 1 1 auto; min-height: 120px; overflow: auto; }
/* 看板整页：flex 列 + min-height:100%，把剩余高度让给图表区 ——
   这样三张图的 ECharts 容器拿到真实高度，卡内不会出现竖向滚动条（20260923h） */
.adm-dash { display: flex; flex-direction: column; min-height: 100%; box-sizing: border-box; }
/* 直接子元素一律不参与伸缩：否则 .pt-sum（渠道后台的编号/推广链接条）会被压扁 */
.adm-dash > .page-header, .adm-dash > .astat-kpis, .adm-dash > .adm-note,
.adm-dash > .pt-sum { flex: none; }
/* 看板图表：三列并排，**给定合适高度**（20260923i 用户反馈「撑满屏幕太高了」→
   由「吃掉全部剩余高度」改为固定 300px，底部自然留白，页面依旧不出现竖向滚动条；
   20260924k 每日/每月图表高度统一 +15% → 345px，六张图共用本类） */
.adm-charts {
  flex: none; height: 345px;
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  grid-template-rows: 1fr;
  gap: 12px; margin-bottom: 14px;
}
.adm-chart-card { min-height: 0; }
/* 覆盖 .astat-card-body 的 overflow:auto —— 图表自适应高度，不该出现滚动条 */
.adm-chart-body { display: block; overflow: hidden; position: relative; }
.adm-echart { width: 100%; height: 100%; }
.adm-chart-fallback {
  display: flex; align-items: center; justify-content: center;
  height: 100%; font-size: 14px; color: var(--ink-400);
}
@media (max-width: 1180px) {
  /* 两列两行：345*2 + 12 间距 */
  .adm-charts { grid-template-columns: repeat(2, minmax(0, 1fr));
                grid-template-rows: repeat(2, 1fr); height: 702px; }
}
@media (max-width: 820px) {
  /* 一列三行：345*3 + 12*2 间距 */
  .adm-charts { grid-template-columns: 1fr;
                grid-template-rows: repeat(3, 1fr); height: 1059px; }
}
/* 看板口径说明里的一句小提示 */
.adm-note-tip { color: var(--ink-500); }

/* 口径说明 / 提示文字 */
.adm-note {
  font-size: 13.5px; color: var(--ink-400); line-height: 1.7;
  background: var(--bg-paper-2); border-radius: 8px; padding: 10px 14px;
}
.adm-note b { color: var(--ink-700); font-weight: 600; }
.adm-note-plain { font-size: 13.5px; color: var(--ink-400); margin-top: 6px; }

/* 活跃分析卡头统计（20261015k 并入卡头；20261015l 左右两栏；
   20261015m 拆成两块独立背景、中间间隔 10px——不再是一整条灰底里把文字左右推开） */
.astat-head-stat.act-stat {
  gap: 10px; padding: 0; background: none; border: none; align-items: stretch;
}
.act-stat-item {
  flex: 1; display: flex; align-items: baseline; justify-content: space-between;
  background: #f1f3f5; border: 1px solid #e5e7eb; border-radius: 8px;
  padding: 8px 12px; font-size: 13.5px; color: var(--ink-500); white-space: nowrap;
}
.act-stat-item b {
  font-family: var(--font-mono); font-size: 20px; font-weight: 700;
  color: var(--ink-800); margin: 0 0 0 8px;
}
html.dark .astat-head-stat.act-stat { background: none; border-color: transparent; }
html.dark .act-stat-item { background: var(--bg-panel-2); border-color: var(--border-hairline); }
/* 活跃两卡容器（20261015l）：宽屏走 .adm-charts 三列取前两格（与上方图表同宽）；
   窄屏覆盖 .adm-charts 媒体查询的行数/高度——两卡实际只占一行/两行 */
@media (max-width: 1180px) {
  /* 20261023b：本行有 3 卡（DAU/MAU/排名）⇒ 两列两行，不再是一行 */
  .adm-charts.adm-charts-act { grid-template-rows: repeat(2, 1fr); height: 702px; }
}
@media (max-width: 820px) {
  .adm-charts.adm-charts-act { grid-template-columns: 1fr; grid-template-rows: repeat(3, 1fr); height: 1059px; }
}

/* 搜索框（用户列表右上角） */
.adm-search {
  width: 240px; padding: 6px 12px; font-size: 14px;
  border: 1px solid var(--border-default); border-radius: var(--radius-md);
  background: var(--bg-paper); color: var(--ink-900); outline: none;
}
.adm-search:focus { border-color: var(--accent-500); box-shadow: 0 0 0 3px rgba(var(--accent-glow), 0.10); }

/* 系统日志筛选条 */
.adm-filters { margin-bottom: 10px; }
.adm-filters input, .adm-filters select { font-size: 14px; }
.adm-dim { font-size: 12.5px; color: var(--ink-400); margin-top: 1px; }
.adm-left { text-align: left !important; }
/* 日志表：宽内容允许换行（详情列可能较长） */
#log-table td.adm-left { white-space: normal; word-break: break-all; line-height: 1.5; }

/* 用户列表「操作」列（20260923f）：4 个按钮 + 长邮箱会把表格顶宽到横向溢出（实测 38px）→
   这一列允许换行，让浏览器把溢出量吸收成「必要时折成两行」，其余列仍保持不折行（table.grid 默认 nowrap） */
#user-table td.adm-ops { white-space: normal; padding: 4px 6px 4px 12px; }
/* 20261011x：新增「创建时间」列后该列被压窄、4 个按钮折成 3+1 两行（行高 46→65px）⇒
   按钮左右内边距 8→7px、flex gap 4→3px，共省 ~13px，1920 视口下 4 个按钮重新排成一行 */
#user-table td.adm-ops .btn { white-space: nowrap; padding: 4px 7px; }
/* 包一层 flex：4 个按钮折行时均匀排布（td 直接设 flex 会破坏表格单元格布局）
   20261011x 用户口径：按钮**左对齐**（原居中），左侧 padding 与其它列同为 12px，
   保证首个按钮与「操作」表头文字左边对齐 */
#user-table td.adm-ops .adm-ops-in {
  display: flex; flex-wrap: wrap; gap: 3px; justify-content: flex-start; align-items: center;
}
/* 用户列表「创建时间」列（20261011x）：精确到分钟 + 等宽数字（防列宽随秒数抖动） */
#user-table td.adm-time {
  white-space: nowrap; font-size: 14px; color: var(--ink-500);
  font-variant-numeric: tabular-nums;
}
html.dark #user-table td.adm-time { color: var(--ink-400); }

/* 左下角「退出登录」：与个人信息页的浅红按钮同款 */
.btn.adm-logout {
  display: flex; align-items: center; justify-content: center;
  width: calc(100% - 20px); margin: 0 10px 14px;
  background: var(--danger-soft); border-color: rgba(var(--danger-glow), 0.30); color: var(--danger);
  font-weight: 500;
}
.btn.adm-logout:not(:disabled):hover {
  background: #fbdede; border-color: rgba(var(--danger-glow), 0.45); color: var(--danger);
}

/* 弹框内说明条 */
.adm-field-tip {
  font-size: 13.5px; color: var(--ink-500); line-height: 1.6;
  background: var(--accent-50); border: 1px solid var(--accent-100);
  border-radius: 8px; padding: 8px 12px; margin-bottom: 14px;
}
.adm-field-tip b { color: var(--accent-700); }

/* 用户列表右上角工具区（20260923h）：筛选 + 搜索 + 导出 + 新增，窄屏换行不挤爆 */
.adm-actions { flex-wrap: wrap; justify-content: flex-end; }
.adm-select {
  padding: 6px 26px 6px 10px; font-size: 14px; border-radius: var(--radius-md);
  border: 1px solid var(--border-default); color: var(--ink-900);
  /* 20260928r：background 简写会重置全局 select 箭头的 repeat/position（深色下箭头平铺满框），
     改 background-color 保留箭头；padding-right 让出箭头位 */
  background-color: var(--bg-paper);
}

/* ============================================================
   行内操作弹框（20260923h）：开通订阅 / 赠送试用 / 重置密码
   三个操作共用一个外壳，选项直接写内容（1 个月 / 3 天 / 1 年…），
   不再让用户在 prompt 里输入 1234。
   ============================================================ */
.modal-box.op-box { max-width: 480px; }
.op-target {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px; margin-bottom: 12px;
  background: var(--bg-paper-2); border-radius: 10px;
}
.op-t-avatar {
  flex: none; width: 34px; height: 34px; border-radius: 50%;
  background: var(--accent-500); color: #fff;
  display: flex; align-items: center; justify-content: center;
  font-size: 15px; font-weight: 600;
}
.op-t-info { min-width: 0; display: flex; flex-direction: column; }
.op-t-info b { font-size: 15px; font-weight: 600; color: var(--ink-900); }
.op-t-sub { font-size: 12.5px; color: var(--ink-400); margin-top: 1px; }
.op-opts { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
/* 开通订阅弹框的档位选择行（20261011a） */
.op-tier-row { margin-top: 10px; }
.op-tier-row .adm-field-tip { margin-bottom: 6px; }
/* 4 档时长（1/3/6/12 个月）铺成一行，避免 3+1 的孤行 */
.op-opts.op-opts-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.op-opt {
  position: relative; cursor: pointer; text-align: center;
  border: 2px solid var(--border-default); border-radius: 10px;
  padding: 10px 6px; background: var(--bg-paper);
  transition: border-color .12s, background .12s;
}
.op-opt:hover { border-color: var(--accent-300); background: var(--accent-50); }
.op-opt.active { border-color: var(--accent-500); background: var(--accent-50); }
.op-opt-label { display: block; font-size: 15px; font-weight: 600; color: var(--ink-800); }
.op-opt-note { display: block; font-size: 12.5px; color: var(--ink-400); margin-top: 2px; }
.op-opt-tick {
  position: absolute; top: -8px; right: -6px;
  width: 18px; height: 18px; border-radius: 50%;
  background: var(--accent-500); color: #fff;
  font-size: 12px; line-height: 18px; text-align: center;
  opacity: 0; transition: opacity .12s;
}
.op-opt.active .op-opt-tick { opacity: 1; }
.op-preview {
  display: flex; align-items: center; flex-wrap: wrap; gap: 8px;
  margin-top: 14px; padding: 10px 12px; border-radius: 8px;
  background: var(--accent-50); border: 1px solid var(--accent-100);
  font-size: 14px; color: var(--ink-500);
}
.op-preview b { font-family: var(--font-mono); font-weight: 600; color: var(--ink-800); }
.op-pv-new { color: var(--accent-700); }
.op-pv-arrow { color: var(--accent-500); font-weight: 600; }
.op-pv-note { font-size: 13px; color: var(--ink-400); }
@media (max-width: 560px) {
  .op-opts,
  .op-opts.op-opts-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ============================================================
   问题反馈 / 邀约（20260923m）
   ============================================================ */
/* 侧栏：「我要定制」下的子入口（缩进对齐父项文字） */
/* 20260923n：问题反馈菜单取消子项缩进/缩字号 —— 与其它菜单完全对齐（用户反馈「和上面没对齐」） */
.side-sub { /* 保持类名兼容既有断言，样式与普通 side-item 一致 */ }
/* 邀约菜单右侧灰色说明文字（比菜单名称小一号） */
.side-note { margin-left: auto; font-size: 11px; color: var(--ink-400); font-weight: 400; white-space: nowrap; }
/* 「问题反馈」菜单右上角红点角标（有已回复未查看的咨询时显示） */
.side-dot { position: absolute; top: 6px; right: 8px; width: 8px; height: 8px; border-radius: 50%; background: #e5484d; box-shadow: 0 0 0 2px #f5f6f9; }
/* 列表长文本截断 */
.fb-clip { max-width: 320px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 20260923u：列表行内「查看详情 / 删除」改用员工管理同款 .emp-row-btn / .emp-row-del，原 .fb-del 已废弃 */
/* 我要咨询弹框（20260923p：表单组件对齐员工管理页 —— 边框/圆角/字号走全局 input/textarea 规则） */
.fb-textarea { width: 100%; resize: vertical; min-height: 88px; }
/* 20260923x：「附件」标题行右侧的「选择文件」文字按钮（复用 .link-btn），原生 file input 视觉隐藏
   —— 用户端 #fb-modal / #ct-modal / 人工比对 #mc-setup-modal（20260928b）三处共用；
   管理端回复附件仍用 .fb-file-input 不受影响。
   ⚠️ 必须带 ID 前缀，否则被 .form-field input{width:100%} 按特异性顶掉（1x1 隐藏失效） */
/* 20260923y：「我要反馈」弹框宽度在原 480px 基础上加宽 1/3 → 640px（仅此弹框，不影响其它弹框） */
#fb-modal .modal-box { max-width: 640px; }
#fb-modal .fb-file-hidden,
#ct-modal .fb-file-hidden,
#mc-setup-modal .fb-file-hidden,
#inv-up-modal .fb-file-hidden {
  position: absolute; width: 1px; height: 1px; min-width: 0; padding: 0; border: 0;
  opacity: 0; overflow: hidden; pointer-events: none;
}
/* 20260923y：「附件」标题与右侧「选择文件」文字按钮严格同基线 ——
   align-items 由 center 改 baseline；按钮继承标题行高（line-height:normal 会再偏 0.75px） */
#fb-modal .fb-att-head { display: flex; align-items: baseline; margin-bottom: 6px; }
#fb-modal .fb-att-head .link-btn { margin-left: 0; line-height: inherit; }
/* 管理后台上传发票弹窗（20260928k）：附件交互与「我要定制」同款（标题行+选择文件+即时上传列表） */
#inv-up-modal .fb-att-head { display: flex; align-items: baseline; margin-bottom: 6px; }
#inv-up-modal .fb-att-head .link-btn { margin-left: 0; line-height: inherit; }
/* 文件选择：右侧不显示已选文件名（color:transparent 只隐藏文件名文字），按钮样式与全局输入框一致 */
.fb-file-input { color: transparent; max-width: 260px; }
.fb-file-input::file-selector-button {
  border: 1px solid var(--border-default); border-radius: var(--radius-md);
  padding: 8px 14px; font-size: 15.5px; font-family: inherit; background: var(--bg-paper);
  color: var(--ink-800); cursor: pointer; margin-right: 10px;
  transition: border-color .18s, box-shadow .18s;
}
.fb-file-input::file-selector-button:hover { border-color: var(--accent-500); }
.fb-file-input::file-selector-button:active { border-color: var(--accent-600); }
.fb-up-list { margin-top: 8px; display: flex; flex-direction: column; gap: 6px; }
.fb-att-item { display: flex; align-items: center; gap: 8px; padding: 6px 10px; background: var(--bg-paper-2); border-radius: var(--radius-md); font-size: 13px; }
.fb-att-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--ink-900); }
.fb-att-name i { font-style: normal; color: var(--ink-400); }
/* 20260924a：图标基线修正提到通用级。svgIco() 输出的 svg 默认 vertical-align:baseline，
   而 SVG 的基线就是元素底边 → 图标「坐」在文字基线上、视觉整体偏下。
   原来只挂在 .fb-att-name/.fb-att-link/.fb-att-more 三个父选择器下，详情页/回复区的
   裸 <a>（#fbd-att、#fbd-reply-att 及管理端 afbd-* 同款）拿不到修正 → 图标与文件名不在一条水平线。
   注：空态图标 .empty-icon svg 是 display:block，vertical-align 对其无效，不受影响。 */
.ico { vertical-align: -2.5px; }
/* 20260923z：附件小图标（扁平回形针 SVG）—— 与相邻文字基线对齐，不参与缩放/挤压 */
.fb-att-name .ico, .fb-att-link .ico, .fb-att-more .ico { width: 14px; height: 14px; vertical-align: -2.5px; margin-right: 2px; flex: none; }
.fb-att-link .ico, .fb-att-more .ico { width: 13px; height: 13px; vertical-align: -2px; }
.fb-att-pct { color: var(--ink-700); flex: none; }
.fb-att-ok { color: var(--success, #1f7a3f); flex: none; }
.fb-att-err { color: var(--danger, #c0392b); flex: none; }
.fb-att-del { flex: none; border: none; background: transparent; color: var(--ink-400); cursor: pointer; font-size: 14px; padding: 2px 6px; line-height: 1.4; border-radius: 4px; }
.fb-att-del:hover { color: var(--danger, #c0392b); background: var(--danger-soft, #fdeaea); }
.fb-hint { font-size: 12px; color: var(--ink-400); margin-top: 4px; }
/* 详情弹框 */
.fb-detail-status { margin-bottom: 12px; }
/* 详情标题行里的徽章与卡片内徽章同字号（13px），保持同一视觉量级 */
.fb-detail-status .badge { font-size: 13px; }
.fb-detail-block { padding: 10px 12px; background: var(--bg-paper-2); border-radius: 8px; margin-bottom: 10px; }
.fb-detail-k { font-size: 13px; color: var(--ink-400); margin-bottom: 4px; }
.fb-detail-v { font-size: 15px; line-height: 1.6; color: var(--ink-900); word-break: break-all; white-space: pre-wrap; }
.fb-detail-v.muted { font-size: 13px; }
.fb-detail-reply { background: var(--accent-50); }
.fb-detail-reply .fb-detail-k { color: var(--accent-700); }
.fb-detail-v a { color: var(--accent-700); text-decoration: underline; font-size: 14px; }
/* 回复弹框顶部的目标条目提示 */
.fb-adm-target { font-size: 13px; color: var(--ink-700); background: var(--bg-paper-2); border-radius: 8px; padding: 8px 12px; margin-bottom: 12px; word-break: break-all; }
/* 列表附件列链接（20260923n）：用户端 + 管理端共用 */
.fb-att-link { color: var(--accent-700); text-decoration: underline; font-size: 13px; word-break: break-all; }
/* 附件即时上传状态条（20260923o）：用户端「我要咨询」+ 管理端「回复」共用 */
.fb-up-status { margin-top: 6px; font-size: 13px; padding: 6px 10px; border-radius: 8px; }
.fb-up-busy { background: var(--bg-paper-2); color: var(--ink-700); }
.fb-up-ok { background: var(--success-soft, #e6f6ec); color: var(--success, #1f7a3f); }
.fb-up-err { background: var(--danger-soft, #fdeaea); color: var(--danger, #c0392b); }
/* 问题反馈列表卡片式（20260923q）：原表格 → 一个问题一张卡；字段与功能不变
   20260923r 视觉重排：左侧状态色条（待回复橙/已回复绿）、正文去掉小灰标签直排 15px、
   回复时间与标题同行、操作区加淡分隔线；卡片加轻阴影 + hover 抬升
   20260923s：回复块改灰色填充块（去掉左侧竖线），卡片左侧状态色条保留
   20260923t：列表改响应式（宽度够左右两列，放不下折成一列） */
/* 问题反馈左右分栏主从布局（20260923u）：左栏固定宽度为记录列表（一个问题一张卡），
   点「查看详情」→ 内容在右栏内渲染（原弹框已移除）；右栏未选中时显示占位提示 */
.fb-split { flex: 1 1 0; min-height: 0; display: flex; gap: 16px; }
/* 左栏：固定宽度（20260923v 起 480px，配两档窄屏收窄），内部列表独立滚动 */
.fb-pane-left { flex: 0 0 480px; min-width: 0; min-height: 0; display: flex; flex-direction: column; }
.fb-list {
  flex: 1 1 0; min-height: 0; height: 0; overflow-y: auto;
  display: flex; flex-direction: column; gap: 10px; padding: 2px 6px 14px 2px;
}
/* 右栏：自适应占满剩余宽度；明细卡片化（头部 + 可滚动内容区）
   20260923w：描边由 border-subtle(.12) 加深到 border-default(.22) */
.fb-pane-right {
  flex: 1 1 0; min-width: 0; min-height: 0; display: flex; flex-direction: column;
  border: 1px solid var(--border-default); border-radius: 12px; background: var(--bg-paper); overflow: hidden;
}
.fb-pane-empty { flex: 1 1 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; color: var(--ink-400); font-size: 14px; }
/* 20260923z：右栏空态图标改为扁平线性 SVG（尺寸走 CSS，颜色继承 .fb-pane-empty 的 --ink-400） */
.fb-pane-empty-icon { width: 34px; height: 34px; opacity: .75; }
.fb-pane-empty-icon svg { width: 100%; height: 100%; display: block; }
.fb-detail-body { flex: 1 1 0; min-height: 0; display: flex; flex-direction: column; }
.fb-pane-right-head { flex: none; display: flex; align-items: center; gap: 10px; padding: 14px 18px; border-bottom: 1px solid var(--ink-100); }
.fb-pane-right-title { font-size: 16px; font-weight: 600; color: var(--ink-900); }
.fb-pane-right-head .fb-detail-status { margin-bottom: 0; }
.fb-pane-right-scroll { flex: 1 1 0; min-height: 0; overflow-y: auto; padding: 16px 18px 18px; }
/* 窄屏逐档收窄左栏，避免右栏被挤没 */
@media (max-width: 1280px) { .fb-pane-left { flex-basis: 400px; } }
@media (max-width: 1080px) { .fb-pane-left { flex-basis: 340px; } }
.fb-card {
  position: relative; overflow: hidden; cursor: pointer;
  border: 1px solid var(--border-default); border-radius: 12px;
  padding: 14px 16px 11px; background: var(--bg-paper);
  box-shadow: 0 1px 2px rgba(16, 24, 40, .04);
  transition: box-shadow .16s ease, border-color .16s ease;
}
.fb-card:hover { border-color: var(--border-strong); box-shadow: 0 4px 14px rgba(16, 24, 40, .07); }
/* 选中（右栏正在展示）：灰色描边 var(--border-line) 2px、不要阴影；整卡可点击打开详情 */
.fb-card.is-selected { border-color: var(--border-line); border-width: 2px; box-shadow: none; }
.fb-card-head { display: flex; align-items: center; gap: 8px; }
/* 状态圆点（20260924d）：原「卡片左侧 3px 彩色竖条」已去掉，改为放在状态徽章「内部」左侧的
   小圆点 —— .badge 本身是 inline-flex 容器，::before 作为首个 flex 项由 gap 自动留白、
   align-items:center 自动居中；颜色用 currentColor 跟随徽章文字色（黄=待处理 / 绿=已处理） */
.fb-card-head .badge::before {
  content: ''; flex: none; width: 7px; height: 7px; border-radius: 50%;
  background: currentColor;
}
/* 字号体系（20260923v 统一）：元信息 13px / 附件链接 14px / 正文 15px —— 卡片与详情逐类对齐 */
/* 20260924d：卡片徽章内的圆点与文字间距单独调大（全局 .badge 的 gap:3px 不动，
   避免影响管理端表格等处徽章）；padding 与字号沿用 23v 口径 */
.fb-card-head .badge { flex: none; font-size: 13px; padding: 2px 9px; gap: 6px; }
.fb-card-time { margin-left: auto; flex: none; font-size: 13px; color: var(--ink-400); font-family: var(--font-mono); }
.fb-card-desc { margin-top: 9px; font-size: 15px; line-height: 1.6; color: var(--ink-800); white-space: pre-wrap; word-break: break-word; }
/* 左栏条目里描述/回复摘要最多 2 行（完整内容在右栏详情看） */
.fb-card-desc.fb-clamp2 { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.fb-card-att { margin-top: 9px; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
/* 卡片内附件链接去掉下划线（避免「📎 文件名 共N个」整段带下划线显乱），hover 才显 */
.fb-card-att .fb-att-link { text-decoration: none; font-size: 14px; }
.fb-card-att .fb-att-link:hover { text-decoration: underline; }
.fb-att-more { font-size: 13px; color: var(--ink-400); }
/* 回复块：灰色填充块（20260923s 起去掉左侧竖线，改整块灰底；回复附件在块内逐个可下载） */
.fb-card-reply { margin-top: 11px; padding: 11px 14px 12px; background: var(--bg-paper-2); border-radius: 8px; }
.fb-card-reply .fb-card-att { margin-top: 8px; }
.fb-card-reply-head { display: flex; align-items: center; gap: 8px; margin-bottom: 3px; }
.fb-card-reply-head .k { font-size: 13px; font-weight: 600; color: var(--accent-700); }
.fb-card-reply-head .t { margin-left: auto; flex: none; font-size: 13px; color: var(--ink-400); font-family: var(--font-mono); }
.fb-card-reply .fb-card-desc { margin-top: 0; font-size: 15px; line-height: 1.55; color: var(--ink-700); }
/* 底部操作：灰底黑字行内按钮（.emp-row-btn，与员工管理操作列同款） */
.fb-card-foot { margin-top: 11px; padding-top: 10px; border-top: 1px solid var(--ink-100); display: flex; justify-content: flex-start; gap: 8px; }

/* ============================================================
   我要定制（20260924b）
   ============================================================ */
/* 左栏顶端引导区（20260924f）：视觉与「问题反馈」无记录时的空态**完全一致** ——
   内部直接复用 .empty-state（虚线框 + 居中 + 浅灰文字 + 46px 图标），
   仅在其内追加一个「我要定制」按钮；这里只留容器定位，不再自绘灰底卡片 */
.ct-hero { flex: none; margin-bottom: 14px; }
/* 20260924g：左栏这个「空态框」的描边改成与右栏卡片（.fb-pane-right）**完全同款** ——
   1px 实线 + 同一个 --border-default 色。原先沿用 .empty-state 的虚线：
   两处 rgba 叠在白底上渲染出的像素色其实完全一样（都是 rgb(221,224,230)），
   但虚线有一半是断口，看上去明显比右侧实线淡、像「两个不同色的框」。
   ⚠️ 只覆写这一处（.ct-hero 内），全局 .empty-state 的虚线样式保持不变
   （其它页面空态仍按虚线占位风格）。 */
.ct-hero .empty-state { border-style: solid; }
.ct-hero-text { margin: 0 auto 14px; font-size: 14px; line-height: 1.7; }
.ct-hero-btn { min-width: 132px; }
/* 弹框：字段多于问题反馈弹框，宽度再放宽一档（仅此弹框） */
#ct-modal .modal-box { max-width: 680px; }
/* 「附件」标题与右侧「选择文件」文字按钮同基线（同 #fb-modal 口径） */
#ct-modal .fb-att-head { display: flex; align-items: baseline; margin-bottom: 6px; }
#ct-modal .fb-att-head .link-btn { margin-left: 0; line-height: inherit; }
/* 选择题：提示 / 可多选标注 */
.ct-tip { margin: -2px 0 8px; font-size: 14px; color: var(--ink-400); }
.ct-note { margin-left: 6px; font-size: 14px; font-weight: 400; color: var(--ink-400); }
/* 联系方式说明（20260924c）：手机号 / 微信号二选一 */
.ct-contact-tip { margin: -4px 0 4px; font-size: 14px; color: var(--ink-400); }
/* 弹框内的提示文字统一 14px（20260924c：含输入框 placeholder 与附件下方说明） */
#ct-modal input::placeholder, #ct-modal textarea::placeholder { font-size: 14px; }
#ct-modal .fb-hint { font-size: 14px; }
.ct-choices { display: flex; flex-wrap: wrap; gap: 8px; }
.ct-choice {
  display: inline-flex; align-items: center; gap: 7px; padding: 7px 13px;
  border: 1px solid var(--border-default); border-radius: var(--radius-md);
  font-size: 15px; color: var(--ink-800); background: var(--bg-paper); cursor: pointer;
  transition: border-color .15s, background .15s, color .15s;
}
.ct-choice:hover { border-color: var(--accent-500); }
/* 选中态：浅蓝底 + 蓝字 + 蓝边（JS 同步 .is-on，不依赖 :has()） */
.ct-choice.is-on { border-color: var(--accent-500); background: var(--accent-50); color: var(--accent-700); }
/* 勾选控件在 .form-field 内会吃到全局 input{width:100%} → 必须用 ID 前缀压过去 */
#ct-modal .ct-choice input {
  width: auto; height: auto; min-width: 0; margin: 0; padding: 0;
  accent-color: var(--accent-500); cursor: pointer; flex: none;
}
/* 卡片上的字段摘要（键值对）：一个问题一行，值超长省略 */
.ct-card-kv { margin-top: 8px; display: flex; flex-direction: column; gap: 4px; }
.ct-card-kv .row { display: flex; gap: 8px; font-size: 13px; line-height: 1.5; }
.ct-card-kv .k { flex: none; width: 62px; color: var(--ink-400); }
.ct-card-kv .v { flex: 1 1 auto; min-width: 0; color: var(--ink-800); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 待沟通卡片提示条（20260924c）：浅绿底 + 绿字，只在 status=pending 时出现 */
.ct-card-hint {
  margin-top: 10px; padding: 8px 12px; border-radius: 8px;
  background: var(--success-soft); color: var(--success);
  font-size: 13px; line-height: 1.6;
}
/* 详情里的多选值：胶囊标签 */
.ctd-tags { display: flex; flex-wrap: wrap; gap: 6px; }
.ctd-tag { display: inline-block; padding: 2px 10px; border-radius: 999px; background: var(--accent-50); color: var(--accent-700); font-size: 13px; }
/* 管理端「定制服务」表格（20260924b）：列多且文本长 —— 固定布局 + 单行省略，
   否则需求描述会把表格撑得远超屏幕宽（需一直横向滚动才能看到操作列）
   20260924c：新增「状态」列与「已沟通」按钮 → 最小宽度同步放宽 */
#acd-table { table-layout: fixed; width: 100%; min-width: 1310px; }
#acd-table td { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 操作列两个按钮并排（详情 / 已沟通） */
#acd-table td.acd-acts { overflow: visible; }
#acd-table td.acd-acts .btn + .btn { margin-left: 6px; }

/* ============================================================
   邀请好友 / 积分（20260924i）
   页面结构：积分总览（.iv-hero）+ 专属链接 + 邀请记录 + 积分明细，三块均为灰底卡片。
   配色沿用全站 token，不再引入新色值。
   20260924j：灰底块的 1px 描边去掉（用户要求，只留灰底）——靠底色与间距区分分块。
   ============================================================ */
#page-invite .iv-scroll { flex: 1; min-height: 0; overflow-y: auto; padding-right: 4px; }

.iv-hero {
  display: flex; align-items: center; gap: 28px; flex-wrap: wrap;
  background: var(--bg-paper-2); border: none;
  border-radius: var(--radius-lg); padding: 18px 22px; margin-bottom: 16px;
}
.iv-hero-main { min-width: 180px; }
.iv-hero-label { font-size: 14px; color: var(--ink-500); }
.iv-hero-num { font-size: 34px; font-weight: 700; line-height: 1.25; color: var(--ink-900); }
.iv-hero-stats { display: flex; gap: 10px; flex: 1 1 auto; flex-wrap: wrap; }
.iv-stat {
  flex: 1 1 0; min-width: 104px;
  background: var(--bg-paper); border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md); padding: 10px 12px;
}
.iv-stat b { display: block; font-size: 20px; color: var(--ink-900); line-height: 1.3; }
.iv-stat span { font-size: 13px; color: var(--ink-400); }

.iv-block {
  background: var(--bg-paper-2); border: none;
  border-radius: var(--radius-lg); padding: 14px 18px 16px; margin-bottom: 16px;
}
.iv-block-head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 12px; }
.iv-block-title { font-size: 15px; font-weight: 600; color: var(--ink-800); }
.iv-block-sub { margin-left: auto; font-size: 13px; color: var(--ink-400); }

.iv-link-row { display: flex; gap: 10px; align-items: center; }
.iv-link-input {
  flex: 1 1 auto; min-width: 0; height: 34px; padding: 0 12px;
  border: 1px solid var(--border-default); border-radius: var(--radius-md);
  background: var(--bg-paper); color: var(--ink-800); font-size: 14px;
  font-family: inherit;
}
.iv-link-input:focus { outline: none; border-color: var(--accent-500); }
.iv-note { font-size: 13px; color: var(--ink-400); margin-top: 10px; line-height: 1.7; }
.iv-note b { color: var(--ink-800); font-weight: 600; }

.iv-rows { display: flex; flex-direction: column; gap: 8px; }
.iv-row {
  display: flex; align-items: center; gap: 12px;
  background: var(--bg-paper); border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md); padding: 10px 14px;
}
.iv-row-main { display: flex; align-items: center; gap: 8px; flex: none; min-width: 200px; }
.iv-row-name { font-size: 14px; color: var(--ink-800); }
.iv-row-order { font-size: 12px; color: var(--ink-400); }
.iv-badge {
  font-size: 12px; padding: 1px 8px; border-radius: 999px;
  background: var(--bg-paper-2); color: var(--ink-500); border: 1px solid var(--border-subtle);
}
.iv-badge-paid { background: var(--success-soft); color: var(--success); border-color: transparent; }
.iv-row-meta {
  flex: 1 1 auto; min-width: 0; font-size: 13px; color: var(--ink-400);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.iv-row-right { display: flex; align-items: baseline; gap: 6px; flex: none; }
.iv-pt { font-size: 15px; font-weight: 600; }
.iv-pt-up { color: var(--success); }
.iv-pt-down { color: var(--ink-500); }
.iv-pt-none { color: var(--ink-300); }
.iv-pt-unit { font-size: 12px; color: var(--ink-400); }
.iv-empty { padding: 34px 20px; }

@media (max-width: 1280px) {
  .iv-hero { gap: 18px; }
  .iv-row-main { min-width: 150px; }
}

/* ---------- 订阅弹框：积分抵扣（20260924i） ---------- */
.sub-sec-title-row { display: flex; align-items: baseline; gap: 10px; }
.sub-sec-bal { margin-left: auto; font-size: 13px; color: var(--ink-400); font-weight: 400; }
.sub-sec-bal b { color: var(--accent-500); font-size: 14px; }
/* 积分抵扣（20261011e）：只留输入框本体，外层背景图层去掉 */
.sub-points { border: none; border-radius: 0; padding: 0; margin-bottom: 0; background: transparent; }
.sub-points-row { display: flex; align-items: center; gap: 10px; }
/* 20260924j：输入框宽度自适应弹框宽度 —— 外层输入框撑满整行，内部 input 再吃掉剩余宽度 */
.sub-points-field {
  display: flex; align-items: center; gap: 6px;
  flex: 1 1 auto; min-width: 0;
  border: 1px solid var(--border-default); border-radius: var(--radius-md);
  background: var(--bg-paper); padding: 0 10px; height: 40px;
}
.sub-points-field:focus-within { border-color: var(--accent-500); }
/* 输入框自身不要边框/背景：外层 .sub-points-field 已经是「输入框」的外观，
   这里再画一层会出现双框（历史踩坑：原生 input 的默认样式） */
.sub-points-field input {
  flex: 1 1 auto; min-width: 0; width: auto; border: none; background: transparent; outline: none;
  font-size: 15px; font-family: inherit; color: var(--ink-800); text-align: left;
  -moz-appearance: textfield;
}
/* 无可用积分：输入框置禁用（20260924j —— 取代原来的「暂无可用积分…」说明文字） */
.sub-points-field input:disabled { cursor: not-allowed; color: var(--ink-400); }
.sub-points-field input::-webkit-outer-spin-button,
.sub-points-field input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.sub-points-unit { font-size: 13px; color: var(--ink-400); }
.sub-points-all {
  border: 1px solid var(--border-default); background: var(--bg-paper);
  border-radius: var(--radius-md); height: 40px; padding: 0 14px;
  font-size: 13px; font-family: inherit; color: var(--ink-800); cursor: pointer;
}
.sub-points-all:hover { border-color: var(--border-strong); color: var(--accent-500); }
.sub-points-tip { font-size: 13px; color: var(--ink-400); margin-top: 8px; line-height: 1.6; }
.sub-points-tip-ok { color: var(--success); }

/* ---------- 管理后台：积分列 / 积分明细弹框 / 订阅记录（20260924i） ---------- */
.pt-cell {
  display: inline-flex; align-items: baseline; gap: 4px;
  border: 1px solid transparent; background: none; border-radius: var(--radius-md);
  padding: 2px 8px; cursor: pointer; font-family: inherit;
}
.pt-cell:hover { border-color: var(--border-default); background: var(--bg-paper-2); }
.pt-cell b { font-size: 15px; color: var(--accent-500); }
.pt-cell span { font-size: 12px; color: var(--ink-400); }
.pt-up { color: var(--success); font-weight: 600; }
.pt-down { color: var(--ink-500); font-weight: 600; }
.pt-sub { margin-left: 6px; font-size: 12px; color: var(--ink-400); }
.pt-order { font-size: 12px; color: var(--ink-400); }

.pt-sum { display: flex; gap: 10px; margin-bottom: 12px; }
.pt-sum-item {
  flex: 1 1 0; background: var(--bg-paper-2); border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md); padding: 10px 12px;
}
.pt-sum-item span { display: block; font-size: 13px; color: var(--ink-400); }
.pt-sum-item b { font-size: 20px; color: var(--ink-900); }

/* 20261007m 渠道后台「数据看板」顶部条：删掉我的编号/代理费用后只剩两项 ——
   左「推广链接」占大头（flex:3），右「抽佣比例」窄（flex:1）。 */
.pt-sum-2 .ag-promo { flex: 3 1 0; min-width: 0; }
.pt-sum-2 .ag-rate  { flex: 1 1 0; }
.ag-promo-head {
  display: flex; align-items: center; gap: 6px;
  font-size: 13px; color: var(--ink-400); margin-bottom: 4px;
}
/* 标题右侧提示图标：hover / 聚焦显示气泡（纯 CSS，不引JS 事件）
   ⚠️ 选择器必须带 .pt-sum-2 前缀压过上面的 `.pt-sum-item span`
      （那条规则是 0,1,1；这里若只写 .ag-promo-tip 是 0,1,0，会被它盖掉
       display 与 color，图标就不显示、hover 也不变色）。 */
.pt-sum-2 .ag-promo-tip {
  position: relative; display: inline-flex; cursor: help;
  color: var(--ink-400); transition: color .12s;
}
.pt-sum-2 .ag-promo-tip:hover,
.pt-sum-2 .ag-promo-tip:focus { color: var(--accent-600); outline: none; }
.pt-sum-2 .ag-promo-tip::after {
  content: attr(data-tip);
  position: absolute; left: 0; top: calc(100% + 8px); z-index: 60;
  width: 264px; padding: 9px 11px;
  background: var(--ink-900); color: var(--bg-paper);
  font-size: 12.5px; line-height: 1.6; font-weight: 400; text-align: left;
  white-space: normal; border-radius: var(--radius-md);
  box-shadow: 0 6px 20px rgba(0, 0, 0, .18);
  opacity: 0; visibility: hidden; transition: opacity .14s;
  pointer-events: none;      /* 气泡不挡鼠标，移出图标即消失 */
}
.pt-sum-2 .ag-promo-tip:hover::after,
.pt-sum-2 .ag-promo-tip:focus::after { opacity: 1; visibility: visible; }
/* 链接 + 复制按钮同一行；URL 过长时省略号截断（完整值仍可一键复制） */
.ag-promo-body { display: flex; align-items: center; gap: 10px; min-width: 0; }
.ag-promo-body b {
  flex: 1 1 auto; min-width: 0; font-size: 14px; line-height: 1.4;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ag-promo-copy { flex: none; }
.pt-meta {
  display: flex; flex-wrap: wrap; gap: 6px 20px; font-size: 13px; color: var(--ink-500);
  padding: 10px 12px; background: var(--bg-paper-2); border-radius: var(--radius-md); margin-bottom: 12px;
}
.pt-meta b { color: var(--ink-800); }
/* 积分明细弹框（20260924j）：弹框加宽 + 表格不再撑出横向滚动条
   （去掉「说明」列后剩 5 列，宽度自适应弹框即可） */
#pt-modal .modal-box { max-width: 960px; }
.pt-table { min-width: 0; }

.aso-stats { display: flex; gap: 10px; margin-bottom: 14px; flex-wrap: wrap; }
.aso-stat {
  flex: 1 1 0; min-width: 150px;
  background: var(--bg-paper-2); border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md); padding: 10px 14px;
}
.aso-stat span { display: block; font-size: 13px; color: var(--ink-400); }
.aso-stat b { font-size: 18px; color: var(--ink-900); }

/* ==================== 异常检查模式（20260924n，20260924o/p 调整） ==================== */
/* 五类异常色（20260924p 用户口径：缺卡红 · 旷工#f9c716 · 迟到紫 · 早退蓝 · 请假绿），
   格子填充/图例/入口按钮渐变统一用深色主色：
   请假 var(--success) · 迟到 #7c3aed · 早退 #0066cc · 缺卡 var(--danger) · 旷工 #f9c716 */

/* 入口按钮：描边用五色渐变（双背景法），文字用内层 span 单独裁切渐变（两种 clip 不能同层）
   20260928x 用户口径：五色顺序 红→黄→绿→蓝→紫，从左向右水平填充（90deg） */
.ck-btn {
  --ck-grad: linear-gradient(90deg, var(--danger) 0%, #f9c716 25%, var(--success) 50%, #0066cc 75%, #7c3aed 100%);
  border: 1.5px solid transparent;
  background: linear-gradient(var(--bg-card), var(--bg-card)) padding-box, var(--ck-grad) border-box;
  border-radius: var(--radius-md);
  padding: 7px 14px;
  font-size: 13.5px;
  cursor: pointer;
  transition: box-shadow .15s ease, transform .15s ease;
}
.ck-btn-txt {
  font-weight: 600;
  color: transparent;
  background: var(--ck-grad);
  -webkit-background-clip: text;
  background-clip: text;
}
.ck-btn:hover {
  box-shadow: 0 2px 10px rgba(100, 116, 139, .25);
  transform: translateY(-1px);
}
.ck-btn:active { transform: translateY(0); }

/* 覆盖层大板：宽度由 ckRenderGrid 按当月天数自适应设置（20260924p），92vw 封顶 */
.ck-box {
  width: 92vw; height: 88vh; max-width: none;
  background: var(--bg-card); border-radius: var(--radius-lg);
  display: flex; flex-direction: column;
  overflow: hidden;
  box-shadow: 0 18px 50px rgba(13, 17, 23, .28);
}
.ck-head {
  display: flex; align-items: center; gap: 16px;
  padding: 14px 18px; border-bottom: 1px solid var(--border-subtle);
  flex: none;
}
.ck-head-left { flex: 1; min-width: 0; }
.ck-head .modal-title { margin-bottom: 2px; }
#ck-sub { font-size: 12.5px; }
.ck-legend { display: flex; align-items: center; gap: 12px; flex: none; }
.ck-legend .lg-item { font-size: 13px; }
/* 图例可勾选（20260929i）：checkbox 控制该类异常是否在下方格子标色；取消勾选整项置灰 */
.ck-legend .ck-lg { cursor: pointer; user-select: none; gap: 5px; }
.ck-legend .ck-lg input {
  margin: 0; width: 13px; height: 13px; cursor: pointer; accent-color: #2563eb;
}
.ck-legend .ck-lg.ck-off { opacity: .4; }
.ck-legend .ck-lg.ck-off .lg-dot { filter: grayscale(.8); }
/* 「当日合计」图例提示图标（20260929j）：比字段提示默认 15px 缩一号，随图例字号 */
.ck-legend .cfg-tip { width: 13px; height: 13px; margin-left: 1px; color: var(--ink-300); }
.ck-legend .ck-lg.ck-off .cfg-tip { opacity: .5; }
/* mc-modal 头部（20260928b）：标题+副标题一行，图例换行到第二行（用户口径：不要左右布局）；
   关闭按钮绝对定位右上角，避免被换行后的图例挤下去 */
#mc-modal .ck-head { position: relative; flex-wrap: wrap; row-gap: 6px; }
#mc-modal .ck-head-left { flex: 1 1 100%; padding-right: 40px; }
#mc-modal .ck-legend { flex-basis: 100%; flex-wrap: wrap; }
#mc-modal .ck-close { position: absolute; top: 10px; right: 14px; }
/* 20260928l：重选比对文件按钮固定在右上角关闭按钮左侧 */
#mc-modal .mc-reselect { position: absolute; top: 28px; right: 60px; }
#mc-modal .mc-diff-num { color: #2563eb; font-weight: 700; }

/* 员工筛选多选下拉（20260928m）：复用全局 .msel 组件骨架，仅补空态文案样式 */
.msel-empty { padding: 10px 14px; font-size: 13px; color: var(--ink-400); white-space: nowrap; }
/* 20261016j（用户口径）：员工管理部门/考勤组筛选面板——
   ① 高度收窄 340px（原全局 100vh-16 会抵到页面底部，选项多时整屏都是面板）；
   ② 宽度上限放宽 480px（原 320px 长部门名被省略号截断），超长名仍由行内
      ellipsis 兜底 + 行 title 悬停提示全名（见 mselRender） */
.msel-pop-filter { max-height: 340px; max-width: 480px; }
/* 20260928c：标题与右侧「选择文件」文字按钮的间距（约 4 个空格宽）+ 白底卡片突出显示 */
#mc-setup-modal .fb-att-head {
  gap: 0 16px; background: var(--bg-card); border: 1px solid var(--border-subtle);
  border-radius: 8px; padding: 10px 14px; margin-bottom: 10px;
}
.ck-close {
  flex: none; width: 30px; height: 30px; border-radius: 50%;
  border: 1px solid var(--border-subtle); background: var(--bg-card);
  color: var(--ink-500); font-size: 14px; cursor: pointer; line-height: 1;
}
.ck-close:hover { background: var(--bg-paper-2); color: var(--ink-800); }

.ck-body {
  flex: 1; overflow: auto;
  padding: 14px 18px 20px;
}

/* 每人一行：姓名列固定 + 横向格子带（格子 20px 圆角正方形、间距 2px） */
.ck-row { display: flex; align-items: center; gap: 12px; padding: 5px 0; }
.ck-row + .ck-row { border-top: 1px dashed var(--border-subtle); }
.ck-name {
  flex: none; width: 96px;              /* 20260924o：不再显示部门，收窄 */
  font-size: 13.5px; font-weight: 600; color: var(--ink-800);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  line-height: 18px;                    /* 与格子同高，单行垂直居中 */
}
.ck-cells { display: flex; flex-wrap: wrap; gap: 2px; align-items: center; }

.ck-cell {
  width: 18px; height: 18px; flex: none;
  border-radius: 5px;
  background: var(--bg-hover);               /* 默认灰（与统计页休息日底色一致） */
  cursor: pointer;
  position: relative;
  transition: transform .1s ease, box-shadow .1s ease;
}
.ck-cell:hover {
  transform: scale(1.25);
  box-shadow: 0 0 0 2px var(--bg-card), 0 0 0 3.5px var(--accent-500);
  z-index: 2;
}
/* 人工修改过的天：左上角小三角（口径 = edited_cells，与统计页角标同源）
   20260924o：格子改深色填充，三角改白色保证可见 */
.ck-cell.ck-edited::before {
  content: ''; position: absolute; left: 0; top: 0;
  border-style: solid; border-width: 6px 6px 0 0;
  border-color: rgba(255, 255, 255, .92) transparent transparent transparent;
  border-top-left-radius: 5px;
}

/* 日期表头行（1-31 数字 + 星期小字，与格子一一对位） */
.ck-row-head { position: sticky; top: -14px; background: var(--bg-card); z-index: 1; padding: 10px 0 6px; }
.ck-row-head .ck-name { font-size: 11px; color: var(--ink-400); font-weight: 400; }
.ck-daynum {
  width: 18px; flex: none;
  font-size: 10.5px; line-height: 18px; text-align: center;   /* 20260924p：只显示数字，行高与格子对齐 */
  color: var(--ink-500);
}
.ck-daynum.is-rest { color: var(--ink-400); }

/* 悬停预览 tooltip（fixed 定位跟随鼠标） */
.ck-tip {
  position: fixed; z-index: 3000;
  max-width: 320px;
  background: var(--ink-900); color: #fff;
  font-size: 12.5px; line-height: 1.55;
  padding: 8px 12px; border-radius: 8px;
  pointer-events: none;
  box-shadow: 0 6px 20px rgba(13, 17, 23, .35);
}
.ck-tip b { font-weight: 600; }
.ck-tip .muted { color: rgba(255, 255, 255, .55); }

/* 单日编辑弹框（叠在检查模式之上）—— 20260924o：去掉 wide，回归默认 480px */
#ck-day-modal { z-index: 2600; }
#ck-day-modal .modal-box { max-height: 86vh; overflow: auto; }
.ckf-list { display: flex; flex-direction: column; }
.ckf-row {
  display: flex; align-items: center; gap: 10px;
  padding: 6px 0; border-bottom: 1px dashed var(--border-subtle);
}
.ckf-row:last-of-type { border-bottom: none; }
.ckf-label { flex: none; width: 110px; font-size: 13.5px; color: var(--ink-700); }
.ckf-input {
  flex: 1; min-width: 0;
  border: 1px solid var(--ink-200); border-radius: var(--radius-sm);
  padding: 6px 10px; font-size: 13.5px;
}
.ckf-input:focus { outline: none; border-color: var(--accent-500); box-shadow: 0 0 0 2.5px var(--accent-50); }
.ckf-leave { flex: 1; font-size: 13.5px; color: var(--ink-800); }

/* ---- 自动补卡（20261001d）：异常检查模式缺卡自动补齐 ---- */
/* 姓名上方的「自动补卡规则」入口（20261001f 用户定版：蓝字加粗 14px，无背景描边） */
.ck-rule-btn {
  border: none; background: none; padding: 0;
  color: var(--accent-500); font-size: 14px; font-weight: 700; line-height: 1.25;
  cursor: pointer; white-space: nowrap;
}
.ck-rule-btn:hover { color: var(--accent-600); }
/* 每人行尾「补缺卡」按钮列 */
.ck-act { flex: none; width: 64px; display: flex; justify-content: flex-end; gap: 6px; }
/* 20261032c（需求④）：同一行既「补缺卡」又「恢复补卡」时固定更宽的按钮列，
   保证各行右边缘对齐（网格是 flex 行，宽度不一致看起来会参差） */
.ck-grid-2act .ck-act { width: 148px; }
/* 「恢复补卡」用警示色描边（撤销动作，和补缺卡区分开）；颜色一律走主题变量
   —— --warning 在深色主题里已提亮为 #ff9f0a，不要写死色值 */
.ck-restore-btn { color: var(--warning); border-color: var(--warning); font-weight: 600; }
.ck-restore-btn:hover { background: var(--bg-paper-2); color: var(--warning); }
/* 表头行「自动补卡规则」按钮列（20261001g：位于 1-31 日期右侧，宽度按按钮内容） */
.ck-act-rule { width: auto; padding-left: 8px; justify-content: flex-end; }
.ck-fill-btn {
  border: 1px solid var(--border-subtle); background: var(--bg-card);
  color: var(--ink-500); font-size: 11.5px; padding: 3px 8px;
  border-radius: 6px; cursor: pointer; white-space: nowrap;
}
.ck-fill-btn:hover { background: var(--bg-paper-2); color: var(--ink-800); }
/* 两个新弹框叠在检查模式之上（与 #ck-day-modal 同层高半档） */
#ck-rule-modal { z-index: 2650; }
#ck-fill-modal { z-index: 2650; }
/* 规则弹框（20261001g）：宽度随两栏类型卡自适应，不出现横向滚动条 */
#ck-rule-modal .modal-box { max-height: 86vh; width: fit-content; min-width: 480px; max-width: 96vw; overflow: auto; }
#ck-fill-modal .modal-body { max-height: 66vh; overflow: auto; }
/* 补缺卡弹框（20261001f）：宽度自适应缺卡天数（fit-content），上限 96vw */
.ck-fill-box { width: fit-content; min-width: 560px; max-width: 96vw; }
#ck-fill-modal .modal-actions { justify-content: center; position: relative; }
/* 补缺卡统计文字（20261001g）：移到顶部标题下方 */
#ck-fill-count { margin: -10px 0px 10px 0px; font-size: 12.5px; }

/* 规则弹框：小节标题 / 类型卡片（格子可视化：打勾=有卡，空=无卡） */
.cfr-sec { font-size: 13px; font-weight: 600; color: var(--ink-800); margin: 12px 0 8px; }
.cfr-types { display: grid; grid-template-columns: repeat(2, 320px); gap: 8px 12px; }
.cfr-type {
  display: flex; align-items: center; gap: 8px; width: 320px;   /* 20261001g：卡片统一固定宽 */
  border: 1px solid #cccccc; border-radius: 8px;   /* 20261001h：描边 #cccccc */
  padding: 8px 10px; cursor: pointer; user-select: none;
  background: var(--bg-card); font-size: 13px;
}
/* 20261001h：选中卡片增加蓝色描边（多选框蓝色勾选示意不变，不加底色） */
.cfr-type.on { border-color: #2563eb; }
.cfr-type input { margin: 0; width: 13px; height: 13px; cursor: pointer; accent-color: #2563eb; }
/* 「开始补卡」上方提示文字（20261001i；20261001j 居中+字号 13px+去左右内边距） */
.cf-gotip {
  font-size: 13px; color: var(--ink-500); line-height: 1.5;
  /* padding: 0 24px; */ margin: 10px 0 -10px 0; text-align: center;
}
/* 4缺3 子项勾选区（20261001i）：卡片选中后展开「补哪几张卡」 */
.cfr-cell { width: 320px; min-width: 0; }
.cfr-sub {
  display: flex; flex-wrap: wrap; gap: 4px 10px;
  border: 1px dashed #cccccc; border-radius: 8px;
  padding: 6px 10px; margin-top: 6px;
}
.cfr-subitem {
  display: flex; align-items: center; gap: 4px;
  font-size: 12px; color: var(--ink-700); cursor: pointer; user-select: none;
}
.cfr-subitem input { margin: 0; width: 12px; height: 12px; cursor: pointer; accent-color: #2563eb; }
.cfr-grids { display: inline-flex; gap: 4px; }
.cfr-g {
  width: 18px; height: 18px; border-radius: 4px;
  border: 1.5px solid var(--border-subtle); background: var(--bg-hover);
  font-size: 12px; line-height: 15px; text-align: center; color: transparent;
  font-style: normal; flex: none;
}
.cfr-g.ok {
  border-color: var(--success); color: var(--success); font-weight: 700;
}
.cfr-tname { color: var(--ink-800); white-space: nowrap; }
.cfr-tdesc { font-size: 11.5px; color: var(--ink-400); white-space: nowrap; }
/* 4缺1/4缺2/4缺3 小标题（20261001g）：居中 + 圆角背景胶囊 */
.cfr-cat {
  width: max-content; margin: 10px auto 6px;
  font-size: 12px; font-weight: 600; color: var(--ink-600);
  background: var(--bg-hover); border-radius: 999px; padding: 3px 14px;
}
.cfr-rules { display: flex; flex-direction: column; gap: 4px; }
.cfr-rule {
  font-size: 12.5px; color: var(--ink-700); line-height: 1.6;
  background: #eef0f5; border-radius: 6px; padding: 6px 10px;   /* 20261001h：底色 #eef0f5 */
  max-width: 640px;   /* 20261001g：长文案换行，不参与弹框 fit-content 撑宽 */
}

/* 补缺卡弹框：缺卡日期卡栅格（2 次卡 16 天一行；4 次卡 8 天一行）；
   20261001e：上班/下班标签统一在栅格左侧一列显示一次，日期卡内只放时间 */
/* 20261001j：cf-body 改纵向堆叠多个日期行（.cf-row），每个日期行都带标题列 */
.cf-body { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.cf-row { display: flex; gap: 8px; align-items: flex-start; min-width: 0; }
.cf-labcol { flex: none; display: flex; flex-direction: column; gap: 4px; padding: 7px 0; }
.cf-labhead { height: 15px; }
.cf-lab { height: 19px; line-height: 19px; font-size: 11px; color: var(--ink-500); white-space: nowrap; }
/* 补缺卡栅格（20261001f）：列宽 max-content——天数少时整框随内容收窄 */
.cf-grid { flex: none; display: grid; grid-template-columns: repeat(16, max-content); gap: 6px; }
.cf-grid.cf-grid4 { grid-template-columns: repeat(8, max-content); }
.cf-day {
  border: 1px solid var(--border-subtle); border-radius: 8px;
  padding: 6px 4px; display: flex; flex-direction: column; gap: 4px; align-items: stretch;
}
.cf-day.will-fill { border-color: var(--success); }
.cf-d { font-size: 11px; font-weight: 600; color: var(--ink-700); text-align: center; height: 15px; line-height: 15px; }
.cf-chiprow { display: flex; min-width: 0; }
.cf-t {
  flex: 1; min-width: 46px; text-align: center;
  font-size: 11px; line-height: 18px; border-radius: 4px;
  background: var(--bg-hover); color: var(--ink-400);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* 自动补的时间突出显示（绿底加粗）；已有时间弱化（灰）；缺位未补（红虚线） */
.cf-t.fill {
  background: #dcfce7; color: #166534; font-weight: 700;
  border: 1px solid var(--success);
}
/* 20261001l：绿色补卡格 hover → 黑色透明覆盖 + 白色✕（title 提示「移除当前补卡」），点击移除该补卡 */
.cf-t.fill { position: relative; cursor: pointer; }
.cf-t.fill::after {
  content: '✕';
  position: absolute; inset: -1px;   /* 盖住描边 */
  display: flex; align-items: center; justify-content: center;
  background: rgba(0, 0, 0, .7); color: #ffffff;
  font-size: 12px; font-weight: 600; line-height: 18px;
  border-radius: 4px;
  opacity: 0; pointer-events: none; transition: opacity .12s;
}
.cf-t.fill:hover::after { opacity: 1; }
.cf-t.miss {
  background: transparent; border: 1px dashed var(--danger);
  color: var(--danger);
}
html.dark .cf-t.fill { background: rgba(22, 163, 74, .22); color: #4ade80; }

/* 定位至当日考勤（20260928f，用户口径升级）：当日竖向整列高亮——
   该员工当天所有指标格加红色透明底连成一列（左右各留红色竖边），
   另在滚动容器内放 #ck-located-band 覆盖整列的红框发光层
   （box-shadow 脉冲、溢出单元格范围）；闪烁 0.9s×4≈3.6s 后定格静态红色，
   8 秒或下次定位自动移除。 */
#summary-grid { position: relative; }
#summary-grid td.col-day.ck-located {
  background: rgba(220, 38, 38, 0.15) !important;
}
#ck-located-band {
  position: absolute; z-index: 60; pointer-events: none;
  border: 2.5px solid var(--danger); border-radius: 6px;
  background: rgba(220, 38, 38, 0.06);
  animation: ckLocatedGlow .9s ease-in-out 4;
}
@keyframes ckLocatedGlow {
  0%, 100% { box-shadow: 0 0 0 3px rgba(220, 38, 38, 0.22), 0 0 14px 3px rgba(220, 38, 38, 0.35); }
  50%      { box-shadow: 0 0 0 10px rgba(220, 38, 38, 0.10), 0 0 30px 14px rgba(220, 38, 38, 0.55); }
}

/* 结果页/预览/归档详情「工号」「岗位」信息列（20261001a，原 20260929u 仅结果页工号列）：
   「配置考勤明细/汇总表格格式 → ＋ 添加」勾选后出现（kind='info'），位置固定 ——
   工号在「部门」前、岗位在「部门」后。sticky 吸附链偏移随勾选组合变化 →
   left 由各渲染点行内样式动态给，这里只定义外观、不写 left；
   背景不在此固定：th 落 table.grid-full thead th 的 --bg-paper-2，
   td 落 tr.block-a/b 斑马纹——姓名/部门/序号列实际显示的就是斑马纹色
   （block 规则与 line 645-660 同特异性但靠后胜出），ID/通用作用域里
   写固定背景反而会压掉斑马纹，导致与左右列色不一致（20260929v 教训） */
table.grid-full th.col-empno, table.grid-full td.col-empno,
table.grid-full th.col-pos, table.grid-full td.col-pos {
  /* 20261001b 用户定版：与姓名/部门列同宽（86px）同字体（继承表格 15px/ink-900），
     外观完全一致 —— 不再有 12px 灰字小号样式 */
  width: 86px; min-width: 86px; max-width: 86px;
  position: sticky; z-index: 2;
  white-space: normal; word-break: break-all; line-height: 1.35;
}
table.grid-full thead th.col-empno, table.grid-full thead th.col-pos { z-index: 4; }

/* 结果页标题行背景统一（20261001b 用户定版）：左侧吸附列表头（序号/姓名/工号/部门/岗位）
   与指标列表头原各带 --col-name-bg/--col-dept-bg/--col-metric-bg/--bg-paper-2 四种底色，
   现统一为表头默认 --bg-paper-2，整行同色。td 不在此列：数据格背景由斑马纹 block-a/b 兜底 */
table.grid-full thead th.col-seq, table.grid-full thead th.col-name,
table.grid-full thead th.col-empno, table.grid-full thead th.col-pos,
table.grid-full thead th.col-dept, table.grid-full thead th.col-metric {
  background: var(--bg-paper-2);
}

/* 结果页姓名单元格 hover「移除」（20260927c）：只影响统计结果，不动员工管理。
   ⚠️ td.col-name 本身是 sticky 吸附列（position:sticky; left:44px）——绝不能再覆盖
   position（relative 会让 left:44px 变成整体右移 44px，姓名列压进部门列、按钮被盖）。
   20260929u 用户定版：按钮锚定姓名文字下方 20px——姓名包 .nm-wrap（relative），
   按钮 absolute 于其 top:100%+20px；姓名在 rowspan 大单元格内也始终贴近文字。
   原为单元格底边向上偏移 20px（20260929t）。 */
#summary-grid td.col-name:hover { z-index: 5; }   /* hover 时压过相邻 sticky 格（z-index:2） */
#summary-grid .col-name .nm-wrap { position: relative; display: inline-block; }
#summary-grid .col-name .res-del {
  display: none;
  position: absolute; left: 50%; top: 100%; bottom: auto; transform: translate(-50%, 20px);
  z-index: 5;
  padding: 1px 8px; font-size: 12px; line-height: 18px;
  border: 1px solid var(--danger); border-radius: 4px;
  background: var(--bg-card); color: var(--danger); cursor: pointer; white-space: nowrap;
}
#summary-grid .col-name:hover .res-del { display: inline-block; }
#summary-grid .col-name .res-del:hover { background: var(--danger); border-color: var(--danger); color: #fff; }

/* 已移除恢复条（筛选栏右侧，点击姓名恢复） */
.res-excluded-bar {
  display: inline-flex; align-items: center; gap: 6px;
  margin-left: auto; font-size: 12px; color: var(--ink-400);
}
.res-excluded-bar.hidden { display: none; }
.resx-chip {
  padding: 1px 8px; border: 1px solid var(--ink-200); border-radius: 10px;
  background: var(--ink-50); color: var(--danger); cursor: pointer;
}
.resx-chip:hover { border-color: var(--danger); background: var(--danger-soft); }
/* 更多按钮（20260927h：>5 人折叠，第 5 位） */
.resx-more {
  padding: 1px 8px; border: 1px solid var(--ink-200); border-radius: 10px;
  background: var(--ink-50); color: var(--ink-600); cursor: pointer;
}
.resx-more:hover { border-color: var(--brand); color: var(--brand); }
/* 已移除人员对话框（20260927h「更多」入口）：fixed 遮罩 + 居中小卡 */
.resx-dialog { position: fixed; inset: 0; z-index: 2600; }
.resx-dialog.hidden { display: none; }
.resx-dialog-mask { position: absolute; inset: 0; background: rgba(15, 23, 42, .35); }
.resx-dialog-card {
  position: absolute; left: 50%; top: 34%; transform: translate(-50%, -50%);
  width: min(520px, calc(100vw - 48px));
  background: var(--paper, var(--bg-card)); border: 1px solid var(--ink-200); border-radius: 10px;
  box-shadow: 0 12px 40px rgba(15, 23, 42, .18);
}
.resx-dialog-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 12px 16px; border-bottom: 1px solid var(--ink-100);
  font-weight: 600; color: var(--ink-800); font-size: 13px;
}
.resx-x { cursor: pointer; font-size: 18px; line-height: 1; color: var(--ink-400); padding: 0 2px; }
.resx-x:hover { color: var(--ink-700); }
.resx-dialog-body {
  display: flex; flex-wrap: wrap; gap: 8px;
  padding: 14px 16px; max-height: 46vh; overflow: auto;
}
.resx-dialog-body .resx-chip { font-size: 13px; padding: 3px 10px; }
.resx-empty { color: var(--ink-400); font-size: 13px; }
.resx-dialog-foot {
  padding: 9px 16px; border-top: 1px solid var(--ink-100);
  font-size: 12px; color: var(--ink-400);
}

/* 统计范围面板（20260927d）：异常检查模式按钮左侧，复用 filter-panel 骨架 */
.scope-panel { min-height: 0; min-width: 280px; max-width: 320px; }
.scope-panel-head {
  padding: 10px 12px 4px; font-weight: 600; font-size: 13px; color: var(--ink-600);
}
.scope-opt {
  display: flex; align-items: center; gap: 8px;
  padding: 7px 12px; font-size: 13px; color: var(--ink-700); cursor: pointer;
}
.scope-opt:hover { background: var(--ink-50); }
.scope-groups {
  border-top: 1px solid var(--ink-150); margin-top: 4px;
  padding: 6px 4px; max-height: 220px; overflow: auto;
}
.scope-group-item {
  display: flex; align-items: center; gap: 8px;
  padding: 5px 8px; font-size: 13px; color: var(--ink-700);
  border-radius: 6px; cursor: pointer;
}
.scope-group-item:hover { background: var(--ink-50); }
.scope-foot {
  display: flex; justify-content: flex-end; gap: 8px;
  padding: 8px 10px; border-top: 1px solid var(--ink-150);
}

/* ==================== 历史数据 · 卡片选中 / 查看汇总（20260927j） ==================== */
/* 全选按钮与左侧「重置条件」拉开一点距离（20260927j2：按钮组紧跟重置右侧） */
.hist-gap { margin-left: 16px; }
/* 卡片前置勾选框：与归档图标同行，点击不触发行打开 */
.hist-ck {
  display: flex; align-items: center; flex-shrink: 0;
  cursor: pointer; padding: 2px;
}
.hist-ck input[type="checkbox"] {
  width: 16px; height: 16px; margin: 0;
  accent-color: var(--accent-600); cursor: pointer;
}
/* 查看汇总弹框：宽版 + 固定高度表格区（内部滚动） */
#hist-sum-modal .hist-sum-box { max-width: 980px; width: 96vw; }
.hist-sum-range {
  font-size: 14px; font-weight: 600; color: var(--ink-700);
  margin-bottom: 10px;
}
.hist-sum-wrap {
  max-height: 52vh; overflow: auto;
  /* 20260927j2 修正：.grid-wrap 全局规则是 flex:1 1 0 + height:0（靠 flex 父级撑开），
     弹框 modal-body 是普通块级布局 → height:0 生效表格整体被裁没（用户报「看不到汇总结果」）。
     此处显式恢复 auto 并脱离 flex 语义，表格自然撑高、超出走纵向滚动。 */
  height: auto; flex: none;
}
/* 重名人员询问弹窗（20260927j）：同名人员名单 */
.dup-list {
  margin: 10px 0 2px; padding: 10px 12px;
  background: var(--ink-50, #f6f7f9);
  border: 1px solid var(--ink-150, #e3e5e8);
  border-radius: 10px;
  max-height: 180px; overflow: auto;
}
.dup-item {
  display: flex; align-items: center; justify-content: space-between;
  padding: 5px 2px; font-size: 14px;
}
.dup-item + .dup-item { border-top: 1px dashed var(--ink-150, #e3e5e8); }
.dup-name { font-weight: 600; color: var(--ink-800); }
.dup-count { font-size: 12.5px; color: var(--warn, #b7791f); }
/* 工号列表（20261011g）：重名弹窗中展示同名人员的工号，帮助判断合并/独立 */
.dup-nos { font-size: 12px; color: var(--ink-500, #7a7f87); margin-left: 10px;
  max-width: 55%; text-align: right; word-break: break-all; }

/* ============ 人工结果比对模式（20260927m）：参考异常检查模式视觉 ============ */
/* toolbar 入口按钮（20260928a）：正常白底，不再用 ck-btn 渐变描边 */
.mc-btn {
  margin-left: 10px; padding: 7px 14px;
  border: 1px solid var(--ink-200); border-radius: var(--radius-md);
  background: var(--bg-card); color: var(--ink-800);
  font-size: 13.5px; cursor: pointer; line-height: 1.4;
}
.mc-btn:hover { background: var(--ink-50); border-color: var(--ink-300); }

/* ---- 设置弹框 ---- */
.mc-setup-hint {
  font-size: 13.5px; color: var(--ink-700);
  margin-bottom: 10px;
}
.mc-sec-title {
  font-size: 13px; font-weight: 600; color: var(--ink-800);
  margin-bottom: 8px;
}
.mc-fields-wrap, .mc-upload-wrap {
  padding: 12px 14px;
  background: var(--ink-50, #f6f7f9);
  border: 1px solid var(--ink-150, #e3e5e8);
  border-radius: 10px;
  margin-bottom: 10px;
}
.mc-fields { display: flex; flex-wrap: wrap; gap: 8px 18px; }
.mc-field {
  display: flex; align-items: center; gap: 6px;
  font-size: 13.5px; color: var(--ink-800);
  cursor: pointer; white-space: nowrap;
}
.mc-field input[type="checkbox"] {
  width: 15px; height: 15px; margin: 0;
  accent-color: var(--accent-600); cursor: pointer;
}
/* 20260928a：上传入口改「选择文件」link-btn + fb-att-item 附件行（对齐我要定制），原 file-selector 样式删除 */
/* 文件格式示意图：让用户照着摆放姓名/指标项/每日列 */
.mc-sample-wrap { margin-top: 12px; }
.mc-sample { overflow-x: auto; }
.mc-sample-t {
  border-collapse: collapse; font-size: 12.5px;
  background: var(--bg-card); min-width: 100%;
}
.mc-sample-t th, .mc-sample-t td {
  border: 1px solid var(--ink-150, #e3e5e8);
  padding: 5px 12px; text-align: center;
  min-width: 52px; height: 28px;
}
.mc-sample-t th {
  background: var(--ink-50, #f6f7f9);
  font-weight: 600; color: var(--ink-700);
  white-space: nowrap;
}
.mc-sample-t td:first-child { min-width: 72px; }
/* 示意图中同人后续行姓名列留空：去上边框形成视觉合并 */
/* 20260928a：示意图姓名列改 rowspan 合并单元格，原姓名延续行边框 hack 删除 */
.mc-warn { color: var(--danger); font-size: 13px; }

/* ---- 结果覆盖层：每人一块 × 指标行 × 每日格（格子复用 .ck-cell 基础样式） ---- */
/* 指标名/表头列：130px（mcRenderGrid 宽度公式 130+12+cellsW+36+22 与此对应） */
.mc-flabel {
  flex: none; width: 130px;
  font-size: 13px; color: var(--ink-800);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  line-height: 18px;
}
.mc-name-head { font-weight: 600; color: var(--ink-700); }
.mc-emp { padding: 6px 0 10px; }
.mc-emp + .mc-emp { border-top: 1px solid var(--border-subtle); }
.mc-emp-name {
  font-size: 13.5px; font-weight: 600; color: var(--ink-800);
  margin: 2px 0 6px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* 一致 = 灰（用户口径：正常灰）；不一致 = 红 */
/* 20260928a：一致格子与异常检查模式正常格子同色（#e8ebf1）；空/0 视为一致 */
.mc-cell { background: var(--bg-hover); }
.mc-cell.mc-diff { background: var(--danger); }
/* 已核对（计算结果正确）：红色消除 + 绿描边 */
.mc-cell.mc-vcalc { background: var(--bg-hover); box-shadow: inset 0 0 0 1.5px var(--success); }

/* 20261005h：不一致格内直接显示「计算/人工」。
   宽度由 mcRenderGrid 按最长内容算出写入 --mc-cell-w（未加宽时保持 18px 原样）；
   文字单行 nowrap + ellipsis 截断，绝不撑破格子。 */
#mc-grid .mc-cell { width: var(--mc-cell-w, 18px); }
#mc-grid .ck-daynum { width: var(--mc-cell-w, 18px); }
.mc-cell .mc-txt {
  display: block;
  width: 100%;
  font-size: 9.5px; line-height: 16px;
  font-weight: 500;
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  pointer-events: none;          /* 事件仍落在格子本身，不影响 click/mouseover 委托 */
  font-variant-numeric: tabular-nums;
  letter-spacing: -.2px;/* 窄格内压缩字距，尽量多显示一位 */
}
/* 红底白字；已核对态为浅灰底 → 用墨色，保持可读 */
.mc-cell.mc-diff .mc-txt { color: #fff; }
.mc-cell.mc-vcalc .mc-txt { color: var(--ink-700); }
/* 加宽后 hover 放大 1.25 会盖住相邻格，改用 1.1 并加强描边 */
#mc-grid.mc-wide .mc-cell:hover { transform: scale(1.1); }
/* 摘要行「红格内为 计算/人工」提示（20261005h）：弱化处理，不抢不一致数字 */
#mc-modal .mc-sub-tip { color: var(--ink-400); }

/* 核对结果模块（20260928a）：两个矩形盒子 2 选 1 */
.mc-verdict-wrap {
  margin-top: 12px; padding-top: 12px;
  border-top: 1px solid var(--border-subtle);
}
.mc-verdict-boxes { display: flex; gap: 10px; }
.mc-vbox {
  flex: 1; padding: 9px 12px;
  border: 1.5px solid var(--border-subtle); border-radius: 8px;
  background: var(--bg-card); color: var(--ink-800);
  font-size: 13.5px; cursor: pointer; text-align: center;
}
.mc-vbox:hover { background: var(--bg-paper-2); }
.mc-vbox.mc-von {
  border-color: var(--accent-600); color: var(--accent-600);
  font-weight: 600; background: var(--accent-50, #eef5ff);
}

/* ---- 格子详情弹框（计算结果 vs 人工导入） ---- */
.mc-cell-rows { display: flex; flex-direction: column; gap: 8px; }
.mc-crow {
  display: flex; align-items: center; gap: 12px;
  padding: 9px 12px;
  background: var(--ink-50, #f6f7f9);
  border: 1px solid var(--ink-150, #e3e5e8);
  border-radius: 10px;
  font-size: 13.5px;
}
.mc-clabel { flex: none; width: 72px; color: var(--ink-500); font-weight: 600; }
.mc-cval { flex: 1; color: var(--ink-800); word-break: break-all; }
.mc-cval.mc-cdiff { color: var(--danger); font-weight: 600; }
.mc-cwarn {
  font-size: 13px; color: var(--danger);
  padding: 2px 2px 0;
}

/* ============================================================
   深色模式（20260928n）：macOS 深色配色（窗口 #1e1e1e / 次级表面
   #28282a / 系统蓝 #0a84ff / 文字 #f5f5f7）。
   机制：html.dark 由 <head> 防闪烁脚本 + initTheme() 控制；
   ink 色阶语义反转（50=深底 → 900=亮字），绝大多数组件走变量自动适配；
   少量硬编码白底组件在此逐个覆盖。
   ============================================================ */
html.dark {
  /* 中性灰反转：50=最深表面 → 900=最亮文字
     20260928o：顶部四档整体降一档亮度（用户反馈纯白字体太刺眼） */
  --ink-50: #2c2c2e;
  --ink-100: #323234;
  --ink-150: #3a3a3c;
  --ink-200: #48484a;
  --ink-300: #57575b;
  --ink-400: #98989d;
  --ink-500: #a8a8ad;
  --ink-600: #b7b7bc;
  --ink-700: #c6c6cb;
  --ink-800: #d5d5da;
  --ink-900: #e5e5ea;

  /* macOS 深色系统蓝 */
  --accent-50: rgba(10, 132, 255, 0.15);
  --accent-100: rgba(10, 132, 255, 0.26);
  --accent-200: rgba(10, 132, 255, 0.40);
  --accent-300: #5ea8ff;
  --accent-500: #0a84ff;
  --accent-600: #3b9eff;
  --accent-700: #6db2ff;
  --accent-glow: 10, 132, 255;

  /* 深色下琥珀/状态色提亮 */
  --yellow-50: rgba(255, 214, 10, 0.13);
  --yellow-100: rgba(255, 214, 10, 0.22);
  --yellow-200: rgba(255, 214, 10, 0.34);
  --yellow-300: #ffd60a;
  --yellow-400: #ffd60a;
  --yellow-500: #ffe234;
  --yellow-glow: 255, 214, 10;
  --success: #30d158;
  --success-glow: 48, 209, 88;
  --warning: #ff9f0a;
  --warning-glow: 255, 159, 10;
  --danger: #ff453a;
  --danger-glow: 255, 69, 58;
  --info: #0a84ff;
  --info-glow: 10, 132, 255;

  /* 表面与边框 */
  --bg-canvas: #161618;
  --bg-paper: #1e1e1e;
  --bg-paper-2: #28282a;
  --bg-tinted: #232325;
  --border-subtle: rgba(255, 255, 255, 0.07);
  --border-default: rgba(255, 255, 255, 0.13);
  --border-strong: rgba(255, 255, 255, 0.24);
  --border-table: #48484a;

  /* 阴影加深 */
  --shadow-xs: 0 1px 2px rgba(0,0,0,0.4);
  --shadow-sm: 0 2px 4px rgba(0,0,0,0.4), 0 1px 2px rgba(0,0,0,0.35);
  --shadow-md: 0 4px 12px rgba(0,0,0,0.5), 0 1px 3px rgba(0,0,0,0.4);
  --shadow-lg: 0 12px 32px rgba(0,0,0,0.55), 0 4px 8px rgba(0,0,0,0.4);

  --brand-softer: rgba(10, 132, 255, 0.10);

  /* 20260928n 补丁新增语义变量（浅色对应值见 :root） */
  --bg-hover: #323234;
  --bg-panel: #252527;
  --bg-panel-2: #2a2a2c;
  --border-hairline: #48484a;
  --border-line: #3a3a3c;
  --col-name-bg: #2a2a2c;
  /* 20260928n 补丁3：卡片/单元格/白底按钮 & 浅红 hover（原 :root 别名指向 --bg-paper） */
  --bg-card: #28282a;
  --danger-soft: rgba(255, 69, 58, 0.16);
  --danger-line: #7a3531;
  /* grid-full 吸顶/吸底列底色（浅色 #eef1f6 系 → 深色表面） */
  --col-dept-bg: #2c2c2e;
  --col-metric-bg: #2a2a2c;
  --col-total-bg: rgba(255, 214, 10, 0.10);
  /* 结果/历史表格斑马纹（浅色 #ffffff/#f8f9fc → 深色两档）与周末列（浅蓝 #eaf1fe → 深色蓝调） */
  --row-a: #1e1e1e;
  --row-b: #28282a;
  --col-rest-bg: rgba(10, 132, 255, 0.12);
  /* 20261013e（用户反馈）：法定节假日列底色此前**只覆盖了 --col-rest-bg**，
     漏了 --col-holiday-bg ⇒ 深色模式下节假日日期单元格仍是浅色模式的浅黄
     （#fdf3d4）。此处补深色琥珀半透明（同 --warning-soft 色系），
     与周末列的深色蓝调保持同一"深底 + 同色系低透明"口径。 */
  --col-holiday-bg: rgba(255, 159, 10, 0.14);
  /* 徽章/横幅浅色软底 → 深色同色系半透明（20260928n 补丁4） */
  --success-soft: rgba(48, 209, 88, 0.14);
  --info-soft: rgba(10, 132, 255, 0.14);
  --warning-soft: rgba(255, 159, 10, 0.14);

  /* 20260928o 补丁5：旧组件 fallback 边线 --line 反转（tpl-card/fmt-remember 等描边） */
  --line: #3a3a3c;
}

/* 原生控件（多选框/单选/下拉/滚动条/输入框）交给系统深色渲染 */
html.dark { color-scheme: dark; }

html.dark body { background: var(--bg-paper); color: var(--ink-700); }

/* 次级按钮：macOS 深灰底浅字（绿/红/蓝主按钮/蓝字按钮保留彩底彩字。
   20260928o：排除 .btn-primary（弹框保存/确定、导入考勤文件、我要定制 → 保持系统蓝）
   与 .btn-linkblue（部门管理/配置表格格式/节假日补班等入口 → 深底蓝字，全站一致） */
/* 20261035f：再排除 .btn-cancel（弹框取消＝白色）与 .modal-close（右上角关闭＝浅红），
   二者有各自的主题规则，不能被这条深灰兜底盖掉（该选择器 :not 堆叠后特异度很高）。 */
/* 20261039f：再排除 .de-jump-btn（明细/汇总配置页右上角跨页跳转）—— 它走 .btn-blue
   的深色变体（深蓝底浅蓝字），不能被这条深灰兜底盖成普通次级按钮 */
html.dark .btn:not(.btn-accent):not(.btn-green):not(.btn-danger):not(.btn-primary):not(.btn-linkblue):not(.btn-cancel):not(.modal-close):not(.de-jump-btn):not(:disabled) {
  background: var(--bg-paper-2); border-color: var(--border-strong); color: var(--ink-800);
}
html.dark .btn:not(.btn-accent):not(.btn-green):not(.btn-danger):not(.btn-primary):not(.btn-linkblue):not(.btn-cancel):not(.modal-close):not(.de-jump-btn):not(:disabled):hover {
  background: var(--ink-100); border-color: var(--ink-300); color: var(--ink-900);
}
html.dark table.grid td .btn:not(:disabled) { background: transparent; }
html.dark table.grid td .btn:not(:disabled):hover { background: var(--accent-100); color: var(--accent-300); }

/* 计算考勤项目卡片 hover：比卡片底略亮一档，反馈柔和（用户要求浅一点） */
html.dark .list-item:hover { background: #2e2e30; }

/* 侧栏底走 --bg-panel（深色块已重定义），此处无需额外覆盖 */
html.dark .sidebar-brand .logo { background: transparent; }

/* 20260928n 补丁3：白底已全部变量化（--bg-card 等），以下旧覆盖仅保留仍有差异的：
   - switch 旋钮深色保持白（macOS 惯例）
   - 覆盖层内部元素（ck-row-head/ck-close/mc-* 等）源已是 var(--bg-card)，自动深色 */
html.dark .switch .slider::before { background: #f5f5f7; }

/* 订阅页卡片（源非白底变量） */
html.dark .sub-plan-card, html.dark .sub-pay-card,
html.dark .sub-method.sub-method-pill, html.dark .sub-pay-refresh { background: var(--bg-paper-2); }
/* 套餐类型卡深色兜底（20261011d） */
html.dark .sub-tier-card { background: var(--bg-paper-2); border-color: var(--ink-700, #2c2c34); }
html.dark .sub-tier-card.selected { border-color: var(--accent-500, #4a6cf7); }
html.dark .sub-tier-card.sub-tier-pro { border-color: var(--accent-700, #35508f); }
/* 20261014c：锁定卡（当前版本）深色兜底 */
html.dark .sub-tier-card.sub-tier-locked { background: var(--bg-paper-2); border-color: var(--ink-700, #2c2c34); }
html.dark .sub-tier-cur { background: var(--ink-700, #2c2c34); border-color: var(--ink-700, #2c2c34);
  color: var(--ink-300); }
html.dark .lc-empno { background: var(--ink-700, #2c2c34); color: var(--ink-300); }
html.dark .tier-upgrade-icon { background: rgba(74,108,247,.15); }

/* 数据表格页（detail-view de-*）表格线用 --border-table */
html.dark .de-table th, html.dark .de-table td { border-right-color: var(--border-table); border-bottom-color: var(--border-table); }

/* 配置考勤汇总/明细（de-overlay 全屏子页）：页面底 + hover 蓝调 + 周末格（20260928n 补丁4） */
html.dark .de-overlay {
  background: var(--bg-paper);
  --de-hot: rgba(10, 132, 255, 0.16);
  --de-hot-line: rgba(10, 132, 255, 0.42);
}
html.dark .de-table .de-day-rest { background: rgba(255, 69, 58, 0.10); }

/* 表头深色提亮一档（20260928r）：--bg-paper-2(#28282a) 与斑马纹原 row-a 同色，
   滚动时表头与内容融为一体（视觉"透底"）——固定 #2c2c2e 区分 */
html.dark table.grid-full thead th, html.dark table.grid thead th { background: #2c2c2e; }

/* 结果/历史表格状态格深色适配（20260928n 补丁4）：同色系暗底 + 提亮文字；
   20260928r：color 加 !important —— 预览页（preview-grid）浅色规则 color 带 !important，
   原深色文字被压住，出现深底深字 */
html.dark table.grid-full td.c-late { background: rgba(124, 58, 237, 0.28) !important; color: #c4b5fd !important; }
html.dark table.grid-full td.c-early { background: rgba(10, 132, 255, 0.22) !important; color: #8ecbff !important; }
html.dark table.grid-full td.c-missing { background: rgba(255, 69, 58, 0.22) !important; color: #ff8a80 !important; }
html.dark table.grid-full td.c-absent { background: rgba(255, 214, 10, 0.16) !important; color: #ffd60a !important; }
html.dark table.grid-full td.c-rest-mark { color: #8e939c !important; }
html.dark .lg-dot.c-late { background: rgba(124, 58, 237, 0.55); }
html.dark .lg-dot.c-early { background: rgba(10, 132, 255, 0.45); }
html.dark .lg-dot.c-missing { background: rgba(255, 69, 58, 0.55); }
html.dark .lg-dot.c-absent { background: rgba(255, 214, 10, 0.40); }

/* 浅蓝动作按钮 btn-blue → 深色同色系（20260928n 补丁4） */
html.dark .btn-blue { background: rgba(10, 132, 255, 0.18); border-color: rgba(10, 132, 255, 0.42); color: #8ecbff; }
html.dark .btn-blue:not(:disabled):hover { background: rgba(10, 132, 255, 0.28); border-color: rgba(10, 132, 255, 0.55); color: #a8d4ff; }

/* 提示横幅边框提亮 */
html.dark .banner-warn { border-color: rgba(255, 159, 10, 0.35); }
html.dark .banner-ok { border-color: rgba(48, 209, 88, 0.35); }

/* 下拉选择框箭头深色适配（20260928r）：黑箭头 → 灰白箭头（覆盖全局 select 与
   .holiday-cell/.lt-days-unit/#inv-status 三处自定义箭头，源顺序后置 + 特异性更高） */
html.dark select,
html.dark .holiday-cell select,
html.dark #inv-status {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 10 10'><path d='M1 3h8L5 8z' fill='%23aeaeb2'/></svg>");
}

/* 滚动条（color-scheme 已托管，此处保留下凸质感） */
html.dark ::-webkit-scrollbar-thumb { background: var(--ink-200); }
html.dark ::-webkit-scrollbar-thumb:hover { background: var(--ink-300); }

/* 弹窗遮罩加深 */
html.dark .modal { background: rgba(0, 0, 0, 0.55); }

/* 头像/占位浅底 → 深底 */
html.dark .avatar-ph, html.dark .empty-state { color: var(--ink-400); }

/* ============================================================
   深色补漏第五轮（20260928o）
   ============================================================ */
/* 图表卡头统计行（加班构成/请假类型分布/出勤率分布的灰底合计条） */
html.dark .astat-head-stat { background: var(--bg-panel-2); border-color: var(--border-hairline); }

/* 考勤统计页「考勤组未设置上下班时间」常驻红条 */
html.dark .group-time-warn { background: rgba(255, 69, 58, 0.12); border-color: rgba(255, 69, 58, 0.38); color: #ff8a80; }
html.dark .group-time-warn u { color: #ff6961; }

/* 格式说明弹窗缩略图（浅色粉彩渐变 → 深色同色系半透明渐变） */
html.dark .fmt-thumb { background: linear-gradient(135deg, rgba(10, 132, 255, 0.14), rgba(10, 132, 255, 0.30)); }
html.dark .fmt-card:nth-child(2) .fmt-thumb { background: linear-gradient(135deg, rgba(48, 209, 88, 0.12), rgba(48, 209, 88, 0.26)); }
html.dark .fmt-card:nth-child(3) .fmt-thumb { background: linear-gradient(135deg, rgba(255, 214, 10, 0.10), rgba(255, 159, 10, 0.24)); color: #ffd60a; }
html.dark .fmt-card:nth-child(4) .fmt-thumb { background: linear-gradient(135deg, rgba(255, 69, 58, 0.10), rgba(255, 69, 58, 0.24)); }

/* 导入格式选择弹窗（tpl-*）：描边走 --line（深色块已反转），缩略图底/备注文字补齐 */
html.dark .tpl-thumb { background: var(--bg-panel); }
html.dark .tpl-req { color: var(--ink-500); }

/* 订阅页：支付卡片分隔线 / 支付方式条 / 选中态 / 刷新按钮 / 转圈 */
html.dark .sub-pay-card-head, html.dark .sub-methods { border-bottom-color: var(--border-hairline); }
html.dark .sub-methods { background: var(--bg-tinted); }
html.dark .sub-method.sub-method-pill.active {
  border-color: var(--accent-500); background: var(--accent-50); color: var(--accent-300);
  box-shadow: 0 2px 10px rgba(10, 132, 255, 0.22);
}
html.dark .sub-pay-refresh:hover { color: var(--accent-300); border-color: var(--accent-300); background: var(--accent-50); }
html.dark .sub-spin { border-color: var(--border-hairline); border-top-color: var(--accent-500); }

/* 侧栏「问题反馈」红点角标外圈 = 侧栏底色 */
html.dark .side-dot { box-shadow: 0 0 0 2px var(--bg-panel); }

/* 人工结果比对摘要不一致数字（浅色 #2563eb 深色下偏暗 → 提亮） */
html.dark #mc-modal .mc-diff-num { color: #7cb8ff; }

/* 异常检查模式入口按钮（20260928p）：五色渐变整体提亮适配深底（边框与文字共用 --ck-grad）
   20260928x：顺序同步改为 红→黄→绿→蓝→紫 从左向右水平填充 */
html.dark .ck-btn {
  --ck-grad: linear-gradient(90deg, #ff453a 0%, #ffd60a 25%, #30d158 50%, #5ea8ff 75%, #a78bfa 100%);
}
html.dark .ck-btn:hover { box-shadow: 0 2px 10px rgba(0, 0, 0, .55); }

/* ==================== 渠道结算（20261007j） ==================== */
/* 账户余额卡：主余额 + 提现中醒目条 + 明细四格
   提现中的金额**已从余额扣除**（不能再提），所以必须醒目告知用户 */
.ag-balance {
  display: flex; flex-wrap: wrap; gap: 12px; align-items: stretch;
  margin-bottom: 14px;
}
.ag-bal-main {
  flex: 1 1 380px; min-width: 300px;
  background: var(--accent-50); border: 1px solid var(--accent-200);
  border-radius: var(--radius-md); padding: 14px 18px;
  /* ⚠️20261007l 改为「左信息 + 右侧按钮」两栏，按钮并排贴在卡片右边 */
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
}
/* 窄屏时按钮换到下一行，仍靠右对齐（不居中，避免看着像标题按钮） */
@media (max-width: 560px) {
  .ag-bal-main { flex-wrap: wrap; }
  .ag-bal-acts { margin-left: auto; }
}
.ag-bal-info { min-width: 0; }
.ag-bal-acts { display: flex; align-items: center; gap: 8px; flex: 0 0 auto; }
.ag-bal-acts .btn { white-space: nowrap; }
.ag-bal-label { font-size: 13px; color: var(--ink-500); }
.ag-bal-val {
  font-size: 30px; font-weight: 600; color: var(--ink-900);
  letter-spacing: -0.02em; line-height: 1.2; margin: 2px 0 2px;
  font-variant-numeric: tabular-nums;
}
.ag-bal-tip { font-size: 12px; color: var(--ink-400); }
/* 提现中：琥珀底 + 左侧粗条，视觉上「被占用」 */
.ag-bal-wd {
  flex: 1 1 260px; min-width: 240px;
  background: var(--warning-soft); border: 1px solid var(--yellow-300);
  border-left: 4px solid var(--yellow-500);
  border-radius: var(--radius-md); padding: 14px 18px;
  display: flex; flex-direction: column; justify-content: center;
  font-size: 13px; color: var(--ink-600);
}
.ag-bal-wd b {
  font-size: 22px; font-weight: 600; color: var(--yellow-500);
  font-variant-numeric: tabular-nums; margin-right: 4px;
}
.ag-bal-items { flex: 2 1 380px; display: flex; gap: 10px; flex-wrap: wrap; }
.ag-bal-item {
  flex: 1 1 120px; min-width: 110px;
  background: var(--bg-paper-2); border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md); padding: 12px 14px;
}
.ag-bal-item span { display: block; font-size: 12px; color: var(--ink-400); }
.ag-bal-item b {
  font-size: 17px; color: var(--ink-900); font-variant-numeric: tabular-nums;
}
.ag-bal-item b.muted { color: var(--ink-400); }
/* 三个 tab 的内容面板 */
.ag-tab-pane { min-width: 0; }
/* 表格数字列右对齐 + 等宽（金额列必须能上下对齐比较） */
.grid td.num, .grid th.num { text-align: right; font-variant-numeric: tabular-nums; }
.grid td.nowrap, .grid th.nowrap { white-space: nowrap; }
/* ⚠️20261007l 列宽自适应表：列一律用 min-width（不是 width），表格给整体 min-width。
   固定 width + table.grid 的 width:100% 会让列既不随容器伸缩、也不随内容伸缩
   （富余时按比例拉伸、不足时挤成一团），最后一列没设宽度还会独吞剩余空间。
   min-width 语义 = 「至少这么宽，还能再长」——正好是自适应。 */
table.grid-fit { width: 100%; }
/* 深色：余额卡底色用反转后的中性色（accent-50 已是半透明 rgba，可直接用） */
html.dark .ag-bal-main { border-color: var(--accent-300); }
html.dark .ag-bal-wd { border-color: var(--yellow-500); border-left-color: var(--yellow-400); }

/* ============================================================
   加班比对规则弹框 + 加班单元格比对说明（20261010d）
   ============================================================ */
/* 弹框宽度 20261017u：560 → 620px（部门表格 5 列 + 汇总提示需要更多横向空间，
   同时仍远小于桌面视口的弹框上限，不影响其它场景） */
/* 🔴 20261017u：弹框加**最大高度 + 内容滚动** —— 部门加多后（每行约 34px）
   原实现弹框会一直往下长，超出视口导致底部行与「＋ 添加部门」「确定」看不到。
   口径与项目既有弹框（#leave-import-format-modal / #att-import-format-modal）一致：
   box 用 flex column + max-height，head/actions 固定不滚，**只有 body 滚动**。 */
.modal-box.ot-rule-box {
  max-width: 620px;
  display: flex; flex-direction: column;
  max-height: calc(100vh - 48px);
}
.modal-box.ot-rule-box .modal-head { flex-shrink: 0; }
.modal-box.ot-rule-box .modal-body {
  flex: 1 1 auto; min-height: 0; overflow-y: auto; padding-right: 6px;
}
.modal-box.ot-rule-box .modal-actions { flex-shrink: 0; }
.ot-rule-q {
  font-size: 15px; color: var(--ink-700); margin-bottom: 12px; line-height: 1.6;
}
/* 示例区：浅底卡片，突出「申请结果 / 计算结果 / 比对后结果」三处数值颜色 */
.ot-rule-demo {
  background: var(--bg-tinted); border: 1px solid var(--ink-150);
  border-radius: var(--radius-md); padding: 14px 16px; margin-bottom: 14px;
}
.ot-rule-demo-line {
  font-size: 16px; line-height: 1.9; color: var(--ink-600);
}
.ot-rule-demo-line b {
  font-size: 19px; font-weight: 800; letter-spacing: .2px;
  font-variant-numeric: tabular-nums; padding: 0 1px;
}
/* 三处数值用三种颜色区分（深色主题下由 html.dark 覆盖为提亮版） */
.ot-rule-demo .otv-apply { color: var(--accent-600); }
.ot-rule-demo .otv-calc  { color: var(--warning); }
.ot-rule-demo .otv-final { color: var(--success); }
.ot-rule-demo-note { font-size: 12.5px; color: var(--ink-400); margin-top: 6px; }

/* 四个选项：整行可点的单选卡片（默认不选中） */
.ot-rule-opts { display: flex; flex-direction: column; gap: 8px; }
.ot-rule-opt {
  display: flex; align-items: center; gap: 10px;
  padding: 11px 13px; cursor: pointer;
  border: 1px solid var(--ink-150); border-radius: var(--radius-md);
  background: var(--bg-paper); transition: border-color .15s, background .15s;
}
.ot-rule-opt:hover { border-color: var(--accent-300); background: var(--accent-50); }
.ot-rule-opt input[type="radio"] {
  width: 17px; height: 17px; margin: 0; flex-shrink: 0; accent-color: var(--accent-500);
  cursor: pointer;
}
.ot-rule-opt-txt { font-size: 14.5px; color: var(--ink-700); line-height: 1.5; }
.ot-rule-opt.active {
  border-color: var(--accent-500); background: var(--accent-50);
}
.ot-rule-opt.active .ot-rule-opt-txt { color: var(--accent-700); font-weight: 600; }

/* 加班单元格弹框里的「计算结果 / 申请结果 / 比对后结果」说明条 */
/* 20261020b（用户定版）：说明条与下方内容留 10px 间距 */
.cell-ot-info {
  margin-top: 12px; margin-bottom: 10px; padding: 11px 13px;
  background: var(--bg-tinted); border: 1px solid var(--ink-150);
  border-radius: var(--radius-md); font-size: 14px; color: var(--ink-600);
  line-height: 1.85;
}
.cell-ot-info b { font-weight: 700; font-variant-numeric: tabular-nums; }
.cell-ot-info b.otv-apply { color: var(--accent-600); }
.cell-ot-info b.otv-calc  { color: var(--warning); }
.cell-ot-info b.otv-final { color: var(--success); }
.cell-ot-info .cell-ot-tag {
  display: inline-block; padding: 1px 7px; margin-right: 6px;
  border-radius: 999px; font-size: 12px;
  background: var(--accent-50); color: var(--accent-700);
}
/* ⚠️ 深色主题下三色统一提亮（--accent-600/--warning/--success 已在 html.dark 提亮，
   但浅色卡片底色在深色下需换成反转中性色，避免亮底黑字） */
html.dark .ot-rule-demo,
html.dark .cell-ot-info { background: var(--ink-50); border-color: var(--ink-150); }
html.dark .ot-rule-demo-line { color: var(--ink-500); }
html.dark .ot-rule-demo-note { color: var(--ink-400); }
html.dark .ot-rule-opt { background: var(--bg-paper); border-color: var(--ink-150); }
html.dark .ot-rule-opt:hover,
html.dark .ot-rule-opt.active { background: var(--accent-50); border-color: var(--accent-300); }
html.dark .ot-rule-opt-txt { color: var(--ink-800); }
html.dark .ot-rule-opt.active .ot-rule-opt-txt { color: var(--accent-700); }
html.dark .cell-ot-info .cell-ot-tag { background: var(--accent-50); color: var(--accent-700); }
/* 20261010e：加班比对规则弹框只留一个「确定」，居中显示（用户口径：取消按钮去掉、
   确定按钮居中）。默认 .modal-actions 是 flex-end ⇒ 此处覆盖为 center。 */
.modal-box.ot-rule-box .modal-actions.ot-rule-actions { justify-content: center; }
/* 参与比对的人员范围（20261017t）：默认「导入的全部人员」（不用的人不看不管）；
   选「仅指定部门」才展开部门表格 —— 每行三勾「工作日/休息日/法定节假日」。
   🔴 每行三勾后紧跟文字「对比」（用户口径：勾选框旁要有「对比」字样才看得懂）。 */
.ot-scope-sec { margin-top: 18px; border-top: 1px solid var(--border-default); padding-top: 14px; }
.ot-scope-hd { font-size: 14px; font-weight: 600; color: var(--ink-800); margin-bottom: 8px; }
.ot-scope-opt { display: flex; align-items: center; gap: 7px; padding: 5px 0;
  font-size: 14px; color: var(--ink-800); cursor: pointer; }
.ot-scope-opt input[type="radio"] { margin: 0; cursor: pointer; }
.ot-scope-hint { font-size: 12.5px; color: var(--ink-400); }
.ot-scope-panel { margin-top: 10px; border: 1px solid var(--border-default);
  border-radius: var(--radius-md); padding: 10px 12px; background: var(--bg-paper-2); }
/* 🔴 20261017u：部门表格列宽必须**收在弹框内**（弹框 max-width 560px）。原
   `minmax(180px,1fr) 92 92 112 40` + gap = 约 550px，再叠加面板 padding 与弹框
   padding 后撑破右边界（删除按钮被挤到弹框外，用户截图反馈）。
   改小后三列并 60px + 删除按钮 28px，总宽 ~420px，留足余量。
   ⚠️ 用 minmax(0,1fr) 而非固定最小宽：窄屏时部门名可省略，不撑破容器。 */
.ot-scope-tbl-hd, .ot-scope-row { display: grid;
  grid-template-columns: minmax(0, 1fr) 62px 62px 78px 26px;
  gap: 6px; align-items: center; }
.ot-scope-tbl-hd { font-size: 12px; color: var(--ink-500); padding: 0 2px 6px;
  border-bottom: 1px solid var(--border-default); margin-bottom: 6px;
  white-space: nowrap; }
.ot-scope-tbl-hd span { text-align: center; overflow: hidden; }
.ot-scope-tbl-hd span:first-child { text-align: left; }
.ot-scope-row { padding: 5px 2px; }
.ot-scope-row .ot-scope-dept { width: 100%; min-width: 0; padding: 5px 6px;
  font-size: 13px; text-overflow: ellipsis; }
.ot-scope-ck { display: flex; align-items: center; justify-content: center; gap: 4px;
  margin: 0; font-size: 12.5px; color: var(--ink-600); cursor: pointer;
  user-select: none; white-space: nowrap; }
.ot-scope-ck input[type="checkbox"] { margin: 0; cursor: pointer; flex: none; }
.ot-scope-del { justify-self: center; padding: 2px 6px; font-size: 12.5px; line-height: 1.2; }
.ot-scope-empty { font-size: 13px; color: var(--ink-400); padding: 8px 2px; }
.ot-scope-foot { display: flex; align-items: center; gap: 12px; margin-top: 8px;
  flex-wrap: wrap; }
.ot-scope-sum { font-size: 12.5px; color: var(--ink-500); }
html.dark .ot-scope-panel { background: var(--ink-50); border-color: var(--ink-150); }
html.dark .ot-scope-hd, html.dark .ot-scope-opt { color: var(--ink-800); }
html.dark .ot-scope-ck { color: var(--ink-500); }

/* ============================================================================
   全局加载动画（20261011v）—— 导入考勤文件解析 / 打开项目计算 / 保存规则后重算
   用法：showLoading(title, hint) → hideLoading()（见 app.js）
   设计口径：
     · 延迟 200ms 才显示（由 JS 控制），小项目秒开时用户看不到闪烁；
     · 遮罩 1500 —— 高于全屏子页面遮罩(.de-overlay 1000 / .de-pop 1100)，
       低于全局提示浮层 #msg(2000)，所以加载中弹提示依然可见；
     · 转圈复用已有的 @keyframes btn-spin。
   ============================================================================ */
.load-mask {
  position: fixed; inset: 0; z-index: 1500;
  display: flex; align-items: center; justify-content: center;
  background: rgba(245, 246, 249, .72);
  -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
}
html.dark .load-mask { background: rgba(12, 14, 18, .68); }
.load-card {
  display: flex; flex-direction: column; align-items: center;
  min-width: 250px; max-width: 340px;
  padding: 26px 30px 20px;
  background: var(--bg-card);
  border: 1px solid var(--border-default);
  border-radius: 14px;
  box-shadow: 0 12px 40px rgba(16, 24, 40, .16);
}
html.dark .load-card { box-shadow: 0 12px 40px rgba(0, 0, 0, .5); }
.load-spinner {
  width: 34px; height: 34px; border-radius: 50%;
  border: 3px solid var(--accent-100);
  border-top-color: var(--accent-500);
  animation: btn-spin .8s linear infinite;
}
.load-title { margin-top: 15px; font-size: 15px; font-weight: 600; color: var(--ink-900); }
.load-hint {
  margin-top: 7px; font-size: 12.5px; line-height: 1.55; text-align: center;
  color: var(--ink-400);
}

/* ---------- 班次选择弹框（20261012f）：结果页「班次」格点击选择当日班次 ---------- */
.shift-pick-box { max-width: 470px; }
.shift-pick-list { display: flex; flex-direction: column; gap: 8px; margin-top: 12px; }
.shift-opt {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 10px 14px; border: 1px solid var(--line, #e2e8f0); border-radius: 10px;
  background: var(--bg-paper, #fff); cursor: pointer; text-align: left;
  transition: border-color .15s, background .15s;
}
.shift-opt:hover, .shift-opt.cur { border-color: var(--accent-500); background: var(--accent-50); }
.shift-opt .so-name { font-weight: 600; font-size: 14px; color: var(--ink-700); min-width: 3.5em; }
.shift-opt .so-time { font-size: 12.5px; color: var(--ink-400); flex: 1; }
.shift-opt .so-badge {
  font-size: 11px; color: var(--accent-600); border: 1px solid var(--accent-300);
  border-radius: 999px; padding: 1px 8px; white-space: nowrap;
}
html.dark .shift-opt { background: var(--bg-panel-2); }
html.dark .shift-opt:hover, html.dark .shift-opt.cur { background: rgba(var(--accent-glow), .14); }
html.dark .shift-opt .so-name { color: var(--ink-100); }
html.dark .shift-opt .so-time { color: var(--ink-300); }
/* 结果页「班次」行：可点击格（与原始打卡行同款 hover 描边） */
table.grid-full td.c-shift { cursor: pointer; }
table.grid-full td.c-shift:hover { outline: 2px solid var(--accent-500); outline-offset: -2px; background: var(--accent-50) !important; }
/* 结果页「请假」行：点击直接修改请假数据（20261017e，与班次行同款交互提示） */
table.grid-full td.c-leave-edit { cursor: pointer; }
table.grid-full td.c-leave-edit:hover { outline: 2px solid var(--accent-500); outline-offset: -2px; background: var(--accent-50) !important; }

/* ============================================================
   上手向导（20261015a）
   —— 首次登录引导：侧栏入口 + 居中清单 + 「带我做」定位脉冲。
   颜色全部走主题变量（浅色 / 深色同一套规则，不写死背景色）。
   ============================================================ */
/* 侧栏入口右侧的进度小字（位置复用 .side-note）；7/7 时转绿 */
#ob-badge.ob-badge-done { color: var(--success); font-weight: 600; }

.ob-mask {
  position: fixed; inset: 0; z-index: 1700;
  background: rgba(15, 15, 15, 0.45);
  display: flex; align-items: center; justify-content: center;
  padding: 24px;
}
.ob-box {
  background: var(--bg-paper); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  width: 100%; max-width: 700px; max-height: calc(100vh - 48px);
  display: flex; flex-direction: column;
  padding: 22px 24px 18px;
}
.ob-head { display: flex; align-items: flex-start; gap: 12px; }
.ob-head-l { flex: 1 1 auto; min-width: 0; }
.ob-title { font-size: 20px; font-weight: 600; color: var(--ink-900); }
.ob-sub { margin-top: 4px; font-size: 13.5px; color: var(--ink-400); }
.ob-close {
  flex: 0 0 auto; width: 30px; height: 30px; line-height: 1;
  border: 1px solid transparent; background: transparent;
  color: var(--ink-400); border-radius: var(--radius-sm); font-size: 15px;
}
.ob-close:hover { background: var(--bg-paper-2); color: var(--ink-800); }
.ob-prog {
  height: 4px; margin: 14px 0 4px; border-radius: 999px;
  background: var(--bg-paper-2); overflow: hidden;
}
.ob-prog > i {
  display: block; height: 100%; width: 0; background: var(--accent-500);
  border-radius: 999px; transition: width .3s var(--ease-out-quart);
}
.ob-list { flex: 1 1 auto; overflow-y: auto; margin: 8px -6px 0; padding: 0 6px; }
.ob-step {
  display: flex; align-items: center; gap: 12px;
  padding: 12px; margin-bottom: 8px;
  border: 1px solid var(--border-subtle); border-radius: var(--radius-md);
  /* 卡片底用 --bg-paper-2（比弹窗底深/浅一档）：浅色下是浅灰、深色下是浅黑，
     两种主题都能和弹窗底分开，不会糊成一片 */
  background: var(--bg-paper-2);
}
.ob-step.ob-done { border-color: rgba(var(--success-glow), 0.34); }
.ob-step.ob-skipped { opacity: .68; }
.ob-idx {
  flex: 0 0 auto; width: 26px; height: 26px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 13px; font-weight: 600;
  background: var(--bg-paper); color: var(--ink-500);
}
.ob-step.ob-done .ob-idx { background: var(--success); color: #ffffff; }
.ob-main { flex: 1 1 auto; min-width: 0; }
.ob-step-t { font-size: 15px; font-weight: 600; color: var(--ink-900); }
.ob-step-d { margin-top: 2px; font-size: 13px; color: var(--ink-400); line-height: 1.5; }
.ob-acts { flex: 0 0 auto; display: flex; align-items: center; gap: 6px; }
.ob-act {
  font-size: 13px; padding: 5px 11px; border-radius: var(--radius-sm);
  /* 透明底 + 描边：卡片底在浅/深两套主题里都比弹窗底深一档，
     按钮若再给实底会糊在卡上；透明描边在两种主题下都清晰 */
  border: 1px solid var(--border-default); background: transparent;
  color: var(--ink-600); cursor: pointer; text-decoration: none; white-space: nowrap;
  font-family: inherit; line-height: 1.4;
}
.ob-act-main { border-color: var(--accent-500); color: var(--accent-600); }
.ob-act-main:hover { background: var(--accent-50); }
/* 20261015b：「手册详解」入口去掉后对应链接样式已无载体 → 样式一并删掉（不留死类名）。
   操作区只剩「跳过 | 主操作」两个按钮，DOM 顺序即视觉顺序（跳过在主按钮左侧）。 */
.ob-act-ghost { border-color: transparent; background: transparent; color: var(--ink-400); }
.ob-act-ghost:hover { color: var(--ink-700); }
.ob-foot {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--border-subtle);
}
.ob-nomore { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; color: var(--ink-400); cursor: pointer; }
.ob-nomore input { width: auto; }

/* 「带我做」高亮（20261015c 重做 / 20261015d 修裁切）：**常驻**直到用户点
   「我知道了/下一步」或目标按钮。用户口径：原来的蓝色脉冲闪两下不够明显、
   且自动消失猜不准用户看完没有 → 改红色系（红色透明填充 + 红描边 + 轻呼吸），
   不依赖主题色变量（红色在深浅两主题下都可读）。
   🔴 20261015d：红框**不再画在目标元素自身** —— outline/box-shadow 会被
   overflow:hidden 的容器（侧栏、卡片、表格包裹层）裁掉。改为 JS 建一个
   fixed 覆盖层 .ob-ring（body 直属、pointer-events:none、随目标 rect 移动），
   任何容器都裁不到；红色填充画在覆盖层上（半透明叠在按钮之上，白字仍可读），
   也不会踩 15c「background-color 覆盖实底按钮」的坑。
   目标元素上的 .ob-pulse 只留作「当前引导目标」识别标记（E2E 依赖），无视觉。 */
.ob-pulse { scroll-margin: 84px; }

.ob-ring {
  position: fixed;
  z-index: 1699;                    /* 高于页面内容、低于 .ob-tip(1701) */
  pointer-events: none;             /* 点击穿透：用户可直接点目标按钮 */
  border: 2px solid #ef4444;
  border-radius: 8px;
  background: rgba(239, 68, 68, 0.10);
  box-shadow: 0 0 0 6px rgba(239, 68, 68, 0.12);
  animation: ob-ring-breath 1.6s ease-in-out infinite;
}
@keyframes ob-ring-breath {
  0%, 100% { box-shadow: 0 0 0 5px rgba(239, 68, 68, 0.10); }
  50% { box-shadow: 0 0 0 9px rgba(239, 68, 68, 0.22); }
}

/* 「带我做」说明卡（20261015c 新增）：贴着高亮目标下方（放不下则上方）浮出，
   说明文字 + 「我知道了 / 下一步」按钮。z-index 1701 高于引导清单弹窗(1700)。 */
.ob-tip {
  position: fixed; z-index: 1701;
  max-width: 360px;
  background: var(--bg-paper);
  border: 1px solid var(--border-default);
  border-left: 3px solid #ef4444;
  border-radius: 8px;
  box-shadow: 0 8px 28px rgba(0, 0, 0, 0.18);
  padding: 12px 14px;
}
.ob-tip-text { font-size: 13.5px; line-height: 1.65; color: var(--ink-700); }
.ob-tip-acts { display: flex; justify-content: flex-end; margin-top: 9px; }
.ob-tip-btn {
  border: none; cursor: pointer; font-family: inherit;
  background: #ef4444; color: #fff;
  font-size: 13px; padding: 6px 16px; border-radius: 6px;
}
.ob-tip-btn:hover { background: #dc2626; }
@media (max-width: 620px) {
  .ob-tip { max-width: min(360px, calc(100vw - 20px)); }
}
@media (max-width: 620px) {
  .ob-step { flex-wrap: wrap; }
  .ob-acts { width: 100%; justify-content: flex-end; }
}

/* ===== 显示格式：竖向（20261016a）=====
   横向 = 日期占列、指标占行（原口径，样式见上）；竖向 = 日期占行、指标占列。
   两种版式共用同一份单元格渲染（app.js metricDayCell），这里只调排布相关的
   宽度 / 吸附 / 行高，互不影响。 */
/* 竖版指标列（20261016c 用户口径）：84 → 76px，与横向指标项列同口径
   （够内置最长指标名折 2 行显示完整；原始打卡列另有 JS 动态宽，不受此限） */
table.grid-full.grid-v th.col-day, table.grid-full.grid-v td.col-day {
  width: 76px; min-width: 76px; max-width: 76px;
}
/* 原始打卡记录列（20261016b 用户口径）：卡片横向排开、单行不换行 → 行高只占一行打卡
   时间的高度；列宽由 JS（vPunchWidth）按**当前页最宽的打卡单元格**写成内联 style，
   这里只给无数据时的兜底宽度（20261016a 的 132px 固定宽 + 折叠已取消）。 */
table.grid-full.grid-v th.c-rawpunch, table.grid-full.grid-v td.c-rawpunch {
  width: 96px; min-width: 96px;
}
table.grid-full.grid-v td.c-rawpunch-v {
  white-space: nowrap; overflow: visible; max-height: none; padding: 4px 6px;
}
/* 日期列：吸附在信息列右侧（left 由 JS 按信息列勾选态动态给），行方向即日期。
   20261016d：数据格**不填灰**（原 --col-metric-bg）→ 跟随斑马纹行底色；
   ⚠️ 必须有实底（sticky 列），故用 --row-a/--row-b 而不是 transparent；
   休息日 / 节假日仍由下方 `td.col-date.rest` / `.holiday`（带 !important）覆盖。 */
table.grid-full.grid-v th.col-date, table.grid-full.grid-v td.col-date {
  width: 88px; min-width: 88px; max-width: 88px;
  position: sticky; z-index: 2;
  white-space: nowrap; line-height: 1.3;
}
table.grid-full.grid-v thead th.col-date { z-index: 4; background: var(--bg-paper-2); }
table.grid-full.grid-v td.col-date { background: var(--row-a); }
table.grid-full.grid-v tr.block-b td.col-date { background: var(--row-b); }
table.grid-full.grid-v td.col-date.rest { background-color: var(--col-rest-bg) !important; }
table.grid-full.grid-v td.col-date.holiday { background-color: var(--col-holiday-bg) !important; }
table.grid-full.grid-v thead th.col-day { white-space: normal; overflow-wrap: anywhere; line-height: 1.25; }

/* --- 配置页竖向预览（.de-table-v）---
   20261016d：日期列**不填灰**（去掉灰底 --col-metric-bg）→ 直接不写 background，
   数据格落回 `.de-table td` 的 --bg-card（白）、表头落回 `.de-table thead th` 的表头色；
   ⚠️ 不能改成 transparent —— 日期格是 sticky 列，必须有实底，否则横向滚动会透出下层内容。 */
.de-table.de-table-v .de-c-date { white-space: nowrap; }
/* ⚠️ 内容格 min-width 必须与表头声明的指示列宽一致（20261016c）：
   表格是 auto 布局，**列宽取「表头 width」与「内容格 min-width」的较大者** ——
   20261016b 把这里写成 88px，导致表头写 76px 也不生效（实测列宽 88）。
   20261016d：普通指标列收窄到 64px（原始打卡记录列仍 76，取其表头声明的较大值）；
   日期格单独由行内 style 给 88px（略宽以容纳「9/1 3倍·二」）。 */
.de-table.de-table-v .de-daycell { min-width: 64px; }
/* 竖向日期单行（20261016b 用户口径）：「9/1 周二」中间一个空格、不换行（横版是上下两行） */
.de-table.de-table-v .de-date-one { white-space: nowrap; display: inline-block; }
.de-table.de-table-v th.de-vcol { cursor: grab; vertical-align: middle; }
.de-table.de-table-v th.de-vcol .de-name-text { display: block; }
/* 表头悬停动作组提升层级（20261016b）：指标列表头 / 汇总列头悬停时会横向排出
   「编辑 / 修改规则 / 移除」三个按钮（约 116px），若列宽不足会略微溢出，
   不提升 z-index 就被右邻单元格背景盖住（看得见、点不到）→ hover 时提到 50，
   高于表头吸附列的 40 与「＋ 添加」列的 45。 */
.de-table thead th.de-name:hover,
.de-table thead th.de-vcol:hover,
.de-table thead th.de-sum-head:hover { z-index: 50; }
/* 指标列横向拖拽的落点指示（竖向列表头，data-axis="x"） */
[data-axis="x"].de-drop-before { box-shadow: inset 2px 0 0 var(--brand); }
[data-axis="x"].de-drop-after { box-shadow: inset -2px 0 0 var(--brand); }

/* --- 配置页顶栏：显示格式切换（横向 / 纵向）---
   20261016b：位置移到「恢复默认」右侧，与它**视觉间距 20px**
   （.de-topbar-actions 自身 flex gap 8px → 再补 12px margin-left） */
.de-fmt { display: flex; align-items: center; gap: 8px; margin-left: 12px; margin-right: 4px; }
.de-fmt-label { font-size: 13px; color: var(--ink-500); }
.de-seg { display: inline-flex; border: 1px solid var(--border-default); border-radius: 8px; overflow: hidden; }
.de-seg-btn { border: 0; background: transparent; padding: 5px 12px; font-size: 13px; color: var(--ink-700); cursor: pointer; }
.de-seg-btn + .de-seg-btn { border-left: 1px solid var(--border-default); }
.de-seg-btn.on { background: var(--brand); color: #fff; }

/* ===== 全勤「规则6：请假次数」配置规则（20261017g） ===== */
/* 标题右侧的「配置规则」按钮：比 .link-btn 常规字号小一档，避免把字段标题挤换行 */
.field-label .fa-cfg-btn { font-size: 13px; font-weight: 500; margin-left: 2px; }
.fa-lt-tip { font-size: 13px; color: var(--ink-500); line-height: 1.7; margin-bottom: 12px; }
.fa-lt-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px 12px; }
.fa-lt-item {
  display: flex; align-items: center; gap: 8px; padding: 8px 10px;
  border: 1px solid var(--line-200); border-radius: 8px; cursor: pointer;
  font-size: 14px; color: var(--ink-800); word-break: break-all;
}
.fa-lt-item:hover { border-color: var(--accent-500); }
.fa-lt-item input { accent-color: var(--accent-500); flex: 0 0 auto; }
.fa-lt-empty { font-size: 13px; color: var(--ink-400); padding: 10px 0; }
@media (max-width: 720px) { .fa-lt-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* ===== 20261019q 加班比对差异标记 + 定位高亮 + 假勤姓名筛选 ===== */

/* 加班比对差异角标（橙色三角，与「人工修改」蓝色三角区分）：
   两边数据不同就显示 —— 申请空-计算有值、申请有值-计算空都在内 */
table.grid-full td.ot-diff { position: relative; }
table.grid-full td.ot-diff::after {
  content: ''; position: absolute; top: 0; right: 0;
  width: 0; height: 0; border-style: solid;
  border-width: 0 8px 8px 0; border-color: transparent #f59e0b transparent transparent;
}

/* 弹框内的「存在差异」条 + 定位按钮 */
.cell-ot-info .cell-ot-diff {
  margin-top: 8px; padding-top: 8px; border-top: 1px dashed var(--ink-150);
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  font-size: 13px; color: var(--ink-600);
}
.cell-ot-info .cell-ot-diff-tag {
  display: inline-block; padding: 1px 7px; border-radius: 999px;
  font-size: 12px; background: #fef3c7; color: #b45309;
}
html.dark .cell-ot-info .cell-ot-diff-tag { background: rgba(245, 158, 11, .18); color: #fbbf24; }

/* 20261019t（用户定版）：弹框标题下方提示文字与「定位到加班申请」同行、按钮靠右；
   比对说明框内多行内容统一行距（规则行/差异行与首行留 6px 呼吸感） */
/* 20261020a（用户定版）：弹框标题（如「修改加班汇总（H）」）距上方间距 10px */
#cell-edit-modal .modal-head { margin-top: 10px; }
.cell-edit-hint-row { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; }
.cell-edit-hint-row .cell-edit-hint { margin-bottom: 0; }
.cell-edit-hint-row .cell-ot-jump { margin-left: auto; flex: none; }
.cell-ot-info > div + div { margin-top: 6px; }
.cell-ot-info .cell-ot-rule { font-size: 12.5px; color: var(--ink-500); }

/* 假勤页姓名筛选（请假 / 加班 / 补卡 三档共用） */
.lc-filter-row { display: flex; align-items: center; justify-content: flex-end; gap: 10px; flex-wrap: wrap; }
.lc-name-filter { width: 160px; height: 30px; font-size: 13px; padding: 0 10px; }
.lc-filter-sum { font-size: 13px; color: var(--ink-500); }
/* 分页条左侧的单元格提示（20261024f）：跟在「共 N 人 · N 页」后面，浅灰 + 细分隔线，
   不抢合计的视觉权重；整段提示由 renderLeavePagination 渲染（三档 tab 同一句）。 */
.lc-page-hint {
  margin-left: 10px; padding-left: 10px;
  border-left: 1px solid var(--border-default);
  font-size: 13px; color: var(--ink-400); white-space: nowrap;
}
table.grid-full tr td.lc-empty-filter {
  text-align: center; color: var(--ink-400); padding: 22px 0; font-size: 13px;
}

/* 定位后的目标单元格：红色闪烁（约 4 秒，由 JS 移除 class） */
table.grid-full td.lc-flash {
  animation: lcFlash 0.65s ease-in-out 6;
  outline: 2px solid #ef4444; outline-offset: -2px;
}
@keyframes lcFlash {
  0%, 100% { background: #fee2e2; }
  50% { background: transparent; }
}
html.dark table.grid-full td.lc-flash { animation-name: lcFlashDark; }
@keyframes lcFlashDark {
  0%, 100% { background: rgba(239, 68, 68, .35); }
  50% { background: transparent; }
}

/* 20261020c（用户定版）：actions 位于 .modal-body 内部的弹窗（我要反馈 / 绑定 /
   改密码 / 邀请注册 等）——操作区吸附在滚动容器底部：内容超高滚动时，
   「保存 / 确定」等按钮始终可见可点，不会随内容滚出视口。 */
.modal-body .modal-actions {
  position: sticky; bottom: 0;
  background: var(--bg-paper);
  margin-top: 14px; margin-bottom: 0; padding-top: 10px;
}
html.dark .modal-body .modal-actions { background: var(--bg-card); }

/* ============================================================
   规则设置 20261020r：页内左列表 + 右侧单页（系统设置式）
   —— 系统左侧主菜单与入口不变，仅规则设置页面内部改版
   ============================================================ */
/* 左列表：搜索框 + 分组小标题 + 页项（无图标、无编号） */
.config-sidenav { width: 180px; gap: 1px; padding: 0 6px 16px 0; }
/* 20261020t：搜索框与分组小标题已去掉，左列表只留页名 */
.config-nav-item { padding: 8px 11px; }
.cfg-nav-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cfg-nav-cnt { flex: none; min-width: 16px; text-align: center; font-size: 10.5px; line-height: 15px; border-radius: 8px; background: var(--warning-soft); color: var(--warning); padding: 0 5px; }
.config-nav-item.active .cfg-nav-cnt { background: var(--accent-100); color: var(--accent-700); }

/* 右侧：单页容器（20261020t：前进/后退按钮已移除） */
.cfg-main { flex: 1 1 0; min-width: 0; min-height: 0; display: flex; flex-direction: column; }

/* 单页显隐 + 页头 */
.cfg-page { display: none; }
.cfg-page.on { display: block; }
/* 空页说明（20261025b）：加班规则页在「2 次卡 + 非自由打卡」时一个可设项都没有，
   用这张浅卡告诉用户这些设置去哪了（别给一片空白） */
.cfg-page-empty {
  background: var(--bg-paper-2, #f5f6f9); border: 1px dashed var(--ink-200, #dfe2e8);
  border-radius: 10px; padding: 18px 20px; margin-top: 4px;
}
.cfg-page-empty-t { font-size: 14px; font-weight: 600; color: var(--ink-700); margin-bottom: 8px; }
.cfg-page-empty ul { margin: 0; padding-left: 18px; }
.cfg-page-empty li {
  font-size: 13.5px; line-height: 1.9; color: var(--ink-500);
}
.cfg-page-empty li b { color: var(--ink-700); font-weight: 600; }
.cfg-phd { display: block; padding: 0 2px 12px; }
.cfg-phd h2 { display: block; font-size: 19px; font-weight: 600; color: var(--ink-900); }
.cfg-phd p { display: block; margin-top: 4px; font-size: 13px; color: var(--ink-400); }

/* 行式布局：一张卡片内一行一项（标题在左、控件在右） */
#global-config-body .cfg-card-body { padding: 4px 0 6px; }
#global-config-body .field-grid { display: block; }
#global-config-body .field-group-col { display: block; }
#global-config-body .field {
  flex-direction: row; align-items: center; gap: 16px;
  padding: 12px 22px; border-bottom: 1px solid var(--ink-150);
}
/* 20261020v：末行由 cfgRefreshDividers() 打 .cfg-fld-last（按「可见的最后一行」判定），
   ⚠️ 不能再用 :last-child —— 一行一个 field-grid 时每格末行都会被当成卡片末行 */
#global-config-body .field.cfg-fld-last { border-bottom: none; }
#global-config-body .cfg-shadow .field, #global-config-body .cfg-shadow .field-grid { display: none; }
/* 20261020v：字号 +1px（13.5 → 14.5），列宽同步 216 → 232（最长标题 206px × 14.5/13.5） */
#global-config-body .field > .field-label {
  flex: 0 0 232px; max-width: 232px; white-space: nowrap; margin: 0; align-self: center;
  font-size: 14.5px; line-height: 1.45; color: var(--ink-800);
}
#global-config-body .field > :not(.field-label) { flex: 1 1 auto; min-width: 0; }
#global-config-body .field > switch-row-placeholder { }
/* 单控件行：控件靠右、宽度适中（与标题拉开距离，不再拉满整行） */
#global-config-body .field > select.input,
#global-config-body .field > .input-wrap,
#global-config-body .field > .select-wrap,
#global-config-body .field > .msel,
#global-config-body .field > .noon-box { max-width: 330px; margin-left: auto; }
#global-config-body .field > select.input { width: 100%; }
#global-config-body .field > .switch-row { justify-content: flex-end; }
#global-config-body .field > .ladder-box,
#global-config-body .field > .cfg-att-grid,
#global-config-body .field > .cfg-att-grid-3,
#global-config-body .field > .deduct-ro { max-width: 640px; margin-left: auto; }
/* 「开关 + 数值」组合整体靠右，开启后数值输入框在开关左侧；
   宽度与其它单控件行统一 330px（20261020t：360 会让该行控件左缘比上下行偏左 30px） */
#global-config-body .field > .flex-inline-row { max-width: 330px; margin-left: auto; }
#global-config-body .field > .free-quota-row { max-width: 330px; margin-left: auto; }
#global-config-body .field > .deduct-ro { max-width: 330px; }

/* 开关类（是 / 否 + 数值）：开启后输入框出现在开关左侧（本轮用户口径） */
#global-config-body .flex-inline-row { flex-direction: row-reverse; justify-content: flex-start; }
#global-config-body .flex-inline-row .select-wrap { flex: 0 0 72px; }

/* 一行两控件（20261022w 用户定版）——「旷工与休息统计」子页两行：
   · 休息天数统计单位：左「是否跟随旷工结果单位」+ 右「休息天数统计单位」
   · 休息日显示「休」  ：左「显示 / 不显示」+ 右「显示值」（选「显示」才出现）
   整体限宽 330px 靠右，右缘与上下单控件行对齐；两控件等分（flex:1 1 0），
   选「显示」后左侧下拉收窄 96px 把宽度让给右侧输入框（.sv-on）。
   🔴 必须带 #global-config-body 前缀：`#global-config-body .field > :not(.field-label)`
      设了 flex:1 1 auto，光用类名压不住外层宽度约束。 */
#global-config-body .unit-inline-row,
#global-config-body .show-val-row {
  display: flex; align-items: center; gap: 8px;
  max-width: 330px; margin-left: auto;
}
#global-config-body .unit-inline-row > .select-wrap,
#global-config-body .show-val-row > .select-wrap { flex: 1 1 0; min-width: 0; }
#global-config-body .show-val-row > .input-wrap { flex: 1 1 0; min-width: 0; }
#global-config-body .show-val-row.sv-on > .select-wrap { flex: 0 0 96px; }
/* 跟随开启时「休息天数统计单位」置灰（disabled 由 JS/渲染给） */
#global-config-body .unit-inline-row select:disabled {
  opacity: 0.55; cursor: not-allowed; background: var(--bg-paper-2);
}

/* 底部保存条：未保存提示 + 放弃修改（无改动时整条与现在一致） */
.cfg-save-bar { gap: 14px; align-items: center; }
.cfg-dirty-tip { font-size: 13px; color: var(--warning); white-space: nowrap; }
.cfg-dirty-tip:empty { display: none; }
#cfg-discard { min-width: 0; }

/* 窄屏：左右改上下，左列表变顶部横向滚动条；行内改上下两段 */
@media (max-width: 900px) {
  .config-wrap { flex-direction: column; gap: 10px; }
  .config-sidenav { width: 100%; flex-direction: row; overflow-x: auto; overflow-y: hidden; gap: 6px; padding: 0 0 8px; }
  .config-nav-item { flex: none; white-space: nowrap; border: 1px solid var(--line); }
  .config-nav-item.active { background: var(--accent-50); color: var(--accent-700); }
  #global-config-body .field { flex-direction: column; align-items: stretch; gap: 7px; padding: 11px 14px; }
  #global-config-body .field > .field-label { flex: none; max-width: none; align-self: stretch; justify-content: flex-start; }
  #global-config-body .field > .input-wrap { max-width: none; }
}

/* ============================================================
   规则设置 20261020s（用户定版）：内容区居中限宽 + 页头贴顶
   ① 宽屏不再左右铺满：左列表 + 内容区整体限宽 1180 居中
   ② 页头「班次与加班」上移：前进/后退按钮从独立一行改绝对定位到
      内容区右上角，省掉原先 34px 空白（滚动时按钮也不跑了）
   ============================================================ */
#view-config .config-wrap { width: 100%; max-width: 1180px; margin: 0 auto; }
/* 页头标题「规则设置」与面板同宽居中，避免面板漂在中间、标题孤立在左 */
#view-config .page-header { width: 100%; max-width: 1180px; margin-left: auto; margin-right: auto; }
#view-config .cfg-save-bar { width: 100%; max-width: 1180px; margin-left: auto; margin-right: auto; }
.cfg-phd { padding: 2px 2px 10px; }

@media (max-width: 900px) {
  .cfg-phd { padding: 0 2px 9px; }
}

/* ============================================================
   规则设置 20261020t（用户定版）：二级页 + 页头精简
   ① 左列表去掉搜索框与分组小标题，只留 8 项页名
   ② 页头只留标题，去掉标题下方说明文字
   ③ 「配置」类入口不再弹窗，改为进入下级页面；返回按钮 ‹ 在标题左侧
   ============================================================ */
.cfg-phd { display: flex; align-items: center; gap: 8px; padding: 2px 2px 12px; }
/* 20261021a（用户定版）：标题不再吃满整行 —— 原来是 flex:1 1 auto，把标题右侧的ⓘ
   顶到页面最右边（标题短时图标离标题老远）。改 0 1 auto 后图标紧跟标题右侧 6px。
   ⚠️ 顺带消掉横向滚动条：标题行那个ⓘ的气泡是 320px 定宽且以图标为中心
   （left:50% + translateX(-50%)），图标贴右边缘时气泡右半截跑到 #global-config-body
   之外，opacity/visibility 隐藏态仍计入 scrollWidth ⇒ 页面出现横向滚动条。 */
.cfg-phd { gap: 6px; }
.cfg-phd h2 { flex: 0 1 auto; min-width: 0; font-size: 19px; font-weight: 600; color: var(--ink-900); }
.cfg-phd > .cfg-tip { flex: none; }
.cfg-back {
  flex: none; width: 26px; height: 26px; padding: 0;
  border: 1px solid var(--line); border-radius: 7px;
  background: var(--bg-paper); color: var(--ink-600);
  font-size: 16px; line-height: 1; font-family: inherit; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.cfg-back:hover { border-color: var(--accent-300); background: var(--accent-50); color: var(--accent-700); }

/* 子页里的配置面板：原弹窗节点搬进来后平铺显示（去遮罩 / 去投影 / 去限高） */
.cfg-sub-body { display: block; }
.modal-mask.cfg-inline {
  position: static; inset: auto; z-index: auto;
  background: none; padding: 0; display: block; overflow: visible;
}
.modal-mask.cfg-inline > .modal-box {
  /* 🔴 必须 !important：free-modal 的 .modal-box 有 inline style="max-width:520px"，
     普通规则压不住，面板会在页内只占 520px 且偏左 */
  width: 100% !important; max-width: none !important; max-height: none !important; padding: 0;
  background: transparent; box-shadow: none; border-radius: 0; overflow: visible;
}
.modal-mask.cfg-inline .modal-head,
.modal-mask.cfg-inline .modal-actions { display: none; }
.modal-mask.cfg-inline .modal-body { max-height: none; overflow: visible; }

/* 子页面板外观对齐主页面（20261020t）：免罚面板内容少，套一张浅灰卡片，
   行内下拉与主页面同样 330px 靠右，不至于在白底上拉成整行超宽 */
/* 所有子页面板统一套主页面同款浅灰卡片，内部区块/提示条改白底 */
/* 20261020w（用户定版，覆盖 20v）：子页底板改**透明**（background:none），
   灰底只落在子页里的卡片上（#f5f6f9）—— 白卡套白底太糊，灰卡 + 透明底层次更清楚。
   🔴 写 var(--bg-paper-2, #f5f6f9) 而不是硬编码：浅色下它就是 #f5f6f9，
      深色下是 #28282a；硬编码会在深色模式变成一块刺眼白板 */
.cfg-sub-body { background: none; border-radius: 12px; padding: 0; }
.cfg-sub-body .cfg-card { background: var(--bg-paper-2, #f5f6f9); margin-bottom: 0; }
.cfg-sub-body .cfg-card + .cfg-card { margin-top: 12px; }
/* 20261020w：kind='modal' 的子页（扣款类型）没有 .cfg-card —— 面板本体是 .dm-sec，
   底板转透明后它必须自己顶上灰卡底，否则白块套白底等于没有卡片 */
.modal-mask.cfg-inline .dm-sec { background: var(--bg-paper-2, #f5f6f9); }
.modal-mask.cfg-inline .dm-hint { margin-bottom: 12px; }
.modal-mask.cfg-inline .dm-row .dm-select { max-width: 330px; margin-left: auto; }
.cfg-back { width: 28px; height: 28px; font-size: 18px; border-color: var(--ink-150); }
.cfg-back:hover { border-color: var(--accent-300); }
/* 20261022f：子页空态说明卡（配置状态导致子页里一个控件都没有时）—— 灰卡 + 居中说明，
   与子页其它卡片同一底色，不再让用户看到一片空白 */
.cfg-sub-body > .cfg-sub-empty {
  background: var(--bg-paper-2, #f5f6f9); border-radius: 12px;
  padding: 26px 22px; text-align: center;
}
/* 20261022v：子页「模块」小标题（一个模块一张白卡，同卡字段不再散落）——
   用灰阶与 .cfg-card-sub 同一套色，不新造变量：浅/深色都跟着 --ink-* 走 */
.cfg-sub-body .cfg-mod-hd { margin: 0 0 12px; }
.cfg-sub-body .cfg-mod-hd .cfg-card-title {
  font-size: 16px; display: flex; align-items: center; gap: 6px;
}
.cfg-sub-body .cfg-mod-hd .cfg-card-sub {
  font-size: 13px; color: var(--ink-400); margin-top: 2px;
}
.cfg-sub-body > .cfg-sub-empty .cfg-sub-empty-t {
  font-size: 14.5px; font-weight: 600; color: var(--ink-700); margin-bottom: 8px;
}
.cfg-sub-body > .cfg-sub-empty .cfg-sub-empty-d {
  font-size: 13px; line-height: 1.75; color: var(--ink-400);
  max-width: 620px; margin: 0 auto;
}
/* 20261022t：「旷工与休息统计」子页底部一致性警示条 —— 规则组合的后果
   （休+旷重复计数 / 关减可休不标休）在保存前亮出来；颜色全走主题变量。 */
.cfg-sub-body > .cfg-sub-warn {
  background: var(--warning-soft, rgba(251, 191, 36, .12));
  color: var(--warning, #b7791f);
  border: 1px solid rgba(217, 119, 6, .25);
  border-radius: 10px;
  padding: 10px 14px;
  font-size: 12.5px;
  line-height: 1.7;
}

/* ============================================================
   规则设置 20261020u（用户定版）
   ① 左列表页名：字号增大加粗、行距加大
   ② 标题列加宽到 216px 且不折行（全部 74 个字段里最长标题 206px）
   ③ 「配置」入口 → 本行最右侧 › 箭头；二级页入口行同款箭头
   ============================================================ */
.config-sidenav { gap: 3px; }
.config-nav-item { font-size: 14.5px; font-weight: 600; padding: 11px 13px; }
.config-nav-item.active { font-weight: 700; }
.cfg-nav-cnt { font-size: 11px; }

/* 取整区间行：标题宽度按内容自适应（区间字段标题较短，避免挤压输入区） */
#global-config-body .interval-field > .field-label { flex: 0 0 auto; max-width: 420px; }

/* 行尾 › 箭头（进入下级页面） */
#global-config-body .field > .cfg-more {
  flex: 0 0 auto; width: 22px; height: 22px; padding: 0; margin-left: 2px;
  border: 0; background: none; color: var(--ink-400);
  font-size: 19px; line-height: 1; font-family: inherit; cursor: pointer;
  display: flex; align-items: center; justify-content: center; border-radius: 6px;
}
#global-config-body .field > .cfg-more:hover { background: var(--bg-paper-2); color: var(--accent-700); }

/* 二级页入口行：整行可点，右侧 ›（卡片底色沿用 01~10 的浅灰块，见 cfg-tint-*） */
.cfg-entry-card { padding: 0; }
.cfg-entry-card:hover { background: var(--bg-paper-3, #eceef3); }
.cfg-entry {
  display: flex; align-items: center; gap: 12px; width: 100%;
  padding: 15px 22px; border: 0; background: none; text-align: left;
  font-family: inherit; cursor: pointer;
}
.cfg-entry:hover { background: var(--bg-paper-2); }
.cfg-entry-text { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.cfg-entry-title { font-size: 15px; font-weight: 600; color: var(--ink-900); }
.cfg-entry-desc { font-size: 12.5px; color: var(--ink-400); }
.cfg-entry-arrow { flex: none; font-size: 20px; line-height: 1; color: var(--ink-400); }
.cfg-entry:hover .cfg-entry-arrow { color: var(--accent-700); }

/* 被搬进子页的单字段（请假类型出勤天数）：套白卡片，与子页里其它白块一致 */
.cfg-sub-body .cfg-inline-field {
  background: var(--bg-paper); border-radius: 12px; border-bottom: 0; padding: 14px 18px;
}
.cfg-sub-white { background: var(--bg-paper); }

/* 字段被搬走后原行变空（父 .field-grid 无子节点）⇒ 不占高度 */
#global-config-body .field-grid[data-cfg-empty] { display: none; }

/* 20261021k（用户定版）：午间/晚间连班二级子页改**纵向布局** ——
   标题在上、设置块在下，不再「标题左 232px + 内容右 330px」的行式排布；
   🔴 只作用于这两个子页（[data-page] 限定）——补贴/扣款/取整等其它子页仍是行式布局 */
#global-config-body [data-page="sub-noon_ot"] .field,
#global-config-body [data-page="sub-dinner_ot"] .field {
  flex-direction: column; align-items: stretch; gap: 10px;
}
#global-config-body [data-page="sub-noon_ot"] .field > .field-label,
#global-config-body [data-page="sub-dinner_ot"] .field > .field-label {
  flex: 0 0 auto; max-width: none; align-self: auto;
}
#global-config-body [data-page="sub-noon_ot"] .field > .noon-box,
#global-config-body [data-page="sub-dinner_ot"] .field > .noon-box {
  max-width: 560px; margin-left: 0;
}
/* 20261021l（用户定版）：子页里的字段子标题行（「午间连班（仅 4 次卡及以上适用）」等）去掉 ——
   页头已是「午间连班」，不重复；ⓘ 帮助随行隐藏（开启校验仍由联动 toast 兜底） */
#global-config-body [data-page="sub-noon_ot"] .field > .field-label,
#global-config-body [data-page="sub-dinner_ot"] .field > .field-label { display: none; }

@media (max-width: 900px) {
  #global-config-body .field > .field-label { flex: none; max-width: none; white-space: normal; }
  #global-config-body .interval-field > .field-label { max-width: none; }
  .config-nav-item { font-size: 14px; padding: 9px 12px; }
}

/* 20261020u 补充：
   ① 取整区间行（标题 ｜ 区间列表 ｜ + 添加一行）：行式布局下原本三者横排、
      添加按钮跑到列表右侧像独立小盒 ⇒ 改两列网格，列表与添加按钮都在右列上下排
   ② 被搬进子页的「请假类型出勤天数」是列表型字段：标题置顶、列表占满整行
      （横排会让标题孤零零挂在左侧、列表被挤到右半边） */
#global-config-body .field.interval-field {
  display: grid;
  grid-template-columns: 232px minmax(0, 1fr);
  align-items: start;
  column-gap: 16px;
}
#global-config-body .interval-field > .field-label { grid-row: 1; grid-column: 1; align-self: center; }
#global-config-body .interval-field > .interval-list { grid-row: 1; grid-column: 2; }
#global-config-body .interval-field > .interval-foot { grid-row: 2; grid-column: 2; display: flex; align-items: center; gap: 14px; margin-top: 8px; }

/* 🔴 必须带 #global-config-body 前缀：`#global-config-body .field` 的 flex-direction:row
   优先级更高，光用两个类名压不住（第一版就是被它盖掉了，列表仍被挤到右半边） */
#global-config-body .cfg-sub-body .cfg-inline-field { flex-direction: column; align-items: stretch; gap: 10px; }
#global-config-body .cfg-sub-body .cfg-inline-field > .field-label {
  flex: none; max-width: none; white-space: normal;
  /* 列方向下 align-self:center 会把标题挤到水平居中（继承自行式布局的 align-self） */
  align-self: stretch; justify-content: flex-start;
}

/* ============================================================
   规则设置 20261020v（用户定版）
   ① 入口行（迟到早退免罚/宽限/扣款类型/算缺勤、请假类型…）：整行可点 + 右侧当前值摘要
   ② 「配置规则」按钮移到下拉选择框左侧
   ③ 子页白底、白卡；请假类型「添加」式列表
   ④ 扣款子页：迟到/早退两块阶梯 + 「复制迟到设置」
   ============================================================ */

/* 入口行：整行就是按钮（不必点右侧箭头） */
#global-config-body .field.field-link { cursor: pointer; }
#global-config-body .field.field-link:hover { background: var(--bg-paper-2); }
#global-config-body .field.field-link:focus-visible { outline: 2px solid var(--accent-300); outline-offset: -2px; }
#global-config-body .field.field-link > .field-label { cursor: pointer; }
#global-config-body .field-entry-sum {
  flex: 1 1 auto; min-width: 0; margin-left: auto; text-align: right;
  /* 20261025b（用户定版）：回显值改**黑色**并加大字号（原 13.5px + --ink-500 太灰太小） */
  font-size: 15px; color: #000;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
html.dark #global-config-body .field-entry-sum { color: var(--ink-900); }
#global-config-body .field.field-link > .cfg-more {
  /* 20261025b（用户定版）：箭头加大 + 按口径用 #333333（原 --ink-300 太浅，19px 太小） */
  color: #333333; width: 24px; height: 24px; font-size: 22px;
}
html.dark #global-config-body .field.field-link > .cfg-more { color: var(--ink-700); }

/* 「配置规则」按钮：放到下拉选择框左侧 */
#global-config-body .field > .fa-cfg-btn {
  flex: 0 0 auto; margin: 0 0 0 auto; padding: 0 2px;
  font-size: 13px; font-weight: 500; white-space: nowrap;
}
#global-config-body .field > .fa-cfg-btn + .flex-inline-row,
#global-config-body .field > .fa-cfg-btn + select.input { margin-left: 10px; }

/* 请假类型子页：添加行 + 已添加类型 chip */
/* 列表型内容统一左对齐（从控件列起点开始），右对齐会在换行时显得散 */
.lt-add-row { display: flex; align-items: center; gap: 10px; width: 100%; max-width: 420px; }
.lt-add-row .input { flex: 1 1 auto; min-width: 0; }
.lt-add-row .btn { flex: none; white-space: nowrap; }
.lt-chip-list {
  flex: 1 1 auto; min-width: 0;
  display: flex; flex-wrap: wrap; gap: 8px; justify-content: flex-start;
}
/* 20261023e：「请假类型」子页里第二张卡（逐类型规则）与上方「添加 / 已添加」卡
   同一套白卡底，靠 .cfg-sub-body .cfg-card + .cfg-card 的 12px 间距分隔 */
.lt-chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 6px 4px 11px; border-radius: 999px;
  background: var(--accent-50); color: var(--accent-700);
  font-size: 13.5px; line-height: 1.5;
}
.lt-chip-del {
  padding: 0; width: 17px; height: 17px; border: 0; border-radius: 50%;
  background: transparent; color: var(--accent-600); font-size: 11px; line-height: 1;
  font-family: inherit; cursor: pointer; display: flex; align-items: center; justify-content: center;
}
.lt-chip-del:hover { background: var(--accent-100); color: var(--accent-800); }

/* 扣款子页：区块标题行 + 「复制迟到设置」按钮 */
.dm-sec-title-row { display: flex; align-items: center; gap: 10px; }
.dm-sec-title-row > span { flex: 1 1 auto; min-width: 0; }
.dm-copy { flex: none; margin-left: auto; }

/* 子页里的字段行：末行不画线（cfgRefreshDividers 打标记，跨子页同样生效） */
.cfg-sub-body .field { background: transparent; }

@media (max-width: 900px) {
  #global-config-body .field-entry-sum { margin-left: 0; text-align: left; white-space: normal; }
  .lt-add-row, .lt-chip-list { max-width: none; }
  #global-config-body .field > .fa-cfg-btn { margin-left: 0; }
}

/* 20261020v：02 上下班时间那两行带 .cfg-time-grid（原为 6 栏并排做底对齐/42px 等高），
   行式布局下已不需要 —— 否则每行被撑到 67px（比其它行高 20px），间距看着忽大忽小。
   统一交给 .field 的 12px 内距 + 控件自身高度。 */
#global-config-body .field-grid.cfg-time-grid .field > .input-wrap,
#global-config-body .field-grid.cfg-time-grid .field > .select-wrap,
#global-config-body .field-grid.cfg-time-grid .field > select.input,
#global-config-body .field-grid.cfg-time-grid .field > .flex-inline-row,
#global-config-body .field-grid.cfg-time-grid .field > .free-quota-row { height: auto; margin-top: 0; }
#global-config-body .field-grid.cfg-time-grid .field { align-items: center; }
#global-config-body .field-grid.cfg-time-grid .field-label { flex-wrap: nowrap; align-items: center; row-gap: 0; }

/* ── 20261020x（用户定版）：扣款子页阶梯配置区样式美化 ─────────────────────────
   改之前：一行里两格 + 删除按钮被 justify-content:space-between 拉满整宽（约 660px），
   标签/输入/单位散在两端、每行右侧挂一颗粉色药丸 ×、封顶行与「添加一行」各自漂浮 ⇒ 看着乱。
   改之后：阶梯行收进一个描边圆角容器（.dm-ladder-box）；行内改 grid 两等分 + 右侧 24px 删除位，
   行间 hairline 分隔；封顶行做容器底条（浅灰底 + 虚线分隔）；「添加一行」做容器页脚虚线小按钮。
   🔴 只作用于扣款子页（.dm-ladder-box 仅此处渲染），主表单里的阶梯行样式完全不动。
   🔴 .interval-row 的基础样式带 display:flex / flex-direction:row 的 !important，覆盖必须同级 !important。 */
.dm-ladder-box {
  background: var(--bg-paper); border: 1px solid var(--ink-150);
  border-radius: 10px; overflow: hidden;
}
.dm-ladder-box .dm-ladder { gap: 0; }
.dm-ladder-box .dm-ladder .ladder-row {
  display: grid !important;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) 24px;
  align-items: center; gap: 6px 12px;
  width: 100%; margin: 0; padding: 8px 12px;
  background: none; border-radius: 0; border-bottom: 1px solid var(--ink-150);
}
.dm-ladder-box .dm-ladder .ladder-row:last-child { border-bottom: none; }
.dm-ladder-box .dm-ladder .ladder-cell {
  display: flex; align-items: center; gap: 6px;
  flex: 1 1 auto; min-width: 0;
}
.dm-ladder-box .dm-ladder .ladder-lbl { font-size: 13.5px; color: var(--ink-500); }
.dm-ladder-box .dm-ladder .interval-input {
  width: 88px; flex: 0 0 88px; text-align: center;
}
.dm-ladder-box .dm-ladder .interval-unit { font-size: 13.5px; color: var(--ink-400); }
.dm-ladder-box .dm-ladder .ladder-del {
  width: 24px; height: 24px; min-width: 0; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  background: none; border: none; color: #f87171;   /* 浅红（用户定版） */
  font-size: 16px; line-height: 1; border-radius: 6px;
}
.dm-ladder-box .dm-ladder .ladder-del:hover {
  background: rgba(248, 113, 113, .14); color: var(--danger);
}
/* 深色模式：该按钮同时带 .btn —— `html.dark .btn:not(...)` 一组 :not 的选择器
   特异性远高于上面两条，会把颜色盖回 --ink-800（浅灰）⇒ 必须补同前缀的深色规则 */
html.dark .dm-ladder-box .dm-ladder .ladder-del { color: #f87171 !important; }
html.dark .dm-ladder-box .dm-ladder .ladder-del:hover {
  background: rgba(248, 113, 113, .18); color: #ef4444 !important;
}
.dm-ladder-box .ladder-cap-line {
  margin: 0; padding: 9px 12px; gap: 8px;
  border-top: 1px solid var(--ink-150); background: var(--bg-paper);
}
.dm-ladder-box .ladder-cap-line .ladder-lbl { font-size: 13.5px; color: var(--ink-700); }
.ladder-hint { font-size: 12.5px; color: var(--ink-400); }
.dm-ladder-box .ladder-foot { padding: 8px 12px; border-top: 1px solid var(--ink-150); }
.ladder-add {
  background: none; border: 1px dashed var(--ink-300); border-radius: 8px;
  padding: 5px 12px; font-size: 13.5px; font-family: inherit;
  color: var(--accent-600, #2563eb); cursor: pointer; transition: all .18s;
}
.ladder-add:hover { background: var(--accent-100, #dbeafe); border-color: var(--accent-500); }

/* 20261020x：扣款子页顶部「扣款类型 / 计量单位 / 扣款分钟减去宽限」三行 ——
   标签最长的那条（扣款分钟减去可迟到早退宽限）在固定 88px 标签列里被折成 4 行。
   改成 grid（标签列 = 最宽标签宽度、控件列吃满剩余），三行左缘对齐、下拉同一起点。 */
.dm-sec-head {
  display: grid; grid-template-columns: max-content minmax(0, 1fr);
  align-items: center; gap: 12px;
}
.dm-sec-head .dm-row { display: contents; }
.dm-sec-head .dm-label { flex: none; white-space: nowrap; }
.dm-sec-head .dm-row .dm-select { width: 100%; }

/* ============================================================
   班次设置弹窗改版（20261021f）：左列表 5 页 + 右侧单页
   交互语言与「规则设置」页一致（左列表 + 单页 + 灰底卡片），
   字段排布改为「标签在上、控件在下 + 2/3 列网格」——
   班次字段大量是「双 time / 下拉 + 数字」复合控件，横排标签列会压掉控件宽度。
   类名统一 sf- 前缀，避免与既有 .shift-card（班次列表卡）/ .page / .grid 冲突。
   ============================================================ */
.modal-box.sf-modal {
  max-width: 1060px; padding: 0; overflow: hidden;
  height: min(712px, calc(100vh - 40px));
  display: flex; flex-direction: column;
}
/* 头部：标题 + 副标题 + 关闭 */
.sf-head {
  flex: none; margin-bottom: 0; padding: 16px 22px 12px;
  display: flex; align-items: flex-start; gap: 12px;
  border-bottom: 1px solid var(--border-subtle);
}
.sf-head-main { flex: 1; min-width: 0; }
.sf-head-sub { font-size: 13px; color: var(--ink-400); margin-top: 4px; line-height: 1.5; }
.sf-head .modal-close { flex: none; margin-top: -2px; }
/* 主体：左列表 + 右单页 */
.sf-body { flex: 1 1 auto; min-height: 0; display: flex; }
.sf-nav {
  width: 208px; flex: none; padding: 12px 10px 16px 14px;
  display: flex; flex-direction: column; gap: 1px; overflow: auto;
  border-right: 1px solid var(--border-subtle);
}
.sf-nav-item {
  display: block; width: 100%; padding: 8px 10px; border-radius: 8px; border: none;
  background: transparent; cursor: pointer; font: inherit; font-size: 14.5px;
  /* 20261035c（用户）：左侧页签文字默认加粗，未选中项也要一眼可读 */
  font-weight: 600;
  color: var(--ink-600); text-align: left; line-height: 1.4;
  transition: background .14s, color .14s;
}
.sf-nav-item:hover { background: var(--bg-paper-2); color: var(--ink-900); }
.sf-nav-item.on { background: var(--bg-paper-2); color: var(--ink-900); }
.sf-nav-top { display: flex; align-items: center; gap: 9px; }
.sf-nav-item.on .sf-nav-top { font-weight: 600; }
.sf-nav-n {
  font-family: var(--font-mono); font-size: 12px; color: var(--ink-300);
  min-width: 16px; flex: none; font-weight: 500;
}
.sf-nav-item.on .sf-nav-n { color: var(--accent-500); }
.sf-nav-t { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sf-nav-dot {
  width: 5px; height: 5px; border-radius: 50%; background: var(--accent-500);
  flex: none; opacity: 0; transition: opacity .14s;
}
.sf-nav-sum {
  display: block; font-size: 12.5px; color: var(--ink-400); margin-top: 2px;
  padding-left: 25px; font-weight: 400; line-height: 1.5;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.sf-nav-item.on .sf-nav-sum { color: var(--ink-500); }
.sf-nav-item.off { color: var(--ink-300); cursor: default; }
.sf-nav-item.off .sf-nav-n, .sf-nav-item.off .sf-nav-sum { color: var(--ink-200); }
.sf-nav-item.off:hover { background: transparent; color: var(--ink-300); }
/* 页面区 */
.sf-pages { flex: 1; min-width: 0; position: relative; overflow: hidden; }
.sf-page {
  position: absolute; inset: 0; overflow-y: auto; overscroll-behavior: contain;
  padding: 14px 22px 22px; display: none;
}
.sf-page.on { display: block; }
.sf-phd { display: flex; align-items: flex-start; gap: 10px; margin: 2px 0 12px; }
.sf-phd h2 { margin: 0; font-size: 18px; font-weight: 600; color: var(--ink-900); }
.sf-pd { font-size: 13px; color: var(--ink-400); margin-top: 4px; line-height: 1.6; }
.sf-pill {
  margin-left: auto; flex: none; font-size: 12px; padding: 4px 10px; border-radius: 999px;
  white-space: nowrap; background: var(--success-soft, #e7f7ed); color: var(--success, #16a34a);
  font-weight: 500;
}
.sf-pill.mute { background: var(--ink-100); color: var(--ink-500); font-weight: 400; }
.sf-pill.warn { background: var(--warning-soft, #fef4e6); color: var(--warning, #d97706); }
/* 卡片 */
.sf-card {
  background: var(--bg-paper-2); border-radius: var(--radius-lg);
  padding: 14px 16px 16px; margin-bottom: 12px;
}
.sf-card:last-child { margin-bottom: 0; }
/* 20261021i（用户定版）：弹窗页内模块（时间轴/时间线/加班计算/连班）之间要有间距，
   12px 偏挤 ⇒ 本弹窗页内统一 16px；子元素级（.sf-cardrow 里）不受影响 */
.sf-pwrap > .sf-card { margin-bottom: 16px; }
.sf-pwrap > .sf-card:last-child { margin-bottom: 0; }
.sf-card-hd { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; flex-wrap: wrap; }
.sf-ct { font-size: 15px; font-weight: 600; color: var(--ink-800); }
.sf-cs { font-size: 14px; color: var(--ink-400); font-weight: 400; }
.sf-sum {
  margin-left: auto; font-size: 12.5px; color: var(--ink-500); background: var(--bg-paper);
  padding: 3px 8px; border-radius: 6px; font-family: var(--font-mono);
}
.sf-cardrow { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 12px; margin-bottom: 12px; }
.sf-cardrow.two { grid-template-columns: 1fr 1fr; }
.sf-cardrow .sf-card { margin-bottom: 0; }
/* 字段网格 */
.sf-grid { display: grid; gap: 12px 16px; align-items: start; }
.sf-g1 { grid-template-columns: 1fr; }
.sf-g2 { grid-template-columns: 1fr 1fr; }
.sf-g3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
/* 20261021h：一行 4 栏，超过折行到下一行；4 栏下双时间区间允许收窄 */
.sf-g4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.sf-g4 .sf-range input { min-width: 62px; padding: 0 6px; }
.sf-g4 .sf-range { gap: 4px; }
.sf-f { display: flex; flex-direction: column; gap: 6px; min-width: 0; margin: 0; }
.sf-lb {
  /* 20261035b（用户 2026-10-27）：字重/颜色向「规则设置」页 .field-label 对齐
     （原 400 + ink-500 看着比规则页小一档） */
  font-size: 15px; font-weight: 500; color: var(--ink-900);
  display: flex; align-items: center; gap: 5px; line-height: 1.35; margin: 0;
  /* 20261023c：原来是 flex-wrap: wrap —— 标签文字 + 提示图标宽度超出单栏时，
     图标会被整体挤到**第二行左侧**（用户截图：跨凌晨班「是否存在跨凌晨下班情况」
     的 ① 折行、下拉框随之下沉与左栏错位）。改 nowrap：文字自身换行（中文可任意
     断行），图标始终跟在文字右侧，任何宽度下都不会孤立成行。 */
  flex-wrap: nowrap;
}
.sf-lb > .cfg-tip, .sf-lb > .sf-inh, .sf-lb > .req { flex: none; }
.sf-lb > .cfg-tip, .sf-lb > .sf-inh { align-self: center; }
.sf-lb .req { color: var(--danger); font-size: 12px; }
.sf-lb .cfg-tip { margin-left: 0; width: 14px; height: 14px; flex: none; }
.sf-lb .cfg-tip svg { width: 14px; height: 14px; }
.sf-f > input, .sf-f > select, .sf-f > .select-wrap > select {
  height: 36px; border-radius: var(--radius-sm, 8px);
  border: 1px solid var(--border-default);
  /* 用 background-color 而非 background 简写，避免清掉全站 select 的黑色三角箭头 */
  background-color: var(--bg-paper); color: var(--ink-800);
  font: inherit; font-size: 15px; padding: 0 10px; width: 100%; min-width: 0;
  box-sizing: border-box;
}
.sf-f > .select-wrap { width: 100%; }
/* 20261021j：单时间输入与区间输入同宽（填满所在栏），网格内不再一长一短 */
.sf-f > input[type="time"] { max-width: 100%; }
.sf-f > input:focus, .sf-f > select:focus, .sf-f > .select-wrap > select:focus {
  outline: none; border-color: var(--accent-500);
  box-shadow: 0 0 0 3px rgba(var(--accent-glow), .12);
}
.sf-f > input::placeholder { color: var(--ink-300); }
html.dark .sf-f > input, html.dark .sf-f > select { color-scheme: dark; }
/* 双时间（区间）行 */
.sf-range { display: flex; align-items: center; gap: 6px; min-width: 0; }
.sf-range input {
  flex: 1 1 0; min-width: 92px; height: 34px; border-radius: var(--radius-sm, 8px);
  border: 1px solid var(--border-default); background: var(--bg-paper); color: var(--ink-800);
  font: inherit; font-size: 15px; padding: 0 10px; box-sizing: border-box;
}
.sf-range input:focus { outline: none; border-color: var(--accent-500); box-shadow: 0 0 0 3px rgba(var(--accent-glow), .12); }
.sf-range-sep { color: var(--ink-300); font-size: 12px; flex: none; }
/* 20261021g：弹窗内的提示气泡未激活时改「右对齐图标」——
   气泡是 320px 定宽 + left:50% 居中，图标落在 g3 第三列（如「跨凌晨打卡记录是否错位」）
   时右半边会顶出页面，opacity/visibility 隐藏**也计入** scrollWidth ⇒ 整页横向滚动条。
   改 right:-6px 向左展开后不再溢出；hover 时 JS 改 position:fixed 并重置 left/right，不受影响。 */
.sf-modal .cfg-tip-bubble { left: auto; right: -6px; transform: none; }

/* 「沿用全局 / 已覆盖」标记 */
.sf-inh {
  font-size: 14px; color: var(--ink-400); border: 1px solid var(--border-subtle);
  padding: 1px 6px; border-radius: 5px; background: var(--bg-paper);
  font-weight: 400; margin-left: 2px; white-space: nowrap;
}
.sf-inh.set {
  color: var(--accent-600); border-color: var(--accent-100, #d5e9ff);
  background: var(--accent-50, #eaf4ff);
}
html.dark .sf-inh { background: var(--bg-paper); }
/* 页底说明 */
.sf-hintline { font-size: 13px; color: var(--ink-400); line-height: 1.65; margin: 10px 4px 0; }
.sf-hintline b { font-weight: 600; color: var(--ink-500); }
/* 空状态 */
.sf-empty {
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  padding: 52px 24px; text-align: center;
  color: var(--ink-400); font-size: 14px; line-height: 1.7;
}
.sf-empty .sf-ei { font-size: 26px; color: var(--ink-200); }
.sf-empty b { color: var(--ink-600); font-weight: 600; }
/* 连班块（卡内白底，避免灰底套灰底） */
#shift-cont-row .sf-f { gap: 0; }
#shift-cont-row .group-noon-box { background: var(--bg-paper); border-color: var(--border-subtle); }
#shift-cont-row .sf-f + .sf-f { margin-top: 10px; }
/* 补贴容器（原 4 栏网格改卡片堆叠） */
.sf-subwrap { display: block; }
/* 午餐只有 1 个字段：多班次时它常独占一行，控件限宽避免拉成 800px 长条 */
#sf-sub-lunch .sf-g1 { max-width: 320px; }
/* 底部：摘要 + 取消 + 保存（唯一操作区，切页不丢值）
   20261035f：这里多了「取消」，改成「摘要 flex:1 撑满左侧、取消与保存贴右侧」，
   否则保存按钮的 margin-left:auto 会把取消顶到摘要旁边，两个按钮被拉开。 */
.sf-foot {
  flex: none; margin-top: 0; padding: 12px 22px;
  border-top: 1px solid var(--border-subtle);
  display: flex; align-items: center; gap: 12px; justify-content: flex-start;
  background: var(--bg-paper);
}
.sf-sumline {
  font-size: 13.5px; color: var(--ink-500); display: flex; align-items: center;
  gap: 7px; flex-wrap: wrap; min-width: 0; flex: 1 1 auto;
}
.sf-sumline b { color: var(--ink-800); font-weight: 600; }
.sf-sumline .sf-k { color: var(--ink-300); }
.sf-foot .btn-primary { margin-left: 0; flex: none; }
/* 时间轴预览 */
.sf-tl { background: var(--bg-paper); border-radius: var(--radius-md, 10px); padding: 13px 14px; }
.sf-tl-empty { font-size: 13px; color: var(--ink-400); text-align: center; padding: 10px 0; }
.sf-tl-hd { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--ink-400); margin-bottom: 14px; flex-wrap: wrap; }
.sf-tl-hd .sf-tlb { font-size: 13px; color: var(--ink-600); font-weight: 600; }
.sf-tl-row { position: relative; height: 15px; border-radius: 5px; background: var(--ink-100); margin-bottom: 6px; }
.sf-tl-row:last-of-type { margin-bottom: 0; }
.sf-tl-seg { position: absolute; top: 0; height: 15px; border-radius: 4px; }
.sf-tl-seg.work { background: var(--accent-300, #7ab8f5); }
.sf-tl-seg.rest { background: var(--ink-200); }
.sf-tl-seg.meal { background: #f6cd6e; }
html.dark .sf-tl-seg.meal { background: #8a6a1e; }
.sf-tl-mark { position: absolute; top: -3px; height: 21px; width: 2px; background: var(--accent-600); border-radius: 2px; }
.sf-tl-mark::after {
  content: attr(data-l); position: absolute; top: -15px; left: 50%; transform: translateX(-50%);
  font-size: 10.5px; color: var(--accent-600); white-space: nowrap; font-family: var(--font-mono);
}
.sf-tl-ticks {
  display: flex; justify-content: space-between; font-size: 10.5px;
  color: var(--ink-300); font-family: var(--font-mono); margin-top: 5px;
}
.sf-tl-legend {
  display: flex; gap: 16px; font-size: 12.5px; color: var(--ink-400);
  margin-top: 11px; padding-top: 10px; border-top: 1px solid var(--border-subtle); flex-wrap: wrap;
}
.sf-tl-legend span { display: flex; align-items: center; gap: 6px; }
.sf-tl-legend i { width: 9px; height: 9px; border-radius: 3px; display: inline-block; }
.sf-tl-legend .sf-v { margin-left: auto; font-family: var(--font-mono); color: var(--ink-500); }
/* 窄屏（< 1040）：左列表转横向 tab */
@media (max-width: 1040px) {
  .sf-body { flex-direction: column; }
  .sf-nav {
    width: 100%; flex-direction: row; overflow-x: auto; overflow-y: hidden;
    padding: 8px 12px; gap: 6px; border-right: none;
    border-bottom: 1px solid var(--border-subtle);
  }
  /* width:auto 必须显式覆盖 —— 基础样式里是 width:100%（竖排撑满），
     横排时不覆盖会让每个 tab 各占满一整行宽、把后 4 项挤出可视区 */
  .sf-nav-item { flex: 0 0 auto; width: auto; white-space: nowrap; border: 1px solid var(--border-subtle); }
  .sf-nav-sum { display: none; }
  .sf-page { padding: 12px 14px 18px; }
  .sf-g2, .sf-g3, .sf-g4 { grid-template-columns: 1fr; }
  .sf-cardrow.two { grid-template-columns: 1fr; }
  .sf-head { padding: 14px 16px 10px; }
  .sf-foot { padding: 10px 16px; flex-wrap: wrap; }
}
/* 时间轴加班标记：贴近左右边缘时把标签往回收，避免溢出产生横向滚动 */
.sf-tl-mark.end::after { left: auto; right: 0; transform: none; }
.sf-tl-mark.start::after { left: 0; transform: none; }
/* 时间输入框去掉原生时钟图标（20261021f，与 20x 规则设置页口径一致） */
.sf-f input[type="time"]::-webkit-calendar-picker-indicator,
.sf-range input[type="time"]::-webkit-calendar-picker-indicator { display: none; }
.sf-f input[type="time"], .sf-range input[type="time"] {
  -webkit-appearance: none; appearance: none;
}

/* ==========================================================================
   20261023a：活跃用户排名 + 图表下钻明细 + 用户类别
   ========================================================================== */
/* ---- 活跃用户排名（20261023a 独立整行 → 20261023b 进活跃分析行第三栏） ----
   标题 + 右侧「按周 / 按月」chip（复用 .astat-chips/.astat-chip）；
   卡片高度由所在 .adm-charts 行给定（345px），表体吃掉剩余高度并自己竖向滚动，
   表头 sticky 吸顶 —— TOP50 不会把看板整体拉长。 */
.adm-rank-cell { min-width: 0; min-height: 0; display: flex; }
.adm-rank-card { flex: 1 1 auto; min-width: 0; }
.adm-rank-head { align-items: center; flex-wrap: nowrap; gap: 8px; margin-bottom: 6px; }
.adm-rank-head .astat-title { flex: 0 1 auto; min-width: 0; white-space: nowrap; }
.adm-rank-head .astat-chips { margin: 0 0 0 auto; flex-wrap: nowrap; gap: 6px; margin-bottom: 0; }
/* 一栏宽（约 1/3 屏）里 chip 收小一号，避免标题与 chip 抢位折行 */
.adm-rank-head .astat-chip { padding: 2px 8px; font-size: 13px; }
/* 周期区间 + TOP50（20261023b 用户定版）：与标题同一行、紧贴标题右侧；
   flex:0 1 auto + 省略号 ⇒ 一栏宽放不下时先收窄它，不挤掉右侧 chip。 */
.adm-rank-sum { flex: 0 1 auto; min-width: 0; font-size: 12.5px; color: var(--ink-400);
  margin: 0; padding: 1px 0 0 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* 🔴 body 必须能吃满剩余高度（.astat-card-body 的 flex:1 1 0 在这里是对的 ——
   卡片高度由网格行固定）；min-height:0 让表体能收缩出滚动条。 */
.adm-rank-body { flex: 1 1 auto; min-height: 0; padding: 0; overflow: hidden; }
.rank-scroll { height: 100%; overflow-y: auto; overflow-x: hidden; }
.rank-table { width: 100%; }
.rank-table thead th {
  position: sticky; top: 0; z-index: 2; background: var(--bg-paper-2, #f5f6f9);
}
.rank-table th.rk-no, .rank-table td.rk-no { width: 66px; }
.rank-table th.rk-cnt, .rank-table td.rk-cnt { width: 96px; text-align: right; }
.rank-table td.rk-cnt b { font-family: var(--font-mono); font-size: 15px; color: var(--ink-800); }
.rank-no {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 24px; height: 24px; border-radius: 7px; font-size: 13px; font-weight: 700;
  font-family: var(--font-mono); color: var(--ink-500);
  background: var(--bg-paper-2, #f5f6f9);
}
.rank-no-1 { background: #fff3cd; color: #a86b00; }
.rank-no-2 { background: #eceef2; color: #5b6470; }
.rank-no-3 { background: #fbe7d5; color: #9a5b1f; }
html.dark .rank-no-1 { background: #4a3a12; color: #ffd166; }
html.dark .rank-no-2 { background: #33343a; color: #cfd3da; }
html.dark .rank-no-3 { background: #4a3524; color: #f0b27a; }
.rk-name { max-width: 0; }
.rk-nm {
  display: block; color: var(--ink-800);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.rk-un {
  display: block; font-size: 12.5px; color: var(--ink-400);
  font-family: var(--font-mono);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* ---- 图表下钻明细弹框 ---- */
.drill-sum { font-size: 13.5px; color: var(--ink-500); margin-bottom: 8px; }
.drill-scroll {
  max-height: 52vh; overflow: auto;
  border: 1px solid var(--border-line); border-radius: 8px;
}
.drill-table { width: 100%; }
.drill-table thead th {
  position: sticky; top: 0; z-index: 2; background: var(--bg-paper-2, #f5f6f9);
}

/* ---- 用户类别：列表徽章 + 设置弹框 ----
   20261029a 用户定版：徽章**按类别整块填充底色**（原来只有小圆点带色，远看分不出来）
     未设置=灰 · 待跟进=蓝 · 有意向=橙 · 已付费=绿 · 不满意=紫
   🔴 颜色只在这 5 行 .cat-xxx 变量里定义一次，列表徽章（.cat-cell）与弹框选项
      （.cat-opt）共用同一套 —— 改色只改这里，别在别处再写死一个色值。
   🔴 「未设置」不做实色填充：浅灰底 + 深灰字（灰底上白字对比度不足 3:1，
      而且「未设置」本就不该和已分类的一样抢眼）。
   🔴 深色主题见下方 html.dark 段：--cat-soft 必须换深灰，否则整块发白。 */
.cat-none    { --cat-solid: #5c6672; --cat-ink: #5c6672; --cat-bd: #d8dde4; --cat-soft: #eef0f3; }
.cat-follow  { --cat-solid: #2f7cf6; --cat-ink: #2f7cf6; --cat-bd: #bcd4fb; --cat-soft: #eaf2fe; }
.cat-intent  { --cat-solid: #d97a00; --cat-ink: #b37400; --cat-bd: #f6d9ae; --cat-soft: #fff5e6; }
.cat-paid    { --cat-solid: #22a35a; --cat-ink: #1c8b4c; --cat-bd: #b7e3c9; --cat-soft: #e9f8ef; }
.cat-unhappy { --cat-solid: #7c5cf0; --cat-ink: #6b48e0; --cat-bd: #d3c7fb; --cat-soft: #f2eefe; }

.cat-cell {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 3px 10px; border-radius: 999px;
  border: 1px solid transparent;
  background: var(--cat-solid, #8b95a1);
  font-size: 13px; font-weight: 500; color: #fff;
  cursor: pointer; max-width: 220px;
  transition: filter .12s ease, background .12s ease;
}
/* 未设置：浅灰底 + 深灰字（唯一不做实色填充的一档） */
.cat-cell.cat-none {
  background: var(--cat-soft, #eef0f3);
  color: var(--cat-ink, #5c6672);
  border-color: var(--cat-bd, #d8dde4);
}
.cat-cell:hover { filter: brightness(1.08); }
.cat-cell:active { filter: brightness(0.95); }
.cat-cell.cat-none:hover { background: #e3e7eb; filter: none; }
.cat-dot {
  width: 7px; height: 7px; border-radius: 50%; flex: none;
  background: rgba(255, 255, 255, .8);
}
.cat-cell.cat-none .cat-dot { background: #a7b0bb; }
.cat-why {
  font-size: 12px; color: rgba(255, 255, 255, .82);
  max-width: 96px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cat-modal-box { max-width: 520px; }
.cat-who { font-size: 14px; color: var(--ink-600); margin-bottom: 12px; }
.cat-opts { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 12px; }
.cat-opt {
  border: 1px solid var(--cat-bd, var(--border-line));
  background: var(--bg-paper);
  border-radius: 999px; padding: 6px 16px; font-size: 14px;
  color: var(--cat-ink, var(--ink-600)); cursor: pointer;
}
.cat-opt:hover { border-color: var(--cat-solid, var(--ink-200)); }
.cat-opt.on {
  background: var(--cat-solid, var(--accent-500));
  border-color: var(--cat-solid, var(--accent-500));
  color: #fff; font-weight: 600;
}
.cat-reason-box { margin-bottom: 10px; }
.cat-reason-label { font-size: 13.5px; color: var(--ink-500); margin-bottom: 6px; }
.cat-reason-label b { color: #e5484d; font-weight: 600; }
textarea.cat-reason {
  width: 100%; box-sizing: border-box;
  border: 1px solid var(--border-line); border-radius: 8px;
  padding: 8px 10px; font-size: 14px; color: var(--ink-800);
  background: var(--bg-paper); resize: vertical; font-family: inherit;
}
textarea.cat-reason:focus { border-color: var(--accent-500); outline: none; }
.cat-reason-count { text-align: right; font-size: 12px; color: var(--ink-400); }
/* 类别弹框内的校验错误（红字，与列表其它错误提示同色） */
.cat-msg { margin-top: 6px; font-size: 13.5px; color: #e5484d; }

/* 用户类别配色 · 深色主题（20261029a）
   🔴 必须整组覆盖：浅色那套 --cat-soft(#eef0f3) / --cat-ink(#5c6672) 在深底上
      会变成「白块」和「看不见的灰字」；彩色实色按钮则只微调一点点。 */
html.dark .cat-none    { --cat-solid: #474d57; --cat-ink: #b9c1cb; --cat-bd: #4e555f; --cat-soft: #33373e; }
html.dark .cat-follow  { --cat-solid: #3b7ef8; --cat-ink: #7fb2ff; --cat-bd: #2d4a78; --cat-soft: #1e2a3b; }
html.dark .cat-intent  { --cat-solid: #e08a12; --cat-ink: #f2b552; --cat-bd: #6b5330; --cat-soft: #332a1c; }
html.dark .cat-paid    { --cat-solid: #2bb268; --cat-ink: #62d295; --cat-bd: #2f5b44; --cat-soft: #1d3128; }
html.dark .cat-unhappy { --cat-solid: #8b6ef5; --cat-ink: #b4a0fb; --cat-bd: #4d3f7d; --cat-soft: #272238; }
html.dark .cat-cell.cat-none:hover { background: #3c414a; }
html.dark .cat-cell.cat-none .cat-dot { background: #8d959f; }

/* ============================================================
   弹性打卡 v2（20261035a）
   ① 班次弹窗改为「右侧抽屉」：从右浮出、高度满屏
   ② 弹性打卡独立卡片（allow 晚到晚走 / 早到早走 / 晚走换次日）
   ============================================================ */
#shift-form-modal.modal-mask {
  align-items: stretch; justify-content: flex-end; padding: 0;
}
#shift-form-modal .modal-box.sf-modal {
  width: min(1080px, 94vw); max-width: min(1080px, 94vw);
  height: 100vh; max-height: 100vh; border-radius: 0;
  animation: sfDrawerIn .22s ease-out;
}
@keyframes sfDrawerIn {
  from { transform: translateX(100%); }
  to { transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  #shift-form-modal .modal-box.sf-modal { animation: none; }
}

.flex-sw { display: flex; align-items: flex-start; gap: 10px; padding: 12px 0 0; }
.flex-sw + .flex-sw { margin-top: 6px; border-top: 1px dashed var(--border-subtle); padding-top: 14px; }
.flex-sw-txt { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.flex-sw-txt b { font-size: 15px; font-weight: 500; color: var(--ink-900); }
.flex-sw-txt span { font-size: 14px; color: var(--ink-400); line-height: 1.5; }
.flex-pane { display: none; padding: 10px 0 2px 52px; }
.flex-pane.on { display: block; }
.flex-ratio { font-size: 14px; color: var(--ink-400); padding: 9px 0; }
.flex-src-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 10px; }
/* 20261035b（用户 2026-10-27）：班次弹窗字号整体上调，与「规则设置」页对齐 ——
   来源 chip 原为 13px（规则页 .chip-label 是 15px），看着明显比规则页小 */
.flex-src-t { font-size: 15px; color: var(--ink-500); flex: none; }
.chip.flex-src { padding: 6px 11px; gap: 8px; }
.chip.flex-src .chip-label { font-size: 15px; }
.chip.flex-src.is-off { opacity: .38; cursor: not-allowed; }
.flex-note {
  margin-top: 8px; font-size: 14px; color: var(--ink-500);
  background: var(--bg-paper-2); border-radius: 8px; padding: 5px 0; line-height: 1.6;
}
/* 20261035d（用户 2026-10-27）：晚到晚走 / 早到早走 的 1:1 说明不再独占一行，
   改为跟在录入框右侧同行显示 ⇒ 容器一行两件，说明去底色当普通灰字提示。 */
.flex-max-row { display: flex; align-items: center; gap: 12px; min-width: 0; }
.flex-max-row > input {
  flex: 0 0 168px; width: 168px; height: 36px; border-radius: var(--radius-sm, 8px);
  border: 1px solid var(--border-default); background: var(--bg-paper); color: var(--ink-800);
  font: inherit; font-size: 15px; padding: 0 10px; box-sizing: border-box; min-width: 0;
}
.flex-max-row > input:focus {
  outline: none; border-color: var(--accent-500);
  box-shadow: 0 0 0 3px rgba(var(--accent-glow), .12);
}
.flex-max-row > input::placeholder { color: var(--ink-300); }
html.dark .flex-max-row > input { color-scheme: dark; }
.flex-note.flex-note-inline {
  flex: 1 1 auto; min-width: 0; margin-top: 0; padding: 5px 0;
  background: transparent; border-radius: 0;
}
.flex-rules { display: flex; flex-direction: column; gap: 10px; }
/* 一条规则 = 设置行 + 紧随其后的结果提示（20261035b：提示不再堆到列表末尾） */
.flex-rule-item { display: flex; flex-direction: column; gap: 0; }
.flex-rule { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; font-size: 15px; color: var(--ink-700); }
.flex-rule-n { font-size: 14px; color: var(--ink-400); flex: none; min-width: 46px; }
.flex-rule input[type="number"] {
  width: 62px; height: 34px; border-radius: var(--radius-sm, 8px);
  border: 1px solid var(--border-default); background: var(--bg-paper);
  color: var(--ink-800); font: inherit; font-size: 15px; padding: 0 8px;
  box-sizing: border-box; text-align: center;
}
.flex-rule input[type="number"]:focus { outline: none; border-color: var(--accent-500); }
.flex-rule .flex-rule-u { color: var(--ink-400); font-size: 14px; }
.flex-rule-del { margin-left: 4px; color: var(--ink-400); }
.flex-rule-add { margin-top: 10px; }
.flex-rule-hint {
  margin: 6px 0 0 52px; font-size: 14px; color: var(--ink-500);
  background: var(--bg-paper-2); border-radius: 8px; padding: 5px 0; line-height: 1.7;
}
.flex-rule-hint:empty { display: none; }
.flex-rule-hint.is-warn { color: var(--warn-600, #b4791f); background: var(--warn-50, #fdf6e3); }
.flex-next-ot { margin-top: 14px; max-width: 260px; }
html.dark .flex-rule input[type="number"] { color-scheme: dark; }

/* ===== 20261035c：班次编辑抽屉内的字号统一 =====
   用户反馈抽屉里文字比「规则设置」页小一档。统一口径：
     · 字段标签 / 填写值  → 15px（标签再叠 500 字重 + ink-900，见 .sf-lb）
     · 说明性提示文字      → 14px（.flex-note / .flex-rule-hint / .sf-cs / .sf-inh …）
   这里用抽屉作用域兜底一遍，避免散落各处的 select / textarea / 提示类漏改。 */
#shift-form-modal .sf-f > input,
#shift-form-modal .sf-f > select,
#shift-form-modal .sf-f > .select-wrap > select,
#shift-form-modal .sf-range input,
#shift-form-modal .flex-rule input[type="number"],
#shift-form-modal .flex-inline-row input[type="number"],
#shift-form-modal input.input,
#shift-form-modal textarea {
  font-size: 15px;
}
#shift-form-modal .sf-f > textarea { font-size: 15px; line-height: 1.6; }
/* 说明性提示：统一 14px，行高略放开保证可读 */
#shift-form-modal .sf-cs,
#shift-form-modal .flex-note,
#shift-form-modal .flex-rule-hint,
#shift-form-modal .flex-rule-n,
#shift-form-modal .flex-rule .flex-rule-u,
#shift-form-modal .flex-sw-txt span,
#shift-form-modal .flex-ratio,
#shift-form-modal .sf-inh,
#shift-form-modal .field-help,
#shift-form-modal .cfg-tip,
#shift-form-modal .ot-rule-demo-note,
#shift-form-modal .noon-note,
#shift-form-modal .mc-setup-hint,
#shift-form-modal .tpl-note,
#shift-form-modal .muted,
#shift-form-modal .warn {
  font-size: 14px;
}
#shift-form-modal .sf-lb { font-size: 15px; font-weight: 500; color: var(--ink-900); }
/* 「计入来源」是字段标签而非说明文字，跟标签同级 */
#shift-form-modal .flex-src-t { font-size: 15px; color: var(--ink-500); }

/* ============================================================
   弹框统一按钮（20261035f，用户定版）
   ① 右下角对齐的弹框：保存按钮左侧统一有「取消」（白色样式）
   ② 所有右上角关闭按钮：统一浅红色样式
   颜色沿用站内既有的浅红体系（#fdeceb 底 / #f5b5b0 边 / 深红字）
   ============================================================ */

/* —— 取消：白色（比 .btn-ghost 的浅蓝底更中性，视觉上不抢保存按钮） —— */
.btn.btn-cancel:not(:disabled) {
  background: var(--bg-card);
  border-color: var(--ink-200);
  color: var(--ink-700);
}
.btn.btn-cancel:not(:disabled):hover {
  background: var(--bg-paper-2);
  border-color: var(--ink-300);
  color: var(--ink-900);
  transform: none;
  box-shadow: none;
}
.btn.btn-cancel:not(:disabled):active { transform: translateY(1px); box-shadow: none; }
html.dark .btn.btn-cancel:not(:disabled) {
  background: var(--bg-paper-2); border-color: var(--border-strong); color: var(--ink-800);
}
html.dark .btn.btn-cancel:not(:disabled):hover {
  background: var(--ink-100); border-color: var(--ink-300); color: var(--ink-900);
}

/* —— 右上角关闭：浅红（含方角 ✕、圆形 ck-close） —— */
.btn.modal-close:not(:disabled),
.ck-close {
  background: #fdeceb;
  border-color: #f5b5b0;
  color: #d0342c;
}
.btn.modal-close:not(:disabled):hover,
.ck-close:hover {
  background: #fbdbd8;
  border-color: #eda9a3;
  color: #b3261e;
}
html.dark .btn.modal-close:not(:disabled),
html.dark .ck-close {
  background: rgba(248, 113, 113, .16);
  border-color: rgba(248, 113, 113, .32);
  color: #ff8a84;
}
html.dark .btn.modal-close:not(:disabled):hover,
html.dark .ck-close:hover {
  background: rgba(248, 113, 113, .28);
  border-color: rgba(248, 113, 113, .48);
  color: #ffb3ae;
}

/* 订阅/升级弹框顶部是蓝色渐变，浅红底改实色才看得清 */
.sub-modal-close {
  background: #fdeceb;
  border: 1px solid rgba(255, 255, 255, .55);
  color: #d0342c;
}
.sub-modal-close:hover { background: #fbdbd8; color: #b3261e; }


/* ==================== 系统配置 · 节假日管理（20261036a） ====================
   12 个月一屏（auto-fill 自适应列数），每格 = 一天，点一下循环切换
   无 → 3倍 → 2倍 → 补班 → 无。颜色只表达「这一天属于哪一类」，不与考勤表配色冲突。 */
.hol-bar {
  display: flex; align-items: center; flex-wrap: wrap; gap: 6px 16px;
  padding: 10px 14px; margin-bottom: 14px;
  background: var(--bg-paper-2); border-radius: var(--radius-md);
  font-size: 13.5px; color: var(--ink-500);
}
.hol-lg { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
.hol-dot { width: 10px; height: 10px; border-radius: 3px; display: inline-block; flex: none; }
.hol-dot.d3 { background: #dc2626; }
.hol-dot.d2 { background: #d97706; }
.hol-dot.dm { background: #0071e3; }
.hol-bar-hint { color: var(--ink-400); font-size: 13px; }
.hol-bar .grow { flex: 1 1 auto; }
#hol-stat { font-size: 13px; white-space: nowrap; }

.hol-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(270px, 1fr));
  gap: 12px; align-items: start; padding-bottom: 8px;
}
.hol-m {
  background: var(--bg-paper); border: 1px solid var(--border-subtle);
  border-radius: 10px; padding: 10px 12px 12px;
}
.hol-m-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 7px; }
.hol-m-name { font-size: 14.5px; font-weight: 600; color: var(--ink-900); }
.hol-m-cnt { font-size: 12px; color: var(--ink-400); }
.hol-m-cnt.has { color: var(--accent-600); font-weight: 600; }
.hol-cal { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 3px; }
.hol-wd { text-align: center; font-size: 11px; color: var(--ink-300); padding-bottom: 2px; }
.hol-d {
  height: 30px; display: flex; align-items: center; justify-content: center;
  font-size: 12.5px; font-family: inherit; line-height: 1;
  color: var(--ink-700); background: var(--bg-tinted);
  border: 1px solid transparent; border-radius: 6px;
  cursor: pointer; padding: 0;
  transition: background .12s, color .12s, border-color .12s;
}
.hol-d:hover { border-color: var(--accent-300); }
.hol-d.is-blank { background: transparent; border-color: transparent; cursor: default; }
.hol-d.is-blank:hover { border-color: transparent; }
.hol-d.is-wk { color: var(--ink-400); background: var(--bg-paper-2); }
.hol-d.is-3x { background: #fdecec; border-color: #f5b5b0; color: #c0261d; font-weight: 600; }
.hol-d.is-2x { background: #fffbeb; border-color: #f6cd6e; color: #a15c00; font-weight: 600; }
.hol-d.is-makeup { background: #d5e9ff; border-color: #7ab8f5; color: #0056ad; font-weight: 600; }
html.dark .hol-d.is-3x { background: rgba(248,113,113,.18); border-color: rgba(248,113,113,.42); color: #ff9a94; }
html.dark .hol-d.is-2x { background: rgba(238,185,47,.18); border-color: rgba(238,185,47,.42); color: #f6cd6e; }
html.dark .hol-d.is-makeup { background: rgba(0,113,227,.24); border-color: rgba(122,184,245,.45); color: #8ec2ff; }

/* 20261036b：「节假日管理」子菜单无图标 —— 左缩进对齐父项文字（10px padding + 24px icon + 9px gap） */
.side-item[data-page="holidays"].side-sub { padding-left: 43px; }

/* ==================== 20261036c/d：侧栏折叠组 + 通用年份选择器（year-picker.js） ==================== */
/* 「系统配置」父项右侧展开箭头：收起朝右、展开转 90° 朝下 */
.side-item .side-arrow {
  margin-left: auto; flex-shrink: 0; color: var(--ink-400);
  transition: transform .18s var(--ease-out-quart);
}
.side-item.side-group-open .side-arrow { transform: rotate(90deg); }
.side-item.side-group-open { background: var(--bg-hover); }

/* 年份选择器：触发按钮沿用 .adm-select 观感，弹层网格 4 列 × 3 行 */
.yp-wrap { position: relative; }
.yp-btn {
  min-width: 96px; height: 32px; padding: 0 10px; text-align: center; cursor: pointer; user-select: none;
  font-family: inherit; font-size: 14px; color: var(--ink-900);
  background-color: var(--bg-paper); border: 1px solid var(--border-default); border-radius: var(--radius-md);
}
.yp-btn:focus { outline: none; border-color: var(--accent-500); }
.yp-pop {
  position: absolute; top: calc(100% + 6px); right: 0; z-index: 40;
  width: 264px; padding: 10px;
  background: var(--bg-paper); border: 1px solid var(--border-subtle);
  border-radius: 10px; box-shadow: 0 10px 30px rgba(0,0,0,.14);
}
.yp-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.yp-range { font-size: 13.5px; font-weight: 600; color: var(--ink-900); }
.yp-nav {
  width: 26px; height: 26px; border: none; border-radius: 6px; cursor: pointer;
  background: var(--bg-tinted); color: var(--ink-700); font-size: 16px; line-height: 1;
}
.yp-nav:hover:not(:disabled) { background: var(--bg-hover); }
.yp-nav:disabled { opacity: .35; cursor: default; }
.yp-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 4px; }
.yp-cell {
  height: 30px; border: 1px solid transparent; border-radius: 6px; cursor: pointer;
  background: var(--bg-tinted); color: var(--ink-700); font-size: 13px; font-family: inherit;
}
.yp-cell:hover { border-color: var(--accent-300); }
.yp-cell.cur { background: var(--accent-500); color: #fff; font-weight: 600; }
.yp-cell.off { opacity: .32; cursor: default; }
.yp-tip { margin-top: 8px; font-size: 11.5px; color: var(--ink-400); text-align: center; }

/* ==================== 取整规则库（20261037b 改版） ====================
   列表铺满展示（名称/类型/内容/操作）+ 弹框编辑（#rr-modal：正班/加班两个模块）。
   字段标签与提示已去掉；「+ 新增规则」挂在子页页头 h2 右侧（.cfg-h2-act）。
   老的三栏卡片布局（.rr-card/.rr-side 等）已随 37b 删除。
   20261037c：列表去白底；弹框改用班次弹窗同款 sf-card 灰底卡片 + sf-lb 标签；
   取整配置形式提升为规则级（规则名称下方）；取整类型按用户原文句子式 + 示例。 */
.cfg-phd h2 { display: flex; align-items: center; gap: 10px; }
.cfg-h2-act { margin-left: auto; }
/* 取整规则库字段：覆盖 #global-config-body .field 的 row+center 布局，
   改为纵向排列、交叉轴 stretch —— 让 toolbar（新增按钮行）与表格铺满整行宽度。
   必须用 #global-config-body 前缀提特异性，否则盖不过 ID 选择器 */
#global-config-body .rr-field { width: 100%; flex-direction: column; align-items: stretch; gap: 8px; }
/* 20261037d：工具行（新增规则按钮）在表格上方，按钮靠左。
   width:100% 强制撑满父级（.field 是 column flex，交叉轴未 stretch 时 toolbar 会缩到内容宽）。 */
.rr-toolbar { display: flex; justify-content: flex-start; width: 100%; margin-bottom: 8px; }
.rr-table { width: 100%; border-collapse: collapse; }
.rr-table th {
  text-align: left; font-size: 14px; font-weight: 600; color: var(--ink-600);
  padding: 9px 12px; border-bottom: 1px solid var(--border-subtle); white-space: nowrap;
}
.rr-table td {
  padding: 11px 12px; font-size: 15px; color: var(--ink-900);
  border-bottom: 1px solid var(--border-subtle); vertical-align: middle;
}
.rr-table tbody tr:last-child td { border-bottom: none; }
.rr-table tbody tr:hover td { background: var(--bg-paper-2); }
.rr-td-name { display: flex; align-items: center; gap: 8px; font-weight: 500; white-space: nowrap; }
.rr-td-desc { min-width: 200px; }
.rr-td-ops { white-space: nowrap; }
.rr-td-ops .btn + .btn { margin-left: 6px; }
.rr-def-badge {
  display: inline-block; padding: 1px 8px; border-radius: 999px;
  font-size: 11.5px; font-weight: 600; line-height: 18px;
  color: var(--accent-600, #2563eb); background: var(--accent-50, #eff6ff);
  border: 1px solid var(--accent-200, #bfdbfe); white-space: nowrap;
}
/* 弹框：复用班次弹窗的 sf-card/sf-f/sf-lb/sf-grid（班次时间与加班同款观感） */
.rr-modal-box { width: 720px; max-width: 94vw; padding: 0; }
.rr-modal-box .modal-head { margin-bottom: 0; padding: 10px 16px 8px; border-bottom: 1px solid var(--border-subtle); }
.rr-modal-box .modal-body { max-height: 70vh; overflow-y: auto; padding: 12px 16px 14px; }
.rr-modal-box .modal-actions { margin-top: 0; padding: 10px 16px 12px; }
.rr-modal-box .sf-card { margin-bottom: 12px; }
.rr-modal-box .sf-card:last-child { margin-bottom: 0; }
.rr-modal-box .sf-card-hd { margin-bottom: 10px; }
.rr-modal-box .sf-card-hd .link-btn { margin-left: auto; font-size: 13px; }
/* 单列纵向排布（复用 .sf-g1 = grid 1fr，去掉多余 gap 覆盖） */
.rr-modal-box .sf-g1 { gap: 10px; }
/* 20261037c：正班/加班的字段改为左右布局——标签在左、控件在右（顶层规则名称/取整
   配置形式那一卡保持上下布局，见 .rr-card-top） */
.rr-modal-box .sf-g1 .sf-f { flex-direction: row; align-items: center; gap: 12px; }
.rr-modal-box .sf-g1 .sf-lb { flex: none; width: 96px; font-size: 13.5px; justify-content: flex-end; }
.rr-modal-box .sf-g1 .sf-f > .select-wrap,
.rr-modal-box .sf-g1 .sf-f > input { width: auto; }
.rr-modal-box .sf-g1 .sf-f > .select-wrap select { width: 200px; }
/* 区间行 / 提示 / 句子式控件占满剩余宽度 */
.rr-modal-box .sf-g1 .rr-ivs,
.rr-modal-box .sf-g1 .rr-tip,
.rr-modal-box .sf-g1 .rr-sentence { flex: 1; min-width: 0; }
/* 无左侧标题的句子式行（递增时长）：与上方下拉框左对齐
   （label 96px + gap 12px = 108px，与 .rr-tip 同口径），不与左侧标签对齐 */
.rr-modal-box .sf-g1 .sf-f-nolabel { padding-left: 108px; }
.rr-modal-box .sf-g1 .sf-f-nolabel .rr-sentence { flex: none; }
/* 下拉箭头走全站统一 select 背景三角（见「全站下拉选择框箭头统一」段），
   不再单独用 ::after 画 chevron —— 保持全局一致 */
/* 句子式「按 X 分钟为最小时长递增」 */
.rr-sentence { display: flex; align-items: center; gap: 6px; font-size: 14px; color: var(--ink-700); }
.rr-x { width: 64px; text-align: center; height: 36px !important; }
/* 类型提示 + 示例（sf-card 内独立行，紧跟取整类型下方；
   20261037c 左对齐到控件列（label 96px + gap 12px），不与左侧标题对齐） */
.rr-tip {
  margin: 0 0 0 108px; padding: 8px 12px; border-radius: 8px;
  background: var(--bg-paper); font-size: 13px; color: var(--ink-700); line-height: 1.7;
  border: 1px solid var(--border-subtle);
}
.rr-tip-eg { color: var(--ink-500); }
.rr-ivs { display: flex; flex-direction: column; gap: 6px; }
.rr-iv-empty { font-size: 12.5px; }

/* ============================================================
   配置考勤汇总表格格式 · 快捷格式（内置格式模板 20261039a / 重设计 20261039b）
   页面上半部分 = 「快捷格式」模板卡片区；下半部分 = 原配置明细表格。
   缩略图 = 极简色块示意（窄卡片里塞文字表头会糊成一团，实测踩过）；
   点缩略图打开的大图才显示完整列头与真实示例值。

   20261039b 用户定版（改之前先读，别把这几条又改回去）：
     ① 卡片里不再出现「指标 N 项 · 每日明细 开/关」那一行；
     ② 「默认 / 当前选择」统一为药丸标签，绝对定位悬浮卡片右上角
        （top:-8px 跨在卡片上边框上；列表 padding-top 留出探出的高度）；
     ③ 标题「格式模板」→「快捷格式」，右侧说明文字整条删除；
     ④ 卡片标题与描述之间用 3px 小间距（.de-tpl-txt 的 gap），**不再用 min-height 撑行数** ——
        原来 1 行名的卡片会凭空多出 ~15px 留白，看着像间距错乱；
     ⑤ 选中态 = 2px 蓝色描边（outline，不参与布局），**不要蓝色光晕阴影**；
     ⑥ 卡片等高等宽、按钮吸底（margin-top:auto）—— 8 张卡片底部按钮必须一条线。
   ============================================================ */
.de-body.has-tpl .de-table-wrap { flex: 1 1 auto; }
.de-tpl { flex: 0 0 auto; background: var(--bg-paper-2); border: 1px solid var(--border-default);
  border-radius: 10px; padding: 12px 14px 12px; }
/* 标题行：左侧 3px 蓝色竖条做视觉锚点；下边一条细分隔线，与下方卡片区分层次 */
.de-tpl-head { display: flex; align-items: center; gap: 10px; margin-bottom: 10px;
  padding-bottom: 9px; border-bottom: 1px solid var(--border-subtle); }
.de-tpl-title { position: relative; padding-left: 10px; font-size: 14px; font-weight: 600;
  letter-spacing: .2px; color: var(--ink-800); }
.de-tpl-title::before { content: ''; position: absolute; left: 0; top: 50%;
  transform: translateY(-50%); width: 3px; height: 13px; border-radius: 2px;
  background: var(--accent-500); }
/* 卡片等分：宽屏一屏能看到全部 8 个模板，窄屏才横向滚动。
   上 padding 9px = 药丸标签探出卡片上边框的高度，留不够会被 overflow 裁掉 */
.de-tpl-list { display: flex; align-items: stretch; gap: 10px; overflow-x: auto;
  overflow-y: hidden; padding: 9px 2px 4px; }
/* 20261039c：整张卡片可点 = 直接应用（cursor + hover 上浮 + :active 回落） */
.de-tpl-card { position: relative; flex: 1 1 0; min-width: 148px; max-width: 244px;
  display: flex; flex-direction: column; gap: 8px; padding: 10px; cursor: pointer;
  background: var(--bg-paper); border: 1px solid var(--border-default); border-radius: 10px;
  box-shadow: var(--shadow-xs);
  transition: border-color .16s var(--ease-out-quart), transform .16s var(--ease-out-quart),
    box-shadow .16s var(--ease-out-quart); }
.de-tpl-card:hover { border-color: var(--accent-300); transform: translateY(-1px);
  box-shadow: var(--shadow-sm); }
.de-tpl-card:active { transform: translateY(0); }
.de-tpl-card:focus-visible { outline: 2px solid var(--accent-500); outline-offset: 2px; }
/* 选中：2px 蓝色描边（outline 不参与布局 ⇒ 卡片不会被撑大、内容不位移）+ 极浅蓝顶色 */
/* 选中：只有一圈 2px 蓝环 —— border 置透明让 outline 顶上去（不再 1px 边框 + 2px outline
   叠成 3px 的"双重描边"），也不铺顶部蓝色渐变（用户口径：不要蓝色阴影/光晕） */
.de-tpl-card.on { border-color: transparent; outline: 2px solid var(--accent-500);
  outline-offset: -2px; }
/* 药丸标签：悬浮在卡片右上角（跨在上边框上，探出 8px）。
   20261039c：只剩「当前选择」一个（「默认」标签按用户口径删除） */
.de-tpl-bads { position: absolute; top: -8px; right: 10px; z-index: 3;
  display: flex; align-items: center; gap: 5px; pointer-events: none; }
.de-tpl-badge { height: 17px; line-height: 17px; padding: 0 8px; border-radius: 999px;
  font-size: 10.5px; font-weight: 600; letter-spacing: .2px; white-space: nowrap;
  box-shadow: 0 1px 3px rgba(15, 23, 42, .14); }
.de-tpl-badge.is-cur { background: linear-gradient(135deg, var(--accent-500), var(--accent-600));
  color: #fff; }
.de-tpl-badge.hidden { display: none; }
/* 缩略图：白底 + 细边，hover 时边框转蓝提示「可点开」 */
.de-tpl-thumb { position: relative; cursor: zoom-in; border: 1px solid var(--border-subtle);
  border-radius: 8px; overflow: hidden; background: var(--bg-paper); padding: 5px;
  /* 固定高度：行数少的模板（1~2 行）靠行高均分撑满，8 张缩略图高度一致 */
  height: 74px; box-sizing: border-box;
  transition: border-color .16s, background .16s; }
/* 悬停提示：告诉用户「点这里看大图」（卡片本身点一下就应用，缩略图是唯一的例外）。
   ::after = 半透明蒙层（只压 30%），::before = 居中药丸文字 —— 比裸文字更清爽 */
.de-tpl-thumb::after { content: ''; position: absolute; inset: 0;
  background: rgba(15, 23, 42, .30); opacity: 0;
  transition: opacity .16s; pointer-events: none; }
.de-tpl-thumb:hover::after { opacity: 1; }
.de-tpl-thumb::before { content: '查看大图'; position: absolute; left: 50%; top: 50%; z-index: 2;
  transform: translate(-50%, -50%) scale(.94); height: 20px; line-height: 20px; padding: 0 10px;
  border-radius: 999px; background: rgba(15, 23, 42, .74); color: #fff;
  font-size: 11px; letter-spacing: .3px; white-space: nowrap;
  opacity: 0; transition: opacity .16s, transform .16s; pointer-events: none; }
.de-tpl-thumb:hover::before { opacity: 1; transform: translate(-50%, -50%) scale(1); }
.de-tpl-card:hover .de-tpl-thumb { border-color: var(--accent-200); }
/* 缩略图（20261039c 重做）：真表格等比缩小 —— 细线网格 + 浅灰表头 + 淡蓝汇总列。
   固定 3 行 ⇒ 8 张卡片等高；完整列头与真实示例值在点开的大图里。 */
.de-tpl-mini { width: 100%; height: 100%; border-collapse: collapse; table-layout: fixed;
  font-size: 9.5px; line-height: 1.1; }
.de-tpl-mini th, .de-tpl-mini td { padding: 1px; border: 1px solid var(--border-subtle);
  text-align: center; vertical-align: middle; color: var(--ink-500); font-weight: 400;
  overflow: hidden; white-space: nowrap; background: transparent; }
.de-tpl-mini thead th { background: var(--ink-100); color: var(--ink-300);
  font-weight: 500; font-size: 9px; }
/* 深色下细线太淡（--border-subtle 只有 7% 白），缩略图的"网格感"会消失 → 单独提亮 */
html.dark .de-tpl-mini th, html.dark .de-tpl-mini td { border-color: rgba(255, 255, 255, .16); }
/* 首列（指标项 / 姓名）：宽 34%，左对齐 + 4 字截断 */
.de-tpl-mini .m-c1 { width: 34%; text-align: left; padding-left: 3px; }
.de-tpl-mini thead th.m-c1 { color: var(--ink-300); }
.de-tpl-mini td.m-c1 { color: var(--ink-600); font-size: 9px; }
/* 汇总列（20261039d 用户定版）：**缩略图里不出现任何蓝字/蓝底** ——
   数值用深灰加粗、表头与普通表头同款灰底，靠"加粗 + 与左侧留白"区分即可 */
.de-tpl-mini .m-sum { color: var(--ink-700); font-weight: 600; }
.de-tpl-mini thead th.m-sum { background: var(--ink-100); color: var(--ink-300);
  font-weight: 500; }
/* 空值：一小段灰短线，比留白更像"表格里的空" */
.de-tpl-mini i.m-nil { display: inline-block; width: 8px; height: 2px; border-radius: 1px;
  background: var(--ink-200); vertical-align: middle; }
/* 标题 + 描述成组（3px 小间距），与缩略图/按钮之间仍是 8px —— 层内紧、层间松 */
.de-tpl-txt { display: flex; flex-direction: column; gap: 3px; }
.de-tpl-name { font-size: 13px; font-weight: 600; color: var(--ink-800); line-height: 1.35;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  /* 长名两行时均分断行，避免「上下午时长加平时加班格 / 式」这种单字孤行 */
  text-wrap: balance; }
.de-tpl-desc { font-size: 11.5px; color: var(--ink-400); line-height: 1.5;
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
/* 按钮吸底：卡片高度不一致时也让 8 个按钮落在同一条基线上 */
.de-tpl-apply { margin-top: auto; height: 28px; border-radius: 7px;
  border: 1px solid var(--accent-500); background: var(--bg-paper); color: var(--accent-600);
  font-size: 12px; font-weight: 500; cursor: pointer;
  transition: background .16s, color .16s, border-color .16s; }
.de-tpl-apply:hover { background: var(--accent-500); color: #fff; }
.de-tpl-apply.is-cur { border-color: var(--border-default); background: var(--bg-paper-2);
  color: var(--ink-400); cursor: default; }
.de-tpl-apply.is-cur:hover { background: var(--bg-paper-2); color: var(--ink-400); }
/* 大图（点缩略图）：完整列头 + 真实示例值 */
.de-tpl-zoom { position: fixed; inset: 0; z-index: 1200; background: rgba(15, 23, 42, .46);
  -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px);
  display: flex; align-items: center; justify-content: center; padding: 24px; }
.de-tpl-zoom.hidden { display: none; }
.de-tpl-zoom-box { background: var(--bg-paper); border: 1px solid var(--border-default);
  border-radius: 14px; padding: 16px 18px 18px; max-width: 92vw; max-height: 88vh;
  overflow: auto; box-shadow: var(--shadow-lg); }
.de-tpl-zoom-head { display: flex; align-items: center; gap: 16px; }
.de-tpl-zoom-title { font-size: 16px; font-weight: 600; color: var(--ink-900); }
.de-tpl-zoom-title i { font-style: normal; font-size: 13px; font-weight: 400; color: var(--ink-400);
  margin-left: 6px; }
.de-tpl-zoom-x { margin-left: auto; height: 28px; padding: 0 13px; border-radius: 999px;
  border: 1px solid var(--border-default); background: var(--bg-paper); font-size: 12.5px;
  color: var(--ink-600); cursor: pointer; transition: background .16s, border-color .16s; }
.de-tpl-zoom-x:hover { background: var(--bg-paper-2); border-color: var(--border-strong); }
.de-tpl-zoom-desc { font-size: 12.5px; color: var(--ink-400); margin: 5px 0 12px; }
.de-tpl-tbl { border-collapse: collapse; }
.de-tpl-tbl th, .de-tpl-tbl td { border: 1px solid var(--border-hairline); padding: 2px 6px;
  text-align: center; white-space: nowrap; color: var(--ink-500); }
.de-tpl-tbl thead th { background: var(--bg-paper-2); font-weight: 500; color: var(--ink-600); }
.de-tpl-tbl .c-ind { text-align: left; }
.de-tpl-tbl .c-sum { background: var(--bg-tinted); }
.de-tpl-tbl.is-big td[rowspan] { vertical-align: middle; }
.de-tpl-tbl.is-big { font-size: 12.5px; }
.de-tpl-tbl.is-big th, .de-tpl-tbl.is-big td { padding: 6px 12px; }
.de-tpl-tbl.is-big .c-seq { width: 58px; }
.de-tpl-tbl.is-big .c-nm { width: 78px; }
.de-tpl-tbl.is-big .c-dept { width: 78px; }
.de-tpl-tbl.is-big .c-ind { width: 118px; }

/* ---------- 显示字段弹框（20261043a，结果页「统计范围」右侧） ---------- */
.hf-card { top: 50%; width: min(720px, calc(100vw - 48px)); }
.hf-tools {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 10px 16px; border-bottom: 1px solid var(--ink-100);
}
.hf-count { font-size: 12px; color: var(--ink-500); }
.hf-body { padding: 8px 16px 14px; max-height: 52vh; overflow: auto; }
.hf-grp { margin-top: 10px; }
/* 分组标题行：左标题 + 右「全选 / 全不选」（20261043b 拆到组内各自控制） */
.hf-grp-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 8px; margin-bottom: 6px;
}
.hf-grp-t { font-size: 12px; font-weight: 600; color: var(--ink-600); }
.hf-grp-tools { display: flex; gap: 4px; }
.hf-grp-tools .btn { padding: 1px 8px; font-size: 12px; line-height: 18px; }
/* 字段等宽：auto-fill + 1fr 均分，每列宽度一致（20261043b） */
.hf-grp-list {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(112px, 1fr));
  gap: 6px 8px;
}
.hf-item {
  display: flex; align-items: center; gap: 6px; width: 100%; min-width: 0;
  box-sizing: border-box;
  padding: 3px 9px; border: 1px solid var(--ink-100); border-radius: 6px;
  background: var(--ink-50); font-size: 13px; color: var(--ink-700); cursor: pointer;
}
.hf-item > span {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.hf-item:hover { border-color: var(--brand); }
.hf-foot {
  display: flex; justify-content: flex-end; gap: 8px;
  padding: 10px 16px; border-top: 1px solid var(--ink-100);
}
