:root{--bg:#f6f7f9;--text:#1f2933;--muted:#68727f;--line:#dfe5ec;--panel:#fff;--brand:#22577a;--good:#16825d}*{box-sizing:border-box}body{margin:0;background:var(--bg);color:var(--text);font:14px/1.45 Arial,"PingFang SC",sans-serif}button,input,select{font:inherit}button{min-height:44px;border:1px solid var(--line);border-radius:8px;background:#fff;color:var(--text);cursor:pointer}button.on,button:hover,.link{border-color:var(--brand);color:var(--brand)}button:focus-visible,input:focus-visible,select:focus-visible{outline:3px solid #8ecae6;outline-offset:2px}.shell{min-height:100vh;min-height:100dvh;display:grid;place-items:center;padding:18px}.login{width:min(380px,100%);padding:28px;border:1px solid var(--line);border-radius:8px;background:#fff;box-shadow:0 18px 45px #12202d14}.login h1{margin:0 0 18px}.login form{display:grid;gap:10px}.login input{height:46px;border:1px solid var(--line);border-radius:8px;padding:0 12px}.login button,.content header button,.tools button{background:var(--brand);color:#fff;border-color:var(--brand)}.login p{min-height:22px;color:#b42318}.layout{display:grid;grid-template-columns:260px 1fr;min-height:100vh;min-height:100dvh}aside{border-right:1px solid var(--line);background:#fff;padding:18px;overflow:auto}aside h1{margin:0 0 14px;font-size:20px}nav,.sub{display:grid;gap:6px}nav button,.sub button{text-align:left;padding:0 12px}.sub{margin-top:16px;padding-top:16px;border-top:1px solid var(--line)}.sub button{background:#f8fafc}.content{min-width:0;padding:22px;display:grid;align-content:start;gap:16px}.content header,.drawer header{display:flex;align-items:center;justify-content:space-between;gap:12px}.content h1,.panel h2,.drawer h2{margin:0}.content small,.drawer small{color:var(--muted)}.tools{display:grid;grid-template-columns:minmax(180px,1fr) 100px 100px;gap:8px}.tools input,.tools select{min-width:0;height:44px;border:1px solid var(--line);border-radius:8px;background:#fff;padding:0 12px}.cards{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px}.cards article,.panel{border:1px solid var(--line);border-radius:8px;background:var(--panel);padding:16px}.cards b{display:block;font-size:24px;color:var(--good)}.cards span{color:var(--muted)}.panel{overflow:hidden}.panel h2{font-size:16px;margin-bottom:12px}.table{overflow:auto;border:1px solid var(--line);border-radius:8px}.tr{display:grid;grid-template-columns:repeat(var(--cols,7),minmax(110px,1fr));min-width:min(100%,calc(var(--cols,7)*130px));border-top:1px solid var(--line)}.tr:first-child{border-top:0}.tr span{min-width:0;padding:11px 12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.head{background:#f2f5f8;color:var(--muted);font-weight:700}.ops{display:flex;flex-wrap:wrap;gap:8px}.ops button,.confirm button{min-width:88px}.confirm{display:grid;gap:8px}.confirm input{height:40px;border:1px solid var(--line);border-radius:8px;padding:0 10px}.link{min-height:0;border:0;background:transparent;padding:0;text-align:left}.err{margin:0;padding:12px;border-radius:8px;background:#fff0f0;color:#b42318}.empty{margin:0;padding:22px;border:1px dashed var(--line);border-radius:8px;color:var(--muted);background:#fff}.shade{position:fixed;inset:0;background:#0f172a55;z-index:4}.drawer{position:fixed;z-index:5;right:0;top:0;width:min(760px,100vw);height:100vh;height:100dvh;border-left:1px solid var(--line);display:grid;align-content:start;gap:14px}.drawer .cards{grid-template-columns:repeat(2,minmax(0,1fr))}@media(max-width:900px){.layout{grid-template-columns:1fr}aside{position:sticky;top:0;z-index:2;border-right:0;border-bottom:1px solid var(--line);padding:12px}nav,.sub{display:flex;overflow-x:auto}nav button,.sub button{flex:0 0 auto}.content{padding:14px}.cards{grid-template-columns:1fr 1fr}}@media(max-width:520px){.cards,.tools,.drawer .cards{grid-template-columns:1fr}.tr{min-width:calc(var(--cols,7)*120px)}.content header{align-items:flex-start;flex-direction:column}.content header button{width:100%}.login{padding:22px}}
.confirm.danger,.panel.danger{border:1px solid #c0392b;background:#fff5f4;border-radius:8px;padding:10px}
.confirm.danger span,.panel.danger h2{color:#c0392b}
.confirm.danger button[data-user-action],.panel.danger button[type=submit],.panel.danger form button:not([type=button]){background:#c0392b;color:#fff;border-color:#c0392b}
.confirm.danger input[data-phrase],.confirm input[data-phrase-for],.tools input[data-phrase-for],.panel.danger input[name=confirmation]{border:1px solid #c0392b;font-family:ui-monospace,monospace}
/* 确认框必须占满一行：.tools 是 1fr/100px/100px 的三列网格，落到 100px 那一列会把
   ROLLBACK_ICOIN_TO_INTERNAL_TEST 这种长确认词挤成看不清，管理员就只会去复制粘贴。 */
.tools input[data-phrase-for]{grid-column:1/-1}
.tr input[type=checkbox]{width:18px;height:18px;cursor:pointer}
.tr.head span{font-weight:600;color:#444;white-space:nowrap}
.tr span{overflow:hidden;text-overflow:ellipsis}
.empty.tip{display:flex;align-items:center;gap:10px;border-style:dashed;border-color:#c9d6e4;background:#f8fbff;color:#5b6b7c}
.empty.tip .ico{font-size:20px;line-height:1;filter:grayscale(.2)}
.cfg{display:grid;gap:14px}.cfg-g h3{margin:0 0 8px;font-size:14px;color:var(--brand)}
.cfg-row{display:grid;grid-template-columns:minmax(200px,1.4fr) minmax(140px,1fr) 100px;gap:8px;align-items:center;padding:10px 0;border-top:1px solid var(--line)}
.cfg-g .cfg-row:first-of-type{border-top:0}
.cfg-row label{display:grid;grid-template-columns:1fr minmax(120px,160px);gap:8px;align-items:center;min-width:0}
.cfg-k{display:grid;min-width:0}.cfg-k b{font-weight:600}.cfg-k code{color:var(--muted);font-size:12px;overflow:hidden;text-overflow:ellipsis}
.cfg-row select,.cfg-row input{height:40px;min-width:0;border:1px solid var(--line);border-radius:8px;background:#fff;padding:0 10px}
.cfg-v{padding:0 10px;color:var(--text)}.cfg-ro{color:var(--muted);font-size:12px;text-align:right}
.todo{display:grid;gap:8px}
.todo-row{display:grid;grid-template-columns:56px 1fr auto;align-items:center;gap:12px;width:100%;padding:10px 12px;border:1px solid var(--line);border-radius:8px;background:#fff;text-align:left}
.todo-row .n{font-size:20px;font-weight:700;color:var(--muted)}.todo-row .go{color:var(--muted);font-size:13px}
.todo-row.warn{border-color:#e8a33d;background:#fff8ec}.todo-row.warn .n{color:#b26a00}
.todo-row.alert{border-color:#c0392b;background:#fff5f4}.todo-row.alert .n{color:#c0392b}
/* 「未知」既不是正常也不是故障：不许落回 ok 那身白底（跟「没有积压」一模一样），也不许飘 alert 的红。
   用的是本表已有的第三种语义——.empty / .empty.tip / .cols-tip 那套虚线 + 冷灰蓝，
   全站的意思一直是「这里没有可用的读数」，不新造第四种颜色。 */
.todo-row.unknown{border-style:dashed;border-color:#c9d6e4;background:#f8fbff}
.todo-row.unknown .n{color:#5b6b7c;font-size:14px}
/* 卡片同理：card() 已经把读不到写成「未知」，但 .cards b 一律是 --good 的绿——
   「未知」和一个真实数字在卡片上是同一种绿，扫一眼整屏都是「正常」。
   用的是上面 .todo-row.unknown 同一套虚线 + 冷灰蓝，不新造第二种；真实读数照旧是绿的。 */
.cards article.unknown{border-style:dashed;border-color:#c9d6e4;background:#f8fbff}
.cards article.unknown b{color:#5b6b7c;font-size:16px}
button.todo-row:hover,button.todo-row:focus-visible{border-color:var(--brand)}
@media(max-width:900px){.cfg-row,.cfg-row label{grid-template-columns:1fr}.cfg-ro{text-align:left}}
/* ① 列溢出提示：明确告知还有多少列没显示，并指向展开入口 */
.cols-tip{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin:0 0 10px;padding:8px 12px;border:1px dashed #c9d6e4;border-radius:8px;background:#f8fbff;color:#5b6b7c;font-size:13px}
.cols-tip .ico{color:var(--brand)}.cols-tip b{color:var(--brand);font-weight:600}
/* ② 行展开：完整字段 + 未截断原文，不依赖 hover */
.tr[data-row]{cursor:pointer}
.tr .det{padding:6px 12px}.det button{min-height:32px;white-space:nowrap}
.tr-detail,.tr-sum{min-width:min(100%,calc(var(--cols,7)*130px));border-top:1px solid var(--line);padding:10px 12px;background:#fbfdff}
.tr-detail .dv{display:grid;grid-template-columns:minmax(90px,140px) 1fr;gap:10px;padding:5px 0}
.tr-detail .dv b{color:var(--muted);font-weight:600}
.tr-detail .dv span{white-space:pre-wrap;overflow-wrap:anywhere}
/* ③ summary：一句人话的操作摘要，整行显著展示，不当普通列 */
.tr-sum{display:flex;gap:8px;align-items:flex-start;background:#f4f9ff;color:#2c3f52}
.tr-sum .t{overflow-wrap:anywhere}
.tr .k{display:none}
/* 窄屏：表格摊成卡片，每个值配上列名，不再靠横向滚动与 hover */
@media(max-width:520px){
.table{overflow:visible;border:0;background:transparent}
.tr{grid-template-columns:88px 1fr;min-width:0;margin-top:10px;border:1px solid var(--line);border-radius:8px;background:#fff}
.tr.head{display:none}
.tr:first-of-type{margin-top:0}
.tr .k{display:block;padding:9px 0 9px 12px;color:var(--muted);font-style:normal;font-size:12px}
.tr span{white-space:normal;overflow:visible;text-overflow:clip;overflow-wrap:anywhere;padding:9px 12px 9px 0}
.tr .pick,.tr .ops,.tr .det{grid-column:1/-1;padding:8px 12px}
.tr .det button{min-height:40px;width:100%}
.tr-sum,.tr-detail{min-width:0;border:1px solid var(--line);border-top:0}
.tr-detail .dv{grid-template-columns:1fr;gap:2px}
}
