/* ─── SCADA Registry ─────────────────────────────────────────────────────────
 *
 * A human-machine interface built the way system software was built before
 * anyone thought of flat design: every surface is either proud of the one
 * behind it or recessed into it, and you can tell which by looking at its
 * edges.
 *
 * That trick is the whole language here, and it is always the same four
 * declarations:
 *
 *   RAISED    border-color: hi lo lo hi
 *             box-shadow: inset 1px 1px 0 edge-in, inset -1px -1px 0 edge-sh
 *   RECESSED  the same contour inverted
 *
 * Light on the top and left, black on the bottom and right. Two pixels of
 * border and two inset highlights, nothing more, and a rectangle stops being
 * a div and becomes a panel you could put a thumb on.
 *
 * Windows, buttons and query keys are raised. Readouts, tables, the console
 * and input fields are recessed. A pressed button is a raised thing wearing
 * the recessed contour.
 *
 * It is not Windows grey. The contours are borrowed; the palette is the
 * Registry's own - cyan and amber on near-black, so it reads as a different
 * machine from the dApp's monochrome green. Same facility, different rack.
 */

:root {
  --bg:        #060a0f;
  --face:      #121b24;   /* the face of a raised panel */
  --face-lit:  #1a2733;   /* hovered / title bars */
  --well:      #03070b;   /* recessed interiors */

  /* The contour. Light top-left, black bottom-right - and the highlight has
     to be genuinely light against the face or the lip does not read at all.
     On a grey desktop that was #fff against #c0c0c0; this is the same
     relationship moved into the dark. */
  --edge-hi:   #52708a;
  --edge-lo:   #000000;
  --edge-in:   rgba(255, 255, 255, 0.13);
  --edge-sh:   #04070a;

  --text:      #c2d0dd;
  --dim:       #637789;
  --dimmer:    #3d4a59;

  --cyan:      #46d5ff;
  --cyan-dim:  #1b5a70;
  --cyan-glow: rgba(70, 213, 255, 0.45);
  --amber:     #ffb454;
  --amber-dim: #5c3f16;

  --ok:        #41e08a;
  --warn:      #ffb454;
  --fault:     #ff5468;

  --mono: 'JetBrains Mono', ui-monospace, 'SFMono-Regular', Menlo, monospace;
  --display: 'VT323', var(--mono);

  --gutter: 18px;
  --maxw: 1280px;
}

*, *::before, *::after { box-sizing: border-box; }
[hidden] { display: none !important; }

html { background: var(--bg); }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--mono);
  font-size: 12.5px;
  line-height: 1.5;
  font-variant-numeric: tabular-nums;
  -webkit-font-smoothing: antialiased;
}

/* The surface the windows sit on. A faint weave, the way a desktop had one. */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  background:
    repeating-linear-gradient(90deg, rgba(70,213,255,.025) 0 1px, transparent 1px 44px),
    repeating-linear-gradient(0deg,  rgba(70,213,255,.025) 0 1px, transparent 1px 44px),
    radial-gradient(90% 60% at 50% 0%, rgba(70,213,255,.05), transparent 65%);
}

/* Scanlines, at the threshold of noticing. */
body::after {
  content: '';
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 100;
  background: repeating-linear-gradient(to bottom,
    rgba(0,0,0,.2) 0px, rgba(0,0,0,.2) 1px, transparent 1px, transparent 3px);
  opacity: .5;
}

.wrap {
  position: relative;
  z-index: 1;
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 18px var(--gutter) 70px;
}

a { color: var(--cyan); text-decoration: none; border-bottom: 1px dotted var(--cyan-dim); }
a:hover { border-bottom-style: solid; }

/* ── the rail ───────────────────────────────────────────────────────────── */

.rail {
  position: sticky;
  top: 0;
  z-index: 40;
  background: var(--face);
  border-bottom: 2px solid var(--edge-lo);
  box-shadow: inset 0 1px 0 var(--edge-in), 0 2px 0 #0a1118;
}
.rail-inner { max-width: var(--maxw); margin: 0 auto; padding: 0 var(--gutter); }
.rail-top { display: flex; align-items: center; gap: 16px; height: 46px; }

.mark {
  font-family: var(--display);
  font-size: 28px;
  letter-spacing: 3px;
  text-transform: uppercase;
  color: var(--cyan);
  text-shadow: 0 0 14px var(--cyan-glow);
  line-height: 1;
  white-space: nowrap;
}
.mark span { color: var(--dimmer); text-shadow: none; }

.rail-state {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12.6px;
  letter-spacing: .6px;
  text-transform: uppercase;
  color: var(--dim);
  white-space: nowrap;
}

.rail-stats {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-left: auto;
  font-size: 12.6px;          /* 10.5 + 20%: these are the readings, not chrome */
  letter-spacing: .6px;
  text-transform: uppercase;
  color: var(--dim);
  white-space: nowrap;
}
.rail-stats b { color: var(--text); font-weight: 500; margin-left: 5px; letter-spacing: 0; text-transform: none; }

.lamp {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--dimmer);
  box-shadow: inset 0 0 2px rgba(0,0,0,.8);
  flex: none;
}
.lamp.ok   { background: var(--ok);    box-shadow: 0 0 9px rgba(65,224,138,.85); animation: pulse 2.6s ease-in-out infinite; }
.lamp.warn { background: var(--warn);  box-shadow: 0 0 9px rgba(255,180,84,.85); }
.lamp.bad  { background: var(--fault); box-shadow: 0 0 9px rgba(255,84,104,.9);  animation: blink 1.1s steps(1) infinite; }
@keyframes pulse { 50% { opacity: .55; } }
@keyframes blink { 50% { opacity: .25; } }

/* ── buttons: raised, and they go in when you press them ────────────────── */

.ghost, .key {
  border: 2px solid;
  border-color: var(--edge-hi) var(--edge-lo) var(--edge-lo) var(--edge-hi);
  background: var(--face);
  box-shadow: inset 1px 1px 0 var(--edge-in), inset -1px -1px 0 var(--edge-sh);
  color: var(--text);
  font: inherit;
  cursor: pointer;
}
.ghost {
  font-size: 10px;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  padding: 4px 11px;
  color: var(--dim);
}
.ghost:hover:not(:disabled) { color: var(--cyan); background: var(--face-lit); }
/* Pressed: the contour inverts and the label moves a pixel into the press.
   The padding is rebalanced rather than reduced - 11+9 is the same twenty
   pixels as 10+10 - because shrinking a button shrinks the window around it,
   and a dialog that jumps when you click it is a broken dialog. */
.ghost:active:not(:disabled), .key:active:not(:disabled) {
  border-color: var(--edge-lo) var(--edge-hi) var(--edge-hi) var(--edge-lo);
  box-shadow: inset 1px 1px 0 var(--edge-sh), inset -1px -1px 0 var(--edge-in);
}
.ghost:active:not(:disabled) { padding: 5px 10px 3px 12px; }
.key:active:not(:disabled)   { padding: 11px 25px 9px 27px; }
.ghost:disabled, .key:disabled { opacity: .4; cursor: not-allowed; }

.key {
  font-size: 12px;
  letter-spacing: 2.4px;
  text-transform: uppercase;
  padding: 10px 26px;
  color: var(--cyan);
  text-shadow: 0 0 10px var(--cyan-glow);
  margin-top: 20px;
}
.key:hover:not(:disabled) { background: var(--face-lit); }

/* ── windows ────────────────────────────────────────────────────────────── */

.win {
  margin-top: 16px;
  border: 2px solid;
  border-color: var(--edge-hi) var(--edge-lo) var(--edge-lo) var(--edge-hi);
  background: var(--face);
  box-shadow:
    inset 1px 1px 0 var(--edge-in),
    inset -1px -1px 0 var(--edge-sh),
    3px 3px 0 rgba(0, 0, 0, .55);
}

.win-bar {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 5px 8px;
  margin: 2px;
  background: linear-gradient(90deg, #0e3f55 0%, #092834 62%, #071d26 100%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.08);
}
.win-title {
  font-family: var(--display);
  font-size: 19.8px;
  letter-spacing: 3px;
  text-transform: uppercase;
  color: #dff4ff;
  text-shadow: 0 0 10px var(--cyan-glow);
  line-height: 1.1;
}
/* The slashes are the house mark, so every window wears them. */
.win-title span { color: #466b7f; text-shadow: none; }
.win-note { font-size: 11.8px; color: #7ea6ba; letter-spacing: .6px; }

/* The minimize key. A real key: raised, and it goes in when pressed. */
.win-min {
  margin-left: auto;
  flex: none;
  position: relative;
  width: 22px;
  height: 17px;
  padding: 0;
  border: 2px solid;
  border-color: var(--edge-hi) var(--edge-lo) var(--edge-lo) var(--edge-hi);
  background: var(--face);
  box-shadow: inset 1px 1px 0 var(--edge-in), inset -1px -1px 0 var(--edge-sh);
  cursor: pointer;
}
.win-min::before {
  content: '';
  position: absolute;
  left: 4px;
  right: 4px;
  bottom: 3px;
  height: 2px;
  background: var(--text);
}
.win-min:hover { background: var(--face-lit); }
.win-min:active {
  border-color: var(--edge-lo) var(--edge-hi) var(--edge-hi) var(--edge-lo);
  box-shadow: inset 1px 1px 0 var(--edge-sh), inset -1px -1px 0 var(--edge-in);
}
/* The close key. Same housing as the minimize key, with a cross cut into it. */
.win-close {
  margin-left: 5px;
  flex: none;
  position: relative;
  width: 22px;
  height: 17px;
  padding: 0;
  border: 2px solid;
  border-color: var(--edge-hi) var(--edge-lo) var(--edge-lo) var(--edge-hi);
  background: var(--face);
  box-shadow: inset 1px 1px 0 var(--edge-in), inset -1px -1px 0 var(--edge-sh);
  cursor: pointer;
}
.win-close::before, .win-close::after {
  content: '';
  position: absolute;
  left: 50%;
  top: 50%;
  width: 9px;
  height: 2px;
  margin: -1px 0 0 -4.5px;
  background: var(--text);
}
.win-close::before { transform: rotate(45deg); }
.win-close::after  { transform: rotate(-45deg); }
.win-close:hover { background: var(--face-lit); }
.win-close:hover::before, .win-close:hover::after { background: var(--fault); }
.win-close:active {
  border-color: var(--edge-lo) var(--edge-hi) var(--edge-hi) var(--edge-lo);
  box-shadow: inset 1px 1px 0 var(--edge-sh), inset -1px -1px 0 var(--edge-in);
}

/* Minimised: the title bar stays exactly where it was, the body goes. */
.win.collapsed .win-body,
.report.collapsed .report-body { display: none; }
/* The key reads as a restore once there is nothing left to minimise. */
.collapsed .win-min::before { bottom: 50%; transform: translateY(1px); }
.win-body { padding: 14px; }

/* ── the login window ───────────────────────────────────────────────────── */

.login {
  max-width: 560px;
  margin: 9vh auto 0;
}
.login .win-body { padding: 22px 24px 24px; }
.explain { color: var(--dim); margin: 0; line-height: 1.75; }
.explain strong { color: var(--text); font-weight: 500; }

.boot { margin-top: 18px; font-size: 12px; }
.boot div { opacity: 0; animation: cut .16s steps(1) forwards; color: var(--dim); }
.boot div::before { content: '> '; color: var(--dimmer); }
.boot div b { color: var(--text); font-weight: 500; }
.boot div.grant { color: var(--ok); text-shadow: 0 0 10px rgba(65,224,138,.35); }
@keyframes cut { to { opacity: 1; } }

@media (prefers-reduced-motion: reduce) {
  .boot div { animation: none; opacity: 1; }
  .lamp.ok, .lamp.bad { animation: none; }
}

/* ── readouts ───────────────────────────────────────────────────────────── */

.vitals { display: grid; grid-template-columns: repeat(auto-fit, minmax(166px, 1fr)); gap: 9px; }

.tile {
  padding: 9px 11px 10px;
  border: 2px solid;
  border-color: var(--edge-lo) var(--edge-hi) var(--edge-hi) var(--edge-lo);
  background: var(--well);
  box-shadow: inset 1px 1px 0 var(--edge-sh);
}
.tile .k { display: block; font-size: 10.8px; letter-spacing: 1.7px; text-transform: uppercase; color: var(--dim); }
.tile .k::after { content: ':'; color: var(--dimmer); }
.tile .v {
  font-size: 21px; line-height: 1.15; margin-top: 4px;
  color: var(--text); letter-spacing: -.4px;
  text-shadow: 0 0 10px rgba(194,208,221,.18);
}
.tile .v.accent { color: var(--cyan);  text-shadow: 0 0 12px var(--cyan-glow); }
.tile .v.ok     { color: var(--ok);    text-shadow: 0 0 12px rgba(65,224,138,.4); }
.tile .v.warn   { color: var(--warn);  text-shadow: 0 0 12px rgba(255,180,84,.4); }
.tile .v.bad    { color: var(--fault); text-shadow: 0 0 12px rgba(255,84,104,.45); }
.tile .sub { font-size: 11.4px; color: var(--dimmer); margin-top: 4px; }

.meter {
  height: 8px; margin-top: 7px;
  border: 2px solid;
  border-color: var(--edge-lo) var(--edge-hi) var(--edge-hi) var(--edge-lo);
  background: #000;
  padding: 1px;
}
.meter i { display: block; height: 100%; background: var(--cyan); box-shadow: 0 0 6px var(--cyan-glow); }
.meter.ok i   { background: var(--ok);    box-shadow: 0 0 6px rgba(65,224,138,.6); }
.meter.warn i { background: var(--warn);  box-shadow: 0 0 6px rgba(255,180,84,.6); }
.meter.bad i  { background: var(--fault); box-shadow: 0 0 6px rgba(255,84,104,.6); }

/* ── pipelines, console, tables: all recessed ───────────────────────────── */

.pipes {
  width: 100%;
  border-collapse: collapse;
  margin-top: 10px;
  border: 2px solid;
  border-color: var(--edge-lo) var(--edge-hi) var(--edge-hi) var(--edge-lo);
  background: var(--well);
}
.pipes th {
  font-size: 9px; letter-spacing: 1.7px; text-transform: uppercase;
  color: var(--dim); font-weight: normal; text-align: left;
  padding: 6px 11px;
  background: var(--face);
  border-bottom: 2px solid var(--edge-lo);
  box-shadow: inset 1px 1px 0 var(--edge-in);
}
.pipes td { padding: 4px 11px; border-bottom: 1px solid rgba(45,66,83,.25); }
.pipes tr:last-child td { border-bottom: 0; }
.pipes tr:hover td { background: rgba(70,213,255,.04); }
.pipes .num { text-align: right; }
.pipes .name { color: var(--dim); }
.pipes .drift.ok { color: var(--ok); }
.pipes .drift.warn { color: var(--warn); }
.pipes .drift.bad { color: var(--fault); }

.log {
  border: 2px solid;
  border-color: var(--edge-lo) var(--edge-hi) var(--edge-hi) var(--edge-lo);
  background: var(--well);
  box-shadow: inset 1px 1px 0 var(--edge-sh);
  height: 150px;
  min-height: 60px;
  max-height: 70vh;
  overflow: auto;
  padding: 7px 11px;
  font-size: 10.5px;
  line-height: 1.8;
  /* Drag the bottom edge. Height only: the width belongs to the window. */
  resize: vertical;
}
/* The native grip is a pale triangle that belongs to no other surface here,
   so it is replaced with a ribbed corner cut from the same bevel as the
   window it sits in. */
.log::-webkit-resizer { display: none; }
.log-wrap { position: relative; }
.log-grip {
  position: absolute;
  right: 3px;
  bottom: 3px;
  width: 13px;
  height: 13px;
  pointer-events: none;
  background:
    linear-gradient(135deg, transparent 0 46%, var(--edge-hi) 46% 54%, transparent 54%),
    linear-gradient(135deg, transparent 0 71%, var(--edge-hi) 71% 79%, transparent 79%);
  opacity: .8;
}

/* The browser's default scrollbar is the one piece of chrome on this page
   that was never designed - a pale slab on a near-black recess. This is the
   same bevel as everything else: a sunken channel with a raised thumb. */
.log::-webkit-scrollbar { width: 14px; height: 14px; }
.log::-webkit-scrollbar-track {
  background: var(--well);
  border-left: 2px solid var(--edge-lo);
  box-shadow: inset 1px 0 0 var(--edge-sh);
}
.log::-webkit-scrollbar-thumb {
  background: var(--face);
  border: 2px solid;
  border-color: var(--edge-hi) var(--edge-lo) var(--edge-lo) var(--edge-hi);
  box-shadow: inset 1px 1px 0 var(--edge-in), inset -1px -1px 0 var(--edge-sh);
}
.log::-webkit-scrollbar-thumb:hover { background: var(--face-lit); }
.log::-webkit-scrollbar-corner { background: var(--well); }
/* Firefox has no part-level control, so it gets the colours only. */
.log { scrollbar-width: thin; scrollbar-color: var(--face) var(--well); }

/* One block's activity, ruled off from the next. */
.log .blk {
  display: flex;
  align-items: center;
  gap: 8px;
  color: var(--dim);
  letter-spacing: 1.4px;
  margin-top: 6px;
  white-space: nowrap;
}
.log div:first-child.blk { margin-top: 0; }
.log .blk .bar {
  flex: 1 1 auto;
  height: 0;
  border-top: 1px solid var(--edge-hi);
  opacity: .45;
}
.log .blk b { color: var(--cyan); font-weight: 500; letter-spacing: .5px; }

.log .verb { color: var(--text); }
.log .verb.bought  { color: var(--ok); }
.log .verb.sold    { color: var(--fault); }
.log .verb.liq     { color: var(--amber); }
.log .verb.quiet   { color: var(--dim); }
/* A tax leg belongs to the transfer above it, so it reads as a sub-line. */
.log div.quiet .who { color: var(--dim); }
.log div.quiet b    { color: var(--dim); font-weight: 400; }
.log div.quiet      { opacity: .72; }
.log .who { color: var(--cyan); }
.log .tag { color: var(--amber); }

/* Clickable, but only advertising it under the pointer - a dotted rule under
   every address and hash would turn the feed into a page of underlines. */
.log .copy { cursor: pointer; }
.log .copy:hover {
  color: var(--cyan);
  border-bottom: 1px dotted currentColor;
}
.log .copy.copied {
  color: var(--ok);
  border-bottom: 0;
  letter-spacing: 1px;
}
.log .tx  { color: var(--dimmer); }
.log div { color: var(--dim); white-space: nowrap; }
.log .t { color: var(--dimmer); }
.log .tag { color: var(--cyan); }
.log .tag.warn { color: var(--warn); }
.log .tag.bad { color: var(--fault); }
.log b { color: var(--text); font-weight: 500; }

/* ── the query keys ─────────────────────────────────────────────────────── */

.palette { display: grid; grid-template-columns: repeat(auto-fill, minmax(206px, 1fr)); gap: 7px; }

.q {
  border: 2px solid;
  border-color: var(--edge-hi) var(--edge-lo) var(--edge-lo) var(--edge-hi);
  background: var(--face);
  box-shadow: inset 1px 1px 0 var(--edge-in), inset -1px -1px 0 var(--edge-sh);
  text-align: left;
  padding: 8px 11px;
  color: var(--text);
  font: inherit;
  cursor: pointer;
}
.q:hover { background: var(--face-lit); }
.q.on {
  border-color: var(--edge-lo) var(--edge-hi) var(--edge-hi) var(--edge-lo);
  box-shadow: inset 1px 1px 0 var(--edge-sh), inset -1px -1px 0 var(--edge-in);
  background: var(--well);
}
.q .n { display: block; font-size: 12.5px; }
.q.on .n { color: var(--cyan); }
.q .t { display: block; font-size: 9px; letter-spacing: 1.5px; text-transform: uppercase; color: var(--dimmer); margin-top: 2px; }
.q mark { background: transparent; color: var(--cyan); text-shadow: 0 0 8px var(--cyan-glow); }

/* ── reports ────────────────────────────────────────────────────────────── */

.stream { margin-top: 16px; }
.stream > * + * { margin-top: 14px; }

.report {
  border: 2px solid;
  border-color: var(--edge-hi) var(--edge-lo) var(--edge-lo) var(--edge-hi);
  background: var(--face);
  box-shadow: inset 1px 1px 0 var(--edge-in), inset -1px -1px 0 var(--edge-sh),
              3px 3px 0 rgba(0,0,0,.5);
}
.report-bar {
  display: flex; align-items: center; gap: 10px;
  padding: 5px 8px; margin: 2px;
  background: linear-gradient(90deg, #0e3f55 0%, #092834 62%, #071d26 100%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.08);
}
.report-bar .seq {
  font-size: 10px; color: var(--amber);
  border: 1px solid var(--amber-dim); padding: 0 5px; letter-spacing: 1px;
}
.report-bar .ttl {
  font-family: var(--display); font-size: 18.7px; letter-spacing: 2.4px;
  text-transform: uppercase; color: #dff4ff; text-shadow: 0 0 10px var(--cyan-glow);
  line-height: 1.1;
}
.report-bar .ttl span { color: #466b7f; text-shadow: none; }
/* What the report was asked about. Monospace because it is usually an
   address, and the first thing allowed to shrink: it takes the slack so the
   clock, minimise and close never get pushed off a narrow window. */
.report-bar .subj {
  flex: 0 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-family: var(--mono, ui-monospace, monospace);
  font-size: 11.8px;
  letter-spacing: .4px;
  color: var(--amber);
}
.report-bar .sep { font-size: 11.8px; color: #466b7f; }
.report-bar .when { flex: 0 0 auto; font-size: 11.8px; color: #7ea6ba; }
.report-body { padding: 14px; }

.headline { font-family: var(--display); font-size: 23px; letter-spacing: 1px; color: var(--text); margin: 0 0 8px; }
/* Prose runs the full width of the report rather than sitting in a column on
   the left with the panel empty beside it. The reports that carry an
   explainer are read once and then skimmed, so filling the panel costs less
   than the ragged gap it replaces. */
.lead { color: var(--dim); margin: 0 0 5px; }
.lead strong { color: var(--text); font-weight: 500; }

.knobs {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  margin-top: 14px; padding-top: 12px;
  border-top: 1px solid var(--edge-lo);
  box-shadow: 0 -1px 0 var(--edge-in) inset;
}
.knobs label { font-size: 9px; letter-spacing: 1.7px; text-transform: uppercase; color: var(--dim); }
.knobs label::after { content: ':'; color: var(--dimmer); }
.knobs input {
  border: 2px solid;
  border-color: var(--edge-lo) var(--edge-hi) var(--edge-hi) var(--edge-lo);
  background: var(--well);
  box-shadow: inset 1px 1px 0 var(--edge-sh);
  color: var(--cyan);
  font: inherit; font-size: 12px;
  padding: 4px 7px; width: 92px;
}
.knobs input.wide { width: 390px; max-width: 100%; }

/* ── the calendar ──────────────────────────────────────────────────────────
   Built rather than borrowed: a native date input's popup is browser chrome,
   not DOM, so it cannot be made to match anything around it. This is the same
   bevel as every other surface here. */

/* The mode keys. The armed one stays pressed, so which window the Run button
   will actually use is visible rather than inferred. */
.knobs .mode { letter-spacing: 1.2px; }
.knobs .mode.on {
  color: var(--cyan);
  border-color: var(--edge-lo) var(--edge-hi) var(--edge-hi) var(--edge-lo);
  box-shadow: inset 1px 1px 0 var(--edge-sh), inset -1px -1px 0 var(--edge-in);
  background: var(--well);
}
/* SCADA's history. Each series is scaled to its own range, so the shapes are
   comparable but the heights are not - the endpoints below carry the values. */
.trend {
  width: 100%;
  height: 120px;
  display: block;
  margin: 8px 0 6px;
  background: var(--well);
  box-shadow: inset 1px 1px 0 var(--edge-sh), inset -1px -1px 0 var(--edge-in);
}

.knob-fields { display: inline-flex; align-items: center; gap: 8px; margin-left: 6px; }

.date-wrap { position: relative; display: inline-block; }
.knobs input.date { width: 118px; text-align: center; cursor: pointer; }

.cal {
  position: absolute;
  top: calc(100% + 5px);
  left: 0;
  z-index: 60;
  padding: 7px;
  border: 2px solid;
  border-color: var(--edge-hi) var(--edge-lo) var(--edge-lo) var(--edge-hi);
  background: var(--face);
  box-shadow: inset 1px 1px 0 var(--edge-in), inset -1px -1px 0 var(--edge-sh),
              3px 3px 0 rgba(0, 0, 0, .55);
}

.cal-head {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 6px;
}
.cal-title {
  flex: 1 1 auto;
  text-align: center;
  font-family: var(--display);
  font-size: 17px;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--cyan);
  text-shadow: 0 0 10px var(--cyan-glow);
  white-space: nowrap;
}
.cal-step {
  flex: none;
  width: 20px;
  height: 18px;
  padding: 0;
  font: inherit;
  font-size: 13px;
  line-height: 1;
  color: var(--text);
  border: 2px solid;
  border-color: var(--edge-hi) var(--edge-lo) var(--edge-lo) var(--edge-hi);
  background: var(--face);
  box-shadow: inset 1px 1px 0 var(--edge-in), inset -1px -1px 0 var(--edge-sh);
  cursor: pointer;
}
.cal-step:hover { background: var(--face-lit); color: var(--cyan); }
.cal-step:active {
  border-color: var(--edge-lo) var(--edge-hi) var(--edge-hi) var(--edge-lo);
  box-shadow: inset 1px 1px 0 var(--edge-sh), inset -1px -1px 0 var(--edge-in);
}

.cal-grid {
  display: grid;
  grid-template-columns: repeat(7, 26px);
  gap: 2px;
}
.cal-dow {
  text-align: center;
  font-size: 9px;
  letter-spacing: 1px;
  color: var(--dim);
  padding-bottom: 2px;
}
.cal-pad { height: 22px; }
.cal-day {
  height: 22px;
  padding: 0;
  font: inherit;
  font-size: 11px;
  color: var(--text);
  border: 2px solid;
  border-color: var(--edge-hi) var(--edge-lo) var(--edge-lo) var(--edge-hi);
  background: var(--face);
  box-shadow: inset 1px 1px 0 var(--edge-in);
  cursor: pointer;
}
.cal-day:hover:not(:disabled) { background: var(--face-lit); color: var(--cyan); }
.cal-day:disabled {
  color: var(--dimmer);
  background: var(--well);
  border-color: var(--edge-lo) var(--edge-hi) var(--edge-hi) var(--edge-lo);
  box-shadow: none;
  cursor: not-allowed;
}
/* The snapshot's own day, so "now" is the index's now and not the browser's. */
.cal-day.today { color: var(--amber); }
.cal-day.on {
  color: var(--cyan);
  border-color: var(--edge-lo) var(--edge-hi) var(--edge-hi) var(--edge-lo);
  box-shadow: inset 1px 1px 0 var(--edge-sh), 0 0 10px rgba(70, 213, 255, .25);
  background: var(--well);
}
.knobs input:focus { outline: none; }
.knobs input[type=number] { -moz-appearance: textfield; appearance: textfield; }
.knobs input[type=number]::-webkit-inner-spin-button,
.knobs input[type=number]::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }

.sect { margin-top: 18px; }
.sect-head { display: flex; align-items: center; gap: 10px; margin-bottom: 6px; }
.sect-head h3 { font-size: 10px; letter-spacing: 2px; text-transform: uppercase; color: var(--amber); font-weight: normal; margin: 0; }
.sect-head .rule { flex: 1 1 auto; height: 2px; border-top: 1px solid var(--edge-lo); border-bottom: 1px solid var(--edge-in); }
.sect-head .count { font-size: 9.5px; color: var(--dimmer); letter-spacing: 1px; }

.scroll-x { overflow-x: auto; }

table.data {
  width: 100%;
  border-collapse: collapse;
  font-size: 12px;
  border: 2px solid;
  border-color: var(--edge-lo) var(--edge-hi) var(--edge-hi) var(--edge-lo);
  background: var(--well);
}
table.data th {
  font-size: 9px; letter-spacing: 1.5px; text-transform: uppercase;
  color: var(--dim); font-weight: normal; text-align: left;
  padding: 5px 11px; white-space: nowrap;
  background: var(--face);
  border-bottom: 2px solid var(--edge-lo);
  box-shadow: inset 1px 1px 0 var(--edge-in);
}
table.data td { padding: 4px 11px; border-bottom: 1px solid rgba(45,66,83,.22); white-space: nowrap; }
table.data tr:last-child td { border-bottom: 0; }
table.data tr:hover td { background: rgba(70,213,255,.045); }
table.data .num, table.data th.num { text-align: right; }
/* The row a report is about - SCADA among ninety other tokens. Marked by the
   query, not by position, so it stays found wherever the sort puts it. The
   left edge carries the weight; the tint is faint enough that the figures
   still read as figures. */
table.data tbody tr.row-subject td {
  background: rgba(70, 213, 255, .07);
  color: var(--text);
  border-bottom-color: rgba(70, 213, 255, .2);
}
table.data tbody tr.row-subject td:first-child { box-shadow: inset 2px 0 0 var(--cyan); }
table.data tbody tr.row-subject:hover td { background: rgba(70, 213, 255, .11); }

/* A column you can order the table by. The header is the control, so it has
   to look like one without turning the head row into a row of buttons. */
table.data th.sortable { cursor: pointer; user-select: none; }
table.data th.sortable:hover { color: var(--text); background: rgba(70, 213, 255, .06); }
table.data th.sortable:focus-visible { outline: 1px solid var(--cyan); outline-offset: -1px; }
table.data th.sorted { color: var(--cyan); }

table.data .addr { color: var(--text); }
table.data .pos  { color: var(--ok); }
table.data .neg  { color: var(--fault); }
table.data .zero { color: var(--dimmer); }

/* Every piece of prose in a report reads at one weight: the opening paragraph,
   the notes under a section and an empty-section line are all the report
   talking, and setting the later ones smaller and fainter implied a hierarchy
   that is not there. Size is inherited, colour is the same --dim as .lead. */
.notes { margin-top: 8px; color: var(--dim); }

/* The chart's key. Each entry is coloured to match the stroke it names, so
   the legend cannot disagree with the lines. */
.trend-legend { display: flex; flex-wrap: wrap; gap: 16px; }
.trend-key { white-space: nowrap; }
.empty { color: var(--dim); padding: 10px 11px; }

/* ── small screens ──────────────────────────────────────────────────────── */

@media (max-width: 760px) {
  :root { --gutter: 10px; }
  .rail-top { height: auto; padding: 8px 0; flex-wrap: wrap; gap: 9px; }
  .rail-stats { margin-left: 0; width: 100%; gap: 10px; flex-wrap: wrap; white-space: normal; }
  .mark { font-size: 23px; }
  .login { margin-top: 5vh; }
  .win-title { font-size: 15px; letter-spacing: 2px; }
  .win-body { padding: 11px; }
  table.data { font-size: 11px; }
}
