/* ===================================================================
   生产计划软件 · 主题样式（紧凑 · 商务版）
   配色沿用用户主题：深藏青 #1F3864 + 微软雅黑
   设计基调：小圆角、细边框、弱阴影、行高紧凑、数字等宽对齐
   =================================================================== */
:root{
  --navy:#1f3864;          /* 深藏青 主色 */
  --navy-2:#2a4a82;
  --navy-soft:#e8edf5;     /* 浅蓝灰 */
  --ink:#20293a;
  --muted:#6b7686;
  --line:#dde3ec;
  --line-2:#dde4ef;        /* 行分隔线：略压深，长表里行边界才不糊成一片 */
  --bg:#eef1f6;
  --panel:#ffffff;
  --red:#c0392b;
  --green:#2f8f62;
  --amber:#c07d12;
  /* 隔行底色：原来 #f7f9fc 离白底只差 3%，长表里等于没有隔行 → 压深到能一眼分辨 */
  --row-alt:#e9f0fa;
  /* 排产表隔行（按「订单组」，详见文末 ⑦ 说明）：
     计划行 / 实际行各一个值 —— 组内「实际」要比「计划」亮一档，
     组间再整体错开，两条线索互不干扰。
     ⚠ 2026-10-13 用户要求「同一行着色颜色一致」：这一行的**所有格子**（含 pt-kind 标签格、
     pt-edit 可编辑格、pt-gray 空值格、左侧冻结列）都必须取同一个底色，
     不能再各自带固定色 → 那一行看上去是一条完整的色带，而不是拼贴。
     仍保留「组内计划 vs 实际」的深浅差 —— 那是区分两个物理行的线索，与同行一致性不冲突。 */
  --plan-odd:#ffffff;   --plan-odd-act:#f2f6f2;
  --plan-even:#e9f0fa;  --plan-even-act:#e2ecdf;
  /* 浅色主题组色本身不透明，不透明版直接同值 */
  --plan-odd-op:#ffffff;   --plan-odd-act-op:#f2f6f2;
  --plan-even-op:#e9f0fa;  --plan-even-act-op:#e2ecdf;
  /* 旧 --plan-sci / --plan-sci-alt（冻结列实底）2026-10-13 起由 --plan-*-op 取代，见下 */
  /* 冻结列的「不透明底 + 上层行色」两层叠加方案用（见文末 ⑦）。
     行色是半透明时（深色/玻璃/深空主题）必须有个不透明底，否则滚动会穿帮；
     这里给各主题自己的面板底色当那个底。 */
  --plan-sci-under:#ffffff;
  /* 产能表左右两块的区隔竖线（分隔列已不用底色块，改用线，各主题在变量块里覆盖） */
  --cap-sep-line:#c6d3e6;
  --r:4px;                 /* 统一小圆角 */
  /* ---- 表格行距（数值越小行越紧凑） ---- */
  --row-pad:1px;           /* 单元格上下内边距 */
  --row-lh:1.25;           /* 单元格行高倍数 */
  --row-pad-h:3px;         /* 表头上下内边距 */
  /* ---- 主题可变量（各主题覆盖这些即可换肤） ---- */
  --font:"Microsoft YaHei","PingFang SC","Segoe UI",sans-serif;
  --sidebar-bg:var(--navy);
  --sidebar-fg:#fff;
  --sidebar-fg-dim:#d9e1ef;
  --sidebar-line:rgba(255,255,255,.12);
  --nav-hover:rgba(255,255,255,.08);
  --nav-active:rgba(255,255,255,.13);
  /* 菜单项外框（每个菜单是一个带框的小卡片） */
  --nav-line:rgba(255,255,255,.16);
  --nav-line-hi:rgba(255,255,255,.34);
  --nav-bg:rgba(255,255,255,.04);
  /* 仪表盘图表配色（--c1..--c6 依次取用；--chart-track 是柱/环的底槽色） */
  --c1:#2a6fb5; --c2:#2f8f62; --c3:#c07d12;
  --c4:#7a5aa8; --c5:#2a8fa8; --c6:#c0392b;
  --chart-track:#e8edf5;
  --chart-sel-bg:rgba(42,111,181,.13); --chart-hit-bg:rgba(42,111,181,.07);
  --thead-bg:var(--navy);
  --thead-fg:#fff;
  --thead-line:rgba(255,255,255,.12);
  --btn-bg:#fff;
  --btn-fg:var(--ink);
  --btn-line:var(--line);
  --btn-hover-bg:#fff;
  --row-hover:#eef3fb;
  --cell-hover:#e3ecf9;
  --foot-bg:#f7fafd;
  --form-head-bg:var(--navy);
  --form-head-fg:#fff;
  --form-op:1;             /* 弹窗（窗体）不透明度：2026-10-13 起顶栏滑杆已改为「高斯模糊」，此值固定 1 */
  --win-border:var(--line);
  --win-shadow:0 14px 40px rgba(0,0,0,.24);
  --wrap-bg:#fff;
  /* 弹窗（.modal / .fmodal / .confirm-box）专用底色：必须**半透明**，
     否则 backdrop-filter 的模糊被实色底整个盖住，等于白加。
     各主题在自己的变量块里覆盖（深色主题要压深）；没覆盖的走这里的值。 */
  --modal-bg:rgba(255,255,255,.80);
  --modal-blur:blur(22px) saturate(160%);

  /* ---------- 计划表 / 日历小表专用色（2026-10-13 新增）----------
     为什么要有这一组：这一块的样式早于主题体系写成，里面全是硬编码
     （#fff / #eef3fb / #f4f8ff / #7a4b4b / #1f3864 …），
     在 dark / glass / space 下只能靠后面几十条 `html[data-theme=…] .plan-tbl …`
     打补丁逐个覆盖 —— 漏一条就是一处「深底浅字看不清」或「深色主题里一块白」。
     收敛成变量后，各主题只需在自己的变量块里给一份值，换肤不再靠打补丁。

     分区：滚动容器 / 单元格 / 网格线 ‖ 表头四层（第4行列名、第1~3行参数、
     参数值格、参数标签格、可编辑格）‖ 排产区（计划/实际/派生/延期/已改标记）‖
     日期列状态（周末/上班/放假）‖ 就地编辑框 ‖ 表头里嵌的「上班/放假日期」小表。 */
  --pt-scroll-bg:#ffffff;          /* 表格滚动容器底 */
  --pt-cell-bg:#ffffff;            /* 明细单元格兜底底色（实际由行组色接管） */
  --pt-grid:#dde4ef;               /* 单元格网格线 */
  --pt-hd-bg:#1f3864;              /* 表头第 4 行（列名行） */
  --pt-hd-fg:#ffffff;
  --pt-hd-line:rgba(255,255,255,.12);
  --pt-sub-bg:#eef3fb;             /* 表头第 1~3 行（标题/参数/系数） */
  --pt-sub-fg:#1f3864;
  --pt-val-bg:#ffffff;             /* 参数值格（可点改） */
  --pt-val-fg:#1f3864;
  --pt-param-bg:#2b4778;           /* 参数标签格 */
  --pt-param-fg:#dbe4f2;
  --pt-edit-hd-bg:#33507f;         /* 可编辑列的列名格 */
  --pt-edit-hd-fg:#ffffff;
  --pt-edit-bg:#f4f8ff;            /* 可编辑表头格（每日工时/人数） */
  --pt-edit-fg:#1f3864;
  --pt-edit-hi-bg:#dbe7fa;         /* 可编辑格悬停高亮 */
  --pt-edit-hi-ring:#8fb4e8;
  --pt-wkend-bg:#7a4b4b;           /* 周六/周日日期列 */
  --pt-wkend-fg:#ffe3e3;
  --pt-workday-bg:#e8f5e9;         /* 上班日 */
  --pt-workday-fg:#2e7d32;
  --pt-holiday-bg:#d9d9d9;         /* 放假 */
  --pt-holiday-fg:#5a5a5a;
  --pt-num-fg:#1f3864;             /* 计划产量数字 */
  --pt-num-act-fg:#4a6b3f;         /* 实际产量数字 */
  --pt-kind-fg:#1f3864;            /* 「计划」标签字 */
  --pt-kind-act-fg:#3f5a3f;        /* 「实际」标签字 */
  --pt-calc-fg:#31507f;            /* 计算得出列（起止日期/数量） */
  --pt-late-fg:#c0392b;            /* 逾期（预计结束 > 订单交期） */
  --pt-dirty:#e08b2f;              /* 手工改过的橙色标记条 */
  --pt-dirty-fg:#b45309;           /* 手工改过的数字字色 */
  --pt-group-line:#dfe6f0;         /* 一个订单与下一个订单之间的 2px 分界 */
  --pt-inline-bg:#ffffff;          /* 就地编辑输入框 */
  --pt-inline-fg:#1f3864;
  --pt-inline-line:#8fb4e8;
  --pt-cal-cell-bg:#ffffff;        /* 表头内嵌「上班/放假日期」小格 */
  --pt-cal-cell-fg:#20293a;
  --pt-cal-label-fg:#1f3864;
  --pt-cal-cell-line:#dde4ef;
  --pt-cal-hi-bg:#f0f5fc;
  --pt-cal-hi-line:#8fb4e8;
}
*{box-sizing:border-box;}
html,body{height:100%;margin:0;}
body{
  font-family:var(--font);
  color:var(--ink);background:var(--bg);font-size:12.5px;line-height:1.45;
  -webkit-font-smoothing:antialiased;
}
#app{display:flex;height:100vh;}

/* ---------- 侧栏 ---------- */
.sidebar{
  width:166px;background:var(--sidebar-bg);color:var(--sidebar-fg);display:flex;flex-direction:column;
  flex-shrink:0;
}
/* 品牌区：竖排锁版 —— 上面是 FAXSTAR 横版字标（原图 364×63，比例 5.78:1，
   塞进原来的 25×25 方块会糊成一团，所以整块改成上下排），下面是标题/副标题。
   ★ logo.png 本身是**透明背景** PNG（角点 alpha=0），所以这里不加白色底板 ——
   让字标直接透出侧栏的主题色，与整块品牌区融在一起（用户 2026-10-12 要求）。
   代价：字标主色是深蓝(24,48,144)+ 亮绿(72,168,48)，在 dark/glass/space 三个
   深色主题下深蓝会糊掉，故用 --logo-filter 提亮（各主题单独覆盖，见下）。 */
.brand{flex-direction:column;align-items:stretch;gap:5px;padding:9px 9px 8px;
  border-bottom:1px solid var(--sidebar-line);}
.logo{
  display:block;width:100%;height:auto;border-radius:var(--r);
  padding:2px 4px;object-fit:contain;
  filter:var(--logo-filter, none);
  opacity:var(--logo-op, 1);
}
.brand-text{min-width:0;text-align:center;}
.brand-title{font-size:12.5px;font-weight:700;letter-spacing:.3px;}
.brand-sub{font-size:9px;opacity:.66;margin-top:1px;letter-spacing:.3px;}
/* 菜单区上下左右留白 + 每个菜单项独立成「带框的小卡片」。
   2026-10-12 用户要求「菜单栏高度做大」：菜单项整体加高（3px→8px 上下留白），
   图标 20→26px、字号 11.5→13px、间距同步放大；9 个可见项总高约 +100px，
   侧栏 flex:1 + overflow:auto，矮窗口自动出滚动条，不会挤出屏幕。 */
#nav{flex:1;overflow:auto;padding:8px 8px;display:flex;flex-direction:column;gap:6px;}
#nav a{
  display:flex;align-items:center;gap:8px;padding:8px 10px;color:var(--sidebar-fg-dim);
  text-decoration:none;font-size:13px;line-height:1.4;border-radius:8px;cursor:pointer;
  border:1px solid var(--nav-line,rgba(255,255,255,.16));
  background:var(--nav-bg,rgba(255,255,255,.04));
  box-shadow:inset 0 1px 0 rgba(255,255,255,.10),0 1px 2px rgba(0,0,0,.10);
  position:relative;transition:color .15s,background .15s,border-color .15s,box-shadow .15s;
}
#nav a:hover{background:var(--nav-hover);color:var(--sidebar-fg);border-color:var(--nav-line-hi,rgba(255,255,255,.32));}
#nav a.active{
  background:var(--nav-active);color:var(--sidebar-fg);font-weight:600;
  border-color:#8fb0e8;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.22),0 0 0 1px rgba(143,176,232,.22),0 2px 6px rgba(0,0,0,.18);
}

/* ---------- 左侧菜单的 3D 立体图标 ----------
   每个图标是一块「凸起的厚方块」：
   · 上亮下暗的斜面渐变（斜向高光，像光从左上打来）
   · 顶/底两向内阴影 → 厚度感；底边再加一道更实的暗色棱
   · 外投影 + 内侧白描边 → 从侧栏背景里"浮"起来
   · 悬停时整体上浮 1px、投影加深；选中时压下 1px（像被按下） */
.nav-ico{
  position:relative;flex:none;width:32px;height:32px;border-radius:8px;
  display:flex;align-items:center;justify-content:center;color:#fff;
  background:
    linear-gradient(158deg,
      var(--c-hi, #7cc6ee) 0%,
      var(--c-mid,#2f7fb8) 46%,
      var(--c-lo, #17527f) 100%);
  box-shadow:
    0 2px 3px rgba(0,0,0,.34),              /* 落在侧栏上的投影 */
    0 1px 0 var(--c-lo,#17527f),           /* 底棱（更实的暗边，撑厚度） */
    inset 0 1px 0 rgba(255,255,255,.62),   /* 顶部高光棱 */
    inset 0 -1px 0 rgba(0,0,0,.34),        /* 底部暗棱 */
    inset 1px 0 0 rgba(255,255,255,.20),
    inset -1px 0 0 rgba(0,0,0,.18);
  transition:transform .16s,box-shadow .16s,filter .16s;
}
/* 图标顶部的一道玻璃反光（伪元素，不吃鼠标事件） */
.nav-ico::before{
  content:'';position:absolute;left:4px;right:4px;top:2px;height:44%;border-radius:7px 7px 11px 11px;
  background:linear-gradient(180deg,rgba(255,255,255,.46),rgba(255,255,255,0));
  pointer-events:none;
}
.nav-ico svg{
  position:relative;width:22px;height:22px;display:block;
  filter:drop-shadow(0 1px 1px rgba(0,0,0,.45));   /* 线条也带一点厚度 */
}
.nav-tx{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
#nav a:hover .nav-ico{
  transform:translateY(-1px);filter:saturate(1.14) brightness(1.06);
  box-shadow:
    0 5px 8px rgba(0,0,0,.40),
    0 1px 0 var(--c-lo,#17527f),
    inset 0 1px 0 rgba(255,255,255,.72),
    inset 0 -1px 0 rgba(0,0,0,.34),
    inset 1px 0 0 rgba(255,255,255,.24),
    inset -1px 0 0 rgba(0,0,0,.18);
}
#nav a.active .nav-ico{
  transform:translateY(1px);filter:saturate(1.2) brightness(1.1);
  box-shadow:
    0 1px 1px rgba(0,0,0,.32),
    0 2px 0 var(--c-lo,#17527f),                   /* 底棱更厚 → 按下的实心感 */
    inset 0 1.5px 3px rgba(0,0,0,.30),              /* 顶部内阴影（按下而非凸起） */
    inset 0 -1px 0 rgba(255,255,255,.34),
    inset 1px 0 0 rgba(255,255,255,.14),
    inset -1px 0 0 rgba(0,0,0,.20);
}
#nav a.active .nav-ico::before{opacity:.55;height:36%;}
/* 底部说明条：与上方菜单项同款的带框小卡片（原为横跨整个侧栏的宽条，太宽） */
.sidebar-foot{
  margin:0 8px 8px;padding:6px 8px;font-size:9.5px;opacity:.62;line-height:1.4;
  border:1px solid var(--nav-line);border-radius:8px;background:var(--nav-bg);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.10);
}

/* ---------- 主区 ---------- */
.main{flex:1;display:flex;flex-direction:column;min-width:0;}
.topbar{
  height:38px;background:var(--panel);border-bottom:1px solid var(--line);
  display:flex;align-items:center;justify-content:space-between;padding:0 12px;flex-shrink:0;
}
.page-title{font-size:13.5px;font-weight:700;color:var(--navy);letter-spacing:.3px;}
.topbar-actions{display:flex;align-items:center;gap:8px;}
.hint{color:var(--muted);font-size:11px;}
.content{flex:1;overflow:auto;padding:10px 12px;}

/* ---------- 卡片 / 工具栏 ---------- */
.panel{background:var(--panel);border:1px solid var(--line);border-radius:var(--r);box-shadow:0 1px 1px rgba(31,56,100,.04);}
.toolbar{display:flex;gap:6px;align-items:center;flex-wrap:wrap;margin-bottom:8px;}
.toolbar .spacer{flex:1;}
/* 同一行里的控键分组竖线（计划表页把「隐藏类」控键并到第一行） */
.toolbar-sep{width:1px;height:16px;background:var(--line);margin:0 3px;flex:none;}
.search-input,.inp{
  border:1px solid var(--line);border-radius:var(--r);padding:4px 8px;font-size:12px;width:210px;
  font-family:inherit;outline:none;background:#fff;color:var(--ink);
}
.search-input:focus,.inp:focus{border-color:var(--navy);box-shadow:0 0 0 2px rgba(31,56,100,.08);}
select.search-input{width:auto;min-width:110px;}
.btn{
  border:1px solid var(--btn-line);background:var(--btn-bg);color:var(--btn-fg);border-radius:var(--r);
  padding:4px 10px;font-size:12px;line-height:1.5;cursor:pointer;font-family:inherit;transition:.15s;
}
.btn:hover{border-color:var(--navy);color:var(--navy);background:var(--btn-hover-bg);}
.btn-primary{background:var(--navy);color:#fff;border-color:var(--navy);font-weight:600;}
.btn-primary:hover{background:var(--navy-2);color:#fff;}
.btn-danger{color:var(--red);border-color:#eccfcc;}
.btn-danger:hover{background:#fbeeed;color:var(--red);border-color:var(--red);}

/* 仪表盘顶部概览带 ---------- */
/* 原先是「6 个统计卡（整行）+ 4 个 KPI（再一行）」共占两行、语义还互相重复，
   这里压成一行大 KPI + 一行小圆角计数条，纵向省掉约 70px，图表更早进入视野。
   2026-10-16 用户要求「做成一行」：KPI 卡与计数胶囊合成同一行 ——
   dash-top 由 column 改 row（flex-wrap），kpi-row 由 4 等分 grid 改 flex（卡片收窄到
   内容宽，把横向让给计数胶囊）。窄屏放不下时自动折回两行，内容不丢。 */
.dash-top{display:flex;flex-direction:row;flex-wrap:wrap;align-items:center;gap:8px;margin:2px 0 11px;}
.kpi-row{display:flex;flex-wrap:wrap;gap:9px;}
.kpi{position:relative;overflow:hidden;background:var(--panel);border:1px solid var(--line);
  border-radius:var(--r);padding:6px 10px 6px 12px;display:flex;align-items:center;justify-content:space-between;
  gap:10px;box-shadow:0 1px 1px rgba(31,56,100,.04);}
.kpi::before{content:'';position:absolute;left:0;top:0;bottom:0;width:3px;background:var(--k-c,var(--navy-2));}
.kpi-lbl{color:var(--muted);font-size:11.5px;white-space:nowrap;display:flex;align-items:center;gap:6px;}
.kpi-lbl i{width:7px;height:7px;border-radius:50%;background:var(--k-c,var(--navy-2));flex:none;
  outline:2px solid rgba(255,255,255,.35);outline-offset:-1px;}
.kpi-val{font-size:16px;font-weight:800;color:var(--navy);font-variant-numeric:tabular-nums;
  white-space:nowrap;letter-spacing:-.2px;}
.kpi.warn{border-color:var(--red);}
.kpi.warn .kpi-val{color:var(--red);}
.kpi.warn .kpi-lbl{color:var(--red);}

/* 计数条：订单/BOM/库存/采购/MRP 行数等纯计数，压成小胶囊 */
.chip-row{display:flex;flex-wrap:wrap;gap:6px;}
.chip{display:inline-flex;align-items:baseline;gap:6px;padding:2px 9px;border-radius:14px;
  background:var(--panel);border:1px solid var(--line);font-size:11px;color:var(--muted);
  line-height:1.6;white-space:nowrap;}
.chip b{color:var(--navy);font-size:12px;font-weight:800;font-variant-numeric:tabular-nums;}
.chip.warn{border-color:var(--red);color:var(--red);background:var(--row-alt);}
.chip.warn b{color:var(--red);}

/* ---------- 仪表盘图表 ----------
   图表一律用内联 SVG 画（离线可用 + 随主题换色），这里只管容器排版与图例。
   布局用 12 栅格：span4=三分之一、span6=一半、span12=通栏，按图表形态分配，
   保证任何窗口宽度下都不会出现「一格空着、卡片孤零零」的情况。 */
.chart-grid{display:grid;grid-template-columns:repeat(12,minmax(0,1fr));gap:10px;align-items:stretch;}
.chart-card{grid-column:span 4;margin-bottom:0;display:flex;flex-direction:column;}
.chart-card.span3{grid-column:span 3;}
.chart-card.span6{grid-column:span 6;}
.chart-card.span12{grid-column:span 12;}
@media (max-width:1180px){
  .chart-card,.chart-card.span3{grid-column:span 6;}
  .chart-card.span6,.chart-card.span12{grid-column:span 12;}
}
@media (max-width:820px){
  .chart-card,.chart-card.span3,.chart-card.span6,.chart-card.span12{grid-column:span 12;}
}
/* 卡片头：标题左、说明右，同一行内对齐，比原来堆叠更省高度也更整齐 */
.chart-card .section-h{display:flex;align-items:baseline;justify-content:space-between;gap:10px;
  margin:0 0 8px;padding-left:8px;}
.chart-card .section-h .hint{margin-left:0;flex:none;text-align:right;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:62%;}
.chart-box{flex:1;min-height:42px;display:flex;flex-direction:column;justify-content:center;}
.chart-empty{color:var(--muted);font-size:11px;text-align:center;padding:22px 0;
  border:1px dashed var(--line);border-radius:var(--r);background:var(--row-alt);}
.chart-pair{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:14px;align-items:center;}
@media (max-width:900px){.chart-pair{grid-template-columns:1fr;}}
/* 双栏等分但不限高度（用于「环形图 + 排行榜」这类天然不等高的组合） */
.chart-cols{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:14px;align-items:start;}
@media (max-width:900px){.chart-cols{grid-template-columns:1fr;}}
/* 卡头切换键（2026-10-17「采购结构」：采购单 / 收退货单）—— 与卡头基线对齐，当前项描边加粗 */
.pu-switch{display:inline-flex;gap:4px;flex:none;}
.pu-switch .btn-mini{font-size:10.5px;padding:1px 7px;}
.pu-switch .btn-mini.is-on{font-weight:700;border-color:var(--navy);color:var(--navy);
  background:var(--navy-soft);}
html[data-theme="glass"] .pu-switch .btn-mini.is-on,
html.theme-space .pu-switch .btn-mini.is-on{border-color:var(--ink);color:var(--ink);
  background:rgba(127,119,221,.14);}
/* 切换内容里的排行容器：吃满网格单元，条形图纵向铺开（与环形图同高时更好看） */
.pu-bar{min-width:0;}
.pu-bar .chart-box,.pu-bar .barlist{flex:1;justify-content:space-evenly;}
.chart-pair-cell{min-width:0;}
/* 榜内「标题在左、柱状图在右」的左右结构（2026-10-13 用户要求，库存/采购 TOP10 榜）。
   标题列固定窄宽（过长自动换行，如「库存金额 / Top 10」两行），柱状图吃剩余宽度。 */
.chart-side{display:flex;align-items:center;gap:10px;min-width:0;}
.chart-side .sub-h{margin-bottom:0;flex:none;max-width:62px;flex-wrap:wrap;line-height:1.35;}
.chart-side .chart-box{flex:1;min-width:0;}
@media (max-width:900px){.chart-side .sub-h{max-width:none;}}
/* 子区块标题：前加一小段主题色竖条，与卡片标题形成层级区分 */
.sub-h{font-size:11px;color:var(--muted);margin-bottom:6px;font-weight:600;
  display:flex;align-items:center;gap:5px;}
.sub-h::before{content:'';width:3px;height:11px;border-radius:2px;background:var(--navy-2);flex:none;}
/* 卡内小结条：把原先一串竖线文字改成一排小指标格 */
.chart-note{font-size:11px;color:var(--muted);align-self:center;line-height:1.5;
  display:flex;flex-wrap:wrap;gap:4px 6px;}
.chart-note span{background:var(--row-alt);border:1px solid var(--line-2);border-radius:11px;
  padding:2px 9px;white-space:nowrap;font-variant-numeric:tabular-nums;}
.chart-note b{color:var(--navy);font-weight:700;}
.chart-note .em{color:var(--red);}
.chart-note .em-w{color:var(--amber);}
/* 卡内纵向堆叠（小结条在上、图在下） */
.chart-stack{display:flex;flex-direction:column;gap:8px;flex:1;justify-content:center;}

/* 横向条形排行（Top N）
   2026-10-16 用户要求内容高度 -20%：行高约 21→16px（字号 11.5→10.5、内边距 1px→0、
   间距 4→3px、序号徽标 15→13px、条高 13→10px）。lead-wrap 内的覆盖值仍然优先。 */
.barlist{display:flex;flex-direction:column;gap:3px;}
.barrow{display:flex;align-items:center;gap:7px;font-size:10.5px;padding:0;border-radius:3px;}
.barrow:hover{background:var(--row-hover);}
/* 序号徽标：让排行一眼看出名次，前三名用主题色区分 */
.barrow .rk{flex:none;width:13px;height:13px;border-radius:3px;display:flex;align-items:center;
  justify-content:center;font-size:9px;font-weight:700;color:#fff;background:var(--chart-track);
  font-variant-numeric:tabular-nums;}
.barrow.top1 .rk{background:var(--c1);}
.barrow.top2 .rk{background:var(--c3);}
.barrow.top3 .rk{background:var(--c5);}
.barlabel{color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;flex:none;}
.bartrack{flex:1;min-width:30px;height:10px;background:var(--chart-track);border-radius:3px;overflow:hidden;
  box-shadow:inset 0 1px 1px rgba(0,0,0,.04);}
.barfill{height:100%;border-radius:3px;min-width:2px;position:relative;
  transition:width .5s cubic-bezier(.4,0,.2,1);}
.barval{flex:none;min-width:50px;text-align:right;color:var(--muted);font-variant-numeric:tabular-nums;}
.barrow:hover .barval{color:var(--ink);}

/* ---------- 供应商交期图（平均交期条 + 最小~最大 区间须 + 时间段选择） ----------
   2026-10-12 新增。区间须画在 .bartrack 里（绝对定位），故 leadtrack 需要 position:relative；
   须比实心条细且半透明，避免抢了「平均交期」这个主信息的视觉重量。 */
.lead-wrap{display:flex;flex-direction:column;gap:8px;flex:1;justify-content:center;}
.lead-bar{display:flex;align-items:center;gap:6px;flex-wrap:wrap;}
.lead-bar .btn-mini.btn-primary{font-weight:700;}
.lead-sep{font-size:11px;color:var(--muted);flex:none;}
/* 数据源分段开关：收退货 / 采购单（2026-10-12 用户要求，三张供应商卡各持选择态） */
.lead-src{display:inline-flex;flex:none;border:1px solid var(--btn-line);border-radius:6px;
  overflow:hidden;background:var(--btn-bg);}
.lead-src button{border:0;background:transparent;color:var(--muted);font-size:11px;
  padding:3px 10px;cursor:pointer;line-height:1.4;font-family:var(--font);}
.lead-src button + button{border-left:1px solid var(--btn-line);}
.lead-src button:hover{color:var(--ink);}
.lead-src button.on{background:var(--navy);color:#fff;font-weight:700;}
.lead-date{width:134px;flex:none;font-size:11px;padding:2px 6px;}
/* 矩阵「要求交期」输入框：2026-10-13 起改成天数（窄数字框），比日期框短得多 */
.mx-req-days{width:62px;flex:none;font-size:11px;padding:2px 6px;}
.lead-data-range{margin-left:auto;font-size:11px;color:var(--muted);white-space:nowrap;}
.bartrack.leadtrack{position:relative;}
.lead-whisk{position:absolute;top:50%;height:2px;transform:translateY(-50%);
  background:var(--muted);opacity:.5;border-radius:2px;min-width:2px;}
.lead-whisk::before,.lead-whisk::after{content:'';position:absolute;top:-2px;width:2px;height:6px;
  background:var(--muted);opacity:.85;border-radius:1px;}
.lead-whisk::before{left:0;}
.lead-whisk::after{right:0;}
.leadfill{opacity:.94;}
.leadval{min-width:104px;line-height:1.25;}
.leadval b{color:var(--ink);font-weight:700;}
.lead-sub{display:block;font-size:9.5px;color:var(--muted);white-space:nowrap;}

/* 仪表盘分区标题（2026-10-12 布局优化：卡片分三段后，每段一个通栏小标题）。
   它就是栅格里的 span12 元素，不占卡片行列；主题色跟随 --navy（六主题均已定义）。 */
.dash-sec{grid-column:span 12;display:flex;align-items:baseline;gap:9px;
  margin:4px 2px 0;padding:0 2px;}
.dash-sec:first-child{margin-top:0;}
.dash-sec-t{font-size:12.5px;font-weight:800;color:var(--navy);letter-spacing:.2px;
  display:inline-flex;align-items:center;white-space:nowrap;}
.dash-sec-t::before{content:'';width:3px;height:12px;border-radius:2px;
  background:var(--navy-2);margin-right:7px;flex:none;}

/* 供应商明细卡：下拉框 + 最近明细小表（复用 lead-bar 的选择条布局） */
.sup-bar{gap:7px;}
.sup-sel{width:220px;max-width:100%;flex:none;font-size:11.5px;padding:2px 6px;
  cursor:pointer;}
.sup-recent{margin-top:2px;min-width:0;}
/* 2026-10-15 用户要求：明细表一屏最多 12 条，超出的用鼠标滚轮滚动查看。
   ⚠ max-height 的**兜底值**（真正生效的是 app.js 的 supFitVisible 按实测行高写的 inline 值，
   因为行高随主题字号变化，CSS 写死必然对不上）：thead 21 + 行 18 × 12 ≈ 240px。
   overflow 用 auto（两个方向都要）：表格 7 列在半宽卡片里横向也会溢出，
   之前没给 overflow-x 结果被挤成两行；用 auto 后只出滚动条、不折行，行高才稳定。 */
.sup-tbl-wrap{max-height:240px;overflow:auto;border:1px solid var(--line-2);border-radius:var(--r);
  background:var(--panel);}
/* 滚动容器内不允许折行 —— 折行会让某行变高，supFitVisible 量的行高就不再是常量了 */
.sup-tbl-wrap .sup-tbl{white-space:nowrap;}
/* 表格宽度跟着容器走：先前 .sup-tbl{width:100%} 但 7 列有 nowrap + min-content 宽度，
   半宽卡片里实际要 367px > 容器 258px，横向溢出出一条滚动条，
   而**横向滚动条会吃掉纵向可视高度**（实测 13px）→ 明明设了 12 行却只露 10 行。
   下面这组把各列压缩进容器内，横向滚动条就不存在了，纵向高度也就准了。 */
.sup-tbl-wrap .sup-tbl{table-layout:fixed;width:100%;}
.sup-tbl-wrap .sup-tbl th,.sup-tbl-wrap .sup-tbl td{overflow:hidden;text-overflow:ellipsis;}
.sup-tbl-wrap .sup-tbl td.nm{max-width:none;}   /* 名称列不再省略号截断题外 */
.sup-tbl-wrap.is-scroll{border-color:var(--line);}
.sup-tbl-wrap .sup-tbl thead th{position:sticky;top:0;z-index:1;background:var(--thead-bg);
  color:var(--thead-fg);}
/* ⚠ glass / 深空 / 半透明主题的 --thead-bg 是 rgba(…,.8) —— sticky 表头下滚时
   下方的行会直接透上来，糊成一片。给这几档补一层**近乎不透明**的实色底衬。
   做法：color-mix 把不透明基色和半透明主题色按 82:18 混（预乘后 alpha≈0.98，肉眼等效实色），
   既保住主题色调，又不会透行。纯亮色主题的 --thead-bg 本来就是不透明色，不需要这层。 */
html[data-theme="glass"] .sup-tbl-wrap .sup-tbl thead th{
  background-color:color-mix(in srgb, #0a0f1a 82%, var(--thead-bg));
}
html.theme-space .sup-tbl-wrap .sup-tbl thead th{
  background-color:color-mix(in srgb, #f2f6fc 82%, var(--thead-bg));
}
/* 行分隔线跟着滚：thead 有独立底色后，tbody 首行的 border 会显得多余，去掉更干净 */
.sup-tbl-wrap .sup-tbl tbody tr:first-child td{border-top:none;}
/* 2026-10-16 用户要求内容 -20%：字号 11→10.5、单元格内边距 2.5→1.5px，行高约 22→18px */
.sup-tbl{width:100%;border-collapse:collapse;font-size:10.5px;
  font-variant-numeric:tabular-nums;}
.sup-tbl th{text-align:left;font-weight:600;color:var(--muted);padding:2px 8px 3px 0;
  border-bottom:1px solid var(--line);white-space:nowrap;}
.sup-tbl td{padding:1.5px 8px 1.5px 0;border-bottom:1px solid var(--line-2);
  color:var(--ink);white-space:nowrap;}
.sup-tbl tbody tr:last-child td{border-bottom:none;}
.sup-tbl tbody tr:hover td{background:var(--row-hover);}
.sup-tbl td.c{text-align:center;}
/* 半宽卡片内「货品名称」列超长时省略号截断（title 悬浮显示全称，信息不丢） */
.sup-tbl td.nm{max-width:120px;overflow:hidden;text-overflow:ellipsis;}

/* ==================================================================
   供应商交货矩阵（2026-10-12 新增，仿原 Excel「统计交货日期」表）
   行 = 供应商，列 = 收退货日期，格内数字 = 当天/当周单数。
   · 表头 sticky 置顶、首列 sticky 置左 → 横竖滚动都不迷失；
   · 格子按单数做蓝色热力（inline background，见 app.js mxTable）；
   · ★ 红色供应商名 = 重点关注（点名字切换，存 localStorage）；
   · 黄色竖线 = 我方「要求交期」日期（.mx-req-line，绝对定位覆盖矩阵）。
   ================================================================== */
.mx-host{max-height:520px;padding:0;}
.mx-wrap{max-height:520px;overflow:auto;border:1px solid var(--line);border-radius:var(--r);
  background:var(--panel);}
.mx-inner{position:relative;min-width:100%;}
.mx{border-collapse:separate;border-spacing:0;font-size:10.5px;
  font-variant-numeric:tabular-nums;}
.mx th,.mx td{border-right:1px solid var(--line-2);border-bottom:1px solid var(--line-2);
  padding:2px 2px;white-space:nowrap;}
/* 2026-10-13 用户要求「所有格宽度调小」：列宽 34→24px、内边距 5→2px。
   矩阵动辄 70 列，压窄后一屏能看到的天数翻倍，横向滚动次数大幅减少。 */
.mx thead th{position:sticky;top:0;z-index:2;background:var(--thead-bg);color:var(--thead-fg);
  font-weight:600;text-align:center;min-width:24px;border-bottom:1px solid var(--thead-line);}
.mx thead th.is-req{background:#b8860b;color:#fff;}     /* 要求交期所在列：表头染黄 */
/* 左上角「供方＼天数」角标：它比数字列宽（2026-10-13 文案由「供应商＼交期天数」缩写而来），
   显式给宽度，否则会被 24px 的 min-width 挤到换行/竖排。 */
.mx thead th.mx-corner{min-width:86px;text-align:left;padding-left:5px;}
.mx tbody th{position:sticky;left:0;z-index:1;background:var(--panel);text-align:left;
  font-weight:600;color:var(--ink);min-width:92px;max-width:124px;
  overflow:hidden;text-overflow:ellipsis;}   /* 2026-10-17 起不可点（重点关注功能已移除），去 pointer */
.mx tbody th:hover{background:var(--row-hover);}
.mx-sup-n{display:inline-block;margin-left:5px;font-weight:400;font-size:9.5px;
  color:var(--muted);font-variant-numeric:tabular-nums;}
.mx-cell{text-align:center;color:var(--ink);min-width:24px;height:22px;}
.mx-cell.has{font-weight:600;}
.mx tbody tr:hover th,.mx tbody tr:hover td{filter:brightness(.97);}
/* 黄线：盖住矩阵整列（含表头），不吃鼠标事件；顶端小标签说明来由 */
.mx-req-line{position:absolute;top:0;bottom:0;width:0;z-index:3;pointer-events:none;
  border-left:2px solid #f2c200;box-shadow:0 0 0 1px rgba(0,0,0,.22);}
.mx-req-tag{position:absolute;top:2px;left:3px;font-size:9.5px;font-weight:700;
  color:#7a5a00;background:#ffe9a8;border:1px solid #e0b400;border-radius:3px;
  padding:0 4px;line-height:15px;white-space:nowrap;}
.mx-trunc{font-size:10px;color:var(--amber);margin-left:6px;}

/* ==================================================================
   供应商月度价格变动矩阵（2026-10-16 新增，仿用户提供的 Excel 图）
   行 = 供应商，列 = 月份（26/01…），格内数字 = 当月价格变动次数。
   · 复用交货矩阵的 .mx-*（sticky 表头/首列、滚动容器）；
   · 标色：当月均为涨价 → 红、均为降价 → 绿、有涨有跌 → 不标色
     （inline background，见 app.js pcMatrix；红涨绿跌为国内惯例）；
   · hover 浮层 = 该供应商当月的价格变动明细（订单数据）。
   ================================================================== */
.pc-legend{margin-left:10px;font-size:10.5px;color:var(--muted);white-space:nowrap;}
.pc-legend .pc-lg{display:inline-block;width:10px;height:10px;border-radius:2px;
  margin:0 3px 0 10px;vertical-align:-1px;border:1px solid var(--line-2);}
.pc-legend .pc-lg:first-child{margin-left:0;}
.pc-legend .pc-lg.up{background:rgba(206,44,44,.45);border-color:rgba(206,44,44,.6);}
.pc-legend .pc-lg.down{background:rgba(22,138,72,.45);border-color:rgba(22,138,72,.6);}
.pc-legend .pc-lg.mix{background:transparent;}
.pc-dir-up{color:#c0392b;font-weight:600;}
.pc-dir-down{color:#1e8449;font-weight:600;}
html[data-theme="glass"] .pc-dir-up{color:#ff8a7a;}
html[data-theme="glass"] .pc-dir-down{color:#7ee0a0;}
html.theme-space .pc-dir-up{color:#d6453a;}
html.theme-space .pc-dir-down{color:#15915a;}

/* 订单价格明细表页：价格版本折叠（2026-10-16 用户要求）
   每组（供应商+物料编码）默认只显示最新一行，行内「▸ N」展开历史版本；
   历史版本行整体置灰 + ↳ 缩进，与当前价格行区分。 */
.pp-fold{padding:0 5px;line-height:18px;font-size:10.5px;}
table.grid tr.pp-hist td{color:var(--muted);background:rgba(127,127,127,.07);}
table.grid tr.pp-hist td.row-actions{background:transparent;}
/* 「不参考供应商（同料号合并）」模式下，折叠行供应商列后的「共N家」角标 */
.pp-sup-n{display:inline-block;margin-left:5px;padding:0 5px;line-height:15px;
  font-size:10px;border-radius:8px;color:var(--navy);
  background:var(--navy-soft);vertical-align:1px;white-space:nowrap;}

/* 纵向柱状
   坐标系：viewBox = 真实像素（见 app.js chartBarV 注释）。所以这里的字号/线宽都是真实 px。
   2026-10-16 用户要求：仪表盘各图「内容高度缩小 20%」——
     186→149、通栏 206→165；供应商两张卡 10-15 已缩过一轮（186→149），本轮再 -20% → 119。 */
.chart-svg{width:100%;height:149px;display:block;}
.chart-card.span12 .chart-svg{height:165px;}
/* 2026-10-15 用户要求：「供应商交期」与「供应商明细」两张图的高度缩小 20%
   （供应商明细用 chartBarV（.chart-svg），供应商交期用 chartLead（.barlist 行高））；
   2026-10-16 再次要求内容 -20% → 119px。 */
.lead-wrap .chart-svg{height:119px;}
.lead-wrap .barlist{gap:1px;}
/* 2026-10-17 用户要求：「供应商交期柱状把上下的空间利用起来，不要留空」——
   条形列表撑满卡片剩余高度（chart-box 是 flex 列、内容原来居中，行数固定 20 行时
   上下各空出一段）；行高本身不变，多余高度由行间距均摊（space-evenly），
   供应商很少时也不会挤在中间。 */
.lead-wrap .chart-box{justify-content:flex-start;}
.lead-wrap .chart-box .barlist{flex:1;justify-content:space-evenly;}
.lead-wrap .barrow{font-size:10.5px;padding:0;gap:5px;}
.lead-wrap .barrow .rk{width:12px;height:12px;font-size:9px;}
.lead-wrap .bartrack{height:9px;}
.lead-wrap .barfill{border-radius:2px;}
.lead-wrap .barlabel{font-size:10px;}
.lead-wrap .barval{min-width:92px;font-size:10px;line-height:1.1;}
/* 2026-10-16 用户要求内容 -20%：均值/区间/单数改单行显示（原来 min-width:92px 装不下
   「46.7 天46~49天 · 40单」被折成两行，行高 22px；放到 128px + nowrap 后单行 14px）。
   分隔符「 · 」由 app.js chartLead 的 lead-sub 前缀补上（inline 元素之间没有 gap）。 */
.lead-wrap .leadval{min-width:128px;white-space:nowrap;line-height:1.05;}
/* ⚠ 基础规则 .lead-sub{display:block}（第 414 行）会让区间/单数独占一行 —— 单行显示
   必须把 display 改回 inline，否则 min-width/nowrap 都不起作用。 */
.lead-wrap .lead-sub{display:inline;font-size:9px;opacity:.9;}
.chart-svg .chart-grid{stroke:var(--line);stroke-width:1;}
.chart-axis{fill:var(--muted);font-size:9.5px;text-anchor:middle;}
.chart-axis.ay{text-anchor:end;font-variant-numeric:tabular-nums;}
.chart-axis.ax{font-size:10px;}
.chart-axis.unit{text-anchor:start;font-size:9.5px;opacity:.85;}
.chart-bar{transition:height .5s cubic-bezier(.4,0,.2,1),y .5s cubic-bezier(.4,0,.2,1);}
.chart-bar:hover{opacity:.72;}
.chart-bar.back{opacity:.85;}
/* 2026-10-15：柱子可选中（点柱看明细）—— 热区铺满整槽全高并置于最上层，
   否则值很小的柱只有 1.5px 高，根本点不中。hover 用极淡底纹提示「这一列可选」。 */
.chart-hit{fill:transparent;cursor:pointer;}
.chart-hit:hover{fill:var(--chart-hit-bg);}
.chart-bar.sel{stroke:var(--navy-2);stroke-width:1.2;}
.chart-sel-band{pointer-events:none;}
.chart-sel-tick{pointer-events:none;}
/* 图上方的操作提示（点柱看明细） */
.chart-tip{font-size:10.5px;color:var(--muted);line-height:1.4;margin:0 0 2px;}
/* 明细区选中条：日期 + 笔数 + 返回入口 */
.sup-pick-h{gap:8px;}
.sup-pick-t{color:var(--ink);font-weight:700;}
.sup-pick-n{color:var(--muted);font-weight:400;font-size:10.5px;}
.chart-line,.chart-dot{transition:opacity .15s;}
.chart-line:hover,.chart-dot:hover{opacity:.7;}

/* 图例 */
.chart-legend{display:flex;flex-wrap:wrap;gap:6px 14px;margin-top:7px;font-size:11px;color:var(--muted);}
.chart-legend .lg{display:inline-flex;align-items:center;gap:5px;white-space:nowrap;}
.chart-legend .lg i{width:10px;height:10px;border-radius:3px;display:inline-block;flex:none;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.3);}
.chart-legend .lg.own{color:var(--ink);}
.chart-legend .lg i.mk-line{width:14px;height:3px;border-radius:2px;box-shadow:none;}

/* 环形图（2026-10-16 用户要求内容 -20%：116→93px，图例行距同步收窄） */
.chart-donut-wrap .chart-donut{display:grid;grid-template-columns:auto minmax(0,1fr);gap:12px;align-items:center;}
.chart-donut svg{width:93px;height:93px;display:block;flex:none;overflow:visible;}
.chart-donut .dn-val{fill:var(--navy);font-size:5.2px;font-weight:800;text-anchor:middle;}
.chart-donut .dn-lbl{fill:var(--muted);font-size:2.6px;text-anchor:middle;}
.chart-donut-side{display:flex;flex-direction:column;gap:2px;min-width:0;}
.chart-donut-side .dl-row{display:flex;align-items:center;gap:6px;font-size:10.5px;
  padding:1px 4px;border-radius:3px;}
.chart-donut-side .dl-row:hover{background:var(--row-hover);}
.chart-donut-side .dl-row i{width:9px;height:9px;border-radius:3px;flex:none;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.3);}
.chart-donut-side .dl-name{flex:1 1 auto;min-width:0;color:var(--ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.chart-donut-side .dl-num{flex:none;color:var(--muted);font-variant-numeric:tabular-nums;white-space:nowrap;}
.chart-donut-side .dl-pct{flex:none;color:var(--navy);font-weight:700;min-width:40px;text-align:right;
  font-variant-numeric:tabular-nums;}

/* 堆叠条（2026-10-16 用户要求内容 -20%：24→19px） */
.stackbar{display:flex;height:19px;border-radius:4px;overflow:hidden;background:var(--chart-track);
  box-shadow:inset 0 1px 2px rgba(0,0,0,.06);}
.stackseg{transition:width .55s cubic-bezier(.4,0,.2,1);position:relative;
  display:flex;align-items:center;justify-content:center;overflow:hidden;}
.stackseg b{font-size:10.5px;color:#fff;font-weight:700;text-shadow:0 1px 1px rgba(0,0,0,.28);
  font-variant-numeric:tabular-nums;}
.stackseg:hover{filter:brightness(1.1);}

/* ---------- 表格 ---------- */
/* overflow-anchor:none —— 关掉浏览器自带的「滚动锚定」。
   2026-10-16：就地删行时我们自己按被删行高度回退 scrollTop 来保证视口内容不跳，
   而 Chrome 的锚定也会做同样的事 → 两者叠加会多减一行高，反而跳得更明显。统一由 JS 负责。 */
.table-wrap{overflow:auto;overflow-anchor:none;border:1px solid var(--line);border-radius:var(--r);background:var(--wrap-bg);}
table.grid{width:100%;border-collapse:collapse;font-size:11.5px;line-height:var(--row-lh);}
table.grid th{
  position:sticky;top:0;background:var(--thead-bg);color:var(--thead-fg);font-weight:600;padding:var(--row-pad-h) 8px;
  text-align:left;white-space:nowrap;z-index:2;letter-spacing:.3px;
  border-right:1px solid var(--thead-line);
}
table.grid td{
  padding:var(--row-pad) 8px;border-bottom:1px solid var(--line-2);white-space:nowrap;
  max-width:220px;overflow:hidden;text-overflow:ellipsis;font-variant-numeric:tabular-nums;
}
table.grid tbody tr:nth-child(even){background:var(--row-alt);}
table.grid tbody tr:hover{background:var(--row-hover);}
.cell-edit{cursor:pointer;}
.cell-edit:hover{background:var(--cell-hover);}
/* 保存成功后该格闪一下绿底 —— 替代原来「整表重绘」给用户的确认反馈。
   （原来每存一格就 toast('已保存') + 重绘整表，闪得刺眼且慢；这里只提示真正写入的那一格）*/
table.grid td.cell-saved{animation:cellSaved .7s ease-out;}
@keyframes cellSaved{
  0%{background:rgba(46,160,90,.42);}
  100%{background:transparent;}
}
@keyframes cellSavedDark{
  0%{background:rgba(64,200,120,.40);}
  100%{background:transparent;}
}
.cell-calc{cursor:default;background:transparent;}
.cell-calc:hover{background:transparent;}
/* 订单表 订单欠料 / 订单在库：行高固定不撑高，单击弹层查看全部子件 */
table.grid td.cell-more{cursor:help;box-shadow:inset 0 -2px 0 -1px #c8d5e8;}
table.grid td.cell-more:hover{background-color:var(--cell-hover);box-shadow:inset 0 -2px 0 0 #8fa9cd;}
/* 2026-10-13 用户要求：订单欠料 / 订单在库 两列字体调小。
   这两格塞的是一长串子件名（实测常见 8~12 项），与表体同字号（11.5px）时列宽被撑到
   别的列都挤掉，扫读时也看不清分隔。降到 10px 并收紧字间距，一屏能多看几项。
   只降这两列 —— 其余列（订单号/品名/数量等）字号不动，保持与原表一致。 */
table.grid td.cell-seg{font-size:10px;letter-spacing:-.1px;}
table.grid td.cell-seg .seg-r,
table.grid td.cell-seg .seg-g{font-size:10px;}
/* ---------- 列宽调整：表头右缘拖拽手柄 ---------- */
table.grid th .col-resizer{
  position:absolute;top:0;right:0;width:8px;height:100%;z-index:6;
  cursor:col-resize;user-select:none;
}
table.grid th .col-resizer::after{
  content:'';position:absolute;left:3px;top:0;width:1px;height:100%;
  background:rgba(255,255,255,.2);transition:background .12s;
}
table.grid th:hover .col-resizer::after{background:rgba(255,255,255,.5);}
table.grid th .col-resizer:hover::after,
table.grid th .col-resizer.active::after{background:#8ec0ff;width:2px;left:3px;}
/* 客制列宽后（table-layout:fixed）：表头/单元格超出即裁剪，避免压到相邻列 */
table.grid.colw-fixed th{overflow:hidden;text-overflow:ellipsis;}
table.grid.colw-fixed td{max-width:none;}
body.col-resizing,body.col-resizing *{cursor:col-resize !important;user-select:none !important;}
/* 产能表：与原表「产能」工作表一致 —— 料号级 A–H ｜ 分隔列 ｜ 产品系列级 K–P 并排于同一张表 */
table.grid.cap-tbl th{white-space:pre-line;line-height:1.2;vertical-align:middle;}
/* 2026-10-13 用户要求「同一行着色颜色一致」改造（分两步）：
   ① 底色原先硬编码 #eef2f8/#e8edf6 —— dark/space 等深色主题下是一整条刺眼白竖条。
   ② 改成读 --cap-sep/--cap-sep-alt 虽解决了①，但**仍是独立于隔行色的一层**：
      实测一行 17 格里有 15 格透明（跟 tr 底色）、2 格分隔列有 `rgba(255,255,255,.07/.13)`，
      同一行两种底色。
   现在：分隔列**不再自带底色**（transparent，跟同行其它格完全一致），
   两块的区分改由**竖线**承担（.cap-start 的 border-left + 分隔列自身的左右边框）。
   这样整行是一条完整色带，横着扫过去不再半路变色。 */
table.grid.cap-tbl th.cap-sep,table.grid.cap-tbl td.cap-sep{
  width:30px;max-width:30px;padding:3px 4px;background:transparent;}
/* 分隔竖线：两侧各一道细线 + 右侧块起点一道粗线，替代原来的「底色块」 */
table.grid.cap-tbl th.cap-sep,table.grid.cap-tbl td.cap-sep{
  border-left:1px solid var(--cap-sep-line,#c6d3e6);
  border-right:1px solid var(--cap-sep-line,#c6d3e6);}
table.grid.cap-tbl .cap-start{border-left:2px solid var(--cap-sep-line,#c6d3e6);}
/* 产能表：分组标题行 —— 让「料号级明细」与「产品系列基准」两块一眼可辨，不再像重复的两张表 */
table.grid.cap-tbl thead tr.cap-group th{
  position:sticky;top:0;z-index:3;height:23px;box-sizing:border-box;
  background:#e7edf8;color:var(--navy);font-size:11px;font-weight:700;
  letter-spacing:.4px;padding:2px 8px;white-space:nowrap;line-height:1.2;
  border-bottom:1px solid #ccd8ea;border-right:1px solid #dbe3f0;
}
table.grid.cap-tbl thead tr.cap-group th.cap-gh-mid{background:#eef2f8;}
table.grid.cap-tbl thead tr.cap-group th.cap-start{border-left:2px solid #b9c9e2;}
/* 真正的列名行跟随分组行之下 */
table.grid.cap-tbl thead tr:not(.cap-group) th{top:23px;}
/* 未能按产品系列联动到右侧块的行（系列为空/未找到）：淡黄底提示 */
table.grid.cap-tbl td.cap-unlinked{background:#fff8e4;box-shadow:inset 0 0 0 1px #f0e0b0;}
/* 右侧「产品系列产能基准」尚未填写的空白行：整行可点，点击即新增一个产品系列 */
table.grid.cap-tbl td.cap-new-cell{cursor:pointer;}
table.grid.cap-tbl td.cap-new-cell:hover{background:#e8f0fd;box-shadow:inset 0 0 0 1px #b9cdee;}
table.grid.cap-tbl .cap-add-tag{color:#5a7bb0;font-weight:600;font-size:10.5px;}
table.grid.cap-tbl td.cap-new-cell:hover .cap-add-tag{color:var(--navy);}
/* 产品系列重名提醒（重名时左侧料号只取最后一个同名行的值） */
table.grid td.cap-dup{background:#fdeceb;color:var(--red);font-weight:600;}
/* ===== 附件表 ===== */
/* 表头：「附件明细」跨 6 列居中，子列在其下方 */
table.grid.sheet-attachments th.att-main-head{text-align:center;background:var(--navy-soft);color:var(--navy);font-weight:700;}
/* 多行表头 sticky：第一行贴顶，第二行在第一行下方 */
table.grid.sheet-attachments thead tr:first-child th{top:0;}
table.grid.sheet-attachments thead tr:nth-child(2) th{top:23px;}
/* 附件格：fixed 布局下宽度完全由 colgroup 决定，min/max 不设限（长文件名 ellipsis 兜底） */
table.grid.sheet-attachments td.att-cell{padding:4px 6px;vertical-align:top;min-width:0;max-width:none;}
/* 固定列宽布局（table-layout:fixed）：默认列宽见 app.js renderAttachments 的 table._defColW ——
   左侧 5 列 + 备注/操作定宽，6 个附件列均分剩余宽度。长规格/长文件名不再把表撑宽、
   挤占附件列；用户拖表头手柄可改，双击还原。 */
table.grid.sheet-attachments{table-layout:fixed;min-width:960px;}
table.grid.sheet-attachments td{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.att-list{display:flex;flex-direction:column;gap:3px;}
/* 单元格多文件折叠（2026-10-15）：默认只显示最新版本一行，点三角/空白处展开全部 */
.att-cell-more{position:relative;padding-right:28px!important;cursor:pointer;}
.att-list-row{min-width:0;}
.att-toggle{position:absolute;right:2px;top:2px;padding:0 4px;margin:0;
  border:1px solid var(--line);border-radius:6px;background:var(--wrap-bg);color:var(--muted);
  font-size:9.5px;line-height:15px;cursor:pointer;}
.att-toggle:hover{color:var(--navy);border-color:var(--navy);}
.att-toggle.is-open{color:var(--navy);border-color:var(--navy);}
html.theme-space .att-toggle{background:rgba(255,255,255,.06);}
/* 文件名显示为普通超链接：蓝字 + 下横线（与 Excel 里的链接一致），不再用胶囊底块 */
.att-file{display:inline-block;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  color:var(--navy);font-size:10.5px;text-decoration:underline;padding:0;}
/* 表格里登记了、但磁盘上已经找不到的附件文件：标红 + 删除线（悬停有完整路径，点击给出提示） */
a.att-file.att-missing{color:var(--red);text-decoration:line-through;}
a.att-file-name.att-missing{color:var(--red);text-decoration:line-through;}

/* 附件表按「类别」分组：组头行（折叠/展开）+ 对照表弹窗 */
.att-group-row{cursor:pointer;background:var(--att-group-bg,#eef3fb);transition:background .12s;}
.att-group-row:hover{background:var(--att-group-bg2,#e2eaf6);}
.att-group-cell{padding:7px 10px;border-bottom:1px solid var(--line);font-size:12.5px;}
.att-glyph{display:inline-block;width:18px;color:var(--navy);font-weight:700;}
.att-group-name{font-weight:700;color:var(--navy);}
.att-group-count{margin-left:8px;color:var(--muted);font-weight:400;font-size:11.5px;}
html.theme-space .att-group-row{background:rgba(120,160,220,.12);}
html.theme-space .att-group-row:hover{background:rgba(120,160,220,.2);}
html.theme-space .att-glyph{color:var(--ink);}
html.theme-space .att-group-name{color:var(--ink);}
.catmap-head{display:flex;gap:8px;font-size:11.5px;color:var(--muted);margin:8px 2px 2px;}
.catmap-head span:first-child{width:92px;}
.catmap-head span:nth-child(2){flex:1;min-width:120px;}
.catmap-body{max-height:300px;overflow:auto;margin:2px 0 6px;}
.catmap-row{display:flex;gap:8px;align-items:center;margin:5px 0;}
.catmap-pfx{width:92px;flex:none;}
.catmap-cat{flex:1;min-width:120px;}
.catmap-row .btn{min-width:auto;}

/* 更新名称/规格 弹窗 */
.upd-body{max-height:340px;overflow:auto;margin:2px 0 6px;}
.upd-row{display:flex;gap:10px;align-items:flex-start;padding:7px 4px;border-bottom:1px solid var(--line);}
.upd-row:last-child{border-bottom:none;}
.upd-ck{margin-top:3px;flex:none;width:16px;height:16px;}
.upd-meta{flex:1;min-width:0;}
.upd-code{font-weight:600;color:var(--ink);font-family:Consolas,"Courier New",monospace;margin-bottom:3px;}
.upd-line{display:flex;gap:8px;align-items:baseline;font-size:12px;line-height:1.6;}
.upd-line.upd-same{color:var(--muted);}
.upd-field{flex:none;width:38px;color:var(--muted);}
.upd-old{color:var(--red);text-decoration:line-through;}
.upd-arrow{flex:none;color:var(--muted);}
.upd-new{color:var(--green);font-weight:600;}
html.theme-space .upd-new,html[data-theme="glass"] .upd-new{color:#7ee081;}
.upd-all{display:inline-flex;gap:6px;align-items:center;margin-top:6px;font-size:12px;color:var(--muted);}
.upd-all-ck{width:15px;height:15px;}

/* 附件弹窗表单 */
.att-form{display:flex;flex-direction:column;gap:16px;}
/* 弹窗两行布局（2026-10-15 调整）：第一行 供应商/物料编码/物料名称 各占 1/3；第二行 规格 */
.att-form-row{display:grid;gap:14px 18px;align-items:start;}
.att-row3{grid-template-columns:repeat(3,1fr);}
.att-row1{grid-template-columns:1fr;}
.att-form .field{display:flex;flex-direction:column;gap:5px;margin:0;}
.att-form .field label{font-size:12px;font-weight:600;color:var(--ink);}
.att-form .att-mat-input{width:100%;}
/* 物料编码 combobox 全宽 */
.att-form .f-code .att-combo{width:100%;}
/* 物料编码模糊查找 combobox */
.att-combo{position:relative;}
.att-combo-drop{position:absolute;top:100%;left:0;right:0;z-index:90;max-height:260px;overflow:auto;
  border:1px solid var(--line);border-radius:8px;margin-top:3px;display:none;
  background:var(--input-bg);box-shadow:0 10px 28px rgba(0,0,0,.3);}
.att-combo-drop.open{display:block;}
.att-combo-opt{display:flex;gap:8px;align-items:baseline;padding:6px 10px;cursor:pointer;font-size:12.5px;}
.att-combo-opt.active,.att-combo-opt:hover{background:var(--row-hover);}
.att-combo-code{font-weight:700;color:var(--navy);white-space:nowrap;}
.att-combo-name{color:var(--ink);flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.att-combo-spec{color:var(--muted);white-space:nowrap;}
.att-combo-none{padding:8px 10px;color:var(--muted);font-size:12px;cursor:default;}
/* 提示：已新增到表格的料号不在下拉候选里 */
.att-code-hint{font-size:11.5px;line-height:1.4;color:var(--muted);}
/* 「＋ 添加文件」按钮加大 */
.att-add-file{padding:9px 18px;font-size:13.5px;font-weight:600;border-radius:8px;}
.att-form .att-readonly{background:var(--bg2);color:var(--muted);cursor:not-allowed;}
.att-form .att-section{border:1px solid var(--line);border-radius:var(--r);padding:12px;background:var(--wrap-bg);}
.att-sec-head{display:flex;justify-content:space-between;align-items:center;margin-bottom:8px;}
.att-sec-head label{font-weight:700;color:var(--navy);font-size:13px;}
.att-files{display:flex;flex-direction:column;gap:6px;min-height:28px;}
.att-empty{color:var(--muted);font-size:12px;font-style:italic;}
.att-file-row{display:flex;align-items:center;justify-content:space-between;gap:10px;
  padding:4px 8px;border-radius:4px;background:var(--bg2);border:1px solid var(--line);}
.att-file-name{flex:0 1 auto;max-width:56%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  color:var(--navy);font-size:12px;text-decoration:underline;}
.att-file-desc{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  color:var(--muted);font-size:11.5px;}
/* 备注列：只在表格里手动输入（弹窗无此字段），点单元格即填 */
table.grid.sheet-attachments th.att-remark-head{min-width:0;}
table.grid.sheet-attachments td.att-remark-cell{min-width:0;max-width:none;
  white-space:pre-wrap;word-break:break-all;cursor:text;}
table.grid.sheet-attachments td.att-remark-cell:empty::after{
  content:'点击填写';color:var(--muted);font-style:italic;}
table.grid.sheet-attachments td.att-remark-cell .pt-inline{width:100%;min-width:0;}
table.grid.sheet-attachments td.att-remark-cell input.pt-inline{
  width:100%;min-width:0;box-sizing:border-box;font-size:12px;padding:2px 5px;
  border:1px solid var(--navy);border-radius:4px;background:var(--input-bg);color:var(--ink);outline:none;}
/* 删除确认弹窗：列出该行涉及的所有附件文件 */
.att-del-rowinfo{font-weight:700;color:var(--navy);margin:2px 0 8px;word-break:break-all;}
.att-del-none{color:var(--muted);font-size:12px;margin:4px 0 2px;}
.att-del-list{max-height:190px;overflow:auto;margin:4px 0 2px;
  border:1px solid var(--line);border-radius:6px;background:var(--bg2);}
.att-del-file{display:flex;align-items:center;gap:8px;padding:4px 9px;font-size:12px;}
.att-del-file+.att-del-file{border-top:1px dashed var(--line);}
/* 明细复选框：勾选才会删；默认不勾选，一个都没勾时删除键禁用 */
.att-del-all{display:inline-flex;align-items:center;gap:5px;font-size:12px;color:var(--muted);
  margin:2px 0 5px;cursor:pointer;user-select:none;}
.att-del-all:hover{color:var(--ink);}
.att-del-all input,.att-del-file input.att-del-ck{width:14px;height:14px;margin:0;cursor:pointer;accent-color:var(--red);}
.att-del-type{flex:0 0 44px;color:var(--muted);}
.att-del-name{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--ink);}
.att-del-flag{flex:0 0 auto;color:var(--red);font-size:11px;}
.att-del-file.att-missing .att-del-name{color:var(--red);text-decoration:line-through;}
/* 删除键禁用（未勾选任何文件） */
button.btn-danger:disabled{opacity:.5;cursor:not-allowed;}
button.btn-danger:disabled:hover{background:transparent;color:var(--red);border-color:#eccfcc;}
/* 「再次点击确认删除」待确认状态：脉冲光圈提醒 */
button.btn-danger.btn-arming{animation:att-arm-pulse 1s ease-in-out infinite;}
@keyframes att-arm-pulse{
  0%,100%{box-shadow:0 0 0 0 rgba(192,57,43,.45);}
  50%{box-shadow:0 0 0 5px rgba(192,57,43,.14);}
}

/* 深色 / 玻璃 / 深空主题适配 */
html.theme-space .att-form .att-section{background:rgba(255,255,255,.05);}
html.theme-space a.att-file.att-missing{color:#ff8a80;}
html.theme-space a.att-file-name.att-missing{color:#ff8a80;}
/* 删除确认弹窗（深空） */
html.theme-space .att-del-rowinfo{color:#9ec7f0;}
html.theme-space .att-del-list{border-color:rgba(255,255,255,.14);background:rgba(255,255,255,.04);}
html.theme-space .att-del-name{color:#e9eef6;}
html.theme-space .att-del-flag,html.theme-space .att-del-file.att-missing .att-del-name{color:#ff8a80;}
html.theme-space button.btn-danger.btn-arming{animation:att-arm-pulse-sp 1s ease-in-out infinite;}
@keyframes att-arm-pulse-sp{
  0%,100%{box-shadow:0 0 0 0 rgba(255,107,91,.5);}
  50%{box-shadow:0 0 0 5px rgba(255,107,91,.16);}
}
/* combobox 下拉 = 第 3 层浮层：与 confirm-box 同材质 */
html.theme-space .att-combo-drop{
  background:rgba(20,26,38,.96);border-color:rgba(255,255,255,.26);
  box-shadow:0 14px 42px rgba(0,0,0,.65);
}
html.theme-space .att-combo-code{color:#9ec7f0;}
html.theme-space .att-combo-opt.active,html.theme-space .att-combo-opt:hover{background:rgba(255,255,255,.10);}
/* 齐套分析/订单表的料号下拉也统一成第 3 层 */
html.theme-space .kit-prod-drop{
  background:rgba(20,26,38,.96);border-color:rgba(255,255,255,.26);
  box-shadow:0 14px 42px rgba(0,0,0,.65);
}
/* 版本 / 变更内容 弹窗 */
.ver-box{min-width:400px;max-width:480px;}
.ver-row{display:flex;flex-direction:column;gap:5px;margin-top:12px;}
.ver-row label{font-size:12px;font-weight:600;color:var(--ink);}
.ver-v{max-width:120px;}
.ver-desc{resize:vertical;font-family:inherit;line-height:1.5;min-height:56px;}
/* 同名弹窗里的「已有版本 / 跨文件夹冲突」明细（2026-10-15：同名弹窗增加描述） */
.dup-box{min-width:460px;max-width:580px;}
.dup-head,.dup-row{display:flex;gap:8px;align-items:baseline;font-size:12px;}
.dup-head{color:var(--muted);font-weight:600;padding:0 2px 4px;border-bottom:1px solid var(--line);}
.dup-list{max-height:170px;overflow:auto;margin:8px 0 2px;}
.dup-row{padding:4px 2px;}
.dup-row+.dup-row{border-top:1px dashed var(--line);}
.dup-type{flex:0 0 66px;color:var(--navy);font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.dup-v{flex:0 0 38px;color:var(--muted);}
.dup-date{flex:0 0 76px;color:var(--muted);}
.dup-desc{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--ink);}
.ver-hist{max-height:120px;margin-top:6px;}
/* 同名弹窗里的「改名输入框」：默认原文件名，用户在原名后补描述 */
.dup-name{width:100%;box-sizing:border-box;}
/* 版本弹窗里的落盘文件名预览（原名_20261015_v2.pdf） */
.ver-preview{margin-top:6px;font-size:12px;color:var(--muted);word-break:break-all;}

/* 订单表 欠料/在库 列内着色（对应原表字符级标色） */
.seg-r{color:#c0271c;text-decoration:underline;}
.seg-g{color:#1a35c8;text-decoration:line-through;}
.tag{display:inline-block;padding:0 6px;border-radius:3px;font-size:10.5px;font-weight:600;line-height:1.3;}
.tag.red{background:#fbeae8;color:var(--red);}
.tag.green{background:#e6f4ec;color:var(--green);}
.tag.amber{background:#faf0dc;color:var(--amber);}
.tag.gray{background:#eef1f6;color:var(--muted);}
/* 采购单价变动清单（2026-10-16）：原单价 / 新单价 用色区分 */
table.grid.price-chg td.old{color:#c0392b;font-weight:600;}
table.grid.price-chg td.new{color:#1e8449;font-weight:700;}
html[data-theme="glass"] table.grid.price-chg td.old{color:#ff8a7a;}
html[data-theme="glass"] table.grid.price-chg td.new{color:#7ee0a0;}
html.theme-space table.grid.price-chg td.old{color:#d6453a;}
html.theme-space table.grid.price-chg td.new{color:#15915a;}
/* 采购订单价格明细：金额/单价列右对齐 + 等宽数字 */
table.grid td.num{text-align:right;font-variant-numeric:tabular-nums;white-space:nowrap;}
/* 订单「日期」列：最晚到料日期 +「在购 N 项」角标 并排显示，悬停出子件在购明细浮层 */
.cell-note{cursor:help;}
.cell-note:hover{background:#f3f7fd;}
.note-badge{display:inline-block;padding:0 7px;border-radius:9px;background:#eaf1fb;color:var(--navy);
  font-size:10.5px;font-weight:600;line-height:1.35;border:1px solid #cdddf2;white-space:nowrap;}
.cell-note:hover .note-badge{background:#dbe8fa;}
/* 2026-10-13：M 列「日期」改为**只显示在购角标**后，.kit-cell / .kit-date
   （原为「日期值 + 角标」并排而设的 flex 容器）已无人使用，一并删除，避免留下误导性的死样式。
   日期值改由 td.title 承载。*/
/* 悬停浮层：fixed 定位（表格是内部滚动容器），跟随锚点重定位。
   ⚠ 明细表**不复用主表排版**：主表为了塞下几十列把 --row-pad 压到 1px、字号 11px，
   照搬到浮层里行挤成一团、字小发虚 → 这里自成一套（紧凑但仍清晰：11.5px / 行高 ~1.45 / 斑马纹 / 悬停行）。
   配色走局部变量 --np-*，深色与玻璃主题各自覆盖，避免「白底 + 浅色字」看不清。
   「淡」：底色半透明 + 背后轻模糊、阴影更轻更散、描边/斑马纹更淡；
   **文字颜色保持不变**（可读性优先，淡的是"面"不是"字"）。 */
.note-pop{
  --np-bg:rgba(255,255,255,.93); --np-fg:#16233a; --np-fg2:#4b5a70; --np-line:#e6ebf3;
  --np-head-bg:rgba(31,56,100,.055); --np-head-fg:#1b3a63;
  --np-zebra:rgba(31,56,100,.022); --np-hover:rgba(31,56,100,.07);
  --np-bar-fg:#fff;
  position:fixed;z-index:9000;background:var(--np-bg);color:var(--np-fg);
  border:1px solid rgba(168,188,214,.55);border-radius:var(--r);
  box-shadow:0 7px 20px rgba(25,50,90,.13);
  backdrop-filter:blur(14px) saturate(130%);-webkit-backdrop-filter:blur(14px) saturate(130%);
  max-width:min(880px,94vw);max-height:70vh;
  display:flex;flex-direction:column;overflow:hidden;}
.note-pop-h{padding:5px 10px;background:var(--np-bar-bg,var(--navy));color:var(--np-bar-fg);
  font-size:11.5px;font-weight:700;letter-spacing:.3px;
  background-image:linear-gradient(rgba(255,255,255,.10),rgba(255,255,255,.10));}
.note-pop-b{overflow:auto;padding:0;}
.note-pop-t{border-collapse:separate;border-spacing:0;width:100%;font-size:11.5px;line-height:1.45;}
.note-pop-t th{background:var(--np-head-bg);color:var(--np-head-fg);font-weight:700;font-size:11px;
  padding:4px 9px;text-align:left;white-space:nowrap;position:sticky;top:0;z-index:1;
  letter-spacing:.3px;border-bottom:1px solid var(--np-line);box-shadow:0 1px 0 var(--np-line);}
.note-pop-t td{padding:3px 9px;border-bottom:1px solid var(--np-line);white-space:nowrap;
  font-variant-numeric:tabular-nums;vertical-align:middle;color:var(--np-fg);}
.note-pop-t tbody tr:nth-child(even) td{background:var(--np-zebra);}
.note-pop-t tbody tr:hover td{background:var(--np-hover);}
.note-pop-t tbody tr:last-child td{border-bottom:none;}
.note-pop-t .np-idx{color:var(--np-fg2);text-align:right;width:34px;}
.note-pop-t .np-date{color:var(--np-head-fg);font-weight:700;width:74px;}
.note-pop-t .np-code{font-family:Consolas,Menlo,monospace;font-size:11px;}
.note-pop-t .np-name{min-width:84px;}
.note-pop-t .np-memo{color:var(--np-fg2);white-space:normal;min-width:110px;max-width:260px;}
.note-pop .np-code{width:78px;}
/* 浮层内的标色与主表单元格**完全一致**：红字+下划线（16-/17- 排在前面）
   / 蓝字+删除线（26-/27- 排在后面）。缺 text-decoration 会让浮层看着"没标注"。*/
.note-pop .seg-r{color:#c0271c;font-weight:600;text-decoration:underline;}
.note-pop .seg-g{color:#1a35c8;font-weight:600;text-decoration:line-through;}
/* 整行极淡底色，让两类标色在长列表里一眼可分（不遮文字） */
.note-pop-t tbody tr.np-seg-r td{background:rgba(192,39,28,.055);}
.note-pop-t tbody tr.np-seg-g td{background:rgba(26,53,200,.05);}
/* 玻璃主题：白底 + 浅色字 = 几乎读不出来，这里整体切深色（同样做淡处理） */
/* 订单 M 列「在购 N 项」角标：深色下默认的浅蓝底会刺眼且与整体脱节 → 转成半透明描边 */
/* 玻璃主题 */
html[data-theme="glass"] .note-pop{
  --np-bg:rgba(9,15,26,.90); --np-fg:#e9eff8; --np-fg2:rgba(233,239,248,.62); --np-line:rgba(255,255,255,.10);
  --np-head-bg:rgba(255,255,255,.07); --np-head-fg:#f0f6ff; --np-zebra:rgba(255,255,255,.025);
  --np-hover:rgba(255,255,255,.09);
}
html[data-theme="glass"] .note-pop .seg-r{color:#ff9a8c;text-decoration:underline;}
html[data-theme="glass"] .note-pop .seg-g{color:#9db4ff;text-decoration:line-through;}
.row-actions{white-space:nowrap;}
.row-actions button{margin-right:4px;padding:0 6px;font-size:10.5px;}
/* 订单表：序号列后的「上移 / 下移」列（2026-10-17 用户要求放在序号与下单日期之间） */
table.grid.sheet-orders th.col-move,
table.grid.sheet-orders td.col-move{text-align:center;padding:2px 3px;white-space:nowrap;vertical-align:middle;}
table.grid.sheet-orders td.col-move .btn-mini{padding:0 3px;min-width:0;font-size:10px;line-height:1.35;}
/* 行序控件（订单表 上移 / 下移） */
.btn-mini{padding:0 5px;font-size:10px;line-height:1.3;min-width:20px;border-radius:3px;}
.btn-mini:disabled{opacity:.32;cursor:not-allowed;border-color:var(--line);color:var(--muted);}

/* ---------- 弹窗 ---------- */
.modal-mask{position:fixed;inset:0;background:rgba(20,30,50,.38);display:flex;align-items:center;justify-content:center;z-index:50;}
/* 行编辑弹窗（从其它窗体弹窗内部触发，如「产品系列产能」里点编辑）需盖在窗体弹窗之上 */
#modalMask{z-index:60;}
/* ⚠ 弹窗一律「外壳不滚、内容区滚」：
   backdrop-filter 加在**自身是滚动容器**的元素上，滚动时 Chromium 每帧都要重算
   被它盖住的那片背景 —— 表现是滚动时整块糊一下／闪回（历史上实测过）。
   所以 .modal 改成 overflow:hidden + flex 列，让 .modal-body 自己滚；
   这样带模糊的外壳几何不变，模糊结果可被缓存，滚动就稳了。 */
.modal{background:var(--modal-bg);border-radius:6px;width:450px;max-width:92vw;max-height:86vh;
  overflow:hidden;display:flex;flex-direction:column;
  box-shadow:var(--win-shadow);
  backdrop-filter:var(--modal-blur);-webkit-backdrop-filter:var(--modal-blur);}
.modal-title{font-size:13px;font-weight:700;color:var(--navy);padding:9px 13px;border-bottom:1px solid var(--line);
  letter-spacing:.3px;flex:0 0 auto;}
.modal-body{padding:12px 13px;display:grid;grid-template-columns:1fr 1fr;gap:8px;
  flex:1 1 auto;min-height:0;overflow:auto;align-content:start;}
.modal-body .field{display:flex;flex-direction:column;gap:3px;}
.modal-body label{font-size:11px;color:var(--muted);}
/* 派生字段的说明小字（订单号→客户代码）：告诉用户这一格不用手填、是怎么来的 */
.modal-body .field-tip{font-size:10px;color:var(--muted);opacity:.85;line-height:1.35;margin-top:-1px;}
/* 自动带出的一瞬高亮：让用户确认「它自己填好了」 */
.modal-body input.auto-filled{animation:autoFilled .9s ease-out;}
@keyframes autoFilled{
  0%{background:#fff3cd;border-color:#e0a800;box-shadow:0 0 0 2px rgba(224,168,0,.28);}
  100%{background:transparent;}
}
.modal-body input,.modal-body select{
  border:1px solid var(--line);border-radius:var(--r);padding:4px 8px;font-size:12px;font-family:inherit;outline:none;
}
.modal-body input:focus{border-color:var(--navy);box-shadow:0 0 0 2px rgba(31,56,100,.08);}
.modal-foot{display:flex;justify-content:flex-end;gap:6px;padding:9px 13px;border-top:1px solid var(--line);
  background:rgba(255,255,255,.35);flex:0 0 auto;}

/* 通用确认框（改「开始日期」等牵动全局的值时二次确认，2026-10-13）
   独立于行编辑弹窗 #modalMask(z-index:60)，故抬到 70；低于 toast(80)。 */
.confirm-mask{z-index:70;}
/* 确认框内容短、自身不滚，可以直接上模糊（同 .modal 的材质，观感一致） */
.confirm-box{background:var(--modal-bg);border-radius:8px;min-width:300px;max-width:400px;
  padding:14px 16px 12px;box-shadow:var(--win-shadow);display:flex;flex-direction:column;gap:10px;
  backdrop-filter:var(--modal-blur);-webkit-backdrop-filter:var(--modal-blur);}
.confirm-title{font-size:13px;font-weight:700;color:var(--navy);letter-spacing:.3px;}
.confirm-msg{font-size:12.5px;line-height:1.65;color:var(--ink);word-break:break-word;}
.confirm-msg b{color:var(--navy);font-weight:700;}
.confirm-foot{display:flex;justify-content:flex-end;gap:8px;}
/* 手动粘贴文件夹路径输入框（附件表） */
.fp-row{display:flex;gap:8px;align-items:center;}
.fp-tip{font-size:11.5px;line-height:1.6;color:var(--ink);opacity:.8;word-break:break-word;}
.fp-input{flex:1;min-width:0;font-size:12.5px;padding:7px 9px;border:1px solid var(--line);
  border-radius:6px;background:var(--input-bg);color:var(--ink);outline:none;}
.fp-input:focus{border-color:var(--navy);}
.fp-row .btn{white-space:nowrap;}

/* ---------- Toast ---------- */
.toast{position:fixed;bottom:16px;left:50%;transform:translateX(-50%);background:var(--navy);color:#fff;
  padding:7px 14px;border-radius:var(--r);font-size:12px;z-index:80;box-shadow:0 6px 18px rgba(0,0,0,.24);}

/* ---------- 甘特（备用视图） ---------- */
.gantt{display:flex;font-size:10.5px;}
.gantt-left{width:220px;flex-shrink:0;border-right:1px solid var(--line);}
.gantt-right{overflow:auto;flex:1;}
.gantt-row{display:flex;height:22px;align-items:center;border-bottom:1px solid var(--line-2);}
.gantt-left .gantt-row{position:sticky;left:0;background:#fff;padding:0 8px;}
.gantt-head{display:flex;position:sticky;top:0;z-index:3;background:var(--navy);color:#fff;height:22px;}
.gantt-head .gantt-left{background:var(--navy);}
.gantt-timeline{position:relative;height:22px;}
.gantt-day{position:absolute;top:0;height:22px;border-left:1px solid var(--line-2);display:flex;align-items:center;justify-content:center;font-size:9px;color:#fff;opacity:.85;}
.gantt-month{position:sticky;top:0;height:18px;background:#33508c;color:#fff;display:flex;align-items:center;padding:0 8px;font-size:9.5px;z-index:4;}
.gantt-bar{position:absolute;top:2px;height:18px;border-radius:2px;background:var(--navy);color:#fff;
  display:flex;align-items:center;padding:0 4px;font-size:9.5px;white-space:nowrap;overflow:hidden;box-shadow:0 1px 2px rgba(0,0,0,.15);}
.gantt-bar.short{background:var(--red);}

/* ---------- 导入导出 ---------- */
.io-box{padding:13px;}
.io-row{display:flex;gap:6px;align-items:center;margin-bottom:8px;flex-wrap:wrap;}
.io-note{color:#4a5666;font-size:11px;line-height:1.6;background:var(--navy-soft);
  border:1px solid #d8e1ef;border-radius:var(--r);padding:8px 11px;margin-top:6px;}
.io-note b{color:var(--navy);}
.io-sheet-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:8px;margin-top:6px;}
.io-sheet-cell{background:#fff;border:1px solid var(--line);border-radius:var(--r);padding:9px;display:flex;flex-direction:column;gap:6px;}
.io-sheet-name{font-size:12px;font-weight:700;color:var(--navy);}
.io-sheet-cell .btn{align-self:flex-start;}
.section-h{font-size:12.5px;font-weight:700;color:var(--navy);margin:12px 0 7px;letter-spacing:.3px;
  padding-left:7px;border-left:3px solid var(--navy);}
.pill{display:inline-block;background:var(--navy-soft);color:var(--navy);border-radius:3px;padding:1px 8px;
  font-size:10.5px;margin:1px;border:1px solid #d8e1ef;font-variant-numeric:tabular-nums;}

/* ---------- 操作面板（主控制面板，对应原 UserForm3） ---------- */
.panel-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(118px,1fr));gap:7px;margin-bottom:6px;}
/* 2026-10-12：按键下方的说明小字已删（用户要求），卡片只剩一行标题 ——
   改为固定最小高度 + 居中，单行文字在格子里垂直居中，观感更像按钮而不是残缺的卡片。
   .panel-card-d 规则保留未删：留着以备恢复小字（app.js 加回一行即可），当前没有元素命中它。 */
.panel-card{background:var(--panel);border:1px solid var(--line);border-radius:var(--r);padding:8px 10px;cursor:pointer;
  transition:.15s;border-left:3px solid var(--navy);
  display:flex;align-items:center;justify-content:center;min-height:42px;text-align:center;}
.panel-card:hover{box-shadow:0 2px 8px rgba(31,56,100,.1);border-color:#c6d2e4;}
/* 仪表盘图表卡与按键卡同挂 .panel-card，但需要子项水平拉伸：
   .panel-card 的 align-items:center 同特异性下靠后胜出，会把卡片子项掐成内容宽
   （SVG 固有宽只有 300px → 图变窄、x 轴标签被过度抽稀），故用双类特异性盖掉。
   垂直居中（justify-content:center）保留，卡片高度不满时内容仍居中。 */
.panel-card.chart-card{align-items:stretch;}
/* 2026-10-12 用户要求「按键颜色一致」：原先 .panel-card.exec 会把一部分键渲染成
   深藏青实底 + 白字，与其余白底键混在一起像两套界面。现已全部统一成同一种样式，
   .panel-card.exec 相关规则（基础 3 条 + glass 2 条 + space 1 条）全部删除。
   想恢复「主操作」区分度，把这些规则加回来 + app.js 侧同步改 class 拼接即可。 */
.panel-card-t{font-size:12.5px;font-weight:700;color:var(--navy);line-height:1.35;}
.panel-card-d{font-size:10.5px;color:var(--muted);margin-top:3px;line-height:1.45;}
.panel-result{margin-top:6px;}
.panel-result:empty{display:none;}
.io-flash{animation:ioflash 1.6s ease-out;}
@keyframes ioflash{0%{box-shadow:0 0 0 3px rgba(31,56,100,.4);background:#eef3fb;}100%{box-shadow:0 0 0 0 rgba(31,56,100,0);background:transparent;}}

/* ---------- 齐套查询 ---------- */
.kit-result{margin-top:4px;}
.kit-result table.grid{max-width:920px;}

/* 成品料号下拉（自定义 combobox：料号 + 产品名称，名称仅展示不参与计算） */
.kit-prod-wrap{position:relative;display:inline-block;vertical-align:middle;}
.kit-prod-drop{display:none;position:absolute;top:calc(100% + 3px);left:0;z-index:60;
  min-width:280px;max-width:440px;max-height:240px;overflow:auto;
  background:var(--wrap-bg);border:1px solid var(--line);border-radius:var(--r);
  box-shadow:var(--win-shadow);padding:3px;}
.kit-prod-item{display:flex;align-items:baseline;gap:10px;padding:4px 8px;border-radius:3px;
  cursor:pointer;font-size:12px;line-height:1.35;}
.kit-prod-item:hover{background:var(--row-hover);}
.kit-prod-item.active{background:var(--navy-soft);}
.kit-prod-code{font-weight:600;color:var(--ink);white-space:nowrap;}
.kit-prod-name{color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.kit-prod-empty{padding:6px 8px;color:var(--muted);font-size:12px;}

/* ---------- 树状BOM（对应原 UserForm1 TreeView） ---------- */
.tree-wrap{background:#fff;border:1px solid var(--line);border-radius:var(--r);padding:8px 10px;overflow:auto;max-height:70vh;}
.tree-root,.tree-children{list-style:none;margin:0;padding-left:15px;}
.tree-root{padding-left:0;}
.tree-li{margin:0;}
.tree-label{display:flex;align-items:center;gap:5px;padding:1px 5px;border-radius:3px;cursor:pointer;font-size:11.5px;}
.tree-label:hover{background:var(--navy-soft);}
.tree-label.active{background:#cfe0f7;font-weight:700;color:var(--navy);}
.tree-toggle{width:11px;display:inline-block;text-align:center;color:var(--navy);font-size:9.5px;user-select:none;}
.tree-toggle.leaf{visibility:hidden;}
.tree-text{white-space:nowrap;}
.tree-li.match > .tree-label{box-shadow:inset 3px 0 0 #c99700;background:#fff8e3;}
/* 原窗体选中效果：选中节点＝商务金、父节点＝浅蓝 */
.tree-label.sel{background:rgba(180,155,0,.16);}
.tree-label.par{background:rgba(100,150,200,.20);}

/* ---------- 通用「窗体」弹窗（原表所有 UserForm 都以此形式弹出） ---------- */
/* 窗体弹窗：本身 overflow:hidden（滚动在 .fscroll 里），所以模糊加在它身上是安全的。
   .fscroll 的底色改透明 —— 否则内容区那块实色会把刚做好的模糊整片挡掉。 */
.fmodal{width:1000px;max-width:94vw;height:82vh;max-height:90vh;display:flex;flex-direction:column;overflow:hidden;
  background:var(--modal-bg);
  backdrop-filter:var(--modal-blur);-webkit-backdrop-filter:var(--modal-blur);}
.fhead{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:7px 12px;background:var(--form-head-bg);
  color:var(--form-head-fg);font-size:12.5px;font-weight:700;letter-spacing:.3px;flex:0 0 auto;}
.fhead-title{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.fhead-x{cursor:pointer;opacity:.8;padding:0 4px;font-size:12px;}
.fhead-x:hover{opacity:1;}
.fbar{display:flex;align-items:center;gap:6px;padding:6px 12px;border-bottom:1px solid var(--line);background:var(--foot-bg);flex-wrap:wrap;flex:0 0 auto;}
.fbar:empty{display:none;}
.fscroll{flex:1 1 auto;overflow:auto;padding:9px 12px;background:transparent;}
.ffoot{display:flex;align-items:center;gap:6px;padding:6px 12px;border-top:1px solid var(--line);background:var(--foot-bg);flex:0 0 auto;}
.ffoot-btns{display:flex;gap:6px;}
.ffoot-btns .btn{white-space:nowrap;}
.fstatus{font-size:11px;color:var(--muted);}

/* ---------- 计划表（原表「计划表」的表格形态：信息区 A~T + 每日一列） ---------- */
/* 颜色一律读 --pt-* 变量（定义见 :root），各主题在自己的变量块里给值；
   这里不再出现任何硬编码色 —— 否则换主题就得靠后面几十条 !important 打补丁，漏一条就穿帮。 */
/* contain:layout paint（2026-10-13 性能优化，CDP 实测滚动成本 -24%）：
     layout  → 表格内部的重排不会向上冒泡到整页（换窗增删行是最高频的操作）；
     paint   → 容器外的内容保证不会被容器内绘制影响，浏览器可以放心跳过不可见部分。
   安全性已核对：本软件所有 position:fixed 元素（复制用的 textarea、批注浮层、
   确认框）都挂在 document.body 上，不在表格容器内，不会被 contain 变成相对定位。 */
.plan-scroll{overflow:auto;max-height:74vh;border:1px solid var(--line);border-radius:var(--r);background:var(--pt-scroll-bg);
  contain:layout paint;}
/* 计划表页：表格吃掉整屏剩余高度，表格下方不再留一大片空白 */
.content.plan-page{display:flex;flex-direction:column;overflow:hidden;}
.content.plan-page .plan-scroll{flex:1;min-height:0;max-height:none;}
.content.plan-page .toolbar{flex:none;}

/* ---------- 计划表：列宽拖动手柄（2026-10-13 新增）----------
   计划表的列宽不在 JS 里写死成像素，而是走 <table> 上的 CSS 变量
   --pc-<列key> / --pc-U / --pc-D（见 app.js cwVar），所以这里的重置只要删变量。
   手柄只挂在「有列名」的第 4 行（tr.pt-colname-row）上。
   该行所有 th 都已被 `thead tr:nth-child(4) th{position:sticky}` 定位（冻结列另有内联 sticky），
   sticky 本身就是定位父级，absolute 手柄能直接相对它定位。
   ⚠ 所以**不要**再给这一行写 position:relative —— 那会连 sticky 一起顶掉，
     横向滚动时 6 个冻结列会跟着内容一起跑掉。
   ⚠ 不能复用 table.grid 那条 `.col-resizer` 规则：它没有考虑计划表表头是
     「深底 + 白字 + 竖冻结」，手柄的竖线要跟着表头底色走，否则浅色主题下
     深蓝表头上会出现一条几乎看不见的线。 */
.plan-tbl th .col-resizer{
  position:absolute;top:0;right:0;width:8px;height:100%;z-index:7;
  cursor:col-resize;user-select:none;
}
.plan-tbl th .col-resizer::after{
  content:'';position:absolute;left:3px;top:0;width:1px;height:100%;
  background:var(--pt-hd-line);transition:background .12s,width .12s,left .12s;
}
.plan-tbl th:hover .col-resizer::after{background:var(--pt-hd-fg);opacity:.6;}
.plan-tbl th .col-resizer:hover::after,
.plan-tbl th .col-resizer.active::after{background:#8ec0ff;width:2px;left:3px;opacity:1;}

/* ---------- 各表页：表头冻结，明细在表格内滚动 ----------
   ★ 为什么不能只写 th{position:sticky;top:0}（第 341 行已写）：
     position:sticky 是相对**最近的滚动祖先**定位的。.table-wrap 自己带 overflow:auto，
     它就是 th 的滚动祖先；可它没有高度约束（clientHeight == scrollHeight，永远不滚），
     th 只能贴着这个「不会动的容器」顶端 —— 于是跟着整页一起滚走了（实测 thTop 85 → -415）。
     正确做法是让 .table-wrap **成为真正的滚动容器**：
       ① .content 转 flex 列 + overflow:hidden → 高度由视口决定，不再整页滚；
       ② .table-wrap flex:1 + min-height:0 → 吃掉剩余高度，overflow:auto 开始生效；
          ★ min-height:0 必写：flex 子项默认 min-height:auto，会被内容高度顶开而无法收缩。
     这样 th 的 top:0 参照系就是 .table-wrap，滚动明细时表头原地不动。 */
.content.sheet-page{display:flex;flex-direction:column;overflow:hidden;}
.content.sheet-page .toolbar{flex:none;}
/* 表格上方若有提示行（如余数汇总的说明），一并固定，不参与滚动 */
.content.sheet-page .table-wrap{flex:1;min-height:0;}
.content.sheet-page > .table-wrap{max-height:none;}
.plan-tbl{border-collapse:separate;border-spacing:0;font-size:10.5px;table-layout:fixed;}
.plan-tbl th,.plan-tbl td{border-right:1px solid var(--pt-grid);border-bottom:1px solid var(--pt-grid);
  padding:1px 4px;text-align:center;white-space:nowrap;background:var(--pt-cell-bg);line-height:1.35;
  font-variant-numeric:tabular-nums;}
.plan-tbl tbody td{overflow:hidden;}
/* 冻结列的 left 偏移（2026-10-13 性能改造）：
   原来由 JS 在每次换窗时遍历所有 [data-sci] 格子逐个写 style.left —— 实测单次 16ms
   （30 个订单对时约 600 个格子，30~50ms），而换窗本身就是滚动时每帧都要跑的。
   改成：JS 只在「列宽可能变了」时量一次，把结果写进 <table> 的 --sl-0..--sl-5 变量；
   所有 data-sci 格子（含换窗新挂进来的）直接读变量 → 换窗时零成本，且天然不会漏。 */
.plan-tbl [data-sci="0"]{left:var(--sl-0,0px);}
.plan-tbl [data-sci="1"]{left:var(--sl-1,0px);}
.plan-tbl [data-sci="2"]{left:var(--sl-2,0px);}
.plan-tbl [data-sci="3"]{left:var(--sl-3,0px);}
.plan-tbl [data-sci="4"]{left:var(--sl-4,0px);}
.plan-tbl [data-sci="5"]{left:var(--sl-5,0px);}
.plan-tbl thead th{background:var(--pt-hd-bg);color:var(--pt-hd-fg);font-weight:600;font-size:10.5px;overflow:hidden;
  border-right:1px solid var(--pt-hd-line);letter-spacing:.2px;}
.plan-tbl thead tr:nth-child(1) th,.plan-tbl thead tr:nth-child(2) th,.plan-tbl thead tr:nth-child(3) th{
  background:var(--pt-sub-bg);color:var(--pt-sub-fg);font-weight:500;font-size:9.5px;overflow:visible;height:18px;}
.plan-tbl thead .pt-title{font-size:12px;font-weight:700;letter-spacing:2px;text-align:center;padding:2px 6px;
  background:var(--pt-sub-bg);color:var(--pt-sub-fg);
  white-space:normal;word-break:break-word;overflow-wrap:anywhere;vertical-align:middle;overflow:visible;
  line-height:1.35;}
.plan-tbl thead .pt-val{background:var(--pt-val-bg);color:var(--pt-val-fg);font-weight:700;overflow:visible;}
/* 冻结表头 4 行（原 5 行中第4、5行已合并为列名+空行一行）：纵向滚动时大标题/参数行/日期行都不滚走 */
.plan-tbl thead tr:nth-child(1) th{position:sticky;top:0;z-index:8;}
.plan-tbl thead tr:nth-child(2) th{position:sticky;top:18px;z-index:8;}
.plan-tbl thead tr:nth-child(3) th{position:sticky;top:36px;z-index:8;}
.plan-tbl thead tr:nth-child(4) th{position:sticky;top:54px;z-index:8;height:auto;min-height:40px;}
.plan-tbl thead .pt-day{font-size:9.5px;font-weight:500;}
/* ★ 2026-10-13：列名行（标题行）的列名允许换行——当某列被拖窄到比列名文字更宽时，
   列名自动折行而非被 overflow:hidden 截断（默认列宽足够，仅拖窄触发）。
   覆盖全局 .plan-tbl th 的 white-space:nowrap 与 .plan-tbl thead th 的 overflow:hidden。 */
.plan-tbl thead tr.pt-colname-row th{white-space:normal;word-break:break-word;overflow-wrap:anywhere;
  overflow:visible;line-height:1.25;vertical-align:middle;}
/* ★ 2026-10-13：列名行（标题行）的**列名单元格**整行统一底色 —— 消除「可编辑列名」
   (pt-edit-hd) 造成的色块差异，实现标题行颜色一致。
   日期列(.pt-day) 不在此列：周六/周日/放假/上班日的着色单独保留（见下方 wkend/holiday/workday 规则）。 */
.plan-tbl thead tr.pt-colname-row th:not(.pt-day){
  background:var(--pt-hd-bg) !important;color:var(--pt-hd-fg) !important;}
.plan-tbl thead th.wkend{background:var(--pt-wkend-bg) !important;color:var(--pt-wkend-fg);}   /* 第4行日期：周六周日着色（不再整列着色） */
/* ⚠ 2026-10-13「同一行颜色一致」：这里原来还有一条
   `.plan-tbl tbody tr.pt-actual td{background:#f7f9fc}`（实际行整行一个灰白），
   与组规则（--plan-odd-act 等）**各走各的**，是「一行两种颜色」的来源之一。
   已删除 —— 实际行的底色统一由文末 ⑦ 的 `tr.pt-grp-X.pt-actual td` 给。 */
/* 2026-10-13「同一行颜色一致」：pt-kind 底色已并入行组色（见文末 ⑦），
   这里只保留**文字色**用于区分「计划(蓝) / 实际(绿)」—— 底色统一后靠字色+字重辨认。
   底色一律交给 tbody 组规则，这里再写 background 会把它顶掉。 */
.plan-tbl td.pt-kind{color:var(--pt-kind-fg);font-weight:600;}
.plan-tbl td.pt-kind.actual{color:var(--pt-kind-act-fg);font-weight:600;}
.plan-tbl td.pt-num{text-align:right;color:#ff0000;font-weight:600;}    /* 计划数字：红字（与原表一致） */
.plan-tbl td.pt-num.actual{color:#000000;font-weight:400;}               /* 实际数字：黑字（与原表一致） */
/* 计划行排程数值单元格标色（原表规则，2026-10-13 落实）：
   取计划行「最晚排产日期」(有值的最后一天) 与 N 列订单交期(r.order_date) 比较：
     > 交期 → 超期：黄底红字加粗；= 交期 → 按期：蓝底白字加粗；< 交期 → 提前：绿底黑字。
   固定 RGB，与主题无关；仅「有值单元格」上色（pt-val 才带状态类）。
   特异性需压过「同组行背景」与基础 pt-val 黄底，故带 tbody tr.pt-plan 前缀。 */
.plan-tbl tbody tr.pt-plan td.pt-num.pt-val.pt-over{background:#ffff00 !important;color:#ff0000 !important;font-weight:700 !important;}
.plan-tbl tbody tr.pt-plan td.pt-num.pt-val.pt-ontime{background:#2b6bc0 !important;color:#ffffff !important;font-weight:700 !important;}
.plan-tbl tbody tr.pt-plan td.pt-num.pt-val.pt-ahead{background:#3ddc97 !important;color:#000000 !important;font-weight:400 !important;}
/* 默认兜底：无交期或无法比较时，计划有值单元格保持黄底红字（原表超期态）。 */
.plan-tbl td.pt-num.pt-val{background:#ffff00 !important;}
.plan-tbl td.pt-num.actual.pt-gray{background:#d9d9d9 !important;}
.plan-tbl td.pt-calc{color:var(--pt-calc-fg);}
.plan-tbl td.late{color:var(--pt-late-fg);font-weight:700;}
/* 窗口化渲染的「撑高行」：只负责把总高度撑对，让滚动条长度/滚动位置照旧。
   必须完全不可见（无边框、无背景、无内容），否则窗口边界会露出一条假横线。 */
.plan-tbl tbody tr.pt-spacer td{
  padding:0;border:0 !important;background:transparent !important;
  font-size:0;line-height:0;
}
/* 订单组的分隔线（原表口径：每个订单的 rowspan 合并格下画一道粗线）。
   ⚠ 这道线在浅色主题下是浅灰（--pt-group-line）、合理；
   但深色主题下它在近黑底上是一条刺眼的白线，各主题必须给「比行底更深」的暗色，
   否则比隔行本身还抢眼 —— 所以值的来源统一收进 --pt-group-line，不再按主题打补丁。 */
.plan-tbl tbody tr.pt-plan td[rowspan]{border-bottom:2px solid var(--pt-group-line);}
/* 2026-10-13 优化：原来组间粗线只画在左侧 A~T 的 rowspan 合并格上，右侧排产区
   仍是 1px 细线 —— 横着扫过去时「一个订单」这条分界在右边是断的，容易把上下两单看成一单。
   这里让整行（含右侧每日产量格）都收到 2px 组界线，「2 行 = 1 单」的结构才处处一致。 */
.plan-tbl tbody tr.pt-plan .pt-num,
.plan-tbl tbody tr.pt-plan .pt-kind{border-bottom-width:2px;border-bottom-style:solid;
  border-bottom-color:var(--pt-group-line);}
.plan-tbl tbody tr.pt-plan td[rowspan]{border-bottom-color:var(--pt-group-line);}

/* —— 计划表：可编辑单元格（表头第2/3行 + 行内 G/H/I·J·M·O·R + 实际行）—— */
.plan-tbl thead .pt-param{background:var(--pt-param-bg);color:var(--pt-param-fg);font-weight:600;font-size:10px;}
.plan-tbl th.pt-edit,.plan-tbl td.pt-edit{cursor:pointer;}
.plan-tbl thead th.pt-edit{background:var(--pt-edit-bg);color:var(--pt-edit-fg);font-weight:700;}
.plan-tbl thead th.pt-edit:hover{background:var(--pt-edit-hi-bg);box-shadow:inset 0 0 0 2px var(--pt-edit-hi-ring);}
.plan-tbl thead th.pt-edit-hd{background:var(--pt-edit-hd-bg);color:var(--pt-edit-hd-fg);}
/* ⚠ 2026-10-13「同一行颜色一致」：pt-edit 的底色已全部交给文末 ⑦ 的组规则
   （`tr.pt-grp-X.pt-plan/actual td.pt-edit{background:var(--plan-*)}`）。
   原来这里的 866/868 两条硬编码（#f4f8ff / #fbfcfe）以及 glass 主题里那条
   `tr.pt-actual td.pt-edit{background:rgba(255,255,255,.18)!important}`
   会与组规则打架 —— 后者带 !important，实测让实际行 143 格全被刷成 .18，
   与同行的 .21 组色对不上。已删除。
   「可编辑」的表达靠：cursor:pointer（第 845 行）+ hover 高亮。 */
.plan-tbl tbody td.pt-edit:hover,
.plan-tbl tbody tr.pt-actual td.pt-edit:hover{background:var(--pt-edit-hi-bg);box-shadow:inset 0 0 0 2px var(--pt-edit-hi-ring);}
/* 已手工改过：左侧橙色标记条 */
.plan-tbl th.pt-dirty,.plan-tbl td.pt-dirty{box-shadow:inset 3px 0 0 0 var(--pt-dirty);}
.plan-tbl th.pt-dirty:hover,.plan-tbl td.pt-dirty:hover{box-shadow:inset 3px 0 0 0 var(--pt-dirty),inset 0 0 0 2px var(--pt-edit-hi-ring);}
/* 实际行灰底＝上方计划行当天有量（原表 MarkGrayBelow 镜像灰底）
   ⚠ 2026-10-13「同一行着色颜色一致」改造后，**pt-gray 不再自带底色**。
   原来这里是 #e8ebf0 硬编码（玻璃主题另有一套 rgba(255,255,255,.14)），
   与所在行组色毫无关系 —— 是「一行四色」的一个来源。
   现在底色交给文末 ⑦ 的 tbody 组规则（那里已按组 + !important 覆盖本选择器），
   镜像灰的语义改由「文字为空」+ 相邻的「实际」字样承载，不再靠底色区分。
   ⚠ 不要在这里用 color-mix() 派生「轻微差异」：本机 WebView2 运行时可能偏旧，
     color-mix 不被支持时会整条失效退回透明，比原来的硬编码更糟。 */
.plan-tbl td.pt-num.actual.pt-dirty{color:var(--pt-dirty-fg);font-weight:600;}
/* 上班/放假日期维护小表 */
.calendar-panel{margin:8px 0 10px 0;padding:8px 10px;border:1px solid var(--line);border-radius:var(--r);background:var(--panel);display:inline-block;box-shadow:0 4px 12px rgba(0,0,0,.08);}
.calendar-row{display:flex;align-items:center;gap:4px;margin:2px 0;}
.calendar-label{width:64px;font-size:10.5px;font-weight:600;color:var(--pt-cal-label-fg);text-align:right;padding-right:4px;}
.calendar-cell{width:52px;height:20px;line-height:20px;border:1px solid var(--pt-cal-cell-line);border-radius:3px;text-align:center;font-size:10px;cursor:pointer;background:var(--pt-cal-cell-bg);color:var(--pt-cal-cell-fg);}
.calendar-cell:hover{background:var(--pt-cal-hi-bg);border-color:var(--pt-cal-hi-line);}
.calendar-tip{font-size:9.5px;color:var(--muted);margin-top:6px;max-width:620px;}
/* 上班/放假日期小表：嵌入计划表表头第 2/3 行（中间 12 列）时的紧凑样式 */
.plan-tbl thead th.pt-cal-cell{padding:1px 3px;vertical-align:middle;overflow:visible;}
.plan-tbl thead tr:nth-child(2) th.pt-cal-cell{height:auto;line-height:normal;}
.calendar-inline{margin:0;padding:0;border:none;background:transparent;box-shadow:none;display:block;}
.calendar-inline .calendar-row{margin:0;gap:2px;}
.calendar-inline .calendar-label{width:50px;font-size:9.5px;padding-right:2px;flex:none;}
.calendar-inline .calendar-cell{width:42px;height:14px;line-height:14px;font-size:9px;border-radius:2px;flex:none;}
/* 计划表参数行（生产人员/工作时间/开始日期）：与下方「上班/放假日期」小表同宽对齐。
   参数整体占第 7~18 列（与 .pt-cal-cell 的 colspan 12 一致），三组左右均分铺满，
   左右两条边与小表对齐。样式取「label 芯片 + value 小框」与小表同族，整块才协调。 */
.plan-tbl thead th.pt-param-inline{padding:0 3px;vertical-align:middle;overflow:visible;}
.plan-tbl thead .params-inline{display:flex;align-items:center;justify-content:space-between;gap:8px;height:18px;}
.params-inline .param-item{display:inline-flex;align-items:center;gap:5px;}
.params-inline .param-label{font-size:10px;font-weight:600;color:var(--pt-param-fg);background:var(--pt-param-bg);
  padding:1px 6px;border-radius:3px;white-space:nowrap;}
.params-inline .param-label.pt-dirty{box-shadow:inset 3px 0 0 0 var(--pt-dirty);}
.params-inline .param-box{font-size:10px;font-weight:700;color:var(--pt-val-fg);background:var(--pt-val-bg);
  border:1px solid var(--pt-cal-cell-line);border-radius:3px;padding:1px 8px;min-width:34px;
  line-height:13px;text-align:center;cursor:pointer;}
.params-inline .param-box:hover{background:var(--pt-edit-hi-bg);border-color:var(--pt-edit-hi-ring);}
/* 内联参数框里的就地编辑输入框：收窄以适配小框（默认 .pt-inline 是 width:100%） */
.params-inline .param-box input.pt-inline{width:64px;min-width:44px;}
.plan-tbl thead th.pt-holiday{background:var(--pt-holiday-bg) !important;color:var(--pt-holiday-fg);}
.plan-tbl thead th.pt-workday{background:var(--pt-workday-bg) !important;color:var(--pt-workday-fg);}
.plan-tbl input.pt-inline{width:100%;box-sizing:border-box;border:1px solid var(--pt-inline-line);border-radius:2px;
  background:var(--pt-inline-bg);color:var(--pt-inline-fg);font:inherit;font-size:10.5px;padding:0 3px;height:19px;outline:none;text-align:right;}
.plan-tbl input.pt-inline[type=text]{text-align:left;}
/* 就地编辑框不要数值输入框的上下微调箭头（实际行/表头填数时更干净） */
.plan-tbl input.pt-inline::-webkit-outer-spin-button,
.plan-tbl input.pt-inline::-webkit-inner-spin-button{-webkit-appearance:none;appearance:none;margin:0;height:auto;}
.plan-tbl input.pt-inline[type=number]{-moz-appearance:textfield;appearance:textfield;}

/* ---- 工作流小窗（操作面板点控制键后弹出：导入 / 运算 / 表格预览） ---- */
.wf-body{padding:2px 0 6px;}
.wf-row-flex{display:flex;align-items:center;gap:8px;margin:8px 0;flex-wrap:wrap;}
.wf-row-flex .spacer{flex:1;}   /* 把右侧动作按钮推到行尾（原 .spacer 只在 .toolbar 内生效）*/
.wf-lbl{font-size:12px;color:#1f3864;font-weight:600;flex:none;}
/* 玻璃主题下这行标签原本是写死的深蓝，在深底上几乎看不见（2026-10-13 截图发现）。
   注意 space / win7 虽然名字听着像深色，实际 --panel 是 #ffffff，仍属浅色主题，别加进来。 */
/* 缺件明细窗底部的灰色小提示（取代原先一排一键复制键） */
.wf-tip{font-size:11.5px;color:var(--muted);flex:none;line-height:1.5;}
.wf-result{margin-top:10px;}
.btn.wf-mini{padding:2px 7px;font-size:11px;line-height:1.35;}
.wf-dir{margin:6px 0 10px;border:1px solid #c9d6ea;border-radius:3px;background:#f7fafd;}
.wf-quick{display:flex;align-items:center;gap:6px;flex-wrap:wrap;padding:5px 7px;
  border-bottom:1px solid #dde6f2;background:#f2f7fd;}
.wf-crumb{display:flex;align-items:center;gap:6px;flex-wrap:wrap;padding:5px 7px;border-bottom:1px solid #dde6f2;background:#eef4fb;}
.wf-path{font-size:11px;color:#1f3864;font-family:Consolas,Menlo,monospace;word-break:break-all;}
.wf-list{max-height:220px;overflow:auto;padding:3px 0;}
.wf-row{display:flex;align-items:center;justify-content:space-between;gap:10px;
  padding:3px 9px;font-size:12px;cursor:pointer;white-space:nowrap;}
.wf-row:hover{background:#dbe7fa;}
.wf-folder{color:#1f3864;font-weight:600;}
.wf-file{color:#333;}
.wf-name{overflow:hidden;text-overflow:ellipsis;}
.wf-meta{font-size:11px;color:#8a94a6;flex:none;}

/* ===================================================================
   主题（整表换肤）+ 弹窗透明度
   切主题：顶栏「主题」下拉（html[data-theme]）；背景图：顶栏「背景图」按钮（所有主题可用）；
   背景模糊：顶栏「高斯模糊」滑杆（--bg-blur）
   =================================================================== */
/* ---- ① Windows 7（Aero 玻璃 · 经典蓝）---- */
html[data-theme="win7"]{
  --font:"Segoe UI","Microsoft YaHei",Tahoma,sans-serif;
  --navy:#1b4f91; --navy-2:#2b6bc0; --navy-soft:#dbe8f7;
  --ink:#1a2b3f; --muted:#5c6b7d;
  --line:#9db8d6; --line-2:#c9dcee;
  --bg:#dce8f4;                                  /* Win7 桌面蓝 */
  --panel:#ffffff; --wrap-bg:#ffffff;
  --row-alt:#dfeaf9; --row-hover:#c9ddf5; --cell-hover:#bfd7f2;
  --plan-odd:#ffffff;  --plan-odd-act:#eef4f0;
  --plan-even:#e3edfa; --plan-even-act:#dde9e1;
  --plan-odd-op:#ffffff;  --plan-odd-act-op:#eef4f0;
  --plan-even-op:#e3edfa; --plan-even-act-op:#dde9e1;
  --plan-sci-under:#ffffff;
  /* 产能表分隔列（2026-10-13 新增）：跟随本主题的隔行色系，避免硬编码浅色在深色主题下成白条 */
  --cap-sep-line:#c6d3e6;
  --sidebar-bg:linear-gradient(180deg,#f0f8ff 0%,#d3e6f8 46%,#bfd9f2 54%,#e2effb 100%);
  --sidebar-fg:#123c68; --sidebar-fg-dim:#2f5f92; --sidebar-line:#a9c6e2;
  --nav-hover:linear-gradient(180deg,#fdfdfe,#e6f1fc);
  --nav-active:linear-gradient(180deg,#e9f3fd,#c6dcf3);
  --nav-line:#a9c6e2; --nav-line-hi:#6f9bcb; --nav-bg:rgba(255,255,255,.55);
  --c1:#2b6bc0; --c2:#2e8b57; --c3:#c07d12; --c4:#6b4fa0; --c5:#2b8ca8; --c6:#c0392b;
  --chart-track:#d8e7f7;
  --chart-sel-bg:rgba(42,111,181,.13); --chart-hit-bg:rgba(42,111,181,.07);
  --thead-bg:linear-gradient(180deg,#f4fafe 0%,#ddeaf8 48%,#cfe0f3 52%,#e6f0fb 100%);
  --thead-fg:#123c68; --thead-line:#9db8d6;
  --btn-bg:linear-gradient(180deg,#fcfdfe 0%,#eaf2fb 49%,#dce8f5 51%,#f2f7fd 100%);
  --btn-fg:#1a2b3f; --btn-line:#8fb0d4; --btn-hover-bg:linear-gradient(180deg,#fdfdff,#dbeaf9);
  --foot-bg:linear-gradient(180deg,#f5fafe,#e3edf9);
  --form-head-bg:linear-gradient(180deg,#eaf4fd 0%,#c4dcf4 48%,#aeccec 52%,#d8e8f8 100%);
  --form-head-fg:#123c68;
  --win-border:#6f9bcb;
  --win-shadow:0 0 0 1px #6f9bcb,0 12px 34px rgba(16,44,76,.34),inset 0 1px 0 rgba(255,255,255,.7);
  --r:3px;

  /* 计划表 / 日历小表（--pt-*）：Win7 Aero 的特征是「亮蓝表头 + 玻璃蓝网格」，
     表头用 --thead-bg 那道四段渐变（顶部亮、腰部暗），比纯色更有 Win7 的立体感。 */
  --pt-scroll-bg:#ffffff;
  --pt-cell-bg:#ffffff;
  --pt-grid:#c9dcee;
  --pt-hd-bg:var(--thead-bg);--pt-hd-fg:#123c68;--pt-hd-line:#9db8d6;
  --pt-sub-bg:#e6f0fb;--pt-sub-fg:#123c68;
  --pt-val-bg:#ffffff;--pt-val-fg:#123c68;
  --pt-param-bg:#c3d9ef;--pt-param-fg:#123c68;
  --pt-edit-hd-bg:#2b6bc0;--pt-edit-hd-fg:#ffffff;   /* 实测：#4a8ad4 配白字只有 3.57:1，压深到 Aero 蓝才够 */
  --pt-edit-bg:#eaf3fd;--pt-edit-fg:#123c68;
  --pt-edit-hi-bg:#cfe3f8;--pt-edit-hi-ring:#2b6bc0;
  --pt-wkend-bg:#6a4f7d;--pt-wkend-fg:#f6eeff;      /* 实测：#7f6a8f 配浅紫只有 4.10:1 */
  --pt-workday-bg:#ddf0e2;--pt-workday-fg:#1f6b30;
  --pt-holiday-bg:#dfe6ee;--pt-holiday-fg:#4a5a6e;
  --pt-num-fg:#123c68;--pt-num-act-fg:#1f6b30;
  --pt-kind-fg:#123c68;--pt-kind-act-fg:#1f6b30;
  --pt-calc-fg:#1b4f91;
  --pt-late-fg:#a5271a;
  --pt-dirty:#c07d12;--pt-dirty-fg:#8a5a00;
  --pt-group-line:#9db8d6;
  --pt-inline-bg:#ffffff;--pt-inline-fg:#123c68;--pt-inline-line:#6f9bcb;
  --pt-cal-cell-bg:#ffffff;--pt-cal-cell-fg:#1a2b3f;--pt-cal-cell-line:#9db8d6;
  --pt-cal-label-fg:#123c68;
  --pt-cal-hi-bg:#dcebfa;--pt-cal-hi-line:#2b6bc0;
}
html[data-theme="win7"] .brand{border-bottom:1px solid #a9c6e2;}
/* 浅色主题（win7/blue/classic）：侧栏本身是浅蓝/浅灰，字标深蓝+亮绿直接可读，
   只需去掉旧的白底板（logo 现在透明，规则留空即可）。 */
html[data-theme="win7"] .logo{background:none;box-shadow:none;}
html[data-theme="win7"] #nav a.active{border-color:#2b6bc0;font-weight:700;}
html[data-theme="win7"] .topbar{background:linear-gradient(180deg,#f7fbff,#dfeaf8);border-bottom:1px solid #9db8d6;}
html[data-theme="win7"] .page-title{color:#123c68;text-shadow:0 1px 0 rgba(255,255,255,.7);}
html[data-theme="win7"] .btn{box-shadow:inset 0 1px 0 rgba(255,255,255,.85);}
html[data-theme="win7"] .btn-primary{
  background:linear-gradient(180deg,#8fc0f5 0%,#4d95df 48%,#3a84d0 52%,#6aa8e8 100%);
  border-color:#2b6bc0;color:#fff;text-shadow:0 1px 1px rgba(0,30,70,.35);}
html[data-theme="win7"] .btn-primary:hover{background:linear-gradient(180deg,#a3ccf8,#4f9ae6);color:#fff;}
html[data-theme="win7"] .btn:hover{border-color:#2b6bc0;color:#123c68;}
html[data-theme="win7"] .panel,
html[data-theme="win7"] .table-wrap{box-shadow:0 0 0 1px #9db8d6;}
html[data-theme="win7"] .stat{border-left-color:#2b6bc0;
  background:linear-gradient(180deg,#ffffff,#f2f7fd);box-shadow:0 0 0 1px #b6cee6;}
html[data-theme="win7"] .stat .num{color:#123c68;}
/* Aero 窗体：蓝边 + 顶部高光 */
html[data-theme="win7"] .fmodal{border:1px solid var(--win-border);border-radius:6px 6px 3px 3px;
  box-shadow:var(--win-shadow);}
html[data-theme="win7"] .fhead{border-bottom:1px solid #8fb0d4;box-shadow:inset 0 1px 0 rgba(255,255,255,.8);}
html[data-theme="win7"] .fhead-x{color:#123c68;}
html[data-theme="win7"] .modal-mask{background:rgba(16,44,76,.28);}
html[data-theme="win7"] .search-input,html[data-theme="win7"] .inp{
  border-color:#8fb0d4;background:linear-gradient(180deg,#fbfdff,#ffffff);}
/* Win7 经典滚动条 */
html[data-theme="win7"] ::-webkit-scrollbar{width:13px;height:13px;}
html[data-theme="win7"] ::-webkit-scrollbar-track{background:#f2f6fb;border-left:1px solid #dbe6f2;}
html[data-theme="win7"] ::-webkit-scrollbar-thumb{
  background:linear-gradient(180deg,#fbfdfe,#d8e6f4);border:1px solid #a9c6e2;border-radius:2px;}
html[data-theme="win7"] ::-webkit-scrollbar-thumb:hover{background:linear-gradient(180deg,#ffffff,#c9ddf3);}

/* ---- ③ 经典灰（Office 2003 风格）---- */
html[data-theme="classic"]{
  --font:Tahoma,"Microsoft YaHei","SimSun",sans-serif;
  --navy:#0a3d7a; --navy-2:#14539b; --navy-soft:#dfe6ee;
  --ink:#000000; --muted:#5a5a5a;
  --line:#9aa5b1; --line-2:#c6ccd4;
  --bg:#d4d0c8; --panel:#ffffff; --wrap-bg:#ffffff;
  --row-alt:#e6e6e0; --row-hover:#d5dfee; --cell-hover:#c8d8ec;
  --plan-odd:#ffffff;  --plan-odd-act:#f2f2ef;
  --plan-even:#eeeeea; --plan-even-act:#e4e4e0;
  --plan-odd-op:#ffffff;  --plan-odd-act-op:#f2f2ef;
  --plan-even-op:#eeeeea; --plan-even-act-op:#e4e4e0;
  --plan-sci-under:#ffffff;
  --cap-sep-line:#c9c9c1;
  --sidebar-bg:linear-gradient(180deg,#eef2f7 0%,#d4d0c8 100%);
  --sidebar-fg:#000000; --sidebar-fg-dim:#26333f; --sidebar-line:#9aa5b1;
  --nav-hover:#e6ecf5; --nav-active:#cfdcec;
  --nav-line:#9aa5b1; --nav-line-hi:#0a3d7a; --nav-bg:rgba(255,255,255,.55);
  --c1:#0a3d7a; --c2:#2e7d4f; --c3:#a06a0c; --c4:#5b4a8a; --c5:#0f6f80; --c6:#a5271a;
  --chart-track:#d8d8d4;
  --chart-sel-bg:rgba(42,111,181,.13); --chart-hit-bg:rgba(42,111,181,.07);
  --thead-bg:linear-gradient(180deg,#f4f6f8,#dfe4ea);
  --thead-fg:#000000; --thead-line:#9aa5b1;
  --btn-bg:linear-gradient(180deg,#fbfbfb,#e6e6e2); --btn-fg:#000; --btn-line:#9aa5b1;
  --btn-hover-bg:linear-gradient(180deg,#ffffff,#eef2f7);
  --foot-bg:#eceadf;
  --form-head-bg:linear-gradient(180deg,#3a7fd5 0%,#1f5aa8 100%);
  --form-head-fg:#ffffff;
  --r:2px;

  /* 计划表 / 日历小表（--pt-*）：经典灰是 Office 2003 的方正观感 ——
     网格线更实、表头用饱和度高的纯色而不是藏青渐变、圆角一律 2px。 */
  --pt-scroll-bg:#ffffff;
  --pt-cell-bg:#ffffff;
  --pt-grid:#c6ccd4;
  --pt-hd-bg:#0a3d7a;--pt-hd-fg:#ffffff;--pt-hd-line:#ffffff;
  --pt-sub-bg:#dfe6ee;--pt-sub-fg:#0a3d7a;
  --pt-val-bg:#ffffff;--pt-val-fg:#0a3d7a;
  --pt-param-bg:#b8cde3;--pt-param-fg:#0a3d7a;
  --pt-edit-hd-bg:#14539b;--pt-edit-hd-fg:#ffffff;
  --pt-edit-bg:#e8f0f9;--pt-edit-fg:#0a3d7a;
  --pt-edit-hi-bg:#cfe0f3;--pt-edit-hi-ring:#0a3d7a;
  --pt-wkend-bg:#8a5a5a;--pt-wkend-fg:#ffe9e9;
  --pt-workday-bg:#dff0e2;--pt-workday-fg:#1f5c28;
  --pt-holiday-bg:#d9d9d2;--pt-holiday-fg:#4a4a4a;
  --pt-num-fg:#0a3d7a;--pt-num-act-fg:#256b45;   /* 实际行绿字：#2e7d4f 实测只有 4.50:1，压深一档 */
  --pt-kind-fg:#0a3d7a;--pt-kind-act-fg:#2e7d4f;
  --pt-calc-fg:#14539b;
  --pt-late-fg:#a5271a;
  --pt-dirty:#c07d12;--pt-dirty-fg:#8a5a00;
  --pt-group-line:#9aa5b1;
  --pt-inline-bg:#ffffff;--pt-inline-fg:#000000;--pt-inline-line:#0a3d7a;
  --pt-cal-cell-bg:#ffffff;--pt-cal-cell-fg:#000000;--pt-cal-cell-line:#9aa5b1;
  --pt-cal-label-fg:#0a3d7a;
  --pt-cal-hi-bg:#d5dfee;--pt-cal-hi-line:#0a3d7a;
}
html[data-theme="classic"] .logo{border-radius:2px;}
html[data-theme="classic"] .topbar{background:linear-gradient(180deg,#f6f7f8,#e2e2dd);}
html[data-theme="classic"] #nav a.active{border-color:#0a3d7a;}
html[data-theme="classic"] .btn{border-radius:2px;}
html[data-theme="classic"] table.grid th{font-weight:700;}

/* ---- ⑤ 毛玻璃（Glassmorphism · 深色高级玻璃）---- */
html[data-theme="glass"]{
  --font:"Microsoft YaHei","PingFang SC","Segoe UI",sans-serif;
  --navy:#4a7fc8; --navy-2:#6a9fe0; --navy-soft:rgba(255,255,255,.55);
  --ink:#e8edf5; --muted:rgba(255,255,255,.6);
  --line:rgba(255,255,255,.16); --line-2:rgba(255,255,255,.11);
  /* 深色基底 + 多色光晕：玻璃模糊后透出柔和彩光，产生通透感 */
  --bg:
    radial-gradient(circle at 14% 18%,rgba(88,128,210,.40),transparent 42%),
    radial-gradient(circle at 86% 12%,rgba(168,94,222,.32),transparent 40%),
    radial-gradient(circle at 78% 86%,rgba(40,186,176,.30),transparent 44%),
    radial-gradient(circle at 22% 82%,rgba(228,124,92,.24),transparent 46%),
    #090d15;
  --panel:rgba(22,28,40,.42);
  --wrap-bg:rgba(255,255,255,.09);
  --modal-bg:rgba(16,22,34,.62);
  --row-alt:rgba(255,255,255,.028);
  --row-hover:rgba(255,255,255,.17);
  --cell-hover:rgba(255,255,255,.22);
  --plan-odd:rgba(255,255,255,.155);  --plan-odd-act:rgba(255,255,255,.21);
  --plan-even:rgba(255,255,255,.075); --plan-even-act:rgba(255,255,255,.125);
  /* 冻结列的**不透明版**组色（2026-10-13 新增）。
     为什么需要：玻璃/深空主题的组色是半透明白（叠在页面底色上才显色），
     而冻结列是 position:sticky，必须自己带一个不透明底，否则横向滚动时
     右侧日产量会从底下透出来。直接把半透明色当 background 用，两种做法结果不同：
       · 半透明 + 不透明垫底 → 底色是「垫底色」，与旁边格子透出页面底色的效果对不上
       · 预先压成不透明     → 与旁边格子视觉完全一致，且天然不透底
     下面的值 = 半透明组色叠在**表格区实际底色**上的结果色。
     ⚠ 那个底色不是页面 --bg，而是「页面 --bg + --wrap-bg」叠完之后的颜色
     （玻璃 #090d15 + rgba(255,255,255,.09) = #1f232a），算错会让冻结列与同行差十几级灰。
     公式：over + (255-over)*alpha。深空主题同理（见其变量块）。 */
  --plan-odd-op:#42454b;  --plan-odd-act-op:#4e5157;
  --plan-even-op:#30343a; --plan-even-act-op:#3b3e45;
  /* 冻结列要「实底」才挡得住横向滚动时右侧数字，但用接近全不透明的深色，
   .96 以上确保完全不透。 */
  --plan-sci-under:#0f1522;
  --cap-sep-line:rgba(255,255,255,.22);
  --sidebar-bg:rgba(12,16,26,.38);
  --sidebar-fg:#e8edf5; --sidebar-fg-dim:rgba(255,255,255,.70); --sidebar-line:rgba(255,255,255,.14);
  --nav-hover:rgba(255,255,255,.13); --nav-active:rgba(255,255,255,.22);
  --nav-line:rgba(255,255,255,.22); --nav-line-hi:rgba(255,255,255,.48); --nav-bg:rgba(255,255,255,.06);
  --c1:#5fa8e8; --c2:#4fc79a; --c3:#f0b95c; --c4:#a98ae0; --c5:#4fc4dd; --c6:#ff7a68;
  --chart-track:rgba(255,255,255,.16);
  --chart-sel-bg:rgba(120,175,245,.20); --chart-hit-bg:rgba(120,175,245,.10);
  --thead-bg:rgba(8,12,22,.84); --thead-fg:#e8edf5; --thead-line:rgba(255,255,255,.18);
  --btn-bg:rgba(255,255,255,.10); --btn-fg:#e8edf5;
  --btn-line:rgba(255,255,255,.26); --btn-hover-bg:rgba(255,255,255,.22);
  --foot-bg:rgba(255,255,255,.06);
  --form-head-bg:rgba(0,0,0,.45); --form-head-fg:#e8edf5;
  --red:#ff6b5b; --green:#5ecf8e; --amber:#f0b84a;
  --win-shadow:0 22px 64px rgba(0,0,0,.55);
  --win-border:rgba(255,255,255,.22);
  --r:10px;

  /* 计划表 / 日历小表（--pt-*）：玻璃的底是半透明的，但**表头必须实底**——
     半透明表头叠上表格网格线之后文字会糊在网格上。表头给近黑实底 + 亮字，
     明细区的底色仍交给 --plan-* 组色，--pt-cell-bg 只做兜底。 */
  --pt-scroll-bg:rgba(14,21,35,.34);
  --pt-cell-bg:rgba(255,255,255,.09);
  --pt-grid:rgba(255,255,255,.12);
  --pt-hd-bg:rgba(8,12,22,.88);--pt-hd-fg:#e8edf5;--pt-hd-line:rgba(255,255,255,.14);
  --pt-sub-bg:rgba(20,28,44,.86);--pt-sub-fg:#e8edf5;
  --pt-val-bg:rgba(255,255,255,.10);--pt-val-fg:#e8edf5;
  --pt-param-bg:rgba(0,0,0,.5);--pt-param-fg:#dbe4f2;
  --pt-edit-hd-bg:rgba(0,0,0,.5);--pt-edit-hd-fg:#e8edf5;
  --pt-edit-bg:rgba(255,255,255,.16);--pt-edit-fg:#e8edf5;
  --pt-edit-hi-bg:rgba(255,255,255,.22);--pt-edit-hi-ring:#8fb4e8;
  --pt-wkend-bg:rgba(120,55,55,.7);--pt-wkend-fg:#ffd9d2;
  --pt-workday-bg:rgba(120,200,120,.22);--pt-workday-fg:#d6f5d6;
  --pt-holiday-bg:rgba(255,255,255,.06);--pt-holiday-fg:rgba(255,255,255,.62);
  --pt-num-fg:#cfe0f7;--pt-num-act-fg:#a8e0bd;
  --pt-kind-fg:#cfe1fb;--pt-kind-act-fg:#b6e6c6;
  --pt-calc-fg:#9fb6d8;
  --pt-late-fg:#ff8a7a;
  --pt-dirty:#e8a44f;--pt-dirty-fg:#f0b96a;
  --pt-group-line:rgba(0,0,0,.42);
  --pt-inline-bg:rgba(255,255,255,.14);--pt-inline-fg:#e8edf5;--pt-inline-line:rgba(255,255,255,.3);
  --pt-cal-cell-bg:rgba(255,255,255,.08);--pt-cal-cell-fg:#e8edf5;--pt-cal-cell-line:rgba(255,255,255,.22);
  --pt-cal-label-fg:#e8edf5;
  --pt-cal-hi-bg:rgba(255,255,255,.18);--pt-cal-hi-line:rgba(255,255,255,.5);

  /* ---------- 玻璃棱边（统一配方，见下方「玻璃表面」注释） ----------
     真实玻璃切边不是一条均匀白线，而是五层光学效果叠加出来的，缺一层就「塑料感」：
     ① 切边暗环：全内反射把光留在玻璃内部，边缘比内部更暗 —— 这是「有厚度」最关键的一层
     ② 上沿迎光：一道 1px 锐利亮线 + 向内快速衰减的柔光（第二层斜面）
     ③ 下沿背光：细暗线；左右介于迎光/背光之间
     ④ 色散彩边：顶沿掺极淡的青蓝（真实玻璃边缘那一丝彩）
     ⑤ 内侧柔和凹陷：让视线觉得边缘「陷进去」而不是平贴上去          */
  --g-cut:rgba(0,0,0,.34);              /* ① 切边暗环（即边框本身） */
  --g-cut-hi:rgba(0,0,0,.20);           /* 小件的切边暗环 */
  --g-lit:rgba(255,255,255,.62);        /* ② 上沿迎光亮线 */
  --g-lit-soft:rgba(255,255,255,.22);   /* ② 上沿斜面柔光 */
  --g-shade:rgba(0,0,0,.42);            /* ③ 下沿背光 */
  --g-bleed:rgba(120,190,255,.16);      /* ④ 色散彩边 */
  --g-inner:rgba(0,0,0,.13);            /* ⑤ 内侧凹陷 */

  /* ---------- 渐变描边（--g-edge*）：由伪元素 + mask 绘制，四角跟随 border-radius ---------- */
  --g-edge:linear-gradient(150deg,      /* 大面板：默认 */
    rgba(255,255,255,.78) 0%,rgba(255,255,255,.34) 18%,
    rgba(190,225,255,.16) 42%,rgba(0,0,0,.26) 74%,rgba(0,0,0,.48) 100%);
  --g-edge-hi:linear-gradient(150deg,    /* 大面板 hover：被照亮 */
    rgba(255,255,255,.95) 0%,rgba(255,255,255,.52) 18%,
    rgba(190,225,255,.28) 42%,rgba(0,0,0,.24) 74%,rgba(0,0,0,.46) 100%);
  --g-edge-sm:linear-gradient(150deg,    /* 小件（按钮/菜单/胶囊）：亮线更细、暗侧更浅，否则整屏「毛」成噪点 */
    rgba(255,255,255,.70) 0%,rgba(255,255,255,.28) 24%,
    rgba(190,225,255,.12) 48%,rgba(0,0,0,.22) 78%,rgba(0,0,0,.38) 100%);
  --g-edge-sm-hi:linear-gradient(150deg,
    rgba(255,255,255,.95) 0%,rgba(255,255,255,.46) 24%,
    rgba(190,225,255,.24) 48%,rgba(0,0,0,.20) 78%,rgba(0,0,0,.36) 100%);
  --g-edge-on:linear-gradient(150deg,     /* 选中态：整圈发亮 */
    rgba(255,255,255,1) 0%,rgba(255,255,255,.55) 24%,
    rgba(200,230,255,.32) 48%,rgba(255,255,255,.30) 76%,rgba(255,255,255,.46) 100%);
  --g-edge-pri:linear-gradient(150deg,
    rgba(255,255,255,.82) 0%,rgba(255,255,255,.34) 26%,
    rgba(190,225,255,.18) 50%,rgba(0,0,0,.24) 80%,rgba(0,0,0,.42) 100%);
  --g-edge-dng:linear-gradient(150deg,
    rgba(255,190,180,.72) 0%,rgba(255,150,140,.34) 26%,
    rgba(255,120,110,.16) 50%,rgba(0,0,0,.24) 80%,rgba(0,0,0,.42) 100%);
  --g-edge-kpi:linear-gradient(150deg,
    rgba(255,255,255,.62) 0%,rgba(255,255,255,.26) 22%,
    rgba(190,225,255,.13) 44%,rgba(0,0,0,.26) 76%,rgba(0,0,0,.44) 100%);
  --g-edge-kpi-hi:linear-gradient(150deg,
    rgba(255,255,255,.88) 0%,rgba(255,255,255,.42) 22%,
    rgba(190,225,255,.24) 44%,rgba(0,0,0,.24) 76%,rgba(0,0,0,.42) 100%);
  --g-edge-ico:linear-gradient(150deg,    /* 立体图标本身已有一层厚度，棱边再亮一档才立得住 */
    rgba(255,255,255,.92) 0%,rgba(255,255,255,.46) 26%,
    rgba(200,230,255,.24) 50%,rgba(0,0,0,.24) 80%,rgba(0,0,0,.40) 100%);
  --g-edge-ico-hi:linear-gradient(150deg,
    rgba(255,255,255,1) 0%,rgba(255,255,255,.62) 26%,
    rgba(200,230,255,.34) 50%,rgba(0,0,0,.22) 80%,rgba(0,0,0,.38) 100%);
  --g-edge-ico-on:linear-gradient(150deg,
    rgba(255,255,255,1) 0%,rgba(255,255,255,.72) 26%,
    rgba(210,235,255,.42) 50%,rgba(255,255,255,.34) 76%,rgba(255,255,255,.52) 100%);
  /* 滚动容器专用：定向外阴影环（上/左迎光、下/右背光）
     外阴影跟随 border-radius 且固定在边框盒上，不会像绝对定位伪元素那样随内容滚走。 */
  --g-ring:0 -1px 0 0 rgba(255,255,255,.30),
          -1px 0 0 0 rgba(255,255,255,.11),
          0 1px 0 0 rgba(0,0,0,.30),
          1px 0 0 0 rgba(0,0,0,.20);
}
/* 背景固定，玻璃模糊才稳定 */
html[data-theme="glass"] body{background:var(--bg);background-attachment:fixed;}

/* ============ 玻璃棱边核心配方 ============
   真实玻璃的切边**不是一条均匀白线**，而是一圈随光线方向变化的渐变：
   朝光的上/左沿最亮 → 侧沿中等 → 背光的下/右沿最暗，且边缘比玻璃内部更暗（有厚度）。

   ★ 为什么不用 border-image 画这圈渐变描边：
   border-image 画的是**一个矩形图片铺满边框盒**，它**完全无视 border-radius**
   —— 元素本体是 10px 圆角、描边却是笔直的直角方框，四角就出现"圆角里套直角"的错位。
   （本机 Chromium 实测确认，见验证记录。）
   现在改用**伪元素 + mask 挖空**：伪元素绝对定位铺满元素、padding:1px，
   再用 `mask` 只保留 content-box 之外的那一圈 → 描边环的圆角来自 `border-radius:inherit`，
   四角与本体严格一致，且仍是随位置变化的渐变。
   注意：滚动/高频重绘容器（.table-wrap/.plan-scroll/.modal/.fmodal）**不能**用这招 ——
   绝对定位伪元素会随内容滚走，所以它们改用 `box-shadow` 外扩环（--g-ring），同样跟随圆角。 */
html[data-theme="glass"] .panel,
html[data-theme="glass"] .panel-card,
html[data-theme="glass"] .note-pop,
html[data-theme="glass"] .io-sheet-cell,
html[data-theme="glass"] .btn,
html[data-theme="glass"] #nav a,
html[data-theme="glass"] .nav-ico,
html[data-theme="glass"] .sidebar-foot,
html[data-theme="glass"] .kpi,
html[data-theme="glass"] .chip,
html[data-theme="glass"] .calendar-cell,
html[data-theme="glass"] .wf-dir{
  border:1px solid transparent;
}
/* 渐变环是绝对定位的 ::after，宿主必须有定位上下文。
   .panel-card/.kpi/.note-pop/.btn/#nav a/.nav-ico 原本就有；这里补齐缺的那几个。 */
html[data-theme="glass"] .panel,
html[data-theme="glass"] .io-sheet-cell,
html[data-theme="glass"] .fmodal{position:relative;}
/* .io-sheet-cell 基础样式是白底卡片，在深色玻璃主题下是一块刺眼的白板；
   这里改成深玻璃（内部 .inp/.btn 已有各自的玻璃样式，无需再覆盖）。 */
html[data-theme="glass"] .io-sheet-cell{background:rgba(255,255,255,.07);}
html[data-theme="glass"] .io-sheet-cell .io-sheet-name{color:#e8edf5;}
/* overflow:hidden 的宿主（.panel-card/.kpi）会把 ::after 的外沿裁掉一截，
   让 ::after 外扩 1px 补偿：这样环仍精确落在边框盒的外边缘上。 */
html[data-theme="glass"] .panel-card::after,
html[data-theme="glass"] .kpi::after{inset:-1px;}
/* 渐变环本体：mask 只留 1px 边环，圆角由 border-radius:inherit 保证与本体一致 */
html[data-theme="glass"] .panel::after,
html[data-theme="glass"] .panel-card::after,
html[data-theme="glass"] .note-pop::after,
html[data-theme="glass"] .io-sheet-cell::after,
html[data-theme="glass"] .btn::after,
html[data-theme="glass"] #nav a::after,
html[data-theme="glass"] .nav-ico::after,
html[data-theme="glass"] .sidebar-foot::after,
html[data-theme="glass"] .kpi::after,
html[data-theme="glass"] .chip::after,
html[data-theme="glass"] .calendar-cell::after,
html[data-theme="glass"] .wf-dir::after,
html[data-theme="glass"] .fmodal::after{
  content:'';position:absolute;inset:0;border-radius:inherit;padding:1px;
  pointer-events:none;z-index:2;
  background:var(--g-edge, linear-gradient(150deg,
    rgba(255,255,255,.78) 0%,rgba(255,255,255,.34) 18%,
    rgba(190,225,255,.16) 42%,rgba(0,0,0,.26) 74%,rgba(0,0,0,.48) 100%));
  -webkit-mask:linear-gradient(#fff 0 0) content-box,linear-gradient(#fff 0 0);
  -webkit-mask-composite:xor;
          mask:linear-gradient(#fff 0 0) content-box,linear-gradient(#fff 0 0);
          mask-composite:exclude;
}
html[data-theme="glass"] .panel{
  backdrop-filter:blur(24px) saturate(180%);
  -webkit-backdrop-filter:blur(24px) saturate(180%);
  /* 内斜面：上沿一道锐利亮线（迎光）＋ 迅速衰减的柔光（第二层斜面）；
     下/右沿压暗形成"厚度"；外投影把面板从背景里托起来 */
  box-shadow:
    inset 0 1px 0 var(--g-lit),
    inset 0 2px 4px var(--g-lit-soft),
    inset 0 0 16px var(--g-inner),
    inset 0 -1.5px 1px var(--g-shade),
    inset -1px 0 1px rgba(0,0,0,.26),
    0 18px 44px rgba(0,0,0,.42),
    0 0 0 1px rgba(255,255,255,.07);
}
/* hover 时棱边"被照亮"：迎光亮线提亮、彩边加强 —— 玻璃的互动反馈 */
html[data-theme="glass"] .panel-card:hover,
html[data-theme="glass"] .panel:hover{
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.85),
    inset 0 2px 5px rgba(255,255,255,.30),
    inset 0 0 16px var(--g-inner),
    inset 0 -1.5px 1px var(--g-shade),
    inset -1px 0 1px rgba(0,0,0,.26),
    0 20px 48px rgba(0,0,0,.48),
    0 0 0 1px rgba(255,255,255,.12);
}
html[data-theme="glass"] .panel:hover::after{background:var(--g-edge-hi);}
html[data-theme="glass"] .panel-card:hover::after{background:var(--g-edge-hi);}
/* 侧栏只有右边一条棱：纵向渐变（上亮下暗），符合光从上方来的直觉 */
html[data-theme="glass"] .sidebar{
  border-width:0 1px 0 0;
  /* 单边棱不能用伪元素（会绕成一整圈），用外阴影环把光只投到右侧 */
  box-shadow:
    1px 0 0 0 rgba(255,255,255,.34),
    1px 0 3px rgba(255,255,255,.10),
    1px 2px 6px rgba(0,0,0,.34),
    inset -1px 0 0 rgba(255,255,255,.30),
    inset 0 1.5px 0 rgba(255,255,255,.52),
    inset 0 2px 5px rgba(255,255,255,.18),
    inset 0 0 20px var(--g-inner),
    inset 0 -1.5px 0 rgba(0,0,0,.34),
    0 0 44px rgba(0,0,0,.38);
}
/* 顶栏只有下边一条棱 */
html[data-theme="glass"] .topbar{
  border-width:0 0 1px 0;
  box-shadow:
    0 1px 0 0 rgba(255,255,255,.34),
    0 1px 4px rgba(255,255,255,.08),
    0 2px 7px rgba(0,0,0,.30),
    inset 0 1px 0 rgba(255,255,255,.46),
    inset 0 2px 4px rgba(255,255,255,.16),
    inset 0 -1.5px 0 rgba(0,0,0,.30),
    0 8px 28px rgba(0,0,0,.32);
}
html[data-theme="glass"] .panel-card{background:rgba(255,255,255,.06);}
/* 面板卡的左侧强调条：单独用伪元素画，不占边框（边框要留给玻璃棱）
   注意 .panel-card 的 ::before 已被强调条占用，渐变环改画在 ::after 上。 */
html[data-theme="glass"] .panel-card{position:relative;overflow:hidden;}
html[data-theme="glass"] .panel-card::before{
  content:'';position:absolute;left:0;top:0;bottom:0;width:3px;z-index:3;
  background:linear-gradient(180deg,rgba(143,176,232,.95),rgba(90,130,200,.55));
}
/* 滚动容器不能用伪元素画环（绝对定位的 ::after 会随内容一起滚走），
   改用 box-shadow 外扩环 —— 它钉在 padding box 外沿、不随滚动、且同样跟随 border-radius。
   也不能加 backdrop-filter（Chromium 滚动闪烁/闪回）。 */
html[data-theme="glass"] .table-wrap,
html[data-theme="glass"] .plan-scroll,
html[data-theme="glass"] .tree-wrap,
html[data-theme="glass"] .confirm-box,
html[data-theme="glass"] .modal{
  /* 原来是 rgba(10,16,28,.52) —— 近黑半透明，等于在深色玻璃上又蒙一层黑纱，
     表格明细整片发闷、读数费劲。提到 .34：底衬交给玻璃底图本身，
     这里只留一点点压暗，让数字仍然浮得出来。 */
  background:rgba(14,21,35,.34);
  border:1px solid transparent;
  box-shadow:
    var(--g-ring),
    inset 0 1px 0 rgba(255,255,255,.32),
    inset 0 2px 4px rgba(255,255,255,.12),
    inset 0 0 18px var(--g-inner),
    inset 0 -1.5px 1px rgba(0,0,0,.34),
    inset -1px 0 1px rgba(0,0,0,.18),
    0 12px 36px rgba(0,0,0,.36);
}
/* 树形BOM 内部：白底会与深色玻璃打架 */
html[data-theme="glass"] .tree-label{color:#dbe3f0;}
html[data-theme="glass"] .tree-label:hover{background:rgba(255,255,255,.12);}
html[data-theme="glass"] .tree-label.active{background:rgba(143,176,232,.32);color:#fff;}
/* .fmodal 自身 overflow:hidden、内容在 .fscroll 里滚 → 伪元素不会跑，可以照常用 */
html[data-theme="glass"] .fmodal{background:rgba(8,13,23,.88);}
html[data-theme="glass"] .gantt-head{background:rgba(8,12,22,.82);}
html[data-theme="glass"] .gantt-left .gantt-row{background:rgba(14,20,34,.9);}
/* 毛玻璃按钮：深玻璃 + 白边 + 高光
   模糊半径从 24→8px：按钮下方的 .panel 本身已经做过模糊，这里再叠一层大半径几乎看不出差别，
   但每个按钮都是一层独立的 backdrop 图层（操作面板上百个），半径越大重绘越贵。*/
html[data-theme="glass"] .btn{
  position:relative;
  backdrop-filter:blur(8px) saturate(180%);
  -webkit-backdrop-filter:blur(8px) saturate(180%);
  background:rgba(255,255,255,.10);
  /* 小件的棱边要比面板更收敛：亮线更细、暗侧更浅，否则整屏按钮会「毛」成一团 */
  color:#e8edf5;
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.42),
    inset 0 1.5px 2px rgba(255,255,255,.14),
    inset 0 0 8px rgba(0,0,0,.10),
    inset 0 -1.5px 0 rgba(0,0,0,.26),
    inset -1px 0 0 rgba(0,0,0,.14),
    0 6px 16px rgba(0,0,0,.30);
  font-weight:600;
}
html[data-theme="glass"] .btn::after{background:var(--g-edge-sm);}
html[data-theme="glass"] .btn:hover{
  background:rgba(255,255,255,.20);
  color:#fff;
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.72),
    inset 0 1.5px 3px rgba(255,255,255,.24),
    inset 0 0 8px rgba(0,0,0,.08),
    inset 0 -1.5px 0 rgba(0,0,0,.24),
    inset -1px 0 0 rgba(0,0,0,.14),
    0 8px 20px rgba(0,0,0,.36);
}
html[data-theme="glass"] .btn:hover::after{background:var(--g-edge-sm-hi);}
html[data-theme="glass"] .btn-primary{
  background:rgba(31,56,100,.55);color:#fff;
}
html[data-theme="glass"] .btn-primary::after{background:var(--g-edge-pri);}
html[data-theme="glass"] .btn-primary:hover{background:rgba(31,56,100,.72);}
html[data-theme="glass"] .btn-danger{color:#ffd9d2;}
html[data-theme="glass"] .btn-danger::after{background:var(--g-edge-dng);}
html[data-theme="glass"] .btn-danger:hover{background:rgba(210,70,60,.35);color:#fff;}
html[data-theme="glass"] .btn-mini{box-shadow:0 2px 8px rgba(0,0,0,.25),inset 0 1px 0 rgba(255,255,255,.18);}
/* 弹窗 / 窗体 */
/* 遮罩只做压暗，不做全屏 backdrop-filter：全屏模糊每帧重算，弹窗内任何重绘都会被它拖慢 */
html[data-theme="glass"] .modal-mask{background:rgba(2,6,14,.62);}
html[data-theme="glass"] .fmodal{border-radius:12px;}
html[data-theme="glass"] .fhead{border-bottom:1px solid rgba(255,255,255,.14);}
html[data-theme="glass"] .fbar,html[data-theme="glass"] .ffoot{background:rgba(255,255,255,.10);}
html[data-theme="glass"] .fscroll{background:rgba(255,255,255,.07);}
html[data-theme="glass"] .note-pop{position:fixed;z-index:9000;backdrop-filter:blur(16px) saturate(150%);
  -webkit-backdrop-filter:blur(16px) saturate(150%);
  box-shadow:0 7px 20px rgba(0,0,0,.30),
    inset 0 1px 0 rgba(255,255,255,.28),
    inset 0 -1.5px 1px rgba(0,0,0,.22);}
html[data-theme="glass"] .note-pop-h{background:rgba(0,0,0,.45);}
/* 导入小窗的目录浏览器 */
html[data-theme="glass"] .wf-dir{position:relative;background:rgba(10,16,28,.45);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.26),inset 0 0 12px var(--g-inner);}
html[data-theme="glass"] .wf-dir::after{background:var(--g-edge-sm);}
html[data-theme="glass"] .wf-quick{background:rgba(255,255,255,.06);border-bottom-color:rgba(255,255,255,.12);}
html[data-theme="glass"] .wf-crumb{background:rgba(255,255,255,.08);border-bottom-color:rgba(255,255,255,.12);}
html[data-theme="glass"] .wf-path{color:#e8edf5;}
html[data-theme="glass"] .wf-row{color:#dbe3f0;}
html[data-theme="glass"] .wf-row:hover{background:rgba(255,255,255,.14);}
html[data-theme="glass"] .wf-folder{color:#fff;}
/* 左侧菜单：深色玻璃上给立体图标加一圈白色描边（通透感），文字提亮
   菜单项也是玻璃小片，用同一套棱边渐变（比面板收敛一档） */
html[data-theme="glass"] #nav a{
  color:#cdd8ea;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.26),inset 0 -1px 0 rgba(0,0,0,.22);
}
html[data-theme="glass"] #nav a::after{background:var(--g-edge-sm);}
html[data-theme="glass"] #nav a:hover{
  color:#fff;background:rgba(255,255,255,.10);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.46),inset 0 -1px 0 rgba(0,0,0,.20),0 2px 8px rgba(0,0,0,.30);
}
html[data-theme="glass"] #nav a:hover::after{background:var(--g-edge-sm-hi);}
html[data-theme="glass"] #nav a.active{
  color:#fff;background:rgba(255,255,255,.14);
  /* 选中态整圈发亮：玻璃被"打亮"的观感 */
  box-shadow:inset 0 1px 0 rgba(255,255,255,.70),inset 0 0 10px rgba(255,255,255,.16),
    0 0 0 1px rgba(255,255,255,.16),0 3px 12px rgba(0,0,0,.38);
}
html[data-theme="glass"] #nav a.active::after{background:var(--g-edge-on);}
html[data-theme="glass"] .sidebar-foot{
  position:relative;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.20);
}
html[data-theme="glass"] .sidebar-foot::after{
  background:linear-gradient(150deg,
    rgba(255,255,255,.42) 0%,rgba(255,255,255,.16) 28%,
    rgba(0,0,0,.20) 80%,rgba(0,0,0,.32) 100%);
}
/* ---- 仪表盘专属小件的玻璃棱 ---- */
/* KPI 卡：与面板同一套配方，但亮线略细（它比面板小，棱边要收敛） */
html[data-theme="glass"] .kpi{
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.34),
    inset 0 2px 3px rgba(255,255,255,.13),
    inset 0 0 12px var(--g-inner),
    inset 0 -1.5px 0 rgba(0,0,0,.32),
    0 10px 26px rgba(0,0,0,.32);
}
html[data-theme="glass"] .kpi::before{content:'';position:absolute;left:0;top:0;bottom:0;width:3px;z-index:3;
  background:var(--k-c,var(--navy-2));}
html[data-theme="glass"] .kpi::after{background:var(--g-edge-kpi);}
html[data-theme="glass"] .kpi:hover::after{background:var(--g-edge-kpi-hi);}
/* 计数胶囊：极小件，棱边只要一薄圈明暗就够，多了会糊成噪点 */
html[data-theme="glass"] .chip{
  position:relative;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.22),inset 0 -1px 0 rgba(0,0,0,.18);
}
html[data-theme="glass"] .chip::after{
  background:linear-gradient(150deg,
    rgba(255,255,255,.42) 0%,rgba(255,255,255,.16) 30%,
    rgba(0,0,0,.18) 82%,rgba(0,0,0,.30) 100%);
}
html[data-theme="glass"] .chip b{color:#e8edf5;}
html[data-theme="glass"] .chip.warn b{color:var(--red);}
html[data-theme="glass"] .chart-empty{
  background:rgba(255,255,255,.05);
  border:1px dashed rgba(255,255,255,.20);
}
html[data-theme="glass"] .calendar-cell{position:relative;}
html[data-theme="glass"] .calendar-cell::after{
  background:linear-gradient(150deg,
    rgba(255,255,255,.44) 0%,rgba(255,255,255,.18) 28%,
    rgba(0,0,0,.20) 82%,rgba(0,0,0,.32) 100%);
}
html[data-theme="glass"] .calendar-cell:hover::after{
  background:linear-gradient(150deg,
    rgba(255,255,255,.85) 0%,rgba(255,255,255,.40) 28%,
    rgba(0,0,0,.18) 82%,rgba(0,0,0,.30) 100%);
}
html[data-theme="glass"] .bartrack,
html[data-theme="glass"] .stackbar{
  box-shadow:inset 0 1px 2px rgba(0,0,0,.22);
}
html[data-theme="glass"] .nav-ico{
  box-shadow:
    0 3px 6px rgba(0,0,0,.42),
    0 1px 0 var(--c-lo,#17527f),
    inset 0 1px 0 rgba(255,255,255,.78),
    inset 0 -1px 0 rgba(0,0,0,.34),
    inset 1px 0 0 rgba(255,255,255,.30),
    inset -1px 0 0 rgba(0,0,0,.20);
}
/* 图标已有 ::before 画顶部玻璃反光，渐变环只能画在 ::after 上 */
html[data-theme="glass"] .nav-ico::after{background:var(--g-edge-ico);z-index:1;}
html[data-theme="glass"] #nav a:hover .nav-ico::after{background:var(--g-edge-ico-hi);}
html[data-theme="glass"] #nav a.active .nav-ico::after{background:var(--g-edge-ico-on);}
/* 浅色侧栏主题（win7 / classic）：立体图标改用「白底浮起」配方，才不会糊在浅背景里 */
html[data-theme="win7"] .nav-ico,
html[data-theme="classic"] .nav-ico{
  border:1px solid rgba(255,255,255,.92);
  box-shadow:
    0 2px 3px rgba(30,50,80,.24),
    0 1px 0 var(--c-lo,#17527f),
    inset 0 1px 0 rgba(255,255,255,.95),
    inset 0 -1px 0 rgba(0,0,0,.30),
    inset 1px 0 0 rgba(255,255,255,.55),
    inset -1px 0 0 rgba(0,0,0,.16);
}
html[data-theme="win7"] #nav a:hover .nav-ico,
html[data-theme="classic"] #nav a:hover .nav-ico{border-color:#fff;}
/* 普通弹窗（modal）深色玻璃适配；.modal 自身滚动，故不加 backdrop-filter */
html[data-theme="glass"] .modal-title{color:#e8edf5;border-bottom-color:rgba(255,255,255,.14);}
html[data-theme="glass"] .modal-body label{color:rgba(255,255,255,.55);}
html[data-theme="glass"] .modal-body input,
html[data-theme="glass"] .modal-body select{
  background:rgba(0,0,0,.25);color:#e8edf5;border-color:rgba(255,255,255,.18);}
html[data-theme="glass"] .modal-body input:focus,
html[data-theme="glass"] .modal-body select:focus{
  border-color:rgba(255,255,255,.55);box-shadow:0 0 0 2px rgba(255,255,255,.15);}
html[data-theme="glass"] .modal-foot{background:rgba(255,255,255,.08);border-top-color:rgba(255,255,255,.14);}
/* ---- 计划表（毛玻璃）----
   2026-10-13：这一段原来有 20 多条硬编码补丁（表头底、字色、wkend、pt-val、
   pt-param、pt-edit、日历小格、就地编辑框…），现在**全部删掉** —— 它们的值已经
   收进 glass 变量块里的 --pt-*，基础规则直接读变量即可。
   保留的只有玻璃特有的「表面质感」：面板的 backdrop 模糊与内阴影，
   以及日历面板的玻璃卡外观。文字色与边框色统一交给 --pt-*（--pt-grid 已是半透明白）。 */
html[data-theme="glass"] .calendar-panel{
  background:rgba(255,255,255,.06);border-color:rgba(255,255,255,.18);
  box-shadow:0 8px 24px rgba(0,0,0,.32),inset 0 1px 0 rgba(255,255,255,.14);
  backdrop-filter:blur(16px) saturate(150%);}
html[data-theme="glass"] .calendar-tip{color:rgba(255,255,255,.55);}
html[data-theme="glass"] .calendar-inline{background:transparent;border:none;box-shadow:none;backdrop-filter:none;}
/* 侧栏品牌 / 标志 */
html[data-theme="glass"] .brand-title,html[data-theme="glass"] .brand-sub{color:#e8edf5;}
/* 深色主题：字标深蓝在深底上对比度不足，用 brightness+saturate 提亮，
   保留品牌色相（不会变成灰白），亮度抬到与深底拉开 ≥4.5:1。 */
html[data-theme="glass"] .logo{--logo-filter:brightness(1.42) saturate(1.28);}
html[data-theme="glass"] .sidebar-foot{color:rgba(255,255,255,.55);}
/* 输入框 */
html[data-theme="glass"] .search-input,html[data-theme="glass"] .inp{
  background:rgba(0,0,0,.25);color:#e8edf5;border-color:rgba(255,255,255,.18);}
html[data-theme="glass"] .search-input::placeholder,html[data-theme="glass"] .inp::placeholder{color:rgba(255,255,255,.4);}
html[data-theme="glass"] .search-input:focus,html[data-theme="glass"] .inp:focus{
  border-color:rgba(255,255,255,.55);box-shadow:0 0 0 2px rgba(255,255,255,.15);}
/* 深色玻璃上的标题/文字 */
html[data-theme="glass"] .page-title{color:#e8edf5;}
/* 深色主题：弱化隔行着色，避免「奇偶行明暗反差」让空单元格与有值单元格看起来不一致
   （奇数行 .42 白底、偶数行 .035 透底在深色背景上反差极强，空单元格尤显突兀）
   ★ 2026-10-12 反过来调：原来奇 .055 / 偶 .03 只差 2.5 个百分点，
     长表里等于没有隔行。现拉到奇 .085 / 偶 .022（差 6.3 个百分点），
     既保留「不成块」的观感，又能一眼分清行边界。 */
html[data-theme="glass"] table.grid tbody tr{background:rgba(255,255,255,.085);}
html[data-theme="glass"] table.grid tbody tr:nth-child(even){background:rgba(255,255,255,.022);}
html[data-theme="glass"] table.grid tbody tr:hover{background:rgba(255,255,255,.17);}
html[data-theme="glass"] table.grid tbody tr:nth-child(even):hover{background:rgba(255,255,255,.17);}
html[data-theme="glass"] table.grid.sheet-orders tbody tr:nth-child(odd),
html[data-theme="glass"] table.grid.sheet-orders tbody tr:nth-child(even){background:rgba(255,255,255,.085);}
html[data-theme="glass"] table.grid.sheet-orders tbody tr:nth-child(even){background:rgba(255,255,255,.022);}
/* 计算列（通常为空或公式值）在深色下保持与同行一致 */
html[data-theme="glass"] table.grid td.cell-calc{background:transparent;}
/* 产能表：分组表头在深色下也走暗玻璃，避免亮条。
   （分隔列 2026-10-13 起**不再有底色**、只用 --cap-sep-line 竖线，glass 已在其变量块里给值，
     这里不再硬编码覆盖，否则会把变量方案架空。） */
html[data-theme="glass"] table.grid.cap-tbl thead tr.cap-group th{background:rgba(0,0,0,.42);color:#e8edf5;border-bottom-color:rgba(255,255,255,.14);}

/* ---- 弹窗（窗体）透明度：2026-10-13 起顶栏滑杆改为高斯模糊，--form-op 固定 1 ---- */
#formBox{opacity:var(--form-op);}
#formBox.fop-on{transition:opacity .12s;}

/* ---- 顶栏主题 / 透明度控件 ---- */
.op-range{width:74px;vertical-align:middle;accent-color:var(--navy);}
.op-val{font-size:11px;color:var(--muted);min-width:30px;text-align:right;font-variant-numeric:tabular-nums;}
.op-wrap{display:flex;align-items:center;gap:4px;}

/* ---- 背景图选择器（深空主题专用）----
   放在顶栏主题下拉右侧，只有深空下显示（syncBgPickerVisible 控制 hidden）。 */
.bg-picker{display:flex;align-items:center;gap:5px;}
.bg-picker[hidden]{display:none;}
.bg-btn{padding:2px 10px;font-size:11.5px;line-height:1.5;}
.bg-name{
  max-width:110px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  font-size:11px;opacity:.75;
}
/* 模糊强度滑杆：0 = 保持原图（不模糊），数值越大越糊 */
.bg-blur-wrap{display:flex;align-items:center;gap:3px;}
.bg-blur-wrap .hint{font-size:11px;}
.bg-blur{width:56px;vertical-align:middle;accent-color:var(--navy);}
.bg-blur-val{font-size:11px;color:var(--muted);min-width:26px;text-align:right;font-variant-numeric:tabular-nums;}

/* ---- 订单表：着色统一为隔行（清掉单元格级花色）---- */
table.grid.sheet-orders tbody td{background:transparent;}
table.grid.sheet-orders tbody tr:nth-child(odd){background:var(--panel);}
table.grid.sheet-orders tbody tr:nth-child(even){background:var(--row-alt);}
table.grid.sheet-orders tbody tr:hover{background:var(--row-hover);}
table.grid.sheet-orders tbody tr:hover td{background:transparent;}
table.grid.sheet-orders td.cell-calc,table.grid.sheet-orders td.cell-calc:hover{background:transparent;}

/* ===================================================================
   ⑥ 深空（Deep Space）—— 深色悬浮玻璃卡片
   -------------------------------------------------------------------
   2026-10-13 用户按参考图重做：**取图中「中间那块卡片」的质感**，
   即 —— 近黑半透明的玻璃卡片浮在暗色实景上：
     ① 卡面本身是**深色**（不是白色）：底色 rgba(255,255,255,.05~.08) 的白玻璃
        叠在近黑环境光上，视觉上就是「深色玻璃」，文字用亮色；
     ② 一圈 1px 半透明白描边勾出玻璃厚度 + 顶部一道内亮线；
     ③ 大圆角（--r:18px）+ 弥散投影，卡片「浮」在背景上；
     ④ 背景一律用软件内「背景图」选的那张图（见 #bgLayer），不写死任何图。
   ⚠ data-theme 仍是 glass（复用毛玻璃全部表格/弹窗基础规则），
     差异只写在 .theme-space 下；切主题时该 class 被摘掉即完全失效。
   =================================================================== */
html.theme-space{
  --navy:#6ba6e8; --navy-2:#8dc0f5; --navy-soft:rgba(107,166,232,.16);
  --ink:#e9eef6; --muted:rgba(233,238,246,.62);
  --line:rgba(255,255,255,.15); --line-2:rgba(255,255,255,.10);

  /* ★ 无背景图时的底：近黑 + 极淡冷色环境光。
     有背景图时由 .has-bg 那段接管（--bg 退成半透明，让照片透上来）。*/
  --bg:
    radial-gradient(1100px 780px at 12% 6%,rgba(70,110,190,.20),transparent 62%),
    radial-gradient(940px 680px at 90% 10%,rgba(120,90,190,.16),transparent 64%),
    radial-gradient(900px 700px at 84% 94%,rgba(50,150,150,.14),transparent 66%),
    #05070c;
  --panel:rgba(17,21,30,.50);
  --wrap-bg:rgba(11,15,23,.56);
  --modal-bg:rgba(11,15,23,.62);
  --row-alt:rgba(255,255,255,.038);
  --row-hover:rgba(255,255,255,.085);
  --cell-hover:rgba(255,255,255,.11);
  --plan-odd:rgba(255,255,255,.130);  --plan-odd-act:rgba(255,255,255,.180);
  --plan-even:rgba(255,255,255,.065); --plan-even-act:rgba(255,255,255,.105);
  /* 冻结列的不透明版组色 = 半透明组色叠在「页面底 + 表格容器底」上的结果
     （under = #090c13，见下方注释），横向滚动时右侧数字才不会透出来。*/
  --plan-odd-op:#292c32;  --plan-odd-act-op:#35383d;
  --plan-even-op:#191c22; --plan-even-act-op:#23252c;
  --plan-sci-under:#090c13;
  --cap-sep-line:rgba(255,255,255,.20);
  --sidebar-bg:rgba(11,15,23,.46);
  --sidebar-fg:var(--ink); --sidebar-fg-dim:rgba(233,238,246,.66);
  --sidebar-line:rgba(255,255,255,.12);
  --nav-hover:rgba(255,255,255,.09); --nav-active:rgba(255,255,255,.16);
  --nav-line:rgba(255,255,255,.20); --nav-line-hi:rgba(255,255,255,.46); --nav-bg:rgba(255,255,255,.05);
  --c1:#6ba6e8; --c2:#4fc79a; --c3:#f0b95c; --c4:#a98ae0; --c5:#4fc4dd; --c6:#ff7a68;
  --chart-track:rgba(255,255,255,.10);
  --chart-sel-bg:rgba(120,175,245,.20); --chart-hit-bg:rgba(120,175,245,.10);
  --thead-bg:rgba(9,13,20,.86); --thead-fg:var(--ink); --thead-line:rgba(255,255,255,.16);
  --btn-bg:rgba(255,255,255,.09); --btn-fg:var(--ink);
  --btn-line:rgba(255,255,255,.20); --btn-hover-bg:rgba(255,255,255,.17);
  --foot-bg:rgba(255,255,255,.05);
  --form-head-bg:rgba(0,0,0,.42); --form-head-fg:var(--ink);
  --red:#ff6b5b; --green:#5ecf8e; --amber:#f0b84a;
  --win-shadow:0 24px 68px rgba(0,0,0,.62);
  --win-border:rgba(255,255,255,.18);
  --r:18px;                     /* 大圆角 —— 参考图最显眼的特征 */

  /* 计划表 / 日历小表（--pt-*）：深色玻璃。表头必须近黑实底 + 亮字，
     半透明表头叠上网格线后文字会糊在网格上；明细区底色交给 --plan-* 组色。*/
  --pt-scroll-bg:rgba(9,13,20,.42);
  --pt-cell-bg:rgba(255,255,255,.055);
  --pt-grid:rgba(255,255,255,.11);
  --pt-hd-bg:rgba(8,12,20,.90);--pt-hd-fg:var(--ink);--pt-hd-line:rgba(255,255,255,.14);
  --pt-sub-bg:rgba(18,25,38,.88);--pt-sub-fg:var(--ink);
  --pt-val-bg:rgba(255,255,255,.08);--pt-val-fg:var(--ink);
  --pt-param-bg:rgba(0,0,0,.46);--pt-param-fg:#dbe4f2;
  --pt-edit-hd-bg:rgba(0,0,0,.48);--pt-edit-hd-fg:var(--ink);
  --pt-edit-bg:rgba(255,255,255,.10);--pt-edit-fg:var(--ink);
  --pt-edit-hi-bg:rgba(107,166,232,.24);--pt-edit-hi-ring:#8dc0f5;
  --pt-wkend-bg:rgba(120,55,55,.62);--pt-wkend-fg:#ffd9d2;
  --pt-workday-bg:rgba(46,120,90,.45);--pt-workday-fg:#cdeed9;
  --pt-holiday-bg:rgba(255,255,255,.05);--pt-holiday-fg:rgba(255,255,255,.66);
  --pt-num-fg:#d6e4f7;--pt-num-act-fg:#a8e0bd;
  --pt-kind-fg:#d3e2fa;--pt-kind-act-fg:#b6e6c6;
  --pt-calc-fg:#9db3d2;
  --pt-late-fg:#ff8a7a;
  --pt-dirty:#e8a44f;--pt-dirty-fg:#f0b96a;
  --pt-group-line:rgba(255,255,255,.30);
  --pt-inline-bg:rgba(255,255,255,.13);--pt-inline-fg:var(--ink);--pt-inline-line:rgba(255,255,255,.34);
  --pt-cal-cell-bg:rgba(255,255,255,.06);--pt-cal-cell-fg:var(--ink);--pt-cal-cell-line:rgba(255,255,255,.20);
  --pt-cal-label-fg:var(--ink);
  --pt-cal-hi-bg:rgba(255,255,255,.16);--pt-cal-hi-line:rgba(255,255,255,.46);

  /* 玻璃棱边：参考图那道「1px 亮边 + 顶部内亮线」。上/左沿迎光最亮，
     下/右沿背光收暗，边缘比内部略暗 → 有厚度。*/
  --g-edge:linear-gradient(160deg,
    rgba(255,255,255,.42) 0%,rgba(255,255,255,.16) 26%,
    rgba(255,255,255,.05) 52%,rgba(0,0,0,.22) 78%,rgba(0,0,0,.36) 100%);
  --g-edge-hi:linear-gradient(160deg,
    rgba(255,255,255,.70) 0%,rgba(255,255,255,.28) 26%,
    rgba(255,255,255,.09) 52%,rgba(0,0,0,.20) 78%,rgba(0,0,0,.34) 100%);
  --g-edge-sm:linear-gradient(160deg,
    rgba(255,255,255,.34) 0%,rgba(255,255,255,.13) 30%,
    rgba(255,255,255,.04) 60%,rgba(0,0,0,.20) 100%);
  --g-edge-sm-hi:linear-gradient(160deg,
    rgba(255,255,255,.62) 0%,rgba(255,255,255,.24) 30%,
    rgba(255,255,255,.07) 60%,rgba(0,0,0,.18) 100%);
  --g-edge-on:linear-gradient(160deg,
    rgba(255,255,255,.85) 0%,rgba(255,255,255,.42) 40%,rgba(255,255,255,.30) 100%);
  --g-edge-pri:linear-gradient(160deg,
    rgba(255,255,255,.48) 0%,rgba(255,255,255,.18) 34%,rgba(255,255,255,.08) 100%);
  --g-edge-kpi:linear-gradient(160deg,
    rgba(255,255,255,.38) 0%,rgba(255,255,255,.13) 30%,
    rgba(255,255,255,.04) 58%,rgba(0,0,0,.20) 100%);
  --g-edge-kpi-hi:linear-gradient(160deg,
    rgba(255,255,255,.66) 0%,rgba(255,255,255,.24) 30%,
    rgba(255,255,255,.07) 58%,rgba(0,0,0,.18) 100%);
  --g-edge-ico:linear-gradient(160deg,
    rgba(255,255,255,.52) 0%,rgba(255,255,255,.20) 34%,rgba(255,255,255,.07) 100%);
  --g-edge-ico-hi:linear-gradient(160deg,
    rgba(255,255,255,.80) 0%,rgba(255,255,255,.32) 34%,rgba(255,255,255,.11) 100%);
  --g-ring:0 -1px 0 0 rgba(255,255,255,.26),
          0 1px 0 0 rgba(0,0,0,.40);
}

/* ---- 底图：深空比其它主题更暗，卡片才浮得出来 ---- */
html.theme-space body{background:var(--bg);background-attachment:fixed;}

/* ---- 背景图层（软件内「背景图」选的那张）----
   ⚠ 为什么单独一层而不是直接写 body{background-image}：
   body 上已经有 --bg 的多层 radial-gradient（环境光）。若再叠 background-image，
   后写的会整层盖住前面的渐变。想保留「照片 + 压幕」就必须用独立图层。

   ⚠⚠ **绝对不能给 body 加 isolation / z-index**：
   body 是 #app 里所有 position:sticky（表头、冻结列）的**祖先容器**，
   一旦它成为层叠上下文（isolation:isolate）或带 z-index，sticky 的参照系就变了
   → 表头/冻结列全部错位。正确做法：图层 position:fixed; z-index:0（不是 -1，
   靠 DOM 顺序天然垫底），#app 再显式 z-index:1 抬起来。*/
#bgLayer{
  position:fixed;inset:0;z-index:0;
  background-size:cover;background-position:center;background-repeat:no-repeat;
  /* ★ 用 CSS 变量承接图片，而不是 JS 写 background-image。
     直接写内联 background-image 实测不稳（部分环境下普通内联赋值会被丢弃、
     只有 !important 才生效 —— 坑过一次）。JS 只设 --bg-img，这里消费。*/
  background-image:var(--bg-img,none);
  opacity:0;                          /* 没有设图时完全不可见 */
  transition:opacity .45s ease;
  pointer-events:none;
  /* 高斯模糊：把实景揉成柔和色块。⚠ 必须配 scale 放大一点：
     blur() 会把元素边缘往外吸出透明，不放大就在四周露出 body 底色的硬边。
     ⚠ 只给这一层做 filter，不给任何滚动容器做 —— 表格滚动时每帧重算大半径
     模糊会拖垮帧率（已实测）。*/
  filter:blur(var(--bg-blur,16px)) saturate(var(--bg-sat,1.20));
  transform:scale(1.08);
  transform-origin:center center;
  will-change:filter;
}
/* 2026-10-13：背景图对所有主题开放。给 #app 加 position:relative;z-index:1 之后，
   各主题的 sticky 表头/冻结列依然正常（实测逐主题验证）。*/
html.has-bg #app{position:relative;z-index:1;}
/* 照片上面压一层暗色渐变，保证表格数字的对比度（照片再好看也不能牺牲可读性）。
   深空主题卡片本身是深色的 → 压幕走**暗色**，照片透上来仍被卡片托住。
   ⚠ 压幕强度是「背景图能否透出来」的决定项：.52~.66 会把照片压成一片黑，
     这里收到 .40~.56 —— 卡片自身有足够暗底托住数字，照片仍能透出环境色。*/
#bgLayer::after{
  content:'';position:absolute;inset:0;
  background:
    radial-gradient(1200px 900px at 10% 4%,rgba(70,116,208,.24),transparent 66%),
    radial-gradient(1000px 720px at 92% 10%,rgba(140,104,224,.18),transparent 64%),
    linear-gradient(180deg,rgba(4,6,12,.40),rgba(4,6,12,.56));
}
/* 有背景图 → 图层可见（所有主题） */
html.has-bg #bgLayer{opacity:1;}
/* 深空 + 背景图：卡片底再收一档，让实景透得更明显，但表头/冻结列保持实底。*/
html.theme-space.has-bg{
  --bg:rgba(5,7,12,.30);
  --panel:rgba(15,19,27,.42);
  --wrap-bg:rgba(9,12,19,.46);
  --thead-bg:rgba(8,12,20,.84);
  --sidebar-bg:rgba(10,14,21,.42);
}

/* ---- 背景图在**其它浅色主题**下的适配（所有主题都能换背景图）----
   深空（theme-space）是深色底、沿用上面的暗压幕；这里处理 win7/classic：
   它们原本白底，换上照片后若沿用暗压幕会变成白面板浮在暗照片上、字发灰，
   故改走**浅色柔光**（照片被提亮而不是压暗），深色文字依旧清晰。*/
html.has-bg[data-theme="win7"] #bgLayer::after,
html.has-bg[data-theme="classic"] #bgLayer::after{
  background:
    radial-gradient(1200px 900px at 10% 4%,rgba(255,255,255,.30),transparent 66%),
    radial-gradient(1000px 720px at 92% 10%,rgba(208,226,250,.26),transparent 64%),
    linear-gradient(180deg,rgba(247,250,253,.58),rgba(238,244,251,.68));
}
html.has-bg[data-theme="win7"]{
  --panel:rgba(255,255,255,.70); --wrap-bg:rgba(255,255,255,.70);
  --row-alt:rgba(223,234,249,.42); --row-hover:rgba(201,221,245,.60); --cell-hover:rgba(191,215,242,.60);
}
html.has-bg[data-theme="classic"]{
  --panel:rgba(255,255,255,.70); --wrap-bg:rgba(255,255,255,.70);
  --row-alt:rgba(230,230,224,.42); --row-hover:rgba(213,223,238,.60); --cell-hover:rgba(200,216,236,.60);
}
/* 极细噪点：给纯数字渐变加一点"胶片颗粒"，大面积平色阶否则会看出色带 */
html.theme-space body::after{
  content:'';position:fixed;inset:0;z-index:9500;pointer-events:none;opacity:.035;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='3'/%3E%3C/filter%3E%3Crect width='120' height='120' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ---- 侧栏 / 顶栏：深色玻璃，底色更透让背景透上来 ---- */
html.theme-space .sidebar{
  background:rgba(11,15,23,.46);
  backdrop-filter:blur(26px) saturate(150%);
  -webkit-backdrop-filter:blur(26px) saturate(150%);
  box-shadow:
    1px 0 0 0 rgba(255,255,255,.10),
    inset -1px 0 0 rgba(255,255,255,.10),
    inset 0 1.5px 0 rgba(255,255,255,.22),
    0 0 44px rgba(0,0,0,.34);
}
html.theme-space .topbar{
  background:rgba(11,15,23,.44);
  backdrop-filter:blur(26px) saturate(150%);
  -webkit-backdrop-filter:blur(26px) saturate(150%);
  box-shadow:
    0 1px 0 0 rgba(255,255,255,.10),
    inset 0 1px 0 rgba(255,255,255,.20),
    0 6px 24px rgba(0,0,0,.30);
}
html.theme-space .logo{
  --logo-filter:brightness(1.42) saturate(1.28);
  --logo-op:1;
}

/* ---- 菜单项：胶囊形；选中态是「亮起的玻璃胶囊」，参考图里最抓眼的元素 ---- */
html.theme-space #nav a{
  border-radius:999px;
  padding:5px 10px 5px 6px;
  box-shadow:0 0 0 1px rgba(255,255,255,.05);
}
html.theme-space #nav a:hover{
  background:rgba(255,255,255,.09);
  box-shadow:0 0 0 1px rgba(255,255,255,.12),0 2px 10px rgba(0,0,0,.34);
}
html.theme-space #nav a.active{
  background:rgba(255,255,255,.15);
  color:#fff;font-weight:700;border-color:transparent;
  box-shadow:0 4px 16px rgba(0,0,0,.42),inset 0 1px 0 rgba(255,255,255,.42);
}
html.theme-space #nav a.active::after{
  background:linear-gradient(160deg,rgba(255,255,255,.80),rgba(255,255,255,.22));
}
html.theme-space #nav a.active .nav-ico{
  background:linear-gradient(158deg,#8fb9ff 0%,#4a86e8 46%,#2a5cb0 100%);
  box-shadow:
    0 1px 2px rgba(0,0,0,.40),
    0 1px 0 #2a5cb0,
    inset 0 1px 0 rgba(255,255,255,.62),
    inset 0 -1px 0 rgba(0,0,0,.30);
}
html.theme-space .sidebar-foot{
  border-radius:999px;background:rgba(255,255,255,.05);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.20);
}

/* ---- 卡片：参考图的招牌质感 —— 深色玻璃 + 强模糊 + 一圈亮边 ----
   它的通透感来自三件事同时成立，缺一就发闷：
     ① 卡面是**半透明白**（rgba(255,255,255,.05)）而不是实色黑 —— 白玻璃会散射光；
     ② blur 拉到 30px 且加 saturate，背后的实景被彻底揉开，只剩色块；
     ③ 外描边一圈半透明白，勾出玻璃的"厚度"。
   ⚠ 只给面板/弹窗主体上 backdrop-filter；表格滚动容器一律不上
     （模糊成本 = 半径×图层×重绘频率，排产表几十列滚动时会拖垮帧率）。*/
html.theme-space .panel{
  backdrop-filter:blur(32px) saturate(165%);
  -webkit-backdrop-filter:blur(32px) saturate(165%);
  box-shadow:
    0 0 0 1px rgba(255,255,255,.12),           /* 第 1 层：外描边最弱，让背景多透一点 */
    inset 0 1px 0 rgba(255,255,255,.24),        /* 顶部亮线 */
    inset 0 0 34px rgba(255,255,255,.03),
    0 20px 52px rgba(0,0,0,.50);                /* 悬浮投影：卡要"浮"起来 */
}
/* 操作面板按键：深色玻璃 + 白字（白字需要深色底才能读清），
   左边条保留 --navy 蓝，与其它主题同族 */
html.theme-space .panel-card{
  background:rgba(255,255,255,.065);
  padding:11px 13px;color:#fff;
  backdrop-filter:blur(14px) saturate(150%);
  -webkit-backdrop-filter:blur(14px) saturate(150%);
  box-shadow:
    0 0 0 1px rgba(255,255,255,.14),
    inset 0 1px 0 rgba(255,255,255,.24),
    0 8px 22px rgba(0,0,0,.34);
}
html.theme-space .panel-card-t{color:#fff;}
html.theme-space .panel-card-d{color:rgba(255,255,255,.78);}
html.theme-space .panel-card:hover{
  background:rgba(255,255,255,.13);
  box-shadow:
    0 0 0 1px rgba(255,255,255,.32),
    inset 0 1px 0 rgba(255,255,255,.36),
    0 10px 26px rgba(0,0,0,.42);
}
html.theme-space .panel-card::before{
  background:linear-gradient(180deg,rgba(141,192,245,.95),rgba(107,166,232,.35));
  width:3px;
}

/* ---- KPI：大圆角玻璃数字卡 ---- */
html.theme-space .kpi{
  padding:9px 14px 10px 16px;border-radius:16px;
  background:rgba(255,255,255,.06);
  backdrop-filter:blur(22px) saturate(150%);
  -webkit-backdrop-filter:blur(22px) saturate(150%);
  box-shadow:
    0 0 0 1px rgba(255,255,255,.10),
    inset 0 1px 0 rgba(255,255,255,.24),
    0 8px 24px rgba(0,0,0,.34);
}
html.theme-space .kpi::before{
  width:100%;height:2px;left:0;top:0;bottom:auto;
  background:linear-gradient(90deg,var(--k-c,#6ba6e8),transparent 78%);
}
html.theme-space .kpi-val{font-size:20px;letter-spacing:-.4px;}
/* 2026-10-16 用户要求「KPI 与计数胶囊做成一行」：磨砂主题的 KPI 卡原本 padding 偏大
   （9/14/10/16），4 张卡 + 7 个胶囊在 1475px 内容宽下刚好占满、没有余量，
   这里略收一档，窗口稍窄也不至于折行。 */
html.theme-space .kpi{padding:8px 12px 9px 14px;}
html.theme-space .chip{border-radius:999px;background:rgba(255,255,255,.07);}

/* ---- 按钮：胶囊形；主按钮用饱和蓝（参考图那个高亮小键）---- */
html.theme-space .btn{
  border-radius:999px;padding:5px 14px;font-weight:600;
  background:rgba(255,255,255,.10);
  color:var(--ink);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.26),0 3px 10px rgba(0,0,0,.30);
}
html.theme-space .btn:hover{background:rgba(255,255,255,.19);color:#fff;}
html.theme-space .btn-primary{
  background:linear-gradient(180deg,rgba(64,132,222,.90),rgba(38,86,164,.92));
  color:#fff;border-color:rgba(255,255,255,.22);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.40),0 4px 16px rgba(28,72,142,.50);
}
html.theme-space .btn-primary:hover{
  background:linear-gradient(180deg,rgba(84,152,240,.94),rgba(50,104,190,.94));color:#fff;
}
/* 背景图按钮：胶囊形，与深空其它按钮同族；文件名太长会撑开顶栏，靠 .bg-name 的 ellipsis 收住 */
html.theme-space .bg-btn{
  border-radius:999px;padding:2px 10px;font-size:11.5px;font-weight:600;
  background:rgba(255,255,255,.10);
  color:var(--ink);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.26),0 2px 8px rgba(0,0,0,.28);
}
html.theme-space .bg-btn:hover{background:rgba(255,255,255,.19);color:#fff;}
html.theme-space .search-input,html.theme-space .inp{
  border-radius:999px;background:rgba(255,255,255,.10);
  border-color:rgba(255,255,255,.18);color:var(--ink);
}
html.theme-space .search-input:focus,html.theme-space .inp:focus{
  border-color:rgba(107,166,232,.70);
  box-shadow:0 0 0 3px rgba(107,166,232,.22);
}
html.theme-space .page-title{color:var(--ink);letter-spacing:.5px;}
html.theme-space .op-range{accent-color:var(--navy);}

/* ---- 滚动容器：深色玻璃 + 亮边环。
   ⚠ 不用 backdrop-filter：滚动容器上加全屏大半径模糊在 Chromium 下会
     滚动闪烁/闪回（已实测），故用「半透明深底 + box-shadow 环」代替。*/
html.theme-space .table-wrap,
html.theme-space .plan-scroll,
html.theme-space .tree-wrap{
  background:rgba(9,13,20,.46);
  box-shadow:
    var(--g-ring),
    inset 0 1px 0 rgba(255,255,255,.22),
    inset 0 0 20px rgba(0,0,0,.20),
    0 12px 34px rgba(0,0,0,.36);
}
/* ---- 弹窗：按参考图做 3 层景深。
   · 第 2 层 = 一级弹窗（.fmodal 窗体，如「新增附件记录」）：仍用 backdrop-filter 模糊，
     但比主界面更实、边框更亮，让它“浮”在软件主界面之上。
   · 第 3 层 = 二级弹窗（.modal 行编辑 / .confirm-box 确认框 / 各种下拉浮层）：
     最靠实、最亮边、阴影最大；.modal/.confirm-box 是滚动容器不能加 backdrop-filter，
     靠高不透明度 + 强 box-shadow 环实现“更近一层”的质感。
   ⚠ .fmodal 是 overflow:hidden（内容在 .fscroll 里滚）→ 伪元素不跑，可以照常 blur。*/
html.theme-space .modal,
html.theme-space .confirm-box{
  background:rgba(20,26,38,.95);          /* 第 3 层：最实 */
  border-radius:16px;
  box-shadow:
    0 0 0 1px rgba(255,255,255,.28),       /* 亮边更粗 */
    inset 0 1px 0 rgba(255,255,255,.42),
    inset 0 0 32px rgba(255,255,255,.06),
    0 32px 82px rgba(0,0,0,.74);
}
html.theme-space .fmodal{
  background:rgba(12,16,24,.86);           /* 第 2 层：比主界面实、比二级弹窗透 */
  border-radius:20px;
  backdrop-filter:blur(34px) saturate(170%);
  -webkit-backdrop-filter:blur(34px) saturate(170%);
  box-shadow:
    0 0 0 1px rgba(255,255,255,.20),
    inset 0 1px 0 rgba(255,255,255,.32),
    inset 0 0 44px rgba(255,255,255,.04),
    0 30px 78px rgba(0,0,0,.68);
}
html.theme-space .modal-mask{background:rgba(3,5,10,.70);} /* 压暗一点，让弹窗更突出 */
/* 第 2 层内部：fmodal 的顶栏/底栏/滚动区随 fmodal 一起更亮一点 */
html.theme-space .fhead{border-bottom-color:rgba(255,255,255,.18);}
html.theme-space .fbar,html.theme-space .ffoot{background:rgba(255,255,255,.08);}
html.theme-space .fscroll{background:rgba(255,255,255,.04);}
/* 第 3 层内部：确认框/行编辑小弹窗的标题栏/底栏/输入框更实 */
html.theme-space .modal-title{color:#fff;border-bottom-color:rgba(255,255,255,.18);}
html.theme-space .modal-body label{color:rgba(233,238,246,.70);}
html.theme-space .modal-body .field-tip{color:rgba(233,238,246,.54);}
html.theme-space .modal-foot{background:rgba(255,255,255,.10);border-top-color:rgba(255,255,255,.18);}
html.theme-space .modal-body input,html.theme-space .modal-body select{
  background:rgba(255,255,255,.13);color:var(--ink);border-color:rgba(255,255,255,.22);}
html.theme-space .modal-body input:focus,html.theme-space .modal-body select:focus{
  border-color:var(--navy);box-shadow:0 0 0 2px rgba(107,166,232,.24);}

/* ---- 表格：奇数行透明、偶数行一道隔行色（半透明白叠在深底上）---- */
html.theme-space table.grid tbody tr{background:transparent;}
html.theme-space table.grid tbody tr:nth-child(even){background:rgba(255,255,255,.038);}
html.theme-space table.grid tbody tr:hover{background:rgba(255,255,255,.085);}
html.theme-space table.grid tbody tr:nth-child(even):hover{background:rgba(255,255,255,.085);}
html.theme-space table.grid thead th{background:rgba(9,13,20,.86);color:var(--ink);}
html.theme-space table.grid.sheet-orders tbody tr:nth-child(odd),
html.theme-space table.grid.sheet-orders tbody tr:nth-child(even){background:var(--panel);}
html.theme-space table.grid.sheet-orders tbody tr:nth-child(even){background:var(--row-alt);}

/* ★★ 有背景图时，奇数行必须全透明 ——
   行底色是「并排的兄弟 tr」而不是叠层，理论上不会互相叠加，
   但排产表有 146 行 × 十几列，每格都刷一层白，实景会被铺成一片灰纱，
   背景图等于白设。所以保留「奇数行透明、只给偶数行上隔行色」的策略。*/
html.theme-space.has-bg table.grid tbody tr,
html.theme-space.has-bg table.grid.sheet-orders tbody tr:nth-child(odd),
html.theme-space.has-bg table.grid.sheet-orders tbody tr:nth-child(even){
  background:transparent;
}
html.theme-space.has-bg table.grid tbody tr:nth-child(even),
html.theme-space.has-bg table.grid.sheet-orders tbody tr:nth-child(even){
  background:rgba(255,255,255,.045);
}
/* 行悬停与选中仍要有反馈（背景图上尤其需要） */
html.theme-space.has-bg table.grid tbody tr:hover,
html.theme-space.has-bg table.grid tbody tr:nth-child(even):hover{background:rgba(107,166,232,.20);}
/* 表格容器本身也要压低不透明度，否则 wrap-bg 依然是第一道实心墙 */
html.theme-space.has-bg .table-wrap,
html.theme-space.has-bg .plan-scroll{background:rgba(9,13,20,.40);}
html.theme-space.has-bg table.grid thead th{background:rgba(8,12,20,.84);}
/* 有背景图时计划表表头再压一档（has-bg 只改颜色，不重写整条选择器） */
html.theme-space.has-bg{--pt-hd-bg:rgba(8,12,20,.88);--pt-sub-bg:rgba(18,25,38,.86);}

/* ---- 计划表 / 日历 / 树 / 目录浏览：深色玻璃 ---- */
html.theme-space .calendar-panel{background:rgba(20,26,38,.96);border-color:rgba(255,255,255,.26);box-shadow:0 14px 42px rgba(0,0,0,.65);}
html.theme-space .wf-dir{background:rgba(0,0,0,.42);}
html.theme-space .wf-row:hover{background:rgba(255,255,255,.10);}
html.theme-space .tree-label{color:var(--ink);}
html.theme-space .tree-label:hover{background:rgba(255,255,255,.12);}
html.theme-space .tree-label.active{background:rgba(107,166,232,.28);color:#fff;}

/* ---- 悬停浮层（订单表）= 第 3 层浮层 ---- */
html.theme-space .note-pop{
  --np-bg:rgba(20,26,38,.96); --np-fg:var(--ink); --np-fg2:rgba(233,238,246,.62);
  --np-line:rgba(255,255,255,.26);
  --np-head-bg:rgba(255,255,255,.10); --np-head-fg:var(--ink);
  --np-zebra:rgba(255,255,255,.03); --np-hover:rgba(255,255,255,.10);
  --np-bar-bg:rgba(255,255,255,.07); --np-bar-fg:var(--ink);
  border-color:rgba(255,255,255,.26);border-radius:14px;
  box-shadow:0 20px 52px rgba(0,0,0,.62);
}
html.theme-space .note-pop .seg-r{color:#ff9a8c;}
html.theme-space .note-pop .seg-g{color:#9db4ff;}

/* ===================================================================
   ⑦ 表格明细：提高照度 + 拉大隔行反差
   -------------------------------------------------------------------
   用户 2026-10-12 反馈：「所有表内明细显示不能太暗，隔行明显些」。
   改之前的实测差值（奇数行 vs 偶数行的底色亮度差）：
     商务蓝 3% / Win7 6% / 经典灰 5% / 暗夜 5% / 毛玻璃 2.5% / 深空 2.3%
   —— 都在「看得见但几乎等于没有」的区间，146 行的排产表尤其糊成一片。
   两手一起抓：① 容器底色提亮（治「暗」）② 奇偶差值翻三倍（治「不分明」）。

   ⚠ 本节必须放在文件**最末尾**：前面玻璃/深空那 200 多条覆盖规则里，
   有不少带 !important 的单元格底色（pt-kind / pt-edit / pt-gray），
   本节写在它们前面会被整段盖掉。
   =================================================================== */

/* ---------- 排产表：按「订单组」隔行，且**不能靠 nth-child** ----------
   ⚠⚠ 排产表每个订单是**两行**：tr1 = 计划、tr2 = 实际，左侧 A~T 列用 rowspan=2 纵向合并。
   如果用 `tr:nth-child(even)` 隔行，一个订单的计划行和实际行会落到不同组里 ——
   视觉上变成「上订单的实际行」紧贴「下订单的计划行」，比没有隔行更容易看错行。
   正确做法：一个订单的两行挂**同一个组 class**（pt-grp-a / pt-grp-b），计划行与实际行
   再各带 pt-plan / pt-actual 区分深浅：
     组A = tr.pt-grp-a.pt-plan 计划 / tr.pt-grp-a.pt-actual 实际
     组B = tr.pt-grp-b.pt-plan 计划 / tr.pt-grp-b.pt-actual 实际
   同一订单的两行永远同族，不会被劈开。

   ⚠⚠ 2026-10-13 为什么从 nth-child(4n+N) 改成显式 class：
   计划表已改成**窗口化渲染**，tbody 的第 1 个子元素是 .pt-spacer（撑高行，
   见 app.js 的 applyWindow/spTop/spBot），它同样被 nth-child 计数 →
   整条「4 行一组」的规律被顶偏一位，计划/实际两行的配对错乱；
   而且**滚动换窗后 spacer 数量会变**，同一订单滚到不同位置会显示不同底色。
   显式 class 由数据下标 `ix % 2` 决定（见 buildPair），与 DOM 位置、窗口边界彻底解耦。*/
.plan-tbl tbody tr.pt-grp-a.pt-plan td{background:var(--plan-odd);}
.plan-tbl tbody tr.pt-grp-a.pt-actual td{background:var(--plan-odd-act);}
.plan-tbl tbody tr.pt-grp-b.pt-plan td{background:var(--plan-even);}
.plan-tbl tbody tr.pt-grp-b.pt-actual td{background:var(--plan-even-act);}

/* ---------- 2026-10-13 用户要求：同一行的着色颜色一致 ----------
   改之前实测一行里有**4 种底色**（玻璃主题，行1 共 164 格）：
     rgba(255,255,255,.157) x149  主体数字格   ← 跟组色
     rgba(255,255,255,.16)  x8    pt-edit 可编辑格 ← 跟组色但差一档，看着像另一种颜色
     rgba(15,21,34,.97)     x6    左侧冻结列  ← 完全脱离组色的深色，横扫时像贴了条黑带
     rgb(227,236,249)       x1    pt-kind「计划/实际」标签格 ← 亮蓝，完全跳色
   一行本该是一条完整色带，现在成了拼贴。下面把 pt-gray / pt-kind / pt-edit / 冻结列
   **全部改为取所在行的组色**，一个格子都不再自带底色。
   · 灰格pt-gray：不再单独深一档，跟本行同色（它靠「文字为空」表达含义，不需要底色区分）
   · pt-kind   ：标签靠**文字**（计划/实际 + 蓝/绿字色）区分，底色并入行色
   · pt-edit   ：靠 hover 高亮 + 手型光标表达「可编辑」，底色并入行色
   · 冻结列    ：行色是半透明时（玻璃/深空）单靠它会横向滚动穿帮 →
                 改用预先压实的不透明版组色 --plan-*-op（每个主题各算一份），
                 观感与同行一致，且天然不透底。 */

/* 排程数据颜色标注：与原表一致 —— 计划有值=黄底，实际有值/镜像计划=灰底。
   固定 RGB（原表与主题无关）：黄 rgb(255,255,0) / 灰 rgb(217,217,217)。
   ⚠ 必须带 !important：`.pt-num.pt-val`/`.pt-num.actual.pt-gray`（前面已定义）特异性更低，
   且本组规则在文件更靠后，要靠 !important 才钉得住。 */
.plan-tbl tbody tr.pt-grp-a.pt-plan td.pt-val{background:#ffff00 !important;}
.plan-tbl tbody tr.pt-grp-a.pt-actual td.pt-gray{background:#d9d9d9 !important;}
.plan-tbl tbody tr.pt-grp-b.pt-plan td.pt-val{background:#ffff00 !important;}
.plan-tbl tbody tr.pt-grp-b.pt-actual td.pt-gray{background:#d9d9d9 !important;}

/* 标签格pt-kind：底色并入行色（原来按 plan/actual 各钉一个亮蓝/亮绿）
   ⚠ 原第 800/801 行带 !important，这里也必须带才钉得住。 */
.plan-tbl tbody tr.pt-grp-a.pt-plan td.pt-kind{background:var(--plan-odd)!important;}
.plan-tbl tbody tr.pt-grp-b.pt-plan td.pt-kind{background:var(--plan-even)!important;}
.plan-tbl tbody tr.pt-grp-a.pt-actual td.pt-kind.actual{background:var(--plan-odd-act)!important;}
.plan-tbl tbody tr.pt-grp-b.pt-actual td.pt-kind.actual{background:var(--plan-even-act)!important;}
/* 可编辑格：底色并入行色；「可编辑」改由 hover 高亮 + 光标（.pt-edit 第 838 行 cursor:pointer）表达 */
.plan-tbl tbody tr.pt-grp-a.pt-plan td.pt-edit{background:var(--plan-odd);}
.plan-tbl tbody tr.pt-grp-a.pt-actual td.pt-edit{background:var(--plan-odd-act);}
.plan-tbl tbody tr.pt-grp-b.pt-plan td.pt-edit{background:var(--plan-even);}
.plan-tbl tbody tr.pt-grp-b.pt-actual td.pt-edit{background:var(--plan-even-act);}
.plan-tbl tbody tr.pt-grp-a.pt-plan td.pt-edit:hover,
.plan-tbl tbody tr.pt-grp-a.pt-actual td.pt-edit:hover,
.plan-tbl tbody tr.pt-grp-b.pt-plan td.pt-edit:hover,
.plan-tbl tbody tr.pt-grp-b.pt-actual td.pt-edit:hover{
  background:var(--pt-edit-hi-bg);box-shadow:inset 0 0 0 2px var(--pt-edit-hi-ring);}

/* 冻结的左侧列：直接用**不透明版**组色（--plan-*-op）。
   position:sticky 的格子必须自带不透明底，否则横向滚动时右侧日产量会从底下透出来；
   而半透明组色直接当 background 用，透出的是「表格容器底色」而不是「页面底色」，
   与同一行其它格子（半透明叠在页面上）对不上 → 视觉上仍是两种颜色。
   所以每个主题都预先算好一份「压实后的组色」（over = 该主题 --plan-sci-under，
   色值 = under + (255-under)×alpha，alpha 就是组色那个 .155/.21/.075/.125）。 */
.plan-tbl tbody tr.pt-grp-a.pt-plan [data-sci]{background:var(--plan-odd-op,#fff);}
.plan-tbl tbody tr.pt-grp-a.pt-actual [data-sci]{background:var(--plan-odd-act-op,#fff);}
.plan-tbl tbody tr.pt-grp-b.pt-plan [data-sci]{background:var(--plan-even-op,#fff);}
.plan-tbl tbody tr.pt-grp-b.pt-actual [data-sci]{background:var(--plan-even-act-op,#fff);}

/* ---------- 深色系 ----------
   2026-10-13「同一行颜色一致」改造后：pt-kind / pt-edit / pt-gray / 冻结列
   **一律跟随所在行的组色**，各主题不再单独给它们钉底色 —— 之前这四条各钉各的，
   正是「一行四种颜色」的来源。深色下唯一需要单独处理的是冻结列的**不透明底**
   （--plan-*-op 已按主题给值，见上）。 */
/* hover 高亮**已由 --pt-edit-hi-bg / --pt-edit-hi-ring 承担**（2026-10-13）：
   基础规则 `.plan-tbl tbody td.pt-edit:hover` 直接读变量，
   原来这三行按主题各钉一份（dark #37424f / glass .22 / space .24）
   删掉即可 —— 差异已经表达在各主题的 --pt-edit-hi-bg 上。 */
/* ⚠ 这里**不要**再写 `html[data-theme="glass"] ... [data-sci]{...}` ——
   深空主题的 data-theme 就是 glass（靠 .theme-space 区分），
   在这里按 glass 设冻结列底色会把深空也一起改掉。
   冻结列统一交给上面的 --plan-*-op 变量。 */
/* 白色磨砂深空：data-theme 仍是 glass，直接复用 .plan-tbl 的基础隔行规则
   （var(--plan-odd)/--plan-even，已在变量块里改成白磨砂浅色），
   不再单独钉死半透明白 —— 否则在白色磨砂底上会整片消失。 */
html.theme-space .plan-tbl tbody tr.pt-grp-a.pt-plan td{background:var(--plan-odd);}
html.theme-space .plan-tbl tbody tr.pt-grp-a.pt-actual td{background:var(--plan-odd-act);}
html.theme-space .plan-tbl tbody tr.pt-grp-b.pt-plan td{background:var(--plan-even);}
html.theme-space .plan-tbl tbody tr.pt-grp-b.pt-actual td{background:var(--plan-even-act);}
/* 有背景图时，排产表同样让奇数组透明，只留偶数组的隔行色 */
html.theme-space.has-bg .plan-tbl tbody tr.pt-grp-a.pt-plan td,
html.theme-space.has-bg .plan-tbl tbody tr.pt-grp-b.pt-plan td{background:transparent;}

/* ---- 滚动条：深色玻璃上是**亮色**细条（原来深色主题遗留的 rgba(0,0,0,..)
   在近黑底上等于隐形），轨道用极淡白，滑块亮一档 + hover 再亮 ---- */
html.theme-space ::-webkit-scrollbar{width:11px;height:11px;}
html.theme-space ::-webkit-scrollbar-track{background:rgba(255,255,255,.045);}
html.theme-space ::-webkit-scrollbar-thumb{
  background:rgba(255,255,255,.22);border-radius:6px;
  border:2px solid transparent;background-clip:padding-box;}
html.theme-space ::-webkit-scrollbar-thumb:hover{background:rgba(255,255,255,.38);background-clip:padding-box;}


/* ==================================================================
   数据流页（2026-12 新增）
   为什么单独一节：本页要在**所有主题**下都清晰（深藏青 / 深空 / 毛玻璃），
   所以颜色一律走主题变量 + 类名，绝不在 JS 里写死十六进制。
   ================================================================== */
.flow-wrap{padding-bottom:24px;}

/* 数据流：表清单 / 依赖关系 表格（替代原手工排坐标的 SVG，按实际数据生成） */
.flow-table{border-collapse:separate;border-spacing:0;width:100%;max-width:1560px;font-size:12px;
  background:var(--panel);border:1px solid var(--line);border-radius:var(--r);overflow:hidden;margin-bottom:8px;}
.flow-table th{background:var(--pt-hd-bg);color:var(--pt-hd-fg);text-align:left;padding:6px 10px;font-weight:600;
  border-bottom:1px solid var(--line);white-space:nowrap;}
.flow-table td{padding:6px 10px;border-bottom:1px solid var(--line);vertical-align:top;}
.flow-table tr:last-child td{border-bottom:none;}
.flow-table .num{text-align:right;font-variant-numeric:tabular-nums;white-space:nowrap;}
.flow-table .ft-name{font-weight:700;color:var(--navy);}
html.theme-space .flow-table .ft-name{color:var(--ink);}
.flow-table .ft-entry{color:var(--muted);font-size:11.5px;line-height:1.5;white-space:nowrap;}
/* 2026-10-17 用户要求：说明精简后整行不换行；表名 / 数据入口 / 删除后果 也保持一行，
   省下的宽度由表格自动布局分给这些列（max-width 已放宽到 1560px）。 */
.flow-table .ft-name,.flow-table .ft-desc{white-space:nowrap;}
.flow-table .ft-warn,.flow-table .ft-ok{white-space:nowrap;}
.flow-table .ft-act{white-space:nowrap;}
.flow-table .ft-warn{color:#c0392b;font-weight:700;}
.flow-table .ft-ok{color:#0f6e56;font-weight:700;}
html.theme-space .flow-table .ft-ok{color:#3fbb92;}
.flow-table .ft-arrow{color:var(--muted);font-size:15px;text-align:center;width:30px;padding:6px 0;}
.flow-table .ft-back{background:rgba(127,119,221,.07);}
.fk-badge{display:inline-block;padding:1px 8px;border-radius:3px;font-size:11px;border:1px solid;}
.fk-badge.fk-src{background:rgba(15,110,86,.12);color:#0f6e56;border-color:#0f6e56;}
.fk-badge.fk-mas{background:rgba(83,74,183,.12);color:#534ab7;border-color:#534ab7;}
.fk-badge.fk-der{background:rgba(133,79,11,.12);color:#854f0b;border-color:#854f0b;}
.fk-badge.fk-view{background:rgba(61,143,196,.12);color:#2b6f9e;border-color:#2b6f9e;}
.fk-badge.fk-cfg,.fk-badge.fk-dyn{background:rgba(122,99,201,.12);color:#5b47a5;border-color:#5b47a5;}
html.theme-space .fk-badge.fk-src{color:#3fbb92;border-color:#3fbb92;}
html.theme-space .fk-badge.fk-mas{color:#a79ff0;border-color:#a79ff0;}
html.theme-space .fk-badge.fk-der{color:#e8a94f;border-color:#e8a94f;}
html.theme-space .fk-badge.fk-view{color:#82cdf0;border-color:#82cdf0;}
html.theme-space .fk-badge.fk-cfg,html.theme-space .fk-badge.fk-dyn{color:#b3a3f2;border-color:#b3a3f2;}
/* 明细表分组标题行（2026-10-16 用户要求按类型分组） */
.flow-table tr.ft-group td{background:var(--pt-hd-bg);color:var(--pt-hd-fg);
  padding:4px 10px;font-size:11.5px;font-weight:700;letter-spacing:.2px;
  border-bottom:1px solid var(--line);border-top:1px solid var(--line);}
.flow-table .ftg-dot{display:inline-block;width:8px;height:8px;border-radius:2px;margin-right:7px;vertical-align:middle;}
.ftg-src{background:#0f6e56;}
.ftg-mas{background:#534ab7;}
.ftg-der{background:#854f0b;}
.ftg-view{background:#3d8fc4;}
.ftg-cfg,.ftg-dyn{background:#7a63c9;}
.ftg-iso{background:transparent;border:1.4px dashed var(--muted);}
.flow-table tr.fk-row-der{box-shadow:inset 3px 0 0 0 #854f0b;}
.flow-table tr.fk-row-mas{box-shadow:inset 3px 0 0 0 #534ab7;}
.flow-table tr.fk-row-src{box-shadow:inset 3px 0 0 0 #0f6e56;}
html.theme-space .flow-table tr.fk-row-der{box-shadow:inset 3px 0 0 0 #e8a94f;}
html.theme-space .flow-table tr.fk-row-mas{box-shadow:inset 3px 0 0 0 #a79ff0;}
html.theme-space .flow-table tr.fk-row-src{box-shadow:inset 3px 0 0 0 #3fbb92;}

/* ---- 流程图（SVG，坐标按实际数据计算，不写死；深空/深色/浅色全自适应） ---- */
.fl-scroll{overflow:auto;background:var(--panel);border:1px solid var(--line);
  border-radius:var(--r);padding:6px 14px;margin-bottom:10px;}
.fl-svg{display:block;transition:opacity .15s;}
.fl-svg.fl-dim .fl-edge{opacity:.18;}
.fl-svg.fl-dim .fl-arrow{opacity:.18;}
.fl-svg.fl-dim .fl-lbl-bg{opacity:.22;}
.fl-svg.fl-dim .fl-lbl{opacity:.32;}
.fl-edge{fill:none;stroke:var(--fl-edge,#5b6b7e);stroke-width:2;opacity:.92;transition:opacity .15s,stroke-width .15s;}
.fl-arrow{fill:var(--fl-edge,#5b6b7e);stroke:none;opacity:.92;transition:opacity .15s;}
.fl-back{stroke:var(--fl-back,#c0392b);stroke-dasharray:6 4;opacity:1;}
.fl-arrow.fl-back{fill:var(--fl-back,#c0392b);}
/* 弱关系边（只读关联：收退货↔采购 / 附件↔库存 / 替代料↔树形BOM）——
   灰蓝细虚线，视觉上明显弱于主流程的顺流 / 回写边（2026-10-16 数据流优化） */
.fl-edge.fl-weak{stroke:var(--fl-weak,#7d8ea3);stroke-width:1.6;stroke-dasharray:3 4;opacity:.8;}
.fl-arrow.fl-weak{fill:var(--fl-weak,#7d8ea3);opacity:.8;}
.fl-lbl.fl-weak{fill:var(--fl-weak,#66788c);font-weight:500;}
.fl-lbl-bg.fl-weak{fill:var(--fl-lbl-bg,#fff);stroke:rgba(125,142,163,.45);}
.fl-edge.fl-active{stroke-width:3.2;opacity:1;z-index:1;}
.fl-arrow.fl-active{opacity:1;transform:scale(1.1);transform-origin:center;}
.fl-lbl{font:500 12.5px var(--font);fill:var(--fl-text,#1b2430);pointer-events:none;}
.fl-lbl.fl-back{fill:var(--fl-back,#c0392b);}
.fl-lbl-bg{fill:var(--fl-lbl-bg,#fff);stroke:var(--line);stroke-width:1;opacity:.98;pointer-events:none;}
.fl-lbl-bg.fl-back{fill:#fff0f0;stroke:rgba(192,57,43,.45);}
.fl-lbl-bg.fl-active{filter:drop-shadow(0 2px 4px rgba(0,0,0,.18));opacity:1;}
.fl-lbl.fl-active{font-weight:700;}
.fl-node .fl-rect{stroke-width:1.8;transition:filter .15s,stroke-width .15s;filter:drop-shadow(0 2px 3px rgba(0,0,0,.08));}
.fl-node:hover .fl-rect{filter:drop-shadow(0 4px 8px rgba(0,0,0,.14));stroke-width:2.4;}
.fl-title{font:600 13.5px var(--font);fill:var(--fl-text,#1b2430);}
.fl-sub{font:400 11.5px var(--font);fill:var(--fl-sub,#44596e);}
/* 节点按类型配色（浅色主题） */
.fl-node.src .fl-rect{fill:var(--fl-src,#e8f0fb);stroke:var(--fl-src-b,#4a78c4);}
.fl-node.mas .fl-rect{fill:var(--fl-mas,#fff3e0);stroke:var(--fl-mas-b,#d9933a);}
.fl-node.der .fl-rect{fill:var(--fl-der,#e9f7ee);stroke:var(--fl-der-b,#2f9e57);stroke-dasharray:6 3;}
/* 派生视图（只读，不落库：计划表 / 订单价格明细）—— 青蓝点线，和绿虚线的派生表区分开 */
.fl-node.view .fl-rect{fill:#e4f2fa;stroke:#3d8fc4;stroke-dasharray:2 3;}
.fl-node.dyn .fl-rect,.fl-node.cfg .fl-rect{fill:#efeafa;stroke:#7a63c9;stroke-dasharray:2 3;}
/* 深空 / 玻璃主题覆盖 */
html.theme-space .fl-edge,html[data-theme="glass"] .fl-edge{stroke:rgba(200,215,235,.62);}
html.theme-space .fl-arrow,html[data-theme="glass"] .fl-arrow{fill:rgba(200,215,235,.62);}
html.theme-space .fl-back,html[data-theme="glass"] .fl-back{stroke:rgba(255,150,140,.95);}
html.theme-space .fl-arrow.fl-back,html[data-theme="glass"] .fl-arrow.fl-back{fill:rgba(255,150,140,.95);}
html.theme-space .fl-lbl,html[data-theme="glass"] .fl-lbl{fill:#eaf0f8;}
html.theme-space .fl-lbl-bg,html[data-theme="glass"] .fl-lbl-bg{fill:rgba(18,26,40,.96);stroke:rgba(255,255,255,.12);}
html.theme-space .fl-lbl-bg.fl-back,html[data-theme="glass"] .fl-lbl-bg.fl-back{fill:rgba(60,25,25,.96);stroke:rgba(255,150,140,.55);}
html.theme-space .fl-title,html[data-theme="glass"] .fl-title{fill:#eaf0f8;}
html.theme-space .fl-sub,html[data-theme="glass"] .fl-sub{fill:rgba(220,230,245,.72);}
html.theme-space .fl-node.src .fl-rect,html[data-theme="glass"] .fl-node.src .fl-rect{fill:rgba(90,130,200,.18);stroke:rgba(150,190,255,.78);}
html.theme-space .fl-node.mas .fl-rect,html[data-theme="glass"] .fl-node.mas .fl-rect{fill:rgba(210,150,90,.18);stroke:rgba(255,200,140,.82);}
html.theme-space .fl-node.der .fl-rect,html[data-theme="glass"] .fl-node.der .fl-rect{fill:rgba(80,200,140,.16);stroke:rgba(150,240,190,.82);}
html.theme-space .fl-node.view .fl-rect,html[data-theme="glass"] .fl-node.view .fl-rect{fill:rgba(70,170,220,.16);stroke:rgba(150,220,255,.8);}
html.theme-space .fl-node.dyn .fl-rect,html[data-theme="glass"] .fl-node.dyn .fl-rect,
html.theme-space .fl-node.cfg .fl-rect,html[data-theme="glass"] .fl-node.cfg .fl-rect{fill:rgba(150,130,230,.16);stroke:rgba(200,190,255,.8);}
/* 弱关系边在深空 / 玻璃下必须重新定义，否则会被上面 html.theme-space .fl-edge 的浅色覆盖 */
html.theme-space .fl-edge.fl-weak,html[data-theme="glass"] .fl-edge.fl-weak{stroke:rgba(180,198,222,.44);stroke-width:1.6;stroke-dasharray:3 4;}
html.theme-space .fl-arrow.fl-weak,html[data-theme="glass"] .fl-arrow.fl-weak{fill:rgba(180,198,222,.44);}
html.theme-space .fl-lbl.fl-weak,html[data-theme="glass"] .fl-lbl.fl-weak{fill:rgba(206,220,238,.66);}
html.theme-space .fl-lbl-bg.fl-weak,html[data-theme="glass"] .fl-lbl-bg.fl-weak{fill:rgba(18,26,40,.96);stroke:rgba(180,200,225,.3);}
html.theme-space .fl-node .fl-rect,html[data-theme="glass"] .fl-node .fl-rect{filter:drop-shadow(0 2px 4px rgba(0,0,0,.22));}
html.theme-space .fl-node:hover .fl-rect,html[data-theme="glass"] .fl-node:hover .fl-rect{filter:drop-shadow(0 5px 12px rgba(0,0,0,.35));}
/* 独立表（不参与 MRP 主流程）虚线框 + 顶部标注：把 substitute / receipt / attachments
   与主流程的源数据列区分开（2026-10-14 数据流优化） */
.fl-iso-frame{fill:none;stroke:var(--muted);stroke-width:1.4;stroke-dasharray:6 5;opacity:.7;}
.fl-iso-cap{font:600 11.5px var(--font);fill:var(--muted);}
html.theme-space .fl-iso-frame,html[data-theme="glass"] .fl-iso-frame{stroke:rgba(200,215,235,.5);opacity:.85;}
html.theme-space .fl-iso-cap,html[data-theme="glass"] .fl-iso-cap{fill:rgba(220,230,245,.72);}

/* 2026-10-17 数据流更清晰（用户要求「显示更完整更清晰明了」）：
   ① 节点 hover = 高亮全部上下游连线/对端节点，其余变淡。
      ⚠ .fl-svg.fl-dim .fl-edge (0,3,0) 比 .fl-edge.fl-active (0,2,0) 特异性高，
      不补这组规则的话「高亮的那条」也会被一起淡掉（连原先的连线 hover 也有此隐患）。 */
.fl-svg.fl-dim .fl-edge.fl-active{opacity:1;}
.fl-svg.fl-dim .fl-arrow.fl-active{opacity:1;}
.fl-svg.fl-dim .fl-lbl-bg.fl-active{opacity:1;}
.fl-svg.fl-dim .fl-lbl.fl-active{opacity:1;}
.fl-svg.fl-nodedim .fl-node{opacity:.26;transition:opacity .15s;}
.fl-svg.fl-nodedim .fl-node.fl-on{opacity:1;}
.fl-node.fl-on .fl-rect{stroke-width:2.8;}
/* ② 表明细行 ↔ 图节点双向联动 */
.flow-table tr.ft-hl td,.flow-table tr.ft-hl th{background:var(--row-hover);}
/* ③ 表明细新加的「说明」列 */
.flow-table .ft-desc{color:var(--muted);font-size:11.5px;line-height:1.5;}

/* 图例：实线 / 红虚线 用一小段线表示 */
.lg-edge::before{width:20px;height:0;border:0;border-top:2px solid var(--muted);border-radius:0;background:transparent;}
.lg-back::before{width:20px;height:0;border:0;border-top:2px dashed var(--red);border-radius:0;background:transparent;}
.lg-weak::before{width:20px;height:0;border:0;border-top:2px dashed #7d8ea3;border-radius:0;background:transparent;}
.lg-iso::before{border-style:dashed;border-color:var(--muted);background:transparent;}

/* ---- 图例 ---- */
.flow-legend{display:flex;gap:16px;flex-wrap:wrap;margin:0 0 4px;font-size:11.5px;color:var(--muted);}
.flow-legend .lg{display:inline-flex;align-items:center;gap:6px;}
.flow-legend .lg::before{content:"";width:16px;height:11px;border-radius:3px;border:1.2px solid;display:inline-block;}
.lg-src::before{background:#e1f5ee;border-color:#0f6e56;}
.lg-mas::before{background:#eeedfe;border-color:#534ab7;}
.lg-der::before{background:#faeeda;border-color:#854f0b;border-style:dashed;}
.lg-view::before{background:#e4f2fa;border-color:#3d8fc4;border-style:dotted;}
.lg-cfg::before{background:#efeafa;border-color:#7a63c9;border-style:dotted;}
.lg-dyn::before{background:#efeafa;border-color:#7a63c9;border-style:dotted;}
/* ---- 表卡片 ---- */
.flow-cards{display:grid;grid-template-columns:repeat(auto-fill,minmax(330px,1fr));gap:9px;}
.flow-card{
  background:var(--panel);border:1px solid var(--line);border-left:3px solid var(--muted);
  border-radius:var(--r);padding:9px 11px;
}
.flow-card.fk-src{border-left-color:#0f6e56;}
.flow-card.fk-mas{border-left-color:#534ab7;}
.flow-card.fk-der{border-left-color:#854f0b;}
/* 参数配置(config) / 动态生成(dynamic) 配色 */
.fl-node.cfg .fl-rect{fill:#e6f1f8;stroke:#1f7a9e;}
.fl-node.dyn .fl-rect{fill:#fbe9f3;stroke:#b83280;}
.fk-badge.fk-cfg{background:rgba(31,122,158,.12);color:#1f7a9e;border-color:#1f7a9e;}
.fk-badge.fk-dyn{background:rgba(184,50,128,.12);color:#b83280;border-color:#b83280;}
.lg-cfg::before{background:#e3f1f7;border-color:#1f7a9e;}
.lg-dyn::before{background:#fbe9f3;border-color:#b83280;}
.flow-card.fk-cfg{border-left-color:#1f7a9e;}
.flow-card.fk-dyn{border-left-color:#b83280;}
html.theme-space .fl-node.cfg .fl-rect,html[data-theme="glass"] .fl-node.cfg .fl-rect{fill:rgba(90,160,210,.18);stroke:rgba(150,200,255,.8);}
html.theme-space .fl-node.dyn .fl-rect,html[data-theme="glass"] .fl-node.dyn .fl-rect{fill:rgba(200,120,180,.18);stroke:rgba(240,160,210,.82);}
html.theme-space .fk-badge.fk-cfg,html[data-theme="glass"] .fk-badge.fk-cfg{border-color:#6fc6e8;color:#6fc6e8;}
html.theme-space .fk-badge.fk-dyn,html[data-theme="glass"] .fk-badge.fk-dyn{border-color:#e98fc7;color:#e98fc7;}
html.theme-space .lg-cfg::before,html[data-theme="glass"] .lg-cfg::before{background:rgba(31,122,158,.3);border-color:#6fc6e8;}
html.theme-space .lg-dyn::before,html[data-theme="glass"] .lg-dyn::before{background:rgba(184,50,128,.3);border-color:#e98fc7;}
html.theme-space .flow-card.fk-cfg,html[data-theme="glass"] .flow-card.fk-cfg{border-left-color:#6fc6e8;}
html.theme-space .flow-card.fk-dyn,html[data-theme="glass"] .flow-card.fk-dyn{border-left-color:#e98fc7;}
.flow-card-h{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:5px;}
.flow-card-t{font-size:12.5px;font-weight:700;color:var(--navy);}
.flow-card-n{font-size:11px;color:var(--muted);font-variant-numeric:tabular-nums;}
.flow-card-k{font-size:10.5px;border:1px solid var(--line);border-radius:3px;padding:0 6px;color:var(--muted);}
.flow-card-d{font-size:11.5px;line-height:1.6;color:var(--ink);opacity:.88;margin-bottom:6px;}
.flow-card-e{font-size:11px;line-height:1.55;color:var(--muted);margin-bottom:7px;}
.flow-card-el{color:var(--navy);font-weight:700;margin-right:5px;}
.flow-card-a{display:flex;gap:6px;flex-wrap:wrap;}

/* ---- 备份清单 ---- */
.flow-backups{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:6px;}
.flow-bk{background:var(--panel);border:1px solid var(--line);border-radius:var(--r);
  padding:6px 10px;display:flex;justify-content:space-between;align-items:center;gap:8px;}
.flow-bk-n{font-size:11.5px;color:var(--ink);font-family:Consolas,"Courier New",monospace;}
/* 连线标签的衬托底：浅色用纯白、深色用面板色，保证压在连线上也读得清 */
.flow-lb-bg{fill:#ffffff;opacity:.96;}
.flow-leader{fill:none;stroke:var(--muted);stroke-width:.8;stroke-dasharray:3 3;opacity:.6;}

/* ==================================================================
   BOM 缺失提示条（2026-10-12 新增；原在订单表页，同日按用户要求挪到树形BOM表页顶部）
   用户要求：「订单上没有完成的料号，树状BOM没有对应的料号，需要进行提示」。
   原来只有操作面板里一个「无BOM的产品」按钮，要用户自己点才会看到；
   现在一进树形BOM表就自动提示，未完成/已完成分开计数。
   配色走琥珀（提醒）→ 红（有未完成缺BOM，会阻碍排产）两档，
   全部用主题变量，深色主题下另提亮，避免深底压暗字。
   ================================================================== */
.bom-miss{
  display:flex;align-items:center;gap:8px;flex-wrap:wrap;
  margin:0 0 8px;padding:8px 11px;border-radius:var(--r);
  background:#fdf3e3;border:1px solid #ecc98f;border-left:3px solid #c8871f;
  font-size:12px;color:#5c4310;line-height:1.5;
}
.bom-miss.is-crit{
  background:#fdeceb;border-color:#f0b4ae;border-left-color:#b3261e;color:#7a1a14;
}
.bom-miss-ico{font-size:14px;line-height:1;flex:none;}
.bom-miss-tx{font-weight:400;}
.bom-miss-tx b{font-weight:700;}
.bom-miss-sub{opacity:.78;margin-left:2px;}
.bom-miss-act{opacity:.9;}
.bom-miss-btn{margin-left:auto;flex:none;}

/* 明细表里「有未完成订单」的行：整行标红底，一眼看出必须补的 */
.grid tbody tr.row-crit td{background:#fdeceb;}
.grid tbody tr.row-crit:hover td{background:#fbdcd9;}

/* ---- 深色两主题：底色改半透明、文字提亮 ---- */
/* ---- 可复制单元格（2026-10-13 用户要求：缺件明细窗的料号要能复制）----
   单击即复制：虚线下划 + 手型光标 + 悬停微高亮，一眼能看出"这里能点"。
   不能用 user-select:none（那会连手动框选都禁掉，用户仍要能拖选复制）。*/
.cp-cell{
  cursor:copy;
  border-bottom:1px dashed currentColor;
  padding-bottom:1px;
  border-radius:2px;
  transition:background .12s ease;
}
.cp-cell:hover{background:rgba(60,120,200,.14);}
.cp-cell:active{background:rgba(60,120,200,.26);}
.grid tbody tr.row-crit .cp-cell{font-weight:600;}

/* ==================================================================
   排程色块「倒角 + 金属质感」（2026-10-13，胶囊→倒角 / 玻璃→金属）
   ------------------------------------------------------------------
   分段规则（class 由 app.js 的 segOf() 打，见 buildPair）：
     pt-cap-s  段长 1 天  → 四角倒角，一块独立金属牌
     pt-cap-l  段首       → 只有左端倒角
     pt-cap-m  段中       → 直角（必须直角，相邻块才能无缝接成一条）
     pt-cap-r  段尾       → 只有右端倒角
   计划行（黄/蓝/绿三态）与实际行（灰）同一套处理，颜色规则一个字没动。

   ⚠⚠ 为什么只改 border-radius / border-color / box-shadow、**绝不碰 background** ——
     三态底色是原表固定的 RGB（超期黄 #ffff00 / 按期蓝 #2b6bc0 / 提前绿 #3ddc97 /
     实际灰 #d9d9d9），散落在文件前面 4 处 `background:...!important` 上。
     一旦用 background 简写去叠渐变，那 4 条整条被清掉 → 原表口径直接跑偏。
     box-shadow 不属于 background 简写的管辖区，照样能叠出「顶棱镜面高光 + 抛光反射
     + 底棱暗边 + 厚度描边」的金属感，且完全不惊动底色。这是本改造能在不动算法的
     前提下成立的唯一原因。

   ⚠ 金属 vs 玻璃的分水岭在「衰减距离」：
     玻璃 = 大面积柔和散射（inset 0 5px 7px -3px 这种 spread 远大于 blur 的写法）；
     金属 = 高光必须**锐利且快速收干**（blur 1px、负 spread 立刻掐断）+ 明暗对比硬。
     所以下面每条高光的 -spread 都等于或大于 blur，亮带不会糊满整格。

   ⚠ 为什么 border-right 必须 transparent：
     .plan-tbl 是 border-collapse:separate + border-spacing:0，相邻格的背景本来就严丝合缝，
     但**每格各自画 1px 右边框**。直角时看不出来，一改圆角这 1px 就会在长条中间切一刀，
     直接断成两截。separate 模式下边框不共享，各自设 transparent 一定生效
     （换成 collapse 模式就会被邻格的实色边框覆盖 —— 幸好本表是 separate）。

   ⚠ border-bottom 保留不动（组间那条 2px 粗线要贯通到右侧排产区，用户明确要求过），
     只把颜色换成半透明黑 —— 在黄/蓝/绿/灰任一底色上都读作「金属块下沿的暗棱」。

   ⚠ 侧棱（--m-l / --m-r，左右 1px 竖向高光/暗边）**只给端点格**：
     段中格一旦画竖棱，长条内部就会冒出一条竖线，等于把一条金属牌切成好几块。
     所以 pt-cap-m 只吃 --metal，不吃侧棱 —— 这是无缝长条成立的关键。

   ⚠ 圆角写 5px（倒角感）而不是 999px（胶囊）：CSS 里 999px 会被自动钳制到短边一半，
     于是无论行高多少都恒等于「半圆」。用户要的是小弧度的倒角，就必须给实数值。
     要整体调弧度只改 --cap-r 一处。
   ================================================================== */
.plan-tbl tbody td.pt-num.pt-val,
.plan-tbl tbody td.pt-num.actual.pt-gray{
  --cap-r:5px;
  /* 金属本体六层：①顶棱镜面高光 ②紧贴的次高光 ③上半抛光反射 ④下半背光 ⑤底棱暗线 ⑥厚度描边 */
  --metal:
    inset 0 1px 0 rgba(255,255,255,.92),
    inset 0 2px 1px -1px rgba(255,255,255,.55),
    inset 0 8px 8px -8px rgba(255,255,255,.34),
    inset 0 -8px 8px -8px rgba(0,0,0,.20),
    inset 0 -1px 0 rgba(0,0,0,.40),
    inset 0 0 0 1px rgba(0,0,0,.13);
  --m-l:inset 1px 0 0 rgba(255,255,255,.38);
  --m-r:inset -1px 0 0 rgba(0,0,0,.20);
  border-right-color:transparent;
  border-bottom-color:rgba(0,0,0,.30);
  box-shadow:var(--metal);
}
.plan-tbl tbody td.pt-num.pt-cap-s{border-radius:var(--cap-r);}
.plan-tbl tbody td.pt-num.pt-cap-l{border-radius:var(--cap-r) 0 0 var(--cap-r);}
.plan-tbl tbody td.pt-num.pt-cap-m{border-radius:0;}
.plan-tbl tbody td.pt-num.pt-cap-r{border-radius:0 var(--cap-r) var(--cap-r) 0;}

/* 端点格补侧棱（段中格不补，见上方说明）。
   ⚠ 这三条的特异性必须与上面「--metal 默认值」那条打平（同为 .plan-tbl+tbody+td+2 类），
     靠**文件位置更靠后**胜出 —— 写成 .pt-cap-s 单类会被上面两条类的规则压掉。 */
.plan-tbl tbody td.pt-num.pt-cap-s{box-shadow:var(--metal),var(--m-l),var(--m-r);}
.plan-tbl tbody td.pt-num.pt-cap-l{box-shadow:var(--metal),var(--m-l);}
.plan-tbl tbody td.pt-num.pt-cap-r{box-shadow:var(--metal),var(--m-r);}

/* 可编辑格 hover：整组金属层必须重写一遍 —— box-shadow 是整条覆盖的，
   写少了金属层会在 hover 时整片消失（只剩默认态）。只把厚度描边换成高亮环。 */
.plan-tbl tbody td.pt-num.pt-edit.pt-val:hover,
.plan-tbl tbody td.pt-num.pt-edit.actual.pt-gray:hover{
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.98),
    inset 0 2px 1px -1px rgba(255,255,255,.62),
    inset 0 8px 8px -8px rgba(255,255,255,.40),
    inset 0 -8px 8px -8px rgba(0,0,0,.18),
    inset 0 -1px 0 rgba(0,0,0,.38),
    inset 0 0 0 2px var(--pt-edit-hi-ring);
}

/* ===================================================================
   ★★★ 深空主题 → 白色磨砂玻璃（2026-10-15 用户选定「整个主题改白磨砂」）
   -------------------------------------------------------------------
   参考图是 iOS 白色磨砂：浅蓝柔光背景 + 半透明白玻璃卡片 + 柔和阴影。
   本块把 theme-space 从「近黑玻璃」整体换成「白色磨砂玻璃」，覆盖前面所有深色规则。

   为什么必须放在**文件最末尾**：
     前面 theme-space 那 100 多条深色硬编码（以及与 dark/glass 合写的流程图规则）
     分散在各处，且部分与其它主题合写在同一条选择器里。CSS 只认「同特异性比位置」，
     所以把整段光色覆盖写在最后，用同特异性的 html.theme-space 选择器逐条压过去，
     避免去改那 100 多条（改一处漏一处，且会误伤 dark/glass 两个主题）。

   保持的 3 层景深（与上一轮一致）：
     第 1 层主界面最透 / 第 2 层 .fmodal 中等 / 第 3 层确认框+下拉最实、最亮、阴影最大。
   =================================================================== */
html.theme-space{
  /* 文字 / 线 */
  --navy:#1f3864; --navy-2:#2a4a82; --navy-soft:#e8edf5;
  --ink:#1e2733; --muted:#5d6a7d;
  --line:rgba(31,56,100,.20); --line-2:rgba(31,56,100,.13);

  /* 底：浅蓝柔光环境光（参考图的色调）+ 近白底 */
  --bg:
    radial-gradient(1100px 780px at 12% 6%,rgba(150,190,240,.30),transparent 62%),
    radial-gradient(940px 680px at 90% 10%,rgba(200,180,240,.22),transparent 64%),
    radial-gradient(900px 700px at 84% 94%,rgba(150,215,215,.20),transparent 66%),
    #eaf0f8;

  /* 面板 / 表格 / 弹窗底：半透明白（必须半透，backdrop-filter 才透得出） */
  --panel:rgba(255,255,255,.68);
  --wrap-bg:rgba(255,255,255,.74);
  --modal-bg:rgba(255,255,255,.82);
  --row-alt:rgba(31,56,100,.05);
  --row-hover:rgba(31,56,100,.09);
  --cell-hover:rgba(31,56,100,.12);

  /* 排产表隔行组色（浅色磨砂）。
     ⚠ 2026-10-15 用户反馈「其他列滚动时透明度太高」：非冻结列用半透明底，背景图透过来
       数字发虚、且与冻结列(不透明)对不上。这里加实到接近不透明（~.88），
       既解决可读性/一致性，又保留一点磨砂质感（与背景图观感一致）。 */
  --plan-odd:rgba(255,255,255,.88);  --plan-odd-act:rgba(244,249,245,.86);
  --plan-even:rgba(219,231,248,.88); --plan-even-act:rgba(214,232,220,.86);
  /* 冻结列不透明版组色（position:sticky 必须自带实底，否则横向滚动穿帮） */
  --plan-odd-op:#ffffff;   --plan-odd-act-op:#f1f7f3;
  --plan-even-op:#e2ebf8;  --plan-even-act-op:#dbeade;
  --plan-sci-under:#ffffff;
  --cap-sep-line:rgba(31,56,100,.26);

  /* 侧栏 / 菜单：浅色玻璃 */
  --sidebar-bg:rgba(255,255,255,.60);
  --sidebar-fg:#1e2733; --sidebar-fg-dim:rgba(30,39,51,.62);
  --sidebar-line:rgba(31,56,100,.14);
  --nav-hover:rgba(255,255,255,.55); --nav-active:rgba(255,255,255,.85);
  --nav-line:rgba(31,56,100,.16); --nav-line-hi:rgba(31,56,100,.34); --nav-bg:rgba(255,255,255,.34);

  /* 图表配色（浅底用深一点的，亮色在白底上看不清） */
  --c1:#2a6fb5; --c2:#2f8f62; --c3:#c07d12;
  --c4:#7a5aa8; --c5:#2a8fa8; --c6:#c0392b;
  --chart-track:rgba(31,56,100,.10);
  --chart-sel-bg:rgba(42,111,181,.13); --chart-hit-bg:rgba(42,111,181,.07);

  --thead-bg:rgba(255,255,255,.80); --thead-fg:#1f3864; --thead-line:rgba(31,56,100,.14);
  --btn-bg:rgba(255,255,255,.78); --btn-fg:#1e2733;
  --btn-line:rgba(31,56,100,.20); --btn-hover-bg:rgba(255,255,255,.95);
  --foot-bg:rgba(255,255,255,.55);
  --form-head-bg:rgba(255,255,255,.62); --form-head-fg:#1f3864;
  --red:#c0392b; --green:#2f8f62; --amber:#c07d12;
  --win-shadow:0 24px 60px rgba(31,56,100,.22);
  --win-border:rgba(255,255,255,.70);

  /* 计划表 / 日历小表（--pt-*）浅色 */
  --pt-scroll-bg:rgba(255,255,255,.60);
  --pt-cell-bg:rgba(255,255,255,.55);
  --pt-grid:rgba(31,56,100,.16);
  --pt-hd-bg:rgba(255,255,255,.82);--pt-hd-fg:#1f3864;--pt-hd-line:rgba(31,56,100,.14);
  --pt-sub-bg:rgba(238,243,251,.86);--pt-sub-fg:#1f3864;
  --pt-val-bg:rgba(255,255,255,.80);--pt-val-fg:#1f3864;
  --pt-param-bg:rgba(43,71,120,.92);--pt-param-fg:#dbe4f2;
  --pt-edit-hd-bg:rgba(51,80,127,.92);--pt-edit-hd-fg:#ffffff;
  --pt-edit-bg:rgba(244,248,255,.85);--pt-edit-fg:#1f3864;
  --pt-edit-hi-bg:rgba(219,231,250,.9);--pt-edit-hi-ring:#8fb4e8;
  --pt-wkend-bg:rgba(120,75,75,.55);--pt-wkend-fg:#ffe3e3;
  --pt-workday-bg:rgba(232,245,233,.85);--pt-workday-fg:#2e7d32;
  --pt-holiday-bg:rgba(217,217,217,.7);--pt-holiday-fg:#5a5a5a;
  --pt-num-fg:#1f3864;--pt-num-act-fg:#4a6b3f;
  --pt-kind-fg:#1f3864;--pt-kind-act-fg:#3f5a3f;
  --pt-calc-fg:#31507f;
  --pt-late-fg:#c0392b;
  --pt-dirty:#e08b2f;--pt-dirty-fg:#b45309;
  --pt-group-line:rgba(31,56,100,.26);
  --pt-inline-bg:#ffffff;--pt-inline-fg:#1f3864;--pt-inline-line:#8fb4e8;
  --pt-cal-cell-bg:rgba(255,255,255,.7);--pt-cal-cell-fg:#20293a;--pt-cal-cell-line:rgba(31,56,100,.18);
  --pt-cal-label-fg:#1f3864;
  --pt-cal-hi-bg:rgba(240,245,252,.9);--pt-cal-hi-line:#8fb4e8;

  /* 玻璃棱边 --g-*（被 glass 的 ::after / panel box-shadow 引用）：
     白磨砂上要「亮白为主、下/右沿收一点淡灰蓝」，不能沿用深空的近黑下沿。 */
  --g-edge:linear-gradient(160deg,
    rgba(255,255,255,.92) 0%,rgba(255,255,255,.55) 26%,
    rgba(255,255,255,.34) 52%,rgba(31,56,100,.10) 78%,rgba(31,56,100,.16) 100%);
  --g-edge-hi:linear-gradient(160deg,
    rgba(255,255,255,1) 0%,rgba(255,255,255,.72) 26%,
    rgba(255,255,255,.42) 52%,rgba(31,56,100,.12) 78%,rgba(31,56,100,.18) 100%);
  --g-edge-sm:linear-gradient(160deg,
    rgba(255,255,255,.82) 0%,rgba(255,255,255,.48) 30%,
    rgba(255,255,255,.30) 60%,rgba(31,56,100,.10) 100%);
  --g-edge-sm-hi:linear-gradient(160deg,
    rgba(255,255,255,.95) 0%,rgba(255,255,255,.66) 30%,
    rgba(255,255,255,.40) 60%,rgba(31,56,100,.10) 100%);
  --g-edge-on:linear-gradient(160deg,
    rgba(255,255,255,1) 0%,rgba(255,255,255,.62) 40%,rgba(255,255,255,.44) 100%);
  --g-edge-pri:linear-gradient(160deg,
    rgba(255,255,255,.88) 0%,rgba(255,255,255,.52) 34%,rgba(255,255,255,.30) 100%);
  --g-edge-kpi:linear-gradient(160deg,
    rgba(255,255,255,.86) 0%,rgba(255,255,255,.48) 30%,
    rgba(255,255,255,.28) 58%,rgba(31,56,100,.10) 100%);
  --g-edge-kpi-hi:linear-gradient(160deg,
    rgba(255,255,255,1) 0%,rgba(255,255,255,.66) 30%,
    rgba(255,255,255,.38) 58%,rgba(31,56,100,.10) 100%);
  --g-edge-ico:linear-gradient(160deg,
    rgba(255,255,255,.92) 0%,rgba(255,255,255,.54) 34%,rgba(255,255,255,.32) 100%);
  --g-edge-ico-hi:linear-gradient(160deg,
    rgba(255,255,255,1) 0%,rgba(255,255,255,.72) 34%,rgba(255,255,255,.40) 100%);
  --g-ring:0 -1px 0 0 rgba(255,255,255,.40),
          0 1px 0 0 rgba(31,56,100,.14);
  --g-lit:rgba(255,255,255,.90); --g-lit-soft:rgba(255,255,255,.55);
  --g-inner:rgba(255,255,255,.28); --g-shade:rgba(31,56,100,.10);
}

/* ---- 背景图层：白色磨砂要把照片「提亮」而不是压暗 ----
   前面 #bgLayer::after 是通用暗色压幕；浅色主题（blue/win7/classic）另有一段浅色柔光，
   深空当时走暗压幕。现在改成浅色柔光，否则白玻璃卡片浮在一片暗照片上会发灰。 */
html.theme-space #bgLayer::after{
  background:
    radial-gradient(1200px 900px at 10% 4%,rgba(255,255,255,.28),transparent 66%),
    radial-gradient(1000px 720px at 92% 10%,rgba(214,230,250,.24),transparent 64%),
    linear-gradient(180deg,rgba(242,246,252,.46),rgba(228,237,249,.56));
}
html.theme-space.has-bg{
  --bg:rgba(233,240,250,.32);
  --panel:rgba(255,255,255,.62);
  --wrap-bg:rgba(255,255,255,.68);
  --thead-bg:rgba(255,255,255,.80);
  --sidebar-bg:rgba(255,255,255,.55);
}

/* ---- 侧栏 / 顶栏：白色磨砂玻璃 ---- */
html.theme-space .sidebar{
  background:rgba(255,255,255,.55);
  backdrop-filter:blur(26px) saturate(170%);
  -webkit-backdrop-filter:blur(26px) saturate(170%);
  box-shadow:
    1px 0 0 0 rgba(255,255,255,.60),
    inset -1px 0 0 rgba(31,56,100,.10),
    inset 0 1.5px 0 rgba(255,255,255,.75),
    0 0 44px rgba(31,56,100,.14);
}
html.theme-space .topbar{
  background:rgba(255,255,255,.50);
  backdrop-filter:blur(26px) saturate(170%);
  -webkit-backdrop-filter:blur(26px) saturate(170%);
  box-shadow:
    0 1px 0 0 rgba(255,255,255,.55),
    inset 0 1px 0 rgba(255,255,255,.72),
    0 6px 24px rgba(31,56,100,.14);
}
/* logo 是深蓝字标，白底不需要提亮（深空时用 brightness 提亮，现在要去掉） */
html.theme-space .logo{--logo-filter:none;--logo-op:1;}

/* ---- 菜单项：白色胶囊；**深色字体**；选中＝更实的白玻璃 + 深蓝字 ----
   ⚠ glass 共享规则里 #nav a 是浅字(#cdd8ea)、hover 白字、brand-title/brand-sub/
     sidebar-foot 也是浅字(#e8edf5 / rgba(255,255,255,.55))——白磨砂下必须逐条改成深字，
     否则菜单栏在浅色侧栏上是「看不见的浅字」。 */
html.theme-space #nav a{color:#2b3a4d;box-shadow:0 0 0 1px rgba(31,56,100,.08);}
html.theme-space #nav a:hover{
  color:#1f3864;background:rgba(255,255,255,.60);
  box-shadow:0 0 0 1px rgba(31,56,100,.14),0 2px 10px rgba(31,56,100,.14);
}
html.theme-space #nav a.active{
  background:rgba(255,255,255,.90);
  color:#1f3864;font-weight:700;border-color:transparent;
  box-shadow:0 4px 16px rgba(31,56,100,.18),inset 0 1px 0 rgba(255,255,255,.95);
}
html.theme-space #nav a.active::after{background:linear-gradient(160deg,#4a86e8,#2a5cb0);}
/* 品牌区标题/副标题、侧栏底部：glass 里是浅字，白磨砂改深字 */
html.theme-space .brand-title{color:#1f3864;}
html.theme-space .brand-sub{color:rgba(31,56,100,.62);}
html.theme-space .sidebar-foot{
  color:#2b3a4d;
  background:rgba(255,255,255,.45);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.75);
}

/* ---- 卡片：白色磨砂 + 柔和投影 ---- */
html.theme-space .panel{
  backdrop-filter:blur(30px) saturate(180%);
  -webkit-backdrop-filter:blur(30px) saturate(180%);
  box-shadow:
    0 0 0 1px rgba(255,255,255,.66),
    0 18px 46px rgba(31,56,100,.18);
}
html.theme-space .panel-card{
  background:rgba(255,255,255,.60);
  padding:11px 13px;color:#1e2733;
  backdrop-filter:blur(14px) saturate(160%);
  -webkit-backdrop-filter:blur(14px) saturate(160%);
  box-shadow:
    0 0 0 1px rgba(255,255,255,.60),
    0 8px 22px rgba(31,56,100,.14);
}
html.theme-space .panel-card-t{color:#1f3864;}
html.theme-space .panel-card-d{color:rgba(30,39,51,.65);}
html.theme-space .panel-card:hover{
  background:rgba(255,255,255,.85);
  box-shadow:
    0 0 0 1px rgba(31,56,100,.14),
    0 10px 26px rgba(31,56,100,.18);
}
/* 2026-10-16 用户要求：去掉卡片左侧的蓝色竖杠（强调条）。 */
html.theme-space .panel-card::before{display:none;}

/* ---- KPI / 按钮 / 输入框 ---- */
html.theme-space .kpi{
  background:rgba(255,255,255,.62);
  backdrop-filter:blur(22px) saturate(160%);
  -webkit-backdrop-filter:blur(22px) saturate(160%);
  box-shadow:
    0 0 0 1px rgba(255,255,255,.60),
    0 8px 24px rgba(31,56,100,.14);
}
/* 2026-10-16 用户要求：去掉 KPI 卡上方的彩色横杠。 */
html.theme-space .kpi::before{display:none;}
html.theme-space .chip{background:rgba(255,255,255,.60);}
html.theme-space .btn{
  background:rgba(255,255,255,.72);
  color:#1e2733;
  box-shadow:0 0 0 1px rgba(255,255,255,.60),0 3px 10px rgba(31,56,100,.14);
}
html.theme-space .btn:hover{background:rgba(255,255,255,.95);color:#1f3864;}
html.theme-space .btn-primary{
  background:linear-gradient(180deg,#5b9ae8,#2f63b8);
  color:#fff;border-color:rgba(255,255,255,.55);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.55),0 4px 14px rgba(31,56,100,.30);
}
html.theme-space .btn-primary:hover{background:linear-gradient(180deg,#4a86e8,#2a5cb0);color:#fff;}
html.theme-space .bg-btn{
  background:rgba(255,255,255,.72);
  color:#1e2733;
  box-shadow:0 0 0 1px rgba(255,255,255,.60),0 2px 8px rgba(31,56,100,.12);
}
html.theme-space .bg-btn:hover{background:rgba(255,255,255,.95);color:#1f3864;}
html.theme-space .search-input,html.theme-space .inp{
  background:rgba(255,255,255,.78);
  border-color:rgba(31,56,100,.18);color:#1e2733;
}
html.theme-space .search-input:focus,html.theme-space .inp:focus{
  border-color:#5b9ae8;
  box-shadow:0 0 0 3px rgba(91,154,232,.20);
}

/* ---- 滚动容器：白色磨砂 + 亮边环（不加 backdrop-filter）---- */
html.theme-space .table-wrap,
html.theme-space .plan-scroll,
html.theme-space .tree-wrap{
  background:rgba(255,255,255,.72);
  box-shadow:
    0 0 0 1px rgba(255,255,255,.66),
    0 12px 34px rgba(31,56,100,.16);
}

/* ---- 3 层景深弹窗：白磨砂 ---- */
/* 第 3 层：确认框 / 行编辑（滚动容器不能加 backdrop-filter，用高不透明白+柔和投影） */
html.theme-space .modal,
html.theme-space .confirm-box{
  background:rgba(255,255,255,.88);
  border-radius:16px;
  box-shadow:
    0 0 0 1px rgba(255,255,255,.75),
    0 16px 48px rgba(31,56,100,.26);
}
/* 第 2 层：一级弹窗（overflow:hidden，可安全 blur）*/
html.theme-space .fmodal{
  background:rgba(255,255,255,.78);
  border-radius:20px;
  backdrop-filter:blur(30px) saturate(180%);
  -webkit-backdrop-filter:blur(30px) saturate(180%);
  box-shadow:
    0 0 0 1px rgba(255,255,255,.65),
    0 24px 70px rgba(31,56,100,.28);
}
/* 遮罩：白磨砂上用「轻暗」压暗背景，白卡片才浮得出来（深空原来压成近黑） */
html.theme-space .modal-mask{background:rgba(90,110,140,.26);}
html.theme-space .fhead{background:rgba(255,255,255,.55);border-bottom-color:rgba(31,56,100,.12);}
html.theme-space .fbar,html.theme-space .ffoot{background:rgba(255,255,255,.50);}
html.theme-space .fscroll{background:rgba(255,255,255,.35);}
html.theme-space .modal-title{color:#1f3864;border-bottom-color:rgba(31,56,100,.12);}
html.theme-space .modal-body label{color:#5d6a7d;}
html.theme-space .modal-body .field-tip{color:rgba(93,106,125,.85);}
html.theme-space .modal-foot{background:rgba(255,255,255,.55);border-top-color:rgba(31,56,100,.12);}
html.theme-space .modal-body input,html.theme-space .modal-body select{
  background:rgba(255,255,255,.92);color:#1e2733;border-color:rgba(31,56,100,.20);}
html.theme-space .modal-body input:focus,html.theme-space .modal-body select:focus{
  border-color:#5b9ae8;box-shadow:0 0 0 2px rgba(91,154,232,.20);}

/* ---- 表格：浅底隔行 ---- */
html.theme-space table.grid tbody tr:nth-child(even){background:rgba(31,56,100,.045);}
html.theme-space table.grid tbody tr:hover,
html.theme-space table.grid tbody tr:nth-child(even):hover{background:rgba(91,154,232,.14);}
html.theme-space table.grid thead th{background:rgba(255,255,255,.82);color:#1f3864;}
html.theme-space.has-bg table.grid tbody tr:nth-child(even),
html.theme-space.has-bg table.grid.sheet-orders tbody tr:nth-child(even){background:rgba(255,255,255,.55);}
html.theme-space.has-bg table.grid tbody tr:hover,
html.theme-space.has-bg table.grid tbody tr:nth-child(even):hover{background:rgba(91,154,232,.16);}
html.theme-space.has-bg .table-wrap,
html.theme-space.has-bg .plan-scroll{background:rgba(255,255,255,.66);}
html.theme-space.has-bg table.grid thead th{background:rgba(255,255,255,.86);}
html.theme-space.has-bg{--pt-hd-bg:rgba(255,255,255,.86);--pt-sub-bg:rgba(240,245,252,.88);}
/* 排产表在 has-bg 时，「计划行」原本被整条设成 background:transparent（深空为让背景图透出），
   白磨砂下透得太多 → 横向滚动时数字发虚。这里改回用 --plan-odd（近不透明），
   与冻结列（不透明 --plan-*-op）观感一致。 */
html.theme-space.has-bg .plan-tbl tbody tr.pt-grp-a.pt-plan td,
html.theme-space.has-bg .plan-tbl tbody tr.pt-grp-b.pt-plan td{background:var(--plan-odd);}

/* ---- 下拉 / 浮层 / 日历：第 3 层白色磨砂 ---- */
html.theme-space .calendar-panel{
  background:rgba(255,255,255,.92);border-color:rgba(31,56,100,.18);
  box-shadow:0 14px 42px rgba(31,56,100,.22);
}
html.theme-space .wf-dir{background:rgba(31,56,100,.06);}
html.theme-space .wf-row:hover{background:rgba(31,56,100,.08);}
html.theme-space .tree-label:hover{background:rgba(91,154,232,.16);}
html.theme-space .tree-label.active{background:rgba(91,154,232,.28);color:#1f3864;}
/* ---- 缺件提示横幅（BOM 缺失 / 产能缺失，两个横幅共用 .bom-miss）：
   glass 共享规则给的是浅字（#f7d79a / #ffc9c0，深底用），白磨砂下背景变浅 → 浅字看不见，
   这里改回「浅琥珀底 + 深棕字」。 */
html.theme-space .bom-miss{
  background:rgba(240,180,90,.20);border-color:rgba(200,135,31,.40);
  border-left-color:#c8871f;color:#5c4310;
}
html.theme-space .bom-miss.is-crit{
  background:rgba(230,120,110,.18);border-color:rgba(190,80,70,.36);
  border-left-color:#b3261e;color:#7a1a14;
}
html.theme-space .note-pop{
  --np-bg:rgba(255,255,255,.94); --np-fg:#1e2733; --np-fg2:rgba(30,39,51,.62);
  --np-line:rgba(31,56,100,.16);
  --np-head-bg:rgba(31,56,100,.06); --np-head-fg:#1f3864;
  --np-zebra:rgba(31,56,100,.03); --np-hover:rgba(31,56,100,.07);
  --np-bar-bg:rgba(31,56,100,.06); --np-bar-fg:#1f3864;
  border-color:rgba(31,56,100,.18);border-radius:14px;
  box-shadow:0 20px 52px rgba(31,56,100,.22);
}
html.theme-space .note-pop .seg-r{color:#c0392b;}
html.theme-space .note-pop .seg-g{color:#31507f;}

/* ---- 补漏：其余 glass 里为「深底」写的浅字组件，白磨砂下也要改深色 ----
   （页面标题、导入工作流、标签、占位符、删除键、产能表分组头、动态徽标） */
html.theme-space .page-title{color:#1f3864;}
html.theme-space .wf-lbl{color:#5d6a7d;}
html.theme-space .wf-path{color:#1f3864;}
html.theme-space .wf-row{color:#2b3a4d;}
html.theme-space .wf-folder{color:#1f3864;}
html.theme-space .chip b{color:#1f3864;}
html.theme-space .calendar-tip{color:#5d6a7d;}
html.theme-space .io-sheet-cell .io-sheet-name{color:#1f3864;}
html.theme-space .search-input::placeholder,
html.theme-space .inp::placeholder{color:rgba(93,106,125,.78);}
html.theme-space .btn-danger{color:#a8352a;}
html.theme-space table.grid.cap-tbl thead tr.cap-group th{
  background:rgba(255,255,255,.86);color:#1f3864;border-bottom-color:rgba(31,56,100,.14);}
html.theme-space .fk-badge.fk-dyn{border-color:#b8357f;color:#b8357f;}

/* ---- 附件相关（原本是给深底写的亮色，改成深字）---- */
html.theme-space .att-toggle{background:rgba(31,56,100,.08);}
html.theme-space .att-group-row{background:rgba(150,190,240,.22);}
html.theme-space .att-group-row:hover{background:rgba(150,190,240,.34);}
html.theme-space .att-form .att-section{background:rgba(255,255,255,.50);}
html.theme-space a.att-file.att-missing,
html.theme-space a.att-file-name.att-missing{color:#c0392b;}
html.theme-space .att-del-rowinfo{color:#1f4e79;}
html.theme-space .att-del-list{border-color:rgba(31,56,100,.16);background:rgba(31,56,100,.04);}
html.theme-space .att-del-name{color:#1e2733;}
html.theme-space .att-del-flag,
html.theme-space .att-del-file.att-missing .att-del-name{color:#c0392b;}
html.theme-space .att-combo-drop{
  background:rgba(255,255,255,.94);border-color:rgba(31,56,100,.20);
  box-shadow:0 14px 42px rgba(31,56,100,.22);
}
html.theme-space .att-combo-code{color:#1f4e79;}
html.theme-space .att-combo-opt.active,
html.theme-space .att-combo-opt:hover{background:rgba(31,56,100,.08);}
html.theme-space .kit-prod-drop{
  background:rgba(255,255,255,.94);border-color:rgba(31,56,100,.20);
  box-shadow:0 14px 42px rgba(31,56,100,.22);
}
html.theme-space .upd-new{color:#1f8a55;}

/* ---- 数据流页徽标 / 行条：浅底用深色 ---- */
html.theme-space .flow-table .ft-ok{color:#0f6e56;}
html.theme-space .fk-badge.fk-src{color:#0f6e56;border-color:#0f6e56;}
html.theme-space .fk-badge.fk-mas{color:#534ab7;border-color:#534ab7;}
html.theme-space .fk-badge.fk-der{color:#854f0b;border-color:#854f0b;}
html.theme-space .flow-table tr.fk-row-der{box-shadow:inset 3px 0 0 0 #854f0b;}
html.theme-space .flow-table tr.fk-row-mas{box-shadow:inset 3px 0 0 0 #534ab7;}
html.theme-space .flow-table tr.fk-row-src{box-shadow:inset 3px 0 0 0 #0f6e56;}

/* ---- 流程图（前面与 dark/glass 合写成浅字，浅底要改深字）---- */
html.theme-space .fl-edge{stroke:rgba(31,56,100,.58);}
html.theme-space .fl-arrow{fill:rgba(31,56,100,.58);}
html.theme-space .fl-back{stroke:rgba(192,57,43,.95);}
html.theme-space .fl-arrow.fl-back{fill:rgba(192,57,43,.95);}
html.theme-space .fl-lbl{fill:#1e2733;}
html.theme-space .fl-lbl-bg{fill:rgba(255,255,255,.96);stroke:rgba(31,56,100,.18);}
html.theme-space .fl-lbl-bg.fl-back{fill:rgba(255,240,240,.96);stroke:rgba(192,57,43,.45);}
html.theme-space .fl-title{fill:#1e2733;}
html.theme-space .fl-sub{fill:rgba(69,89,110,.85);}
html.theme-space .fl-node.src .fl-rect{fill:rgba(90,130,200,.16);stroke:rgba(60,100,180,.60);}
html.theme-space .fl-node.mas .fl-rect{fill:rgba(210,150,90,.16);stroke:rgba(180,120,50,.60);}
html.theme-space .fl-node.der .fl-rect{fill:rgba(80,200,140,.14);stroke:rgba(40,150,100,.60);}
html.theme-space .fl-iso-frame{stroke:rgba(90,107,126,.7);}
html.theme-space .fl-iso-cap{fill:rgba(69,89,110,.8);}

/* ---- 滚动条：白底用深一点的滑块（深空原来是亮色细条）---- */
html.theme-space ::-webkit-scrollbar-track{background:rgba(31,56,100,.06);}
html.theme-space ::-webkit-scrollbar-thumb{
  background:rgba(31,56,100,.26);border-radius:6px;
  border:2px solid transparent;background-clip:padding-box;}
html.theme-space ::-webkit-scrollbar-thumb:hover{background:rgba(31,56,100,.40);background-clip:padding-box;}

/* ---- 局域网访问状态 / 解锁编辑入口（顶栏，仅局域网来源显示）---- */
/* 放在文件末尾：深空主题（html.theme-space）的覆盖块在它之前，
   这里用的中性浅底深字在四种主题下都能读，无需再逐主题覆盖。 */
.lan-badge{
  display:inline-flex;align-items:center;gap:6px;
  padding:2px 8px;border-radius:11px;font-size:11.5px;line-height:1.6;
  background:#eef2f8;color:#3a4658;border:1px solid #d3dbe8;
}
.lan-badge .btn{margin-left:2px;}
.lan-dot{width:7px;height:7px;border-radius:50%;background:#9aa6b8;display:inline-block;}
.lan-dot.on{background:#2e9e5b;}

/* 网络版开关（顶栏，仅本机主程序显示）：勾选框 + 「设置」小按钮 */
.lan-set{display:inline-flex;align-items:center;gap:4px;}
.lan-chk{
  display:inline-flex;align-items:center;gap:4px;cursor:pointer;
  padding:2px 8px;border-radius:11px;font-size:11.5px;line-height:1.6;
  background:#eef2f8;color:#3a4658;border:1px solid #d3dbe8;user-select:none;
}
.lan-chk input{margin:0;cursor:pointer;}
.lan-chk:hover{background:#e6ecf5;}

/* 网络版设置窗内容 */
.lan-cfg{padding:6px 10px;display:flex;flex-direction:column;gap:12px;font-size:12.5px;color:#26303f;}
.lan-cfg-row{display:flex;align-items:center;gap:8px;flex-wrap:wrap;}
.lan-cfg-lab{width:64px;flex:none;color:#5c6a80;}
.lan-cfg .hint{color:#7a8698;font-size:11.5px;}
.lan-addr{display:inline-flex;align-items:center;gap:4px;}
/* 「短网址」：跟在公网网址后面（公网随机域名太长，发给别人用短链） */
.lan-short{display:inline-flex;align-items:center;gap:5px;margin-left:10px;}
.lan-cfg-note{
  line-height:1.75;font-size:11.5px;color:#6b7686;
  background:#f4f7fb;border:1px solid #e2e8f0;border-radius:6px;padding:8px 10px;
}
/* 网络版设置：模块权限 / 字段隐藏 */
.lan-sec{border-top:1px solid #e6ebf2;padding-top:10px;display:flex;flex-direction:column;gap:6px;}
.lan-sec-t{font-size:12.5px;font-weight:700;color:#2b3648;}
.lan-sec-bar{display:flex;align-items:center;gap:6px;}
.lan-mods,.lan-hides{display:flex;flex-wrap:wrap;gap:4px 10px;}
.lan-mod{
  display:inline-flex;align-items:center;gap:4px;cursor:pointer;
  min-width:104px;font-size:12px;color:#33405a;user-select:none;
}
.lan-mod input{margin:0;cursor:pointer;}
/* 未授权模块的占位提示 */
.lan-denied{
  margin:40px auto;max-width:520px;text-align:center;
  background:#f6f8fb;border:1px solid #dfe6ef;border-radius:8px;padding:26px 22px;
}
.lan-denied-t{font-size:15px;font-weight:700;color:#33405a;margin-bottom:8px;}
.lan-denied-s{font-size:12.5px;color:#6b7686;line-height:1.8;}
.lan-lim{color:#8a6d1f;}
