:root {
  color-scheme: dark;
  --bg: #101313;
  --panel: #171b1d;
  --panel-raised: #202628;
  --ink: #edf1ed;
  --muted: #98a39d;
  --line: #303a3d;
  --accent: #29b17f;
  --accent-dark: #197452;
  --signal: #d7a12d;
  --danger: #d35d52;
  --blue: #5b91c9;
  --idle: #596267;
  --shadow: 0 18px 40px rgba(0, 0, 0, 0.45);
  --radius: 8px;
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: "JetBrains Mono", "Fira Code", ui-monospace, "Cascadia Code", Consolas, Inter, ui-sans-serif, system-ui, sans-serif;
  font-size: 13px;
}

button,
select,
input,
a {
  font: inherit;
  color: inherit;
}

h1, h2, h3, p, dl, dd, dt, table, ol, ul {
  margin: 0;
  padding: 0;
}

.console {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

/* ---------- Toolbar ---------- */

.toolbar {
  display: flex;
  align-items: center;
  gap: 22px;
  padding: 10px 18px;
  border-bottom: 1px solid var(--line);
  background: linear-gradient(180deg, var(--panel-raised), var(--panel));
  box-shadow: var(--shadow);
  /* Always-visible brand/status bar -- everything else in .console (including the
     subscriber-picker bar right below it) scrolls underneath. */
  position: sticky;
  top: 0;
  z-index: 6;
}

/* Calling/Called Subscriber row -- the one control every "place a call" workflow needs,
   pinned directly under the sticky toolbar for the entire page, not just while its parent
   panel happens to be on screen. --toolbar-height is measured and kept in sync by app.js
   (the toolbar can wrap onto two lines at the mobile breakpoint, so its height isn't a
   fixed constant); 64px is a reasonable single-line fallback before that first runs. */
.control-strip.subscriber-picker-bar {
  /* .control-strip qualifier deliberately matches this element's other class for
     specificity -- otherwise ".control-strip { margin-bottom: 8px }" (declared later in
     this file) would win the cascade over a bare ".subscriber-picker-bar" rule despite
     this one being more specific in intent. */
  position: sticky;
  top: var(--toolbar-height, 64px);
  z-index: 5;
  background: var(--panel);
  border-bottom: 1px solid var(--line);
  box-shadow: var(--shadow);
  padding: 10px 18px;
  margin: 0;
}

.toolbar-brand {
  display: flex;
  align-items: baseline;
  gap: 10px;
  white-space: nowrap;
}

.toolbar-brand h1 {
  font-size: 1.1rem;
  font-weight: 800;
  letter-spacing: 0.03em;
  color: var(--accent);
}

.toolbar-brand .subtitle {
  color: var(--muted);
  font-size: 0.72rem;
}

.toolbar-controls {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.toolbar-status {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-left: auto;
  color: var(--muted);
  font-size: 0.78rem;
  white-space: nowrap;
}

.sim-time strong,
.stat-list dd {
  color: var(--ink);
}

.run-status,
.connection-status {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-weight: 700;
}

.account-status {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding-left: 12px;
  border-left: 1px solid var(--line);
  color: var(--muted);
  font-size: 0.76rem;
}

.account-status .btn {
  min-height: auto;
  padding: 4px 10px;
}

.status-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--idle);
}

.status-dot.ok,
.run-status.running .status-dot {
  background: var(--accent);
  box-shadow: 0 0 0 4px rgba(47, 184, 166, 0.18);
}

.run-status.paused .status-dot {
  background: var(--signal);
  box-shadow: 0 0 0 4px rgba(212, 156, 33, 0.18);
}

.audio-mixer {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

.audio-mixer-label {
  color: var(--muted);
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.audio-channel {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  color: var(--muted);
  font-size: 0.66rem;
  font-weight: 700;
  cursor: pointer;
}

.audio-channel input[type="range"] {
  width: 50px;
}

/* ---------- Buttons / inputs ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 32px;
  padding: 6px 12px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--panel-raised);
  color: var(--ink);
  font-weight: 700;
  font-size: 0.76rem;
  cursor: pointer;
  text-decoration: none;
}

.btn:hover {
  border-color: var(--accent);
  color: var(--accent);
}

.btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.btn:disabled:hover {
  border-color: var(--line);
  color: var(--ink);
}

.btn:active {
  transform: translateY(1px);
}

.btn-run {
  border-color: var(--accent);
  background: var(--accent-dark);
  color: #ffffff;
}

.btn-primary {
  border-color: var(--blue);
  background: var(--blue);
  color: #ffffff;
}

.btn-danger {
  border-color: var(--danger);
  background: var(--danger);
  color: #ffffff;
}

.btn-outline-danger,
.btn-danger-outline {
  border-color: var(--danger);
  color: var(--danger);
}

.btn-warning {
  border-color: var(--signal);
  background: var(--signal);
  color: #241a03;
}

.btn-ghost {
  background: transparent;
}

.btn-small {
  min-height: 26px;
  padding: 4px 8px;
  font-size: 0.7rem;
}

select,
input[type="text"],
input[type="number"] {
  min-height: 30px;
  padding: 4px 8px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--bg);
  color: var(--ink);
  font-size: 0.76rem;
}

.input-small {
  width: 100%;
}

/* ---------- Grid layout ---------- */

.console-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-template-areas:
    "controls controls controls controls"
    "lessons lessons lessons lessons"
    "timeline timeline timeline timeline"
    "diagram diagram diagram diagram"
    "calls calls calls calls"
    "network network network network"
    "trunkview trunkview trunkview trunkview"
    "inspector callpath overview status"
    "eventlog eventlog eventlog eventlog";
  gap: 12px;
  flex: 1;
  padding: 12px 18px;
}

.panel {
  min-width: 0;
  padding: 14px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--panel);
  box-shadow: var(--shadow);
  overflow: hidden;
}

.panel-title {
  margin-bottom: 12px;
  color: var(--muted);
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.panel-title span {
  color: var(--accent);
  text-transform: none;
  letter-spacing: 0;
}

.panel-title .panel-subtitle {
  margin-left: 6px;
  color: var(--muted);
  font-style: italic;
  font-weight: 600;
}

.panel-title-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 10px;
}

.section-heading {
  margin: 14px 0 8px;
  color: var(--muted);
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.diagram-panel { grid-area: diagram; overflow-x: auto; overflow-y: auto; }

.panel-description {
  margin: -4px 0 10px;
  color: var(--muted);
  font-size: 0.72rem;
}

/* ---------- Live Exchange Diagrams: one exchange visible at a time, via tab bar ---------- */

.exchange-tab-bar {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  margin-bottom: 10px;
}

.exchange-tab-button {
  padding: 7px 16px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--panel-raised);
  color: var(--muted);
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.02em;
  cursor: pointer;
}

.exchange-tab-button:hover {
  border-color: var(--accent);
  color: var(--ink);
}

.exchange-tab-button.active {
  border-color: var(--accent);
  background: var(--accent-dark);
  color: #fff;
}

.exchange-tab-button.exchange-tab-add {
  border-style: dashed;
  color: var(--accent);
}

.exchange-diagrams {
  display: flex;
  flex-direction: column;
  gap: 18px;
}

.exchange-block {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--panel-raised);
  padding: 12px;
}

.exchange-block.hidden {
  display: none;
}

.exchange-block + .exchange-block {
  border-top: 2px solid var(--accent);
}

/* Sidebar (view tabs + live component-count inventory) alongside the main diagram panel,
   matching the mockup's left-rail layout -- replaces the tab buttons that used to sit in
   the block header. */
.exchange-body {
  display: flex;
  align-items: flex-start;
  gap: 14px;
}

.exchange-sidebar {
  flex: 0 0 190px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.diagram-tabs.vertical {
  flex-direction: column;
  align-items: stretch;
}

.diagram-tabs.vertical .tab-button {
  text-align: left;
}

.sidebar-components {
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 8px 10px;
  background: var(--panel);
}

.sidebar-heading {
  color: var(--muted);
  font-size: 0.66rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding-bottom: 6px;
  border-bottom: 1px solid var(--line);
  margin-bottom: 6px;
}

.component-count-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.component-count-list li {
  display: flex;
  justify-content: space-between;
  gap: 8px;
  font-size: 0.68rem;
  color: var(--muted);
}

.component-count-value {
  font-weight: 700;
  color: var(--ink);
}

.exchange-main {
  flex: 1;
  min-width: 0;
}

.exchange-block-header {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 8px;
}

.exchange-block-title {
  margin: 0;
  font-size: 0.85rem;
  font-weight: 800;
  color: var(--ink);
}

.exchange-activity-badge {
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--panel);
  border: 1px solid var(--line);
  color: var(--muted);
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.02em;
}

.exchange-role-badge {
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}

.exchange-role-badge.role-originating {
  background: rgba(74, 138, 92, 0.14);
  border: 1px solid var(--accent);
  color: var(--accent);
}

.exchange-role-badge.role-terminating {
  background: rgba(90, 110, 200, 0.14);
  border: 1px solid var(--signal);
  color: var(--signal);
}

.exchange-activity-badge.activity-quiet {
  color: var(--muted);
  border-color: var(--line);
}

.exchange-activity-badge.activity-active {
  color: var(--accent);
  border-color: var(--accent);
}

.exchange-activity-badge.activity-busy {
  color: var(--signal);
  border-color: var(--signal);
}

.exchange-activity-badge.activity-congestion {
  color: var(--danger);
  border-color: var(--danger);
  animation: activity-congestion-pulse 1.2s ease-in-out infinite;
}

@keyframes activity-congestion-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(211, 93, 82, 0.4); }
  50% { box-shadow: 0 0 0 4px rgba(211, 93, 82, 0); }
}

.simulation-mode-badge {
  padding: 2px 10px;
  border-radius: 999px;
  background: var(--panel);
  border: 1px solid var(--line);
  color: var(--muted);
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}

.simulation-mode-badge.mode-manual {
  color: var(--accent);
  border-color: var(--accent);
}

.manual-dial-strip {
  align-items: center;
  gap: 8px;
}

.manual-dial-display {
  font-family: var(--mono, monospace);
  font-size: 1rem;
  letter-spacing: 0.15em;
  min-width: 5ch;
  padding: 2px 8px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--panel);
}

.manual-dial-keypad {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 4px;
}

.manual-dial-keypad.hidden {
  display: none;
}

.control-strip .manual-dial-keypad .btn {
  /* Extra .control-strip qualifier deliberately raises specificity above the later
     ".control-strip .btn { flex: 1 1 150px }" rule below (equal specificity would
     otherwise let source order pick that one) -- without this override, each digit
     button grows to fill its wrapped flex row on its own, stacking the keypad into a
     ten-row column instead of a compact row of digits. */
  flex: 0 0 auto;
  min-width: 2.2em;
  padding: 4px 0;
}

#manualAnswerButton.hidden,
#manualHangupButton.hidden {
  display: none;
}

.exchange-block-header .diagram-tabs {
  margin-left: auto;
}

/* ---------- Diagram tabs (Cabinet View / Call Flow) ---------- */

.diagram-tabs {
  display: flex;
  align-items: center;
  gap: 6px;
}

.diagram-readonly-note {
  margin: -4px 0 10px;
  padding: 6px 10px;
  border: 1px solid var(--signal);
  border-radius: 6px;
  background: var(--panel-raised);
  color: var(--signal);
  font-size: 0.68rem;
}

.diagram-readonly-note.hidden {
  display: none;
}

/* ---------- Interoffice call banner: shown on both ends of a selected inter-exchange call ---------- */

.interoffice-banner {
  margin: -4px 0 10px;
  padding: 6px 10px;
  border: 1px solid var(--blue);
  border-right: 4px solid var(--blue);
  border-radius: 6px;
  background: var(--panel-raised);
  color: var(--blue);
  font-size: 0.68rem;
  font-weight: 700;
  animation: interoffice-banner-pulse 1.6s ease-in-out infinite;
}

.interoffice-banner.hidden {
  display: none;
}

@keyframes interoffice-banner-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.65; }
}

.tab-button {
  padding: 5px 12px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--panel-raised);
  color: var(--muted);
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  cursor: pointer;
}

.tab-button:hover {
  border-color: var(--accent);
  color: var(--ink);
}

.tab-button.active {
  border-color: var(--accent);
  background: var(--accent-dark);
  color: #fff;
}

.tab-button:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.tab-button:disabled:hover {
  border-color: var(--line);
  color: var(--muted);
}

.diagram-tab-panel.hidden {
  display: none;
}

/* ---------- Cabinet explorer (Level 1-5 drill-down) ---------- */

.cabinet-breadcrumb {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px;
  margin-bottom: 8px;
  font-size: 0.72rem;
}

.cabinet-breadcrumb .crumb {
  padding: 3px 8px;
  border: 1px solid var(--line);
  border-radius: 999px;
  color: var(--muted);
  background: var(--panel-raised);
  cursor: pointer;
}

.cabinet-breadcrumb .crumb:hover {
  border-color: var(--accent);
  color: var(--ink);
}

.cabinet-breadcrumb .crumb.current {
  border-color: var(--blue);
  color: var(--ink);
  cursor: default;
}

.cabinet-breadcrumb .sep {
  color: var(--muted);
}

.cabinet-explorer {
  display: grid;
  grid-template-columns: 200px 1fr;
  gap: 10px;
  min-height: 420px;
}

.explorer-tree {
  overflow-y: auto;
  max-height: 460px;
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 6px;
  background: var(--bg);
  font-size: 0.72rem;
}

.explorer-node {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  padding: 4px 6px;
  border-radius: 4px;
  cursor: pointer;
  color: var(--muted);
}

.explorer-node:hover {
  background: var(--panel-raised);
  color: var(--ink);
}

.explorer-node.current {
  background: rgba(47, 184, 166, 0.15);
  color: var(--accent);
  font-weight: 700;
}

.explorer-node .count {
  font-size: 0.62rem;
  color: var(--muted);
}

.explorer-children {
  margin-left: 10px;
  border-left: 1px solid var(--line);
  padding-left: 6px;
}

.cabinet-view {
  min-height: 420px;
  max-height: 460px;
  overflow-y: auto;
}

/* Per-exchange Event Log tab -- same row styling as the global diagnostic Event Log, but
   sized to the same min/max-height as this exchange block's other two tabs (Cabinet View's
   .cabinet-view above) so switching tabs never changes the block's overall footprint.
   Newest events render first (see renderExchangeEventLog in app.js) -- scrolling down
   reveals older ones, exactly like the global Event Log. */
.exchange-event-log {
  min-height: 420px;
  max-height: 460px;
}

.cabinet-floor-plan {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 10px;
}

.cabinet-tile {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 12px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: linear-gradient(180deg, var(--panel-raised), var(--bg));
  cursor: pointer;
  transition: border-color 120ms ease, transform 120ms ease;
}

.cabinet-tile:hover {
  border-color: var(--accent);
  transform: translateY(-2px);
}

.cabinet-tile .cabinet-label {
  font-size: 0.74rem;
  font-weight: 800;
}

.cabinet-tile .cabinet-meta {
  color: var(--muted);
  font-size: 0.64rem;
}

.cabinet-tile .cabinet-gauge {
  height: 5px;
  border-radius: 999px;
  background: var(--line);
  overflow: hidden;
}

.cabinet-tile .cabinet-gauge span {
  display: block;
  height: 100%;
  background: var(--accent);
}

.cabinet-tile.empty {
  opacity: 0.45;
  cursor: default;
}

.rack-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 8px;
}

.rack-tile {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 10px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--panel-raised);
  cursor: pointer;
}

.rack-tile:hover {
  border-color: var(--accent);
}

.rack-tile .rack-label {
  font-size: 0.7rem;
  font-weight: 800;
}

.rack-tile .rack-meta {
  color: var(--muted);
  font-size: 0.62rem;
}

.cabinet-view .component-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: 8px;
  max-height: none;
}

.level4-summary {
  padding: 14px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--panel-raised);
  text-align: center;
}

.level4-summary p {
  margin-bottom: 10px;
  color: var(--muted);
  font-size: 0.76rem;
}

.component-level-view {
  display: grid;
  place-items: center;
  min-height: 320px;
  padding: 20px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: radial-gradient(circle at 50% 30%, rgba(47, 184, 166, 0.08), var(--bg));
}

.illustration-relay-bank {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 16px 22px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--panel-raised);
}

.illustration-relay-bank span {
  position: relative;
  padding: 8px 14px;
  border: 1px solid var(--line);
  border-radius: 4px;
  background: var(--bg);
  color: var(--muted);
  font-size: 0.68rem;
  font-weight: 700;
  text-align: center;
}

.illustration-relay-bank span::before {
  content: "";
  position: absolute;
  left: 6px;
  top: 50%;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--signal);
  transform: translateY(-50%);
  animation: relay-contact-flicker 2.2s ease-in-out infinite;
}

.illustration-relay-bank span:nth-child(2)::before { animation-delay: 0.3s; }
.illustration-relay-bank span:nth-child(3)::before { animation-delay: 0.6s; }
.illustration-relay-bank span:nth-child(4)::before { animation-delay: 0.9s; }
.illustration-relay-bank span:nth-child(5)::before { animation-delay: 1.2s; }

@keyframes relay-contact-flicker {
  0%, 80%, 100% { opacity: 0.3; box-shadow: none; }
  90% { opacity: 1; box-shadow: 0 0 6px rgba(215, 161, 45, 0.8); }
}

.illustration-crosspoint {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  padding: 20px 30px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--panel-raised);
}

.illustration-crosspoint span {
  padding: 8px 16px;
  border: 1px solid var(--line);
  border-radius: 4px;
  background: var(--bg);
  color: var(--muted);
  font-size: 0.68rem;
  font-weight: 700;
}

.illustration-crosspoint .operating-magnet {
  border-color: var(--signal);
  color: var(--signal);
}

.illustration-crosspoint .contact-pair {
  border-color: var(--accent);
  color: var(--accent);
  animation: cross-blink 1.4s ease-in-out infinite alternate;
}

.illustration-crosspoint .hold-magnet {
  border-color: var(--blue);
  color: var(--blue);
}
.timeline-panel { grid-area: timeline; }
.controls-panel {
  grid-area: controls;
}
.lessons-panel { grid-area: lessons; }
.calls-panel { grid-area: calls; max-height: 260px; display: flex; flex-direction: column; }

.lesson-controls {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  margin-bottom: 10px;
}

.lesson-description {
  color: var(--muted);
  font-size: 0.72rem;
  margin-bottom: 10px;
}

.lesson-narration {
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--panel-raised);
  font-size: 0.78rem;
  line-height: 1.5;
  min-height: 44px;
}

.lesson-narration.active {
  border-color: var(--accent);
}

.lesson-progress {
  margin-top: 8px;
  color: var(--muted);
  font-size: 0.66rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

/* The four information panels share one row, equal width (grid columns) and equal height
   (fixed panel height + internal scroll) so Equipment Inspector's fuller content sets the
   pace without forcing the others to grow or shrink around it. */
.inspector-panel,
.callpath-panel,
.overview-panel,
.status-panel {
  min-height: 480px;
  max-height: 480px;
  overflow-y: auto;
}

.inspector-panel { grid-area: inspector; }
.callpath-panel { grid-area: callpath; }
.overview-panel { grid-area: overview; }
.status-panel { grid-area: status; display: flex; flex-direction: column; }

.eventlog-panel { grid-area: eventlog; display: flex; flex-direction: column; min-height: 340px; }

/* ---------- Exchange overview ---------- */

.preset-controls {
  display: flex;
  gap: 6px;
  margin-bottom: 10px;
}

.preset-controls select {
  flex: 1;
  min-width: 0;
}

.custom-config-controls {
  flex-wrap: wrap;
}

.custom-config-controls input {
  width: 90px;
}

.exchange-identity {
  margin-bottom: 6px;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--line);
}

.exchange-identity strong {
  display: block;
  font-size: 0.95rem;
  color: var(--ink);
}

.exchange-identity span {
  color: var(--muted);
  font-size: 0.72rem;
}

.stat-list {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 6px 10px;
  font-size: 0.76rem;
}

.stat-list dt {
  color: var(--muted);
}

.stat-list dd {
  font-weight: 700;
  text-align: right;
}

/* ---------- Per-exchange overview strip: compact, horizontal, embedded in each stacked block ---------- */

.exchange-overview-strip {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 14px;
  margin: 0 0 10px;
  padding: 6px 10px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--bg);
  font-size: 0.68rem;
}

.exchange-overview-strip .stat-item {
  display: flex;
  align-items: baseline;
  gap: 4px;
  white-space: nowrap;
}

.exchange-overview-strip dt {
  color: var(--muted);
}

.exchange-overview-strip dd {
  margin: 0;
  font-weight: 800;
  color: var(--ink);
}

.stat-list dd.warn {
  color: var(--signal);
}

.stat-list dd.danger {
  color: var(--danger);
}

/* ---------- Release 0.9 (Phase 3): congestion propagation + cause taxonomy ---------- */

.congestion-panel {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 18px;
  margin: 0 0 10px;
  padding: 6px 10px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--bg);
  font-size: 0.68rem;
}

.congestion-propagation {
  display: flex;
  align-items: center;
  gap: 4px;
}

.congestion-stage {
  padding: 3px 8px;
  border: 1px solid var(--line);
  border-radius: 999px;
  color: var(--muted);
  font-weight: 700;
  white-space: nowrap;
  transition: background 150ms ease, color 150ms ease, border-color 150ms ease;
}

.congestion-stage::after {
  content: "→";
  margin-left: 8px;
  color: var(--muted);
}

.congestion-stage:last-child::after {
  content: "";
  margin-left: 0;
}

.congestion-stage.active {
  border-color: var(--danger);
  color: var(--danger);
  background: rgba(211, 93, 82, 0.12);
}

.congestion-causes {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 14px;
  margin: 0;
}

.congestion-causes .stat-item {
  display: flex;
  align-items: baseline;
  gap: 4px;
  white-space: nowrap;
}

.congestion-causes dt {
  color: var(--muted);
}

.congestion-causes dd {
  margin: 0;
  font-weight: 800;
  color: var(--ink);
}

/* ---------- Connection legend + node-link wiring lines ---------- */

.connection-legend {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 14px;
  margin-bottom: 8px;
  font-size: 0.66rem;
  color: var(--muted);
}

.connection-legend span {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}

.legend-sep {
  width: 1px;
  height: 12px;
  background: var(--line);
}

.line-swatch {
  display: inline-block;
  width: 16px;
  height: 2px;
  border-radius: 1px;
}

.line-swatch.speech-idle { background: var(--line); }
.line-swatch.speech-active { background: var(--accent); }
.line-swatch.control { background: #c0392b; }
.line-swatch.ringing { background: var(--signal); }

.connection-lines {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
  pointer-events: none;
}

.connection-line {
  stroke-width: 2;
  fill: none;
  transition: stroke 200ms ease;
}

.connection-line.line-idle { stroke: var(--line); }
.connection-line.line-speech-active { stroke: var(--accent); }
.connection-line.line-control {
  stroke: #c0392b;
  stroke-dasharray: 6 4;
  animation: connection-signal-flow 900ms linear infinite;
}
.connection-line.line-ringing {
  stroke: var(--signal);
  stroke-width: 3;
  stroke-dasharray: 5 5;
  animation: connection-signal-flow 500ms linear infinite;
}

@keyframes connection-signal-flow {
  to { stroke-dashoffset: -20; }
}

/* ---------- Equipment diagram ---------- */

.equipment-diagram {
  position: relative;
  z-index: 0;
  display: grid;
  /* Subscribers (calling AND called together, 2 sub-columns) | Registers | Translators |
     Senders | Markers | Junctors | Crossbar (both stages side by side, track is half its
     original 3.6fr width -- each stage frame renders at half its original size) | Trunks.
     No trailing "called" track any more -- both subscribers sit together at the left (see
     CONNECTION_STAGES's comment in app.js for why a right-side "far end" stopped making
     sense for intra-office calls). */
  grid-template-columns: 3.6fr 0.85fr 0.85fr 0.85fr 0.85fr 0.85fr 1.8fr 0.9fr;
  gap: 10px;
  align-items: start;
  min-width: 1650px;
}

/* A terminating exchange never allocates its own register/translator/sender for a call it
   is only receiving (see compute_exchange_role() in telephonex/network.py) -- hide those
   three columns entirely rather than show them idle, and collapse their grid tracks so the
   remaining columns re-flow to fill the space. */
.equipment-diagram.role-terminating {
  grid-template-columns: 3.6fr 0.85fr 1.8fr 0.9fr;
}

.equipment-diagram.role-terminating [data-role="registers"],
.equipment-diagram.role-terminating [data-role="translators"],
.equipment-diagram.role-terminating [data-role="senders"] {
  display: none;
}

/* The calling-subscriber side of the combined stack has nothing to show on a terminating
   exchange (no calling telephone, no calling line circuit/line finder here) -- replaced by
   the incoming-trunk banner above instead. */
.equipment-diagram.role-terminating .calling-only {
  display: none;
}

/* A pure intra-office call (both parties on this exchange) never allocates a real Trunk --
   there's nothing at the far end of that column to show, so it's dropped and the grid
   collapses to fill the space (see ORIGINATING_LOCAL_STAGES in app.js). */
.equipment-diagram.role-originating-local {
  grid-template-columns: 3.6fr 0.85fr 0.85fr 0.85fr 0.85fr 0.85fr 1.8fr;
}

.equipment-diagram.role-originating-local [data-role="trunks"] {
  display: none;
}

.incoming-trunk-banner {
  margin: 0 0 8px;
  padding: 6px 10px;
  border: 1px solid var(--blue);
  border-left: 4px solid var(--blue);
  border-radius: 6px;
  background: var(--panel-raised);
  color: var(--blue);
  font-size: 0.7rem;
  font-weight: 700;
}

.incoming-trunk-banner.hidden {
  display: none;
}

.diagram-stack,
.diagram-column {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

/* Calling/Called Subscriber stacks split into a subscriber-equipment sub-column (the
   customer's own telephone/subscriber record) and an exchange-equipment sub-column (line
   circuit, line finder -- hardware the exchange itself owns) instead of one flat vertical
   list, so it's visually clear which side of the demarcation point each card is on. */
.split-stack-row {
  display: flex;
  gap: 10px;
  align-items: start;
}

.split-stack-column {
  display: flex;
  flex-direction: column;
  gap: 6px;
  flex: 1 1 0;
  min-width: 0;
}

/* One Telephone card per call this exchange has originated/received, oldest at the top --
   scrolls internally (max-height + overflow-y) so a long-running exchange's call history
   never grows the page itself, matching every other bounded-height scrolling list in this
   diagram (.component-list, .cabinet-view, etc). */
.telephone-history {
  display: flex;
  flex-direction: column;
  gap: 6px;
  /* Calling and called now stack in the same column (see callingStack's combined markup),
     so each gets a shorter cap than the old single-list 260px -- otherwise the two
     together could run noticeably taller than every other column in the diagram. */
  max-height: 180px;
  overflow-y: auto;
}

.equipment-card.telephone-idle-card {
  /* .equipment-card qualifier deliberately raises specificity above the later
     ".equipment-card { border: ...; background: ... }" base rule (equal specificity would
     otherwise let source order pick that one). */
  border-color: var(--accent);
  background: rgba(41, 177, 127, 0.12);
}

.stack-heading,
.column-heading {
  color: var(--muted);
  font-size: 0.66rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.column-heading {
  padding-bottom: 4px;
  border-bottom: 1px solid var(--line);
}

.component-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-height: 420px;
  overflow-y: auto;
}

.column-footer {
  color: var(--muted);
  font-size: 0.68rem;
  text-align: center;
}

.equipment-card {
  padding: 8px 10px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--panel-raised);
  cursor: pointer;
  transition: border-color 120ms ease, background 120ms ease;
}

.equipment-card:hover {
  border-color: var(--accent);
}

.equipment-card.selected {
  border-color: var(--blue);
  box-shadow: 0 0 0 1px var(--blue);
}

.equipment-card.busy {
  border-color: var(--accent);
  background: #1d2a27;
}

.equipment-card.state-ringing,
.equipment-card.state-searching,
.equipment-card.state-selecting,
.equipment-card.state-collectingdigits {
  box-shadow: inset 3px 0 0 var(--signal);
}

/* Release 0.7.2 (Phase 10): a connected trunk gets a moving stripe across its top edge --
   traffic actually flowing across the circuit -- instead of just the flat "busy" tint every
   other equipment card gets. */
.trunk-card.busy {
  position: relative;
  overflow: hidden;
}

.trunk-card.busy::before {
  content: "";
  position: absolute;
  top: 0;
  left: -40%;
  width: 40%;
  height: 3px;
  background: var(--accent);
  animation: trunk-traffic-flow 1.1s linear infinite;
}

@keyframes trunk-traffic-flow {
  from { left: -40%; }
  to { left: 100%; }
}

.equipment-card.state-offhook {
  box-shadow: inset 3px 0 0 var(--blue);
}

.equipment-card.state-connected,
.equipment-card.state-operated {
  box-shadow: inset 3px 0 0 var(--accent);
}

.equipment-card.state-fault,
.equipment-card.state-congested,
.equipment-card.state-busy {
  box-shadow: inset 3px 0 0 var(--danger);
}

.equipment-card .card-id {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  font-weight: 800;
  font-size: 0.78rem;
}

.equipment-card .card-state {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 0.68rem;
  font-weight: 700;
  color: var(--muted);
}

.equipment-card .card-state .dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
}

.equipment-card .card-detail {
  margin-top: 4px;
  color: var(--muted);
  font-size: 0.68rem;
  line-height: 1.5;
  overflow-wrap: anywhere;
}

.progress-track,
.finder-track {
  position: relative;
  height: 5px;
  margin-top: 8px;
  border-radius: 999px;
  background: #0f1515;
  overflow: hidden;
}

.progress-track span {
  display: block;
  height: 100%;
  border-radius: inherit;
  background: var(--accent);
  transition: width 180ms ease;
}

.progress-track.amber span { background: var(--signal); }
.progress-track.blue span { background: var(--blue); }

.finder-track span {
  position: absolute;
  top: 0;
  width: 18px;
  height: 100%;
  border-radius: inherit;
  background: var(--signal);
  box-shadow: 0 0 10px rgba(215, 161, 45, 0.65);
  transform: translateX(-50%);
  transition: left 220ms ease;
}

.equipment-card.active-pulse {
  animation: pulse-border 900ms ease-in-out infinite alternate;
}

@keyframes pulse-border {
  from { box-shadow: 0 0 0 1px rgba(47, 184, 166, 0.25); }
  to { box-shadow: 0 0 0 3px rgba(47, 184, 166, 0.55); }
}

.equipment-card.release-flash,
.crosspoint.release-flash {
  animation: release-flash 900ms ease-out;
}

@keyframes release-flash {
  0% { box-shadow: 0 0 0 3px rgba(212, 87, 79, 0.85); background: rgba(212, 87, 79, 0.22); }
  100% { box-shadow: 0 0 0 0 rgba(212, 87, 79, 0); }
}

.equipment-card.activity-flash,
.crosspoint.activity-flash {
  animation: activity-flash 700ms ease-out;
}

@keyframes activity-flash {
  0% { box-shadow: 0 0 12px 3px rgba(47, 184, 166, 0.75); background: rgba(47, 184, 166, 0.18); }
  100% { box-shadow: 0 0 0 0 rgba(47, 184, 166, 0); }
}

/* General "glow" for any hardware currently holding a call, per the Idle -> Searching ->
   Allocated -> Busy -> Released -> Idle lifecycle -- movement/colour alone can be missed,
   an ambient glow makes "this is busy right now" readable at a glance. */
.equipment-card.busy {
  box-shadow: 0 0 10px rgba(47, 184, 166, 0.35);
}

.equipment-card.state-searching,
.equipment-card.state-selecting,
.equipment-card.state-collectingdigits,
.equipment-card.state-ringing {
  animation: searching-glow 1.4s ease-in-out infinite;
}

@keyframes searching-glow {
  0%, 100% { box-shadow: inset 3px 0 0 var(--signal), 0 0 4px rgba(215, 161, 45, 0.25); }
  50% { box-shadow: inset 3px 0 0 var(--signal), 0 0 14px rgba(215, 161, 45, 0.65); }
}

.subscriber-card {
  min-height: 64px;
}

.telephone-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  margin-right: 6px;
  border-radius: 50%;
  background: var(--bg);
  border: 1px solid var(--line);
}

.telephone-icon.ringing {
  animation: ring-shake 400ms ease-in-out infinite;
  border-color: var(--signal);
}

@keyframes ring-shake {
  0%, 100% { transform: rotate(0deg); }
  25% { transform: rotate(-8deg); }
  75% { transform: rotate(8deg); }
}

/* ---------- Crossbar ---------- */

.crossbar-column {
  min-width: 0;
}

.crossbar-stage-pair {
  /* Stage 1 (Line Link Frame) and Stage 2 (Trunk Link Frame) side by side on one row --
     the crossbar-column grid track itself (see .equipment-diagram) is what's sized down
     to half its original width, so each frame renders at half its original size without
     leaving dead space in the row. */
  display: flex;
  gap: 10px;
  align-items: start;
}

.crossbar-stage-pair .crossbar-frame {
  /* Crosspoint cell size is purely a function of this container's rendered width
     (grid-template-columns: repeat(N, 1fr), see renderCrossbarStage()) -- flex:1 splits
     the already-halved column evenly between the two stages. */
  flex: 1;
  min-width: 0;
}

.crossbar-frame {
  padding: 8px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--panel-raised);
}

.crossbar-frame-label {
  margin-bottom: 6px;
  color: var(--blue);
  font-size: 0.7rem;
  font-weight: 800;
  text-align: center;
}

.crossbar-grid {
  display: grid;
  gap: 2px;
  aspect-ratio: 1;
}

.crosspoint {
  min-width: 0;
  border-radius: 2px;
  background: var(--idle);
  opacity: 0.55;
  transition: opacity 150ms ease, background 150ms ease, box-shadow 150ms ease;
}

.crosspoint.reserved { background: var(--signal); opacity: 0.7; }
.crosspoint.operated { background: var(--accent); opacity: 1; box-shadow: 0 0 6px rgba(47, 184, 166, 0.7); }
.crosspoint.selected { background: var(--blue); opacity: 1; animation: cross-blink 700ms ease-in-out infinite alternate; }
.crosspoint.fault { background: var(--danger); opacity: 1; }

@keyframes cross-blink {
  from { opacity: 0.5; }
  to { opacity: 1; }
}

.crossbar-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 8px;
  color: var(--muted);
  font-size: 0.64rem;
}

.crossbar-legend .swatch {
  display: inline-block;
  width: 9px;
  height: 9px;
  margin-right: 4px;
  border-radius: 2px;
  vertical-align: middle;
}

.swatch.idle { background: var(--idle); }
.swatch.reserved { background: var(--signal); }
.swatch.operated { background: var(--accent); }
.swatch.selected { background: var(--blue); }
.swatch.fault { background: var(--danger); }

/* ---------- Timeline ---------- */

.timeline-meta {
  color: var(--muted);
  font-size: 0.7rem;
}

.call-timeline {
  display: flex;
  gap: 0;
  padding: 10px 4px;
  overflow-x: auto;
}

.call-timeline.split {
  flex-direction: column;
}

/* Release 0.7.2 (Phase 11): an interoffice call's timeline splits into one row per
   exchange -- the origin's own off-hook-through-conversation chain, and the destination's
   separate incoming-trunk-through-conversation chain -- rather than one merged strip, since
   they're genuinely two different Call objects on two different controllers. */
.timeline-exchange-row + .timeline-exchange-row {
  margin-top: 4px;
  border-top: 1px dashed var(--line);
  padding-top: 4px;
}

.timeline-exchange-label {
  font-size: 0.68rem;
  font-weight: 700;
  color: var(--muted);
  padding: 4px 4px 0;
}

.timeline-exchange-row .call-timeline {
  padding: 4px;
}

.timeline-event {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  min-width: 120px;
  padding: 0 6px;
  cursor: pointer;
  text-align: center;
}

.timeline-event::before {
  content: "";
  position: absolute;
  top: 15px;
  left: -50%;
  width: 100%;
  height: 2px;
  background: var(--line);
  z-index: 0;
}

.timeline-event:first-child::before {
  display: none;
}

.timeline-event .dot {
  position: relative;
  z-index: 1;
  width: 12px;
  height: 12px;
  margin-bottom: 6px;
  border-radius: 50%;
  background: var(--panel-raised);
  border: 2px solid var(--accent);
}

.timeline-event .time {
  color: var(--muted);
  font-size: 0.66rem;
}

.timeline-event .label {
  font-size: 0.7rem;
  font-weight: 700;
}

.timeline-event.pending {
  opacity: 0.42;
}

.timeline-event.complete .dot {
  background: var(--accent);
}

.timeline-event.pending .dot {
  border-color: var(--line);
}

.timeline-event.pending .label {
  color: var(--muted);
}

.timeline-event.selected .label {
  color: var(--blue);
}

.timeline-event.selected .dot {
  background: var(--blue);
}

.timeline-event.current .dot {
  background: var(--signal);
  border-color: var(--signal);
  box-shadow: 0 0 0 4px rgba(215, 161, 45, 0.28);
  animation: current-stage-pulse 1.1s ease-in-out infinite;
}

.timeline-event.current .label {
  color: var(--signal);
}

@keyframes current-stage-pulse {
  0%, 100% { box-shadow: 0 0 0 3px rgba(215, 161, 45, 0.22); }
  50% { box-shadow: 0 0 0 7px rgba(215, 161, 45, 0.34); }
}

/* ---------- Event log ---------- */

.eventlog-filters {
  display: grid;
  grid-template-columns: repeat(4, 1fr) auto auto;
  gap: 6px;
  margin-bottom: 8px;
}

.event-log {
  display: flex;
  flex-direction: column;
  gap: 4px;
  flex: 1;
  overflow-y: auto;
  list-style: none;
}

.eventlog-pagination {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 10px;
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px solid var(--line);
  font-size: 0.7rem;
  color: var(--muted);
}

.eventlog-pagination label {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-right: auto;
}

.eventlog-pagination select {
  padding: 3px 6px;
}

.event-log li {
  display: grid;
  grid-template-columns: 72px minmax(120px, 160px) minmax(100px, 140px) minmax(82px, 110px) 1fr 78px;
  gap: 8px;
  align-items: start;
  padding: 7px 0;
  border-top: 1px solid var(--line);
  color: var(--muted);
  font-size: 0.72rem;
  cursor: pointer;
}

.event-log li:hover {
  color: var(--ink);
}

.event-log li.active {
  color: var(--ink);
  background: rgba(47, 184, 166, 0.08);
}

.event-log li strong {
  color: var(--ink);
  overflow-wrap: anywhere;
}

.severity {
  justify-self: end;
  font-size: 0.64rem;
  font-weight: 800;
  text-transform: uppercase;
}

.severity-info { color: var(--blue); }
.severity-notice { color: var(--signal); }
.severity-error { color: var(--danger); }

/* ---------- Utilisation table ---------- */

.table-scroll {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
}

/* ---------- Release 0.9 (Phase 5): equipment utilisation heat-map ---------- */

.heatmap-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 12px;
  margin-bottom: 6px;
  font-size: 0.64rem;
  color: var(--muted);
}

.heatmap-swatch {
  display: inline-block;
  width: 9px;
  height: 9px;
  border-radius: 2px;
  margin-right: 3px;
  vertical-align: middle;
}

.utilisation-heatmap {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-bottom: 10px;
  max-height: 160px;
  overflow-y: auto;
}

.heatmap-row {
  display: flex;
  align-items: center;
  gap: 8px;
}

.heatmap-row-label {
  flex: 0 0 130px;
  font-size: 0.66rem;
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.heatmap-cells {
  display: flex;
  flex-wrap: wrap;
  gap: 2px;
}

.heatmap-cell {
  width: 12px;
  height: 12px;
  border-radius: 2px;
  cursor: pointer;
  transition: transform 100ms ease;
}

.heatmap-cell:hover {
  transform: scale(1.3);
}

.utilisation-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.72rem;
}

.utilisation-table th {
  position: sticky;
  top: 0;
  padding: 4px 6px;
  color: var(--muted);
  font-size: 0.64rem;
  text-align: left;
  text-transform: uppercase;
  background: var(--panel);
  border-bottom: 1px solid var(--line);
}

.utilisation-table td {
  padding: 4px 6px;
  border-bottom: 1px solid var(--line);
}

.util-bar {
  position: relative;
  height: 6px;
  border-radius: 3px;
  background: var(--bg);
  overflow: hidden;
}

.util-bar-fill {
  height: 100%;
  background: var(--accent);
}

/* ---------- Call path ---------- */

.call-path {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.call-path-step {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 6px 8px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--panel-raised);
  font-size: 0.72rem;
}

.call-path-step .role {
  color: var(--muted);
  font-size: 0.64rem;
  text-transform: uppercase;
}

.call-path-step.empty {
  opacity: 0.4;
}

.call-path-step.call-path-link {
  border-style: dashed;
  border-color: var(--muted);
  background: transparent;
  justify-content: center;
  text-align: center;
}

.call-path-step.call-path-link.active {
  border-color: var(--accent);
  color: var(--accent);
}

.call-path-step.call-path-routing {
  background: var(--bg);
  font-size: 0.68rem;
}

/* ---------- Controls ---------- */

.control-strip {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 8px;
}

.control-strip.secondary {
  align-items: center;
}

.call-duration-control {
  display: flex;
  align-items: center;
  gap: 6px;
  color: var(--muted);
  font-size: 0.72rem;
  white-space: nowrap;
}

.subscriber-picker {
  display: flex;
  flex-direction: column;
  gap: 3px;
  flex: 1 1 220px;
  color: var(--muted);
  font-size: 0.66rem;
  font-weight: 800;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.control-strip .subscriber-picker select {
  /* Extra .control-strip qualifier deliberately raises specificity above the later
     ".control-strip select" rule below (equal specificity would otherwise let source
     order pick that one) -- inside .subscriber-picker's column-direction flex container,
     that rule's flex: 1 1 190px grows the select along the vertical (main) axis instead
     of the horizontal one, stretching it to fill the whole row's height. */
  flex: 0 0 auto;
  width: 100%;
  font-size: 0.76rem;
  font-weight: 400;
  text-transform: none;
  letter-spacing: normal;
}

.call-arrow {
  display: flex;
  align-items: center;
  color: var(--accent);
  font-size: 1.1rem;
  padding: 0 2px;
}

.call-duration-control input {
  flex: 0 0 64px;
  width: 64px;
}

.control-strip .btn {
  flex: 1 1 150px;
}

.control-strip select,
.control-strip input {
  flex: 1 1 190px;
}

.fault-group select {
  flex: 1 1 180px;
}

.fault-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-height: 140px;
  overflow-y: auto;
  list-style: none;
}

.fault-list li {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 6px 8px;
  border: 1px solid var(--danger);
  border-radius: 6px;
  background: rgba(212, 87, 79, 0.1);
  font-size: 0.7rem;
}

/* ---------- Call queue / traffic controls ---------- */

.traffic-controls {
  display: flex;
  align-items: center;
  gap: 6px;
}

.traffic-controls.hidden {
  display: none;
}

.traffic-controls input {
  width: 110px;
}

.traffic-status {
  padding: 3px 8px;
  border: 1px solid var(--line);
  border-radius: 6px;
  color: var(--muted);
  font-size: 0.66rem;
  font-weight: 800;
  text-transform: uppercase;
  white-space: nowrap;
}

.traffic-status.running {
  border-color: var(--accent);
  color: var(--accent);
}

.day-cycle-toggle {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 0.68rem;
  font-weight: 700;
  color: var(--muted);
  white-space: nowrap;
  cursor: pointer;
}

.day-cycle-status {
  padding: 3px 8px;
  border: 1px solid var(--blue);
  border-radius: 6px;
  color: var(--blue);
  font-size: 0.66rem;
  font-weight: 700;
  white-space: nowrap;
}

.day-cycle-status.hidden {
  display: none;
}

.call-queue-grid {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 8px;
  flex: 1;
  min-height: 0;
}

.call-queue-bucket {
  display: flex;
  flex-direction: column;
  min-height: 0;
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 6px;
  background: var(--bg);
}

.call-queue-bucket[data-bucket="blocked"],
.call-queue-bucket[data-bucket="failed"] {
  border-color: rgba(212, 87, 79, 0.4);
}

.bucket-heading {
  margin-bottom: 4px;
  color: var(--muted);
  font-size: 0.64rem;
  font-weight: 800;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

/* ---------- Multi-exchange network ---------- */

.network-panel { grid-area: network; }
.trunkview-panel { grid-area: trunkview; }

.trunk-call-outcomes {
  display: flex;
  gap: 18px;
  margin-bottom: 8px;
  font-size: 0.72rem;
  color: var(--muted);
}

.trunk-call-outcomes strong {
  margin-left: 4px;
  color: var(--ink);
}

.network-controls {
  display: flex;
  align-items: center;
  gap: 6px;
}

.network-diagram {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  align-items: start;
  gap: 14px;
  margin-bottom: 14px;
}

.network-exchange-card {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 10px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg);
}

.network-exchange-heading {
  color: var(--muted);
  font-size: 0.66rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.network-exchange-identity {
  color: var(--accent);
  font-size: 0.72rem;
  font-weight: 700;
}

.network-exchange-calls {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-top: 4px;
}

/* ---------- Add-exchange form / network call controls ---------- */

.add-exchange-form,
.network-call-controls {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  margin-bottom: 10px;
}

.add-exchange-form.hidden {
  display: none;
}

.add-exchange-form input,
.network-call-controls select {
  min-width: 0;
}

.form-error {
  color: var(--danger);
  font-size: 0.68rem;
}

/* ---------- Active inter-exchange call links ---------- */

.network-links {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.network-link-row {
  padding: 6px 8px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--panel-raised);
  font-size: 0.72rem;
}

.network-link-row.active {
  border-color: var(--accent);
  color: var(--accent);
}

/* ---------- Calls list ---------- */

.calls-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  overflow-y: auto;
}

.call-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 8px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--panel-raised);
  cursor: pointer;
  font-size: 0.72rem;
}

.call-row:hover {
  border-color: var(--accent);
}

.call-row.selected {
  border-color: var(--blue);
  box-shadow: 0 0 0 1px var(--blue);
}

.call-row .call-status {
  font-size: 0.64rem;
  font-weight: 800;
  text-transform: uppercase;
}

.call-row .call-duration {
  font-size: 0.64rem;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
}

/* ---------- Inspector ---------- */

.component-inspector .muted {
  color: var(--muted);
}

.inspector-title {
  margin-bottom: 8px;
  font-size: 0.95rem;
  font-weight: 800;
  color: var(--accent);
}

.inspector-section {
  margin-bottom: 10px;
}

.inspector-section h4 {
  margin-bottom: 6px;
  color: var(--muted);
  font-size: 0.64rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.inspector-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px 10px;
  font-size: 0.72rem;
}

.inspector-grid .k {
  color: var(--muted);
}

.inspector-grid .v {
  font-weight: 700;
  text-align: right;
  overflow-wrap: anywhere;
}

.inspector-note {
  color: var(--ink);
  font-size: 0.72rem;
  line-height: 1.55;
}

.inspector-util {
  height: 9px;
}

/* ---------- Status bar ---------- */

.statusbar {
  display: flex;
  gap: 18px;
  padding: 6px 18px;
  border-top: 1px solid var(--line);
  background: var(--panel);
  color: var(--muted);
  font-size: 0.68rem;
}

.statusbar strong {
  color: var(--ink);
}

.statusbar-right {
  margin-left: auto;
}

/* ---------- Responsive ---------- */

@media (max-width: 1100px) {
  .console-grid {
    grid-template-columns: 1fr;
    grid-template-areas:
      "controls"
      "lessons"
      "timeline"
      "diagram"
      "calls"
      "network"
      "trunkview"
      "inspector"
      "callpath"
      "overview"
      "status"
      "eventlog";
  }

  .inspector-panel,
  .callpath-panel,
  .overview-panel,
  .status-panel {
    max-height: none;
  }
  .network-diagram {
    grid-template-columns: 1fr;
  }

  .toolbar {
    flex-wrap: wrap;
  }

  .exchange-body {
    flex-direction: column;
  }

  .exchange-sidebar {
    flex: 1 1 auto;
    width: 100%;
  }

  .diagram-tabs.vertical {
    flex-direction: row;
  }
}
