/* Yagura — Infra Map. Static viewer styles. No build step. */

:root {
  /* Base surfaces — dark, dense, data-first (mirrors the placeholder bg). */
  --bg:           #0e1116;
  --surface:      #161b22;
  --surface-2:    #1c232d;
  --surface-3:    #232c38;
  --border:       #2a323d;
  --border-soft:  #222a34;

  /* Ink */
  --ink:          #e6edf3;
  --ink-dim:      #9aa6b2;
  --ink-faint:    #6b7682;

  /* Brand red — reserved for brand mark + destructive/unhealthy only. */
  --red:          #d6453f;
  --red-soft:     #3a1d1f;

  /* Live status palette (overlay over the cartography). */
  --st-healthy:   #2ea043;
  --st-unhealthy: #d6453f;
  --st-present:   #d4a017; /* present but no health signal (running, no HC) */
  --st-absent:    #6b7682; /* declared in manifest, not on the daemon */
  --st-ephemeral: #8b5cf6; /* expected-optional ephemeral class */
  --st-runonce:   #3b82c4; /* run-once init container, exited(0) by design */

  /* Cluster tints — desaturated for dark bg, echo the poster palette
     (EsportGate blue, grid green, db amber, grid-stack purple…). */
  --cl-edge:      #2b3a2f; /* public edge — muted green */
  --cl-gateway:   #1e3a5f; /* gateway — blue (EsportGate hub) */
  --cl-backends:  #233140; /* application backends — slate blue */
  --cl-databases: #3a3322; /* databases — amber */
  --cl-grid:      #2f2942; /* grid private stack — purple */
  --cl-infra:     #2a3338; /* infra / introspection — teal-grey */

  --accent:       #4a9eff; /* edges / interactive accent (gateway blue) */
  --radius:       8px;
  --radius-lg:    12px;
  --font: "Inter", "Segoe UI", system-ui, -apple-system, sans-serif;
  --mono: "SFMono-Regular", "JetBrains Mono", "Consolas", ui-monospace, monospace;

  /* Absolute floor: no text below 12px anywhere (workspace rule). */
  --fs-min: 12px;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  height: 100%;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font);
  font-size: 14px;
  -webkit-font-smoothing: antialiased;
}

button { font-family: inherit; }

/* ---------- App shell ---------- */
.app {
  display: grid;
  grid-template-rows: auto 1fr;
  height: 100%;
}

.topbar {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 10px 18px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  z-index: 10;
}

.brand {
  display: flex;
  align-items: baseline;
  gap: 8px;
}
.brand-mark {
  width: 9px; height: 9px; border-radius: 2px;
  background: var(--red);
  transform: translateY(-1px);
}
.brand-name { font-weight: 700; letter-spacing: 0.2px; }
.brand-sub { font-size: var(--fs-min); color: var(--ink-faint); }

.topbar-spacer { flex: 1; }

.legend-inline {
  display: flex;
  align-items: center;
  gap: 14px;
  font-size: var(--fs-min);
  color: var(--ink-dim);
  flex-wrap: wrap;
}
.legend-inline .lg { display: flex; align-items: center; gap: 5px; }
.dot { width: 9px; height: 9px; border-radius: 50%; flex: none; }
.dot.healthy   { background: var(--st-healthy); }
.dot.unhealthy { background: var(--st-unhealthy); }
.dot.present   { background: var(--st-present); }
.dot.absent    { background: var(--st-absent); }
.dot.ephemeral { background: var(--st-ephemeral); }
.dot.runonce   { background: var(--st-runonce); }

.btn {
  background: var(--surface-2);
  color: var(--ink);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 6px 12px;
  font-size: 13px;
  cursor: pointer;
  transition: background .12s, border-color .12s;
}
.btn:hover { background: var(--surface-3); border-color: #3a4654; }
.btn:disabled { opacity: .5; cursor: default; }
.btn-icon { display: inline-flex; align-items: center; gap: 6px; }

.updated { font-size: var(--fs-min); color: var(--ink-faint); }

/* ---------- Main area ---------- */
.main {
  position: relative;
  overflow: hidden;
  min-height: 0;
}

/* The cartography canvas host */
.map-wrap {
  position: absolute;
  inset: 0;
  overflow: auto;
}
.map-svg { display: block; }

/* node groups are SVG, but tooltips/badges are HTML overlays handled inline */

/* ---------- Side panel ---------- */
.panel {
  position: absolute;
  top: 0; right: 0; bottom: 0;
  width: 420px;
  max-width: 90vw;
  background: var(--surface);
  border-left: 1px solid var(--border);
  box-shadow: -8px 0 24px rgba(0,0,0,.35);
  display: flex;
  flex-direction: column;
  transform: translateX(100%);
  transition: transform .18s ease;
  z-index: 20;
}
.panel.open { transform: translateX(0); }

.panel-head {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 14px 16px;
  border-bottom: 1px solid var(--border);
}
.panel-title { font-weight: 600; font-size: 15px; word-break: break-all; }
.panel-sub { font-size: var(--fs-min); color: var(--ink-dim); margin-top: 3px; }
.panel-close {
  margin-left: auto;
  background: none; border: none; color: var(--ink-dim);
  font-size: 20px; line-height: 1; cursor: pointer; padding: 0 4px;
}
.panel-close:hover { color: var(--ink); }

.panel-body { overflow-y: auto; padding: 14px 16px; flex: 1; }

.status-pill {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: var(--fs-min); font-weight: 600;
  padding: 3px 9px; border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--surface-2);
}

.kv { display: grid; grid-template-columns: 110px 1fr; gap: 4px 10px; margin: 14px 0; }
.kv dt { color: var(--ink-faint); font-size: var(--fs-min); }
.kv dd { margin: 0; font-size: 13px; word-break: break-word; }
.kv dd.mono { font-family: var(--mono); font-size: var(--fs-min); }

.section-title {
  font-size: var(--fs-min);
  text-transform: uppercase;
  letter-spacing: .6px;
  color: var(--ink-faint);
  margin: 18px 0 8px;
  display: flex; align-items: center; gap: 8px;
}
.section-title::after { content: ""; flex: 1; height: 1px; background: var(--border-soft); }

/* stat bars */
.stat-row { margin: 10px 0; }
.stat-row .stat-label { display: flex; justify-content: space-between; font-size: var(--fs-min); margin-bottom: 4px; }
.stat-label .v { color: var(--ink); font-family: var(--mono); }
.stat-label .k { color: var(--ink-dim); }
.bar { height: 7px; border-radius: 4px; background: var(--surface-3); overflow: hidden; }
.bar > i { display: block; height: 100%; background: var(--accent); border-radius: 4px; transition: width .3s; }
.bar > i.warn { background: var(--st-present); }
.bar > i.crit { background: var(--st-unhealthy); }

.net-list { display: flex; flex-wrap: wrap; gap: 6px; }
.net-tag {
  font-size: var(--fs-min); font-family: var(--mono);
  padding: 2px 8px; border-radius: 999px;
  background: var(--surface-2); border: 1px solid var(--border); color: var(--ink-dim);
}

/* logs drawer */
.logs-controls { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; flex-wrap: wrap; }
.logs-controls label { font-size: var(--fs-min); color: var(--ink-dim); }
.logs-controls input[type=number] {
  width: 70px; background: var(--surface-2); color: var(--ink);
  border: 1px solid var(--border); border-radius: 5px; padding: 4px 6px; font-size: var(--fs-min);
}
.follow-toggle { display: inline-flex; align-items: center; gap: 6px; cursor: pointer; }
.logs {
  background: #0a0d11;
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 10px;
  font-family: var(--mono);
  font-size: var(--fs-min);
  line-height: 1.5;
  white-space: pre-wrap;
  word-break: break-word;
  max-height: 320px;
  overflow-y: auto;
  color: #c7d0d9;
}
.logs .ln { display: block; }
.logs-empty { color: var(--ink-faint); }
.follow-live { color: var(--st-healthy); }
.follow-live::before { content: "● "; }

/* ---------- Overlay states (loading / 403 / error) ---------- */
.overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--bg);
  z-index: 30;
  padding: 24px;
}
.overlay-card {
  max-width: 460px;
  text-align: center;
}
.overlay-card h2 { font-size: 18px; margin: 0 0 8px; }
.overlay-card p { color: var(--ink-dim); font-size: 13px; line-height: 1.6; margin: 0 0 18px; }
.overlay-icon {
  width: 48px; height: 48px; border-radius: 12px;
  display: inline-flex; align-items: center; justify-content: center;
  margin-bottom: 14px; font-size: 24px;
}
.overlay-icon.lock  { background: var(--surface-2); border: 1px solid var(--border); }
.overlay-icon.error { background: var(--red-soft); border: 1px solid #5a2b2d; }

/* skeleton */
.skeleton-map { position: absolute; inset: 0; padding: 40px; }
.sk-cluster {
  border: 1px dashed var(--border);
  border-radius: var(--radius-lg);
  margin: 0 auto 22px;
  max-width: 900px;
  height: 92px;
  background: linear-gradient(90deg, var(--surface) 25%, var(--surface-2) 37%, var(--surface) 63%);
  background-size: 400% 100%;
  animation: shimmer 1.4s ease infinite;
}
.sk-cluster:nth-child(2) { height: 150px; }
.sk-cluster:nth-child(3) { height: 130px; }
@keyframes shimmer { 0% { background-position: 100% 0; } 100% { background-position: -100% 0; } }

.spinner {
  width: 28px; height: 28px;
  border: 3px solid var(--surface-3);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin .8s linear infinite;
  margin: 0 auto 14px;
}
@keyframes spin { to { transform: rotate(360deg); } }

.hidden { display: none !important; }

/* ---------- SVG node styling helpers (applied via classes on <g>) ---------- */
.node-box { cursor: pointer; }
.node-box .node-rect { transition: stroke .12s, filter .12s; }
.node-box:hover .node-rect { stroke: var(--accent); filter: brightness(1.12); }
.node-box.selected .node-rect { stroke: var(--accent); stroke-width: 2; }
.node-label { font-size: var(--fs-min); fill: var(--ink); pointer-events: none; }
.node-meta  { font-size: 11px; fill: var(--ink-dim); pointer-events: none; }
.node-port  { font-family: var(--mono); }
.cluster-label { font-size: var(--fs-min); fill: var(--ink-dim); text-transform: uppercase; letter-spacing: .5px; pointer-events: none; }
.edge-line { fill: none; stroke: var(--accent); stroke-opacity: .55; }
.edge-line.dim { stroke: var(--ink-faint); stroke-opacity: .35; stroke-dasharray: 4 4; }
.edge-line.local-db { stroke: var(--st-databases, #d4a017); stroke-opacity: .4; }
.edge-label { font-size: 11px; fill: var(--ink-faint); pointer-events: none; }

/* node-meta is 11px which is below the 12px floor — bump to floor.
   The rule above for --node-meta size is overridden here intentionally. */
.node-meta, .edge-label { font-size: var(--fs-min); }

.health-ring { pointer-events: none; }

.zoom-hint {
  position: absolute;
  left: 14px; bottom: 12px;
  font-size: var(--fs-min);
  color: var(--ink-faint);
  background: rgba(14,17,22,.7);
  padding: 4px 10px;
  border-radius: 6px;
  pointer-events: none;
}

.invariant-banner {
  position: absolute;
  left: 14px; bottom: 40px;
  display: flex; flex-direction: column; gap: 6px;
  z-index: 5;
  max-width: 320px;
}
.invariant-banner .inv-head {
  font-size: var(--fs-min); text-transform: uppercase; letter-spacing: .6px;
  color: var(--ink-faint); margin-bottom: 2px;
}
.inv-chip {
  font-size: var(--fs-min);
  padding: 6px 10px;
  border-radius: 6px;
  border: 1px solid var(--border);
  background: rgba(22,27,34,.92);
  backdrop-filter: blur(2px);
  display: flex; align-items: center; gap: 8px;
  line-height: 1.35;
}
.inv-chip.ok   { border-color: #245c30; }
.inv-chip.fail { border-color: #5a2b2d; background: var(--red-soft); }
.inv-chip .inv-dot { width: 8px; height: 8px; border-radius: 50%; flex: none; }
.inv-chip.ok   .inv-dot { background: var(--st-healthy); }
.inv-chip.fail .inv-dot { background: var(--st-unhealthy); }
.inv-chip .inv-id { font-family: var(--mono); color: var(--ink-dim); }
