/* ============================================================================
 * EX-17 应用开发管理系统 —— 界面样式
 *
 * 2026-09-20 紧凑化整改（HOW21 §4.26「界面紧凑化与信息密度」通则）：
 *   用户反馈"胶囊和卡片太大了、段落行距偏大，界面需要更紧凑，像 EX-12 那样"。
 *   实测整改前的问题（桌面 1600×1000 实测）：
 *     · .card padding 14px + .card-desc 写死 min-height:38px → 卡片被撑到 ~135px 高，
 *       一屏只能放 3 行卡片，大片空白；
 *     · 状态胶囊各写各的（.status/.tag/.code/.hint-badge/.admin-toc a padding 1~2px 8~12px、
 *       圆角 9~11px、无统一高度），视觉重量压过正文；
 *     · body 没有设 line-height，段落/表格 margin 偏大（h3 22px、table 20px、section-box 20px）；
 *     · th,td padding 8px 10px、.btn padding 6px 14px，信息密度偏低。
 *   整改口径：数值一律走 --wl-* token（事实源 web-common\wl-compact.css，HOW21 §4.26），
 *   本文件只做「应用特有组件」的紧凑化，通用组件由 wl-compact.css 负责；token 带回落值，
 *   单独加载本文件也不会退回旧尺寸。
 *   触屏点按 ≥40px 由 wl-mobile.css 在 ≤900px 兜底（桌面紧凑 ≠ 手机变小）。
 *
 * 移动/折叠屏适配（HOW21 §4.18）：共享基线 wl-mobile.css/wl-mobile.js 为唯一事实源，
 *   本文件只保留应用特有的窄屏微调，且整段包在 @media screen and (…) 内（打印媒体不受影响）。
 * ============================================================================ */

/* ============ 基础：hidden 属性必须真的隐藏（2026-10-14 事故修复）============
 * 事故现象：业务方在门户点「公司／部门」筛选，按钮高亮与「当前筛选」文案都对，
 *   但卡片一张不少、部门按钮一个不少 —— 看起来"点了没反应"。
 * 根因：筛选脚本用 `el.hidden = true` 藏元素，而 UA 的 `[hidden]{display:none}`
 *   只是**用户代理样式**，会被任何作者样式里的 display 盖过：
 *   本文件 `.card{display:flex}`（118 行）、`.fbtn{display:inline-flex}`（501 行）
 *   ⇒ 属性写了 true，计算样式仍是 flex，元素照旧占位显示。
 * 修法：这一条把 [hidden] 提升到作者样式之上。用 !important 是必要的 ——
 *   本文件之后还加载 wl-compact.css / wl-table.css 等共享件，同特异性无法保证胜出。
 * 影响面（2026-10-14 普查过：EX-17 全部 7 个页面共 64 个 [hidden] 元素）：
 *   · .card / .fbtn —— 本次要修的筛选；
 *   · #wlMask（.wl-mask 自身已 display:none，且显示时代码会先 hidden=false）；
 *   · .wl-tbl-hint（.wl-tbl-bar 里的空占位 span，本来就是隐藏的）。
 *   即：除了本该隐藏的，没有元素会因此消失；页面加载态 64 个 hidden 元素
 *   在修复前后"渲染可见数"均为 0（证据 _scratch\ex17_hidden_census\）。
 * 同源教训（本工作区已记过名）：wl-ask.js 的注释里写着"不要用 [hidden] 属性"——
 *   那条经验当时只落在那个共享件上，应用侧没有兜底，于是门户筛选中招。
 *   ⚠ 自定义元素若要与本规则共存：不要给 [hidden] 元素写 display，改用 class 开关。 */
[hidden]{ display:none !important; }

/* ============ WLIT-HOW21 4.2 双主题 (how21-theme-dark) ============ */
:root{
  --bg:#f4f6f8; --panel:#ffffff; --line:#dde3ea; --line2:#c6cdd6;
  /* 字色四级。2026-10-02 收紧：原 #555/#888/#999 在 #fff / #eef2f6 上实测
     --muted 3.15:1、--faint 2.85:1（11px 正文），都低于 §4.25 的 4.5 底线；
     现按"最浅也不得浅于 #6b6b6b"重排四级，实测最差组合（#faint on --th-bg）4.74:1。 */
  --text:#222222; --text2:#4d4d4d; --muted:#5c5c5c; --faint:#6b6b6b;
  --nav:#1f3a5f; --nav2:#2b4d7a; --navlink:#ffffff; --primary:#1f3a5f; --primary-h:#2b4d7a;
  --th-bg:#eef2f6; --hover-bg:#f7f9fb; --input-bg:#ffffff; --chip-bg:#eef2f6;
  /* ── 紧凑化与信息密度（HOW21 §4.26）────────────────────────────────────
     数值来源：web-common\wl-compact.css 的 --wl-* token；这里给出同名回落值，
     使本文件即使单独存在（没引 wl-compact.css）也保持紧凑，不会退回旧的大尺寸。 */
  --gap:var(--wl-gap, 12px); --gap-sm:var(--wl-gap-sm, 8px);
  --pad-card:var(--wl-pad-card, 10px 12px);
  --radius:var(--wl-radius, 8px); --radius-sm:var(--wl-radius-sm, 6px);
  --ctrl-h:var(--wl-ctrl-h, 32px); --pill-h:var(--wl-pill-h, 16px); --pill-fs:var(--wl-pill-fs, 11px);
  --fs:var(--wl-fs, 13.5px); --lh:var(--wl-line, 1.45);
}
[data-theme="dark"]{
  --bg:#12161f; --panel:#1a2029; --line:#2a3342; --line2:#39465a;
  /* 深色主题四级：原 #8b97a8/#6b7687 在 --panel:#1a2029 上实测 5.53:1 / 3.84:1，
     最浅一级不达标，故整体上提（--faint 5.55:1，--muted 7.56:1）。 */
  --text:#e6ebf3; --text2:#c6cfdb; --muted:#a7b1c0; --faint:#8d97a6;
  --nav:#0e1726; --nav2:#16233a; --navlink:#ffffff; --primary:#3f6fb5; --primary-h:#527fbf;
  --th-bg:#202836; --hover-bg:#1f2733; --input-bg:#151b25; --chip-bg:#202836;
}
/* 状态胶囊的深色配色见下方 .status 段落（浅底 + 同色亮字），此处不再统一写 color:#fff */
[data-theme="dark"] .topbar{background:var(--nav)}
[data-theme="dark"] .login-body{background:linear-gradient(135deg,#0e1726,#16233a)}
[data-theme="dark"] .btn{background:var(--primary)}
[data-theme="dark"] .btn:hover{background:var(--primary-h)}
[data-theme="dark"] .btn.gray{background:#4a5568}
[data-theme="dark"] .dept-tag{background:var(--primary)}
[data-theme="dark"] input[type=text],input[type=password],input[type=number],select,textarea{background:var(--input-bg);color:var(--text)}
[data-theme="dark"] .dept-picker-input,.dept-picker-panel{background:var(--input-bg)}
[data-theme="dark"] .thread .reply{background:var(--hover-bg)}
[data-theme="dark"] .card .code{background:var(--chip-bg);color:var(--muted)}
/* 亮色标签底色调暗 */
[data-theme="dark"] .tag.bug{background:rgba(192,57,43,.15);color:#e8837a}
[data-theme="dark"] .tag.suggestion{background:rgba(46,134,222,.15);color:#7db6e8}
[data-theme="dark"] .tag.pending{background:rgba(183,149,11,.15);color:#d4bc55}
[data-theme="dark"] .tag.processing{background:rgba(202,111,30,.15);color:#e09a5a}
[data-theme="dark"] .tag.resolved{background:rgba(30,132,73,.15);color:#5fc489}
/* ============ end HOW21 4.2 ============ */

* { box-sizing: border-box; margin: 0; padding: 0; }
body { font-family: "等线", "DengXian", "Microsoft YaHei", sans-serif; background: var(--bg); color: var(--text);
  font-size: var(--fs); line-height: var(--lh); }
a { color: #1a6fb5; text-decoration: none; }
a:hover { text-decoration: underline; }

/* ── 顶栏：桌面高度压到 40px 量级（原 padding 10px → 20+20+内容 ≈ 52px）── */
.topbar { display: flex; align-items: center; gap: 14px; background: var(--primary); color: #fff;
  padding: 6px 14px; position: sticky; top: 0; z-index: 10; flex-wrap: wrap; }
.topbar .brand { font-size: 14.5px; font-weight: bold; display: flex; align-items: center; gap: 6px; }
.brand-logo { height: 24px; }
.login-logo { height: 56px; display: block; margin: 0 auto 10px; }
.topbar .links { display: flex; gap: 12px; flex: 1; flex-wrap: wrap; }
.topbar .links a { color: var(--navlink); font-size: 13px; }
.topbar .links a:hover { color: #fff; text-decoration: none; }
.topbar .user { color: var(--navlink); font-size: 12.5px; }
.topbar .user a { color: #fff; margin-left: 8px; }
/* ★★ 2026-10-13（业务方口径：顶栏只留"点用户名弹确认层"，去掉独立的「退出」链接）：
   `html.wl-chip-ok` 由共享件 wl-help.js 在**成功**把用户名标成可点胶囊时挂上（见该文件 wlMarkUserChip）。
   所以这里的效果是：脚本正常 ⇒ 顶栏不再有「退出」（点用户名即可）；
   脚本没加载/报错 ⇒ 类名不在 ⇒ 「退出」照旧显示 —— **不会把用户锁死在页面里**。 */
html.wl-chip-ok .topbar .user a.wl-logout-fallback { display: none; }
/* EX 编码与版本徽标：原来的样式写在 base.html 行内（行内样式会压过 CSS，
   窄屏适配必须靠 !important 才盖得住），现收进样式表统一按 §4.26 胶囊尺寸走。 */
.topbar .wl-ex, .topbar .wl-ver { display: inline-flex; align-items: center; height: var(--pill-h);
  padding: 0 6px; font-size: var(--pill-fs, 11px); font-weight: 600; letter-spacing: .4px;
  border-radius: 4px; margin-left: 6px; }
.topbar .wl-ex { color: #7fb3ff; border:0; }
.topbar .wl-ver { color: #9db1d8; border:0; text-decoration: none; }
.topbar .wl-ver:hover { color: #fff; border-color: #fff; text-decoration: none; }
.badge { background: #e74c3c; color: #fff; border-radius: 9px; padding: 0 5px; font-size: 11px; margin-left: 4px; }
/* 通知页「未读」标签（2026-09-25）：.badge 从只读标记升级为可点按钮 —— 点一下即标记该条已读。
   必须显式抹掉浏览器默认按钮外观（灰边框/系统字体/系统底色），否则和原来的红点标签不是一个样子；
   line-height 用 1.5 保持 11px 字号下的胶囊高度与原标签一致。 */
button.badge { border: 0; cursor: pointer; font-family: inherit; line-height: 1.5;
               -webkit-appearance: none; appearance: none; }
button.badge:hover { background: #c0392b; }
button.badge:disabled { opacity: .6; cursor: default; }

/* HOW21 §4.1：按 1920×1080 设计，主区加宽（1780 上限 + 居中），超宽屏居中留白 */
.container { max-width: 1780px; width: 100%; margin: 12px auto 24px; padding: 0 14px; }
h2 { margin: 6px 0; font-size: 16.5px; line-height: 1.3; }
h3 { margin: 14px 0 6px; font-size: 15px; line-height: 1.3; border-left: 3px solid var(--primary); padding-left: 8px; }
.sub { color: var(--text2); margin-bottom: 8px; }

/* ── 应用门户卡片：间距 14→12px、内边距 14→10/12px、去掉写死的 min-height ──
   卡片高度由**本行最高的一张**决定（grid 默认 stretch），而描述文字长短不一
   （最长 6 行），会把整行卡片一起撑高到 207px、底部留一大片空白 —— 实测结论：
   卡片高度才是"一屏能看几个应用"的决定因素。故描述**限 2 行**（超出省略号），
   全文在悬停 title 与详情页里都能看到，不丢信息。 */
.cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(200px,100%), 1fr)); gap: var(--gap); }
.card { background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius);
  padding: var(--pad-card); display: flex; flex-direction: column; gap: 4px; }
.card-head { display: flex; justify-content: space-between; align-items: center; gap: 5px;
  flex-wrap: wrap; min-height: 0; }
/* 右侧胶囊组：靠右排列，放不下时内部换行而不是把编号挤走 */
.card-head > span:last-child { display: flex; align-items: center; gap: 4px; flex-wrap: wrap;
  justify-content: flex-end; min-width: 0; }
.card-head > span:last-child > span { margin: 0; }
.code { font-size: var(--pill-fs, 11px); color: var(--muted); background: var(--th-bg); padding: 0 6px;
  height: var(--pill-h); display: inline-flex; align-items: center; border-radius: 4px; }
/* ── 应用图标（v1.63.0，造型 A 城垛砖）────────────────────────────────────────
   图标与编号并成一组，是 .card-head 的第一个 flex 子项。
   为什么不把 34px 图标塞进 .code 药丸：那药丸高 --pill-h（18px），塞进去会把它撑破，
   一行卡片的基线会全乱（这也是"先量后改"量出来的：.code 的 height 是显式的）。 */
.head-id { display: inline-flex; align-items: center; gap: 5px; min-width: 0; flex: 0 0 auto; }
.head-id .wl-ic { flex: 0 0 auto; display: block; }
/* 顶栏品牌区里的「本应用图标」：紧跟公司品牌标，与 26px 高的品牌标垂直居中。
   ⚠ v1.64.0（造型乙 + 深底亮坡）必加这圈浅色描边：新图标是**深底**，
   而顶栏底色是深藏蓝 —— 深底压深底，图标边界会糊在一起（实测过）。
   加 1.5px 半透明白环 + 一点外投影后，图标在深色顶栏上才立得住。 */
.brand-appicon { display: inline-flex; align-items: center; margin: 0 7px 0 6px; vertical-align: middle; }
.brand-appicon .wl-ic { display: block; border-radius: 7px;
  box-shadow: 0 0 0 1.5px rgba(255, 255, 255, .55), 0 1px 3px rgba(0, 0, 0, .45); }
@media screen and (max-width: 900px) {
  /* 手机档顶栏空间紧张：本应用图标缩到 20px，仍看得出垛口与色，但不挤走应用名 */
  .brand-appicon { margin: 0 5px 0 4px; }
  .brand-appicon .wl-ic { width: 20px; height: 20px; }
}
/* 应用卡片：端口号显示在 EX 编号后面（同一芯片内弱化，等宽数字避免相邻卡片对不齐） */
.code-port { margin-left: 4px; opacity: .82; font-variant-numeric: tabular-nums; letter-spacing: .2px; }
/* 信息部管理台：页标题行 + 页内目录 + 段落标题旁的「回到首页」按钮 */
.page-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; flex-wrap: wrap; }
.page-head h2 { margin: 0; }
.admin-toc { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin: 0 0 10px;
  padding: 6px 10px; background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius); font-size: 12.5px; }
.admin-toc .toc-label { color: var(--faint); }
.admin-toc a { color: var(--text2); text-decoration: none; background: var(--th-bg);
  border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 1px 8px; }
.admin-toc a:hover { color: var(--text); border-color: var(--line2); text-decoration: none; }
.admin-toc .toc-tip { color: var(--faint); font-size: 11.5px; }
.sec-anchor { scroll-margin-top: 52px; }
.sec-home { float: right; margin-left: 8px; font-weight: 400; }
/* 状态胶囊：统一到 §4.26 的 --pill-h 与圆角（原 padding 2px 8px / 圆角 10px）
   ── 2026-10-02 改「浅底 + 同色深字」（与上方 .tag 一致，§4.27 方向取极值）：
   原做法是白字压饱和中色调底，实测 11px 正文对比度只有 2.19~3.82，七种状态全部低于 4.5；
   且 apps.status 实际有 approved 这个值，CSS 里却没有 .st-approved，
   于是 `.status{color:#fff}` 落到卡片白底上 → 白字白底、对比度 1.00，字完全看不见。
   现在两件事一起解决：① 给 .status 一个**兜底底色**，将来再加状态值也不会变隐形；
   ② 全部状态改成浅色同色底 + 深色同色字，对比度一律 > 4.5。 */
.status { font-size: var(--pill-fs, 11px); height: var(--pill-h); display: inline-flex; align-items: center;
  padding: 0 6px; border-radius: 4px; background: var(--chip-bg, #eef2f6); color: #414a4a; }
.st-released, .st-approved { background: rgba(39,174,96,.14); color: #1a5e37; }
.st-maintaining { background: rgba(46,134,222,.14); color: #14508a; }
.st-developing { background: rgba(243,156,18,.20); color: #6f4704; }
.st-internal_test { background: rgba(142,68,173,.14); color: #5f2977; }
.st-fixing { background: rgba(230,126,34,.20); color: #6f3b04; }
.st-pending_accept { background: rgba(231,76,60,.14); color: #8a2318; }
.st-archived { background: rgba(127,140,141,.20); color: #3b4344; }
[data-theme="dark"] .status { background: rgba(255,255,255,.10); color: #c8d1dd; }
[data-theme="dark"] .st-released, [data-theme="dark"] .st-approved { background: rgba(39,174,96,.18); color: #6fd39a; }
[data-theme="dark"] .st-maintaining { background: rgba(46,134,222,.18); color: #8cc0ee; }
[data-theme="dark"] .st-developing { background: rgba(243,156,18,.20); color: #e8bd68; }
[data-theme="dark"] .st-internal_test { background: rgba(142,68,173,.22); color: #cfa6e2; }
[data-theme="dark"] .st-fixing { background: rgba(230,126,34,.20); color: #eeae72; }
[data-theme="dark"] .st-pending_accept { background: rgba(231,76,60,.20); color: #ee9489; }
[data-theme="dark"] .st-archived { background: rgba(149,165,166,.20); color: #b9c5c6; }
.card-title { font-size: 14px; font-weight: bold; line-height: 1.3;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 原来写死 min-height:38px 把每张卡片都撑高；改为不定高 + 限 2 行，
   卡片高度由内容决定而非写死，行与行之间也不会再出现大片空白。 */
.card-desc { color: var(--text2); font-size: 12.5px; line-height: 1.4; min-height: 0;
  display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; }
.card-actions { margin-top: 2px; display: flex; gap: 6px; flex-wrap: wrap; }
.card-meta { font-size: 10.5px; color: var(--faint); line-height: 1.3;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* 应用门户卡片排序工具条（EX-17 门户） */
.sortbar { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; margin: 0 0 8px; }
.sortbar-label { font-size: 12.5px; color: var(--text2); }
.sortbar .sbtn { background: var(--panel); border: 1px solid var(--line2); color: var(--text2);
  border-radius: var(--radius-sm); padding: 3px 10px; font-size: 12.5px; cursor: pointer; }
.sortbar .sbtn:hover { border-color: var(--primary); color: var(--primary); }
.sortbar .sbtn.active { background: var(--primary); border-color: var(--primary); color: #fff; }
.sortbar .sbtn.dir { min-width: 66px; }
.sortbar-tip { font-size: 11.5px; color: var(--faint); }
.btn { display: inline-block; background: var(--primary); color: #fff; padding: 4px 10px;
  border-radius: var(--radius-sm); font-size: 12px; border: none; cursor: pointer; line-height: 1.3; }
.btn:hover { background: var(--primary-h); text-decoration: none; }
.btn.small { padding: 2px 8px; font-size: 11.5px; }
.btn.gray { background: #5d6d7e; }   /* 改前 #7f8c8d：白字只有 3.48:1，13px 正文不达 AA */
.btn.red { background: #c0392b; }
.btn.green { background: #27ae60; }

table { width: 100%; border-collapse: collapse; background: var(--panel); margin: 6px 0 12px; }
th, td { border: 1px solid var(--line); padding: 5px 8px; text-align: left; font-size: 12.5px; vertical-align: top; line-height: 1.4; }
th { background: var(--th-bg); }

form label { display: block; margin: 6px 0 3px; font-weight: bold; font-size: 12.5px; }
input[type=text], input[type=password], input[type=number], select, textarea {
  width: 100%; padding: 5px 8px; border: 1px solid var(--line2); border-radius: var(--radius-sm);
  font-size: 13px; font-family: inherit; line-height: 1.4;
}
textarea { min-height: 56px; }
.form-row { margin-bottom: 4px; }
.hint { color: var(--faint); font-size: 11.5px; margin-top: 4px; }

.thread { background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius);
  padding: var(--pad-card); margin-bottom: var(--gap); }
.thread .meta { font-size: 11.5px; color: var(--muted); margin-bottom: 4px; }
.thread .content { margin: 4px 0; line-height: 1.45; }
.thread .reply { background: var(--hover-bg); border-left: 3px solid var(--primary); padding: 6px 8px; margin-top: 6px; font-size: 12.5px; }
/* v1.61.56：回复的「回复人 + 时间」独立成行（与 AI 气泡的 .fb-who 同一版式），正文改块级
   .reply-text —— ① 行内盒 max-height 不生效，收短对行内 <span> 等于没写；② 时间提到正文之上，
   默认收短态下时间线仍然看得见（业务方要的正是「时间线和条理都看得清楚」）。 */
.thread .reply .reply-meta { font-size: 11.5px; color: var(--muted); margin-bottom: 2px; }
.tag { display: inline-flex; align-items: center; height: var(--pill-h); font-size: var(--pill-fs, 11px);
  padding: 0 6px; border-radius: 4px; margin-left: 6px; }
.tag.bug { background: #fdecea; color: #c0392b; }
.tag.suggestion { background: #eaf4fd; color: #2e86de; }
.tag.pending { background: #fef9e7; color: #b7950b; }
.tag.processing { background: #fdebd0; color: #ca6f1e; }
.tag.resolved { background: #eafaf1; color: #1e8449; }

.login-body { display: flex; align-items: center; justify-content: center; min-height: 100vh; background: linear-gradient(135deg,var(--nav),var(--nav2)); }
.login-box { background: var(--panel); padding: 24px; border-radius: 10px; width: 360px; box-shadow: 0 10px 30px rgba(0,0,0,.2); }
.login-box h1 { font-size: 19px; text-align: center; margin-bottom: 4px; }
.login-box .sub { text-align: center; }
.login-box button { width: 100%; margin-top: 12px;
  /* 2026-10-02：紧凑基线把按钮压到 18px 高，宽屏上就是一条细线、不好点 —— 登录按钮最低 38px、
     输入框最低 34px、字号 14px（手机档由 wl-mobile.css 的 40px 触控目标接管，不受影响）。 */
  min-height: 38px; font-size: 14px; padding: 8px 12px; }
.login-box input[type=text], .login-box input[type=password] { min-height: 34px; font-size: 14px; }

.flash { position: fixed; top: 48px; right: 16px; padding: 8px 14px; border-radius: 6px; color: #fff; z-index: 99; max-width: 360px; font-size: 13px; }
.flash.ok { background: #27ae60; }
.flash.err { background: #c0392b; }
.login-box .flash { position: static; margin-bottom: 8px; }

.section-box { background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius);
  padding: var(--pad-card); margin-bottom: var(--gap); }
.section-box h4 { margin-bottom: 6px; font-size: 14px; }
.progress-bar { background: var(--th-bg); height: 6px; border-radius: 3px; overflow: hidden; width: 110px; display: inline-block; vertical-align: middle; }
.progress-bar i { display: block; height: 100%; background: #27ae60; }
.inline-form { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
.inline-form select, .inline-form input[type=number] { width: auto; }
.muted { color: var(--faint); font-size: 11.5px; }

/* 申请表单:逐条列表 / 部门多选 / 多行展示 */
.item-row { display: flex; gap: 6px; margin: 4px 0; }
.item-row input { flex: 1; }
.dept-picker { position: relative; max-width: 420px; }
.dept-picker-input { border: 1px solid var(--line2); border-radius: var(--radius-sm); padding: 5px 8px; cursor: pointer; background: var(--panel); display: flex; justify-content: space-between; align-items: center; min-height: 20px; }
.dept-picker-input .caret { color: var(--faint); }
.dept-picker-panel { position: absolute; top: 100%; left: 0; right: 0; z-index: 20; background: var(--panel); border: 1px solid var(--line2); border-radius: var(--radius-sm); max-height: 220px; overflow: auto; box-shadow: 0 4px 12px rgba(0,0,0,.12); padding: 4px 0; }
.dept-opt { display: block; padding: 5px 10px; cursor: pointer; font-size: 12.5px; }
.dept-opt:hover { background: var(--th-bg); }
.dept-tags { margin-top: 4px; display: flex; flex-wrap: wrap; gap: 5px; }
.dept-tag { background: var(--primary); color: #fff; border-radius: 4px; height: var(--pill-h);
  display: inline-flex; align-items: center; padding: 0 6px; font-size: var(--pill-fs, 11px); cursor: pointer; }
.dept-tag:hover { background: #c0392b; }
.multiline { white-space: pre-line; line-height: 1.45; }

/* ============ 反馈 AI 追问 + 附件（v1.57，2026-09-30）====================
 * 业务方两条硬要求：
 *   ① 「界面支持分行，避免文字一段铺满」——所有反馈/回答/AI 正文一律 pre-line（保留换行），
 *      并且 .fb-text 限制单行长度（max-width + 行高），长段自动折行而不是铺满整屏；
 *   ② AI 输出的「需求澄清单」本身按 一~六 节 + 「· 」短行生成（提示词里写死），
 *      这里只负责把它按等宽块渲染出来，不做二次压缩。
 * 颜色一律走 token，暗色主题自动跟随（见上方 [data-theme="dark"] 段）。
 */
.thread .content, .thread .reply .multiline { white-space: pre-line; }
.fbai-tag { background: var(--chip-bg); color: var(--primary); }
.fb-atts { margin: 6px 0 2px; display: flex; flex-wrap: wrap; gap: 6px; }
.fb-att { display: inline-flex; align-items: center; gap: 5px; background: var(--hover-bg);
  border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 2px 7px; font-size: 12px; }
.fb-att a { text-decoration: none; }
.fb-att-del { color: var(--faint); text-decoration: none; padding: 0 2px; }
.fb-att-del:hover { color: #c0392b; }
.fb-ai { margin-top: 8px; border: 1px dashed var(--line2); border-radius: var(--radius);
  padding: 8px 10px; background: var(--hover-bg); }
.fb-ai-head { font-size: 12px; color: var(--text2); display: flex; justify-content: space-between;
  gap: 8px; flex-wrap: wrap; }
.fb-ai-state { color: var(--faint); font-size: 11.5px; }
.fb-ai-body { margin-top: 6px; }
.fb-ai-empty { margin: 4px 0; }
.fb-msg { border-radius: var(--radius-sm); padding: 6px 8px; margin: 6px 0; max-width: 92%; }
.fb-msg.ai { background: var(--panel); border-left: 3px solid var(--primary); }
.fb-msg.user { background: var(--panel); border-left: 3px solid #27ae60; margin-left: auto; }
.fb-who { font-size: 11px; color: var(--faint); margin-bottom: 3px; }
.fb-text { white-space: pre-line; line-height: 1.55; font-size: 12.8px; }
.fb-summary { background: var(--panel); border: 1px solid var(--primary);
  border-left: 4px solid var(--primary); border-radius: var(--radius-sm); padding: 8px 10px; margin: 8px 0; }
.fb-sum-title { font-size: 12.5px; font-weight: 600; color: var(--primary); margin-bottom: 5px; }
.fb-ai-actions { margin-top: 6px; }
.fb-ai-actions textarea { min-height: 64px; }
.fb-ans-hint { font-size: 11.5px; color: var(--faint); margin: 4px 0; }
.fb-ai-busy { margin-top: 6px; color: var(--primary); font-size: 12px; }
.fb-ai-busy::after { content: ''; display: inline-block; width: 8px; }
.fb-ai-det { margin-top: 6px; }
.fb-ai-det > summary { cursor: pointer; font-size: 11.5px; color: var(--faint); }
.fb-ai-det[open] > summary { margin-bottom: 4px; }
@media screen and (max-width: 900px) {
  .fb-msg { max-width: 100%; }
  .fb-ai { padding: 6px 7px; }
}

/* ============ 反馈正文「默认收短 + 一键展开/收起」（v1.61.56~58，2026-10-09）============
 * 业务方原话：「这类反馈页面中，有些一轮反馈的文字篇幅太大了会看得很吃力。因此，需要增加一个
 *   按钮来实现以下功能：① 默认展示篇幅有限；② 点击按钮可以展开，再次点击可以收缩。这样的话，
 *   所有的评论反馈占用的篇幅都有限，整个看下来可以把时间线和条理都看得清楚。」
 *   （追问一轮后他追加一句：「AI 问答那一箱也折掉」。）
 * 口径（四条，配套判据见 _scratch\ex17_fbclamp_probe.py）：
 *   ① 默认只看 6 行 —— 高度＝该块实测行高 ×6，由 static/ex17-fbclamp.js 写进 --fb-clamp-h
 *      （不写死像素：正文字号在 .content/.reply/.fb-text 三种块里各不同）；
 *   ② 只有**真的值得收**的块才出现「展开全文」按钮 —— 短反馈不出按钮，也不改外观；
 *   ③ JS 没跑 / 被禁用 ⇒ 不加类、不裁切（功能可灭、内容不失）；打印一律展开，避免打印稿被截半。
 *   ④ AI 问答**整箱**再加一层：默认只留最新 2 条，箱顶出「展开全部 N 条问答」。
 * 【前提】被收短的必须是**块级盒**：max-height/overflow 对非替换行内盒不生效（回复正文原为
 *   行内 <span>，第一版因此完全没被裁到 —— 已改成块级 .reply-text）。
 * 为什么用 mask 而不是在底部盖一层渐变：同一块底色有三种（--panel / --hover-bg / 气泡），
 * 盖色会串味、亮暗主题还各要一套；mask 让文字自己淡出，任何底色都对，且不占布局。
 */
.fb-clamp {
  max-height: var(--fb-clamp-h, 120px);
  overflow: hidden;
  -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 26px), transparent);
          mask-image: linear-gradient(to bottom, #000 calc(100% - 26px), transparent);
}
/* 点按目标 ≥36px（§4.18 口径；≤900px 由 wl-mobile.css 的 button 安全网抬到 40px）
   .fb-more = 单块「展开全文」；.fb-fold = AI 问答整箱「展开全部 N 条问答」（同一个外观，两个类） */
.fb-more, .fb-fold {
  display: inline-flex; align-items: center; min-height: 36px;
  margin: 2px 0 4px; padding: 0 10px;
  font: inherit; font-size: 11.5px; line-height: 1;
  color: var(--primary); background: transparent;
  border: 1px solid var(--line2); border-radius: var(--radius-sm); cursor: pointer;
}
.fb-more:hover, .fb-fold:hover { background: var(--hover-bg); }
.fb-more:focus-visible, .fb-fold:focus-visible { outline: 2px solid var(--primary); outline-offset: 1px; }
/* AI 问答整箱折叠（v1.61.58）：默认只留最新 2 条，早前的标 .fb-hidden；显示与否只由父类
   .fb-ai-fold 一个开关决定（标记是一次性的，不会被反复点成两套状态）。 */
.fb-ai-fold .fb-hidden { display: none; }
.fb-fold { margin: 2px 0 6px; }        /* 站在箱顶那颗（被收起的问答之上） */
/* 反馈「逐条回复」的层级缩进与回复框（2026-10-09；用户侧 app_detail 与信息部侧 admin_it 共用，
   逻辑在 static/ex17-fbreply.js，这里只放外观——两处各写一份就会分叉）。 */
.fb-depth-0 { margin-left: 0; }
.fb-depth-1 { margin-left: 18px; }
.fb-depth-2 { margin-left: 36px; }
.fb-depth-3 { margin-left: 54px; }
.fb-reply-btn { margin-left: 8px; }
.fb-reply-box { margin: 6px 0 0; }
.fb-reply-box textarea { width: 100%; box-sizing: border-box; }
@media screen and (max-width: 520px) {
  /* 窄屏不再往右缩进（否则正文被挤成一条竖线）；改用左侧色条区分层级 */
  .fb-depth-1, .fb-depth-2, .fb-depth-3 {
    margin-left: 0; border-left: 3px solid var(--line2); padding-left: 8px;
  }
}

@media print {
  .fb-clamp { max-height: none !important; overflow: visible;
    -webkit-mask-image: none; mask-image: none; }
  .fb-more, .fb-fold { display: none !important; }
  /* 折起来的问答在打印稿里一律还原（只还原消息，不还原按钮）——打印不许少内容 */
  .fb-ai-fold .fb-msg.fb-hidden { display: block !important; }
  /* 逐条回复的输入框在打印稿里没有意义，一律不出现 */
  .fb-reply-btn, .fb-reply-box { display: none !important; }
}

/* 新增应用弹窗 */
.modal-overlay { position: fixed; inset: 0; background: rgba(0,0,0,.45); display: flex; align-items: center; justify-content: center; z-index: 100; }
.modal { background: var(--panel); border-radius: var(--radius); padding: 14px 16px; width: 600px; max-width: 94vw; max-height: 88vh; overflow: auto; box-shadow: 0 8px 30px rgba(0,0,0,.25); }
.modal h4 { margin-top: 0; margin-bottom: 6px; font-size: 14px; }
.form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 6px 12px; margin-top: 8px; }
.form-grid label { display: flex; flex-direction: column; gap: 3px; font-size: 12.5px; color: var(--text2); }
.form-grid input, .form-grid select, .form-grid textarea { font-size: 12.5px; }

/* ============ 应用特有窄屏微调（HOW21 §4.18 手机/折叠屏适配）================
   通用部分（栅格降列、宽表容器化、点按 ≥40px、输入 16px、弹窗贴边、矮视口压缩）
   由共享基线 web-common\wl-mobile.css 负责且带 !important，本段**不重复实现**，
   只补 EX-17 自己的组件。整段包在 @media screen 内：打印媒体不得命中。
   六档实测视口：390×844 / 344×882（折叠外屏）/ 841×701（折叠展开）/ 841×500（半折）
   / 844×390（手机横屏）/ 1366×768（桌面，须与改动前一致）。 */
.host-tip { font-size: 12.5px; }
.host-tip b { color: var(--primary); }
/* 深色主题下 --primary(#3f6fb5) 压在 --bg(#12161f) 上只有 3.58:1，换深色档的亮蓝（8.42:1） */
[data-theme="dark"] .host-tip b { color: #7fb3ff; }
/* 2026-10-02：浅底深字全部收进"同色系 + 深到 4.5 以上"。
   改前 #2e86de on #eaf4fd = 3.38、#1e8449 on #eafaf1 = 4.37、#b45309 on #fef3c7 = 4.51（踩线）。 */
.hint-badge { font-size: var(--pill-fs, 11px); color: #14508a; background: #eaf4fd; border-radius: 4px;
  height: var(--pill-h); display: inline-flex; align-items: center; padding: 0 6px; }
.hint-badge.ok { color: #1a5e37; background: #eafaf1; }
.hint-badge.warn { color: #8a3f07; background: #fef3c7; }
[data-theme="dark"] .hint-badge { background: rgba(46,134,222,.16); color: #8ec1ff; }
[data-theme="dark"] .hint-badge.ok { background: rgba(30,132,73,.18); color: #5fc489; }
[data-theme="dark"] .hint-badge.warn { background: rgba(180,83,9,.18); color: #f0b429; }

/* 服务状态胶囊（EX-17 门户 v1.58.23 新增；v1.58.24 视觉加强；v1.58.26 修「桌面档不生效」）：
   「Web 应用在不在跑」= TCP 端口是否在监听（口径与实测见 svcstatus.py 文件头），
   15 秒缓存、检测时刻写在卡片元信息行。尺寸与 .hint-badge 对齐（§4.26 紧凑基线：
   一律用 --pill-fs / --pill-h，不写字号与高度）。
   ⚠ 这一整段**必须留在任何 @media 之外**：v1.58.24 那次把 19 行规则误插进了下面
     `@media screen and (max-width: 900px)` 段内，结果桌面档（>900px）完全不命中 ——
     业务方看到的正是「『运行中』全是普通字、没有背景胶囊」。教训：给组件加样式前先确认
     落点在哪个块里（本文件那段窄屏微调有明确分段注释，别插进去），改完要在**桌面视口**
     复测 computed 值，窄屏通过不等于桌面通过。
   视觉加强（业务方 2026-10-01 追加：「状态『运行中』等需要一点视觉加强」）：
     · 运行中 / 已停止 → **实色填充 + 白字 + 字重 600 + 8px 大圆点**，与卡片里既有的
       「已发布」绿胶囊同一套视觉语言，一眼可见；未知仍是浅琥珀底 + 深字（保持轻量，
       业务方原话：「未知保持轻量」）。
     · ⚠ 底色是**选出来的、不是挑好看的**（_scratch/ex17_badge_colors.py 实测 WCAG 对比度）：
       胶囊文字 10.5px 属小字，白字需 ≥4.5:1。实测 #27AE60（.st-released 同色）只有 2.87:1、
       #E74C3C（.st-pending_accept 同色）只有 3.82:1 —— **都不可用作实色底**，会比我改之前
       的浅底更难认。故选 #1E8449（4.72:1）与 #C0392B（5.44:1）。想换色先跑那个脚本。
     · 宽度代价：实色胶囊比浅底宽 2~5px。桌面档卡片仅 213px 宽、头部本来就是「编号在左、
       右侧组在右」的换行布局（改动前实测 19/21 张已两行），此代价在预期内，已用真浏览器复测。 */
.svc-badge { font-size: var(--pill-fs, 11px); height: var(--pill-h); display: inline-flex;
  align-items: center; gap: 5px; padding: 0 6px; border-radius: 4px; white-space: nowrap;
  color: #1e8449; background: #eafaf1; }
.svc-badge .svc-dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor;
  flex: 0 0 auto; }
/* 运行中：深绿实色底 + 白字加粗 + 8px 大圆点 */
.svc-badge.svc-running { color: #fff; background: #1e8449; font-weight: 600; }
.svc-badge.svc-running .svc-dot { width: 8px; height: 8px; box-shadow: 0 0 0 1.5px rgba(255, 255, 255, .45); }
/* 已停止：红实色底 + 白字加粗（异常态，与运行中同等重量；橙色偏黄，白字对比只有 2.9:1，不用） */
.svc-badge.svc-stopped { color: #fff; background: #c0392b; font-weight: 600; }
.svc-badge.svc-stopped .svc-dot { width: 8px; height: 8px; box-shadow: 0 0 0 1.5px rgba(255, 255, 255, .45); }
/* 未知：保持轻量（浅琥珀底 + 深字，5.3:1），不抢运行中/停止的注意力 */
.svc-badge.svc-unknown { color: #b45309; background: #fef3c7; }
/* 暗色主题：实色底足够深，不再改底色，只保证白字与浅琥珀底的可读性 */
[data-theme="dark"] .svc-badge.svc-running { color: #fff; background: #1e8449; }
[data-theme="dark"] .svc-badge.svc-stopped { color: #fff; background: #c0392b; }
[data-theme="dark"] .svc-badge.svc-unknown { background: rgba(180, 83, 9, .25); color: #f0b429; }
/* 打印：状态是「此刻」的快照，交到纸面上只会误导，故不进打印版面 */
@media print { .svc-badge { display: none; } }

/* 服务状态汇总条 + 刷新按钮（v1.58.27）：门户「Web 应用」分区标题下、管理台「应用开发管理」标题下。
   为什么在这里而不是塞进 .sortbar：排序条属于「列表怎么排」，状态汇总属于「服务健不健康」，
   两件事混一条会让人以为刷新按钮会改变排序。 */
.svc-sum { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; margin: 0 0 8px;
  padding: 5px 8px; background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius); }
.svc-sum-label { font-size: 12.5px; color: var(--text2); font-weight: 600; }
.svc-sum-at { font-size: 11.5px; color: var(--faint); }
.svc-sum .sbtn { margin-left: auto; background: var(--panel); border: 1px solid var(--line2);
  color: var(--text2); border-radius: var(--radius-sm); padding: 3px 10px; font-size: 12.5px; cursor: pointer; }
.svc-sum .sbtn:hover { border-color: var(--primary); color: var(--primary); }
.svc-sum .sbtn[disabled] { opacity: .6; cursor: default; }
/* 详情页标题行里的胶囊：与标题基线对齐，不撑高标题 */
h2 .svc-badge { margin-left: 6px; vertical-align: middle; }
/* 详情页标题最左边的应用图标（v1.63.0）：与 16.5px 的 h2 文字基线对齐 */
.detail-icon { display: inline-flex; align-items: center; margin-right: 7px; vertical-align: -6px; }
.detail-icon .wl-ic { display: block; border-radius: 7px; }
/* 登录页 h1 里的应用图标（v1.63.0）：登录页是独立外壳（不 extends base.html），单独定位 */
.login-box h1 .wl-ic { display: inline-block; vertical-align: -7px; margin-right: 7px; border-radius: 7px; }

/* ══════════════════════════════════════════════════════════════════════════════
   应用矩阵（2026-10-14 v1.62.0）
   业务方原话：「我们开发了30多个app，需要分类，不然找起来太累。按照不同部门来分类，
   做成应用矩阵的样子。」
   分层：公司（一级，h3 色带）→ 部门（二级，小色带 + 计数）→ 卡片网格（沿用 .cards）。
   ── 设计约束（不是审美偏好，是量出来的） ──
     · 复用既有 .cards / .card / 胶囊类，**不新造卡片样式**：卡片高度、密度、点按尺寸
       都已经过 §4.26 / §4.18 的实测整改，新造一套必然把踩过的坑再踩一遍。
     · 公司色只用在**左侧 4px 竖条**与标题文字上，不做大色块：色块会压过状态胶囊
       （§4.27 明度秩序：状态色必须最醒目，分类色属于装饰层）。
     · 部门小色带用 --th-bg（浅），悬停/当前不吃色 —— 它只是分隔符，不是可点对象。
   ══════════════════════════════════════════════════════════════════════════════ */

/* ══════════════════════════════════════════════════════════════════════════════
   两级筛选 + 公司与部门标签（2026-10-14 v1.65.0 业务方改版）
   业务方口径：「应用矩阵可以给各公司和各部门按钮做两层筛选应用，按钮有颜色区分，
   用来避免一个个查找」「应用卡片和状态栏加上各公司和各部门的标签」。
   ── 设计约束 ──
     · 按钮的**颜色直接用行内 `--c`**（来自 appicons 的同一套色板：公司色/部门色），
       所以筛选按钮的色、卡片标签的色、图标的色**三者同源**，不可能对不上。
     · 未选中态是「白底 + 左侧色条 + 深字」，选中态才铺满颜色 —— 避免一屏十几个色块打架。
     · 手机档两行按钮各自横滑（不折成一片），页面级横向滚动仍为 0。
   ══════════════════════════════════════════════════════════════════════════════ */
.flt { background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 7px 9px; margin: 0 0 8px; }
.flt-row { display: flex; align-items: center; flex-wrap: wrap; gap: 5px; margin: 3px 0; }
.flt-label { font-size: 12px; color: var(--text2); font-weight: 600; flex: 0 0 auto; min-width: 52px; }
.fbtn { display: inline-flex; align-items: center; gap: 4px; cursor: pointer; font-family: inherit;
  font-size: 12.5px; line-height: 1.2; color: var(--text); background: var(--panel);
  border: 1px solid var(--line2); border-left: 3px solid var(--c, var(--line2));
  border-radius: var(--radius-sm); padding: 3px 8px 3px 6px; flex: 0 0 auto; white-space: nowrap; }
.fbtn:hover { border-color: var(--c, var(--primary)); }
.fbtn .fbtn-n { font-size: 11px; color: var(--faint); font-variant-numeric: tabular-nums; }
.fbtn.on { background: var(--c, var(--primary)); border-color: var(--c, var(--primary)); color: #fff; }
.fbtn.on .fbtn-n { color: rgba(255, 255, 255, .85); }
.fbtn-all { border-left-color: var(--line2); }
.fbtn-all.on { background: var(--primary); border-color: var(--primary); color: #fff; }
.flt-cur { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; margin-top: 5px;
  padding-top: 5px; border-top: 1px dashed var(--line); }
.flt-cur b { font-size: 13px; color: var(--primary); }
.flt-tip { font-size: 11.5px; color: var(--faint); }
.flt-none { color: var(--faint); font-size: 13px; margin: 10px 0; }

/* 卡片上的公司与部门标签：两枚彩色小签，与筛选按钮、图标同色源 */
.card-tags { display: flex; align-items: center; flex-wrap: wrap; gap: 4px; margin: 1px 0 2px; }
.tag-co, .tag-dp { font-size: 11px; line-height: 1.5; border-radius: var(--radius-sm, 4px);
  padding: 0 6px; white-space: nowrap; }
/* 公司签：实心（深色底 + 白字，公司色都是深色，白字对比度已验） */
.tag-co { background: var(--c, #5d6d7e); color: #fff; }
/* 部门签：浅底 + 同色深字（部门色是原色、偏深，做浅底更好读，也不会跟公司签抢） */
.tag-dp { background: color-mix(in srgb, var(--c, #5d6d7e) 16%, #fff); color: var(--c, #5d6d7e);
  border: 1px solid color-mix(in srgb, var(--c, #5d6d7e) 34%, #fff); }
/* 兼容不支持 color-mix 的浏览器：给一层中性浅底，至少不透明（色相丢失但可读） */
@supports not (background: color-mix(in srgb, red 10%, #fff)) {
  .tag-dp { background: var(--th-bg); border-color: var(--line2); color: var(--text); }
}

/* ══════════════════════════════════════════════════════════════════════════════
   以下 .mx-* 是 v1.62.0「公司→部门分区块矩阵」的样式。
   ⚠ v1.65.0 起**门户不再使用分区块**（业务方要求改成按 EX 编号平铺 + 两级筛选），
   模板里已无 .mx-co / .mx-dept 节点。保留样式只为：① 别的页面（若有）仍可复用；
   ② 万一分区块要回退，样式不用重写。**新代码不要再用它**。
   ══════════════════════════════════════════════════════════════════════════════ */
/* 矩阵标题行：标题 + 总量统计同一行，放不下时统计换行而不是压缩标题 */
.mx-title { display: flex; align-items: baseline; flex-wrap: wrap; gap: 4px 10px; margin: 16px 0 0; }
.mx-title h3 { margin: 0; }
.mx-title-stat { font-size: 12.5px; color: var(--faint); }
.mx-title-stat b { color: var(--text2); font-variant-numeric: tabular-nums; }

/* 公司区块：左侧竖色条 + 与下一区块之间的间隔。scroll-margin 给将来做锚点跳转留位。
   ⚠ v1.63.0（业务方拍板「公司色并入部门色，全站一套色板」）：
   `--co-color` 不再由下面这几条按公司写死，而是**由模板行内传入**（= 该公司第一个部门的颜色，
   取自生成物 appicons.COMPANY_COLOR）。所以 .mx-co-jt/.mx-co-fh… 这些类只剩兜底作用，
   色值统一走 --co-* 变量（事实源 static/wl-appdept.css）。 */
.mx-co { --co-color: var(--co-jt, #1f3a5f); margin: 12px 0 0; scroll-margin-top: 56px;
  border-left: 4px solid var(--co-color); padding: 0 0 0 10px; }
.mx-co-jt { --co-color: var(--co-jt, #1f3a5f); }
.mx-co-fh { --co-color: var(--co-fh, #1e8449); }
.mx-co-xc { --co-color: var(--co-xc, #b45309); }
.mx-co-yl { --co-color: var(--co-yl, #a93226); }
.mx-co-ty { --co-color: var(--co-ty, #5d6d7e); }
.mx-co-un { --co-color: #7d3c98; }   /* 未分类（兜底段，紫 = 需要人来处理） */

.mx-co-head { display: flex; align-items: baseline; flex-wrap: wrap; gap: 4px 8px;
  margin: 8px 0 4px; font-size: 15px; border-left: 0; padding-left: 0;
  border-bottom: 1px solid var(--line); padding-bottom: 3px; }
.mx-co-name { font-weight: 700; color: var(--co-color); }
.mx-co-stat { font-size: 11.5px; font-weight: 400; color: var(--faint);
  background: var(--th-bg); border-radius: var(--radius-sm); padding: 1px 7px;
  font-variant-numeric: tabular-nums; }

/* 部门区块：浅色带标题 + 组内卡片网格 */
.mx-dept { margin: 0 0 10px; }
.mx-dept-head { display: flex; align-items: center; flex-wrap: wrap; gap: 6px;
  background: var(--th-bg); border-left: 3px solid var(--dp-color, var(--co-color));
  border-radius: var(--radius-sm); padding: 3px 8px; margin: 0 0 6px; }
/* 部门色点（v1.63.0）：与应用图标同色，看到色带就知道下面卡片的图标是什么颜色 */
.mx-dept-dot { width: 10px; height: 10px; border-radius: 3px; flex: 0 0 auto;
  background: var(--dp-color, var(--co-color)); }
.mx-dept-name { font-size: 13px; font-weight: 600; color: var(--text); }
.mx-dept-count { font-size: 11.5px; color: var(--faint); font-variant-numeric: tabular-nums; }
/* 部门内的卡片网格：与全局 .cards 同口径，只是保证不继承上面的缩进意外 */
.mx-dept .cards { margin: 0; }

/* 已归档折叠区：默认收起，不占主视野（业务方 2026-10-14 选定） */
.mx-arch { margin: 16px 0 0; border: 1px dashed var(--line2); border-radius: var(--radius);
  padding: 6px 10px; background: var(--panel); }
.mx-arch > summary { cursor: pointer; font-size: 13px; color: var(--text2); font-weight: 600;
  min-height: 24px; display: flex; align-items: center; }
.mx-arch > summary:hover { color: var(--primary); }
.mx-arch .cards { margin-top: 8px; }
/* 归档卡片：整体降饱和，一眼区分「还在用的」与「已下线的」 */
.card-arch { opacity: .72; }
.card-arch .card-title { font-weight: 400; }

/* ============ 应用特有窄屏微调（HOW21 §4.18 手机/折叠屏适配）================ */

@media screen and (max-width: 900px) {
  /* 顶栏：单行放不下就换行，品牌占满一行，链接横滑（基线已保证不做容器强制换行） */
  .topbar { gap: 8px; padding: 6px 10px; }
  .topbar .brand { font-size: 14px; flex: 1 1 100%; }
  .brand-logo { height: 22px; }
  .topbar .links { order: 3; flex: 1 1 100%; gap: 10px; flex-wrap: nowrap; overflow-x: auto;
    -webkit-overflow-scrolling: touch; padding-bottom: 2px; }
  .topbar .links a { white-space: nowrap; font-size: 13.5px; padding: 4px 0; }
  .topbar .user { font-size: 12px; }
  .container { margin: 10px auto 20px; padding: 0 12px; }
  h3 { margin: 12px 0 6px; }
  .card-desc { min-height: 0; }
  .sortbar { gap: 6px; }
  .sortbar-tip { flex: 1 1 100%; }
  /* 管理台密集表格：保持可读列宽 + 容器内横滑（避免 table{display:block} 把列挤到 33px 宽） */
  .section-box table { min-width: 100%; }
  .section-box table > tbody { display: table; min-width: 720px; }
  .section-box table select,
  .section-box table input[type=text],
  .section-box table input[type=number] { min-width: 88px; min-height: 36px; }
  .section-box { padding: 10px 12px; }
  .inline-form input, .inline-form select, .inline-form textarea { width: 100%; }
  .modal { padding: 14px; }
  .form-grid { grid-template-columns: 1fr; }
  .dept-picker { max-width: 100%; }
  .login-box { width: min(92vw, 420px); padding: 20px 16px; }
  .flash { right: 10px; left: 10px; max-width: none; }
  /* 应用矩阵（v1.62.0，v1.65.0 起门户已不使用，仅保底）：手机档把公司色条收窄 */
  .mx-co { padding-left: 8px; border-left-width: 3px; }
  .mx-co-head { font-size: 14.5px; }
  .mx-title { margin-top: 12px; }
  .mx-title-stat { flex: 1 1 100%; }
  /* v1.65.0 两级筛选：手机档两行按钮各自横滑（不折成一片高墙），
     容器内的横滑不算页面级横向滚动（§4.18 判据：页面级横向滚动必须为 0）。 */
  .flt { padding: 6px 8px; }
  .flt-row { flex-wrap: nowrap; overflow-x: auto; -webkit-overflow-scrolling: touch;
    padding-bottom: 2px; }
  .flt-row .flt-label { position: sticky; left: 0; background: var(--panel); z-index: 1;
    padding-right: 4px; }
  .fbtn { min-height: 36px; }          /* §4.18 手指点按 ≥36px */
  .flt-tip { flex: 1 1 100%; }
  /* 部门色带点按目标 ≥40px 是给**可点对象**的门槛；此处是纯分隔标题，不设点按；
     但折叠区的 summary 可点，必须撑到 40px（§4.18 主操作点按高度 ≥40px）。 */
  .mx-arch > summary { min-height: 40px; font-size: 14px; }
}

@media screen and (max-width: 600px) {
  .container { padding: 0 10px; }
  h2 { font-size: 18px; }
  .topbar .brand { font-size: 13.5px; }
}

/* 半折 / 分屏 / 手机横屏（可视高度 ≤520px）：把纵向留白还给内容 */
@media screen and (max-height: 520px) {
  .container { margin-top: 6px; margin-bottom: 12px; }
  .admin-toc { margin-bottom: 6px; }
  .card { padding: 8px 10px; }
}
/* ============ end 应用特有窄屏微调 ============ */


/* ═══════════════════════════════════════════════════════════════════════════════
   HOW21 §4.39 应用外壳三件套：状态栏 / 左侧栏 / 标签页（2026-10-02，EX-17 门户）
   适用范围依据 §4.36【建议】：页面入口 ≥8 个。本应用 11 个入口，达门槛。
   参考实现：EX-24（侧栏 + 标签）、EX-23（§4.39 定稿件）。
   验收判据（§4.39 四）：「同一行」按**垂直中心差 ≤2px** 判，不按顶边差
   （元素高度不同时顶边天然不同，舰队已据此误判过两轮）。
   ═══════════════════════════════════════════════════════════════════════════════ */

/* ── 变量：顶栏高度由脚本实测量写入（§4.39 一①：sticky 常被祖先 overflow 截断，
      故手机档用 position:fixed，并按实测高度补 body padding-top，避免遮住正文）── */
:root { --wl-top-h: 46px; --wl-side-w: 200px; }

/* ── 一、状态栏 ───────────────────────────────────────────────────────────── */
.topbar {
  position: fixed; top: 0; left: 0; right: 0; z-index: 70;
  display: flex; flex-wrap: nowrap; align-items: center;   /* ② 只允许一行 */
  height: var(--wl-top-h); min-height: 46px; max-height: 46px;
  overflow: hidden;
  padding: 0 10px; gap: 8px;
  border-bottom: 1px solid var(--line, rgba(127,127,127,.25));
  /* ⚠ 底色必须用应用自己的 --primary（深藏蓝 #1f3a5f），文字配 #fff。
     2026-10-02 血案：我一度把底色换成 var(--panel)（亮色主题下是 #ffffff），却**没动文字色**
     —— 而应用原样式是 `.topbar{background:var(--primary); color:#fff}`，是给**深色底**写的。
     结果亮色主题下出现「白字白底」，实测对比度 **1.00**（完全看不见）；EX 徽标 2.14、
     版本号 2.16，全部低于 §4.25/§4.27 的 4.5 绝对底线。
     HOW21 §4.39 一⑤ 那句「实测深蓝底 rgb(31,58,95) 配深灰字 rgb(34,34,34) 不可读」说的就是本应用。
     教训：**改底色必须同时验文字色**，且两套主题都要量（本次只在暗色主题下看过，暗色下恰好正常）。 */
  background: var(--primary, #1f3a5f); color: #fff;
}
.topbar > * { flex: 0 0 auto; }
/* ② 控件统一 26px 高并垂直居中（§4.39 一②）——用高度与 line-height 双管齐下，
   只写 height 时 inline-flex 的子元素仍可能按内容撑高，实测过
   UI专项 2026-10-06（状态栏 C6「字体不统一 ['Arial','等线']」）：本行补 `font-family:inherit`。
   `<button>`（#themeToggle / #wlBurger）不吃 body 的 font-family，UA 默认落 Arial；
   同排的 `.wl-user-btn`、`.wl-ex`、`.wl-ver` 都是 `<span>/<a>`，继承 body 的等线 ⇒ 顶栏两种字体族。
   桌面档只有 #themeToggle 带文字（🌙/☀），449 档 #wlBurger（☰）也露出来，两个都要盖住。 */
.topbar .wl-burger, .topbar #themeToggle, .topbar .user,
.topbar .user > span, .topbar .user > a, .topbar .wl-ex, .topbar .wl-ver {
  height: 26px; min-height: 26px; max-height: 26px; line-height: 26px;
  display: inline-flex; align-items: center;
  font-family: inherit;
}
.topbar .wl-burger {
  display: none;                                           /* 桌面不显示（§4.39 二①侧栏常驻，不需要汉堡） */
  width: 26px; padding: 0; justify-content: center;
  background: none; border: 1px solid var(--navlink, #cfe0f5);
  color: var(--navlink, #cfe0f5); border-radius: 6px; cursor: pointer;
  font-size: 14px; z-index: 40;                            /* ④ 汉堡 z-index 必须低于侧栏(60) */
}
/* UI专项 2026-10-06（窄 449 档两条判据：C8「调试图标落在顶栏左侧 x=10」+「顶栏真换行 内容高多 27」）：
   根因是本应用自己的"固定高 + 裁切"：.topbar 写死 height/max-height:46px 且 overflow:hidden，
   而共享基线 wl-mobile.css 在窄档对 `body nav` 强制 `flex-wrap:wrap !important`
   ⇒ 折到第二行的 `#uidbg-btn`（共享件注入）下半截被剪掉（scrollHeight 73 > clientHeight 46 = 多 27），
   且第二行左对齐 ⇒ 调试图标落在 x=10（半屏 449 的左侧）。
   口径 §6/§25：栏内塞不下时**允许折行**（右对齐、仍在栏内、绝不浮动），栏高允许 +1 行（≤44px）。
   故窄档放开固定高与裁切；栏高由本应用 ex17-shell.js 的 wlSyncTopH() 实测量写回
   `--wl-top-h` 与 body padding-top（第 21~31 行），增高 27px 不会压住正文。 */
@media screen and (max-width: 900px) {
  .topbar {
    height: auto; min-height: var(--wl-top-h); max-height: none;
    overflow: visible;
    flex-wrap: wrap; justify-content: flex-end; row-gap: 4px;
  }
}
/* ③ 手机端隐藏应用名与 logo —— 它们由左侧栏抽屉顶部承担 */
.topbar .brand { display: flex; align-items: center; gap: 6px; font-size: 14.5px; font-weight: bold; min-width: 0; }
.topbar .wl-topright { display: flex; align-items: center; gap: 8px; margin-left: auto; }
.topbar .user { color: var(--navlink); font-size: 12.5px; gap: 4px; }
.topbar .user a { color: #fff; }
/* 原来的横向菜单容器已置空：:empty 必须 display:none —— 否则它仍占 flex:1 的宽度，
   把右侧工具组挤出视口（HOW21 记过 EX-23 同类事故：空 nav 占宽 374px） */
.topbar .links:empty { display: none; }
.topbar .links { display: none; }   /* 菜单已全部移入左侧栏；保留选择器兼容 */

/* ── 二、左侧栏 ───────────────────────────────────────────────────────────── */
.wl-side {
  position: fixed; left: 0; top: var(--wl-top-h); bottom: 0; z-index: 60;
  width: var(--wl-side-w); display: flex; flex-direction: column;
  background: var(--panel, var(--bg, #fff));
  border-right: 1px solid var(--line, rgba(127,127,127,.25));
}
/* ② 抽屉顶部：logo + 应用名 + 编号角标 + 版本号（不用胶囊、纯文字下划线链接），文字垂直居中 */
.wl-side .side-head {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  height: 34px; line-height: 34px; padding: 0 10px;
  border-bottom: 1px solid var(--line, rgba(127,127,127,.18));
  font-size: 12.5px; white-space: nowrap;
}
.wl-side .side-logo { width: 18px; height: 18px; }
.wl-side .side-name { font-weight: 600; }
/* ⚠ 侧栏头部与标签栏的文字色**必须按主题分别给**：这两处底色是 var(--panel)（亮色 #fff / 暗色 #1a2029），
   而 §4.27 给的 #7fb3ff（EX 徽标）/#9db1d8（版本胶囊）是为**深色顶栏**挑的浅蓝 ——
   直接搬到浅色底上实测只有 2.1:1（远低于 4.5 底线）。§4.27 只把「顶栏装饰」排除在"方向取极值"之外，
   并**没有**免除 4.5:1 绝对底线，故浅色主题下改用深蓝。
   实测：亮色 #2f6fd0 on #fff = 4.86:1、#3b5f92 on #fff = 6.53:1；暗色 #7fb3ff on #1a2029 = 6.9:1。 */
.wl-side .side-head .wl-ex {
  font-size: 11px; font-weight: 600; letter-spacing: .4px;
  color: #2f6fd0; border:0; border-radius: 4px;
  padding: 0 5px; line-height: 16px; height: 16px;
}
.wl-side .side-ver {
  margin-left: auto; color: #3b5f92; text-decoration: underline;
  background: none; border: none; border-radius: 0; height: 34px; line-height: 34px;
}
[data-theme="dark"] .wl-side .side-head .wl-ex { color: #7fb3ff; border-color: #7fb3ff; }
[data-theme="dark"] .wl-side .side-ver { color: #9db1d8; }
/* ③ 菜单超高自动纵向滚动：flex:1 + min-height:0 缺一不可（不写 min-height:0 时
   flex 子项的自动最小尺寸会把它撑开、overflow 不生效） */
.wl-side .side-inner { flex: 1; min-height: 0; overflow-y: auto; overflow-x: hidden; padding: 6px 0 12px; }
.wl-side .side-group { padding: 2px 0; }
.wl-side .side-title {
  display: block; padding: 6px 12px 2px; font-size: 11.5px; letter-spacing: .5px;
  /* 用 --text2 而不是 --muted：#888 on #fff 实测 3.27:1，低于 §4.25/§4.27 的 4.5 底线；
     #555 on #fff = 6.66:1。分组标题虽小，但它是"可读的导航文字"，不属装饰豁免范围。 */
  color: var(--text2, #555); text-transform: none;
}
.wl-side .side-item {
  display: block; padding: 6px 12px; font-size: 13px; line-height: 1.5;
  /* §4.27：**菜单文字按「方向取极值」判**（浅底纯黑 #000、深底纯白 #fff），不按"够不够 AA"判。
     2026-10-02 实测踩到两处：① 用 var(--text)/--text2 的灰蓝 → 方向不达标；
     ② 选中项用 var(--primary)（暗色下 #3f6fb5）配深底只有 **2.88:1**，连 4.5 绝对底线都不到。
     现改为纯黑/纯白，选中态一律靠**左侧强调条 + 底色 + 加粗**区分（不靠改文字深浅）。 */
  color: #000; text-decoration: none; border-left: 3px solid transparent;
  /* ⚠ 必须显式写 justify-content —— 共享基线 `wl-mobile.css` 里有一条**裸 `nav a`** 规则：
       nav a { min-height:40px; min-width:36px; display:inline-flex;
               align-items:center; justify-content:center; }
     它本意是给老的顶栏菜单项做触屏点按下限，但侧栏结构是 `<nav><a class="side-item">`，
     正好被 `nav a` 命中 → 菜单文字被**水平居中**（实测「应用门户」文字起点 x=104，左对齐应为 14）。
     本规则特异性 (0,2,0) 高于 `nav a` 的 (0,0,2)，写上即胜出。 */
  justify-content: flex-start;
}
[data-theme="dark"] .wl-side .side-item { color: #fff; }
.wl-side .side-item:hover { background: rgba(127,127,127,.10); text-decoration: none; }
/* ⑤ 当前项高亮：左侧强调条 + 底色 + 加粗（**不改文字颜色**，以守住 §4.27 的方向极值） */
.wl-side .side-item.on {
  border-left-color: var(--primary, #2f6fd0);
  background: rgba(47,111,208,.18);
  font-weight: 700;
}
.wl-side .badge { margin-left: 6px; }
/* ④ 遮罩：桌面不需要（侧栏常驻） */
.wl-mask { display: none; position: fixed; inset: var(--wl-top-h) 0 0 0; z-index: 59;
           background: rgba(0,0,0,.42); }
/* 桌面：给正文让出侧栏宽度；并**隐藏侧栏头部** —— 品牌/应用名/EX/版本在顶栏已经有一份，
   侧栏再显示一遍就是重复（EX-23 定稿口径：「桌面常驻侧栏、抽屉形态仅 ≤900px，**桌面不显示抽屉顶栏**」）。
   侧栏头部只在窄屏抽屉里承担"品牌 + 版本"的职责（因为那时顶栏按 §4.39 一③ 把品牌隐藏了）。 */
@media screen and (min-width: 901px) {
  body { padding-left: var(--wl-side-w); }
  .wl-side .side-head { display: none; }
}

/* ── 三、标签页 ───────────────────────────────────────────────────────────── */
.wl-tabs {
  /* ⚠ 用 **fixed** 而不是 sticky：实测本应用 `body{overflow:auto}`，sticky 的参照系被祖先
     overflow 截断 —— 滚动 600px 后标签栏 y=-554（完全没吸住）。这正是 §4.39 一① 记录过的
     同一条坑（「sticky 常被祖先 overflow 截断，实测滚动后 top=-580」），那里的解法也是改 fixed。
     top 用 --wl-top-h（顶栏实测量）；占位由脚本写进 body padding-top（顶栏高 + 标签栏高）。 */
  position: fixed; top: var(--wl-top-h); left: 0; right: 0; z-index: 55;
  display: flex; flex-wrap: nowrap; align-items: center; gap: 2px;
  overflow-x: auto; overflow-y: hidden;                  /* 只横滚；不写 overflow-y 会被计算成 auto → 多出纵向滚动条 */
  padding: 4px 10px 0; min-height: 34px;
  background: var(--bg, #fff);
  border-bottom: 1px solid var(--line, rgba(127,127,127,.18));
  -webkit-overflow-scrolling: touch;
}
.wl-tabs::-webkit-scrollbar { height: 6px; }
.wl-tabs .wl-tab {
  flex: 0 0 auto; white-space: nowrap;
  display: inline-flex; align-items: center; gap: 6px;
  height: 26px; padding: 0 10px; font-size: 12.5px;
  border: 1px solid var(--line, rgba(127,127,127,.3)); border-bottom: none;
  border-radius: 6px 6px 0 0; background: transparent;
  /* 未选中标签同属"菜单文字"，按 §4.27 方向极值给纯黑/纯白（见上 .side-item 的说明） */
  color: #000; text-decoration: none;
}
[data-theme="dark"] .wl-tabs .wl-tab { color: #fff; }
.wl-tabs .wl-tab.on { background: var(--panel, #fff); font-weight: 700; }
.wl-tabs .wl-tab .wl-tab-x {
  font-size: 11px; opacity: .6; cursor: pointer; padding: 0 2px; border-radius: 3px;
}
.wl-tabs .wl-tab .wl-tab-x:hover { opacity: 1; background: rgba(127,127,127,.22); }

/* ⚠ 桌面档标签栏必须从侧栏右侧开始，否则会被侧栏（z-index 60 > 标签栏 55）**压住左边的标签**。
   2026-10-02 血案：这条覆盖原本写在"二、左侧栏"那个 @media 块里，**位置在基础 `.wl-tabs{left:0}`
   之前** —— 同特异性 (0,1,0) 下后者胜出，覆盖失效。实测桌面 1440 时 `#wlTabs` 的 left 计算值是
   **0px**（应为 200px），于是标签条从 x=0 铺满、侧栏盖住前两个半标签：tab0 10..82、tab1 84..175
   全被盖，**tab2 177..268 只露出右半截** —— 业务方点的 `a.wl-tab[2]` 就是它，报的是"文字显示不全、
   标签宽度不对"，而真因是**被侧栏压住**。
   教训：**媒体查询里的覆盖必须写在基础规则之后**；同特异性靠源顺序决胜，顺序错了就静默失效。 */
@media screen and (min-width: 901px) {
  .wl-tabs { left: var(--wl-side-w); }
}

/* ── 手机/窄屏（≤900px）：左侧栏收为抽屉（§4.36④ / §4.39 二①）─────────────── */
@media screen and (max-width: 900px) {
  body { padding-left: 0; }
  .topbar .wl-burger { display: inline-flex; }            /* 汉堡只在窄屏出现 */
  .topbar .brand { display: none; }                       /* ③ 应用名与 logo 交给抽屉顶部 */
  /* ★★ 2026-10-13（业务方报障：顶栏「姓名（部门）」显示不全）：
     原来这里把用户名钉死 `max-width:34vw` + 省略号（430px 档更狠，26vw=93.6px），
     而「刘万里（集团-总经办）」要 123px ⇒ 被裁成半截（截图里只剩「里（集团-总经」）。
     业务方口径：「重要的信息要**简约但完整**地展示；不必用胶囊，有下划线表示可点就够」。
     ⇒ 窄屏**不再截断**：不设 max-width、不省略号；放不下就让顶栏折行（`.topbar` 本来就是 flex-wrap）。
     外观（纯文字＋下划线＋可点）由共享件 wl-help.js 的 `.wl-user-btn` 统一负责。 */
  .topbar .user > span { max-width: none; white-space: normal; overflow: visible; text-overflow: clip; }
  .wl-side {
    transform: translateX(-100%); transition: transform .2s ease;
    width: min(78vw, 260px); box-shadow: 2px 0 12px rgba(0,0,0,.22);
  }
  .wl-side.open { transform: none; }
  .wl-mask.show { display: block; }
  /* 窄屏的侧栏是**触摸菜单**，菜单项必须够大（§4.18 手机档点按目标 ≥36px）。
     桌面档保持紧凑的 6px 内边距即可；手机上用 flex 居中 + min-height 给足命中区
     （不靠加大 line-height —— 那会让文字在行盒里偏上）。
     实测这条把"小点按"从 6/6/5/5/5 降到只剩顶栏那几个（顶栏 26px 属 §4.39 口径，
     与 §4.18 的 36px 冲突，另行登记，不在本次擅自改）。 */
  .wl-side .side-item {
    display: flex; align-items: center;
    min-height: 36px; padding: 4px 14px; font-size: 13.5px;
  }
  .wl-side .side-title { padding: 8px 14px 3px; }
  /* 抽屉顶部那行在手机上也是触摸目标：版本链接给到 36px（桌面档保持 34px 的紧凑行高） */
  .wl-side .side-head { height: auto; min-height: 40px; line-height: normal; align-items: center; }
  .wl-side .side-ver { height: 36px; line-height: 36px; padding: 0 4px; }
  /* 标签栏在手机上是主要切换入口，同样给到 36px 命中区 */
  .wl-tabs { min-height: 42px; padding-top: 5px; }
  .wl-tabs .wl-tab { height: 36px; font-size: 13px; }
  /* ④ 抽屉打开时锁定页面滚动（由脚本给 body 加 .wl-drawer-open） */
  body.wl-drawer-open { overflow: hidden; }
}
@media screen and (max-width: 430px) {
  .topbar { padding: 0 6px; gap: 6px; }
  /* 2026-10-13：原来这里再收到 26vw（＝360px 下 93.6px）⇒ 用户名被裁。现按业务方口径**不截断**。 */
  .topbar .user > span { max-width: none; }
}

/* ══════════════════════════════════════════════════════════════════════════════
   ★ 2026-10-07（guidefix）：「使用指导」菜单被顶栏的 overflow:hidden 裁掉
   ──────────────────────────────────────────────────────────────────────────────
   现象（业务方口径）：点「使用指导」图标，「点了没有任何反应」。
   实测（1440 档，真 Edge + 真鼠标）：`.wg-menu.on` 的 computed style 一切正常
   （display:block / z-index:60 / 有宽高），`getBoundingClientRect()` 也给出
   `[917,43,260,161]`，但**上面那条 `.topbar{overflow:hidden}`（本文件 442 行）把它裁掉**
   —— `.topbar` 自身 rect 只有 `[0,0,1440,46]`，菜单整个落在裁切区外。
   于是 `document.elementFromPoint(菜单项中心)` 命中正文 `H2`，真鼠标点菜单项点不到、
   `wlGuide.start()` 根本没被调用 ⇒ 用户看到的就是"点了没反应"。
   （窄 ≤900 档本来就 `overflow:visible`（483 行那段媒体查询），故只有 1440 档复现。）

   修法：**只在引导菜单真的开着时**放开裁切。基线态仍保持 `overflow:hidden`
   ⇒ 顶栏"固定高 + 一行"的口径、以及 `audit_statusbar` 的 C 判据（scrollOver）都不变：
   1440 / 449 基线实测 scrollOver 仍为 0。
   ⚠ 必须用 `:has()` 提特异性（0-3-0 > 442 行 .topbar 的 0-1-0），否则会被文档顺序压回去。
   回退：删掉本段即可。
   ══════════════════════════════════════════════════════════════════════════════ */
.topbar:has(.wg-menu.on) { overflow: visible; }
