:root {
    --bg: #161616;
    --surface: #1f1f1f;
    --border: #2e2e2e;
    --text: #f2f2f2;
    --muted: #9a9a9a;
    --accent: #c5f547;
    --edge: #5a5a5a;
    --edge-active: #c5f547;
    --schema: #8ec8e8;
    --function: #9b7eed;
    --constant: #e8b88a;
    --defect-placeholder: #e8b88a;
    --defect-drop: #d96b6b;
    --defect-coarse: #d9b84a;
}

* {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

body,
#canvas-wrap {
    background-color: var(--bg);
    background-image: radial-gradient(circle, #2a2a2a 1px, transparent 1px);
    background-size: 18px 18px;
    color: var(--text);
}

body {
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
    height: 100vh;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.75rem 1.25rem;
    background: var(--surface);
    border-bottom: 1px solid var(--border);
    flex-shrink: 0;
}

header h1 {
    font-size: 0.95rem;
    font-weight: 600;
    letter-spacing: 0.02em;
}

.stats {
    display: flex;
    gap: 1.25rem;
    font-size: 0.8rem;
    color: var(--muted);
}

.stats strong {
    color: var(--text);
}

.controls {
    display: flex;
    gap: 0.5rem;
}

button {
    background: var(--surface);
    color: var(--text);
    border: 1px solid var(--border);
    border-radius: 12px;
    padding: 0.35rem 0.75rem;
    font-size: 0.78rem;
    cursor: pointer;
    transition: border-color 0.15s, background 0.15s;
}

button:hover {
    border-color: var(--accent);
    background: #2a2a2a;
}

#canvas-wrap {
    flex: 1;
    position: relative;
    cursor: grab;
    overflow: hidden;
    touch-action: none;
    user-select: none;
}

#canvas-wrap.dragging {
    cursor: grabbing;
}

svg {
    width: 100%;
    height: 100%;
    display: block;
}

.edge {
    fill: none;
    stroke: var(--edge);
    stroke-width: 1.2;
    opacity: 0.75;
    transition: opacity 0.12s, stroke 0.12s;
}

.edge.active {
    stroke: var(--edge-active);
    opacity: 0.9;
    stroke-width: 1.6;
}

.node {
    cursor: grab;
}

.node.dragging-node {
    cursor: grabbing;
}

/* Scoped to the fill dot. An unscoped `.node circle` is (0,1,1) and beats
   `.node-ring` / `.node-unterminated` (0,1,0), so rings would inherit the
   generic halo instead of --defect-*. */
.node circle:not(.node-ring):not(.node-unterminated) {
    stroke: rgba(255, 255, 255, 0.15);
    stroke-width: 1.5;
    transition: stroke-width 0.12s, filter 0.12s;
}

.node:hover circle:not(.node-ring):not(.node-unterminated),
.node.selected circle:not(.node-ring):not(.node-unterminated) {
    stroke: #fff;
    stroke-width: 2.5;
    filter: drop-shadow(0 0 6px rgba(197, 245, 71, 0.55));
}

.node-label {
    font-size: 3px;
    fill: var(--muted);
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.12s;
}

.node:hover .node-label,
.node.selected .node-label,
body.show-labels .node-label {
    opacity: 1;
    fill: var(--text);
}

.node-ring {
    fill: none;
    stroke: var(--defect-placeholder);
    stroke-width: 1.2;
    pointer-events: none;
}

.node.is-placeholder .node-ring {
    stroke-dasharray: 2.5 1.75;
}

.node.is-approximation .node-ring {
    opacity: 0.6;
}

/* Catch-all for any status other than ok/placeholder/approximation (e.g.
   multi-branch-verify, pruned-orphan) — distinct stroke and dash from is-placeholder
   so an unmodeled status still announces itself instead of rendering clean. */
.node.is-unverified .node-ring {
    stroke: var(--defect-coarse);
    stroke-dasharray: 1 2;
}

.node-unterminated {
    fill: none;
    stroke: var(--defect-drop);
    stroke-width: 1;
    pointer-events: none;
}

.node.is-coarse circle:not(.node-ring):not(.node-unterminated) {
    stroke: var(--defect-coarse);
}

#tooltip {
    position: fixed;
    pointer-events: none;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 12px;
    padding: 0.45rem 0.65rem;
    font-size: 0.78rem;
    line-height: 1.35;
    max-width: 280px;
    opacity: 0;
    transition: opacity 0.1s;
    z-index: 10;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
}

#tooltip.visible {
    opacity: 1;
}

#tooltip .type {
    color: var(--accent);
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    margin-bottom: 0.15rem;
}

#legend {
    position: absolute;
    bottom: 1rem;
    left: 1rem;
    background: rgba(31, 31, 31, 0.92);
    border: 1px solid var(--border);
    border-radius: 12px;
    padding: 0.65rem 0.85rem;
    font-size: 0.72rem;
    display: flex;
    flex-wrap: wrap;
    gap: 0.45rem 0.85rem;
    max-width: 420px;
    backdrop-filter: blur(6px);
}

.legend-item {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    color: var(--muted);
}

.legend-swatch {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    flex-shrink: 0;
}

.hint {
    position: absolute;
    bottom: 1rem;
    right: 1rem;
    font-size: 0.7rem;
    color: var(--muted);
    background: rgba(31, 31, 31, 0.85);
    border: 1px solid var(--border);
    border-radius: 12px;
    padding: 0.4rem 0.6rem;
}

.grid-line {
    stroke: #2a2a2a;
    stroke-width: 1;
    vector-effect: non-scaling-stroke;
}

.grid-line-major {
    stroke: #3a3a3a;
}

.grid-axis {
    stroke: var(--edge);
    stroke-width: 1.5;
    vector-effect: non-scaling-stroke;
}

.grid-label {
    font-size: 9px;
    fill: var(--muted);
    pointer-events: none;
    user-select: none;
}

.grid-origin {
    fill: var(--muted);
    font-weight: 600;
}

/* .stub-in / .stub-out (set alongside .stub on the path element) are direction hooks
   with no styling of their own today — both render via the shared rules below. */
.stub {
    fill: none;
    stroke: var(--defect-drop);
    stroke-width: 1.1;
    stroke-dasharray: 3 2;
    opacity: 0.85;
}

.stub-end {
    /* Filled with the canvas color (not none) so the hollow-looking terminator is
       still a real hit target — the outline alone is too thin to hover reliably. */
    fill: var(--bg);
    stroke: var(--defect-drop);
    stroke-width: 1;
}

.stub-group {
    cursor: help;
}

.stub-group:hover .stub,
.stub-group:hover .stub-end {
    opacity: 1;
    stroke-width: 1.8;
}

.node-badge {
    font-size: 3.2px;
    fill: var(--defect-drop);
    pointer-events: none;
}

.legend-chip {
    font: inherit;
    color: var(--muted);
    background: transparent;
    border: 1px solid var(--border);
    border-radius: 999px;
    padding: 0.1rem 0.5rem;
    cursor: pointer;
}

span.legend-chip {
    cursor: default;
}

.legend-chip strong {
    color: var(--text);
}

.legend-chip.active {
    border-color: var(--accent);
    color: var(--text);
}

.chip-placeholder strong { color: var(--defect-placeholder); }
.chip-approximation strong { color: var(--defect-placeholder); }
.chip-unresolved strong { color: var(--defect-drop); }
.chip-unterminated strong { color: var(--defect-drop); }
.chip-coarse strong { color: var(--defect-coarse); }

#canvas-wrap.dim-placeholder .node:not(.is-placeholder),
#canvas-wrap.dim-approximation .node:not(.is-approximation),
#canvas-wrap.dim-unterminated .node:not(.is-unterminated),
#canvas-wrap.dim-coarse .node:not(.is-coarse),
#canvas-wrap.dim-unresolved .node:not(.is-dropped) {
    opacity: 0.12;
}

#canvas-wrap.dim-placeholder .edge,
#canvas-wrap.dim-placeholder .stub-group,
#canvas-wrap.dim-approximation .edge,
#canvas-wrap.dim-approximation .stub-group,
#canvas-wrap.dim-unterminated .edge,
#canvas-wrap.dim-unterminated .stub-group,
#canvas-wrap.dim-coarse .edge,
#canvas-wrap.dim-coarse .stub-group,
#canvas-wrap.dim-unresolved .edge,
#canvas-wrap.dim-unresolved .stub-group:not(.is-dropped) {
    opacity: 0.08;
}
