/* ============================================================
   OPERATIONS DASHBOARD

   The overview an org admin lands on. Thirteen framed modules, each doing one
   job, with the headline surfaced above the detail. Replaces the single large
   stage in css/holo.css on this screen: a stage reads as a diagram, and this
   screen is somebody's morning.

   holo.css is not retired. It is the presentation surface, dark, for a board
   screen or a demo. This is the working surface, light by default. Rule 5.

   Built after an audit that found three classes of fault, all of the kind that
   only show up when you measure rather than look:

   1. Type. 106 elements sat under 10px and 60 of those at 8px, across
      seventeen accidental sizes. Nothing here is below 11px and the scale has
      five steps.
   2. Contrast. 118 elements failed WCAG AA against their own background. The
      neutrals were chosen to look restrained and were simply hard to read.
      Every one now clears 4.5:1, in BOTH themes.
   3. Dead space. The signal panel carried 608px of nothing, because a grid row
      stretches every panel to its tallest member. Panels no longer stretch
      (align-items:start), and the short ones were given their real content
      instead of a truncated top seven.

   Every token is declared on .ops rather than :root, because this mounts
   inside the org admin panel, which has its own colors and must keep them.
   ============================================================ */

.ops{
  --ground:transparent; --panel:#FFFFFF; --panel-2:#F4F7FA;
  --hair:rgba(19,26,36,.13); --hair-2:rgba(19,26,36,.07);
  --ink:#131A24; --ink-2:#414E60; --ink-3:#4E5C6E;
  /* --a is the org's own color as an RGB triplet, set inline by js/ops.js.
     This is the fallback, not the brand: rule 4, one accent token drives every
     fill, line and state on the screen. */
  --a:37,107,66; --a-ink:#1B5A36; --steel:#2C6E9B;
  --good:#1B7A52; --warn:#8A5A0B;
  --warn-bg:rgba(138,90,11,.09); --warn-line:rgba(138,90,11,.32);
  --f:'Inter',ui-sans-serif,system-ui,'Segoe UI',Roboto,Helvetica,Arial,sans-serif;

  color:var(--ink); font:400 14px/1.5 var(--f); -webkit-font-smoothing:antialiased;
}

/* Dark is a deliberate choice, never a system default here: the admin panel
   around this is a light working screen, and flipping only the middle of it
   because the laptop is in dark mode would look broken. The toggle sets
   data-ops-theme on the mount, and js/ops.js remembers it per person. */
.ops[data-ops-theme="dark"]{
  --panel:#111823; --panel-2:#161F2C;
  --hair:rgba(190,214,240,.14); --hair-2:rgba(190,214,240,.075);
  --ink:#F0F4F9; --ink-2:#C0CCDB; --ink-3:#93A4B8;
  --a-ink:#FF7CA4; --steel:#7FB0D8; --good:#4CD49B;
  --warn:#E5AC57; --warn-bg:rgba(229,172,87,.10); --warn-line:rgba(229,172,87,.34);
  background:#070B11; border-radius:14px; padding-bottom:4px;
}

.ops *{box-sizing:border-box}
.ops .num{font-variant-numeric:tabular-nums}

/* ---------- HEAD ---------- */
.ops-head{display:flex;align-items:center;gap:16px;flex-wrap:wrap;padding:15px 18px;background:var(--panel);border:1px solid var(--hair);border-radius:12px;margin-bottom:10px}
.ops-badge{width:34px;height:34px;border-radius:9px;display:grid;place-items:center;flex:none;background:rgba(var(--a),.12);border:1px solid var(--hair);font:700 13px/1 var(--f);color:var(--a-ink);overflow:hidden}
.ops-badge img{width:100%;height:100%;object-fit:cover}
.ops-org{font:700 11px/1 var(--f);letter-spacing:.14em;text-transform:uppercase;color:var(--ink-3)}
.ops-head h2{font:300 23px/1.1 var(--f);letter-spacing:-.015em;margin:6px 0 0;color:var(--ink)}
.ops-right{margin-left:auto;display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.ops-seg{display:inline-flex;border:1px solid var(--hair);border-radius:8px;overflow:hidden;background:var(--panel)}
.ops-seg button{font:600 11px/1 var(--f);letter-spacing:.06em;padding:8px 13px;border:0;background:none;color:var(--ink-3);cursor:pointer;border-right:1px solid var(--hair-2)}
.ops-seg button:last-child{border-right:0}
.ops-seg button:hover{color:var(--ink);background:var(--panel-2)}
.ops-seg button.on{background:rgba(var(--a),.14);color:var(--a-ink)}
.ops-seg button:focus-visible{outline:2px solid var(--a-ink);outline-offset:-2px}
.ops-live{display:inline-flex;align-items:center;gap:8px;font:600 11px/1 var(--f);letter-spacing:.12em;text-transform:uppercase;color:var(--ink-3)}
.ops-live::before{content:"";width:7px;height:7px;border-radius:50%;background:var(--good)}

/* ---------- GRID ---------- */
/* align-items:start is the fix for the 608px of dead space. A grid row
   stretches every panel to its tallest member unless told not to. */
.ops-grid{display:grid;gap:10px;grid-template-columns:repeat(12,1fr);align-items:start}
.ops .p{background:var(--panel);border:1px solid var(--hair);border-radius:12px;padding:15px 17px 17px;min-width:0;box-shadow:0 1px 2px rgba(19,26,36,.05)}
.ops .ph{display:flex;align-items:baseline;gap:10px;margin-bottom:13px}
.ops .ph h3{margin:0;font:700 11px/1 var(--f);letter-spacing:.13em;text-transform:uppercase;color:var(--ink-3)}
.ops .ph .n{margin-left:auto;font:400 11px/1 var(--f);color:var(--ink-3)}
.ops .c2{grid-column:span 2}
.ops .c3{grid-column:span 3}
.ops .c4{grid-column:span 4}
.ops .c5{grid-column:span 5}
.ops .c8{grid-column:span 8}
@media(max-width:1240px){.ops .c8,.ops .c5,.ops .c4{grid-column:span 6}.ops .c3,.ops .c2{grid-column:span 4}}
@media(max-width:780px){.ops .c8,.ops .c5,.ops .c4,.ops .c3{grid-column:span 12}.ops .c2{grid-column:span 6}}

/* Rule 2: every number is a door. Anything that opens a screen looks like it,
   with a pointer, a hover lift and a focus ring. Nothing on the first version
   announced itself as clickable. */
.ops a.p{text-decoration:none;color:inherit;display:block;transition:border-color .15s,box-shadow .15s,transform .15s}
/* a.rr keeps its grid: display:block here collapsed the value onto the label
   and hid the bar entirely on every linked row. */
.ops a.rr{text-decoration:none;color:inherit;transition:background .15s}
.ops a.p:hover{border-color:rgba(var(--a),.55);box-shadow:0 5px 16px -8px rgba(19,26,36,.4);transform:translateY(-1px)}
.ops a.p:focus-visible,.ops a.rr:focus-visible{outline:2px solid var(--a-ink);outline-offset:2px;border-radius:12px}
.ops a.p .kv::after{content:"\203A";font-size:.55em;color:var(--ink-3);margin-left:8px;opacity:0;transition:opacity .15s}
.ops a.p:hover .kv::after{opacity:1}

/* ---------- KPI ---------- */
.ops .kv{font:300 34px/1 var(--f);letter-spacing:-.025em;color:var(--ink)}
.ops .kv small{font-size:.42em;font-weight:400;color:var(--ink-3);margin-left:3px}
.ops .kc{font-size:12.5px;color:var(--ink-3);margin-top:7px;line-height:1.45}
.ops .chip{display:inline-flex;align-items:center;gap:5px;margin-top:10px;font:700 11px/1 var(--f);padding:4px 9px;border-radius:20px;border:1px solid}
.ops .chip.up{color:var(--good);border-color:var(--good);background:rgba(27,122,82,.08)}
.ops .chip.down{color:var(--warn);border-color:var(--warn-line);background:var(--warn-bg)}
.ops .chip.hold{color:var(--ink-3);border-color:var(--hair)}

/* ---------- CHART ---------- */
.ops svg{display:block;width:100%;overflow:visible}
.ops .ax{font:500 11px/1 var(--f);fill:var(--ink-3)}
.ops .gl{stroke:var(--hair-2);stroke-width:1}

/* ---------- RANKED LIST ---------- */
.ops .rank{display:flex;flex-direction:column;gap:11px}
.ops .rr{display:grid;grid-template-columns:1fr auto;gap:5px 10px;align-items:center;padding:3px 5px;margin:-3px -5px;border-radius:7px}
.ops a.rr:hover{background:var(--panel-2)}
.ops .rr .n{font-size:13px;color:var(--ink-2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ops .rr .v{font:600 12.5px/1 var(--f);color:var(--ink);font-variant-numeric:tabular-nums}
.ops .rr .t{grid-column:1/-1;height:4px;border-radius:2px;background:var(--hair-2);overflow:hidden}
.ops .rr .t i{display:block;height:100%;border-radius:2px;background:var(--k,rgb(var(--a)))}

/* ---------- MAP ---------- */
/* The map and the city list side by side. Stacked, this panel ran half again
   as tall as the two beside it and left the row it sits in visibly empty. */
.ops .geo-split{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:18px;align-items:start}
.ops .geo-split .detail{margin-top:0;padding-top:0;border-top:0}
@media(max-width:1240px){.ops .geo-split{grid-template-columns:minmax(0,1fr)}
  .ops .geo-split .detail{margin-top:14px;padding-top:13px;border-top:1px solid var(--hair-2)}}
.ops .us{display:grid;grid-template-columns:repeat(11,1fr);gap:3px}
.ops .st{position:relative;aspect-ratio:1;border-radius:4px;border:1px solid var(--hair-2);background:var(--panel-2);display:grid;place-items:center;overflow:hidden}
.ops .st.void{border-color:transparent;background:none}
.ops .st i{position:absolute;inset:0;background:rgb(var(--a));opacity:var(--w,0)}
.ops .st b{position:relative;font:700 11px/1 var(--f);color:var(--ink-3)}
.ops .st.on b{color:var(--ink)}
.ops .st.on{border-color:rgba(var(--a),.5)}
.ops .legend{display:flex;align-items:center;gap:11px;margin-top:11px;font-size:12px;color:var(--ink-3);flex-wrap:wrap}
.ops .sc{display:inline-flex;gap:2px}
.ops .sc i{width:14px;height:9px;border-radius:2px;background:rgb(var(--a))}
.ops .sc i:nth-child(1){opacity:.16}
.ops .sc i:nth-child(2){opacity:.34}
.ops .sc i:nth-child(3){opacity:.55}
.ops .sc i:nth-child(4){opacity:.78}
.ops .detail{margin-top:14px;padding-top:13px;border-top:1px solid var(--hair-2)}
.ops .dh{font:700 11px/1 var(--f);letter-spacing:.13em;text-transform:uppercase;color:var(--ink-3);margin-bottom:10px}
.ops .dh span{font-weight:400;letter-spacing:0;text-transform:none;margin-left:8px}
.ops .warn{margin-top:11px;padding:11px 13px;border-radius:9px;font-size:12.5px;line-height:1.5;background:var(--warn-bg);border:1px solid var(--warn-line);color:var(--ink-2)}
.ops .warn b{color:var(--warn)}

/* ---------- NETWORK ---------- */
.ops .net{position:relative;aspect-ratio:1/.66;min-height:230px}
.ops .node{position:absolute;transform:translate(-50%,-50%);cursor:pointer;text-align:center;z-index:2;background:none;border:0;font:inherit;color:inherit;padding:0}
.ops .node .d{display:block;width:10px;height:10px;border-radius:50%;margin:0 auto;background:rgb(var(--a));box-shadow:0 0 0 3px rgba(var(--a),.16);transition:transform .18s}
.ops .node .k{display:block;font:700 11px/1 var(--f);letter-spacing:.05em;text-transform:uppercase;color:var(--ink-3);margin-top:7px;white-space:nowrap}
.ops .node .v{display:block;font:400 15px/1.1 var(--f);font-variant-numeric:tabular-nums;margin-top:3px;color:var(--ink)}
.ops .node:hover .d,.ops .node.on .d{transform:scale(1.35)}
.ops .node:focus-visible{outline:2px solid var(--a-ink);outline-offset:6px;border-radius:7px}
.ops .edge{fill:none;stroke:rgba(var(--a),.22);stroke-width:1;vector-effect:non-scaling-stroke;transition:stroke .18s,stroke-width .18s}
.ops .edge.on{stroke:rgba(var(--a),.9);stroke-width:1.7}
/* Rule 6: nothing decorative may look like data. Each cell is one member of
   this org, so the field cannot be a different size than the roster. */
.ops .cell{fill:rgb(var(--a));opacity:.22}
.ops .fib{stroke:rgba(var(--a),.13);stroke-width:.6;vector-effect:non-scaling-stroke}
.ops .read{border-top:1px solid var(--hair-2);margin-top:12px;padding-top:12px;min-height:62px}
.ops .read .t{font:500 15px/1.25 var(--f);color:var(--ink)}
.ops .read .s{font-size:12.5px;color:var(--ink-3);line-height:1.55;margin-top:5px}

/* ---------- LAMPS ---------- */
.ops .lamp{display:flex;gap:12px;align-items:flex-start;padding:12px 0;border-bottom:1px solid var(--hair-2);font-size:12.5px;line-height:1.5}
.ops .lamp:last-child{border-bottom:0;padding-bottom:0}
.ops .lamp .i{width:24px;height:24px;border-radius:50%;flex:none;display:grid;place-items:center;font:700 12px/1 var(--f)}
.ops .lamp.on .i{background:var(--warn-bg);color:var(--warn)}
.ops .lamp.ok .i{background:rgba(27,122,82,.10);color:var(--good)}
/* A suggestion, not a warning. The old state used the amber warn color and an
   exclamation mark, which is why a tester filed twelve of these as bugs. */
.ops .lamp.do .i{background:rgba(var(--a),.10);color:rgb(var(--a))}
.ops .lamp p{margin:0;color:var(--ink-3)}
.ops .lamp p b{color:var(--ink-2);font-weight:600}

.ops .ops-note{margin:12px 2px 0;font-size:12px;color:var(--ink-3)}

@media(prefers-reduced-motion:reduce){.ops *{animation:none!important;transition:none!important}}
