:root{
  --navy:#0d2137;--navy2:#13314f;--navy3:#1b4066;
  --accent:#0e7490;--accent-l:#e0f2fe;--blue:#2563eb;--purple:#6d28d9;
  --bg:#f2f6fa;--card:#ffffff;--line:#e2e9f1;--line2:#cfdae6;
  --text:#1f2b38;--muted:#697b8f;--green:#15803d;--amber:#b45309;--red:#b91c1c;
  --soft:#f8fafc;--soft2:#f9fbfd;--hover:#eef4fa;--accent-soft:#eaf4fd;
  --label:#41546a;--head-tx:#5b6e82;--btn-tx:#33465c;--toast-bg:#0f2b45;
  --pie-ok:#54759e;--pie-over:#a2707a;
  --pie-ok-d:#3d5875;--pie-over-d:#7d5259;
  --arrow-body:#98a7b8;--arrow-hi:#c6cfda;
  --wc-60:#7c8ca1;--wc-30:#8b81a4;--wc-exp:#a1848c;
  /* 统一的字号 / 字重体系（把原来 11/12/12.5/13/26/21 混用收敛成一套） */
  --fs-h2:17px;--fs-title:13.5px;--fs-num-xl:26px;--fs-num:20px;--fs-num-sm:20px;
  --fs-body:13px;--fs-label:12.5px;--fs-hint:12px;
  --fw-num:600;--fw-title:600;--fw-label:600;--fw-body:400;
  --radius:10px;--shadow:0 1px 2px rgba(16,38,60,.06),0 6px 20px rgba(16,38,60,.06);
  /* A4 版心宽（需求方 2026-09-18）：210mm ≈ 794px @96dpi。全站内容区按此宽度居中，不再铺满全屏。 */
  --a4:794px;
}
*{box-sizing:border-box}
html,body{height:100%}
body{margin:0;background:var(--bg);color:var(--text);font:14px/1.6 "Microsoft YaHei","PingFang SC","Segoe UI",system-ui,sans-serif}
button,input,select,textarea{font-family:inherit;font-size:13px}
a{color:var(--blue)}
.hidden{display:none !important}

/* ===== 登录页：左右分栏的正式商务版式（2026-09-17 重做） =====
   左＝品牌展示面（深钢蓝 + 细网格 + 抬头线 + 能力清单 + 落款），右＝登录表单（纯白，克制）。
   🔴 硬约束（2026-09-22 方案 A 后**在右窗口**）：`#login .lc-brand img`（logo.jpg）与 `.lc-brand .lc-t`
      （CrossNet IT）必须同在 `.lc-brand` 内且**竖排**（桌面壳 --smoke 自检 + `tools/ui_check.js` 会校验）；
      `#lg-*` 全部 id 不得改名。 */
#login{position:fixed;inset:0;display:flex;align-items:center;justify-content:center;z-index:50;overflow:hidden;
  /* 背景底色：多层渐变（斜向主渐变 + 左上光晕 + 右下紫色收口）—— 背景图未载入时的兜底底色 */
  background:
    radial-gradient(ellipse 90% 70% at 22% 10%, rgba(38,116,168,.40) 0%, rgba(8,24,40,0) 62%),
    radial-gradient(ellipse 70% 60% at 88% 92%, rgba(72,58,158,.22) 0%, rgba(8,24,40,0) 62%),
    linear-gradient(150deg,#061322 0%,#0a2136 32%,#0f3555 64%,#132c4c 100%)}
/* ===== 登录页背景图 + 「镜头跟随」（需求方 2026-09-22） =====
   背景素材取自 CrossNet-AIIT 登录页的 `/brand/login-bg.jpg`（原图直取 → web/login-bg.jpg，未压缩）。
   层次（从下到上）：#login 底色渐变（图未载入时兜底） < .login-bg-fx（背景图 + 暗纱） < .login-shell 两栏外壳。
   🔴 原来那层「防截图水印」已按需求方 2026-09-22 的要求**下线**（样式一并删除）。
   🔴 「镜头跟随」与 AIIT 同一套做法：鼠标位置归一化成 ±1 的 mx/my，背景层**反向**平移 3.2% / 2.4%，
      过渡 0.35s cubic-bezier(.2,.6,.3,1)；层自身向内扩 4%（inset:-4%），平移后四周不会露边。
      位移由 app.js 的 mousemove 写入 `.login-bg-par` 的 transform（合并到一帧，避免逐事件写样式）。
   背景图另带缓慢的缓动浮动（AIIT 的 kenburns），与鼠标跟随叠加。 */
#login .login-bg-fx{position:absolute;inset:0;overflow:hidden;pointer-events:none;z-index:0}
#login .login-bg-par{position:absolute;inset:-4%;transition:transform .35s cubic-bezier(.2,.6,.3,1);will-change:transform}
#login .login-bg-img{position:absolute;inset:0;background-image:url('/login-bg.jpg');
  background-size:cover;background-position:center;background-repeat:no-repeat;
  animation:lgKenburns 34s ease-in-out infinite alternate}
@keyframes lgKenburns{from{transform:scale(1) translate(0,0)}to{transform:scale(1.06) translate(-1%,.8%)}}
/* 暗纱：把夜景压回登录页本来的深蓝调 —— 左侧略重（靠品牌面板一侧），
   外壳之外的留白区仍有层次。 */
#login .login-bg-veil{position:absolute;inset:0;background:
  linear-gradient(90deg,rgba(6,17,32,.44) 0%,rgba(6,17,32,.22) 36%,rgba(6,17,32,.26) 64%,rgba(6,17,32,.42) 100%),
  linear-gradient(180deg,rgba(6,17,32,.26) 0%,rgba(6,17,32,.04) 32%,rgba(6,17,32,.24) 100%)}
@media (prefers-reduced-motion: reduce){
  #login .login-bg-img{animation:none} #login .login-bg-par{transition:none}}
/* 登录外壳：左右一体、圆角裁切；四周留出边距，让背景图的边缘透出来。
   🔴 2026-09-22 需求方「下面空白又多了，有没有可能左边板块可以宽度收紧变窄点」→ 两处尺寸同时改：
   · **宽 1120 → 1000px**：右卡定宽 424px 不动，所以左栏 = 1000 − 424 = **576px**（原来 696，收窄 120px）。
     1000 是**实测出来的下限**：左栏内容宽 496px，而页脚那一组（公司信息 + 两张 100px 二维码）
     固定要 **472px**，再窄就会顶到左内边距上（980 时只剩 4px 余量、940 时会溢进边距）。
   · **高 固定 648 → 内容驱动**（`height:auto` + `max-height:min(648px,88vh)`）：
     原来高度写死 648，而面板内容只占 ~544px ⇒ 底部凭空剩 44px 空白（就是需求方说的"下面空白又多了"）。
     改成 auto 后，外壳高度 = 两栏里更高那一栏的自然高度 ⇒ **底部余量恒为 0**
     （实测 1440×1040 → 604px；1120×700 媒体查询下 → 537px），不需要为每个窗口写死数字。
     `max-height` 保留 88vh 钳制（视口过矮时仍不会顶出屏幕）、`min-height:512px` 保留。
   ⚠️ 别把 height 改回固定值（底部空白会回来）；也别为了"自适应"去掉 max-height（矮视口会顶出屏幕）。 */
.login-shell{position:relative;z-index:1;display:flex;width:min(1000px,94vw);height:auto;max-height:min(648px,88vh);min-height:512px;
  border-radius:18px;overflow:hidden;
  box-shadow:0 40px 90px rgba(2,12,24,.55),0 0 0 1px rgba(255,255,255,.07)}

/* 左：品牌展示面 —— 2026-09-22 需求方「布局有点乱、没有设计感」后的**重排版**。
   🔴 2026-09-22 再改（需求方：「中间部分留白是太多了」）：原来用 `justify-content:space-between`
      **均分**余量，区块从 4 个减到 3 个之后余量变大，中段被摊出两处 88px 空白 → 看起来"空、散"。
      ⚠️ 关键点：**余量要"分散"，不能"集中"** —— 试过"固定间距 + 底栏 `margin-top:auto` 贴底"，
      结果余量全堆到「功能块 ↔ 底栏」之间变成 120px，等于把一处空白换成另一处更大的空白（已否决）。
      现行 = **固定块间距 44px + 内容整体靠上**，余量自然落到面板底部（≈44px）：三段之间与底部各约 44px，
      中段不再空旷，观感从"被摊开"回到"紧凑均衡"。省下的高度同时**给内容**（行距上调，见功能块）。
      ⚠️ 别改回 `space-between`（中段会被重新摊空）；也别给底栏加 `margin-top:auto`（余量会集中成一处大空白）。 */
.login-brand{flex:1 1 auto;min-width:0;position:relative;overflow:hidden;color:#eaf2fa;
  display:flex;flex-direction:column;justify-content:flex-start;gap:44px;padding:34px 40px 26px;
  /* 🔴 2026-09-22「左面板轻微透出背景图」（建议项⑤）：透明度各降 4%（.97/.95/.93 → .93/.91/.89）。
     代价是文字对比度要重新体检 —— 已跑 `--only visual` 的 WCAG AA 九项，全部仍达标（见探针输出）。
     别再加透明了：再降就会把 ISO 体系名 / 信息块标签压到 4.5:1 边缘。 */
  background:linear-gradient(155deg,rgba(9,26,45,.93) 0%,rgba(13,42,68,.91) 46%,rgba(19,52,84,.89) 100%)}
/* 细网格（"图纸感"）+ 一道斜向柔光，纯装饰、不抢文字、不拦点击。
   🔴 2026-09-22「背景网格降到几乎看不见」（建议项②）：不透明度 .9 → .52，
      并加一层**顶部渐隐**遮罩 —— 网格在上部（抬头区）还能看见一点"图纸感"，
      到底部的业务网格 / ISO 徽章一带基本消失，避免"格子感"和内容抢注意力。 */
.login-brand::before{content:'';position:absolute;inset:0;pointer-events:none;opacity:.52;
  background-image:linear-gradient(rgba(255,255,255,.045) 1px,transparent 1px),
                   linear-gradient(90deg,rgba(255,255,255,.045) 1px,transparent 1px);
  background-size:34px 34px;
  -webkit-mask-image:linear-gradient(180deg,rgba(0,0,0,.95) 0%,rgba(0,0,0,.55) 42%,rgba(0,0,0,.06) 100%);
  mask-image:linear-gradient(180deg,rgba(0,0,0,.95) 0%,rgba(0,0,0,.55) 42%,rgba(0,0,0,.06) 100%)}
.login-brand::after{content:'';position:absolute;left:-18%;top:-30%;width:70%;height:150%;pointer-events:none;
  background:linear-gradient(90deg,rgba(120,200,255,0),rgba(120,200,255,.08) 45%,rgba(120,200,255,0));
  transform:rotate(18deg)}
.login-brand>*{position:relative}
/* 登录页背景水印（需求方 2026-09-16 加入）—— 🔴 **2026-09-22 需求方要求不要了**，整块已删除，
   连同 app.js 里的 `buildLoginWatermark()` 与 index.html 的 `.login-wm` 容器一并下线，无残留。 */
/* 右：登录窗口（需求方 2026-09-22 —— 改用 CrossNet-AIIT 登录窗口的**深色玻璃拟态**版式与内容：
   LOGO + 品牌名 + 副标题居中在表单上方、深色半透明输入框、通栏渐变按钮、按钮下方＝隐私与免责声明 + 版本号。
   与左品牌面共用外壳圆角，故不设圆角、只留一道左侧分隔线） */
.login-card{flex:0 0 424px;min-width:0;display:flex;flex-direction:column;justify-content:center;color:#fff;
  padding:30px 40px 22px;
  background:rgba(11,22,42,.55);
  backdrop-filter:blur(18px) saturate(1.25);-webkit-backdrop-filter:blur(18px) saturate(1.25);
  border-left:1px solid rgba(255,255,255,.16);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.10)}
/* 卡片顶部（对应 AIIT 模板里的品牌行，本项目类名已改为 lc-brand）：LOGO + 品牌名 + 副标题，居中 */
.login-card .lc-brand{margin-bottom:20px;text-align:center}
/* 🔴 LOGO 沿用 `logo/logo.jpg`（需求方既定：LOGO 不变），且**透明背景** ——
   不加 AIIT 那种白色圆角底块（需求方 2026-09-17 明确去过白底块，保持同一口径）。 */
.login-card .lc-logo{width:56px;height:56px;margin:0 auto 10px;display:block;object-fit:contain;
  background:transparent;padding:0;border-radius:0;
  filter:drop-shadow(0 6px 16px rgba(30,100,200,.35))}
.login-card .lc-t{margin:0;font-size:23px;font-weight:700;color:#fff;letter-spacing:.6px}
/* 登录页次要文字：深色玻璃底上的浅灰白（对比度远高于 WCAG AA 4.5:1；不再是白底上的 #5c6f83） */
.login-card .lc-s{margin:6px 0 0;font-size:13px;color:rgba(255,255,255,.64);letter-spacing:.3px}
/* 「关于我们」弹窗（桌面「帮助」菜单入口，需求方 2026-09-16）：公司名 + 400 热线 + 客服二维码 */
.about-box{text-align:center;padding:4px 2px 0}
/* 「迭代计划」弹窗（需求方 2026-09-22：**桌面菜单栏「关于我们」右边的独立菜单**打开它，
   不是在「关于我们」弹窗里 → 所以这段是**独立弹窗**的样式，不再是"两栏右半边"）。 */
.about-plan{text-align:left;max-height:52vh;overflow:auto}
.ap-t{font-size:13px;font-weight:700;color:#0f2a4a;letter-spacing:1px;padding-bottom:7px;border-bottom:1px dashed var(--line)}
.ap-list{margin-top:9px;display:flex;flex-direction:column;gap:7px}
.ap-item{border:1px solid var(--line);border-radius:9px;padding:7px 10px;background:#fff}
.ap-h{display:flex;align-items:center;gap:8px}
.ap-h b{font-size:12.5px;color:#0f2a4a;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ap-s{flex:none;font-size:10.5px;border-radius:999px;padding:1px 7px;border:1px solid var(--line2);color:#5b6e82}
.ap-s.doing{color:#1d4ed8;border-color:#cddff8;background:#eef4ff}
.ap-s.done{color:#0f7a3d;border-color:#c8e6d0;background:#eefbf1}
.ap-d{flex:none;margin-left:auto;font-style:normal;font-size:11px;color:#94a3b8;font-variant-numeric:tabular-nums}
.ap-c{margin-top:5px;font-size:11.5px;color:#5b6e82;line-height:1.65;white-space:pre-wrap}
.ap-none{margin-top:10px;line-height:1.7}
.about-box .ab-name{font-size:17px;font-weight:700;color:var(--text);letter-spacing:.5px}
/* 公司口号：用与品牌同色的渐变字，克制但有识别度 */
.about-box .ab-slogan{margin-top:7px;font-size:12.5px;font-weight:600;letter-spacing:2px;
  background:linear-gradient(90deg,#1d4ed8,#4f46e5 55%,#7c3aed);
  -webkit-background-clip:text;background-clip:text;color:transparent;-webkit-text-fill-color:transparent}
.about-box .ab-line a{color:var(--accent);text-decoration:none;font-weight:600}
.about-box .ab-line a:hover{text-decoration:underline}
.about-box .ab-prod{margin-top:6px;font-size:12.5px;color:var(--muted)}
.about-box .ab-line{margin-top:14px;font-size:13px;color:var(--label)}
.about-box .ab-line b{font-size:16px;color:var(--accent);letter-spacing:.6px}
.about-box .ab-qrs{margin-top:14px;display:flex;gap:18px;justify-content:center;align-items:flex-start}
.about-box .ab-qr-item{display:flex;flex-direction:column;align-items:center;gap:6px}
.about-box .ab-qr-item img{width:132px;height:132px;object-fit:contain;background:#fff;border:1px solid var(--line);border-radius:10px;padding:6px}
/* 「关于我们」：隐藏右上角的关闭，只保留右下角按钮（需求方 2026-09-16） */
#modal.about-mode .mh button{display:none}
/* 「知识判定」页（需求方 2026-09-22）—— 版式页：四列表格（条目可展开 / 类型 / AI 判定 / 删除）
   + AI 判定浮窗（结论条 + 成稿表单 + 入库 / 放弃 / 待定）。样式只服务这一页，不外溢。
   🔴 版心 **A3**（需求方 2026-09-22 二次指定：「只是判定页面从 A4 调整为 A3」）——
      A3 = 297mm 宽，96dpi 下 297 ÷ 25.4 × 96 ≈ 1123px；**只给这一页**加宽，
      全站 `--a4`（794px）不动，建单页等其它 A4 页面不受影响。 */
.a4-wrap.kbj-a3{max-width:1123px}
.kbj-tbl td{vertical-align:top}
/* 🔴 列宽（需求方 2026-09-22）：「第一列要尽量加宽，后面三列自适应收窄」
   —— 后三列 `width:1%` + nowrap = **贴着内容缩到最窄**，剩余全部留给第 1 列。 */
.kbj-tbl col.kbj-w2,.kbj-tbl col.kbj-w3,.kbj-tbl col.kbj-w4{width:1%}
.kbj-tbl th:nth-child(n+2),.kbj-tbl td:nth-child(n+2){width:1%;white-space:nowrap}
/* 🔴 整行可点展开 / 收起（需求方 2026-09-22） */
.kbj-row{cursor:pointer}
.kbj-row:hover td{background:#f6f9ff}
.kbj-acts{display:flex;gap:8px;margin-top:8px;padding-top:8px;border-top:1px dashed var(--line)}
.kbj-t{font-size:13px;color:#0f2a4a;font-weight:600;text-decoration:none}
.kbj-row:hover .kbj-t{color:#1d4ed8}
.kbj-more{margin:6px 0 4px}
.kbj-more pre{margin:0;padding:8px 10px;background:var(--soft2);border:1px solid var(--line);border-radius:8px;
  font-size:12px;line-height:1.75;white-space:pre-wrap;word-break:break-word;max-height:260px;overflow:auto;
  font-family:inherit;color:#41546a}
.kbj-src{margin-top:3px}
.kbj-res{margin-top:4px;max-width:220px;line-height:1.5}
.kbj-sheet{max-height:66vh;overflow:auto;padding:2px 1px}
.kbj-v{display:flex;align-items:baseline;gap:10px;font-size:14px;font-weight:700;
  padding:8px 10px;border-radius:9px;margin-bottom:8px}
.kbj-v.ok{background:#eefbf1;color:#0f7a3d;border:1px solid #c8e6d0}
.kbj-v.bad{background:#fef2f2;color:#b3261e;border:1px solid #f3c3c3}
.kbj-v .mini{font-weight:400;color:#5b6e82}
.kbj-meta{margin-bottom:10px;line-height:1.7}
.kbj-foot{display:flex;gap:8px;justify-content:flex-end;margin-top:12px;padding-top:10px;border-top:1px dashed var(--line)}
/* 迭代计划「留言板」（需求方 2026-09-22） */
.pm-list{display:flex;flex-direction:column;gap:8px;max-height:56vh;overflow:auto}
.pm-item{border:1px solid var(--line);border-radius:9px;padding:8px 11px;background:#fff}
.pm-item.unread{border-color:#cddff8;background:#f7fbff}
.pm-h{display:flex;align-items:center;gap:8px;margin-bottom:4px}
.pm-h b{font-size:12.5px;color:#0f2a4a}
.pm-h i{margin-left:auto;font-style:normal;font-size:11px;color:#94a3b8;font-variant-numeric:tabular-nums}
.pm-new{font-size:10.5px;color:#1d4ed8;background:#eef4ff;border:1px solid #cddff8;border-radius:999px;padding:1px 7px}
.pm-ok{font-size:10.5px;color:#94a3b8}
.pm-c{font-size:12.5px;color:#41546a;line-height:1.75;white-space:pre-wrap}
.pm-dot{display:inline-block;min-width:15px;margin-left:5px;padding:0 4px;border-radius:999px;background:#dc2626;
  color:#fff;font-size:10.5px;line-height:15px;text-align:center;font-style:normal}
/* 抬头区（2026-09-22 **方案 A**，需求方选定）：
   🔴 左面板**不再放「大 logo + CrossNet IT」** —— 同屏两个品牌（左 54px/31px、右 56px/23px）是重复，
      品牌位只留给右侧登录窗口的 `.lc-brand`。本面板抬头 = **口号 + 渐变抬头线**（保留抬头仪式感、不重复品牌）。
   故原「品牌行容器 / 透明底 54px 的 logo 图 / 31px 品牌名标题」三条规则**已整体删除**（无残留，本文件里已无对应选择器）。
   ⚠️ 连带改动：桌面壳 `--smoke` 自检与 `tools/ui_check.js` 原本校验的就是上面这三样（旧选择器名），
      已一并改指到右侧窗口的品牌头（详表见 .workbuddy/memory/RULES-APP.md 的登录页小节）。 */
.login-brand .lb-top{flex:0 0 auto}
/* 抬头标语（**艺术字**，需求方 2026-09-22 两轮要求：先「标语太小了」→ 16.5px；再「希望艺术字效果大点、醒目点」）：
   16.5px 实色浅蓝 → **23px 加粗 + 渐变裁切文字 + 外发光**。
   · 渐变：三段**亮色**色标（浅青 → 浅蓝紫 → 浅紫），在深色面板上每一段都仍达 WCAG AA
     （对比度体检已升级为"渐变前景感知"：取最差色标算，见 ui_visual_metrics.js 的 fgCands）；
   · 发光用 `filter:drop-shadow()` 而**不是** `text-shadow` —— 后者在 `color:transparent` 时会整块透出来；
   · 🔴 探针 guard：字号 ≥20px + 必须真的是渐变裁切 + 不换行（防以后改回小字/实色）。 */
.login-brand .brand-sub{margin-top:0;font-size:23px;font-weight:700;letter-spacing:5px;line-height:1.25;
  background:linear-gradient(96deg,#93e0ff 0%,#c7d2fe 48%,#e9d5ff 100%);
  -webkit-background-clip:text;background-clip:text;
  color:transparent;-webkit-text-fill-color:transparent;
  filter:drop-shadow(0 2px 12px rgba(56,140,248,.5))}
/* 抬头分隔线：细金属感色带，正式文档里常见的"抬头线" */
.login-brand .brand-rule{margin-top:26px;height:3px;width:76px;border-radius:2px;
  background:linear-gradient(90deg,#38bdf8 0%,#6366f1 62%,rgba(99,102,241,0) 100%)}
/* 🔴 「公司简介」整段**已下线**（2026-09-22 需求方：改成对本系统的**主要功能介绍**，版式沿用下面的业务板块）——
   段落规则（含当时加的行宽限制）随内容一并删除，本文件里已无对应选择器；
   现在这一块与「六大业务板块」**共用 .lb-biz 系列样式**（见下方），靠 data-block 区分功能/业务两块。 */
/* 六大业务板块（需求方 2026-09-22，标题取自官网）：**小标题（渐变竖条 + 中文）+ 3 列 × 2 行文本网格**。
   🔴 重排要点：不再用 6 个细框标签（那是"方框农场"的来源）→ 改**纯文本 + 小圆点**，列宽由 grid 天然对齐；
   小标题用 3px 渐变竖条建立层级（与抬头那条渐变线同一色系）；原右侧英文小字「Core Business」已按要求去掉。 */
.login-brand .lb-biz{flex:0 0 auto}
.login-brand .lb-biz-cap{display:flex;align-items:center;gap:9px}
.login-brand .lb-biz-cap .cap-bar{flex:0 0 auto;width:3px;height:15px;border-radius:2px;
  background:linear-gradient(180deg,#38bdf8,#6366f1)}
/* 🔴 「六大业务板块字也太小了」→ 小标题 12px → 14px，字距 .9 → .6；
   2026-09-22「中间留白太多」时再提一档到 **15px**（把省下的高度给内容）。 */
.login-brand .lb-biz-cap span{font-size:15px;font-weight:600;color:#e8f1f9;letter-spacing:.6px}
/* 系统主要功能的正文档位 = **四类分组、一类一行**（需求方 2026-09-22：
   「按基础功能和管理功能和 AI 功能和统计分析，四类功能来体现」）：
   左＝类别标签（固定宽 68px，浅蓝、加字距，读起来像小标题），右＝该类功能条目（用「·」分隔的纯文本）。
   🔴 不用方框、不用图标、不加分隔线 —— 面板里已经有一个「细框徽章」语汇（ISO），这里保持纯文本更干净。 */
/* 🔴 2026-09-22「中间留白太多」：条目 14 → **15px**、类别 13 → **14px**；行距 11 → 15 → **18px**、上边距 13 → **20px**
   —— 把块间省下的高度还给内容，中段由内容撑实（字号只增不减，与需求方"字要大"的既定偏好同向）。 */
.login-brand .lb-feat{list-style:none;margin:20px 0 0;padding:0;display:flex;flex-direction:column;gap:18px}
.login-brand .lb-feat li{display:flex;align-items:baseline;gap:12px;min-width:0;font-size:15px;color:#d7e6f3}
.login-brand .lb-feat .lf-k{flex:0 0 74px;font-size:14px;font-weight:600;color:#8fc4e8;letter-spacing:.6px;white-space:nowrap}
.login-brand .lb-feat .lf-v{flex:1 1 auto;min-width:0;color:#d7e6f3;letter-spacing:.2px}
/* 🔴 随「六大业务板块」整块撤掉（2026-09-22 需求方：「六大业务板块不要了」），下列规则**已删除**
   （本文件里已无对应选择器）：业务条目的链接样式（无下划线 / 悬停变亮 + 下划线 / focus-visible 描边）、
   以及"悬停标题时圆点同步点亮并右移 1px"的那条 `:has()` 规则 —— 现列表内已无链接，该效果自然失效。
   现在这一块只做**纯文本展示**（介绍本系统功能），不需要可点反馈。 */

/* 公司信息 + 官网信息**放一起**，且与二维码**整体靠右**（需求方 2026-09-22：
   「公司信息放到二维码旁边，和二维码都靠右」）—— 两者合成一个右对齐的组贴在面板右下角；
   信息块不再 `flex:1`（那会让它顶到最左边、与二维码之间拉开一大段空白）。
   左侧一块信息（公司全名 / 官方网站 / 服务热线），右侧客户二维码；
   🔴 二维码按需求方要求**不写「扫码咨询」、也不加任何外框**（图片 400×400 自带白边，可直接扫），
      所以这里既没有 border/背景，也没有说明文字，只有一张图。 */
/* 右对齐的组：`margin-left:auto` + `justify-content:flex-end` ⇒ 信息块与二维码都贴面板右侧 */
.login-brand .lb-links{flex:0 0 auto;display:flex;align-items:center;justify-content:flex-end;gap:18px;margin-left:auto}
.login-brand .lb-info{flex:0 0 auto;min-width:0;display:flex;flex-direction:column;align-items:flex-end;gap:8px}
/* 公司全名（需求方 2026-09-22：「字能大点，可以不用粗体」→ 12.5px/600 改 15px/400；
   同日「二维码好了，他左边的公司信息是否也要等比例变大，否则不对称」→ 再提到 **17px/400**）。
   🔴 字重恒为 400（需求方明确不粗体），17px/400 按"正文"标准要求 4.5:1（#e2edf7 在深色面板实测 8.35:1）。 */
.login-brand .lb-info .lbi-co{font-size:17px;font-weight:400;color:#e2edf7;letter-spacing:.4px;line-height:1.3;text-align:right}
/* 每行「标签 + 值」右对齐：标签列宽固定 → 标签互相左对齐、值与值左对齐、整组右边缘齐 */
.login-brand .lb-info .lb-site, .login-brand .lb-info .lbi-hot{display:flex;align-items:baseline;gap:8px;justify-content:flex-end;min-width:0}
/* 标签列宽随字号一起放大（11 → 12.5px，"官方网站"4 字 + 字距约 58px → 列宽给 62px，保证右对齐不挤） */
.login-brand .lb-info .lbi-k{flex:0 0 62px;font-size:12.5px;color:#9dc0dc;letter-spacing:.6px}
/* 官网 / 服务热线 的值（需求方 2026-09-22：「官方网站也不要粗体，服务热线也不要粗体」→ 600 改 **400**；
   同日「等比例变大」→ 12.5 → **14px**，字重**仍为 400**）。 */
.login-brand .lb-info .lbi-v{font-size:14px;font-weight:400;color:#dbeafe;letter-spacing:.4px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.login-brand .lb-info a.lb-site{text-decoration:none;transition:opacity .15s}
.login-brand .lb-info a.lb-site:hover{opacity:.82}
.login-brand .lb-info a.lb-site:hover .lbi-v{text-decoration:underline}
/* 二维码：无框、无字、无底色 —— 只有图本身；两张并排（客户咨询 + 公众号「网越智汇栈」） */
.login-brand .lb-qrs{flex:0 0 auto;display:flex;align-items:center;gap:10px}
/* 🔴 2026-09-22 需求方：「二维码有问题，扫不出，需把二维码放大」→ 62/68px → **100px**。
   原图 400×400 PNG / 430×430 JPEG，100px 显示仍有 4 倍余量（清晰、单个码点约 2.4px，手机可扫）。
   🔴 仍**不加外框 / 不加白底 / 不写说明文字**（需求方既定口径：图片自带白边即可）。
   矮窗口（≤740px）另给 84px（见文件末尾的 max-height 媒体查询）。 */
.login-brand .lb-qr{flex:0 0 auto;width:100px;height:100px;object-fit:contain;border:0;background:none;padding:0;
  border-radius:2px;display:block}
/* 底部信息带（2026-09-22 重排 + 「ISO 放细线之上」）：
   结构 = ISO 三标签 → **一条细线** → 公司信息（含官网）+ 两张二维码（收在面板最底部）。
   🔴 细线挂在 **ISO 行的下边框**上（不是带子的上边框）—— 这样 ISO 恰好落在细线**之上**，
      细线之下只留「联系入口」，语义清楚：上面是资质，下面是联系方式。 */
/* 底栏：是面板里的**最后一段**（需求方 2026-09-22：「公司信息和二维码这一段放到底下」）。
   🔴 **不加 `margin-top:auto`** —— 加了会把"抬头/功能块/底栏"之间的余量全挤到这一段上方（实测 120px），
      反而成了"中间一大片空"。现在由容器的固定 gap 控制间距，剩余余量落在面板底部（约 44px）。 */
.brand-foot{flex:0 0 auto;display:flex;flex-direction:column;gap:12px;padding-top:0;border-top:0}
/* 资质小标题（建议项④）：与「六大业务板块」**同构** —— 3px 渐变竖条 + 中文标题。
   为什么加它：上面是"有标题的三列文本网格"、下面是"没标题的三个等宽徽章"，两块都是三列节奏却层级不明，
   看上去像重复。补上标题后两块形成一致的"小标题 + 内容"结构，重复感消失、层级清楚。
   🔴 只写中文（右侧英文小字已按需求方要求去掉，不得回归）。 */
.brand-foot .bf-cap{display:flex;align-items:center;gap:9px}
.brand-foot .bf-cap .cap-bar{flex:0 0 auto;width:3px;height:14px;border-radius:2px;
  background:linear-gradient(180deg,#38bdf8,#6366f1)}
.brand-foot .bf-cap span{font-size:14px;font-weight:600;color:#e8f1f9;letter-spacing:.6px}
/* ISO 认证徽章：细框 + 双行（标准号在上、体系名在下）。用细线徽章的语汇，不做彩色贴纸 —— 更贴合正式版式。
   🔴 2026-09-22 需求方要求**三个标签等宽** → 独立一行、每个 `flex:1 1 0` 各占 1/3（内容居中）。 */
.brand-foot .bf-iso{display:flex;gap:8px;padding-bottom:14px;border-bottom:1px solid rgba(255,255,255,.10)}
.brand-foot .iso-chip{flex:1 1 0;min-width:0;display:flex;flex-direction:column;align-items:center;gap:1px;
  padding:5px 6px;border-radius:6px;text-align:center;
  border:1px solid rgba(125,211,252,.30);background:rgba(125,211,252,.07)}
.brand-foot .iso-chip b{font-size:11.5px;font-weight:700;color:#bfe0f5;letter-spacing:.7px;line-height:1.25;white-space:nowrap}
/* 体系名是 10px 小字 → 必须过 WCAG AA 4.5:1。#93b0c8 实测只有 4.14:1（在"面板渐变 + 7% 亮蓝底"上），
   提到 #a6c3d8 实测 5.09:1；同时把 9.5px 抬到 10px，避免"徽章里的小字看不清"。
   🔴 2026-09-22 面板透明度下调（建议项⑤）后，本行实测掉到 **4.66:1**（仍达标但余量只剩 0.16），
      故再提到 **#aecbe0** 把余量补回来（探针实测见输出；这是全页最紧的一处，别再往下压）。
   等宽后每格更窄，故允许"体系名"内折行（不裁字），并收敛字距避免挤出格子。 */
.brand-foot .iso-chip i{font-style:normal;font-size:10px;color:#aecbe0;letter-spacing:0;line-height:1.35;
  white-space:normal;word-break:break-all;overflow-wrap:anywhere}

/* 矮窗口适配（建议项⑦，桌面壳最小 1120×700；2026-09-22）：
   🔴 **只收间距、不缩字号**。原本这份建议里写的是"简介回 15px、业务回 13px"，落笔时否掉了 ——
      需求方当日连续三次要求"字大点"，用缩字来适配矮窗口既会被驳回，也让最小窗口的正文更难读。
      改为：收面板内边距、业务行距、二维码尺寸（二维码是图，不是正文）。
   ⚠️ 阈值取 740px：探针（1280×860）与对比度体检都在 860 高度上跑，不受这条影响；
      守卫断言另有一条"矮窗口下字号**不得变小**"，防止以后有人用缩字来"适配"。 */
@media (max-height:740px){
  /* 🔴 矮窗口「只收间距/非文字元素、不缩字号」（需求方对字号敏感，别用缩字来适配）：块间距 44 → 26px
     ⚠️ 固定 gap 在空间不足时**不会自动压缩**（容器 overflow:hidden 会直接裁掉底部）——所以这里必须比大窗口小。 */
  .login-brand{padding:24px 34px 18px;gap:40px}
  .login-brand .lb-feat{gap:12px}
  .login-brand .lb-qr{width:84px;height:84px}
  .brand-foot{gap:10px}
  .brand-foot .bf-iso{padding-bottom:11px}
}
.login-card .row{margin-bottom:14px}
.login-card label{display:block;font-size:12.5px;font-weight:600;color:rgba(255,255,255,.72);margin-bottom:6px;letter-spacing:.4px}
/* 输入框：AIIT 同款深色半透明（白 10% 底 + 白 18% 细描边），聚焦换亮蓝描边 */
.login-card input{width:100%;padding:10px 13px;border:1px solid rgba(255,255,255,.18);border-radius:8px;outline:none;
  background:rgba(255,255,255,.10);color:#fff;transition:border-color .15s,box-shadow .15s,background .15s}
.login-card input:hover{background:rgba(255,255,255,.14)}
.login-card input:focus{border-color:#5aa2ff;background:rgba(255,255,255,.14);box-shadow:0 0 0 3px rgba(90,162,255,.20)}
.login-card input::placeholder{color:rgba(255,255,255,.42)}
.login-card .lc-row{display:flex;align-items:center;justify-content:space-between;margin:2px 0 16px}
.login-card .remember{display:flex;align-items:center;gap:7px;font-size:12.5px;color:rgba(255,255,255,.72);cursor:pointer;user-select:none;width:max-content}
/* 「记住密码」复选框：必须把上面那套输入框样式**复位**，否则会被画成一个小方块底 */
.login-card .remember input{width:auto;height:auto;margin:0;padding:0;background:none;border:0;box-shadow:none;
  accent-color:#5aa2ff;cursor:pointer}
.login-card .remember span{line-height:1}
/* 通栏渐变按钮（AIIT 同款：蓝紫渐变 + 字距；`.btn-primary` 已随本次改版下线，无其它引用方） */
/* 🔴 需求方 2026-09-22：「登录按钮不要有边框」→ 四边 border 明确置 0/none，
   连聚焦时的默认描边（Chromium 的 focus ring）也一并去掉；键盘聚焦改用**变亮**提示，不画框。 */
.login-btn{width:100%;height:42px;margin-top:2px;border:0 none;outline:0;-webkit-appearance:none;appearance:none;
  background:linear-gradient(92deg,#2f7cf0 0%,#6d5cf6 100%);background-clip:padding-box;border-radius:10px;
  color:#fff;font-size:15px;font-weight:600;letter-spacing:6px;cursor:pointer;
  box-shadow:0 10px 26px rgba(47,124,240,.34);transition:filter .15s,box-shadow .15s}
.login-btn:hover{filter:brightness(1.08);box-shadow:0 12px 30px rgba(47,124,240,.46)}
.login-btn:disabled{opacity:.7;cursor:default;box-shadow:none}
.login-btn:focus,.login-btn:focus-visible{outline:0 none;border:0 none}
.login-btn:focus-visible{filter:brightness(1.1)}
/* 卡片底部：**隐私与免责声明**（需求方 2026-09-22：「原来那几行『CrossNet IT · 全栈智维矩阵 /
   上海网越信息技术股份有限公司 · 服务热线 400-626-5185』不要再出现在登录按钮下面了，
   那个位置应当是『隐私和免责声明』」）—— 两处可点开的文本走既有 #modal。 */
.login-card .lc-legal{margin-top:14px;text-align:center;font-size:12px;line-height:1.7;color:rgba(255,255,255,.60)}
.login-card .lc-legal .sep{margin:0 3px;opacity:.8}
.login-card .lc-legal a{color:#8fc0ff;text-decoration:none;cursor:pointer}
.login-card .lc-legal a:hover{text-decoration:underline}
/* 声明弹窗正文（复用 #modal 的 .modal-box；.mb 自带 overflow:auto，长文本可滚动） */
.doc-body{font-size:13px;line-height:1.95;color:var(--text)}
.doc-body p{margin:0 0 10px}
.doc-body p:last-child{margin-bottom:0}
.doc-body b{color:#0f2a4a}
/* 版本号行：🔴 本项目**必须保留**（只放版本号，取值由 app.js 从 /api/health 取，单一真源 = package.json） */
.login-foot{margin-top:12px;padding-top:11px;border-top:1px solid rgba(255,255,255,.14);font-size:12px;color:rgba(255,255,255,.58);
  display:flex;justify-content:center;align-items:center;letter-spacing:.4px}
/* 服务端连接设置行（仅桌面壳显示）：🔴 本项目**必须保留** —— 两端对齐的信息条 */
#lg-conn{margin-top:10px;padding-top:9px;border-top:1px dashed rgba(255,255,255,.16);
  display:flex;justify-content:space-between;align-items:center;gap:10px;font-size:12px;color:rgba(255,255,255,.58)}
#lg-conn a{text-decoration:none;color:#7fb2ff;font-weight:600}
#lg-conn a:hover{text-decoration:underline}
#lg-conn #lg-mode{max-width:232px;text-align:right;line-height:1.45}
.login-err{margin-top:10px;font-size:13px;color:#fff;min-height:0;font-weight:500}
.login-err:not(:empty){background:#b91c1c;border-radius:8px;padding:9px 12px;display:block}
.login-err:empty{display:none}
/* 登录页：纯客户端角色「未设置服务器连接」时的醒目提示（需求方 2026-09-16） */
#lg-mode.warn-text{color:#fbbf24;font-weight:600}
input.err-input{border-color:#f87171 !important;box-shadow:0 0 0 3px rgba(248,113,113,.20) !important}

/* 应用外壳：左轨 232px（品牌区 + 导航）、上栏 56px。
   🔴 改这两行的高度必须同步改下方 .tbl-wrap / .topo-wrap 的 100vh 扣减常量（现为 264 / 256）。 */
#app{display:none;height:100vh;grid-template-columns:232px 1fr;grid-template-rows:56px 1fr;grid-template-areas:"brand header" "nav view"}
#app.on{display:grid}
/* 左侧栏（品牌区 + 导航）：竖向渐变材质，上端与品牌区同色以保证连续无缝 */
.brandbar{grid-area:brand;background:var(--navy);display:flex;align-items:center;gap:10px;padding:0 14px;color:#fff;
  border-bottom:1px solid rgba(255,255,255,.07);overflow:hidden}
/* 侧边栏 LOGO：与登录页同口径 —— **透明背景**（需求方 2026-09-17）。
   原来那层 `background:rgba(255,255,255,.95)` + `padding:2px` + 圆角会在深色品牌区糊出一个小白块；
   `logo/logo.jpg` 自身带 alpha，对品牌区底色（#0d2137）对比度约 4.4:1，直接透出即可。 */
.brandbar img{height:32px;width:32px;object-fit:contain;background:transparent;padding:0;flex:0 0 auto}
.brandbar .bb-text{display:flex;flex-direction:column;gap:1px;min-width:0;overflow:hidden}
.brandbar b{font-size:14px;font-weight:700;letter-spacing:.8px;white-space:nowrap;line-height:1.25}
.brandbar .bb-sub{font-size:10.5px;color:#87a6c0;letter-spacing:.6px;white-space:nowrap;line-height:1.2}
/* 侧边栏品牌文字：正式版式 = **实色白 + 字距**（渐变字在深底上偏"消费级"）。
   需求方 2026-09-17：**品牌名与下方小字之间不要横线** —— 原来的：「青蓝短线」识别色已按需求去除，
   只靠字号/字重/色彩的层次区分即可，更干净。 */
.brandbar b.brand-text{display:block}
/* 顶部工具栏 + 上方边框：与**左侧栏同色系**（需求方 2026-09-17：上方边框色与工具栏要用与侧边栏搭配的颜色）。
   取侧边栏渐变的上端色作为起点、底部压一道更深的边框色与左侧栏衔接 →
   窗口上方与左侧连成**完整的深色框架**，中部内容区保持明亮，层次更正式。 */
header.topbar{grid-area:header;background:linear-gradient(180deg,#16385a 0%,#0d2137 100%);
  border-bottom:1px solid #08182a;color:#cfe0ee;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.05);
  display:flex;align-items:center;justify-content:space-between;padding:0 20px;gap:12px}
/* 页眉左侧面包屑：深色顶栏上统一用**白色**（需求方 2026-09-17），用字重区分层级 */
.crumb{font-size:13px;color:#fff;display:flex;align-items:center;gap:9px}
.crumb b{color:#fff;font-weight:600}
/* 面包屑前的细色条：给信息条一个"版式起点" */
.crumb::before{content:'';width:3px;height:14px;border-radius:2px;flex:0 0 auto;
  background:linear-gradient(180deg,#38bdf8,#6366f1)}
/* —— 深色顶栏上的控件适配（原来的白底按钮在深色上会"糊成一块白"）—— */
.topbar .icon-btn{background:rgba(255,255,255,.07);border-color:rgba(255,255,255,.16);color:#cfe0ee}
.topbar .icon-btn:hover{background:rgba(255,255,255,.15);border-color:rgba(255,255,255,.30);color:#fff}
.topbar .icon-btn.on{background:rgba(56,189,248,.22);border-color:#38bdf8;color:#eaf7ff}
.topbar .me-btn{background:rgba(255,255,255,.07);border-color:rgba(255,255,255,.16);color:#e2eef8}
.topbar .me-btn:hover{background:rgba(255,255,255,.15);border-color:rgba(255,255,255,.30)}
.topbar .me-btn.on{background:rgba(56,189,248,.22);border-color:#38bdf8}
.topbar .btn-quit{background:rgba(255,255,255,.06);border-color:rgba(255,255,255,.18);color:#d3e1ee;
  box-shadow:none}
.topbar .btn-quit:hover{background:rgba(239,68,68,.22);border-color:#f3b0b0;color:#ffe8e8;box-shadow:none}
.topbar .pill{background:rgba(56,189,248,.16);border-color:rgba(56,189,248,.40);color:#bfe6ff}
.topbar .pill.danger{background:rgba(239,68,68,.20);border-color:rgba(248,113,113,.50);color:#ffd9d9}
/* ⚠️ 这里历史上还有一条 `.crumb b{color:var(--text)}`（深色）—— 自顶栏改深色后它会**覆盖**上面的白色规则，
   导致面包屑粗体部分仍是深色、在深底上看不清。已删除（2026-09-17 顶栏配色改造时一并清理）。 */
.topbar .right{display:flex;align-items:center;gap:6px;font-size:13px}
/* 页眉右侧账号名：**缩略显示**（需求方 2026-09-17："页面显示要缩略，不用很长"）；
   公司 / 所在组织 / 主部门等完整信息移到「个人信息」浮窗里。 */
.topbar .right #p-user{font-size:12.5px;font-weight:600;color:#e8f1f8;max-width:92px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pill{display:inline-flex;align-items:center;gap:6px;padding:3px 10px;border-radius:999px;font-size:12px;background:var(--accent-l);color:#0b5f75;border:1px solid #bae6fd}
.pill.warn{background:#fef3c7;border-color:#fcd34d;color:#92400e}
.pill.gray{background:#f1f5f9;border-color:#e2e8f0;color:#64748b}
.dot{width:7px;height:7px;border-radius:50%;background:#22c55e;display:inline-block}
.dot.off{background:#94a3b8}
.pill.danger{background:#fdecec;border-color:#f3c9c9;color:#b3261e}

/* ===== 页眉右侧按钮组（2026-09-17：缩略 + 记事本 / 计算器 / 个人信息 / 退出） =================
   图标一律用**内联 SVG 线性图标**（商务风，不依赖图标字体/网络，离线也正常）。 */
.icon-btn{width:32px;height:32px;flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;
  border:1px solid var(--line2);border-radius:8px;background:var(--card);color:#43607d;cursor:pointer;
  transition:background .13s,border-color .13s,color .13s}
.icon-btn:hover{background:#f3f8fd;border-color:#b9cfe2;color:#1d4ed8}
.icon-btn.on{background:#e8f1ff;border-color:#93b8e8;color:#1d4ed8}
.icon-btn svg{width:17px;height:17px;display:block}
/* 字母图标（记事本 EM，需求方 2026-09-17 指定用字母而非图形） */
.icon-btn .txt-ico{font-size:11.5px;font-weight:700;letter-spacing:.6px;line-height:1}
.me-btn{display:inline-flex;align-items:center;gap:7px;height:32px;padding:0 11px 0 5px;flex:0 0 auto;
  border:1px solid var(--line2);border-radius:999px;background:var(--card);cursor:pointer;
  font-family:inherit;font-size:12.8px;color:var(--text);max-width:158px;
  transition:background .13s,border-color .13s}
.me-btn:hover{background:#f3f8fd;border-color:#b9cfe2}
.me-btn.on{background:#e8f1ff;border-color:#93b8e8}
.me-av{width:23px;height:23px;flex:0 0 auto;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;
  background:linear-gradient(135deg,#1d4ed8,#4f46e5);color:#fff;font-size:11.5px;font-weight:600}
.me-nm{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.btn-quit{display:inline-flex;align-items:center;gap:6px;height:32px;padding:0 13px;flex:0 0 auto;border-radius:8px;
  border:1px solid #cbd9e8;background:linear-gradient(180deg,#ffffff,#f4f8fc);color:#3f5670;cursor:pointer;
  font-family:inherit;font-size:12.8px;letter-spacing:.3px;
  box-shadow:0 1px 2px rgba(16,38,60,.05);transition:all .13s}
.btn-quit:hover{border-color:#e2a9a9;background:linear-gradient(180deg,#fff6f6,#ffeaea);color:#b3261e;
  box-shadow:0 2px 6px rgba(179,38,30,.12)}
.btn-quit svg{width:16px;height:16px;display:block}

/* ===== 页眉浮窗（记事本 / 计算器 / 个人信息共用） ================= */
#hdr-pop{position:fixed;top:62px;right:16px;z-index:40;width:322px;
  background:var(--card);border:1px solid var(--line);border-radius:12px;
  box-shadow:0 18px 46px rgba(16,38,60,.18);padding:14px}
#hdr-pop[hidden]{display:none}
.hp-t{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:10px}
.hp-t b{font-size:13.5px;font-weight:600;color:var(--text)}
.hp-x{border:0;background:none;color:var(--muted);cursor:pointer;font-size:15px;line-height:1;padding:2px 4px}
.hp-x:hover{color:var(--text)}

/* 个人信息卡 */
.me-card{display:flex;gap:11px;align-items:center;padding-bottom:11px;margin-bottom:11px;border-bottom:1px solid var(--line)}
.me-av-lg{width:40px;height:40px;flex:0 0 auto;border-radius:50%;display:flex;align-items:center;justify-content:center;
  background:linear-gradient(135deg,#1d4ed8,#4f46e5);color:#fff;font-size:16px;font-weight:600}
.me-info b{font-size:14px;display:block;color:var(--text)}
.me-info span{font-size:12px;color:var(--muted)}
.me-row{display:flex;gap:8px;font-size:12.5px;margin-bottom:8px;align-items:flex-start}
.me-row .k{color:var(--muted);flex:0 0 60px;padding-top:1px}
.me-row .v{flex:1;min-width:0;color:var(--text);word-break:break-all}
.me-orgs{display:flex;flex-wrap:wrap;gap:5px}
.me-org{display:inline-flex;align-items:center;gap:4px;border:1px solid var(--line2);border-radius:999px;
  padding:2px 8px;font-size:11.8px;background:#fafcfe;color:var(--text)}
.me-org.primary{border-color:#93b8e8;background:#eef4ff;color:#1d4ed8;font-weight:500}
.me-org button{border:0;background:none;color:#1d4ed8;cursor:pointer;font-size:11px;font-family:inherit;padding:0 0 0 1px}
.me-org button:hover{text-decoration:underline}
.hp-foot{margin-top:11px;padding-top:11px;border-top:1px solid var(--line);display:flex;justify-content:flex-end;gap:8px}

/* 记事本：**单列 + 段落符号 / 勾选框**（需求方 2026-09-22 改版：「四象限不要了，可插勾选框和段落符号，
   勾选框名字叫办结，勾了后该勾选框相关的段落出现删除线」）—— 一列一条、放不下就滚动 */
#hdr-pop.wide{width:452px}
/* 按日期翻页条（需求方 2026-09-22：「记事本根据日期左右翻页」）：← 日期 → ，今天加标记、历史给「回今天」 */
.note-day{display:flex;align-items:center;gap:8px;margin:0 0 8px;padding:5px 8px;
  border:1px solid var(--line2);border-radius:9px;background:var(--soft2)}
.note-day .btn.sm{padding:2px 9px;line-height:1.5}
.note-day-t{font-size:13px;color:#0f2a4a;letter-spacing:.4px;font-variant-numeric:tabular-nums}
.note-today{font-style:normal;font-size:10.5px;color:#1d4ed8;background:#eef4ff;border:1px solid #cddff8;
  border-radius:999px;padding:1px 7px}
.note-back{margin-left:auto;font-size:11.5px;color:#1d4ed8;text-decoration:none}
.note-back:hover{text-decoration:underline}
.note-none{padding:12px 6px;font-size:12.5px;color:#94a3b8;text-align:center}
.note-list{display:flex;flex-direction:column;gap:6px;max-height:46vh;overflow:auto;padding-right:2px}
.note-badge{margin-right:auto;font-size:10.5px;letter-spacing:.2px;color:#1d4ed8;
  background:#eef4ff;border:1px solid #cddff8;border-radius:999px;padding:1px 8px;white-space:nowrap}
.note-row{display:flex;align-items:flex-start;gap:7px;border:1px solid var(--line2);border-radius:9px;
  padding:5px 8px;background:#fff}
.note-row:focus-within{border-color:var(--accent);box-shadow:0 0 0 3px rgba(14,116,144,.1)}
/* 🔴 「段落符号（•）/ 勾选框（办结）/ 勾上办结加删除线」三套样式已**删除**（需求方 2026-09-22：
   「页眉记事本不要段落符号和选框的功能了」）—— 同时删掉的类：`.note-mark`、`.note-mark.none`、
   `.note-todo`、`.note-todo input`、`.note-row.done .note-area`（删功能要连死样式一起清，别留下没人用的规则）。 */
.note-row .note-area{flex:1 1 auto;min-width:0;min-height:30px;max-height:34vh;resize:none;overflow:auto;
  box-sizing:border-box;padding:4px 2px;border:0;border-radius:0;outline:none;
  font-family:inherit;font-size:12.5px;line-height:1.7;color:var(--text);background:transparent}
.note-row .note-area::placeholder{color:#b7c3d0}
.note-row .note-del{flex:0 0 auto;border:0;background:none;color:#b0bece;cursor:pointer;
  font-size:14px;line-height:1;padding:2px 4px;margin-top:1px}
.note-row .note-del:hover{color:#b3261e}
.note-bar{display:flex;align-items:center;gap:6px;margin-top:9px}
.note-bar .pg{margin-left:auto;font-size:12px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

/* 计算器 */
.calc-disp{background:#f5f8fc;border:1px solid var(--line);border-radius:9px;padding:9px 11px;text-align:right;margin-bottom:9px}
.calc-expr{font-size:11.5px;color:var(--muted);min-height:15px;word-break:break-all;line-height:1.4}
.calc-val{font-size:24px;font-weight:600;letter-spacing:.4px;color:var(--text);word-break:break-all;line-height:1.3}
.calc-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:6px}
.calc-grid button{height:38px;border:1px solid var(--line2);border-radius:8px;background:var(--card);cursor:pointer;
  font-size:14px;font-family:inherit;color:var(--text);transition:background .12s,border-color .12s}
.calc-grid button:hover{background:#f3f8fd}
.calc-grid button.fn{background:#f1f5fa;color:#43607d;font-size:13px}
.calc-grid button.op{background:#eef4ff;color:#1d4ed8;font-weight:600}
.calc-grid button.eq{background:linear-gradient(180deg,#2563eb,#1d4ed8);color:#fff;border-color:#1d4ed8;font-weight:600}
.ghost{padding:6px 12px;border:1px solid var(--line2);background:var(--card);border-radius:7px;cursor:pointer;color:var(--label)}
.ghost:hover{border-color:var(--accent);color:var(--accent)}

/* ===== 侧边栏（需求方 2026-09-17：主菜单加正式 SVG 图标 + 主/子菜单字号统一美化）==========
   字号收敛成**两档**（原来 11px 与 13.2px 混排，看起来大小不一）：
     · 主菜单（顶级项 + 分组标题）= 13px / 500 / #d3e1ee —— **同一档**，视觉一致
     · 子菜单                       = 12.6px / 400 / #bccfe0 —— 缩进对齐，从属关系明确
   图标：主菜单 = SVG（.mi，17px，统一 1.7 线宽）；子菜单 = 字符（.ic）—— 形态不同，不会混淆。 */
nav.side{grid-area:nav;background:linear-gradient(180deg,#0d2137 0%,#14314f 48%,#1d2b5c 100%);overflow:auto;padding:8px 0 24px}

/* ---- 主菜单：分组标题（可折叠）---- */
/* 左内边距 22px（需求方 2026-09-17：原 14px 太贴边，整体右移） */
nav.side .grp{padding:12px 22px 6px;font-size:13px;font-weight:500;color:#d3e1ee;letter-spacing:.4px;
  display:flex;align-items:center;gap:9px;cursor:pointer;user-select:none;transition:color .13s}
nav.side .grp:hover{color:#fff}
nav.side .grp .grp-t{flex:0 1 auto;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* 展开/收起箭头（需求方 2026-09-17 优化）：
   改用**统一线宽的 SVG chevron**（原先的字符 `▾` 只有 9px、又小又糊）；
   尺寸 13px、线宽 2.2 与主菜单图标同一套观感；紧跟标题文字右侧、空开一个字符宽。
   ⚠️ 不要用 `justify-content:space-between` 或让标题 `flex:1` —— 那会把箭头推到行尾。 */
nav.side .grp .grp-c{width:15px;height:15px;flex:0 0 auto;margin-left:1ch;color:#8fb0c9;
  display:inline-flex;align-items:center;justify-content:center;
  transform:rotate(-90deg);transition:transform .18s ease,color .13s}
nav.side .grp .grp-c svg{width:13px;height:13px;display:block}
nav.side .grp:hover .grp-c{color:#dceaf6}
nav.side .grp.open .grp-c{transform:none;color:#7ed4f8}
nav.side .grp-items[hidden]{display:none}

/* ---- 主菜单：顶级项（无分组，永远可见）---- */
nav.side .top-items{display:block}

/* ---- 图标：主菜单 = SVG，子菜单 = 字符 ---- */
nav.side .mi{width:17px;height:17px;flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;opacity:.9}
nav.side .mi svg{width:17px;height:17px;display:block}
nav.side .grp.open .mi{color:#7ed4f8}
nav.side a.on .mi{opacity:1}

nav.side a{display:flex;align-items:center;gap:9px;color:#bccfe0;text-decoration:none;font-size:12.6px;
  padding:8px 18px 8px 44px;cursor:pointer;border-left:3px solid transparent;transition:background .13s,color .13s}
nav.side .top-items a{padding:10px 22px;font-size:13px;font-weight:500;color:#d3e1ee}
nav.side a:hover{background:rgba(255,255,255,.07);color:#fff}
nav.side a.on{background:rgba(255,255,255,.12);color:#fff;border-left-color:#38bdf8}
nav.side a .ic{width:16px;text-align:center;font-size:12.5px;opacity:.8;flex:0 0 auto}
nav.side a .lb{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
nav.side a .tag{margin-left:auto;font-size:11px;background:#1b4a6b;color:#9fd8ee;border-radius:999px;padding:0 7px}
/* 未授权菜单（需求方 2026-09-16：菜单全部显示，未授权的置灰加锁；点进去工作区大字提示） */
nav.side a.off{color:#7b8ea3}
nav.side a.off:hover{color:#a9bccf}
nav.side a .lk-ico{margin-left:auto;font-size:10.5px;opacity:.75;filter:grayscale(1)}
/* 「未授权，请联系贵司管理员」提示页（工作区大字） */
.noperm-box{display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:380px;gap:12px;text-align:center}
.noperm-lock{font-size:42px;line-height:1;opacity:.9;filter:grayscale(.35)}
.noperm-t{font-size:38px;font-weight:800;letter-spacing:6px;color:#1e293b}
.noperm-s{font-size:19px;font-weight:500;color:#475569;letter-spacing:1px}
.noperm-n{font-size:12.5px;color:#94a3b8;margin-top:6px}
/* 「流程中心 · 重新设计中」占位页（需求方 2026-09-17）：
   与「未授权」页共用同一套大字版式，但**另起类名**（语义不同：一个是权限，一个是建设中，
   混用会让后来人以为"没权限"）。 */
.soon-box{display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:380px;gap:12px;text-align:center}
.soon-ico{font-size:40px;line-height:1;color:#94a3b8;opacity:.85;display:inline-flex;align-items:center;justify-content:center}
.soon-ico svg{width:46px;height:46px;display:block}
.soon-t{font-size:38px;font-weight:800;letter-spacing:6px;color:#1e293b}
.soon-s{font-size:19px;font-weight:500;color:#475569;letter-spacing:1px}
.soon-n{font-size:12.5px;color:#94a3b8;margin-top:6px}

/* 内容区版式（需求方 2026-09-18 追加口径）：**只有「创建工单 / 新建工单」用 A4 版心**，
   其余页面保持满屏 —— 建单页整页包在 `.a4-wrap` 里（210mm ≈ 794px，居中）。
   🔴 `--tk-scale` = **整体缩放**（`zoom`，字号/控件/间距一起放大缩小），由工作区**最右侧**的 − / + 调节；
      不是只改宽高。默认 1 = 正 A4（见 app.js 的 tkZoom / tkScaleVal）。 */
main#view{grid-area:view;overflow:auto;padding:18px 20px 40px}
/* 工作区全屏（需求方 2026-09-19）：只把日历铺满整屏 —— 页眉与左侧边栏不在 #view 内，天然不显示；
   退出走浏览器原生 ESC，或再点一次「退出全屏」按钮。 */
main#view:fullscreen{background:#eef2f6;padding:24px 28px 40px;overflow:auto}
.a4-wrap{max-width:var(--a4);margin:0 auto;zoom:var(--tk-scale, 1)}
/* 缩放控件：**固定在工作区最右侧**（不放页眉 / 不压在工单上），竖排 ＋ / 比例 / −。
   🔴 必须放在 `.a4-wrap` **之外**（在缩放容器内会被一起缩放 → 按钮自己变大变小）。 */
/* 缩放控件（需求方 2026-09-19 二改：「＋− 太大了，要**分离的小按钮**」）——
   ＋ / − 各自独立成一个小圆角按钮（26×26），中间夹一个百分比小标；三者互不相连、各留 6px 间距，不再有外框罩着。 */
.tk-zoom{position:fixed;right:18px;top:96px;z-index:30;display:flex;flex-direction:column;align-items:center;gap:6px}
.tk-zoom .tk-zbtn{width:26px;height:26px;border:1px solid var(--line2);border-radius:8px;background:var(--card);
  color:var(--btn-tx);font-size:15px;line-height:1;cursor:pointer;padding:0;box-shadow:0 1px 3px rgba(15,23,42,.07);
  transition:border-color .15s,color .15s,box-shadow .15s}
.tk-zoom .tk-zbtn:hover:not(:disabled){border-color:var(--accent);color:var(--accent);box-shadow:0 2px 6px rgba(37,99,235,.16)}
.tk-zoom .tk-zbtn:disabled{color:#c3ced9;cursor:not-allowed;box-shadow:none}
.tk-zoom b{min-width:26px;padding:2px 5px;border:1px solid var(--line2);border-radius:7px;background:var(--card);
  text-align:center;font-size:10.5px;font-weight:600;color:var(--muted);font-variant-numeric:tabular-nums}
/* 编辑工单（需求方 2026-09-20）：**基础信息整块只读** —— 字段灰底、不可编辑，并把原因写在标题右侧 */
.tk-locknote{margin-left:10px;font-size:12px;font-weight:600;color:#b45309}
.tk-ro,.tk-ro:disabled{background:#f1f5f9 !important;color:#64748b !important;cursor:not-allowed !important}
select.tk-ro,.tk-ro:disabled{opacity:1}
/* 「延长解决」= **SLA适配 标题右边的小按钮**（需求方 2026-09-20：「应该是小按钮，放在 SLA适配 标题的右边」）——
   标题行改成**横向一行**：标题（下划线只跟文字一样长）+ 迷你按钮紧跟其后 + 已延长提示。 */
/* ⚠️ 必须用 id 选择器（或 .form .f.tk-sla-hd）压过 `.form .f{flex-direction:column}`：
   用 `.tk-sla-hd` 单独一条会**被 `.form .f` 的 specificity 压掉** → 按钮仍掉到第二行（本轮踩过）。
   `align-items:baseline` = 按钮上的字与「SLA适配」几个字**按文字基线对齐**（需求方 2026-09-20）。 */
#tk-sla-title,.form .f.tk-sla-hd{flex-direction:row;align-items:baseline;flex-wrap:wrap}
#tk-sla-title .sub-t{display:inline-block;width:auto;margin:0}
#tk-sla-title .tk-mini{margin-left:10px}
/* 「延长解决」小按钮：**浅蓝渐变底**（需求方 2026-09-20）——
   用 `#tk-sla-title .tk-mini` 是为了压过 `.btn` 的底色（两者 specificity 相同时看源码先后，不可靠）。 */
#tk-sla-title .tk-mini{height:24px;padding:0 10px;font-size:11.5px;line-height:22px;font-weight:600;border-radius:7px;
  background:linear-gradient(180deg,#eaf4ff 0%,#d3e7fd 100%);border:1px solid #b3d2f2;color:#1d4ed8;
  box-shadow:0 1px 2px rgba(29,78,216,.10)}
#tk-sla-title .tk-mini:hover{background:linear-gradient(180deg,#e0f0ff 0%,#c3defb 100%);border-color:#8fb8ea;color:#1a45c2}
/* 查阅模式（只读）：分段按钮 / SLA 档位卡一律点不动（外观保持，能看清选的是哪一项） */
.tk-seg-off{pointer-events:none;opacity:.9}
/* 查阅 / 编辑页的「工单流转记录」（需求方 2026-09-20：放在「SLA适配」区块**下面**）——
   与详情抽屉里的时间线同一套 `.steps` 渲染，这里只给一层浅底容器，读起来像一张卡。 */
.tk-log{border:1px solid var(--line);border-radius:10px;background:#fbfdff;padding:12px 14px}
.tk-log .steps{max-height:none}
/* ---- 建单页「SLA适配」（需求方 2026-09-19）：档位卡**一行 5 个** · 考核卡**一行 3 个** · 两类卡片同一尺寸口径 ---- */
/* 服务范围不支持时的**带背景色警示**（需求方 2026-09-19）：横在服务方式那一行下方、居中 */
.tk-nosla{margin-top:8px;padding:9px 12px;border:1px solid #fcd34d;border-radius:9px;background:#fef3c7;color:#92400e;font-size:12.5px;font-weight:600;text-align:center;letter-spacing:.2px}
/* 补建工单（需求方 2026-10-09）：时间轴补录区 = **按流程顺序的竖排列表**（每行一个节点，
   行内可带"处理人 / 处置结果"等附加控件），窄屏自动落成一列 */
.tk-bf-list{display:flex;flex-direction:column;gap:8px;margin-top:6px}
.tk-bf-row{display:grid;grid-template-columns:22px 84px 190px minmax(0,1fr);align-items:center;gap:8px;
  padding:6px 10px;border:1px solid var(--line);border-radius:9px;background:#fbfcfd}
.tk-bf-row>i{width:20px;height:20px;line-height:20px;text-align:center;border-radius:50%;background:#2563eb;color:#fff;
  font-size:11.5px;font-style:normal;font-weight:600}
.tk-bf-row>label{margin:0;font-size:12.5px;color:var(--fg);white-space:nowrap}
.tk-bf-row input[type=datetime-local],.tk-bf-row select{width:100%;min-width:0;font-size:12.5px}
.tk-bf-row select{max-width:260px}
.tk-bf-row textarea{grid-column:3/-1;width:100%;min-width:0;font-size:12.5px;resize:vertical}
/* 🔴 说明文字必须**独占一行、从标签列跨到最右**（需求方 2026-10-09：「保留注释吧，但是文字不要竖排」）——
   原来没给它定位：带下拉的那两行（响应派单 / 处置结果）**有 5 个子元素**，而栅格只有 4 列
   ⇒ 说明被自动换到下一行的**第 1 列（仅 22px 宽）** ⇒ 一个字一行 = 竖排。定位后就横排了。 */
.tk-bf-row>em{grid-column:2/-1;font-size:11.5px;color:var(--muted);font-style:normal;line-height:1.5;white-space:normal}
.tk-bf-row input[type=datetime-local]+select{justify-self:start}
@media (max-width:900px){.tk-bf-row{grid-template-columns:22px 1fr;grid-auto-rows:auto}
  .tk-bf-row>label,.tk-bf-row>input,.tk-bf-row>select,.tk-bf-row>textarea,.tk-bf-row>em{grid-column:2}}
#tk-bf-cell{border-top:1px dashed var(--line);padding-top:10px;margin-top:10px}
.tk-sla-tip{font-size:11.5px;color:var(--muted);padding:0 0 4px}
.tk-sla-tiers{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:8px}
.tk-sla-btn{display:flex;flex-direction:column;align-items:flex-start;gap:2px;min-width:0;
  padding:6px 9px;border:1px solid var(--line2);border-radius:9px;background:var(--card);cursor:pointer;
  text-align:left;transition:border-color .15s,box-shadow .15s}
.tk-sla-btn:hover{border-color:var(--accent);box-shadow:0 2px 8px rgba(37,99,235,.10)}
.tk-sla-btn b{font-size:12.5px;line-height:1.15;color:var(--text)}
.tk-sla-btn span{font-size:10.5px;color:var(--accent);line-height:1.2}
.tk-sla-btn em{font-style:normal;font-size:10px;color:var(--muted);line-height:1.25}
.tk-sla-btn.on{border-color:#0e7490;background:#ecfeff;box-shadow:0 0 0 2px rgba(14,116,144,.14)}
.tk-sla-btn.on b,.tk-sla-btn.on span{color:#0e7490}
.tk-sla-bar{margin-top:9px;border:1px solid var(--line2);border-left:3px solid var(--accent);border-radius:10px;
  padding:8px 10px;background:var(--card)}
.tk-sla-start{font-size:11.5px;color:var(--muted);margin-bottom:7px;display:flex;align-items:baseline;gap:8px;flex-wrap:wrap}
.tk-sla-start b{color:var(--text);font-size:12px;font-variant-numeric:tabular-nums}
.tk-sla-of{color:var(--muted);font-size:10.5px}
.tk-sla-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px}
.tk-sla-cell{min-width:0;padding:6px 9px;border:1px solid var(--line2);border-radius:9px;background:var(--card);
  display:flex;flex-direction:column;gap:2px}
.tk-sla-ch{display:flex;align-items:baseline;gap:4px}
.tk-sla-cell i{font-style:normal;font-size:11px;color:var(--accent);font-weight:600;line-height:1.15}
.tk-sla-cell b{font-size:11px;color:var(--label);line-height:1.2}
.tk-sla-cell span{font-size:12.5px;font-weight:600;color:var(--text);font-variant-numeric:tabular-nums;line-height:1.25}
.tk-sla-cell span.none{font-size:11.5px;font-weight:400;color:var(--muted)}
.tk-sla-cell em{font-style:normal;font-size:10px;color:var(--muted);line-height:1.25}
.tk-sla-loading{font-size:12.5px;color:var(--muted)}
.tk-sla-warn{font-size:12.5px;color:var(--red)}
.page-head{display:flex;align-items:flex-end;justify-content:space-between;gap:12px;margin-bottom:14px;flex-wrap:wrap}
.page-head h2{margin:0;font-size:var(--fs-h2);font-weight:var(--fw-title)}
.page-head .desc{color:var(--muted);font-size:12.5px;margin-top:3px}
.toolbar{display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.toolbar input,.toolbar select{padding:7px 10px;border:1px solid var(--line2);border-radius:7px;background:var(--card);color:var(--text);min-width:120px}
.btn{padding:7px 13px;border-radius:7px;border:1px solid var(--line2);background:var(--card);cursor:pointer;color:var(--btn-tx)}
.btn:hover{border-color:var(--accent);color:var(--accent)}
.btn.pri{background:linear-gradient(90deg,#0e7490,#2563eb);border:0;color:#fff}
.btn.pri:hover{filter:brightness(1.07)}
.btn.danger{color:var(--red);border-color:#f3c3c3}
.btn.danger:hover{background:#fef2f2}
.btn:disabled,.btn[disabled]{opacity:.45;cursor:not-allowed;filter:none}
.btn.danger:disabled,.btn.danger[disabled]{color:var(--muted);border-color:var(--line2);background:transparent}
/* 连体输入组（拓扑检索框 + 「突显节点」按钮）：边框拼成一体，看起来是一个控件 */
/* 工具栏右侧按钮组（需求方 2026-09-19：「新建按钮和派单设置按钮靠右边框」）
   🔴 2026-09-22 需求方报「工单列表后面的刷新、新增和派单设置按钮都换行了」——
   根因：`margin-left:auto` 在 flex-wrap 容器里会让这一组**被推到独立一行**
   （auto 外边距要吃掉整行剩余空间 → 换行算法判它放不下）。
   改成 `flex:1 1 auto` + `justify-content:flex-end`：它在当前行里吸收剩余空间、把按钮顶到右端
   （仍满足"靠右边框"），只有本行真的挤不下时才换行。 */
.toolbar .tb-right{flex:1 1 auto;margin-left:6px;display:inline-flex;gap:8px;align-items:center;justify-content:flex-end}
/* 🔴 工单管理工具栏**两段式**（需求方 2026-09-22：「刷新、新增和派单设置按钮都换行了」）——
   工单检索区控件多（1 号检索 + 7 个下拉 + 4 个功能键 + 右侧 3 键），窄窗口下筛选区自己就要占 2~3 行；
   只要右侧按钮组和筛选控件排在**同一条行流**里，它就会被挤到下面单独一行去（这正是需求方看到的现象）。
   所以工单页（`.page-head.tk-bar`，由 viewCrud 只在工单时挂）把工具栏拆成两段：
     · `.tb-filters` = 筛选控件区，**自己换行**（行数随窗口自适应）；
     · `.tb-right`   = 右侧按钮组，`flex:none` + 顶对齐 → **永远钉在第一行右端、不换行**。
   只作用于工单页；其它列表页不加 `.tk-bar`，结构/顺序/宽度完全照旧。 */
.page-head.tk-bar .toolbar{flex-wrap:nowrap;align-items:flex-start}
.toolbar .tb-filters{flex:1 1 auto;min-width:0;display:flex;flex-wrap:wrap;gap:8px;align-items:center}
.page-head.tk-bar .toolbar .tb-right{flex:none;margin-left:10px}
.toolbar .join{display:inline-flex;align-items:stretch}
.toolbar .join>input{border-radius:7px 0 0 7px}
.toolbar .join>.btn{border-radius:0 7px 7px 0;margin-left:-1px;white-space:nowrap}
/* 拓扑检索框的**候选下拉**（输入即出，快捷选择）：限宽限高、内部可滚动 */
.toolbar .join.tsearch{position:relative}
.tsug{position:absolute;top:calc(100% + 3px);left:0;z-index:60;width:380px;max-height:268px;overflow:auto;
  background:var(--card);border:1px solid var(--line2);border-radius:9px;padding:4px;
  box-shadow:0 12px 28px rgba(15,35,60,.16)}
.tsug-opt{display:flex;flex-direction:column;gap:1px;padding:6px 9px;border-radius:6px;cursor:pointer}
.tsug-opt:hover,.tsug-opt.on{background:var(--accent-soft)}
.tsug-opt b{font-weight:500;font-size:12.4px;color:#1f2b38}
.tsug-opt .mini{font-size:11.5px;color:var(--muted)}
.tsug-tip{padding:5px 9px 3px;margin-top:3px;font-size:11.4px;color:var(--muted);border-top:1px dashed var(--line)}
/* 候选面板顶部的**已选 chips**（检索结果可多选：点标签或 × 移除、一键清空） */
.tsug-chips{display:flex;flex-wrap:wrap;align-items:center;gap:4px;padding:5px 6px 7px;border-bottom:1px dashed var(--line);margin-bottom:3px}
.tchip{display:inline-flex;align-items:center;gap:4px;max-width:232px;padding:2px 7px;border-radius:11px;
  background:linear-gradient(90deg,#bae6fd,#e0f2fe);color:#0b3d5c;font-size:11.5px;cursor:pointer;white-space:nowrap;overflow:hidden}
.tchip b{font-weight:500;overflow:hidden;text-overflow:ellipsis}
.tchip i{font-style:normal;color:#0284c7;font-weight:700}
.tchip:hover{filter:brightness(.97)}
.tsug-clear{margin-left:auto;font-size:11.4px;color:var(--muted);cursor:pointer;white-space:nowrap}
.tsug-clear:hover{color:var(--accent)}
/* 突显按钮的"已开启"态：天蓝实心，与画布上的天蓝呼吸呼应 */
.btn.on{background:linear-gradient(90deg,#0284c7,#0ea5e9);border-color:#0284c7;color:#fff}
.btn.on:hover{filter:brightness(1.06);color:#fff}
/* 「影响分析」按钮的"已开启"态：红色实心（与故障源的红呼应） */
#tflt.on{background:linear-gradient(90deg,#b91c1c,#dc2626);border-color:#b91c1c;color:#fff}
#tflt.on:hover{filter:brightness(1.08);color:#fff}
/* 工具栏里的竖向分隔（把"筛选/刷新"与"模拟故障"分开） */
.toolbar .tb-sep{display:inline-block;width:1px;height:20px;background:var(--line2);margin:0 2px}
.btn.sm{padding:4px 9px;font-size:12px}
/* 数据表格：显式声明 table 布局，避免被其它工具类影响 */
table.dtbl{table-layout:auto;width:100%}
/* 批量删除：勾选列与选中行（仅列表页的表格，避免影响抽屉里的展示表格） */
table.dtbl th:first-child,table.dtbl td:first-child{width:38px;text-align:center}
table.dtbl input[type=checkbox]{width:15px;height:15px;cursor:pointer;vertical-align:middle;accent-color:var(--accent)}
table.dtbl tbody tr.sel{background:#f0f9ff}
table.dtbl tbody tr.sel:hover{background:#e6f4fe}
/* 点击整行查看详情：整行可点、有手型与悬停反馈 */
table.dtbl tbody tr.rowlink{cursor:pointer}
table.dtbl tbody tr.rowlink:hover:not(.sel){background:#f7fbff}
/* 列宽拖动 handle：贴在表头右边界内侧，拖动调整该列宽度（双击恢复）
   注意：把手必须完整落在本列 th 内 —— 若跨到右边界外，会压到相邻表头上，点不中自己 */
table.dtbl th .colrs{position:absolute;top:0;right:0;width:8px;height:100%;z-index:3;cursor:col-resize}
table.dtbl th .colrs::after{content:'';position:absolute;right:2px;top:22%;height:56%;width:1px;background:#dbe4ee}
table.dtbl th .colrs:hover::after,table.dtbl th .colrs:active::after{background:var(--accent);width:2px}
/* 拖动过程中：全局保持列宽光标、禁止选中文字 */
body.colresizing{cursor:col-resize;user-select:none}
body.colresizing *{cursor:col-resize !important}
/* 列表工具条：弹出面板（列设置 / 批量操作） */
.pop-wrap{position:relative;display:inline-block}
.pop-panel{position:absolute;right:0;top:calc(100% + 6px);z-index:40;min-width:230px;max-height:62vh;overflow:auto;
  background:var(--card);border:1px solid var(--line2);border-radius:10px;box-shadow:0 12px 32px rgba(16,38,60,.18);padding:6px}
.pp-head{padding:7px 9px;font-size:12px;color:var(--muted);border-bottom:1px solid var(--line);margin-bottom:4px;white-space:nowrap}
.pp-body{display:flex;flex-direction:column;gap:2px;padding:2px}
.pp-item{display:flex;align-items:center;gap:8px;padding:6px 9px;border-radius:7px;font-size:13px;cursor:pointer;white-space:nowrap}
.pp-item:hover{background:#f3f7fc}
.pp-item input[type=checkbox]{width:15px;height:15px;margin:0;padding:0;accent-color:var(--accent);cursor:pointer}
.pp-item input[type=checkbox][disabled]{cursor:default;opacity:.55}
/* 列设置：每一列一行（勾选框 + 列名 + 上移/下移），整行可拖动排序 */
.pp-col{display:flex;align-items:center;gap:2px;border-radius:7px;cursor:grab}
.pp-col:hover{background:#f3f7fc}
.pp-col.dragging{opacity:.45}
.pp-col .pp-item{flex:1;min-width:0;padding-right:2px}
.pp-col .pp-item .pp-name{overflow:hidden;text-overflow:ellipsis}
.pp-ctrl{display:flex;gap:2px;padding-right:4px}
.pp-ctrl .btn.sm{padding:1px 6px;line-height:1.3}
/* 列表行右键菜单 */
.ctxmenu{position:fixed;z-index:60;min-width:170px;background:#fff;border:1px solid var(--line);border-radius:9px;
  box-shadow:0 8px 24px rgba(15,32,56,.16);padding:4px;font-size:13px}
.ctx-item{padding:7px 10px;border-radius:7px;cursor:pointer;color:#25384d;white-space:nowrap}
.ctx-item:hover{background:#f1f6fc}
.ctx-item.sep{margin-top:4px;border-top:1px solid var(--line);padding-top:8px}
.pp-act{display:block;width:100%;text-align:left;padding:8px 9px;border:0;background:transparent;border-radius:7px;font-size:13px;color:var(--text);cursor:pointer;white-space:nowrap}
.pp-act:hover{background:#f3f7fc}
.pp-act.danger{color:var(--red)}
.pp-act.danger:hover{background:#fef2f2}
.pp-foot{display:flex;gap:6px;padding:6px 4px 2px;border-top:1px solid var(--line);margin-top:4px}
/* 可排序表头 */
th.sortable{cursor:pointer;user-select:none}
th.sortable:hover{background:#eef4fb;color:var(--navy3)}
th.sortable .arw{font-style:normal;margin-left:5px;font-size:10px;opacity:.38}
th.sortable .arw.on{opacity:1;color:var(--accent)}
.pop-wrap .caret{font-style:normal;font-size:10px;opacity:.7;margin-left:2px}

.card{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow)}
.card+.card{margin-top:14px}
/* 网格/栅格里同一行的卡片是并排关系，不能吃「堆叠间距」——否则右侧卡片会比左侧低 14px（曾导致
   「数据健康检查」与「配置项分类分布」明显不对齐） */
.grid>.card+.card{margin-top:0}
.card h3{margin:0;padding:12px 16px;border-bottom:1px solid var(--line);font-size:var(--fs-title);font-weight:var(--fw-title);display:flex;justify-content:space-between;align-items:center;gap:10px}
.card h3 .mini{font-size:var(--fs-hint);font-weight:var(--fw-body)}
.card .body{padding:14px 16px}
.grid{display:grid;gap:14px}
/* 概览两列卡片（配置项分类分布 / 数据健康检查）必须等高：网格项拉伸 + 卡片撑满 + body 吃掉剩余高度 */
.grid.g2{align-items:stretch}
.grid.g2>.card{height:100%;display:flex;flex-direction:column}
.grid.g2>.card>.body{flex:1 1 auto}
.g4{grid-template-columns:repeat(4,minmax(0,1fr))}
.g3{grid-template-columns:repeat(3,minmax(0,1fr))}
.g2{grid-template-columns:repeat(2,minmax(0,1fr))}
@media(max-width:1180px){.g4{grid-template-columns:repeat(2,minmax(0,1fr))}.g3{grid-template-columns:repeat(2,minmax(0,1fr))}}
.stat{--sc:#7c8ca1;background:var(--card);border:1px solid var(--line);border-radius:var(--radius);padding:14px 16px;box-shadow:var(--shadow)}
.stat .k{font-size:var(--fs-label);font-weight:var(--fw-label);color:var(--muted);display:flex;align-items:center;gap:6px}
.stat .k::before{content:'';width:6px;height:6px;border-radius:50%;background:var(--sc);opacity:.85;flex:0 0 auto}
.stat .v{font-size:var(--fs-num-xl);font-weight:var(--fw-num);color:var(--text);margin-top:3px;letter-spacing:.3px;line-height:1.35;font-variant-numeric:tabular-nums}
.stat .f{font-size:var(--fs-hint);color:var(--muted);margin-top:2px}
/* 数字一律中性色，只用标签前的小圆点做区分（与「到期预警」卡同一套设计语言，避免每种数字一个颜色） */
.stat.b{--sc:#6b8fb5}.stat.t{--sc:#5f9c9c}.stat.p{--sc:#8b81a4}.stat.a{--sc:#a1895f}
/* 「资产总数」卡片：右侧空白处放 3D 双色饼图（未过保 / 过保） */
.stat.has-pie{display:flex;align-items:center;justify-content:space-between;gap:10px}
.stat.has-pie .stat-info{min-width:0}
.stat.has-pie .stat-pie{flex:0 0 auto;line-height:0;margin:-5px -8px -5px 0}
.pie3d{display:block}
.lg{font-weight:600}
.lg-ok{color:#2563eb}
.lg-over{color:#c0392b}
/* 「弃保」图例（2026-09-16）：紫色，与「过保」的红区分 —— 弃保不进饼图，只在卡片文字里单列 */
.lg-disc{color:#6d28d9}
/* 列表页工具栏的「⋮ 更多」按钮（2026-09-16）：资产类别 / 配置项类型 / 配置关系的固定入口 */
.btn.more{padding:6px 11px;font-weight:700;line-height:1;font-size:15px}
/* 字段级权限锁（2026-09-16）：没有该字段的维护权限时（编辑态），整块不可交互并给出原因 */
.f.locked{opacity:.92}
.f.locked input,.f.locked textarea,.f.locked .ssel,.f.locked .checks,.f.locked select{pointer-events:none}
.hint.warn-lock{color:#b45309}
/* ===== 资产概览（需求方 2026-09-20 改版）==================================
   ① 检索框美化（需求方：「页面的检索框都美化下」+「检索区域太窄，加宽」）：
      · 卡片里的「客户 / 项目」两个检索框**并排、各占一半**、**撑满卡片宽度**；
      · 统一美化：加高（36px）、圆角 10px、**左侧放大镜图标**、悬停描边、聚焦光晕（「1号检索」同款观感）；
      · 「快速检索到期」那三个框原来最小宽度只有 92px（太窄）→ 提到 140px，放不下就自动换行，框更宽。
      只作用于本页的筛选行（`.hx-filter` 两列卡片 + `.warn-quick .qrow` 快速检索），不动其它页面。 */
.hx-filter{display:flex;gap:8px;margin-bottom:10px}
.hx-filter .ssel{display:flex;flex:1 1 0;width:auto;min-width:0}
.hx-filter .ssel .ssel-in,.warn-quick .qrow .ssel .ssel-in{
  height:36px;border:1px solid var(--line2);border-radius:10px;background-color:var(--card);outline:none;
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'><circle cx='7' cy='7' r='4.6' fill='none' stroke='%238092a6' stroke-width='1.6'/><path d='M10.6 10.6 L14 14' stroke='%238092a6' stroke-width='1.6' stroke-linecap='round'/></svg>");
  background-repeat:no-repeat;background-position:10px center;background-size:14px 14px;
  padding-left:32px;padding-right:28px;transition:border-color .15s ease,box-shadow .15s ease,background-color .15s ease}
.hx-filter .ssel .ssel-in:hover,.warn-quick .qrow .ssel .ssel-in:hover{border-color:#a9c4ea;background-color:#fbfdff}
.hx-filter .ssel .ssel-in:focus,.warn-quick .qrow .ssel .ssel-in:focus{border-color:var(--accent);background-color:#fff;box-shadow:0 0 0 3px rgba(14,116,144,.15)}
.hx-filter .ssel .ssel-btn,.warn-quick .qrow .ssel .ssel-btn{right:5px;color:#8ea2b6}

/* ② 三张 KPI 卡的右侧图表（需求方 2026-09-20：「留白太多」→ 内容加满）
   · `.pies2`（资产总数）= 上行（数字 + 右侧立体柱状图）+ 下行（设备分类图例）；
   · `.pie-right`（配置项 CI）= 原来的右侧 **TOP 散点图与 4 行指标均已删除**（2026-09-20），
     上下两块按「资产总数」卡**同样的比例**先分出来（上 : 下 ≈ **106 : 122**，实测 1440×900 下的高度）。 */
.stat.pies2,.stat.pie-right{display:flex;flex-direction:column}
/* 让「数字+图」的那一行吃掉整张卡的高度：左边指标行才能铺到底（否则底部必留一片白） */
.stat.pies2 .stat-top{flex:1 1 auto;min-height:0}
/* ——— CI 卡的上下划分（需求方 2026-09-20：「配置项 CI **根据与他一样的大小比例划分**」）———
   用与「资产总数」卡**同样的比例 106 : 122**，且**同样带 10px 上间距** —— 这条间距就是虚线的高度差：
   资产总数卡的虚线 = `.stat-top` 底边 + 10px（`.stype-lg` 的 margin-top），CI 卡原来没有这 10px，
   所以它的虚线比资产总数卡**高 10px**（需求方 2026-09-20 指出「配置项 CI 明显比资产总数的高」）。 */
.stat.pie-right .stat-top{flex:0 0 106px;min-height:0}
.stat.pie-right .stat-info{flex:0 0 auto;justify-content:center;padding-right:10px}
/* 「账号 / 组织」卡的**标题 + 大数字**位置：由下面的两列网格 + 106px 行高决定
   （与「配置项 CI」卡的标题 / 数字落在同一条水平线）。 */
/* 右侧** 4 个许可窗格**（需求方 2026-09-20：「账号 / 组织 和数字右边……根据许可信息里
   **第一行那 4 个窗格的形式**来显示」→「**四个并排与账号 / 组织数字对齐**」→「与**履带同水平带**对齐」）——
   结构照「系统管理 → 许可信息」页第一行那四张卡（标签带彩色圆点 + 值 + 小注）；
   **4 个并排一行**，整行放进上块 106px 带内居中 → 与「配置项 CI」卡的**履带落在同一条水平带**上
   （实测履带 43px 起、高 48、中心线 67；本行中心线 68）。 */
/* ——— 「账号 / 组织」卡：**两列网格**布局（需求方 2026-09-20）———
   左列 = 内容最大宽度、**上下两行共用** → 下块（AI 模型标签）左边缘**自动与上块「当前版本」框对齐**
   （需求方：「便签左边应该与上面版本框对齐，现在靠左边文字太近了」）；
   行高固定 106px（许可框那一行）+ 1fr（AI 标签那一行），行间距 10px = 虚线位置，
   与「资产总数」「配置项 CI」两卡的中线**同一条水平线**。 */
/* 行高**写死** 106px（许可框）+ 121px（AI 标签）＝ 与另外两张卡等高、总高锁 267。
   🔴 不能用 `1fr`：卡片高度是 auto 时 `1fr` 会按内容撑开 —— 6 个标签一行一个就能把卡片顶到 312
   （三卡等高 → 一高全高，资产总数卡的中线也跟着被推下去）。 */
.stat.a.pies2{display:grid;grid-template-columns:max-content 1fr;grid-template-rows:106px 121px;row-gap:10px}
.stat.a.pies2 .stat-info{min-width:0;display:flex;flex-direction:column;justify-content:center}
/* 右上：4 个许可窗格（列宽由 JS 按内容写 inline fr；行高 106px 内垂直居中） */
.stat.a.pies2 .lic-grid{min-width:0;align-self:center;padding-left:10px;
  display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:5px;align-content:center}
.stat.a.pies2 .lic-w{min-width:0;background:var(--soft);border:1px solid var(--line);border-radius:9px;
  padding:4px 6px;display:flex;flex-direction:column;justify-content:center;--sc:#7c8ca1}
.stat.a.pies2 .lic-w.b{--sc:#6b8fb5}
.stat.a.pies2 .lic-w.t{--sc:#5f9c9c}
.stat.a.pies2 .lic-w.p{--sc:#8b81a4}
.stat.a.pies2 .lic-w .lk{font-size:11px;font-weight:600;color:var(--muted);display:flex;align-items:flex-start;
  justify-content:center;gap:4px;line-height:1.22;text-align:center}
.stat.a.pies2 .lic-w .lk::before{content:'';width:5px;height:5px;border-radius:50%;background:var(--sc);opacity:.85;flex:0 0 auto;margin-top:4px}
.stat.a.pies2 .lic-w .lk b{font-weight:700;font-size:12px;color:var(--text);font-variant-numeric:tabular-nums}
.stat.a.pies2 .lic-w .lv{margin-top:1px;font-size:12px;font-weight:700;color:var(--text);line-height:1.22;
  font-variant-numeric:tabular-nums;overflow-wrap:anywhere;text-align:center}
.stat.a.pies2 .lic-w .lv.ok{color:#15803d}
.stat.a.pies2 .lic-w .lv.warn{color:#b45309}
.stat.a.pies2 .lic-w .lv.bad{color:#b91c1c}
.stat.a.pies2 .lic-w .lf{margin-top:1px;font-size:11px;color:var(--muted);line-height:1.22;text-align:center}
/* ——— 「账号 / 组织」卡**中线下方**：已启用的 AI 模型（需求方 2026-09-20）———
   左＝「AI 模型启用」换行「**启用数 / 总数**」；右＝**只用模型名字标签**（空间有限，不再放 KEY / 用量 / tokens 行），
   标签底色沿用「模型设置」那套（已启用＝深蓝渐变；**本机模型＝红渐变**），
   标签内的小角标标出「**本地**（本地优先）」「**兜底**（知识库兜底）」；
   **单击标签 → 浮窗里显示该模型的卡片**（＝「模型设置」页那张卡，不是配置弹窗）。
   下块高 1fr（=121px，与「配置项 CI」卡下半块同高，卡片总高锁 267 不变）；虚线画在两格的上边框上。 */
.stat.a.pies2 .ai-left{min-width:0;display:flex;flex-direction:column;justify-content:center;
  border-top:1px dashed #111;padding-top:9px}
/* 左下角的「AI 模型启用 / 启用数 / 总数」**不另写字号**（需求方 2026-09-20：「文字与『账号 / 组织』
   一样样式大小，数字也是」）—— 直接复用 `.stat .k` 与 `.stat .v`，样式/字号/圆点自动一致；
   只有「**启用数**」（斜杠前那个）用刚才的蓝色（需求方 2026-09-20：「启用的数字用刚才的颜色」）。 */
.stat.a.pies2 .ai-left .v b{color:#1d4ed8;font-weight:inherit}
/* 右侧标签区：**垂直居中对齐**（需求方 2026-09-20：「标签在右边应该自动垂直居中摆放」）；
   左内边距 10px = 与上块许可框的左内边距一致（列间距为 0 才能让虚线连续贯通）。
   🔴 **模型名不截断**（需求方 2026-09-20：「模型标签不要出现省略号」）→ 标签按名字宽度整条显示，
   一行放不下就换行；超过 121px 的高度时**在格子里滚动**（滚动条隐藏，滚轮可用），
   `safe center` 保证内容溢出时不会被居中裁掉上半截。 */
.stat.a.pies2 .ai-tags{min-width:0;display:flex;flex-wrap:wrap;gap:5px;align-content:safe center;
  overflow-y:auto;overflow-x:hidden;scrollbar-width:none;
  border-top:1px dashed #111;padding:9px 0 0 10px}
.stat.a.pies2 .ai-tags::-webkit-scrollbar{display:none}
/* 左下角的「AI 模型启用 / 启用数 / 总数」**不另写字号**（需求方 2026-09-20：「文字与『账号 / 组织』
   一样样式大小，数字也是」）—— 直接复用 `.stat .k` 与 `.stat .v`，样式/字号/圆点自动一致；
   只有「**启用数**」（斜杠前那个）用刚才的蓝色（需求方 2026-09-20：「启用的数字用刚才的颜色」）。 */
.stat.a.pies2 .ai-left .v b{color:#1d4ed8;font-weight:inherit}
.stat.a.pies2 .ai-mc{display:inline-flex;align-items:center;gap:4px;max-width:100%;padding:2px 7px;border-radius:999px;
  cursor:pointer;line-height:1.5;font-size:10.5px}
.stat.a.pies2 .ai-mc.is-on{background:linear-gradient(135deg,#0e2244 0%,#153a75 55%,#1b4ea8 100%);border:1px solid #1e3a8a}
.stat.a.pies2 .ai-mc.is-local{background:linear-gradient(135deg,#4c0519 0%,#7f1d1d 55%,#b91c1c 100%);border:1px solid #7f1d1d}
.stat.a.pies2 .ai-mc:hover{filter:brightness(1.14)}
.stat.a.pies2 .ai-mc-n{min-width:0;font-weight:700;color:#fff;white-space:normal;overflow-wrap:anywhere;line-height:1.25}
/* 🔴 名字**不截断、不加省略号**（需求方 2026-09-20：「模型标签不要出现省略号」）——
   标签里允许**折行**显示全名（格子高度不够时整块可滚动），绝不出现「…」。 */
.stat.a.pies2 .ai-tg{flex:0 0 auto;font-style:normal;font-size:9px;line-height:1.5;padding:0 5px;border-radius:999px}
.stat.a.pies2 .ai-tg.mk-lc{background:#e6f7ee;color:#15803d}
.stat.a.pies2 .ai-tg.mk-fb{background:#eae6ff;color:#5b21b6}
.stat.a.pies2 .ai-empty{font-size:11.5px;color:var(--muted);line-height:1.7}
/* 🔴 min-height:0 必须有：flex 子项默认 min-height:auto，会被里面 40 条变更记录**撑高卡片** →
   三张卡等高，一高全高（需求方 2026-09-20：「不要改变大窗格的高度」） */
/* 🔴 下块必须**固定高度**：若用 flex:1，容器高度 auto 时它等于内容高度 —— 40 条变更记录
   会把卡片撑到 1036px（三卡等高，一高全高）。需求方 2026-09-20：「不要改变大窗格的高度」。 */
.stat.pie-right .ci-foot{flex:0 0 121px;min-height:0;overflow:hidden;margin-top:10px;padding-top:9px;border-top:1px dashed #111}
/* 中线**下面**的「资产变更条目」：**从下往上**循环滚动（需求方 2026-09-20）；单击条目 → 与履带同样的浮窗 */
.ci-feed{height:100%;overflow:hidden}
.ci-feed-track{display:flex;flex-direction:column;animation:ciFeedRun 24s linear infinite}
/* 变更条目**单行不换行**：**公司全称·项目名称——变更信息：…**（需求方 2026-09-20） */
.ci-feed-it{display:flex;align-items:center;height:22px;padding:0 6px;border-radius:6px;cursor:pointer;
  flex:0 0 auto;font-size:12px;white-space:nowrap}
.ci-feed-it:hover{background:#eef6ff}
.cf-co{flex:0 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;color:#1d4ed8;font-weight:600}
.cf-sep{flex:0 0 auto;color:var(--muted)}
.cf-p{flex:0 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;color:var(--text)}
.cf-d{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;color:var(--muted)}
/* 最右端显示**变更时间（年月日时分秒）**（需求方 2026-09-20：「最后面显示变更年月日时分秒」） */
.cf-time{flex:0 0 auto;margin-left:8px;color:var(--muted);font-size:11px;font-variant-numeric:tabular-nums}
@keyframes ciFeedRun{from{transform:translateY(0)}to{transform:translateY(-50%)}}
.ci-feed:hover .ci-feed-track{animation-play-state:paused}
/* ——— CI 卡右侧的**履带循环**（需求方 2026-09-20：「右边从左到右履带循环前 10 名的关系数」
   →「下面项目名称不要了，就**上下两层**」→「在履带**下面中间**显示『关系数TOP10 · 重点保障对象』」）———
   每条约**统一宽度**（`--w` 由 JS 按**最长设备名称**算好，需求方「每卡片字要显示全」），
   条目**从左到右**循环跑；内容**复制两遍**、位移正好 -50% → 无缝衔接；两侧 mask 渐隐。 */
.stat.pie-right .ci-belt-wrap{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;justify-content:flex-start;padding-top:28px;gap:12px}
.stat.pie-right .ci-belt{width:100%;overflow:hidden;margin-right:-2px;
  -webkit-mask-image:linear-gradient(90deg,transparent 0,#000 14px,#000 calc(100% - 14px),transparent 100%);
  mask-image:linear-gradient(90deg,transparent 0,#000 14px,#000 calc(100% - 14px),transparent 100%)}
.ci-belt-track{display:flex;width:max-content;animation:ciBeltRun 26s linear infinite}
/* gap 用**条目的右外边距**（不是 flex gap）—— 这样"复制两遍"的总宽能被 2 整除，-50% 位移才严丝合缝 */
.ci-belt-it{flex:0 0 auto;width:var(--w,88px);margin-right:9px;cursor:pointer;display:flex;flex-direction:column;align-items:center;
  justify-content:center;gap:2px;padding:6px 4px;border-radius:8px;background:#f6f9fd;border:1px solid var(--line)}
.ci-belt-it b{font-size:15px;font-weight:800;color:#1d4ed8;line-height:1.15;font-variant-numeric:tabular-nums}
/* 设备名称**不截断**（条目宽度就是按它算的）——需求方「每卡片字要显示全」 */
.ci-belt-it .ci-b-name{font-size:12px;color:var(--text);line-height:1.25;white-space:nowrap}
/* 底色由 JS 按关系数写成 inline 渐变（越大的越深），所以悬停用**边框 + 阴影**表达，不用背景色 */
.ci-belt-it:hover{border-color:#93b4dc;box-shadow:0 2px 8px rgba(37,99,235,.22)}
.ci-belt-cap{text-align:center;font-size:13px;color:#111;letter-spacing:.3px;line-height:1.3}
@keyframes ciBeltRun{from{transform:translateX(0)}to{transform:translateX(-50%)}}   /* 换方向：从右到左 */
/* 悬停暂停，方便看清楚某一条 */
.ci-belt:hover .ci-belt-track{animation-play-state:paused}
.stat .stat-top{display:flex;align-items:stretch;justify-content:space-between;gap:10px}
.stat .stat-top .stat-info{min-width:0;display:flex;flex-direction:column}
/* 资产总数卡：左列只剩「标题 + 数字」，右侧柱状图较高 → 左列**垂直居中**，
   不至于数字顶在上边、下面留一大片空（需求方 2026-09-20 一直强调去留白）。 */
.stat.b.pies2 .stat-top .stat-info{justify-content:center}
/* 需求方 2026-09-20：「除到期预警外都必须去留白」——左列改成**纵向铺满的指标行**，
   行距由 `space-between` 自动撑开（原来数字下面一大片空） */
.stat .stat-rows{flex:1 1 auto;display:flex;flex-direction:column;justify-content:space-between;gap:3px;margin-top:8px}
.stat .stat-row{display:flex;align-items:center;gap:7px;font-size:12px;color:var(--muted);min-width:0}
.stat .stat-row i.lg{width:7px;height:7px;border-radius:50%;flex:0 0 auto;background:currentColor}
.stat .stat-row b{margin-left:auto;font-size:13px;font-weight:700;color:var(--text);font-variant-numeric:tabular-nums;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:62%}
.stat .stat-row.warn b{color:#b45309}
.stat .stat-row.bad b{color:#b91c1c}
.stat .stat-row .lg-inuse{color:#5f9c9c}
/* 资产总数卡右侧：**两个立体柱状图**（需求方 2026-09-20：「**原饼图去除**」→
   上＝按**资产状态**（**蓝渐变**）、下＝按**设备类型**统计**百分比**（**各色渐变**）；
   数量为 0 的档位也**留一根底片**（浅灰短柱），不隐藏。
   🔴 布局：从「资产总数」右边**挨着**、一直**平铺到卡片右边框**、柱子**等距** ——
   所以用 HTML + flex 等分（不用固定宽度的 SVG，否则会被拉伸或缩到一边）。 */
.stat .stat-hbars{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;justify-content:center;margin:-2px -2px -2px 0}
.hb-cols{display:flex;align-items:flex-end;justify-content:space-between;gap:4px;height:82px}
.hb-col{flex:1 1 0;min-width:0;height:100%;display:flex;flex-direction:column;justify-content:flex-end;align-items:center;
  border-radius:6px;transition:background .12s}
/* 鼠标悬停：该柱所在的整列出现**浅灰底长方形**（需求方 2026-09-20：「柱状图下要鼠标悬停显示，加了底色」） */
.hb-col:hover{background:#eef2f8}
/* 🔴 柱顶数值（需求方 2026-09-20：「柱状图的文字没显示出来，且字太小」→ 字号 9.5 → **12px**，
   0 值那档原来用很浅的灰几乎看不见 → 换成看得清的深灰） */
.hb-v{display:block;font-size:12px;font-weight:700;color:#1e3a5f;line-height:1.2;font-variant-numeric:tabular-nums;margin-bottom:2px}
.hb-v.z{color:#8b9bab}
/* 柱体（等距投影的「顶面」高光条保留；**右侧那根深色斜边已去掉** ——
   需求方 2026-09-20：「蓝色旁边的这个类似柱状图的东西去掉」：那根 3px 斜条紧贴在蓝柱右侧，
   看起来像"旁边又多了一根小柱子"，去掉后每根柱子就是干净的单体） */
.hb-rod{position:relative;display:block;flex:0 0 auto;width:62%;max-width:24px;border-radius:2px 2px 0 0}
.hb-rod::before{content:'';position:absolute;top:-3px;left:0;width:100%;height:3px;background:var(--top);
  transform:skewX(-45deg);transform-origin:0 100%}
/* 🔴 柱下的**数据标签**（需求方 2026-09-20：「数据标签还是要的，且字要看得清」→ 字号 10 → **12px**）——
   超宽用省略号；完整名称与占比另有悬停浮窗 `#hb-tip` 兜底。 */
.hb-l{display:block;font-size:12px;color:#33475e;line-height:1.3;margin-top:4px;max-width:100%;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* 分类多（>10 根）时格子窄：柱子收一档、数值略小（这些柱子不写柱下标签，名字看图例 / 悬停浮窗） */
.hb-cols.many .hb-v{font-size:10px}
.hb-cols.many .hb-rod{width:76%;max-width:14px}
.hb-cols.many{gap:2px}
/* 柱状图悬停浮窗（跟随鼠标的小气泡） */
#hb-tip{position:fixed;z-index:9999;display:none;pointer-events:none;padding:5px 9px;border-radius:7px;
  background:rgba(15,32,52,.94);color:#fff;font-size:12px;line-height:1.5;white-space:nowrap;
  box-shadow:0 6px 18px rgba(6,20,36,.28)}
#hb-tip.on{display:block}
/* AI 模型卡片浮窗（需求方 2026-09-20）：点概览里的模型标签 → 浮窗里放「模型设置」那张 `.aim-card`。
   模型卡本来是网格单元（约 260px 宽），这里按它的舒适宽度给浮窗，超高就内部滚动。 */
#ai-pop{position:fixed;z-index:9998;display:none;width:296px;max-height:74vh;overflow:auto;padding:10px;
  background:var(--card);border:1px solid var(--line2);border-radius:12px;box-shadow:0 14px 44px rgba(8,26,48,.24)}
#ai-pop.on{display:block}
#ai-pop .ai-pop-h{display:flex;align-items:center;gap:6px;margin:0 0 8px}
#ai-pop .ai-pop-h b{font-size:13px;font-weight:700;color:var(--text);min-width:0;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
#ai-pop .ai-pop-h .mini{margin-right:auto;flex:0 0 auto}
#ai-pop .ai-pop-x{flex:0 0 auto;width:22px;height:22px;line-height:1;border:1px solid var(--line);
  border-radius:6px;background:#fff;color:var(--muted);cursor:pointer;font-size:12px}
#ai-pop .ai-pop-x:hover{color:var(--text);border-color:var(--line2)}
#ai-pop .aim-card{width:100%;box-shadow:none}
/* 设备分类的**数据标签（图例）**：4 列，色块 + 名称 + 台数 + 占比（12px）—— 🔴 **资产总数卡这块不动** */
.stype-lg{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:4px 12px;margin-top:10px;
  padding-top:9px;border-top:1px dashed #111}
.stype-li{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--muted);min-width:0}
.stype-li i{width:9px;height:9px;border-radius:2px;flex:0 0 auto}
.stype-li span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--text)}
.stype-li b{margin-left:auto;font-weight:700;color:var(--text);font-variant-numeric:tabular-nums;flex:0 0 auto}
.stype-li em{font-style:normal;flex:0 0 42px;text-align:right;font-variant-numeric:tabular-nums;font-size:11.5px}
/* 立体柱状的容器与说明（`.b3d` 用 1:1 像素输出，窄窗口靠 max-width 兜底等比缩小） */
.stat .stat-bars{flex:0 0 auto;align-self:flex-end;line-height:0;margin-top:8px}
.stat .stat-bars .b3d{display:block;max-width:100%;height:auto}
.b3d-v{font-size:8.5px;font-weight:700;fill:#1e3a5f}
.b3d-l{font-size:8px;fill:#5d7488}
.b3d-cap{margin-top:3px;font-size:10px;color:var(--muted);line-height:1.2}
.p3m-lb{font-size:8.5px;font-weight:700;fill:#fff;pointer-events:none}
/* 配置项 CI 卡的 **TOP 排名散点图** */
.stat-scat{flex:0 0 auto;align-self:center;line-height:0;margin:-2px -6px -4px 0;text-align:center}
.scat{display:block;max-width:100%;height:auto}
.sc-g{stroke:#e6edf5;stroke-width:1}
.sc-stem{stroke:#dbe6f1;stroke-width:1;stroke-dasharray:2 2}
.sc-dot{fill:#3f7099;fill-opacity:.88;stroke:#fff;stroke-width:.8}
.sc-lb{font-size:8px;fill:#5d7488;font-family:Consolas,monospace}
.sc-ax{font-size:7.5px;fill:#9aa9b8}
.scat-cap{margin-top:2px;font-size:10px;color:var(--muted);line-height:1.2}


/* ③ 「账号 / 组织」卡：**系统授权有效期已并入左列指标行**（`.stat-row`，见上面的 `.stat-rows` 段）；
   卡片底部 = 跨整卡宽的「立体柱状」（各顶层组织账号占用，从右到左、从高到低）。 */

/* ④ 「数据健康检查」重新设计：**健康度环**（100 分制）+ **检查项网格** */
.hx-top{display:flex;align-items:center;gap:16px;padding:2px 0 12px}
.hx-gauge{position:relative;flex:0 0 auto;width:96px;height:96px;line-height:0}
.hx-gauge svg{display:block;width:96px;height:96px}
.hx-gauge .hx-gv{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;line-height:1.1}
.hx-gauge .hx-gv b{font-size:21px;font-weight:800;color:var(--text);font-variant-numeric:tabular-nums}
.hx-gauge .hx-gv em{font-style:normal;font-size:10px;color:var(--muted);margin-top:1px}
.hx-sum{min-width:0;display:flex;flex-direction:column;gap:4px}
/* ——— 健康度右边的**模拟心电图**（需求方 2026-09-20）———
   监护仪走纸效果：亮点从左往右、身后是**折线**（canvas 逐点直连，不做平滑）；走完一轮换一段波形重来。
   正常绿 / 关注橙 / 异常红（与健康度环同一套配色）；标题只写「健康监测 状态 X」，**不显示心率**。 */
.hx-ecg{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;gap:4px}
.hx-ecg-h{display:flex;align-items:baseline;gap:7px;min-width:0}
.hx-ecg-h i{width:7px;height:7px;border-radius:50%;flex:0 0 auto;background:#15803d;align-self:center}
.hx-ecg-h b{font-size:12.5px;font-weight:700;color:var(--text);flex:0 0 auto}
.hx-ecg-h span{font-size:11.5px;color:var(--muted);flex:0 0 auto}
.hx-ecg-h em{font-style:normal;font-size:12.5px;font-weight:700;color:#15803d;flex:0 0 auto}
.hx-ecg.ok .hx-ecg-h i{background:#15803d}
.hx-ecg.warn .hx-ecg-h i{background:#d97706}
.hx-ecg.warn .hx-ecg-h em{color:#b45309}
.hx-ecg.bad .hx-ecg-h i{background:#dc2626}
.hx-ecg.bad .hx-ecg-h em{color:#b91c1c}
.hx-ecg-box{position:relative;flex:1 1 auto;min-height:52px;max-height:70px;overflow:hidden;border-radius:8px;
  border:1px solid var(--line);background:#f7fafd;
  background-image:linear-gradient(90deg,rgba(148,163,184,.16) 1px,transparent 1px),
    linear-gradient(0deg,rgba(148,163,184,.16) 1px,transparent 1px);
  background-size:14px 14px}
.hx-ecg-box canvas{display:block;width:100%;height:100%}
.hx-tag{align-self:flex-start;font-size:12px;font-weight:700;padding:2px 10px;border-radius:999px;border:1px solid transparent}
.hx-tag.ok{color:#15803d;background:#f0fdf4;border-color:#bbf7d0}
.hx-tag.warn{color:#b45309;background:#fffbeb;border-color:#fde68a}
.hx-tag.bad{color:#b91c1c;background:#fef2f2;border-color:#fecaca}
.hx-grid{display:grid;grid-template-columns:1fr 1fr;gap:9px;flex:1 1 auto;align-content:space-between}
.hx-i{display:flex;align-items:center;gap:6px;border:1px solid var(--line);border-radius:8px;padding:11px 10px;min-width:0;background:var(--soft)}
.hx-i:hover{border-color:var(--line2)}
.hx-i i{width:7px;height:7px;border-radius:50%;flex:0 0 auto;background:#94a3b8}
.hx-i.ok i{background:#15803d}.hx-i.warn i{background:#d97706}.hx-i.bad i{background:#dc2626}.hx-i.info i{background:#64748b}
.hx-i .hk{font-size:11.5px;color:var(--muted);flex:0 0 auto}
.hx-i .hv{font-size:12.5px;font-weight:700;color:var(--text);flex:1 1 auto;min-width:0;text-align:right;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-variant-numeric:tabular-nums}
.hx-i .hs{font-style:normal;font-size:10.5px;padding:1px 6px;border-radius:999px;flex:0 0 auto}
.hx-i.ok .hs{color:#15803d;background:#dcfce7}.hx-i.warn .hs{color:#b45309;background:#fef3c7}
.hx-i.bad .hs{color:#b91c1c;background:#fee2e2}.hx-i.info .hs{color:#475569;background:#e2e8f0}

/* ⑤ 「资产状态构成」+「最近入库」（替换原「最近操作（审计）」）
   —— 需求方 2026-09-20：「**除到期预警外都必须去留白**」（实测这块原来底部空 211px）：
   左边大 3D 饼**按卡片高度撑满**，右边状态行**均匀顶开**（`space-around`），空白不再堆在底部。 */
.ov-st-body{display:flex;flex-direction:column;gap:10px}
/* 大饼：高度**跟着卡片走**（不设死高），宽度按比例自动（max-width 兜底）→ 卡片底部不留白 */
.ov-pie{flex:1 1 auto;min-height:0;min-width:0;display:flex;align-items:center;justify-content:center;line-height:0}
.ov-pie svg{height:100%;width:auto;max-width:100%}
.ov-lg2{flex:0 0 auto;display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:8px}
.ov-lg2 .empty{grid-column:1 / -1}
.ov-li2{display:flex;flex-direction:column;justify-content:center;cursor:pointer;border-radius:8px;padding:8px 10px;background:var(--soft);border:1px solid var(--line)}
.ov-li2:hover{background:var(--hover)}
.ov-l2t{display:flex;align-items:baseline;gap:6px}
.ov-l2t i{width:10px;height:10px;border-radius:3px;flex:0 0 auto;align-self:center}
.ov-l2t span{font-size:12.5px;color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ov-l2t b{margin-left:auto;font-size:19px;font-weight:800;color:var(--text);font-variant-numeric:tabular-nums;flex:0 0 auto}
.ov-l2t b em{font-style:normal;font-size:10px;font-weight:400;color:var(--muted);margin-left:2px}
.ov-l2t u{text-decoration:none;font-size:11.5px;color:var(--muted);flex:0 0 44px;text-align:right;font-variant-numeric:tabular-nums}
.ov-l2b{margin-top:7px;height:9px;border-radius:5px;background:var(--soft2);overflow:hidden}
.ov-l2b i{display:block;height:100%;border-radius:4px}
/* 最近入库（时间线）：行高放大，10 条铺满卡片 */
/* ——— 概览「最近入库」（需求方 2026-09-20：「最近入库里面**从下往上循环滚播**，注意**窗格高度不变**，
   入库条目信息：编号、资产类别、资产名称、品牌、型号、存放位置、资产来源、采购日期、
   保修到期（如果是租赁则显示租赁到期）、价格（单位一起显示）、CI标记」；口径＝只列资产）———
   ① 窗格高度不变：`.ov-rec-body` 撑满卡片、`.ov-rec-feed` 固定占剩余高度并 `overflow:hidden`，
      只有里面的 track 在动 —— 卡片高度仍由同行右侧「资产状态构成」卡决定，不因条数变化而变；
   ② 滚法与 CI 卡「资产变更条目」一致：内容**复制两遍** + `translateY(0 → -50%)` 从下往上无缝循环
      （行高固定、无 gap，-50% 正好等于一份的高度）；鼠标移入暂停；
   ③ 表头与数据行**共用同一组列宽类**（`rc-*`）→ 列对得齐；窄窗口下弹性列（名称 / 位置）先被压缩、
      超长省略（各自带 title 可看全文），固定列（编号 / 日期 / 价格…）不受影响。 */
.ov-rec-body{display:flex;flex-direction:column;min-height:0;overflow:hidden}
/* 表头与条目**同宽同步收缩**（需求方 2026-09-20：「**保证不换行、不用左右拉滚动条**」）——
   两行都铺满容器宽，列宽用 `flex:0 1 Npx`（基础宽 = 按内容算好、内联下发），空间不够时**等比收缩**、
   文字走省略号（`title` 里是全文），所以永远不会有横向滚动条；表头与数据行各列宽度天然一致。 */
.ov-rec-scroll{flex:1 1 auto;min-height:0;display:flex;flex-direction:column;
  overflow:hidden}
.ov-rec-head{display:flex;align-items:center;gap:6px;flex:0 0 auto;
  margin-bottom:4px;padding:0 6px 6px;border-bottom:1px solid var(--line);
  font-weight:600;color:var(--muted);white-space:nowrap}
/* 🔴 滚动区用 `flex:1 1 260px`（basis = **10 行条目的高度**：10 × 26px，需求方 2026-09-20
   「最近入库和 RAG 知识库变成 10 行吧」，两张卡共用这一条）——
   basis:auto 会让「N 条 × 26px × 2 份」把卡片自己撑到 1000px 以上（实测 1145px），
   等于窗格高度跟着内容变；basis:260px 后窗格只由这个固定值决定、**不随条目多少变化**，
   多出来的条目裁在窗格里循环滚；卡片被网格拉伸或全屏压缩时 grow/shrink 再跟着变。
   宽度铺满容器（列宽由 `flex:0 1 Npx` 收缩适配）→ 不出现横向滚动。 */
.ov-rec-feed{flex:1 1 260px;min-height:0;overflow:hidden;
  -webkit-mask-image:linear-gradient(180deg,transparent 0,#000 10px,#000 calc(100% - 10px),transparent 100%);
  mask-image:linear-gradient(180deg,transparent 0,#000 10px,#000 calc(100% - 10px),transparent 100%)}
/* 时长默认 40s 只是**兜底**：正常渲染时由 JS 按「与 CI 卡变更条目**同一每秒像素**」算好，
   再用 inline 的 `animation-duration` 覆盖（需求方 2026-09-20：「最近入库滚动的速度，
   大概和上面变更滚动的速度保持一致」）。 */
.ov-rec-track{display:flex;flex-direction:column;animation:ovRecRun 40s linear infinite}
.ov-rec-it{display:flex;align-items:center;gap:6px;flex:0 0 auto;height:26px;padding:0 6px;
  border-radius:7px;cursor:pointer;white-space:nowrap;color:var(--text)}
.ov-rec-it:hover{background:#eef6ff}
@keyframes ovRecRun{from{transform:translateY(0)}to{transform:translateY(-50%)}}
.ov-rec-feed:hover .ov-rec-track{animation-play-state:paused}
/* 单元格：**基础宽度由 JS 按内容算好后内联下发**（`flex:0 1 Npx`，表头与数据行同一组值 → 列列对得齐），
   这里只管文字样式。🔴 `min-width:0` 必须给：flex 子项默认 `min-width:auto`，**不加就缩不动**，
   窄窗口下列宽会顶破容器（变成真要横向拖）。收缩后超长文字走省略号，`title` 里能看到全文。 */
.rc{flex:0 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rc-no{font-family:Consolas,monospace;color:#5d7488}
.rc-name{font-weight:600}
.rc-model{color:#33475e}
.rc-loc,.rc-src{color:var(--muted)}
.rc-vendor{color:#33475e}
.rc-date{font-family:Consolas,monospace;color:var(--muted);font-variant-numeric:tabular-nums}
.rc-price{text-align:right;color:#b45309;font-variant-numeric:tabular-nums}
.rc-ci{text-align:center;color:#1d4ed8;font-weight:700}
/* 「配置项分类分布」：分类行**均匀铺开**（原来 6 行挤在上半张卡，下半张全空） */
.cat-list{flex:1 1 auto;display:flex;flex-direction:column;justify-content:space-between;gap:4px}
.cat-row{flex:1 1 auto;display:flex;flex-direction:column;justify-content:flex-end}
.cat-row .mini{display:flex;align-items:baseline;gap:6px}
.cat-row .mini b{margin-left:auto;color:var(--text);font-weight:700;font-variant-numeric:tabular-nums}
.cat-row .mini u{text-decoration:none;color:var(--muted);flex:0 0 46px;text-align:right;font-variant-numeric:tabular-nums}
.cat-row .bar{height:10px;margin-top:6px}

/* 概览「「保修期 | 租赁期」到期预警」栏：三档预警卡片（→ 相连）+ 右侧「快速检索到期」（单按钮）。
   配色刻意柔和（灰蓝 / 柔紫灰 / 柔玫瑰灰）——只用左侧细色条与标题点区分，数字保持中性色。
   高度与上方「资产总数」统计卡一致，行高与原来相同。 */
.warn-panel .body{padding:10px 14px}
.warnbar{display:grid;align-items:stretch;gap:10px;
  /* 最后一列（快速检索到期）由 2fr 加宽到 **3fr**（需求方 2026-09-20：「检索区域太窄，加宽」）——
     三个检索框因此能在**同一行内**变宽（不再换行把整条预警栏撑高）；三张预警卡只是变窄一点，
     数字与标题完全放得下。 */
  grid-template-columns:1fr 26px 1fr 26px 1fr 26px 3fr}
/* 快速块固定在第 7 列（第 6 列留空作"隐形箭头位"，与两处箭头的间隔一致 → 左右节奏对称） */
.warn-quick{grid-column:7;grid-row:1}
@media(max-width:1280px){.warnbar{grid-template-columns:1fr 26px 1fr 26px 1fr;row-gap:10px}
  .warnbar .warn-quick{grid-column:1 / -1;grid-row:auto}}
.warn-card{min-width:0;display:flex;align-items:center;justify-content:space-between;gap:8px;
  border:1px solid var(--line);border-left:3px solid var(--wc);
  border-radius:var(--radius);padding:9px 12px 9px 11px;cursor:pointer;background:var(--card);
  transition:box-shadow .15s,transform .15s,border-color .15s}
.warn-card:hover{box-shadow:0 3px 14px rgba(16,38,60,.12);transform:translateY(-1px);border-color:var(--line2);border-left-color:var(--wc)}
.warn-card .wc-main{min-width:0}
.warn-card .wc-top{display:flex;align-items:center;gap:6px}
.warn-card .wc-top i{width:6px;height:6px;border-radius:50%;background:var(--wc);opacity:.85;flex:0 0 auto}
.warn-card .k{font-size:var(--fs-label);color:var(--wc);font-weight:var(--fw-label);white-space:nowrap}
.warn-card .v{font-size:var(--fs-num);font-weight:var(--fw-num);line-height:1.25;margin-top:1px;letter-spacing:.3px;color:var(--text);font-variant-numeric:tabular-nums}
.warn-card .v small{font-size:var(--fs-hint);font-weight:400;color:var(--muted);margin-left:3px}
.warn-card .f{font-size:var(--fs-hint);color:var(--muted);margin-top:1px;white-space:nowrap}
/* 右侧：占资产总数的百分比（保留两位小数） */
.warn-card .wc-pct{flex:0 0 auto;text-align:right;font-size:var(--fs-num-sm);font-weight:var(--fw-num);line-height:1.1;
  letter-spacing:.2px;color:var(--wc);font-variant-numeric:tabular-nums}
.warn-card .wc-pct small{font-size:var(--fs-hint);font-weight:400;color:var(--muted);margin-left:1px}
.warn-card.w-60{--wc:var(--wc-60)}
.warn-card.w-30{--wc:var(--wc-30)}
.warn-card.w-exp{--wc:var(--wc-exp)}
/* 向右的三角材质箭头（渐变 + 高光面，不是文字箭头） */
.warn-arrow{display:flex;align-items:center;justify-content:center;padding:0}
.warn-arrow svg{display:block}
.warn-arrow .tri-body{fill:var(--arrow-body)}
.warn-arrow .tri-hi{fill:var(--arrow-hi)}
.warn-quick{min-width:0;border:1px solid var(--line);border-radius:var(--radius);padding:8px 12px;background:var(--soft);display:flex;flex-direction:column;justify-content:center}
.warn-quick .wk{font-size:var(--fs-label);color:var(--label);font-weight:var(--fw-label);margin-bottom:5px;white-space:nowrap}
.warn-quick .qrow{display:flex;align-items:center;gap:7px;flex-wrap:wrap}
/* 快速检索到期的三个框**加宽**（需求方 2026-09-20：「检索区域太窄，加宽」）——
   配合上面把该列从 2fr 放宽到 3fr：三个框在**同一行内**各约 140px（原约 111px），
   最小宽度不再触发放行（一旦换行会把整条预警栏撑高、三张预警卡被拉长）。 */
.warn-quick .qrow .ssel{flex:1 1 128px;min-width:124px}
.warn-quick .qrow .btn{flex:0 0 auto}
.warn-quick .qf{font-size:var(--fs-hint);color:var(--muted);margin-top:4px}
.warn-quick .qf b{color:var(--text);font-size:var(--fs-label)}
/* 3D 饼图：颜色走变量，深浅主题各自成套；侧面用半透明做"厚度" */
.pie3d .pie-base{fill:var(--line2)}
.pie3d .pie-side-ok{fill:url(#pieGradOk)}
.pie3d .pie-side-over{fill:url(#pieGradOver)}
.pie3d .pie-top-empty{fill:var(--soft)}
.pie3d .pie-shadow{fill:rgba(16,38,60,.16)}
.pie3d .pie-top-ok{fill:var(--pie-ok)}
.pie3d .pie-top-over{fill:var(--pie-over)}
.pie3d .pie-empty-tx{fill:var(--muted);font-size:11px}

table{width:100%;border-collapse:collapse}
th,td{padding:9px 10px;border-bottom:1px solid var(--line);text-align:left;font-size:13px;vertical-align:middle}
th{background:var(--soft);color:var(--head-tx);font-weight:500;font-size:12.5px;white-space:nowrap;position:sticky;top:0;z-index:1}
tbody tr:hover{background:var(--soft2)}
td.nowrap,th.nowrap{white-space:nowrap}
.tbl-wrap{overflow:auto;max-height:calc(100vh - 264px)}
.empty{padding:34px;text-align:center;color:var(--muted);font-size:13px}
.tags{display:flex;gap:6px;flex-wrap:wrap}
.tag{font-size:11.5px;padding:1px 8px;border-radius:999px;border:1px solid var(--line2);color:var(--head-tx);background:var(--soft)}
.tag.s-在用,.tag.s-已完成,.tag.s-关闭,.tag.s-启用{background:#dcfce7;border-color:#86efac;color:#15803d}
.tag.s-库存,.tag.s-备用,.tag.s-计划,.tag.s-草稿{background:#e0f2fe;border-color:#7dd3fc;color:#075985}
.tag.s-维修,.tag.s-审批中,.tag.s-实施,.tag.s-实施中,.tag.s-验证,.tag.s-借用{background:#fef3c7;border-color:#fcd34d;color:#92400e}
.tag.s-借出{background:#ffedd5;border-color:#fdba74;color:#c2410c}
.tag.s-报废,.tag.s-停用,.tag.s-已驳回,.tag.s-下线,.tag.s-已回滚{background:#fee2e2;border-color:#fca5a5;color:#b91c1c}
.tag.s-已通过{background:#dbeafe;border-color:#93c5fd;color:#1d4ed8}
/* 资产「质保状态」：按到期日自动判定（与后端 assetWarrantyStatus / SQL CASE 同口径） */
.tag.s-质保中{background:#dcfce7;border-color:#86efac;color:#15803d}
.tag.s-已过保{background:#fee2e2;border-color:#fca5a5;color:#b91c1c}
/* 「已弃保」（2026-09-16 需求方新增标签）：用紫色，与「已过保」的红色区分开 ——
   弃保是人工决定"不再维保"，不该和"忘记续保"用同一种报警色 */
.tag.s-已弃保{background:#ede9fe;border-color:#c4b5fd;color:#5b21b6}
/* 只读派生字段（表单内的展示框，如自动判定的质保状态） */
.ro-box{display:inline-flex;align-items:center;gap:8px;min-height:32px;padding:0 10px;border:1px dashed var(--line2);border-radius:8px;background:var(--soft);font-size:13px;color:var(--head-tx)}
.pager{display:flex;justify-content:space-between;align-items:center;padding:10px 16px;color:var(--muted);font-size:12.5px;border-top:1px solid var(--line)}
.bar{height:8px;background:#eef2f7;border-radius:5px;overflow:hidden;margin:5px 0 2px}
.bar>i{display:block;height:100%;background:linear-gradient(90deg,#0e7490,#2563eb)}
.kv{display:grid;grid-template-columns:104px 1fr;gap:7px 12px;font-size:var(--fs-hint)}
/* 详情「行布局」（`sc.detailRows`，项目信息详情）—— 每行 **1~4 格**、行内等分：
   ① 每格 =「标签块 + 值」；标签块**加粗深色 + 浅蓝底**，值与正文同色 → 一眼分得开；
   ② 标签块给了**统一最小宽度**、值不折行（只在超长时省略号）→ 同一行的值起点对齐、看着规整；
   ③ 唯一允许换行的是**项目地址**（一条地址一行，多地址多行）。
   需求方 2026-09-18：「布局调整，规整，不换行」「标题和内容一眼分辨」
   ＋ 后续把行序改成 3 格 / 2 格 / 4 格并排。 */
.kv.kv-rows{display:flex;flex-direction:column;gap:9px}
/* 项目详情「项目管理入口」版块（需求方 2026-09-18）：一排按钮，窄屏自动换行 */
.manage-btns{display:flex;gap:8px;flex-wrap:wrap}
/* 管理按钮里的展开箭头：原先**没给样式**（默认 <i> 斜体 + 紧贴角标）→ 看着像个小点。
   这里与项目其它箭头口径一致（.pop-wrap .caret 那套），并留出间距；展开时翻转 180°做反馈。 */
.manage-btns .caret{font-style:normal;font-size:10px;opacity:.75;margin:0 4px;
  display:inline-block;transition:transform .16s ease}
#mg-duty-btn.on .caret{transform:rotate(180deg)}
/* 驻场管理：点按钮后**在下方拉出**的配置区（需求方 2026-09-18）—— 浅底 + 细边框的独立块 */
.mg-panel{margin-top:10px;padding:12px 14px;border:1px solid var(--line);border-radius:10px;background:var(--soft2)}
.mg-row{display:flex;align-items:center;gap:8px;margin:6px 0;flex-wrap:wrap}
.mg-lb{flex:0 0 76px;color:var(--label);font-weight:var(--fw-label);font-size:var(--fs-hint)}
/* 面板内的输入控件统一放大到 32px（需求方 2026-09-18「选择太小、不方便」）；
   工作小时的「时 / 分」数字框再大一点（.mg-time，34px + 居中 + 加大字号）。 */
.mg-panel input[type=number],.mg-panel input[type=text],.mg-panel select{
  height:32px;padding:0 8px;border:1px solid var(--line2);border-radius:6px;background:#fff;
  font-size:var(--fs-hint);color:var(--text)}
.mg-panel input[type=text]{flex:1 1 auto;min-width:120px}
/* ⚠️ 选择器要带 .mg-panel input[type=number] 的前缀，否则特异性不够、会被上面那条 32px 规则盖掉（实测踩过） */
.mg-panel input[type=number].mg-time{width:60px;height:34px;text-align:center;font-size:var(--fs-body)}
.mg-unit{color:var(--muted);font-size:12px;font-style:normal}
.mg-sep{color:var(--muted)}
.mg-foot{margin-top:10px;text-align:right}
/* 多选勾选按钮（周几 / 每月第几周）—— 可点选多个，选中 = 主题色实底（需求方 2026-09-18「周一选到周末勾选」） */
.mg-tgs{display:flex;gap:6px;flex-wrap:wrap}
.mg-tgs .tgb{height:26px;padding:0 10px;border:1px solid var(--line2);border-radius:6px;background:#fff;
  color:var(--btn-tx);font-size:var(--fs-hint);cursor:pointer}
.mg-tgs .tgb:hover{background:var(--hover)}
.mg-tgs .tgb.on{background:var(--accent);border-color:var(--accent);color:#fff}
/* 「已启用 / 停用」角标 —— 挂在三个管理按钮上，不打开配置区也能一眼看到状态（需求方 2026-09-18） */
.mg-on{margin-left:6px;padding:1px 7px;border-radius:9px;background:#dcfce7;color:var(--green);
  font-size:11px;font-weight:600}
.mg-off{margin-left:6px;padding:1px 7px;border-radius:9px;background:var(--line);color:var(--muted);
  font-size:11px;font-weight:600}
.mg-tip{color:var(--muted);font-size:11px}
/* ---- 服务管理：现场 / 远程两块 + L1~L4 档位表（需求方 2026-09-18）----
   每块 = 小标题（现场服务 / 远程服务）+ 该块的启用/停用 2 连按钮 + 档位表；
   表列 = 档位 · 响应时间（分钟）·［到场时间（小时）**仅现场**］· 解决时间（小时）· 适用勾选。 */
.svc-blk{margin-top:10px;padding:9px 11px;border:1px solid var(--line);border-radius:9px;background:#fff}
.svc-hd{display:flex;align-items:center;gap:10px;margin-bottom:7px}
.svc-hd b{color:var(--label);font-weight:var(--fw-label);font-size:var(--fs-hint)}
.svc-tbl{width:100%;border-collapse:collapse;font-size:var(--fs-hint)}
/* 表内容**一律居中**（需求方 2026-09-18：「SLA填写的数字和标题、列、行，的内容都居中」）——
   表头（列名）/ 档位 / 数字框 / 「适用」勾选 全部水平居中；数字框内的数字也居中。 */
.svc-tbl th,.svc-tbl td{padding:4px 6px;text-align:center;white-space:nowrap}
.svc-tbl th{color:var(--muted);font-weight:500;font-size:11.5px}
.svc-tbl tr + tr td{border-top:1px solid var(--line)}
.svc-tbl th:first-child,.svc-lv{width:52px}
.svc-lv{color:var(--label);font-weight:600}
.mg-panel input[type=number].svc-in{width:96px;text-align:center}
.svc-ck{display:inline-flex;align-items:center;gap:5px;color:var(--label);cursor:pointer}
/* 工作日响应的到场时间用 **BD 文本**（SBD / NBD / 2BD…）→ 文本框，比数字框宽一点放得下 */
.mg-panel input[type=text].svc-in{width:126px;text-align:center}
/* 「+ 添加层级」/ 每行 ✕ 删除（需求方 2026-09-18：层级可增可删，最少保留 1 级） */
.svc-op{width:52px}
.svc-x{width:22px;height:22px;padding:0;border:1px solid var(--line2);border-radius:5px;background:#fff;
  color:var(--muted);font-size:12px;line-height:1;cursor:pointer}
.svc-x:hover{background:#fee2e2;border-color:#fca5a5;color:#b91c1c}
.svc-add{margin-top:6px;text-align:right}
/* 空表占位行（默认不带层级 → 三张表初始都是空的） */
.svc-tbl td.svc-empty{color:var(--muted);font-size:var(--fs-hint);padding:9px 6px}
/* 工作日响应开关右边的「工作时间」标签（BD 到场时限的判定基准） */
.svc-wt{margin-left:10px;color:var(--label);font-weight:var(--fw-label);font-size:var(--fs-hint)}
/* 「工作时间」= 按钮式选时（时 / 分 两个下拉）。需求方 2026-09-18：原数字框**太大、挤占开关和标题** →
   缩到 50×28 的下拉，点开选值（不手敲、无滚轮绕圈问题）。 */
.mg-panel select.svc-hm{width:50px;height:28px;padding:0 3px;font-size:var(--fs-hint)}
.svc-hm-sep{color:var(--muted);font-style:normal;margin:0 1px}
/* 现场服务下**两类响应**（工作日响应 / 7×24 响应）各占一个子块（需求方 2026-09-18）：
   只用虚线细分隔线区分层级 —— ⚠️ 子块的标题行**刻意复用已有的 .svc-hd**（不再定义 .svc-hd2），
   否则客户端 style.css 被缓存时新类不生效 → 「开关掉到文字下面一行」。 */
.svc-sub{margin-top:9px;padding-top:8px;border-top:1px dashed var(--line2)}
.mg-sub{display:none}   /* 条件子行（周几 / 每月第几周 / 隔周起始周）：由 dutySyncRows() 按周期档显示 */
.kv-rows .drow{display:flex;gap:18px;align-items:flex-start}
.kv-rows .dcell{flex:1 1 0;min-width:0;display:flex;gap:8px;align-items:flex-start}
.kv-rows .k{flex:0 0 auto;min-width:76px;text-align:center;white-space:nowrap;
  font-weight:var(--fw-label);color:var(--label);background:var(--hover);border-radius:6px;padding:2px 8px}
/* 值 = **纯文本**（需求方 2026-09-18：「不要刚才加的文本框」）——
   宽度按**内容**取（`flex:0 1 auto`，不再撑满整格），内容短就短、不留大片空白；
   仍**不折行**（超长才省略号），唯一例外是「项目地址」（一条地址一行）。 */
.kv-rows .v{flex:0 1 auto;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.kv-rows .v .addr-view,.kv-rows .v .addr-view>div{white-space:normal;overflow:visible;text-overflow:clip}
.kv .k{color:var(--muted)}
.tree{font-size:13px}
.tree .node{padding:5px 0 5px 0}
.tree .node .row{display:flex;align-items:center;gap:8px;padding:4px 6px;border-radius:6px}
.tree .node .row:hover{background:#f2f7fb}
.tree .kids{margin-left:20px;border-left:1px dashed var(--line2);padding-left:8px}
.tree .caret{width:14px;cursor:pointer;color:var(--muted);user-select:none}
/* 组织架构分区（需求方 2026-09-17：**上面客户组织、下面运维单位**）——
   只在两组之间加一道虚线分隔 + 区块标题，节点本身的样式一律不变。
   区块标题（2026-09-17 追加）：**蓝紫渐变底 + 白字**。
   🔴 渐变末段用 `#6d28d9` 而不是更亮的 `#7c3aed`：白字对 `#6d28d9` 的对比度约 **7.2:1**
      （对 `#7c3aed` 只有约 5.0:1）。小字号标题要留足余量。
   🔴 底色**要紧贴文字**（需求方 2026-09-17 反馈"留白太多"）→ 用 `inline-flex` 自适应宽度，
      不要 `min-width`，内边距压到 2px/9px。 */
.org-sec + .org-sec{margin-top:10px;padding-top:10px;border-top:1px dashed var(--line)}
.org-sec-h{display:inline-flex;align-items:center;gap:7px;
  margin:0 0 5px;padding:2px 9px;border-radius:5px;line-height:1.5;
  background:linear-gradient(90deg,#1d4ed8 0%,#4f46e5 52%,#6d28d9 100%);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.16)}
.org-sec-t{font-size:12.5px;font-weight:700;color:#fff;letter-spacing:.7px}
.org-sec-h .mini{color:rgba(255,255,255,.86);letter-spacing:.3px;font-size:11.5px}
/* 组织架构检索区（需求方 2026-09-17：可检索 客户名称 / 下级名称 / 负责人姓名 / 账号姓名）——
   🔴 **独立成一块面板**，位于组织树面板**上方**（不塞进树面板内部）。 */
.org-search{display:flex;align-items:center;gap:10px}
.org-search-t{font-size:12.5px;font-weight:700;color:var(--text);letter-spacing:.5px;white-space:nowrap}
.org-search input{flex:1 1 auto;min-width:220px;padding:7px 11px;border:1px solid var(--line2);
  border-radius:8px;outline:none;font-size:13px;font-family:inherit;background:#fff}
.org-search input:focus{border-color:var(--accent);box-shadow:0 0 0 3px rgba(14,116,144,.12)}
.org-search .mini{color:var(--muted);white-space:nowrap}
.org-search #org-q-clear{flex:0 0 auto}
/* 检索命中高亮 */
.org-hit{background:#fff3bf;color:#8a5a00;border-radius:3px;padding:0 1px;font-weight:700}
/* 账号命中指示（需求方 2026-09-17）：按账号姓名检索时，命中行上直接显示 `→ 姓名`，
   一眼看出**这个账号挂在哪个部门**（否则树里只有「账号 N 个」，看不出是谁）。 */
.org-acct{display:inline-flex;align-items:center;flex:0 0 auto;white-space:nowrap;
  font-size:11.5px;font-weight:700;color:#0e7490;background:#e8f6fb;border:1px solid #bfe3ef;
  border-radius:999px;padding:0 7px;line-height:1.7;letter-spacing:.3px}
/* 结构化「地址列表」控件（项目地址，需求方 2026-09-17）：每行 = 名称 + 详细地址 + 备注 + 删除 */
.addr-list{display:flex;flex-direction:column;gap:7px;margin-top:2px}
.addr-row{display:flex;gap:8px;align-items:center}
.addr-row input{flex:1 1 auto;min-width:0;padding:6px 10px;border:1px solid var(--line2);
  border-radius:7px;outline:none;font-size:12.5px;font-family:inherit;background:#fff}
.addr-row input:focus{border-color:var(--accent);box-shadow:0 0 0 3px rgba(14,116,144,.12)}
.addr-row .ar-name{flex:0 0 92px}          /* 地址名称：够录 4~6 个字即可（需求方 2026-09-18） */
.addr-row .btn{flex:0 0 auto}
/* 字段标题行 + 右侧工具（如「项目地址」右边的「+ 添加地址」按钮，需求方 2026-09-18）。
   🔴 按钮**要紧挨着标题**（`flex-start`），**不要用 `space-between` 推到最右边** —— 需求方明确否掉了靠右沿的版本。 */
.lb-flex{display:flex;align-items:center;gap:10px}
.addr-view{display:flex;flex-direction:column;gap:3px}
/* 服务日历（2026-09-17 批次 4）：筛选条 + 月历网格 + 班次条目（冲突项红框） */
.oc-bar{display:flex;flex-wrap:wrap;align-items:center;gap:12px 18px;padding-bottom:10px;border-bottom:1px solid var(--line);margin-bottom:10px}
.oc-bar label{display:flex;align-items:center;gap:6px;font-size:12.5px;color:var(--label)}
.oc-bar select{padding:5px 9px;border:1px solid var(--line2);border-radius:7px;outline:none;font-size:12.5px;font-family:inherit;background:#fff;min-width:130px}
.oc-month{font-size:13.5px;font-weight:700;color:var(--text);letter-spacing:.5px;margin-left:auto}
/* 全屏入口（需求方 2026-09-19：项目检索框右边） */
.oc-fullbtn{flex:none}
/* 全屏大标题（仅全屏可见）：第一行 = 当前账号顶层组织全称（加大），换行第二行 = 固定小标题 */
/* 全屏时日历上方的大标题（顶层组织全称 + 「信息化架构运维服务日历」）——
   需求方 2026-09-20：「日历全屏时大标题和副标题**再大些**」→ 27/15px → **40/20px**（字距同步放大）；
   随后「全屏之后大标题**太靠顶上了，往下移一点**」→ 上边距 2px → **28px**（概览与服务日历共用）。 */
.oc-fh{display:none;text-align:center;margin:28px 0 20px}
.oc-fh h1{font-size:40px;font-weight:800;color:var(--text);letter-spacing:2px;margin:0;line-height:1.3}
.oc-fs{margin-top:11px;font-size:20px;font-weight:600;color:var(--muted);letter-spacing:5px}
main#view:fullscreen .oc-fh{display:block}
/* 全屏时**不显示页头的标题与那句说明**（需求方 2026-09-20：概览页头挂 `.ov-head`；
   服务日历随后也要求同样处理 → 挂 `.oc-head`）——
   只藏页头里的标题区（`>div:first-child`），右侧**工具栏 / 全屏按钮保留**
   （否则全屏后按钮也一起消失，只剩 ESC 一条退路）；页头改右对齐 → 工具栏仍在原来的右上角位置。
   两个页面各挂各的类，互不影响。 */
main#view:fullscreen .page-head.ov-head>div:first-child,
main#view:fullscreen .page-head.oc-head>div:first-child{display:none}
main#view:fullscreen .page-head.ov-head,
main#view:fullscreen .page-head.oc-head{justify-content:flex-end;margin-bottom:8px}
.oc-cf{color:#b91c1c}
.oc-grid{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:6px}
.oc-hd{text-align:center;font-size:12px;font-weight:700;color:var(--muted);padding:4px 0}
/* 工作日格子的底色（需求方 2026-09-20）：「**浅蓝渐变**」—— 先说"一定要浅"，看过实际界面后追加
   「**太浅了，稍微再深点**」，所以取浅蓝但**看得出蓝**（上近白 → 下浅蓝，约 blue-50～blue-100 之间）。
   仍属浅色调：不会压过格子里的日期背条与排班卡片。
   其余三态（周末淡灰 / 节假日红渐变 / 调休上班白底绿标）保持原样不变。 */
.oc-cell{min-height:96px;border:1px solid var(--line);border-radius:8px;padding:5px 6px;
  background:linear-gradient(180deg,#f8fbff 0%,#e4effc 100%);display:flex;flex-direction:column;gap:4px}
.oc-cell.blank{background:transparent;border:0}
/* 上月 / 下月落在本月视图里的窗格（需求方 2026-09-20：「前后月的窗格用斜线拉满体现」）：
   斜线填充 + 灰色日期数字 —— 一眼分清是上月/下月的哪一天，也不会被误当成本月的格子。 */
.oc-cell.other{border-style:dashed;background-color:#fcfdff;
  background-image:repeating-linear-gradient(45deg,rgba(148,163,184,.20) 0,rgba(148,163,184,.20) 1px,transparent 1px,transparent 8px)}
.oc-cell.other .oc-d{background:transparent;color:#c3cdd9;font-weight:400;padding:0 4px}
.oc-cell.other:hover{background-color:#f7fafd}
/* 「批量排班 / 批量删除」弹窗（需求方 2026-09-20）
   · 项目改为**直接检索**（不再选客户）→ 原来的客户 / 项目下拉样式 `.ocb-sel` 已随之废弃移除 */
/* 批量排班的「项目」检索列表：比人员列表矮一档 —— 一屏里两个检索区都要看得见
   （双类选择器提高特异性，压过上面的 .rsp-list{max-height:52vh}） */
.rsp-list.ocb-plist{max-height:26vh;margin-top:8px}
/* 关联客户（选中项目后**自动带出** · 只读一行：简称 + 全称） */
.ocb-cli{display:flex;align-items:center;gap:9px;font-size:13px;background:#f6f9fd;
  border:1px solid var(--line);border-radius:8px;padding:8px 11px;min-height:36px;box-sizing:border-box}
.ocb-cli b{color:#0e5a72;font-weight:700}
.ocb-rule{font-size:12.5px;line-height:1.95;background:#f6f9fd;border:1px solid var(--line);border-radius:8px;padding:8px 11px}
.ocb-rule b{color:var(--muted);font-weight:600;margin-right:2px}
.ocb-warn{color:#b45309;font-weight:600}
.ocd-bar{display:flex;align-items:center;gap:8px;margin-bottom:8px}
.ocd-bar .mini{margin-left:auto}
.ocd-i{display:flex;align-items:center;gap:8px;padding:5px 9px;border:1px solid var(--line);border-radius:8px;
  background:#fff;cursor:pointer;font-size:12.5px;margin-bottom:5px}
.ocd-i:hover{border-color:#93b4e8;background:#f7fbff}
.ocd-i.on{border-color:#2563eb;background:#eef4fd}
.ocd-i input{margin:0;flex:none}
.ocd-d{font-weight:600;font-variant-numeric:tabular-nums}
.ocd-i .mini{margin-left:auto;color:var(--muted)}
.oc-cell:hover{background:linear-gradient(180deg,#f1f8ff 0%,#d8e8fb 100%)}
/* 日期（需求方 2026-09-20）：显示**年月日**（YYYY-MM-DD）并**带背条** —— 青蓝渐变圆角条 + 白字，
   等宽数字对齐；周末 / 节假日 / 前后月各自换背条底色，原来的四态区分照旧。 */
.oc-d{display:inline-block;font-size:10.5px;font-weight:700;line-height:16px;padding:0 6px;border-radius:5px;
  background:linear-gradient(90deg,#0e7490,#2563eb);color:#fff;font-variant-numeric:tabular-nums;letter-spacing:.2px}
/* 格子里的条目容器（需求方 2026-09-20 最终口径：「**服务日历单日期格固定显示 4 条目**，
   超过 4 条目按之前的方式滚播」——期间在 3 条 / 4 条之间来回改过，**以 4 条为准**）。
   条目高度锁死 38px：4 条 = 4×38 + 3×1（分隔虚线）+ 6×4（间隙）——4 张卡 + 3 条虚线 = 7 项 → 6 个 gap，
   合计 179px，精确可算；超过 4 条就滚动（每 10 秒轮换一格，鼠标移入停、可用滚轮自己翻 —— JS 见 `ocScrollInit()`）。
   滚动条**隐藏**：格子只有百来像素宽，出现滚动条会把卡片挤窄。 */
.oc-chips{display:flex;flex-direction:column;gap:4px;overflow-y:auto;overflow-x:hidden;
  height:calc(4 * 38px + 3 * 1px + 6 * 4px);scrollbar-width:none}
.oc-chips::-webkit-scrollbar{width:0;height:0;display:none}
/* 排班卡片（需求方 2026-09-20 定稿）：**两行** ——
   ① 姓名（靠左、**加粗**）+「驻场：工作日时间范围」（**靠右**）；② 项目名称（靠左）。
   🔴 底色与字色**互换**：深蓝底白字 → **白底 + 深蓝字**；🔴 需求方随后要求「**驻场的条目左边框可以参考
   现在工单条目左边框那个效果**」→ 加一条**深蓝左侧竖条**（与工单条目的亮蓝左条同款做法）；
   冲突（`cf`）仍用 **box-shadow 红描边**标出（不占布局，避免抖动）。
   高度锁死 38px（两行：15.5 + 15.5 + 1 + 上下 padding 6）—— 格子"固定 3 条"的高度就靠它。 */
.oc-chip{flex:none;height:38px;box-sizing:border-box;font-size:11.5px;line-height:1.35;padding:3px 7px 3px 6px;
  border:0;border-left:3px solid #1e3a8a;border-radius:6px;
  background:#fff;color:#1e3a8a;cursor:pointer;overflow:hidden;
  /* 🔴 承载「完工」水印（2026-09-22）：relative 给水印定位参照；**isolation:isolate 让本元素自成层叠上下文**，
     这样水印（z-index:-1）只压在**本条目自己的底色之上、文字之下**，不会掉到格子底色后面去。 */
  position:relative;isolation:isolate}
.oc-chip:hover{background:#eff5ff}
.oc-c1{display:flex;align-items:baseline;gap:6px}
/* 姓名**可收缩**（长了显示省略号），右侧「驻场：时间范围」不压缩 —— 保证靠右那一截始终完整 */
.oc-c1 b{flex:0 1 auto;min-width:0;font-weight:700;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.oc-when{margin-left:auto;flex:0 0 auto;font-size:11px;color:#3b5bab}
.oc-c2{margin-top:1px;color:#33518f;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* 冲突（同一人同日时段重叠）：红描边提示 —— 不阻断保存；用 box-shadow 不改变尺寸 */
.oc-chip.cf{box-shadow:0 0 0 1px #dc2626}
/* 同一格里**多于一条**排班时，**条目与条目中间**留一条细细的虚线（需求方 2026-09-20 原话：
   「条目与条目中间给条细细的虚线」）—— 用独立的 `.oc-sep` 元素插在两条卡片之间，
   由格子的 flex gap 自然把它顶在两条的正中间（不是贴在某一侧的边上）。
   🔴 `flex:none` 必须给：`.oc-chips` 是 flex 列容器，写死 max-height（= 4 条）后
   子项默认会被 `flex-shrink` 压扁（实测卡片被压成 29px → 永远装得下、永远不溢出、滚不起来）。 */
.oc-sep{flex:none;height:0;border-top:1px dashed rgba(30,58,138,.28)}
/* 工单条目（需求方 2026-09-20）：与**排班条目同色调**（白底 + 深蓝字）——
   （先试过深蓝渐变底，需求方反馈「太突兀了，还是和驻场的一样色调吧」）；
   两者靠**左侧竖条颜色**区分：排班 = 深蓝，工单 = **橙色**（需求方指定）。
   两行 —— ① **工程师**（靠左、加粗）+「远程 / 现场：预约时间 - 截止基线」（靠右，只写钟点）；
   ② **项目名称**（靠左）+ **三个 KPI 小图标**（响应 / 到场 / 解决：✓ 达标 · ✗ 违约 · · 还没到考核点）——
   需求方 2026-09-20：「考核点的勾和叉就**不需要小白格的背景**了」→ 只留字符，按考核结果着色。
   **已解决 / 未解决 / 已关闭** → **第一行整行**加删除线（原话「用删除线来整行划去条目中的第一行内容」；
   2026-09-20 追加「是从**姓名开始到时间**划整行」，并把「已关闭」也纳入，见下方 .oc-tk.done 那段）。
   高度同样锁 38px（统一"固定 3 条"的高度算法）。 */
.oc-tk{flex:none;height:38px;box-sizing:border-box;font-size:11.5px;line-height:1.35;padding:3px 7px 3px 6px;
  border:0;border-left:3px solid #f97316;border-radius:6px;
  background:#fff;color:#1e3a8a;cursor:pointer;overflow:hidden;
  /* 同上：承载「完工」水印（`.oc-tk.done` 时铺） */
  position:relative;isolation:isolate}
.oc-tk:hover{background:#fff7ed}
.oc-tk1{display:flex;align-items:baseline;gap:6px}
.oc-tk1 b{flex:0 1 auto;min-width:0;font-weight:700;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:#1e3a8a}
/* 🔴 删除线**已全部取消**（需求方 2026-09-20 先要「从姓名到时间划整行」，随即改口：
   「这个划线取消吧，都不用划线，换种方式 —— 在条目的三个考核小图标**左边**显示个『**完工**』标签
   （亮蓝渐变底色 + 白字）」）。历史坑留档：曾用 `.oc-tk1{text-decoration:line-through}` ——
   `.oc-tk1` 是 **flex 容器**，`text-decoration` **不会传播到 flex 子项**，计算值虽是 line-through
   却**屏幕上一条线都画不出来**（假绿断言掩盖过它）；后来改的 `::after` 整行线也一并撤掉了。 */
.oc-tk .oc-when{color:#3b5bab}
.oc-tk2{display:flex;align-items:baseline;gap:6px;margin-top:1px}
.oc-tkp{flex:0 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:#33518f}
/* 〔历史〕「完工」**标签**（亮蓝渐变底 + 白字，曾在姓名右边）—— 需求方 2026-09-22：
   「条目中原来的完工标签不要了，但是不要影响水印的显示」⇒ **规则整条删除**（无残留），
   语义改由下方 `.oc-tk.done::before / .oc-chip.fin::before` 的**水印**扛（判定条件一字未改）。 */
/* ===== 「完工」水印（需求方 2026-09-22）=====
   「服务日历中，带完工标签的条目，将带有『完工』两个字的水印（**斜、等距满铺、透明浅色**）」。
   实现：给带完工标签的条目（工单条目 `.oc-tk.done` / 驻场条目 `.oc-chip.fin`）用 `::before` 铺一层
   **重复平铺的 SVG 贴砖**（每砖一个斜排的「完工」，字色 #2563eb、由 opacity 压成浅色）；砖块网格本身等距，
   所以平铺出来就是"等距满铺"，字符自带 −24° 倾斜 = 那点"斜"。
   · `z-index:-1` + 容器 `isolation:isolate` ⇒ 水印在**条目底色之上、文字之下**，不糊字；
   · `pointer-events:none` ⇒ 水印不吃点击（条目的 onclick 照旧）；
   · 条目本来就有 `overflow:hidden` + `border-radius` ⇒ 水印自然被裁在圆角内，不会溢到格子。
   🔴 2026-09-22 二次调整：条目里的「完工」**标签已撤**，水印语义不变；并按需求方「水印文字可以再深一点点」
      把 opacity 由 .18 调到 **.25**（实测"开水印 / 关水印"逐像素比对的**最大色差 39 → 54**，仍属浅色不糊字）。
   🔴 中文用**百分号编码**（完=%E5%AE%8C 工=%E5%B7%A5）——data URI 里直接写中文在部分解析路径上会乱码；
   🔴 这里是**普通样式块**（不属于数字大屏那一段），所以可以改；数字大屏用的是另一套类名
      （oc-row / oc-name / oc-slot…），**不共用** `.oc-tk` / `.oc-chip`，不会被动到。
      ⚠️ 注释里刻意**不写**数字大屏那个作用域选择器名 —— 写进去会让以后 `grep` 数"改动落点"时
      把注释行当成真规则、误判成改了禁改区（2026-09-22 亲测被带偏过一次）。
   🔴 2026-09-22 二次扩展（需求方：「这种完工水印**同时应用于**相关工单的**工单页面**（工单点击查阅的那个页面），
      以及**工单管理列表中行的显示**；若行是**取消**工单的话，则水印是**已取消**」）⇒ 同一套贴砖搬到
      列表行 与 查阅页 A4 卡；取消单换字为「已取消」；判定与日历**完全同一套**（`app.js` 的 `tkWmCls`）。 */
/* —— 一套水印，三处共用（需求方 2026-09-22）：
   ① 服务日历条目 `.oc-tk.done` / `.oc-chip.fin`；② 工单管理**列表行** `tr.wm-row[.wm-cancel]`；
   ③ 工单**查阅页**那张 A4 卡 `.card.wm-pg[.wm-cancel]`。
   默认贴砖 = 「完工」；`.wm-cancel` 只换字（**已取消**）。
   🔴 两种铺法**按宿主分**（2026-09-22 踩过一次真回归：使用方报「列表内容错乱」）：
     · **`tr`（表格行）只能用 `background-image`** —— 在 `<tr>` 里放 `::before`，浏览器会把它当成
       **多出来的一个单元格**参与列宽计算，整张表被重排（实测：表格宽 1848 → 2094、行高 102 → 68、列位置全变）。
       background 不生成盒子，绝不影响布局。行上的透明度写进 SVG（`fill-opacity`）—— background-image
       没法只给"图层"设 opacity。
     · `div`（日历条目 / A4 卡片）用 `::before` 层（`.wm-pg`）—— 能精确压在**文字之下**、也不吃点击。
   🔴 2026-09-22 三次口径（需求方）：日历条目 .25 → 工单页/列表行**更小更淡**（贴砖 28×22、透明度 **.13**）。 */
/* ⚠️ 必须铺在 **`td`** 上：实测 Chromium **不绘制 `tr` 的 background-image**
   （贴砖图本身合法：能解码、有 95 个非透明像素；挂在 tr 上却一个像素都不出现 —— 挂 td 上正常）。
   铺在 td 上同样**不生成盒子、不影响布局**（background 永远不参与布局）。 */
tr.wm-row>td{background-repeat:repeat;background-size:28px 22px}
tr.wm-row:not(.wm-cancel)>td{
  background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='28' height='22'%3E%3Ctext x='14' y='15' font-family='sans-serif' font-size='10' fill='%232563eb' fill-opacity='.13' text-anchor='middle' transform='rotate(-24 14 11)'%3E%E5%AE%8C%E5%B7%A5%3C/text%3E%3C/svg%3E")}
tr.wm-row.wm-cancel>td{
  background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='40' height='22'%3E%3Ctext x='20' y='15' font-family='sans-serif' font-size='9' fill='%232563eb' fill-opacity='.13' text-anchor='middle' transform='rotate(-24 20 11)'%3E%E5%B7%B2%E5%8F%96%E6%B6%88%3C/text%3E%3C/svg%3E");
  background-size:40px 22px}
/* 伪元素铺法（div 宿主） */
.wm-pg{position:relative;isolation:isolate}
.oc-tk.done::before, .oc-chip.fin::before, .wm-pg::before{
  content:'';position:absolute;inset:0;z-index:-1;pointer-events:none;border-radius:inherit;
  background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='28' height='22'%3E%3Ctext x='14' y='15' font-family='sans-serif' font-size='10' fill='%232563eb' text-anchor='middle' transform='rotate(-24 14 11)'%3E%E5%AE%8C%E5%B7%A5%3C/text%3E%3C/svg%3E");
  background-repeat:repeat;background-size:28px 22px;opacity:.25}
/* 已取消：同一款贴砖、只把字换成「已取消」（贴砖加宽到 40×22，三个字在斜排里排得下） */
.wm-pg.wm-cancel::before{
  background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='40' height='22'%3E%3Ctext x='20' y='15' font-family='sans-serif' font-size='9' fill='%232563eb' text-anchor='middle' transform='rotate(-24 20 11)'%3E%E5%B7%B2%E5%8F%96%E6%B6%88%3C/text%3E%3C/svg%3E");
  background-size:40px 22px}
/* 🔴 「工单里的水印**太大了，要小**」+「要**很小，很淡**」（需求方 2026-09-22 两次口径）：
   A4 工单页**不再放大贴砖**（原 112×88 → 56×44 → 现在**与条目同尺寸 28×22**，字号 10px），
   并把这一处的透明度单独压到 **.13**（日历条目仍是 .25）—— 大面积上小字 + 淡色才像水印，不像噪点。 */
.wm-pg::before{opacity:.13}
/* ============ 「解决 / 未解决」弹窗里的建单 AI 建议（需求方 2026-09-22）============
   弹窗可能在**任何页面**打开（工单列表 / 查阅页），建单页那套 `.tk-ai-*` 是随建单页一起注入的
   → 这里**另起 `.tk-sug-*`**、样式落在全局，不依赖建单页。
   ⚠️ 本段是普通样式块（不属于数字大屏那一段），落在日历 / 水印段之后、大屏段之前。 */
.tk-sug{margin-top:6px;display:flex;flex-direction:column;gap:8px;max-height:300px;overflow:auto}
.tk-sug-it{border:1px solid var(--line);border-radius:9px;background:#fff}
.tk-sug-it[data-used="1"]{border-color:#86efac;background:#f7fef9}
.tk-sug-hd{display:flex;align-items:center;gap:8px;padding:8px 10px;cursor:pointer}
.tk-sug-hd .i{flex:0 0 auto;width:0;height:0;border-left:5px solid #64748b;border-top:4px solid transparent;border-bottom:4px solid transparent;transition:transform .15s}
.tk-sug-it[data-open="1"] .tk-sug-hd .i{transform:rotate(90deg)}
.tk-sug-tt{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:700;color:var(--text)}
.tk-sug-bdg{flex:0 0 auto;font-size:11px;padding:1px 7px;border-radius:999px;border:1px solid #bfdbfe;background:#eff6ff;color:#1d4ed8}
.tk-sug-bdg.model{border-color:#ddd6fe;background:#f5f3ff;color:#6d28d9}
.tk-sug-bd{display:none;padding:0 10px 6px}
.tk-sug-it[data-open="1"] .tk-sug-bd{display:block}
.tk-sug-k{font-size:11px;color:var(--muted);margin:2px 0 3px}
.tk-sug-v{font-size:13px;line-height:1.75;color:var(--text);white-space:pre-wrap;word-break:break-word}
.tk-sug-ft{display:flex;align-items:center;gap:6px;padding:0 10px 9px}
.tk-sug-msg{color:#16a34a}
.tk-sug-msg.bad{color:#dc2626}
/* ============ 「交付管理」报告面板（需求方 2026-09-22）============
   生成记录表 + 生成弹窗里的**邮件字段预留**区。本段是普通样式块，落在日历 / 水印 / 建议段之后、
   数字大屏段之前（大屏段从 2573 行起）。 */
.mg-rep-list{margin-top:8px;max-height:360px;overflow:auto;border:1px solid var(--line);border-radius:8px;background:#fff}
.mg-rep-list .rep-tbl{width:100%;border-collapse:collapse}
.mg-rep-list .rep-tbl th{position:sticky;top:0;background:#f1f6fd;z-index:1}
.mg-rep-list .rep-tbl th,.mg-rep-list .rep-tbl td{padding:6px 8px;font-size:12px;border-bottom:1px solid var(--line);text-align:left;vertical-align:top}
.mg-rep-list .rep-tbl a{color:#1d4ed8}
.rep-mail{border:1px solid #dbe7f6;background:#f8fbff;border-radius:8px;padding:10px 12px;margin-top:12px}
.rep-mail .ln{display:flex;align-items:center;gap:8px;margin-top:8px}
/* 🔴 `.ln` = 「标签 + 控件」的行容器 —— 此前**全站没有这条样式**（只有上面那条 .rep-mail .ln 限定版），
   于是子元素上写的 `flex:1` 全部**失效**：输入框退回浏览器默认宽度（约 170px）、怎么改都"伸不满"。
   用户 2026-09-22 反馈的"输入框太短"就是这个根因（会议议题弹窗、报告邮件面板、在线语音面板都踩到）。
   这里补一条**通用**的 flex 行：标签按自身宽度（`.mg-lb` 有 flex:0 0 76px），输入类控件吃满剩余。
   ⚠️ 只给「填满」+「垂直居中」，**不加外边距**（间距由各调用处的 style 自己给，避免动到既有版式）。 */
.ln{display:flex;align-items:center;gap:8px}
.ln>.mg-lb{flex:0 0 auto}
.ln input[type=text],.ln input[type=date],.ln input[type=time],.ln select{flex:1 1 auto;min-width:0}
.rep-mail input[type=text],.rep-mail input[type=date]{height:34px;border-radius:8px;border:1px solid var(--line2);padding:0 10px;font-size:13px;font-family:inherit;color:var(--text);background:#fff}
.rep-mail select,.rep-mail input[type=time]{height:34px;border-radius:8px;border:1px solid var(--line2);padding:0 8px;font-size:13px;font-family:inherit;color:var(--text);background:#fff}
/* 账号里的「发件箱设置」（需求方 2026-09-22）：按钮 + 一行状态摘要；展开区里的行用 mbln（新类名，不碰别处样式）。
   🔴 `.mb-set` 必须**跨两列**（需求方 2026-09-22：「邮箱设置部分的框宽度有问题」）：
   表单 `.form` 是两列网格，只有 `.f.full` 才 `grid-column:1/-1`，而发件箱块是**裸 div**（不是 `.f`）→
   实测只占一列 294px、右边半幅空着、里面输入框被压到 168px。加这条与整行字段对齐（604）。 */
/* 报告按钮（需求方 2026-09-22：「这些报告按钮都给上底色，默认不要选好」）——
   浅蓝底色、**默认不选中**（不用主色 pri，避免看着像"已选中"） */
.btn.rep{background:#eef4fd;border-color:#c9dcf5;color:#1d4ed8}
.btn.rep:hover{background:#e3eefc;border-color:#a9c9ef}
.mb-set{display:flex;align-items:center;gap:10px;flex-wrap:wrap;grid-column:1/-1}
.mb-inline{flex:1 1 100%;border:1px solid #dbe7f6;background:#f8fbff;border-radius:8px;padding:10px 12px;margin-top:8px}
.mbln{display:flex;align-items:center;gap:8px;margin-top:10px}
.mbln .k{min-width:92px;font-size:12.5px;color:#64748b}
.mbln input[type=text],.mbln input[type=password],.mbln select{height:34px;border-radius:8px;border:1px solid var(--line2);padding:0 10px;font-size:13px;font-family:inherit;color:inherit;background:#fff;flex:1;min-width:0}
.oc-kpi{flex:none;display:flex;gap:4px;font-weight:700;margin-left:auto}
.oc-kpi i{font-style:normal;font-size:11.5px;line-height:1.35}
.oc-kok{color:#15803d}
.oc-kbad{color:#dc2626}
.oc-kwait{color:#cbd5e1}
/* 服务日历 · **条目小浮窗**（需求方 2026-09-20）：左键单击条目只弹它 —— 列信息 + 一个「复制」按钮。
   定位由 JS 按鼠标位置夹进视口（`ocPopShow`），这里只管样式。 */
#oc-pop{position:fixed;z-index:70;display:none;width:330px;max-width:calc(100vw - 20px);max-height:72vh;overflow:auto;
  background:#fff;border:1px solid var(--line2);border-radius:10px;box-shadow:0 14px 36px rgba(15,35,70,.24)}
#oc-pop.on{display:block}
.oc-pop-hd{display:flex;align-items:center;gap:8px;padding:9px 12px;background:linear-gradient(90deg,#0e7490,#2563eb);
  color:#fff;border-radius:9px 9px 0 0}
.oc-pop-hd b{font-size:13px}
.oc-pop-x{margin-left:auto;flex:none;width:22px;height:22px;padding:0;border:0;border-radius:6px;
  background:rgba(255,255,255,.18);color:#fff;cursor:pointer;font-size:12px;line-height:22px;text-align:center}
.oc-pop-x:hover{background:rgba(255,255,255,.32)}
.oc-pop-bd{padding:7px 12px}
.oc-pop-r{display:flex;gap:8px;font-size:12.5px;line-height:1.65;padding:3px 0;border-bottom:1px dashed #eef1f5}
.oc-pop-r:last-child{border-bottom:0}
.oc-pop-r i{flex:0 0 74px;font-style:normal;color:var(--muted)}
.oc-pop-r span{flex:1 1 auto;min-width:0;color:var(--text);white-space:pre-wrap;word-break:break-all}
.oc-pop-ft{display:flex;align-items:center;gap:8px;padding:8px 12px;border-top:1px solid var(--line)}
.oc-pop-ft .mini{margin-left:auto}
/* 服务日历 · **人员窗格行 + 小日历浮窗**（需求方 2026-09-20）：
   位置 = **全屏按钮那一排里、按钮的右边**（需求方纠正：「加在全屏按钮的右边，不是在日历区域里」）；
   每个人员一个窗格（姓名 + 小日历图标），图标右上角**覆盖**显示本月剩余工时；
   点图标弹小日历，工作日格子底部**色块面积**= 当天还剩多少可安排时间（每工作日 8 小时）。 */
.oc-engrow{display:flex;flex-wrap:wrap;gap:8px;margin:0}
.oc-eng{display:flex;align-items:center;gap:7px;padding:3px 9px;border:1px solid var(--line2);border-radius:9px;background:#fff}
.oc-eng-nm{font-size:12.5px;font-weight:600;color:var(--text);max-width:78px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.oc-eng-cal{position:relative;flex:none;width:26px;height:26px;padding:0;border:1px solid var(--line2);border-radius:7px;
  background:#f8fafc;cursor:pointer;font-size:13px;line-height:24px;text-align:center}
.oc-eng-cal:hover{border-color:var(--accent);background:#eef4fd}
.oc-eng-badge{position:absolute;top:-8px;right:-10px;font-style:normal;font-size:10px;font-weight:700;line-height:15px;
  padding:0 5px;border-radius:999px;background:linear-gradient(90deg,#0e7490,#2563eb);color:#fff;white-space:nowrap}
#oc-mini{position:fixed;z-index:70;display:none;width:300px;padding:10px 12px;background:#fff;
  border:1px solid var(--line2);border-radius:10px;box-shadow:0 14px 36px rgba(15,35,70,.24)}
#oc-mini.on{display:block}
.oc-mini-hd{display:flex;align-items:center;gap:8px;margin-bottom:8px}
.oc-mini-hd b{font-size:13.5px}
.oc-mini-hd .mini{margin-left:auto}
.oc-mini-g{display:grid;grid-template-columns:repeat(7,1fr);gap:3px}
.oc-mini-w{text-align:center;font-size:10px;font-weight:700;color:var(--muted);padding-bottom:2px}
.oc-mini-d{position:relative;height:36px;border:1px solid var(--line);border-radius:6px;background:#fbfdff;overflow:hidden}
.oc-mini-d.off{background:#f1f5f9;border-style:dashed}
.oc-mini-n{position:absolute;left:3px;top:1px;z-index:1;font-size:9.5px;color:var(--muted);font-variant-numeric:tabular-nums}
.oc-mini-bar{position:absolute;left:0;right:0;bottom:0;background:linear-gradient(180deg,#38bdf8,#2563eb)}
.oc-mini-ft{margin-top:8px;color:var(--muted)}
/* ---------------------------------------------------------------
   节假日例外（2026-09-19 复刻 CrossNet-AIIT 服务日历格内「节假」开关）：日期行 + 四种底色
     · 工作日登记的「节假」= **节假日** → 红渐变底（当天按非工作日计，SLA 考核顺延）；
     · 周末登记的「节假」 = **调休上班日** → 白底 + 绿标（按正常工作日计时，SLA 不顺延）；
     · 未登记的周末 = 淡灰；其余日期 = 白（原来的一致底色）。
   ⚠️ 顺序要紧：.wk 在前、.hol 在后（红底必须压过灰底）；且各态都要单独写 :hover ——
      否则会被上面那条 .oc-cell:hover 的浅蓝底盖掉。 */
.oc-hdrow{display:flex;align-items:center;gap:4px;min-height:17px}
.oc-wk{flex:none;font-size:10px;line-height:15px;padding:0 5px;border-radius:999px;background:#e8f7ee;
  border:1px solid #b7e4c7;color:#15803d;font-weight:700;white-space:nowrap}
.oc-hsw{margin-left:auto;flex:none;height:15px;padding:0 6px;border-radius:999px;border:1px solid #e2e8f0;
  background:rgba(255,255,255,.75);color:#94a3b8;font-size:10px;line-height:13px;font-family:inherit;cursor:pointer}
.oc-hsw:hover{border-color:#f0a7a7;color:#b91c1c;background:#fff}
.oc-hsw.on{border-color:#dc2626;background:#fff1f2;color:#b91c1c;font-weight:700}
.oc-cell.wk{background:#f6f8fa;border-color:#e6ebf1}
.oc-cell.wk:hover{background:#eef2f7}
.oc-cell.wk .oc-d{background:#e9eef4;color:#7b8798}
.oc-cell.hol{background:linear-gradient(168deg,#fca5a5 0%,#ef4444 55%,#b91c1c 100%);
  border-color:#991b1b;box-shadow:inset 0 1px 0 rgba(255,255,255,.28),0 2px 9px rgba(153,27,27,.26)}
.oc-cell.hol:hover{background:linear-gradient(168deg,#f8a0a0 0%,#e23c3c 55%,#a91a1a 100%)}
.oc-cell.hol .oc-d{background:rgba(255,255,255,.94);color:#b91c1c;text-shadow:none}
/* 节假日格子里的排班卡片**不再单独改色** —— 卡片刻度统一「深蓝底 + 白字」（需求方 2026-09-20），
   深蓝在红格子上边界清晰，无需再翻成白底红字（翻了反而破坏统一口径）。 */
.oc-cell.hol .oc-hsw{background:rgba(255,255,255,.92);border-color:#fecaca;color:#991b1b}
.oc-cell.hol .oc-hsw.on{background:#fff;border-color:#7f1d1d;color:#7f1d1d}
.oc-cell.holwk{background:#fff;border-color:#bbf7d0;box-shadow:inset 0 0 0 1px rgba(22,163,74,.10)}
.oc-cell.holwk:hover{background:#f6fef9}
/* 图例（日历下方说明文字里的色块） */
.oc-lg{display:inline-block;font-size:11.5px;font-weight:700;padding:0 6px;border-radius:5px;border:1px solid var(--line)}
.oc-lg.wk{background:#f6f8fa;border-color:#e6ebf1;color:#8a99ab}
.oc-lg.hol{background:linear-gradient(168deg,#fca5a5 0%,#ef4424 55%,#b91c1c 100%);border-color:#991b1b;color:#fff}
.oc-lg.holwk{background:#fff;border-color:#bbf7d0;color:#15803d}
/* SLA 统计（2026-09-17 批次 5）：KPI 卡片 + 时限设置区 */
.sla-kpis{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px;margin-top:12px}
.sla-kpi{border:1px solid var(--line);border-radius:10px;padding:10px 12px;background:#fff}
.sla-kpi .k{font-size:12px;color:var(--muted)}
.sla-kpi .v{font-size:22px;font-weight:700;color:var(--text);line-height:1.35}
.sla-kpi .s{font-size:11.5px;color:var(--muted)}
.sla-kpi.ok .v{color:#0f766e}
.sla-kpi.warn .v{color:#b91c1c}
.sla-rules{margin-top:14px;padding-top:12px;border-top:1px dashed var(--line)}
.sla-in{padding:5px 8px;border:1px solid var(--line2);border-radius:6px;outline:none;font-size:12.5px;font-family:inherit}
.sla-in:focus{border-color:var(--accent);box-shadow:0 0 0 3px rgba(14,116,144,.12)}
/* 成本管理（2026-09-17 批次 5b）：合计行加重 */
.cost-sum{background:#f5fafc}
.cost-sum td{font-weight:600}
/* 模型设置（2026-09-17 批次 6a）：测试连接结果条 */
.aim-test{margin-top:12px;padding:10px 12px;border-radius:8px;border:1px solid var(--line);font-size:12.5px;background:#f8fafc}
.aim-test.ok{background:#f0fdf4;border-color:#bbf7d0;color:#166534}
.aim-test.bad{background:#fef2f2;border-color:#fecaca;color:#b91c1c}
/* 「关联账号」抽屉（2026-09-17）：改用可检索多选控件（ssel），不再铺表格 —— 无需额外样式 */

#drawer-mask{position:fixed;inset:0;background:rgba(13,33,55,.30);z-index:29;opacity:0;visibility:hidden;transition:opacity .2s ease,visibility .2s ease}
#drawer-mask.on{opacity:1;visibility:visible}
#drawer,#drawer-l{position:fixed;top:0;bottom:0;width:440px;background:var(--card);transition:transform .22s ease;z-index:30;display:flex;flex-direction:column}
#drawer{right:0;border-left:1px solid var(--line);box-shadow:-14px 0 40px rgba(16,38,60,.14);transform:translateX(100%)}
#drawer.on{transform:none}
/* 左侧「相关工单」抽屉（需求方 2026-09-20）：从工单流转记录点工单号开出来，
   🔴 **紧贴当前详情抽屉的左边框拉出**（两个详情**挨着**并排对照）——
   横向位置由 JS 按右抽屉实宽设置（`right = 右抽屉宽`，右抽屉没开则为 0），这里只负责动效与外观：
   关闭态 opacity/visibility 收起（fixed + 位移都不产生滚动条），打开时从右往左滑出，像从详情左边缘拉出来。 */
#drawer-l{right:0;box-shadow:-12px 0 34px rgba(16,38,60,.12);transform:translateX(-18px);opacity:0;visibility:hidden;
  transition:transform .2s ease,opacity .2s ease,visibility .2s ease;z-index:31}
#drawer-l.on{transform:none;opacity:1;visibility:visible}
/* 项目信息详情用**更宽的抽屉**（需求方 2026-09-18）：
   默认 440px 下并排两格会把值列挤到 60 多像素 → 项目名称 / 手机号折行，故加宽；
   行结构定型为「编号独立一行 + 其余最多 2 格并排」后，860/720 偏空（需求方两次提醒「留白太多 / 缩小」）——
   但收到 640 时实测**长客户名会被截断**（「中国电子技术标准化研究院华东分院」需 ~204px，640 下只给到 188px），
   故定为 **680px**：库里现有最长客户名 / 项目名 + 手机号 + 标签块 76px 都放得下、不折行不截断。
   值本身按内容取宽（见 .kv-rows .v），抽屉不为"最长内容"预留大片空白。
   ⚠️ 只有 project 详情加 `.dr-wide`（其它实体详情维持 440px）。 */
#drawer.dr-wide{width:min(680px,94vw)}
/* 宽抽屉里的**留白**也放宽一点（需求方 2026-09-18「合理留白」）—— 卡片到抽屉边、字段行之间都要有呼吸感。 */
#drawer.dr-wide .db{padding:18px 22px}
/* 「用户管理 → 详情」用**加宽一倍的抽屉**（需求方 2026-09-26：「用户详情的抽屉加宽一倍」）——
   默认 440px → **880px**：部门 / 账号 / 项目三张表列多，440 下横向太挤。
   ⚠️ 只有「用户管理详情」加 `.dr-xwide`（项目详情仍是 `.dr-wide` 680px、其它实体维持 440px）；
      打开时加、关闭时移除，不会串到别的抽屉。 */
#drawer.dr-xwide{width:min(880px,96vw)}
#drawer.dr-xwide .db{padding:18px 22px}
#drawer .dh,#drawer-l .dh{padding:13px 16px;border-bottom:1px solid var(--line);display:flex;justify-content:space-between;align-items:center}
#drawer .dh b,#drawer-l .dh b{font-size:14.5px;font-weight:500}
/* 抽屉标题右边的工具区（工单详情的「复制」按钮，需求方 2026-09-20）：
   `margin-right:auto` 让按钮**紧挨标题**、把「关闭」继续留在最右（.dh 是 space-between）。 */
#drawer .dh-tools{margin-left:10px;margin-right:auto;display:inline-flex;align-items:center;gap:6px}
#drawer .dh-tools .btn{height:24px;padding:0 10px;font-size:12px;line-height:22px;border-radius:7px}
#drawer .db,#drawer-l .db{overflow:auto;padding:14px 16px;flex:1}
#drawer .df,#drawer-l .df{padding:11px 16px;border-top:1px solid var(--line);display:flex;gap:8px;flex-wrap:wrap}
/* 工单流转记录里的**工单号链接**（需求方 2026-09-20）：点一下在左侧开这张单的详情，便于对照 */
.tk-no{color:var(--accent);font-weight:600;text-decoration:underline;text-underline-offset:2px;cursor:pointer}
.tk-no:hover{color:#1d4ed8}

#modal{position:fixed;inset:0;background:rgba(13,33,55,.42);display:none;align-items:center;justify-content:center;z-index:120}
#modal.on{display:flex}
.modal-box{width:640px;max-width:94vw;max-height:90vh;background:var(--card);border-radius:14px;display:flex;flex-direction:column;box-shadow:0 26px 70px rgba(0,0,0,.3)}
.modal-box .mh{padding:14px 18px;border-bottom:1px solid var(--line);display:flex;justify-content:space-between;align-items:center}
.modal-box .mh b{font-size:15px;font-weight:500}
.modal-box .mb{padding:16px 18px;overflow:auto}
.modal-box .mf{padding:12px 18px;border-top:1px solid var(--line);display:flex;justify-content:flex-end;gap:9px}
/* 大弹窗（配置关系设置页）：更宽、遮罩近乎透明 —— 便于拖到旁边时仍能看清列表；
   标题栏是拖动把手（见 app.js bindModalDrag / resetModalPos）。 */
#modal.wide{background:rgba(13,33,55,.06)}
#modal.wide .modal-box{width:min(1120px,96vw);max-width:96vw;max-height:92vh}
/* 录入弹窗按 **A4 版心**（需求方 2026-09-18）：**「项目信息」点「+ 新增 / 编辑」后的录入页**用 A4 宽度
   （210mm ≈ 794px，居中），**列表页不受影响、仍满屏**。默认 .modal-box 是 640px，A4 略宽、字段更好排。
   ⚠️ 只有 project 加了这个 class（见 app.js 的 openForm）；其他模块的录入弹窗需求方未点名 → 维持 640px。 */
#modal.a4 .modal-box{width:min(var(--a4),94vw)}
.modal-box .mh.draggable{cursor:move;user-select:none}
.modal-box .mh.draggable b::after{content:'  ⠿';font-size:11px;color:var(--muted);cursor:move}
body.dragging,body.dragging *{user-select:none!important}
.form{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px 16px}
/* 工单建单页的区块小标题（基础信息 / 工单内容 / 分类与 SLA / SLA 例外） */
.sub-t{font-size:12.5px;font-weight:700;color:var(--text);letter-spacing:.5px;padding-bottom:6px;
  border-bottom:1px solid var(--line);margin:2px 0 4px}
.form .f{display:flex;flex-direction:column;gap:5px}
/* 建单页「项目经理 / 联系方式 / 项目联系人 / 联系方式」= **一整行 4 格 + 中间一条竖线**
   （需求方 2026-09-18：第三行放两对"姓名 + 联系方式"，两块之间**用竖线隔开**以免看混）。
   ⚠️ 选择器必须是 `.form .f.pair-row`（三层）：`.form .f` 是 flex，本规则要盖掉它改用 grid。 */
.form .f.pair-row{display:grid;
  grid-template-columns:minmax(0,1fr) minmax(0,1.05fr) 1px minmax(0,1fr) minmax(0,1.05fr);gap:12px 14px}
.form .pair-row > .pair-sep{background:var(--line2);border-radius:1px;align-self:stretch;margin:1px 0}
/* 项目新增 / 编辑页第三行（需求方 2026-09-18）：**关联账号 + 联系方式 ‖ 项目经理 + 联系方式**
   —— 5 列 = 内容 | 内容 | 竖线 | 内容 | 内容（schema 里四个字段标 `row:'pj-mgr'`，见 app.js 的 fieldsHtml）。
   🔴 竖线要**居中分割**：左右两组各占 2.2fr（1.2 + 1），所以线正好落在中间（原来是 2.2 : 1.95 → 偏右）。
   两块各自都是「账号 → 旁边就是自动带出的联系方式」。 */
.form .f.pair-row.pj-mgr{grid-template-columns:minmax(0,1.2fr) minmax(0,1fr) 1px minmax(0,1.2fr) minmax(0,1fr)}
/* 项目第二行（需求方 2026-09-18）：**项目期限 | 开始日期 | 结束日期** —— 3 格等宽，无竖线。
   🔴 这一行原**漏了列定义** → 落到 `.pair-row` 的 5 列基础模板（`1fr 1.05fr 1px 1fr 1.05fr`，
      那是给「关联账号+联系方式 ‖ 项目经理+联系方式」用的，第 3 列正是 **1px 的竖线**）——
      于是「结束日期」被塞进那 1px 的列里，输入框宽度只剩 22px、看着像一条线（需求方 2026-09-18 报障：
      「编辑项目页面结束时间显示异常」）。本行给出独立 3 列定义即可修好。
      ⚠️ 以后**每新增一个 `row:'xxx'` 分排行，必须同时在这里补列定义**，否则就会踩同一个坑。 */
.form .f.pair-row.pj-term{grid-template-columns:repeat(3,minmax(0,1fr))}
/* 项目第一行（需求方 2026-09-18）：**项目名称（左半）| 项目类型 | 项目编号（右半各半）** —— 3 格，无竖线。 */
.form .f.pair-row.pj-top{grid-template-columns:minmax(0,1fr) minmax(0,.5fr) minmax(0,.5fr)}
/* 项目第四行（需求方 2026-09-18）：**客服专员 | 资产专员 | 配置专员** —— 3 格等宽，**每格各带一个外框**便于看清界面。 */
.form .f.pair-row.pj-staff{grid-template-columns:repeat(3,minmax(0,1fr))}
/* 🔴 分排行里**每格各带一个外框**（需求方 2026-09-18）：
   · 第四行（客服专员 | 资产专员 | 配置专员）定稿时用的就是这个样式；
   · 需求方随即要求**第一行（项目名称 | 项目类型 | 项目编号）也用同一类样式框起来** → 两条共用同一条规则。
   ⚠️ 第三行（关联账号+联系方式 ‖ 项目经理+联系方式）**不框**（需求方没要，别顺手加）。
   `*{box-sizing:border-box}` 已全局生效，加边框/内边距不会改变各格宽度（比例仍是 2:1:1 / 1:1:1）。 */
.form .f.pair-row.pj-top > .f,
.form .f.pair-row.pj-staff > .f{border:1px solid var(--line2);border-radius:10px;padding:9px 11px;background:#fff}
@media(max-width:1180px){
  .form .f.pair-row{grid-template-columns:1fr 1fr}
  .form .f.pair-row.pj-mgr{grid-template-columns:1fr 1fr}
  .form .f.pair-row.pj-top{grid-template-columns:1fr 1fr}
  .form .f.pair-row.pj-term{grid-template-columns:1fr 1fr}
  .form .f.pair-row.pj-staff{grid-template-columns:1fr 1fr}
  .form .pair-row > .pair-sep{display:none}
}
/* 问题类（RCA）/ 变更类**扩展选填区**（需求方 2026-09-18）：跟在问题描述下面，且要**紧凑** ——
   原来每格占一整行、留白大、行数多；现在 = **两列网格 + 收紧内边距/间距**，左侧一道强调色条做视觉分组。
   🔴 显示/隐藏由 `tkOnType()` 写 inline `display`：显示时置空串 → 落回本规则的 `display:grid`。 */
#tk-rca-block,#tk-chg-block{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:6px 14px;
  margin:2px 0 4px;padding:8px 10px 10px;border:1px solid var(--line);border-left:3px solid var(--accent);
  border-radius:8px;background:var(--soft2)}
#tk-rca-block .sub-t,#tk-chg-block .sub-t{padding-bottom:2px;margin:0;font-size:12px;border-bottom:0}
#tk-rca-block .f,#tk-chg-block .f{gap:3px}
#tk-rca-block input,#tk-rca-block select,#tk-rca-block textarea,
#tk-chg-block input,#tk-chg-block select,#tk-chg-block textarea{padding:6px 9px}
/* 建单页首行（标题行）：label [+ 并排在右边的服务方式 2 连按钮]（需求方 2026-09-18）。
   🔴 `min-height` 必须**两格一致**（现 26px = 2 连按钮的高度）—— 否则「工单标题」的输入框会与
      「工单类型」的四连按钮错位（需求方一眼看出"歪"，实测差 6px）。 */
.form .lb-row{display:flex;align-items:center;gap:12px;flex-wrap:wrap;min-height:26px}
/* 来源：**工单录入板块右上角、与「基础信息」同一行**的灰色小字，仅显示（需求方 2026-09-18）——
   格式「工单来源：XXXX　年月日时分秒」；用绝对定位贴在该行右端，**不影响 .sub-t 的整行分隔线**。
   🔴 位置口径被需求方纠过一次：不是页眉（工单上方），而是录入板块的首行右侧。 */
.form .sub-row{position:relative}
/* 🔴 2026-09-22 二次修订（需求方：「创建工单和新建工单左上角姓名和时间换下位置，注意不要重叠遮挡」）：
   ① **姓名与时间换位** → 现在的顺序是「工单来源：X　姓名　时间」；
   ② **硬保证不遮挡左侧「基础信息」标签**：块宽上限 `calc(100% - 96px)`（给标签留出位置），
      超长就省略号（完整内容在 `title` 里）—— 这样无论窗口多窄、姓名多长，都**不可能盖住标签**。
      用绝对定位是为了不破坏 `.sub-t` 那条整行分隔线（改 flex 行会把线截断）。 */
.tk-src{position:absolute;right:0;top:0;font-size:12px;color:var(--muted);user-select:none;white-space:nowrap;
  max-width:calc(100% - 96px);overflow:hidden;text-overflow:ellipsis;
  /* 🔴 2026-09-22 需求方：「三者（工单来源： / 姓名 / 时间）要在同一水平带上对齐」——
     用 inline-flex + `align-items:baseline` 让三段按**基线**对齐（原来各是 inline 元素，
     字号/字体不同时会有 1~2px 的错位，"看着不齐"就是它）。 */
  display:inline-flex;align-items:baseline}
.tk-src .tk-src-t{font-style:normal;color:#9aa8b8;margin-left:12px}
/* 🔴 「报告人」（需求方 2026-09-22）：「不要写『报告人：』，直接写姓名」，且**报出与时间重叠**了 ——
   原来两个 span 各自 `position:absolute;right:0` → 后一个（报告人）正好压在前一个的**时间**上。
   现在两者合并进**同一个**右对齐块（来源 → 姓名 → 时间），整块右端对齐。
   同日再补两条（需求方：「工单来源：→姓名的距离有点远，要挨着；姓名颜色与工单来源相同」）：
   · `margin-left:4px` —— 姓名**紧挨**冒号（原来是 18px，看着像隔了一格）；
   · `color:inherit` —— 姓名与「工单来源：」**完全同色**（原来偏深蓝，显得是另一个层级）。 */
.tk-src .tk-src-r{margin-left:4px;font-style:normal;color:inherit;font-weight:400}
.form .lb-row label{margin:0}
.form .tk-modes{display:inline-flex;align-items:center;gap:8px}
.form .tk-modes .mod-lb{margin:0}
/* 服务方式 = 2 连按钮：复用 .seg，但要**自适应宽度**（默认 .seg 是 width:100% 的整行控件） */
.seg.seg-sm{width:auto}
.seg.seg-sm .seg-b{flex:0 0 auto;padding:4px 12px;font-size:12.5px}
/* 工单类型：**四个连体按钮**（需求方 2026-09-18）—— 无间隙、相邻边框合并、两端圆角；
   默认不选（没有任何 .on），点中一个即选中（单选）。外观尺寸与同行的 input / select 对齐。 */
.seg{display:flex;width:100%;border:1px solid var(--line2);border-radius:7px;overflow:hidden;background:#fff}
.seg .seg-b{flex:1 1 0;min-width:0;padding:8px 6px;border:0;border-left:1px solid var(--line2);
  background:#fff;color:var(--btn-tx);font-size:13px;cursor:pointer;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.seg .seg-b:first-child{border-left:0}
.seg .seg-b:hover{background:var(--hover)}
.seg .seg-b.on{background:var(--accent);color:#fff;font-weight:600}
/* 服务方式按钮：该项目**不具备**的那一种 → 划**一条对角线**示意不可用（需求方 2026-09-19：
   「只需要对角，不要打满」）—— 用 to top right 正好连住两个对角，不再铺满斜线网格。
   点它无效（tkPickMode 里拦）并提示原因，不给"选了又没用"的错觉。 */
.seg .seg-b.off{position:relative;color:#c3ced9;cursor:not-allowed}
.seg .seg-b.off:hover{background:#fff}
.seg .seg-b.off::after{content:'';position:absolute;inset:-1px;border-radius:inherit;pointer-events:none;
  background-image:linear-gradient(to top right,
    transparent calc(50% - .6px), rgba(100,116,139,.55) calc(50% - .6px),
    rgba(100,116,139,.55) calc(50% + .6px), transparent calc(50% + .6px))}
/* 建单页整页按 A4 版心（见 style 顶部 --a4）：由 app.js 的 `a4-wrap` 包裹 */
.form .f.full{grid-column:1/-1}
.form label{font-size:12.5px;color:var(--label)}
.form label i{color:var(--red);font-style:normal;margin-left:3px}
.form input,.form select,.form textarea{padding:8px 10px;border:1px solid var(--line2);border-radius:7px;outline:none;width:100%}
.form input:focus,.form select:focus,.form textarea:focus{border-color:var(--accent);box-shadow:0 0 0 3px rgba(14,116,144,.1)}
.form textarea{min-height:66px;resize:vertical}
.form .hint{font-size:11.5px;color:var(--muted)}
.checks{display:flex;flex-wrap:wrap;gap:8px 16px;border:1px solid var(--line);border-radius:8px;padding:10px;max-height:210px;overflow:auto}
/* 可检索填入框（所有选择型填入框：输入关键字检索 + 点选） */
.ssel{position:relative;display:inline-flex;align-items:center;min-width:150px}
/* 关键：input 的浏览器默认固有宽度约 188px，会**溢出** .ssel 的盒子并盖住右侧的按钮
   （曾导致「快速检索到期」的 GO 按钮点不到）。锁定宽度并允许收缩。 */
.ssel .ssel-in{width:100%;min-width:0;padding-right:30px}
.ssel-btn{position:absolute;right:3px;top:50%;transform:translateY(-50%);border:0;background:transparent;color:#7b8ea3;
  cursor:pointer;font-size:11px;line-height:1;padding:6px 8px;border-radius:6px}
.ssel-btn:hover{background:var(--hover);color:var(--accent)}
.ssel-pop{position:fixed;z-index:210;background:var(--card);border:1px solid var(--line2);border-radius:9px;
  box-shadow:0 14px 34px rgba(16,38,60,.18);padding:4px;overflow:auto;min-width:190px}
.ssel-opt{padding:7px 9px;border-radius:6px;font-size:13px;cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* 带副标题的候选（配置项：类型 · 品牌 型号 · IP）—— 双行小字，便于区分同名设备 */
.ssel-opt.has-sub{display:flex;flex-direction:column;gap:1px;white-space:normal;line-height:1.4}
.ssel-opt .so-sub{font-size:11px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ssel-opt.has-sub.hi .so-sub,.ssel-opt.has-sub:hover .so-sub{color:#3f6b8a}
.ssel-opt:hover,.ssel-opt.hi{background:var(--accent-soft)}
.ssel-opt.dis{color:#a3b2c2;cursor:not-allowed;background:transparent}
.ssel-none{padding:8px 10px;font-size:12px;color:var(--muted)}
/* 多选（配置关系「对端配置项」可多选）：chips 在输入框上方；候选项点一下=选中/取消（面板不关） */
.ssel.ssel-multi{display:flex;flex-direction:column;align-items:stretch;gap:6px;width:100%;min-width:0}
.ssel-multi .ssel-row{position:relative;display:flex;align-items:center;width:100%}
.ssel-chips{display:flex;flex-wrap:wrap;gap:5px 6px;max-height:78px;overflow:auto}
.ssel-chip{display:inline-flex;align-items:center;gap:4px;max-width:100%;background:var(--accent-soft);border:1px solid var(--line2);border-radius:999px;padding:2px 4px 2px 9px;font-size:12px;color:#2b4a63}
.ssel-chip-t{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:240px}
.ssel-chip-x{cursor:pointer;font-weight:700;color:#7b8ea3;padding:0 4px;font-style:normal;border-radius:50%;line-height:1}
.ssel-chip-x:hover{color:#fff;background:#c0392b}
.ssel-chip-ph{font-size:11.5px;color:var(--muted)}
.ssel-opt.on{background:var(--accent-soft);box-shadow:inset 3px 0 0 var(--accent)}
/* 多选（可检索）：项目关联部门 / 账号 */
.multisel{display:flex;flex-direction:column;gap:6px}
.multisel .ms-in{padding:7px 10px;border:1px solid var(--line2);border-radius:7px;outline:none;width:100%;font-size:12.5px}
.multisel .ms-in:focus{border-color:var(--accent);box-shadow:0 0 0 3px rgba(14,116,144,.1)}
.multisel .checks{max-height:190px}
.multisel .hint{min-height:15px;font-size:11.5px;color:var(--muted)}
.ssel-none[hidden]{display:none}
.checks label{display:flex;align-items:center;gap:6px;font-size:12.5px;color:#33465c}
.checks input{width:auto}
/* 单字段勾选框（如资产「CI 标记」）：与 .checks 内的勾选项保持同一视觉语言 */
.chk{display:flex;align-items:center;gap:6px;font-size:12.5px;color:#33465c;border:1px solid var(--line);border-radius:8px;padding:8px 10px;cursor:pointer}
.chk input{width:auto;cursor:pointer}

#toast{position:fixed;top:16px;left:50%;transform:translateX(-50%);z-index:60;display:flex;flex-direction:column;gap:8px;align-items:center}
.toast{padding:9px 16px;border-radius:8px;background:var(--toast-bg);color:#fff;font-size:13px;box-shadow:0 10px 30px rgba(0,0,0,.3);opacity:0;transform:translateY(-8px);transition:.2s}
.toast.on{opacity:1;transform:none}
.toast.err{background:#b91c1c}
.toast.ok{background:#15803d}

/* 画布高度：默认**按视口自适应**（需求方 2026-09-17：窗口最大化后要跟着变大）。
   以前不给高度 → 高度由 SVG 的 viewBox 宽高比撑出来（900×520），窗口一宽画布高度就随宽度暴涨、
   直接顶出视口；而且没有任何拖拽把手（"下边框被锁死"）。
   现在：默认 clamp 自适应；用户拖底部把手时由 JS 写内联 height（本机记忆），双击把手恢复自适应。 */
.topo-wrap{position:relative;background:#fbfdff;border:1px solid var(--line);border-radius:var(--radius);overflow:hidden;height:clamp(360px, calc(100vh - 256px), 2400px)}
.topo-wrap svg{display:block;width:100%;height:100%;cursor:grab}
/* 底部拖拽把手：拖动改画布高度；双击恢复"随窗口自适应" */
.topo-grip{position:absolute;left:0;right:0;bottom:0;height:11px;cursor:ns-resize;z-index:3;display:flex;align-items:center;justify-content:center;background:linear-gradient(180deg,rgba(255,255,255,0),var(--overlay))}
.topo-grip::before{content:'';width:54px;height:3px;border-radius:2px;background:#c7d5e4}
.topo-grip:hover::before,.topo-grip.dragging::before{background:var(--accent)}
.topo-tools{position:absolute;right:12px;top:12px;display:flex;flex-direction:column;gap:6px}
.topo-tools button{width:30px;height:30px;border:1px solid var(--line2);background:var(--card);border-radius:7px;cursor:pointer;font-size:14px;color:var(--label)}
.topo-tools button:hover{border-color:var(--accent);color:var(--accent)}
.topo-legend{position:absolute;left:12px;bottom:23px;background:var(--overlay);border:1px solid var(--line);border-radius:8px;padding:8px 10px;font-size:11.5px;color:var(--label);display:flex;gap:12px;flex-wrap:wrap;max-width:calc(100% - 24px)}
.topo-legend i{display:inline-block;width:9px;height:9px;border-radius:2px;margin-right:4px}
.syncbar{position:absolute;left:12px;top:12px;background:var(--overlay);border:1px solid var(--line);border-radius:8px;padding:5px 10px;font-size:11.5px;color:var(--label);display:flex;align-items:center;gap:7px}
.node-g{cursor:pointer}
.node-g:hover rect.body{stroke:#2563eb}
.rel-label{font-size:10.5px;fill:var(--head-tx)}
.steps{display:flex;flex-direction:column;gap:8px}
.steps .st{display:flex;gap:10px;font-size:12.8px}
.steps .st .n{width:20px;height:20px;border-radius:50%;background:var(--accent-l);color:#0b5f75;display:flex;align-items:center;justify-content:center;font-size:11.5px;flex:none}
.impact-depth{margin-bottom:6px}
/* ===== 关联拓扑：连线双向流动 / 异常状态呼吸 / 节点浮窗（2026-09-15） ===== */
@keyframes topoflow{from{stroke-dashoffset:30}to{stroke-dashoffset:0}}
@keyframes topoflowr{from{stroke-dashoffset:0}to{stroke-dashoffset:30}}
@keyframes topobreath{0%,100%{opacity:1}50%{opacity:.58}}
#tsvg .fl{stroke-dasharray:6 9;pointer-events:none}
#tsvg .fl-f{animation:topoflow 1.5s linear infinite}
#tsvg .fl-b{animation:topoflowr 1.5s linear infinite}
/* 与非在用设备相连的连线：数据传输动效**停止**（虚线保留但不再流动） */
#tsvg .fl.halt{animation-play-state:paused}
/* 底色呼吸：质保已过保 / 非在用 / 非在用设备的下游（只作用于节点框，不影响文字） */
#tsvg rect.breath{animation:topobreath 2.4s ease-in-out infinite}
/* 检索突显（需求方 2026-09-15）：命中的节点底色转**天蓝渐变**并呼吸 + 天蓝光晕，一眼从全图里挑出来 */
@keyframes topohl{0%,100%{opacity:1;filter:drop-shadow(0 0 0 rgba(56,189,248,0))}50%{opacity:.93;filter:drop-shadow(0 0 10px rgba(56,189,248,.92))}}
#tsvg rect.hlbr{animation:topohl 2.2s ease-in-out infinite}
/* 分组标注：互不关联的设备被分成多组左右摆放时，组上方标注 + 组间虚线分隔 */
#tsvg .grp-label{font-size:11.5px;fill:#7b8ea3;font-weight:600;letter-spacing:.3px}
#tsvg .grp-sep{stroke:#dbe4ee;stroke-width:1;stroke-dasharray:4 7}
/* 组左侧的「上游 ↓ 下游」方向标（金字塔式的依赖走向） */
#tsvg .ud-line{stroke:#c3d2e2;stroke-width:1.2;stroke-dasharray:3 5}
#tsvg .ud-t{font-size:11px;fill:#9aabbd}
/* 「主备 / 包含」外框：把成套的节点框在一起（最底层，不拦截点击） */
#tsvg .fr{fill:rgba(14,116,144,.05);stroke:#7fb3c9;stroke-width:1.4;stroke-dasharray:7 5;pointer-events:none}
#tsvg .fr-tag-bg{fill:var(--card);stroke:#7fb3c9;stroke-width:1;pointer-events:none}
#tsvg .fr-tag{font-size:11px;fill:#2b6b83;font-weight:600;pointer-events:none}
.topo-tools button.off{color:#b6c4d4;border-style:dashed}
.tp-card{position:absolute;z-index:30;width:292px;max-height:calc(100% - 20px);overflow:auto;background:var(--card);border:1px solid var(--line2);border-radius:10px;box-shadow:0 10px 26px rgba(15,42,70,.18)}
.tp-h{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:8px 10px;border-bottom:1px solid var(--line);position:sticky;top:0;background:var(--card);border-radius:10px 10px 0 0}
.tp-t{font-size:13px;font-weight:600;color:var(--head-tx);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tp-x{border:0;background:transparent;font-size:16px;line-height:1;cursor:pointer;color:#7b8ea3;padding:0 4px}
.tp-x:hover{color:#c0392b}
.tp-b{padding:8px 10px 10px}
.tp-kv{display:flex;gap:8px;font-size:12.3px;padding:3px 0;align-items:baseline}
.tp-kv>span{color:var(--muted);flex:none;width:66px}
.tp-kv>b{color:#1f2b38;font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tp-acc{border-top:1px dashed var(--line);margin-top:6px;padding-top:6px}
.tp-acc-h{display:flex;align-items:center;justify-content:space-between;font-size:12.3px;color:var(--label);cursor:pointer;user-select:none}
.tp-acc-h:hover{color:var(--accent)}
.tp-acc-h i{transition:transform .18s;font-style:normal}
.tp-acc.on .tp-acc-h i{transform:rotate(180deg)}
/* 上下游明细：弹出的小列表（限宽 100% + 限高 + 内部滚动），不把浮窗撑长 */
.tp-pop{display:none;margin-top:6px;max-height:186px;overflow:auto;border:1px solid var(--line2);border-radius:8px;background:#fbfdff;padding:6px 8px;width:100%;box-sizing:border-box}
.tp-acc.on .tp-pop{display:block}
.tp-peer{display:flex;flex-direction:column;gap:1px;font-size:12.2px;padding:4px 0;border-bottom:1px dotted var(--line)}
.tp-peer:last-child{border-bottom:0}
.tp-peer b{font-weight:500;color:#1f2b38;display:block;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tp-peer .mini{color:var(--muted);display:block;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tp-peer .tag{align-self:flex-start;margin-top:2px}
.tp-btn{display:flex;flex-wrap:wrap;gap:6px;margin-top:8px;border-top:1px solid var(--line);padding-top:8px}
.mini{font-size:var(--fs-hint);font-weight:var(--fw-body);color:var(--muted)}
code{background:#f1f5f9;padding:1px 5px;border-radius:4px;font-size:12px}

/* ---------- 备份恢复：按内容勾选 / 包含内容 / 自动备份（2026-09-16） ---------- */
.bk-mods{display:grid;grid-template-columns:repeat(auto-fill,minmax(250px,1fr));gap:5px 16px;padding:9px 11px;border:1px solid var(--line2);border-radius:8px;background:#fbfdff}
.bk-mod{display:flex;align-items:flex-start;gap:7px;font-size:13px;font-weight:var(--fw-body);color:#1f2b38;cursor:pointer;padding:3px 0}
.bk-mod input{margin-top:2px;flex:none}
.bk-mod>span{display:flex;flex-direction:column;gap:1px;min-width:0}
.bk-mod b{font-weight:500}
.bk-mod i{font-style:normal;color:var(--muted);font-size:var(--fs-hint);line-height:1.35}
.bk-switch{display:flex;align-items:center;gap:8px;font-size:13.5px;font-weight:500;margin-bottom:10px;cursor:pointer}
.bk-switch input{flex:none}
.bk-switch .mini{font-weight:var(--fw-body)}
.bk-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(148px,1fr));gap:8px 14px;margin-bottom:4px}
.bk-grid label{display:block;margin-bottom:3px}
.bk-grid input,.bk-grid select{width:100%;box-sizing:border-box}
.bk-chip{display:inline-block;background:#eef4ff;border:1px solid #d6e2ff;color:#1e40af;border-radius:10px;padding:0 7px;font-size:11.6px;line-height:18px;margin:1px 3px 1px 0;white-space:nowrap}
.bk-chip.auto{background:#fff7ed;border-color:#fed7aa;color:#b45309}
.bk-chip.legacy{background:#f1f5f9;border-color:#e2e8f0;color:#475569}
.bk-keep{display:inline-block;background:#fef2f2;border:1px solid #fecaca;color:#b91c1c;border-radius:9px;padding:0 6px;font-size:11.4px;line-height:17px}
.bk-kind{display:inline-block;background:#eff6ff;border:1px solid #bfdbfe;color:#1d4ed8;border-radius:9px;padding:0 6px;font-size:11.4px;line-height:17px}
/* 「备份目录与容量」：三列**横向等比例**（需求方 2026-09-21：「三个横向等比例放」） */
.bk-dirs3{display:grid;grid-template-columns:repeat(3,1fr);gap:12px 18px;align-items:start}
.bk-dircell{min-width:0;display:flex;flex-direction:column;gap:5px}
.bk-dirlb{font-size:13px;color:#334155;font-weight:500}
.bk-dirctl{display:flex;align-items:center;gap:7px;min-width:0;min-height:26px}   /* 三格控制行同高：否则下面那行注释会错开 3px */
.bk-dirctl>input{flex:1 1 auto;min-width:0}
.bk-unit{flex:0 0 auto;font-size:12.5px;color:#475569}
.bk-dirnow{font-size:12px;color:var(--muted);line-height:1.6;word-break:break-all}
.bk-dirnow b{color:#b45309}
.bk-dirnow code{background:#f1f5f9;border-radius:5px;padding:1px 6px;color:#334155;word-break:break-all}
/* 「保存目录与容量」这一行：与「自动备份」卡的按钮**同一角位、同一对齐线**
   （需求方 2026-09-21：「还是不对，放在与自动备份同角位，他的注释文字也没对准」）
   —— 按钮在左、注释文字紧跟其后、两者垂直居中对齐；上面不加 inset，保证左边界与三列一致。 */
.bk-dirfoot{display:flex;align-items:center;gap:12px;margin-top:14px;padding-top:12px;border-top:1px dashed var(--line)}
.bk-dirfoot .btn{flex:0 0 auto}
.bk-dirfoot .mini{flex:0 1 auto;min-width:0;line-height:1.5}
@media (max-width:1180px){.bk-dirs3{grid-template-columns:1fr 1fr}}
@media (max-width:880px){.bk-dirs3{grid-template-columns:1fr}}
/* 「选择服务器文件夹」弹窗的目录列表（需求方 2026-09-21） */
.bk-brlist{max-height:290px;overflow:auto;border:1px solid var(--line2);border-radius:8px;background:#fbfdff;padding:4px}
.bk-brit{padding:5px 8px;border-radius:6px;cursor:pointer;font-size:13px;color:#1f2b38;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.bk-brit:hover{background:#eef4fb}

/* ===== 模型设置（2026-09-18 改版）：卡片式主流模型 + 知识库兜底开关 + A4 弹窗 =====
   需求方口径：一行 = 一个**具体版本**；只有**支持识图**的模型卡片上才有「知识库兜底」开关；
   卡片上给「近 14 天 token 趋势 + 当月 tokens」；点卡片 → A4 弹窗（只填 API Key）。 */
.badge{display:inline-flex;align-items:center;gap:4px;font-size:11.5px;line-height:1;
  padding:3px 7px;border-radius:999px;border:1px solid var(--line2);background:var(--soft);color:#41546a;white-space:nowrap}
.badge.info{color:#1d4ed8;border-color:#c7d7f7;background:#f2f6ff}
.badge.grey{color:#697b8f}
.badge.warn{color:#b45309;border-color:#f2d9a8;background:#fff8ec}
.tag.ok{background:#dcfce7;border-color:#86efac;color:#15803d}
.sec-h{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin:0 0 8px}
.sec-h b{font-size:13.5px;letter-spacing:.3px}
.sec-bar{width:3px;height:14px;border-radius:2px;background:linear-gradient(180deg,#1d4ed8,#6d28d9);flex:none}

/* ① 固定流程 */
.aim-flow{display:grid;grid-template-columns:1fr auto 1fr auto 1.25fr;gap:8px;align-items:stretch}
.aim-flow .aim-step{display:flex;gap:8px;align-items:flex-start;border:1px solid var(--line);border-radius:10px;
  padding:10px 11px;background:linear-gradient(180deg,#fbfdff,#f6faff)}
.aim-flow .aim-step b{font-size:12.5px;display:block;line-height:1.35}
.aim-flow .aim-step .n{width:17px;height:17px;border-radius:50%;flex:none;background:#1d4ed8;color:#fff;font-size:11px;
  display:flex;align-items:center;justify-content:center;margin-top:1px}
.aim-flow .arw{display:flex;align-items:center;color:#a9b8c8;font-size:14px}
.aim-flow .aim-step.hot{border-color:#c7d7f7;background:linear-gradient(180deg,#f5f9ff,#eef4ff)}
.aim-fbline{display:flex;align-items:center;gap:9px;margin-top:12px;padding-top:11px;
  border-top:1px dashed var(--line2);flex-wrap:wrap}
.aim-note{display:flex;gap:8px;align-items:flex-start;font-size:12px;color:#41546a;
  background:#f7fbff;border:1px solid #d8e6f7;border-radius:8px;padding:9px 11px;margin-top:10px;line-height:1.6}

/* 筛选条 */
.aim-filters{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin:0 0 10px}
.aim-chip{font-size:12px;border:1px solid var(--line2);background:#fff;color:#41546a;border-radius:999px;padding:4px 11px;cursor:pointer}
.aim-chip:hover{background:var(--hover)}
.aim-chip.on{border-color:transparent;background:linear-gradient(135deg,#1d4ed8,#6d28d9);color:#fff;font-weight:600}
.aim-filter-r{margin-left:auto;font-size:12px;color:var(--muted);white-space:nowrap}

/* ② 卡片 */
/* 一行 5 个卡片（需求方 2026-09-18 晚：由 4 个改为 5 个） */
.aim-grid{display:grid;grid-template-columns:repeat(5,1fr);gap:9px}
.aim-card{position:relative;display:flex;flex-direction:column;background:#fff;border:1px solid var(--line);
  border-radius:11px;box-shadow:var(--shadow);padding:10px;cursor:pointer;transition:.16s}
.aim-card:hover{transform:translateY(-1px);border-color:#c7d7f7;box-shadow:0 6px 22px rgba(16,38,60,.12)}
.aim-card.is-fb{border-color:#b9c9f2;box-shadow:0 0 0 3px rgba(37,99,235,.08),var(--shadow)}
.aim-card .aim-nm{font-size:12.5px}
.aim-card .aim-api{font-size:10.5px}
.aim-fb-flag{position:absolute;top:0;right:0;font-size:10.5px;color:#fff;padding:2px 8px 3px;
  border-bottom-left-radius:8px;background:linear-gradient(135deg,#1d4ed8,#6d28d9)}
.aim-top{display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.aim-logo{width:21px;height:21px;border-radius:6px;flex:none;display:flex;align-items:center;justify-content:center;
  color:#fff;font-size:10.5px;font-weight:700;background:linear-gradient(135deg,#1d4ed8,#6d28d9)}
.aim-nm{font-size:13px;font-weight:600;letter-spacing:.2px}
.aim-ver{color:#fff;border-color:transparent;background:linear-gradient(135deg,#1d4ed8,#6d28d9);font-weight:600}
.aim-stat{margin-left:auto;display:flex;align-items:center;gap:5px;font-size:11.5px;color:var(--muted);white-space:nowrap}
.aim-dot{width:7px;height:7px;border-radius:50%;background:#cbd5e1}
.aim-dot.ok{background:#22c55e}
.aim-api{font-size:11px;color:#8fa1b3;margin-top:3px;font-family:Consolas,Monaco,monospace;word-break:break-all}
.aim-caps{display:flex;flex-wrap:wrap;gap:3px;margin-top:7px}
.aim-card .badge{font-size:10.5px;padding:2px 5px}
.aim-fb{display:flex;align-items:center;gap:6px;margin-top:9px;padding:7px 8px;
  border:1px solid var(--line);border-radius:8px;background:var(--soft2)}
.aim-fb-lb{font-size:11.5px;color:#41546a;font-weight:600}
.aim-fb-hint{font-size:11px;color:#8fa1b3;margin-left:auto}
.aim-sw{position:relative;width:34px;height:18px;border-radius:999px;background:#cbd5e1;transition:.15s;flex:none;cursor:pointer}
.aim-sw i{position:absolute;top:2px;left:2px;width:14px;height:14px;border-radius:50%;background:#fff;transition:.15s}
.aim-sw.on{background:linear-gradient(135deg,#1d4ed8,#6d28d9)}
.aim-sw.on i{left:18px}
.aim-sw.dis{background:#e8edf3;cursor:not-allowed}
.aim-sw.dis i{background:#f7f9fc}
.aim-txt{font-size:11.5px;color:#5b6e82;line-height:1.5;margin-top:8px;min-height:34px}
.aim-spark{height:34px;margin:6px 0 2px}
.aim-sum{display:flex;align-items:flex-end;gap:6px}
.aim-sum b{font-size:16px;font-weight:600;letter-spacing:.2px}
.aim-sum span{font-size:11px;color:var(--muted);margin-bottom:2px}
.aim-fine{font-size:10.5px;color:#9aabbb;margin-top:2px;line-height:1.45}
.aim-foot{display:flex;gap:5px;align-items:center;flex-wrap:wrap;margin-top:auto;padding-top:9px;border-top:1px solid var(--line)}
.aim-go{margin-left:auto;font-size:12px;color:#1d4ed8}
.aim-empty{border:1px dashed var(--line2);border-radius:10px;padding:20px;text-align:center;color:var(--muted);background:#fcfdff}

/* ③ A4 弹窗（794px = 全站 --a4；纸面内部滚动） */
.aim-mask{position:fixed;inset:0;z-index:70;display:none;align-items:center;justify-content:center;
  padding:18px;background:rgba(9,20,34,.55)}
.aim-mask.on{display:flex}
.aim-sheet{width:var(--a4);max-width:100%;max-height:calc(100vh - 36px);overflow:auto;background:#fff;
  border-radius:8px;box-shadow:0 30px 70px rgba(3,14,28,.45)}
.aim-shd{position:sticky;top:0;z-index:2;display:flex;align-items:center;gap:10px;padding:14px 18px;color:#fff;
  background:linear-gradient(90deg,#0d2137,#1b4066)}
.aim-shd .ic{width:26px;height:26px;border-radius:7px;background:rgba(255,255,255,.16);flex:none;
  display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:700}
.aim-shd b{font-size:14.5px}
.aim-shd .sub{font-size:12px;color:#a9c8e4}
.aim-shd .x{margin-left:auto;width:28px;height:28px;border-radius:7px;cursor:pointer;
  border:1px solid rgba(255,255,255,.28);background:transparent;color:#fff}
.aim-shd .x:hover{background:rgba(255,255,255,.14)}
/* 工单「响应」选处理人（需求方 2026-09-19）：三组候选（工程师 / 项目经理 / 项目集经理）+ 检索 + 单选 */
.rsp-bd{padding:12px 18px 4px}
/* ===== 议题模版弹窗（新建议题 / 修改议题）：标签 + 输入 的**行**（需求方 2026-09-22）=====
   🔴 别再用 `.ln` —— 全站**没有** `.ln` 的样式（只有 `.rep-mail .ln` 一条），
      所以写在 input 上的 `flex:1` 完全不生效 → 议题标题框退化成浏览器默认宽度（约 170px），"太短"。
   `.mtln` 一次把三件事定好：① flex 行（标签定宽 + 控件吃满剩余）；② 输入框外观（高 36 / 圆角 10 / 内边距）；
   ③ 悬停与聚焦反馈（聚焦光晕）。只管本弹窗，不外溢。 */
.mtln{display:flex;align-items:flex-start;gap:9px}
.mtln>.mg-lb{flex:0 0 74px;width:74px;padding-top:9px}
.mtln input[type=text],.mtln textarea{flex:1 1 auto;min-width:0;box-sizing:border-box;
  border-radius:10px;border:1px solid var(--line2);background:#fff;padding:8px 12px;
  font-size:13.5px;font-family:inherit;color:var(--text);outline:none;
  transition:border-color .15s ease,box-shadow .15s ease}
.mtln input[type=text]{height:36px;padding:0 12px}
.mtln textarea{resize:vertical;line-height:1.7}
.mtln input[type=text]::placeholder,.mtln textarea::placeholder{color:#b7c3d0}
.mtln input[type=text]:hover,.mtln textarea:hover{border-color:#c7d6e6}
.mtln input[type=text]:focus,.mtln textarea:focus{border-color:var(--accent);box-shadow:0 0 0 3px rgba(14,116,144,.12)}
/* 「参考句式」按钮组：点一下填入 / 再点一下撤下来，选中的高亮 */
.mt-tips{display:flex;gap:6px;flex-wrap:wrap;margin-top:7px}
.mt-tip.on{background:#e8f2ff;border-color:#9dc2ee;color:#1d4ed8;font-weight:600}
/* ===== 会议议题**清单**（需求方 2026-09-22：「议题可以累加……议题后面带有开始按钮」）=====
   一行 = 序号 + 标题（可点开浮窗）+ 状态 + 「▶ 开始」/「⏹ 结束」。进行中那行整行高亮。 */
.mtr-tp-list{display:flex;flex-direction:column;gap:6px}
.mtr-tp{display:flex;align-items:center;gap:6px;border:1px solid var(--line2);border-radius:9px;
  background:#fff;padding:6px 8px;transition:border-color .15s ease,background .15s ease}
.mtr-tp.on{border-color:#9dc2ee;background:#f2f8ff}
.mtr-tp.off{opacity:.72}
.mtr-tp-t{display:flex;align-items:center;gap:6px;flex:1 1 auto;min-width:0;text-decoration:none;
  color:var(--text);font-size:13px;font-weight:600;line-height:1.45}
.mtr-tp-t:hover{color:#1d4ed8}
.mtr-tp-t:hover .mtr-tp-x{text-decoration:underline}
.mtr-tp-n{flex:0 0 auto;font-style:normal;width:17px;height:17px;border-radius:5px;background:#eef3f9;
  color:#5b6e82;font-size:11px;font-weight:700;display:inline-flex;align-items:center;justify-content:center}
.mtr-tp.on .mtr-tp-n{background:#d9e8ff;color:#1d4ed8}
.mtr-tp-x{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.mtr-tp-s{flex:0 0 auto;font-size:11px;color:var(--muted);padding:0 2px}
.mtr-tp.on .mtr-tp-s{color:#1d4ed8;font-weight:600}
.rsp-kw{width:100%;box-sizing:border-box;padding:8px 11px;border:1px solid var(--line2);border-radius:8px;
  outline:none;font-size:13px;font-family:inherit;background:#fff}
.rsp-kw:focus{border-color:#93b4e8;box-shadow:0 0 0 3px rgba(37,99,235,.10)}
.rsp-list{margin-top:10px;max-height:52vh;overflow:auto}
.rsp-g{margin-bottom:10px}
.rsp-gl{font-size:12px;font-weight:700;color:var(--muted);letter-spacing:.5px;padding:2px 2px 6px}
.rsp-gl i{font-style:normal;font-weight:400;color:#9fb0c2;margin-left:5px}
.rsp-i{display:flex;align-items:center;gap:8px;width:100%;text-align:left;cursor:pointer;
  padding:7px 10px;border:1px solid var(--line);border-radius:8px;background:#fff;margin-bottom:5px;font-family:inherit}
.rsp-i:hover{border-color:#93b4e8;background:#f7fbff}
.rsp-i.on{border-color:#2563eb;background:#eef4fd;box-shadow:inset 0 0 0 1px #2563eb}
.rsp-i b{font-size:13px;color:var(--text);flex:none}
.rsp-i .mini{flex:1 1 auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rsp-m{flex:none;font-style:normal;font-size:10.5px;font-weight:700;color:#c2410c;background:#fff7ed;
  border:1px solid #fed7aa;border-radius:999px;padding:0 6px;line-height:16px}
.rsp-hint{font-size:12px;color:#c2410c;background:#fff7ed;border:1px solid #fed7aa;border-radius:8px;
  padding:7px 10px;margin-bottom:9px;line-height:1.55}
.rsp-ft{position:sticky;bottom:0;display:flex;align-items:center;gap:10px;padding:11px 18px;
  border-top:1px solid var(--line);background:#fff}
.rsp-ft .mini{margin-right:auto}
/* 「派单设置」弹窗（需求方 2026-09-19）：**1 号检索**（组织 / 角色 / 账号）→ 结果可多选 */
.dsp-bd{padding:12px 18px 4px}
.dsp-sel{min-height:22px;padding:8px 0 10px;border-bottom:1px solid var(--line);margin-bottom:11px}
.dsp-t{font-size:12px;font-weight:700;color:var(--muted);letter-spacing:.5px;display:block;margin-bottom:6px}
.dsp-tags{display:flex;flex-wrap:wrap;gap:6px}
.dsp-tag{display:inline-flex;align-items:center;gap:5px;padding:3px 9px;border-radius:999px;cursor:pointer;
  background:#eef4fd;border:1px solid #b9d0f0;color:#1d4ed8;font-size:12px}
.dsp-tag:hover{border-color:#dc2626;background:#fef2f2;color:#b91c1c}
.dsp-tag i{font-style:normal;font-size:10px;opacity:.7}
.dsp-hits{margin-top:11px;max-height:44vh;overflow:auto}
.dsp-r{display:flex;align-items:center;gap:8px;width:100%;text-align:left;cursor:pointer;
  padding:7px 10px;border:1px solid var(--line);border-radius:8px;background:#fff;margin-bottom:5px;font-family:inherit}
.dsp-r:hover{border-color:#93b4e8;background:#f7fbff}
.dsp-r.on{border-color:#2563eb;background:#eef4fd;box-shadow:inset 0 0 0 1px #2563eb}
.dsp-r b{font-size:13px;color:var(--text);flex:none}
.dsp-r .mini{flex:1 1 auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.dsp-k{flex:none;font-style:normal;font-size:10.5px;color:#0e7490;background:#ecfeff;border:1px solid #a5f3fc;
  border-radius:5px;padding:0 5px;line-height:16px}
.dsp-ok{flex:none;font-style:normal;font-size:10.5px;font-weight:700;color:#15803d;background:#e8f7ee;
  border:1px solid #b7e4c7;border-radius:999px;padding:0 6px;line-height:16px}
.aim-sbd{padding:16px 18px 20px}
.aim-paper{font-size:11.5px;color:#8fa1b3;margin:-4px 0 12px}
.aim-hero{border:1px solid #cfe0f8;border-radius:10px;padding:13px 14px;background:linear-gradient(180deg,#f7fbff,#eef5ff)}
.aim-hero h3{font-size:13px;display:flex;align-items:center;gap:7px}
.aim-hero h3 .num{width:17px;height:17px;border-radius:50%;background:#1d4ed8;color:#fff;font-size:11px;flex:none;
  display:flex;align-items:center;justify-content:center}
.aim-keyline{display:flex;gap:8px;align-items:center;margin-top:10px;flex-wrap:wrap}
.aim-keyline input{flex:1;min-width:220px;height:36px;border:1px solid #a9c4ea;border-radius:8px;padding:0 11px}
.aim-tip{font-size:11.5px;color:#5c7590;margin-top:7px;line-height:1.6}
.aim-tip.warn{color:#b45309}
.aim-blk{margin-top:16px}
.aim-blk h3{font-size:12.5px;color:#31465e;display:flex;align-items:center;gap:7px;margin-bottom:4px;flex-wrap:wrap}
.aim-kv{width:100%;border-collapse:collapse;margin-top:6px}
.aim-kv td{border-bottom:1px solid var(--line);padding:7px 2px;font-size:12.5px;vertical-align:top}
.aim-kv td:first-child{width:104px;color:var(--muted)}
.aim-fbbox{display:flex;align-items:center;gap:10px;border:1px solid var(--line);border-radius:9px;
  padding:10px 12px;background:var(--soft2);margin-top:8px}
.aim-fbbox.dis{opacity:.75}
.aim-fbbox .lb{font-size:12.5px;color:#31465e;font-weight:600}
.aim-adv{border:1px solid var(--line);border-radius:10px;padding:0 12px;margin-top:10px;background:var(--soft2)}
.aim-adv>summary{cursor:pointer;padding:10px 0;font-size:12.5px;color:#31465e;list-style:none}
.aim-adv>summary::-webkit-details-marker{display:none}
.aim-adv>summary::before{content:"▸ ";color:#1d4ed8}
.aim-adv[open]>summary::before{content:"▾ "}
.aim-frm{display:grid;grid-template-columns:1fr 1fr;gap:10px 12px;margin-top:8px}
.aim-frm .f{display:flex;flex-direction:column;gap:4px}
.aim-frm .f.full{grid-column:1/-1}
.aim-frm label{font-size:12px;color:var(--label);font-weight:600}
.aim-frm input,.aim-frm select{height:33px;border:1px solid var(--line2);border-radius:8px;padding:0 10px;background:#fff;color:var(--text)}
.aim-frm .hint{font-size:11.5px;color:#8fa1b3;line-height:1.5}
.aim-use{display:grid;grid-template-columns:186px 1fr;gap:14px;align-items:center;margin-top:8px}
.aim-use b{font-size:24px;font-weight:600}
.aim-faq{background:#fcfdff;border:1px solid var(--line);border-radius:10px;padding:10px 12px;margin-top:10px}
.aim-faq b{font-size:12.5px}
.aim-faq ul{margin:6px 0 0;padding-left:18px;font-size:12px;color:#41546a;line-height:1.75}
.aim-sft{position:sticky;bottom:0;display:flex;align-items:center;gap:8px;flex-wrap:wrap;
  padding:11px 18px;border-top:1px solid var(--line);background:rgba(255,255,255,.97)}
.aim-sft .mini{margin-right:auto}
@media(max-width:1180px){
  .aim-flow{grid-template-columns:1fr;gap:6px}
  .aim-flow .arw{display:none}
}

/* 「有新版 / 型号已退役 → 一键更新」条 + 升级弹窗里的小件（2026-09-18） */
.aim-up{display:flex;align-items:center;gap:6px;margin-top:8px;padding:6px 8px;border-radius:8px;cursor:pointer;
  border:1px solid #c7d7f7;background:#f2f6ff}
.aim-up:hover{background:#e9f1ff}
.aim-up.bad{border-color:#f2d9a8;background:#fff8ec}
.aim-up b{font-size:11px;color:#1d4ed8;white-space:nowrap}
.aim-up.bad b{color:#b45309}
.aim-up span{font-size:11px;color:#5b6e82;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.aim-up-btn{margin-left:auto;font-size:11px;color:#fff;border-radius:999px;padding:2px 8px;
  background:linear-gradient(135deg,#1d4ed8,#6d28d9);white-space:nowrap}
.aim-ul{margin:6px 0 0;padding-left:18px;font-size:12.5px;color:#31465e;line-height:1.8}
.aim-warn{font-size:12.5px;color:#8a4b00;background:#fff8ec;border:1px solid #f2d9a8;border-radius:8px;padding:9px 11px;line-height:1.7}

/* 卡片内的「录入 KEY」按钮 / 就地输入行 / 卡片中心测试结果（需求方 2026-09-18） */
/* 「录入 KEY」+「官网 KEY·用量」+ 状态标识(=未启用/待填 Key/已连接) 同行放在标题下方
   （需求方 2026-09-18：模型名较长时挤在标题行会被换行；状态标识紧挨用量按钮右边） */
.aim-acts{display:flex;align-items:center;flex-wrap:wrap;gap:5px;margin-top:6px}
.aim-acts .aim-stat{margin-left:0}
.aim-keybtn{font-size:10.5px;padding:2px 6px;border-radius:6px;white-space:nowrap}
.aim-keybtn.on{border-color:#bfe3c9;background:#f1faf3;color:#15803d}
.aim-keyrow{display:none;gap:5px;align-items:center;margin-top:7px}
.aim-keyrow.on{display:flex}
.aim-keyrow input{flex:1;min-width:0;height:27px;border:1px solid #a9c4ea;border-radius:7px;padding:0 8px;font-size:11.5px}
.aim-res{position:absolute;inset:0;display:none;align-items:center;justify-content:center;border-radius:11px;
  background:rgba(255,255,255,.9);font-size:14px;font-weight:600;letter-spacing:.5px;color:#5b6e82;z-index:2}
.aim-res.on{display:flex}
.aim-res.ok{color:#15803d}
.aim-res.bad{color:#b91c1c}
.aim-keylink{font-size:10px;padding:2px 5px;border-radius:6px;white-space:nowrap;color:#1d4ed8;text-decoration:none}
.aim-keylink:hover{background:var(--hover);text-decoration:none}

/* 卡片上的「停用 / 启用」按钮 + 标签卡计数（需求方 2026-09-18） */
.aim-onoff{font-size:10.5px;padding:2px 6px;border-radius:6px;white-space:nowrap}
.aim-chip-n{opacity:.85}

/* 被设为「知识库兜底」的卡片：右上角有标签 → 标题行右侧留白，状态文字不被压住（需求方 2026-09-18） */
.aim-card.is-fb .aim-top{padding-right:64px}
.aim-foot .aim-onoff{margin-left:0}

/* ===== 模型设置 v3（需求方 2026-09-18 晚）：每日自查条 / 余额行 / 启用卡片深色渐变底 =====
   命名前缀 aim- 保持一致；深色卡片的文字/角标/按钮**全部用实色**（不用半透明），
   这样对比度是可确定的（本项目 ui_visual_metrics 会量对比度，渐变底 + 半透明容易误判）。 */
/* ① 每日自查状态条（显示上次自查时间与结果；服务端每天自动跑） */
.aim-selfchk{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-top:14px;padding:8px 11px;
  border:1px solid var(--line);border-radius:9px;background:var(--soft2);font-size:12px}
.aim-sc-lb{font-size:11px;font-weight:600;color:#41546a;letter-spacing:.2px}
.aim-sc-bits{color:#8fa1b3}
.aim-sc-diff{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin-top:6px;padding:7px 11px;
  border:1px solid #f2d9a8;border-radius:8px;background:#fff8ec;font-size:12px}
/* 「自查发现」每条差异 = 徽章 + 操作按钮成组（需求方 2026-09-22：「可是我无法选择接下来的操作」） */
.aim-sc-diff .aim-df{display:inline-flex;align-items:center;gap:5px;padding:1px 2px}
.aim-sc-diff .aim-df .btn.sm{padding:1px 8px;font-size:11.5px;line-height:1.6}
/* ② 余额行（只有官方提供余额接口的厂商才有：DeepSeek / Kimi） */
.aim-bal{display:flex;align-items:center;gap:6px;margin-top:7px;padding:4px 8px;cursor:pointer;
  border:1px dashed #cfe0f5;border-radius:7px;background:#f7fbff;font-size:11.5px}
.aim-bal:hover{border-color:#8fb6e8;background:#eef6ff}
.aim-bal-lb{font-size:11px;color:#5b6e82}
.aim-bal-v{margin-left:auto;font-family:Consolas,Monaco,monospace;color:#0f5132}
.aim-bal-r{font-size:12px;color:#1d4ed8}
/* ③ 已启用卡片：深色渐变底（需求方 2026-09-18「启用的模型卡片底色设计个深色渐变色」） */
.aim-card.aim-dark{color:#eaf2ff}
.aim-card.is-on{background:linear-gradient(135deg,#0e2244 0%,#153a75 55%,#1b4ea8 100%);
  border-color:#1e3a8a;box-shadow:0 6px 20px rgba(11,42,92,.28)}
.aim-card.aim-dark:hover{border-color:#3f74c8;box-shadow:0 8px 26px rgba(11,42,92,.38)}
.aim-card.aim-dark .aim-nm,.aim-card.aim-dark .aim-sum b{color:#fff}
.aim-card.aim-dark .aim-logo{background:linear-gradient(135deg,#3b82f6,#8b5cf6)}
.aim-card.aim-dark .aim-api{color:#bcd2ef}
.aim-card.aim-dark .aim-txt{color:#d7e4f7}
.aim-card.aim-dark .aim-fine{color:#c9daf1}
.aim-card.aim-dark .aim-sum span{color:#dce8f9}
/* 深色卡片：底部「配置 ›」与状态标签也要跟着换色
   （需求方 2026-09-18 晚指出：深底上「用量」那几行与「配置」二字看不清） */
.aim-card.aim-dark .aim-go{color:#cfe2ff}
.aim-card.aim-dark .tag{background:#12305f;border-color:#2f5c9e;color:#dbe7f9}
.aim-card.aim-dark .tag.ok{background:#0f3a26;border-color:#2f7a52;color:#b8f5d0}
.aim-card.aim-dark .aim-stat{color:#dbe7f9}
.aim-card.aim-dark .aim-foot{border-top-color:rgba(255,255,255,.16)}
.aim-card.aim-dark .badge{background:#12305f;border-color:#2f5c9e;color:#dbe7f9}
.aim-card.aim-dark .badge.aim-ver{border-color:transparent;color:#fff}
.aim-card.aim-dark .btn{background:#14305e;border-color:#35619f;color:#dbe7f9}
.aim-card.aim-dark .btn:hover{border-color:#9fc4ff;color:#fff}
.aim-card.aim-dark .aim-keylink{color:#9fc4ff}
.aim-card.aim-dark .aim-fb{background:#12305f;border-color:#2f5c9e}
.aim-card.aim-dark .aim-fb-lb{color:#dbe7f9}
.aim-card.aim-dark .aim-fb-hint{color:#b3c8e4}
.aim-card.aim-dark .aim-sw{background:#3a5580}
.aim-card.aim-dark .aim-bal{background:#12305f;border-color:#3a67a8}
.aim-card.aim-dark .aim-bal-lb{color:#bcd2ef}
.aim-card.aim-dark .aim-bal-v{color:#a7f3c9}
.aim-card.aim-dark .aim-bal-r{color:#9fc4ff}
.aim-card.aim-dark .aim-up{background:#12305f;border-color:#2f5c9e}
.aim-card.aim-dark .aim-up b,.aim-card.aim-dark .aim-up span{color:#dbe7f9}
.aim-card.aim-dark .aim-res{background:rgba(9,25,52,.86);color:#dbe7f9}

/* ===== 调用模式三选一（需求方 2026-09-18 定稿）：1 云端版 / 2 本地优先版 / 3 全本地版 ===== */
.aim-modebar{display:grid;grid-template-columns:repeat(3,1fr);gap:9px;margin-top:14px}
.aim-mode{background:#fff;border:1px solid var(--line);border-radius:10px;padding:10px 11px;cursor:pointer;
  transition:.15s;box-shadow:var(--shadow)}
.aim-mode:hover{border-color:#c7d7f7;transform:translateY(-1px)}
.aim-mode.on{border-color:#1d4ed8;box-shadow:0 0 0 3px rgba(37,99,235,.10),var(--shadow);
  background:linear-gradient(135deg,#f7fbff,#eef4ff)}
.aim-mode-h{display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.aim-mode-h b{font-size:13px;color:var(--head-tx)}
.aim-mode-cur{margin-left:auto;font-size:11px;font-weight:600;color:#fff;background:linear-gradient(135deg,#1d4ed8,#6d28d9);
  border-radius:999px;padding:2px 8px}
.aim-mode-f{font-size:12px;color:#31465e;line-height:1.6;margin-top:6px}
.aim-mode-t{display:flex;gap:4px;flex-wrap:wrap;margin-top:6px}
.aim-mode-t .badge{font-size:10.5px;padding:2px 5px}
.aim-mode .mini{margin-top:6px;line-height:1.5;color:#7f93a8}
.aim-mode-now{display:flex;align-items:center;gap:7px;flex-wrap:wrap;margin-top:8px;padding:7px 11px;
  border:1px solid var(--line);border-radius:8px;background:var(--soft2);font-size:12px}
.aim-mode-now b{color:#1d4ed8}

/* 本机模型（Ollama 等）：**红色渐变底**（需求方 2026-09-18 晚）+ 与深色卡同一套浅色字（.aim-dark） */
.aim-card.is-local{background:linear-gradient(135deg,#4c0519 0%,#7f1d1d 55%,#b91c1c 100%);border-color:#7f1d1d;
  box-shadow:0 6px 20px rgba(120,20,30,.30)}
.aim-card.is-local:hover{border-color:#ef4444;box-shadow:0 8px 26px rgba(120,20,30,.40)}

/* ===== RAG知识库列表（需求方 2026-09-19）：顶部条 / 分类按钮 / 使用痕迹三计数 / A4 编辑弹窗 ===== */
.kb-top{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.kb-cats{display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.kb-cat{display:inline-flex;align-items:center;gap:5px;font-size:12px;color:#41546a;background:#fff;
  border:1px solid var(--line2);border-radius:999px;padding:4px 11px;cursor:pointer;transition:.15s}
.kb-cat:hover{border-color:#8fb6e8;color:#1d4ed8}
.kb-cat.on{background:linear-gradient(135deg,#1d4ed8,#6d28d9);border-color:transparent;color:#fff}
.kb-cat.on b{color:#fff}
.kb-cat b{font-weight:600;opacity:.85}
.kb-cat.add{border-style:dashed;color:#1d4ed8}
.kb-cat-x{font-style:normal;font-size:10px;opacity:.5;padding:0 1px}
.kb-cat-x:hover{opacity:1;color:#b91c1c}
.kb-cat.on .kb-cat-x{color:#fff}
.kb-cat-new{display:inline-flex;align-items:center;gap:5px}
.kb-cat-new input{height:30px;width:130px;border:1px solid var(--line2);border-radius:8px;padding:0 9px;font-size:12px;outline:none}
.kb-cat-new input:focus{border-color:var(--accent);box-shadow:0 0 0 3px rgba(14,116,144,.12)}
/* 「使用痕迹」列：有用 / 无用 / 负面（黄色三角感叹号）三计数 */
.kbtrace{display:inline-flex;align-items:center;gap:5px}
.kbtrace .btn{font-size:11.5px;padding:2px 7px;border-radius:999px;display:inline-flex;align-items:center;gap:4px}
.kbtrace .btn b{font-weight:600}
.kbtrace .kbt-good{border-color:#bbf7d0;background:#f0fdf4;color:#15803d}
.kbtrace .kbt-good:hover{background:#dcfce7;color:#15803d}
.kbtrace .kbt-bad{border-color:#fecaca;background:#fef2f2;color:#b91c1c}
.kbtrace .kbt-bad:hover{background:#fee2e2;color:#b91c1c}
.kbtrace .kbt-neg{border-color:#fde68a;background:#fffbeb;color:#92400e}
.kbtrace .kbt-neg:hover{background:#fef3c7;color:#92400e}
/* A4 编辑弹窗里的表单（复用全站 .form/.f；这里只收一收间距，保证"格式统一"） */
.kb-form{gap:10px 16px}
.kb-form textarea{line-height:1.7;font-family:inherit}

/* ===== 「AI建议」问答页（需求方 2026-09-19）：答案卡 / 关联答案下拉 ===== */
.ai-ans{border:1px solid var(--line);border-radius:10px;padding:11px 13px;background:#fff}
.ai-ans-main{border-color:#c7d7f7;background:linear-gradient(135deg,#fbfdff,#f4f8ff);box-shadow:var(--shadow)}
.ai-ans-h{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:7px}
.ai-ans-h b{font-size:13.5px;color:var(--head-tx)}
.ai-ans-f{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin-top:9px;padding-top:8px;border-top:1px dashed var(--line2)}
.ai-rel{margin-top:12px;border:1px solid var(--line);border-radius:10px;background:#fbfdff}
.ai-rel>summary{cursor:pointer;padding:9px 12px;font-size:12.5px;font-weight:600;color:#1d4ed8;list-style:none}
.ai-rel>summary::-webkit-details-marker{display:none}
.ai-rel>summary::before{content:'▸ ';font-weight:700}
.ai-rel[open]>summary::before{content:'▾ '}
.ai-rel-item{margin:0 10px 10px;border:1px solid var(--line);border-radius:9px;background:#fff}
.ai-rel-item>summary{cursor:pointer;padding:8px 11px;font-size:12.5px;color:#31465e;list-style:none}
.ai-rel-item>summary::-webkit-details-marker{display:none}
.ai-rel-item>summary::before{content:'▸ ';color:#8fa1b3}
.ai-rel-item[open]>summary::before{content:'▾ '}
.ai-rel-item .ai-answer{margin:0 11px 8px;font-size:12.5px}
.ai-rel-item .ai-ans-f{margin:0 11px 9px}

/* ===== RAG知识库列表：内容居中（需求方 2026-09-19） =====
   基样式 `th,td{text-align:left}` 是**显式**声明，会压过继承 → 必须直接命中 th/td 才生效；
   代码里同时写了内联样式（防 style.css 缓存导致改了看不到）。 */
#kb-tbl th,#kb-tbl td{text-align:center}

/* ===== 「AI建议」答案区（需求方 2026-09-19）：关联答案**全部展开** + 每条答案「复制」 ===== */
.ai-ans-rel{margin-top:9px}
.ai-sp{flex:1 1 auto}
.ai-copy{white-space:nowrap;margin-left:2px;padding:1px 6px;font-size:11px;line-height:1.5}
.ai-copy:hover{border-color:#8fb6e8;color:#1d4ed8}

/* ===== 「AI风暴」标题字标（需求方 2026-09-19）=====
   "AI" 两个字单独设计：走**常见的 AI 科技风字体**（Bahnschrift 是 Windows 自带的技术感字体，
   逐级回退到 Segoe UI Black / Arial Black / Impact），再加青→蓝→紫渐变字 + 字距加大 + 下划光条；
   "风暴"两个字用本站常规标题字重，形成"标识 + 名称"的组合。
   🔴 离线环境不引任何外部字体文件（纯系统字体回退，Electron 内也一定渲染得出来）。 */
.aist-h2{display:flex;align-items:baseline;gap:3px;margin:0;font-size:var(--fs-h2);flex-wrap:wrap}
.aist-mark{
  font-family:'Bahnschrift','Bahnschrift SemiBold','Segoe UI Black','Arial Black',Impact,sans-serif;
  font-weight:800;font-size:30px;line-height:1.05;letter-spacing:3px;padding:0 3px;
  background:linear-gradient(115deg,#0ea5e9 0%,#2563eb 45%,#7c3aed 100%);
  -webkit-background-clip:text;background-clip:text;
  color:transparent;-webkit-text-fill-color:transparent;
  position:relative;transform:skewX(-6deg)
}
.aist-mark::after{content:'';position:absolute;left:3px;right:3px;bottom:-2px;height:3px;border-radius:2px;
  background:linear-gradient(90deg,#0ea5e9,#7c3aed);opacity:.85}
.aist-nm{font-weight:var(--fw-title);letter-spacing:2px;color:var(--head-tx)}

/* ===== 「AI模型会议」会议室（需求方 2026-09-19）=====
   版式：左=交流大屏（深色玻璃，会场感）· 右=议题与消耗 · 下=控制条 · AI 入座 · 我的会议记录。
   🔴 深色面板上的文字一律用**实色浅色**（不用半透明），保证对比度可确定。 */
.mtr{display:grid;grid-template-columns:1fr 322px;gap:14px;align-items:stretch}
@media (max-width:1180px){.mtr{grid-template-columns:1fr}}
/* —— 交流大屏 ——
   🔴 左栏随右栏（议题/消耗栏）等高拉伸：右栏内容长于窗口高度估算值时，左栏下方不会再空出一块 */
.mtr-stage{position:relative;display:flex;flex-direction:column;border:1px solid #1e3a8a;border-radius:14px;overflow:hidden;
  background:radial-gradient(120% 90% at 12% -10%,#1b3f7d 0%,#0d2247 45%,#081428 100%);
  box-shadow:0 10px 34px rgba(8,20,40,.34)}
.mtr-stage::before{content:'';position:absolute;inset:0;pointer-events:none;opacity:.5;
  background-image:linear-gradient(rgba(120,170,255,.07) 1px,transparent 1px),linear-gradient(90deg,rgba(120,170,255,.07) 1px,transparent 1px);
  background-size:26px 26px}
.mtr-bar{position:relative;flex:none;display:flex;align-items:center;gap:9px;padding:11px 14px;flex-wrap:wrap;
  border-bottom:1px solid rgba(140,180,255,.18);background:rgba(9,22,44,.72)}
.mtr-bar b{color:#eaf2ff;font-size:13.5px}
.mtr-live{width:8px;height:8px;border-radius:50%;background:#22c55e;box-shadow:0 0 0 0 rgba(34,197,94,.7);animation:mtrPulse 1.8s infinite}
@keyframes mtrPulse{0%{box-shadow:0 0 0 0 rgba(34,197,94,.6)}70%{box-shadow:0 0 0 9px rgba(34,197,94,0)}100%{box-shadow:0 0 0 0 rgba(34,197,94,0)}}
.mtr-bar-s{font-size:11.5px;color:#0b2240;background:#93c5fd;border-radius:999px;padding:2px 9px;font-weight:600}
.mtr-bar-t{margin-left:auto;font-family:Consolas,Monaco,monospace;color:#9fc4ff;font-size:12.5px}
.mtr-log{position:relative;flex:1 1 auto;min-height:0;overflow:auto;padding:14px 14px 6px;scroll-behavior:smooth}
.mtr-log::-webkit-scrollbar{width:9px}
.mtr-log::-webkit-scrollbar-thumb{background:rgba(150,190,255,.28);border-radius:6px}
.mtr-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;height:100%;color:#cfe0ff;text-align:center}
.mtr-empty-ico svg{width:46px;height:46px;opacity:.75}
.mtr-empty b{color:#fff;font-size:15px}
/* 发言气泡 */
.mtr-msg{display:flex;gap:10px;margin-bottom:12px;animation:mtrIn .28s ease-out}
@keyframes mtrIn{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
.mtr-av{flex:none;width:30px;height:30px;border-radius:9px;color:#fff;font-weight:700;font-size:13px;
  display:flex;align-items:center;justify-content:center;box-shadow:0 2px 8px rgba(0,0,0,.3)}
.mtr-av.sm{width:22px;height:22px;border-radius:7px;font-size:11px}
.mtr-av.xs{width:16px;height:16px;border-radius:5px;font-size:9.5px}
.mtr-bd{flex:1;min-width:0;background:rgba(238,246,255,.96);border:1px solid rgba(150,190,255,.5);border-radius:11px;padding:9px 11px}
.mtr-hd{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin-bottom:5px}
.mtr-hd b{font-size:12.5px;color:#123c6b}
.mtr-tag{font-size:10.5px;color:#31507a;background:#e2ecfb;border:1px solid #c7daf5;border-radius:999px;padding:1px 7px}
.mtr-tag.dim{color:#5b6e82;background:#f1f5fb;border-color:#e2e9f3}
.mtr-tag.host{color:#7c2d12;background:#ffedd5;border-color:#fdba74;font-weight:600}
.mtr-meta{margin-left:auto;font-size:10.5px;color:#7f93a8;font-family:Consolas,Monaco,monospace}
.mtr-tx{font-size:13px;line-height:1.75;color:#1b2b3d;white-space:pre-wrap;word-break:break-word}
/* 主持人 / 开场 / 总结：各自不同的描边与底色 */
.mtr-msg.is-host .mtr-bd{border-color:#fbbf24;box-shadow:0 0 0 3px rgba(251,191,36,.16)}
.mtr-msg.is-open .mtr-bd{background:linear-gradient(135deg,#f5f0ff,#eef2ff);border-color:#c4b5fd}
.mtr-msg.is-sum .mtr-bd{background:linear-gradient(135deg,#eefbf6,#eef6ff);border-color:#5eead4;box-shadow:0 0 0 3px rgba(45,212,191,.14)}
/* 正在发言 / 正在思考（临时气泡，不入库） */
.mtr-msg.is-typing .mtr-bd{background:rgba(20,40,72,.72);border-style:dashed;border-color:rgba(150,190,255,.5)}
.mtr-msg.is-typing .mtr-hd b{color:#eaf2ff}
.mtr-msg.is-typing .mtr-tag{color:#cfe0ff;background:rgba(20,45,85,.8);border-color:rgba(150,190,255,.45)}
.mtr-dots{display:inline-flex;gap:3px;margin-left:4px}
.mtr-dots i{width:5px;height:5px;border-radius:50%;background:#93c5fd;animation:mtrDot 1.1s infinite}
.mtr-dots i:nth-child(2){animation-delay:.16s}
.mtr-dots i:nth-child(3){animation-delay:.32s}
@keyframes mtrDot{0%,60%,100%{opacity:.3;transform:translateY(0)}30%{opacity:1;transform:translateY(-3px)}}
/* 主持人请示条（是否结束本议题） */
.mtr-ask{display:none}
.mtr-ask.on{flex:none;display:block;margin:0 14px 14px;border:1px solid #f2b134;border-radius:12px;overflow:hidden;
  background:linear-gradient(135deg,#fffbeb,#fff7e6);box-shadow:0 6px 20px rgba(180,120,20,.18)}
.mtr-ask-h{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:10px 12px;background:rgba(251,191,36,.16)}
.mtr-ask-h b{font-size:13px;color:#7c2d12}
.mtr-ask-b{padding:10px 12px;font-size:12.5px;color:#4a3520;line-height:1.7}
.mtr-ask-f{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:0 12px 12px}
/* —— 右栏 —— */
.mtr-side{background:var(--card);border:1px solid var(--line);border-radius:14px;padding:13px 13px 15px;box-shadow:var(--shadow)}
.mtr-side-t{font-size:12px;font-weight:700;color:#41546a;letter-spacing:.2px;margin-bottom:7px}
.mtr-side textarea{width:100%;min-height:118px;padding:10px 11px;border:1px solid var(--line2);border-radius:10px;
  font-size:13px;line-height:1.7;font-family:inherit;color:var(--text);outline:none;resize:vertical;box-sizing:border-box}
.mtr-side textarea:focus{border-color:var(--accent);box-shadow:0 0 0 3px rgba(14,116,144,.12)}
.mtr-go{width:100%;margin-top:9px;justify-content:center}
.mtr-info{margin-top:2px}
.mtr-info>div{display:flex;align-items:center;gap:8px;font-size:12.5px;padding:4px 0;border-bottom:1px dashed var(--line2)}
.mtr-info>div:last-child{border-bottom:0}
.mtr-info span{color:var(--muted)}
.mtr-info b{margin-left:auto;color:var(--head-tx);max-width:190px;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.mtr-st{color:#94a3b8!important}
.mtr-st.on{color:#15803d!important}
.mtr-st.paused{color:#b45309!important}
.mtr-mini{display:flex;flex-wrap:wrap;gap:5px;margin-top:9px}
.mtr-mini-seat{display:inline-flex;align-items:center;gap:4px;font-size:11.5px;color:#31507a;background:#f2f7ff;
  border:1px solid #dbe8fa;border-radius:999px;padding:2px 8px}
.mtr-mini-seat.is-host{border-color:#fbbf24;background:#fff7e6;color:#7c2d12}
.mtr-note{margin-top:11px;font-size:11.5px;line-height:1.65;color:#7f93a8;background:var(--soft2);border:1px solid var(--line);border-radius:9px;padding:8px 10px}
/* 资源消耗（估算） */
.mtr-use{margin-top:2px;border:1px solid var(--line);border-radius:10px;overflow:hidden}
.mtr-use-r{display:flex;align-items:center;gap:6px;padding:6px 9px;font-size:12px;border-bottom:1px dashed var(--line2)}
.mtr-use-r:last-of-type{border-bottom:0}
.mtr-use-n{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:#31465e}
.mtr-use-n .badge{font-size:10px;margin-left:4px;padding:1px 5px}
.mtr-use-t{font-family:Consolas,Monaco,monospace;color:#5b6e82;font-size:11.5px}
.mtr-use-r b{font-family:Consolas,Monaco,monospace;color:#1d4ed8}
.mtr-use-r b.ok{color:#15803d}
.mtr-use-sum{display:flex;align-items:center;gap:8px;padding:7px 9px;background:var(--soft2);font-size:12px;border-top:1px solid var(--line)}
.mtr-use-sum b{margin-left:auto;font-family:Consolas,Monaco,monospace;color:#1d4ed8}
.mtr-save{font-size:11.5px;color:#15803d;background:#f0fdf4;border:1px solid #bbf7d0;border-radius:999px;padding:1px 7px}
/* —— 控制条 —— */
.mtr-ctrl{display:flex;align-items:center;gap:9px;flex-wrap:wrap;margin-top:14px;padding:11px 13px;
  background:var(--card);border:1px solid var(--line);border-radius:13px;box-shadow:var(--shadow)}
.mtr-b{min-width:112px;justify-content:center}
.mtr-b.off{opacity:.55}
.mtr-split{flex:1}
.mtr-dl{background:linear-gradient(135deg,#0ea5e9,#6d28d9);color:#fff;border-color:transparent!important}
/* —— AI 入座 —— */
.mtr-seats{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-top:10px;padding:10px 13px;
  background:var(--card);border:1px solid var(--line);border-radius:13px;box-shadow:var(--shadow)}
.mtr-seats-lb{font-size:12px;font-weight:700;color:#41546a}
.mtr-seat{display:inline-flex;align-items:center;gap:6px;font-size:12.5px;color:#31507a;background:#f7fafd;
  border:1px solid var(--line2);border-radius:999px;padding:3px 10px 3px 4px}
.mtr-seat b{font-weight:600}
.mtr-seat.is-host{background:linear-gradient(135deg,#fff7e6,#ffedd5);border-color:#fbbf24;color:#7c2d12}
.mtr-crown{font-size:10.5px;background:#fbbf24;color:#7c2d12;border-radius:999px;padding:1px 7px;font-weight:700}
.mtr-hostset,.mtr-rm{font-size:11px;color:#8fa1b3;text-decoration:none}
.mtr-hostset:hover{color:#1d4ed8}
.mtr-rm:hover{color:#b91c1c}
/* 邀请弹窗里的多选 */
.mtr-picks{display:grid;grid-template-columns:repeat(2,1fr);gap:8px}
.mtr-pick{display:flex;align-items:center;gap:8px;padding:8px 10px;border:1px solid var(--line2);border-radius:10px;cursor:pointer;background:#fff}
.mtr-pick:hover{border-color:#8fb6e8}
.mtr-pick.on{border-color:#1d4ed8;background:#f5f9ff;box-shadow:0 0 0 3px rgba(37,99,235,.08)}
.mtr-pick input{width:15px;height:15px;accent-color:var(--accent)}
.mtr-pick-n{display:flex;flex-direction:column;min-width:0}
.mtr-pick-n b{font-size:12.5px;color:var(--head-tx);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* —— 我的会议记录 —— */
.mtr-rec-wrap{margin-top:18px}
.mtr-rec-t{font-size:13px;font-weight:700;color:#41546a;margin-bottom:9px}
.mtr-rec{display:grid;grid-template-columns:repeat(2,1fr);gap:11px}
@media (max-width:1180px){.mtr-rec{grid-template-columns:1fr}}
.mtr-rec-card{background:var(--card);border:1px solid var(--line);border-radius:12px;padding:11px 12px;box-shadow:var(--shadow)}
.mtr-rec-h{display:flex;align-items:center;gap:7px;flex-wrap:wrap}
.mtr-rec-h b{font-size:13px;color:var(--head-tx)}
.mtr-rec-s{margin-top:7px;font-size:12.5px;line-height:1.7;color:#31465e}
.mtr-rec-f{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin-top:9px;padding-top:8px;border-top:1px dashed var(--line2)}
.mtr-rec-empty{color:var(--muted);font-size:12.5px;padding:14px;border:1px dashed var(--line2);border-radius:11px;text-align:center}

/* 会议预计消耗（需求方 2026-09-19：不是所有客户都有本地模型 → 云端花费要能预估） */
.mtr-est{margin-top:9px;padding:8px 10px;border:1px solid #cfe0f5;border-radius:9px;background:#f7fbff;font-size:12px;color:#31465e}
.mtr-est b{color:#1d4ed8;font-family:Consolas,Monaco,monospace}

/* ===== 「AI模型会议」自适应 + 语音/流式/轮数/忙提示（需求方 2026-09-19 第二批）===== */
/* ① 交流窗口：**左右两栏对齐 + 框内滚动**（需求方 2026-09-19：默认太高了；超出不要撑高整页，要自动滚动）
   做法：给整行一个**受视口约束的高度**，两栏都拉伸到等高；
        左栏（对话）与右栏（议题/说明/消耗）各自 `overflow:auto` —— 鼠标移进去滚轮翻，页面本身不被撑长。
   （前两轮踩过两次：固定 height 估算 → 右栏一变高就留白；min-height 撑满 → 整页被撑高。
     这次用「行高受视口约束 + 两栏内部滚动」，两个毛病一起避免。） */
.mtr{grid-template-columns:1fr 322px;align-items:stretch;height:clamp(420px,calc(100vh - 330px),760px)}
.mtr-side{min-height:0;overflow:auto}
@media (max-width:1080px){
  .mtr{grid-template-columns:1fr;height:auto}
  .mtr-log{height:clamp(260px,46vh,520px)}
  .mtr-side{order:-1;max-height:none;overflow:visible}
}
@media (max-height:700px){ .mtr{height:clamp(380px,calc(100vh - 300px),640px)} }
/* ② 每条发言标题上的「朗读」小按钮 */
.mtr-spk{flex:none;width:22px;height:22px;padding:0;border:1px solid var(--line2);border-radius:6px;
  background:#fff;cursor:pointer;font-size:11px;line-height:1;color:#31507a}
.mtr-spk:hover{border-color:#8fb6e8;background:#f2f7ff}
/* ③ 「暂时忙 · 未响应会议」的灰气泡（不显示任何报错原文） */
.mtr-msg.is-busy .mtr-bd{background:rgba(148,163,184,.16);border-style:dashed;border-color:rgba(148,163,184,.65)}
.mtr-msg.is-busy .mtr-tx{color:#8593a5}
.mtr-msg.is-busy .mtr-hd b{color:#64748b}
/* ④ 我的发言（用户接管主持后说的） */
.mtr-msg.is-me .mtr-bd{background:linear-gradient(135deg,#ecfeff,#f0fdfa);border-color:#5eead4;box-shadow:0 0 0 3px rgba(13,148,136,.12)}
.mtr-msg.is-me .mtr-hd b{color:#0f766e}
/* ⑤ 交流窗口里的系统提示 */
.mtr-msg.is-sys{margin:2px 0 10px}
.mtr-msg.is-sys .mtr-bd{background:rgba(15,32,58,.5);border:1px dashed rgba(150,190,255,.4)}
.mtr-msg.is-sys .mtr-tx{color:#bcd2ef;font-size:12px;text-align:center}
/* ⑥ 轮数加减控件 */
.mtr-roundrow b{display:inline-flex;align-items:center;gap:5px}
.mtr-roundrow .btn.sm{padding:1px 7px;min-width:24px;font-size:13px;line-height:1.4}
.mtr-cap{font-style:normal;font-family:Consolas,Monaco,monospace;font-size:14px;font-weight:700;color:#1d4ed8;min-width:16px;text-align:center}
.mtr-hostrow b{display:inline-flex;align-items:center;gap:5px}
/* ⑦ 输出方式开关（流式 / 本地语音 / 免费语音 / 收费语音） */
/* 🔴 版式沿革：2026-09-22 需求方要「一行三个、字不换行」（当时只有 流式+本地+在线 三个按钮）。
   2026-09-23 语音**多了一个**（收费）→ 一行四格在侧栏（可用约 294px）里塞不下，字号会被挤到看不清。
   所以改成**两行**：第 1 行「流式输出」占整行，第 2 行三个语音按钮**等宽一行、字不换行**。
   保持不变的口径是「字不换行」+「语音三个按钮在同一行内等宽」。 */
.mtr-sw2{display:flex;flex-direction:column;gap:6px;margin-top:2px;align-items:stretch}
.mtr-swb{padding:7px 8px;border:1px solid var(--line2);border-radius:9px;background:#fff;cursor:pointer;
  font-size:12px;color:#5b6e82;transition:.15s}
.mtr-swb:hover{border-color:#8fb6e8;color:#1d4ed8}
.mtr-swb.on{border-color:#1d4ed8;color:#1d4ed8;background:linear-gradient(135deg,#f5f9ff,#eef4ff);font-weight:600}
/* ⑧ 坐席上的「固定声线」小字 */
.mtr-mini-v{font-style:normal;font-size:10.5px;color:#8fa1b3;margin-left:2px}

/* 语音档位说明（两档各自的特性 + 真人语音的配置要求）*/
.mtr-tts-note{line-height:1.7;color:#7f93a8}

/* ===== 「本地语音模型」配置（需求方 2026-09-19）===== */
.mtr-tts-note{margin-top:6px;line-height:1.65;color:#7f93a8}
.mtr-tts-note b{color:#41546a}
.mtr-cfgr{display:flex;align-items:center;gap:8px;margin-top:8px;font-size:12px}
.mtr-cfgr span{flex:none;width:64px;color:#5b6e82}
.mtr-cfgr input{flex:1;min-width:0;height:32px;border:1px solid var(--line2);border-radius:8px;
  padding:0 9px;font-size:12.5px;outline:none;font-family:inherit;color:var(--text)}
.mtr-cfgr input:focus{border-color:var(--accent);box-shadow:0 0 0 3px rgba(14,116,144,.12)}
/* 🔴 下拉与输入框**同一口径**（2026-09-23 加给「收费语音模型」面板的「默认音色」）：
   高 32 / 圆角 8 / 边框 / 聚焦光圈 —— 否则同一个面板里"输入框是样式框、下拉是浏览器原生外观"，
   两者行高也不一致，看着很散。本规则只作用于 `.mtr-cfgr`（仅语音面板在用）。 */
.mtr-cfgr select{flex:1;min-width:0;height:32px;border:1px solid var(--line2);border-radius:8px;
  padding:0 8px;font-size:12.5px;outline:none;font-family:inherit;color:var(--text);background:#fff}
.mtr-cfgr select:focus{border-color:var(--accent);box-shadow:0 0 0 3px rgba(14,116,144,.12)}

/* 语音这一层 = **横向一行**（三个按钮：本地 / 免费 / 收费），与上面的「流式输出」分两行。 */
.mtr-swrow{display:flex;gap:6px}
/* 语音三个按钮**同一个尺寸口径**（用后代选择器限定在 .mtr-swrow 里，免得影响上方的「流式输出」格）：
   flex:1 1 0 = 三者等宽，white-space:nowrap = 字不换行（需求方 2026-09-22 的口径）。 */
.mtr-swrow .mtr-swb{flex:1 1 0;min-width:0;white-space:nowrap;padding:7px 4px;font-size:11.5px;text-align:center}
.mtr-gear{flex:none;width:34px;padding:0;align-self:stretch;display:flex;align-items:center;justify-content:center;border:1px solid var(--line2);border-radius:9px;
  background:#fff;color:#5b6e82;font-size:15px;line-height:1;cursor:pointer;transition:.15s}
.mtr-gear:hover{border-color:#8fb6e8;color:#1d4ed8}
.mtr-gear.on{border-color:#1d4ed8;color:#1d4ed8;background:linear-gradient(135deg,#f5f9ff,#eef4ff)}


/* 「真人语音」未配置本地模型时的不可用态 + 配置弹窗里的部署讲解 */
.mtr-swb.dis{opacity:.55;cursor:not-allowed}
.mtr-guide{margin-top:12px;padding:10px 12px;border:1px solid var(--line);border-radius:10px;
  background:var(--soft2);font-size:12px;line-height:1.75;color:#41546a}
.mtr-guide b{display:block;margin-bottom:5px;color:var(--head-tx)}
.mtr-guide code{font-family:Consolas,Monaco,monospace;background:#fff;border:1px solid var(--line2);
  border-radius:5px;padding:0 4px;font-size:11.5px;color:#1d4ed8}
.mtr-guide .mini{margin-top:6px;color:#7f93a8;line-height:1.65}

/* 部署流程讲解：两条流程分块 + 当前正在配置的那条高亮（需求方 2026-09-19） */
.mtr-guide-rel{margin-bottom:9px;padding:8px 10px;border-left:3px solid #1d4ed8;background:#fff;border-radius:0 8px 8px 0}
.mtr-guide-sec{margin-top:8px;padding:9px 11px;border:1px solid var(--line2);border-radius:9px;background:#fff}
.mtr-guide-sec.now{border-color:#1d4ed8;background:linear-gradient(135deg,#f7fbff,#eef4ff);box-shadow:0 0 0 3px rgba(37,99,235,.07)}
.mtr-guide-sec b{display:block;margin-bottom:4px;color:var(--head-tx);font-size:12.5px}
.mtr-guide-now{display:inline-block;margin-left:6px;font-size:10.5px;font-weight:600;color:#fff;
  background:linear-gradient(135deg,#1d4ed8,#6d28d9);border-radius:999px;padding:1px 8px;vertical-align:1px}

/* ---- 建单页「图片 / 附件」（需求方 2026-09-19）：问题描述下方，图片或文件、≤20MB、数量不限 ---- */
.tk-att{border:1px dashed var(--line2);border-radius:10px;padding:10px 12px;background:var(--card)}
.tk-att-bar{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.tk-att-bar .mini{color:var(--muted);font-size:11.5px}
.tk-att-list{display:flex;flex-direction:column;gap:6px;margin-top:9px}
.tk-att-i{display:flex;align-items:center;gap:9px;padding:6px 9px;border:1px solid var(--line);border-radius:8px;background:var(--hover);font-size:12.5px}
.tk-att-n{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--text)}
.tk-att-s{color:var(--muted);font-size:11.5px;font-variant-numeric:tabular-nums}
.tk-att-a{color:var(--accent);text-decoration:none;font-size:12px}
.tk-att-a:hover{text-decoration:underline}
.tk-att-x{border:1px solid var(--line2);background:var(--card);color:var(--muted);border-radius:7px;width:22px;height:22px;line-height:1;cursor:pointer;padding:0}
.tk-att-x:hover{color:var(--red);border-color:#f3c3c3}

/* ---- 工单管理列表 · 三考核单元格（需求方 2026-09-19）----
   每格两行：上行 = **基线**（建单时锁定的 SLA 快照；浅灰、字号略小），
             下行 = **实际操作时间** + 达标标记（✓ 达标=绿 / ✗ 违约=红 / 待…=灰）。
   用 MM-DD HH:mm 省宽度，完整时间在 title 悬停里。 */
.sla-c{display:inline-flex;flex-direction:column;gap:1px;line-height:1.35;vertical-align:middle}
.sla-c .sla-b{font-style:normal;font-size:11.5px;color:var(--muted);white-space:nowrap}
.sla-c .sla-a{font-style:normal;font-size:12px;white-space:nowrap;font-variant-numeric:tabular-nums}
.sla-c .sla-a.ok{color:var(--green);font-weight:600}
.sla-c .sla-a.bad{color:var(--red);font-weight:600}
.sla-c .sla-a.wait{color:var(--muted)}
/* 到场免责豁免（需求方 2026-09-19）：基线不平移，判定时按豁免秒顺延 → 标识「豁」 */
.sla-c .sla-a.ex{color:#c2410c;font-weight:600}
/* 「迟」＝开始处理晚于预约到场（需求方 2026-09-19：到场考核时间后蓝字） */
.sla-c .sla-late{font-style:normal;color:#2563eb;font-weight:700;margin-left:4px}

/* 三考核格**第三行**（需求方 2026-09-20）：倒计时（到场 = appt-tip / 解决 = sla-rt）与**阶段用时**（sla-used） */
.appt-tip,.sla-rt{font-style:normal;font-size:12px;font-weight:600;white-space:nowrap}
.appt-tip.ok,.sla-rt.ok{color:#15803d}
.appt-tip.warn,.sla-rt.warn{color:#b45309}
.appt-tip.bad,.sla-rt.bad{color:#b91c1c}
/* 已挂起 = 提醒**停表**（需求方 2026-09-20：「挂起应该停住的」）—— 灰字，不再是红/黄/绿 */
.appt-tip.hold,.sla-rt.hold{color:#64748b}
/* 已过预约时间但**仍在到场基线内**（迟到未处理）→ **蓝紫字**（需求方 2026-09-20 定稿）：
   这不是违约（上一行还是 ✓），只是"人还没到场"；真过了基线才转红字「超时」。 */
.appt-tip.late,.sla-rt.late{color:#6d4bd0}
/* 阶段共计用时（自然时间，已扣挂起）：**颜色跟考核结论走**（需求方 2026-09-20「颜色也使用考核色」）：
   达标 = 绿 / 违约 = 红 / 豁免 = 橙（与同格的 ✓ ✗ 豁 一致） */
.sla-used{font-style:normal;font-size:11.5px;white-space:nowrap;font-variant-numeric:tabular-nums;font-weight:600}
.sla-used.ok{color:var(--green)}
.sla-used.bad{color:var(--red)}
.sla-used.ex{color:#c2410c}

/* ===== 数字大屏（复刻 CrossNet-AIIT 数字驾驶舱）· 作用域 #screen-big ===== */
/* ============================================================
   CrossNet 智维数字驾驶舱 — 1920×1080 全屏大屏（等比缩放，绝不超屏）
   设计语言：深空蓝 × 科技青 · 发光曲线 · 斜切角 · 轨道环 · 扫描/脉冲动效
   ============================================================ */
#screen-big .big-wrap {
  position: relative;
  width: 100%;
  min-width: 1080px;
  background: radial-gradient(1200px 700px at 80% -10%, rgba(30, 58, 138, 0.55), transparent 60%),
    radial-gradient(1000px 600px at 8% 108%, rgba(88, 28, 135, 0.4), transparent 62%),
    linear-gradient(180deg, #020814 0%, #041229 55%, #051633 100%);
  overflow: hidden;
}
#screen-big .dash {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 1920px;
  height: 1080px;
  transform-origin: center;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  font-family: 'PingFang SC', 'Microsoft YaHei', 'Segoe UI', sans-serif;
  color: #bcd3f2;
  background:
    radial-gradient(1100px 520px at 50% -12%, rgba(56, 189, 248, 0.16), transparent 62%),
    radial-gradient(900px 480px at 96% 108%, rgba(139, 92, 246, 0.13), transparent 60%),
    radial-gradient(900px 480px at 2% 106%, rgba(34, 211, 238, 0.10), transparent 58%);
}
#screen-big .dash::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.02), transparent 8%, transparent 92%, rgba(56, 189, 248, 0.04));
}
/* 背景纹理 */
#screen-big .bg-grid {
  position: absolute; inset: 0; pointer-events: none; opacity: 0.5;
  background-image:
    linear-gradient(rgba(90, 160, 255, 0.05) 1px, transparent 1px),
    linear-gradient(90deg, rgba(90, 160, 255, 0.05) 1px, transparent 1px);
  background-size: 56px 56px;
  -webkit-mask-image: radial-gradient(1200px 700px at 50% 30%, #000 20%, transparent 78%);
  mask-image: radial-gradient(1200px 700px at 50% 30%, #000 20%, transparent 78%);
}
#screen-big .bg-dots {
  position: absolute; inset: 0; pointer-events: none; opacity: 0.6;
  background-image: radial-gradient(rgba(125, 211, 252, 0.5) 1px, transparent 1.4px);
  background-size: 44px 44px;
  -webkit-mask-image: radial-gradient(900px 600px at 16% 0%, #000 8%, transparent 60%), radial-gradient(900px 600px at 90% 100%, #000 8%, transparent 60%);
  mask-image: radial-gradient(900px 600px at 16% 0%, #000 8%, transparent 60%), radial-gradient(900px 600px at 90% 100%, #000 8%, transparent 60%);
}
.bg-glow { position: absolute; border-radius: 50%; filter: blur(90px); pointer-events: none; opacity: 0.5; }
.bg-glow.g1 { width: 620px; height: 620px; left: -180px; top: 260px; background: rgba(37, 99, 235, 0.16); }
.bg-glow.g2 { width: 700px; height: 700px; right: -240px; top: 340px; background: rgba(124, 58, 237, 0.13); }
.bg-glow.g3 { width: 520px; height: 520px; left: 42%; bottom: -280px; background: rgba(34, 211, 238, 0.10); }

/* ---------------- 顶部 ---------------- */
#screen-big .hdr {
  position: relative; z-index: 3;
  height: 88px;
  display: flex; align-items: center;
  padding: 0 22px;
  background: linear-gradient(180deg, rgba(6, 20, 46, 0.92), rgba(4, 14, 34, 0.35));
  border-bottom: 1px solid rgba(56, 189, 248, 0.22);
}
#screen-big .hdr::before, #screen-big .hdr::after {
  content: ''; position: absolute; left: 0; right: 0; height: 1px;
  background: linear-gradient(90deg, transparent, rgba(34, 211, 238, 0.5), transparent);
}
.hdr::before { top: -1px; }
.hdr::after { bottom: -2px; opacity: 0.7; }
.hdr-side { display: flex; align-items: center; gap: 8px; min-width: 0; }
.hdr-side.left { flex: 1 1 440px; gap: 8px; }
.hdr-side.right { flex: 1 1 420px; justify-content: flex-end; gap: 8px; }
#screen-big .hdr-center {
  flex: 0 0 900px; text-align: center; position: relative;
}
#screen-big .hdr-center h1 {
  margin: 0; font-size: 32px; font-weight: 800; letter-spacing: 2px; line-height: 1.2;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  background: linear-gradient(90deg, #7dd3fc 0%, #ffffff 35%, #a5b4fc 65%, #67e8f9 100%);
  -webkit-background-clip: text; background-clip: text; color: transparent;
  filter: drop-shadow(0 0 14px rgba(56, 189, 248, 0.35));
  font-family: 'PingFang SC', 'Microsoft YaHei', sans-serif;
}
#screen-big .hdr-sub {
  margin-top: 4px; font-size: 17px; font-weight: 400; letter-spacing: 2px; color: #93b8e8;
  display: flex; align-items: center; justify-content: center; gap: 8px; white-space: nowrap;
}
.hdr-center .wings { top: 34px; }
.wings { position: absolute; left: -34px; top: 34px; width: 300px; display: flex; align-items: center; gap: 10px; }
.wings i { height: 1px; flex: 1; background: linear-gradient(90deg, transparent, rgba(34, 211, 238, 0.8)); }
.wings i:nth-child(2) { height: 3px; width: 8px; flex: 0 0 8px; background: #22d3ee; transform: rotate(45deg); box-shadow: 0 0 8px #22d3ee; }
.wings.r { left: auto; right: -34px; flex-direction: row-reverse; }
.wings.r i { background: linear-gradient(270deg, transparent, rgba(34, 211, 238, 0.8)); }
.dot-live { width: 8px; height: 8px; border-radius: 50%; background: #34d399; box-shadow: 0 0 10px #34d399; animation: pulseD 1.6s infinite; }
.pulse-dot { display: inline-block; width: 7px; height: 7px; border-radius: 50%; background: #fb7185; box-shadow: 0 0 8px #fb7185; animation: pulseD 1.2s infinite; }
.pulse-dot.red { background: #fb7185; }
@keyframes pulseD { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: 0.35; transform: scale(0.7); } }
.hdr-chip {
  display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: #8fd8b0;
  border: 1px solid rgba(52, 211, 153, 0.35); background: rgba(52, 211, 153, 0.08);
  border-radius: 999px; padding: 3px 12px; letter-spacing: 1px;
}
.hdr-chip i { width: 6px; height: 6px; border-radius: 50%; background: #34d399; box-shadow: 0 0 8px #34d399; }
#screen-big .mini-btn {
  border: 1px solid rgba(56, 189, 248, 0.4); color: #9fd4ff; background: rgba(56, 189, 248, 0.08);
  border-radius: 6px; font-size: 12px; padding: 3px 10px; cursor: pointer; letter-spacing: 1px;
  transition: all .2s;
}
.mini-btn:hover { background: rgba(56, 189, 248, 0.22); color: #fff; }
.mini-btn.on { border-color: rgba(52, 211, 153, 0.6); color: #7df0b4; background: rgba(52, 211, 153, 0.12); box-shadow: 0 0 12px rgba(52, 211, 153, 0.25); }
#screen-big .clock {
  font-family: Consolas, 'Courier New', monospace; font-size: 15px; color: #bfe3ff;
  background: rgba(8, 22, 48, 0.7); border: 1px solid rgba(56, 189, 248, 0.22); border-radius: 8px;
  padding: 5px 14px; letter-spacing: 1px; text-shadow: 0 0 10px rgba(56, 189, 248, 0.4);
}
.sc-sel { width: 176px; }
#screen-big .sc-chip {
  font-size: 12px; color: #bfe3ff; background: rgba(56, 189, 248, 0.14);
  border: 1px solid rgba(56, 189, 248, 0.35); border-radius: 999px; padding: 2px 12px;
  max-width: 240px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* ---------------- 三列主体 ---------------- */
.cols { flex: 1; display: flex; gap: 20px; padding: 16px 22px 10px; min-height: 0; }
.col { display: flex; flex-direction: column; gap: 16px; min-width: 0; min-height: 0; }
.col.left { flex: 0 0 412px; }
.col.mid { flex: 1; }
.col.right { flex: 0 0 412px; }
/* 右列等高分配：四个区按内容权重分配高度，防裁剪（右下 TOP5 / AI 列表完整可见） */
.col.right .zone { flex: 1 1 0; min-height: 0; }
.col.right .zone:nth-child(1) { flex: 1.0 1 0; }   /* SLA 仪表 */
.col.right .zone:nth-child(2) { flex: 1.42 1 0; }  /* AI 知识库（列表页需显示 5 行） */
.col.right .zone:nth-child(3) { flex: 0.98 1 0; }
.col.right .zone:nth-child(4) { flex: 1.1 1 0; }

/* 斜切角分区（避免传统方框卡片感） */
#screen-big .zone {
  position: relative;
  display: flex; flex-direction: column;
  background: linear-gradient(135deg, rgba(16, 38, 78, 0.5), rgba(6, 16, 38, 0.42));
  clip-path: polygon(0 0, calc(100% - 16px) 0, 100% 16px, 100% 100%, 16px 100%, 0 calc(100% - 16px));
  padding: 12px 16px 10px;
  transition: box-shadow .6s ease, transform .6s ease;
}
#screen-big .zone::before {
  content: ''; position: absolute; left: 16px; right: 16px; top: 0; height: 1px;
  background: linear-gradient(90deg, rgba(34, 211, 238, 0.55), rgba(56, 189, 248, 0.06) 55%, transparent);
}
#screen-big .zone::after {
  content: ''; position: absolute; left: 0; top: 0; width: 100%; height: 100%; pointer-events: none;
  background: linear-gradient(200deg, rgba(125, 211, 252, 0.05), transparent 40%);
}
#screen-big .zone.focus {
  box-shadow: 0 0 34px rgba(34, 211, 238, 0.22), inset 0 0 24px rgba(34, 211, 238, 0.05);
  outline: 1px solid rgba(34, 211, 238, 0.5); outline-offset: -1px;
  transform: translateY(-1px);
}
#screen-big .zt {
  display: flex; align-items: center; gap: 8px; margin-bottom: 8px;
  font-size: 15px; font-weight: 700; letter-spacing: 2px; color: #dff3ff;
}
#screen-big .zt i {
  width: 5px; height: 15px; background: linear-gradient(180deg, #22d3ee, #6366f1);
  clip-path: polygon(0 0, 100% 20%, 100% 80%, 0 100%);
  box-shadow: 0 0 8px rgba(34, 211, 238, 0.6);
}
.zt-r { margin-left: auto; font-size: 11px; font-weight: 400; letter-spacing: 1px; color: #7fa8dd; }
.zt-r.right { margin-left: 8px; }
.zt-r.danger { color: #fb7185; }
.zt-r i { margin-right: 4px; }
.lg-leg { display: inline-flex; align-items: center; gap: 5px; font-size: 11px; font-weight: 400; color: #8fa8cc; margin-left: 12px; letter-spacing: 1px; }
.lg-leg i { width: 14px; height: 4px; border-radius: 2px; box-shadow: 0 0 6px currentColor; }
.empty-tip { color: #5f7ea8; font-size: 12px; letter-spacing: 1px; padding: 10px 0; }

/* L1 态势环 */
.lv-row { display: flex; align-items: center; gap: 18px; flex: 1; }
.ring { border-radius: 50%; -webkit-mask: radial-gradient(farthest-side, transparent 60%, #000 61%); mask: radial-gradient(farthest-side, transparent 60%, #000 61%); }
/* 态势环：立体分割圆饼（conic 段缝 + 3D 受光：顶弧镜面 / 底弧暗部 / 内孔侧壁 / 外缘描边 + 悬浮投影） */
#screen-big .ring.big {
  position: relative; width: 152px; height: 152px; flex: 0 0 152px;
  filter: drop-shadow(0 8px 14px rgba(1, 7, 22, 0.62)) drop-shadow(0 0 16px rgba(56, 189, 248, 0.2));
}
#screen-big .ring.big::before {
  content: ''; position: absolute; inset: 0; border-radius: 50%; pointer-events: none; z-index: 3;
  background:
    radial-gradient(circle 32px at 76px 20px, rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0) 100%),
    radial-gradient(circle 52px at 76px 140px, rgba(2, 7, 24, 0.55), rgba(2, 7, 24, 0) 100%),
    radial-gradient(circle 58px at 76px 76px, rgba(3, 8, 26, 0.5) 47px, rgba(3, 8, 26, 0) 53px),
    radial-gradient(circle 78px at 76px 76px, transparent 72.5px, rgba(255, 255, 255, 0.16) 75px, transparent 77.5px);
  -webkit-mask: radial-gradient(farthest-side, transparent 56%, #000 63%);
  mask: radial-gradient(farthest-side, transparent 56%, #000 63%);
}
.ring.mid { position: relative; width: 92px; height: 92px; }
/* 环上旋转扫描弧（让分布/SLA 指标“活”起来） */
#screen-big .ring-sweep {
  position: absolute; inset: 0; border-radius: 50%; pointer-events: none; opacity: 0.9;
  background: conic-gradient(from 0deg, transparent 0deg 250deg, rgba(125, 211, 252, 0.22) 320deg, rgba(255, 255, 255, 0.5) 350deg, transparent 360deg);
  -webkit-mask: radial-gradient(farthest-side, transparent 58%, #000 60%);
  mask: radial-gradient(farthest-side, transparent 58%, #000 60%);
  animation: rotSweep 4.2s linear infinite;
}
.ring.big .ring-sweep { animation-duration: 3.6s; }
@keyframes rotSweep { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
.ring-in {
  position: absolute; inset: 0; z-index: 2; border-radius: 50%; display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  background: radial-gradient(circle, rgba(6, 18, 42, 0.6), rgba(6, 18, 42, 0.0) 70%);
}
.ring-in b { font-size: 30px; font-weight: 800; color: #eaf6ff; font-family: Consolas, monospace; text-shadow: 0 0 14px rgba(56, 189, 248, 0.6); }
.ring-in b em { font-size: 15px; font-style: normal; }
.ring-in em { font-size: 11px; color: #8fa8cc; font-style: normal; letter-spacing: 1px; margin-top: 2px; }
.ring-in i { font-size: 11px; color: #bcd7f5; font-style: normal; letter-spacing: 1px; margin-top: 2px; }
.orbit { position: absolute; inset: -6px; border: 1px dashed rgba(56, 189, 248, 0.3); border-radius: 50%; animation: rot 24s linear infinite; }
.orbit.o2 { inset: 10px; border-style: solid; border-color: rgba(56, 189, 248, 0.10); animation-duration: 40s; animation-direction: reverse; }
.orbit.o1::before { content: ''; position: absolute; left: -3px; top: 50%; width: 6px; height: 6px; border-radius: 50%; background: #22d3ee; box-shadow: 0 0 10px #22d3ee; }
@keyframes rot { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
.lv-stats { flex: 1; display: grid; grid-template-columns: 1fr 1fr; gap: 10px 8px; }
.lv-b {
  background: linear-gradient(180deg, rgba(18, 44, 86, 0.55), rgba(8, 20, 46, 0.5));
  border-left: 2px solid rgba(56, 189, 248, 0.4);
  padding: 8px 10px; transition: all .2s; text-align: left;
}
.lv-b:hover { background: rgba(30, 64, 120, 0.5); transform: translateY(-1px); }
.lv-b b { display: block; font-size: 24px; font-weight: 800; font-family: Consolas, monospace; }
.lv-b span { font-size: 11px; color: #8fa8cc; letter-spacing: 1px; }
.c-cyan { color: #67e8f9; text-shadow: 0 0 12px rgba(103, 232, 249, 0.5); }
.c-ok { color: #6ee7b7; text-shadow: 0 0 12px rgba(110, 231, 183, 0.5); }
.c-amber { color: #fcd34d; text-shadow: 0 0 12px rgba(252, 211, 77, 0.5); }
.c-sky { color: #93c5fd; text-shadow: 0 0 12px rgba(147, 197, 253, 0.5); }
.c-red { color: #fb7185; text-shadow: 0 0 12px rgba(251, 113, 133, 0.5); }
/* 三态图例：一行三个标签（放大、不换行） */
.mini-legend { display: flex; gap: 8px; padding-top: 8px; }
#screen-big .mlg {
  flex: 1; display: inline-flex; align-items: center; justify-content: center; gap: 5px;
  font-size: 13px; color: #cfe3ff; white-space: nowrap;
  background: linear-gradient(180deg, rgba(17, 40, 82, 0.4), rgba(8, 18, 42, 0.3));
  border: 1px solid rgba(56, 130, 230, 0.22); border-radius: 5px; padding: 3px 6px; letter-spacing: 1px;
}
.mlg i { width: 9px; height: 9px; border-radius: 2px; transform: skewX(-12deg); box-shadow: 0 0 6px currentColor; }
.mlg b { font-size: 15px; font-family: Consolas, monospace; margin-left: 1px; }

/* L2 构成段条 */
.stack-bar { display: flex; height: 14px; border-radius: 3px; overflow: hidden; background: rgba(30, 58, 110, 0.4); }
.stack-bar .stack-seg { height: 100%; min-width: 2px; transition: flex .8s; box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.25); }
.stack-bar.thin { height: 8px; border-radius: 4px; }
.stack-lg { display: flex; flex-wrap: wrap; gap: 4px 16px; margin: 7px 0 4px; }
.slg { display: inline-flex; align-items: center; gap: 5px; font-size: 11px; color: #9fc0ec; }
.slg i { width: 9px; height: 9px; border-radius: 2px; transform: skewX(-14deg); box-shadow: 0 0 6px currentColor; }
.mode-row { display: flex; gap: 8px; margin-top: 2px; }
#screen-big .mode-chip {
  display: inline-flex; align-items: center; gap: 5px; font-size: 11px; color: #bcd7f5;
  border-radius: 5px; padding: 3px 9px; letter-spacing: 1px;
}
.mode-chip i { width: 6px; height: 6px; border-radius: 50%; }
.mode-chip b { font-size: 13px; font-family: Consolas, monospace; }
.mode-chip.site { background: rgba(34, 211, 238, 0.1); border: 1px solid rgba(34, 211, 238, 0.35); } .mode-chip.site i { background: #22d3ee; }
.mode-chip.remo { background: rgba(139, 92, 246, 0.12); border: 1px solid rgba(139, 92, 246, 0.35); } .mode-chip.remo i { background: #a78bfa; }
.mode-chip.none { background: rgba(100, 116, 139, 0.12); border: 1px solid rgba(100, 116, 139, 0.3); } .mode-chip.none i { background: #94a3b8; }

/* L3 驻场 */
.oc-list { flex: 1; overflow: hidden; display: flex; flex-direction: column; gap: 5px; }
#screen-big .oc-row {
  display: flex; align-items: center; gap: 8px; padding: 5px 8px;
  background: linear-gradient(90deg, rgba(20, 48, 92, 0.35), transparent);
  border-left: 2px solid rgba(34, 211, 238, 0.3);
}
#screen-big .oc-avatar {
  width: 24px; height: 24px; flex: 0 0 24px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: linear-gradient(135deg, #1e40af, #7c3aed); color: #fff; font-size: 12px;
  box-shadow: 0 0 8px rgba(99, 102, 241, 0.5);
}
.oc-name { font-size: 13px; color: #e0f0ff; width: 66px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.oc-proj { flex: 1; font-size: 11px; color: #8fa8cc; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.oc-slot { font-size: 10px; padding: 1px 2px; letter-spacing: 1px; }
.oc-slot.all { background: transparent; color: #6ee7b7; }
.oc-slot.half { background: transparent; color: #93c5fd; }
.oc-conf { font-size: 10px; color: #fecdd3; background: rgba(251, 113, 133, 0.18); border: 1px solid rgba(251, 113, 133, 0.5); border-radius: 3px; padding: 1px 6px; animation: warnBlink 1.4s infinite; }
/* V1.73.40.94 未来安排角标 */
.oc-up { font-size: 10px; color: #fcd34d; background: rgba(251, 191, 36, 0.14); border: 1px solid rgba(251, 191, 36, 0.42); border-radius: 3px; padding: 1px 6px; }
/* V1.73.40.95 顶班班次角标 */
.oc-relief { font-size: 10px; color: #b45309; background: rgba(251, 191, 36, 0.22); border: 1px solid rgba(217, 119, 6, 0.45); border-radius: 3px; padding: 1px 6px; }
@keyframes warnBlink { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } }

/* L4 资源对象 */
.res-3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 10px; }
.res-item {
  text-align: center; padding: 8px 4px 6px; position: relative;
  background: linear-gradient(180deg, rgba(17, 40, 80, 0.5), rgba(8, 18, 42, 0.4));
  clip-path: polygon(8px 0, 100% 0, 100% calc(100% - 8px), calc(100% - 8px) 100%, 0 100%, 0 8px);
  transition: all .2s;
}
.res-item:hover { transform: translateY(-2px); background: rgba(24, 54, 106, 0.6); }
#screen-big .res-ico {
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; border-radius: 7px; margin-bottom: 4px;
  font-size: 14px; font-weight: 800; color: #fff;
}
.res-ico.server { background: linear-gradient(135deg, #0891b2, #2563eb); box-shadow: 0 0 10px rgba(37, 99, 235, 0.5); }
.res-ico.hd { background: linear-gradient(135deg, #7c3aed, #db2777); box-shadow: 0 0 10px rgba(139, 92, 246, 0.5); }
.res-ico.kb { background: linear-gradient(135deg, #059669, #65a30d); box-shadow: 0 0 10px rgba(16, 185, 129, 0.5); }
.res-item b { display: block; font-size: 22px; font-weight: 800; color: #eaf6ff; font-family: Consolas, monospace; }
.res-item em { font-style: normal; font-size: 11px; color: #8fa8cc; letter-spacing: 1px; }
.as-line { display: flex; align-items: center; gap: 8px; margin-top: 9px; }
.as-lb, .ci-lb { font-size: 11px; color: #7fa8dd; letter-spacing: 1px; flex: 0 0 auto; }
.as-line .stack-bar { flex: 1; }
.as-lg { display: inline-flex; gap: 8px; font-size: 10px; color: #8fa8cc; white-space: nowrap; }
.as-lg i { width: 7px; height: 7px; border-radius: 2px; display: inline-block; margin-right: 3px; transform: skewX(-14deg); }
.ci-chips { display: flex; align-items: center; flex-wrap: wrap; gap: 5px; margin-top: 8px; }
#screen-big .ci-chip {
  font-size: 10px; color: var(--hc); border: 1px solid color-mix(in srgb, var(--hc) 45%, transparent);
  background: color-mix(in srgb, var(--hc) 12%, transparent);
  border-radius: 3px; padding: 1px 6px; letter-spacing: 0.5px;
}
/* 项目合同周期统计块 */
.proj-blk { margin-top: 7px; }
.proj-line { display: flex; gap: 4px; }
#screen-big .proj-line .pl {
  flex: 1; display: flex; align-items: center; justify-content: center; gap: 4px;
  background: linear-gradient(180deg, rgba(17, 40, 80, 0.45), rgba(8, 18, 42, 0.3));
  border-radius: 4px; padding: 2px 2px; min-width: 0;
}
.proj-line .pl b { font-size: 14px; font-family: Consolas, monospace; }
.proj-line .pl i { font-style: normal; font-size: 10px; color: #8fa8cc; letter-spacing: 0; white-space: nowrap; }
.c-slate { color: #cbd5e1; text-shadow: 0 0 10px rgba(203, 213, 225, .4); }
.proj-rail { display: flex; align-items: flex-end; gap: 8px; margin-top: 5px; }
.rail-t { font-size: 10px; color: #7fa8dd; letter-spacing: 0.5px; flex: 0 0 auto; white-space: nowrap; }
.rail-t em { font-style: normal; color: #fcd34d; margin-left: 2px; }
.rail-cells { flex: 1; display: flex; align-items: flex-end; gap: 3px; height: 22px; padding: 0 1px; }
#screen-big .rc {
  flex: 1; display: inline-flex; align-items: flex-end; justify-content: center; min-width: 2px;
  border-radius: 2px 2px 0 0; font-size: 8px; color: #dbeafe; font-style: normal; line-height: 1;
  padding-top: 1px; transition: all .3s;
}
.rc:hover { filter: brightness(1.25); }
.rc-dim { background: rgba(60, 90, 140, 0.2); }
.rc-red { background: linear-gradient(180deg, #fb7185, #e11d48); box-shadow: 0 0 6px rgba(251, 113, 133, 0.5); }
.rc-amber { background: linear-gradient(180deg, #fbbf24, #d97706); box-shadow: 0 0 6px rgba(251, 191, 36, 0.4); }
.rc-cyan { background: linear-gradient(180deg, #22d3ee, #0891b2); box-shadow: 0 0 6px rgba(34, 211, 238, 0.35); }
.rc-slate { background: linear-gradient(180deg, #94a3b8, #475569); }
.proj-strip b { font-family: Consolas, monospace; font-size: 13px; margin: 0 2px; }

/* C1 KPI 带 */
#screen-big .kpi-strip {
  position: relative; z-index: 2;
  flex: 0 0 auto;
  display: flex; align-items: stretch;
  background: linear-gradient(180deg, rgba(14, 34, 70, 0.5), rgba(7, 17, 40, 0.4));
  clip-path: polygon(0 0, calc(100% - 14px) 0, 100% 14px, 100% 100%, 14px 100%, 0 calc(100% - 14px));
  padding: 12px 4px;
}
.k1 { flex: 1; text-align: center; position: relative; padding: 2px 2px; transition: all .2s; }
.k1:hover { transform: translateY(-2px); }
#screen-big .k1 .num {
  display: block; font-size: 32px; font-weight: 800; line-height: 1.05;
  font-family: Consolas, 'Courier New', monospace;
}
.num.cyan { color: #67e8f9; text-shadow: 0 0 16px rgba(103, 232, 249, 0.55); }
.num.amber { color: #fcd34d; text-shadow: 0 0 16px rgba(252, 211, 77, 0.5); }
.num.sky { color: #93c5fd; text-shadow: 0 0 16px rgba(147, 197, 253, 0.5); }
.num.ok { color: #6ee7b7; text-shadow: 0 0 16px rgba(110, 231, 183, 0.5); }
.num.red { color: #fb7185; text-shadow: 0 0 16px rgba(251, 113, 133, 0.6); }
.num.lime { color: #bef264; text-shadow: 0 0 16px rgba(190, 242, 100, 0.5); }
.num.vio { color: #c4b5fd; text-shadow: 0 0 16px rgba(167, 139, 250, 0.5); }
.num.pink { color: #f9a8d4; text-shadow: 0 0 16px rgba(249, 168, 212, 0.5); }
.num.amber2 { color: #fdba74; text-shadow: 0 0 16px rgba(251, 146, 60, 0.5); }
.num .pct { font-size: 16px; }
.k1 > em { display: block; font-style: normal; font-size: 11px; color: #9fc0ec; letter-spacing: 1px; margin-top: 4px; }
.k1 .sub-line { display: block; font-size: 9px; color: #5f7ea8; letter-spacing: 2px; margin-top: 2px; font-style: normal; }
.k1 .sub-line.warn { color: #fb7185; }
#screen-big .dv {
  width: 1px; align-self: center; height: 60%;
  background: linear-gradient(180deg, transparent, rgba(56, 189, 248, 0.4), transparent);
  flex: 0 0 1px;
}

/* C2 趋势主图 */
.zone.hero { flex: 0 0 auto; height: 330px; }
.trend-body { position: relative; flex: 1; min-height: 0; overflow: hidden; }
.trend-svg { position: absolute; inset: 0; width: 100%; height: calc(100% - 18px); }
/* 扫描细线：1px 极细淡线自左向右扫过图表（纵向渐隐融入背景） */
#screen-big .scanline {
  position: absolute; left: -1px; top: 0; bottom: 0; width: 1px; pointer-events: none;
  background: linear-gradient(180deg, rgba(125, 211, 252, 0), rgba(255, 255, 255, 0.24) 16%, rgba(174, 242, 255, 0.38) 50%, rgba(255, 255, 255, 0.24) 84%, rgba(125, 211, 252, 0));
  box-shadow: 0 0 3px rgba(34, 211, 238, 0.22), 0 0 9px rgba(34, 211, 238, 0.07);
  animation: scanX 4.2s linear infinite;
}
@keyframes scanX { 0% { transform: translateX(0); } 100% { transform: translateX(1102px); } }
.pulse-pt { animation: ptPulse 2s ease-in-out infinite; transform-origin: center; }
@keyframes ptPulse { 0%, 100% { opacity: 0.5; } 50% { opacity: 1; } }
.trend-x { position: relative; height: 16px; margin-top: 4px; font-size: 10px; color: #7e97bd; }
.trend-x span { position: absolute; transform: translateX(-50%); }
.hero-foot {
  display: flex; gap: 22px; align-items: center; padding-top: 4px;
  font-size: 11px; color: #8fa8cc; letter-spacing: 1px;
}
.hero-foot .right { margin-left: auto; }
.hero-foot .ico { font-style: normal; margin-right: 4px; }
.ico.g { color: #34d399; } .ico.b { color: #22d3ee; } .ico.y { color: #fbbf24; }

/* C3 动态轮播 */
.zone.feed { flex: 1; min-height: 0; }
.feed-mask { flex: 1; overflow: hidden; position: relative; min-height: 0; }
.feed-mask::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 26px;
  background: linear-gradient(180deg, transparent, #05142e);
  pointer-events: none;
}
.feed-track { animation: feedUp 14s linear infinite; }
.feed-track:hover { animation-play-state: paused; }
@keyframes feedUp { 0% { transform: translateY(0); } 100% { transform: translateY(-50%); } }
.feed-line {
  display: flex; align-items: center; gap: 10px; padding: 6px 4px;
  border-bottom: 1px dashed rgba(56, 189, 248, 0.12); font-size: 12px;
}
.f-time { color: #5f7ea8; font-family: Consolas, monospace; flex: 0 0 76px; }
.f-no { font-family: Consolas, monospace; color: #22d3ee; flex: 0 0 96px; }
.f-no.hi { color: #fb7185; }
.f-no.warn { color: #fcd34d; }
/* V1.73.40.94 驻场行：琥珀色标识 + 行底微亮，与工单行动态区分 */
.f-no.oc { color: #fbbf24; letter-spacing: 1px; }
/* V1.73.40.102 顶班滚动行=绿色系（与驻场琥珀区分） */
.f-no.ocr { color: #34d399; letter-spacing: 1px; }
.f-tag.ocr { color: #6ee7b7; border-color: rgba(52, 211, 153, 0.4); }
.feed-line.ocr { background: linear-gradient(90deg, rgba(52, 211, 153, 0.09), transparent); }
.f-tag.oc { color: #fcd34d; border-color: rgba(251, 191, 36, 0.35); }
.feed-line.oc { background: linear-gradient(90deg, rgba(251, 191, 36, 0.07), transparent); }
.f-title { flex: 1; color: #bcd7f5; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.f-tag { flex: 0 0 auto; font-size: 10px; color: #7fa8dd; border: 1px solid rgba(56, 189, 248, 0.25); border-radius: 3px; padding: 0 5px; }
.live-tag { display: inline-flex; align-items: center; gap: 5px; font-size: 10px; color: #fb7185; margin-left: 10px; letter-spacing: 1px; }

/* R1 SLA 环 */
/* R1 SLA 摩托车仪表风格半圆表盘 */
.gauge-row { display: flex; justify-content: space-between; gap: 4px; padding: 0 2px; }
.gauge { flex: 1; display: flex; flex-direction: column; align-items: center; min-width: 0; }
.gauge-svg { width: 100%; height: auto; display: block; overflow: visible; }
.g-scale { font-size: 8px; fill: #6e8cb8; font-family: Consolas, monospace; }
.gauge-meta { text-align: center; margin-top: -6px; }
.gauge-meta b { font-size: 19px; font-weight: 800; font-family: Consolas, monospace; text-shadow: 0 0 10px rgba(120, 200, 255, 0.4); }
.gauge-meta b em { font-size: 10px; font-style: normal; opacity: 0.8; }
.gauge-meta i { display: block; font-style: normal; font-size: 10px; color: #9fc0ec; letter-spacing: 1px; }
.gauge-meta span { font-size: 9px; color: #5f7ea8; font-family: Consolas, monospace; }
.sla-note { font-size: 10px; color: #5f7ea8; letter-spacing: 1px; margin-top: 4px; text-align: center; }

/* R2 重点工单轮播 */
.focus-wrap { flex: 1; overflow: hidden; position: relative; min-height: 0; }
.focus-track { transition: transform .6s cubic-bezier(.4, 0, .2, 1); height: 100%; }
.focus-page { height: 100%; display: flex; flex-direction: column; gap: 6px; }
#screen-big .focus-row {
  display: flex; align-items: center; gap: 8px; padding: 6px 8px; cursor: pointer;
  background: linear-gradient(90deg, rgba(20, 44, 88, 0.4), transparent); border-radius: 4px;
  transition: all .2s;
}
.focus-row:hover { background: rgba(30, 64, 120, 0.45); }
.fg-dot { width: 7px; height: 7px; border-radius: 50%; flex: 0 0 auto; box-shadow: 0 0 8px currentColor; }
.fg-no { font-family: Consolas, monospace; font-size: 11px; color: #93c5fd; flex: 0 0 92px; }
.fg-title { flex: 1; font-size: 12px; color: #dbeafe; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fg-prio { font-size: 10px; border-radius: 3px; padding: 0 5px; }
.fg-prio.P1 { background: rgba(251, 113, 133, 0.2); color: #fda4af; border: 1px solid rgba(251, 113, 133, 0.5); }
.fg-prio.P2 { background: rgba(251, 146, 60, 0.18); color: #fdba74; border: 1px solid rgba(251, 146, 60, 0.45); }
.fg-prio.P3, .fg-prio.P4, .fg-prio.P5 { background: rgba(56, 189, 248, 0.15); color: #93c5fd; border: 1px solid rgba(56, 189, 248, 0.35); }
.fg-meta { font-size: 10px; color: #7fa8dd; flex: 0 0 auto; }

/* R2 AI 实时知识库 */
#screen-big .ai-live {
  display: inline-flex; align-items: center; gap: 5px; font-size: 11px; font-weight: 400;
  color: #6ee7b7; border: 1px solid rgba(52, 211, 153, 0.4); background: rgba(52, 211, 153, 0.1);
  border-radius: 999px; padding: 1px 10px; margin-left: 10px; letter-spacing: 0.5px; max-width: 300px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ai-live i { width: 6px; height: 6px; border-radius: 50%; background: #34d399; box-shadow: 0 0 8px #34d399; flex: 0 0 auto; animation: pulseD 1.6s infinite; }
.ai-live.off { color: #fda4af; border-color: rgba(251, 113, 133, 0.4); background: rgba(251, 113, 133, 0.1); }
.ai-live.off i { background: #fb7185; box-shadow: none; animation: none; }
.ai-more { color: #7dd3fc !important; font-size: 11px; }
.ai-kpis { display: grid; grid-template-columns: 1fr 1fr 1fr 1fr; gap: 8px; margin-bottom: 8px; }
#screen-big .ai-k {
  text-align: center; padding: 5px 2px 4px;
  background: linear-gradient(180deg, rgba(17, 40, 80, 0.5), rgba(8, 18, 42, 0.35));
  border-left: 2px solid rgba(34, 211, 238, 0.4); border-radius: 3px;
  transition: all .2s;
}
.ai-k:hover { background: rgba(24, 54, 106, 0.6); transform: translateY(-1px); }
.ai-k b { display: block; font-size: 17px; font-weight: 800; font-family: Consolas, monospace; line-height: 1.1; }
.ai-k b em { font-size: 9px; font-style: normal; opacity: .8; }
.ai-k i { display: block; font-style: normal; font-size: 10px; color: #8fa8cc; letter-spacing: 1px; margin-top: 2px; }
.ai-k b.cyan { color: #67e8f9; text-shadow: 0 0 10px rgba(103, 232, 249, .5); }
.ai-k b.sky { color: #93c5fd; text-shadow: 0 0 10px rgba(147, 197, 253, .5); }
.ai-k b.ok { color: #6ee7b7; text-shadow: 0 0 10px rgba(110, 231, 183, .5); }
.ai-k b.vio { color: #c4b5fd; text-shadow: 0 0 10px rgba(196, 181, 253, .5); }
.ai-wrap { flex: 1; min-height: 0; }
#screen-big .ai-row {
  display: flex; align-items: center; gap: 7px; padding: 2px 8px; margin-bottom: 3px;
  background: linear-gradient(90deg, rgba(20, 44, 88, 0.4), transparent); border-radius: 4px;
  transition: all .2s;
}
.ai-row:hover { background: rgba(30, 64, 120, 0.45); }
.ai-title { flex: 1; font-size: 12px; color: #dbeafe; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#screen-big .ai-tag {
  font-size: 10px; flex: 0 0 auto; color: var(--c); border: 1px solid color-mix(in srgb, var(--c) 40%, transparent);
  background: color-mix(in srgb, var(--c) 12%, transparent); border-radius: 3px; padding: 0 5px;
}
.ai-val { flex: 0 0 auto; font-size: 10px; color: #7fa8dd; font-family: Consolas, monospace; white-space: nowrap; }

/* R3 工程师负载 */
.eng-bars, .cli-bars { flex: 1; display: flex; flex-direction: column; gap: 6px; min-height: 0; }
.eng-bar, .cli-bar { display: flex; align-items: center; gap: 8px; }
#screen-big .rank {
  width: 18px; height: 18px; flex: 0 0 18px; display: inline-flex; align-items: center; justify-content: center;
  font-size: 11px; color: #94a3b8; background: rgba(60, 90, 140, 0.3); border-radius: 3px;
  font-family: Consolas, monospace;
}
.rank.top { color: #1e293b; background: linear-gradient(135deg, #fbbf24, #f59e0b); box-shadow: 0 0 8px rgba(251, 191, 36, 0.4); }
.e-name { width: 68px; font-size: 12px; color: #dbeafe; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.e-tags { display: inline-flex; gap: 4px; flex: 0 0 auto; }
.e-tags em { font-style: normal; font-size: 10px; border-radius: 3px; padding: 0 5px; }
.e-tags em.do { background: rgba(34, 211, 238, 0.14); color: #67e8f9; }
.e-tags em.td { background: rgba(251, 191, 36, 0.14); color: #fcd34d; }
.e-tags em.oc { background: rgba(167, 139, 250, 0.16); color: #c4b5fd; }
.e-track, .c-track { flex: 1; height: 7px; border-radius: 4px; background: rgba(30, 58, 110, 0.4); overflow: hidden; }
.e-fill, .c-fill { height: 100%; border-radius: 4px; transition: width .8s; }
.e-fill { background: linear-gradient(90deg, #0891b2, #22d3ee); box-shadow: 0 0 8px rgba(34, 211, 238, 0.5); }
.e-total { font-size: 13px; color: #eaf6ff; font-family: Consolas, monospace; width: 20px; text-align: right; }

/* R4 客户分布 */
.c-name { flex: 0 0 130px; font-size: 12px; color: #dbeafe; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.c-fill { background: linear-gradient(90deg, #7c3aed, #22d3ee); box-shadow: 0 0 8px rgba(139, 92, 246, 0.5); }
.c-num { font-size: 13px; color: #eaf6ff; font-family: Consolas, monospace; width: 30px; text-align: right; }

/* 轮巡指示 */
#screen-big .roam-chip {
  position: absolute; right: 26px; bottom: 62px; z-index: 20;
  font-size: 11px; letter-spacing: 1px; color: #9fd4ff;
  background: rgba(8, 22, 48, 0.85); border: 1px solid rgba(56, 189, 248, 0.4);
  padding: 3px 12px; border-radius: 999px;
  box-shadow: 0 0 14px rgba(56, 189, 248, 0.2);
}

/* 底部跑马灯 */
#screen-big .ticker {
  position: relative; z-index: 5; flex: 0 0 42px;
  display: flex; align-items: center; gap: 14px;
  margin: 4px 22px 12px;
  background: linear-gradient(90deg, rgba(10, 26, 58, 0.9), rgba(8, 20, 46, 0.7));
  border: 1px solid rgba(56, 189, 248, 0.22);
  border-radius: 6px;
  clip-path: polygon(12px 0, 100% 0, calc(100% - 12px) 100%, 0 100%);
  padding: 6px 18px 6px 22px;
  overflow: hidden;
}
#screen-big .ticker-tag {
  display: inline-flex; align-items: center; gap: 6px; color: #7dd3fc; font-size: 12px; letter-spacing: 2px; flex: 0 0 auto;
}
.ticker-track { flex: 1; overflow: hidden; }
.ticker-inner { display: inline-flex; white-space: nowrap; animation: marquee 50s linear infinite; }
.ticker:hover .ticker-inner { animation-play-state: paused; }
.ticker-item { font-size: 12px; color: #a9c2e8; margin-right: 56px; }
.ticker-item::before { content: '◆ '; color: #22d3ee; font-size: 9px; }
@keyframes marquee { from { transform: translateX(0); } to { transform: translateX(-50%); } }

/* 深色下 EP 控件微调 */
:deep(.el-select .el-input__wrapper) {
  background: rgba(8, 22, 48, 0.75); box-shadow: 0 0 0 1px rgba(56, 189, 248, 0.3) inset;
}
:deep(.el-select .el-input__inner) { color: #dbeafe; }
:deep(.el-button) { --el-button-bg-color: rgba(8, 22, 48, .7); }

/* ===== 系统打印（兜底路径：没有 Edge 时用 window.print 打 A4）——需求方 2026-09-22 =====
   打印时只留工单的 A4 卡：隐藏左侧导航 / 页眉 / 各种按钮与交互件，缩放恢复 1:1。 */
@media print {
  #nav, .top, #hdr, .hdr, .sidebar, .aim-mask { display: none !important; }
  html, body { background: #fff !important; }
  #view .a4-wrap { --tk-scale: 1 !important; zoom: 1 !important; transform: none !important; }
  #view .a4-wrap .btn, #view .a4-wrap button, #view .tk-zoom, #view .tk-zbtn { display: none !important; }
  #view .card { box-shadow: none !important; }
}

/* ============================================================================
   消息中心（需求方 2026-09-23）：① 页眉滚动字幕 ② 右下角提示栏 ③ 消息中心面板
   ============================================================================ */
/* 页眉要成为定位上下文（原规则 header.topbar 没有 position）——
   这里只**合并**一条 position，不改它的其它属性。 */
header.topbar{position:relative}
/* ① 页眉滚动字幕：**黄字 · 透明底 · 不加粗** · 从右向左滚**两遍**后自动消失 */
.hd-marq{position:absolute;left:150px;right:360px;top:0;height:100%;display:flex;align-items:center;
  overflow:hidden;pointer-events:none;z-index:2}
.hd-marq span{white-space:nowrap;font-size:13px;font-weight:400;color:#ffd400;background:transparent;
  text-shadow:0 1px 3px rgba(0,0,0,.6);will-change:transform;animation:hdmarq 18s linear 2}
@keyframes hdmarq{from{transform:translateX(100%)}to{transform:translateX(-100%)}}

/* ② 桌面右下角文字提示栏 */
.alert-toasts{position:fixed;right:18px;bottom:18px;z-index:9000;display:flex;flex-direction:column;
  gap:10px;align-items:flex-end;pointer-events:none}
.alert-toast{pointer-events:auto;position:relative;width:342px;max-width:calc(100vw - 40px);background:#fff;
  border:1px solid #d9e2ec;border-left:4px solid #f59e0b;border-radius:12px;
  box-shadow:0 12px 30px rgba(15,23,42,.20);padding:11px 36px 11px 13px;cursor:pointer;
  animation:atIn .22s ease-out}
.alert-toast:hover{border-color:#9db9dd;border-left-color:#1d4ed8;box-shadow:0 14px 34px rgba(29,78,216,.20)}
.alert-toast .at-t{font-size:13px;font-weight:700;color:#1f2d3d;margin-bottom:3px}
.alert-toast .at-b{font-size:12.5px;color:#5b6e82;line-height:1.65}
.alert-toast .at-m{font-size:11px;color:#9aa8b8;margin-top:4px}
.alert-toast .at-x{position:absolute;right:6px;top:6px;width:23px;height:23px;border-radius:7px;
  border:1px solid #d9e2ec;background:#fff;color:#64748b;font-size:13px;line-height:1;cursor:pointer;
  display:flex;align-items:center;justify-content:center;padding:0}
.alert-toast .at-x:hover{color:#dc2626;border-color:#f3b0b0;background:#fff5f5}
@keyframes atIn{from{opacity:0;transform:translateY(12px)}to{opacity:1;transform:none}}

/* 消息中心入口红点（有未读提醒时显示） */
#btn-msg{position:relative}
.msg-dot{position:absolute;top:4px;right:4px;width:7px;height:7px;border-radius:50%;background:#ef4444;
  box-shadow:0 0 0 2px #0d2137}
/* 广播开关：关掉时图标变暗，一眼看出"不播了" */
#btn-alert-voice.off{color:#7d93a8;opacity:.72}

/* ③ 消息中心面板（内容样式；外框沿用页眉浮窗 #hdr-pop）
   🔴 **宽度必须跟着容器走**：`#hdr-pop` 是固定 322px（加 .wide 是 452px）、内边距 14px，
   内容区最多 424px。面板写死宽度（曾写 440px）会**比容器还宽 → 整块内容溢出到页面外**（2026-09-23 修）。 */
.msg-wrap{width:100%;max-width:100%;box-sizing:border-box;max-height:min(70vh,540px);display:flex;flex-direction:column;min-width:0}
.msg-hd{display:flex;align-items:center;gap:8px;padding:0 0 9px;border-bottom:1px solid #e6edf5;flex:none}
.msg-hd b{font-size:13.5px;color:#1f2d3d}
.msg-hd .n{font-size:11.5px;color:#8b9aab}
.msg-hd .sp{flex:1}
.msg-bd{overflow-y:auto;overflow-x:hidden;flex:1 1 auto;min-height:0}
.msg-it{display:flex;gap:9px;padding:9px 2px;border-bottom:1px dashed #eef2f7;cursor:pointer}
/* 没有「语音播报」权限的账号：条目**点了不会出声**（会给一句红字说明）→ 不给手型，不暗示"可以点" */
.msg-it.no-voice{cursor:default}
.msg-it:hover{background:#f7faff}
.msg-it input[type=checkbox]{margin-top:3px;flex:none}
.msg-it .b{flex:1;min-width:0}
.msg-it .t{font-size:12.5px;font-weight:700;color:#24405f;margin-bottom:2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.msg-it .x{font-size:12.5px;color:#5b6e82;line-height:1.6;word-break:break-word;overflow-wrap:anywhere}
.msg-it .m{font-size:11px;color:#9aa8b8;margin-top:3px}
.msg-empty{padding:26px 12px;text-align:center;color:#9aa8b8;font-size:12.5px;line-height:1.9}
.msg-ft{display:flex;align-items:center;gap:8px;padding:9px 0 0;border-top:1px solid #e6edf5;flex:none}
.msg-ft .sp{flex:1}

/* ============================================================================
   服务日历（需求方 2026-09-23）：① 当天那一格用**蓝紫渐变框** ② 检索区姓名点选 → 条目呼吸突显
   ============================================================================ */
/* ① 当天：用**双层 box-shadow 画渐变环**（内紫外蓝）——
   不用 border-image（会把圆角吃掉），也不动 background（会盖掉节假日红底与条目底色）。 */
.oc-cell.today{box-shadow:0 0 0 2px #6366f1, 0 0 0 4px #38bdf8, 0 6px 16px rgba(56,189,248,.20)}
.oc-cell.today:hover{box-shadow:0 0 0 2px #6366f1, 0 0 0 4px #38bdf8, 0 8px 20px rgba(56,189,248,.30)}
.oc-cell.today .oc-d{background:linear-gradient(135deg,#6366f1,#38bdf8);color:#fff;
  border-radius:6px;padding:1px 7px;font-weight:600}

/* ② 检索区的姓名可点：点一下 = 本月与 TA 相关的条目全部呼吸突显，再点一下取消 */
.oc-eng-nm{cursor:pointer;border-radius:6px;padding:1px 6px;transition:.15s}
.oc-eng-nm:hover{background:rgba(99,102,241,.12)}
.oc-eng.hi .oc-eng-nm{background:linear-gradient(135deg,#6366f1,#38bdf8);color:#fff;font-weight:600}
/* 条目**呼吸色**（需求方 2026-09-23 原话：「**是条目出现呼吸色，不是条目边框**」）——
   做法 = **背景色在浅蓝紫之间脉动**，🔴 **不碰 border**：
   `.oc-chip` / `.oc-tk` 左侧那条 3px 色条（驻场深蓝 / 工单橙）是有语义的，改 border-color 会把它一起染掉。
   背景色做法也安全：`done` / `fin` 的「完工」水印是 `::before` 伪元素（z-index:-1），不受 background 影响。 */
.oc-chip.hi,.oc-tk.hi{animation:ocBreathBg 1.6s ease-in-out infinite}
@keyframes ocBreathBg{
  0%,100%{background:#c9d9fb}
  50%{background:#eef4ff}
}

/* =============================================================================
   终端管理（需求方 2026-09-24）—— H5 页面可视化配置
   左：两台手机模拟（登录界面 / 内容界面）；右：设置栏（通用元素 + 菜单功能字段）。
   手机里的一切都只是**版式示意**（不可输入），用于确认"哪一屏放哪些元素"。
   🔴 尺寸刻意写在小屏友好区间：手机 296×560，两屏 + 设置栏 330 在 1280 宽下正好一行；
      窄屏时 `flex-wrap` 会自动把设置栏折到下面就整行（不做横向滚动）。
   ============================================================================= */
.tm-bar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:11px 14px}
.tm-bar .tm-bl{font-size:var(--fs-label);font-weight:600;color:var(--muted)}
.tm-bar select{min-width:190px}
.tm-name{width:230px}
.tm-flag{margin-left:auto;font-size:12px;color:var(--amber);opacity:0;transition:opacity .15s}
.tm-flag.on{opacity:1}

.tm-wrap{display:flex;gap:16px;align-items:flex-start;margin-top:14px;flex-wrap:wrap}
/* 🔴 两台手机**按可用空间自适应放大**（需求方 2026-09-24：「左边两个界面太小了，尽量大点自适应」）：
   · 每台宽度 = 平分左侧可用宽（`.tm-pw{flex:1 1 0}`），高度由 `aspect-ratio:296/560` 自动跟随；
   · `.tm-left` 的 `max-width` 按**视口可用高**反推（保证两台并排时高度不超出视口）——
     窗口越大手机越大，窗口变矮时自动收小，不会被挤出屏幕；
   · 手机内尺寸全用 `em`（基准字号由 `.tm-screen` 的 `cqw` 给）→ 内容跟着**等比缩放**，不只是外壳变大。 */
.tm-left{display:flex;gap:clamp(14px,1.6vw,26px);flex:1 1 auto;min-width:0;flex-wrap:wrap;justify-content:center;
  max-width:calc((100vh - 236px) * 296 / 560 * 2 + clamp(14px,1.6vw,26px))}
.tm-pw{flex:1 1 0;min-width:0;display:flex;flex-direction:column;gap:8px}
.tm-cap{display:flex;align-items:baseline;justify-content:space-between;gap:8px;
  font-size:var(--fs-title);font-weight:600;color:var(--label)}
/* 内容屏标题旁的「当前菜单」标（需求方 2026-09-24：「上面内容界面旁边会显示当前是哪个菜单功能」） */
.tm-cm{margin-right:auto;padding:1px 7px;border-radius:999px;background:var(--accent-soft);color:var(--blue);
  font-size:11px;font-weight:600;white-space:nowrap}

/* ---- 手机外壳（尺寸自适应：宽 → 高 → 内容字号 三级联动）---- */
.tm-phone{position:relative;width:100%;aspect-ratio:296/560;padding:2.7%;background:#0d2137;
  border-radius:2.3em;container-type:size;
  box-shadow:0 12px 30px rgba(16,38,60,.22),inset 0 0 0 1px rgba(255,255,255,.06)}
.tm-notch{position:absolute;left:50%;top:0.92em;z-index:3;width:5.7em;height:0.38em;border-radius:0.23em;
  transform:translateX(-50%);background:rgba(255,255,255,.28);font-size:clamp(11px,4.4cqw,22px)}
/* 基准字号：手机宽 296px → 13px；用容器查询单位让**内容整体等比缩放**（宽 400 → 17.6px）。
   不支持 `cqw` 的环境该声明失效、回落继承字号，内容仍可用（只是不跟着放大）。 */
.tm-screen{display:flex;flex-direction:column;width:100%;height:100%;overflow:hidden;background:#fff;
  border-radius:1.85em;font-size:clamp(11px,4.4cqw,22px);position:relative}
.tm-sbar{flex:0 0 auto;display:flex;align-items:center;justify-content:space-between;height:1.7em;padding:0 0.92em;
  border-bottom:1px solid var(--line);background:#f6f9fc;font-size:0.77em;color:var(--muted)}
.tm-canvas{flex:1 1 auto;display:flex;flex-direction:column;gap:0.62em;overflow:auto;padding:0.92em;background:#fff}
.tm-canvas.tm-empty-hot{background:var(--accent-soft)}
.tm-ph{margin:auto;padding:1.69em 1.38em;border:1px dashed var(--line2);border-radius:0.77em;
  background:var(--soft);color:var(--muted);font-size:0.92em}

/* ---- 手机内元素 ---- */
/* ⚠️ 这一段里的尺寸**一律用 `em`**（基准 = `.tm-screen` 的 `cqw` 字号）——
   手机被拉大时内容跟着等比放大（换算基准：手机宽 296px / 基准字号 13px）。 */
.tm-el{position:relative;padding:0.15em;border:1px solid transparent;border-radius:0.62em;cursor:grab;transition:background .12s}
.tm-el:hover{border-color:var(--line2);background:var(--soft2)}
.tm-el.tm-hot{box-shadow:0 -0.15em 0 0 var(--blue)}
.tm-x{position:absolute;right:-0.46em;top:-0.46em;z-index:2;display:none;width:1.38em;height:1.38em;padding:0;
  border:1px solid var(--line2);border-radius:50%;background:#fff;color:var(--red);font-size:0.92em;line-height:1.23em;cursor:pointer}
.tm-el:hover .tm-x{display:block}
.tm-el-src{padding:0.15em 0.15em 0;font-size:0.77em;color:var(--muted);opacity:0;transition:opacity .12s}
.tm-el:hover .tm-el-src{opacity:1}
.tm-h1{padding:1.08em 0 0.46em;color:var(--navy);font-size:1.31em;font-weight:700;letter-spacing:.5px;text-align:center}
.tm-item{padding:0.31em 0}
.tm-ilab{margin-bottom:0.31em;color:var(--label);font-size:0.88em;font-weight:600}
.tm-ipt{display:flex;align-items:center;height:2.62em;padding:0 0.77em;border:1px solid var(--line2);border-radius:0.62em;
  background:#fff;font-size:0.96em;color:var(--text)}
.tm-ipt.ph{color:#a8b6c5}
.tm-rem{display:flex;justify-content:space-between;padding:0.15em 0;font-size:0.88em;color:var(--muted)}
.tm-link{color:var(--blue)}
.tm-btn{display:flex;align-items:center;justify-content:center;height:2.92em;margin-top:0.46em;border-radius:0.69em;
  background:var(--blue);color:#fff;font-size:1.04em;font-weight:600;letter-spacing:2px}
/* 🔴 顶栏（需求方 2026-09-24：「所有顶部标题栏…默认做好，不得后期设置修改」）
   ⚠️ 2026-09-27：右上角由「⋯」换成**两行入口**（关注服务号 / 联系客服）⇒ 顶栏改 **grid（1fr auto 1fr）**，
   标题**永远居中**、与两侧宽度无关（原来靠左右等宽"凑"居中，右侧一变宽标题就偏）。
   子元素仍是"左箭头 / 中标题 / 右入口"三个，只换布局方式与右侧内容。 */
.tm-nav{display:grid;grid-template-columns:1fr auto 1fr;align-items:center;gap:0.4em;
  height:2.92em;margin:-0.92em -0.92em 0.31em;padding:0 0.92em;
  background:linear-gradient(135deg,var(--navy) 0%,var(--navy3) 100%);color:#eaf2fa;font-size:1em;font-weight:600}
/* 🔴 返回箭头原来只有 **6px 宽 + opacity .85**（手机预览按 cqw 缩放后看着像"没有返回按钮"，
   需求方 2026-09-27 报障）⇒ 做成**清楚可点**：字号放大、满不透明度、给足点击热区。 */
.tm-nav .tm-back{justify-self:start;opacity:1;cursor:pointer;min-width:1.6em;text-align:center;
  padding:0.1em 0.2em;font-size:1.5em;font-weight:700;line-height:1;border-radius:0.3em}
.tm-nav .tm-back:active{background:rgba(255,255,255,.18)}
/* 「⋯」：顶栏右上角的入口（元素库里那个**可拖拽**的"顶部标题栏"样例也在用它）。
   🔴 面板内容见 `tmMoreHtml`（需求方 2026-09-27：点开后两行 —— 关注服务号 / 联系客服）。 */
/* 🔴 「⋯」**靠右边**（需求方 2026-09-27：「终端管理各页面左上角的...**要靠在右边**」；
   注：他说的就是顶栏那个「⋯」）。原来它在 grid 第 3 列里被**默认拉伸**（`justify-self:stretch`）⇒
   字落在列的**中间**、看着离右边更远。现在：`justify-self:end` 让它靠到内容框右缘，
   再用**负右外边距**把顶栏自身那 0.92em 的内边距抵消掉大半，真正靠到屏边（只留 ~0.3em 呼吸位）。
   ⚠️ grid 三列（1fr auto 1fr）**不动** ⇒ 标题仍严格居中（套件 ②b2c 钉着 ≤2px）。 */
.tm-nav .tm-more{justify-self:end;margin-right:-0.62em;opacity:1;cursor:pointer;min-width:1.6em;text-align:center;
  padding:0.1em 0.2em;font-size:1.5em;font-weight:700;line-height:1;border-radius:0.3em}
.tm-nav .tm-more:active{background:rgba(255,255,255,.18)}
.tm-nav .tm-more:hover{opacity:1}
/* 🔴 顶栏「⋯」的**下拉小菜单**（需求方 2026-09-27 两次澄清：「点击后出现的弹窗中，里面放我表述的
   内容」、「**是下拉，就是一个小菜单，不是这么大的弹窗**」）—— 钉在手机屏内**右上角**、顶栏正下方；
   一级=两行（关注服务号 / 联系客服），二级=关注码。`tm-more-btns` / `.tm-more-qr` 是**已下线**的
   「微信收藏 / 转发」那套留下的，保留备用。 */
.tm-dd{position:absolute;z-index:8;top:4.7em;right:0.55em;min-width:6.4em;max-width:12em;padding:0.3em;
  border:1px solid var(--line2);border-radius:0.54em;background:#fff;font-size:1em;
  box-shadow:0 0.6em 1.5em rgba(16,38,60,.24)}
.tm-dd-row{display:flex;align-items:center;justify-content:space-between;gap:0.9em;padding:0.55em 0.62em;
  border-radius:0.38em;color:var(--text);font-size:0.72em;white-space:nowrap;cursor:pointer}
.tm-dd-row:active{background:var(--soft)}
.tm-dd-row i{font-style:normal;color:var(--muted);font-size:1.15em;line-height:1}
.tm-dd-h{display:flex;align-items:center;gap:0.35em;padding:0.05em 0.15em 0.28em;font-size:0.72em;color:var(--navy)}
.tm-dd-h b{flex:1 1 auto;font-weight:700;text-align:center}
.tm-dd-bk,.tm-dd-x{cursor:pointer;color:var(--muted);line-height:1;padding:0 0.15em}
.tm-dd-qr{text-align:center}
.tm-dd-qr img{width:7.2em;height:7.2em;display:inline-block;border:1px solid var(--line2);
  border-radius:0.45em;background:#fff;object-fit:contain}
.tm-dd-t{margin:0.3em 0 0.05em;font-size:0.62em;line-height:1.5;color:var(--muted);text-align:center}
.tm-more-qr{margin:.5em 0 .1em;text-align:center}
.tm-more-qr img{width:7.6em;height:7.6em;display:inline-block;border:1px solid var(--line2);border-radius:.45em;background:#fff}
.tm-more-btns{display:flex;gap:.45em;margin:.55em 0 .1em}
.tm-more-btns button{flex:1 1 0;padding:.42em 0;border-radius:.42em;border:1px solid var(--line2);
  background:#f4f7fb;color:var(--text);font:inherit;font-size:.62em;font-weight:700;cursor:pointer}
.tm-more-btns button.pri{background:var(--blue);border-color:var(--blue);color:#fff}
.tm-nav .tm-navt{justify-self:center;min-width:0;max-width:100%;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap;font-size:1.04em;text-align:center}
.tm-cardb{padding:0.77em;border:1px solid var(--line);border-radius:0.77em;background:var(--soft2)}
.tm-ct{margin-bottom:0.62em;color:var(--label);font-size:0.96em;font-weight:600}
.tm-line{height:0.62em;margin-bottom:0.46em;border-radius:0.31em;background:var(--line)}
.tm-line.w70{width:70%}
.tm-list{display:flex;flex-direction:column;gap:0.62em}
.tm-li{display:flex;align-items:center;gap:0.62em;padding:0.62em 0.77em;border:1px solid var(--line);border-radius:0.62em}
.tm-dot{flex:0 0 auto;width:0.62em;height:0.62em;border-radius:50%;background:var(--accent)}
.tm-li .tm-line{flex:1 1 auto;margin:0}
.tm-div{height:1px;background:var(--line)}
.tm-tab{display:flex;margin:auto -0.92em -0.92em;border-top:1px solid var(--line);background:#fff}
.tm-tab span{flex:1 1 0;display:flex;flex-direction:column;align-items:center;gap:0.15em;padding:0.62em 0;font-size:0.77em;color:var(--muted)}
.tm-tab span.on{color:var(--blue)}
/* 🔴 内容屏的**固定框架**（顶部标题栏 / 底部标签栏，需求方 2026-09-24：「所有顶部标题栏和底部页底一条
   默认做好，不得后期设置修改」）—— 它们渲染在拖放区（`.tm-canvas`）**之外**，负 margin 归零即可贴边。 */
/* 🔴 固定框架件（顶部标题栏 / 底部标签栏）**不允许被 flex 收缩**（需求方 2026-09-27：
   「**内容界面服务记录顶部标题栏与其他页面尺寸不一**」）。
   根因：`.tm-screen` 是 flex column，nav / tab 默认 `flex:0 1 auto` ⇒ 内容一多（如「服务记录」屏的
   工单列表比可用高度多出 0.5px）就先把固定高度的顶栏**压扁**（实测 44.4px → 27.4px，页间不一致）。
   改成 `flex:0 0 auto`：顶栏 / 底栏尺寸恒定，超出部分交给 `.tm-canvas`（它本来就是 `overflow:auto`）。 */
.tm-nav-fx{flex:0 0 auto;margin:0}
.tm-tab-fx{flex:0 0 auto;margin:0}
/* 「首页」是根、没有上一级 → 顶栏返回箭头**不显示**（需求方 2026-09-24：「首页的标题是否不应该有左边返回箭头」）。
   用 visibility 隐藏而不是删掉，是为了**留住同宽占位**，标题仍居中。 */
.tm-back.off{visibility:hidden}
/* ---- 内容屏 · 「工单记录」屏（需求方 2026-09-27：「工单记录点击后就是查阅与其个人有关工单」）----
   底部那两个键可点后才会有这一屏：屏内是 `/api/h5/tickets` 的**真实工单列表**（可滚动）。
   尺寸一律用 `em`（基准 = `.tm-screen` 的 `cqw` 字号），与手机内其它元素同口径。 */
.tm-tab span[onclick]{cursor:pointer}
.tm-tab span[onclick]:hover{color:var(--blue)}
.tm-tk{display:flex;flex-direction:column;gap:0.54em}
.tm-tk-ph{margin:auto;padding:1.69em 1.38em;border:1px dashed var(--line2);border-radius:0.77em;
  background:var(--soft);color:var(--muted);font-size:0.92em;text-align:center}
.tm-tk-ph.err{border-style:solid;border-color:#f0c9cd;background:#fff5f6;color:#b4333f}
/* 🔴 条目**≤2 行** + 内边距/字号收紧（需求方 2026-09-27：「内容条目显示控制在一条目显示两行内，
   空间优化，否则显示条目太少」）—— 改前每条 3 行（状态＋标题 / 单号·项目 / 时间）≈97px，
   改后 2 行（第 2 行合并 单号·项目·时间）≈0.46+0.88+0.31+0.73+0.46em ≈ 更紧凑；与手机端 H5 同一口径。 */
.tm-tki{padding:0.46em 0.62em;border:1px solid var(--line);border-radius:0.62em;background:#fff}
.tm-tki-h{display:flex;align-items:center;gap:0.38em}
.tm-tki-s{flex:0 0 auto;padding:0.08em 0.46em;border-radius:0.31em;background:var(--accent-soft);
  color:var(--blue);font-size:0.66em;font-weight:700;white-space:nowrap}
.tm-tki-t{flex:1 1 auto;overflow:hidden;font-size:0.88em;font-weight:600;color:var(--text);
  text-overflow:ellipsis;white-space:nowrap}
.tm-tki-m{margin-top:0.15em;overflow:hidden;font-size:0.73em;line-height:1.35;color:var(--muted);
  text-overflow:ellipsis;white-space:nowrap}
/* ---- 「我的」屏（需求方 2026-09-27：点底键「我的」→ H5 页：公司全称 / 项目名称（多个列出多个）/
   每个项目下项目经理 + 联系方式**同行** + 项目周期 / 最后一个「退出登录」）
   🔴 同日追加：「**我的里面也空间优化，文字过大，可单页显示的内容太少**」⇒ 字号与内边距整体收一档
   （与手机端 H5 同一套比例：公司全称 0.92→0.85em、项目名 0.85→0.8em、字段行 0.72→0.69em、
     卡内边距 0.69→0.54em / 0.54→0.46em、二维码上限 6.4→5.6em）。 */
.tm-my{flex:1 1 auto;min-height:0;display:flex;flex-direction:column;gap:0.23em}
.tm-my-co{flex:0 0 auto;padding:0.54em;border:1px solid var(--line);border-radius:0.54em;background:var(--soft)}
.tm-my-co-l{font-size:0.66em;color:var(--muted)}
.tm-my-co-n{margin-top:0.1em;font-size:0.85em;font-weight:700;line-height:1.35;color:var(--text);word-break:break-word}
.tm-my-co-a{margin-top:0.15em;font-size:0.66em;color:var(--muted)}
.tm-my .tm-svc-b{flex:1 1 auto}
.tm-my-p{flex:0 0 auto;padding:0.46em 0.54em;border:1px solid var(--line2);border-radius:0.46em;background:#fff}
.tm-my-p-n{font-size:0.8em;font-weight:700;line-height:1.35;color:var(--text);word-break:break-word}
.tm-my-p-r{display:flex;align-items:baseline;gap:0.31em;margin-top:0.15em;font-size:0.69em;line-height:1.45;
  flex-wrap:wrap}
.tm-my-k{flex:0 0 auto;color:var(--muted)}
.tm-my-v{flex:0 1 auto;min-width:0;color:var(--text);word-break:break-word;white-space:pre-wrap}
.tm-my-sep{color:var(--line2)}
/* 🔴 「我的」里**退出登录键上方并排两张二维码**（需求方 2026-09-27）：左＝客服咨询、右＝网越智汇栈。
   与登录页 / 「关于我们」同一份素材（`/logo/`）；尺寸用 em，跟手机一起等比缩放。 */
.tm-my-qrs{flex:0 0 auto;display:flex;gap:0.54em;justify-content:center;align-items:flex-start;
  margin-top:0;padding:0.31em 0.31em 0.15em;border-top:1px dashed var(--line)}
.tm-my-qr-i{flex:1 1 0;min-width:0;max-width:6.6em;text-align:center}
.tm-my-qr-i img{display:block;width:100%;max-width:5.6em;margin:0 auto;aspect-ratio:1/1;
  object-fit:contain;border:1px solid var(--line2);border-radius:0.45em;background:#fff}
.tm-my-qr-t{margin-top:0.15em;font-size:0.66em;color:var(--muted);line-height:1.35}
/* ---- 「服务记录」屏（需求方 2026-09-27：「上面一半是工单的记录，下面一半是问答的记录，**可分别上下翻滚**，
   单击内容切内容页面」）—— 上下两块各占一半、**各自** overflow:auto；点一条进内容页（工单 / 问答）。
   尺寸一律用 em，跟手机一起等比缩放。 */
.tm-svc{flex:1 1 auto;min-height:0;display:flex;flex-direction:column;gap:0.23em}
/* 上半 / 下半的标题条（固定在各自块顶，不跟着滚） */
/* 🔴 两个分区标题用**整行背景色**明显区隔（需求方 2026-09-27：「工单记录和问答记录标题用整行背景色明显区隔开」）
   —— "整行"= 用负边距铺满手机屏宽（`.tm-canvas` 的 0.92em 内边距），截成一条色带；
     上半蓝系、下半青系（与列表里的状态标同一套配色）。「流转记录」那个标题不带上半/下半的类，走中性灰。
   🔴 同日追加（需求方：「工单记录标题和问答记录都应该**标题文字在左，条数在右，不换行**」）：
     方向写死 `row` + `white-space:nowrap`，标题与条数都 `flex:0 0 auto`（条数 `margin-left:auto` 顶到右边），
     谁都不许被挤到第二行（手机端 H5 上正是被通用类 `.tk` 的 `column` 带歪过，两边一起钉住）。 */
.tm-svc-h{flex:0 0 auto;display:flex;flex-direction:row;white-space:nowrap;
  align-items:center;justify-content:space-between;
  /* ⚠️ 这里的 em 是**自身字号**（0.77em）⇒ 要抵消 canvas 的 0.92em 得写 0.92/0.77 ≈ 1.2em（em 继承的老陷阱，踩过） */
  margin:0 -1.2em;padding:0.36em 1.2em;background:var(--soft);
  font-size:0.77em;font-weight:700;color:var(--text)}
.tm-svc-h>*{flex:0 0 auto;white-space:nowrap}
.tm-svc-h>span{margin-left:auto}
.tm-svc-h.tk{background:#e8f2ff;color:#2b6cb0}
.tm-svc-h.ask{background:#e6f7f3;color:#0f8f7a}
/* 「当日 / 全部」小切换（工单记录标题条右侧，需求方 2026-09-27：「默认从当日开始显示」）
   —— 与 H5 `.svc-h .seg/.sg` **同一套**（不加边框、不抢标题）；尺寸用 em，跟手机屏一起等比缩放。 */
.tm-svc-h .seg{display:inline-flex;align-items:center;vertical-align:middle;margin-right:0.46em;
  padding:0.15em;border-radius:999px;background:rgba(43,108,176,.14)}
.tm-svc-h .sg{padding:0.08em 0.46em;border-radius:999px;font-size:0.92em;font-weight:600;
  color:#2b6cb0;cursor:pointer;white-space:nowrap}
.tm-svc-h .sg.on{background:#fff;box-shadow:0 1px 2px rgba(15,34,51,.12)}
/* 两块滚动区：**各占一半**（flex-basis 50%）+ 自己滚（间距收一档 → 同屏更多条目） */
.tm-svc-b{flex:1 1 50%;min-height:0;overflow:auto;display:flex;flex-direction:column;gap:0.31em;
  padding:0.31em 0.15em 0.15em 0}
.tm-svc .tm-tki{cursor:pointer}
.tm-svc .tm-tki:active{background:var(--soft)}
/* 问答那条的来源短标（本地 / 全网 / 婉拒…）用**青色**，与工单状态标区分开 */
.tm-tki-s.ask{background:#e6f7f3;color:#0f8f7a}
/* 内容页：详情卡 + 字段行（左键右值，长文换行） */
.tm-svc-d{flex:0 0 auto;padding:0.69em;border:1px solid var(--line);border-radius:0.54em;background:#fff}
.tm-svc-t{font-size:0.92em;font-weight:700;line-height:1.4;color:var(--text);word-break:break-word}
.tm-svc-mt{display:flex;align-items:center;gap:0.46em;margin:0.31em 0 0.46em}
.tm-svc-r{display:flex;gap:0.46em;padding:0.23em 0;font-size:0.77em;line-height:1.5}
.tm-svc-k{flex:0 0 4.6em;color:var(--muted)}
.tm-svc-v{flex:1 1 auto;min-width:0;color:var(--text);word-break:break-word;white-space:pre-wrap}
.tm-svc-q{font-size:0.85em;font-weight:700;line-height:1.5;color:var(--text);margin:0.15em 0 0.46em;
  word-break:break-word}
.tm-svc-a{font-size:0.8em;line-height:1.65;color:var(--text);word-break:break-word}
.tm-svc-note{flex:0 0 auto;padding:0.46em 0.62em;border-radius:0.46em;background:#fff5f6;
  color:#b4333f;font-size:0.77em;line-height:1.5}
/* 动作按钮（取消工单 / 删除记录 / **流转按钮**）——
   🔴 需求方 2026-09-27：流转按钮要**有边框或其它方式区分**，「看起来像一大块」不行
   ⇒ 普通键与危险键改**白底 + 边框**（只有实心的主色键保持无边框）；`box-sizing` 保证定高不胀。 */
.tm-svc-act{flex:0 0 auto;display:flex;gap:0.46em}
.tm-svc-btn{flex:1 1 auto;height:2.3em;box-sizing:border-box;border:0;border-radius:0.54em;font:inherit;
  font-size:0.8em;font-weight:700;letter-spacing:.06em;white-space:nowrap;cursor:pointer}
.tm-svc-btn.danger{background:#fff;color:#b4333f;border:1px solid #f0c9cd}
.tm-svc-btn.danger:active{background:#fff1f2}
.tm-svc-btn.ghost{background:#fff;color:var(--text);border:1px solid var(--line2)}
.tm-svc-btn.ghost:active{background:var(--soft)}
/* 「删除记录」下面那一行「返回」：两行按钮之间给一点呼吸（同一 `.tm-svc` 里两个 `.tm-svc-act`） */
.tm-svc-act + .tm-svc-act{margin-top:0.31em}
/* 流转记录（内容页下半；自己滚） */
.tm-svc-lg{padding:0.31em 0.08em;border-bottom:1px dashed var(--line)}
.tm-svc-lg:last-child{border-bottom:0}
.tm-svc-lg-a{margin-right:0.46em;font-size:0.77em;font-weight:700;color:var(--text)}
.tm-svc-lg-n{margin-top:0.15em;font-size:0.72em;line-height:1.5;color:var(--muted);word-break:break-word}
/* 取消工单的二次确认弹层里的原因输入框 + 两颗键 */
.tm-svc-reason{width:100%;box-sizing:border-box;margin:0.31em 0;padding:0.54em 0.62em;
  border:1px solid var(--line2);border-radius:0.46em;background:#fbfdff;color:var(--text);
  font:inherit;font-size:0.8em;line-height:1.5;resize:none;outline:0}
.tm-svc-confirm{display:flex;gap:0.46em}
/* ---- 电脑端「IT智能体」页 · **问答记录**块（需求方 2026-09-27：「同终端原理…设计一块问答记录，可看可删」）
   一行一条：问题 + 来源/渠道/时间；点标题或「查看」就地展开完整问答；「删除记录」直接删（不二次确认）。 */
.airc-it{margin-top:10px;padding:10px 11px;border:1px solid var(--line2);border-radius:9px;background:#fff}
.airc-it.open{border-color:#bcd7f5;background:#fbfdff}
.airc-hd{display:flex;align-items:baseline;gap:10px;cursor:pointer;flex-wrap:wrap}
.airc-q{flex:1 1 240px;min-width:0;font-size:13px;font-weight:600;color:var(--text);word-break:break-word}
.airc-hd .mini{white-space:nowrap}
.airc-bd{margin-top:8px;padding-top:8px;border-top:1px dashed var(--line);font-size:13px;
  line-height:1.8;color:var(--text);word-break:break-word}
.airc-ft{display:flex;gap:8px;margin-top:8px}
/* ---- 内容屏 · 「AI知识库」屏 = **AI 问答页（聊天窗 + 流式输出）**（需求方 2026-09-27：
   「给终端管理的AI知识库按钮点击后做一个AI问答页面」+「问答页面做成聊天窗模式，流式输出」）——
   一问一答两条气泡（问=右侧、答=左侧），答案边生成边显示；尺寸一律用 em，跟手机一起等比缩放。 */
.tm-ai{display:flex;flex-direction:column;gap:0.46em;flex:1 1 auto;min-height:0}
.tm-ai-hd{flex:0 0 auto;padding:0.46em 0.62em;border-radius:0.46em;background:var(--accent-soft);
  color:var(--blue);font-size:0.72em;line-height:1.5}
/* 消息区：自己滚（输入区固定在下面，聊天窗的样子） */
.tm-ai-msgs{flex:1 1 auto;min-height:0;overflow:auto;display:flex;flex-direction:column;gap:0.46em;
  padding:0.15em 0}
.tm-ai-m{display:flex}
.tm-ai-m.me{justify-content:flex-end}
.tm-ai-b{max-width:88%;padding:0.54em 0.69em;border-radius:0.69em;font-size:0.8em;line-height:1.6}
.tm-ai-m.me .tm-ai-b{background:var(--blue);color:#fff;border-bottom-right-radius:0.23em}
.tm-ai-m.ai .tm-ai-b{background:#fff;border:1px solid var(--line);color:var(--text);
  border-bottom-left-radius:0.23em}
.tm-ai-src{margin-bottom:0.31em;padding-bottom:0.31em;border-bottom:1px dashed var(--line);
  color:var(--blue);font-size:0.86em;font-weight:700}
.tm-ai-tx{white-space:pre-wrap;word-break:break-word}
.tm-ai-cur{color:var(--muted)}
/* 🔴 每条回答下面 **3 颗反馈键（带文字）**（需求方 2026-09-27）——本地 → 记 RAG 知识库计数；
   在线 → 落「知识判定」待定条目。点过一颗会**标出来**并禁用（不再重复点）。
   🔴 样式口径（需求方同日）：「按钮中文字**不换行**，盘测按钮或框让点空间出来」+「按钮**不要有边框颜色**」
      ⇒ 去边框（靠浅底区分）、`white-space:nowrap`；间距放宽一点，三个字的键不会被挤成两行。 */
.tm-ai-fb{display:flex;flex-wrap:wrap;gap:0.46em;margin-top:0.46em;padding-top:0.4em;
  border-top:1px dashed var(--line)}
/* 🔴 2026-09-27 追加：三颗键前面加**小图标**（需求方：「终端中知识回答的三个点评给于小图标」）
   —— 图标内联 SVG、1em，跟字号一起缩放；`inline-flex` + `gap` 让图标与文字对齐、间距稳。
   （图标形状见 app.js 的 tmFbIcon：有用=拇指向上 / 无用=同一枚旋转 180° / 负面=黄色三角） */
.tm-ai-fbb{display:inline-flex;align-items:center;gap:0.31em;padding:0.28em 0.69em;border:0;
  border-radius:0.46em;background:var(--soft);color:var(--text);font:inherit;font-size:0.72em;
  line-height:1.15;white-space:nowrap;cursor:pointer}
.tm-ai-fbb svg{flex:0 0 auto;display:block}
.tm-ai-fbb:hover{background:var(--accent-soft);color:var(--blue)}
.tm-ai-fbb.on{background:var(--blue);color:#fff;font-weight:700}
.tm-ai-fbb[disabled]{cursor:default;opacity:.75}
.tm-ai-fbok{align-self:center;color:var(--blue);font-size:0.69em;white-space:nowrap}
.tm-ai-ph{padding:1.08em 0.77em;border:1px dashed var(--line2);border-radius:0.54em;background:var(--soft);
  color:var(--muted);font-size:0.77em;line-height:1.6;text-align:center}
.tm-ai-err{flex:0 0 auto;padding:0.54em 0.69em;border-radius:0.46em;border:1px solid #f0c9cd;
  background:#fff5f6;color:#b4333f;font-size:0.77em;line-height:1.6}
.tm-ai-in{flex:0 0 auto;display:flex;gap:0.46em;align-items:stretch}
.tm-ai-q{flex:1 1 auto;min-width:0;box-sizing:border-box;padding:0.54em 0.62em;border:1px solid var(--line2);
  border-radius:0.54em;background:#fbfdff;color:var(--text);font:inherit;font-size:0.8em;
  line-height:1.5;resize:none;outline:0}
/* 🔴 发送按钮**上下两个**（需求方 2026-09-27：「上面是"问本地"，下面是"问模型"」）—— 右列两格，等高。
   样式口径同日：「按钮中文字**不换行**，盘测按钮或框让点空间出来」+「按钮**不要有边框颜色**」
   ⇒ 无边框（靠渐变实底区分）、`white-space:nowrap`；列宽 5.2em 是**实测**留够"问本地"三个字一行 +
   两边内边距的余量（挤不下时宁可缩字号也不让它换行）。 */
.tm-ai-btns{flex:0 0 auto;display:flex;flex-direction:column;gap:0.31em;width:5.2em}
.tm-ai-btn{flex:1 1 0;display:flex;align-items:center;justify-content:center;
  border:0;border-radius:0.54em;color:#fff;font:inherit;font-size:0.77em;font-weight:700;
  letter-spacing:.02em;white-space:nowrap;cursor:pointer;padding:0 0.23em}
.tm-ai-btn.loc{background:linear-gradient(92deg,#2f7cf0,#6d5cf6)}
.tm-ai-btn.web{background:linear-gradient(92deg,#12a37b,#0f8f8f)}
.tm-ai-btn[disabled]{opacity:.6;cursor:default}
.tm-row{display:flex;justify-content:space-between;gap:0.77em;padding:0.54em 0.77em;border-bottom:1px solid var(--line)}
.tm-rl{flex:0 0 auto;font-size:0.92em;color:var(--muted)}
.tm-rv{flex:1 1 auto;overflow:hidden;font-size:0.96em;color:var(--text);text-align:right;text-overflow:ellipsis;white-space:nowrap}

/* ---- 内容屏 · 「真实数据预览」（需求方 2026-09-24：「内容界面要能正常显示内容，能点击」）----
   元素读真实记录：字段显示真实值、列表块显示真实记录、卡片显示真实条数；整块可点 → 弹下面这个面板。 */
.tm-row.has{cursor:pointer}
.tm-rv.ph{color:#a8b6c5}
.tm-cv{margin:-0.2em 0 0.5em;font-size:1.05em;font-weight:700;color:var(--navy)}
.tm-lx{flex:1 1 auto;overflow:hidden;font-size:0.94em;color:var(--text);text-overflow:ellipsis;white-space:nowrap}
.tm-lx.ph{color:#a8b6c5}
.tm-cardb[onclick],.tm-list[onclick]{cursor:pointer}
.tm-pv{position:absolute;z-index:6;left:0;right:0;bottom:0;max-height:80%;overflow:auto;
  padding:0.7em 0.75em 0.6em;border-top:1px solid var(--line);border-radius:1.1em 1.1em 0 0;background:#fff;
  box-shadow:0 -0.6em 1.4em rgba(16,38,60,.2)}
.tm-pv-h{display:flex;align-items:center;justify-content:space-between;font-size:0.78em;font-weight:700;color:var(--navy)}
.tm-pv-x{padding:0 0.2em;color:var(--muted);font-size:1.15em;line-height:1;cursor:pointer}
.tm-pv-t{margin:0.25em 0 0.4em;font-size:0.62em;line-height:1.5;color:var(--muted);word-break:break-all}
.tm-pv-e{margin-bottom:0.3em;font-size:0.62em;color:var(--red)}
.tm-pv-l{display:flex;flex-direction:column;gap:0.3em}
.tm-pv-r{padding:0.3em 0.42em;border:1px solid var(--line);border-radius:0.45em;background:var(--soft2)}
.tm-pv-r1{display:flex;align-items:center;gap:0.35em}
.tm-pv-i{flex:0 0 auto;width:1.15em;height:1.15em;border-radius:0.3em;background:var(--blue);color:#fff;
  font-size:0.56em;line-height:1.15em;text-align:center}
.tm-pv-n{flex:1 1 auto;overflow:hidden;font-size:0.66em;font-weight:600;color:var(--text);text-overflow:ellipsis;white-space:nowrap}
.tm-pv-r2{display:flex;flex-wrap:wrap;gap:0.12em 0.6em;margin-top:0.2em;font-size:0.58em;color:var(--muted)}
.tm-pv-r2 i{margin-right:0.25em;font-style:normal;color:var(--label)}
.tm-pv-f{margin-top:0.45em;font-size:0.56em;color:var(--muted);text-align:center}

/* ---- 登录屏：**固定成项目登录页的样式**（需求方 2026-09-24：「右边登录界面的设置就不需要了，
        直接按我要求在左边登录界面做好」）—— 不再由设置栏拼装，配色/结构照 `#login`：
        深色渐变 + 背景图 + 暗纱 → 深色玻璃登录卡（logo / 品牌 / 副标题 / 账号 / 密码 / 记住密码 / 登录按钮 / 隐私声明）。
        尺寸仍用 em（跟手机一起等比缩放）。 */
/* ---- 登录屏的**背景层**（两套共用 · 需求方 2026-09-24：「页面1和2都做窗口自动随机在背景图中移动视角的效果」）----
   背景图从伪元素（`.tm-login::before`）**抽成真实元素** —— 伪元素没法用 JS 驱动。
   层向外扩 16%（`inset:-16%`）且最多放大 1.30 倍 ⇒ JS 写入的"平移 ±7%"**四周不会露边**；
   `transition 4.2s` 让每 4 秒换一次的随机目标**平滑滑过去**，观感 = 镜头在画面里缓慢游走（不是一格一跳）。
   🔴 类名与真实登录页 `#login` 的 `.login-bg-fx/.login-bg-par/.login-bg-img` **完全不同**，
      且 JS 侧只查 `#view .tm-bg-i` ⇒ 真实登录页的镜头跟随**不受任何影响**。 */
.tm-bg{position:absolute;inset:0;overflow:hidden;pointer-events:none;z-index:0}
.tm-bg-i{position:absolute;inset:-16%;background-size:cover;background-position:center;background-repeat:no-repeat;
  transform:translate3d(0,0,0) scale(1.16);
  transition:transform 4.2s cubic-bezier(.36,.05,.3,1);will-change:transform}
@media (prefers-reduced-motion: reduce){ .tm-bg-i{transition:none} }
.tm-login{position:relative;flex:1 1 auto;overflow:hidden;padding:1.5em 1.15em;
  /* 🔴 **登录卡与下面的协议文字等宽**（需求方 2026-09-24：「页面1登录窗口可以和下面文字等宽」）——
     用 grid 的 `max-content` 单列让两者共用同一列宽（谁内容宽听谁），卡片占满列宽、协议文字也占满。 */
  display:grid;grid-template-columns:minmax(0,max-content);justify-content:center;align-content:center;
  background:
    radial-gradient(ellipse 90% 70% at 22% 10%, rgba(38,116,168,.40) 0%, rgba(8,24,40,0) 62%),
    radial-gradient(ellipse 70% 60% at 88% 92%, rgba(72,58,158,.22) 0%, rgba(8,24,40,0) 62%),
    linear-gradient(150deg,#061322 0%,#0a2136 32%,#0f3555 64%,#132c4c 100%)}
/* 页面1 的背景图**压暗到 .55**（沿用原来 `::before` 的口径：深色底 + 图 + 暗纱） */
.tm-login .tm-bg-i{opacity:.55}
.tm-login::after{content:'';position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(180deg,rgba(6,17,32,.34) 0%,rgba(6,17,32,.10) 42%,rgba(6,17,32,.36) 100%)}
/* 🔴 登录卡**变小居中**（需求方 2026-09-24：「页面中中间登录窗太大了，变小居中」→
   「用户协议和隐私挂在登录窗外面，登录窗就还能小」）——
   宽度不再撑满手机（`max-width` + `margin:0 auto`），协议移到卡片外（见 `.tm-lg-legal`），内部各件同步收一档。 */
.tm-lg-card{position:relative;z-index:1;width:100%;max-width:none;margin:0;
  padding:1.15em .9em .9em;border-radius:1em;text-align:center;
  background:rgba(11,22,42,.55);border:1px solid rgba(255,255,255,.16);
  backdrop-filter:blur(18px) saturate(1.25);-webkit-backdrop-filter:blur(18px) saturate(1.25);
  box-shadow:inset 0 .08em 0 rgba(255,255,255,.10),0 .8em 1.9em rgba(2,12,24,.38)}
.tm-lg-logo{display:block;width:2.7em;height:2.7em;margin:0 auto .45em;object-fit:contain;
  filter:drop-shadow(0 .3em .8em rgba(30,100,200,.35))}
.tm-lg-t{margin:0;font-size:1.45em;font-weight:700;color:#fff;letter-spacing:.6px}
.tm-lg-s{margin:.32em 0 .95em;font-size:.76em;color:rgba(255,255,255,.64);letter-spacing:.3px}
/* 🔴 账号 / 密码 = **与页面2 同款：标签在输入框内、一行**（需求方 2026-09-24：「页面1的登录窗里，
   账号密码四个字和页面2一样放入输入框内，这样登录窗口就不用那么高了」）——
   原来「标签在上 + 输入框在下」占两行，现在并成一行（每行省约 1.3em 高），卡片随之变矮。 */
/* 🔴 输入行 **无边框、透明填充**（需求方 2026-09-24：「页面1和页面2的输入框都要无边框，透明填充」）——
   原来是 glass 小框（`rgba(255,255,255,.10)` 底 + `.18` 边框），现按最新口径撤掉；
   padding / margin 一字不动 ⇒ 行高与卡片高度不变（两套登录卡"等高"的机制不受影响）。 */
.tm-lg-item{display:flex;align-items:center;gap:.5em;margin-bottom:.52em;padding:.46em .62em;
  border:0;border-radius:.5em;background:transparent}
.tm-lg-lab{flex:0 0 auto;font-size:.78em;color:rgba(255,255,255,.8);letter-spacing:.4px}
/* 🔴 账号 / 密码 = **真输入框**（需求方 2026-09-24：「登录界面账户可真实登录」）——
   外观与原来那个只读示意块一致：透明底、无自己的边框（边框由外层 `.tm-lg-item` 提供）；
   `width:100%` + `min-width:0` 收掉浏览器给 `<input>` 的默认尺寸（默认 ~170px 会把卡片顶宽）。 */
.tm-lg-inp{flex:1 1 auto;min-width:0;width:100%;border:0;outline:0;background:transparent;
  padding:0;font:inherit;font-size:.8em;line-height:1.5;color:#fff}
.tm-lg-inp::placeholder{color:rgba(255,255,255,.42)}
.tm-lg-row2{display:flex;align-items:center;margin:.08em 0 .72em;font-size:.72em;color:rgba(255,255,255,.74)}
.tm-lg-link{margin-left:auto;color:#38bdf8}
.tm-lg-btn{display:flex;align-items:center;justify-content:center;height:2.2em;border-radius:.58em;
  background:linear-gradient(92deg,#2f7cf0 0%,#6d5cf6 100%);color:#fff;font-size:.84em;font-weight:600;
  letter-spacing:.34em;text-indent:.34em;box-shadow:0 .7em 1.6em rgba(47,124,240,.34)}
/* 协议在卡外 → **整块居中 + 不换行**（需求方 2026-09-24：「移到下面后居中，与勾选框要对齐，
   注意字体颜色要清晰，与背景反差」+「不要换行」+「隐私和免责字体颜色跟背景混了，字体改成白色，
   《隐私声明》《免责声明》用蓝色字体」）——正文**纯白**、链接**亮蓝**。
   🔴 2026-09-24 需求方追问「是不是上面覆盖东西了」→ **猜对了**：`.tm-login::before`（背景图）与
      `::after`（深色暗纱）都是 `position:absolute;inset:0` **铺满整屏**，本块原来**静态定位、无 z-index**
      ⇒ 被那层暗纱**压在上面**（同一层叠上下文里，定位元素绘制在非定位元素之上）—— 于是"白字看着发灰、
      蓝链发暗、整体跟背景混"。修法：与 `.tm-lg-card` 同款 `position:relative;z-index:1`，抬到装饰层之上。
      ⚠️ 同类漏网的还有页面2 的 `.tm-l2-agree`（其 `::after` 是浅色纱，影响小但一并修）；
      `.tm-lg-card`(1) / `.tm-lg-foot`(2) / `.tm-l2-card`(1) / `.tm-l2-foot`(1) 本来就有 z-index，没被盖。 */
.tm-lg-legal{position:relative;z-index:1;width:100%;max-width:none;margin:.72em 0 0;
  font-size:.7em;line-height:1.7;white-space:nowrap;text-align:center;color:#fff}
.tm-lg-legal a{color:#58a6ff;text-decoration:none}
/* 底部公司信息（需求方 2026-09-24：「页面1 底部加上上海网越信息技术股份有限公司和我们服务热线
   400-626-5185，替换掉『终端 H5 · 登录页』」）—— 两行结构与页面2 的 `.tm-l2-foot` 一致，深色底用亮色 */
.tm-lg-foot{position:absolute;z-index:2;left:0;right:0;bottom:.85em;text-align:center;
  font-size:.68em;line-height:1.75;white-space:nowrap}
.tm-lg-fb{color:rgba(255,255,255,.76)}
.tm-lg-fh{color:#58a6ff;font-weight:500}
/* 登录中：按钮置灰 + 字距收窄（「登 录 中…」比「登 录」长，原 .34em 字距会顶出卡片） */
.tm-lg-btn.busy{opacity:.72;letter-spacing:.18em;text-indent:.18em}
/* 🔴 登录结果提示（两套登录屏共用 `#tm-lg-msg`）—— **绝对定位浮层、不占流**：
   两套登录卡是要求**等高**的（`tmSyncLoginCard` 取两套较大值），在卡片里加一行会把高度顶开；
   浮在屏底（公司信息条之上），成功绿 / 失败红。 */
.tm-lg-msg{position:absolute;z-index:3;left:.8em;right:.8em;bottom:4.5em;text-align:center;
  font-size:.7em;line-height:1.6;white-space:nowrap;pointer-events:none}
.tm-lg-msg.ok{color:#7ee787}
.tm-lg-msg.err{color:#ff9a9a}

/* ---- 登录屏顶部的**样式切换标签**（需求方 2026-09-24：「在左边这个登录界面顶上做 2 个切换标签，
        可以在你现在做的和那个之间切换选择」）---- */
.tm-ltabs{display:flex;gap:4px;margin-left:auto}
.tm-ltab{padding:3px 9px;border:1px solid var(--line2);border-radius:999px;background:var(--soft);
  font-size:11.5px;color:var(--muted);cursor:pointer;white-space:nowrap;transition:background .12s,color .12s,border-color .12s}
.tm-ltab:hover{border-color:var(--accent);color:var(--accent)}
.tm-ltab.on{background:var(--accent-soft);border-color:var(--blue);color:var(--blue);font-weight:700}

/* ---- 登录屏 · 第二套样式：**CrossNet 小程序**登录页（结构只读参考 `D:\CrossNet\pages\login\login.wxss`）——
        白色卡片 + 协议勾选 + 底部公司信息（这部分仍照那边复刻，品牌蓝 `#2b6cb0`；rpx→em 按手机宽 296/750rpx 折算）。
        🔴 **背景已换成"机房场景"**（需求方 2026-09-24：「页面2的背景图不要用白的，建议设计机房场景」）——
        底图 `web/terminal-login-bg.jpg` = AI 自绘**数据中心机房**（服务器机柜 + 冷色指示灯，实测平均 RGB 21/49/68、
        暗像素 89%、**明显不是白底**）。底图一变深，**卡片之外**的文字/纱层就要跟着改亮条（见下），否则看不见。 */
.tm-login2{position:relative;flex:1 1 auto;display:flex;flex-direction:column;justify-content:center;align-items:center;
  overflow:hidden;padding:1.1em 1.05em 3.1em;
  background:linear-gradient(160deg,#0a1520 0%,#0d2131 55%,#091722 100%)}   /* 深色兜底（图未载入时） */
/* 🔴 点阵纹理**压在机房底图之上**——`.tm-bg` 是 z-index:0 的定位元素，原来无 z-index 的伪元素会被它盖住
   ⇒ 抬到 1 并降不透明度，让"星图"肌理淡淡地叠在机房画面上（卡片 z-index:1 且 tree order 在后，仍在最上）。 */
.tm-login2::before{content:'';position:absolute;inset:0;z-index:1;opacity:.30;
  background-image:
    radial-gradient(rgba(120,190,255,.30) .09em, transparent .1em),
    radial-gradient(rgba(160,140,255,.22) .07em, transparent .08em);
  background-size:2.6em 2.6em,4.1em 4.1em;background-position:0 0,1.3em 1.7em}
/* 暗纱（原来是"浅蓝纱"，深底上用不上）：压暗机房画面并把中部收平，让白卡与亮字都跳出来 */
.tm-login2::after{content:'';position:absolute;inset:0;
  background:linear-gradient(180deg,rgba(4,12,22,.46) 0%,rgba(4,12,22,.16) 45%,rgba(4,12,22,.50) 100%)}
/* 🔴 同上：白卡也**变小居中**（需求方 2026-09-24「登录窗太大了，变小居中」+「协议挂外面，登录窗还能小」） */
.tm-l2-card{position:relative;z-index:1;width:100%;max-width:14em;padding:1.25em 1.05em .9em;border-radius:.9em;
  background:#fff;box-shadow:0 .65em 1.9em rgba(0,0,0,.46),0 0 0 1px rgba(255,255,255,.10)}
.tm-l2-logo{display:block;width:2.6em;height:2.6em;margin:0 auto .5em;border-radius:.55em;background:#fff;object-fit:contain}
.tm-l2-name{font-size:1.2em;font-weight:700;color:#1a202c;letter-spacing:.05em;text-align:center}
/* 副标题**不换行**（需求方 2026-09-24：「页面2 的技术筑基 · 服务致远 · 智汇未来不要换行，可以调整字体大小」）
   —— 字号收一档 + `nowrap`，保证一行放得下 */
.tm-l2-sub{font-size:.7em;font-weight:500;color:#2d3748;letter-spacing:.03em;text-align:center;
  white-space:nowrap;margin:.3em 0 .95em}
/* 🔴 输入项 **无边框、透明填充**（需求方 2026-09-24 最新口径：「页面1和页面2的输入框都要无边框，透明填充」）
   —— 覆盖当日早些时候的「页面二账号密码输入框需要细边框」（`1px solid #dbe3ec` + `#f8fafc` 底已撤）。 */
.tm-l2-item{display:flex;align-items:center;padding:.5em .68em;margin-bottom:.5em;border-radius:.42em;
  border:0;background:transparent}
.tm-l2-lab{flex:0 0 2.7em;font-size:.86em;color:#4a5568}
/* 真输入框（需求方 2026-09-24：「登录界面账户可真实登录」）：无边框、透明底，外观跟原来那个示意块一样 */
.tm-l2-inp{flex:1 1 auto;min-width:0;width:100%;border:0;outline:0;background:transparent;
  padding:0;font:inherit;font-size:.92em;line-height:1.5;color:#1a202c}
.tm-l2-inp::placeholder{color:#a0aec0}
/* 协议在卡外 → **整块居中 + 不换行 + 勾选框与文字垂直居中对齐**；
   🔴 底色由浅色机房图换成**深色机房**后，卡外这一块必须改**亮色**（原 `#3d4757` 深灰在深底上直接看不见）。 */
.tm-l2-agree{position:relative;z-index:1;display:flex;align-items:center;justify-content:center;gap:.42em;
  width:auto;max-width:100%;margin:.8em auto 0;
  font-size:.7em;color:#e8f1fb;line-height:1.7;white-space:nowrap}
.tm-l2-ck{flex:0 0 auto;width:1.15em;height:1.15em;margin-top:0;border:1px solid rgba(255,255,255,.55);border-radius:.3em;
  background:rgba(255,255,255,.16);display:flex;align-items:center;justify-content:center;font-size:.85em;line-height:1;color:#fff}
.tm-l2-ck.on{background:#2b6cb0;border-color:#5b9bd5}
.tm-l2-lk{color:#7cc4ff}
.tm-l2-btn{margin-top:.22em;padding:.5em 0;border-radius:.46em;background:#2b6cb0;color:#fff;text-align:center;
  font-size:.9em;font-weight:600;letter-spacing:.27em;text-indent:.27em}
.tm-l2-btn.busy{opacity:.75;letter-spacing:.14em;text-indent:.14em}
.tm-l2-foot{position:absolute;z-index:1;left:0;right:0;bottom:.85em;text-align:center;font-size:.7em;line-height:1.75}
/* 底部公司信息在**卡外**（深色机房底上）→ 同样改亮色 */
.tm-l2-fb{color:rgba(255,255,255,.82)}
.tm-l2-fh{color:#7cc4ff;font-weight:500}
/* 登录结果提示：底色变深后与页面1 统一（原来那对"深绿/深红"是给浅底配的，深底上太暗） */
.tm-login2 .tm-lg-msg.ok{color:#7ee787}
.tm-login2 .tm-lg-msg.err{color:#ff9a9a}

/* ---- 设置栏 ---- */
.tm-side{flex:0 0 262px;max-width:100%;display:flex;flex-direction:column;gap:12px}
/* ---- ② 扫码打开 H5（需求方 2026-09-24：原「③ 怎么用」整块下架 → 换成**二维码卡片 + 复制链接**；
        并明确「复制链接按钮不要放两屏顶上了，只放一个在这个二维码下面」）----
        二维码是 **SVG（前端现算）**，不是图片 ⇒ 链接一变它自己就变（`web/qr.js`）。 */
.tm-qr{width:100%;max-width:214px;margin:10px auto 0;padding:9px;box-sizing:border-box;aspect-ratio:1/1;
  border:1px solid var(--line2);border-radius:10px;background:#fff;
  display:flex;align-items:center;justify-content:center;overflow:hidden;position:relative}
.tm-qr-sv{width:100%;height:100%}
.tm-qr svg{display:block;width:100%;height:100%}
/* 二维码**正中的「CrossNet IT」字母标签**（需求方 2026-09-25：「在二维码中间加上 CrossNet IT 字母标签」+
   「CrossNet IT，不换行」+「加上边框，字体改成蓝紫渐变艺术字体」）——
   **一行不换行**；白底 + **蓝紫渐变描边**（双 background 叠加：内层白垫底、外层渐变只从 border 区透出）；
   文字用 **`background-clip:text` 做成蓝紫渐变艺术字**。
   🔴 尺寸是**实测定出来的，别随手放大**：它遮住的是中心的数据模块，实测（v5 真实链接、jsqr 真解码）
   `182px 码区 + 12.5px 字号 = 遮挡 9.05%` **解不出**；同一字号把二维码放到 200px（遮挡 7.7%）就稳过，
   所以尺寸与字号是**成对**的。① 生成器纠错等级必须是 **H（30%）**；② `.tm-qr` 的 `max-width` 别往回收；
   ③ `pointer-events:none` 免得挡住点击；④ 绝对居中、**始终落在码区之内**（不压静区）。 */
.tm-qr-lb{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);z-index:1;pointer-events:none;
  padding:3px 7px;border-radius:6px;border:1px solid transparent;
  background:linear-gradient(#fff,#fff) padding-box,linear-gradient(96deg,#2f7cf0,#6d5cf6) border-box;
  font-size:12.5px;font-weight:800;line-height:1;white-space:nowrap}
.tm-qr-lb b{font-weight:800;background:linear-gradient(96deg,#2f7cf0,#6d5cf6);
  -webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;color:#4a5fe0}
.tm-qr-ph{font-size:12px;color:var(--muted);text-align:center;line-height:1.6}
.tm-qr-url{margin-top:8px;font-size:11.5px;line-height:1.5;color:var(--muted);text-align:center;
  word-break:break-all;max-height:34px;overflow:hidden}
/* 「这个二维码打开的是哪一页」（需求方 2026-09-25：页面1/页面2 的选择要与右边二维码关联）——
   和左边标签一样只显示**页面1 / 页面2**，当前那个加粗着色，一眼能看出关联 */
.tm-qr-pg{margin-top:8px;font-size:11.5px;color:var(--muted);text-align:center}
.tm-qr-pg b{font-weight:700}
.tm-qr-pg b.it{color:var(--blue)}
.tm-qr-pg b.mini{color:#2b6cb0}
.tm-qr-copy{width:100%;margin-top:8px;justify-content:center;display:flex}

/* ---- **一棵树**（原「功能树」+「菜单树」合并，需求方 2026-09-24：
        「菜单树与功能树可以合并，方框的选择点击主菜单即可，子菜单前面要空开距离，主菜单粗体，
          点击主菜单就是选框，子菜单和之前一样点击后是切换内容界面的页面」）----
        少了一列 ⇒ 宽度还给这一列（178 → 218px），剩下的仍归左侧手机。 */
.tm-tree{flex:0 0 218px;max-width:100%;display:flex;flex-direction:column;padding:12px 13px;
  border:1px solid var(--line);border-radius:var(--radius);background:var(--card)}
/* 🔴 **不设高度上限、不滚动**（需求方 2026-09-24：「功能树不要滚动条，下面一起显示出来」）——
   条目全部展开，页面该多长就多长（原来是 max-height:min(62vh,640px) + overflow:auto 的内部滚动） */
.tm-tlist{flex:1 1 auto;margin-top:6px;padding-right:2px}
.tm-tg{display:flex;align-items:center;gap:7px;margin:6px 0 2px;padding:5px 7px;border-radius:7px;
  background:var(--soft);color:var(--label);font-size:12px;font-weight:600}
.tm-ti{display:flex;align-items:center;gap:7px;border-radius:7px;padding:5px 7px;
  color:var(--text);font-size:12.5px;cursor:pointer}
/* 🔴 **主菜单粗体**（需求方：「主菜单粗体」）；**子菜单前空开一级**（需求方：「子菜单前面要空开距离」）——
   ⚠️ 缩进要按**文字**位置算，主菜单文字前面有 **方框 + 编号** 两件：
      7(padding) + 13(方框) + 7(gap) + 23(编号 2.1em@11px) + 7(gap) ≈ **57px**；
      子菜单没有方框，padding 给 **40px** ⇒ 文字 ≈ 40+23+7 = 70px ⇒ 比主菜单文字**右移约 13px**（明显一级）。
      （踩过两次：22px 时子菜单反而更靠左 -5px；30px 时只差 +3px，都不像"缩进"。） */
.tm-ti.main{font-weight:700}
.tm-ti.sub{padding-left:40px}
.tm-ti:hover{background:var(--soft2)}
.tm-ti.on{background:var(--accent-soft);color:var(--blue);font-weight:700}
.tm-tck,.tm-tck2{flex:0 0 auto;width:13px;height:13px;border:1px solid var(--line2);border-radius:3px;background:#fff;
  cursor:pointer;transition:background .12s,border-color .12s}
.tm-tck.on,.tm-tck2.on{background:var(--blue);border-color:var(--blue);box-shadow:inset 0 0 0 2px #fff}
.tm-tgl{flex:1 1 auto}
.tm-tx{flex:1 1 auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* ---- 树结构编号（需求方 2026-09-24：「功能树里不需要勾选框，以树结构编号即可」「菜单树里也要有编号」）---- */
.tm-tno{flex:0 0 auto;min-width:2.1em;font-family:Consolas,monospace;font-size:11px;color:var(--muted);
  text-align:right}
.tm-tg .tm-tno{color:var(--label);font-weight:700}
/* ---- 主菜单条目可**上下挪移排序**（顺序 = 首页里的排列顺序）---- */
.tm-ti.tm-drag{cursor:grab}
.tm-ti.tm-drag:active{cursor:grabbing}

/* ---- 首页（需求方 2026-09-24：「首页的设计：图标 + 菜单树勾选的菜单…进行设计」「这个首页你帮我设计好」）：
        图标 + 名称的宫格，按菜单树顺序排列；尺寸全用 em，跟手机一起等比缩放 ---- */
/* 首页 = 一列：头部大字 → 宫格（可滚动区里的自定义元素跟在后面）→ **页脚**（`margin-top:auto` 顶到最下） */
.tm-home{position:relative;display:flex;flex-direction:column;flex:1 1 auto;padding:.1em 0 .5em}
.tm-home-hd{margin-bottom:.7em}
.tm-home-hi{font-size:.86em;font-weight:700;color:var(--navy)}
/* 大字下面那行问候语（AI 设计，可换）——🔴 2026-09-27 起**略扩展成两句**（需求方：「把原欢迎回来...这段文字
   略扩展下，精简介绍下终端用户可以使用快速报修和AI建议查阅功能」）⇒ 加 `line-height` 让它两行也读得舒服，
   两个功能名用 `<b>` 轻提一下色（不加图标、不加按钮，仍是纯文案）。 */
.tm-home-hw{margin-top:.22em;font-size:.62em;line-height:1.55;color:var(--muted);letter-spacing:.02em}
.tm-home-hw b{color:var(--blue);font-weight:700}
/* 头部下面两行小字：**居中放在底下**（需求方 2026-09-24）——「CrossNet IT」换行 + 副标题 */
/* 页脚：顶到最下 + **居中**（需求方 2026-09-24 先要"不居中"、随后确认「怎么没居中」→ 改回居中） */
.tm-home-c{margin-top:auto;padding-top:.9em;text-align:center}
.tm-home-hs1{font-size:.66em;font-weight:600;color:var(--label);letter-spacing:.06em}
.tm-home-hs2{margin-top:.16em;font-size:.6em;color:var(--muted);white-space:nowrap}
/* 九宫格（需求方 2026-09-24：分割线下要放"快速建单"窗口 → **整体压缩一档**，把高度让出来） */
.tm-home-g{display:grid;grid-template-columns:repeat(3,1fr);gap:.34em}
/* 九宫格下面的**分割线**（需求方 2026-09-24：「九宫格下面一条分割线」） */
.tm-home-div{height:1px;margin:.6em 0 0;background:var(--line)}
/* 「快速报修」窗口（需求方 2026-09-24：「分割线下面放置快速建单的窗口」→ 随后「改成**快速报修**，
   下面**不是按钮，是创建工单内容**」）—— 下面是**创建工单的表单**（只读示意） */
.tm-home-qk{margin-top:.65em;padding:.65em .7em;border:1px solid var(--line);border-radius:.6em;background:var(--soft2)}
.tm-home-qkt{margin-bottom:.5em;font-size:.66em;font-weight:700;color:var(--navy)}
.tm-home-qkf{display:flex;flex-direction:column;gap:.34em}
/* 一行两列（客户名称 + 项目名称 / 项目经理 + 联系方式）——需求方 2026-09-24：「客户名称、项目名称放一行」 */
.tm-home-qk2{display:flex;gap:.34em}
.tm-home-qk2 > .tm-home-qkrow{flex:1 1 0;min-width:0}
/* 「纯下拉 / 只读」变体：**不要输入框外观**（无边框无底），下拉文字用主题蓝提示可点 ——
   需求方 2026-09-24：「客户名称读取无需填」「项目名称去掉输入框，点击下拉选」 */
/* 「纯下拉 / 只读」变体：**不要输入框外观**（无边框无底），下拉文字用主题蓝提示可点 ——
   需求方 2026-09-24：「客户名称读取无需填」「项目名称去掉输入框，点击下拉选」 */
.tm-home-qkrow.plain{border:0;background:transparent;padding-left:0;padding-right:0}
.tm-home-qkrow.plain .tm-home-qksel{color:var(--blue);font-weight:600}
/* 必填星号（全部必填） */
.tm-req{margin-left:.12em;font-style:normal;color:var(--red)}
/* 只读值（自动读取 / 自动带出）用淡一点的底色，与"要填的"区分开 */
.tm-home-qkp.ro{color:#8b9bb0}
.tm-home-qkrow{display:flex;align-items:center;gap:.4em;padding:.4em .5em;border:1px solid var(--line);
  border-radius:.42em;background:#fff}
.tm-home-qksel{white-space:nowrap}   /* 下拉文字不换行 */
/* 项目名称 = **真实 `<select>`**（该客户下多个项目时可点开手选，选谁带出谁；需求方 2026-09-24：
   「项目名称（读取/多项目的点击出现下拉手选）」）—— 无边框、跟主题蓝，与只读文字同一排样式 */
select.tm-home-qksel{flex:1 1 auto;width:100%;min-width:0;border:0;background:transparent;color:var(--blue);
  font-family:inherit;font-size:.58em;font-weight:600;line-height:1.7;outline:none;cursor:pointer;
  text-overflow:ellipsis;-webkit-appearance:none;appearance:none}
/* 「快速报修」三个**真录入框**（需求方 2026-09-24：「内容页面要像真机使用，可以正常录入并流转」）——
   透明底、无边框（外框由所在行给），与只读文字同一排样式；聚焦时给一点底色，能看出光标在哪 */
.tm-home-qki{flex:1 1 auto;width:100%;min-width:0;padding:0;border:0;background:transparent;
  font-family:inherit;font-size:.58em;line-height:1.7;color:var(--text);outline:none;resize:none;
  -webkit-appearance:none;appearance:none}
.tm-home-qki::placeholder{color:#a8b6c5}
.tm-home-qki:focus{background:var(--accent-soft);border-radius:.25em}
textarea.tm-home-qki{display:block;min-height:2.3em}
textarea.tm-home-qki.ta2{min-height:3.6em}
.tm-home-qksub{cursor:pointer}
/* 「快速报修」标题右边的**服务方式多选**（需求方 2026-09-24：「现场和远程的勾选」+「改成多选」）——
   方框可多选、真 checkbox，`accent-color` 跟主题蓝 */
.tm-home-qkt{display:flex;align-items:center;justify-content:space-between;gap:.4em}
.tm-qkmodes{display:inline-flex;align-items:center;gap:.7em;flex:0 0 auto}
.tm-qkck{display:inline-flex;align-items:center;gap:.25em;font-size:.58em;font-weight:600;color:var(--text);
  cursor:pointer;white-space:nowrap}
.tm-qkck input{width:.92em;height:.92em;margin:0;cursor:pointer;accent-color:var(--blue)}
/* 项目**不具备**的那种服务方式 → **灰色 + 禁止勾选**（需求方 2026-09-24，与新建/创建工单同口径） */
.tm-qkck.off{opacity:.42;cursor:not-allowed}
.tm-qkck.off input{cursor:not-allowed}
/* 项目两种都不支持 → 用提示条**替换**「提交工单」按钮的文字（并且不能提交） */
.tm-home-qkno{flex:1 1 auto;display:flex;align-items:center;justify-content:center;padding:.55em .5em;
  border-radius:.45em;background:#fdecec;color:#b91c1c;font-size:.56em;font-weight:700;
  line-height:1.35;text-align:center}
/* 🔴 「服务方式能力**没读到**」的提示条（需求方 2026-09-25 报障的观感来源：读失败时静默 → 两个都能勾，
   看起来像"没按项目置灰"）。**不替换按钮**（临时故障不该把人拦死，真拦在提交时的实时校验）。 */
.tm-home-qkwarn{margin-top:.4em;padding:.45em .55em;border-radius:.45em;background:#fff7e6;color:#8a6d1b;
  font-size:.52em;line-height:1.5}
/* 底部两个按钮（需求方 2026-09-24：「提交工单按钮分两个，右边提交工单，左边 AI 建议·查阅（蓝框无填充蓝字）」；
   🔴 2026-09-27 需求方把左边那颗**拆成「问本地 / 问模型」两颗**，并要求「按钮中文字**不换行**，
      盘测按钮或框让点空间出来」⇒ `white-space:nowrap` + 内边距按三字按钮实测留够（不挤压「提交工单」）。
   🔴 同日另一条「按钮不要有边框颜色」**只针对 AI 问答页那几颗**；首页这两颗需求方随后明确：
      「**首页的问本地和问模型按钮要有边框**」⇒ 保持原样（**蓝框、无填充、蓝字**），此处不动。 */
.tm-home-qkbtns{display:flex;gap:.4em;align-items:stretch;margin-top:.5em}
/* 🔴 **不等分**（需求方 2026-09-24：「算了，两个按钮不要左右等分了，就现在这样吧」→ 此处**冻结**）：
   左 = 次按钮按内容自适应宽度，右 = 主按钮占满剩余宽度 */
.tm-home-qkalt{flex:0 0 auto;padding:.5em .55em;border:1px solid var(--blue);border-radius:.45em;
  background:transparent;color:var(--blue);font-family:inherit;font-size:.58em;font-weight:600;
  white-space:nowrap;cursor:pointer}
.tm-home-qkalt:active{background:var(--accent-soft)}
.tm-home-qkbtns .tm-home-qksub{flex:1 1 auto;min-width:0;display:flex;align-items:center;justify-content:center;margin-top:0}
/* 「项目地址」= **自适应高度**：默认一行；内容显示不够时才自然撑成两行（不给 min-height、允许换行）——
   需求方 2026-09-24：「项目地址默认一行，若显示不够，才会出现两行」 */
.tm-home-qkrow.auto{align-items:flex-start}
.tm-home-qkrow.auto .tm-home-qkp{white-space:normal;line-height:1.5}
/* 多行输入分级：ta1 = 两行高（备用联系人/地址）、ta2 = 更高（工单描述）—— 需求方 2026-09-24 */
.tm-home-qkrow.ta{align-items:flex-start}
.tm-home-qkrow.ta1{min-height:3.15em}
.tm-home-qkrow.ta2{min-height:4.7em}
.tm-home-qkl{flex:0 0 4.4em;font-size:.56em;color:var(--muted);white-space:nowrap}
.tm-home-qk2 .tm-home-qkl{flex:0 0 3.6em}
.tm-home-qkp{flex:1 1 auto;overflow:hidden;font-size:.56em;color:#a8b6c5;text-overflow:ellipsis;white-space:nowrap}
.tm-home-qkrow.ta .tm-home-qkp{white-space:normal;line-height:1.5}
.tm-home-qksel{flex:1 1 auto;display:flex;align-items:center;justify-content:space-between;
  font-size:.56em;color:#a8b6c5}
.tm-home-qksub{margin-top:.5em;padding:.55em 0;border-radius:.45em;background:var(--blue);color:#fff;
  font-size:.6em;font-weight:600;letter-spacing:.26em;text-indent:.26em;text-align:center}
.tm-home-i{position:relative;display:flex;flex-direction:column;align-items:center;gap:.2em;
  padding:.36em .18em .32em;border:1px solid var(--line);border-radius:.5em;background:var(--soft2);cursor:pointer}
.tm-home-i:active{background:var(--accent-soft)}
.tm-home-i.off{opacity:.78;background:var(--soft)}
/* 框内**右上角小标识**：已开通（绿）/ 未开通（红）——需求方 2026-09-24 */
.tm-home-b{position:absolute;top:.24em;right:.24em;padding:.04em .28em;border-radius:.5em;
  font-size:.42em;line-height:1.5;white-space:nowrap;background:#e8f5ec;color:#1a7f4b;border:1px solid #bfe3cd}
.tm-home-b:not(.on){background:#fdecec;color:#c0392b;border-color:#f2c6c6}
/* 未开通点击后的**屏内提示** */
.tm-home-tip{position:absolute;inset:0;z-index:5;display:flex;align-items:center;justify-content:center;
  padding:.8em;background:rgba(8,24,40,.5);border-radius:.5em}
.tm-home-tipc{padding:.7em .85em;border-radius:.5em;background:#fff;color:var(--text);font-size:.62em;
  line-height:1.7;text-align:center;box-shadow:0 .5em 1.4em rgba(2,12,24,.28)}
.tm-home-ic{display:flex;align-items:center;justify-content:center;width:1.42em;height:1.42em;border-radius:.4em;
  background:#fff;color:var(--blue);border:1px solid var(--line)}
.tm-home-ic svg{width:.88em;height:.88em}
.tm-home-n{font-size:.52em;color:var(--text);line-height:1.2;text-align:center}
.tm-home-ph{margin-top:.7em;padding:.9em .6em;border:1px dashed var(--line2);border-radius:.5em;
  background:var(--soft);color:var(--muted);font-size:.62em;line-height:1.8;text-align:center}
.tm-sec{padding:12px 13px;border:1px solid var(--line);border-radius:var(--radius);background:var(--card)}
.tm-sec-t{display:flex;align-items:baseline;justify-content:space-between;gap:8px;margin-bottom:8px;
  color:var(--label);font-size:var(--fs-title);font-weight:600}
.tm-sec-s{margin:8px 0 6px;color:var(--muted);font-size:11.5px;font-weight:600}
.tm-sec select{width:100%}
.tm-chips{display:flex;flex-wrap:wrap;gap:6px}
.tm-chip{padding:4px 10px;border:1px solid var(--line2);border-radius:999px;background:var(--soft);
  font-size:12px;cursor:grab;user-select:none}
.tm-chip:hover{border-color:var(--accent);color:var(--accent)}
.tm-fields{display:flex;flex-direction:column;gap:5px;max-height:300px;overflow:auto;margin-top:8px;padding-right:2px}
.tm-chip.fld{display:flex;justify-content:space-between;gap:8px;border-radius:8px;padding:6px 10px}
.tm-cf{font-size:12px}
.tm-ck{font-family:Consolas,monospace;font-size:11px;color:var(--muted)}
.tm-tip{margin-top:8px;color:var(--muted);font-size:11.5px;line-height:1.75}
.tm-tip b{color:var(--accent)}
@media(max-width:1180px){
  .tm-side{flex:1 1 100%}
  .tm-tree{flex:1 1 100%}
  .tm-fields{max-height:220px}
}


/* ===== SLA统计 · 「临时受理基线」统计块（需求方 2026-09-24：「这个临时的受理基线应该在 SLA 统计中增加统计」）=====
   只在有此类工单时出现；样式与页面其它统计块一致，不碰任何既有选择器（尤其不碰 #screen-big 那一段）。 */
.sla-prov .q-tip{margin:6px 0 8px}
.sla-prov .prov-row{display:flex;flex-wrap:wrap;align-items:baseline;gap:16px;margin-top:2px;
  font-size:13px;color:var(--text)}
.sla-prov .prov-k{display:inline-flex;align-items:baseline;gap:5px;color:var(--muted)}
.sla-prov .prov-k b{font-size:15px;font-weight:700;color:var(--navy)}
.sla-prov .prov-k.ok b{color:#0f8a52}
.sla-prov .prov-k.bad b{color:#b91c1c}

/* 🔴 首页问答答案区（需求方 2026-09-27：「首页点击问本地或问全网，解答内容**直接流式输出下方页面，
   不要切换页面**」）—— 就在**快速报障表单下方**就地展开，不弹层、不遮内容；尺寸一律用 em 随手机等比缩放。 */
.tm-home-ai{margin-top:0.62em;padding:0.62em 0.69em;border:1px solid var(--line);border-radius:0.54em;background:#fff}
.tm-home-ai-h{display:flex;align-items:baseline;gap:0.46em;margin-bottom:0.31em;
  padding-bottom:0.31em;border-bottom:1px dashed var(--line)}
.tm-home-ai-h b{color:var(--blue);font-size:0.85em}
.tm-home-ai-s{margin-left:auto;color:var(--muted);font-size:0.69em}
.tm-home-ai-b{font-size:0.8em;line-height:1.65;color:var(--text);white-space:pre-wrap;word-break:break-word}
.tm-home-ai-b.wait{color:var(--muted)}

/* 🔴 「支持工单」按钮点开后的**「支持对象」面板**（需求方 2026-09-27：工单管理列表检索区）
   —— 浮层（`position:fixed`，位置由 JS 按按钮实体位置算），不占工具栏布局、不进任何页面模板串。 */
.tk-sup-pop{position:fixed;z-index:70;width:220px;max-height:320px;overflow:auto;padding:6px;box-sizing:border-box;
  border:1px solid var(--line2);border-radius:10px;background:#fff;box-shadow:0 10px 26px rgba(15,34,51,.16)}
.tk-sup-pop .h{padding:4px 8px 6px;font-size:12px;font-weight:700;color:var(--muted)}
.tk-sup-pop .it{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:7px 9px;
  border-radius:7px;font-size:13px;color:var(--text);cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.tk-sup-pop .it:hover{background:var(--soft)}
.tk-sup-pop .it.on{background:var(--accent-soft);color:var(--blue);font-weight:700}
.tk-sup-pop .it .n{flex:0 0 auto;font-size:11.5px;color:var(--muted)}
.tk-sup-pop .it.on .n{color:var(--blue)}
.tk-sup-pop .it.clr{color:var(--muted)}
.tk-sup-pop .sp{height:1px;margin:5px 6px;background:var(--line2)}
.tk-sup-pop .ld{padding:8px 9px;font-size:12.5px;color:var(--muted)}

/* 🔴 驻场条目的状态标（需求方 2026-09-27：工单记录里同时显示驻场）—— 与 H5 `.tki-s.duty` 同一套配色。 */
.tm-tki-s.duty{background:#eef0ff;color:#4a4fc0}

/* ===== 终端管理·模拟手机：工单详情的**流转按钮**与**动作弹层**（需求方 2026-09-27「3要处理」）=====
   与真机 H5 同一口径：按钮由服务端 `acts` 算（`.tm-svc-acts` 两列网格，只有一颗时整宽）；
   动作弹层复用预览端自己的 `tmPvShow()`（`.tm-pv*`），字段与本文件 `.tm-svc-btn` 同一套观感。 */
.tm-svc-acts{flex:0 0 auto;display:grid;grid-template-columns:1fr 1fr;gap:0.31em;margin-top:0.31em}
.tm-svc-acts.one{grid-template-columns:1fr}
.tm-svc-acts .tm-svc-btn{width:auto}
.tm-svc-btn.pri{background:var(--blue);color:#fff}
.tm-svc-btn.pri:active{filter:brightness(.94)}
.tm-ta-f{margin-bottom:0.4em}
.tm-ta-f .tm-ta-l{margin-bottom:0.2em;font-size:0.62em;color:var(--muted)}
.tm-ta-f input,.tm-ta-f textarea{width:100%;box-sizing:border-box;padding:0.42em 0.5em;border:1px solid var(--line);
  border-radius:0.45em;background:var(--soft2);color:var(--text);font:inherit;font-size:0.66em;line-height:1.6;outline:0}
.tm-ta-f textarea{resize:none}
.tm-ta-f select{width:100%;box-sizing:border-box;padding:0.42em 0.5em;border:1px solid var(--line);
  border-radius:0.45em;background:var(--soft2);color:var(--text);font:inherit;font-size:0.66em;outline:0}
.tm-ta-ex{display:flex;align-items:center;gap:0.3em;margin:0.1em 0 0.4em;font-size:0.6em;color:var(--muted)}
.tm-ta-ft{display:flex;gap:0.46em;margin-top:0.5em}
.tm-ta-b{flex:1 1 auto;height:2.1em;border:0;border-radius:0.5em;background:var(--soft);color:var(--text);
  font:inherit;font-size:0.72em;cursor:pointer}
.tm-ta-b.pri{background:var(--blue);color:#fff}
.tm-hp{display:flex;flex-direction:column;gap:0.3em;max-height:9em;overflow:auto}
.tm-hp-it{display:flex;align-items:center;justify-content:space-between;gap:0.35em;padding:0.42em 0.5em;
  border:1px solid var(--line);border-radius:0.45em;background:var(--soft2);font-size:0.66em;cursor:pointer}
.tm-hp-it:active{background:var(--soft)}
.tm-mini{font-size:0.62em;color:var(--muted)}
/* 「建单时的 AI 建议」列表（解决 / 未解决弹层；与真机 `.ta-sug-*` 同一套内容与手感） */
.tm-ta-sh{display:flex;align-items:baseline;gap:0.3em;margin:0.5em 0 0.3em;font-size:0.64em;font-weight:700;color:var(--text)}
.tm-ta-sug{display:flex;flex-direction:column;gap:0.4em;max-height:9em;overflow:auto}
.tm-ta-sit{padding:0.45em 0.5em;border:1px solid var(--line);border-radius:0.45em;background:var(--soft2)}
.tm-ta-st{display:flex;align-items:center;gap:0.3em;font-size:0.66em;font-weight:700;color:var(--text);
  word-break:break-word}
.tm-ta-sbdg{flex:0 0 auto;padding:0 0.35em;border-radius:999px;background:#e6f7f3;color:#0f8f7a;
  font-size:0.55em;font-weight:700;white-space:nowrap}
.tm-ta-sbdg.model{background:#eef0ff;color:#4a4fc0}
.tm-ta-sv{margin-top:0.2em;max-height:3.2em;overflow:hidden;font-size:0.62em;line-height:1.6;color:var(--muted);
  white-space:pre-wrap;word-break:break-word}
.tm-ta-sf{display:flex;align-items:center;gap:0.4em;margin-top:0.35em}
.tm-ta-sb{padding:0.2em 0.5em;border:1px solid var(--line2);border-radius:0.4em;background:#fff;color:var(--blue);
  font:inherit;font-size:0.62em;font-weight:600;cursor:pointer}
.tm-ta-sb[data-used="1"]{color:var(--muted);border-color:var(--line);background:var(--soft)}
.tm-ta-smsg{word-break:break-word}
.tm-ta-exwrap{margin-top:0.15em}
/* 「重复工单」检索行（预览端；与真机 `.dup*` 同一套观感） */
.tm-dup{display:flex;flex-direction:column;gap:0.3em;width:100%}
.tm-dup-in{width:100%;box-sizing:border-box;padding:0.42em 0.5em;border:1px solid var(--line2);
  border-radius:0.45em;background:#fff;color:var(--text);font:inherit;font-size:0.66em;outline:0}
.tm-dup-res{display:none;border:1px solid var(--line);border-radius:0.45em;overflow:hidden;background:#fff}
.tm-dup-res.on{display:block}
.tm-dup-it{display:flex;align-items:center;gap:0.4em;padding:0.4em 0.5em;border-bottom:1px solid var(--line);
  font-size:0.64em;cursor:pointer}
.tm-dup-it:last-child{border-bottom:0}
.tm-dup-it:active{background:var(--soft)}
.tm-dup-it.none{color:var(--muted);cursor:default}
.tm-dup-it b{flex:0 0 auto;color:var(--blue);white-space:nowrap}
.tm-dup-it i{flex:1 1 auto;min-width:0;overflow:hidden;font-style:normal;text-overflow:ellipsis;
  white-space:nowrap;color:var(--text)}
.tm-dup-it em{flex:0 0 auto;font-style:normal;font-size:0.9em;color:var(--muted);white-space:nowrap}
.tm-dup-pick{font-size:0.62em;line-height:1.6;color:var(--muted);word-break:break-word}
.tm-dup-pick b{color:var(--text)}
.tm-dup-pick a{color:var(--blue);text-decoration:none}
/* 受理态说明条（预览端；与真机 `.acc-hint` 同一套观感） */
.tm-qkacc{margin:0 0 0.45em;padding:0.5em 0.6em;border:1px solid #cfe3ff;border-radius:0.5em;
  background:#f2f8ff;color:#2b6cb0;font-size:0.62em;line-height:1.6}
.tm-qkacc b{color:var(--text)}
.tm-qkacc a{margin-left:0.4em;color:#b4333f;text-decoration:none}

