/* ================================================================
   Energy SCADA — Industrial HMI theme  (all text → white)
   ================================================================ */
:root{
  /* ================================================================
     Light theme palette — every pairing below was checked against
     WCAG contrast ratios (text targets >=4.5:1, borders/UI >=3:1),
     not picked by eye. See the design notes in each group.
     ================================================================ */
  --bg:#eef2f7;              /* page background — soft blue-gray, not stark white */
  --bg-2:#e4e9f0;            /* sidebar — a touch more tinted than the page, for depth */
  --panel:#ffffff;           /* cards / modals — pure white, floats above --bg */
  --panel-2:#f4f6fa;         /* sunken wells, table stripes, dropdown hover */
  --line:#cbd5e1;            /* borders/dividers — subtle but visible (1.5:1 vs panel) */
  --input-border:#64748b;    /* input/select borders — 4.76:1 vs white panel, clearly visible */
  --txt:#0f1729;             /* primary text — 17.9:1 vs white, near-black slate (not pure
                                 black — softer, reads as "designed" rather than harsh) */
  --txt-dim:#3b4759;         /* secondary text — 9.4:1 vs white */
  --txt-muted:#64748b;       /* muted text — 4.76:1 vs white, still comfortably readable */
  /* Accent colors: the old values (amber-500, cyan-400, emerald-400, rose-500,
     violet-400) were tuned to pop against near-black panels. As TEXT on a white
     panel they fail contrast outright (e.g. amber-500 on white = 2.15:1). Each
     was moved one to two steps darker on its own hue until it cleared 4.5:1,
     so KPI numbers/labels stay exactly as colorful and legible as before, just
     against light backgrounds instead of dark ones. */
  --amber:#b45309;           /* was #f59e0b · 5.02:1 vs white (was 2.15:1) */
  --amber-soft:rgba(180,83,9,.12);
  --cyan:#0e7490;            /* was #22d3ee · 5.36:1 vs white (was 1.81:1) */
  --emerald:#047857;         /* was #34d399 · 5.48:1 vs white (was 1.92:1) */
  --red:#be123c;             /* was #f43f5e · 6.29:1 vs white (was 3.67:1) */
  --violet:#6d28d9;          /* was #a78bfa · 7.10:1 vs white (was 2.72:1) */
  --blue:#1d4ed8;            /* 6.70:1 vs white — used for solid colored buttons */
}

/* ── Light theme overrides ──────────────────────────────────────── */

*{box-sizing:border-box}
html,body{margin:0;height:100%}
body{
  background:
    radial-gradient(1200px 600px at 80% -10%, rgba(14,116,144,.05), transparent 60%),
    radial-gradient(900px 500px at -10% 110%, rgba(180,83,9,.05), transparent 55%),
    var(--bg);
  color:var(--txt);
  font-family:'Inter',system-ui,-apple-system,Segoe UI,Roboto,sans-serif;
  -webkit-font-smoothing:antialiased;
}
.mono{font-family:'JetBrains Mono','IBM Plex Mono',ui-monospace,Menlo,monospace}

/* ---- layout ---------------------------------------------------- */
.shell{display:flex;min-height:100vh}
.sidebar{
  width:248px;flex:0 0 248px;background:var(--bg-2);
  border-right:1px solid var(--line);
  display:flex;flex-direction:column;
  transition:width .28s cubic-bezier(.4,0,.2,1),flex-basis .28s cubic-bezier(.4,0,.2,1);
  position:sticky;top:0;height:100vh;overflow:hidden;z-index:30;
}
.sidebar.collapsed{width:74px;flex-basis:74px}

/* Sidebar is HIDDEN by default; the floating arrow slides it in/out. */
.sidebar.hidden{width:0;flex-basis:0;border-right:none}
.side-arrow{
  position:fixed;left:10px;top:12px;z-index:60;
  width:34px;height:34px;border-radius:9px;
  display:flex;align-items:center;justify-content:center;
  background:var(--bg-2);border:1px solid var(--line);color:#334155;
  cursor:pointer;box-shadow:0 6px 18px rgba(0,0,0,.35);
  transition:opacity .2s ease, transform .2s ease, left .28s cubic-bezier(.4,0,.2,1);
}
.side-arrow svg{width:18px;height:18px;transition:transform .28s cubic-bezier(.4,0,.2,1)}
.side-arrow:hover{color:var(--txt);border-color:var(--txt-muted)}
/* Open: the same button stays on top of the menu and flips to point back,
   so one control at the top does both jobs (no Hide button inside). */
.side-arrow.open{left:202px}
.side-arrow.open svg{transform:rotate(180deg)}
.side-arrow.gone{opacity:0;pointer-events:none;transform:translateX(-8px)}
/* When the menu is hidden, keep page content clear of the floating arrow. */
.sidebar.hidden ~ .main .content{padding-left:3.4rem}
.brand{display:flex;align-items:center;gap:.7rem;padding:1.15rem 1.2rem;
  border-bottom:1px solid var(--line);white-space:nowrap}
.brand-mark{width:34px;height:34px;border-radius:9px;flex:0 0 34px;
  background:linear-gradient(135deg,var(--amber),#b45309);
  display:grid;place-items:center;color:#1a1206;font-weight:800;
  box-shadow:0 0 0 1px rgba(245,158,11,.35),0 8px 20px -8px rgba(245,158,11,.6)}
.brand-name{font-weight:700;letter-spacing:.02em;line-height:1.1;color:var(--txt)}
.brand-name small{display:block;color:var(--txt-dim);font-weight:500;font-size:.66rem;
  letter-spacing:.18em;text-transform:uppercase}
.sidebar.collapsed .label-text,.sidebar.collapsed .brand-name{opacity:0;width:0;overflow:hidden}

.nav{padding:.5rem .5rem;display:flex;flex-direction:column;gap:.15rem;flex:1;overflow-y:auto}
.nav a{display:flex;align-items:center;gap:.7rem;padding:.5rem .65rem;
  border-radius:8px;color:#334155;text-decoration:none;font-size:.82rem;
  font-weight:500;white-space:nowrap;transition:.15s;position:relative}
.nav a:hover{background:var(--panel);color:var(--txt)}
.nav a.active{background:var(--amber-soft);color:var(--amber)}
.nav-icon{font-size:.9rem;flex:0 0 18px;text-align:center;color:#64748b}
.nav a:hover .nav-icon,.nav a.active .nav-icon{color:inherit}
/* SVG icons in nav — fixed small size */
.nav a svg{
  width:15px;height:15px;flex-shrink:0;
  stroke-width:1.75;color:inherit;opacity:.75;
}
.nav a:hover svg,.nav a.active svg{opacity:1}
.label-text{white-space:nowrap;color:inherit;font-size:.82rem}

.topbar-btn{background:transparent;border:1px solid var(--line);border-radius:9px;
  padding:.45rem .6rem;color:#334155;cursor:pointer;transition:.15s;font-size:.85rem}
.topbar-btn:hover{border-color:var(--txt-muted);color:var(--txt)}

.main{flex:1;min-width:0;display:flex;flex-direction:column}
.topbar{display:flex;align-items:center;gap:1rem;padding:.9rem 1.5rem;
  border-bottom:1px solid var(--line);background:var(--bg-2)}
.topbar .crumb{color:var(--txt-dim);font-size:.78rem;letter-spacing:.14em;
  text-transform:uppercase;flex:1;font-weight:600}
.topbar .crumb a{color:var(--txt-muted);text-decoration:none}
.topbar .crumb a:hover{color:var(--txt)}
.topbar-right{display:flex;align-items:center;gap:.6rem}
.page-content{flex:1;padding:1.5rem;overflow-x:hidden}

/* ---- panels ---------------------------------------------------- */
.panel{background:var(--panel);border:1px solid var(--line);
  box-shadow:0 1px 3px rgba(0,0,0,.4)}
.panel-h{padding:1.2rem 1.5rem .8rem;border-bottom:1px solid var(--line);display:flex;align-items:center;gap:1rem}
.panel-h h2{font-size:1.05rem;font-weight:700;color:var(--txt);margin:0}
.panel-h .sub{color:var(--txt-dim);font-size:.76rem}
.panel-body{padding:1.2rem 1.5rem}

/* ---- KPI tiles ------------------------------------------------- */
.kpi{background:var(--panel-2);border:1px solid var(--line);border-radius:12px;
  padding:1rem 1.2rem}
.kpi .k-label{display:flex;align-items:center;gap:.5rem;color:#475569;
  font-size:.72rem;font-weight:600;text-transform:uppercase;letter-spacing:.12em;margin-bottom:.5rem}
.kpi .k-val{font-family:'JetBrains Mono','IBM Plex Mono',monospace;
  font-size:1.75rem;font-weight:800;line-height:1}
.kpi .k-unit{font-size:.95rem;color:#475569;margin-left:.25rem;font-weight:500}
.kpi.amber .k-val{color:var(--amber)}
.kpi.cyan  .k-val{color:var(--cyan)}
.kpi.green .k-val{color:var(--emerald)}
.kpi.red   .k-val{color:var(--red)}

/* ---- table grid ------------------------------------------------ */
/* display:table is not redundant — it is the whole fix.
   Tailwind ships a utility called .grid{display:grid}, and these tables are
   marked class="grid" for our own styling. The names collide, so every table
   was being turned into a CSS Grid container: thead and tbody became grid
   items, each row then formed its own anonymous table, and the header row and
   the data rows ended up sizing their columns independently. That is why the
   headings sat to the left of the data they belonged to on every page.
   table.grid (0,1,1) outranks .grid (0,1,0), so this wins regardless of the
   order the stylesheets load in. */
table.grid{display:table;width:100%;border-collapse:collapse}
table.grid th{text-align:left;padding:.7rem .9rem;color:#334155;
  font-size:.73rem;font-weight:600;letter-spacing:.1em;text-transform:uppercase;
  border-bottom:1px solid var(--line);white-space:nowrap}
table.grid td{padding:.65rem .9rem;border-bottom:1px solid #e6eaf0;
  font-size:.88rem;vertical-align:middle;color:#0f1729}
table.grid tr:last-child td{border-bottom:none}
table.grid tr:hover td{background:var(--panel-2)}

/* ---- forms ----------------------------------------------------- */
label.fld{display:block;margin-bottom:.85rem}
label.fld span{display:block;font-size:.76rem;color:#475569;
  font-weight:600;letter-spacing:.1em;text-transform:uppercase;margin-bottom:.35rem}
.form-input,.form-select{
  width:100%;background:var(--bg);border:1px solid var(--input-border);
  border-radius:8px;padding:.6rem .85rem;color:var(--txt);font-size:.9rem;
  transition:border-color .15s;outline:none;
  -webkit-appearance:none;
}
.form-input:focus,.form-select:focus{border-color:var(--amber);box-shadow:0 0 0 3px var(--amber-soft)}
.form-input::placeholder{color:var(--txt-muted)}
input[type="datetime-local"]{color-scheme:light}
select.form-input option,select option{background:var(--panel-2);color:var(--txt)}
/* Dropdowns get a coloured border + a custom amber chevron (replacing the
   flat native arrow) so they read as interactive pickers at a glance,
   instead of looking identical to a plain text field. */
select.form-input,select.form-select{
  appearance:none;-webkit-appearance:none;-moz-appearance:none;
  border-color:#d97706;padding-right:2.5rem;cursor:pointer;
  box-shadow:0 1px 2px rgba(217,119,6,.1);
  transition:border-color .15s,background-color .15s,box-shadow .15s;
  background-repeat:no-repeat,no-repeat;
  background-position:right .8rem center,right 2.15rem center;
  background-size:14px,1px 58%;
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23b45309' stroke-width='2.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E"),
    linear-gradient(180deg,transparent,#eab30866,transparent);
}
select.form-input:hover,select.form-select:hover{
  border-color:var(--amber);background-color:#fffbeb;
  box-shadow:0 2px 5px rgba(217,119,6,.16);
}

/* ---- buttons --------------------------------------------------- */
.btn{display:inline-flex;align-items:center;gap:.4rem;padding:.55rem 1.1rem;
  border-radius:8px;font-size:.85rem;font-weight:600;cursor:pointer;
  border:1px solid var(--line);background:transparent;color:#334155;
  transition:.15s;white-space:nowrap}
.btn:hover{border-color:#94a3b8}
.btn-primary{background:var(--amber);border-color:var(--amber);color:#1a1206;font-weight:700}
.btn-primary:hover{background:#e08b00;border-color:#e08b00}
.btn-secondary{background:var(--panel-2);border-color:var(--line);color:#334155}
.btn-secondary:hover{border-color:var(--txt-muted);color:var(--txt)}
.btn-danger{background:#7f1d1d;border-color:#991b1b;color:#ffffff}
.btn-danger:hover{background:#991b1b}

/* Solid, semantically-colored buttons — used instead of the flat gray
   .btn-secondary for a handful of common, repeated actions (Back, Export,
   Arrange, Theme, Link/Refresh) so the toolbar reads at a glance instead of
   every button looking the same pale gray. Each pairs a saturated fill with
   white (or, for amber, dark) text — same contrast-safe pattern already
   used for .btn-primary/.btn-amber and the colored status badges. */
.btn-nav{background:var(--amber);border-color:var(--amber);color:#1a1206;font-weight:700}
.btn-nav:hover{background:#e08b00;border-color:#e08b00}
.btn-export{background:var(--emerald);border-color:var(--emerald);color:#ffffff;font-weight:700}
.btn-export:hover{background:#065f46;border-color:#065f46}
.btn-arrange{background:var(--blue);border-color:var(--blue);color:#ffffff;font-weight:700}
.btn-arrange:hover{background:#1e40af;border-color:#1e40af}
.btn-theme{background:var(--violet);border-color:var(--violet);color:#ffffff;font-weight:700}
.btn-theme:hover{background:#5b21b6;border-color:#5b21b6}
.btn-link{background:var(--cyan);border-color:var(--cyan);color:#ffffff;font-weight:700}
.btn-link:hover{background:#155e75;border-color:#155e75}

/* ---- badges ---------------------------------------------------- */
.badge{display:inline-flex;align-items:center;gap:.3rem;padding:.22rem .7rem;
  border-radius:999px;font-size:.72rem;font-weight:600}
.badge.green{background:rgba(52,211,153,.15);color:var(--emerald)}
.badge.amber{background:rgba(245,158,11,.15);color:var(--amber)}
.badge.red{background:rgba(244,63,94,.15);color:var(--red)}
.badge.gray{background:var(--panel-2);color:#475569}

/* ---- utils ----------------------------------------------------- */
.muted{color:var(--txt-dim)}
.empty{text-align:center;padding:3rem 1rem;color:var(--txt-dim)}

/* ---- toast ----------------------------------------------------- */
#toastArea{position:fixed;bottom:1.5rem;right:1.5rem;z-index:9999;
  display:flex;flex-direction:column;gap:.5rem;pointer-events:none}
.toast-msg{padding:.7rem 1.1rem;border-radius:10px;font-size:.85rem;
  font-weight:600;backdrop-filter:blur(6px);animation:slideIn .2s ease;color:#0f1729}
.toast-msg.success{background:rgba(52,211,153,.2);border:1px solid rgba(52,211,153,.4)}
.toast-msg.error  {background:rgba(244,63,94,.2); border:1px solid rgba(244,63,94,.4)}
.toast-msg.info   {background:rgba(34,211,238,.2);border:1px solid rgba(34,211,238,.4)}
@keyframes slideIn{from{transform:translateX(110%);opacity:0}to{transform:none;opacity:1}}

/* ---- tailwind-like utilities used in templates ----------------- */
/* Text colours */
.text-white{color:var(--txt) !important}
.text-slate-300{color:var(--txt-dim) !important}
.text-slate-400{color:var(--txt-muted) !important}
.text-slate-500{color:var(--txt-muted) !important}
.text-amber-400{color:#b45309 !important}
.text-emerald-400{color:#047857 !important}
.text-violet-400{color:#6d28d9 !important}
.text-cyan-400{color:#0e7490 !important}
.text-orange-400{color:#c2410c !important}
.text-sky-400{color:#0369a1 !important}
.text-red-400{color:#be123c !important}
/* Backgrounds */
.bg-emerald-700{background:#047857}.bg-amber-700{background:#b45309}
.bg-emerald-900{background:#064e3b}.bg-amber-900{background:#78350f}
.text-emerald-300{color:#6ee7b7}.text-amber-300{color:#fcd34d}
/* Spacing / layout shorthands */
.panel{background:var(--panel);border:1px solid var(--line)}
/* Table headers, labels, form elements all white */
th, label, select, input, textarea, option{color:var(--txt)}
select option{background:var(--bg-2);color:var(--txt)}

/* ================================================================
   COMPATIBILITY LAYER — classes used by existing templates / app.js
   ================================================================ */

/* .content = main page area (base.html uses this class) */
.content{flex:1;padding:1rem 1.5rem 1.5rem;overflow-x:hidden}

/* .inp = form input alias */
.inp{
  width:100%;background:var(--bg);border:1px solid var(--input-border);
  border-radius:8px;padding:.6rem .85rem;color:var(--txt);font-size:.9rem;
  transition:border-color .15s;outline:none;-webkit-appearance:none;
}
.inp:focus{border-color:var(--amber);box-shadow:0 0 0 3px var(--amber-soft)}
.inp::placeholder{color:var(--txt-muted)}
input.inp[type="datetime-local"],input.inp[type="date"]{color-scheme:light}
select.inp option{background:var(--bg-2);color:var(--txt)}
select.inp{
  appearance:none;-webkit-appearance:none;-moz-appearance:none;
  border-color:#d97706;padding-right:2.5rem;cursor:pointer;
  box-shadow:0 1px 2px rgba(217,119,6,.1);
  transition:border-color .15s,background-color .15s,box-shadow .15s;
  background-repeat:no-repeat,no-repeat;
  background-position:right .8rem center,right 2.15rem center;
  background-size:14px,1px 58%;
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23b45309' stroke-width='2.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E"),
    linear-gradient(180deg,transparent,#eab30866,transparent);
}
select.inp:hover{
  border-color:var(--amber);background-color:#fffbeb;
  box-shadow:0 2px 5px rgba(217,119,6,.16);
}
/* Button-based dropdown triggers (multi-select filters that open a custom
   checkbox menu, where a native <select> can't hold multiple checkboxes) —
   same colored-picker treatment as a real select, plus a chevron since
   there's no native arrow to recolor. */
.dropdown-btn{
  position:relative;border-color:#d97706 !important;padding-right:2.3rem !important;
}
.dropdown-btn::after{
  content:'';position:absolute;right:.75rem;top:50%;width:9px;height:9px;
  border-right:2.4px solid #b45309;border-bottom:2.4px solid #b45309;
  transform:translateY(-65%) rotate(45deg);pointer-events:none;
}
.dropdown-btn:hover{border-color:var(--amber) !important}

/* .panel-pad = panel body padding */
.panel-pad{padding:1.2rem 1.5rem}

/* .btn variants */
.btn-amber{background:var(--amber);border-color:var(--amber);color:#1a1206;font-weight:700}
.btn-amber:hover{background:#e08b00;border-color:#e08b00;color:#1a1206}
.btn-ghost{background:transparent;border-color:var(--line);color:#475569}
.btn-ghost:hover{border-color:var(--txt-muted);color:var(--txt)}
.btn-sm{padding:.3rem .65rem;font-size:.75rem;border-radius:6px}
.btn-sm svg{width:13px;height:13px}

/* .badge variants */
.badge-role{background:rgba(245,158,11,.15);color:var(--amber);border:1px solid rgba(245,158,11,.3);
  display:inline-flex;align-items:center;padding:.18rem .55rem;border-radius:999px;
  font-size:.72rem;font-weight:600}
.badge-online{background:rgba(52,211,153,.15);color:var(--emerald)}
.badge-offline{background:rgba(100,116,139,.12);color:#475569}

/* .grid-2 = two-column panel layout */
.grid-2{display:grid;grid-template-columns:1fr 1fr;gap:1.2rem}
@media(max-width:860px){.grid-2{grid-template-columns:1fr}}

/* ── Modal overlay (used by openModal in app.js) ─────────────────── */
.modal-bg{
  display:none;position:fixed;inset:0;background:rgba(0,0,0,.65);
  backdrop-filter:blur(3px);z-index:9000;
  align-items:center;justify-content:center;padding:1rem;
}
.modal-bg.show{display:flex}
.modal{
  background:var(--panel);border:1px solid var(--line);border-radius:14px;
  width:100%;max-width:500px;max-height:90vh;overflow-y:auto;
  box-shadow:0 25px 60px -20px rgba(15,23,41,.35);
}
.modal .panel-h{
  display:flex;align-items:center;justify-content:space-between;
  padding:.9rem 1.25rem;border-bottom:1px solid var(--line);
}
.modal .panel-h h2{margin:0;font-size:1rem;font-weight:700;color:var(--txt)}
.modal .panel-pad{padding:1.25rem}
.modal label.fld span{color:var(--txt)}
.modal .flex{display:flex}
.modal .justify-end{justify-content:flex-end}
.modal .gap-2{gap:.5rem}
.modal .mt-2{margin-top:.5rem}

/* ── Sidebar footer collapse button ─────────────────────────────── */
.side-foot{padding:.7rem .6rem;border-top:1px solid var(--line)}

/* Header moved into the sidebar: page title, Live + clock, and the user row.
   With no top bar, the page content now starts at the very top and gets the
   full height of the window. */
.side-page{padding:.15rem 1.2rem .7rem;border-bottom:1px solid var(--line);margin-bottom:.5rem}
.side-page .crumb{color:var(--txt-dim);font-size:.66rem;letter-spacing:.14em;
  text-transform:uppercase;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.side-page h1{margin:.15rem 0 0;font-size:1.05rem;font-weight:700;color:var(--txt);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.side-status{display:flex;align-items:center;gap:.4rem;flex-wrap:wrap;
  padding:0 1.2rem .75rem}
.side-status .pill{font-size:.72rem}
.side-user{display:flex;align-items:center;gap:.45rem;flex-wrap:wrap;
  padding:.1rem .3rem .6rem}
.side-user-name{max-width:100px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sidebar.collapsed .side-page{display:none}
.sidebar.collapsed .side-status{padding:0 0 .6rem;justify-content:center}
.sidebar.collapsed .side-status .clock{display:none}
.sidebar.collapsed .side-user{justify-content:center;gap:.3rem}
.sidebar.collapsed .side-user .badge-role{display:none}
.toggle-btn{
  display:flex;align-items:center;gap:.7rem;padding:.45rem .65rem;
  background:transparent;border:none;border-radius:8px;color:#475569;
  cursor:pointer;font-size:.82rem;font-weight:500;width:100%;
  transition:.15s;white-space:nowrap;
}
.toggle-btn:hover{background:var(--panel);color:var(--txt)}
.toggle-btn svg{width:15px;height:15px;flex-shrink:0}
.sidebar.collapsed .side-foot .label-text{display:none}

/* ── Custom sidebar background (Branding) — auto text contrast ──────
   If an admin picks a DARK sidebar color, every text rule above (tuned for
   the sidebar's normal light background) would turn invisible. JS computes
   the picked color's luminance and adds this class when it's dark, flipping
   every sidebar text color to a light one — so any admin-picked color
   (light OR dark) always stays readable. */
.sidebar.on-dark .brand-name{color:#ffffff}
.sidebar.on-dark .brand-name small{color:#cbd5e1}
.sidebar.on-dark .nav a{color:#dbe3ee}
.sidebar.on-dark .nav a:hover{color:#ffffff}
.sidebar.on-dark .nav-icon{color:#94a3b8}
.sidebar.on-dark .side-page .crumb{color:#94a3b8}
.sidebar.on-dark .side-page h1{color:#ffffff}
.sidebar.on-dark .toggle-btn{color:#cbd5e1}
.sidebar.on-dark .toggle-btn:hover{color:#ffffff}
.sidebar.on-dark .pill{color:#dbe3ee;background:rgba(255,255,255,.08);border-color:rgba(255,255,255,.14)}
.sidebar.on-dark .side-user-name{color:#dbe3ee}
.sidebar.on-dark .side-foot{border-top-color:rgba(255,255,255,.12)}
.sidebar.on-dark .side-page{border-bottom-color:rgba(255,255,255,.12)}

/* ── pill / clock in topbar ──────────────────────────────────────── */
.pill{display:inline-flex;align-items:center;gap:.4rem;padding:.25rem .7rem;
  border-radius:999px;font-size:.75rem;font-weight:600;
  background:var(--panel-2);border:1px solid var(--line);color:#334155}
.pill .dot{width:6px;height:6px;border-radius:50%;background:#94a3b8}
.pill .dot.live{background:var(--emerald);box-shadow:0 0 6px var(--emerald)}
.clock{font-family:'JetBrains Mono',monospace;letter-spacing:.05em}
.topbar h1{margin:0;font-size:1.1rem;font-weight:700;color:var(--txt)}

/* ── Flex helpers (for modal/reports layout) ─────────────────────── */
.flex{display:flex}.flex-wrap{flex-wrap:wrap}.flex-1{flex:1}
/* .hidden MUST always win over flex/grid/block/etc, even when combined on the
   same element (e.g. class="hidden fixed inset-0 flex ..." — a very common
   modal pattern: "flex when shown, hidden when not"). Without !important,
   .hidden{display:none} and .flex{display:flex} have EQUAL CSS specificity
   (0,1,0), so the rule that's declared LAST in the cascade wins — and because
   this stylesheet loads after vendor/tailwind.min.css and re-declares .flex
   right above, .flex was winning regardless of whether JS added or removed
   the hidden class. That made every "hidden ... flex ..." modal in the app
   (Edit Node, Add Department, Add Device, and any other) render fully VISIBLE
   the instant its page loaded, with no click involved — the JS toggle was
   never actually broken, this CSS-cascade conflict just made it a no-op.
   !important is the correct, standard fix here: .hidden's entire purpose is
   "unconditionally not shown", so it should never lose a specificity fight. */
.hidden{display:none!important}
.items-center{align-items:center}.items-end{align-items:flex-end}
.justify-end{justify-content:flex-end}.justify-between{justify-content:space-between}
.gap-2{gap:.5rem}.gap-3{gap:.75rem}.mb-3{margin-bottom:.75rem}
.mb-4{margin-bottom:1rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}
.mt-3{margin-top:.75rem}.font-semibold{font-weight:600}
.text-sm{font-size:.85rem}.mono{font-family:'JetBrains Mono',monospace}

/* ================================================================
   SCADA-style professional device cards
   ================================================================ */
.scada-card{
  position:relative;
  min-height:var(--scada-card-minh, 160px);
  display:flex;
  flex-direction:column;
  background:linear-gradient(155deg,#ffffff 0%,#f9fbfd 55%,#f2f5f9 100%);
  border:1px solid #dde3ec;
  border-radius:10px;
  overflow:hidden;
  cursor:pointer;
  transition:transform .15s, box-shadow .15s, border-color .15s;
  box-shadow:0 1px 3px rgba(15,23,41,.08), 0 1px 2px rgba(15,23,41,.05);
}
.scada-card:hover{
  transform:translateY(-2px);
  border-color:var(--accent);
  box-shadow:0 10px 24px -8px rgba(15,23,41,.18), 0 0 0 1px var(--accent);
}
.scada-card-top{
  height:3px;
  background:linear-gradient(90deg,var(--accent),transparent);
}
.scada-card-body{padding:11px 12px}
.scada-status{
  display:inline-flex;align-items:center;gap:4px;
  font-size:9px;font-weight:800;letter-spacing:.5px;
  padding:2px 7px;border-radius:999px;
}
.scada-status.on{background:rgba(4,120,87,.1);color:#047857;border:1px solid rgba(4,120,87,.3)}
/* OFF badge: solid red fill + white text (not a soft tint) — reads as an
   alarm, not just a label. */
.scada-status.off{background:#e11d48;color:#ffffff;border:1px solid #e11d48;
  font-weight:900;animation:scadaOffBadge 1.2s ease-in-out infinite}
@keyframes scadaOffBadge{0%,100%{opacity:1}50%{opacity:.72}}
/* Offline card: a visibly rose-tinted card (not just a thin border) so it
   reads as "this meter is down" the instant the page opens — even on a
   screenshot that happens to catch a quiet moment of the blink below,
   the baseline look is already unmistakably different from a healthy card. */
.scada-card.offline{
  background:linear-gradient(155deg,#fef2f4 0%,#fde3e8 55%,#fbd9e0 100%) !important;
  animation:scadaOffline 1.4s ease-in-out infinite;
}
.scada-card.offline .scada-card-top{
  background:#e11d48 !important;   /* force the accent bar red, regardless of the meter's normal accent color */
}
@keyframes scadaOffline{
  0%,100%{
    border-color:#e11d48 !important;
    box-shadow:0 0 0 1.5px rgba(225,29,72,.6), 0 8px 22px -6px rgba(225,29,72,.45);
  }
  50%{
    border-color:#f43f5e !important;
    box-shadow:0 0 0 1.5px rgba(225,29,72,.32), 0 4px 14px -6px rgba(225,29,72,.25);
  }
}
.scada-card.offline .scada-dot{
  box-shadow:0 0 6px #e11d48;
  animation:scadaPulse 1.3s ease-in-out infinite;
}
.scada-dot{width:6px;height:6px;border-radius:50%;background:currentColor}
.scada-status.on .scada-dot{box-shadow:0 0 6px #047857;animation:scadaPulse 1.6s infinite}
@keyframes scadaPulse{0%,100%{opacity:1}50%{opacity:.35}}
.scada-kpi{
  background:linear-gradient(150deg,#fbfcfe,#eef1f6);
  border:1px solid #dde3ec;
  border-top:2px solid var(--c);
  border-radius:6px;padding:6px 4px;text-align:center;
}
.scada-kpi-val{
  font-family:'JetBrains Mono',monospace;font-weight:700;
  font-size:14px;color:var(--c);line-height:1.1;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.scada-kpi-lbl{font-size:8.5px;color:#64748b;text-transform:uppercase;letter-spacing:.5px;margin-top:1px}
/* Voltage / Current footer — aligned rows with icon + label */
.scada-card-foot{
  margin-top:9px;padding-top:8px;border-top:1px solid #e6eaf0;
  display:flex;flex-direction:column;gap:4px;
}
.scada-foot-row{
  display:flex;align-items:center;gap:6px;
  font-family:'JetBrains Mono',monospace;font-size:10.5px;
}
.scada-foot-ico{
  width:16px;height:16px;flex:none;border-radius:4px;
  display:flex;align-items:center;justify-content:center;font-size:10px;
}
.scada-foot-ico.v{background:rgba(2,132,199,.12);color:#0369a1}
.scada-foot-ico.a{background:rgba(234,88,12,.12);color:#c2410c}
.scada-foot-val{flex:1;letter-spacing:.3px;color:var(--txt-dim)}
.scada-foot-val.v{color:#0369a1}
.scada-foot-val.a{color:#c2410c}
.scada-foot-unit{color:#64748b;font-size:9px}

/* ================================================================
   Device Live Dashboard — grouped metric sections
   ================================================================ */
.dash-group{
  background:linear-gradient(155deg,#ffffff00,#f8fafc);
  border:1px solid #e2e8f0;
  border-left:3px solid var(--ga,#64748b);
  border-radius:8px;
  overflow:hidden;
}
.dash-group-head{
  display:flex;align-items:center;gap:6px;
  padding:8px 12px;
  font-size:11px;font-weight:700;letter-spacing:.5px;text-transform:uppercase;
  color:var(--ga,#334155);
  background:rgba(15,23,41,.02);
  border-bottom:1px solid #e6eaf0;
}
.dash-group-body{padding:6px 12px}
.dash-metric{
  display:flex;align-items:center;gap:8px;
  padding:6px 0;
  border-bottom:1px solid #eef1f6;
}
.dash-group-body .dash-metric:last-child{border-bottom:none}
.dash-metric-name{
  flex:1;color:#64748b;font-size:11px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.dash-metric-val{
  font-family:'JetBrains Mono',monospace;font-weight:700;font-size:15px;
  color:var(--txt);text-align:right;min-width:70px;
}
.dash-metric-unit{color:#64748b;font-size:10px;min-width:18px}

/* ================================================================
   Interactive dashboard polish
   ================================================================ */
/* Hero tiles glow + lift on hover */
#heroGrid .scada-kpi{
  transition:transform .15s, box-shadow .15s, border-color .15s;
  cursor:default;
  position:relative;
}
#heroGrid .scada-kpi:hover{
  transform:translateY(-2px);
  box-shadow:0 8px 20px -6px rgba(15,23,41,.18), 0 0 0 1px var(--c);
}
.scada-kpi-val{transition:color .2s}
/* Smooth value update flash */
@keyframes valFlash{0%{filter:brightness(1.35)}100%{filter:brightness(1)}}
.val-flash{animation:valFlash .4s ease-out}
/* Metric rows highlight on hover */
.dash-metric{transition:background .12s;border-radius:4px;padding-left:6px;padding-right:6px}
.dash-metric:hover{background:rgba(15,23,41,.035)}
.dash-metric-val{transition:color .2s}
/* Group hover accent */
.dash-group{transition:box-shadow .15s,border-color .15s}
.dash-group:hover{box-shadow:0 4px 16px -6px rgba(15,23,41,.16)}
/* Live pulse dot in group headers */
.dash-group-head::after{
  content:'';width:6px;height:6px;border-radius:50%;
  background:var(--ga,#047857);margin-left:auto;
  box-shadow:0 0 6px var(--ga,#047857);
  animation:scadaPulse 2s infinite;
}

/* ================================================================
   Card arrange mode (admin drag-reorder)
   ================================================================ */
#deptDevCards.arranging .scada-card{
  cursor:grab;
  border-style:dashed;
  border-color:#b45309;
}
#deptDevCards.arranging .scada-card:active{cursor:grabbing}
#deptDevCards .scada-card.dragging{
  opacity:.5;
  outline:2px dashed #b45309;
}
#deptDevCards.arranging .scada-card::before{
  content:'⇅ drag';
  position:absolute;top:4px;right:6px;z-index:2;
  font-size:9px;color:#b45309;font-weight:700;
  pointer-events:none;
}

/* Departments overview tiles — arrange/reorder affordance */
#deptCards.arranging > div{
  cursor:grab;
  border-style:dashed !important;
  border-color:#b45309 !important;
}
#deptCards.arranging > div:active{cursor:grabbing}
#deptCards.arranging > div .dt-actions{pointer-events:none;opacity:.45}
#deptCards.arranging > div .flex.gap-1\.5{pointer-events:none;opacity:.45}
#deptCards > div.dragging{opacity:.5;outline:2px dashed #b45309}

/* ================================================================
   SLD node selection highlight
   ================================================================ */
.sld-node.sld-selected{
  outline:2px solid #b45309;
  outline-offset:3px;
  border-radius:8px;
  box-shadow:0 0 0 4px rgba(180,83,9,.15);
}

/* ================================================================
   PROFESSIONAL SCADA REFRESH — instrument-panel aesthetic
   (departments list, department detail, device detail)
   ================================================================ */

/* ---- Department overview tiles ---------------------------------- */
.dept-tile{
  position:relative;
  background:linear-gradient(160deg,#ffffff 0%,#f8fafc 100%);
  border:1px solid #dde3ec;
  border-radius:14px;
  padding:16px 16px 14px;
  min-height:var(--dept-card-minh,168px);
  display:flex;flex-direction:column;
  transition:transform .16s cubic-bezier(.4,0,.2,1),
             border-color .16s, box-shadow .16s;
  overflow:hidden;
}
.dept-tile::before{           /* top accent hairline in the dept colour */
  content:'';position:absolute;left:0;top:0;right:0;height:2px;
  background:var(--tile-accent,#b45309);opacity:.85;
}
.dept-tile:hover{
  transform:translateY(-3px);
  border-color:var(--tile-accent,#b45309);
  box-shadow:0 14px 28px -14px rgba(15,23,41,.3),
             0 0 0 1px var(--tile-accent,#b45309)33;
}
.dept-tile .dt-head{display:flex;align-items:flex-start;justify-content:space-between;gap:8px;margin-bottom:2px}
.dept-tile .dt-name{font-weight:700;letter-spacing:.01em;line-height:1.2;
  color:var(--txt);font-size:15px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.dept-tile .dt-desc{color:#64748b;font-size:11px;margin-top:2px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* status LED */
.dt-led{width:9px;height:9px;border-radius:50%;flex:none;margin-top:4px;
  background:#c3cbd6;box-shadow:0 0 0 3px rgba(148,163,184,.18)}
.dt-led.on{background:#047857;box-shadow:0 0 0 3px rgba(4,120,87,.2);
  animation:dtpulse 2.4s ease-in-out infinite}
@keyframes dtpulse{0%,100%{box-shadow:0 0 0 3px rgba(4,120,87,.2)}
  50%{box-shadow:0 0 0 5px rgba(4,120,87,.05)}}

/* SLD interactive: current-flow animation on energized wires */
@keyframes sldFlow{0%{background-position:0 0}100%{background-position:24px 24px}}
/* SLD interactive: alarm blink (breaker trip / fault) */
@keyframes sldAlarm{0%,100%{box-shadow:0 0 0 2px rgba(225,29,72,.85),0 0 14px rgba(225,29,72,.55);border-color:#e11d48}
  50%{box-shadow:0 0 0 2px rgba(225,29,72,.15),0 0 4px rgba(225,29,72,.2);border-color:#fecdd3}}
.sld-alarm{animation:sldAlarm 1s ease-in-out infinite}
/* SLD interactive: energized glow (steady) */
.sld-energized{box-shadow:0 0 0 1px rgba(4,120,87,.55),0 0 10px rgba(4,120,87,.35)!important}

.dept-tile .dt-power{text-align:left;margin:12px 0 4px}
.dept-tile .dt-power .v{font-family:'JetBrains Mono',monospace;font-weight:800;
  font-size:30px;line-height:1;color:var(--tile-accent,#b45309)}
.dept-tile .dt-power .u{font-size:11px;color:#64748b;font-weight:600;
  text-transform:uppercase;letter-spacing:.1em;margin-top:5px}

/* online meter bar */
.dt-online{margin:8px 0 12px}
.dt-online .row{display:flex;align-items:center;justify-content:space-between;
  font-size:10.5px;color:#64748b;margin-bottom:5px;
  text-transform:uppercase;letter-spacing:.08em;font-weight:600}
.dt-online .track{height:4px;border-radius:3px;background:#e6eaf0;overflow:hidden}
.dt-online .fill{height:100%;border-radius:3px;background:var(--tile-accent,#047857);
  transition:width .4s ease}

.dt-actions{display:flex;gap:6px;margin-top:auto}
.dt-btn{flex:1;display:inline-flex;align-items:center;justify-content:center;gap:4px;
  font-size:11px;font-weight:600;padding:7px 8px;border-radius:8px;
  border:1px solid #dde3ec;background:#f8fafc;color:#475569;cursor:pointer;
  transition:.14s;text-decoration:none}
.dt-btn:hover{border-color:var(--tile-accent,#b45309);color:var(--tile-accent,#b45309);background:#ffffff}
.dt-btn.icon{flex:0 0 auto;padding:7px 9px}

/* Neutral "off/disabled" status pill — a dark fill with light text, kept
   deliberately theme-independent (like the colored on/live pills) rather
   than the general utility text-slate-400 (which is about to be redefined
   app-wide to a DARK color for ordinary body text — that would make this
   badge's own text invisible against its own dark fill). */
.badge-neutral{background:#334155;color:#cbd5e1;border:1px solid #475569}

/* ---- Department / device detail: section-header cards ----------- */
.inst-panel{
  background:linear-gradient(180deg,#ffffff 0%,#f8fafc 100%);
  border:1px solid #dde3ec;border-radius:14px;overflow:hidden;
}
.inst-panel .ip-head{
  display:flex;align-items:center;gap:8px;
  padding:11px 15px;border-bottom:1px solid #dde3ec;
  background:linear-gradient(180deg,#f4f6fa,#ffffff);
}
.inst-panel .ip-head .ip-ico{font-size:13px}
.inst-panel .ip-head .ip-title{font-size:12px;font-weight:700;letter-spacing:.1em;
  text-transform:uppercase;color:#334155}
.inst-panel .ip-head .ip-dot{margin-left:auto;width:7px;height:7px;border-radius:50%;
  background:#c3cbd6}
.inst-panel .ip-head .ip-dot.live{background:#047857;box-shadow:0 0 8px #04785788}
.inst-panel .ip-body{padding:6px 4px}

/* instrument reading rows (voltage / current / thd) */
.inst-row{display:flex;align-items:center;justify-content:space-between;
  padding:9px 14px;border-bottom:1px solid #eef1f6;transition:background .12s}
.inst-row:last-child{border-bottom:none}
.inst-row:hover{background:#f8fafc}
.inst-row .ir-label{font-size:12px;color:#64748b;font-weight:500}
.inst-row .ir-val{font-family:'JetBrains Mono',monospace;font-weight:700;
  font-size:14px;color:var(--txt)}
.inst-row .ir-unit{font-size:10px;color:#64748b;margin-left:5px;font-weight:600}

/* ---- Hero KPI tiles (device detail top row) --------------------- */
.kpi-hero{
  position:relative;
  background:linear-gradient(160deg,#ffffff,#f8fafc);
  border:1px solid #dde3ec;border-radius:14px;padding:18px 22px;
  overflow:hidden;
}
.kpi-hero::after{content:'';position:absolute;inset:0;
  background:radial-gradient(120px 80px at 90% -20%,var(--kpi-accent,#b45309)0d,transparent 70%);
  pointer-events:none}
.kpi-hero .kh-val{font-family:'JetBrains Mono',monospace;font-weight:800;
  font-size:34px;line-height:1;color:var(--kpi-accent,#b45309)}
.kpi-hero .kh-label{font-size:11px;color:#64748b;font-weight:600;
  text-transform:uppercase;letter-spacing:.12em;margin-top:9px}

/* ================================================================
   Device detail: professional "physical meter" panel + gauge grid
   ================================================================ */
.meter-device{display:grid;gap:16px;grid-template-columns:minmax(240px,300px) 1fr;align-items:stretch}
@media (max-width:860px){.meter-device{grid-template-columns:1fr}}

/* ---- the meter itself: plastic bezel + dark LCD (a physical panel
   meter's screen is genuinely dark even in a bright room — the ONE
   deliberate exception to the light theme, for authenticity) -------- */
.meter-visual{
  display:flex; flex-direction:column;
  background:linear-gradient(165deg,#eef1f5 0%,#dde3ec 55%,#cbd3de 100%);
  border:1px solid #b9c2d0; border-radius:16px; padding:14px;
  box-shadow:0 1px 2px rgba(15,23,41,.06), 0 10px 26px -14px rgba(15,23,41,.35),
             inset 0 1px 0 rgba(255,255,255,.6);
}
.meter-visual-head{display:flex;align-items:center;justify-content:space-between;
  padding:0 4px 10px}
.meter-brand{font-size:10.5px;font-weight:800;letter-spacing:.14em;color:#475569;
  text-transform:uppercase}
.meter-class{font-size:9px;color:#94a3b8;font-weight:600}
.meter-led{display:flex;align-items:center;gap:5px;font-size:9px;font-weight:700;
  color:#64748b;text-transform:uppercase;letter-spacing:.06em}
.meter-led .dot{width:7px;height:7px;border-radius:50%;background:#94a3b8}
.meter-led.on .dot{background:#22c55e;box-shadow:0 0 6px #22c55e;
  animation:scadaPulse 1.8s ease-in-out infinite}
.meter-led.off .dot{background:#ef4444;box-shadow:0 0 6px #ef4444;
  animation:scadaPulse 1.3s ease-in-out infinite}
.meter-lcd{
  flex:1; display:flex; flex-direction:column; justify-content:center;
  background:linear-gradient(175deg,#16241c 0%,#0e1a14 100%);
  border-radius:10px; padding:16px 16px 12px;
  box-shadow:inset 0 2px 8px rgba(0,0,0,.5), inset 0 0 0 1px rgba(255,255,255,.04);
}
.meter-digit-row{padding:9px 2px;border-bottom:1px solid rgba(148,222,178,.12)}
.meter-digit-row:last-child{border-bottom:none}
.meter-digit-lbl{font-size:9.5px;font-weight:700;letter-spacing:.14em;
  color:#5fae82;text-transform:uppercase;margin-bottom:2px;opacity:.85}
.meter-digit-val{font-family:'JetBrains Mono',monospace;font-weight:700;
  font-size:27px;line-height:1.15;color:#7CFFB2;
  text-shadow:0 0 10px rgba(124,255,178,.45);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.meter-digit-val .unit{font-size:12px;color:#5fae82;margin-left:6px;font-weight:600;
  text-shadow:none}
.meter-visual-foot{display:flex;justify-content:space-between;align-items:center;
  padding:10px 4px 0;font-size:9px;color:#94a3b8;font-weight:600}
.meter-visual-foot .phases{display:flex;gap:5px}
.meter-visual-foot .phases span{width:14px;height:3px;border-radius:2px;background:#cbd5e1}
.meter-visual-foot .phases span.live{background:#22c55e}

/* ---- gauge grid + individual gauge card --------------------------- */
/* Each titled sub-group (Phase Voltage, Line Voltage, Current, Voltage
   THD%, Current THD%...) sizes itself to its own item count (via an inline
   flex-basis set in JS) and they all wrap together — packing tightly
   side-by-side where they fit, instead of a fixed 2-column pairing that
   looked squeezed/misaligned whenever the groups' sizes didn't match. */
.gauge-flow{display:flex;flex-wrap:wrap;gap:22px 20px;align-items:start}
.gauge-grid{display:grid;gap:10px;
  grid-template-columns:repeat(auto-fill,minmax(104px,1fr))}
.gauge-card{
  background:linear-gradient(160deg,var(--gc-bg,#f8fafc) 0%,#ffffff 75%);
  border:1px solid var(--gc,#dde3ec);border-radius:12px;
  padding:10px 6px 9px;text-align:center;
  transition:transform .15s,box-shadow .15s,border-color .15s;
}
.gauge-card:hover{transform:translateY(-2px);
  box-shadow:0 10px 22px -12px rgba(15,23,41,.28)}
.gauge-svg{width:100%;max-width:92px;margin:0 auto;display:block;
  filter:drop-shadow(0 3px 5px rgba(15,23,41,.1))}
/* Filled dial face — now a radial gradient (defined per-gauge in JS) that's
   lighter at the upper-left and gently deepens toward the rim, giving the
   glass a subtle domed/recessed feel instead of one flat colour. */
.gauge-face{opacity:.95}
/* Zone arcs (safe/warning/danger bands), rounded at both ends so the bands
   read as smooth pills meeting at soft seams rather than sharp square-cut
   segments — a small detail real instrument dials always get right. */
.gauge-zone-ok{fill:none;stroke:#bfe3cf;stroke-width:7;stroke-linecap:round}
.gauge-zone-warn{fill:none;stroke:#fbdba3;stroke-width:7;stroke-linecap:round}
.gauge-zone-danger{fill:none;stroke:#f3b8c2;stroke-width:7;stroke-linecap:round}
/* Metallic outer bezel ring — the thin gradient rim that makes the dial
   read as a physical instrument set into a panel, not a flat icon. */
.gauge-bezel{fill:none;stroke-width:2.4}
/* Soft glass-reflection highlight across the upper dial — the same trick
   used on car dashboards and premium gauge widgets to suggest a curved
   glass cover catching light. Purely decorative, ignores pointer events. */
.gauge-glass{pointer-events:none}
.gauge-tick{stroke:#7c8aa0;stroke-width:1.5}
.gauge-tick.major{stroke:#334155;stroke-width:2.2}
.gauge-scale-lbl{font-family:'JetBrains Mono',monospace;font-size:7.5px;
  fill:#475569;font-weight:700}
/* Tapered "kite" needle (wide at the hub, sharp at the tip, short
   counterweight tail) — a filled shape reads as a real instrument pointer
   far more convincingly than a plain stroked line. A subtle light-to-dark
   red gradient (defined per-gauge in JS) gives it a metallic, machined
   look instead of one flat red; the colour itself stays consistent across
   every differently-coloured gauge so it's always clearly visible. */
.gauge-needle{stroke:#991b1b;stroke-width:.4;
  filter:drop-shadow(0 .8px 1.2px rgba(15,23,41,.45));
  transition:transform .5s cubic-bezier(.34,1.4,.64,1)}
.gauge-hub{stroke:#fff;stroke-width:1.3}
.gauge-hub-accent{fill:#f8fafc;opacity:.85}
.gauge-readout{margin-top:1px}
.gauge-readout .v{font-family:'JetBrains Mono',monospace;font-weight:800;
  font-size:14px;color:var(--gc,#b45309);line-height:1.1}
.gauge-readout .u{font-size:8.5px;color:#94a3b8;font-weight:600;margin-left:2px}
.gauge-label{font-size:9.5px;color:#64748b;font-weight:700;text-transform:uppercase;
  letter-spacing:.05em;margin-top:3px;white-space:nowrap;overflow:hidden;
  text-overflow:ellipsis}
.gauge-section{min-width:0}
.gauge-section-title{display:flex;align-items:center;gap:6px;font-size:11px;
  font-weight:800;letter-spacing:.1em;text-transform:uppercase;color:#475569;
  margin:0 0 8px}
.gauge-section-title .line{flex:1;height:1px;background:#e2e8f0}
.gauge-flow + .gauge-flow{margin-top:18px}

/* ---- Live-overview stat strip (dept detail) --------------------- */
.stat-strip{display:grid;gap:12px;grid-template-columns:repeat(3,1fr)}
.stat-cell{position:relative;background:linear-gradient(160deg,#ffffff,#f8fafc);
  border:1px solid #dde3ec;border-radius:12px;padding:14px 18px;overflow:hidden}
.stat-cell .sc-accent{position:absolute;left:0;top:0;bottom:0;width:3px;
  background:var(--sc-accent,#b45309)}
.stat-cell .sc-val{font-family:'JetBrains Mono',monospace;font-weight:800;
  font-size:22px;color:var(--txt);line-height:1}
.stat-cell .sc-label{font-size:10.5px;color:#64748b;font-weight:600;
  text-transform:uppercase;letter-spacing:.1em;margin-top:6px}

@media (max-width:640px){
  .stat-strip{grid-template-columns:1fr}
}

/* ================================================================
   Professional polish  (additive · presentational only)
   Stable numerics, themed scrollbars, accessible focus, selection
   colour, tactile buttons, motion safety. No layout/logic changes.
   ================================================================ */

/* ── Stable live numerics ────────────────────────────────────────
   Live readouts jitter when digit widths differ (a "1" is narrower
   than an "8"), so values visibly shift on every refresh. Tabular
   figures lock each digit to one width — the numbers now sit still
   as they update, the way a real instrument panel reads.           */
.mono,
.kpi .k-val, .kpi .k-unit,
.clock,
.scada-kpi-val, .scada-foot-row,
.dash-metric-val,
.dept-tile .dt-power .v,
.inst-row .ir-val,
.kpi-hero .kh-val,
.stat-cell .sc-val{
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

/* ── Crisper text rendering ─────────────────────────────────────*/
body{ -moz-osx-font-smoothing:grayscale; text-rendering:optimizeLegibility; }
html{ scroll-behavior:smooth; }

/* ── Themed scrollbars (Firefox + WebKit) ───────────────────────*/
*{ scrollbar-width:thin; scrollbar-color:#c3cbd6 transparent; }
::-webkit-scrollbar{ width:10px; height:10px; }
::-webkit-scrollbar-track{ background:transparent; }
::-webkit-scrollbar-thumb{
  background:#c3cbd6; border:2px solid transparent;
  background-clip:padding-box; border-radius:8px;
}
::-webkit-scrollbar-thumb:hover{ background:#94a3b8; background-clip:padding-box; }
::-webkit-scrollbar-corner{ background:transparent; }

/* ── Text selection ─────────────────────────────────────────────*/
::selection{ background:rgba(180,83,9,.22); color:#0f1729; }

/* ── Accessible keyboard focus (mouse clicks stay clean) ────────*/
a:focus-visible, button:focus-visible, .btn:focus-visible,
.nav a:focus-visible, [role="button"]:focus-visible, [tabindex]:focus-visible{
  outline:2px solid var(--amber);
  outline-offset:2px;
}
.form-input:focus-visible, .form-select:focus-visible{ outline:none; } /* already ringed */

/* ── Tactile buttons ────────────────────────────────────────────*/
.btn{ transition:background .15s ease, border-color .15s ease,
       color .15s ease, box-shadow .15s ease, transform .06s ease; }
.btn:active{ transform:translateY(1px); }
.btn-primary:hover{ box-shadow:0 4px 14px -6px rgba(245,158,11,.6); }
.btn-nav:hover{ box-shadow:0 4px 14px -6px rgba(180,83,9,.5); }
.btn-export:hover{ box-shadow:0 4px 14px -6px rgba(4,120,87,.5); }
.btn-arrange:hover{ box-shadow:0 4px 14px -6px rgba(29,78,216,.5); }
.btn-theme:hover{ box-shadow:0 4px 14px -6px rgba(109,40,217,.5); }
.btn-link:hover{ box-shadow:0 4px 14px -6px rgba(14,116,144,.5); }
.btn:disabled, .btn[disabled], .btn.is-loading{
  opacity:.55; cursor:not-allowed; pointer-events:none;
}

/* ── Sidebar active-page accent bar ─────────────────────────────*/
.nav a{ transition:background .15s ease, color .15s ease; }
.nav a.active::before{
  content:''; position:absolute; left:0; top:50%; transform:translateY(-50%);
  width:3px; height:58%; border-radius:0 3px 3px 0; background:var(--amber);
}

/* ── Panels: gentle interactive lift ────────────────────────────*/
.panel{ transition:border-color .2s ease, box-shadow .2s ease; }

/* ── Respect the OS "reduce motion" preference ──────────────────*/
@media (prefers-reduced-motion: reduce){
  *, *::before, *::after{
    animation-duration:.001ms !important;
    animation-iteration-count:1 !important;
    transition-duration:.001ms !important;
    scroll-behavior:auto !important;
  }
}

/* ================================================================
   Professional polish · v2  (additive · presentational only)
   Depth, life & readability — living status dot, layered panel
   depth, KPI accent + hover lift, zebra tables. No logic changes.
   ================================================================ */

/* ── Living "Live" dot in the sidebar (matches the card dots) ───*/
.pill .dot.live{ animation:livePulse 2s ease-in-out infinite; }
@keyframes livePulse{
  0%,100%{ box-shadow:0 0 6px var(--emerald), 0 0 0 0 rgba(52,211,153,.55); }
  50%    { box-shadow:0 0 10px var(--emerald), 0 0 0 5px rgba(52,211,153,0); }
}

/* ── Panels: soft elevation (restrained shadow for a light surface) ─*/
.panel{
  box-shadow:
    0 1px 2px rgba(15,23,41,.06),
    0 8px 24px -16px rgba(15,23,41,.16);
}

/* ── KPI tiles: thin coloured accent + gentle hover lift ────────*/
.kpi{
  position:relative; overflow:hidden;
  transition:transform .18s ease, border-color .18s ease, box-shadow .18s ease;
}
.kpi::before{
  content:''; position:absolute; left:0; right:0; top:0; height:2px; opacity:.55;
  background:linear-gradient(90deg, transparent, #94a3b8, transparent);
}
.kpi.amber::before{ background:linear-gradient(90deg, transparent, var(--amber),   transparent); }
.kpi.cyan::before { background:linear-gradient(90deg, transparent, var(--cyan),    transparent); }
.kpi.green::before{ background:linear-gradient(90deg, transparent, var(--emerald), transparent); }
.kpi.red::before  { background:linear-gradient(90deg, transparent, var(--red),     transparent); }
.kpi:hover{
  transform:translateY(-2px); border-color:#cbd5e1;
  box-shadow:0 14px 30px -22px rgba(15,23,41,.18);
}

/* ── Tables: zebra rows + smooth hover + sticky header ──────────*/
table.grid thead th, table.grid th{
  position:sticky; top:0; z-index:1;
  background:var(--bg-2);
}
table.grid tbody tr{ transition:background .12s ease; }
table.grid tbody tr:nth-child(even) td{ background:rgba(15,23,41,.02); }
table.grid tr:hover td{ background:var(--panel-2); }

/* ================================================================
   Loading skeletons  (shimmer placeholders shown until first data)
   Auto-injected by app.js into any [data-skeleton] container, then
   replaced the moment the page renders real content. Presentational.
   ================================================================ */
@keyframes skShimmer{ 100%{ transform:translateX(100%); } }
.skeleton{
  position:relative; overflow:hidden;
  background:var(--panel-2); border:1px solid var(--line); border-radius:12px;
}
.skeleton::after{
  content:''; position:absolute; inset:0; transform:translateX(-100%);
  background:linear-gradient(90deg, transparent, rgba(15,23,41,.06), transparent);
  animation:skShimmer 1.25s infinite;
}
.sk-card{ padding:16px; min-height:120px; }
.skeleton .sk-line{ height:10px; border-radius:6px;
  background:rgba(15,23,41,.08); margin:9px 0; }
.skeleton .sk-val{ height:26px; width:62%; border-radius:8px;
  background:rgba(15,23,41,.11); margin:12px 0; }
.sk-line.w70{ width:70%; } .sk-line.w50{ width:50%; }
.sk-line.w40{ width:40%; } .sk-line.w30{ width:30%; }

/* ================================================================
   Global light-mode override for Tailwind's raw text-color utilities
   ================================================================
   The app's markup (templates + JS-generated HTML) has ~450 uses of
   Tailwind's text-white / text-slate-NNN utilities, written when the whole
   app was dark (white/light-gray text on near-black panels). Rather than
   hand-edit every one of those call sites individually — high risk of
   missing some on a codebase this size — the SAME small set of utility
   classes is redefined here to route through the new light palette. This
   is safe specifically because these utilities are used almost
   exclusively as ordinary body/label text sitting on the app's OWN panel
   backgrounds (which are now light); the small number of genuine
   exceptions — status pills / badges that keep a dark saturated fill with
   light text regardless of theme — were identified and moved to their own
   explicit colors or a dedicated .badge-neutral class BEFORE this override
   was added, specifically so they are unaffected by it.
   Loads after every other rule in this file, so it wins the cascade
   without needing !important (matches how .flex/.hidden work above).   */
.text-white{color:var(--txt)}
.text-slate-100,.text-slate-200,.text-slate-300{color:var(--txt-dim)}
.text-slate-400,.text-slate-500{color:var(--txt-muted)}
.text-slate-600,.text-slate-700,.text-slate-800,.text-slate-900{color:var(--txt)}
.border-slate-600,.border-slate-700,.border-slate-800{border-color:var(--line)}
.bg-slate-800,.bg-slate-900{background:var(--panel-2)}
/* hover:bg-slate-700/NN and hover:bg-slate-800 dropdown/row highlights were
   tuned to lighten a dark row; on light panels the same intent is a subtle
   darkening instead. */
.hover\:bg-slate-700:hover,.hover\:bg-slate-700\/40:hover,
.hover\:bg-slate-700\/50:hover,.hover\:bg-slate-800:hover{
  background:rgba(15,23,41,.045)!important;
}

/* Light-weight (300/400) accent text — used throughout as KPI numbers/table
   values on the app's own light panels, e.g. text-amber-400/text-emerald-400.
   Darkened to the same contrast-verified hues as the --amber/--cyan/etc CSS
   variables. text-emerald-300 and text-amber-300 are deliberately NOT
   touched here — both are also used on a couple of very dark (900-weight)
   status badges that must keep light text; those two specific non-badge
   usages were fixed individually with inline styles instead. */
.text-amber-400{color:#b45309}
.text-emerald-400{color:#047857}
.text-cyan-400,.text-cyan-300{color:#0e7490}
.text-red-400{color:#be123c}
.text-violet-400{color:#6d28d9}
.text-orange-400,.text-orange-300{color:#c2410c}
.text-sky-400,.text-sky-300{color:#0369a1}
.text-pink-400{color:#be185d}

/* Opacity-modifier utilities (Tailwind bakes these to a fixed rgba at build
   time, so the plain-class overrides above don't reach them). Same intent:
   mini KPI tiles get a light sunken-well fill, dividers get a light line. */
.bg-slate-800\/60{background:#f4f6fa!important}
.border-slate-700\/40{border-color:#e6eaf0!important}
