/* ==========================================================================
   sub2api-watch design system (UI v4)
   scale tokens -> one table primitive -> page specifics -> breakpoints
   no raw px for border-radius / font-size anywhere below this block
   ========================================================================== */

/* ---- scale: shared by both themes ---- */
:root{
  --r-xs:4px;--r-sm:6px;--r:10px;--r-lg:14px;--r-pill:999px;
  --s1:4px;--s2:6px;--s3:8px;--s4:12px;--s5:16px;--s6:20px;--s7:24px;--s8:32px;
  --fs-2xs:12px;--fs-xs:13px;--fs-sm:14px;--fs-md:16px;--fs-lg:19px;--fs-xl:24px;--fs-hero:40px;
  --fw:400;--fw-med:500;--fw-bold:600;--fw-black:700;
  --font-ui:"Noto Sans","Noto Sans SC","Microsoft YaHei","PingFang SC",sans-serif;--font-number:"JetBrains Mono",ui-monospace,monospace;--font-display:"Space Grotesk","Noto Sans SC",sans-serif;
  --lh-tight:1.25;--lh:1.5;
  --cell-y:10px;--cell-x:16px;
  --maxw:1720px;--pad:24px;--topH:54px;
}
/* Darkmatter tokens from tweakcn; operational danger retains red. */
:root,:root[data-theme="dark"]{color-scheme:dark;--bg:#0E1013;--panel:#15181C;--panel2:#1C2026;--panel3:#232830;--line:#2A3038;--line2:#21262C;--text:#E9ECEF;--text2:#AEB6BF;--muted:#8A939E;--muted2:#79828C;--accent:#5B8DEF;--accentbg:#1D2A44;--chip:#1C2026;--chipon:#5B8DEF;--chipontext:#0B1220;--green:#3FB984;--amber:#E3A33C;--red:#E5544F;--blue:#9AA3AE;--redbg:color-mix(in srgb,var(--red) 13%,var(--panel));--amberbg:color-mix(in srgb,var(--amber) 13%,var(--panel));--greenbg:color-mix(in srgb,var(--green) 13%,var(--panel));--bluebg:color-mix(in srgb,var(--blue) 14%,var(--panel));--shadow:0 1px 2px rgba(0,0,0,.28),0 8px 24px rgba(0,0,0,.18);--overlay:rgb(0 0 0 / .62);--knob:#fff;--focus:var(--accent);--c1:#5B8DEF;--c2:#2FB3BE;--c3:#3FB984;--c4:#E3A33C;--c5:#EE7B5B;--c6:#A0AAB6;}
:root[data-theme="light"]{color-scheme:light;--bg:#F6F6F3;--panel:#FFFFFF;--panel2:#F1F1EE;--panel3:#E9E9E5;--line:#DFDFDA;--line2:#ECECE8;--text:#16191D;--text2:#414750;--muted:#61686F;--muted2:#70777E;--accent:#2F62D4;--accentbg:#E4EBFB;--chip:#F1F1EE;--chipon:#2F62D4;--chipontext:#FFFFFF;--green:#17855C;--amber:#8A5D10;--red:#C4332F;--blue:#5A626D;--redbg:color-mix(in srgb,var(--red) 13%,var(--panel));--amberbg:color-mix(in srgb,var(--amber) 13%,var(--panel));--greenbg:color-mix(in srgb,var(--green) 13%,var(--panel));--bluebg:color-mix(in srgb,var(--blue) 14%,var(--panel));--shadow:0 1px 2px rgba(22,25,29,.07),0 8px 24px rgba(22,25,29,.06);--overlay:rgb(0 0 0 / .45);--knob:#fff;--focus:var(--accent);--c1:#2F62D4;--c2:#0E7A85;--c3:#17855C;--c4:#8A5D10;--c5:#B4502C;--c6:#5F6874;}

/* ---- base ---- */
*{box-sizing:border-box}
html,body{margin:0;padding:0;background:var(--bg);color:var(--text);
  font-family:var(--font-ui);
  font-size:var(--fs-sm);line-height:var(--lh);-webkit-font-smoothing:antialiased}
body{overflow-x:hidden}
a{color:var(--accent);text-decoration:none}a:hover{opacity:.85}
button,input,select,textarea{font:inherit;color:inherit}
[v-cloak]{display:none}
a:focus-visible,button:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible,
summary:focus-visible,[tabindex]:focus-visible,.toggle:focus-visible,label:focus-visible{
  outline:2px solid var(--focus);outline-offset:2px;border-radius:var(--r-xs)}

/* ---- text utilities: body / meta / tertiary. no fourth grey ---- */
.num{font-family:var(--font-display);font-variant-numeric:tabular-nums;font-feature-settings:"tnum";letter-spacing:-.01em}
.mono{font-family:var(--font-number);font-size:var(--fs-xs)}
.muted{color:var(--muted)}.muted2{color:var(--muted2)}
.small{font-size:var(--fs-xs)}.tiny{font-size:var(--fs-2xs)}.nowrap{white-space:nowrap}
.c-red{color:var(--red)}.c-amber{color:var(--amber)}.c-green{color:var(--green)}.c-blue{color:var(--blue)}
.c-none{color:var(--muted2)}   /* "none" = a cell with no requests at all (overview.rate_color) */
.bg-red{background:var(--red)}.bg-amber{background:var(--amber)}.bg-green{background:var(--green)}
.bg-gray,.bg-none{background:var(--muted2)}
.ellipsis{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.clickable{cursor:pointer}
svg.i{width:14px;height:14px;fill:none;stroke:currentColor;stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round;flex:none}
.only-m{display:none!important}
/* number + caption stack (rate cells, usage cells, strip) */
.metric{display:flex;flex-direction:column;line-height:var(--lh-tight);min-width:0}
.metric>b{font-weight:var(--fw-black)}
.metric>.sub{font-size:var(--fs-2xs);color:var(--muted2)}

/* ---- top bar ---- */
.top{height:var(--topH);background:var(--panel);border-bottom:1px solid var(--line);display:flex;align-items:center;gap:var(--s6);position:sticky;top:0;z-index:20;
  padding-left:max(var(--pad), calc((100% - var(--maxw))/2));padding-right:max(var(--pad), calc((100% - var(--maxw))/2))}
.brand{display:flex;align-items:center;gap:var(--s3);font-family:var(--font-display);font-weight:var(--fw-bold);font-size:var(--fs-md);letter-spacing:-.01em;color:var(--text)}
.brand svg{width:20px;height:20px;stroke:var(--accent)}
/* eight tabs no longer fit every width: the bar scrolls instead of shrinking its type */
.tabs{display:flex;gap:2px;min-width:0;overflow-x:auto;scrollbar-width:none;-webkit-overflow-scrolling:touch}
.tabs::-webkit-scrollbar{display:none}
.tabs a{flex:none;padding:var(--s2) var(--s4);border-radius:var(--r-sm);color:var(--muted);font-weight:var(--fw);white-space:nowrap;scroll-margin-inline:var(--s3)}
.tabs a.on{background:var(--accentbg);color:var(--accent);font-weight:var(--fw-bold)}
.grow{flex-grow:1}

/* ---- controls ---- */
.ctl{display:flex;align-items:center;gap:var(--s2);height:32px;padding:0 var(--s4);border:1px solid var(--line);border-radius:var(--r-sm);background:var(--panel);color:var(--text);cursor:pointer;white-space:nowrap}
.ctl:hover{border-color:var(--accent)}
.ctl.sm{height:28px;padding:0 var(--s3);font-size:var(--fs-xs)}
.ctl.primary{background:var(--accent);border-color:var(--accent);color:var(--chipontext)}
.ctl.danger{color:var(--red)}
.ctl:disabled{opacity:.5;cursor:not-allowed}
input.ctl{cursor:text}
input.ctl::placeholder{color:var(--muted2)}
.seg{display:flex;gap:var(--s1);padding:var(--s1);border:1px solid var(--line);border-radius:var(--r-sm);background:var(--panel);flex:none}
.seg button{border:0;background:transparent;padding:var(--s1) var(--s4);border-radius:var(--r-xs);cursor:pointer;color:var(--muted);font-weight:var(--fw-med);display:flex;align-items:center;gap:var(--s2);white-space:nowrap}
.seg button.on{background:var(--chipon);color:var(--chipontext);font-weight:var(--fw-bold)}
.seg button.on.acc{background:var(--accentbg);color:var(--accent)}
.seg button.up{color:var(--red)}.seg button.usr{color:var(--blue)}
.seg button.up.on{background:var(--redbg);color:var(--red)}.seg button.usr.on{background:var(--bluebg);color:var(--blue)}
.dot{width:7px;height:7px;border-radius:50%;display:inline-block;flex:none}
.pill{display:inline-flex;align-items:center;gap:var(--s1);padding:1px var(--s3);border-radius:var(--r-pill);font-size:var(--fs-2xs);font-weight:var(--fw-bold);white-space:nowrap;vertical-align:middle}
.pill.up{background:var(--redbg);color:var(--red)}.pill.user{background:var(--bluebg);color:var(--blue)}
.pill.green{background:var(--greenbg);color:var(--green)}.pill.amber{background:var(--amberbg);color:var(--amber)}.pill.red{background:var(--redbg);color:var(--red)}
.pill.gray,.pill.none{background:var(--chip);color:var(--muted)}
.chip{display:inline-block;max-width:100%;padding:1px var(--s3);border-radius:var(--r-sm);background:var(--chip);font-weight:var(--fw-med);color:var(--text);white-space:nowrap;vertical-align:middle}
.count{padding:1px var(--s3);border-radius:var(--r-pill);background:var(--chipon);color:var(--chipontext);font-weight:var(--fw-black);font-size:var(--fs-xs)}
.toggle{width:32px;height:18px;border-radius:var(--r-pill);background:var(--muted2);position:relative;display:inline-block;cursor:pointer;flex:none}
.toggle.on{background:var(--accent)}
.toggle i{position:absolute;top:2px;left:2px;width:14px;height:14px;border-radius:50%;background:var(--knob);transition:left .15s}
.toggle.on i{left:16px}

/* ---- layout ---- */
.main{width:100%;display:flex;flex-direction:column;gap:var(--s4);padding:var(--s6) max(var(--pad), calc((100% - var(--maxw))/2)) 40px}
.card{background:var(--panel);border:1px solid var(--line);border-radius:var(--r);box-shadow:var(--shadow)}
.card.pad{padding:var(--s4) var(--s5)}
.card h3{margin:0;font-size:var(--fs-md);font-weight:var(--fw-bold);color:var(--text);display:flex;justify-content:space-between;align-items:center;gap:var(--s3)}
.card h3 .tiny{color:var(--muted2);font-weight:var(--fw)}
.grid2{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s4)}
.sechead{display:flex;justify-content:space-between;align-items:flex-end;gap:var(--s4)}
.sechead b{font-family:var(--font-display);font-size:var(--fs-xl);font-weight:var(--fw-bold);letter-spacing:-.02em;line-height:var(--lh-tight)}
.sechead .hd{display:flex;align-items:baseline;gap:var(--s4);flex-wrap:wrap;min-width:0}
.sechead .hd>.small{color:var(--muted2)}
.sechead>.ctl{align-self:flex-start}
.legend{display:flex;gap:var(--s4);font-size:var(--fs-xs);color:var(--muted2);flex-wrap:wrap}
.legend span{display:flex;align-items:center;gap:var(--s1)}
.legend i{width:8px;height:8px;border-radius:50%;display:inline-block;flex:none}
.legend .lgk{font-weight:var(--fw-bold);color:var(--muted)}

/* ---- help-box: the "?" next to a page title and the panel it folds open ---- */
.hb-btn{width:22px;height:22px;padding:0;flex:none;display:inline-flex;align-items:center;justify-content:center;
  border:1px solid var(--line);border-radius:var(--r-pill);background:var(--panel);color:var(--muted);
  font-size:var(--fs-2xs);font-weight:var(--fw-bold);line-height:1;cursor:pointer;align-self:center}
.hb-btn:hover{background:var(--panel2);border-color:var(--accent);color:var(--accent)}
.hb-btn.on{background:var(--accentbg);border-color:var(--accent);color:var(--accent)}
/* the card is a sibling of the title inside .hd: order pushes it past the status line,
   flex-basis 100% drops it onto its own row under the header */
.hb-card{order:99;flex:1 1 100%;margin-top:var(--s3);padding:var(--s4) var(--s5);
  background:var(--panel);border:1px solid var(--line);border-radius:var(--r);
  font-size:var(--fs-xs);color:var(--muted);line-height:var(--lh);display:flex;flex-direction:column;gap:var(--s1)}
.hb-card .legend{margin-top:var(--s2)}

/* ==========================================================================
   ONE table primitive. every list on every page uses these four rows.
   per-page differences live only in .cols-* (grid-template-columns).
   ========================================================================== */
.tb{background:var(--panel);border:1px solid var(--line);border-radius:var(--r);box-shadow:var(--shadow);overflow:hidden}
.tb-h,.tb-r,.tb-g,.tb-f{display:grid;gap:var(--s4);align-items:center;padding:var(--cell-y) var(--cell-x)}
.tb-h{background:var(--panel2);border-bottom:1px solid var(--line);text-transform:uppercase;
      font-size:var(--fs-2xs);font-weight:var(--fw-bold);color:var(--muted);letter-spacing:.04em}
.tb-r{border-bottom:1px solid var(--line2)}
.tb-r:last-child{border-bottom:0}
.tb-r:hover{background:var(--panel2)}
.tb-r.sel{background:var(--accentbg)}
.tb-g{background:var(--panel2);border-bottom:1px solid var(--line2);font-size:var(--fs-xs);color:var(--muted)}
.tb-g.flat{display:flex;flex-wrap:wrap}
.tb-g.g2{background:var(--panel3)}
.tb-f{display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:var(--s3);
      background:var(--panel2);border-top:1px solid var(--line);color:var(--muted);font-size:var(--fs-xs)}
.tb-r.clickable,.tb-g.clickable{cursor:pointer}
.tb-r.clickable:active,.tb-g.clickable:active{background:var(--panel3)}
.tb-r>*,.tb-h>*,.tb-g>*,.tb-f>*{min-width:0}
.tb .empty{border-bottom:1px solid var(--line2)}
.tb .empty:last-child{border-bottom:0}
.pager{display:flex;align-items:center;gap:var(--s1);flex:none;flex-wrap:wrap;justify-content:flex-end}
.pager .ctl.sm{padding:0 var(--s3)}
.pg-n{min-width:30px;justify-content:center;font-variant-numeric:tabular-nums}
.pg-n.on{background:var(--accent);border-color:var(--accent);color:var(--chipontext);font-weight:var(--fw-bold)}
.pg-step{gap:var(--s1)}
.pg-prev{transform:rotate(90deg)}.pg-next{transform:rotate(-90deg)}
.pg-gap{padding:0 var(--s1);color:var(--muted2);user-select:none}
.empty{padding:var(--s8) var(--s5);text-align:center;color:var(--muted2);font-size:var(--fs-sm)}

/* column sets */
.cols-err{grid-template-columns:96px minmax(200px,280px) 150px 110px minmax(0,1fr) 56px}
.cols-rate{grid-template-columns:minmax(230px,1fr) repeat(5,96px) 96px;gap:var(--s3)}
.cols-usage{grid-template-columns:minmax(200px,1.4fr) minmax(0,1fr) repeat(4,120px)}
.cols-users{grid-template-columns:minmax(165px,1.3fr) 96px 156px 88px 92px 120px minmax(118px,1fr) minmax(118px,1fr) 104px}
.cols-rc{grid-template-columns:130px 76px 100px minmax(0,1fr)}
.cols-ga{grid-template-columns:minmax(150px,1.1fr) minmax(200px,1.5fr) minmax(190px,1.35fr) 86px 76px 118px 74px;gap:var(--s3)}
.cols-gr{grid-template-columns:110px 74px 160px minmax(130px,1fr) minmax(0,1.4fr)}
/* the two overview cards: rows sit flush inside a padded card, and their header is a
   caption rather than a filled strip: all that survives of the two classes they had */
.cols-ovr{grid-template-columns:minmax(0,1fr) 110px 64px;gap:var(--s3);padding-left:0;padding-right:0}
.tb-h.cols-ovr{background:transparent;padding-top:var(--s1);padding-bottom:var(--s2)}
.tb-h.cols-ovr div:nth-child(2),.tb-h.cols-ovr div:nth-child(3){text-align:right}
.cols-ovr .rmain{min-width:0}
.cols-ovr .rmain b{display:inline-block;max-width:100%;vertical-align:middle}
.cols-ovr .sub{font-size:var(--fs-2xs);color:var(--muted2)}
.cols-ovr .frac{font-size:var(--fs-xs);color:var(--muted);text-align:right;font-variant-numeric:tabular-nums}
.cols-ovr .rt{font-weight:var(--fw-black);text-align:right;font-variant-numeric:tabular-nums}
/* lists that used to be <table class="plain">: inside a card (notify) or a modal */
.cols-ch{grid-template-columns:minmax(90px,1fr) 66px minmax(0,1.2fr) 62px auto}
.cols-pk{grid-template-columns:minmax(0,1fr) 116px 116px 64px}
.cols-ss{grid-template-columns:minmax(0,1.2fr) 124px 110px 110px}
.cols-qt{grid-template-columns:96px minmax(120px,1fr) 76px 76px 92px}
.cols-nt{grid-template-columns:104px 64px minmax(80px,1fr) minmax(80px,1fr) minmax(0,2fr)}
/* <td> was vertical-align:top and td.num right-aligned; keep both */
.cols-ch,.cols-pk,.cols-ss,.cols-qt,.cols-nt{align-items:start}
.cols-qt .num,.tb-h.cols-usage .num{text-align:right}
.cols-ch .acts,.cols-pk .acts{display:flex;gap:var(--s2);flex-wrap:wrap}
.brk{word-break:break-all}

/* ---- rate strip (overview) ---- */
.strip{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));overflow:hidden}
.strip .cell{position:relative;height:92px;padding:var(--s4) var(--s5);display:flex;flex-direction:column;justify-content:space-between;gap:var(--s1);cursor:pointer;border-left:1px solid var(--line2);min-width:0}
.strip .cell:first-child{border-left:0}
.strip .cell:hover{background:var(--panel2)}
.strip .cell:active{background:var(--panel3)}
.strip .cell.on{background:var(--accentbg)}
.strip .cell.on::before{content:"";position:absolute;left:0;top:0;bottom:0;width:3px;background:var(--accent)}
.strip .lbl{display:flex;justify-content:space-between;align-items:center;gap:var(--s3);font-size:var(--fs-xs);font-weight:var(--fw-bold);color:var(--muted);line-height:1}
.strip .lbl .dot{width:9px;height:9px}
/* usage: the range headers are the sort control, and each machine shows its share */
.usort{display:flex;align-items:center;justify-content:flex-end;gap:var(--s1);background:transparent;border:0;padding:0;cursor:pointer;color:var(--muted);font:inherit;font-size:var(--fs-2xs);letter-spacing:.07em;text-transform:uppercase;font-weight:var(--fw-bold)}
.usort:hover{color:var(--text2)}
.usort.on{color:var(--accent)}
.usort .i{width:11px;height:11px}
.ushare{display:block;height:5px;border-radius:3px;background:var(--panel3);overflow:hidden;max-width:220px}
.ushare>i{display:block;height:100%;border-radius:3px;background:var(--accent)}
@media(max-width:700px){.usort{justify-content:flex-start;min-height:36px}.ushare{display:none}}

/* sparkline: 12 hourly points, scaled to the worst hour in view */
.jspark{margin-top:auto;padding-top:var(--s4);color:var(--accent)}
.jspark svg{display:block;width:100%;height:46px}
.jspark-x{display:flex;justify-content:space-between;align-items:baseline;gap:var(--s2);margin-top:var(--s1);color:var(--muted2);font-size:var(--fs-2xs)}

/* ---- judgement area: one window judged, what it is made of, the rest ---- */
.judge{display:grid;grid-template-columns:minmax(260px,320px) minmax(0,1fr) minmax(240px,300px);gap:var(--s4);align-items:stretch}
.judge .card{display:flex;flex-direction:column;min-width:0}
.jlbl{font-size:var(--fs-2xs);letter-spacing:.07em;text-transform:uppercase;color:var(--muted);font-weight:var(--fw-bold);margin-bottom:var(--s3)}
.jhero .jrate{display:flex;align-items:baseline;gap:var(--s4);flex-wrap:wrap}
.jhero .rate{display:flex;align-items:baseline;gap:var(--s1);line-height:1}
.jhero .rate b{font-size:var(--fs-hero);font-weight:var(--fw-black);letter-spacing:-.03em}
.jhero .rate span{font-size:var(--fs-md);font-weight:var(--fw-med);color:var(--muted)}
.jhero .sub{margin-top:var(--s4);color:var(--muted)}
.jhero .tiny{margin-top:var(--s2)}
.jbreak{gap:var(--s3)}
.jrow{display:block;width:100%;text-align:left;background:transparent;border:0;padding:var(--s2) 0;cursor:pointer;color:inherit;font:inherit;border-radius:var(--r-xs)}
.jrow:hover{background:var(--panel2)}
.jrow-h{display:flex;align-items:baseline;gap:var(--s3);min-width:0}
.jrow-h b{flex:1;min-width:0;font-weight:var(--fw-med);font-size:var(--fs-xs)}
.jrow-h .num{font-weight:var(--fw-bold)}
.jshare{color:var(--muted);width:38px;text-align:right}
.jtrack{height:5px;border-radius:3px;background:var(--panel3);overflow:hidden;margin-top:var(--s2)}
.jtrack>i{display:block;height:100%;border-radius:3px}
.jstack{display:flex;height:9px;border-radius:3px;overflow:hidden;background:var(--panel3);margin-bottom:var(--s2)}
.jstack>i{display:block;height:100%}
.jreason{display:flex;align-items:center;gap:var(--s3)}
.jreason .ellipsis{flex:1;min-width:0;font-size:var(--fs-xs)}
.jwins{gap:1px}
.jwin{display:flex;align-items:center;justify-content:space-between;gap:var(--s3);width:100%;background:transparent;border:0;cursor:pointer;color:var(--text2);font:inherit;font-size:var(--fs-xs);padding:var(--s2) var(--s2);border-radius:var(--r-xs);text-align:left;min-width:0}
.jwin:hover{background:var(--panel2)}
.jwin-v{display:flex;align-items:baseline;gap:var(--s3);flex:none}
.jwin-v b{font-size:var(--fs-md);font-weight:var(--fw-bold)}
@media(max-width:1100px){.judge{grid-template-columns:1fr 1fr}.jwins{grid-column:1/-1}}
@media(max-width:700px){.judge{grid-template-columns:1fr}.jhero .rate b{font-size:var(--fs-xl)}.jwin{min-height:44px}.jrow{min-height:44px}}

.strip .rate{display:flex;align-items:baseline;gap:var(--s1);line-height:1}
.strip .rate b{font-size:var(--fs-hero);font-weight:var(--fw-black);letter-spacing:-.02em}
.strip .rate span{font-size:var(--fs-md);font-weight:var(--fw-med);color:var(--muted)}
.strip .sub{font-size:var(--fs-2xs);color:var(--muted);line-height:var(--lh-tight)}
.strip .sub b{color:var(--text)}

/* ---- filter bar ---- */
.filters{display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap;margin-top:2px}
.fmore{display:contents}
.filters .xs{flex:none}
.fmodel{width:110px}
.fq{flex:1 1 220px;max-width:320px;min-width:160px}
.fmerge{display:flex;align-items:center;gap:var(--s3);cursor:pointer;margin-left:auto;white-space:nowrap}
.fmask{display:none}

/* ---- overview failure table cells ---- */
.c-time{display:flex;flex-direction:column;gap:var(--s1);align-items:flex-start}
.c-time .t{font-size:var(--fs-xs);color:var(--muted);white-space:nowrap;letter-spacing:-.01em}
.mtag{font-size:var(--fs-2xs);font-weight:var(--fw-black);letter-spacing:.04em;color:var(--muted2);background:var(--chip);border-radius:var(--r-xs);padding:0 var(--s1);line-height:1.4}
.c-user b{display:block;font-weight:var(--fw-bold)}
.c-user .nick{margin-top:1px}
.c-acct{display:flex;align-items:center;gap:var(--s1);min-width:0}
.c-acct .chip{min-width:0;overflow:hidden;text-overflow:ellipsis}
.c-model{color:var(--text2)}
.c-err{display:flex;align-items:center;gap:var(--s3);min-width:0}
.c-err .etext{color:var(--text2);min-width:0;flex:1 1 auto}
.c-err .etext .ecode{color:var(--text);font-weight:var(--fw-bold)}
.inline-model{display:none;color:var(--muted)}
.c-n{text-align:right}
.tb-g.thour b{color:var(--text)}

/* ---- drawer ---- */
.mask{position:fixed;inset:0;background:var(--overlay);z-index:40}
/* Centred, not a right-hand rail: this panel is a page of evidence -- a verdict, 14
   key/value rows and two context boxes -- and a 500px column beside a full-width table
   made every value wrap two or three times to read. Header and footer stay put, the
   evidence between them scrolls. Still a bottom sheet on phones (see the media query). */
.drawer{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);width:min(780px,calc(100vw - 48px));max-height:calc(100dvh - 64px);background:var(--panel);border:1px solid var(--line);border-radius:var(--r-lg);z-index:41;padding:var(--s6) var(--s7);overflow:hidden;box-shadow:0 24px 64px rgba(0,0,0,.4);display:flex;flex-direction:column;gap:var(--s5)}
.dbody{flex:1;min-width:0;min-height:0;overflow:auto;display:flex;flex-direction:column;gap:var(--s5)}
.drawer h2{margin:0;font-size:var(--fs-lg);font-weight:var(--fw-black)}
.dhd{display:flex;justify-content:space-between;align-items:center;gap:var(--s3)}
.dhandle{width:36px;height:4px;border-radius:var(--r-pill);background:var(--line);margin:0 auto}
.verdict{padding:var(--s4) var(--s5);border-radius:var(--r);display:flex;flex-direction:column;gap:var(--s1)}
.verdict.up{background:var(--redbg);border:1px solid var(--red)}
.verdict.user{background:var(--bluebg);border:1px solid var(--blue)}
.verdict .k{font-size:var(--fs-xs);font-weight:var(--fw-bold)}
.verdict .t{font-weight:var(--fw-black);font-size:var(--fs-lg)}
.kv{display:grid;grid-template-columns:104px 1fr;gap:var(--s3) var(--s5);font-size:var(--fs-sm)}
.kv .k{color:var(--muted2)}
.kv .v{overflow-wrap:anywhere;min-width:0}
.ctx{padding:var(--s4);border-radius:var(--r-sm);background:var(--panel3);border:1px solid var(--line2);display:flex;flex-direction:column;gap:var(--s2)}
.ctx .k{font-size:var(--fs-xs);font-weight:var(--fw-bold);color:var(--muted)}
.ctx .row{display:flex;justify-content:space-between;gap:var(--s3)}
.actions{display:flex;gap:var(--s3);justify-content:flex-end;margin-top:auto}
.actions .ctl{flex-grow:1;justify-content:center;font-weight:var(--fw-bold)}

/* ---- modal / forms ---- */
.modal-mask{position:fixed;inset:0;background:var(--overlay);z-index:50;display:grid;place-items:center;padding:var(--s6)}
.modal{background:var(--panel);border-radius:var(--r-lg);width:min(760px,100%);max-height:92vh;overflow:auto;padding:var(--s7);border:1px solid var(--line)}
.modal h2{margin:0 0 var(--s5);font-size:var(--fs-lg);font-weight:var(--fw-black)}
.form{display:grid;grid-template-columns:repeat(2,1fr);gap:var(--s4)}
.form .full{grid-column:1/-1}
.form label{display:flex;flex-direction:column;gap:var(--s1);font-size:var(--fs-xs);color:var(--muted)}
.form input,.form select,.form textarea{width:100%;height:34px;padding:0 var(--s3);border:1px solid var(--line);border-radius:var(--r-sm);background:var(--panel2);color:var(--text);outline:none}
.form textarea{height:auto;padding:var(--s3);font-family:ui-monospace,Menlo,Consolas,monospace;font-size:var(--fs-xs)}
.form input:focus,.form select:focus,.form textarea:focus{border-color:var(--accent)}
.form input:focus-visible,.form select:focus-visible,.form textarea:focus-visible{outline:2px solid var(--focus);outline-offset:2px}
.form .hint{font-size:var(--fs-xs);color:var(--muted2)}
.modal .actions{margin-top:var(--s5)}
.modal .actions .ctl{flex-grow:0}
.code{background:var(--panel2);border:1px solid var(--line);border-radius:var(--r-sm);padding:var(--s3) var(--s4);font-family:ui-monospace,Menlo,Consolas,monospace;font-size:var(--fs-xs);white-space:pre-wrap;word-break:break-all}
.toast{position:fixed;bottom:var(--s7);left:50%;transform:translateX(-50%);background:var(--chipon);color:var(--chipontext);padding:var(--s3) var(--s5);border-radius:var(--r-sm);z-index:99;font-weight:var(--fw-med);box-shadow:0 8px 24px rgba(0,0,0,.35)}
pre.preview{background:var(--panel2);border:1px solid var(--line);border-radius:var(--r-sm);padding:var(--s4);white-space:pre-wrap;font-size:var(--fs-xs);max-height:420px;overflow:auto;margin:0}

/* ---- machines page ---- */
.mcard{padding:var(--s4) var(--s5);display:flex;flex-direction:column;gap:var(--s3)}
.mcard .hd{display:flex;justify-content:space-between;align-items:flex-start;gap:var(--s3)}
.mcard .name{font-weight:var(--fw-black);font-size:var(--fs-md);display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap}
.mcard .site{font-size:var(--fs-xs);color:var(--muted);word-break:break-all}
.mcard .mono{word-break:break-all}
.mcard .nums span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:block}
.mcard .nums{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--s3)}
.mcard .nums div{background:var(--panel3);border:1px solid var(--line2);border-radius:var(--r-sm);padding:var(--s3) var(--s3)}
.mcard .nums b{display:block;font-size:var(--fs-xl);font-weight:var(--fw-black);font-variant-numeric:tabular-nums;line-height:var(--lh-tight)}
.mcard .nums span{font-size:var(--fs-2xs);color:var(--muted2)}
.mcard .macts{display:flex;gap:var(--s2);flex-wrap:wrap;justify-content:flex-end}
details summary{cursor:pointer;color:var(--muted);font-size:var(--fs-xs)}

/* ---- login ---- */
.login{min-height:100vh;display:grid;place-items:center;padding:var(--s6)}
.login .card{width:min(380px,100%);padding:var(--s8)}
.login h1{margin:0 0 var(--s6);font-size:var(--fs-xl);font-weight:var(--fw-black)}
.login p{color:var(--muted);margin:0 0 var(--s6)}
.login input{width:100%;height:36px;padding:0 var(--s3);border:1px solid var(--line);border-radius:var(--r-sm);background:var(--panel2);color:var(--text);margin-bottom:var(--s4);outline:none}
.login input:focus{border-color:var(--accent)}
.login input:focus-visible{outline:2px solid var(--focus);outline-offset:2px}
.login .ctl{width:100%;justify-content:center}
.login .ctl svg.i{margin-right:2px}
.ordiv{display:flex;align-items:center;gap:var(--s3);margin:var(--s2) 0 var(--s3);color:var(--muted2);font-size:var(--fs-xs)}
.ordiv:before,.ordiv:after{content:"";flex:1;height:1px;background:var(--line)}
.ordiv:empty{gap:0}   /* the "或使用密码" caption is gone; keep the rule unbroken */

/* ---- listbox: the one dropdown in the app (no native <select> is left) ---- */
.xs{position:relative;display:inline-block;min-width:0}
.xs-btn{width:100%;justify-content:space-between;gap:var(--s3)}
.xs-btn.on{border-color:var(--accent)}
.xs-caret{color:var(--muted2);width:12px;height:12px;transition:transform .15s}
.xs.open .xs-caret{transform:rotate(180deg)}
.xs-pop{position:absolute;left:0;min-width:100%;max-width:min(90vw,360px);background:var(--panel);border:1px solid var(--line);border-radius:var(--r-sm);box-shadow:0 12px 32px rgba(0,0,0,.35);padding:var(--s1);z-index:60;display:flex;flex-direction:column;max-height:min(340px,60vh)}
.xs-pop.to-down{top:calc(100% + var(--s2))}
.xs-pop.to-up{bottom:calc(100% + var(--s2))}
.xs-search{display:flex;align-items:center;gap:var(--s2);padding:var(--s2) var(--s3);border-bottom:1px solid var(--line2);margin-bottom:var(--s1);color:var(--muted2);flex:none}
.xs-search input{flex:1;min-width:0;border:0;background:transparent;color:var(--text);outline:0;font-size:var(--fs-xs)}
.xs-search input::placeholder{color:var(--muted2)}
.xs-list{overflow:auto;min-height:0}
.xs-opt{display:flex;align-items:center;justify-content:space-between;gap:var(--s3);padding:var(--s2) var(--s3);border-radius:var(--r-xs);cursor:pointer;color:var(--text);white-space:nowrap}
/* keyboard and pointer share one highlight, so arrowing and hovering cannot disagree */
.xs-opt.active{background:var(--panel2)}
.xs-opt.on{background:var(--accentbg);color:var(--accent);font-weight:var(--fw-bold)}
.xs-opt.grp{cursor:default;color:var(--muted2);font-size:var(--fs-2xs);font-weight:var(--fw-bold);letter-spacing:.04em;padding-top:var(--s3)}
.xs-opt.grp.active,.xs-opt.grp:hover{background:transparent}
.xs-none{padding:var(--s4) var(--s3);color:var(--muted2);font-size:var(--fs-xs);text-align:center}
.xs-check{width:13px;height:13px;color:var(--accent)}
.top .xs{flex:none}

/* ==========================================================================
   machine rates page
   ========================================================================== */
.rbar{display:flex;align-items:center;gap:var(--s3);flex-wrap:wrap;margin-top:2px}
.mchips{display:flex;gap:var(--s2);flex-wrap:wrap;min-width:0}
.mchip{display:flex;align-items:center;gap:var(--s2);height:32px;padding:0 var(--s4);border:1px solid var(--line);border-radius:var(--r-pill);background:var(--panel);color:var(--muted);font-weight:var(--fw-bold);font-size:var(--fs-xs);cursor:pointer;white-space:nowrap}
.mchip:hover{border-color:var(--accent)}
.mchip.on{border-color:var(--accent);background:var(--accentbg);color:var(--text)}
.mchip .ck{width:15px;height:15px;border-radius:var(--r-xs);border:1px solid var(--line);display:flex;align-items:center;justify-content:center;color:var(--chipontext);flex:none}
.mchip .ck svg{width:11px;height:11px;stroke-width:3.2}

/* summary table (natural days only since P3d: the rolling columns were the strip again) */
.tb-h .c-r,.tb-h .c-up{text-align:right}
.tb-r.off{opacity:.45}
.tb-r.rtfoot{background:var(--panel2);border-bottom:0}
.c-m{display:flex;align-items:center;gap:var(--s3);min-width:0}
.c-m .sw{width:9px;height:9px;border-radius:var(--r-xs);flex:none}
.c-m .nm{display:flex;flex-direction:column;gap:1px;min-width:0}
.c-m b{font-weight:var(--fw-black)}
.c-r{display:flex;flex-direction:column;align-items:flex-end;gap:1px;line-height:var(--lh-tight)}
.c-r b{font-size:var(--fs-lg);font-weight:var(--fw-black)}
.c-r .rsub{font-size:var(--fs-2xs);color:var(--muted2)}
.c-up{text-align:right;font-variant-numeric:tabular-nums;color:var(--text2)}

/* hourly (or daily) upstream failure rate matrix: fixed columns, scrolls inside .tbx */
.tbx{overflow-x:auto;margin-top:var(--s3);border:1px solid var(--line);border-radius:var(--r)}
.hrtb{width:max-content;min-width:100%}
.cols-hr{grid-template-columns:minmax(140px,1fr) repeat(var(--hn,19),50px);gap:var(--s2)}
.cols-hr .c-hm{display:flex;align-items:center;gap:var(--s2);min-width:0}
.cols-hr .c-hm .sw{width:9px;height:9px;border-radius:var(--r-xs);flex:none}
.cols-hr .c-hm b{font-weight:var(--fw-black)}
.cols-hr .c-hc{text-align:center;font-size:var(--fs-xs);font-weight:var(--fw-bold);white-space:nowrap}
.tb-h.cols-hr .c-hc{font-weight:var(--fw-bold);font-size:var(--fs-2xs);letter-spacing:0}
.tb-r.cols-hr:last-child{border-bottom:0}

/* ==========================================================================
   usage / accounts / expiry cells
   ========================================================================== */
.ucell{display:flex;flex-direction:column;align-items:flex-end;gap:1px;line-height:var(--lh-tight);text-align:right}
.ucell b{font-size:var(--fs-md);font-weight:var(--fw-black)}
.ucell .tiny{color:var(--muted2)}
.tb-g.umhead{font-size:var(--fs-sm);color:var(--text);border-bottom:1px solid var(--line)}
.tb-g.ughead svg.i{color:var(--muted2);transition:transform .12s}
.ughead>div:first-child{display:flex;align-items:center;gap:var(--s2)}
.unum{display:inline-block;width:22px;text-align:right;margin-right:var(--s3);font-size:var(--fs-2xs)}

.aq{display:flex;flex-direction:column;gap:var(--s2)}
.aqw{display:flex;flex-direction:column;gap:3px}
.aqline{display:flex;justify-content:space-between;align-items:baseline;gap:var(--s3)}
.aqline b{font-size:var(--fs-md);font-weight:var(--fw-black)}
.abar{height:7px;border-radius:var(--r-xs);background:var(--line2);overflow:hidden}
.abar i{display:block;height:100%;border-radius:var(--r-xs);transition:width .2s}

.cols-users .num b,.cols-users .col-tier b{font-size:var(--fs-md);font-weight:var(--fw-black)}
.cols-users .col-user b{display:block}
.cols-users .aqline{gap:var(--s2)}
.cols-users .aqline b{font-size:var(--fs-sm)}
.tb-h.cols-users .clickable{user-select:none}
/* the expiry cell: date + pencil, or the date editor in its place */
.expcell{display:flex;align-items:flex-start;gap:var(--s2);min-width:0}
.expval{min-width:0;flex:1 1 auto}
.expval .pill{margin-left:var(--s2)}
.ebtn{margin-top:-1px}
.expedit,.renewbox{display:flex;align-items:center;gap:var(--s2);flex-wrap:wrap}
.expedit .xin{flex:1 1 118px;min-width:110px}
input.xin{height:28px;padding:0 var(--s3);font-size:var(--fs-xs);cursor:text;
  border:1px solid var(--line);border-radius:var(--r-sm);background:var(--panel);color:var(--text)}
input.xin:focus-visible{outline:2px solid var(--focus);outline-offset:1px}
.renewbox{gap:var(--s3);background:var(--panel3)}
.renewbox .xin{width:72px;text-align:right}
.renewbox .rhint{flex:1 1 100%}
/* actions: the renew button and the reminder switch, always on one line */
.cols-users .col-act{display:flex;align-items:center;gap:var(--s3)}
.cols-users .col-act .ctl.on{border-color:var(--accent);background:var(--accentbg)}
.mchip .dot{margin-right:1px}
/* the quota cell (two bars, a provenance line and one reset-credit line per site) is
   the tallest, so every other cell in the row reads from the top */
.tb-r.cols-ga,.tb-h.cols-ga{align-items:start}
.cols-ga .num b,.cols-ga .col-acct>b{font-size:var(--fs-md);font-weight:var(--fw-black)}
.cols-ga .col-acct>b,.cols-ga .col-s1>b,.cols-ga .col-s2>b{display:block}
.cols-ga .aqline b{font-size:var(--fs-sm)}
.cols-ga .aq{gap:var(--s1)}
.cols-ga .pill{margin-top:2px}
/* an idle account's quota block is the last snapshot, not a live reading:
   same colours, turned down, so it cannot be mistaken for a current number */
.cols-ga .aq.muted{opacity:.62}
/* site cell: one line per site - a state dot, the machine code, then where that
   machine comes out to the internet. The origin moved into the expanded row (P3f). */
.cols-ga .site{display:flex;flex-direction:column;gap:5px;align-items:flex-start}
.cols-ga .sitem{display:flex;flex-direction:column;gap:1px;min-width:0;max-width:100%}
.cols-ga .sline{display:flex;align-items:baseline;gap:var(--s2);flex-wrap:wrap}
.cols-ga .sline b{font-size:var(--fs-sm);font-weight:var(--fw-black)}
.cols-ga .sline.muted b{font-weight:var(--fw-bold)}
.sdot{width:7px;height:7px;border-radius:50%;background:var(--muted2);flex:none;align-self:center}
.sdot.on{background:var(--green)}
.cols-ga .pill{margin-top:0}
/* an account hidden by hand, shown only because the reader asked to see the hidden ones */
.tb-r.cols-ga.hid{opacity:.55}
/* the two grey lines under the idle view: what it is not showing */
.tb-f.ganote{justify-content:flex-start;gap:var(--s5);border-top:1px solid var(--line2)}
/* reset credits: the count and the button that spends one, on one line under the bars */
.crd{display:flex;align-items:center;gap:var(--s2);flex-wrap:wrap;margin-top:2px}
.crd .ctl.sm{height:26px;min-height:26px;padding:0 var(--s3);font-size:var(--fs-2xs)}
.crd .ulink{margin-top:0}
.surl{font-size:var(--fs-xs);color:var(--accent);text-decoration:none;word-break:break-all;line-height:var(--lh-tight)}
.surl:hover{text-decoration:underline}
.ulink{background:var(--chip);color:var(--text);border:1px solid var(--line);border-radius:var(--r-sm);
  padding:2px var(--s3);font-size:var(--fs-2xs);font-weight:var(--fw-med);cursor:pointer;margin-top:2px}
.ulink:hover:not(:disabled){background:var(--panel3);border-color:var(--accent);color:var(--accent)}
.ulink:disabled{opacity:.5;cursor:default}

/* Settings page: a sticky section rail on the left, one scroll of six sections on the
   right. This replaces the notify page's two-column card grid, so .grid2.gstart and
   .vstack are gone with it. */
.setwrap{display:grid;grid-template-columns:184px minmax(0,1fr);gap:var(--s6);align-items:start}
.setnav{position:sticky;top:calc(var(--topH) + var(--s4));display:flex;flex-direction:column;gap:2px;min-width:0}
.setnav a{padding:var(--s2) var(--s4);border-radius:var(--r-sm);color:var(--muted);font-size:var(--fs-sm);font-weight:var(--fw-med);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.setnav a:hover{background:var(--panel2);color:var(--text)}
.setnav a.on{background:var(--accentbg);color:var(--accent);font-weight:var(--fw-bold)}
.setbody{display:flex;flex-direction:column;gap:var(--s7);min-width:0}
.setbody>section{display:flex;flex-direction:column;gap:var(--s4);min-width:0;
  scroll-margin-top:calc(var(--topH) + var(--s5))}
/* the last section has to be able to reach the top of the viewport, or its rail entry
   can never light up (the page simply runs out of scroll before it gets there) */
.setbody>section:last-child{min-height:calc(100vh - var(--topH) - var(--s7))}
/* a section heading is one step below the page title */
.sechead.sub b{font-size:var(--fs-lg);font-weight:var(--fw-bold);letter-spacing:-.015em}
/* a labelled group of form fields (rules section, machine modal) */
.fgrp{display:flex;flex-direction:column;gap:var(--s3)}
.fgrp+.fgrp{margin-top:var(--s5)}
.fgrp>h4{margin:0;font-size:var(--fs-2xs);font-weight:var(--fw-bold);color:var(--muted);letter-spacing:.04em;
  padding-bottom:var(--s2);border-bottom:1px solid var(--line2)}
.tb-f.cfoot{background:transparent;border-top:1px solid var(--line2);margin-top:var(--s3);padding:var(--s3) 0 0}

.secadd{display:flex;gap:var(--s3);align-items:center;flex-wrap:wrap;margin:var(--s3) 0}
.secadd input.ctl{width:220px}
.swlabel{display:flex;align-items:center;gap:var(--s3);cursor:pointer;white-space:nowrap}
.modal.wide{width:min(960px,100%)}
.modal.wide.ai{width:min(820px,100%)}
.airesult{background:var(--panel3);margin-bottom:var(--s3)}

/* ==========================================================================
   breakpoints
   ========================================================================== */
@media (min-width:1600px){
  .cols-rate{grid-template-columns:minmax(230px,1fr) repeat(5,112px) 104px}
}
/* two-column pages start at 1280 (see the tablet block); match the form there */
@media (min-width:1280px){
  .form.f3{grid-template-columns:repeat(3,1fr)}
}

/* ---- tablet: 900 - 1279 ---- */
@media (max-width:1279px){
  :root,:root[data-theme]{--pad:18px}
  .strip{grid-template-columns:repeat(3,minmax(0,1fr))}
  .strip .cell:nth-child(4){border-left:0}
  .strip .cell:nth-child(n+4){border-top:1px solid var(--line2)}
  .cols-err{grid-template-columns:96px minmax(180px,260px) 150px minmax(0,1fr) 56px}
  .c-model{display:none}
  .inline-model{display:inline}
  .grid2{grid-template-columns:1fr}
  .cols-rate .col-day2,.cols-rate .col-up{display:none}
  .cols-rate{grid-template-columns:minmax(230px,1fr) repeat(4,96px)}
  .cols-usage{grid-template-columns:minmax(180px,1.2fr) repeat(4,110px)}
  .cols-usage>.uspacer,.cols-usage>.c-sub{display:none}
  .cols-users{grid-template-columns:minmax(140px,1.2fr) 88px 150px 84px 112px minmax(110px,1fr) 100px}
  .cols-users>.col-consumed,.cols-users>.col-month{display:none}
  .cols-rc{grid-template-columns:120px 70px 96px minmax(0,1fr)}
  /* "served" is the one column the expanded row repeats per site, so it goes first */
  .cols-ga{grid-template-columns:minmax(136px,1fr) minmax(170px,1.25fr) minmax(170px,1.3fr) 80px 108px 72px}
  .cols-ga>.col-served{display:none}
  .cols-gr{grid-template-columns:100px 64px 132px minmax(90px,.8fr) minmax(0,1.4fr)}
}
@media (max-width:1279px) and (min-width:900px){
  .fq{max-width:none}
}

/* ---- mobile: <= 899 ---- */
@media (max-width:899px){
  /* the wrapped top bar measures 8+44+8+44+8+1: the hour bar sticks right under it */
  :root,:root[data-theme]{--pad:14px;--topH:113px}
  .only-m{display:flex!important}
  .only-d{display:none!important}
  .top{height:auto;flex-wrap:wrap;gap:var(--s3);padding:var(--s3) var(--pad) var(--s3)}
  .top>.grow{display:none}
  .top>div.ctl{display:none}
  .top .brand{flex:0 0 auto;order:0;min-height:44px}
  /* the wordmark is the one thing on this bar the tab strip already tells you */
  .top .brand-name{display:none}
  /* the palette sits with the icon buttons instead of claiming a row of its own */
  .top .xs.palette-select{order:1;flex:0 1 auto!important;width:auto!important;min-width:0;max-width:132px}
  .top>button.ctl{order:2;width:44px;padding:0;justify-content:center}
  .top>a.small{order:3;display:flex;align-items:center;min-height:44px;padding:0 var(--s1)}
  .top .xs:not(.palette-select){order:4;flex:1 1 100%!important;width:100%!important}
  .top .tabs{position:fixed;left:0;right:0;bottom:0;height:calc(52px + env(safe-area-inset-bottom));padding-bottom:env(safe-area-inset-bottom);background:var(--panel);border-top:1px solid var(--line);display:flex;gap:0;z-index:30;box-shadow:0 -2px 12px rgba(0,0,0,.18)}
  /* eight tabs cannot fit one phone row: scroll them instead of shrinking the type further */
  .top .tabs{overflow-x:auto;scrollbar-width:none;-webkit-overflow-scrolling:touch}
  .top .tabs::-webkit-scrollbar{display:none}
  .top .tabs a{flex:0 0 auto;min-width:60px;display:flex;align-items:center;justify-content:center;border-radius:0;font-size:var(--fs-xs);font-weight:var(--fw-med);height:52px;white-space:nowrap;padding:0 var(--s4);letter-spacing:normal;scroll-margin-inline:var(--s3)}
  .top .tabs a.on{background:transparent;color:var(--accent);box-shadow:inset 0 -2px 0 var(--accent)}
  .main{padding:var(--s4) var(--pad) calc(72px + env(safe-area-inset-bottom));gap:var(--s4)}
  .card.pad{padding:var(--s4) var(--s4)}
  .sechead{flex-direction:column;align-items:flex-start;gap:var(--s1)}
  /* the column stack sizes .hd to its content, so a long status line used to push the
     row (and now the "?" button) past the right edge, where overflow-x:hidden ate it */
  .sechead .hd{flex-wrap:wrap;width:100%}
  .sechead b{white-space:nowrap}
  .ctl{min-height:44px;height:44px}
  .ctl.sm{height:36px;min-height:36px}
  .seg button{min-height:38px}

  /* settings: the rail becomes a scrolling seg pinned under the top bar */
  .setwrap{grid-template-columns:minmax(0,1fr);gap:var(--s4)}
  .setnav{position:sticky;top:var(--topH);z-index:10;flex-direction:row;gap:var(--s2);
    overflow-x:auto;scrollbar-width:none;-webkit-overflow-scrolling:touch;
    background:var(--bg);padding:var(--s2) 0}
  .setnav::-webkit-scrollbar{display:none}
  .setnav a{flex:0 0 auto;display:flex;align-items:center;min-height:38px;
    border:1px solid var(--line);background:var(--panel);scroll-margin-inline:var(--s3)}
  .setnav a.on{border-color:var(--accent)}
  .setbody{gap:var(--s6)}
  .setbody>section{scroll-margin-top:calc(var(--topH) + 52px)}
  .seg-kind{flex:1 1 100%;overflow-x:auto;scrollbar-width:none}
  .seg-kind::-webkit-scrollbar{display:none}
  .seg-kind button{flex:1 1 0;justify-content:center;padding:var(--s1) var(--s2);font-size:var(--fs-xs)}

  /* ---- one mobile rule for every table ---- */
  .tb-h{display:none}
  .tb-r,.tb-g{display:flex;flex-wrap:wrap;gap:var(--s3);padding:var(--s4) var(--s4)}
  .tb-f{padding:var(--s4)}
  .tb-r>[data-l]::before,.tb-g>[data-l]::before{content:attr(data-l);display:block;
    font-size:var(--fs-2xs);font-weight:var(--fw-bold);color:var(--muted2);letter-spacing:.04em;line-height:var(--lh-tight)}
  .tb-r>[data-l].nl::before,.tb-g>[data-l].nl::before{content:none}
  .tb-r>[data-l].il::before,.tb-g>[data-l].il::before{display:inline;margin-right:var(--s1)}

  /* GPT accounts on a phone: one card per account.
     The generic card rule gives every cell its own full-width line plus a label line
     above it, which for this table meant ~14 lines of mostly air - including two lines
     spent rendering an empty "site 2". Here the three short numbers share a row, their
     labels move onto the value's line, and anything empty is dropped. */
  .tb-r.cols-ga{gap:var(--s2) var(--s4);padding:var(--s4)}
  .cols-ga>.site{flex:1 1 100%}
  /* a bold site code with its own state dot needs no "site" caption to explain it */
  .tb-r.cols-ga>.site::before{content:none}
  .cols-ga>.col-risk,.cols-ga>.col-gquota{flex:1 1 100%}
  .cols-ga>.col-rate,.cols-ga>.col-conc{flex:1 1 auto;min-width:96px;text-align:left}
  /* rate and concurrency are short, so pull them onto one row; in DOM order the two
     full-width cells (quota, risk) sit between them and would force three lines */
  .cols-ga>.col-acct{order:0}
  .cols-ga>.site{order:1}
  .cols-ga>.col-rate{order:2}
  .cols-ga>.col-conc{order:4}
  .cols-ga>.col-risk{order:5}
  .cols-ga>.col-gquota{order:6}
  .cols-ga>.col-rate>b,.cols-ga>.col-conc>b{font-size:var(--fs-lg)}
  .cols-ga .sline{margin-bottom:1px}

  /* rate strip: horizontal snap scroller */
  .strip{display:flex;overflow-x:auto;scroll-snap-type:x mandatory;-webkit-overflow-scrolling:touch}
  .strip .cell{flex:0 0 auto;min-width:148px;scroll-snap-align:start;border-top:0;border-left:1px solid var(--line2)}
  .strip .cell:first-child{border-left:0}

  /* filters: segment + sheet */
  .filters{gap:var(--s3)}
  .filters .seg-side,.filters .seg-users{flex:1 1 100%;display:flex}
  .filters .seg-side button,.filters .seg-users button{flex:1 1 0;justify-content:center;padding:var(--s1) var(--s1);font-size:var(--fs-xs)}
  .filters .fbtn{flex:1 1 100%;justify-content:center;font-weight:var(--fw-bold)}
  .fmask{display:block;position:fixed;inset:0;background:var(--overlay);z-index:44}
  .fmore{display:none}
  .fmore.open{display:flex;flex-direction:column;gap:var(--s3);position:fixed;left:0;right:0;bottom:0;z-index:45;background:var(--panel);border-top:1px solid var(--line);border-radius:var(--r-lg) var(--r-lg) 0 0;padding:var(--s4) var(--s4) calc(var(--s4) + env(safe-area-inset-bottom));max-height:86dvh;overflow:auto}
  .fmore.open .fhd{display:flex;justify-content:space-between;align-items:center;font-size:var(--fs-md);font-weight:var(--fw-black)}
  .fmore.open .seg-win{display:flex;flex-wrap:wrap}
  .fmore.open .seg-win button{flex:1 1 30%;justify-content:center}
  .fmore.open .xs{width:100%!important;flex:none}
  .fmore.open .fmodel,.fmore.open .fq{width:100%;max-width:none;flex:none}
  .fmore.open .fmerge{margin-left:0;justify-content:space-between;min-height:44px}
  .fmore.open .fft{display:flex;gap:var(--s3)}
  .fmore.open .fft .ctl{flex:1 1 0;justify-content:center;font-weight:var(--fw-bold)}

  /* overview failure table -> card flow */
  /* overflow:hidden would make .tb the sticky scrollport -- it never scrolls, so the first hour
     bar got shoved var(--topH) down on top of the first row instead of sticking to the page.
     clip keeps the rounded corners without capturing the sticky. */
  .tb{overflow:clip}
  .tb-g.thour{position:sticky;top:var(--topH);z-index:10;padding:var(--s2) var(--s4);gap:var(--s3);font-size:var(--fs-2xs)}
  .cols-err{align-items:baseline;gap:2px var(--s3)}
  .cols-err .c-time{flex:0 0 auto;order:1;flex-direction:row;align-items:center;gap:var(--s2)}
  .cols-err .c-n{order:2;margin-left:auto;text-align:right;white-space:nowrap}
  .cols-err .c-user{order:3;flex:1 1 100%;margin-top:2px}
  .cols-err .c-user .nick{display:none}
  .cols-err .c-acct{order:4;flex:0 1 auto;max-width:62%;font-size:var(--fs-xs);color:var(--muted)}
  .cols-err .c-acct .chip{background:transparent;padding:0;color:var(--muted);font-weight:var(--fw-med)}
  .cols-err .c-model{order:5;display:block;flex:1 1 auto;color:var(--muted2);font-size:var(--fs-2xs)}
  .cols-err .c-model::before{content:"\00b7 ";display:inline;font-size:inherit;color:inherit;font-weight:inherit;letter-spacing:0}
  .cols-err .c-err{order:6;flex:1 1 100%;flex-direction:column;align-items:flex-start;gap:var(--s1);margin-top:3px}
  .cols-err .c-err .etext{white-space:normal;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;text-overflow:ellipsis;line-height:1.4}
  .inline-model{display:none}

  /* per-entity lists: narrower columns, but still a table -- three short cells per row
     read better than three labelled lines */
  .tb-h.cols-ovr{display:grid}
  .tb-r.cols-ovr{display:grid;grid-template-columns:minmax(0,1fr) 88px 56px;gap:var(--s3);padding:var(--s3) 0}

  /* machine rates */
  .rbar{gap:var(--s3)}
  .seg-range{flex:1 1 100%;display:flex}
  .seg-range button{flex:1 1 0;justify-content:center;padding:var(--s1) 2px;font-size:var(--fs-xs)}
  .mchips{flex:1 1 100%;flex-wrap:nowrap;overflow-x:auto;-webkit-overflow-scrolling:touch;scrollbar-width:none;padding-bottom:2px}
  .mchips::-webkit-scrollbar{display:none}
  .mchip{height:38px;flex:0 0 auto}
  .cols-rate{align-items:center;gap:var(--s3) 0;padding:var(--s4) var(--s4)}
  .cols-rate .c-m{flex:1 1 60%;order:1}
  .cols-rate .c-up{flex:0 0 auto;order:2;margin-left:auto;display:flex;align-items:baseline;gap:var(--s2);font-size:var(--fs-xs)}
  .cols-rate .c-up::before{display:inline;font-size:var(--fs-2xs)}
  .cols-rate .col-day2,.cols-rate .col-up{display:flex}
  .cols-rate .c-r{order:3;flex:1 1 17%;align-items:center;text-align:center;background:var(--panel3);border:1px solid var(--line2);border-radius:var(--r-sm);padding:var(--s1) 2px;margin-right:var(--s1);min-width:0}
  .cols-rate .c-r::before{text-align:center}
  .cols-rate .c-r.col-d14{margin-right:0}
  .cols-rate .c-r b{font-size:var(--fs-md)}
  .cols-rate .c-r .rsub{font-size:var(--fs-2xs)}
  .rtfoot .c-r{background:var(--panel)}
  .tb-h.cols-hr{display:grid}
  .tb-r.cols-hr{display:grid;gap:var(--s2);padding:var(--cell-y) var(--s4)}
  .cols-hr{grid-template-columns:minmax(88px,1fr) repeat(var(--hn,19),44px)}
  .cols-hr .c-hm .sw{display:none}
  .cols-hr .c-hc{font-size:var(--fs-2xs)}

  /* usage */
  .cols-usage>div:first-child{flex:1 0 100%;min-width:0}
  .cols-usage>.uspacer,.cols-usage>.c-sub{display:none}
  .cols-usage .ucell{flex:1 1 calc(50% - var(--s2));align-items:flex-start;text-align:left;background:var(--panel3);border:1px solid var(--line2);border-radius:var(--r-sm);padding:var(--s2) var(--s3)}
  .tb-g.umhead .ucell,.tb-g.ughead .ucell{background:var(--panel)}
  /* the machine row used to print its own range caption under each amount (S7); with that
     gone, the data-l label is the only thing naming the column here, so let it through */
  .cols-usage .ucell b{font-size:var(--fs-md)}

  /* users: identity on top, then the date, the money, the two bars, the actions last */
  .cols-users{gap:var(--s3) var(--s4)}
  .cols-users>.col-user{flex:1 1 100%;order:1;min-width:0}
  .cols-users>.col-exp{flex:1 1 auto;order:2;display:block}
  .cols-users>.col-tier{flex:0 0 auto;order:3;text-align:right;margin-left:auto;display:block}
  .cols-users>.col-bal,.cols-users>.col-consumed,.cols-users>.col-rech{flex:1 1 calc(33% - var(--s4));order:4;text-align:left;display:block}
  .cols-users>.col-week,.cols-users>.col-month{flex:1 0 100%;display:flex}
  .cols-users>.col-week{order:5}
  .cols-users>.col-month{order:6}
  /* the editor needs the whole row to itself, or the date input and its two buttons
     would have to share the line with the plan column */
  .cols-users>.col-exp.editing{flex:1 0 100%;margin-right:0}
  .expedit .xin{flex:1 1 130px}
  .cols-users>.col-act{flex:1 0 100%;order:7;display:flex}
  .renewbox{gap:var(--s2) var(--s3)}
  .renewbox .xin{width:64px}
  .cols-rc{gap:var(--s2) var(--s4)}
  .cols-rc>[data-l]:nth-child(-n+3){flex:0 0 auto}
  .cols-rc>[data-l]:last-child{flex:1 0 100%}

  /* drawer -> bottom sheet */
  .drawer{top:auto;left:0;right:0;bottom:0;transform:none;width:100%;height:100dvh;max-height:100dvh;border:0;border-radius:var(--r-lg) var(--r-lg) 0 0;padding:var(--s3) var(--s5) calc(var(--s4) + env(safe-area-inset-bottom));gap:var(--s4)}
  .dbody{gap:var(--s4)}
  .drawer .dhd{position:sticky;top:0;background:var(--panel);padding:var(--s2) 0 var(--s3);z-index:2}
  .drawer .actions{position:sticky;bottom:0;background:var(--panel);padding:var(--s3) 0 var(--s1);margin-top:auto;flex-wrap:wrap}
  .kv{grid-template-columns:76px 1fr;gap:var(--s3) var(--s3)}

  /* machines / notify */
  .mcard .hd{flex-direction:column}
  .mcard .macts{justify-content:flex-start;width:100%}
  .modal{padding:var(--s5);border-radius:var(--r-lg)}
  .form{grid-template-columns:1fr}
  /* the lists that were <table class="plain">: one labelled line per cell, like every
     other table on a phone; the action buttons keep their own row */
  .cols-ch>.acts,.cols-pk>.acts{flex:1 0 100%;padding-top:var(--s2)}
  .cols-ch>.acts::before,.cols-pk>.acts::before{content:none}
  .cols-nt,.cols-qt,.cols-ss,.cols-pk,.cols-ch{gap:var(--s2) var(--s4)}

  .secadd{flex-direction:column;align-items:stretch}
  .secadd input.ctl,.secadd .ctl{width:100%;justify-content:center}
  .secadd label{justify-content:space-between;padding:var(--s1) 2px}
}

/* boot gate: invisible for a fast auth check, a quiet mark only if it drags */
.bootwrap{min-height:100vh;display:grid;place-items:center;opacity:0;animation:bootfade .25s ease-out .3s forwards}
.bootmark{width:44px;height:44px;border-radius:var(--r);display:grid;place-items:center;
  background:var(--panel);border:1px solid var(--line);color:var(--accent)}
.bootmark svg.i{width:22px;height:22px;animation:bootpulse 1.4s ease-in-out infinite}
@keyframes bootfade{to{opacity:1}}
@keyframes bootpulse{0%,100%{opacity:.35}50%{opacity:1}}
@media (prefers-reduced-motion:reduce){.bootwrap{animation-delay:.3s;animation-duration:0s}.bootmark svg.i{animation:none;opacity:.7}}

/* Failure scopes share the existing table and mobile layout. */
.failure-note{display:flex;align-items:center;justify-content:space-between;gap:12px;color:var(--muted);font-size:var(--fs-xs);margin:0 0 12px}
.unknown-list{margin-bottom:16px}.unknown-row{display:grid;grid-template-columns:100px 100px minmax(0,1fr);gap:12px;padding:10px 0;border-bottom:1px solid var(--line)}
.reason-row{display:flex;gap:10px;align-items:center;padding:10px 0}.reason-row b{margin-left:auto}
.pill.system{color:var(--amber);background:var(--amberbg)}.pill.unknown{color:var(--muted);background:var(--panel2)}
@media(max-width:600px){.failure-note{align-items:flex-start;flex-direction:column}.unknown-row{grid-template-columns:70px minmax(0,1fr)}.unknown-row>span:last-child{grid-column:1/-1}.strip .tiny{white-space:normal}.seg-side{flex-wrap:wrap}}

.strip.service .cell{height:auto;min-height:112px}.strip.service .tiny{line-height:1.5}

/* Current account inventory: one account, one row per configured site. */
.iv-toolbar{display:flex;align-items:center;gap:var(--s4);flex-wrap:wrap;margin-bottom:var(--s6)}
.um-filters{display:contents}
.iv-search{width:280px;max-width:100%}.iv-total{margin-left:auto}
.iv-account{background:var(--panel);border:1px solid var(--line);border-radius:var(--r);margin-bottom:var(--s5);overflow:hidden}
.iv-account-head{display:flex;align-items:center;gap:var(--s4);padding:var(--s5) var(--s6)}
.iv-account-head h3{font-size:var(--fs-md);font-weight:var(--fw-bold);margin:0;overflow-wrap:anywhere}
.iv-account-head>div{min-width:0}.iv-account small{font-size:var(--fs-2xs);color:var(--muted);display:block}
.iv-avatar{width:36px;height:36px;flex-shrink:0;display:grid;place-items:center;border-radius:var(--r-sm);color:var(--accent);background:var(--accentbg);font-weight:var(--fw-bold);font-size:var(--fs-xs)}
.iv-site-count{margin-left:auto;white-space:nowrap;color:var(--muted);font-size:var(--fs-xs)}
.iv-site-grid{display:grid;grid-template-columns:1.4fr .9fr .6fr 1.1fr 1.1fr .8fr .8fr .8fr;gap:var(--s4);align-items:center;padding:var(--s5) var(--s6)}
.iv-site-grid>div,.iv-route-grid>div{min-width:0;overflow-wrap:anywhere}
.iv-columns{background:var(--panel2);font-size:var(--fs-2xs);color:var(--muted);padding-top:var(--s3);padding-bottom:var(--s3)}
.iv-site-row+.iv-site-row,.iv-route-row+.iv-route-row{border-top:1px solid var(--line)}
.iv-site-row a,.iv-route-row a{display:block;font-size:var(--fs-2xs);margin-top:var(--s1);overflow-wrap:anywhere}
.iv-number{font-size:var(--fs-lg);font-family:var(--font-number);font-weight:var(--fw-bold);font-variant-numeric:tabular-nums}
.iv-date{font-size:var(--fs-xs);white-space:nowrap}.iv-date small{display:inline}
.iv-meter{height:4px;background:var(--line);max-width:120px;border-radius:var(--r-xs);margin-top:var(--s2);overflow:hidden}
.iv-meter i{height:100%;display:block;border-radius:var(--r-xs)}
.iv-account small.iv-limit{display:inline}
.iv-route-grid{display:grid;grid-template-columns:1.35fr 32px 1.35fr 1fr .7fr .7fr;gap:var(--s5);align-items:center;padding:var(--s5) var(--s6)}
.iv-arrow{color:var(--accent);font-size:var(--fs-xl);text-align:center}
.iv-account small.iv-tag{display:table;background:var(--accentbg);color:var(--accent);border-radius:var(--r-xs);padding:2px var(--s2);margin-top:var(--s1)}
.iv-account>summary{padding:var(--s5) var(--s6);cursor:pointer;font-weight:var(--fw-med)}
.iv-gemini-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s5)}
.bg-gray{background:var(--muted)}
@media(max-width:900px){.iv-site-grid{gap:var(--s3);padding-left:var(--s4);padding-right:var(--s4)}.iv-site-count{white-space:normal}.iv-date{white-space:normal}}
@media(max-width:700px){
 .iv-toolbar .seg{width:100%}.iv-toolbar .seg button{flex:1;min-height:44px}.iv-search{width:calc(100% - 100px);font-size:var(--fs-md)}.iv-total{width:100%;margin-left:0}
 .iv-site-grid{grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--s5);padding:var(--s5)}
 .iv-site-row>div:first-child{grid-column:1/-1}.iv-site-row>div:not(:first-child):before,.iv-route-row>div:nth-child(n+4):before{content:attr(data-label);display:block;color:var(--muted);font-size:var(--fs-2xs);margin-bottom:var(--s2)}
 .iv-route-grid{grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--s4);padding:var(--s5)}
 .iv-columns{display:none}.iv-date{font-size:var(--fs-2xs)}.iv-site-count{font-size:var(--fs-2xs)}.iv-account-head{padding:var(--s5)}.iv-gemini-grid{grid-template-columns:1fr}
}

/* Site-first inventory uses the same Darkmatter surfaces as the account page. */
.si-heading{padding:var(--s5) var(--s6);display:flex;align-items:center;justify-content:space-between;gap:var(--s5);border-bottom:1px solid var(--line)}
.si-heading h3{margin:0 0 var(--s1);font-size:var(--fs-lg)}.si-heading a{font-size:var(--fs-xs);overflow-wrap:anywhere}
.si-meta{display:flex;align-items:center;justify-content:flex-end;gap:var(--s3);flex-wrap:wrap}.si-meta small{white-space:nowrap}
.si-grid{display:grid;grid-template-columns:.9fr 1.6fr 1.5fr .8fr .8fr;gap:var(--s5);align-items:center;padding:var(--s4) var(--s6)}
.si-grid>div{min-width:0;overflow-wrap:anywhere}.si-row+.si-row{border-top:1px solid var(--line)}
.si-row a{display:block;font-size:var(--fs-xs);margin-top:var(--s1)}.si-row small{margin-top:var(--s1)}
.si-target{color:var(--accent)}.si-filters{flex-wrap:wrap}
.si-supply{margin-left:var(--s3);color:var(--accent);border-color:color-mix(in srgb,var(--accent) 40%,var(--line))}
.si-supply:hover{border-color:var(--accent);background:var(--accentbg)}
@media(max-width:700px){.si-supply{margin-left:0;min-height:36px}}
@media(max-width:700px){.si-heading{align-items:flex-start;padding:var(--s5);flex-wrap:wrap}.si-meta{justify-content:flex-start}.si-grid{grid-template-columns:minmax(0,1fr) minmax(0,1.4fr);padding:var(--s5)}.si-grid.iv-columns{display:none}.si-row>div:before{content:attr(data-label);display:block;font-size:var(--fs-2xs);color:var(--muted);margin-bottom:var(--s2)}.si-filters button{min-height:44px}}

/* Supply diagram: arrows point from provider to consuming site, not request direction. */
.sg-legend{display:flex;align-items:center;gap:var(--s4);flex-wrap:wrap;margin-bottom:var(--s6)}.sg-legend span{color:var(--muted);font-size:var(--fs-xs)}
.sg-column-labels{display:flex;justify-content:space-between;color:var(--muted);font-size:var(--fs-xs);margin-bottom:var(--s3)}.sg-column-labels span:first-child{width:34%}.sg-column-labels span:last-child{width:44%}
.sg-group{position:relative;margin-bottom:var(--s6);min-height:84px}.sg-lines{position:absolute;inset:0;width:100%;height:100%;color:var(--accent);pointer-events:none;overflow:visible}
.sg-node{position:relative;text-align:left;background:var(--panel);border:1px solid var(--line);border-radius:var(--r-sm);padding:var(--s3) var(--s4);display:flex;flex-direction:column;gap:2px;width:100%;min-width:0;cursor:pointer}
.sg-node b{font-weight:var(--fw-bold);font-size:var(--fs-sm)}.sg-node span,.sg-node small{color:var(--muted);font-size:var(--fs-2xs);overflow-wrap:anywhere}.sg-node b small{color:var(--amber)}.sg-node.selected{border-color:var(--accent);background:var(--accentbg)}.sg-node.paused{border-style:dashed}
.sg-supplier{position:absolute;top:50%;left:0;transform:translateY(-50%);width:34%;border-color:var(--accent)}.sg-receivers{margin-left:56%;width:44%}.sg-row{height:84px;display:flex;align-items:center}.sg-row .sg-node{max-height:80px}.sg-isolated{margin-top:var(--s6)}
@media(max-width:700px){.sg-column-labels,.sg-lines{display:none}.sg-group{border-bottom:1px solid var(--line);padding-bottom:var(--s5)}.sg-supplier{position:relative;top:auto;transform:none;width:100%;margin-bottom:var(--s3)}.sg-receivers{margin-left:var(--s5);padding-left:var(--s4);width:auto;border-left:2px solid var(--accent)}.sg-row{height:auto;min-height:90px;position:relative}.sg-row:before{content:'→';position:absolute;left:-25px;color:var(--accent);background:var(--bg);font-size:var(--fs-lg)}.sg-row .sg-node{max-height:none}.si-quota:empty{min-height:var(--s6)}}

/* Per-site user management. Horizontal scrolling belongs to the table only. */
.um-site>summary{display:flex;align-items:center;gap:var(--s4);list-style:none}.um-site>summary:before{content:"▾";color:var(--muted)}.um-site:not([open])>summary:before{content:"▸"}
.um-site-meta,.um-site-time{font-size:var(--fs-xs);color:var(--muted)}.um-site-time{margin-left:auto}
.um-table-scroll{overflow-x:auto;max-width:100%}
.um-table{width:100%;min-width:1880px;border-collapse:collapse;font-size:var(--fs-sm);text-align:left}
.um-table .um-band th{background:var(--panel2);border-bottom:0;padding:var(--s3) var(--s4) 2px;
  font-size:var(--fs-2xs);font-weight:var(--fw-bold);letter-spacing:.07em;text-transform:uppercase;color:var(--text2);text-align:left}
.um-table .um-band th:not(:empty){box-shadow:inset 1px 0 0 var(--line)}
.um-table th{background:var(--panel2);font-weight:var(--fw-bold);color:var(--muted);letter-spacing:.04em;padding:var(--s4);white-space:nowrap}
/* A row is as tall as its tallest cell -- a note that wraps to three lines, a trait
   with its daily average under it. Every other value used to hang from the top of
   that, so a row read as a staircase instead of a line. */
.um-table td{padding:var(--s4);border-top:1px solid var(--line);vertical-align:middle}
.um-table td.num,.um-table td .num{white-space:nowrap}.um-table td small{margin-top:var(--s1)}
.um-user{min-width:210px;max-width:280px;overflow-wrap:anywhere}.um-user b{display:block}
.um-contact{min-width:140px;max-width:220px;overflow-wrap:anywhere}.um-contact>span{display:block}
.um-trait small{display:block;white-space:nowrap}
.um-actions .ctl.sm{padding:0 10px}
.um-notes{min-width:150px;max-width:250px;white-space:pre-wrap;overflow-wrap:anywhere}
.um-editor{width:520px;max-width:calc(100vw - 24px);max-height:calc(100dvh - 40px);overflow:auto;border:1px solid var(--line);border-radius:var(--r);padding:var(--s7);color:var(--text);background:var(--panel)}
.um-editor::backdrop{background:var(--overlay)}.um-editor h2{font-size:var(--fs-lg);margin:0}.um-editor p{overflow-wrap:anywhere}
.um-editor fieldset{border:0;padding:0;display:grid;gap:var(--s4);min-width:0}.um-editor label{display:grid;gap:var(--s2);font-size:var(--fs-xs)}
.um-editor textarea{resize:vertical;min-height:100px}.um-editor .ctl{width:100%}.um-editor-actions{display:flex;justify-content:flex-end;gap:var(--s3);margin-top:var(--s6)}.um-editor-actions .ctl{width:auto}
/* 18 columns do not fit any screen, so the table scrolls sideways -- but the person
   it belongs to and the button that edits them must never scroll away. Only above the
   700px breakpoint, below which the table is not a table at all. */
@media(min-width:701px){
  .um-table th:first-child,.um-table td.um-user{position:sticky;left:0;z-index:2}
  .um-table th:last-child,.um-table td.um-actions{position:sticky;right:0;z-index:2}
  .um-table td.um-user,.um-table td.um-actions{background:var(--panel)}
  .um-table th:first-child,.um-table th:last-child{z-index:3}
  .um-table td.um-user{box-shadow:inset -1px 0 0 var(--line2)}
  .um-table td.um-actions{box-shadow:inset 1px 0 0 var(--line2)}
}
@media(max-width:700px){
  .um-site>summary{flex-wrap:wrap}.um-site-time{width:100%;margin-left:0}
  .um-table{min-width:0;display:block}.um-table thead{display:none}.um-table tbody{display:block}
  .um-table tr{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:0 var(--s4);border-top:1px solid var(--line);padding:var(--s3)}
  /* a one-line value does not need two lines: label left, value right, on one row.
     Nine of the thirteen fields are a number or a dash, and stacking them was most
     of the card's height. */
  .um-table td{display:flex;align-items:baseline;justify-content:space-between;gap:var(--s3);min-width:0;max-width:none;border:0;padding:var(--s2) 0}
  .um-table td:before{content:attr(data-label);flex:0 0 auto;font-family:var(--font-ui);font-size:var(--fs-2xs);color:var(--muted)}
  .um-table td>*{min-width:0;text-align:right;overflow-wrap:anywhere}
  /* the four that really can run long keep the stacked form */
  .um-table .um-user,.um-table .um-contact,.um-table .um-notes,.um-table .um-actions{grid-column:1/-1;display:block;padding:var(--s2) 0}
  .um-table .um-user:before,.um-table .um-contact:before,.um-table .um-notes:before,.um-table .um-actions:before{display:block;margin-bottom:var(--s1)}
  .um-table .um-user>*,.um-table .um-contact>*,.um-table .um-notes>*,.um-table .um-actions>*{text-align:left}
  .um-table .um-user{padding-bottom:var(--s3);border-bottom:1px solid var(--line2);margin-bottom:var(--s2)}
  .um-table .um-actions:before{display:none}
  .um-actions .ctl{min-height:44px;width:100%;justify-content:center}
  .um-editor .ctl{font-size:var(--fs-md);min-width:0}
  .user-management>.iv-toolbar .ctl{min-height:44px}
  /* status / sort / order / refresh fit one row instead of spilling over two */
  .user-management>.iv-toolbar{gap:var(--s3)}
  .user-management>.iv-toolbar .iv-search{width:100%}
  .um-filters{display:flex;gap:var(--s2);width:100%}
  .um-filters>.xs{flex:1 1 0;min-width:0}
  .um-filters>.ctl{flex:0 0 auto;padding:0 var(--s3)}
}

/* User page readability: proportional Noto Sans with aligned numeric glyphs. */
.user-management,.um-editor{font-family:var(--font-ui);font-size:var(--fs-sm)}
.user-management .num,.um-editor .num{font-family:var(--font-display);font-variant-numeric:tabular-nums}
.um-table th{font-size:var(--fs-2xs)}.um-table td small{font-size:var(--fs-xs)}
.um-field{display:grid;gap:var(--s2);font-size:var(--fs-sm)}
.dt-trigger{display:flex;align-items:center;justify-content:flex-start;text-align:left;gap:var(--s3);min-height:44px}
.dt-trigger.on{border-color:var(--accent)}
.dt-trigger .i{color:var(--muted);flex:none}
.dt-panel{margin-top:var(--s3);border:1px solid var(--line);border-radius:var(--r);padding:var(--s4);background:var(--panel);box-shadow:var(--shadow)}
.dt-head{display:grid;grid-template-columns:36px minmax(0,1fr) minmax(0,1fr) 36px;gap:var(--s2);align-items:center}
.dt-nav{justify-content:center;padding-left:var(--s2);padding-right:var(--s2)}
.dt-prev{transform:rotate(90deg)}.dt-next{transform:rotate(-90deg)}
.dt-week,.dt-days{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:2px}
.dt-week{margin-top:var(--s4);color:var(--muted);font-size:var(--fs-xs);text-align:center}
.dt-week span{padding:var(--s2)}
.dt-days button{height:38px;border:1px solid transparent;border-radius:var(--r-sm);background:transparent;color:var(--text);font:inherit;cursor:pointer;font-variant-numeric:tabular-nums}
.dt-days button:hover{background:var(--panel2)}
.dt-days button.outside{color:var(--muted2)}
/* today is an outline, selected is a fill: both can show at once */
.dt-days button.today{border-color:var(--line)}
.dt-days button.selected{background:var(--accent);border-color:var(--accent);color:var(--chipontext);font-weight:var(--fw-bold)}
.dt-time{display:flex;align-items:center;gap:var(--s3);border-top:1px solid var(--line);padding-top:var(--s4);margin-top:var(--s4)}
.dt-time-label{color:var(--muted);font-size:var(--fs-xs);flex:none}
.dt-segs{display:inline-flex;align-items:center;gap:2px;border:1px solid var(--line);border-radius:var(--r-sm);background:var(--panel);padding:0 var(--s2);min-height:44px}
.dt-segs:focus-within{border-color:var(--accent)}
.dt-seg{width:2.4em;padding:var(--s2) 0;border:0;background:transparent;color:var(--text);text-align:center;font-family:var(--font-number);font-variant-numeric:tabular-nums;font-size:var(--fs-md);outline:0}
.dt-seg::selection{background:var(--accentbg)}
.dt-colon{color:var(--muted2);font-family:var(--font-number)}
.dt-footer{display:flex;justify-content:flex-end;gap:var(--s2);margin-top:var(--s4)}
.um-editor .dt-footer .ctl{width:auto}.dt-footer button:first-child{margin-right:auto}
@media(max-width:700px){.dt-panel{padding:var(--s3)}.dt-days button{height:40px}.um-editor{padding:var(--s5)}.dt-head{grid-template-columns:32px minmax(0,1fr) minmax(0,1fr) 32px}.dt-time{flex-wrap:wrap}.xs-opt{min-height:44px}.pg-n{min-width:38px;min-height:38px}}
