:root {
  --bg: #14171c;
  --panel: #1d222a;
  --panel-2: #252b35;
  --ink: #e6e9ee;
  --dim: #8b94a3;
  --accent: #4f9dff;
  --ok: #3fb950;
  --warn: #e5534b;
  --busy: #b9912c;
  --border: #2e353f;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font: 14px/1.45 ui-sans-serif, system-ui, "Segoe UI", Roboto, sans-serif;
  background: var(--bg);
  color: var(--ink);
}

header {
  display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
  padding: 12px 20px; border-bottom: 1px solid var(--border); background: var(--panel);
  position: sticky; top: 0; z-index: 2;
}
header .add { display: flex; gap: 8px; margin-right: auto; }
h1 { font-size: 18px; margin: 0; font-weight: 600; }
h2 { font-size: 15px; margin: 0; font-weight: 600; }
h3, .log-head h2 { font-size: 12px; margin: 0 0 8px; text-transform: uppercase; letter-spacing: .06em; color: var(--dim); font-weight: 600; }
.dim { color: var(--dim); font-weight: 400; }
code { font: 12px ui-monospace, "SF Mono", Menlo, monospace; background: var(--panel-2); padding: 1px 5px; border-radius: 4px; }

.pills { display: flex; gap: 6px; flex-wrap: wrap; }
.pill {
  font-size: 12px; padding: 2px 9px; border-radius: 999px; white-space: nowrap;
  background: var(--panel-2); border: 1px solid var(--border); color: var(--dim);
}
.pill.on   { color: #fff; background: #1f6f33; border-color: #2c9446; }
.pill.busy { color: #fff; background: #8a6d1f; border-color: var(--busy); }
.pill.bad  { color: #fff; background: #7d2a26; border-color: var(--warn); }

main {
  display: grid; gap: 16px; padding: 16px 20px;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 560px), 1fr));
  align-items: start;
}
.empty { color: var(--dim); }

.card { background: var(--panel); border: 1px solid var(--border); border-radius: 12px; padding: 14px; display: flex; flex-direction: column; gap: 12px; }
.card-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; flex-wrap: wrap; }
.card-body { display: grid; grid-template-columns: auto 1fr; gap: 14px; align-items: start; }
@media (max-width: 520px) { .card-body { grid-template-columns: 1fr; } }

.screen-col { display: flex; flex-direction: column; align-items: center; gap: 8px; }
.screen-frame { padding: 10px; border-radius: 8px; background: #d8d8cf; border: 1px solid #b9b9ae; }
.screen { width: 176px; height: 264px; image-rendering: pixelated; display: block; background: #fff; }
.indicators { display: flex; gap: 6px; flex-wrap: wrap; justify-content: center; max-width: 200px; }
.ind { font-size: 11.5px; color: var(--dim); display: inline-flex; align-items: center; gap: 5px;
       padding: 1px 7px; border: 1px solid var(--border); border-radius: 999px; }
.led { width: 10px; height: 10px; border-radius: 50%; background: #333a45; display: inline-block; }
.haptic.active { color: #fff; border-color: var(--busy); background: #8a6d1f; animation: buzz .15s linear infinite alternate; }
@keyframes buzz { from { transform: translateX(-1px); } to { transform: translateX(1px); } }
.refresh.flash { animation: flash .6s ease-out; }
@keyframes flash { from { background: var(--ink); color: var(--bg); } to { background: transparent; } }
.passkey { font-size: 13px; }
.passkey b { font-size: 18px; letter-spacing: .12em; color: var(--accent); }

.controls-col { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.panel { background: var(--panel-2); border: 1px solid var(--border); border-radius: 10px; padding: 10px 12px; }
.panel .row + .row { margin-top: 8px; }
details.panel summary { cursor: pointer; color: var(--dim); font-size: 12px; text-transform: uppercase; letter-spacing: .06em; font-weight: 600; }
details.panel[open] summary { margin-bottom: 10px; }
.row { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }

button {
  font: inherit; font-size: 13px; cursor: pointer; color: #fff;
  background: var(--accent); border: none; border-radius: 6px; padding: 6px 11px;
}
button:hover { filter: brightness(1.08); }
button:active { transform: translateY(1px); }
button:disabled { opacity: .35; cursor: not-allowed; filter: none; transform: none; }
button.warn { background: var(--warn); }
button.ghost { background: transparent; border: 1px solid var(--border); color: var(--ink); }
button[hidden] { display: none; }

input[type=text], select {
  font: inherit; font-size: 13px; color: var(--ink); background: var(--bg);
  border: 1px solid var(--border); border-radius: 6px; padding: 5px 8px; min-width: 0;
}
label { color: var(--dim); display: inline-flex; gap: 5px; align-items: center; font-size: 13px; }

.btnpad { display: flex; flex-direction: column; gap: 6px; }
.btnrow { display: flex; align-items: center; gap: 6px; }
.blabel { width: 36px; color: var(--dim); font-size: 13px; }
.bbtn { background: var(--bg); border: 1px solid var(--border); color: var(--ink); padding: 4px 10px; }
.bbtn.warn { background: var(--warn); border-color: var(--warn); color: #fff; }

.hint { margin: 8px 0 0; font-size: 12px; color: var(--dim); overflow-wrap: anywhere; }
.hidden { display: none; }

.log-panel { padding: 0 20px 20px; }
.log-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; flex-wrap: wrap; }
#log {
  margin: 8px 0 0; height: 280px; overflow-y: auto; resize: vertical;
  background: #0e1116; border: 1px solid var(--border); border-radius: 8px;
  padding: 10px 12px; font: 12px/1.5 ui-monospace, "SF Mono", Menlo, monospace;
  color: #c9d1d9; white-space: pre-wrap; word-break: break-word;
}
#log span[hidden] { display: none; }
.log-tx { color: var(--accent); }
.log-rx { color: var(--ok); }
.log-evt { color: #d2a8ff; }
.log-btn { color: #e3b341; }
.log-err { color: var(--warn); }
.log-out { color: #8b949e; }

/* --- beacons ---------------------------------------------------------------- */
.peers { padding: 0 20px 16px; }
.section-title { font-size: 12px; margin: 0 0 10px; text-transform: uppercase; letter-spacing: .06em; color: var(--dim); font-weight: 600; }
.beacon-grid { display: grid; gap: 16px; grid-template-columns: repeat(auto-fill, minmax(min(100%, 360px), 1fr)); align-items: start; }
.bstate { display: grid; grid-template-columns: auto 1fr; gap: 2px 10px; margin: 0; font-size: 12.5px; }
.bstate dt { color: var(--dim); }
.bstate dd { margin: 0; overflow-wrap: anywhere; }
.log-mesh { color: #79c0ff; }
.log-console { color: #f0b37e; }
.hub-result.bad { color: var(--warn); }

/* --- terminals and wires ------------------------------------------------------ */
body { position: relative; }
:root { --mesh: #4f9dff; --ir: #e5534b; }
button.small { font-size: 12px; padding: 3px 8px; }
input[type=number] { font: inherit; font-size: 13px; color: var(--ink); background: var(--bg);
  border: 1px solid var(--border); border-radius: 6px; padding: 5px 6px; width: 76px; }
input[hidden] { display: none; }

.jacks { display: flex; gap: 6px; }
.jack {
  font-size: 11px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase;
  padding: 3px 9px 3px 20px; border-radius: 999px; position: relative; cursor: crosshair;
  background: var(--panel-2); color: var(--dim); border: 1px solid var(--border);
  touch-action: none; user-select: none;
}
.jack::before {
  content: ""; position: absolute; left: 7px; top: 50%; width: 8px; height: 8px; margin-top: -4px;
  border-radius: 50%; border: 2px solid currentColor; box-sizing: border-box;
}
.jack[data-jack="mesh"] { color: var(--mesh); }
.jack[data-jack="ir"] { color: var(--ir); }
.jack.wired::before { background: currentColor; }
.jack.armed { outline: 2px solid currentColor; outline-offset: 2px; }
.jack.can-drop { background: #1e2a3a; border-color: currentColor; animation: pulse 1s ease-in-out infinite alternate; }
@keyframes pulse { from { box-shadow: 0 0 0 0 transparent; } to { box-shadow: 0 0 0 4px rgba(79,157,255,.25); } }
.wire-hint { margin: -4px 0 12px; }

.wires { position: absolute; left: 0; top: 0; pointer-events: none; z-index: 1; overflow: visible; }
.wire { fill: none; stroke-width: 3; stroke-linecap: round; opacity: .85; }
.wire.mesh { stroke: var(--mesh); }
.wire.ir { stroke: var(--ir); stroke-dasharray: 7 6; }
.wire.temp { opacity: .6; stroke-dasharray: 4 5; }
.wire-hit { fill: none; stroke: transparent; stroke-width: 16; pointer-events: stroke; cursor: pointer; }
.wire-g:hover .wire { stroke-width: 5; opacity: 1; }
.wire-label { font: 600 12px ui-monospace, Menlo, monospace; paint-order: stroke; stroke: var(--bg); stroke-width: 4px; pointer-events: none; }
.wire-label.mesh { fill: #9cc8ff; }
.wire-label.ir { fill: #ff9a94; }

.wire-menu {
  position: absolute; z-index: 5; min-width: 200px; display: flex; flex-direction: column; gap: 4px;
  background: var(--panel); border: 1px solid var(--border); border-radius: 10px; padding: 8px;
  box-shadow: 0 8px 24px rgba(0,0,0,.45);
}
.wire-menu[hidden] { display: none; }
.wm-title { font-size: 12px; color: var(--dim); padding: 2px 4px 6px; }
.wm-item { text-align: left; }

/* --- traffic ----------------------------------------------------------------- */
.traffic {
  margin: 8px 0 0; height: 280px; overflow-y: auto; resize: vertical;
  background: #0e1116; border: 1px solid var(--border); border-radius: 8px; padding: 6px 8px;
  font: 12px/1.5 ui-monospace, "SF Mono", Menlo, monospace; color: #c9d1d9;
}
.tr { display: grid; grid-template-columns: 9.5em 4.5em minmax(10em, 16em) 1fr auto; gap: 8px; align-items: baseline; padding: 1px 0; }
.tr[hidden] { display: none; }
.tr-t { color: var(--dim); }
.tr-seam { color: #d2a8ff; }
.tr-who { color: #79c0ff; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tr-desc { overflow-wrap: anywhere; }
.tr-note .tr-desc { color: #e3b341; }
.tr-copy { padding: 0 6px; font-size: 12px; }
@media (max-width: 640px) {
  .tr { grid-template-columns: 1fr auto; }
  .tr-t, .tr-seam { display: none; }
}

/* --- board layout -------------------------------------------------------------- */
html, body { height: 100%; }
body { display: flex; flex-direction: column; overflow: hidden; }
header { position: relative; flex: none; }
.view-tools { gap: 6px; align-items: center; }
#zoom-level { font-size: 12px; min-width: 3.2em; text-align: center; }

.board {
  position: relative; flex: 1 1 auto; min-height: 200px; overflow: hidden; cursor: grab;
  touch-action: none; background-color: #11141a;
  background-image:
    linear-gradient(to right, rgba(255,255,255,.07) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(255,255,255,.07) 1px, transparent 1px),
    linear-gradient(to right, rgba(255,255,255,.03) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(255,255,255,.03) 1px, transparent 1px);
}
.board.panning { cursor: grabbing; }
.world { position: absolute; left: 0; top: 0; width: 0; height: 0; transform-origin: 0 0; }
.world .wires { position: absolute; left: 0; top: 0; width: 1px; height: 1px; overflow: visible;
  pointer-events: none; z-index: 3; }
.node { position: absolute; z-index: 1; box-shadow: 0 6px 22px rgba(0,0,0,.35); cursor: default; }
.node.dragging { z-index: 2; box-shadow: 0 12px 34px rgba(0,0,0,.55); opacity: .96; }
.node .card-head { cursor: move; user-select: none; }
.badge-node { width: 600px; }
.node.beacon { width: 420px; }
.hub-node { width: 320px; }
.hub-node label { display: flex; }
.hub-ports { display: flex; flex-direction: column; gap: 6px; }
.hub-port { justify-content: space-between; }

.board-help {
  position: absolute; left: 12px; bottom: 8px; right: 12px; margin: 0; z-index: 4;
  font-size: 12px; color: var(--dim); pointer-events: none;
}
.board-empty { position: absolute; left: 50%; top: 40%; transform: translate(-50%, -50%);
  color: var(--dim); z-index: 4; pointer-events: none; text-align: center; }
.board-empty[hidden] { display: none; }
.k-mesh { color: var(--mesh); } .k-ir { color: var(--ir); } .k-usb { color: var(--usb); }

:root { --usb: #3fb950; }
.jack[data-jack="usb"] { color: var(--usb); }
.wire.usb { stroke: var(--usb); stroke-width: 4; }
.wire.pending { stroke-dasharray: 2 6; opacity: .6; }
.wire-label.usb { fill: #8fe0a0; }
.wire-menu { position: fixed; }

/* --- dock ------------------------------------------------------------------------- */
.dock { flex: none; height: 300px; display: flex; flex-direction: column; border-top: 1px solid var(--border);
  background: var(--panel); resize: none; }
.dock.collapsed { height: auto; }
.dock.collapsed .dock-pane { display: none; }
.dock-tabs { display: flex; gap: 4px; padding: 6px 12px 0; align-items: center; }
.dock-tab { background: transparent; color: var(--dim); border: 1px solid transparent; border-bottom: none;
  border-radius: 6px 6px 0 0; padding: 4px 12px; }
.dock-tab[aria-selected="true"] { color: var(--ink); background: var(--panel-2); border-color: var(--border); }
#dock-toggle { margin-left: auto; }
.dock-pane { flex: 1; min-height: 0; display: flex; flex-direction: column; padding: 6px 12px 8px; }
.dock-pane[hidden] { display: none; }
.dock-pane .log-head h2 { display: none; }
.dock-pane #traffic, .dock-pane #log { flex: 1; height: auto; min-height: 0; margin-top: 6px; resize: none; }
.dock-pane > .hint { margin: 4px 0 0; }

/* --- configuration panel --------------------------------------------------------- */
.cfg { display: flex; flex-direction: column; gap: 10px; }
.cfg-section { border: 1px solid var(--border); border-radius: 8px; padding: 8px 10px 10px; margin: 0; }
.cfg-section legend { color: var(--dim); font-size: 12px; text-transform: uppercase; letter-spacing: .06em; padding: 0 4px; }
.cfg-row { display: grid; grid-template-columns: 9.5em minmax(0, 1fr); gap: 2px 10px; align-items: center; margin: 4px 0;
  color: var(--ink); font-size: 13px; }
.cfg-row .cfg-label { color: var(--dim); }
.cfg-row input[type=text], .cfg-row input[type=number], .cfg-row select { width: 100%; }
.cfg-row input[type=checkbox] { justify-self: start; }
.cfg-row .mono { font: 12px ui-monospace, "SF Mono", Menlo, monospace; }
.cfg-hint { grid-column: 2; font-size: 11.5px; color: var(--dim); overflow-wrap: anywhere; }
.cfg-value.bad { color: var(--warn); }
.cfg-status { margin: 0; }

/* --- run info sidebar ----------------------------------------------------------- */
.workspace { flex: 1 1 auto; display: flex; min-height: 0; }
.workspace .board { flex: 1 1 auto; min-width: 0; }
.sidebar { flex: none; width: 340px; max-width: 45vw; overflow-y: auto; background: var(--panel);
  border-left: 1px solid var(--border); padding: 12px 14px 20px; }
.sidebar[hidden] { display: none; }
.side-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 6px; }
.sidebar section { margin-top: 14px; }
.sidebar h3 { margin-bottom: 6px; }
.kv { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 4px 10px; margin: 0; font-size: 12.5px; }
.kv dt { color: var(--dim); }
.kv dd { margin: 0; display: flex; gap: 6px; align-items: flex-start; min-width: 0; }
.kv dd > span { overflow-wrap: anywhere; min-width: 0; }
.kv .mono { font: 12px ui-monospace, "SF Mono", Menlo, monospace; }
.kv .copy { padding: 0 6px; font-size: 11px; flex: none; }
.seed { border: 1px solid var(--border); border-radius: 8px; padding: 6px 8px; margin-bottom: 8px; background: var(--panel-2); }
.seed summary { cursor: pointer; font-size: 13px; }
.seed[open] summary { margin-bottom: 6px; }
@media (max-width: 720px) { .sidebar { position: absolute; right: 0; top: 0; bottom: 0; z-index: 6; width: min(340px, 90vw); max-width: none; } .workspace { position: relative; } }
.cfg-row.dirty input, .cfg-row.dirty select { border-color: var(--busy); }
.cfg-row.dirty .cfg-hint { color: #e3b341; }
.cfg-status.bad { color: var(--warn); }
