/* nface-web - the whole visual system, in one file.
 *
 * No framework, no build step, no CDN. A camera on a closed LAN has no internet, and a
 * page that needs to download something is a page that does not work where the product
 * actually runs. The web font below degrades to a system stack when it cannot load.
 *
 * There is not one threshold in this file and there must never be one. Colour encodes
 * STATUS only - never decoration - and the status always came from the camera.
 *
 * SIX spacings, FIVE text sizes, TWO figure sizes, TWO button heights, ONE left edge.
 * Every gap, padding and margin below is one of --s1..--s6, and no template sets any of
 * them inline: an eye that lands in the same place on all eighteen screens is the whole
 * point of the scale.
 */

/* ---------------------------------------------------------------- tokens */
:root {
  --bg:#0c0f13; --surface:#141920; --surface-2:#181e26; --flat:#11161c;
  --line:#232932; --ink:#eef1f5; --ink-2:#a4aebc; --ink-3:#6e7887;
  --accent:#4d9fff; --accent-solid:#2c6fd6;
  --strong:#3ddc97; --maybe:#f5b83d; --weak:#b892f2; --bad:#ff6b6b;
  --radius:16px; --radius-s:12px; --radius-xs:10px;

  /* the spacing scale - nothing between these steps */
  --s1:4px; --s2:8px; --s3:12px; --s4:16px; --s5:24px; --s6:32px;
  /* one left edge for the banner, the flash, the crumb, the h1 and every panel */
  --pad-x:32px; --measure:64ch;
  /* five text sizes */
  --t-h1:22px; --t-h2:15px; --t-body:14.5px; --t-sm:13px; --t-xs:11.5px;
  /* two figure sizes */
  --fig:28px; --fig-s:20px;
}

*,*::before,*::after { box-sizing: border-box; }
html,body { height:100%; }
body {
  margin:0; background:var(--bg); color:var(--ink);
  font-family:"IBM Plex Sans","Helvetica Neue",Helvetica,Arial,sans-serif;
  font-size:var(--t-body); line-height:1.55; -webkit-font-smoothing:antialiased;
}
a { color:var(--accent); text-decoration:none; }
a:hover { color:#84bcff; }
h1,h2,h3,p { margin:0; }
.mono { font-family:"IBM Plex Mono",ui-monospace,SFMono-Regular,Menlo,monospace;
        font-variant-numeric:tabular-nums; }
.muted { color:var(--ink-2); }
.faint { color:var(--ink-3); }
.sm { font-size:var(--t-sm); }
.xs { font-size:var(--t-xs); }
.b6 { font-weight:600; }
.row { display:flex; align-items:center; gap:var(--s3); }
.col { display:flex; flex-direction:column; }
.wrap { flex-wrap:wrap; }
.push { margin-left:auto; }
.hide { display:none !important; }

/* the utilities that replace every inline style= the templates used to carry */
.stack { display:flex; flex-direction:column; gap:var(--s3); }
.stack-lg { gap:var(--s5); }
.tightgap { gap:1px; }
.hgap { display:flex; align-items:center; gap:var(--s3); flex-wrap:wrap; }
.stats { display:flex; flex-wrap:wrap; gap:var(--s6); }
.stat { display:flex; flex-direction:column; gap:var(--s1); }
.stat.atend { align-items:flex-end; text-align:right; }
.formrow { display:flex; flex-wrap:wrap; gap:var(--s4); align-items:flex-end; }
.formrow .field { flex:1; min-width:200px; }
.cardcol { display:flex; flex-direction:column; gap:var(--s4); height:100%; }
.ellipsis { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.grow { flex:1; }
.end { margin-top:auto; }
.measure { max-width:var(--measure); }
.ink { color:var(--ink); }
a.ink:hover { color:var(--accent); }
.centre { align-items:center; text-align:center; }
.idmono { font-size:12px; word-break:break-all; line-height:1.6; }
.brk { word-break:break-all; }

/* ---------------------------------------------------------------- shell */
.app { display:grid; grid-template-columns:250px 1fr; min-height:100vh; }
.rail { background:#101419; padding:var(--s5) var(--s4) var(--s5); display:flex;
        flex-direction:column; gap:var(--s6); }
.brand { display:flex; align-items:center; gap:var(--s3); padding:0 var(--s2); }
.mark { width:34px; height:34px; border-radius:11px; background:#17304d; flex:none;
        display:flex; align-items:center; justify-content:center; color:var(--accent); }
.brandname { font-size:17px; font-weight:600; letter-spacing:.02em; color:var(--ink); }
.navgroup { display:flex; flex-direction:column; gap:var(--s1); }
.nav { display:flex; align-items:center; gap:var(--s3); padding:var(--s3);
       border-radius:11px; color:var(--ink-2); font-weight:500; }
.nav svg { width:20px; height:20px; flex:none; color:#727c8b; }
.nav:hover { background:#161c24; color:var(--ink); }
.nav.on { background:#1b2634; color:var(--ink); }
.nav.on svg { color:var(--accent); }
.railfoot { margin-top:auto; display:flex; flex-direction:column; gap:var(--s2); }
.who { display:flex; align-items:center; gap:var(--s3); padding:var(--s3);
       border-radius:12px; background:#151a21; }
.avatar { width:32px; height:32px; border-radius:50%; background:#1f3350; flex:none;
          display:flex; align-items:center; justify-content:center; color:#8ac8ff;
          font-size:12px; font-weight:600; }
.who .col { min-width:0; flex:1; }
.signout { margin-left:auto; color:var(--ink-3); display:flex; }
.main { display:flex; flex-direction:column; min-width:0; }
.topbar { display:flex; align-items:center; gap:var(--s4);
          padding:var(--s5) var(--pad-x) var(--s1); flex-wrap:wrap; }
.h1 { font-size:var(--t-h1); font-weight:600; letter-spacing:-.015em; }
.subtitle { font-size:var(--t-sm); color:var(--ink-2); margin-top:var(--s1); }
.actions { margin-left:auto; display:flex; align-items:center; gap:var(--s3);
           flex-wrap:wrap; }
.content { padding:var(--s5) var(--pad-x) var(--s6); display:flex;
           flex-direction:column; gap:var(--s5); }
.narrow { max-width:940px; }

/* ---------------------------------------------------------------- surfaces */
.panel { background:var(--surface); border-radius:var(--radius); padding:var(--s5); }
.panel.flat { background:var(--flat); }
.panel.tight { padding:var(--s2); }
.head { display:flex; align-items:center; gap:var(--s3); margin-bottom:var(--s5);
        flex-wrap:wrap; }
.head.flush { margin-bottom:var(--s2); padding:var(--s3) var(--s3) 0; }
.head h2 { font-size:var(--t-h2); font-weight:600; }
.label { font-size:11px; letter-spacing:.1em; text-transform:uppercase;
         color:var(--ink-3); font-weight:600; }
.fig { font-family:"IBM Plex Mono",ui-monospace,Menlo,monospace;
       font-variant-numeric:tabular-nums; font-size:var(--fig); font-weight:500;
       letter-spacing:-.02em; line-height:1.1; }
.fig.s { font-size:var(--fig-s); }
.fig.ok { color:var(--strong); } .fig.bad { color:var(--bad); }
.fig.accent { color:var(--accent); } .fig.weak { color:var(--weak); }
.tile { background:var(--surface); border-radius:var(--radius); padding:var(--s5);
        display:flex; flex-direction:column; gap:var(--s2); }
.g2 { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:var(--s5); }
.g3 { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:var(--s5); }
.g4 { display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); gap:var(--s5); }
.g2.top,.g3.top { align-items:start; }
.g2.side { grid-template-columns:1fr 320px; }

/* ---------------------------------------------------------------- controls */
.btn { display:inline-flex; align-items:center; justify-content:center; gap:var(--s2);
       height:40px; padding:0 var(--s5); border-radius:var(--radius-s); font:inherit;
       font-size:var(--t-body); font-weight:500; cursor:pointer; border:0;
       background:var(--accent-solid); color:#f4f8ff; text-decoration:none; }
.btn:hover { background:#3d80e4; color:#f4f8ff; }
.btn svg { width:18px; height:18px; }
.btn.ghost { background:#1c222b; color:#d5dde7; }
.btn.ghost:hover { background:#232b36; color:var(--ink); }
.btn.quiet { background:transparent; color:var(--ink-2); }
.btn.quiet:hover { background:#181e26; color:var(--ink); }
.btn.danger { background:transparent; color:var(--bad); }
.btn.danger:hover { background:#241416; color:var(--bad); }
.btn.s { height:32px; padding:0 var(--s3); font-size:var(--t-sm);
         border-radius:var(--radius-xs); }
.btn.wide { width:100%; }
.btn[disabled],.btn.off { opacity:.4; pointer-events:none; }
.seg { display:inline-flex; background:#161b22; border-radius:var(--radius-s);
       padding:var(--s1); gap:3px; }
.seg a { padding:var(--s2) var(--s3); border-radius:9px; font-size:var(--t-sm);
         font-weight:500; color:var(--ink-2); }
.seg a.on { background:#26303c; color:var(--ink); }
.seg.start { align-self:flex-start; }
input[type=text],input[type=email],input[type=number],input[type=datetime-local],
input[type=file],select,textarea {
  height:40px; padding:0 var(--s3); border-radius:var(--radius-s); background:var(--flat);
  color:var(--ink); border:1px solid #232a34; font:inherit; font-size:var(--t-body);
  width:100%; max-width:420px;
}
input[type=file] { padding:var(--s2) var(--s3); height:auto; }
input:focus,select:focus { outline:2px solid #2b5f9e; outline-offset:1px; }
.field { display:flex; flex-direction:column; gap:var(--s2); }
.field.wide { flex:1; min-width:220px; max-width:420px; }
.offscreen { position:absolute; left:-9999px; }
.readonly { height:40px; padding:0 var(--s3); border-radius:var(--radius-s);
            background:var(--flat); display:flex; align-items:center;
            font-size:var(--t-body); color:var(--ink-2); }

/* ---------------------------------------------------------- status language */
.pill { display:inline-flex; align-items:center; gap:7px; height:28px; padding:0 var(--s3);
        border-radius:999px; font-size:var(--t-sm); font-weight:600; }
.pill.strong { background:#123026; color:var(--strong); }
.pill.maybe  { background:#2e2612; color:var(--maybe); }
.pill.weak   { background:#262030; color:var(--weak); }
.pill.bad    { background:#2e1719; color:var(--bad); }
.pill.calm   { background:#1c222b; color:var(--ink-2); }
.dot { width:9px; height:9px; border-radius:50%; flex:none; }
.dot.strong{background:var(--strong)} .dot.maybe{background:var(--maybe)}
.dot.weak{background:var(--weak)} .dot.bad{background:var(--bad)}
.dot.calm{background:var(--ink-3)}

/* The confidence ring. Readable before a word is read; it is the raw score rescaled,
   and the colour is the camera's own verdict, never a bar applied here. */
.ring { position:relative; width:52px; height:52px; border-radius:50%; flex:none;
        display:grid; place-items:center;
        background:conic-gradient(var(--c,var(--strong)) calc(var(--p,0)*1%), #262d38 0); }
.ring > i { width:41px; height:41px; border-radius:50%; background:var(--surface);
            display:grid; place-items:center; font-style:normal; font-size:var(--t-sm);
            font-weight:600;
            font-family:"IBM Plex Mono",ui-monospace,Menlo,monospace; }
.ring.big { width:76px; height:76px; }
.ring.big > i { width:61px; height:61px; font-size:var(--fig-s); }
.ring.strong { --c:var(--strong); } .ring.maybe { --c:var(--maybe); }
.ring.weak { --c:#7b6a95; }

/* ---------------------------------------------------------- sighting cards */
.shots { display:grid; grid-template-columns:repeat(auto-fill,minmax(280px,1fr));
         gap:var(--s4); }
.shot { background:var(--surface); border-radius:var(--radius); overflow:hidden;
        display:flex; flex-direction:column; }
.shot .pic { position:relative; aspect-ratio:1; background:#1a212a; display:block; }
.shot .pic img { width:100%; height:100%; object-fit:cover; display:block; }
.shot .ring { position:absolute; right:var(--s3); top:var(--s3);
              background:conic-gradient(var(--c,var(--strong)) calc(var(--p,0)*1%),
                                        rgba(12,15,19,.75) 0); }
.shot .ring > i { background:#101519; }
.shot .play { position:absolute; left:50%; top:50%; transform:translate(-50%,-50%);
              width:46px; height:46px; border-radius:50%; background:rgba(12,15,19,.72);
              display:grid; place-items:center; color:var(--ink); }
.shot .body { padding:var(--s4); display:flex; flex-direction:column; gap:var(--s2);
              align-items:flex-start; }
.shot .body .when { font-size:var(--t-body); font-weight:600; }
.shot.dim .pic { filter:grayscale(1); opacity:.42; }
.shot.dim .body { opacity:.72; }

/* A face crop the camera has already deleted must not leave a broken image icon. */
.crop { border-radius:var(--radius-xs); background:#1a212a; display:block;
        object-fit:cover; }
.crop.square { width:100%; aspect-ratio:1; }
.crop.big { width:160px; height:160px; }
.crop-gone { display:grid; place-items:center; background:#1a212a; color:var(--ink-3);
             font-size:11px; border-radius:var(--radius-xs); }

/* ---------------------------------------------------------------- notes */
.note { display:flex; gap:var(--s3); padding:var(--s3) var(--s4); border-radius:13px;
        font-size:var(--t-sm); line-height:1.5; align-items:flex-start; }
.note svg { width:18px; height:18px; flex:none; margin-top:1px; }
.note.warn { background:#231c0e; color:#f0d49c; }
.note.bad  { background:#251416; color:#f3b5b5; }
.note.info { background:#111e2c; color:#b8d6f2; }
.note.ok   { background:#0f2219; color:#a8e5cb; }
.inset { margin-top:var(--s3); }
.spaced { margin-bottom:var(--s5); }
.spaced-top { margin-top:var(--s5); }
.under { margin-bottom:var(--s4); }

/* ---------------------------------------------------------------- figures */
.icon { width:52px; height:52px; border-radius:15px; background:#182231;
        color:var(--accent); display:grid; place-items:center; flex:none; }
.icon svg { width:24px; height:24px; }
.icon.ok { background:#123026; color:var(--strong); }
.icon.warn { background:#2e2612; color:var(--maybe); }
.icon.bad { background:#2e1719; color:var(--bad); }
.icon.s { width:38px; height:38px; border-radius:11px; }
.chev { color:#39424f; display:flex; align-items:center; }
.chev svg { width:22px; height:22px; }
.dash { border:1.5px dashed #2a323d; background:transparent; }
.kv { display:flex; justify-content:space-between; gap:var(--s4); padding:var(--s3) 0; }
.kv + .kv { border-top:1px solid #1c222a; }
.kvk { color:#8b95a3; font-size:var(--t-sm); }
.kvv { font-family:"IBM Plex Mono",ui-monospace,Menlo,monospace; font-size:var(--t-sm);
       font-variant-numeric:tabular-nums; text-align:right; }
.kvv.ok { color:var(--strong); } .kvv.maybe { color:var(--maybe); }
.kvv.off { color:var(--ink-2); }
.bar { position:relative; height:12px; border-radius:6px; background:#232a34;
       overflow:hidden; }
.bar > span { position:absolute; left:0; top:0; bottom:0; border-radius:6px;
              background:var(--accent-solid); }

/* Progressive disclosure. Everything an engineer needs is still on the page - it is
   just not the first thing a customer reads. */
details.tech { background:var(--flat); border-radius:var(--radius);
               padding:var(--s5); }
details.tech > summary { list-style:none; cursor:pointer; display:flex;
                         align-items:center; gap:var(--s3); }
details.tech > summary::-webkit-details-marker { display:none; }
details.tech > summary .chev svg { transition:transform .15s ease; }
details.tech[open] > summary .chev svg { transform:rotate(180deg); }
.tech-grid { margin-top:var(--s5); display:grid;
             grid-template-columns:repeat(auto-fit,minmax(240px,1fr));
             gap:2px var(--s6); }
.tech-grid.one { grid-template-columns:1fr; margin-top:var(--s2); }
table.tbl-tech { width:100%; border-collapse:collapse; font-size:12px; }
table.tbl-tech th { text-align:left; padding:var(--s2) var(--s3); color:var(--ink-3);
                    font-weight:500; }
table.tbl-tech td { padding:var(--s2) var(--s3); }
table.tbl-tech tbody tr { border-top:1px solid #1c222a; }
.tech-foot { margin-top:var(--s3); }

/* ---------------------------------------------------------------- login */
.split { display:grid; grid-template-columns:1.1fr .9fr; min-height:100vh; }
.split .left { padding:var(--s6) var(--s6); display:flex; flex-direction:column;
               gap:var(--s6); background:#101419; }
.split .right { padding:var(--s6); display:flex; flex-direction:column;
                justify-content:center; gap:var(--s5); }
.split .card { max-width:390px; width:100%; }
.claim { font-size:30px; font-weight:600; letter-spacing:-.025em; line-height:1.2;
         max-width:480px; text-wrap:pretty; }
/* .claim + .sub went with the second line under the login claim: nothing carries
   class="sub" any more, so the rule could only ever match nothing. */
.btn.google { height:50px; background:#fff; color:#1c2028; }
.btn.google:hover { background:#e9edf3; color:#1c2028; }

/* ---------------------------------------------------------------- misc */
.devbanner { margin:var(--s4) var(--pad-x) 0; }
.empty { display:flex; flex-direction:column; align-items:center; gap:var(--s3);
         padding:var(--s6) var(--s5); text-align:center; }
.empty .b6 { font-size:var(--t-h1); }
.empty.s { padding:var(--s5) var(--s3); }
@media (max-width:900px) {
  :root { --pad-x:20px; }
  .app { grid-template-columns:1fr; }
  .rail { flex-direction:row; align-items:center; gap:var(--s4);
          padding:var(--s3) var(--s4); overflow-x:auto; }
  .navgroup { flex-direction:row; }
  .railfoot { margin:0 0 0 auto; }
  .split { grid-template-columns:1fr; }
  .split .left,.split .right { padding:var(--s6) var(--s5); }
  /* One column, or a fixed count divides a phone into slivers: three tiles at 375px
     clipped "20,000,000" to "20,000" and squeezed a camera's name out of its card
     entirely. A figure that is not readable is not a figure. */
  .g2,.g3,.g4,.g2.side { grid-template-columns:1fr; }
}

/* live view - what the camera's analyser sees now */
.panel.live { margin-bottom:0; }
.live-frame { background:#0b0e12; border-radius:12px; overflow:hidden; aspect-ratio:16/9;
              display:flex; align-items:center; justify-content:center;
              margin:var(--s3) 0 var(--s2); }
.live-frame img { width:100%; height:100%; object-fit:contain; display:block; }
#segment-player { width:100%; border-radius:var(--radius); background:#07090c;
                  display:block; }

/* ------------------------------------------------------- search across cameras */
.camrow { padding:var(--s3) var(--s4); }
.camrow + .camrow { border-top:1px solid #1c222a; }
table.fingerprints { width:100%; border-collapse:collapse; font-size:12px; }
table.fingerprints th { text-align:left; padding:var(--s2) var(--s3); color:var(--ink-3);
                        font-weight:500; white-space:nowrap; }
table.fingerprints td { padding:var(--s2) var(--s3); border-top:1px solid #1c222a;
                        white-space:nowrap; }
.scrollx { overflow-x:auto; }
.btn.s svg { width:14px; height:14px; }

/* ------------------------------------------------------------------- sources */
.srcrow { padding:var(--s4) 0; }
.srcrow + .srcrow { border-top:1px solid #1c222a; }
.srcstats { gap:var(--s5); margin:var(--s2) 0 0 50px; font-size:var(--t-sm);
            color:var(--ink-2); }

/* The 5-second clip. Built by common.js; the video inside plays straight from the
   camera, and only after the browser's own HEAD said the segment is sealed. */
.clip-modal { position:fixed; inset:0; z-index:50; background:rgba(5,7,10,.8);
              display:flex; align-items:center; justify-content:center; padding:var(--s5); }
.clip-box { background:var(--surface); border-radius:var(--radius); width:100%;
            max-width:880px; padding:var(--s5); display:flex; flex-direction:column;
            gap:var(--s3); }
.clip-box .head { margin-bottom:0; }
.clip-box .clip-title { font-size:var(--t-h2); font-weight:600; }
.clip-video { width:100%; aspect-ratio:16/9; border-radius:var(--radius-s);
              background:#07090c; display:block; }

/* ------------------------------------------------------------------ timeline
   A single-series column chart in plain HTML. One slot per bucket, full width so the
   hover target is bigger than the mark; the mark itself is capped at 24px, rounded at
   its data end and square on the baseline, with a 2px gap between neighbours. Colour is
   the accent for "faces seen" and nothing else: a flat line is "watching, nobody
   there", hatching is "not watching" - never the same mark, never zero-height bars. */
/* minmax(0,1fr), not 1fr: a plain 1fr column grows to the chart's content width, and
   120 bars then push the chart out of its panel (seen while building this). */
.tl { display:grid; grid-template-columns:30px minmax(0,1fr); column-gap:var(--s2);
      row-gap:var(--s2); }
.tl-y { display:flex; flex-direction:column; justify-content:space-between;
        height:180px; text-align:right; line-height:1; }
.tl-chart { display:flex; align-items:stretch; height:180px; min-width:0;
            border-top:1px solid #1c222a; border-bottom:1px solid #2a323d; }
.tl-bar { position:relative; flex:1 1 0; min-width:0; display:block; }
/* Absolutely placed in its slot: 1px of air each side (the 2px gap), at most 24px wide,
   centred. A flex-sized mark with a percentage height kept its 24px and spilled into
   its neighbours at 120 bars. */
.tl-bar > span { position:absolute; bottom:0; left:1px; right:1px; max-width:24px;
                 margin:0 auto; border-radius:4px 4px 0 0; background:var(--accent-solid); }
/* On a phone 150 slots are ~2px each: the gap would eat the whole bar, so drop it. */
@media (max-width:600px) { .tl-bar > span { left:0; right:0; border-radius:1px 1px 0 0; } }
a.tl-bar:hover > span, a.tl-bar:focus-visible > span { background:var(--accent); }
a.tl-bar:focus-visible { outline:2px solid #2b5f9e; outline-offset:1px; }
.tl-bar.zero > span { height:2px !important; border-radius:0; background:#3a4452; }
.tl-bar.gap { background:repeating-linear-gradient(135deg, #1d242d 0 2px, transparent 2px 6px); }
.tl-bar.on { background:#15283d; border-radius:4px 4px 0 0; }
.tl-bar.on > span { background:var(--accent); }
.tl-bar[data-tip]:hover::after, .tl-bar[data-tip]:focus-visible::after {
  content:attr(data-tip); position:absolute; bottom:calc(100% + 8px); left:50%;
  transform:translateX(-50%); white-space:nowrap; pointer-events:none; z-index:5;
  background:#0b0e12; color:var(--ink); border:1px solid var(--line); border-radius:8px;
  padding:6px 10px; font-size:12px; font-family:"IBM Plex Mono",ui-monospace,Menlo,monospace; }
.tl-axis { display:flex; justify-content:space-between; }
.tl-key { gap:var(--s5); margin-top:var(--s4); }
.tl-swatch { display:inline-block; width:14px; height:10px; border-radius:3px;
             margin-right:7px; vertical-align:-1px; }
.tl-swatch.faces { background:var(--accent-solid); }
.tl-swatch.zero { height:2px; border-radius:0; vertical-align:3px; background:#3a4452; }
.tl-swatch.gap { background:repeating-linear-gradient(135deg, #3a4452 0 2px, transparent 2px 4px); }

.faces { display:grid; grid-template-columns:repeat(auto-fill,minmax(128px,1fr));
         gap:var(--s4); }
.face { display:flex; flex-direction:column; gap:var(--s2); }
.face .btn { width:100%; }
.face .xs { text-align:center; }

/* ------------------------------------------------------------------- groups
   The group is the outermost layer of the console: its name heads the rail and starts
   every page's trail. Roles are shown as calm pills - colour here still means STATUS
   only, and a role is not a status. */
.crumbs { display:flex; align-items:center; flex-wrap:wrap; gap:7px;
          font-size:var(--t-sm); color:var(--ink-3); margin-bottom:var(--s1); }
.crumbs a { color:var(--ink-2); }
.crumbs a:hover { color:var(--ink); }
.crumbs .sep { color:#3a4452; }
.crumb-group { font-weight:600; }
.flash { margin:var(--s4) var(--pad-x) 0; }

.gswitch { position:relative; }
.gswitch > summary { list-style:none; cursor:pointer; display:flex; align-items:center;
                     gap:var(--s2); padding:var(--s3); border-radius:12px;
                     background:#151a21; }
.gswitch > summary::-webkit-details-marker { display:none; }
.gswitch > summary:hover { background:#19202a; }
.gswitch > summary .chev svg { transition:transform .15s ease; }
.gswitch[open] > summary .chev svg { transform:rotate(180deg); }
.gswitch .col { min-width:0; }
.gname { font-size:var(--t-h2); font-weight:600; color:var(--ink); overflow:hidden;
         text-overflow:ellipsis; white-space:nowrap; }
.gmenu { position:absolute; left:0; right:0; top:calc(100% + 6px); z-index:40;
         min-width:220px; background:#161c24; border:1px solid var(--line);
         border-radius:12px; padding:6px; display:flex; flex-direction:column; gap:2px;
         box-shadow:0 12px 30px rgba(0,0,0,.45); }
.gmenu form { margin:0; }
.gmenu .label { padding:var(--s1) var(--s2); }
.gitem { display:flex; align-items:center; justify-content:space-between; gap:var(--s2);
         width:100%; padding:9px 10px; border-radius:9px; background:transparent; border:0;
         color:var(--ink-2); font:inherit; font-size:var(--t-body); text-align:left;
         cursor:pointer; }
.gitem:hover { background:#1c2530; color:var(--ink); }
.gitem.on { background:#1b2634; color:var(--ink); }
.gitem-name { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-weight:500; }

.mrow { padding:var(--s3); gap:var(--s3); }
.mrow + .mrow { border-top:1px solid #1c222a; }
.mrow form { display:flex; gap:var(--s2); align-items:center; margin:0; }
.mrow select { height:32px; width:auto; min-width:118px; font-size:var(--t-sm); }
.mrow .col { min-width:200px; flex:1; gap:1px; }
.pill.s { height:24px; padding:0 var(--s2); font-size:12px; }
.pills { display:flex; flex-wrap:wrap; gap:6px; }
.tbl-wrap { overflow-x:auto; }
table.tbl { width:100%; border-collapse:collapse; font-size:var(--t-sm); }
table.tbl th { text-align:left; padding:9px 12px; color:var(--ink-3); font-weight:500;
               font-size:12px; white-space:nowrap; }
table.tbl td { padding:11px 12px; border-top:1px solid #1c222a; vertical-align:top; }
table.tbl td.num,table.tbl th.num { text-align:right; }
table.tbl td.act { text-align:right; white-space:nowrap; }
table.tbl td.nowrap { white-space:nowrap; }
@media (max-width:900px) {
  .gmenu { position:fixed; left:12px; right:12px; top:72px; }
}
