/**
 * nodal portal — brand override layer (blue-gray #85B0C4).
 * -----------------------------------------------------------------------------
 * Retint of Frest's compiled blue primary (#5a8dee) to the nodal accent.
 * NOTE: A full rebrand should recompile Frest's SCSS with $primary set; this
 * override covers the high-visibility surfaces so the look/feel reads as nodal.
 */

:root,
:root.light-style,
:root.dark-style {
  --bs-primary: #85B0C4;
  --bs-primary-rgb: 133, 176, 196;
  --nodal-blue-1: #9cc2d3;   /* lighter, gradient top */
  --nodal-blue-2: #85B0C4;   /* base (logo accent) */
  --nodal-ink: #0e2a35;      /* dark text on the blue */
  --nodal-link: #4d7d93;     /* readable accent text/links on light */
}

/* Solid primary surfaces */
.bg-primary { background-color: var(--bs-primary) !important; }
.text-primary { color: var(--nodal-link) !important; }
.border-primary { border-color: var(--bs-primary) !important; }
.dark-style .text-primary { color: #9cc2d3 !important; }

.btn-primary {
  background: linear-gradient(135deg, var(--nodal-blue-1) 0%, var(--nodal-blue-2) 100%);
  border-color: var(--nodal-blue-2);
  color: var(--nodal-ink);
}
.btn-primary:hover,
.btn-primary:focus,
.btn-primary:active,
.btn-primary.active {
  background: var(--nodal-blue-2) !important;
  border-color: var(--nodal-blue-2) !important;
  color: var(--nodal-ink) !important;
  box-shadow: 0 0.125rem 0.5rem 0 rgba(133, 176, 196, 0.45) !important;
}
.btn-outline-primary {
  color: var(--nodal-link);
  border-color: var(--bs-primary);
}
.btn-outline-primary:hover {
  background-color: var(--bs-primary);
  border-color: var(--bs-primary);
  color: var(--nodal-ink);
}

/* Soft/label primary (badges, avatars, icon chips) */
.bg-label-primary {
  background-color: rgba(133, 176, 196, 0.18) !important;
  color: var(--nodal-link) !important;
}
.dark-style .bg-label-primary { color: #9cc2d3 !important; }
.badge.bg-primary { background-color: var(--bs-primary) !important; color: var(--nodal-ink) !important; }

/* Links */
a { color: var(--nodal-link); }
.dark-style a { color: #9cc2d3; }
.text-primary:hover { color: var(--bs-primary) !important; }

/* Vertical menu active state */
.menu-vertical .menu-item.active > .menu-link:not(.menu-toggle) {
  background: linear-gradient(135deg, var(--nodal-blue-1) 0%, var(--nodal-blue-2) 100%);
  color: var(--nodal-ink);
  box-shadow: 0 0.125rem 0.5rem 0 rgba(133, 176, 196, 0.45);
}
.menu-vertical .menu-item.active > .menu-link:not(.menu-toggle) .menu-icon { color: var(--nodal-ink); }

/* Form controls focus ring */
.form-control:focus,
.form-select:focus {
  border-color: var(--bs-primary);
  box-shadow: 0 0 0 0.15rem rgba(133, 176, 196, 0.25);
}

/* Brand logo slot: Frest's is a narrow fixed-width square (built for a small
   icon) — let it size to whichever brand variant is showing. */
.app-brand .app-brand-logo {
  width: auto;
  height: auto;
  overflow: visible;
}
.app-brand .nodal-brand-wordmark img { height: 52px; width: auto; }
.app-brand .nodal-brand-mark img { height: 34px; width: auto; }

/* Mode: wordmark when expanded, monogram mark when collapsed. Frest adds
   .layout-menu-collapsed on <html>, and .layout-menu-hover while a collapsed
   menu is hovered (temporarily expanded). */
.app-brand .nodal-brand-mark { display: none; }
.app-brand .nodal-brand-wordmark { display: block; }
.layout-menu-collapsed:not(.layout-menu-hover) .app-brand .nodal-brand-wordmark { display: none; }
.layout-menu-collapsed:not(.layout-menu-hover) .app-brand .nodal-brand-mark { display: block; }

/* Theme: pick the light/dark glyph within whichever variant is shown. */
.app-brand .nodal-brand .theme-dark { display: none; }
.app-brand .nodal-brand .theme-light { display: block; }
.dark-style .app-brand .nodal-brand .theme-light { display: none; }
.dark-style .app-brand .nodal-brand .theme-dark { display: block; }

/* Collapse toggle: chevron points left (collapse) when expanded, right (expand)
   when collapsed — visible while hovering a collapsed menu. */
.app-brand .layout-menu-toggle i { transition: transform 0.3s ease; }
.layout-menu-collapsed .app-brand .layout-menu-toggle i { transform: rotate(180deg); }

/* Status dots for charge-point states */
.nodal-status-dot {
  display: inline-block;
  width: 0.625rem;
  height: 0.625rem;
  border-radius: 50%;
}
.nodal-status-dot.is-online   { background-color: #39da8a; }
.nodal-status-dot.is-charging { background-color: #00cfdd; }
.nodal-status-dot.is-offline  { background-color: #a8b1bb; }
.nodal-status-dot.is-faulted  { background-color: #ff5b5c; }

/* Fleet-style Sites screen: scrollable site list beside a fill-height map */
.nodal-fleet { min-height: 540px; height: calc(100vh - 13rem); }
.nodal-fleet-sidebar { display: flex; flex-direction: column; max-height: 100%; }
.nodal-fleet-list { overflow-y: auto; flex: 1 1 auto; }
.nodal-fleet-map { min-height: 360px; position: relative; }
#nodal-sites-map { position: absolute; inset: 0; height: 100%; width: 100%; }
.nodal-site-item { transition: border-color 0.15s ease, box-shadow 0.15s ease; }
.nodal-site-item.active { border-color: var(--bs-primary) !important; box-shadow: 0 0 0 1px var(--bs-primary); }
.nodal-cp-row:hover { background: rgba(133, 176, 196, 0.10); }
.nodal-cp-row:last-child { border-bottom: 0 !important; }

@media (max-width: 991.98px) {
  .nodal-fleet { height: auto; }
  .nodal-fleet-map { height: 420px; min-height: 420px; }
  #nodal-sites-map { position: relative; }
}

/* OCPP message log table */
.nodal-log-row { cursor: pointer; }
.nodal-log-row .nodal-log-caret { transition: transform 0.2s ease; }
.nodal-log-row[aria-expanded="true"] .nodal-log-caret { transform: rotate(90deg); }
.nodal-log-table pre { background: rgba(0, 0, 0, 0.03); max-height: 340px; overflow: auto; white-space: pre-wrap; word-break: break-word; }
.dark-style .nodal-log-table pre { background: rgba(255, 255, 255, 0.04); }

/* Request/response timeline (legacy stacked frames — kept for fallback) */
.nodal-tl-group pre { background: rgba(0, 0, 0, 0.03); padding: 0.5rem 0.75rem; border-radius: 0.375rem; max-height: 300px; overflow: auto; white-space: pre-wrap; word-break: break-word; }
.dark-style .nodal-tl-group pre { background: rgba(255, 255, 255, 0.04); }
.nodal-tl-frame .btn { font-weight: 500; }

/* =========================================================================
   3-lane swimlane (Charger ↔ nodal ↔ Upstream) — Phase 2 Logs→Timeline.
   Ported/retinted from the admin debug timeline; .nsw-* namespace.
   ========================================================================= */
.nsw {
  --nsw-line: #e6e9ee;
  --nsw-line-soft: #f0f2f5;
  --nsw-hover: #fafbfc;
  --nsw-cp: #e3f2fd;        --nsw-cp-ink: #1565c0;
  --nsw-srv: rgba(133,176,196,0.20); --nsw-srv-ink: #3a6b80;
  --nsw-up: #fff3e0;        --nsw-up-ink: #ef6c00;
  --nsw-mono: 'Roboto Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  position: relative;
}
.dark-style .nsw {
  --nsw-line: #3b4253;
  --nsw-line-soft: #2f3349;
  --nsw-hover: #2b2f44;
  --nsw-cp: rgba(33,150,243,0.18);    --nsw-cp-ink: #90caf9;
  --nsw-srv: rgba(133,176,196,0.22);  --nsw-srv-ink: #9cc2d3;
  --nsw-up: rgba(239,108,0,0.18);     --nsw-up-ink: #ffb74d;
}

.nsw-lane-headers {
  position: sticky; top: 0; z-index: 5;
  display: grid; grid-template-columns: 12rem 1fr 1fr 1fr; gap: 4px;
  padding: 8px 12px; background: var(--bs-card-bg, #fff);
  border-bottom: 1px solid var(--nsw-line);
  font-weight: 600; font-size: 12px;
}
.nsw-lane { padding: 4px 8px; border-radius: 0.375rem; text-align: center; }
.nsw-lane-cp { background: var(--nsw-cp); color: var(--nsw-cp-ink); }
.nsw-lane-srv { background: var(--nsw-srv); color: var(--nsw-srv-ink); }
.nsw-lane-up { background: var(--nsw-up); color: var(--nsw-up-ink); }
.nsw-lane-up.nsw-greyed { opacity: 0.35; }
.nsw-lane-up:not(.nsw-greyed) .nsw-up-na { display: none; }

.nsw-groups { max-height: 70vh; overflow-y: auto; }

.nsw-group { border-bottom: 1px solid var(--nsw-line-soft); position: relative; }
.nsw-group:hover { background: var(--nsw-hover); }
.nsw-group.nsw-expanded { background: var(--nsw-hover); }
.nsw-summary {
  display: grid; grid-template-columns: 12rem 1fr 1fr 1fr; gap: 4px;
  align-items: center; padding: 8px 12px; cursor: pointer; user-select: none;
}
.nsw-time {
  font-family: var(--nsw-mono); font-size: 12px; color: var(--bs-secondary-color, #5f6c7b);
  display: flex; flex-direction: column; align-items: flex-start; gap: 2px;
}
.nsw-time > div:first-child { display: flex; align-items: center; gap: 4px; }
.nsw-summary-action { display: flex; align-items: center; gap: 6px; margin-top: 2px; font-size: 11px; }
.nsw-action-pill {
  display: inline-block; padding: 2px 8px; border-radius: 12px;
  background: var(--nsw-srv); color: var(--nsw-srv-ink);
  font-size: 11px; font-weight: 600;
}
.nsw-frame-count { color: var(--bs-secondary-color, #90a4ae); font-family: var(--nsw-mono); }
.nsw-incomplete {
  display: inline-flex; align-items: center; gap: 3px; padding: 1px 6px; border-radius: 4px;
  background: var(--nsw-up); color: var(--nsw-up-ink); font-size: 10px; font-weight: 600; font-family: var(--nsw-mono);
}

.nsw-cell { min-height: 28px; display: flex; align-items: center; justify-content: center; position: relative; }
.nsw-dot { width: 10px; height: 10px; border-radius: 50%; box-shadow: 0 0 0 3px rgba(0,0,0,0.06); }
.nsw-dot.nsw-req { background: #1976d2; }
.nsw-dot.nsw-resp { background: #2e9e5b; }
.nsw-dot.nsw-err { background: #d32f2f; }
.nsw-arrow { position: absolute; top: 50%; transform: translateY(-50%); font-size: 15px; color: #90a4ae; pointer-events: none; }
.nsw-arrow-right { right: -10px; }
.nsw-arrow-left { left: -10px; }

.nsw-frames { display: none; padding: 0 12px 12px; background: var(--nsw-hover); border-top: 1px dashed var(--nsw-line); }
.nsw-group.nsw-expanded .nsw-frames { display: block; }
.nsw-frame-row { display: grid; grid-template-columns: 12rem 1fr 1fr 1fr; gap: 4px; padding: 4px 0; align-items: start; font-size: 12px; }
.nsw-frame-meta { color: var(--bs-secondary-color, #5f6c7b); font-size: 11px; }
.nsw-payload {
  grid-column: 2 / -1; background: var(--bs-card-bg, #fff); border: 1px solid var(--nsw-line);
  border-radius: 4px; padding: 6px 10px; margin-top: 4px; font-family: var(--nsw-mono);
  font-size: 11px; white-space: pre-wrap; word-break: break-all; max-height: 200px; overflow-y: auto;
}
.nsw-chevron { transition: transform 0.15s ease; color: #90a4ae; width: 12px; text-align: center; }
.nsw-group.nsw-expanded .nsw-chevron { transform: rotate(90deg); }

/* Latency chips */
.nsw-latency { display: inline-flex; align-items: center; gap: 4px; font-size: 10px; font-family: var(--nsw-mono); padding: 1px 6px; border-radius: 4px; margin-left: 6px; white-space: nowrap; }
.nsw-lat-fast { background: rgba(46,158,91,0.15); color: #2e9e5b; }
.nsw-lat-slow { background: rgba(239,108,0,0.15); color: #ef6c00; }
.nsw-lat-bad  { background: rgba(211,47,47,0.15); color: #d32f2f; }

/* State side panel */
.nsw-state-block { padding: 10px 0; border-bottom: 1px solid var(--nsw-line-soft); }
.nsw-state-block:last-of-type { border-bottom: none; }
.nsw-state-title { font-weight: 600; font-size: 11px; text-transform: uppercase; letter-spacing: 0.5px; color: var(--bs-secondary-color, #455a64); margin-bottom: 4px; }
.nsw-state-row { display: flex; justify-content: space-between; align-items: center; padding: 2px 0; font-size: 13px; }
.nsw-state-key { color: var(--bs-secondary-color, #5f6c7b); }
.nsw-state-val { font-weight: 500; }
.nsw-conn-pill { display: inline-block; padding: 2px 8px; border-radius: 12px; font-size: 11px; font-weight: 600; background: #eceff1; color: #455a64; }
.nsw-st-available  { background: rgba(57,218,138,0.18); color: #1b7a45; }
.nsw-st-preparing  { background: rgba(245,124,0,0.16); color: #c25e00; }
.nsw-st-charging   { background: rgba(0,207,221,0.18); color: #00838f; }
.nsw-st-finishing  { background: rgba(94,53,177,0.16); color: #5e35b1; }
.nsw-st-faulted    { background: rgba(211,47,47,0.16); color: #c62828; }
.nsw-st-suspended  { background: rgba(239,108,0,0.16); color: #ef6c00; }
.nsw-st-unavailable{ background: #eceff1; color: #455a64; }
.dark-style .nsw-conn-pill { background: #2f3349; color: #cfd3ec; }
.nsw-hb-stale { color: #d32f2f; font-weight: 600; }
.nsw-hb-fresh { color: #2e9e5b; font-weight: 500; }

/* Live (fresh) pulse for newly-arrived rows */
@keyframes nsw-pulse { 0% { background-color: rgba(133,176,196,0.22); } 100% { background-color: transparent; } }
.nsw-group.nsw-fresh { animation: nsw-pulse 2.5s ease-out; }
