/* =========================================================
   Tree Crawl Graph — theme
   Every colour and metric lives here; edit the tokens below.
   ========================================================= */

:root {
  /* core — material gruvbox */
  --bg:      #282828;   /* graph canvas (bg0) */
  --panel:   #32302f;   /* editor + floating chrome (bg1) */
  --raised:  #3c3836;   /* inputs, buttons (bg2) */
  --line:    #504945;   /* borders, links (bg3) */
  --text:    #d4be98;   /* fg */
  --muted:   #a89984;   /* gray */

  /* accents (kept to two, plus one for destructive edges) */
  --accent:   #7daea3;  /* selection — gruvbox blue */
  --accent-2: #d8a657;  /* search match, second selection — gruvbox yellow */
  --warn:     #ea6962;  /* gruvbox red */

  /* rings: hidden children vs hidden parents */
  --ring-child:  var(--muted);
  --ring-parent: #d3869b;   /* gruvbox purple */

  --radius: 6px;
  --strip: 30px;        /* height of the one-line editor sections */
  --font: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  height: 100%;
  background: var(--bg);
  color: var(--text);
  font: 13px/1.5 var(--font);
  overflow: hidden;
}

#app {
  display: flex;
  height: 100%;
}

/* ---------------------------------------------------------
   Graph pane
   --------------------------------------------------------- */

#graph-pane {
  flex: 0 0 70%;   /* overridden inline by the gripper */
  position: relative;
  overflow: hidden;
}

#graph {
  width: 100%;
  height: 100%;
  display: block;
  cursor: grab;
  user-select: none;
}
#graph:focus { outline: none; }   /* focusable only so Enter can leave the editor */
#graph.panning { cursor: grabbing; }

/* ---------------------------------------------------------
   Gripper — drag to move the graph/editor boundary
   --------------------------------------------------------- */

#gripper {
  flex: 0 0 9px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  background: var(--bg);
  cursor: col-resize;
  touch-action: none;
}
#gripper span {
  width: 3px; height: 3px;
  border-radius: 50%;
  background: var(--line);
}
#gripper:hover span, #gripper.dragging span { background: var(--muted); }
body.resizing { cursor: col-resize; user-select: none; }

/* Floating toolbar */
#toolbar {
  position: absolute;
  top: 12px; left: 12px; right: 12px;
  display: flex;
  gap: 6px;
  z-index: 2;
}

#search {
  flex: 1;
  min-width: 0;
  height: 32px;
  padding: 0 10px;
  color: var(--text);
  background: color-mix(in srgb, var(--panel) 82%, transparent);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  font: inherit;
  backdrop-filter: blur(3px);
}
#search::placeholder { color: var(--muted); }
#search:focus { outline: none; border-color: var(--accent); }

button, a.icon {
  color: var(--text);
  background: var(--raised);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  font: inherit;
  cursor: pointer;
  text-decoration: none;
}
button:hover, a.icon:hover { border-color: var(--muted); }
button:focus-visible, a.icon:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
button:disabled { opacity: .4; cursor: default; }
button:disabled:hover { border-color: var(--line); }

button.wide {
  width: 100%;
  margin-top: 8px;
  padding: 6px 0;
  color: var(--muted);
}
button.wide:hover { color: var(--text); }

.icon {
  width: 32px; height: 32px;
  display: grid;
  place-items: center;
  padding: 0;
}
.icon svg {
  width: 16px; height: 16px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.3;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.icon.on { color: var(--accent); border-color: var(--accent); }

/* Settings popover */
#settings {
  position: absolute;
  top: 52px; right: 12px;
  z-index: 3;
  width: 220px;
  padding: 10px 12px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}
#settings .row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 5px 0;
  color: var(--muted);
}
#settings input[type=checkbox] { accent-color: var(--accent); }
#settings input[type=range] { width: 96px; accent-color: var(--accent); }

/* Add / remove */
#actions {
  position: absolute;
  right: 12px; bottom: 12px;
  display: flex;
  gap: 6px;
  z-index: 2;
}
#actions button {
  width: 32px; height: 32px;
  font-size: 17px;
  line-height: 1;
  background: var(--panel);
}

#status {
  position: absolute;
  left: 12px; bottom: 12px;
  max-width: 60%;
  padding: 6px 10px;
  color: var(--muted);
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  opacity: 0;
  transition: opacity .2s;
  pointer-events: none;
}
#status.show { opacity: 1; }

/* ---------------------------------------------------------
   Graph elements
   --------------------------------------------------------- */

.link .wire { stroke: var(--line); stroke-width: 1.5; }
.link .hit { stroke: transparent; stroke-width: 12; cursor: pointer; pointer-events: stroke; }
/* Selection only recolours the visible wire — the wide invisible hit-line
   must never pick this up, or the whole link looks fat (specificity keeps
   this rule from also matching .hit). */
.link.selected .wire { stroke: var(--accent); }
.link .head { fill: var(--line); }
.link.selected .head { fill: var(--accent); }

.link-label {
  fill: var(--muted);
  font-size: 10px;
  text-anchor: middle;
  pointer-events: none;
  opacity: 0;
  transition: opacity .12s;
}
/* Labels always exist so hovering a link can reveal them even when the
   "show link labels" setting is off. */
.link.show-labels .link-label,
.link:hover .link-label { opacity: 1; }

.node { cursor: pointer; }
.node circle.body {
  fill: var(--raised);
  stroke: none;
}
.node.selected circle.body { stroke: var(--accent); stroke-width: 2; }
.node.selected-2 circle.body { stroke: var(--accent-2); stroke-width: 2; }
.node.match circle.body { fill: var(--accent-2); }
.node.orphan circle.body { stroke: var(--warn); stroke-width: 1.5; stroke-dasharray: 3 2; }

/* Collapsed nodes get up to three concentric rings — a gap, then a thin
   stroke — one per level of hidden depth, fading out toward the rim.
   Child rings count what's hidden below; parent rings count what a focus is
   hiding above, and use a separate accent. */
.node .ring, .node .pring {
  fill: none;
  stroke-width: 1;
  pointer-events: none;
}
.node .ring  { stroke: var(--ring-child); }
.node .pring { stroke: var(--ring-parent); }

.node text {
  fill: var(--text);
  font-size: 11px;
  text-anchor: middle;
  pointer-events: none;
}
.node.selected text, .node.selected-2 text { fill: var(--text); }

.hidden { display: none; }

/* ---------------------------------------------------------
   Editor pane — three stacked sections
   --------------------------------------------------------- */

#editor-pane {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  background: var(--panel);
  border-left: 1px solid var(--line);
}

.strip {
  flex: 0 0 var(--strip);
  display: flex;
  align-items: center;
  border-bottom: 1px solid var(--line);
}

#meta {
  justify-content: space-between;
  padding: 0 10px;
  color: var(--muted);
  font: 11px/1 var(--mono);
  white-space: nowrap;
  overflow: hidden;
}
#meta span { overflow: hidden; text-overflow: ellipsis; }

#label {
  width: 100%;
  height: 100%;
  padding: 0 10px;
  color: var(--text);
  background: none;
  border: 0;
  font: inherit;
}
#label:focus { outline: none; background: var(--raised); }
#label::placeholder { color: var(--muted); }

#text {
  flex: 1;
  padding: 10px;
  color: var(--text);
  background: none;
  border: 0;
  resize: none;
  font: 12px/1.6 var(--mono);
  tab-size: 2;
}
#text:focus { outline: none; }
#text::placeholder { color: var(--muted); }

:disabled { cursor: default; }

/* ---------------------------------------------------------
   Keybindings popup
   --------------------------------------------------------- */

#help {
  position: fixed;
  inset: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: center;
  background: color-mix(in srgb, #000 55%, transparent);
}
#help[hidden] { display: none; }

#help .card {
  position: relative;
  max-width: 460px;
  max-height: 80vh;
  overflow-y: auto;
  padding: 18px 22px 22px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}
#help h2 {
  margin: 16px 0 6px;
  color: var(--accent);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
}
#help h2:first-of-type { margin-top: 0; }
#help dl {
  display: grid;
  grid-template-columns: 134px 1fr;
  gap: 4px 12px;
  margin: 0;
}
#help dt {
  color: var(--accent-2);
  font: 11px/1.5 var(--mono);
}
#help dd { margin: 0; color: var(--muted); }

#help-close {
  position: absolute;
  top: 10px; right: 10px;
  width: 24px; height: 24px;
  padding: 0;
  background: none;
  border: 0;
  color: var(--muted);
  font-size: 18px;
  line-height: 1;
}
#help-close:hover { color: var(--text); }

/* ---------------------------------------------------------
   Small screens: stack the panes
   --------------------------------------------------------- */

@media (max-width: 760px) {
  #app { flex-direction: column; }
  #graph-pane { flex: 0 0 60% !important; }
  #gripper { display: none; }
  #editor-pane { border-left: 0; border-top: 1px solid var(--line); }
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; }
}
