:root{font-size:14px;}*{box-sizing:border-box}body{margin:0}aside{position:fixed;inset:0 auto 0 0;width:238px;background:#102f2e;color:#d9e6e2;padding:32px 22px;display:flex;flex-direction:column}.brand{display:flex;align-items:center;}.brand b{display:grid;place-items:center;}.brand span{display:block;}.workspace{font-size:12px;border-block:1px solid #31504e;margin:32px 0 22px;padding:17px 5px}.workspace small{display:block;margin-top:9px;color:#aacd9c;font-size:10px}nav{display:grid;gap:7px}nav button{background:none;color:#afc8c2;text-align:left;border:0;padding:14px;font-size:14px;border-radius:8px}nav button.active{background:#2c4b45;color:#e4f6c6}footer{margin-top:auto;font-size:11px;color:#9ab7b0}footer p{font-size:9px;color:#74968e}footer i{display:inline-block;background:#acd188;width:6px;height:6px;border-radius:50%;margin-right:7px}header{height:76px;border-bottom:1px solid #dce5e0;background:#fff;padding:0 42px;display:flex;align-items:center;justify-content:space-between;font-size:12px}
/* 画布 / 表单设计器是**三栏工具**，1700px 的容器在窄屏下会把它们压扁。
   这里只对含三栏工具的页面放开宽度上限，其它页面维持 1700px。 */
#app:has(.oa-cv-wrap),#app:has(.oa-fd-wrap){max-width:none}.eyebrow{font-size:10px;letter-spacing:2px;color:#6a8b7b;font-weight:700}h1{font-size:30px;letter-spacing:-1px;font-weight:600;margin:12px 0}p{line-height:1.8;}.page-heading{display:flex;justify-content:space-between;align-items:center;margin-bottom:28px}.page-heading p{margin:7px 0;font-size:13px}button{cursor:pointer;border-radius:6px;font:inherit;}button:hover{filter:brightness(.96)}button:disabled{opacity:.45;}.primary{background:#174f40;color:white;border:0}.cards{display:grid;}.card,.panel{border:1px solid #e0e7e1;}.card .tag{float:right;font-size:10px;}.panel{overflow:auto;}.panel h3{font-size:14px}.grid-form{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));}label{display:grid;gap:7px;font-size:12px;}input,select,textarea{width:100%;border:1px solid #d6e1d8;font:inherit;min-width:0;}textarea{min-height:82px;}.grid-form button{align-self:end}table{width:100%;border-collapse:collapse;text-align:left;font-size:12px}th{white-space:nowrap;}td,th{border-bottom:1px solid #e8eee6;max-width:370px;overflow-wrap:anywhere;}td button{margin:2px;padding:6px 10px;}.badge{padding:4px 8px;border-radius:4px;font-size:10px;white-space:nowrap;}.empty{text-align:center;}.muted{font-size:12px;}pre{white-space:pre-wrap;padding:18px;border-radius:6px;font-size:12px;max-height:350px;overflow:auto;}#notice{position:fixed;bottom:25px;right:25px;padding:14px 22px;border-radius:8px;display:none;max-width:min(600px,calc(100vw - 40px));overflow-wrap:anywhere;}#login h1{line-height:1.4;}#login form{display:grid;gap:17px;}.split{display:grid;grid-template-columns:1fr 1fr;gap:20px}.pill{padding:5px 10px;border-radius:20px;font-size:10px;}[hidden]{display:none!important}@media(max-width:1000px){aside{width:190px;padding:25px 14px}main{margin-left:190px}#app{padding:25px}.grid-form{grid-template-columns:1fr 1fr}.cards{grid-template-columns:1fr 1fr}.split{grid-template-columns:1fr}}@media(max-width:680px){aside{position:static;width:auto;padding:15px}aside nav{display:flex;overflow:auto}nav button{white-space:nowrap}.workspace,footer{display:none}main{margin:0}header{padding:0 20px}.cards,.grid-form{grid-template-columns:1fr}#login{padding:40px 25px}.page-heading{align-items:start;gap:12px}}
.subnav{display:flex;flex-wrap:wrap;margin-bottom:25px;border-bottom:1px solid #dae3db;padding-bottom:15px;}.subnav button{border-color:transparent;background:transparent;}.panel pre{max-width:100%;overflow:auto}.panel textarea{min-height:110px}nav{overflow-y:auto}#login{padding-top:45px}#login form{margin-top:20px}
.wide{grid-column:1/-1}.table-scroll{overflow-x:auto}.scope-editor fieldset{border:1px solid #d6e1d8;border-radius:7px;margin:0 0 12px;padding:12px;display:flex;flex-wrap:wrap;gap:12px}.scope-editor legend{padding:0 5px;}.scope-editor fieldset label,.check-list label{display:flex;align-items:center;gap:7px}.scope-editor input[type=checkbox],.check-list input{width:auto}.check-list{display:flex;flex-wrap:wrap;gap:15px}.scope-editor select{max-width:240px}.panel>button{margin:5px 10px 5px 0}.knowledge-body{white-space:pre-wrap;line-height:1.9;font-size:15px;margin:20px 0}label small{font-weight:normal;line-height:1.6;}summary{cursor:pointer;font-size:13px;}#first-setup{max-width:460px;margin-top:25px;border-top:1px solid #dce5e0;padding-top:20px}#login-error{font-size:13px;}input[type=file]{font-size:12px}nav button{font-size:14px;letter-spacing:.5px}
.bi-context,.bi-toolbar{display:flex;gap:14px;align-items:center;flex-wrap:wrap;}.bi-toolbar select{width:auto;max-width:260px}.bi-toolbar span{font-size:12px;}.bi-kpis{display:grid;grid-template-columns:repeat(auto-fit,minmax(170px,1fr));gap:14px}.bi-kpi{border:1px solid #dae7df;border-top:3px solid #52967b;display:grid;gap:12px;}.bi-kpi>span{font-size:13px;}.bi-kpi strong{font-size:27px;font-variant-numeric:tabular-nums;overflow-wrap:anywhere;}.bi-kpi small{font-size:11px;}.bi-charts,.bi-dashboard-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(330px,100%),1fr));}.bi-charts svg{width:100%;height:auto;max-height:600px}.bi-editor-layout{display:grid;grid-template-columns:minmax(280px,340px) minmax(0,1fr);align-items:start;}.bi-editor-config label{margin-bottom:12px}.bi-editor-config fieldset{margin:15px 0;padding:12px;border:1px solid #e0e8e2;border-radius:6px}.bi-editor-config legend{font-size:12px;}.bi-editor-config .bi-check{display:flex;align-items:center;gap:8px;margin:8px 0}.bi-check input{width:auto}.bi-editor-config details{border-top:1px solid #e4eae5;padding-top:12px;margin-top:12px}.bi-editor-config details>label{margin-top:12px}.bi-editor-canvas{min-width:0}.bi-filter{padding:12px 0;border-bottom:1px solid #e2e9e3}.bi-filter button{font-size:11px;padding:6px 10px}.bi-result table{font-variant-numeric:tabular-nums}.bi-result th{position:sticky;top:0}.bi-result .table-scroll{max-height:520px}.bi-dashboard-grid .panel{margin-bottom:0}.bi-dashboard-grid{margin-bottom:22px}@media(max-width:1150px){.bi-editor-layout{grid-template-columns:1fr}.bi-editor-layout>*{min-width:0}.bi-editor-config{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:14px}.bi-editor-config .panel{margin-bottom:0}}@media(max-width:680px){.bi-kpis{grid-template-columns:1fr 1fr}.bi-kpi{padding:14px}.bi-kpi strong{font-size:22px}.bi-toolbar select{width:100%}}

.success-message{border:1px solid #9ac7aa;border-left:5px solid #2c8051;border-radius:8px;font-size:15px;font-weight:600;line-height:1.8;}

aside nav{min-height:0;overflow-y:auto;align-content:start}aside footer{flex-shrink:0;padding-top:14px}

.phase1-table .table-scroll:last-child table{min-width:800px}.phase1-table td button{white-space:nowrap}.phase1-table td{word-break:normal;overflow-wrap:normal}

/* R&D template and project editors */
.rd-cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));}.rd-health{margin:0}.rd-health strong{display:block;font-size:32px;margin-top:10px}.rd-health.green{border-top:4px solid #2d8765}.rd-health.yellow{border-top:4px solid #c2931e}.rd-health.red{border-top:4px solid #c7544b}.rd-line{display:flex;gap:12px;flex-wrap:wrap;align-items:end;padding:10px 0;border-bottom:1px solid #e4e9ee}.rd-line label{flex:1;min-width:150px}.rd-stage-editor{margin:14px 0;padding:18px;border:1px solid #dce4ea;border-radius:10px}fieldset{min-width:0}fieldset>small{display:block;margin-bottom:10px}.rd-line button{margin:0 0 8px}.rd-stage-editor legend{font-weight:600}form>button{margin-top:16px}.rd-line select,.rd-line input{width:100%}
/* Project planning workspace */
.rd-actions{display:flex;flex-wrap:wrap;}.rd-cards strong{display:block;margin-top:10px;}.gantt-scroll{overflow:auto;max-height:650px;border:1px solid var(--line,#dce3eb);border-radius:10px}.gantt-grid{position:relative;}.gantt-row{display:flex;height:42px;border-bottom:1px solid #e6eaf0;box-sizing:border-box}.gantt-heading{position:sticky;top:0;z-index:5;}.gantt-name{position:sticky;left:0;z-index:3;width:240px;min-width:240px;display:flex;align-items:center;gap:8px;padding:6px 12px;box-sizing:border-box;border-right:1px solid #dde5ee;font-size:13px;overflow:hidden;}.gantt-kind{font-size:10px;white-space:nowrap;border:1px solid #ccd6e1;border-radius:5px;padding:2px 4px;}.gantt-track{position:relative;flex-shrink:0;}.gantt-tick{position:absolute;top:12px;font-size:11px;white-space:nowrap;}.gantt-bar{position:absolute;top:8px;height:26px;min-height:0;padding:3px 8px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;border:0;border-radius:5px;color:white;font-size:12px;text-align:left;z-index:2;}.gantt-bar.milestone{font-size:22px;padding:0;overflow:visible;}.gantt-links{position:absolute;top:0;left:0;pointer-events:none;z-index:1}.gantt-links path{fill:none;stroke-width:1.4;stroke-dasharray:3 2;}
dialog.approval-confirm{width:min(620px,calc(100vw - 48px));max-height:85vh;overflow:auto;border:1px solid #d5dce5;border-radius:14px;padding:28px;}.approval-confirm p{line-height:1.7}.approval-confirm label{display:grid;gap:8px;margin:20px 0}.approval-confirm-actions{display:flex;gap:12px;justify-content:flex-end;margin-top:24px;flex-wrap:wrap}
/* Organization and employee actions remain visible in narrow workspace panels. */
.people-table td:last-child button{white-space:nowrap}
@media(max-width:1000px){
 .people-table,.people-table tbody{display:block;width:100%}
 .people-table thead{display:none}
 .people-table tbody{display:grid;gap:16px}
 .people-table tr{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));border:1px solid #e0e7e1;border-radius:8px;padding:14px;gap:12px;background:#fff}
 .people-table td{display:block;border:0;padding:0;max-width:none;min-width:0;order:2;line-height:1.6}
 .people-table td:before{content:attr(data-label);display:block;font-size:11px;font-weight:400;color:#7f9086;margin-bottom:3px}
 .people-table td:first-child{grid-column:1/-1;order:0;font-size:16px;font-weight:600}
 .people-table td:last-child{grid-column:1/-1;order:1;padding-bottom:8px;border-bottom:1px solid #edf1eb;display:flex;gap:6px;flex-wrap:wrap}
 .people-table td:last-child:before{display:none}
 .people-table td:last-child button{margin:0;font-size:12px;padding:7px 12px}
}
/* Professional R&D uses the existing controls and responsive project workspace. */
.rd-pro-field { padding:12px 0; border-bottom:1px solid #e4e8ef; }
.rd-pro-field p { white-space:pre-wrap; overflow-wrap:anywhere; margin:6px 0; }
.rd-diff {white-space:pre-wrap;overflow-wrap:anywhere;max-height:540px;overflow:auto;padding:16px;border-radius:10px;line-height:1.6;}
.rd-risk-grid { display:grid; grid-template-columns:minmax(84px,1.4fr) repeat(5,minmax(46px,1fr)); gap:6px; max-width:640px; align-items:center; text-align:center; }
.rd-risk-grid button { min-height:42px; margin:0; }
.r
.r
.r
.rd-document-image { display:block; max-width:100%; max-height:640px; object-fit:contain; }
.audit-results{border-top:1px solid #e0e7e1;padding-top:12px;}
.audit-summary{font-weight:600;}
.audit-pagination{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-top:18px}
.audit-results .table-scroll{max-height:650px}
.audit-results th{position:sticky;top:0}

.rd-lifecycle-performance table{min-width:1320px}.rd-lifecycle-performance td,.rd-lifecycle-performance th{white-space:nowrap}.rd-lifecycle-performance .table-scroll{max-width:100%;overflow-x:auto}
/* A07fix（纯新增）：① 表格 caption 的可访问名称保留给读屏，视觉上不占位（A07-A11Y-003）；
   ② 角色管理页提交前提示的行内样式（A07-UX-003/004/005）。 */
.visually-hidden{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
.role-form-notice{padding:7px 10px;border-radius:6px;background:var(--raised,#f7f9fc);border:1px solid var(--line,#e2e7f0);margin:8px 0 0;line-height:1.6}

/* 组织权限中心：沿用平台色板，强调状态、边界与下一步，不制造第二套主题。 */
.role-workspace-nav{margin-bottom:18px;padding:6px;border:1px solid var(--line,#e2e7f0);border-radius:10px;background:var(--raised,#f7f9fc)}
.role-workspace-nav button{flex:1 1 120px;min-height:38px}
.role-workspace-nav button.selected{background:var(--surface,#fff);border-color:var(--line,#dce3eb);box-shadow:0 2px 8px rgb(32 42 61 / 6%)}
.role-overview-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px;margin:0 0 16px}
.role-overview-card{display:grid;gap:7px;min-width:0;padding:15px 16px;border:1px solid var(--line,#dce3eb);border-radius:10px;background:var(--surface,#fff);text-align:left;color:var(--text,#202a3d)}
.role-overview-card>span{font-size:12px;color:var(--muted,#657188)}
.role-overview-card>strong{font-size:23px;line-height:1.2;font-variant-numeric:tabular-nums;overflow-wrap:anywhere}
.role-overview-card>small{font-size:11px;color:var(--muted,#657188);line-height:1.5}
.role-overview-card.risk{border-top:3px solid #c64b5d}.role-overview-card.warn{border-top:3px solid #cf921f}
button.role-health-card{cursor:pointer}.role-health-card.selected{border-color:var(--accent,#3568d4);box-shadow:0 0 0 2px var(--accent-soft,#eaf0ff)}
.role-overview-layout{display:grid;grid-template-columns:minmax(0,1.25fr) minmax(270px,.75fr);gap:12px;align-items:start}
.role-health-list{display:grid;gap:9px}.role-health-item{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:5px 12px;align-items:center;padding:12px;border:1px solid var(--line,#dce3eb);border-left:4px solid var(--accent,#3568d4);border-radius:9px;background:var(--surface,#fff)}
.role-health-item>span{grid-column:1}.role-health-item>button{grid-column:2;grid-row:1/3}.role-health-item.warn{border-left-color:#cf921f}
.role-detail-head{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;margin-bottom:12px}.role-detail-head h2{margin:0 0 4px;font-size:18px}.role-detail-head p{margin:0;line-height:1.6}.role-detail-badges{display:flex;flex-wrap:wrap;gap:7px;margin-top:11px}.role-detail-badges .badge.ok{color:#1d7550;background:#edf8f2}.role-detail-badges .badge.warn{color:#8b5a00;background:#fff7df}.role-detail-badges .badge.risk{color:#a72a3d;background:#fcecee}
.role-readiness{display:flex;flex-wrap:wrap;gap:8px 16px;align-items:center;padding:12px 14px;margin:0 0 16px;border:1px solid var(--line,#dce3eb);border-radius:10px;background:var(--raised,#f7f9fc);font-size:12px;color:var(--muted,#657188)}
.role-readiness strong{color:var(--text,#202a3d)}
.role-capability-intro{display:flex;align-items:center;justify-content:space-between;gap:12px;margin:0 0 12px;padding:0 2px;color:var(--muted,#657188);font-size:12px;line-height:1.65}
.role-capability-intro p{margin:0}
.role-capability-status{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin:0 0 13px}
.role-capability-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;margin:0 0 12px}
.role-capability-card{min-width:0;padding:13px;border:1px solid var(--line,#dce3eb);border-radius:10px;background:var(--surface,#fff)}
.role-capability-card.pending{background:var(--raised,#f7f9fc)}
.role-capability-card-head{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:10px}
.role-capability-card-head>strong{font-size:13px}
.role-capability-card>p{margin:0;line-height:1.6}
.role-capability-choice{display:grid;grid-template-columns:auto minmax(0,1fr);align-items:start;gap:9px;padding:9px 0;border-top:1px solid var(--line,#e2e7f0);cursor:pointer}
.role-capability-choice input{width:auto;margin-top:3px}
.role-capability-choice span{display:grid;gap:3px;min-width:0}
.role-capability-choice strong{font-size:12px;font-weight:600}
.role-capability-choice small{color:var(--muted,#657188);font-size:11px;line-height:1.5}
.role-capability-count{margin:0 0 13px;line-height:1.6}
.role-user-toolbar{display:flex;align-items:end;justify-content:space-between;gap:12px;margin-bottom:12px;padding:12px 14px;border:1px solid var(--line,#dce3eb);border-radius:10px;background:var(--surface,#fff)}
.role-user-toolbar label{display:grid;gap:6px;min-width:min(320px,100%);font-size:12px;color:var(--muted,#657188)}
.role-user-grid{display:grid;grid-template-columns:minmax(220px,.35fr) minmax(0,1fr);gap:12px;align-items:start}.role-user-facts{display:grid;grid-template-columns:72px minmax(0,1fr);gap:9px 10px;margin:14px 0 0;font-size:12px;line-height:1.55}.role-user-facts dt{color:var(--muted,#657188)}.role-user-facts dd{margin:0;overflow-wrap:anywhere}
.role-health-callout{margin:0 0 14px;padding:11px 13px;border:1px solid #ead3a1;border-left:4px solid #cf921f;border-radius:9px;background:#fff9e9;color:#6f5314;font-size:12px;line-height:1.65}
.role-preview-loading,.role-preview-ready,.role-preview-error,.role-not-ready{padding:11px 13px;border-radius:8px;border:1px solid var(--line,#dce3eb);background:var(--raised,#f7f9fc)}
.role-preview-ready{border-color:#b1dbc4;background:#edf8f2;color:#1d7550}.role-preview-error,.role-not-ready{border-color:#edc0c7;background:#fcecee;color:#a72a3d}
@media(max-width:1100px){.role-overview-grid{grid-template-columns:repeat(2,minmax(0,1fr))}.role-overview-layout,.role-user-grid{grid-template-columns:1fr}}
@media(max-width:680px){.role-overview-grid,.role-capability-grid{grid-template-columns:1fr}.role-workspace-nav{flex-wrap:nowrap;overflow-x:auto}.role-workspace-nav button{flex:0 0 auto}.role-user-toolbar{align-items:stretch;flex-direction:column}.role-health-item{grid-template-columns:1fr}.role-health-item>button{grid-column:1;grid-row:auto;justify-self:start}}

/* 权限管理收敛为全局原子策略与排障页；角色日常配置只保留在角色中心。 */
body[data-page="Permissions"] .permission-page-note{display:flex;align-items:center;justify-content:space-between;gap:16px;margin:0 0 12px;padding:13px 15px;border:1px solid var(--line,#dce3eb);border-left:4px solid var(--accent,#3568d4);border-radius:10px;background:var(--surface,#fff)}
body[data-page="Permissions"] .permission-page-note>div{display:grid;gap:4px}body[data-page="Permissions"] .permission-page-note strong{font-size:14px}body[data-page="Permissions"] .permission-page-note span{color:var(--muted,#657188);font-size:12px;line-height:1.6}
body[data-page="Permissions"] .permission-global-ledger .table-scroll{max-height:520px;overflow:auto}body[data-page="Permissions"] .permission-global-ledger th{position:sticky;top:0;z-index:1;background:var(--raised,#f7f9fc)}
@media(max-width:680px){body[data-page="Permissions"] .permission-page-note{align-items:stretch;flex-direction:column}body[data-page="Permissions"] .permission-page-note>button{align-self:flex-start}body[data-page="Permissions"] .permission-global-ledger .table-scroll{max-height:440px}}

/* ── 经营分析：看板卡片 + 二级报表弹窗 ────────────────────────────────────────
   看板列表只负责"挑一个看板"，完整报表在二级弹窗里看（原先直接铺在列表下方，
   一张大表把卡片挤到屏幕外）。颜色全部走 brand.css 的设计令牌，本段不新造主题。 */
.bi-dashboard-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));margin-bottom:22px;align-items:stretch;}
.bi-card{margin-bottom:0;display:flex;flex-direction:column;gap:10px;padding:20px;transition:border-color .16s ease,box-shadow .16s ease,transform .16s ease}
.bi-card:hover{border-color:#c9daff;box-shadow:0 8px 24px rgb(32 42 61 / 8%);transform:translateY(-1px)}
.bi-card-head{display:flex;align-items:flex-start;justify-content:space-between;gap:10px}
.bi-card-head h2{margin:0;font-size:16px;line-height:1.45;color:var(--text)}
.bi-card-facts{display:flex;flex-wrap:wrap;gap:8px}
.bi-card-fact{font-size:12px;color:var(--accent);background:var(--accent-soft);border:1px solid #dbe6ff;border-radius:999px;padding:3px 10px;font-weight:600}
.bi-card-hint{margin:0;font-size:12px;color:var(--muted)}
.bi-card-meta{margin:0;font-size:13px;color:var(--muted)}
.bi-card-meta strong{color:var(--text);font-weight:600}
.bi-card-actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:auto;padding-top:8px}
.bi-card>small{color:var(--muted)}
/* 高度用 `auto` + `max-height`，不用固定 height：固定高度会让表头被压到小于自身内容
   （窄屏换行后表头需要约 162px 却只分到 76px），正文于是滑到它底下，操作按钮被上下文条
   盖住点不到（实测 390px 宽）。`height:auto` 让表头按内容取高，超出 max-height 的部分
   由 `flex:0 0 auto` 的表头拒绝压缩、落到可滚动的正文上。 */
.bi-report-dialog{width:min(1280px,calc(100vw - 48px));max-width:min(1280px,calc(100vw - 48px));height:auto;max-height:min(88vh,88dvh);box-sizing:border-box;padding:0;margin:auto;border:1px solid var(--line);border-radius:14px;background:var(--surface);display:flex;flex-direction:column;overflow:hidden;color:var(--text);box-shadow:0 24px 80px #26395140}
.bi-report-dialog::backdrop{background:rgb(18 24 38 / 52%);backdrop-filter:blur(2px)}
/* 刻意不复用 .selection-dialog：那条规则把弹窗钉死在 920×760（brand.css:14），
   报表需要更宽的画面。这里自带完整外观，只借用同一套设计令牌与遮罩色调。
   表头刻意不用 position:sticky：贴顶定位时表头的"静态位置"只按第一行算，换行出来的
   内容会跑到它背后。滚动只发生在 .bi-report-body，表头本来就不会被滚走。 */
/* 必须显式 height:auto：本文件早先有一条**元素选择器** `header{height:76px}`（给顶栏用的），
   会一并命中这里的 <header class="bi-report-head">，把报表表头压成 76px —— 而它换行后
   实际需要 177px，多出来的内容就溢出到正文之上，窄屏下正好盖住操作按钮（实测
   按钮 89–124px 被 92–142px 的上下文条挡住，点不到）。class 选择器优先于元素选择器。 */
.bi-report-head{display:flex;align-items:flex-start;gap:20px;flex-wrap:wrap;padding:18px 22px;border-bottom:1px solid var(--line);background:var(--surface);min-width:0;flex:0 0 auto;height:auto}
.bi-report-heading{flex:1 1 340px;min-width:0}
.bi-report-heading h2{margin:0 0 8px;font-size:19px;line-height:1.4;color:var(--text);overflow-wrap:anywhere}
.bi-report-meta{display:flex;flex-wrap:wrap;gap:8px;margin:0}
.bi-report-headcount{display:flex;flex-wrap:wrap;gap:8px;align-items:center}
.bi-report-count{font-size:12px;color:var(--muted);background:var(--raised);border:1px solid var(--line);border-radius:999px;padding:4px 11px;font-variant-numeric:tabular-nums;white-space:nowrap}
.bi-report-actions{display:flex;flex-wrap:wrap;gap:8px;align-items:center}
.bi-report-body{padding:20px 22px 26px;overflow:auto;min-width:0;min-height:0;flex:1 1 auto;display:flex;flex-direction:column;gap:18px}
.bi-report-loading{display:grid;place-items:center;gap:14px;padding:72px 0}
.bi-report-loading-text{margin:0;color:var(--muted)}
.bi-spinner{width:32px;height:32px;border:3px solid var(--line);border-top-color:var(--accent);border-radius:50%;animation:bi-spin .8s linear infinite}
@keyframes bi-spin{to{transform:rotate(360deg)}}
.bi-report-strip{display:flex;flex-wrap:wrap;gap:10px;align-items:center;padding:12px 14px;border:1px solid var(--line);border-radius:10px;background:var(--raised)}
.bi-report-stamp{font-size:13px;color:var(--muted);font-variant-numeric:tabular-nums}
.bi-report-filter{font-size:13px;color:var(--text)}
.bi-report-about{display:flex;flex-wrap:wrap;gap:8px}
.bi-report-about>span{font-size:12px;color:var(--muted);background:var(--surface);border:1px solid var(--line);border-radius:6px;padding:5px 10px;max-width:100%;overflow-wrap:anywhere}
.bi-report-kpis{margin:2px 0}
.bi-report-section{display:flex;flex-direction:column;gap:14px}
.bi-report-section-head{display:flex;flex-wrap:wrap;gap:12px;align-items:baseline;justify-content:space-between;border-bottom:1px solid var(--line);padding-bottom:10px}
.bi-report-section-head h3{margin:0;font-size:15px;color:var(--text)}
.bi-report-caption{font-size:12px;color:var(--muted)}
.bi-report-charts{grid-template-columns:repeat(auto-fit,minmax(min(420px,100%),1fr))}
.bi-report-toolbar{margin:0}
.bi-report-toolbar span{color:var(--muted);font-size:12px;font-variant-numeric:tabular-nums}
.bi-report-pager{margin:14px 0 0;justify-content:flex-end;align-items:center}
.bi-report-pager span{color:var(--muted);font-size:12px;font-variant-numeric:tabular-nums}
.bi-report-detail .table-scroll{max-height:none}
.bi-report-dialog .bi-result table{font-variant-numeric:tabular-nums}
.bi-report-dialog .table-scroll{max-height:min(60vh,560px);overflow:auto;border:1px solid var(--line);border-radius:10px}
.bi-report-dialog .bi-kpis{grid-template-columns:repeat(auto-fit,minmax(min(200px,100%),1fr))}
.bi-report-dialog .bi-kpi{border-radius:12px;background:var(--surface)}
@media(max-width:760px){
 .bi-report-dialog{width:100vw;max-width:100vw;height:auto;max-height:100dvh;border-radius:0;border:0}
 .bi-report-head{padding:14px 16px;gap:12px}
 .bi-report-body{padding:16px}
 .bi-report-headcount{order:3}
 .bi-report-actions{order:2;margin-left:auto}
 .bi-dashboard-grid{grid-template-columns:1fr}
}
@media(prefers-reduced-motion:reduce){
 .bi-card{transition:none}
 .bi-card:hover{transform:none}
 .bi-spinner{animation-duration:2s}
}

/* ── 经营分析：看板编辑器与分析页签的现代化版式 ──────────────────────────────────
   作用域：本段所有类名都以 `bi-` 开头，只被经营分析自己的渲染器使用；不覆盖 .panel、
   button、table 等全局组件，因此导航、研发、角色等其它模块的外观不受影响。
   颜色沿用 brand.css 的设计令牌（--accent / --surface / --line / --muted），不新造主题。 */

/* ① 页头动作与通用工具条 */
.bi-lead-actions{display:flex;flex-wrap:wrap;gap:10px;margin-top:10px}
.bi-toolbar-card{display:flex;flex-wrap:wrap;gap:12px;align-items:end;padding:14px 16px;margin:0 0 16px;border:1px solid var(--line);border-radius:12px;background:var(--surface)}
.bi-toolbar-note{font-size:12px;color:var(--muted);margin-left:auto;font-variant-numeric:tabular-nums}
.bi-search{flex:1 1 260px;min-width:200px;display:grid;gap:6px;font-size:12px;color:var(--muted)}
.bi-search input{width:100%}
.bi-hint{margin:6px 0 0;font-size:12px;color:var(--muted);line-height:1.7}
.bi-field-label{display:block;margin:14px 0 8px;font-size:12px;color:var(--muted)}
.bi-dialog-subhead{margin:20px 0 10px;font-size:13px;color:var(--text)}
.bi-steps{margin:10px 0 4px;padding-left:22px;color:var(--muted);line-height:1.9}
.bi-steps li{padding:2px 0}
.bi-empty{padding:28px 22px;border:1px dashed var(--line);border-radius:12px;background:var(--raised);text-align:center;color:var(--muted)}
.bi-empty strong{display:block;color:var(--text);font-size:14px;margin-bottom:8px}
.bi-empty p{margin:0;font-size:13px;line-height:1.7}
.bi-skeleton{display:grid;place-items:center;gap:14px;padding:64px 0;color:var(--muted)}
.bi-skeleton-text{margin:0;font-size:13px}
.bi-chips{display:flex;flex-wrap:wrap;gap:6px}
.bi-chip{display:inline-flex;align-items:center;gap:6px;font-size:12px;color:#526987;background:var(--accent-soft);border:1px solid #dbe6ff;border-radius:999px;padding:3px 10px;line-height:1.6;max-width:100%;overflow-wrap:anywhere}
.bi-chip-remove{border:0;background:none;color:#8fa0bd;font-size:13px;line-height:1;padding:0 2px;cursor:pointer}
.bi-chip-remove:hover:not(:disabled){background:none;color:#b6263b}
.bi-facts{display:grid;grid-template-columns:minmax(88px,150px) minmax(0,1fr);gap:0;margin:4px 0 12px;border:1px solid var(--line);border-radius:10px;overflow:hidden}
.bi-facts dt{background:var(--raised);color:var(--muted);font-size:12px;padding:10px 14px;border-bottom:1px solid var(--line)}
.bi-facts dd{margin:0;padding:10px 14px;font-size:13px;color:var(--text);border-bottom:1px solid var(--line);overflow-wrap:anywhere}
.bi-facts dt:nth-last-of-type(1),.bi-facts dd:nth-last-of-type(1){border-bottom:0}
.pill-warn{background:#fff6e6;color:#8a5a06;border:1px solid #f0dcb0}
.bi-status{font-size:12px;border-radius:999px;padding:4px 11px;border:1px solid var(--line);background:var(--raised);color:var(--muted);white-space:nowrap}
.bi-status-ok{background:#edf8f2;border-color:#b1dbc4;color:#1d7550}
.bi-status-stale{background:#fff8e6;border-color:#e9d3a0;color:#8a5a06}
.bi-status-error{background:#fcecee;border-color:#edc0c7;color:#b6263b}
.bi-status-busy{background:var(--accent-soft);border-color:#c9daff;color:var(--accent)}

/* ② 二级弹窗（经营分析自己的壳；不复用 .selection-dialog 的固定 920×760） */
dialog.bi-dialog{width:min(720px,calc(100vw - 32px));height:auto;max-height:min(88vh,88dvh);box-sizing:border-box;padding:0;margin:auto;border:1px solid var(--line);border-radius:14px;background:var(--surface);color:var(--text);display:flex;flex-direction:column;overflow:hidden;box-shadow:0 24px 80px #26395140}
dialog.bi-dialog-wide{width:min(1040px,calc(100vw - 32px))}
dialog.bi-dialog-tall{max-height:min(92vh,92dvh)}
dialog.bi-dialog::backdrop{background:rgb(18 24 38 / 52%);backdrop-filter:blur(2px)}
.bi-dialog-head{display:flex;align-items:flex-start;gap:16px;padding:18px 22px;border-bottom:1px solid var(--line);background:var(--surface);flex:0 0 auto;height:auto}
.bi-dialog-heading{flex:1 1 auto;min-width:0}
.bi-dialog-heading h2{margin:0;font-size:17px;line-height:1.45;overflow-wrap:anywhere}
.bi-dialog-description{margin:7px 0 0;font-size:13px;line-height:1.65;color:var(--muted)}
.bi-dialog-body{padding:18px 22px;overflow:auto;min-height:0;flex:1 1 auto;display:flex;flex-direction:column;gap:12px}
.bi-dialog-body>.panel{margin-bottom:0;box-shadow:none;border:1px solid var(--line)}
.bi-dialog-foot{display:flex;flex-wrap:wrap;gap:10px;align-items:center;justify-content:flex-end;padding:14px 22px;border-top:1px solid var(--line);background:var(--raised);flex:0 0 auto}
.bi-dialog-foot>.panel{margin:0;padding:0;border:0;background:none;box-shadow:none;flex:1 1 100%}
.bi-dialog-foot>.panel h2,.bi-dialog-foot>.panel>p{display:none}
.bi-dialog-foot .bi-toolbar-note,.bi-dialog-foot .bi-hint{margin-right:auto;margin-left:0}
.bi-dialog fieldset{border:1px solid var(--line);border-radius:10px;padding:14px;margin:0}
.bi-dialog fieldset legend{font-size:12px;color:var(--muted);padding:0 6px}
.bi-dialog fieldset:disabled{opacity:.5}

/* ③ 分组多选：已选一组 chips + 可选一组过滤清单 */
.bi-checkgroup{display:flex;flex-direction:column;gap:10px;min-width:0}
.bi-checkgroup-tools{display:flex;gap:12px;align-items:center;flex-wrap:wrap}
.bi-checkgroup-tools input[type=search]{flex:1 1 220px;min-width:180px}
.bi-checklist{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(210px,100%),1fr));gap:8px;max-height:min(46vh,420px);overflow:auto;border:1px solid var(--line);border-radius:10px;padding:12px;background:var(--raised)}
.bi-check{display:flex;align-items:center;gap:9px;background:var(--surface);border:1px solid var(--line);border-radius:8px;padding:9px 11px;font-size:13px;color:var(--text);margin:0;cursor:pointer}
.bi-check:has(input:checked){border-color:#89b1ff;background:var(--accent-soft)}
.bi-check input{width:auto;flex-shrink:0}
.bi-checkgroup-actions{display:flex;gap:8px;flex-wrap:wrap}
.bi-checkgroup-actions button{font-size:12px;padding:6px 12px}
.bi-segmented{display:inline-flex;flex-wrap:wrap;gap:4px;padding:3px;background:var(--raised);border:1px solid var(--line);border-radius:999px}
.bi-segment{display:inline-flex;align-items:center;gap:6px;border-radius:999px;padding:5px 12px;font-size:12px;color:var(--muted);margin:0;cursor:pointer;white-space:nowrap}
.bi-segment input{width:auto;flex-shrink:0;margin:0;accent-color:var(--accent)}
.bi-segment:has(input:checked){background:var(--surface);color:var(--accent);font-weight:600;box-shadow:0 1px 3px #1b315214}

/* ④ 看板编辑器：左侧配置卡片 + 右侧常驻预览 */
.bi-editor-layout{display:grid;grid-template-columns:minmax(300px,380px) minmax(0,1fr);align-items:start;}
.bi-editor-controls,.bi-editor-preview{display:flex;flex-direction:column;gap:14px;min-width:0}
.bi-name-field{display:grid;gap:6px;margin-top:14px;max-width:420px;font-size:12px;color:var(--muted)}
.bi-config-card,.bi-preview-card{background:var(--surface);border:1px solid var(--line);border-radius:12px;padding:16px 18px;box-shadow:0 2px 5px #1b315204;display:flex;flex-direction:column;gap:10px;min-width:0}
.bi-config-head h3{margin:0;font-size:14px;color:var(--text)}
.bi-config-question{margin:5px 0 0;font-size:12px;color:var(--muted);line-height:1.6}
.bi-config-body{min-width:0}
.bi-config-body label{display:grid;gap:6px;font-size:12px;color:var(--muted)}
.bi-config-body select,.bi-config-body input{width:100%}
.bi-config-summary{display:grid;gap:5px;margin:10px 0 0;font-size:13px;color:var(--text);line-height:1.65}
.bi-config-summary strong{font-size:13px;font-weight:600}
.bi-config-detail{font-size:12px;color:var(--muted);overflow-wrap:anywhere}
.bi-config-foot{display:flex;flex-wrap:wrap;gap:8px;justify-content:flex-end;margin-top:auto;padding-top:4px}
.bi-config-foot button{font-size:12px;padding:8px 14px}
.bi-config-blocked{opacity:.6}
.bi-preview-head{display:flex;flex-wrap:wrap;gap:14px;align-items:flex-start;justify-content:space-between;border-bottom:1px solid var(--line);padding-bottom:12px}
.bi-preview-head h3{margin:0;font-size:15px}
.bi-preview-actions{display:flex;flex-wrap:wrap;gap:8px;align-items:center}
.bi-preview-body{min-width:0}
.bi-preview-body .panel:first-child{margin-top:4px}
.bi-preview-body>.bi-result>.bi-context{margin-top:0}
.bi-filter-rows{display:flex;flex-direction:column;gap:10px}
.bi-filter-row{display:grid;grid-template-columns:minmax(150px,1fr) minmax(150px,1fr) auto;gap:10px;align-items:end;padding:12px;border:1px solid var(--line);border-radius:10px;background:var(--raised)}
.bi-filter-row label{display:grid;gap:6px;font-size:12px;color:var(--muted);margin:0}
.bi-filter-remove{align-self:end}
.bi-format-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(260px,100%),1fr));gap:12px}
.bi-format-card .grid-form{gap:10px}

/* ⑤ 看板卡片墙（经营概览 / 分析看板共用） */
.bi-dash-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(290px,100%),1fr));gap:16px;margin-bottom:22px}
.bi-dash-card{display:flex;flex-direction:column;gap:10px;background:var(--surface);border:1px solid var(--line);border-radius:12px;padding:18px;box-shadow:0 2px 5px #1b315204;transition:border-color .16s ease,box-shadow .16s ease,transform .16s ease}
.bi-dash-card:hover{border-color:#c9daff;box-shadow:0 8px 24px rgb(32 42 61 / 8%);transform:translateY(-1px)}
.bi-dash-head{display:flex;align-items:flex-start;justify-content:space-between;gap:10px}
.bi-dash-title{margin:0;font-size:15px;line-height:1.45;color:var(--text);overflow-wrap:anywhere}
.bi-dash-facts{display:flex;flex-wrap:wrap;gap:7px}
.bi-dash-meta{margin:0;font-size:12px;color:var(--muted)}
.bi-dash-meta strong{color:var(--text);font-weight:600}
.bi-dash-actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:auto;padding-top:6px}
.bi-dash-actions button{font-size:12px;padding:8px 14px}
.bi-dash-note{color:var(--muted)}

/* ⑥ 数据表 / 统计指标 / 分析维度 / 导出任务卡片 */
.bi-dataset-grid,.bi-metric-grid,.bi-dimension-grid,.bi-export-grid{display:grid;gap:14px;margin-bottom:18px}
.bi-dataset-grid,.bi-metric-grid,.bi-export-grid{grid-template-columns:repeat(auto-fill,minmax(min(280px,100%),1fr))}
.bi-dimension-grid{grid-template-columns:repeat(auto-fill,minmax(min(340px,100%),1fr))}
.bi-dataset-card,.bi-metric-card,.bi-dimension-card,.bi-export-card{display:flex;flex-direction:column;gap:10px;background:var(--surface);border:1px solid var(--line);border-radius:12px;padding:16px 18px;box-shadow:0 2px 5px #1b315204;min-width:0}
.bi-dataset-head,.bi-metric-head,.bi-dimension-head,.bi-export-head{display:flex;align-items:flex-start;justify-content:space-between;gap:10px}
.bi-dataset-title,.bi-metric-title,.bi-export-title{margin:0;font-size:14px;line-height:1.45;color:var(--text);overflow-wrap:anywhere}
.bi-dimension-head h3{margin:0;font-size:14px;color:var(--text);overflow-wrap:anywhere}
.bi-dataset-facts,.bi-metric-facts,.bi-export-facts{display:flex;flex-wrap:wrap;gap:7px}
.bi-dataset-actions,.bi-metric-actions,.bi-export-actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:auto;padding-top:6px}
.bi-dataset-actions button,.bi-metric-actions button,.bi-export-actions button{font-size:12px;padding:8px 14px}
.bi-dimension-chip{display:inline-flex;align-items:center;gap:7px;border:1px solid var(--line);background:var(--surface);border-radius:999px;padding:6px 12px;font-size:12px;color:var(--text);cursor:pointer}
.bi-dimension-chip small{color:var(--muted);font-size:11px}
.bi-dimension-chip:hover:not(:disabled){background:var(--accent-soft);border-color:#c9daff}
.bi-field-list{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(220px,100%),1fr));gap:8px}
.bi-field-item{display:flex;flex-wrap:wrap;align-items:center;gap:8px;border:1px solid var(--line);border-radius:9px;padding:10px 12px;background:var(--raised);font-size:13px}
.bi-field-item strong{font-weight:600;color:var(--text)}
.bi-version-list{display:flex;flex-direction:column;gap:12px}
.bi-version-item{border:1px solid var(--line);border-radius:10px;padding:14px;background:var(--raised)}
.bi-version-head{display:flex;align-items:center;gap:10px;margin-bottom:10px}
.bi-version-item .bi-facts{margin-bottom:0;background:var(--surface)}
.bi-version-actions{display:flex;gap:8px;margin-top:10px}

/* ⑦ 使用权限说明卡片 */
.bi-access-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(240px,100%),1fr));gap:14px;margin:12px 0 4px}
.bi-access-card{display:flex;flex-direction:column;gap:8px;border:1px solid var(--line);border-radius:12px;padding:16px 18px;background:var(--raised)}
.bi-access-card h3{margin:0;font-size:14px;color:var(--text)}
.bi-access-card p{margin:0;font-size:13px;color:var(--muted);line-height:1.7}
.bi-access-actions{display:flex;gap:8px;margin-top:auto;padding-top:6px}
.bi-access-actions button{font-size:12px;padding:7px 12px}

@media(max-width:1080px){
 .bi-editor-layout{grid-template-columns:1fr}
 .bi-editor-controls{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(260px,100%),1fr));gap:14px}
 .bi-config-foot{justify-content:flex-start}
}
@media(max-width:760px){
 .bi-filter-row{grid-template-columns:1fr}
 .bi-toolbar-note{margin-left:0}
 .bi-facts{grid-template-columns:1fr}
 .bi-facts dt{border-bottom:0;padding-bottom:2px}
 .bi-dialog-foot{justify-content:stretch}
 .bi-dialog-foot button{flex:1}
 .bi-dash-grid,.bi-dataset-grid,.bi-metric-grid,.bi-dimension-grid,.bi-export-grid{grid-template-columns:1fr}
 .bi-preview-actions{width:100%}
 .bi-preview-actions button{flex:1}
}
@media(prefers-reduced-motion:reduce){
 .bi-dash-card{transition:none}
 .bi-dash-card:hover{transform:none}
}

/* 员工头像（迁移 019）。.avatar 是图片，.avatar-fallback 是无头像/不可见时的首字母块。 */
.avatar-slot{display:inline-flex;align-items:center}
.avatar,.avatar-fallback{width:28px;height:28px;border-radius:8px;display:inline-grid;place-items:center;object-fit:cover;flex:0 0 auto}
.avatar-fallback{background:#e6ede9;color:#42655a;font-size:12px;font-weight:600}
.avatar-editor{display:grid;gap:10px;justify-items:start}
.avatar-editor .avatar-preview .avatar,.avatar-editor .avatar-preview .avatar-fallback{width:72px;height:72px;border-radius:14px;font-size:26px}
.avatar-cell{display:inline-flex;align-items:center;gap:8px}

/* ---- 效率诊断（OaEfficiency 页）。类名与样张一致，只加新类、不覆盖既有选择器。 ---- */
.kpis{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px;margin:2px 0 16px}
.kpi{background:#fff;border:1px solid #e2e9e5;border-radius:10px;padding:14px 15px}
.kpi .k{font-size:11.5px;color:#6b7f78}
.kpi .v{font-size:24px;font-weight:600;margin:6px 0 2px;letter-spacing:-.4px}
.kpi .d{font-size:11.5px;color:#8a9a94}
.kpi .d.warn{color:#9a6a12}
.kpi .d.bad{color:#a33a2a}
.bars{display:grid;gap:9px;margin:4px 0 2px}
.bar{display:grid;grid-template-columns:190px 1fr 74px;gap:10px;align-items:center;font-size:12px}
.bar .t{color:#3d5a51;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.bar .track{height:16px;background:#f1f5f3;border-radius:5px;overflow:hidden}
.bar .fill{height:100%;background:#174f40;border-radius:5px}
.bar .fill.warn{background:#d8a33a}
.bar .fill.bad{background:#c0563f}
.bar .n{text-align:right;color:#5b7a6e;font-variant-numeric:tabular-nums}
@media (max-width:900px){.kpis{grid-template-columns:repeat(2,minmax(0,1fr))}
  .bar{grid-template-columns:120px 1fr 60px}}

/* ---- 流程画布（画布式配置器）。全部 oa-cv- 前缀，只新增，不覆盖既有选择器。 ---- */
.oa-cv-wrap{display:grid;grid-template-columns:230px minmax(320px,1fr) 330px;
  gap:14px;align-items:start;min-width:0}
/* 表单视图：左栏隐藏 ⇒ 网格退化成两栏，宽度让给表单设计器（它自己还有三栏）。 */
.oa-cv-wrap.form-view{grid-template-columns:minmax(0,1fr)}
@media (max-width:1100px){.oa-cv-wrap{grid-template-columns:200px minmax(0,1fr)}
  .oa-cv-side-right{grid-column:1 / -1}}
@media (max-width:860px){.oa-cv-wrap{grid-template-columns:1fr}}

.oa-cv-pane{background:#fff;border:1px solid #e2e9e5;border-radius:10px;padding:13px 14px}
.oa-cv-pane > h3{font-size:12.5px;margin:0 0 10px;color:#3d5a51;font-weight:600}
.oa-cv-pane > h3 + h3{margin-top:16px}

/* 左栏：组件 */
.oa-cv-comp{display:flex;justify-content:space-between;align-items:center;padding:8px 10px;
  border:1px dashed #d7e2dd;border-radius:7px;margin-bottom:7px;font-size:12.5px;color:#3d5a51;
  cursor:pointer;background:#fbfdfc}
.oa-cv-comp:hover{border-color:#174f40;background:#f4faf7}
.oa-cv-comp i{font-style:normal;color:#b7c8c2}

/* 中栏：画布 */
.oa-cv-canvas{background:#f7faf9;border:1px solid #e2e9e5;border-radius:10px;
  padding:16px 14px 26px;min-height:420px}
.oa-cv-lane{display:flex;flex-direction:column;align-items:center}

.oa-cv-node{position:relative;width:100%;max-width:520px;background:#fff;border:1px solid #dfe7e3;
  border-radius:10px;padding:11px 13px;box-shadow:0 1px 2px rgba(16,47,46,.05);cursor:pointer}
.oa-cv-node:hover{border-color:#b7cdc5}
.oa-cv-node.on{border-color:#174f40;box-shadow:0 0 0 3px rgba(23,79,64,.13)}
.oa-cv-node .hd{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.oa-cv-node .nm{font-size:13px;font-weight:600;color:#183131}
.oa-cv-node .meta{font-size:11.5px;color:#6b7f78;margin-top:6px;line-height:1.6}
.oa-cv-node .cfg{margin-left:auto;font-size:11.5px;color:#174f40;white-space:nowrap}
.oa-cv-node .del{position:absolute;top:7px;right:9px;border:0;background:none;color:#b7c8c2;
  font-size:14px;cursor:pointer;padding:2px 5px;line-height:1}
.oa-cv-node .del:hover{color:#a33a2a}
.oa-cv-node.nowait{cursor:default}
.oa-cv-node.start,.oa-cv-node.end{max-width:420px;background:#f6faf8}

/* 节点之间：连接线 + 就地插入 */
.oa-cv-link{display:flex;flex-direction:column;align-items:center;padding:5px 0}
.oa-cv-line{width:2px;height:14px;background:#c9d8d2}
.oa-cv-plus{border:1px dashed #b7cdc5;background:#fff;color:#174f40;border-radius:999px;
  width:24px;height:24px;line-height:1;font-size:15px;cursor:pointer;display:grid;place-items:center;
  margin:3px 0;padding:0}
.oa-cv-plus:hover{background:#174f40;color:#fff;border-color:#174f40}

/* 分支卡（条件 / 并行） */
.oa-cv-branch{width:100%;max-width:640px;border:1px solid #e6eeea;border-radius:10px;
  background:#fbfdfc;padding:10px 11px}
.oa-cv-branch > .bt{font-size:12px;color:#6b7f78;margin-bottom:8px;display:flex;
  justify-content:space-between;align-items:center;gap:8px}
.oa-cv-cards{display:flex;gap:9px;flex-wrap:wrap}
.oa-cv-card{flex:1 1 170px;min-width:150px;border:1px solid #e2e9e5;border-radius:8px;
  background:#fff;padding:9px 10px}
.oa-cv-card.dflt{background:#f6faf8;border-style:dashed}
.oa-cv-card .cp{font-size:10.5px;color:#8a9a94}
.oa-cv-card .cc{font-size:12px;color:#3d5a51;margin-top:4px;line-height:1.55}
.oa-cv-card .ct{font-size:11.5px;color:#174f40;margin-top:5px}

/* 右栏：常驻配置面板 */
.oa-cv-tabs{display:flex;gap:2px;border-bottom:1px solid #eef2f0;margin:-4px -14px 10px;padding:0 14px}
.oa-cv-tabs button{border:0;background:none;font:inherit;font-size:12.5px;color:#5b7a6e;
  padding:9px 11px;cursor:pointer;border-bottom:2px solid transparent}
.oa-cv-tabs button.on{color:#174f40;border-bottom-color:#174f40;font-weight:600}
.oa-cv-empty{color:#9aa8a3;font-size:12.5px;text-align:center;padding:34px 10px;line-height:1.8}
.oa-cv-bar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-bottom:12px}
.oa-cv-bar .grow{margin-left:auto;display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.oa-cv-view{display:flex;border:1px solid #dfe7e3;border-radius:7px;overflow:hidden}
.oa-cv-view button{border:0;border-right:1px solid #eef2f0;background:#fff;font:inherit;
  font-size:12.5px;color:#4a6b61;padding:8px 14px;cursor:pointer}
.oa-cv-view button:last-child{border-right:0}
.oa-cv-view button.on{background:#174f40;color:#fff}

/* ---- 表单设计器（钉钉式三栏：左控件库 / 中表单 / 右属性）。全部 oa-fd- 前缀 ---- */
.oa-fd-wrap{display:grid;grid-template-columns:200px minmax(280px,1fr) 300px;
  gap:14px;align-items:start;min-width:0}
@media (max-width:1100px){.oa-fd-wrap{grid-template-columns:190px minmax(0,1fr)}
  .oa-fd-side-right{grid-column:1 / -1}}
@media (max-width:820px){.oa-fd-wrap{grid-template-columns:1fr}}

.oa-fd-pane{background:#fff;border:1px solid #e2e9e5;border-radius:10px;padding:12px 13px}
.oa-fd-pane > h3{font-size:12px;margin:0 0 9px;color:#3d5a51;font-weight:600}

/* 左：控件库 */
.oa-fd-group{margin-bottom:12px}
.oa-fd-group > b{display:block;font-size:11px;color:#8a9a94;font-weight:500;margin-bottom:6px}
.oa-fd-items{display:grid;grid-template-columns:1fr 1fr;gap:6px}
.oa-fd-item{display:flex;align-items:center;gap:6px;border:1px solid #e6eeea;border-radius:7px;
  padding:7px 8px;font-size:11.5px;color:#3d5a51;cursor:pointer;background:#fbfdfc}
.oa-fd-item:hover{border-color:#174f40;background:#f4faf7}
.oa-fd-item i{font-style:normal;font-size:12px;color:#9ab0a8}

/* 中：表单画布 */
.oa-fd-canvas{background:#f2f6f4;border:1px solid #e2e9e5;border-radius:10px;padding:18px 14px 30px}
.oa-fd-sheet{max-width:460px;margin:0 auto;background:#fff;border-radius:12px;
  box-shadow:0 6px 20px rgba(16,47,46,.07);padding:16px 16px 22px}
.oa-fd-sheet .ft{font-size:15px;font-weight:600;margin-bottom:2px}
.oa-fd-sheet .fs{font-size:11.5px;color:#8a9a94;margin-bottom:14px}
.oa-fd-field{position:relative;border:1px solid transparent;border-radius:8px;padding:9px 10px;
  margin-bottom:8px;background:#fbfdfc;cursor:pointer}
.oa-fd-field:hover{border-color:#cfe0d9}
.oa-fd-field.on{border-color:#174f40;box-shadow:0 0 0 3px rgba(23,79,64,.1);background:#fff}
.oa-fd-field .fl{font-size:12px;color:#4a6b61;margin-bottom:4px}
.oa-fd-field .fl i{color:#c0563f;font-style:normal;margin-left:3px}
.oa-fd-field .fi{border:1px solid #e6eeea;border-radius:6px;padding:7px 9px;font-size:12px;
  color:#9aa8a3;background:#fff}
.oa-fd-field .fo{position:absolute;top:6px;right:8px;display:flex;gap:4px;opacity:0;transition:.1s}
.oa-fd-field:hover .fo,.oa-fd-field.on .fo{opacity:1}
.oa-fd-field .fo button{border:0;background:#fff;border:1px solid #e2e9e5;border-radius:5px;
  width:22px;height:22px;line-height:1;font-size:12px;cursor:pointer;color:#5b7a6e;padding:0}
.oa-fd-field .fo button:hover{color:#174f40;border-color:#b7cdc5}
.oa-fd-drop{border:1px dashed #c9d8d2;border-radius:8px;padding:12px;text-align:center;
  font-size:11.5px;color:#9aa8a3;margin-bottom:8px}
.oa-fd-drop.hot{border-color:#174f40;background:#eef6f2;color:#174f40}
.oa-fd-empty{text-align:center;color:#9aa8a3;font-size:12px;padding:30px 10px;line-height:1.9}

/* 右：属性 */
.oa-fd-row{display:grid;gap:5px;margin-bottom:11px}
.oa-fd-row > span{font-size:11.5px;color:#6b7f78}
.oa-fd-row select,.oa-fd-row input{width:100%;max-width:none}
.oa-fd-flag{display:flex;align-items:center;gap:7px;font-size:12px;color:#3d5a51;
  margin-bottom:8px}
.oa-fd-flag span{white-space:nowrap}
.oa-fd-flag input{flex:0 0 auto;width:auto;margin:0}
.oa-fd-hint{font-size:11px;color:#9aa8a3;line-height:1.6}

/* 右栏顶部「回到流程级设置」入口。必须常驻：流程名称/业务编码只在流程级设置里，
   而它们是必填项 —— 没有它，用户加完节点就填不了必填项。 */
.oa-cv-back{display:flex;align-items:center;justify-content:space-between;gap:8px;
  margin:-2px -14px 10px;padding:8px 14px;border-bottom:1px solid #eef2f0;background:#fbfdfc}
.oa-cv-back .oa-note{margin:0;font-size:11px;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap}

/* 「表单权限」里的一行：勾选框 + 字段名。
   ⚠️ 必须显式写 flex —— 通用规则 `label{display:grid;gap:7px}` 会把它排成两行，
   勾选框掉到文字下面（用户截图报的错位）。 */
.oa-check{display:flex;align-items:center;gap:8px;padding:4px 0;font-size:13px;
  color:#2f4a3e;cursor:pointer}
.oa-check input[type=checkbox]{width:15px;height:15px;margin:0;flex:0 0 auto;cursor:pointer}
.oa-check span{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* 字段权限表头：全选 + 已选计数 */
.oa-check-head{display:flex;align-items:center;justify-content:space-between;gap:8px;
  margin:2px 0 6px;padding-bottom:6px;border-bottom:1px solid #eef2f0}
.oa-check-head .oa-check{padding:0;font-weight:600}
.oa-check-head .oa-note{margin:0;font-size:11px}

/* OA 配置器放进弹窗时的适配。
   `.bi-dialog-body` 是 flex column + padding，而配置器自带 `.oa-cv-wrap` 三栏 grid；
   内层宽度要撑满，否则三栏会被压窄。窄屏（<=900px）在弹窗里堆成一栏，
   避免三栏在 1040px 的弹窗里挤成一条缝。 */
.oa-cfg-dialog .bi-dialog-body{padding:14px 16px}
.oa-cfg-dialog .bi-dialog-body>.oa-cv-wrap,.oa-cfg-dialog .bi-dialog-body>.oa-fd-wrap{width:100%}
.oa-cfg-dialog .oa-cv-wrap{grid-template-columns:200px minmax(280px,1fr) 300px}
@media (max-width:900px){
  .oa-cfg-dialog .oa-cv-wrap,.oa-cfg-dialog .oa-fd-wrap{grid-template-columns:minmax(0,1fr)}
}

/* ── ADR-036 OA 附件 ──────────────────────────────────────────────────────────
   全部是**新名字**，不改写任何既有选择器（`styles.css` / `brand.css` 之间已有 66 个
   重复选择器，见 UI/UX R0 台账；新增样式一律用独占类名，不再叠加重复）。
   图片尺寸照 `.rd-document-image`（本文件 :43）的既有口径，避免第二套图片约束。 */
.oa-attachment-list{display:flex;flex-direction:column;gap:6px;margin:6px 0}
.oa-attachment-item{display:flex;flex-wrap:wrap;align-items:center;gap:8px;
  padding:6px 8px;border:1px solid var(--line,#d8dee7);border-radius:6px}
.oa-attachment-name{flex:1 1 auto;min-width:0;overflow-wrap:anywhere}
.oa-attachment-view{flex-basis:100%}
.oa-attachment-image{display:block;max-width:100%;max-height:640px;object-fit:contain}


/* ── UIUX-B6 / B4.1「流程管理」追加块 ────────────────────────────────────────
   纯追加：不修改、不删除上面任何既有规则；新类名在此之前全仓 0 引用。
   只服务 oaTemplates 的局部状态与行内版本展开。 */

/* 列表被截断时的提示条（读后端既有的 total / has_more） */
.oa-trunc{margin:6px 0 0;font-size:12px;line-height:1.6;color:#526987;
  background:#eef3fb;border:1px solid #dbe4f2;border-radius:6px;padding:7px 10px}

/* 页面级局部状态块（无权限 / 取数失败）——替代 app.js:276 的整页替换 */
.oa-state{padding:26px 8px;text-align:center}
.oa-state-title{font-size:15px;font-weight:600;color:#202a3d;margin:0 0 6px}
.oa-state-why{font-size:13px;line-height:1.65;color:#657188;margin:0 auto 14px;max-width:54ch}

/* 行内版本展开（同一时刻只一行） */
.oa-ver-detail > td{background:#f8faff;padding:0 14px 12px;border-top:1px solid #eef1f7}
.oa-ver-head{display:flex;align-items:center;justify-content:space-between;gap:10px;margin:10px 0 6px}
.oa-ver-title{font-size:12px;color:#657188}

/* ── UIUX-B10：流程配置器弹窗（`oaConfigDialog`）的尺寸 ─────────────────────
   用户报「这个弹窗太小了」。两个来源，都可复核：
   ① `.oa-cfg-dialog` 原先只覆盖 padding，尺寸沿用 BI 的 `.bi-dialog-wide`
      = `min(1040px,…)`；而三栏为 `200px + 1fr + 300px`（`styles.css:476`）
      ⇒ 左右固定吃掉 500px，**画布只剩约 470px**，控件与属性挤成一条缝。
   ② `.bi-dialog` 是 `height:auto`（`styles.css:168`）⇒ 弹窗贴着内容高度，
      **画布没有可伸展的空间**，整块只有约 530px 高，下方大片页面空白浪费。

   这是**三栏工作台**，不是普通表单弹窗，尺寸诉求与 BI 弹窗不同。
   ⇒ 只覆盖 `.oa-cfg-dialog`，**不动 `.bi-dialog-wide`**（BI 模块仍 1040px，零影响）；
      `styles.css:474-478` 的既有规则**一条不改**，靠"同特异度、后来居上"覆盖。 */
dialog.oa-cfg-dialog{width:min(1500px,calc(100vw - 32px));
  height:min(88vh,900px);max-height:min(92vh,92dvh)}
/* 让三栏撑满弹窗高度，画布纵向可伸展（否则 grid 仍是内容高度） */
.oa-cfg-dialog .bi-dialog-body>.oa-cv-wrap,
.oa-cfg-dialog .bi-dialog-body>.oa-fd-wrap{flex:1 1 auto;min-height:0}
/* 画布列拿回被固定列吃掉的宽度：200/300 → 220/320，中间改 minmax(0,1fr) 允许收缩。
   ⚠️ UIUX-B13 修正：**必须排除 `.form-view`**。表单视图（`.oa-cv-wrap.form-view`）靠
   `styles.css:326` 的 `grid-template-columns:minmax(0,1fr)` 走**单列**布局，而表单设计器
   `.oa-fd-wrap`（自身是个三栏栅格）就嵌在它里面的 `.oa-cv-pane` 里。
   原先这条与那条**同特异度 (0,2,0)** 且本规则在后 ⇒ 覆盖掉单列 ⇒ 表单设计器被挤进 220px
   的第一列，表现为"预览卡片只剩一条、单字竖排"。**父链实测**：
   `oa-fd-wrap 190px ← (无类)div 190px ← oa-cv-pane 220px ← oa-cv-wrap.form-view 1372px`。
   加 `:not(.form-view)` 后特异度升到 (0,3,0)，且对表单视图**完全不适用** ⇒ 单列规则重新生效。 */
.oa-cfg-dialog .oa-cv-wrap:not(.form-view){grid-template-columns:220px minmax(0,1fr) 320px}
/* ⚠️ UIUX-B13：**根因其实在更早的一条既有规则**。`styles.css:476` 的
   `.oa-cfg-dialog .oa-cv-wrap{grid-template-columns:200px minmax(280px,1fr) 300px}`
   与 `styles.css:326` 的 `.oa-cv-wrap.form-view{grid-template-columns:minmax(0,1fr)}`
   **同特异度 (0,2,0)**，而 476 在 326 之后 ⇒ **表单视图的单列布局早就被它压掉了**
   （实测 `.oa-cv-wrap.form-view` 计算值 = `200px 844px 300px`）。
   ⇒ **这是既有缺陷，与 UIUX-B10 无关**（我一度误判成自己造成的回归，已更正）。
   修法：在此**新增**一条更高特异度 (0,3,0) 的规则把单列恢复回来，
   **不改 476、也不改 326**（既有规则一行不动，纯追加，可单独回退）。 */
.oa-cfg-dialog .oa-cv-wrap.form-view{grid-template-columns:minmax(0,1fr)}
/* 窄屏仍退回单栏（与既有的 <=900px 行为一致），但弹窗占满可用高度 */
@media (max-width:900px){
  dialog.oa-cfg-dialog{width:calc(100vw - 16px);height:min(92vh,92dvh)}
  .oa-cfg-dialog .oa-cv-wrap{grid-template-columns:minmax(0,1fr)}
}

/* ── UIUX-B17：验收方抓出的两处，逐条修 ────────────────────────────────────── */

/* 【F-01｜窄屏回退被特异度压死】B13 为修表单视图，给 `.oa-cfg-dialog .oa-cv-wrap`
   加了 `:not(.form-view)`，特异度升到 **(0,3,0)**，结果**反而压死了窄屏单栏回退** ——
   `styles.css:478` 的 (0,2,0) 与 B10 媒体查询里的 (0,2,1) **全成死声明** ⇒ ≤900px
   流程视图仍三栏、固定最少 568px。而 `styles.css:545` 的注释还写着"窄屏仍退回单栏
   （与既有的 <=900px 行为一致）" ⇒ **照注释验收必然判通过**。
   修法：把窄屏回退提到**同特异度 (0,3,0)**；它在本文件更靠后 ⇒ 由顺序取胜，
   不再依赖"谁的特异度高"。 */
@media (max-width:900px){
  .oa-cfg-dialog .oa-cv-wrap:not(.form-view){grid-template-columns:minmax(0,1fr)}
  .oa-cfg-dialog .oa-cv-wrap.form-view{grid-template-columns:minmax(0,1fr)}
}

/* 【F-02｜`#notice` 没有 `white-space`】`styles.css:4` 与 `brand.css:11` 两条 `#notice`
   **都没有** `white-space` ⇒ `white-space:normal` ⇒ `notify()` 里的 `\n` **塌缩成空格**。
   而 `oa.js` 的"彻底删除被阻挡"关联清单正是用 `\n` 拼的 ⇒ 用户看到的是一长行，
   「逐条显示关联数据」**在界面上从未兑现**（B11 只把数据链打通了）。
   `notify` 走的是 `textContent`，所以 `pre-wrap` 就够，**不需要 innerHTML**。 */
#notice{white-space:pre-wrap}

/* ── T4：验收代理抓出的 ①② ＋ 用户当轮报的 ④（整块**纯追加**，既有规则一行未改）──────
   为什么整块只落 `styles.css`、不落 `tokens.css`：LAN 入口的静态白名单
   （`control_center/server.py:57-59`）**没有 `/tokens.css`** ⇒ 在 8765 / 8766 上该请求返回
   401、整份样式表**从不生效**（实测：普通 `.pill` 的 border-width = 0px，而 tokens.css 给它
   1px 边框）。把修复放那里等于没修。`brand.css` 是主题层，本轮不动。
   每条都注明特异度与它压过谁 —— 本项目三次事故都出在这里（B13 把 `.oa-cfg-dialog .oa-cv-wrap`
   加 `:not(.form-view)` 抬到 (0,3,0)，反而压死了窄屏媒体查询）。 */

/* ① FAIL-6｜窄屏下列表行的「配置」按钮被横向裁掉：不是"点了没反应"，是**命中不到**
   实测（360px，真实夹具）：`.table-scroll` clientWidth 302 / scrollWidth 350，按钮矩形
   {x:319,w:46}；`elementFromPoint(按钮中心)` 命中 `SECTION.panel` ⇒ `showModal` 调用数 **0**。
   解法＝复用本项目**既有**的「窄屏表格改整行卡片」（`.people-table` @ 本文件 :22-33、
   `.fx-table` @ `tokens.css:217-224`），作用域只给流程管理页：`body[data-page="OaTemplates"]`
   由 `app.js:120` 每次渲染写入 ⇒ 其余列表（共享 `table()` 的 57 个渲染点）一张都不受影响。
   这是**结构性**保证：table/tbody/tr/td 全改块级/网格之后不可能再产生横向溢出，
   所以同时把 `overflow-x` 收回 `visible` —— "不被任何滚动容器裁切"由结构承担，
   而不是"把表格压窄、大概不会溢出"。
   已知代价（**UIUX-DS1 更正，2026-09-22：本段前提已失效**）：原文「共享 `table()` 不写 `data-label`」
   已不成立 —— 共享 `table()` 现在给每个 `td` 写 `data-label`（`app.js:342`；操作列写 `'操作'`，
   `peopleTable` 的写点在 `app.js:509`），所以下面的 `td::before` 能拿到列标签，不再渲染为空；
   原文引用的 `app.js:287`／`:410` 是过期行号。**本块只改注释文字，规则一行未动。** */
@media (max-width:1000px){
  /* (0,2,1) 压本文件 :6 的 `.table-scroll{overflow-x:auto}`(0,1,0) */
  body[data-page="OaTemplates"] .table-scroll{overflow-x:visible}
  /* (0,2,2)/(0,2,3) 压本文件 :4 的 `table{width:100%}`(0,0,1) */
  body[data-page="OaTemplates"] .table-scroll>table,
  body[data-page="OaTemplates"] .table-scroll>table>tbody{display:block;width:100%}
  body[data-page="OaTemplates"] .table-scroll>table>thead{display:none}
  /* (0,3,4)：把每一行变成卡片容器 */
  body[data-page="OaTemplates"] .table-scroll>table>tbody>tr{display:block;margin:0 0 14px}
  /* (0,4,4)：行内版本展开那一行（`tr.oa-ver-detail`）不是数据行，排除在卡片网格之外 */
  body[data-page="OaTemplates"] .table-scroll>table>tbody>tr:not(.oa-ver-detail){
    display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:6px 16px;
    padding:14px;border:1px solid var(--line);border-radius:8px}
  /* 刻意**不写 background**：写了就会盖掉 `brand.css:7` 的 `tbody tr:hover{background:#f8faff}`
     (0,1,2)，卡片会失去悬停反馈；不写时卡片背景＝面板白底，外观相同而悬停保留。 */
  /* (0,4,5) 压本文件 :4 与 `brand.css:7` 的 `td`(0,0,1) —— 去掉表格单元格语义与 370px 上限 */
  body[data-page="OaTemplates"] .table-scroll>table>tbody>tr:not(.oa-ver-detail)>td{
    display:block;border:0;padding:0;max-width:none;min-width:0;order:2}
  body[data-page="OaTemplates"] .table-scroll>table>tbody>tr:not(.oa-ver-detail)>td::before{
    content:attr(data-label);display:block;font-size:11px;line-height:1.5;
    color:var(--muted);margin-bottom:2px}
  /* (0,5,5)：第一格＝卡片标题、最后一格＝动作条（顺序照 `.people-table` :29-31 的既有做法） */
  body[data-page="OaTemplates"] .table-scroll>table>tbody>tr:not(.oa-ver-detail)>td:first-child{
    grid-column:1/-1;order:0;font-size:15px;font-weight:600}
  body[data-page="OaTemplates"] .table-scroll>table>tbody>tr:not(.oa-ver-detail)>td:last-child{
    grid-column:1/-1;order:1;display:flex;flex-wrap:wrap;align-items:center;gap:8px;
    padding-top:10px;border-top:1px solid var(--line)}
  body[data-page="OaTemplates"] .table-scroll>table>tbody>tr:not(.oa-ver-detail)>td:last-child::before{display:none}
  body[data-page="OaTemplates"] .table-scroll>table>tbody>tr:not(.oa-ver-detail)>td:last-child>button{margin:0}
  /* (0,3,5)：只把版本行的单元格块级化，padding/background 仍由本文件 :507 提供
     （避免 `display:table-cell` 在块级父元素里生成匿名表盒） */
  body[data-page="OaTemplates"] .table-scroll>table>tbody>tr.oa-ver-detail>td{display:block;max-width:none}
}

/* ② F-10｜`.pill-warn` 从来是死的（**既有缺陷，非本轮引入**）
   根因：`.pill-warn`（本文件 :160）是 (0,1,0)，与 `brand.css:7` 的 `.badge,.pill`（0,1,0）
   同特异度而 brand 后加载 ⇒ 后到者胜；`tokens.css:185` 的 `.badge,.pill` 再压一次
   （云端入口才有 tokens.css）。CDP `CSS.getMatchedStylesForNode` 实测，元素 `class="pill pill-warn"`：
   命中的两条规则依次是 `.pill-warn{color:#8a5a06;background:#fff6e6}`、`.badge,.pill{background:#eef3fb;color:#526987}`
   ⇒ 计算色与普通 `.pill` **逐位相同**（rgb(238,243,251) / rgb(82,105,135)），
   「尚未发布 / 草稿 / 待审批 / 未批准」四处（`p1.js:45/81/153/267`）从来没有警示色。

   修法**取"提特异度"、不取"调顺序"**：`.pill.pill-warn` = (0,2,0) ⇒ 无论
   styles.css → brand.css → tokens.css 的加载顺序如何、也无论 tokens.css 在不在，
   都以 (0,2,0) > (0,1,0) 胜出。不选调顺序的理由：靠先后决定胜负正是本项目反复踩的那一类坑
   （`.oa-cfg-dialog .oa-cv-wrap` 与 `.oa-cv-wrap.form-view` 同特异度靠顺序，B13 改特异度
   又压死窄屏媒体查询）—— **顺序是隐式依赖，从任何单个文件里都看不出来**。
   只**新增**这一条；本文件 :160 的既有 `.pill-warn` 一字未改（它此后是冗余死声明，
   可留给 S1 那类"删被完全遮盖的声明"的清理批次一并处理）。 */
.pill.pill-warn{background:#fff6e6;color:#8a5a06;border:1px solid #f0dcb0}

/* ④ 用户当轮报「左边导航栏太宽了…**还可以再减少宽度**」（第 ⑤ 项在此基础上再收一档）

   先回答"到底哪一条在生效"：`styles.css:1` 的 `aside{width:238px;padding:32px 22px}` 是 (0,0,1)，
   而 `brand.css:16` 的 `#workspace-sidebar{width:var(--sidebar-width)}` 带 id = (0,1,0) ⇒ **后者胜**；
   `--sidebar-width` 定义在 `brand.css:2` 的 `:root`（216px），`brand.css:31` 在 ≤1100px 把它改成 190px。
   实测确认：1440/1280 下 aside = **216px**（= `--sidebar-width`），**238px 那条是死声明**。
   （本条只覆盖 `width`/`padding-inline` 属性本身，**不新增、不修改任何自定义属性**，
   因此不涉及 `:root`(0,1,0) 赢 `html`(0,0,1) 那个坑。）

   实测（真实夹具 1440/1280，改前）：aside 216 ⇒ `#nav` 191 ⇒ 导航项 191 —— 导航项**本来就撑满** `#nav`，
   空隙不在项外、而在**项内**：最长 chevron 项「组织与权限」文字仅 70px（⚠️ 2026-09-22 该分组已改名为「组织权限」= 实测 56px，**取值 172px 经复核仍然成立**，见本文件末尾「U3 ④ 复核注」），而项内可用 139px，
   右侧约 70px 是空的（项底色透明，只有选中项才看得见底色）。所以能动的是**栏宽＋内边距＋项内间距**。
   按最长项反算"不换行所需的最小栏宽"：
     栏内边距 8+8 ＋ 边框 1 ＋ 项内边距 11+11 ＋ 前导图标 20 ＋ 间距 10 ＋ 最长文字 70 ＋
     间距 10 ＋ chevron 14 = **163px** ⇒ 取 **172px**（留 9px 余量）。
   相对改前 216px：**−44px（−20%）**；相对上一版 190px：再减 18px。
   （最长文字用 chevron 项「组织与权限」70px，不是「AI 用量与预算」——后者 87px 但不带 chevron；
     ⚠️ 2026-09-22 复核：改名后最长 chevron 项是 4 字项（「组织权限」等，并列 56px），所需最小栏宽
     163 → **148px**，172px 的余量由 9px 增至 24px ⇒ **取值不变**，见本文件末尾「U3 ④ 复核注」。
     `app.js` 已把该分组改名为「AI 用量」，无论新旧文案，约束项都是 70px 那一条。）

   作用范围 `@media (min-width:761px)`：≤760px 是**抽屉**（`brand.css:33` 硬编码
   `width:216px;padding:22px 12px`），**一个字节都不动** —— 刻意避开 B13 那种"顺手改坏窄屏"的坑。

   特异度与竞争（逐条写明，这是本项目的高发坑）：
   · `aside#workspace-sidebar`（1,0,1）压 `brand.css:16` 的 `#workspace-sidebar{width:var(--sidebar-width)}`(0,1,0)；
     也压过 `brand.css:31` 那条 `@media(max-width:1100px){:root{--sidebar-width:190px}}` 的**后果**
     （它只改令牌，消费点仍是 (0,1,0)）。该媒体查询里的**其它**声明（顶栏内边距、字号、导航项内边距）
     一条都不受影响 ⇒ 不是"把媒体查询压死"。
   · `body>main`（0,0,2）压 `brand.css:16` 的 `main{margin-left:var(--sidebar-width)}`(0,0,1)；
     登录页 `body[data-authenticated=false] main{margin-left:0}`(0,1,2) 仍高过我 ⇒ 居中不受影响。
   · `#workspace-sidebar #nav .workspace-nav-item`（2,1,0）压 `brand.css:16` 的
     `#nav .workspace-nav-item`(1,1,0)；只覆盖 `padding-inline` 与 `gap`，块向内边距 12px、字号 14px 不动。
   · 761–1100px 段同样是 172px（< `brand.css` 的 190px）⇒ **1100→1101 处不跳变**；
     该段的导航项仍是 brand 的 `padding:11px 10px; gap:9px; font-size:13px`（更紧），反算只需 154px。
     ⚠️ 2026-09-22 复核更正（UIUX-DS6）：上面那个 190px（`brand.css:31` 的 `:root{--sidebar-width:190px}`）
     **从来没生效过** —— 它只改令牌，消费点仍是 `brand.css:16` 的 `var(--sidebar-width)`(0,1,0)，被本块 (1,0,1) 压住。
     实测（级联 PoC，1100 与 1000 两档）`aside` 都是 **172px** ⇒ 761–1100px 与 ≥1101px **同源同值**，
     不存在"密度默认 190px 会被用户偏好覆盖"这回事。详见 `docs/fitease/uiux/DS6_SIDEBAR_ADJUSTABLE.md` §四·补 第 7 条。 */
@media (min-width:761px){
  /* ⚠️ UIUX-DS6-A（2026-09-22 用户已确认）：本条与下一条的 `172px` 原本是**同一条宽度的手工双写**，
     现在改为吃 `--fx-sidebar-w` 并**带 172px 兜底** ⇒ JS 不写变量时（未登录 / 脚本未执行 / 脚本报错）
     与改造前**逐像素相同**。已实测（级联 PoC 50/50）：7 档视口下 `aside` 计算宽、
     `main` 计算 `margin-left`、`main` rect.left 三者在改前/改后**全等**。
     特异度一字未动（仍是 `aside#workspace-sidebar` = 1,0,1 与 `body>main` = 0,0,2），
     所以对 `brand.css` 两位竞争者的胜负关系不变。
     变量**只由 JS 写在 `documentElement` 的内联样式上**，本文件不定义它（两个定义处会立刻产生"谁赢"问题）。 */
  aside#workspace-sidebar{width:var(--fx-sidebar-w,172px);padding-inline:8px}
  body>main{margin-left:var(--fx-sidebar-w,172px)}
}
@media (min-width:1101px){
  #workspace-sidebar #nav .workspace-nav-item{padding-inline:11px;gap:10px}
}

/* ── T4 ⑥：布局密度 第 1+2+3 档（用户已确认；方案 `docs/fitease/uiux/LAYOUT_DENSITY_PLAN.md`）──
   基线（真实夹具，改前实测，1440×900 与 1280×800 同值）：header **68px**、header 底→面板顶 **20px**、
   首个可操作控件 top **177**、数据行高 **57px**、一屏 11/10 行、`.panel` padding 18px、
   `td` padding 11px 12px、`td button` 6px 10px（30×46px）、`table` line-height `normal`、
   BI 页 `.subnav` 1 行未换行。
   全部以**同属性、更高特异度**的追加规则实现（既有规则一行未改），逐条竞争见注释。

   ⚠️ 为什么整段关进 `@media (min-width:761px)`：本次密度目标由 1440/1280 两个视口定，
   而 ≤760px 是**移动抽屉**形态（`brand.css:33`）。把间距改在移动端会同时缩小触控目标、
   并影响 ①② 刚修好的窄屏表格；关起来之后 **360/480 一个字节都不变**（768 属 ≥761，照改）。 */

/* 档 1｜间距与栏宽 */
@media (min-width:761px){
  /* `--header-height` 68 → 56。
     ⚠️ 必须用 `html:root`(0,1,1)：brand.css:2 的 `:root`(0,1,0) 会赢 `html`(0,0,1)（本会话踩过的坑）。
     `html:root` 既压过 brand.css:2，又**不碰** brand.css:33 在 ≤760px 设的 62px（本规则只在 ≥761px 生效）。
     消费点 `#workspace-header{height/min-height:var(--header-height)}`（brand.css:16）随之下降。 */
  html:root{--header-height:56px}
  /* (1,0,1) 压 `brand.css:28` 的 `#app{padding:20px 24px}`(1,0,0) 与 `styles.css:4` 媒体里的
     `#app{padding:25px}`(1,0,0) —— 后者本来就被 brand 那份压着（同特异度、brand 后加载） */
  body #app{padding:14px 20px}
  /* (0,1,1) 压 `brand.css:8` 的 `.subnav{...margin:0 0 16px;padding:0 0 10px}`(0,1,0)
     与 `styles.css:5` 的 `.subnav{margin-bottom:25px;padding-bottom:15px}`(0,1,0) */
  body .subnav{margin:0 0 10px;padding-bottom:8px}
  body .workspace-intro{padding:10px 14px}          /* (0,1,1) 压 `brand.css:41`(0,1,0) */
  body .workspace-heading{gap:10px}                 /* (0,1,1) 压 `brand.css:16` 的 gap:16px(0,1,0) */
  body .workspace-tools{gap:8px}                    /* (0,1,1) 压 `brand.css:16` 的 gap:12px(0,1,0) */
  /* (1,0,1) 压 `brand.css:16` 的 `#workspace-header{...padding:0 24px;gap:18px}`(1,0,0)；
     也压过 `styles.css:1` 的 `header{padding:0 42px}`(0,0,1)。≤760px 的 `padding:0 12px;gap:9px`
     在 brand.css:33，被本媒体查询关在外面 ⇒ 不受影响。 */
  body #workspace-header{padding:0 18px;gap:12px}
  /* (0,1,2)：字号的竞争者 `.panel h2{font-size:15px}`(0,1,1) 与 `.panel>p{font-size:13px}`(0,1,1)
     都带 [data-*] 之外的类选择器，必须再加一层 `body` 才能稳定压过（否则同特异度、brand 后加载 ⇒ 我输） */
  body .workspace-intro>h2{font-size:15px}
  body .workspace-intro>p{font-size:12.5px}
}

/* 档 3｜表格密度（**全局**）：只收 `td` padding 是没用的 —— 行高是被「操作」列里
   默认尺寸的按钮撑起来的（实测 `td button` 30px + margin 4 + td padding 22 ≈ 57px）。
   所以按钮与徽章必须同时收，行高才会真的掉下来。 */
body table{line-height:1.35}                        /* (0,0,2) 压 `styles.css:4` 的 table(0,0,1) */
body td,body th{padding:7px 12px}                   /* (0,0,2) 压 `brand.css:7` 的 `td,th{padding:11px 12px}`(0,0,1) */
body .panel{padding:12px 14px}                      /* (0,1,1) 压 `brand.css:6` 的 `.card,.panel{padding:18px}`(0,1,0)；
                                                       嵌套面板 `.panel .panel{padding:14px}`(0,2,0) 仍胜出 ⇒ 不受影响 */
body td button{padding:3px 8px;font-size:12px;line-height:1.5}
/* (0,0,3) 压 `styles.css:4` 的 `td button{padding:6px 10px}`(0,0,2) 与 `brand.css:7` 的 `td button{font-size:12px}`(0,0,2) */
body td .badge,body td .fx-chip{height:20px;line-height:20px;padding:0 7px}
/* (0,1,3) 压 `styles.css:4` 的 `.badge{padding:4px 8px}`(0,1,0)；`height` 对 inline 元素本不生效，
   但云端入口加载的 `tokens.css` 会把 `.badge` 变成 `inline-flex`（22px）——那时这条把上限压到 20px。
   `line-height:20px` 对两条入口都真生效（行盒高度）。 */
/* ① 的窄屏卡片里，操作按钮保持 6px 12px：档 3 的 3px 8px 是给表格的，卡片上要留触控高度。
   (0,4,6) 压上面那条 `body td button`(0,0,3)。 */
@media (max-width:1000px){
  body[data-page="OaTemplates"] .table-scroll>table>tbody>tr:not(.oa-ver-detail)>td:last-child>button{
    padding:6px 12px}
}

/* ── U3 追加块（**纯追加**：以上既有规则一行未改，只在文件末尾追加）──────────────────
   本文件全程 CRLF、末尾无换行 ⇒ 追加时写入 `\r\n\r\n` + 本块，本块自身也以 CRLF 结尾。
   证据与逐像素对照见 `_validation/uiux-tools/u3-css-finish.md`（真实页面、私有端口夹具）。

   为什么整块只落 `styles.css`：两个入口的静态白名单（`control_center/server.py:57-59`）
   **都没有 `/tokens.css`** ⇒ `/tokens.css` 返回 401、整份 `tokens.css` 不生效（实测该表的
   `sheet.cssRules.length` = 0）。所以本机夹具上 `td .fx-chip` 的真实计算值是
   `display:inline; line-height:16.2px; padding:0px`，而 `tokens.css:146` 给它的是
   `inline-flex; 22px; scale 内边距`。`brand.css` 是主题层，本轮不动。

    ① 窄屏卡片补列标签（跨文件，本文件只做 CSS 那一半）
    **【UIUX-DS1 更正，2026-09-22：以下前提已失效】**原文「共享 `table()` 不写 `data-label`」
    （且称 `peopleTable()` 在 `app.js:458` 写）已不成立 —— 另一半**已经落地**：共享 `table()` 现在给每个
    `td` 写 `data-label`（`app.js:342`；操作列写 `'操作'`，`peopleTable` 的写点在 `app.js:509`）
    ⇒ 本文件 :611 那条 `td::before{content:attr(data-label)}` 现在拿得到标签。
    原文评测记录（保留留痕）：该批验收是在 360/480 的**页面内存里**用 CDP 临时写 `dataset.label`
    （列标题取 `thead th` 原文：名称/编码/类型/已发布版本/状态/操作）验证 CSS 生效，未写进仓库任何文件。
   本条只补既有实现漏掉的分支：**没有标签（或标签是空串）时 `::before` 不该白占一行** ——
   它是 `display:block` 加 `margin-bottom:2px` 的空盒，实测（360/480，真实夹具）每个单元格
   18.19px → 16.19px（**−2.00px/格**）、卡片行 149.63px → 143.63px（**−6.00px**）；
   写了 `data-label` 后 `::before` 高 16.5px、卡片行 143.63px → 199.13px（标签真的显示出来了）。
   特异度 (0,4,6)：类/属性 4（`[data-page]`、`.table-scroll`、`:not(.oa-ver-detail)` 里的
   `.oa-ver-detail`、`:not([data-label])`）＋ 元素 6（body/table/tbody/tr/td/::before），
   压本文件 :610-612 的 `...>td::before`(0,3,6)。只在 `@media (max-width:1000px)` 且
   `body[data-page="OaTemplates"]` 内 ⇒ 1440 宽屏**逐像素零差异**（1218×134 截图
   163212/163212 像素完全相同，全元素计算样式快照 0 处变化）。 */
@media (max-width:1000px){
  body[data-page="OaTemplates"] .table-scroll>table>tbody>tr:not(.oa-ver-detail)>td:not([data-label])::before,
  body[data-page="OaTemplates"] .table-scroll>table>tbody>tr:not(.oa-ver-detail)>td[data-label=""]::before{display:none}
}

/* ② `td .fx-chip` 在 tokens.css 缺席时的几何兜底（**不是**给它定义外观，外观归 tokens.css）
   只补与 `body td .badge`（本文件 :730）**同一组几何**（height / line-height / padding），
   让它缺席时不至于突兀。实测（1440 真实夹具，表格一行）：
     改前 `td .fx-chip` = inline / line-height 16.2px / padding 0 / 36×16px；
     改后 `td .fx-chip` = inline / line-height 20px / padding 0 7px / 50×16px；
     行高 **45px 不变**（行高由操作列按钮决定），也没有新增横向溢出（scrollWidth = clientWidth = 1196）。
   为什么用 `@layer`：**未分层的规则永远胜过分层规则**（与加载顺序、与特异度都无关）。
   所以 `tokens.css:146` 的 `.fx-chip` 一旦恢复生效，本规则**整条自动失效**、一个属性都盖不掉 ——
   实测把 `/tokens.css` 真的喂成 `200 text/css` 后：`.fx-chip` = inline-flex / 22px / padding 0 8px /
   1px 边框 / 圆角 4px，**且"加不加本规则"的数值逐字段相同**（65×22 两种条件一致）。
   刻意**不**用 `body td .fx-chip`(0,1,2) 硬压：那会与 tokens.css 打架。顺带登记一条既有不一致
   （本轮不改任何既有规则）：同一条件下 `.badge` 被本文件 :730 的 (0,1,2) 压到 **20px**，
   而 `.fx-chip` 是 tokens 的 **22px** ⇒ 云端入口两种标签差 2px；本机入口两者都是 inline。
   另登记：本文件 :711 的 `body .workspace-intro{padding:10px 14px}`(0,1,1) 实测被同块 :729 的
   `body .panel{padding:12px 14px}`(0,1,1) 压掉（同特异度、后者靠后）⇒ 引入区实际 padding 12px 14px。
   （**UIUX-DS3 更正 2026-09-22**：原文引用的 `:708`/`:726` 是写入时的行号，随后续追加已漂移 ——
    实测当前位置为 `:711`/`:729`。**行号会漂移，请以选择器文字为准**。本条只改注释，规则一行未动。） */
@layer u3-chip-fallback{
  body td .fx-chip{height:20px;line-height:20px;padding:0 7px}
}


/* ── U3 ⑤：流程配置器弹窗再放一档（用户当轮：「新建流程的窗口界面还可以加大」）──────────
   改前实测（真实夹具，整页截图见 `_validation/uiux-shots/U3-DIALOG/`，CDP 级联逐条可复核）：
     1440×900 → 弹窗 **1406×792**；1920×1080 → **1500×900**（宽被 :522 的 1500px 上限卡住、
     高被 900px 上限卡住 ⇒ 1920 屏上右侧空 420px、下方空 180px）；880×800 → 846×736（单栏）。
   改后实测：1440×900 → **1416×828**（+10 / +36）；1920×1080 → **1680×993.6**（+180 / +93.6）；
     880×800 → **846×736 完全未变**。
   ⚠️ 只加宽 `width` 是不够的：`max-width` 没有任何**作者**声明，实际生效的是浏览器 UA 的
   `dialog:-internal-dialog-in-top-layer{max-width:calc(100% - 2em - 6px)}` —— 实测 1440 下
   声明值 min(1500px,100vw−32px)=1408 却被卡到 **1406**（= 1440 − 2em(28) − 6）。所以这里
   **必须同时声明 `max-width`**（作者声明一律胜过 UA 声明），否则宽度上限纹丝不动。
   特异度与竞争（逐条写明，本项目的高发坑）：
   · `dialog.oa-cfg-dialog` = **(0,1,1)**，与本文件 :522 的 B10 规则**同特异度**，靠"本文件更靠后"
     取胜；同时也压过 `dialog.bi-dialog`(0,1,1，:167) 与 `dialog.bi-dialog-wide`(0,1,1，:168)。
     ⚠️ `dialog.` 元素前缀**不能省**：只写 `.oa-cfg-dialog` 是 (0,1,0)，会被上面三条 (0,1,1) 全部压死
     （B10 第一版就是踩了这个，同一条规则里 `height` 生效而 `width` 不生效）。
   · **整条关进 `@media (min-width:901px)`**：≤900px 的三条既有回退（:477 的
     `.oa-cfg-dialog .oa-cv-wrap{minmax(0,1fr)}`、:546 的 `dialog.oa-cfg-dialog{width:calc(100vw - 16px)}`、
     :560 的 `:not(.form-view)` / `.form-view` 单栏）**一条都不用改**，也不可能被我按顺序压死 ——
     901px 以下本规则**根本不参与级联**。这是 B13 那次事故（把 `:not(.form-view)` 抬到 (0,3,0)，
     反过来把窄屏媒体查询压成死声明）的**结构性**避免办法：不靠顺序、不靠特异度，靠"不在同一个条件里"。
   · 三栏列宽（:535 的 `220px minmax(0,1fr) 320px`）与表单视图单列（:544）**一字未动**：
     实测画布由 1920 下的 898 → 1078px、1440 下的 804 → 814px，左右两栏在 1680 宽下不显窄；
     改列宽会引入新的特异度风险且用户未要求。表单视图（`.form-view` 单列 + 设计器自带三栏）
     改后实测：外层仍单列 1382px、`oa-fd-wrap` 仍 200/824/300，未被压坏。 */
@media (min-width:901px){
  dialog.oa-cfg-dialog{width:min(1680px,calc(100vw - 24px));max-width:min(1680px,calc(100vw - 16px));
    height:min(92vh,1040px);max-height:min(95vh,95dvh)}
}


/* ── U3 ④ 复核注：侧栏 172px 的论据前提已变（2026-09-22 用户改导航分组名）──────────────
   本文件 :653 / :659 两处以「最长 chevron 项『组织与权限』70px」反算侧栏宽度。2026-09-22
   用户把 4 个分组改名（`app.js` 的 `workspaceGroups`）：组织与权限→**组织权限**、
   数据与知识→**数据知识**、助手与集成→**工具集成**、系统与安全→**系统安全** ⇒ 最长 chevron 项
   由 5 字变 4 字。**复核结论：前提变了，取值 172px 仍然成立，且余量更大**（结论不修改）。
   实测（真实夹具，1440 / 1280 / 1101 / 1100 / 900 / 761 / 760 七档；
   证据 JSON 与逐项宽度见 `_validation/uiux-shots/U3-NAV/`）：
     · 导航项共 9 个（8 个分组 +「更多功能」）。最长文字 =「治理概览」4 字 = **56px**
       （≥1101px，14px 字号）/ **52px**（761–1100px，13px 字号）；带 chevron 的最长项
       （「组织权限」「数据知识」「流程中心」「工具集成」「系统安全」并列）同为 **56 / 52px**；
       不带 chevron 的最长项 =「AI 用量」**44.6px** ⇒ 约束项仍是带 chevron 的那一类。
     · 反算所需最小栏宽（chevron 项约束，全部取实测值）：
         ≥1101px：栏内边距 8+8 ＋ 边框 1 ＋ 项内边距 11+11 ＋ 前导图标 20 ＋ 间距 10 ＋
                  最长文字 **56** ＋ 间距 10 ＋ chevron 14 = **148px**（改名前 163px）
         761–1100px：8+8 ＋ 1 ＋ 10+10 ＋ 20 ＋ 9 ＋ **52** ＋ 9 ＋ 14 = **140px**（改名前 154px）
     · 172px 的余量：≥1101px **24px**（改名前 9px）、761–1100px **32px**（改名前 18px）。
     · 七档全部：导航项**无换行、无截断**（`labelLines = 1`、`scrollWidth = clientWidth`）；
       ≤760px 仍是 216px 抽屉（本规则只在 ≥761px 生效，未被触碰）。
   ⇒ 只登记复核结果，**两条注释的取值一个数字都不改**（改的只是"哪个是最长项"这个前提）。 */

/* ── W5（2026-09-22）：单元格内 `.badge` 与 `.fx-chip` 的几何一致性（改 1 行 + 追 1 段兜底）──────
   缺陷：同一张真实表、同一行、同一个 `td` 里两者差 2px ——
     `.fx-chip` 22px（padding 0 8px、line-height 12px）；`.badge` 20px（padding 0 7px、line-height 20px）。
   成因（CDP `CSS.getMatchedStylesForNode` 机器取证，原始 JSON 在 `_validation/uiux-shots/W5/`）：
     · 上面 :732 那条 `body td .badge` 特异度 **(0,1,2)**、**未分层**，压 `tokens.css:185` 的
       `.badge, .pill` **(0,1,0)** ⇒ 单元格内 `.badge` 掉到 20px；
     · 同一条选择器**没有** `.pill` ⇒ `.pill` 保住 tokens 的 22px（产品里 `.pill` 从不出现在 `td` 内，
       实测 10 个页面合计 `pillTd = 0`，所以那不是可复现的现场缺陷，仅登记）；
     · `.fx-chip` 的兜底在 :789 的 `@layer u3-chip-fallback` 内 ⇒ **未分层规则永远胜过分层规则**
       （与加载顺序、与特异度都无关），`tokens.css:146` 的 `.fx-chip` 一恢复生效，兜底整条失效
       ⇒ 单元格内 `.fx-chip` 回到 tokens 的 22px。
     于是"表格内 20 vs 22 不一致、表格外两者都 22 一致"。
   本行改动：只把 `.fx-chip` 并入 :732 那条既有规则 ⇒ `body td .badge,body td .fx-chip{...}`。
   同一条规则、同一特异度 (0,1,2)、同样未分层，**不新增竞争者**，`.badge` 的三条声明一字未改。
   方向取舍：把 `.fx-chip` 收到 20px，而不是把 `.badge` 放回 22px —— 档 3 表格密度（数据行
   57px → 45px）是用户已确认的目标，放回 22px 会抵销它；而 `.fx-chip` 是单元格里更高的那个，
   收它同时满足"一致"与"更密"。
   量值（真实夹具 1440×900，同一张表同一行的同一个 `td`；证据见
   `_validation/uiux-tools/w5-chip-badge-unify.md`）：
     改前 `.fx-chip` 22px / padding 0 8px / line-height 12px；`.badge` 20px / 0 7px / 20px（差 2px）
     改后两者同为 20px / 0 7px / line-height 20px / border-radius 4px（四项全等，盒宽也同为 63px）
     数据行高改前改后都是 **45px**；表格之外的 `.badge` / `.pill` 仍是 22px（未受影响）。 */

/* W5 续：把 `@layer u3-chip-fallback` 补成"缺席时也同形"（**该层的补充，不是替换**）
   为什么另起一个同名 `@layer` 块、而不是改 :789 那块：本文件既有注释大量按行号引用
   （:732 / :789 / :610 …），在 :791 之前插行会让它们集体失效；而 CSS 里同名 `@layer` 是
   **追加到同一层**，写在文件末尾既不移动任何既有行，又与该层原有的
   `body td .fx-chip{height;line-height;padding}` 同层叠加。
   为什么这三条只能放层里：`display` / `align-items` / `border-radius` 只有在**未分层**样式里
   没有竞争者时，分层规则才生效；`tokens.css` 一在场，未分层的 `.badge, .pill` 与 `.fx-chip`
   立刻把它们全部盖掉 ⇒ **tokens.css 存在时这三条的作用恒等于零**，这是"未分层永远胜过分层"
   的直接推论，不是靠取值碰巧相同。已实测：加这三条前后，tokens 在场的四个几何值与
   border / background / color / 圆点逐字段相同（见报告 §5）。
   它们只解决 tokens.css 缺席的那一种条件。那种条件下今天并不一致：`height:20px` 对
   `display:inline` 是**惰性**的（inline 元素 height 不适用，用高度由字体决定 ⇒ `.badge`
   10px 字 ≈ 14px、`.fx-chip` 12px 字 ≈ 16px），并且 `.badge` 从 `styles.css:4` 拿到
   `border-radius:4px` 而 `.fx-chip` 一个圆角来源都没有（0px）。补上 `inline-flex` 让 height
   真的生效、两者拿到同一个 20px 盒；补上 `border-radius` 的**令牌回退值**让两者的圆角同为 4px。 */
@layer u3-chip-fallback{
  body td .badge,body td .fx-chip{display:inline-flex;align-items:center;
    border-radius:var(--fx-radius-sm,4px)}
}

/* ══ 研发管理「项目详情」页签栏：UIUX-RND3（单行横滚）→ **UIUX-A7（两级）** ══════════
   用户 2026-09-24 当轮原话：「**这里要拉横条，一屏都看不完，要整理一下**」⇒ 授权改两级。

   ── 履历（两代的目标不同，别把上一代的做法当基线）──────────────────────────────
   · RND3（2026-09-22）面对的是**排版**问题：26 个平铺 ⇒ 1440/1280 占 2 行 76px、
     1000 占 3 行 111px、768 占 **4 行 146px**；≤760 切单行横滚后 17–22 个页签落在视口外且零线索。
     它的目标明写「**不是"消除横滚"**——26 个页签裸条 1802px，比 1920 视口可用宽还宽，横滚客观存在」，
     于是做了：恒 1 行 + 左右箭头 + 溢出计数 + 两侧渐隐 + 粘性组名 + ←→ 键。
     **结论：排版问题解决了，数量问题没有。**用户实际使用中仍要拉横条。
   · A7（2026-09-24）面对的是**数量**问题，答法是**分层而不是压缩**：
     26 个页签按**代码里本来就有的** `rdTabGroups`（`rnd.js:38-45`）切段后，**每段最多 7 个**
     （专业研发 7 / 计划与执行 7 / 全生命周期 6 / 协作与资料 3 / 治理与记录 2 / 概览 1），
     7 个页签在任何常见宽度都放得下 ⇒ **横滚彻底消失**。

   ── 因此本块**删掉**了 RND3 的全部"溢出补偿手段"（它们在没有溢出时全是死规则）──────
     `body .rnd-tabs{display:flex…}` 的横向排布、`.rd-project-tabs{flex-wrap:nowrap;overflow-x:auto}`、
     箭头 `.rnd-tabs__arrow`（含 ≤1000px 那条只显示数字的媒体查询）、计数 `.rnd-tabs__count`、
     两侧渐隐 `.has-left`/`.has-right`、粘性组名 `.rnd-group-chip`、组间分隔 `[data-group-start]`。
     对应地 `rnd.js` 的 `rdTabsNav` 里删掉了箭头/计数/`scrollBy`/`scroll`+`resize` 同步。
     **本仓刚清过一批被完全遮盖的死声明，不再反向制造。**

   ── 纪律（沿用 RND3 定的那几条，仍然有效）────────────────────────────────────
     · **不改** `styles.css:5` 的 `.subnav` / `brand.css:8` / `brand.css:33` / `brand.css:41` 任何一条；
     · 作用域**只**命中 `.rnd-tabs` / `.rd-project-tabs`（RND 项目详情页签条专用类，`rnd.js` 产出）；
     · 顶层 5 页签（`p1.js` 的 `tabs()`，只有 `.subnav` 没有 `.rd-project-tabs`）**完全不受影响**；
     · 本仓 `styles.css` 在 `brand.css` **之前**加载 ⇒ 一律用 `body` 前缀把特异度提到 (0,2,1) 以上，不靠运气。
   ══════════════════════════════════════════════════════════════════════════════ */

body .rnd-tabs{display:block;margin:0 0 10px}
body .rnd-tabs>.rd-project-tabs{display:block;margin:0;padding:0}
/* 一级：业务段（分段控件）。数量 6 个，与二级分工明确：一级回答"在哪一大块工作"，
   二级回答"具体哪一页"。带一个页签计数，用户不必展开就知道每段有多大。 */
body .rnd-tabs .rd-tab-groups{display:flex;flex-wrap:wrap;gap:6px;margin:0 0 8px}
body .rnd-tabs .rd-tab-groups>button{flex:0 0 auto;display:inline-flex;align-items:center;gap:6px;
  padding:6px 12px;font-size:13px;color:var(--muted);background:var(--surface);
  border:1px solid var(--line);border-radius:8px;cursor:pointer}
body .rnd-tabs .rd-tab-groups>button:hover{background:var(--accent-soft);color:var(--accent)}
body .rnd-tabs .rd-tab-groups>button[aria-current="true"]{background:var(--accent-soft);
  border-color:#c9daff;color:var(--accent);font-weight:600}
body .rnd-tabs .rd-tab-groups .rd-tab-group__count{font-size:11px;color:var(--muted);
  background:#f0f3f9;border-radius:999px;padding:0 6px;font-variant-numeric:tabular-nums}
body .rnd-tabs .rd-tab-groups>button[aria-current="true"] .rd-tab-group__count{background:#fff;color:var(--accent)}
/* 二级：该段的页签。**刻意不设 `overflow-x`** —— 每段最多 7 个，任何常见宽度都放得下
   （这就是横滚消失的原因，而不是"把横滚藏起来"）。
   按钮保留 `flex:0 0 auto`：RND3 真机抓到过——不加它，`flex-wrap` 下中文会被压成
   「一列竖排的字」（实测 35.6×96px），看起来像排版坏了。那条教训继续有效。 */
body .rnd-tabs .rd-tab-l2{display:flex;flex-wrap:wrap;gap:3px;margin:0}
body .rnd-tabs .rd-tab-l2>button{flex:0 0 auto}

/* ══ UIUX-RND4 (b)：研发管理「手工填报的产品表现」表 ══════════════════════════════
   现象（实测，见 `_validation/rnd-ui-rnd1-recon.md` §6.9 与 `uiux-tools/rnd-tab-metrics.json`）：
     该表在 `rnd-lifecycle.js:112` 有 **13 列**（产品/期间/渠道 + 8 个指标 + 客户反馈 + 操作），
     被 `styles.css:50` 强制 `.rd-lifecycle-performance table{min-width:1320px}` + `td,th{white-space:nowrap}`
     ⇒ **1440px 视口下就已经横向溢出**（表 1320 / 容器 1196；1280 溢出 284px；360 溢出 1016px）。
     用户看到的是"一张必须左右拖动的表"，而**不是**"窄屏才有问题"。

   做法（**不另造范式**）：仓库**已有**窄屏卡片范式，见 `tokens.css:217-224`
     （`@media(max-width:1000px){ .fx-table thead{display:none} .fx-table tbody tr{display:grid;…}
        .fx-table tbody td::before{content:attr(data-label)} }`），
     而 `app.js:342` **给每个单元格都写了 `data-label`**（含操作列：逐字核过 `dataset.label='操作'`）。
     ⇒ 本块只做两件：
       ① 让表格在宽屏**铺满可用宽度并允许必要时折行**（去掉"硬撑 1320px"）；
       ② `≤1320px`（＝`min-width` 会生效的整个区间）换成**行转卡片**，直接消灭横向拖动。

   纪律（A 层"只许追加"）：
     · **不改** `styles.css:50` 既有那一条、不改任何既有选择器/规则；
     · 作用域限定 `body[data-page="RND"]`（`app.js:120` 写的页面标记）⇒ **只影响研发管理页**；
     · 特异度用 `(0,2,1)` 及以上，不依赖加载顺序（本文件在 `brand.css` 之前加载）；
     · 行尾 CRLF（本文件为纯 CRLF 文件）。
   ========================================================================== */
body[data-page="RND"] .rd-lifecycle-performance table{width:100%}
body[data-page="RND"] .rd-lifecycle-performance td,
body[data-page="RND"] .rd-lifecycle-performance th{white-space:normal}
@media(max-width:1320px){
  body[data-page="RND"] .rd-lifecycle-performance thead{display:none}
  body[data-page="RND"] .rd-lifecycle-performance table{min-width:0}
  body[data-page="RND"] .rd-lifecycle-performance tbody tr{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
    gap:4px 16px;padding:12px 0;border-bottom:1px solid var(--line)}
  body[data-page="RND"] .rd-lifecycle-performance tbody td{display:flex;flex-direction:column;gap:2px;
    padding:0;border:0;min-width:0;overflow-wrap:anywhere}
  body[data-page="RND"] .rd-lifecycle-performance tbody td::before{content:attr(data-label);
    font-size:11px;color:var(--muted)}
  body[data-page="RND"] .rd-lifecycle-performance tbody td:last-child{grid-column:1/-1}
}

/* ── 侧边栏外观控件与图标模式（UIUX-DS6，用户 2026-09-22 已确认）───────────────────────
   「可调宽窄 + 可换深浅色」两件**外壳偏好**的样式。三条纪律：

   ① **颜色一律走令牌**（`--fx-sidebar-*` / `--fx-flyout-*` / `--fx-nav-scrim`，定义在
      `tokens.css` 的 DS6-B1a 块），本块**一个新色值都不写** —— 写一个，深色就得再来一套覆盖，
      那就是第二套配色（章程明令禁止）。

   ② **图标模式（`body.sb-icon`）只在 ≥761px 生效**。≤760px 是抽屉形态（`brand.css:33`：
      `width:216px` + `main{margin-left:0}`），抽屉宽度固定、也不吃 `--fx-sidebar-w`
      （变量只被本文件 `@media (min-width:761px)` 的两条消费）⇒ 抽屉一个字节不变。

   ③ **手柄必须是 `aside#workspace-sidebar` 的直接子节点、绝对定位于右缘**，不能放进 `#nav`：
      那是 `overflow-y:auto` 的滚动容器，手柄会随导航一起滚走；而且 `#nav` 内每个多页组项
      自带 ←/→ 键处理（`app.js` 的 `open(group,b,true)`），职责混在一起会互相打架。
      `aside` 是 `position:fixed`（实测 64 次量测恒为 fixed）⇒ `absolute` 子节点以它为定位上下文。

   特异度：本文件在 `brand.css` **之前**加载，所以凡与 brand 竞争的规则都必须靠特异度赢，
   不能靠顺序。逐条已在下面注明。 */

/* ① 拖拽手柄（右侧 6px 命中区） */
#sidebar-resize{position:absolute;top:0;right:0;bottom:0;width:6px;cursor:col-resize;touch-action:none;background:transparent;z-index:2}
#sidebar-resize:hover,#sidebar-resize:active{background:var(--fx-sidebar-item-hover-bg)}
body.sb-dragging{user-select:none;cursor:col-resize}
body.sb-dragging #sidebar-resize{background:var(--fx-sidebar-item-hover-bg)}
/* 拖拽中的实时宽度：`aria-hidden="true"` 在 DOM 上（读屏不该被连续报数），只作视觉反馈 */
#sb-width-badge{position:absolute;top:50%;right:-12px;transform:translateY(-50%);padding:2px 7px;border-radius:var(--fx-radius-sm);background:var(--text);color:var(--surface);font-size:11px;line-height:1.4;font-variant-numeric:tabular-nums;pointer-events:none;z-index:3}

/* ② 外观控件：原生 `<details>`（不用 JS 管开关，键盘与展开语义自带） */
#sidebar-appearance{margin-top:10px;border-top:1px solid var(--fx-sidebar-border);flex-shrink:0}
#sidebar-appearance>summary{display:flex;align-items:center;gap:8px;padding:8px 6px;border-radius:var(--fx-radius-md);cursor:pointer;font-size:12px;color:var(--fx-sidebar-foot);list-style:none}
#sidebar-appearance>summary::-webkit-details-marker{display:none}
#sidebar-appearance>summary:hover{background:var(--fx-sidebar-item-hover-bg);color:var(--fx-sidebar-item-hover-fg)}
#sidebar-appearance .workspace-icon{width:16px;height:16px}
.sb-appearance-panel{display:grid;gap:5px;padding:2px 6px 8px}
.sb-appearance-group{margin:4px 0 0;font-size:10px;letter-spacing:.6px;color:var(--fx-sidebar-caption)}
.sb-appearance-row{display:flex;align-items:center;gap:4px;flex-wrap:wrap}
.sb-appearance-row button{padding:4px 7px;border:1px solid var(--fx-sidebar-border);border-radius:var(--fx-radius-sm);background:var(--surface);font-size:11px;color:var(--fx-sidebar-fg)}
.sb-appearance-row button[aria-pressed=true]{background:var(--accent-soft);border-color:var(--accent);color:var(--accent);font-weight:600}
.sb-appearance-num{margin-left:auto;font-size:11px;color:var(--fx-sidebar-foot);font-variant-numeric:tabular-nums}
.sb-appearance-note{margin:6px 0 0;font-size:10px;line-height:1.5;color:var(--fx-sidebar-foot-sub)}

/* ③ 图标模式（宽度 <120px）：只留图标 */
@media (min-width:761px){
  /* `.brand` 里「FITEASE / 企业工作台」两行在 56px 内宽下必然溢出 ⇒ 整块退出，只留品牌方块并居中。
     特异度 (2,2,1) > brand.css 的 `.brand`(0,1,0)；(2,2,1) 也 > 本文件 `:684` 的 (2,1,0)。 */
  body.sb-icon #workspace-sidebar .brand{justify-content:center;padding-inline:0}
  body.sb-icon #workspace-sidebar .brand>div{display:none}
  /* 「工作空间」分区标题同理（它是纯文字） */
  body.sb-icon #workspace-sidebar .sidebar-caption{display:none}
  /* 页脚整块退出。**不能只藏文字**：那段正文是裸文本节点，只藏它会在左下角剩一个
     没有语义的装饰点（`footer i`），读屏也读不出来。 */
  body.sb-icon #workspace-sidebar footer{display:none}
  /* 导航项：图标居中、去掉文字与内边距；(2,2,1) 压 `:684` 的 (2,1,0) */
  body.sb-icon #workspace-sidebar #nav .workspace-nav-item{justify-content:center;padding-inline:0;gap:0}
  body.sb-icon #workspace-sidebar #nav .workspace-nav-item>span{display:none}
  /* 多页组的箭头在两个图标栏里放不下（56 − 0 − 20 = 36px），改成右下角 3px 角标点：
     保留"这一项还有下级"这个可操作提示，代价只是一个不占横向空间的点。 */
  body.sb-icon #workspace-sidebar #nav .workspace-nav-item[aria-expanded]{position:relative}
  body.sb-icon #workspace-sidebar #nav .workspace-nav-item[aria-expanded]>.workspace-icon:last-child:not(:first-child){display:none}
  body.sb-icon #workspace-sidebar #nav .workspace-nav-item[aria-expanded]::after{content:'';position:absolute;right:4px;bottom:4px;width:3px;height:3px;border-radius:50%;background:currentColor;opacity:.65}
  /* 外观控件在图标模式下只剩齿轮；展开的面板改为向右飞出（与 flyout 同一套定位思路） */
  body.sb-icon #sidebar-appearance>summary{justify-content:center;gap:0;padding-inline:0}
  body.sb-icon #sidebar-appearance>summary>span{display:none}
  body.sb-icon #sidebar-appearance[open]>.sb-appearance-panel{position:absolute;left:100%;bottom:0;width:200px;margin-left:6px;padding:8px;background:var(--surface);border:1px solid var(--fx-flyout-border);border-radius:var(--fx-radius-md);box-shadow:var(--fx-shadow-pop);z-index:80}
}

/* ══ UIUX-A2：`.error-message` 的**唯一实现**（此前全仓零定义）══════════════════════════
   总控 2026-09-24 点名，我独立复核成立：这个类是「三处在用、零处定义」——
   `bi-editor.js:262`、`p1.js:283`、`tools/serve_lan_test.py:227`（后者靠一条内联 style 顶替，
   而本平台 CSP 的 style-src 不含 unsafe-inline ⇒ 那条内联 style 被拒，局域网测试横幅
   实测 border-left-width=0px、font-weight=400，即**完全没有样式**）。
   色值一律取**既有令牌**（`tokens.css:88` 的 --fx-danger-bg / -line / -text），不新造。
   与整页错误 `.workspace-error` 的分工：那条是**整页替换**级；本类是**行内/块内**的局部错误，
   只给左侧红边 + 淡红底 + 加粗，不抢整页错误的视觉权重。 */
.error-message{margin:10px 0;padding:8px 12px;border-left:3px solid var(--fx-danger-line);background:var(--fx-danger-bg);color:var(--fx-danger-text);font-weight:600;border-radius:var(--fx-radius-sm,4px)}

/* ══ UIUX-A5：测试环境横幅压薄（用户 2026-09-24 当轮确认「更新到本地版本」）══════════
   这是什么：局域网测试入口在 </header> 之后注入的一条环境警告（`tools/serve_lan_test.py:226-231`，
   注入点 `:244`）。它**只在局域网测试入口存在，生产环境没有这个元素** ⇒ 本规则生产零影响。

   为什么是"压薄"而不是"并入顶栏"：并入顶栏那版**实测会把警告截断** ——
   `_validation/uiux-tools/a4-measure.cjs`（可复跑）：1456px 视口下 `scrollWidth 609 > clientWidth 601`；
   **1258px 下容器只剩 505px ⇒ 只显示 83% 的文案**。为省一行而让「请勿录入真实业务数据」
   变成省略号，与本项目「可理解性 > 效率」的第一原则冲突 ⇒ 该方案已撤回。
   要真正收成一行，唯一诚实的路是**先把文案改短**（`TEST_BANNER` 属 C 层，由总控定），不是截断它。

   形态：保留完整文案，但降为一条 12px 的小字带（不再是一整条加粗红带）。
   id 选择器 (1,0,0) 压过 `.error-message` (0,1,0) 的 margin/padding/font-weight 三条 ——
   `.error-message` 本体一个字节未改（它另外还有 3 处在用）。 */
#lan-test-banner{margin:0 0 10px;padding:4px 10px;font-size:12px;font-weight:500;line-height:1.7;
  border-left:3px solid var(--fx-danger-line);background:var(--fx-danger-bg);color:var(--fx-danger-text);
  border-radius:var(--fx-radius-sm,4px)}

/* ══ UIUX-A6：项目标题行容纳「返回项目列表」（用户 2026-09-24 当轮授权）══════════════════
   配套 `rnd.js` 的 DOM 改动（返回按钮从**容器首位**移进标题面板，与项目名同一行）。
   这三条**必须与那次改动同批**：单独生效只会把面板自身的格线排布改掉，没有任何收益。

   背景（读码得到，不是猜）：`.rd-project-heading` **本来就是一个网格** ——
   `brand.css:41`（本仓 A 层局部追加）写着
     `.rd-project-heading{display:grid;grid-template-columns:1fr auto;…}`
     `.rd-project-heading>h2{grid-column:1}` / `>.rd-project-meta{grid-column:1}`
     `>.rd-actions{grid-column:2;grid-row:1/3}` / `.rd-project-description{grid-column:1/-1}`
   所以这里**不改 brand.css 的任何一条**，只在本文件（**加载早于 brand.css ⇒ 必须靠特异度取胜**）
   追加**覆盖**：`.page-content>.rd-project-heading`(0,2,0) 压 `.rd-project-heading`(0,1,0)；
   `.page-content>.rd-project-heading>h2`(0,2,1) 压 `.rd-project-heading>h2`(0,1,1)。

   格线：第 1 行 = [返回][项目名][操作按钮]，第 2 行 = 项目元信息，项目说明整行。
   作用域限定在 `.page-content >`（研发项目详情专有），不影响任何其它页面。 */
.page-content>.rd-project-heading{grid-template-columns:auto 1fr auto}
.page-content>.rd-project-heading>.rd-back-to-list{grid-column:1;grid-row:1;align-self:center;margin:0}
.page-content>.rd-project-heading>h2{grid-column:2;grid-row:1}
.page-content>.rd-project-heading>.rd-project-meta{grid-column:2;grid-row:2}
.page-content>.rd-project-heading>.rd-actions{grid-column:3;grid-row:1/3}
/* 窄屏：返回按钮与项目名**继续同一行**（这是本次改动的目的，不因窄屏放弃），
   只把操作按钮放到整行下面 —— 与 `brand.css:42` 的既有窄屏处理同口径（那里也是把 .rd-actions 落到整行）。 */
@media(max-width:1100px){
  .page-content>.rd-project-heading{grid-template-columns:auto 1fr}
  .page-content>.rd-project-heading>.rd-actions{grid-column:1/-1;grid-row:auto;justify-content:flex-start}
}

/* ══ UIUX-A8：登录页「忘记密码 / 设置新密码」两个面板的视觉收口 ═══════════════════════
   这两个面板是总控 2026-09-24T10:06 落的最小可用版（`[CLOSE] C-AUTH-RESET-UI`），
   他在 `[OPEN]` 里写明「**风格从简…不做视觉设计**，视觉与组件化**留给设计系统线后续重做**」。
   功能、文案、防枚举口径**已冻结且真站实测可跑**（真浏览器 12/12，见台账 UIUX-A2）⇒ 本批**只补样式**，
   一个字的逻辑都不动。

   ── 修三处不一致（读码得到，不是观感）────────────────────────────────────────
   ① `#reset-panel` **拿不到卡片样式**：它在 `#login` **之外**（`index.html:6`）。
      **不能**把它塞进 `#login` —— `password-reset.js` 的 `showReset()` 正是靠"隐藏 `#login`"来让位，
      塞进去会连同它一起被隐藏。而 `brand.css:30` 的卡片量度**全挂在 `#login` 这个 id 上**
      ⇒ 设置新密码页原本是**裸文本浮在渐变底色上**，与它前后的界面都不同形。
   ② `.login-forgot` 的按钮没有任何样式，走全局 `button{}` ⇒ 它语义上是**一个文字入口**，
      观感上却像一个次要按钮（实测：它带着边框和底色，和「登录」并排时会被误当操作按钮）。
   ③ `#forgot-panel` 是裸 `div` ⇒ 展开后与上方内容没有边界，看不出"这是从上面那个入口展开的"。

   ── 特异度（本仓高发坑，先写清）────────────────────────────────────────────────
   `styles.css` **加载早于** `brand.css` ⇒ 对 `#login` **内部**的元素（`#login form`(1,0,1)、
   `#login p`(1,0,1)、`#login h1`(1,0,1)）我的规则必须**用到两个 id** 才赢得下来：
   `#login #forgot-panel`(2,0,0)、`#login #forgot-panel form`(2,0,1)。
   `#reset-panel` 在 `#login` 之外，单 id (1,0,0) 即可（没有任何既有规则与它竞争）。

   ── ⚠️ 已知耦合：改一处必须改两处 ───────────────────────────────────────────────
   `#reset-panel` 那七个卡片量度**镜像自** `brand.css:30` 的 `#login`：
     `padding:32px 36px` / `max-width:480px` / `margin:35px auto 70px` / `background:white` /
     `border:1px solid #e1e6f1` / `border-radius:16px` / `box-shadow:0 16px 60px #39508b0d`。
   为什么不复用：`#login` 那条是 (1,0,0)，我在本文件里**无法用同特异度取胜**（加载顺序在后）；
   把 `#reset-panel` 加进 `brand.css` 那条的**选择器表**虽然更干净，但会动到登录页那条既有规则
   （它是登录页现状的成因）⇒ 本批不碰。**⇒ 将来改 `#login` 的卡片量度时，必须同步这一段。**
   ══════════════════════════════════════════════════════════════════════════════ */

/* ① 设置新密码页 = 与登录卡同一张卡（量度镜像自 brand.css:30 的 #login，见上） */
#reset-panel{padding:32px 36px;max-width:480px;margin:35px auto 70px;background:white;
  border:1px solid #e1e6f1;border-radius:16px;box-shadow:0 16px 60px #39508b0d}
#reset-panel h1{font-size:27px;margin:16px 0;letter-spacing:0;line-height:1.4}
#reset-panel .eyebrow{color:var(--accent);letter-spacing:1.5px}
#reset-panel p{font-size:13px}
#reset-panel form{margin:22px 0;max-width:none;display:grid;gap:17px}
#reset-panel form>button{margin-top:2px}

/* ② 「忘记密码？」＝文字入口，不是按钮 */
#login .login-forgot{margin:6px 0 0}
#login .login-forgot>button{border:0;background:transparent;padding:2px 0;font-size:13px;color:var(--accent);
  text-decoration:underline;text-underline-offset:3px}
#login .login-forgot>button:hover{color:var(--accent-hover);filter:none}
/* 展开后它不再是"入口"而是"当前的开关"：去掉下划线、换中性色，不与面板里的主按钮抢注意力 */
#login .login-forgot>button[aria-expanded="true"]{color:var(--muted);text-decoration:none}

/* ③ 展开的面板：给出边界，明确"这是从上面那个入口展开的" */
#login #forgot-panel{margin:10px 0 0;padding:14px 16px;background:#f8faff;
  border:1px solid var(--line);border-radius:10px}
#login #forgot-panel>p:first-child{margin:0 0 10px;font-size:12px;line-height:1.7}
#login #forgot-panel form{margin:0;display:grid;gap:12px;max-width:none}
#login #forgot-panel form>button{margin-top:2px}

/* 状态行。回执＝**中性**（命中与未命中必须一模一样，否则样式本身成了枚举预言机）；
   失败＝`.error-message`、成功＝`.success-message` —— 两者都是**平台既有类**，不新造。
   `margin` 挂 id 上是为了压过 `.success-message{margin-bottom:16px}` 那种页面级间距。 */
#login #forgot-status,#reset-panel #reset-status{margin:10px 0 0;font-size:12px;line-height:1.7}

/* ══ UIUX-A9：甘特图面板「头行」—— 接上平台**已有的**两个组件 ═════════════════════════
   用户 2026-09-24 当轮原话：「**这些 和项目甘特图 集合到一行**」。
   现状（读码得到，非观感）：`rdGantt`（`rnd-workspace.js:20`）把**三块竖排**塞进同一个面板 ——
     `[h2 项目甘特图][p 说明][div.rd-actions：按天/按周/按月][div > form.gantt-window：显示日期范围][图]`
   目标：前四块并成**一行**，图留在下面。

   ★ 这不是新造一套布局，而是**接上平台已有的组件**：
     · `.fx-panel-head`（`tokens.css:547`，含 `__title` / `__note` / `__count`）
     · `.fx-toolbar`（`tokens.css:199`，含 `__hint`）
   这两个组件在 **N1 基线卡**里属于「**声明了但零引用**的真库存」（`TASK01_N1_COMPONENT_BASELINE.md` §4b）
   ⇒ **本批是它们的第一次上岗**（与"把 `fx-error*` 交给流程中心 F1 当首个真实使用者"那条裁定同形）。

   ⚠️ **本块在 B 层 DOM 落地前是惰性的**（选择器要求 `.fx-panel-head` / `.fx-toolbar` 存在）。
   之所以**先落**：免去"他落 DOM、我再补 CSS"的两次交接 —— 一次就把外观配好。
   若研发界面最终不采用本方案，**整块删除即可**（没有任何既有规则依赖它）。

   特异度（本仓高发坑）：`tokens.css` 是**最后加载**的，其组件规则写作
   `body .fx-panel-head`(0,1,1) 与 `body .fx-toolbar`(0,1,1) ⇒ 本文件（先加载）**必须用更多类名取胜**：
   `.page-content>.panel>.fx-panel-head`(0,3,0)、`…>.fx-panel-head>.fx-toolbar`(0,4,0)。 */
.page-content>.panel>.fx-panel-head{flex-wrap:wrap;align-items:center;margin:0 0 12px}
/* 控件靠右 —— 与 `.fx-panel-head__count` 同一个手法（`margin-left:auto`）。
   窄屏放不下时整条工具栏换到下一行（`flex-wrap` 已由组件定义），**不会挤压标题**。 */
.page-content>.panel>.fx-panel-head>.fx-toolbar{margin-left:auto}
/* 头行内部：日期范围与缩放按钮同排、**垂直居中**（组件默认 `align-items:end`，直接嵌进头行会"吊"在下面） */
.page-content>.panel>.fx-panel-head>.fx-toolbar>.gantt-window{align-items:center;gap:10px}
.page-content>.panel>.fx-panel-head>.fx-toolbar>.gantt-window h2{margin:0}
/* 日期范围那两个输入框保持自然宽（`brand.css:45` 的 `.gantt-window .grid-form{flex:1}` 会把它们拉满整行） */
.page-content>.panel>.fx-panel-head>.fx-toolbar>.gantt-window .grid-form{flex:0 1 auto}

/* ── UIUX-A11 ④ / UXD-RND-021：甘特图面板头行的「说明句」可收缩 ──────────────────────────
   来源：研发界面 2026-09-24 13:16 的 `[REQUEST]`（用户当轮三选一裁定：走 A 层，不由板块代写）。
   实测因由：1440px 下 标题(80) + 说明句(519) + 工具条(714) + 间距(16) > 可用 1198
   ⇒ `.fx-toolbar` 被 `flex-wrap` 挤到第二行，判据④（工具栏与标题同一行）不成立。
   为什么 `min-width:220px` 而不是 `0`（研发界面实测过两版，不是拍脑袋）：`min-width:0` 在 760px
   会把说明句压成 100px 宽 / 6 行（每行 2–3 字的竖条），还会把工具条挤上同一行 ⇒ 反而破坏窄屏判据；
   给 220px 下限后 1024/760 与改前逐项相同。
   特异度 (0,4,0) 压 `tokens.css` 的 `body .fx-panel-head__note`(0,1,1)。
   作用域不止研发板块：`oa.js` 的流程大厅面板头同样发射 `.fx-panel-head`（它没有 `.fx-toolbar`
   兄弟，但 `__note` + `__count` 同在头行）⇒ A11 把流程中心那处一并量了（见交付证据）。 */
.page-content>.panel>.fx-panel-head>.fx-panel-head__note{flex:1 1 0;min-width:220px}


/* ══ 多页签导航（2026-09-24，A 层）`.fx-wst*`：顶栏页签条 / 页面清单 / 页签容器 / 空态 ══════════════
   用户 2026-09-24 拍板：「这个工作台 治理概览 是不需要的，**直接把下面的标签页放到顶部**，
   当前显示的页面标签用**显著颜色**区分」；随后追加「这个治理概览的标签页也要支持可以删除」。
   ⇒ 页签条就住在**顶栏那一行**里（原来写「工作台 ｜ 治理概览」的那一格），
   视觉顺序「左侧品牌侧栏 ｜ 页签条 ｜ 右侧操作（说明/刷新/头像/退出登录）」；**下方不再有独立的一整行**。
   顶栏本身就是 `position:sticky;top:0` ⇒ 滚动时整条吸顶，不需要第二条 sticky 行。

   ⚠ **一次真实事故的教训（2026-09-24 21:0x，用户当场看到）**：页签条第一版把 `el()` 的参数
   顺序写反了（本仓 `app.js` 是 `el(tag,text,cls)`，样板间那份是 `el(tag,cls,text)`）⇒
   类名字符串被当成**可见文本**写进 DOM（屏幕上出现 `fx-wstabfx-wstab__name`）、真 class 为空 ⇒
   下面所有选择器落空。**教训两条**：① 跨文件复制代码时先核对该文件的工具函数签名；
   ② DOM 里不得出现 `fx-` 前缀的字面文本（探针已加该判据）。

   令牌：全部用既有令牌（`--surface/--raised/--line/--accent/--accent-hover/--muted/--text`），不新造颜色。
   选中态＝用户选定的 **D1 实心主色**：主色底 `--accent`(#2468f2 rgb(36,104,242)) + 白字 + `font-weight:600`
   + 8px 圆角；未选中＝弱化灰字 `--muted`(#657188 rgb(101,113,136)) + 透明底（hover 给一层浅底）。
   **换配色只是换这一条规则的值**，DOM 与 JS 一行都不用动。
   特异度：一律 `body #workspace-header>.` 前缀（(1,2,1) 起）——压过 `brand.css` 的元素级/伪类规则，
   也压过本文档里任何 `.fx-wstab` 的单类写法。 */

/* ① 页签条＝顶栏里的中间一格。三条约束缺一不可：
   · `flex:1 1 auto;min-width:0` 吃掉标题原来那一格；右侧 `.workspace-tools` 是 `flex:0 0 auto`
     ⇒ 页签再多也**不压缩右侧操作、不换行、不重叠**（溢出交给下面的横向滚动）；
   · `overflow-x:auto`：页签多了**横向滚动**，不叠字；`overflow-y:hidden` 保住顶栏固定高度；
   · **静态定位**（不再是自己的 sticky 行）⇒ 跟随顶栏一起吸顶。 */
body #workspace-header>.fx-wstabs { flex:1 1 auto; min-width:0; display:flex; align-items:center;
  align-self:stretch; gap:6px; padding:6px 0; position:static; z-index:auto;
  overflow-x:auto; overflow-y:hidden; background:transparent; border:0; scrollbar-width:thin; }
body #workspace-header>.fx-wstabs::-webkit-scrollbar { height:5px; }
body #workspace-header>.fx-wstabs::-webkit-scrollbar-thumb { background:#cbd5e1; border-radius:3px; }
body #workspace-header>.workspace-tools { flex:0 0 auto; }
/* 未登录（登录页/设置密码页）不显示页签条。特异度 (1,2,1) 压本文上面的 (1,1,0)；
   与 `brand.css:30` 的 `body[data-authenticated=false] …{display:none}` 同一口径。 */
body[data-authenticated="false"] #workspace-header>.fx-wstabs { display:none; }

/* ② 一个页签：居中圆角小胶囊（8px 圆角，与侧栏项/主按钮同一套观感）。
   `×` 对**所有**页签都在，含「治理概览」（用户 2026-09-24 当轮要求）。 */
body #workspace-header>.fx-wstabs>.fx-wstab { flex:0 0 auto; display:flex; align-items:center; gap:6px;
  max-width:200px; padding:6px 8px 6px 12px; border:1px solid transparent; border-radius:8px;
  background:transparent; color:var(--muted); cursor:pointer; font:inherit; font-size:13px; font-weight:400;
  position:relative; box-shadow:none; }
body #workspace-header>.fx-wstabs>.fx-wstab:hover { background:#eef3fb; color:var(--text); }
/* 选中态＝当前页：D1 **实心主色 + 白字 + 加粗**（"显著颜色区分"，用户从 D1/D2/D3 里选的 D1）。 */
body #workspace-header>.fx-wstabs>.fx-wstab[aria-selected="true"] { background:var(--accent); color:#fff;
  font-weight:600; border-color:var(--accent); }
body #workspace-header>.fx-wstabs>.fx-wstab[aria-selected="true"]:hover { background:var(--accent-hover);
  border-color:var(--accent-hover); color:#fff; }
body #workspace-header>.fx-wstabs>.fx-wstab__name { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
body #workspace-header>.fx-wstabs>.fx-wstab>.fx-wstab__x { border:0; background:none; color:inherit;
  cursor:pointer; font:inherit; line-height:1; padding:1px 5px; border-radius:6px; font-size:14px; opacity:.72; }
body #workspace-header>.fx-wstabs>.fx-wstab>.fx-wstab__x:hover { opacity:1; background:#00000014; }
/* 选中页签是主色底 ⇒ `×` 提亮到 .9，白字上仍然看得见（"所有页签都能关"不能只是 DOM 里有个按钮）。 */
body #workspace-header>.fx-wstabs>.fx-wstab[aria-selected="true"]>.fx-wstab__x { opacity:.9; }
body #workspace-header>.fx-wstabs>.fx-wstabadd { flex:0 0 auto; align-self:center; margin:0 2px;
  border:1px solid var(--line); background:var(--surface); border-radius:6px; padding:4px 9px;
  cursor:pointer; font:inherit; font-size:15px; color:var(--muted); }
body #workspace-header>.fx-wstabs>.fx-wstabadd:hover { background:var(--raised); }
@media (max-width:1100px) { body #workspace-header>.fx-wstabs>.fx-wstab { max-width:150px; padding:6px 6px 6px 10px; font-size:12px; } }
@media (max-width:760px) { body #workspace-header>.fx-wstabs { gap:4px; }
  body #workspace-header>.fx-wstabs>.fx-wstab { max-width:118px; padding:5px 5px 5px 9px; font-size:12px; } }

/* ③ 空态引导（关掉最后一个页签之后）：一句说明 +「打开页面」——清单与条尾 `＋` 是**同一份**。 */
body .fx-wsempty { max-width:520px; margin:44px auto 0; padding:22px 24px; text-align:center;
  background:var(--surface); border:1px dashed #cbd5e1; border-radius:12px; }
body .fx-wsempty__title { margin:0 0 6px; font-size:15px; font-weight:600; color:var(--text); }
body .fx-wsempty__hint { margin:0 0 16px; font-size:12.5px; color:var(--muted); }
body .fx-wsempty__open { font-size:13px; padding:8px 16px; }

/* ④ 页面清单（可搜）：绝对定位挂在 body 上 —— 逃出 `.panel{overflow:auto}` 一类裁剪祖先；
   坐标由 `app.js` 的 `pickerPosition()` 用 CSSOM 写入（CSP 只禁内联 `style=`，不禁 CSSOM）。 */
body .fx-wstpicker { position: absolute; z-index: 40; width: 300px; background: var(--surface);
  border: 1px solid #cbd5e1; border-radius: 10px; box-shadow: 0 8px 36px #26395126; padding: 8px; }
body .fx-wstpicker[hidden] { display: none; }
body .fx-wstpicker__q { width: 100%; padding: 7px 10px; border: 1px solid var(--line);
  border-radius: 6px; font: inherit; font-size: 13px; margin-bottom: 6px; outline: none; box-sizing: border-box; }
body .fx-wstpicker__q:focus { border-color: var(--accent); box-shadow: 0 0 0 3px #2468f21f; }
body .fx-wstpicker__list { list-style: none; margin: 0; padding: 0; max-height: 280px; overflow: auto;
  border: 1px solid var(--raised); border-radius: 6px; }
body .fx-wstpicker__list li { display: flex; align-items: center; gap: 8px; padding: 6px 9px; font-size: 13px; }
body .fx-wstpicker__list li:hover { background: var(--raised); }
body .fx-wstpicker__list .grp { margin-left: auto; color: var(--muted); font-size: 11px; }
body .fx-wstpicker__list .again { border: 1px solid var(--line); background: var(--surface);
  border-radius: 6px; padding: 1px 7px; font: inherit; font-size: 11.5px; color: var(--muted); cursor: pointer; }
body .fx-wstpicker__list .again:hover { background: var(--accent-soft); color: var(--accent-hover); }
body .fx-wstpicker__list .none { padding: 8px 9px; color: var(--muted); font-size: 12.5px; }

/* ⑤ 页签容器：与 `.page-content` 同形（**不设** padding/margin/border ⇒ 正文宽度与"没有页签条"时逐项相同） */
body .fx-wspane { display: block; }
body .fx-wspane[hidden] { display: none; }

/* 打印态：页签是界面壳，纸上没有意义（与原型"打印隐藏导航/工具条"同一口径） */
@media print { body #workspace-header>.fx-wstabs { display:none; } }

/* ══ 结束（多页签导航块到此为止）════════════════════════════════════════════════════════════════ */


/* ══ RECYCLE-BIN（task-63，2026-09-24）系统安全 → 回收站 ═══════════════════════════════════════
   为什么只追加这三个类、且全部作用域到 `body[data-page="RecycleBin"]`：
     · 表格（`table()` 造的 `.table-scroll`）、空态（`.empty`）、次要文字（`.muted`）、
       失败态（`.oa-state-title`/`.oa-state-why` —— 与旧效率页同一对）、**禁用按钮**
       （`button:disabled` 在 `brand.css:4` 已有规则）**全部复用平台既有样式**，本页不重造。
     · 本页真正缺的只有三样：**页头一行说明**、「不可恢复」的**就地提示**、以及它后面那句原因。
       既有样式表里没有对应类（`.hint` 其实一条规则都没有，所以本页不用 `.hint`）
       ⇒ 新造 3 个 `rb-*` 类；它们只在本页出现，因此一律加 `body[data-page="RecycleBin"]`
       作用域，不污染其它页面（与 `body[data-page="OaTemplates"]` / `body[data-page="RND"]` 同一手法）。
     · 颜色**只用既有令牌**（`--fx-warn-*` 三件套 + `--muted`），不新增色值；CSP 是
       `style-src 'self'`，本块写在样式表里，**没有任何内联样式**。
     · 特异度：`rb-blocked` 在 `.panel` 内，`brand.css:6` 的 `.panel>p`(0,1,1) 是同分竞争对手；
       这里用 `body[data-page=…]` 前缀把选择器提到 (0,2,1)，**不靠加载顺序取胜**（本文件本就
       在 `brand.css` 之后加载，但显式提分更不容易被后人改坏）。 */
body[data-page="RecycleBin"] .rb-head {
  margin: 0 0 12px; font-size: 12.6px; line-height: 1.7; max-width: 96ch;
}
body[data-page="RecycleBin"] .rb-blocked {
  margin: 6px 0 10px; padding: 8px 10px; font-size: 12.4px; line-height: 1.65;
  color: var(--fx-warn-text); background: var(--fx-warn-bg);
  border: 1px solid var(--fx-warn-line); border-radius: 8px;
}
body[data-page="RecycleBin"] .rb-blocked-note {
  display: inline-block; margin-left: 8px; font-size: 12px; color: var(--muted);
}

/* ══ 结束（RECYCLE-BIN 块到此为止）═══════════════════════════════════════════════════════════ */
