
:root{
  --bg:#0E0E10; --bg2:#131316; --card:#1A1A1F; --card2:#212128; --card3:#2A2A33;
  --line:rgba(255,255,255,.075); --line2:rgba(255,255,255,.14);
  --txt:#F3F3F5; --txt2:#B6B6C0; --dim:#7C7C88; --dim2:#565662;
  --lime:#CBF74E; --blue:#3355FF; --orange:#FF7A3D; --green:#4ADE80; --red:#FF5A5A;
  --ease:cubic-bezier(.22,1,.36,1);
  --r-app:32px; --r-card:24px; --r-in:16px;
  --sans:'Inter','Manrope','PingFang SC','Hiragino Sans GB','Microsoft YaHei',system-ui,sans-serif;
}
*{box-sizing:border-box;margin:0;padding:0}
html,body{height:100%}
body{background:#08080A;color:var(--txt);font-family:var(--sans);font-size:14px;line-height:1.55;-webkit-font-smoothing:antialiased;-webkit-text-size-adjust:100%}
button,input,select,textarea{font:inherit;color:inherit;background:none;border:none;outline:none}
button{cursor:pointer}
::-webkit-scrollbar{width:9px;height:9px}
::-webkit-scrollbar-thumb{background:#2C2C35;border-radius:9px;border:2px solid transparent;background-clip:padding-box}
.num{font-variant-numeric:tabular-nums}
.hide{display:none!important}
/* 图标兜底：ico() 生成的 svg 不带 width/height，必须给安全默认值，
   否则浏览器按替换元素默认尺寸（300×150）渲染，会把同行文字挤到下一行。
   下面所有 .xxx svg 规则都比这个元素选择器更具体，会正常覆盖它。 */
svg{display:inline-block;vertical-align:middle;width:1em;height:1em;flex:0 0 auto}
.muted{color:var(--dim)}
a{color:inherit;text-decoration:none;cursor:pointer}
a:hover{color:var(--lime)}

/* ---------- 登录 ---------- */
.login{min-height:100vh;display:grid;grid-template-columns:1.05fr .95fr;padding:20px;gap:20px}
.brand{background:linear-gradient(160deg,#16161B,#0E0E10 62%);border-radius:var(--r-app);padding:42px 46px;display:flex;flex-direction:column;justify-content:space-between;position:relative;overflow:hidden;border:1px solid var(--line);gap:30px}
.brand::after{content:"";position:absolute;width:540px;height:540px;right:-200px;top:-180px;background:radial-gradient(circle,rgba(203,247,78,.12),transparent 62%);pointer-events:none}
.b-top{display:flex;align-items:center;gap:12px;position:relative;z-index:2}
/* 图标位放公司 logo（取自 Java 版 ruoyi-ui 的 assets/logo/logo.png，只保留图形标记）。
 * 图形是深绿 + 橙的渐变，压在深色侧栏上会糊，所以垫一层白底圆角当「应用图标」。 */
.logo{width:38px;height:38px;border-radius:12px;background:#fff;display:grid;place-items:center;flex:0 0 auto;overflow:hidden}
.logo img{width:100%;height:100%;object-fit:contain;padding:3px;display:block}
.b-name{font-size:15px;font-weight:650}
.b-sub{font-size:12px;color:var(--dim)}
.b-kicker{font-size:12px;letter-spacing:2.4px;color:var(--lime);margin-bottom:16px}
.b-h1{font-size:clamp(30px,3.8vw,50px);line-height:1.14;font-weight:750;letter-spacing:-1.4px}
.b-h1 em{font-style:normal;color:var(--lime)}
.b-desc{color:var(--txt2);font-size:14.5px;max-width:32em;margin-top:18px}
.b-stats{display:flex;gap:13px;position:relative;z-index:2;flex-wrap:wrap}
.b-stat{flex:1;min-width:140px;background:rgba(255,255,255,.032);border:1px solid var(--line);border-radius:var(--r-card);padding:18px 20px;transition:.4s var(--ease)}
.b-stat:hover{background:rgba(203,247,78,.06);border-color:rgba(203,247,78,.24);transform:translateY(-3px)}
.b-stat i{font-style:normal;font-size:28px;font-weight:750;letter-spacing:-1px}
.b-stat span{display:block;color:var(--dim);font-size:12.5px;margin-top:5px}
.loginbox{background:var(--bg2);border-radius:var(--r-app);border:1px solid var(--line);padding:34px 38px 26px;display:flex;flex-direction:column;justify-content:center;overflow-y:auto}
.lb-h{font-size:21px;font-weight:700;letter-spacing:-.3px}
.lb-p{color:var(--dim);font-size:13px;margin-top:6px}
.tabs{display:flex;gap:6px;background:var(--card);padding:5px;border-radius:14px;margin:22px 0 18px}
.tab{flex:1;padding:9px 0;border-radius:10px;color:var(--dim);font-size:13.5px;font-weight:600;transition:.35s var(--ease)}
.tab.on{background:var(--card3);color:var(--txt)}
.field{margin-bottom:12px}
.field>label{display:block;font-size:12px;color:var(--dim);margin-bottom:6px;font-weight:600}
.field>label b{color:var(--orange);font-weight:600}
.inp{width:100%;background:var(--card);border:1px solid var(--line);border-radius:var(--r-in);padding:12px 14px;font-size:14px;transition:.3s var(--ease);color-scheme:dark}
.inp:focus{border-color:rgba(203,247,78,.5);background:var(--card2);box-shadow:0 0 0 4px rgba(203,247,78,.08)}
select.inp{appearance:none;background-image:linear-gradient(45deg,transparent 50%,var(--dim) 50%),linear-gradient(135deg,var(--dim) 50%,transparent 50%);background-position:calc(100% - 18px) 50%,calc(100% - 13px) 50%;background-size:5px 5px;background-repeat:no-repeat}
textarea.inp{min-height:82px;resize:vertical;line-height:1.7}
.grid2{display:grid;grid-template-columns:1fr 1fr;gap:11px}
.btn{width:100%;display:inline-flex;align-items:center;justify-content:center;gap:7px;padding:13px;border-radius:var(--r-in);background:var(--lime);color:#0B0B0D;font-weight:700;font-size:14.5px;line-height:1.25;white-space:nowrap;transition:.35s var(--ease);margin-top:5px}
.btn svg{width:16px;height:16px}
.btn:hover{filter:brightness(1.07);transform:translateY(-1px)}
.btn.ghost{background:var(--card);color:var(--txt);border:1px solid var(--line);font-weight:600}
.btn.ghost:hover{background:var(--card2);transform:none}
.btn.warn{background:var(--orange);color:#1a0d05}
.btn.sm{width:auto;padding:9px 15px;font-size:13px;border-radius:12px;margin:0}
.btn:disabled{opacity:.45;cursor:not-allowed;transform:none}
.demo{margin-top:22px;border-top:1px solid var(--line);padding-top:16px}
.demo-h{font-size:11.5px;color:var(--dim2);letter-spacing:1.2px;margin-bottom:11px}
.chips{display:flex;flex-wrap:wrap;gap:8px}
.chip{display:flex;align-items:center;gap:8px;background:var(--card);border:1px solid var(--line);border-radius:999px;padding:5px 12px 5px 5px;font-size:12.5px;color:var(--txt2);transition:.3s var(--ease)}
.chip:hover{border-color:rgba(203,247,78,.45);color:var(--txt);transform:translateY(-2px)}
.note{margin-top:14px;font-size:11.5px;color:var(--dim2);line-height:1.8;background:rgba(255,255,255,.025);border:1px solid var(--line);border-radius:14px;padding:12px 14px}
.note b{color:var(--txt2);font-weight:600}
.err{color:var(--red);font-size:12.5px;margin-top:9px;min-height:18px}

/* ---------- 表单规范（实现见 public/form-ui.js，条文见 docs/表单与交互规范.md） ----------
   下面这几个类名在样式表里**一直没有规则**，是 2026-10 审计里「表单看着不对劲」的根：
     · .req        —— 合同/设备表单的必填星号渲染成普通加粗黑字，与工作汇报内联的橙色星号不一致；
     · .fld        —— margin:0，导致连续两个字段之间没有任何间距（标签贴着上一个输入框），
                      而本文件自己的 .field 是 margin-bottom:12px —— 同一件事两套口径。这里对齐 .field；
     · .sh-f       —— 弹层底部按钮行没有排版，既不是右对齐也不是 footer；详情弹层里那句
                      `<span style="flex:1">` 因为没有 flex 容器而完全失效。 */
.req{color:var(--orange);font-weight:700;margin-left:3px}
.fld{margin-bottom:12px}
.fld>span b{font-weight:700}
.sh-f{display:flex;align-items:center;justify-content:flex-end;gap:9px;margin-top:16px;padding-top:14px;border-top:1px solid var(--line)}
.sh-f .btn{margin-top:0}
.sh-f .sp{flex:1}
/* 字段级错误（form-ui.js 的 uiFieldErr）：整行标红 + 行内提示，不再只靠表单底部那一行红字。
   空提示不占高度：否则每个字段下面都吊着一条 6px 的空白，长表单会明显变长。 */
.fld-err{color:var(--red);font-size:12px;line-height:1.6;margin-top:5px}
.fld-err:empty{display:none}
.fld.bad>.inp,.fld.bad .inp,.field.bad .inp{border-color:var(--red);background:rgba(255,90,90,.07)}
.fld-hint{font-size:11.5px;color:var(--dim2);margin-top:5px;line-height:1.65}
/* 按钮在途态：uiBusy() 会写 aria-busy="1" + disabled，这里补一个转圈，
   让「提交中」不只是变灰 —— 慢网下用户分不清「在提交」和「没点上」，正是连点的来源。 */
.btn[aria-busy="1"]{opacity:.75;cursor:progress}
.btn[aria-busy="1"]::after{content:'';width:11px;height:11px;border-radius:50%;border:2px solid currentColor;border-top-color:transparent;display:inline-block;animation:uifspin .7s linear infinite}
@keyframes uifspin{to{transform:rotate(360deg)}}
/* 两列表单：默认单列（与既有弹层一致，不改变现有观感）；
   表单声明 cols:2 时加 .uif-cols2，字段默认各占一列，给 span2 的字段跨两列（如备注）。 */
.uif-grid{display:block}
.uif-grid.uif-cols2{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:0 14px}
.uif-grid.uif-cols2>.fld[data-uif-span="2"]{grid-column:1/-1}
.uif-ck{display:flex;align-items:center;gap:8px;font-size:13.5px;color:var(--txt2);padding:10px 0}
.uif-ck input{width:16px;height:16px;accent-color:var(--lime)}
.uif-static{padding:10px 0;font-size:13.5px;color:var(--txt2)}
.uif-html{font-size:12.5px;color:var(--dim);line-height:1.85}

/* ---------- 头像/通用 ---------- */
.av{width:32px;height:32px;border-radius:50%;overflow:hidden;flex:0 0 auto;background:var(--card3);display:grid;place-items:center;font-size:12px;font-weight:700;color:#fff;border:1.5px solid var(--bg);position:relative}
.av img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.rolebadge{font-size:10.5px;padding:2px 7px;border-radius:6px;background:rgba(203,247,78,.15);color:var(--lime);font-weight:700;white-space:nowrap}
.rolebadge.m{background:rgba(255,255,255,.06);color:var(--dim)}
.pill{font-size:11px;padding:3px 9px;border-radius:999px;background:var(--card3);color:var(--txt2);border:1px solid var(--line);white-space:nowrap}
.pill.lime{background:rgba(203,247,78,.14);color:var(--lime);border-color:transparent}
.pill.orange{background:rgba(255,122,61,.14);color:var(--orange);border-color:transparent}
.pill.red{background:rgba(255,90,90,.14);color:#FF8A8A;border-color:transparent}
.pill.blue{background:rgba(51,85,255,.18);color:#96A9FF;border-color:transparent}
.pill.grey{background:rgba(255,255,255,.06);color:var(--dim);border-color:transparent}
/* 类目缩写方块：原代码用了 .code，但样式表里没有这个类，徽标会塌成一行裸文字 */
.code{width:34px;height:34px;flex:0 0 34px;border-radius:11px;display:grid;place-items:center;font-size:12px;font-weight:700;line-height:1;background:var(--card3);color:var(--txt2)}
/* 可点小链接（.sect / .pg-h 里的「配置责任人」「全部记录」等） */
.sect a,.pg-h a{font-size:12px;font-weight:600;color:var(--txt2);white-space:nowrap;transition:.25s var(--ease)}
.sect a:hover,.pg-h a:hover{color:var(--lime);text-decoration:underline;text-underline-offset:3px}

/* ---------- 外框 ---------- */
.app{height:100vh;padding:16px}
.frame{height:100%;display:flex;background:var(--bg);border:1px solid var(--line);border-radius:var(--r-app);overflow:hidden}
/* 左侧导航：带文字的分组侧栏。
   原来是 76px 的纯图标竖条——17 个入口一排到底、不分业务域、悬停才看得到名字，
   而且图标大量复用（人力/住户/部门都是 users，账号/角色/人脸机/管理后台都是 shield），
   点之前根本猜不到里面是什么。现在按业务域分组、每条一个专属图标 + 文字标签；
   窄屏（≤1180px）自动收回纯图标并保留悬停提示，手机端换成底部栏 + 「更多」抽屉。 */
.rail{width:238px;flex:0 0 238px;background:#111114;border-right:1px solid var(--line);display:flex;flex-direction:column;padding:16px 0 12px;min-height:0}
.rail-h{display:flex;align-items:center;gap:11px;padding:0 16px 15px;flex:0 0 auto}
.rail-h .logo{width:40px;height:40px;border-radius:13px}
.rail-t{min-width:0;flex:1}
.rail-t b{display:block;font-size:14px;font-weight:700;letter-spacing:-.2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.rail-t span{display:block;font-size:11px;color:var(--dim);white-space:nowrap}
.rail-scroll{flex:1;min-height:0;overflow-y:auto;overflow-x:hidden;display:flex;flex-direction:column;gap:2px;padding:0 10px 10px}
/* 管理员有 17 个入口，1440×900 下这一列要滚动。滚动条做可见一点，别让人以为菜单就这么多。 */
.rail-scroll::-webkit-scrollbar{width:8px}
.rail-scroll::-webkit-scrollbar-thumb{background:rgba(255,255,255,.14);border-radius:8px;border:2px solid transparent;background-clip:padding-box}
.rail-scroll:hover::-webkit-scrollbar-thumb{background:rgba(255,255,255,.24);background-clip:padding-box}
/* 分组标题吸顶：滚动时始终知道自己在哪个业务域 */
.rail-g{position:sticky;top:0;z-index:3;background:#111114;font-size:10.5px;color:var(--dim2);letter-spacing:1.1px;font-weight:650;padding:11px 11px 4px;white-space:nowrap}
.rail-g:first-child{padding-top:2px}
.nv{position:relative;display:flex;align-items:center;gap:11px;width:100%;padding:8px 11px;border-radius:12px;color:var(--txt2);font-size:13.5px;font-weight:550;text-align:left;transition:.28s var(--ease)}
.nv:hover{background:var(--card);color:var(--txt)}
.nv.on{background:var(--lime);color:#0B0B0D;font-weight:700}
.nv svg{width:19px;height:19px;flex:0 0 19px}
.nv-t{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.nv .tip{display:none}
.nv .badge{margin-left:auto;min-width:19px;height:19px;border-radius:10px;background:var(--orange);color:#fff;font-size:10.5px;font-weight:700;display:grid;place-items:center;padding:0 5px}
.nv.on .badge{background:#0B0B0D;color:var(--lime)}
/* 可展开主菜单（台账管理）：一条父项 + 一组子项。子项缩进并带一条竖向导引线，
   一眼看出它们是同一套功能；父项自己不占页面，只用左侧小竖条表示「我在这一支里」。 */
.nv.menu-h .arw{margin-left:auto;display:flex;color:var(--dim2);transition:.25s var(--ease)}
.nv.menu-h .arw svg{width:14px;height:14px;flex:0 0 14px}
.nv.menu-h.open .arw{transform:rotate(90deg)}
.nv.menu-h.act{color:var(--txt)}
.nv.menu-h.act::before{content:"";position:absolute;left:2px;top:50%;transform:translateY(-50%);width:3px;height:15px;border-radius:2px;background:var(--lime)}
.sub-wrap{display:none;flex-direction:column;gap:2px;margin:0 0 2px 10px;padding-left:9px;border-left:1px solid var(--line)}
.sub-wrap.open{display:flex}
/* 第二层菜单（物业运营 → 台账管理）：嵌在面板里，字号与缩进都收一档，看得出从属关系 */
.sub-wrap .sub-wrap{margin:0 0 2px 6px;padding-left:8px}
.sub-wrap .nv.menu-h{font-size:13px;padding:7px 10px}
.nv.sub{padding:7px 10px;font-size:13px}
.nv.sub svg{width:17px;height:17px;flex:0 0 17px}
.main{flex:1;display:flex;flex-direction:column;min-width:0}
.top{height:72px;flex:0 0 72px;border-bottom:1px solid var(--line);display:flex;align-items:center;gap:12px;padding:0 22px}
.hi{font-size:16px;font-weight:680;letter-spacing:-.2px;min-width:0}
.hi small{display:block;font-size:12px;color:var(--dim);font-weight:400;margin-top:2px}
.top .sp{flex:1}
.search{display:flex;align-items:center;gap:9px;background:var(--card);border:1px solid var(--line);border-radius:13px;padding:9px 12px;color:var(--dim);font-size:13px;min-width:200px;transition:.3s var(--ease)}
.search:hover{border-color:var(--line2);color:var(--txt2)}
.search svg{width:15px;height:15px}
.kbd{margin-left:auto;background:var(--card3);border-radius:6px;padding:2px 7px;font-size:11px;color:var(--txt2)}
.icbtn{width:38px;height:38px;border-radius:12px;display:grid;place-items:center;color:var(--txt2);border:1px solid transparent;transition:.3s var(--ease);position:relative;flex:0 0 auto}
.icbtn:hover{background:var(--card);border-color:var(--line);color:var(--txt)}
.icbtn svg{width:18px;height:18px}
.icbtn .nb{position:absolute;top:7px;right:7px;width:7px;height:7px;border-radius:50%;background:var(--orange);border:1.5px solid var(--bg)}
.meav{display:flex;align-items:center;gap:8px;padding:5px 10px 5px 5px;border-radius:999px;background:var(--card);border:1px solid var(--line);font-size:12.5px;color:var(--txt2);white-space:nowrap}
.view{flex:1;overflow-y:auto;padding:22px 22px 40px;scroll-behavior:smooth}
.pg-h{display:flex;align-items:flex-end;gap:12px;margin-bottom:18px;flex-wrap:wrap}
.pg-h h2{font-size:23px;font-weight:730;letter-spacing:-.6px}
.pg-h p{color:var(--dim);font-size:12.8px;margin-top:3px}
.pg-h .sp{flex:1}
.sect{font-size:13px;font-weight:700;color:var(--txt2);margin:22px 0 11px;display:flex;align-items:center;gap:8px}
.sect svg{width:14px;height:14px;color:var(--dim)}
.sect:first-child{margin-top:0}
.sect .sp{flex:1}
.grid{display:grid;gap:14px}
.card{background:var(--card);border:1px solid var(--line);border-radius:var(--r-card);padding:18px;transition:.4s var(--ease);position:relative}
.card.hov:hover{border-color:var(--line2);transform:translateY(-2px)}
.ch{display:flex;align-items:center;gap:7px;font-size:12.5px;color:var(--dim);margin-bottom:11px;min-width:0}
.ch svg{width:14px;height:14px}
/* 卡片标题里的主标题：长台账名要能省略，否则会把右侧标签挤出卡片 */
.ch .ch-t{font-size:13px;font-weight:700;color:var(--txt);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ch>.pill{flex:0 0 auto}
.sk{background:linear-gradient(90deg,#1A1A1F 25%,#232329 37%,#1A1A1F 63%);background-size:400% 100%;animation:sh 1.3s ease infinite;border-radius:12px}
@keyframes sh{0%{background-position:100% 50%}100%{background-position:0 50%}}
.fade{animation:fd .42s var(--ease)}
@keyframes fd{from{opacity:0;transform:translateY(9px)}to{opacity:1;transform:none}}
@keyframes up{from{transform:translateY(26px)}to{transform:none}}
.kpi{font-size:29px;font-weight:750;letter-spacing:-1.2px}
.kpi small{font-size:13px;font-weight:600;color:var(--dim);margin-left:3px}
.delta{font-size:11.5px;font-weight:650;padding:2px 8px;border-radius:7px;white-space:nowrap}
.delta.up{background:rgba(74,222,128,.14);color:var(--green)}
.delta.warn{background:rgba(255,122,61,.15);color:var(--orange)}
.spark{width:100%;height:44px;display:block;margin-top:10px;overflow:visible}
.bar{height:7px;border-radius:7px;background:rgba(255,255,255,.07);overflow:hidden;flex:1;min-width:40px}
.bar i{display:block;height:100%;border-radius:7px;background:var(--lime);transition:width .9s var(--ease)}
.bar i.warn{background:var(--orange)}
.bar i.blue{background:#5B78FF}
.loadrow{display:flex;align-items:center;gap:11px;padding:9px 0}
.loadrow svg{width:16px;height:16px;color:var(--dim)}
.loadrow .nm{font-size:12.5px;flex:0 0 auto;min-width:0}
.loadrow .vl{width:44px;text-align:right;font-size:12px;color:var(--dim);flex:0 0 auto}
.bars{display:flex;align-items:flex-end;gap:10px;height:158px;padding-top:12px}
.bars .bw{flex:1;display:flex;flex-direction:column;align-items:center;gap:7px;height:100%;justify-content:flex-end}
.bars .bb{width:100%;max-width:36px;border-radius:8px 8px 4px 4px;background:var(--card3);transition:height .9s var(--ease)}
.bars .bb.lime{background:var(--lime)}
.bars .bl{font-size:10.5px;color:var(--dim2)}
.bars .bv{font-size:11.5px;color:var(--txt2);font-weight:650}
.hbar{display:flex;align-items:center;gap:11px;padding:6px 0;font-size:12.5px}
.hbar .hn{width:96px;flex:0 0 96px;color:var(--txt2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.hbar .ht{flex:1;height:9px;background:rgba(255,255,255,.055);border-radius:9px;overflow:hidden}
.hbar .ht i{display:block;height:100%;background:var(--lime);border-radius:9px;transition:width .8s var(--ease)}
.hbar .hv{width:38px;text-align:right;color:var(--dim);font-size:11.5px;flex:0 0 auto}
.empty{text-align:center;padding:38px 18px;color:var(--dim);font-size:13px}
.empty b{display:block;font-size:15px;color:var(--txt2);margin-bottom:7px;font-weight:650}
.filt{display:flex;gap:6px;flex-wrap:wrap;margin-bottom:14px}
.filt button{padding:7px 13px;border-radius:999px;font-size:12px;background:var(--card);border:1px solid var(--line);color:var(--dim)}
.filt button.on{background:var(--lime);color:#0B0B0D;border-color:transparent;font-weight:700}
.feed{display:flex;gap:11px;padding:10px 0;border-bottom:1px solid var(--line);align-items:center}
.feed:last-child{border-bottom:none}
.feed .fx{flex:1;min-width:0;font-size:12.8px;color:var(--txt2)}
.feed .fx b{color:var(--txt);font-weight:650}
.feed .fx i{font-style:normal;color:var(--lime)}
.feed time{font-size:11.5px;color:var(--dim2);flex:0 0 auto}

/* ---------- 台账记录卡 ---------- */
.rec{display:flex;gap:13px;padding:14px;border-radius:var(--r-in);background:var(--card2);border:1px solid var(--line);margin-bottom:10px;transition:.3s var(--ease);cursor:pointer;align-items:flex-start}
.rec:hover{border-color:var(--line2);transform:translateY(-1px)}
.rec.bad{border-color:rgba(255,122,61,.28)}
.rec .rmain{flex:1;min-width:0}
.rec .r1{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.rec .r1 b{font-size:14px;font-weight:680}
.rec .r2{font-size:12.5px;color:var(--txt2);margin-top:5px;line-height:1.65;word-break:break-word}
.rec .r3{display:flex;align-items:center;gap:11px;margin-top:8px;font-size:11.5px;color:var(--dim2);flex-wrap:wrap}
.rec .r3 svg{width:12px;height:12px}
.thumbs{display:flex;gap:5px;flex:0 0 auto}
.thumbs img,.thumbs .ph{width:46px;height:46px;border-radius:10px;object-fit:cover;background:var(--card3);display:grid;place-items:center;font-size:10px;color:var(--dim)}
.stamp{position:absolute;top:12px;right:12px;font-size:10px;color:var(--dim2)}

/* ---------- 照片上传 ---------- */
.shots{display:grid;grid-template-columns:repeat(auto-fill,minmax(84px,1fr));gap:9px}
.shot{position:relative;aspect-ratio:1;border-radius:14px;overflow:hidden;background:#151518;border:1px solid var(--line)}
.shot img{width:100%;height:100%;object-fit:cover;display:block}
.shot .x{position:absolute;top:4px;right:4px;width:22px;height:22px;border-radius:8px;background:rgba(8,8,10,.72);display:grid;place-items:center;color:#fff}
.shot .x svg{width:12px;height:12px}
.shot .kb{position:absolute;left:0;right:0;bottom:0;font-size:9.5px;color:#fff;background:linear-gradient(transparent,rgba(8,8,10,.85));padding:10px 6px 4px;text-align:center}
.addshot{aspect-ratio:1;border-radius:14px;border:1.5px dashed var(--line2);display:grid;place-items:center;color:var(--dim);transition:.3s var(--ease);gap:4px;font-size:11px}
.addshot:hover{border-color:var(--lime);color:var(--lime)}
.addshot svg{width:20px;height:20px}

/* ---------- 表格 ---------- */
.tbl-wrap{overflow:auto;border:1px solid var(--line);border-radius:var(--r-in);max-height:520px}
table.tb{width:100%;border-collapse:collapse;font-size:12px}
table.tb th{background:#151518;color:var(--dim);text-align:left;padding:9px 11px;font-weight:650;border-bottom:1px solid var(--line);white-space:nowrap;position:sticky;top:0;z-index:2}
table.tb td{padding:9px 11px;border-bottom:1px solid var(--line);color:var(--txt2);white-space:nowrap;max-width:300px;overflow:hidden;text-overflow:ellipsis}
table.tb tr:last-child td{border-bottom:none}
table.tb tr:hover td{background:rgba(255,255,255,.022)}
td.ok{color:var(--green)}td.no{color:var(--orange);font-weight:650}

/* ---------- 分页条（页码按钮） ----------
 * 全站列表共用：一页固定条数 + 首页/上一页/页码/下一页/末页 + 每页条数 + 跳页。
 * 不用「加载更多」的原因见 JS 里 pgBar 的注释：追加式渲染会让表格无限变长。 */
.pg-bar{display:flex;gap:6px;align-items:center;flex-wrap:wrap;margin-top:11px;font-size:11.5px;color:var(--dim2)}
.pg-bar .pgb{min-width:32px;padding:7px 10px;font-size:12px;font-weight:600}
.pg-bar .pgb.on{background:var(--lime);color:#0B0B0D;border-color:transparent;font-weight:700}
.pg-bar .pg-gap{color:var(--dim2);padding:0 1px}
.pg-bar .pg-info{white-space:nowrap}
.pg-bar .pg-jump{width:66px;padding:7px 9px;font-size:12px;border-radius:10px;text-align:center}
.pg-hint{font-size:11px;color:var(--dim2);margin-top:4px}

/* ---------- 弹层 ---------- */
.mask{position:fixed;inset:0;background:rgba(6,6,8,.74);backdrop-filter:blur(7px);z-index:200;display:flex;align-items:center;justify-content:center;padding:20px;animation:fd .28s var(--ease)}
.sheet{background:var(--bg2);border:1px solid var(--line2);border-radius:26px;width:min(760px,100%);max-height:88vh;overflow-y:auto;padding:26px 28px;position:relative}
.sheet.w{width:min(520px,100%)}
.sh-x{position:absolute;top:16px;right:16px;width:32px;height:32px;border-radius:10px;display:grid;place-items:center;color:var(--dim);z-index:3}
.sh-x:hover{background:var(--card);color:var(--txt)}
.sh-x svg{width:16px;height:16px}
.sh-h{font-size:19px;font-weight:720;letter-spacing:-.3px;margin-bottom:4px;padding-right:34px}
.sh-p{color:var(--dim);font-size:12.8px;margin-bottom:18px}
.cmd{position:fixed;inset:0;background:rgba(6,6,8,.7);backdrop-filter:blur(7px);z-index:260;display:flex;justify-content:center;padding-top:12vh}
.cmdbox{width:min(600px,92%);height:max-content;background:var(--bg2);border:1px solid var(--line2);border-radius:22px;overflow:hidden;box-shadow:0 30px 90px rgba(0,0,0,.6)}
.cmdin{display:flex;align-items:center;gap:12px;padding:15px 20px;border-bottom:1px solid var(--line)}
.cmdin input{flex:1;font-size:15px}
.cmdin svg{width:17px;height:17px;color:var(--dim);flex:0 0 auto}
.cmdlist{max-height:52vh;overflow-y:auto;padding:8px}
.cmi{display:flex;align-items:center;gap:11px;padding:10px 13px;border-radius:12px;font-size:13.5px;color:var(--txt2);cursor:pointer}
.cmi.on,.cmi:hover{background:var(--card2);color:var(--txt)}
.cmi .k{margin-left:auto;font-size:10.5px;color:var(--dim2)}
.cmi svg{width:15px;height:15px;color:var(--dim);flex:0 0 auto}
.cmdg{font-size:10.5px;color:var(--dim2);padding:11px 13px 5px;letter-spacing:1px;font-weight:650}
.pop{position:absolute;top:62px;right:20px;width:330px;background:var(--bg2);border:1px solid var(--line2);border-radius:20px;padding:8px;z-index:150;box-shadow:0 20px 60px rgba(0,0,0,.55);animation:fd .25s var(--ease)}
.pop .nh{font-size:11.5px;color:var(--dim);padding:9px 12px;font-weight:650;display:flex;gap:8px}
.pop .nh .sp{flex:1}
.nrow{display:flex;gap:11px;padding:11px 12px;border-radius:13px;cursor:pointer;align-items:flex-start}
.nrow:hover{background:var(--card)}
.nrow .nx{flex:1;min-width:0}
.nrow .nx b{display:block;font-size:13px;font-weight:600}
.nrow .nx span{font-size:11.5px;color:var(--dim)}
.nrow time{font-size:10.5px;color:var(--dim2);flex:0 0 auto}
.toasts{position:fixed;bottom:30px;left:50%;transform:translateX(-50%);z-index:320;display:flex;flex-direction:column;gap:9px;align-items:center;pointer-events:none}
.toast{background:#26262F;border:1px solid var(--line2);color:var(--txt);padding:11px 18px;border-radius:14px;font-size:13px;box-shadow:0 14px 44px rgba(0,0,0,.5);animation:fd .3s var(--ease);max-width:80vw}
.toast.warn{border-color:rgba(255,122,61,.5);background:#2A2018}
.toast.ok{border-color:rgba(203,247,78,.45)}
/* ---------- 说明气泡：点 `?` 图标看口径 ----------
 * 2026-10 起全站统一：**要交代但不该占版面**的说明一律挂到 ? 图标上，点开看、点别处关。
 * 为什么不用原生 title=：① 手机上没有 hover，title 根本不弹；② 一段话在悬停提示里读不完；
 * ③ title 不换行，字段名与加粗全糊成一行。三者合起来的结果是「写了等于没写」。
 * 图标 15px、与文字同色系，不抢视线：它只在读者真的想追口径时才被看见。 */
.hint-i{display:inline-flex;align-items:center;justify-content:center;width:15px;height:15px;min-width:15px;
  border-radius:50%;border:1px solid var(--line2);color:var(--dim);font-size:10.5px;font-weight:700;line-height:1;
  cursor:pointer;vertical-align:2px;margin-left:6px;user-select:none;position:relative;z-index:1}
.hint-i:hover,.hint-i.on{border-color:var(--lime);color:var(--lime)}
.hint-i:focus{outline:none;border-color:var(--lime);color:var(--lime)}
.hint-pop{display:none;position:fixed;z-index:315;width:min(360px,88vw);max-height:60vh;overflow-y:auto;
  background:var(--bg2);border:1px solid var(--line2);border-radius:16px;padding:13px 15px;
  font-size:12.5px;line-height:1.85;color:var(--txt2);box-shadow:0 22px 60px rgba(0,0,0,.62);
  animation:fd .22s var(--ease)}
.hint-pop.on{display:block}
.hint-pop b{color:var(--txt);font-weight:650}
.hint-pop code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11.5px;color:var(--txt2);
  background:rgba(255,255,255,.06);border-radius:5px;padding:1px 5px}
.hint-pop i{font-style:normal;color:var(--dim2)}
.tourhi{position:relative;z-index:300!important;box-shadow:0 0 0 9999px rgba(6,6,8,.84)!important;border-radius:16px!important}
.tourbox{position:fixed;z-index:310;width:min(310px,88vw);background:var(--bg2);border:1px solid var(--line2);border-radius:20px;padding:18px;box-shadow:0 24px 70px rgba(0,0,0,.6);animation:fd .3s var(--ease)}
.tourbox b{display:block;font-size:14.5px;margin-bottom:6px}
.tourbox p{font-size:12.8px;color:var(--txt2);line-height:1.8}
.tourbox .tf{display:flex;align-items:center;gap:10px;margin-top:14px}
.tourbox .tf .sp{flex:1}
.tourbox .tf .st{font-size:11px;color:var(--dim2)}
.tourbox .tf button{padding:7px 14px;border-radius:11px;font-size:12.5px;font-weight:650}
.tourbox .tf .nxt{background:var(--lime);color:#0B0B0D}
.tourbox .tf .skp{color:var(--dim)}
.sw{width:40px;height:23px;border-radius:999px;background:var(--card3);position:relative;transition:.32s var(--ease);flex:0 0 40px;cursor:pointer}
.sw::after{content:"";position:absolute;top:3px;left:3px;width:17px;height:17px;border-radius:50%;background:#fff;transition:.32s var(--ease)}
.sw.on{background:var(--lime)}
.sw.on::after{left:20px}
.srow{display:flex;align-items:center;gap:13px;padding:12px 0;border-bottom:1px solid var(--line)}
.srow:last-child{border-bottom:none}
.srow .sx{flex:1;min-width:0}
.srow .sx b{display:block;font-size:13.5px;font-weight:600}
.srow .sx span{font-size:11.5px;color:var(--dim)}

/* ---------- 迎检打印页 ----------
   注意：JS 实际生成的容器是 #sheetview（屏上预览）和 #printwrap（打印用），
   原来只写了 #printsheet 这个从不存在的 id，整套迎检页排版等于没生效。 */
#printwrap,#sheetview{background:#fff;color:#111;border-radius:18px;padding:26px 22px;overflow-x:auto}
#printwrap h3,#sheetview h3{text-align:center;font-size:19px;font-weight:700;letter-spacing:2px;margin-bottom:4px;font-family:'SimSun','Songti SC',serif}
#printwrap .pt2,#sheetview .pt2{text-align:center;font-size:14px;font-weight:600;margin-bottom:3px;font-family:'SimSun',serif}
#printwrap .pt3,#sheetview .pt3{font-size:13px;margin-bottom:9px;font-family:'SimSun',serif}
#printwrap table,#sheetview table{width:100%;border-collapse:collapse;font-size:12px;font-family:'SimSun',serif}
#printwrap th,#printwrap td,#sheetview th,#sheetview td{border:1px solid #333;padding:6px 7px;text-align:center;vertical-align:middle}
#printwrap th,#sheetview th{background:#f2f2f2;font-weight:700;white-space:nowrap}
#printwrap td.l,#sheetview td.l{text-align:left}
#printwrap img,#sheetview img{max-height:78px;max-width:110px;border-radius:2px}
#printwrap .sign,#sheetview .sign{margin-top:14px;font-size:12px;font-family:'SimSun',serif}
.pvimg{max-width:100%;border-radius:14px;display:block}

/* ---------- 财务报表模板（透视报表 / 图表 / 试算） ----------
   报表模板页签与它的表单弹层专用。全是新类名（fr- 前缀），不动既有页面。
   周期 A4 打印的 @page 与 break-inside 规则在下面的 @media print 里。 */
.fr-chart{background:#fff;border-radius:14px;padding:8px;margin-bottom:12px}
.fr-chart img{width:100%;display:block;border-radius:8px}
.fr-chart .fr-cfail{color:#666;font-size:12.5px;text-align:center;padding:38px 14px;line-height:1.8}
.pv-chart{background:var(--card2);border:1px solid var(--line);border-radius:12px;padding:12px 13px}
.pv-chart .pvc-t{font-size:12.5px;font-weight:700;color:var(--txt2);margin-bottom:9px}
.pv-chart .pvc-n{font-size:11px;color:var(--dim2);margin-top:9px;line-height:1.7}
.pv-row{display:flex;align-items:center;gap:9px;padding:5px 0;font-size:12px}
.pv-row .pvl{width:110px;flex:0 0 110px;color:var(--txt2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pv-row .pvt{flex:1;height:9px;background:rgba(255,255,255,.055);border-radius:9px;overflow:hidden}
.pv-row .pvt i{display:block;height:100%;border-radius:9px}
.pv-row .pvv{width:96px;flex:0 0 auto;text-align:right;color:var(--dim);font-size:11.5px}
/* 表单字段：全站 <label class="fld"> 都在用却没有对应的样式（默认 inline，
   冒号与输入框会挤在一行），这里补一条最保险的：竖排 + 输入框占满。 */
.fld{display:block;margin:0}
.fld>span{display:block;font-size:12px;color:var(--dim);margin-bottom:6px}

/* ---------- 栅格工具类 ----------
   这些栅格宽度原来写死在行内 style 里，行内样式优先级高于媒体查询，
   手机端无法降列，4 个 KPI 被压成一条。改成类之后窄屏才能覆盖。 */
.grid.g4{grid-template-columns:repeat(4,1fr)}
.grid.g3{grid-template-columns:repeat(3,1fr)}
.grid.g2{grid-template-columns:1fr 1fr}
.grid.g-wide{grid-template-columns:1.35fr .95fr}
.grid.g-report{grid-template-columns:1.25fr .9fr}
.grid.gap11{gap:11px}
/* 提醒推送的通道卡片：字段数量因投递方式而异，用 flex 把「测试发送」按钮统一压到底部对齐 */
.ch-card{display:flex;flex-direction:column}
.ch-card>.btn{margin-top:auto}
/* ---------- 提醒推送页 ---------- */
.nt-box{border:1px solid var(--line);border-radius:var(--r-in);padding:12px 13px;margin-bottom:11px;background:rgba(255,255,255,.015)}
.nt-h{display:flex;align-items:center;gap:10px;margin-bottom:7px}
.nt-h b{font-size:12.8px;font-weight:700}
.nt-h .sw{margin-left:auto}
.nt-d{font-size:11.5px;color:var(--dim2);line-height:1.7;margin-bottom:11px}
.nt-box .field{margin-bottom:9px}
.nt-box .field>label{font-size:11.5px}
.nt-ov{border:1px solid var(--line);border-radius:var(--r-in);padding:11px 13px;margin-bottom:9px;background:rgba(255,255,255,.015)}
.nt-ov-h{display:flex;align-items:center;gap:9px;flex-wrap:wrap}
.nt-ov-h b{font-size:12.8px}
.nt-prev{border:1px solid var(--line);border-radius:var(--r-in);margin-bottom:10px;overflow:hidden}
.nt-prev-h{display:flex;align-items:center;gap:9px;padding:9px 12px;background:rgba(255,255,255,.03);border-bottom:1px solid var(--line)}
.nt-prev-h b{font-size:12.8px}
.nt-prev-b{padding:11px 13px;font-size:12.5px;color:var(--txt2)}
#nt-body .card{background:var(--card)}

/* ---------- 数字孪生（小区群概况 / 单小区孪生） ----------
   舞台是「画布 + 浮层」：画布吃满，图层开关 / 缩放 / 图例都绝对定位压在画布上，
   这样画布能拿到整块可用面积（等轴测图对纵横比很敏感，被挤窄了就看不全）。
   侧栏与舞台同高、独立滚动：图要看、清单也要滑，两者不该互相顶。 */
.tw-wrap{display:grid;grid-template-columns:1fr 336px;gap:14px;margin-top:14px;align-items:start}
.tw-stage{position:relative;height:min(58vh,540px);border:1px solid var(--line);border-radius:var(--r-card);
  overflow:hidden;background:#0a0e15}
.tw-stage canvas{display:block;width:100%;height:100%;cursor:grab;touch-action:pan-y}
.tw-stage canvas:active{cursor:grabbing}
.tw-layers{position:absolute;left:12px;top:12px;display:flex;flex-wrap:wrap;gap:6px;max-width:calc(100% - 24px)}
.tw-layers button{background:rgba(20,26,36,.86);border:1px solid var(--line2);color:var(--dim);
  border-radius:999px;padding:4px 11px;font-size:11.5px;cursor:pointer;transition:.2s}
.tw-layers button.on{background:rgba(203,247,78,.14);border-color:rgba(203,247,78,.5);color:var(--lime)}
.tw-zoom{position:absolute;right:12px;top:12px;display:flex;flex-direction:column;gap:6px}
.tw-zoom .btn{min-width:38px;padding:5px 8px;justify-content:center}
.tw-hud{position:absolute;left:12px;bottom:10px;right:12px;display:flex;flex-wrap:wrap;gap:12px;align-items:center;
  font-size:11px;color:var(--dim);pointer-events:none;text-shadow:0 1px 3px rgba(0,0,0,.8)}
.tw-hud i{display:inline-block;width:8px;height:8px;border-radius:50%;margin-right:5px;vertical-align:middle}
/* 三维标签用 DOM 覆盖层（three.js 侧每帧投影定位）：中文锐利、不用字体图集 */
.tw3d-labels{position:absolute;left:0;top:0;right:0;bottom:0;pointer-events:none;overflow:hidden}
.tw3d-label{position:absolute;transform:translate(-50%,-100%);white-space:nowrap;font-size:12px;font-weight:600;
  text-shadow:0 1px 3px rgba(0,0,0,.9),0 0 8px rgba(0,0,0,.7);line-height:1.35;text-align:center}
.tw3d-label i{display:block;font-style:normal;font-size:10.5px;font-weight:400;opacity:.82}
.tw-tip{position:absolute;display:none;padding:5px 10px;background:rgba(12,16,24,.94);border:1px solid var(--line2);
  border-radius:9px;font-size:12px;pointer-events:none;transform:translate(12px,-30px);white-space:nowrap;z-index:4}
.tw-side{position:sticky;top:0;max-height:min(58vh,540px);overflow-y:auto;padding-right:2px}
.tw-full{position:fixed;left:12px;right:12px;top:12px;bottom:12px;z-index:200;background:var(--bg);
  border-radius:var(--r-card);padding:12px;grid-template-columns:1fr 336px}
.tw-full .tw-stage{height:calc(100% - 4px)}
.tw-full .tw-side{max-height:100%}
@media(max-width:1180px){
  .tw-wrap{grid-template-columns:1fr}
  .tw-stage{height:min(52vh,420px)}
  .tw-side{position:static;max-height:none}
}

/* Hallmark · Workbench · existing dark/lime system · P4 H4 E4 S4 R4 V4 */
.tw-wrap{grid-template-columns:minmax(0,1fr) 360px;align-items:stretch}
.tw-stage{height:min(66vh,680px);border-radius:20px}
.tw-side{max-height:min(66vh,680px);min-width:0}
.tw-layers{right:68px;max-width:none;z-index:2}
.tw-zoom{z-index:3}
.tw-section-head{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}
.tw-section-head h3{font-size:16px}.tw-section-head h4{font-size:16px;overflow-wrap:anywhere;min-width:0}
.tw-section-head>span,.tw-location{font-size:11px;color:var(--txt2)}
.tw-catalog{margin-top:20px}.tw-catalog p,.tw-geo p{font-size:12px;line-height:1.7;color:var(--txt2);margin:8px 0 12px}
.tw-search{display:block;color:var(--txt2);font-size:12px;margin:12px 0}
.tw-search input,.tw-geo input,.tw-geo select{display:block;width:100%;min-width:0;min-height:44px;padding:10px 12px;border:1px solid var(--line2);background:var(--bg2);border-radius:10px;margin-top:6px;color:var(--txt)}
.tw-community{border:1px solid var(--line2);border-radius:16px;padding:16px;margin-bottom:12px;background:var(--card)}
.tw-community[hidden]{display:none}.tw-community:hover{border-color:var(--lime)}
.tw-facts{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px;border-top:1px solid var(--line);padding:12px 0}
.tw-facts span{font-size:11px;color:var(--txt2)}.tw-facts b{display:block;font-size:19px;font-variant-numeric:tabular-nums;color:var(--txt);font-weight:600}
.tw-actions{display:flex;gap:8px;flex-wrap:wrap;margin-top:12px}.tw-actions .btn{min-height:40px}
.tw-wrap button{white-space:nowrap}.tw-wrap button:focus-visible,.tw-wrap input:focus-visible,.tw-wrap select:focus-visible,.tw-wrap a:focus-visible,.tw-wrap summary:focus-visible{outline:2px solid var(--lime);outline-offset:3px}
.tw-wrap button:active{transform:translateY(1px)}.tw-wrap button:disabled{opacity:.5;cursor:wait}
.tw-geo{padding:16px;margin-bottom:16px;border-color:var(--lime)}.tw-geo label{display:block;font-size:12px;color:var(--txt2)}
.tw-coords{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;margin-top:12px}
.tw-geo a,.tw-references a{font-size:12px;color:var(--lime)}.tw-references{border-top:1px solid var(--line2);padding-top:12px;color:var(--txt2);font-size:12px}.tw-references a{display:block;padding:8px 0}.tw-references summary{cursor:pointer}
.tw-full{inset:0;margin:0;padding:20px;border-radius:0;grid-template-columns:minmax(0,1fr) 380px;grid-template-rows:auto minmax(0,1fr);height:100dvh}
.tw-fullbar{grid-column:1/-1;display:flex;align-items:center;justify-content:space-between;gap:12px;min-width:0}.tw-fullbar b{font-size:18px;overflow-wrap:anywhere}
.tw-full .tw-stage{height:100%;min-height:0}.tw-full .tw-side{max-height:100%;min-height:0;position:static}.tw-full .tw-estate-summary{padding:20px!important}.tw-full .tw-estate-summary>div:last-child>div{padding:10px 0!important;border-bottom:1px solid var(--line);font-size:14px!important}
@media(max-width:1180px){.tw-wrap{grid-template-columns:minmax(0,1fr)}.tw-stage{height:54vh;min-height:340px}.tw-side{max-height:none}.tw-full{grid-template-rows:auto minmax(300px,52dvh) auto;overflow:auto}.tw-full .tw-side{overflow:visible}.tw-full .tw-stage{height:100%}}
@media(max-width:600px){.tw-full{padding:12px;gap:12px}.tw-fullbar b{font-size:15px}.tw-stage{min-height:360px}.tw-layers{left:8px;top:8px;gap:4px;right:58px}.tw-layers button{padding:6px 8px}.tw-zoom{right:8px;top:8px}.tw-hud{gap:8px}.tw-community{padding:14px}.tw-coords{gap:8px}.tw-wrap .btn{min-height:44px}.tw-side .filt{flex-wrap:wrap}.tw-fullbar .btn{font-size:11px;padding:8px}}
@media(prefers-reduced-motion:reduce){.tw-wrap *{transition:none!important}}

.tw3d-label{padding:5px 10px;border-radius:6px;background:var(--card);color:var(--txt);border:1px solid var(--line2);box-shadow:0 4px 12px var(--bg);text-shadow:none;font-size:11px}
.tw3d-label[data-level="bad"]{border-top:2px solid var(--red)}.tw3d-label[data-level="warn"]{border-top:2px solid var(--orange)}
.tw3d-label i{font-size:10px;color:var(--txt2)}
.tw-scene-caption{position:absolute;left:22px;top:68px;pointer-events:none;z-index:2;color:var(--txt)}.tw-scene-caption b{display:block;font-size:20px;letter-spacing:1px;font-weight:500}.tw-scene-caption span{display:block;font-size:11px;color:var(--txt2);margin-top:4px}
@media(max-width:600px){.tw-scene-caption{left:14px;top:100px}.tw-scene-caption b{font-size:17px}.tw-scene-caption span{font-size:10px;max-width:210px}.tw3d-label{font-size:10px;padding:3px 6px}.tw3d-label i{display:none}}
/* ---------- 中等屏：收回纯图标 ----------
   带文字的侧栏要 238px，1024/1180 这类屏上会明显挤压主内容区，
   所以这一档收回 78px 纯图标，并把悬停提示（.tip）打开补足可读性。 */
@media(max-width:1180px){
  .rail{width:78px;flex:0 0 78px;align-items:center;padding:16px 0 12px}
  .rail-h{padding:0 0 15px;justify-content:center}
  .rail-t{display:none}
  .rail-scroll{width:100%;align-items:center;gap:4px;padding:0 0 10px}
  .rail-g{display:none}
  /* 纯图标档放不下「父项 + 子项」两层：父项直接不显示，子项始终铺开（回到收进主菜单之前的
     样子，用 .g1 那条分隔线标出换了一个业务域）。 */
  .nv.menu-h{display:none}
  .sub-wrap{display:flex!important;margin:0;padding-left:0;border-left:0;gap:4px}
  .sub-wrap .sub-wrap{display:flex!important;margin:0;padding-left:0;border-left:0}
  .nv.sub{width:46px;height:44px;flex:0 0 44px;padding:0;justify-content:center;gap:0}
  .nv.sub svg{width:20px;height:20px;flex:0 0 20px}
  /* 纯图标档没有分组标题，用一条细分隔线标出「换了一个业务域」（.g1 是每组第一项，首组不加） */
  .nv.g1{margin-top:8px}
  .nv.g1::before{content:"";position:absolute;top:-5px;left:7px;right:7px;height:1px;background:var(--line)}
  .nv{width:46px;height:44px;flex:0 0 44px;padding:0;justify-content:center;gap:0}
  .nv-t{display:none}
  .nv svg{width:20px;height:20px;flex:0 0 20px}
  .nv .tip{display:block;position:absolute;left:60px;top:50%;transform:translateY(-50%) translateX(-6px);background:#2E2E38;color:#fff;font-size:12px;font-weight:500;padding:5px 10px;border-radius:8px;white-space:nowrap;opacity:0;pointer-events:none;transition:.25s var(--ease);z-index:60}
  .nv:hover .tip{opacity:1;transform:translateY(-50%)}
  .nv .badge{position:absolute;top:2px;right:2px;margin:0;min-width:16px;height:16px;font-size:9.5px;padding:0 4px;border:2px solid #111114}
}
/* ---------- 移动端 ---------- */
.mobbar{display:none}
/* 「更多」抽屉：手机上底栏只放 4 个主入口 + 更多，其余入口按分组收进这个底部抽屉 */
.mobmask{align-items:flex-end;padding:0}
.mobsheet{width:100%;max-height:78vh;overflow-y:auto;background:var(--bg2);border:1px solid var(--line2);border-bottom:none;border-radius:26px 26px 0 0;padding:20px 16px calc(22px + env(safe-area-inset-bottom));animation:up .3s var(--ease)}
.mobsheet-h{display:flex;align-items:baseline;gap:9px;padding:0 8px 8px}
.mobsheet-h b{font-size:17px;font-weight:720}
.mobsheet-h span{font-size:11.5px;color:var(--dim)}
.mobsheet-g{font-size:10.5px;color:var(--dim2);letter-spacing:1.1px;font-weight:650;padding:13px 8px 5px}
/* 嵌在主菜单里的子分组（台账管理）：小一档、缩进一格，表示它属于上面那个业务域 */
.mobsheet-g.sub{font-size:10px;padding:11px 8px 4px 24px;border-left:1px solid var(--line);margin-left:14px}
.mobrow{display:flex;align-items:center;gap:12px;width:100%;padding:11px 10px;border-radius:14px;text-align:left;color:var(--txt2);transition:.25s var(--ease)}
.mobrow:hover,.mobrow.on{background:var(--card)}
.mobrow>svg{width:19px;height:19px;flex:0 0 19px;color:var(--dim)}
.mobrow.on>svg{color:var(--lime)}
.mr-t{flex:1;min-width:0}
.mr-t b{display:block;font-size:13.5px;font-weight:600;color:var(--txt)}
.mr-t i{display:block;font-style:normal;font-size:11px;color:var(--dim);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.mr-go{color:var(--dim2);flex:0 0 auto}
.mr-go svg{width:14px;height:14px}
@media(max-width:860px){
  .login{grid-template-columns:1fr;padding:12px}
  .brand{padding:28px 24px;border-radius:24px;gap:20px}
  .b-desc{display:none}
  .loginbox{padding:26px 22px;border-radius:24px}
  .app{padding:0;height:100vh}
  .frame{border-radius:0;border:none}
  .rail{display:none}
  .main{width:100%}
  .top{height:60px;flex:0 0 60px;padding:0 14px;gap:8px}
  .search{display:none}
  .meav>span:not(.rolebadge){display:none}
  .view{padding:14px 13px 86px}
  .grid2{grid-template-columns:1fr}
  /* 窄屏降列：KPI 四列 → 两列，主次两栏 → 单栏 */
  .grid.g4,.grid.g3{grid-template-columns:1fr 1fr}
  .grid.g2,.grid.g-wide,.grid.g-report{grid-template-columns:1fr}
  .kpi{font-size:24px}
  .btn{font-size:13.5px}
  .mobbar{display:flex;position:fixed;left:0;right:0;bottom:0;height:62px;background:#111114;border-top:1px solid var(--line);z-index:120;padding-bottom:env(safe-area-inset-bottom)}
  .mobbar button{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;color:var(--dim);font-size:11px;position:relative}
  .mobbar button.on{color:var(--lime)}
  /* 选中项顶部一小段高亮，底栏只有 5 个入口，位置比颜色更容易扫到 */
  .mobbar button.on::before{content:"";position:absolute;top:0;left:50%;transform:translateX(-50%);width:24px;height:3px;border-radius:0 0 3px 3px;background:var(--lime)}
  .mobbar svg{width:20px;height:20px}
  .mobbar .badge{position:absolute;top:6px;right:50%;margin-right:-20px;min-width:15px;height:15px;border-radius:8px;background:var(--orange);color:#fff;font-size:9px;font-weight:700;display:grid;place-items:center;padding:0 4px}
  .rec{flex-wrap:wrap}
  .pg-h h2{font-size:20px}
  .sheet{padding:20px 17px;border-radius:20px}
  .hide-sm{display:none!important}
}
@media print{
  body{background:#fff}
  .app,.login,.toasts,.mask,.mobbar{display:none!important}
  #printwrap{display:block!important;position:static;background:#fff;padding:0;overflow:visible;border-radius:0}
  /* 报表模板的打印口径（契约 4.3）：A4 横向 —— 图表 + 宽表在纵向 A4 上会被压得看不清，
     与 xlsx 导出既有的「A4 横向 fitToWidth」一致。
     图表不许跨页断开；表头每页重复；表格本身允许跨页（长报表硬塞一页只会截断数据）。 */
  @page{size:A4 landscape;margin:10mm}
  #printwrap img{max-width:100%;max-height:42vh;break-inside:avoid;page-break-inside:avoid}
  /* 表头每页重复（契约 4.3 第 4 条）。加 !important 是因为这是**打印正确性**而不是审美：
     长报表翻到第 2 页只剩数字、没有列名，读的人就得回头对第 1 页，等于印废了。
     同一条规则万一被别处的 table 样式盖掉，代价比 !important 大得多。 */
  #printwrap thead{display:table-header-group!important}
  #printwrap table{break-inside:auto}
  #printwrap tr,#printwrap td,#printwrap th{page-break-inside:avoid}
  #printwrap table{table-layout:fixed;word-break:break-word}
}
/* ---------- 人力 · 工资表 ----------
   这张表有 18 列，按 .tb 默认的 11px 内边距在 1440 宽下会把「操作」列挤出可视区；
   只收窄这一张表的左右内边距，让一屏看全，窄屏仍由 .tbl-wrap 横向滚动兜底。 */
#hr-pay-tbl th,#hr-pay-tbl td{padding-left:7px;padding-right:7px}
/* ---------- 组织与账号（个人中心 / 部门管理 / 账号管理） ---------- */
.org-chips{display:flex;flex-wrap:wrap;gap:6px;margin-top:2px}
.org-chips button{padding:6px 12px;border-radius:999px;font-size:11.5px;background:var(--card2);border:1px solid var(--line);color:var(--dim);transition:.25s var(--ease)}
.org-chips button.on{background:rgba(203,247,78,.14);color:var(--lime);border-color:transparent;font-weight:650}
.acct-bar{display:flex;gap:9px;flex-wrap:wrap;align-items:center;margin-bottom:12px}
.card .tbl-wrap table.tb .sw{width:26px!important;height:16px!important}
.card .tbl-wrap table.tb .sw::after{width:11px;height:11px;top:2.5px;left:2.5px}
.card .tbl-wrap table.tb .sw.on::after{left:12px}
#pwbig{font-size:26px;font-weight:750;letter-spacing:2px;background:var(--card2);border:1px dashed var(--line2);border-radius:16px;padding:16px;text-align:center;user-select:all;word-break:break-all}
/* ---------- 角色管理 · 权限矩阵 ---------- */
/* 每张角色卡都渲染完整 8 行矩阵，高度相近：用 auto-fit 让 1440 下一行放下 3 张，窄屏自动降列 */
.role-cols{display:grid;grid-template-columns:repeat(auto-fit,minmax(330px,1fr));gap:14px;align-items:start}
.perm-matrix{border:1px solid var(--line);border-radius:var(--r-in);overflow:hidden}
.perm-g{font-size:10.5px;color:var(--dim2);letter-spacing:.6px;padding:7px 12px 4px;background:rgba(255,255,255,.022);border-top:1px solid var(--line)}
.perm-g:first-child{border-top:none}
/* 一行一个权限键：左侧 label，右侧 key 小灰字 + 开关 */
.perm-row{display:flex;align-items:center;gap:10px;padding:6px 12px;border-top:1px solid var(--line)}
.perm-row>b{flex:1;min-width:0;font-size:12.6px;font-weight:600;color:var(--txt)}
.perm-row>.perm-key{font-size:10.5px;color:var(--dim2);white-space:nowrap}
.perm-lock{font-size:10.5px;color:var(--orange);padding:0 12px 6px}
.perm-row .sw.lock{opacity:.45;cursor:not-allowed}
.perm-foot{display:flex;gap:8px;align-items:center;margin-top:12px;flex-wrap:wrap}
select.inp{appearance:none;background-image:linear-gradient(45deg,transparent 50%,var(--dim) 50%),linear-gradient(135deg,var(--dim) 50%,transparent 50%);background-position:calc(100% - 16px) 50%,calc(100% - 11px) 50%;background-size:5px 5px,5px 5px;background-repeat:no-repeat;padding-right:32px}
/* 手机端底栏只放 5 个入口（工作台/上报/查询/预警/更多），不再需要为塞下 11 个按钮压缩字号；
   这一档只留账号管理筛选栏的换行兜底。 */
@media(max-width:640px){
  .mobbar button{font-size:10.5px}
  .acct-bar{gap:7px}
  .acct-bar .inp{max-width:none!important;flex:1 1 calc(50% - 8px)}
  .acct-bar .filt{flex:1 1 100%}
}

.ui-state{padding:24px;text-align:center;color:var(--muted,#667085)}
.ui-state.error{color:var(--bad,#b42318)}
.ui-state.loading{min-height:80px;animation:uipulse 1.4s ease-in-out infinite}
@keyframes uipulse{50%{opacity:.5}}
@media(prefers-reduced-motion:reduce){.ui-state.loading{animation:none}}

.ui-sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}

/* 台账只作业务小标题，避免再展开一层；系统设置与业务域分隔。 */
.ledger-label{position:static;margin-top:10px;border-top:1px solid var(--line);padding-top:12px}
.nv[data-menu="g-system"]{margin-top:16px;border-top:1px solid var(--line);padding-top:12px}

/* ---------- 工作汇报 · 多选清单（public/workreport-ui.js 的 wrPick） ----------
   替代原生 <select multiple>：原生多选要按住 Ctrl 逐个点，点第二个会把第一个取消，
   触屏上更没有 Ctrl —— 用户看到的就是「选不上人」。这里给搜索 + 勾选 + 全选/清空 + 已选计数。 */
.wr-pick{border:1px solid var(--line);border-radius:var(--r-in);background:var(--card);padding:9px 10px}
.wr-pick-h{display:flex;align-items:center;gap:7px;margin-bottom:8px}
.wr-pick-h .inp{flex:1;padding:8px 11px;font-size:13px}
.wr-pick-l{max-height:190px;overflow:auto;display:grid;grid-template-columns:repeat(auto-fill,minmax(230px,1fr));gap:1px 8px}
.wr-pick-i{display:flex;align-items:center;gap:7px;min-width:0;padding:6px 7px;border-radius:9px;
  font-size:12.5px;color:var(--txt2);cursor:pointer;transition:.2s var(--ease)}
.wr-pick-i:hover{background:var(--card2)}
.wr-pick-i input{width:15px;height:15px;flex:0 0 auto;accent-color:var(--lime)}
.wr-pick-i input:checked+span{color:var(--txt);font-weight:650}
.wr-pick-t{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.wr-pick-b{font-size:11px;color:var(--dim2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.wr-pick-empty{font-size:12.5px;color:var(--dim2);padding:10px 4px;line-height:1.7}
.wr-pick-f{display:flex;gap:10px;flex-wrap:wrap;align-items:baseline;margin-top:7px;padding-top:7px;
  border-top:1px solid var(--line);font-size:11.5px;color:var(--dim)}
.wr-pick-note{color:var(--dim2)}
/* 工作汇报列表的操作列（详情 / 审核）：9 列在窄屏要横向滚动，
   不贴右的话「审核」会被挤出可视区 —— 那是这一页的主按钮。 */
.card .tbl-wrap table.tb td.wr-ops{position:sticky;right:0;background:var(--card);
  box-shadow:-10px 0 10px -10px rgba(0,0,0,.55);overflow:visible;text-overflow:clip}
.card .tbl-wrap table.tb tr:hover td.wr-ops{background:var(--card2)}

/* ---------- 工作汇报 · 模板与指派（2026-10 排版重做） ----------
   两处一起改：① 页头动作按钮原来一个个占满整行（本模块有 5 个，撑掉半屏）；
   ② 模板卡的「字段：4 个（…）」挤成一段小字，扫不动。 */
.wr-acts{display:flex;gap:8px;flex-wrap:wrap;justify-content:flex-end;align-items:center}
.wr-acts .btn{width:auto;margin-top:0}
.wr-tplgrid{display:grid;gap:14px;grid-template-columns:repeat(auto-fill,minmax(330px,1fr));align-items:start}
.wr-tplcard{display:flex;flex-direction:column;gap:11px;padding:16px 17px}
.wr-tplcard-h{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.wr-tplcard-h>b{font-size:15px;font-weight:700;letter-spacing:-.2px}
.wr-tplcard-h .sp{flex:1;min-width:10px}
.wr-tplcard-n{font-size:11.5px;color:var(--dim2);white-space:nowrap}
/* 七行「标签 + 值」：标签定宽对齐，值单行省略（鼠标悬停看全） */
.wr-meta{display:grid;gap:6px}
.wr-meta>div{display:flex;gap:9px;align-items:baseline;min-width:0;font-size:12.3px}
.wr-meta i{flex:0 0 66px;color:var(--dim2);font-style:normal}
.wr-meta b{flex:1;min-width:0;font-weight:600;color:var(--txt2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.wr-chips{display:flex;flex-wrap:wrap;gap:5px}
.wr-chip{display:inline-flex;align-items:center;gap:2px;padding:3px 9px;border-radius:999px;
  font-size:11px;color:var(--txt2);background:var(--card2);border:1px solid var(--line);white-space:nowrap}
.wr-chip i{color:var(--orange);font-style:normal;font-weight:700}
.wr-chip-req{color:var(--orange);border-color:rgba(255,122,61,.35);background:rgba(255,122,61,.10)}
.wr-chip-dim{color:var(--dim2)}
.wr-cardacts{display:flex;gap:7px;flex-wrap:wrap;align-items:center}
.wr-cardacts .btn{width:auto;margin:0}
.wr-cardacts .sp{flex:1}
.wr-note{font-size:11.5px;color:var(--dim2);line-height:1.7}
/* 「停用」是破坏性动作：默认低调，悬停才转成警示色，不再和主按钮抢视线 */
.wr-danger{color:var(--dim)}
.wr-danger:hover{color:#FF8A8A;border-color:rgba(255,90,90,.4)}

/* ---------- 工作汇报 · 模板设计器（新建 / 编辑模板弹层） ----------
   比默认弹层宽一档（760 → 940）：里面有 5 个多选清单 + 字段卡，窄了就一直换行。 */
.sheet.wr-tpl{width:min(940px,100%)}
/* 底部操作栏吸底：表单很长，不该滚到底才能按「保存模板」 */
.sheet.wr-tpl>.sh-f{position:sticky;bottom:-26px;z-index:4;margin-bottom:-26px;padding:12px 0 26px;
  border-top:1px solid var(--line);background:var(--bg2)}
.wr-form{display:block}
.wr-sec{margin-bottom:16px}
.wr-sec-h{display:flex;align-items:baseline;gap:9px;flex-wrap:wrap;margin:0 0 9px;font-size:13px;font-weight:700;color:var(--txt)}
.wr-sec-h>span{font-size:11.5px;font-weight:400;color:var(--dim2)}
.wr-sec-h .sp{flex:1}
.wr-sec-n{font-size:11.5px;color:var(--dim)}
.wr-sec-b{background:var(--card);border:1px solid var(--line);border-radius:16px;padding:14px 15px}
.wr-sec-b>.field:last-child{margin-bottom:0}
/* 弹层里的等宽分栏：auto-fit 让被隐藏的「截止日 / 截止星期」自动让位 */
.wr-grid3{display:grid;gap:11px;grid-template-columns:repeat(auto-fit,minmax(210px,1fr))}
/* 截止日 / 星期 / 时点都是短输入，别让它撑成一整行长条 */
.wr-cad{display:grid;gap:11px;margin-top:11px;grid-template-columns:repeat(auto-fit,minmax(190px,240px))}
.wr-2col{display:grid;gap:11px;grid-template-columns:1fr 1fr}
@media(max-width:780px){.wr-2col{grid-template-columns:1fr}}
/* 一个字段 = 一张小卡：抬头（序号/类型/必填/排序删除）+ 正文（4 个输入，选择类多一行选项） */
.wr-fgrid{display:grid;gap:11px;grid-template-columns:1.5fr 1.1fr 1fr .9fr}
@media(max-width:820px){.wr-fgrid{grid-template-columns:1fr 1fr}}
.wr-frow{border:1px solid var(--line);border-radius:14px;background:var(--card2);overflow:hidden}
.wr-frow+.wr-frow{margin-top:9px}
.wr-frow-h{display:flex;align-items:center;gap:8px;padding:8px 11px;border-bottom:1px solid var(--line);
  background:rgba(255,255,255,.022)}
.wr-frow-h .sp{flex:1}
.wr-frow-i{width:21px;height:21px;border-radius:7px;display:grid;place-items:center;flex:0 0 auto;
  font-size:11px;font-weight:700;background:var(--card3);color:var(--dim)}
.wr-frow-b{padding:12px}
.wr-frow-b .field:last-child{margin-bottom:0}
.wr-ib{width:27px;height:27px;border-radius:8px;display:grid;place-items:center;color:var(--dim);
  font-size:13px;line-height:1;transition:.2s var(--ease)}
.wr-ib:hover{background:var(--card3);color:var(--txt)}
.wr-ib:disabled{opacity:.28;cursor:not-allowed}
.wr-ib:disabled:hover{background:none;color:var(--dim)}
.wr-ib-del:hover{color:#FF8A8A;background:rgba(255,90,90,.10)}
.wr-fempty{font-size:12.5px;color:var(--dim2);padding:14px 12px;text-align:center;line-height:1.9}
.wr-fempty b{color:var(--txt2)}
.wr-addfield{width:100%;margin-top:10px;border:1px dashed var(--line2);background:transparent;
  color:var(--dim);padding:10px}
.wr-addfield:hover{color:var(--txt);border-color:rgba(203,247,78,.5);background:rgba(203,247,78,.05)}
/* 报送节奏的「填报人看到的口径」——一句话把三个输入的合成结果说清楚 */
.wr-preview{display:flex;align-items:center;gap:7px;flex-wrap:wrap;margin-top:10px;padding-top:10px;
  border-top:1px dashed var(--line);font-size:12px;color:var(--dim)}
.wr-preview b{color:var(--lime);font-weight:650}

/* =========================================================
 * 工作台 2.0（2026-10）
 *
 * 这一轮把工作台从「四张 KPI + 一张应报清单」升级成**大屏 + 功能区**：
 *   · .wb-hero —— 顶部大屏带（深色渐变 + 网格底纹 + 一道高光），左边是问候与当前范围，
 *     右边是一组 KPI 玻璃块。它的作用是「一眼看见全盘」，所以刻意和下面的卡片拉开层次，
 *     而不是再加四张长得一样的卡。
 *   · .wb-grid —— 主体两栏：左「待办中心 + 应报清单」，右「数字孪生 + 快捷入口 + 最近动态」。
 *   · .wb-scope-* —— 顶栏那个「全量 / 项目 / 小区」范围切换胶囊与浮层。
 * 全部类名都带 wb- 前缀，不改动既有任何一条规则，避免牵动别的页面。
 * ======================================================= */

/* ---- 顶栏：全局范围切换（全量 / 项目 / 小区） ---- */
.wb-scope{position:relative;flex:0 0 auto}
.wb-scope-chip{display:flex;align-items:center;gap:7px;height:38px;padding:0 11px;border-radius:13px;
  background:var(--card);border:1px solid var(--line);color:var(--txt2);font-size:12.5px;white-space:nowrap;
  cursor:pointer;transition:.3s var(--ease);max-width:230px}
.wb-scope-chip:hover{border-color:var(--line2);color:var(--txt)}
.wb-scope-chip.on{border-color:rgba(203,247,78,.42);background:rgba(203,247,78,.07)}
.wb-scope-chip .dot{width:6px;height:6px;border-radius:50%;background:var(--lime);box-shadow:0 0 8px var(--lime);flex:0 0 auto}
.wb-scope-chip .lvb{font-size:10.5px;color:var(--dim2);flex:0 0 auto}
.wb-scope-chip b{font-weight:650;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:140px}
.wb-scope-chip .arw{width:14px;height:14px;color:var(--dim);flex:0 0 auto;transition:.3s var(--ease)}
.wb-scope-chip.on .arw{transform:rotate(90deg)}
.wb-scope-pop{position:absolute;top:46px;left:0;width:312px;max-height:70vh;overflow:auto;
  background:var(--bg2);border:1px solid var(--line2);border-radius:18px;padding:8px;z-index:170;
  box-shadow:0 24px 70px rgba(0,0,0,.62);animation:fd .22s var(--ease)}
.wb-scope-g{font-size:11px;color:var(--dim);padding:10px 12px 5px;font-weight:650;letter-spacing:.2px}
.wb-scope-it{display:flex;align-items:center;gap:9px;width:100%;text-align:left;padding:9px 11px;
  border-radius:12px;background:none;border:0;color:var(--txt2);font-size:12.8px;cursor:pointer;transition:.2s var(--ease)}
.wb-scope-it:hover{background:var(--card2);color:var(--txt)}
.wb-scope-it.on{background:rgba(203,247,78,.11);color:var(--lime)}
.wb-scope-it .sub{margin-left:auto;font-size:11px;color:var(--dim2);white-space:nowrap}
.wb-scope-it .tick{margin-left:auto;color:var(--lime)}
.wb-scope-note{font-size:11px;color:var(--dim2);padding:11px 12px 6px;line-height:1.75;
  border-top:1px dashed var(--line);margin-top:6px}
.wb-scope-note b{color:var(--txt2)}

/* ---- 大屏带 ---- */
.wb{display:block}
.wb-hero{position:relative;overflow:hidden;border-radius:var(--r-card);border:1px solid var(--line2);
  padding:20px 22px;display:flex;gap:20px;align-items:center;flex-wrap:wrap;
  background:
    radial-gradient(1100px 300px at 8% -40%,rgba(203,247,78,.16),transparent 62%),
    radial-gradient(900px 320px at 94% 140%,rgba(51,85,255,.24),transparent 64%),
    linear-gradient(135deg,#15151B 0%,#0F1013 48%,#101218 100%)}
.wb-hero::before{content:'';position:absolute;inset:0;pointer-events:none;opacity:.55;
  background-image:linear-gradient(rgba(255,255,255,.05) 1px,transparent 1px),
    linear-gradient(90deg,rgba(255,255,255,.05) 1px,transparent 1px);
  background-size:38px 38px;
  -webkit-mask-image:radial-gradient(620px 210px at 18% 0%,#000,transparent 80%);
  mask-image:radial-gradient(620px 210px at 18% 0%,#000,transparent 80%)}
.wb-hero::after{content:'';position:absolute;left:22px;right:22px;top:0;height:1px;
  background:linear-gradient(90deg,transparent,rgba(203,247,78,.5),transparent)}
.wb-hero-l{position:relative;flex:1 1 300px;min-width:0}
.wb-hero-l h2{font-size:22px;font-weight:740;letter-spacing:-.6px;display:flex;align-items:center;gap:9px;flex-wrap:wrap}
.wb-hero-l .sub{color:var(--dim);font-size:12.6px;margin-top:7px;line-height:1.75}
.wb-hero-tag{display:inline-flex;align-items:center;gap:6px;font-size:11.5px;color:var(--lime);
  background:rgba(203,247,78,.10);border:1px solid rgba(203,247,78,.28);border-radius:999px;padding:3px 10px;font-weight:600}
.wb-kpis{position:relative;display:flex;gap:10px;flex-wrap:wrap}
.wb-kpi{min-width:104px;padding:11px 13px;border-radius:16px;background:rgba(255,255,255,.035);
  border:1px solid var(--line);-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}
.wb-kpi span{display:block;font-size:11px;color:var(--dim);margin-bottom:5px;white-space:nowrap}
.wb-kpi b{font-size:23px;font-weight:740;letter-spacing:-1px;display:flex;align-items:baseline;gap:4px}
.wb-kpi b small{font-size:11.5px;font-weight:600;color:var(--dim);letter-spacing:0}
.wb-kpi.hot b{color:var(--orange)}
.wb-kpi.ok b{color:var(--lime)}
.wb-kpi.dim b{color:var(--dim)}

/* ---- 主体两栏 ---- */
.wb-grid{display:grid;grid-template-columns:minmax(0,1fr) 392px;gap:14px;margin-top:14px;align-items:start}
.wb-col{min-width:0}
.wb-card{background:var(--card);border:1px solid var(--line);border-radius:var(--r-card);padding:16px}

/* ---- 待办中心 ---- */
.wb-todo-h{display:flex;align-items:center;gap:9px;font-size:13px;font-weight:700;color:var(--txt2);margin-bottom:11px}
.wb-todo-h .sp{flex:1}
.wb-todo-h .hint{font-size:11px;color:var(--dim2);font-weight:400}
.wb-todo-tabs{display:flex;gap:6px;flex-wrap:wrap;margin-bottom:10px}
.wb-todo-tabs button{display:inline-flex;align-items:center;gap:6px;padding:6px 11px;border-radius:999px;
  background:var(--card2);border:1px solid transparent;color:var(--dim);font-size:12px;cursor:pointer;
  transition:.25s var(--ease)}
.wb-todo-tabs button:hover{color:var(--txt2)}
.wb-todo-tabs button.on{background:rgba(203,247,78,.12);border-color:rgba(203,247,78,.35);color:var(--lime)}
.wb-todo-tabs button i{font-style:normal;font-size:11px;opacity:.85}
.wb-todo-body{min-height:60px}
.wb-row{display:flex;align-items:center;gap:11px;padding:11px 8px;border-bottom:1px solid var(--line);
  cursor:pointer;transition:.25s var(--ease);border-radius:10px}
.wb-row:last-child{border-bottom:0}
.wb-row:hover{background:var(--card2)}
.wb-row.od{background:linear-gradient(90deg,rgba(255,90,90,.09),transparent 62%)}
.wb-row-bar{width:3px;align-self:stretch;min-height:30px;border-radius:3px;background:var(--line2);flex:0 0 auto}
.wb-row.od .wb-row-bar{background:var(--red)}
.wb-row-main{flex:1;min-width:0}
.wb-row-t{font-size:13px;font-weight:620;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.wb-row-s{font-size:11.4px;color:var(--dim);margin-top:3px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.wb-row-act{flex:0 0 auto;display:flex;align-items:center;gap:7px}
.wb-src{font-size:10.5px;padding:3px 8px;border-radius:999px;background:var(--card3);color:var(--txt2);
  border:1px solid var(--line);white-space:nowrap}
.wb-src.od{color:#FFB4B4;border-color:rgba(255,90,90,.35);background:rgba(255,90,90,.10)}
.wb-src.grey{color:var(--dim2)}
.wb-empty{text-align:center;padding:30px 16px;color:var(--dim);font-size:12.6px;line-height:1.95}
.wb-empty b{color:var(--txt2)}
.wb-more{display:block;width:100%;margin-top:9px;padding:9px;border-radius:12px;background:var(--card2);
  border:1px dashed var(--line2);color:var(--dim);font-size:12px;cursor:pointer;transition:.25s var(--ease)}
.wb-more:hover{color:var(--lime);border-color:rgba(203,247,78,.4)}
.wb-foot{font-size:11px;color:var(--dim2);margin-top:10px;line-height:1.8}

/* ---- 内嵌数字孪生 ---- */
.wb-twin-host{position:relative;border-radius:16px;overflow:hidden;background:#0B0C0F;
  border:1px solid var(--line);margin:2px 0 10px}
.wb-twin-host canvas{display:block;width:100%}
.wb-twin-bar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;font-size:11.6px;color:var(--dim)}
.wb-twin-bar b{color:var(--txt2)}
.wb-twin-bar .sp{flex:1}

/* ---- 快捷入口 / 最近动态 ---- */
.wb-quick{display:grid;grid-template-columns:1fr 1fr;gap:8px}
.wb-quick button{display:flex;align-items:center;gap:9px;padding:11px;border-radius:14px;background:var(--card2);
  border:1px solid var(--line);color:var(--txt2);font-size:12.4px;text-align:left;cursor:pointer;
  transition:.25s var(--ease)}
.wb-quick button:hover{border-color:var(--line2);color:var(--txt)}
.wb-quick button svg{width:16px;height:16px;color:var(--lime);flex:0 0 auto}
.wb-feed-row{display:flex;gap:9px;align-items:baseline;padding:9px 0;border-bottom:1px dashed var(--line);
  font-size:12.4px;color:var(--txt2)}
.wb-feed-row:last-child{border-bottom:0}
.wb-feed-row time{margin-left:auto;color:var(--dim2);font-size:11px;white-space:nowrap}
.wb-feed-row .dot{width:5px;height:5px;border-radius:50%;background:var(--line2);flex:0 0 auto;align-self:center}
.wb-feed-row .dot.od{background:var(--orange)}

@media(max-width:1180px){
  .wb-grid{grid-template-columns:minmax(0,1fr)}
  .wb-kpis{width:100%}
  .wb-kpi{flex:1 1 96px}
}
@media(max-width:600px){
  .wb-hero{padding:16px;gap:14px}
  .wb-scope-chip{max-width:150px;height:34px;padding:0 9px}
  .wb-scope-chip .lvb{display:none}
  .wb-scope-chip b{max-width:96px}
  .wb-scope-pop{position:fixed;left:10px;right:10px;top:64px;width:auto;max-height:74vh}
  .wb-kpi{min-width:88px;padding:9px 11px}
  .wb-kpi b{font-size:20px}
  .wb-quick{grid-template-columns:1fr}
  .top .hi small{display:none}
}
@media(prefers-reduced-motion:reduce){
  .wb-scope-pop{animation:none}
  .wb *{transition:none!important}
}
