/* 脚本下发管理后台 · 全站样式（浅色主题，无动画特效） */
:root{
  --pri:#2563eb;--pri-d:#1d4ed8;--pri-l:#eef4ff;
  --bg:#f2f4f7;--card:#fff;--bd:#e5e9f0;--bd2:#eef1f6;
  --tx:#1f2733;--tx2:#5b6675;--tx3:#98a2b3;
  --side:#1b2434;--side-h:#26314a;--side-tx:#c3cbd9;--side-tx2:#8b96a8;
  --ok:#16a34a;--bad:#dc2626;--warn:#d97706;
  /* 侧栏宽度：登录页为 0，登录后由 body.has-side 置为实际值；
     弹窗与轻提示一律按「右侧内容区」居中，而不是整个视口。
     注意：算式必须内联写到使用处 —— 自定义属性里的 var() 在定义元素(:root)上就完成求值，
     若包成 --main-cx 再继承，body 上的 --side-w 覆盖不会生效（实测踩坑） */
  --side-w:0px;
}
body.has-side{--side-w:200px}
*{box-sizing:border-box;margin:0;padding:0}
body{font-family:-apple-system,"Segoe UI","Microsoft YaHei",sans-serif;background:var(--bg);color:var(--tx);font-size:14px;-webkit-font-smoothing:antialiased}
/* 左侧固定菜单 + 右侧内容区（vue_admin 式框架布局） */
#side{position:fixed;left:0;top:0;bottom:0;width:200px;background:var(--side);overflow:auto;z-index:10;display:flex;flex-direction:column}
#side .brand{display:flex;align-items:center;gap:10px;padding:16px 16px;border-bottom:1px solid rgba(255,255,255,.07)}
#side .brand .logo{width:32px;height:32px;border-radius:8px;background:linear-gradient(135deg,#3b82f6,#2563eb);color:#fff;display:flex;align-items:center;justify-content:center;font-size:13px;font-weight:700;letter-spacing:.5px;flex:0 0 auto}
#side .brand .bt{min-width:0}
#side .brand .bt b{display:block;font-size:14px;font-weight:600;color:#fff;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
#side .brand .bt i{display:block;font-size:11px;color:var(--side-tx2);font-style:normal;margin-top:2px}
#nav{flex:1;padding:10px 10px 20px}
nav a,nav .ghead{display:flex;align-items:center;padding:9px 12px;margin-bottom:2px;border-radius:6px;color:var(--side-tx);text-decoration:none;cursor:pointer;font-size:13.5px}
nav a:hover,nav .ghead:hover{background:rgba(255,255,255,.06);color:#fff}
nav a.on{background:var(--pri);color:#fff;font-weight:600}
/* 父菜单 + 子菜单（默认收起，规格与单项菜单一致，无箭头）
   高亮块只在父菜单显示，子项选中态用白字加粗 */
nav .ghead{user-select:none}
nav .navgroup.active>.ghead{background:var(--pri);color:#fff;font-weight:600}
nav .sub{margin:0;padding:0}
nav .sub a{padding:8px 12px 8px 26px;font-size:13px;color:var(--side-tx2)}
nav .sub a::before{content:'';display:inline-block;width:4px;height:4px;border-radius:50%;background:currentColor;opacity:.45;margin-right:9px;vertical-align:2px}
nav .sub a:hover{color:#fff}
nav .sub a.on{background:none;color:#fff;font-weight:600}
nav .sub a.on::before{opacity:.9}
nav .closed .sub{display:none}
#main{margin-left:200px;min-height:100vh;display:flex;flex-direction:column}
#main header{position:sticky;top:0;background:#fff;border-bottom:1px solid var(--bd);height:52px;padding:0 24px;display:flex;align-items:center;gap:10px;z-index:9}
#crumb{font-size:15px;font-weight:600;color:var(--tx)}
/* 标题旁的「刷新当前页」（2026-10-31）：与「改密 / 退出」同款小按钮，只放图标不占字 */
#pgRefresh{display:inline-flex;align-items:center;justify-content:center;padding:4px 6px;margin-left:-4px}
#pgRefresh svg{width:14px;height:14px;display:block;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
#user{margin-left:auto;color:var(--tx2);font-size:13px}
main{width:100%;margin:20px auto;padding:0 24px}
/* 右侧浏览器式多标签（2026-10-31）：一个菜单一个标签，设备详情每台一个；
   标签条钉在 header 下面（header 是 sticky 52px），横向多了就左右滚，不换行 */
.tabbar{position:sticky;top:52px;z-index:8;display:flex;align-items:flex-end;gap:4px;
  padding:8px 24px 0;background:#fff;border-bottom:1px solid var(--bd);overflow-x:auto;
  scrollbar-width:thin}
.tabbar::-webkit-scrollbar{height:4px}
.tabbar::-webkit-scrollbar-thumb{background:var(--bd);border-radius:4px}
.tabitem{display:flex;align-items:center;gap:6px;max-width:220px;flex:0 0 auto;
  padding:7px 8px 7px 14px;border:1px solid var(--bd);border-bottom:none;
  border-radius:8px 8px 0 0;background:var(--bg);color:var(--tx2);font-size:13px;
  cursor:pointer;white-space:nowrap}
.tabitem:hover{color:var(--tx)}
/* 当前标签：白底 + 顶边高亮，底边与内容区连成一片（像浏览器那样「抬到最前」） */
.tabitem.on{background:#fff;color:var(--tx);font-weight:600;box-shadow:inset 0 2px 0 var(--pri)}
.tabitem .tt{overflow:hidden;text-overflow:ellipsis}
.tabitem .tabx{flex:0 0 auto;border:none;background:transparent;color:var(--tx3);cursor:pointer;
  font-size:15px;line-height:1;padding:0 3px;border-radius:4px}
.tabitem .tabx:hover{color:var(--bad);background:var(--bd2)}
@media(max-width:900px){
  body.has-side{--side-w:150px}
  #side{width:150px}
  #main{margin-left:150px}
  #side .brand{padding:12px}
  #side .brand .bt i{display:none}
  nav a,nav .ghead,nav .sub a{padding:8px 10px;font-size:13px}
  #main header{padding:0 12px}
  main{padding:0 12px}
  .tabbar{padding:6px 12px 0}
  .tabitem{max-width:150px;padding:6px 6px 6px 10px;font-size:12.5px}
}
.card{background:var(--card);border:1px solid var(--bd);border-radius:10px;padding:18px 18px 14px;margin-bottom:16px;box-shadow:0 1px 2px rgba(16,24,40,.04)}
/* ⭐ `.sec-head` = 「不套外框的分区标题」：形态（左侧竖条）与 `.card>strong` 共用这一份
   —— 抄两份的话，改一处另一处不动，同一个页面会出现两种小标题。 */
.card>strong,.sec-head{display:inline-block;position:relative;padding-left:11px;font-size:15px;font-weight:600;color:var(--tx)}
.card>strong::before,.sec-head::before{content:'';position:absolute;left:0;top:50%;transform:translateY(-50%);width:3px;height:15px;border-radius:2px;background:var(--pri)}
.sec-head{display:block;margin:0 0 10px}
.card .hint{color:var(--tx3);font-size:12px;margin-left:10px;line-height:1.7}
/* ---------- 表格：横向滚动 + 列宽自适应 + 单列限宽（2026-10-12 用户口径） ----------
   用户原话：「所有页面中的表格要有左右滑动条，列名以及行值应该要自适应，可限制最大宽尺寸，
   避免浏览器窗口宽尺寸小的时候表格数据会挤占」。
   ⚠ 下面几条是**互相依赖**的，少一条就退化成「数据被挤成一个字一行」或「根本不出滚动条」：
     ① .tbl 外层承担滚动（表格自己不能滚：`table{display:block;overflow:auto}` 那个老偏方
        会让匿名表格盒退化成 100% 宽、列照样被压，实测无效）
     ② .tbl>table 用 max-content 按内容撑开 + min-width:100% 让宽屏仍然铺满卡片。
        ⚠ 少了 max-content，td 的 max-width 会被**完全忽略**（auto 布局下 td 的 max-width 无效）：
          实测内容 663px 的格子被压成 251px、内容被裁掉却不出滚动条 —— 这正是用户截图的现象
     ③ th,td 不换行 —— 原来的 word-break:break-all 才是「访问时间」竖着排、
        「iOS 15」被逐字拆成 i/O/S/1/5 的元凶
   限宽 360px：在「需要滚动」的窄窗口里把长 URL / 长 JSON 压到可读宽度（超了出省略号）；
   宽屏下多余空间仍会摊给各列，所以它不会把宽屏的表格钉死。 */
.tbl{overflow-x:auto;overflow-y:hidden;max-width:100%;-webkit-overflow-scrolling:touch}
.tbl>table{width:max-content;min-width:100%}
table{width:100%;border-collapse:collapse;margin-top:12px}
th,td{text-align:left;padding:10px 12px;border-bottom:1px solid var(--bd2);vertical-align:top;
  white-space:nowrap;word-break:normal;max-width:360px;overflow:hidden;text-overflow:ellipsis}
th{color:var(--tx2);font-weight:600;font-size:12px;background:#f8fafc;border-bottom:1px solid var(--bd);letter-spacing:.2px}
tbody tr:hover{background:#fafbfd}
tbody tr:last-child td{border-bottom:none}
/* ---------- 操作列固定：钉在最后一列，横向滚动时不跟着动（2026-10-26 用户口径）----------
   用户原话：「系统里所有表格，操作列改成固定列表，固定在最后一列，不随左右滑块移动」。
   ⭐ 只认「表上标了 actfix」的表的**最后一格**（表头最后一个 th、每行最后一个 td）：
     二十几张表逐个给 th/td 写 class 必漏一处，漏的那张就是「有的表固定、有的不固定」。
     所以加表只需在 <table> 上加 class="actfix"，操作列保持在最后一列即可。
   ⚠ 三条依赖，少一条就退化成「看着固定、滚起来穿帮」：
     ① 背景必须**不透明** —— 操作列是压在别的列上的，透明会两层字叠在一起；
        整行 hover 时那一格要单独再写一条，否则划过时它跟其它格子不是一个底色。
     ② `border-collapse:collapse`（上面 table 的全局设定）下，固定单元格的 border **不跟着走**
        （边框属于表格网格，不随单元格位移）→ 左分隔线与底部横线改用 box-shadow 画。
     ③ `:not([colspan])` 排除空态行与展开行：整行只有一格时固定它没有意义，还会凭空多一条竖线。 */
table.actfix>thead>tr>th:last-child,
table.actfix>tbody>tr>td:last-child:not([colspan]){
  position:sticky;right:0;z-index:2;background:var(--card);
  /* 左分隔线 + 左侧淡投影（让人看出它是压在内容上的）+ 底部横线（代替 border-bottom） */
  box-shadow:-1px 0 0 var(--bd2),-8px 0 10px -8px rgba(16,24,40,.22),0 1px 0 var(--bd2)}
/* 表头那格：底色与上面 th 同色，底部横线用深一档的 --bd（与别的表头对齐） */
table.actfix>thead>tr>th:last-child{z-index:3;background:#f8fafc;
  box-shadow:-1px 0 0 var(--bd2),-8px 0 10px -8px rgba(16,24,40,.22),0 1px 0 var(--bd)}
table.actfix>tbody>tr:hover>td:last-child:not([colspan]){background:#fafbfd}
/* 最后一行不画底部横线（与上面 `tbody tr:last-child td` 一致） */
table.actfix>tbody>tr:last-child>td:last-child:not([colspan]){
  box-shadow:-1px 0 0 var(--bd2),-8px 0 10px -8px rgba(16,24,40,.22)}
/* ---------- 勾选列（2026-10-29 用户口径：所有能删的表格第一列加勾选框）----------
   ⭐ 整站只有这一处样式：表头格与行内格都是 .chkcol（JS 那边 chkTh/chkTd 统一产出），
     二十几张表逐个写内联 style 必漏一处，漏的那张就是「单独一列宽得不一样」。
   ⚠ 必须关掉全局那条 max-width:360px + overflow:hidden：勾选框在窄列里会被裁掉右半边
     （而剩下的左半边看起来还是个框，点得到 → 极难发现）。 */
th.chkcol,td.chkcol{width:38px;min-width:38px;max-width:38px;padding:10px 0 10px 12px;
  text-align:center;vertical-align:middle;overflow:visible;white-space:nowrap}
th.chkcol>input,td.chkcol>input{width:15px;height:15px;margin:0;padding:0;cursor:pointer;vertical-align:middle}
/* 操作列固定（actfix）时勾选列也跟着钉在最左：横向滚动时「哪几行勾着」不该跟着滚走。
   ⚠ z-index 要低于最后一列（3/2），否则两边压在一起时勾选框会盖住操作按钮。 */
table.actfix>thead>tr>th.chkcol:first-child{position:sticky;left:0;z-index:3;background:#f8fafc;
  box-shadow:1px 0 0 var(--bd2),8px 0 10px -8px rgba(16,24,40,.22),0 1px 0 var(--bd)}
table.actfix>tbody>tr>td.chkcol:first-child{position:sticky;left:0;z-index:2;background:var(--card);
  box-shadow:1px 0 0 var(--bd2),8px 0 10px -8px rgba(16,24,40,.22),0 1px 0 var(--bd2)}
table.actfix>tbody>tr:hover>td.chkcol:first-child{background:#fafbfd}
table.actfix>tbody>tr:last-child>td.chkcol:first-child{
  box-shadow:1px 0 0 var(--bd2),8px 0 10px -8px rgba(16,24,40,.22)}
/* ---------- 操作列宽度 = 内容宽（2026-10-30 用户口径）----------
   用户原话：「所有表格操作固定列，并没有自适应宽，被超管移除的按钮权限还占位空白。」
   ⭐ 两种「不自适应」都要治：
     ① 表头上写死 width:220/260px —— 那是按「按钮最胖那一版」量出来的尺寸，超管收掉几个权限后
        按钮变少、那格宽度不走，右边留一整片空白（看着像按钮还在、只是空了、点不动）；
     ② 完全不设宽度 —— 表格是 min-width:100%，容器比内容宽时，多余空间会被这最后一列吃掉。
   `width:1px` 是表格里的「尽量窄」写法：会收缩到刚好放下**最宽那一行**的按钮组，
   剩下的空间还给左边的列。所以权限一收，列立刻跟着变窄，不留空。
   ⚠ 别配 max-width:none —— 全局 th,td 那条 360px 上限是防「一整段文本塞进格子」，
     操作列正常按钮组到不了 360px，留着能兜住极端情况。 */
th.actth{width:1px}
/* 可点的数字（报表里「归集总额 / 下级分账」这类）：虚线底 + 手型，
   与正文数字区分开 —— 不加这个就只能靠猜哪一列能点。 */
.numlink{cursor:pointer;border-bottom:1px dashed currentColor}
.numlink:hover{color:var(--pri)}
input,select,textarea,button{font:inherit;padding:7px 11px;border:1px solid #d5dbe4;border-radius:6px;background:#fff;color:var(--tx);outline:none;transition:border-color .15s,box-shadow .15s,background-color .15s}
input:focus,select:focus,textarea:focus{border-color:var(--pri);box-shadow:0 0 0 3px rgba(37,99,235,.12)}
input::placeholder,textarea::placeholder{color:#b3bcc9}
textarea{line-height:1.6;resize:vertical}
button{cursor:pointer;background:var(--pri);color:#fff;border-color:var(--pri);font-weight:500}
button:hover{background:var(--pri-d);border-color:var(--pri-d)}
button:active{background:#1a45c4}
button.ghost{background:#fff;color:var(--tx2);border:1px solid #d5dbe4}
button.ghost:hover{background:#f7f9fc;color:var(--tx);border-color:#c3ccd9}
button.mini{padding:3px 9px;font-size:12px;border-radius:5px}
/* 分页条里的每页条数下拉：与 button.mini 同尺寸同灰（默认 select 的 7px 内边距比按钮大一圈） */
select.mini{padding:2px 16px 2px 7px;font-size:12px;border-radius:5px;color:var(--tx2);width:auto;background:#fff}
button:disabled{opacity:.45;cursor:not-allowed}
/* 长文本单元格（钱包地址 / 交易哈希）：放不下就截成「头…尾」+ 一个下箭头，点箭头展开全文。
   ⚠ 上面 th,td 是 `nowrap + overflow:hidden` → 长地址会被**直接裁掉**（就是「地址显示不全」），
     而只给 td 加 word-break:break-all 又会被 nowrap 吃掉、根本不换行。所以由单元格自己截断，
     展开时才放开 white-space（切换见 js/wallets.js 的 wtCellToggle）。 */
.lc{font-family:ui-monospace,Consolas,Menlo,monospace}
button.lc-b{padding:0 3px;margin-left:3px;border:none;background:none;color:var(--tx3);
  font-size:12px;line-height:1;font-weight:400;vertical-align:middle;border-radius:3px}
button.lc-b:hover{background:#eef2f7;color:var(--tx);border:none}
/* 地址单元格的第二行：同一地址的另一种写法（Ton 的 EQ 可弹回 / UQ 不可弹回）。
   小一号、淡一点，同样能展开与复制。 */
.addr-alt{margin-top:2px;font-size:11px;color:var(--tx3)}
.row{display:flex;gap:10px;flex-wrap:wrap;align-items:flex-end}
.fld{display:flex;flex-direction:column;gap:5px}
/* 域名设置项：控件那一行横排（子域名 · 根域名下拉 · 刷新 并排）。
   2026-10-05 用户口径：「子域名填写框应该和下拉框并行比较好看」。
   外层 .fld 仍是竖排（label / 控件行 / hint 分三行），只有中间这行横排。
   窄屏（≤700px）自动换行，避免输入框被挤成一条缝。 */
.fldrow{display:flex;flex-wrap:wrap;gap:8px;align-items:center}
.fldsep{color:var(--tx3);font-size:14px;line-height:1;flex:0 0 auto}
@media (max-width:700px){
  .fldrow>input,.fldrow>select{flex:1 1 100%!important;width:auto!important;min-width:0}
  .fldsep{display:none}
}
label{font-size:12px;color:var(--tx2)}
.muted{color:var(--tx3);font-size:12px}
/* 命中白名单（2026-11-04 用户口径）：设备列表「已安装项目」列红色字体 */
.red{color:#d93025}
.dot{display:inline-block;width:8px;height:8px;border-radius:50%;margin-right:6px}
.don{background:var(--ok);box-shadow:0 0 0 3px rgba(22,163,74,.14)}
.doff{background:#cbd3dd}
img.shot{max-width:320px;border:1px solid var(--bd);border-radius:8px;margin-top:10px;display:block}
.hide{display:none}
/* 轻提示：右侧内容区顶部居中 */
#msg{position:fixed;top:16px;left:calc(var(--side-w) + (100% - var(--side-w))/2);transform:translateX(-50%);max-width:calc(100% - var(--side-w) - 40px);background:#1f2733;color:#fff;padding:10px 18px;border-radius:8px;font-size:13px;display:none;z-index:120;box-shadow:0 6px 20px rgba(16,24,40,.18)}
/* ⭐⭐⭐ 层序（2026-10-27 修）：通用对话框（#dlg / #mask）必须压在**所有**专用弹窗之上
   （#wl* / #sw* / #ws* 是 102 / 103）。它们全是**从专用弹窗里弹出来的**：
   归集弹窗里的「确认归集」、钱包编辑里的删除确认、密钥库里的删除确认 ——
   压在下面就等于**那道确认根本看不见也点不到**，而代码里一切正常（按钮调了、Promise 也等着）。
   分层的两个理由：
     · #dlg 111 / #mask 110 —— 二次确认是钱出去前的最后一道闸，必须在最上层；
     · #stBox 113 / #stMask 112 —— 「正在执行」压过确认框，否则执行中还能再点一次；
     · #msg 120 —— 轻提示永远最上（它是「刚才那一下成没成」的唯一回执）。 */
#mask{position:fixed;inset:0;background:rgba(16,24,40,.42);display:none;z-index:110}
/* 对话框：右侧内容区垂直+水平居中 */
#dlg{position:fixed;top:50%;left:calc(var(--side-w) + (100% - var(--side-w))/2);transform:translate(-50%,-50%);background:#fff;border:1px solid var(--bd);border-radius:12px;padding:22px;width:380px;max-width:calc(100% - var(--side-w) - 40px);display:none;z-index:111;box-shadow:0 12px 36px rgba(16,24,40,.18)}

/* 多字段表单：字段多到一屏装不下时（opt.cols>1，八条链的归集地址）排成多列 ——
   高度直接砍一半，比「把格式提示藏起来」稳妥：藏了就没人看得到那条链的地址长什么样。
   ⚠ 列数由 JS 写进 --cols；这里只声明「有 --cols 就按它分列」，不在 CSS 里猜列数。

   ⭐⭐ 1120px 是**按最长的地址量出来的**，不是拍脑袋定的（2026-10-27 用户口径
      「弹出框宽度加大到能容纳最长地址」）。线上 Chrome 实测（1440 视口 / 14px 系统字体，
      含输入框自己的内边距与描边）：
       比特币 Taproot 地址 bc1p… 62 位 → 503px（八条链里最长，就是它把宽度顶起来的）
       Solana 44 位 → 433px · Ton 48 位 → 412px · EVM 42 位 → 380px · 波场 34 位 → 335px
     两列时每列 = (1120 - 44 内边距 - 14 间距) / 2 = 531 → 输入框 528px，比最长的那个多 25px
     （余量不能抹平：抹平了换台机器 / 换个字体就重新变回横向滚动，而那种时候本地测不出来）。
     ⚠ 别退回 660px：那时每列只有 298px，**连最短的波场地址都塞不下**，
        只能横向拖着看 —— 抄地址时拖着看，漏一位看不出来。 */
#dlg.dlg-wide{width:1120px}
.fldgrid{display:grid;grid-template-columns:repeat(var(--cols,1),minmax(0,1fr));gap:10px 14px;align-items:start}
/* 整句说明 / 校验错误**跨满整行**：它们不是字段，占了列就会把第一个字段挤到第二列，
   于是第一行看着只有一格，而那句说明自己被压成半宽（更难读）。 */
.fldgrid>#dlgNote,.fldgrid>#dlgErr{grid-column:1/-1}
/* 兜底：字段再多也不能顶出屏幕（弹窗整体仍居中，滚动只发生在字段区） */
#dlgForm{max-height:56vh;overflow:auto}
/* 「一键填充」按钮组（2026-10-27 大额阈值）：贴在它那一格的输入框下面，
   跟着输入框换行 —— 写成一行固定宽的话，窄列里会把按钮挤出格子外。 */
.dlgfill{display:flex;flex-wrap:wrap;gap:6px;margin-top:6px}
/* ⭐⭐ 两列的**前提**是每列还放得下最长地址：每列 505px（输入框 503 + 两侧描边 2）
     + 弹窗两侧内边距 44 + 列间距 14 + 侧栏 200 + 弹窗两侧留白 40 ≈ 视口 1310。
     再往下每列就不到 503px，排两列等于在最长的那格里横向滚动 —— 所以退回**单列**，
     单列时给弹窗腾到最大可用宽（#dlg 的 max-width 已经在顶着视口算了），格宽随之翻倍。
   ⚠ 这里**不许**再写 `#dlg.dlg-wide{width:380px}`：单列 + 380px 会把地址框压回一条缝，
     正是这次要修的那个毛病（以前这条就写在断点里）。 */
@media (max-width:1320px){
  .fldgrid{grid-template-columns:1fr}
}

/* 状态提示弹窗（创建中 / 完成）：比对话框更窄、无按钮、状态切换后自动消失。
   层序：mask 112 / box 113 —— 压过通用对话框（110/111）与专用弹窗（102/103）：
   它是「这一步正在跑，别再点」的唯一提示，被挡住就会出现连点两次保存。两者不会同时出现。 */
#stMask{position:fixed;inset:0;background:rgba(16,24,40,.42);display:none;z-index:112}
#stBox{position:fixed;top:50%;left:calc(var(--side-w) + (100% - var(--side-w))/2);transform:translate(-50%,-50%);background:#fff;border:1px solid var(--bd);border-radius:12px;padding:26px 30px;min-width:190px;max-width:calc(100% - var(--side-w) - 40px);display:none;z-index:113;box-shadow:0 12px 36px rgba(16,24,40,.18);text-align:center}
#stBox .st-ico{width:38px;height:38px;margin:0 auto 12px;display:flex;align-items:center;justify-content:center}
#stBox .st-ico svg{width:38px;height:38px;display:block}
#stBox .st-tx{font-size:14px;color:var(--tx);font-weight:600;line-height:1.5;word-break:break-all;white-space:pre-wrap}
/* 转圈：只转外圈，纯线性动画（不加发光/描边特效） */
.spin{animation:stspin .8s linear infinite;transform-origin:50% 50%}
@keyframes stspin{to{transform:rotate(360deg)}}
#dlgTitle{font-size:14px;font-weight:600;color:var(--tx);word-break:break-all;white-space:pre-wrap;line-height:1.6}
#dlgInput{width:100%;margin-top:12px;display:none}
#dlgBtns{margin-top:18px;display:flex;gap:8px;justify-content:flex-end}
pre.content{background:#f8fafc;border:1px solid var(--bd2);border-radius:6px;padding:8px 10px;font-size:12px;color:#3d4a5c;white-space:pre-wrap;max-width:320px;max-height:120px;overflow:auto;font-family:ui-monospace,Consolas,Menlo,monospace;line-height:1.5}
.tag{display:inline-block;padding:1px 8px;border-radius:4px;font-size:12px;background:var(--pri-l);color:#2c5282;border:1px solid #dce7ff}
#logMask{position:fixed;inset:0;background:rgba(16,24,40,.42);display:none;z-index:97}
/* 手机端抽屉菜单的遮罩与汉堡按钮（仅 ≤700px 生效） */
#sideMask{position:fixed;inset:0;background:rgba(16,24,40,.42);display:none;z-index:59}
#menuBtn{display:none;align-items:center;justify-content:center;padding:5px 8px}
#menuBtn svg{width:16px;height:16px;display:block;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round}
#logView{position:fixed;top:50%;left:calc(var(--side-w) + (100% - var(--side-w))/2);transform:translate(-50%,-50%);width:760px;max-width:calc(100% - var(--side-w) - 40px);max-height:80vh;overflow:auto;z-index:98;background:#fff;border:1px solid var(--bd);border-radius:12px;padding:18px;box-shadow:0 12px 36px rgba(16,24,40,.18)}
#logView pre.content{max-width:none;max-height:45vh}
#logView img.shot{max-width:100%}
#logViewClose{float:right;margin-left:12px}
/* 访问日志（2026-10-05 需求 T）：概览小条 + 详情浮层，沿用设备日志浮层同款定位 */
#accMask{position:fixed;inset:0;background:rgba(16,24,40,.42);display:none;z-index:97}
#accView{position:fixed;top:50%;left:calc(var(--side-w) + (100% - var(--side-w))/2);transform:translate(-50%,-50%);width:720px;max-width:calc(100% - var(--side-w) - 40px);max-height:80vh;overflow:auto;z-index:98;background:#fff;border:1px solid var(--bd);border-radius:12px;padding:18px;box-shadow:0 12px 36px rgba(16,24,40,.18)}
/* 添加钱包地址弹窗（2026-10-19）：比通用 #dlg 更宽（表单字段多），层级压在它上面 */
#wlMask{position:fixed;inset:0;background:rgba(16,24,40,.42);display:none;z-index:102}
#wlDlg{position:fixed;top:50%;left:calc(var(--side-w) + (100% - var(--side-w))/2);transform:translate(-50%,-50%);width:560px;max-width:calc(100% - var(--side-w) - 40px);max-height:84vh;overflow:auto;z-index:103;background:#fff;border:1px solid var(--bd);border-radius:12px;padding:18px;box-shadow:0 12px 36px rgba(16,24,40,.18);display:none}
#wlHead{display:flex;align-items:center;justify-content:space-between;gap:12px}
#wlDlg .fld{margin-top:10px}
#wlDlg .fld input,#wlDlg .fld select{width:100%}
/* 编辑 / 归集弹窗（2026-10-21）：与添加弹窗同一套外观，只是内容不同。
   ⚠ 三个弹窗共用 `#…Mask` / `#…Dlg` 的定位与层级，改其中一个要连另两个一起改，
     否则会出现「一个弹窗被另一个盖住」。 */
#wlEditMask,#swMask,#wlQrMask{position:fixed;inset:0;background:rgba(16,24,40,.42);display:none;z-index:102}
#wlEditDlg,#swDlg{position:fixed;top:50%;left:calc(var(--side-w) + (100% - var(--side-w))/2);transform:translate(-50%,-50%);width:560px;max-width:calc(100% - var(--side-w) - 40px);max-height:84vh;overflow:auto;z-index:103;background:#fff;border:1px solid var(--bd);border-radius:12px;padding:18px;box-shadow:0 12px 36px rgba(16,24,40,.18);display:none}
/* 地址二维码弹窗（2026-10-31）：一个码 + 一行地址，窄版（380）就够。
   ⚠ 码块是 SVG：手机上扫的是屏幕，位图放大必然发糊 → 扫不出来。 */
#wlQrDlg{position:fixed;top:50%;left:calc(var(--side-w) + (100% - var(--side-w))/2);transform:translate(-50%,-50%);width:380px;max-width:calc(100% - var(--side-w) - 40px);max-height:84vh;overflow:auto;z-index:103;background:#fff;border:1px solid var(--bd);border-radius:12px;padding:18px;box-shadow:0 12px 36px rgba(16,24,40,.18);display:none}
#wlQrHead{display:flex;align-items:center;justify-content:space-between;gap:12px}
#wlQrBody{margin-top:14px}
/* ⚠ 码块必须**白底**：二维码靠明暗对比识别，透明/深色底上有相当一部分扫描器直接认不出。 */
#wlQrImg{display:block;margin:0 auto;width:100%;max-width:300px;height:auto;background:#fff;padding:10px;border:1px solid var(--bd2);border-radius:10px}
#wlQrAddr{margin-top:12px;font-size:12px;line-height:1.6;color:var(--tx3);word-break:break-all;text-align:center}

   所以要 820 那档宽版，不是 560 那档。
   ⚠ 层序与上面对齐：遮罩 102、窗体 103 —— 通用确认框 #dlg(111) 与状态窗 #stBox(113)
     必须压在它上面（保存时的二次确认就是从这扇窗里弹出去的）。 */
#gasMask{position:fixed;inset:0;background:rgba(16,24,40,.42);display:none;z-index:102}
#gasDlg{position:fixed;top:50%;left:calc(var(--side-w) + (100% - var(--side-w))/2);transform:translate(-50%,-50%);width:820px;max-width:calc(100% - var(--side-w) - 40px);max-height:84vh;overflow:auto;z-index:103;background:#fff;border:1px solid var(--bd);border-radius:12px;padding:18px;box-shadow:0 12px 36px rgba(16,24,40,.18);display:none}
/* 三列：链 / 地址 / 私钥，最后一列是状态（带版本的链换成版本下拉）。
   ⭐ 「数量」那一列已撤（2026-10-29 改差额补）：补多少按当时的缺口现算，没有可填的格子。 */
#gasBody .gasRow{display:grid;grid-template-columns:96px 1fr 190px 96px;gap:8px;align-items:center}
#gasBody .gasRow.addrver{grid-template-columns:96px 1fr 190px 120px}
.gasName{font-size:13px;font-weight:600}
.gasHead{display:grid;grid-template-columns:96px 1fr 190px 96px;gap:8px;font-size:12px;color:#64748b;margin-bottom:4px}
.gasHead.addrver{grid-template-columns:96px 1fr 190px 120px}
.gasSt{font-size:12px;line-height:1.4}
@media (max-width:900px){
  #gasBody .gasRow,#gasBody .gasRow.addrver,.gasHead,.gasHead.addrver{grid-template-columns:1fr}
}
/* 大额阈值弹窗（2026-10-27）：比上面两个宽 —— 里面是「一条链一行、一格一枚币」的矩阵，
   560px 放不下四列（链名 118 + 三格各 104 输入 + 币种后缀）→ 会被横向滚，
   而横向滚着的表格最容易看错行（把 USDC 那一格当成 USDT 的）。 */
#wlEditHead,#swHead{display:flex;align-items:center;justify-content:space-between;gap:12px}
#wlEditDlg .fld,#swDlg .fld{margin-top:10px}
#wlEditDlg .fld input,#wlEditDlg .fld select,#swDlg .fld input,#swDlg .fld select{width:100%}
/* 钱包密钥库（2026-10-21）：添加 / keystore 解密 / 派生候选 / 查看明文，四个弹窗。
   ⚠ 与上面 wl* / sw* 共用同一套定位与层级（z-index 102 / 103）—— 只改其中一个
     会出现「一个弹窗被另一个盖住」。派生弹窗更宽（要放候选地址表）。 */
#wsAddMask,#wsDecMask,#wsDrvMask,#wsViewMask{position:fixed;inset:0;background:rgba(16,24,40,.42);display:none;z-index:102}
#wsAddDlg,#wsDecDlg,#wsViewDlg{position:fixed;top:50%;left:calc(var(--side-w) + (100% - var(--side-w))/2);transform:translate(-50%,-50%);width:560px;max-width:calc(100% - var(--side-w) - 40px);max-height:84vh;overflow:auto;z-index:103;background:#fff;border:1px solid var(--bd);border-radius:12px;padding:18px;box-shadow:0 12px 36px rgba(16,24,40,.18);display:none}
#wsDrvDlg{position:fixed;top:50%;left:calc(var(--side-w) + (100% - var(--side-w))/2);transform:translate(-50%,-50%);width:820px;max-width:calc(100% - var(--side-w) - 40px);max-height:84vh;overflow:auto;z-index:103;background:#fff;border:1px solid var(--bd);border-radius:12px;padding:18px;box-shadow:0 12px 36px rgba(16,24,40,.18);display:none}
#wsAddHead,#wsDecHead,#wsDrvHead,#wsViewHead{display:flex;align-items:center;justify-content:space-between;gap:12px}
#wsAddDlg .fld,#wsDecDlg .fld,#wsDrvDlg .fld,#wsViewDlg .fld{margin-top:10px}
#wsAddDlg .fld input,#wsAddDlg .fld select,#wsAddDlg .fld textarea,
#wsDecDlg .fld input,#wsDecDlg .fld select,#wsDecDlg .fld textarea,
#wsDrvDlg .fld input,#wsViewDlg .fld textarea{width:100%}
/* 密钥内容输入框要够高：keystore 是一整段 JSON，助记词也要展开好几个词 */
#wsaBody{min-height:120px;font-family:ui-monospace,Consolas,Menlo,monospace;font-size:12px;line-height:1.5;resize:vertical}
#wsViewText{min-height:96px;font-family:ui-monospace,Consolas,Menlo,monospace;font-size:12px;line-height:1.5;resize:vertical}
/* 归集预演的结果表：字段名一列、值一列，值允许换行（地址很长） */
table.swplan{width:100%;font-size:13px;border-collapse:collapse;margin-top:10px}
table.swplan th{width:132px;text-align:left;color:var(--tx3);font-weight:400;padding:6px 12px 6px 0;
  white-space:nowrap;vertical-align:top;border-bottom:1px solid var(--bd2)}
table.swplan td{padding:6px 0;word-break:break-all;white-space:normal;max-width:none;overflow:visible;
  border-bottom:1px solid var(--bd2);font-family:ui-monospace,Consolas,Menlo,monospace;font-size:12px}
/* 今日 PV/UV 概览：与仪表盘统计卡同一口径，但这里是文字条（不抢表格视线） */
.accsum{display:flex;flex-wrap:wrap;gap:18px;margin-top:10px;font-size:13px;color:var(--tx3)}
.accsum b{color:var(--tx);font-weight:600;margin-left:2px}
/* 长文本单元格：**统一走 JS 那一份截断单元**（web/js/wallets.js 的 longCellHtml：
   42 字符宽 + 下箭头点开看全文），css 里不再另留一套省略号。
   ⚠ 原来这里有一条 `.ell{max-width:220px;…ellipsis}`：它只给 hover title、没有展开入口，
     触屏上等于看不全 —— 2026-10-26 起各表全部改成截断单元，这条已无人使用，别再引回来。
   装了截断单元的 td 必须同时放宽 max-width（base.css 上方 th,td 是 360px，42 字符要 420px）。 */
/* 详情键值表 */
table.kv{width:100%;font-size:13px;border-collapse:collapse}
table.kv th{width:110px;text-align:left;color:var(--tx3);font-weight:400;padding:6px 12px 6px 0;white-space:nowrap;vertical-align:top;border-bottom:1px solid var(--bd2)}
table.kv td{padding:6px 0;word-break:break-all;border-bottom:1px solid var(--bd2)}
/* 例外：详情类表格的**值**列（弹窗 kv、设备详情顶栏 dev-info）语义就是「长值要能一次读完」，
   不参与上面那套「不换行 + 横向滚动」，仍然换行；列宽也不限（max-width 会把它截断）。
   表头是固定短标签，继续吃全局 nowrap。 */
table.kv td,#tab-devdetail .dev-info td{white-space:normal;word-break:break-all;max-width:none;overflow:visible}
.tbl>table.kv,.tbl>table.dev-info{width:100%}
/* 单元格里自己排版的块（如域名表的 NS 提示行）：不受单元格「不换行」的约束，照常换行。
   ⚠ 不加这条的话，NS 那串说明会被 nowrap 拉成一行、再被 overflow:hidden 直接裁掉 */
td>div,th>div{white-space:normal}
/* 设备详情页（tab-devdetail）：固定信息表 + 下方页签 */
#tab-devdetail .dev-info th{color:var(--tx3);font-weight:400;font-size:12px;text-align:left;padding:7px 14px 7px 0;white-space:nowrap;border-bottom:1px solid var(--bd2)}
#tab-devdetail .dev-info td{padding:7px 24px 7px 0;border-bottom:1px solid var(--bd2);word-break:break-all}
/* 设备详情页签（2026-09-29 美化）：分段控件（segmented control）风格 */
.devtabs{display:inline-flex;gap:2px;background:var(--bg,#f1f3f7);border:1px solid var(--bd);border-radius:9px;padding:3px;margin-bottom:12px}
.devtabs button{background:transparent;border:none;border-radius:7px;padding:6px 18px;cursor:pointer;color:var(--tx3);font-size:13px;transition:background .12s,color .12s}
.devtabs button:hover{color:var(--tx2)}
.devtabs button.on{background:#fff;color:var(--tx);font-weight:600;box-shadow:0 1px 3px rgba(16,24,40,.12)}
/* ⚠ 这里**不能**再写 `#tab-devdetail table{width:100%}`：id 选择器会盖掉
   `.tbl>table{width:max-content}`，本页的列表表格就退回到「被压扁但不出滚动条」的老毛病。
   宽度交给 .tbl>table 统一管（dev-info 那张值表由上面的例外规则单独改回 width:100%） */
#tab-devdetail table th,#tab-devdetail table td{text-align:left;padding:6px 12px 6px 0}
#tab-devdetail pre.content{max-width:none;background:var(--bg,#f6f7fa);border:1px solid var(--bd);border-radius:8px;padding:12px;font-size:12px;overflow:auto;max-height:60vh}
#tab-devdetail td.devlog-detail{padding:6px 12px 10px 0}
/* 登录页 */
#login{max-width:372px;margin:80px auto 0;padding:0 16px}
#login .card{padding:26px 24px 24px;border-radius:12px;box-shadow:0 4px 20px rgba(16,24,40,.07)}
.login-brand{display:flex;align-items:center;gap:12px;margin-bottom:22px}
.login-brand .logo{width:42px;height:42px;border-radius:11px;background:linear-gradient(135deg,#3b82f6,#2563eb);color:#fff;display:flex;align-items:center;justify-content:center;font-size:14px;font-weight:700;letter-spacing:.5px}
.login-brand b{display:block;font-size:16px;font-weight:600;color:var(--tx)}
.login-brand i{display:block;font-size:12px;color:var(--tx3);font-style:normal;margin-top:4px}
/* 状态文字 */
.st-on{color:var(--ok);font-weight:500}
.st-off{color:var(--tx3)}
#tab-shots .card img.shot{max-width:100%}
/* 通用查看弹窗（大图 / 文本 / 调试预览） */
#viewerMask{position:fixed;inset:0;background:rgba(16,24,40,.42);display:none;z-index:98}
#viewer{position:fixed;top:50%;left:calc(var(--side-w) + (100% - var(--side-w))/2);transform:translate(-50%,-50%);width:860px;max-width:calc(100% - var(--side-w) - 40px);max-height:84vh;overflow:auto;z-index:99;background:#fff;border:1px solid var(--bd);border-radius:12px;padding:16px 18px;box-shadow:0 12px 36px rgba(16,24,40,.18);display:none}
#viewerHead{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:10px}
#viewerHead strong{font-size:14px;color:var(--tx);word-break:break-all}
#viewerBody{font-size:13px}
/* 所有截图：卡片网格 */
.shot-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(190px,1fr));gap:12px}
.shot-card{border:1px solid var(--bd);border-radius:10px;overflow:hidden;background:var(--card,#fff)}
.shot-card img{width:100%;height:150px;object-fit:cover;display:block;cursor:zoom-in;background:var(--bg,#f1f3f7)}
.shot-meta{padding:8px 10px 10px}
.shot-name{font-size:12px;font-weight:500;color:var(--tx);word-break:break-all;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.shot-meta .hint{font-size:11px;margin-top:3px}
/* 开关（调试日志） */
.switch{position:relative;display:inline-block;width:42px;height:24px;flex:0 0 auto}
.switch input{opacity:0;width:0;height:0}
.switch .slider{position:absolute;inset:0;background:#cfd4dd;border-radius:24px;transition:background .15s;cursor:pointer}
.switch .slider::before{content:'';position:absolute;width:18px;height:18px;left:3px;top:3px;background:#fff;border-radius:50%;box-shadow:0 1px 3px rgba(16,24,40,.25);transition:transform .15s}
.switch input:checked + .slider{background:#2563eb}
.switch input:checked + .slider::before{transform:translateX(18px)}
/* 仪表盘统计卡片：每张一个主题色（--c 主色 / --cs 浅底 / --cl 描边） */
.stats{display:grid;grid-template-columns:repeat(4,1fr);gap:14px;margin-bottom:16px}
.stat{position:relative;overflow:hidden;background:var(--card);border:1px solid var(--bd);border-radius:12px;padding:17px 18px 16px;box-shadow:0 1px 3px rgba(16,24,40,.05)}
.stat::after{content:'';position:absolute;left:0;right:0;top:0;height:3px;background:var(--c)}
.stat.c1{--c:#2563eb;--cs:#eff4ff;--cl:#d5e3ff}
.stat.c2{--c:#7c3aed;--cs:#f4f0ff;--cl:#e1d7ff}
.stat.c3{--c:#12a150;--cs:#ebfaf1;--cl:#c6eed7}
.stat.c4{--c:#e07b0a;--cs:#fff5e9;--cl:#ffe0bd}
.stat-k{display:flex;align-items:center;justify-content:space-between;gap:10px;font-size:12.5px;color:var(--tx2)}
.stat-ic{flex:0 0 auto;width:30px;height:30px;border-radius:9px;background:var(--cs);border:1px solid var(--cl);color:var(--c);display:flex;align-items:center;justify-content:center}
.stat-ic svg{width:15px;height:15px;display:block;fill:none;stroke:currentColor;stroke-width:1.9;stroke-linecap:round;stroke-linejoin:round}
.stat-v{font-size:28px;font-weight:600;color:var(--c);line-height:1.15;margin-top:12px;font-variant-numeric:tabular-nums;letter-spacing:.3px}
.stat-s{font-size:12px;color:var(--tx3);margin-top:8px;line-height:1.5}
/* ⭐ 网络 logo 作**背景水印**（2026-10-22 用户口径：右上角那个太小，要大一点、像背景）
   ⚠ 只调透明度不换色：颜色仍取卡片主色 var(--c)，换成写死的灰会在四套配色上都不搭。
   ⚠ pointer-events:none + z-index 0：它只是装饰，不能挡住卡片的点击区域（启停按钮在卡里）。 */
.stat-logo{position:absolute;right:2px;top:0;width:78px;height:78px;color:var(--c);opacity:.12;pointer-events:none;line-height:0;z-index:0}
.stat-logo svg{width:100%;height:100%;display:block;fill:none;stroke:currentColor}
.stat-k,.stat-v,.stat-s{position:relative;z-index:1}
/* 阈值矩阵（归集配置 / 系统模版共用）：一格 = 输入框 + 币名 */
.thr-mx .thr-th{width:150px}
.thr-mx .thr-cell{white-space:nowrap}
.thr-mx .thr-cell input{width:104px}
.thr-unit{margin-left:6px;font-size:12px;color:var(--tx3);letter-spacing:.3px}
/* 仪表盘「所属地址余额」卡片（2026-10-24）：
   ⭐⭐ **固定 4 张一行，与上面四张统计卡同宽同距**（用户口径「要和上面的一致，4 个卡片一行」）。
     列数照抄 `.stats` 的 `repeat(4,1fr)` 与 900px 断点，两排永远对得齐。
     ⚠ 别用 auto-fill + minmax：列数是**窗口宽度算出来的**（宽屏 6 张、窄一点 5 张），
       同一个界面在不同电脑上长得不一样，而且永远跟上面的统计卡对不上（2026-10-24 实测）。
   ⭐⭐ `grid-auto-rows:1fr` 让**每一行等高**：合并卡（USDT / USDC）的副标题要写好几条链，
     比主币卡那一行高出一截 —— 不拉平的话第二排明显比第一排大。
   ⚠ 外面不能套外框（以前套了 .card）：它的内边距 + 描边吃掉近 40px 可用宽度，
     卡片于是比上面的窄 10px、左边缘还往里缩一格（实测 243/278 vs 224/288）。 */
.balgrid{display:grid;grid-template-columns:repeat(4,1fr);
  grid-auto-rows:1fr;gap:14px;margin:0 0 16px}
.balc{position:relative;overflow:hidden;background:var(--card);border:1px solid var(--bd);border-radius:12px;padding:14px 15px 13px;box-shadow:0 1px 3px rgba(16,24,40,.05)}
.balc::before{content:'';position:absolute;left:0;right:0;top:0;height:3px;background:var(--c)}
.balc.t1{--c:#2563eb}
.balc.t2{--c:#12a150}
.balc-k{font-size:12.5px;font-weight:600;color:var(--tx2);letter-spacing:.4px}
.balc-v{font-size:26px;font-weight:600;color:var(--c);line-height:1.2;margin-top:9px;font-variant-numeric:tabular-nums;word-break:break-all}
.balc-s{font-size:12px;color:var(--tx3);margin-top:6px;line-height:1.45}
/* 中等宽度（卡片 200px 上下）：26px 的金额会折成两行，降一档就回到一行 */
@media(max-width:1250px){.balc-v{font-size:22px}}
@media(max-width:900px){.stats{grid-template-columns:repeat(2,1fr)}.stat-v{font-size:24px}.stat{padding:15px 15px 14px}
  /* 与上面四张同步切成 2 列（断点也照抄） */
  .balgrid{grid-template-columns:repeat(2,1fr)}.balc-v{font-size:20px}}
/* 手机 / 窄屏（H5）：侧栏改为抽屉，内容占满全宽，表格横向滚动 */
@media(max-width:700px){
  body.has-side{--side-w:0px}   /* 抽屉不占位，弹窗按全屏内容区居中 */
  #menuBtn{display:inline-flex}
  #side{display:none;z-index:60}
  body.side-open #side{display:flex}
  body.side-open #sideMask{display:block}
  #main{margin-left:0}
  #main header{padding:0 10px}
  #user{display:none}
  #crumb{font-size:14px}
  main{margin:12px auto;padding:0 12px}
  .card{overflow-x:auto;padding:14px 12px 12px}
  /* ⚠ 原来这里还有一句 `table{min-width:620px}`（靠它把表格撑宽好触发卡片滚动）。
     2026-10-12 起表格由 .tbl 容器自己滚，这句只剩副作用：三列的小表在手机上也被
     强行撑到 620px、凭空多出一截横向滚动。已删。 */
  .stat-v{font-size:24px}
  /* 手机上两列只剩 ~160px/张：金额有 13 位（23430262.5824），26px 必然折行 */
  .balc-v{font-size:17px}
  #dlg{padding:18px 16px}
}

/* 参数（params）编辑表单（2026-09-29）：按脚本 params 的 JSON 结构动态生成节点名 + 值，
   值为可编辑控件；加入队列时以表单当前值重组 JSON 为准 */
.pform{margin-top:4px;max-width:620px}
.prow{display:flex;align-items:flex-start;gap:10px;margin-top:6px}
.pkey{flex:0 0 auto;min-width:128px;max-width:220px;padding-top:7px;font-family:ui-monospace,Consolas,monospace;
  font-size:12px;color:var(--tx2);word-break:break-all}
.pgroup{margin-top:10px;font-family:ui-monospace,Consolas,monospace;font-size:12px;font-weight:600;color:var(--tx)}
.pval{flex:1 1 auto;max-width:360px}
textarea.pval{font-family:ui-monospace,Consolas,monospace;font-size:12px;min-height:64px;max-width:520px}
.pstate{margin-top:10px;font-size:12px;color:var(--tx3)}

/* 预览弹窗图片缩放工具条（2026-09-29）：与 button.mini 同款控件，吸顶在弹窗内容顶部 */
.vzoom{display:flex;align-items:center;gap:6px;position:sticky;top:0;background:#fff;z-index:2;
  padding:2px 0 8px;margin-bottom:6px;border-bottom:1px solid var(--bd)}
.vzoom .sp{flex:1}
.vzval{font-size:12px;color:var(--tx3);font-variant-numeric:tabular-nums}

/* 菜单权限配置页（2026-10-23）：一行一个菜单 —— 名称/排序/谁能看到，下面挂该页的操作授权 */
.mct{width:100%;border-collapse:collapse;table-layout:auto}
.mct th,.mct td{border-bottom:1px solid var(--bd2);padding:8px 8px;vertical-align:top;text-align:left;font-weight:400}
.mct th{color:var(--tx2);font-size:12.5px}
.mct .mcl{width:150px}
.mct .mcs{width:72px}
.mcrs{display:flex;gap:12px;flex-wrap:wrap;align-items:center}
.mcb{display:inline-flex;align-items:center;gap:4px;font-size:13px;white-space:nowrap;cursor:pointer}
.mcb input{width:auto;margin:0}
.mcacts{margin-top:8px;display:flex;flex-direction:column;gap:6px}
.mcact{display:flex;align-items:center;gap:12px;flex-wrap:wrap}
.mcan{color:var(--tx2);font-size:13px;min-width:58px}

/* TG 群通知页（2026-10-23 重排版）：左「群与开关」/ 右「转账阈值」两栏，
   窄屏自动叠成一栏。阈值矩阵复用上面的 .thr-mx（与归集配置同一套外观）。 */
.tghd{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.tgpill{display:inline-flex;align-items:center;gap:5px;padding:2px 9px;border-radius:999px;
  font-size:12px;line-height:1.7;border:1px solid var(--bd);background:#f4f6fa;color:var(--tx3)}
.tgpill.on{background:#ebfaf1;border-color:#c6eed7;color:#12803f}
.tgpill.off{background:#f4f6fa;border-color:var(--bd);color:var(--tx3)}
.tggrid{display:grid;grid-template-columns:minmax(300px,400px) minmax(360px,1fr);gap:18px;margin-top:14px}
.tgsec{border:1px solid var(--bd2);border-radius:10px;padding:14px 16px 16px;background:#fcfdff}
.tgsec-t{font-size:13px;font-weight:600;color:var(--tx);margin-bottom:10px}
.tgsec .fld{margin-top:0}
.tgsec .fld input,.tgsec .fld select{width:100%}
.tgrow{display:flex;gap:10px;align-items:flex-end;flex-wrap:wrap;margin-top:10px}
.tgf-grow{flex:1 1 220px;min-width:0}
.tgsw{display:flex;align-items:center;gap:10px;margin-top:12px}
.tgsw .tgl{font-size:13px;color:var(--tx2)}
.tgdirs{display:flex;gap:16px;flex-wrap:wrap;margin-top:12px}
.tgchk{display:inline-flex;align-items:center;gap:6px;font-size:13px;color:var(--tx2);cursor:pointer;white-space:nowrap}
.tgchk input{width:auto;margin:0}
.tgwarn{color:var(--warn)}
.tgsec .hint{margin-left:0;display:block;margin-top:8px}
.tgsteps{display:flex;flex-direction:column;gap:8px;margin-top:4px}
.tgstep{display:flex;gap:8px;align-items:flex-start;font-size:12px;color:var(--tx3);line-height:1.8}
.tgstep i{flex:0 0 auto;width:16px;height:16px;margin-top:3px;border-radius:50%;background:var(--pri-l);
  color:var(--pri);font-size:11px;font-style:normal;font-weight:600;display:flex;align-items:center;justify-content:center}
.tgstep code{background:#f1f4f9;border:1px solid var(--bd2);border-radius:4px;padding:1px 5px;
  font-family:ui-monospace,Consolas,Menlo,monospace;font-size:12px;color:var(--tx)}
.tgpre{display:none;margin:12px 0 0;padding:12px 14px;border-radius:8px;background:#f6f7f9;
  font-size:13px;line-height:1.8;white-space:pre-wrap;border:1px solid var(--bd2)}
/* 渠道页「我的渠道」里的通知面板：与上面同一套板块，只是外面套一层边框卡片 */
.tgpanel{margin-top:14px;border:1px solid var(--bd);border-radius:10px;padding:16px;background:#fcfdff}
.tgpanel-hd{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.tgpanel-t{font-size:14px;font-weight:600;color:var(--tx)}
/* 通知样式编辑器（2026-10-24）：五类通知各一块，块内是「可用占位符 + 多行文本框」 */
.tgtpls{display:flex;flex-direction:column;gap:14px;margin-top:12px}
.tgtpl{border:1px solid var(--bd);border-radius:8px;padding:10px 12px;background:#fcfdff}
.tgtpl-hd{display:flex;align-items:center;justify-content:space-between;gap:10px}
.tgtpl-hd b{font-size:13px;color:var(--tx)}
.tgtpl-v{margin:6px 0 8px;line-height:2}
.tgtpl-v code{background:#f1f4f9;border:1px solid var(--bd2);border-radius:4px;padding:1px 5px;margin-right:4px;
  font-family:ui-monospace,Consolas,Menlo,monospace;font-size:12px;color:var(--pri)}
.tgtpl textarea{width:100%;resize:vertical;font-family:ui-monospace,Consolas,Menlo,monospace;
  font-size:12px;line-height:1.7}
/* 「要阈值」小标签：那两类转账通知还要再过金额阈值，不标出来会被当成勾了就收每一笔 */
.tgthr-tag{font-style:normal;font-size:11px;color:var(--tx3);border:1px solid var(--bd2);
  border-radius:4px;padding:0 4px;margin-left:4px}
@media (max-width:1000px){.tggrid{grid-template-columns:1fr}}

/* 报表双面板（2026-11-04 四级分账）：渠道分账 / 后台分账 两个并列表格 */
.rp-panel{margin-top:18px;padding-top:14px;border-top:1px solid var(--bd)}
.rp-title{font-weight:600;font-size:14px;color:var(--fg)}
.rp-panel:first-of-type{border-top:none}
