/* ==========================================================
 * 报价助手 · 基础样式（客户端与后台共用）
 * 设计语言：Windows 11 Fluent
 *   - 字体 Segoe UI Variable / Segoe UI（中文回退微软雅黑）
 *   - Mica 云母浅灰底 + 一颗旧的 Win11 蓝
 *   - 圆角卡片 + 柔和分层阴影 + 突出按钮（厚度+浮起+高光）
 * 主题变量、按钮/卡片/模态框/表单/标签页、规则表格、匹配状态标记
 * ========================================================== */

:root {
  /* ===== 新拟物（Neumorphism）配色 · 2026-10-25 用户定稿 =====
   * 底色单色 #e0e5ec；卡片同族提亮（保留亮度差，保证「扫一眼分得出区域」）。
   * 强调色 = #248bc8（2026-10-26 用户改定；此前依次为紫 #248bc8、一颗旧的 Win11 蓝）。
   * ⚠️ 卡片与页面刻意不做成完全同色：纯同色会让数据页丢掉边界（用户明确要求可用性优先）。 */
  --bg: #e0e5ec; --card: #f0f0f3; --card-hover: #ebebef;
  --text: #333333; --muted: #6b7280; --text-dim: #6b7280;
  --brand: #248bc8; --brand-dark: #1e72a4;
  --link: #1e72a4;                            /* 链接用加深版：#248bc8 作 13px 文字仅 3.3:1 */
  --on-brand: #ffffff;
  --line: rgba(150,159,172,0.28); --border-strong: rgba(150,159,172,0.42);
  --fill-hover: rgba(36,139,200,0.06); --fill-press: rgba(36,139,200,0.11);
  --btn: #e5e9ef; --btn-hover: #dce2ea; --btn-press: #d3dae4;   /* btn-press = 色板 Secondary */
  /* ===== 语义色：严格取规范 [配色方案] + [颜色角色] 的 4 个强调色 =====
   * Accent 1 #248bc8 → brand；加深版 #1e72a4 → link / fuzzy（文字要 4.5:1）
   * Accent 2 #ff6b6b → mark（原色）/ up（文字加深版）
   * Accent 3 #4ecdc4 → tint（原色）/ down（文字加深版，成功·通过·已定标）
   * Accent 4 #ffe66d → warn-soft（原色）/ warn（文字加深版，警告·待处理）
   * ⚠️ 色相只有这 4 个；文字需要更深时只调明度，❌ 不得换色相。 */
  --up: #db0000; --down: #227771; --fuzzy: #1e72a4; --undecided: #6b7280;
  --warn: #806a00; --warn-soft: #ffe66d;
  /* Accent 3 的墨色版：青 #4ecdc4 只能压深底（1.5:1），要落在浅底上就用这一档 */
  --tint-ink: #227771;
  /* 图标与「试算/统计」类文字的统一着色（2026-10-26 用户约定 #4ecdc4）。
   * ⚠️ 这是浅青色：在浅底上对比只有 1.5:1，只适合「深底 / 大字号 / 图标」，
   *    深色模式的提亮版反之（对深底 9.4:1）。正文小字请勿直接用它。 */
  --tint: #4ecdc4;
  /* 必填标记（2026-10-26 用户约定）：红色星号统一改为 #ff6b6b 圆点 */
  --mark: #ff6b6b;
  /* 列表标记：四角星裁剪路径（2026-10-26 全站统一，改形状只改这一处） */
  --star4: polygon(50% 0%, 62% 38%, 100% 50%, 62% 62%, 50% 100%, 38% 62%, 0% 50%, 38% 38%);
  --radius: 18px; --radius-sm: 12px;

  /* ===== 双光源材质（唯一事实源，2026-10-25 起）=====
   * 光源固定左上：负偏移 = #ffffff 高光，正偏移 = #b8bcc2 暗影。
   * ❌ 不得在组件里手写 box-shadow；❌ 不得翻转光源方向。
   * 交互约定：hover 阴影「缩小」（手指靠近遮光），active 就地 inset（元素长在表面上，不位移）。 */
  --raised-1: 4px 4px 8px #b8bcc2, -4px -4px 8px #ffffff;
  --raised-2: 6px 6px 12px #b8bcc2, -6px -6px 12px #ffffff;
  --raised-3: 8px 8px 16px #b8bcc2, -8px -8px 16px #ffffff;
  /* 按下 = 由凸转凹，物理上「压进表面」 */
  --press-1: inset 5px 5px 10px #b8bcc2, inset -5px -5px 10px #ffffff;
  /* 凹面：输入框 / 拖放区 / 分段控件轨道 */
  --sunken-1: inset 4px 4px 8px #b8bcc2, inset -4px -4px 8px #ffffff;
  --sunken-2: inset 6px 6px 12px #b8bcc2, inset -6px -6px 12px #ffffff;
  --sunken-bg: #dbe1e9;
  /* focus = 凹得更浅（通道打开），不是更深 */
  --sunken-focus: inset 2px 2px 4px #b8bcc2, inset -2px -2px 4px #ffffff;

  /* 兼容旧引用：把 1/2 号阴影改指到新材质，历史组件自动升级 */
  --shadow-1: var(--raised-1); --shadow-2: var(--raised-3);
}
/* ⚠️ 深色变量同时挂在 <html> 与 <body> 上（2026-10-25）：
 *   · <html>.dark 负责**首帧画布底色**（js/theme-boot.js 在 body 第一行就打上），
 *     否则切页面时会先按 :root 的浅色画一帧，看着像"白闪"；
 *   · <body>.dark 仍是下面 65 处 `body.dark …` 组件规则的唯一事实源，未改动。
 *   两者值完全一致，改这里等于同时改两处，不存在漂移。 */
body.dark, html.dark {
  /* 深色映射（规范只给浅色）：同一套双光源逻辑反相 —— 暗影更暗，亮影只是「没那么暗」的灰 */
  --bg: #2b2f36; --card: #343941; --card-hover: #3a3f48;
  --text: #eef1f5; --muted: #a8b0bb; --text-dim: #a8b0bb;
  --brand: #75bce6; --brand-dark: #93cbec;
  /* 深色下亮蓝底必须配深字：白字对 #75bce6 只有 2.1:1，实测发糊 */
  --on-brand: #0c2d41;
  --line: rgba(255,255,255,0.09); --border-strong: rgba(255,255,255,0.15);
  --fill-hover: rgba(90,174,224,0.10); --fill-press: rgba(90,174,224,0.16);
  --btn: #333841; --btn-hover: #3a4049; --btn-press: #424852;
  --link: #75bce6;
  --up: #ff7a7a; --down: #79d9d2; --fuzzy: #75bce6;
  --warn: #ffe66d; --warn-soft: #ffe66d;
  --tint-ink: #79d9d2;
  /* 深色下提亮一档：对深底 9.4:1，反而是这组色里最稳的一处 */
  --tint: #79d9d2;
  --mark: #ff7a7a;
  --raised-1: 4px 4px 8px #212429, -4px -4px 8px #3a3f47;
  --raised-2: 6px 6px 12px #212429, -6px -6px 12px #3a3f47;
  --raised-3: 8px 8px 16px #212429, -8px -8px 16px #3a3f47;
  --press-1: inset 5px 5px 10px #212429, inset -5px -5px 10px #3a3f47;
  --sunken-1: inset 4px 4px 8px #212429, inset -4px -4px 8px #3a3f47;
  --sunken-2: inset 6px 6px 12px #212429, inset -6px -6px 12px #3a3f47;
  --sunken-bg: #262a31;
  --sunken-focus: inset 2px 2px 4px #212429, inset -2px -2px 4px #3a3f47;
  --shadow-1: var(--raised-1); --shadow-2: var(--raised-3);
  /* 原生控件（滚动条 / 日期图标 / 选择框弹层）跟随深色；
     js/theme-boot.js 还会在 <html> 上写同值的内联 color-scheme，二者一致。 */
  color-scheme: dark;
  background: var(--bg);   /* 新拟物禁止渐变底 */
}

* { box-sizing: border-box; margin: 0; padding: 0; }
/* 画布底色（2026-10-25）：<html> 也取主题色，避免橡皮筋滚动 / 首帧露出浏览器默认白底。
   深色由上面 `html.dark` 的同一组变量覆盖。 */
html { background: var(--bg); }
body {
  font-family: "Segoe UI Variable", "Segoe UI", "Microsoft YaHei", "PingFang SC", sans-serif;
  min-height: 100vh;   /* 内容短于视口时底色也要铺满，否则页脚下方出现横向色阶断线（实测 register 449px / 视口 900px） */
  background: var(--bg);   /* 新拟物：单色底，禁用渐变 */
  color: var(--text); line-height: 1.6; font-size: 14px;
}

/* 链接色：Accent 1 紫（2026-10-26 用户定：蓝做主色，紫只给文字链接）。
 * 按钮/导航类 <a> 必须排除，否则会吃掉它们自己的文字色。 */
a { color: var(--link); text-decoration: none; }
a:hover { text-decoration: underline; }
a.btn, a.btn:hover, a.rail-brand, a.rail-brand:hover, a.rail-cta, a.rail-cta:hover,
a.mk-tab, a.mk-tab:hover, a.hint-more { text-decoration: none; }

/* ========== 卡片 ==========
 * 新拟物用「同族提亮 + 双光源」分层；这里保留 1px 极淡描边是用户明确要求的可用性取舍
 * （数据页只看阴影会分不清区块边界，实测扫读变慢）。 */
.card { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); padding: 18px; box-shadow: var(--raised-1); }
.card h2 { font-size: 15px; font-weight: 600; margin-bottom: 4px; display: flex; align-items: center; gap: 8px; }
.card .hint { color: var(--muted); font-size: 12px; margin-bottom: 14px; }

/* ========== 徽章 ========== */
.badge { font-size: 11px; padding: 2px 8px; border-radius: 8px; background: rgba(36,139,200,0.12); color: var(--brand); }
.badge.ok { background: rgba(78,205,196,0.12); color: var(--down); }
.badge.empty { background: rgba(90,98,112,0.10); color: var(--muted); }

/* ========== 拖拽（后台通用）：凹槽——「往里面丢东西」的语汇 ========== */
.drop { border: 1px dashed var(--border-strong); border-radius: var(--radius); padding: 22px; text-align: center; cursor: pointer; transition: box-shadow .3s ease-in-out, border-color .3s ease-in-out; color: var(--muted); background: var(--sunken-bg); box-shadow: var(--sunken-1); }
.drop:hover, .drop.over { border-color: var(--brand); background: var(--sunken-bg); box-shadow: var(--sunken-focus); }
.drop .ic { font-size: 22px; }
.drop b { color: var(--text); }

/* 按钮内图标：颜色跟随按钮文字（currentColor），保证图案与背景对比度一致 */
.btn-ico { flex: none; display: block; }

/* 次按钮的激活态：用于可切换按钮（如「工艺措施/品牌/型号」列显隐），让切换状态肉眼可见 */
.btn-ghost.active { background: var(--brand); color: var(--on-brand); border-color: transparent; }

/* ========== 按钮（新拟物三态：凸起 → hover 缩阴影 → active 就地凹陷） ========== */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  border-radius: var(--radius-sm); padding: 9px 16px; font-size: 13px; font-weight: 600; cursor: pointer;
  border: 1px solid transparent;
  /* 300ms ease-in-out = 软塑料的柔韧感；❌ 不加 transform（元素长在表面上，不浮起） */
  transition: box-shadow .3s ease-in-out, background .3s ease-in-out, color .3s ease-in-out;
}
.btn:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.btn-primary {
  background: var(--brand); color: var(--on-brand);
  border-color: transparent;
  box-shadow: var(--raised-2);
}
/* hover 阴影缩小 = 手指靠近遮光；❌ 不得改回放大阴影 */
.btn-primary:hover { background: var(--brand-dark); box-shadow: var(--raised-1); }
.btn-primary:active { background: var(--brand-dark); box-shadow: var(--press-1); }
.btn-ghost {
  background: var(--bg); color: var(--text); border-color: transparent;
  box-shadow: var(--raised-1);
}
.btn-ghost:hover { background: var(--bg); box-shadow: 2px 2px 4px #b8bcc2, -2px -2px 4px #ffffff; }
.btn-ghost:active { background: var(--bg); box-shadow: var(--press-1); }
.btn-lg { padding: 13px 26px; font-size: 15px; border-radius: var(--radius); width: 100%; justify-content: center; }
.btn:disabled { opacity: .5; cursor: not-allowed; box-shadow: var(--raised-1); }
body.dark .btn-primary { box-shadow: var(--raised-2); }
body.dark .btn-primary:hover { box-shadow: var(--raised-1); }
body.dark .btn-ghost:hover { box-shadow: 2px 2px 4px #212429, -2px -2px 4px #3a3f47; }

/* ========== 顶栏按钮（登录 / 规则等，改用次按钮质感） ========== */
.meta { font-size: 12px; color: var(--muted); }
.meta b { color: var(--text); }
.hidden { display: none !important; }
.user-box { flex: none; display: flex; align-items: center; gap: 8px; }
.btn-login { background: var(--bg); color: var(--text); border: 1px solid transparent; border-radius: var(--radius-sm); padding: 8px 14px; font-size: 13px; font-weight: 600; cursor: pointer; box-shadow: var(--raised-1); transition: box-shadow .3s ease-in-out, background .3s ease-in-out; }
.btn-login:hover { background: var(--bg); box-shadow: 2px 2px 4px #b8bcc2, -2px -2px 4px #ffffff; }
.btn-login:active { box-shadow: var(--press-1); }
.theme-select { background: var(--sunken-bg); color: var(--text); border: 1px solid transparent; border-radius: var(--radius-sm); padding: 7px 10px; font-size: 13px; cursor: pointer; outline: none; box-shadow: var(--sunken-1); }
.theme-select:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.theme-select option { background: var(--card); color: var(--text); }
.user-info { display: flex; align-items: center; gap: 10px; }
.user-name { color: var(--text); font-size: 13px; font-weight: 600; }
.btn-logout { background: var(--bg); color: var(--text); border: 1px solid transparent; padding: 6px 12px; font-size: 12px; border-radius: var(--radius-sm); cursor: pointer; font-weight: 600; box-shadow: var(--raised-1); }
.btn-logout:hover { background: var(--bg); box-shadow: 2px 2px 4px #b8bcc2, -2px -2px 4px #ffffff; }
.btn-logout:active { box-shadow: var(--press-1); }
body.dark .btn-login:hover, body.dark .btn-logout:hover { box-shadow: 2px 2px 4px #212429, -2px -2px 4px #3a3f47; }

/* ========== 模态框 ========== */
.modal { position: fixed; inset: 0; background: rgba(38,42,49,0.42); display: flex; align-items: center; justify-content: center; z-index: 100; }
.modal-box { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); width: 400px; max-width: 92vw; padding: 24px; box-shadow: var(--raised-3); color: var(--text); }
.modal-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 16px; }
.modal-head b { font-size: 16px; }
.close { background: none; border: none; font-size: 22px; color: var(--muted); cursor: pointer; line-height: 1; border-radius: var(--radius-sm); width: 28px; height: 28px; }
.close:hover { background: var(--fill-hover); color: var(--text); }

/* ========== 设置弹层（2026-10-23：主题从侧栏下拉迁入） ========== */
/* 双类选择器：admin.css 在 base.css 之后重声明了 .modal-box{width:400px}，
   同特异性会被它盖掉，这里提高一档，避免「后台页设置弹层莫名变窄」 */
.modal-box.settings-box {
  width: 470px; max-height: 88vh;
  display: flex; flex-direction: column;
  /* 小屏兜底：窗口再窄也不溢出视口（与 _verify-usermenu 的窄屏断言一致：≤92%） */
  max-width: 92vw;
}
/* 分栏布局（左分类 + 右内容）统一 980×641（2026-10-29 用户定：「设置栏窗口大小要统一」）：
   原先「外观」640×210 /「规则」980×641 两档，切分类时弹层横向跳 340px、纵向跳 431px。
   641 = 规则页 6 列表格的实测内容高；外观页共用同高，切分类时尺寸完全不动。
   小屏用 88vh 兜底，不会顶出视口。 */
.modal-box.settings-box.is-split { width: 980px; height: min(641px, 88vh); }
/* .is-wide 类名保留（user-menu.js 仍会切它），宽度与 .is-split 一致，不产生任何视觉变化 */
.modal-box.settings-box.is-wide { width: 980px; }

/* admin.html / market.html 的设置只有「外观」一页，不套左侧分类，仍用这个简单容器 */
.set-sec { display: flex; flex-direction: column; gap: 6px; }

.settings-body { display: flex; gap: 16px; flex: 1; min-height: 0; }

/* 左侧分类导航 */
.set-nav { flex: none; width: 124px; display: flex; flex-direction: column; gap: 2px; padding-right: 14px; border-right: 1px solid var(--line); }
.set-nav-item {
  box-sizing: border-box; width: 100%; padding: 8px 10px;
  border: 1px solid transparent; border-radius: var(--radius-sm); background: none;
  color: var(--muted); font-family: inherit; font-size: 13px; text-align: left; cursor: pointer;
  transition: background .12s, color .12s, box-shadow .12s, border-color .12s;
}
.set-nav-item:hover { background: var(--fill-hover); color: var(--text); }
.set-nav-item.active { background: var(--card); color: var(--brand); font-weight: 600; border-color: transparent; box-shadow: var(--raised-1); }
.set-nav-item:focus-visible { outline: 2px solid var(--brand); outline-offset: 1px; }

/* 账号与数据 pane（2026-11-01 从独立弹窗并进设置）：由 pane 统一滚动，
   内部 .acc-body 取消自己的 flex/overflow，避免出现第二根滚动条 */
#pane-account { overflow-y: auto; overflow-x: hidden; }
#pane-account .acc-body { flex: none; overflow: visible; padding-right: 0; }
#pane-account .acc-sec:first-of-type { padding-top: 0; }

/* 左侧导航底部的「入口项」（2026-10-29：账号与数据从「外观」页移来）
   与分类项的区别：不参与 tab 高亮，点了打开独立弹层（account-panel.js 靠 .acc-open 委托）。
   2026-11-01 起 index 已改成分类，这段样式仅 admin.html 等无分类页面继续复用。 */
.set-nav-sep { height: 1px; margin: 10px 0 8px; background: var(--line); }
.set-nav-link {
  box-sizing: border-box; width: 100%; padding: 8px 10px;
  display: flex; align-items: center; justify-content: space-between; gap: 6px;
  border: 1px solid transparent; border-radius: var(--radius-sm); background: none;
  color: var(--muted); font-family: inherit; font-size: 13px; text-align: left; cursor: pointer;
  transition: background .12s, color .12s;
}
.set-nav-link:hover { background: var(--fill-hover); color: var(--text); }
.set-nav-link:focus-visible { outline: 2px solid var(--brand); outline-offset: 1px; }
.set-nav-link .set-go { font-size: 12px; line-height: 1; }

/* 右侧内容区 */
.set-panes { flex: 1; min-width: 0; min-height: 0; display: flex; }
.set-pane { flex: 1; min-width: 0; min-height: 0; }
/* 外观页可纵向滚动；**禁止横向滚动**（2026-10-29）：
   `.set-link` 用 margin:0 -10px 让整行背景贴边，容器变窄时会顶出 10px → 浏览器画出横向滚动条。
   这 10px 只影响 hover 背景，裁掉不影响任何内容。
   2026-10-29 用户定：内容**顶部对齐** —— 曾试过垂直居中，641 高下面板里一行设置飘在正中，
   上下各空 250px，反而像没加载完；设置项从上往下排才是常规观感。 */
#pane-appearance { overflow-y: auto; overflow-x: hidden; }
/* 个人资料页内容最长（账号 + 单位信息 + 材料上传 + 提交），必须自己能滚：
   `.set-pane` 只是 flex 容器、本身不滚，不设 overflow 时内容会溢出弹层，
   表现成「提交按钮跑到窗口外面、点不到」（2026-11-01 实测）。 */
#pane-profile { overflow-y: auto; overflow-x: hidden; }
/* 规则页的内部已经有 .rules-table-wrap（flex:1 + overflow:auto）负责滚动，
   外层不能再套一层，否则会出现双滚动条 */
#pane-rules { display: flex; flex-direction: column; overflow: hidden; }
#pane-rules > *:not(.rules-table-wrap) { flex: none; }
.set-row { display: flex; align-items: center; justify-content: space-between; gap: 18px; padding: 4px 0 2px; flex-wrap: wrap; }
.set-label { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.set-label b { font-size: 13px; font-weight: 600; color: var(--text); }
.set-label i { font-size: 12px; font-style: normal; color: var(--muted); line-height: 1.5; }
/* 主题状态源：视觉隐藏但保留在 DOM 里，#themeSelect 仍是 initTheme/脚本的读写入口 */
.sr-only { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; border: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* 分段控件：轨道凹、选中项凸（与 .tabs 同一套材质语言） */
.seg { flex: none; display: flex; background: var(--sunken-bg); border-radius: var(--radius); padding: 3px; box-shadow: var(--sunken-1); }
.seg-item {
  border: none; background: none; padding: 7px 13px; font-family: inherit; font-size: 12px;
  color: var(--muted); cursor: pointer; border-radius: var(--radius-sm); font-weight: 500;
  white-space: nowrap; transition: background .12s, box-shadow .12s, color .12s;
}
.seg-item:hover { color: var(--text); }
.seg-item.active { background: var(--card); color: var(--text); font-weight: 600; box-shadow: var(--raised-1); }
.seg-item:focus-visible { outline: 2px solid var(--brand); outline-offset: 1px; }

/* ========== 标签页（分段控件：轨道凹、选中项凸） ========== */
.tabs { display: flex; background: var(--sunken-bg); border-radius: var(--radius); padding: 3px; margin-bottom: 18px; box-shadow: var(--sunken-1); }
body.dark .tabs { background: var(--sunken-bg); }
.tab { flex: 1; border: none; background: none; padding: 8px; font-size: 13px; color: var(--muted); cursor: pointer; border-radius: var(--radius-sm); font-weight: 500; transition: box-shadow .12s, background .12s; }
.tab:hover { color: var(--text); }
.tab.active { background: var(--card); color: var(--text); font-weight: 600; box-shadow: var(--raised-1); }

/* ========== 必填标记（2026-10-26 用户约定：红点替代红星） ==========
 * 全站统一为 6px 圆点 #ff6b6b。
 * HTML 里仍是 <span class="req">*</span>（保留既有结构与语义），
 * 这里用 font-size:0 让星号不渲染，元素本身画成圆点 —— 一处定义，全站生效。 */
.req {
  display: inline-block;
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--mark);
  font-size: 0; line-height: 0;
  margin-right: 5px;          /* 标记在文字之前（2026-10-26 调整） */
  vertical-align: 0.18em;     /* 对齐字高中点：中文视觉中心约在基线上 0.44em，减圆点半径 */
  box-shadow: 0 0 0 2px rgba(255, 107, 107, 0.16);   /* 一圈柔光，和凸凹材质同一套语汇 */
}

/* ========== 表单 ========== */
/* ========== 表单：输入一律凹面（2026-10-21 凸凹材质） ========== */
.field { margin-bottom: 12px; }
.field input { width: 100%; padding: 11px 12px; border: 1px solid transparent; border-radius: var(--radius-sm); font-size: 14px; box-sizing: border-box; background: var(--sunken-bg); color: var(--text); box-shadow: var(--sunken-1); }
.field input:focus { outline: none; border-color: transparent; box-shadow: var(--sunken-focus); }
.code-row { display: flex; gap: 8px; }
.code-row input { flex: 1; }
.err { color: var(--up); font-size: 12px; margin-top: 4px; min-height: 16px; }
.hint2 { color: var(--muted); font-size: 12px; text-align: center; margin-top: 10px; }
.wechat-tip { color: var(--muted); font-size: 13px; text-align: center; margin-bottom: 14px; }
.msg-bar { background: rgba(219,0,0,0.10); color: var(--up); font-size: 12px; padding: 8px 12px; border-radius: var(--radius-sm); margin-bottom: 12px; }

/* ========== 规则管理（我的规则 / 后台共用） ========== */
.rules-box { width: 940px; max-width: 95vw; max-height: 92vh; display: flex; flex-direction: column; }
.rules-stats { display: flex; gap: 12px; margin-bottom: 16px; }
.rstat { flex: 1; background: var(--card); border: 1px solid var(--line); border-radius: var(--radius); padding: 14px; text-align: center; box-shadow: var(--shadow-1); }
.rstat .v { font-size: 26px; font-weight: 700; color: var(--brand); font-variant-numeric: tabular-nums; }
.rstat .k { font-size: 12px; color: var(--muted); margin-top: 2px; }
.rstat.equal .v { color: var(--down); }
.rstat.unequal .v { color: var(--up); }
.rules-toolbar { display: flex; gap: 8px; margin-bottom: 12px; align-items: center; flex-wrap: wrap; }
/* 2026-11-05 用户定：存档弹层里「合成个人定额」独占最右端（不是紧跟在上一个按钮后面）。
   它是一个独立的"建库"动作，不该跟"存这一份"混在一排里。 */
#saveModal .rules-toolbar #pqBtn { margin-left: auto; }
.rules-toolbar input { flex: 1; min-width: 180px; padding: 9px 12px; border: 1px solid transparent; border-radius: var(--radius-sm); font-size: 13px; background: var(--sunken-bg); color: var(--text); box-shadow: var(--sunken-1); }
.rules-toolbar input:focus { outline: none; border-color: transparent; box-shadow: var(--sunken-focus); }
.rules-toolbar select { padding: 9px 12px; border: 1px solid transparent; border-radius: var(--radius-sm); font-size: 13px; background: var(--sunken-bg); color: var(--text); box-shadow: var(--sunken-1); }
.rules-toolbar select:focus { outline: none; border-color: transparent; box-shadow: var(--sunken-focus); }
.rules-table-wrap { flex: 1; overflow: auto; border: 1px solid var(--line); border-radius: var(--radius); min-height: 220px; background: var(--card); }
.rules-table { width: 100%; border-collapse: collapse; font-size: 12px; }
.rules-table th { background: var(--card); text-align: left; padding: 9px 10px; font-weight: 600; border-bottom: 1px solid var(--line); position: sticky; top: 0; white-space: nowrap; z-index: 1; color: var(--muted); }
.rules-table td { padding: 8px 10px; border-bottom: 1px solid var(--line); vertical-align: top; }
.rules-table tr:hover td { background: var(--fill-hover); }
.rules-cell { max-width: 230px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text); }
.rules-cell .muted { color: var(--muted); font-size: 11px; }
.rules-rel { display: inline-block; font-size: 11px; padding: 2px 10px; border-radius: 10px; white-space: nowrap; }
.rules-rel.equal { background: rgba(78,205,196,0.12); color: var(--down); }
.rules-rel.unequal { background: rgba(219,0,0,0.12); color: var(--up); }
.rules-op { display: flex; gap: 6px; }
.rules-op button { border: 1px solid transparent; background: var(--card); font-size: 11px; padding: 3px 10px; border-radius: 9px; cursor: pointer; color: var(--text); white-space: nowrap; font-weight: 500; box-shadow: var(--raised-1); transition: box-shadow .3s ease-in-out, background .3s ease-in-out; }
.rules-op button:hover { border-color: transparent; background: var(--card); box-shadow: 2px 2px 4px #b8bcc2, -2px -2px 4px #ffffff; }
.rules-op button:active { box-shadow: var(--press-1); }
.rules-op .del:hover { border-color: var(--up); color: var(--up); }
.rules-empty { text-align: center; color: var(--muted); padding: 44px; font-size: 13px; }
.rules-pager { display: flex; gap: 10px; align-items: center; justify-content: center; margin-top: 14px; }
.rules-pager span { font-size: 13px; color: var(--muted); }
.rules-form { border: 1px solid var(--line); border-radius: var(--radius); padding: 14px; margin-bottom: 12px; background: var(--card); box-shadow: var(--shadow-1); }
.rf-title { font-weight: 600; font-size: 13px; margin-bottom: 12px; color: var(--text); }
.rf-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-bottom: 12px; }
.rf-group { display: flex; flex-direction: column; gap: 6px; }
.rf-group label { font-size: 12px; color: var(--muted); }
.rf-group input { padding: 8px 10px; border: 1px solid var(--border-strong); border-radius: var(--radius-sm); font-size: 13px; background: var(--sunken-bg); color: var(--text); box-shadow: var(--sunken-1); }
.rf-group input:focus { outline: none; border-color: var(--brand); box-shadow: var(--sunken-focus); }
.rf-foot { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.rf-foot select { padding: 8px 10px; border: 1px solid var(--border-strong); border-radius: var(--radius-sm); font-size: 13px; background: var(--sunken-bg); color: var(--text); box-shadow: var(--sunken-1); }
.rf-foot select:focus { outline: none; border-color: var(--brand); box-shadow: var(--sunken-focus); }
.rf-foot .err { width: 100%; margin: 0; }

/* ========== 页内命名弹窗（name-prompt.js，2026-10-20） ==========
 * 替代浏览器原生 prompt：原生框由浏览器绘制在窗口顶部、位置不可控，
 * 会与触发按钮相隔整屏（用户反馈「起名对话框太远」）。
 * 本组件 fixed 居中 + 遮罩，任何滚动位置都在眼前；z-index 高于 .modal(100)
 * 与矩阵右键菜单(900)、进度层(400)，保证叠加在「云端存档」弹窗之上。 */
.np-mask { position: fixed; inset: 0; background: rgba(0,0,0,0.45); display: flex; align-items: center; justify-content: center; z-index: 1200; }
.np-mask.hidden { display: none; }
.np-box { width: 420px; max-width: 92vw; background: var(--card); border: 1px solid var(--line); border-radius: 12px; box-shadow: var(--shadow-2); color: var(--text); padding: 18px 20px 16px; }
.np-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
.np-title { font-size: 15px; font-weight: 600; }
.np-x { background: none; border: none; font-size: 22px; line-height: 1; color: var(--muted); cursor: pointer; width: 28px; height: 28px; border-radius: var(--radius-sm); }
.np-x:hover { background: var(--fill-hover); color: var(--text); }
.np-label { display: block; font-size: 12px; color: var(--muted); margin-bottom: 6px; }
.np-input { width: 100%; padding: 9px 10px; border: 1px solid transparent; border-radius: var(--radius-sm); background: var(--sunken-bg); color: var(--text); font-size: 13px; box-sizing: border-box; box-shadow: var(--sunken-1); }
.np-input:focus { outline: none; border-color: transparent; box-shadow: var(--sunken-focus); }
.np-err { min-height: 16px; margin-top: 6px; font-size: 12px; color: var(--up); }
.np-foot { display: flex; justify-content: flex-end; gap: 8px; margin-top: 8px; }
.np-btn { padding: 7px 16px; border-radius: 9px; font-size: 13px; cursor: pointer; border: 1px solid transparent; background: var(--bg); color: var(--text); box-shadow: var(--raised-1); transition: box-shadow .3s ease-in-out, background .3s ease-in-out; }
.np-btn:hover { background: var(--bg); box-shadow: 2px 2px 4px #b8bcc2, -2px -2px 4px #ffffff; }
.np-btn:active { box-shadow: var(--press-1); }
.np-btn.primary { background: var(--brand); border-color: transparent; color: var(--on-brand); box-shadow: var(--raised-2); }
.np-btn.primary:hover { background: var(--brand-dark); box-shadow: var(--raised-1); }

/* ==========================================================
 * 材质 · 统一兜底（2026-10-21 定稿，2026-10-25 改新拟物双光源）
 * ------------------------------------------------------------
 * 全站材质只有两种：
 *   凸 = 按钮 / 卡片 / 浮层（--raised-1/2/3，按下转 --press-1）
 *   凹 = 输入框 / 下拉 / 多行文本 / 拖放区 / 分段控件轨道（--sunken-1/2，focus 转 --sunken-focus）
 * 下面用 :where() 把特异性压到 0，只当「默认值」：任何组件自己声明的
 * background / box-shadow 都能盖掉它，所以不会和既有样式打架。
 * ⚠️ 新增组件不要再手写 box-shadow，引用上面那组变量即可，
 *    否则浅色/深色两套材质会脱钩（本项目已经出现过一次"两套质感并存"）。
 * ⚠️ 新拟物没有可见边框：边界靠双光源，不靠线（个别数据区分隔线除外）。
 * ========================================================== */
:where(input:not([type="checkbox"]):not([type="radio"]):not([type="file"]):not([type="range"]):not([type="color"]):not([type="submit"]):not([type="button"]),
       select, textarea) {
  background-color: var(--sunken-bg);
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  box-shadow: var(--sunken-1);
  transition: box-shadow .3s ease-in-out, border-color .3s ease-in-out;
}
:where(input:not([type="checkbox"]):not([type="radio"]):not([type="file"]):not([type="range"]):not([type="color"]),
       select, textarea):focus {
  outline: none;
  border-color: transparent;
  /* focus = 阴影变浅（通道打开），❌ 不得改回加深 */
  box-shadow: var(--sunken-focus);
}
/* 复选/单选：不参与凸凹，保持浏览器原生对勾，避免自绘造成可访问性回退 */
:where(input[type="checkbox"], input[type="radio"]) { box-shadow: none; }

/* ==========================================================
 * 线性图标（2026-10-21，QC.icon / [data-icon] 的产物）
 * ------------------------------------------------------------
 * 统一 16 栅格、stroke=currentColor：颜色跟着文字走，深色模式自动跟随，
 * 不再出现 emoji 那套「不跟主题、不跟字号、跨系统变形」的问题。
 * ========================================================== */
.qc-ico { display: inline-block; vertical-align: -0.16em; flex: none; }
/* 文字前的小图标：与按钮/标题内的文字基线对齐。
   按钮内部本身已有 gap:6px，所以 .btn 里的 .t-ico 不再额外留右边距（否则会变成 12px）。 */
.t-ico { display: inline-flex; align-items: center; margin-right: 6px; vertical-align: -0.18em; }
.btn .t-ico { margin-right: 0; }
.t-ico .qc-ico { display: block; }
/* 大图标位（上传区 / 空态）：居中、品牌色 */
.drop .ic .qc-ico { display: block; margin: 0 auto; color: var(--tint); }   /* 图标统一色（2026-10-26 约定） */

/* ==========================================================
 * 无障碍 · 减少动效（2026-10-26 按 Neumorphism 规范补齐）
 * ------------------------------------------------------------
 * 规范要求「动效有 prefers-reduced-motion 备选方案」。
 * 新拟物全靠阴影过渡，前庭敏感用户看连续阴影变化会不适 ——
 * 这里统一压到 0.01ms（保留状态切换，去掉过程动画）。 */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ==========================================================
 * 账号与数据弹层（2026-10-27）
 * 用途：数据可见范围 / 清空云端数据 / 注销账号
 * 危险按钮用 --up + --on-brand，深浅两套主题都能读（C58）。
 * ========================================================== */
.acc-box { width: 640px; max-width: 94vw; max-height: 88vh; display: flex; flex-direction: column; }
.acc-body { flex: 1; min-height: 0; overflow: auto; padding-right: 2px; }
.acc-id-row { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--muted); margin-bottom: 14px; }
.acc-id-row b { color: var(--text); font-weight: 600; }

.acc-sec { padding: 14px 0; border-top: 1px solid var(--line); }
.acc-sec:first-of-type { border-top: 0; padding-top: 0; }
.acc-h { display: block; font-size: 13px; font-weight: 600; margin-bottom: 8px; color: var(--text); }
.acc-p { font-size: 12.5px; line-height: 1.7; color: var(--muted); margin: 0 0 10px; }
.acc-p b { color: var(--text); }

.acc-table { width: 100%; border-collapse: collapse; font-size: 12px; margin-bottom: 8px; }
.acc-table th, .acc-table td { border: 1px solid var(--line); padding: 6px 8px; text-align: left; }
.acc-table th { background: var(--bg); font-weight: 600; color: var(--muted); white-space: nowrap; }
.acc-table td { color: var(--text); }
.acc-table .ok { color: var(--down); }
.acc-table .no { color: var(--muted); }
.acc-table .warn { color: var(--warn); }

.acc-link { font-size: 12px; color: var(--link); }

.acc-confirm { margin-top: 10px; padding: 12px; border-radius: var(--radius-sm); background: var(--bg); box-shadow: var(--sunken-1); }
.acc-warn { font-size: 12.5px; color: var(--up); margin: 0 0 10px; line-height: 1.6; }
.acc-btns { display: flex; gap: 8px; justify-content: flex-end; margin-top: 10px; }
.acc-confirm input { width: 100%; box-sizing: border-box; padding: 9px 11px; border: 1px solid transparent; border-radius: var(--radius-sm); font-size: 13px; background: var(--sunken-bg); color: var(--text); box-shadow: var(--sunken-1); }
.acc-confirm input:focus { outline: none; box-shadow: var(--sunken-focus); }

.btn.acc-danger { background: var(--up); color: var(--on-brand); border-color: transparent; box-shadow: var(--raised-1); }
.btn.acc-danger:hover { filter: brightness(.94); }
.btn.acc-danger:disabled { opacity: .5; cursor: not-allowed; }

.acc-msg { margin-top: 8px; font-size: 12.5px; line-height: 1.6; }
.acc-msg.is-ok { color: var(--down); }
.acc-msg.is-bad { color: var(--up); }

.acc-foot { display: flex; gap: 16px; align-items: center; padding-top: 12px; margin-top: 4px; border-top: 1px solid var(--line); font-size: 12.5px; }
.acc-foot a { color: var(--link); }

.login-legal { margin-top: 12px; font-size: 12px; color: var(--muted); text-align: center; line-height: 1.7; }
.login-legal a { color: var(--link); }
/* 本机自动登录选项（2026-11-01）：放在两个登录面板之外，微信 / 手机两条路都能看到 */
.login-remember {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  margin: 14px 0 0; font-size: 12px; color: var(--muted);
  cursor: pointer; user-select: none;
}
.login-remember input { width: 14px; height: 14px; accent-color: var(--brand); cursor: pointer; margin: 0; }
.login-remember:hover { color: var(--text); }

/* 设置里的一行入口（账号与数据，2026-10-27 用户定：从账号菜单移入设置）
 * 整行可点，右侧箭头；hover 用主色淡底，不新增色相。
 * 2026-10-29：原先 `margin: 6px -10px 0` 想把背景铺到容器边缘，但 pane 的 padding 是 0，
 *   负 margin 无处抵消 → 行宽比容器多 20px，右侧顶出 10px 横向滚动条。
 *   改为不溢出；分隔线用 box-shadow 画满整行，视觉上仍是通栏。 */
.set-row.set-link { cursor: pointer; padding: 12px 10px 8px; margin: 6px 0 0;
  box-shadow: 0 -1px 0 var(--line); border-radius: 0 0 var(--radius-sm) var(--radius-sm); }
.set-row.set-link:hover { background: var(--fill-hover); }
.set-row.set-link:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.set-go { color: var(--muted); font-size: 13px; }

/* ========== 页内确认浮层（js/confirm-pop.js）==========
 * 替代浏览器原生 confirm：贴着触发按钮弹出，不再固定画在窗口顶端。
 * z-index 1100：高于一般卡片/下拉，低于 np-mask(1200) 命名弹窗。
 * 遮罩是全透明的（background: transparent），只用来接"点外面 = 取消"。
 */
.cp-mask { position: fixed; inset: 0; z-index: 1100; background: transparent; }
.cp-mask.hidden { display: none; }
.cp-box {
  position: fixed; width: 300px; max-width: calc(100vw - 24px);
  background: var(--card); color: var(--text);
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  padding: 14px 16px 12px;
  box-shadow: 0 10px 28px rgba(0, 0, 0, .18), 0 2px 6px rgba(0, 0, 0, .08);
  animation: cp-in .12s ease-out;
}
body.dark .cp-box { box-shadow: 0 10px 28px rgba(0, 0, 0, .55), 0 2px 6px rgba(0, 0, 0, .4); }
@keyframes cp-in { from { opacity: 0; transform: translateY(-2px); } to { opacity: 1; transform: none; } }

/* 指向触发按钮的小三角：旋转 45° 的方块，只留朝外两条边 */
.cp-arrow {
  position: fixed; width: 12px; height: 12px; display: none;
  background: var(--card); border: 1px solid var(--line);
  transform: rotate(45deg); z-index: -1;
}
.cp-arrow[data-side="bottom"] { border-right-color: transparent; border-bottom-color: transparent; }
.cp-arrow[data-side="top"] { border-left-color: transparent; border-top-color: transparent; }

.cp-text { font-size: 13px; line-height: 1.65; white-space: pre-line; word-break: break-word; }
/* 2026-11-05 用户定：确定/删除在**最左**，取消在**最右** —— 两个按钮拉开到两端，
   误点确认的概率更低（尤其删除类）。DOM 顺序也按视觉来写，Tab 顺序不会反过来。 */
.cp-actions { display: flex; justify-content: space-between; align-items: center; gap: 8px; margin-top: 12px; }
.cp-btn {
  border: 0; cursor: pointer; font-size: 13px; padding: 7px 14px;
  border-radius: var(--radius-sm); color: var(--text);
  background: var(--raised-bg); box-shadow: var(--raised-1);
  transition: box-shadow .18s ease, transform .12s ease;
}
.cp-btn:hover { box-shadow: var(--raised-hover); }
.cp-btn:active { transform: translateY(1px); box-shadow: var(--press-1); }
.cp-btn:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
/* 确定 = 主色；danger 场景（删除等）用语义红，并把焦点默认放到「取消」上。
   ⚠️ 必须走变量：--brand / --up / --on-brand 在深浅两套里都已调好对比度；
   在这里手写十六进制色值会被调色板封闭性检查（_verify-palette）判为"越界色"。 */
.cp-btn.is-primary { background: var(--brand); color: var(--on-brand); }
.cp-btn.is-danger { background: var(--up); color: var(--on-brand); }

@media (max-width: 560px) {
  .cp-box { width: auto; left: 12px !important; right: 12px; max-width: none; }
  .cp-arrow { display: none !important; }
}
