/* lab/nodes.css — NODES (lab/nodes.js, 018 D3): the ground (a dotted plane that pans), the node cards (a title bar, a top in-port, a bottom
   out-port), the wires (one SVG layer under the cards), + and the window ↔ rack door in the ground's top corners.  Glass and ink from the skin. */
.nodes-host { display: flex; flex-direction: column; gap: 6px; height: 100%; min-height: 0; }
.nodes-ground { position: relative; overflow: hidden; touch-action: none; cursor: grab; border-radius: var(--r-md); box-shadow: var(--relief-well, var(--neu-inset));
  background: radial-gradient(circle, color-mix(in srgb, var(--ink-faint) 35%, transparent) 1px, transparent 1.5px) 0 0 / 22px 22px, var(--glass-well); }
.nodes-host > .nodes-ground { flex: 1 1 auto; min-height: 0; }
.dev .nodes-ground { height: min(70vh, 680px); }
.nodes-ground:active { cursor: grabbing; }
.nodes-plane { position: absolute; left: 0; top: 0; width: 0; height: 0; transform-origin: 0 0; }
.nodes-wires { position: absolute; left: 0; top: 0; width: 1px; height: 1px; overflow: visible; pointer-events: none; }
.nodes-wires path { fill: none; stroke: var(--acc); stroke-width: 2; opacity: .75; }
.nodes-card { position: absolute; width: 120px; box-sizing: border-box; padding: 0 8px 8px; cursor: default; border-radius: var(--r-md);
  background: var(--glass-raise, var(--glass-tint)); border: 1px solid var(--glass-border); box-shadow: var(--relief-raise, var(--neu-raise)); }
.nodes-card[data-node="curves"] { width: 250px; }
.nodes-card[data-type] { width: 236px; }
.nodes-card[data-type="curves"] { width: 250px; }
.nodes-card.off { opacity: .5; }
.nodes-card.off .nodes-body { pointer-events: none; }
.nodes-mark { font-style: normal; letter-spacing: 0; color: var(--fg-soft); }
.nodes-knobs { --cell-min: 56px; }   /* 022 F2: a card's knobs are a fit row (`.row.fit`); 56-px cells keep OUT WHITE whole */
.nodes-title { display: flex; align-items: center; gap: 6px; height: 26px; margin: 0 -8px 6px; padding: 0 8px; cursor: move; user-select: none;
  font: var(--w-bold) var(--fs-micro) / 1 var(--font-ui); letter-spacing: var(--tr-wider, .12em); color: var(--acc); border-bottom: 1px solid var(--glass-hairline); }
.nodes-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nodes-ico { flex: none; width: 14px; height: 14px; }
.nodes-body { font-size: var(--fs-tiny); color: var(--dim); }
.nodes-card[data-node="curves"] .nodes-body { color: inherit; }
.nodes-port { position: absolute; left: 50%; width: 10px; height: 10px; margin-left: -5px; border-radius: 50%; background: var(--acc); box-shadow: 0 0 0 2px var(--glass-well); }
.nodes-port.in { top: -5px; }
.nodes-port.out { bottom: -5px; }
.nodes-tools button, :is(.nodes-x, .nodes-rm, .nodes-door) { display: grid; place-items: center; width: 26px; height: 26px; min-width: 0; min-height: 0; padding: 0; border: 0;
  background: transparent; box-shadow: none; color: var(--fg-soft); cursor: pointer; }
.nodes-x, .nodes-rm { width: 18px; height: 18px; margin-right: -4px; }
.nodes-x[aria-pressed="true"] { color: var(--acc); }
:is(.nodes-tools button, .nodes-x, .nodes-rm, .nodes-door):is(:hover, :focus-visible) { color: var(--acc); }
:is(.nodes-tools button, .nodes-x, .nodes-rm, .nodes-door) svg { width: 16px; height: 16px; }
.nodes-tools, .nodes-door { position: absolute; top: 6px; z-index: 1; }
.nodes-tools { left: 6px; display: flex; gap: 2px; }
:is(.nodes-tools button, .nodes-door) { border-radius: var(--r-sm); background: var(--glass-tint); }
.nodes-door { right: 6px; }
/* 020 X1 · the ground: focus, the selection's accent outline, the shift-drag box */
.nodes-ground:focus-visible { outline: 1px solid color-mix(in srgb, var(--acc) 50%, transparent); outline-offset: -1px; }
.nodes-card.sel { outline: 2px solid var(--acc); outline-offset: 2px; }
/* 020 X2 · the card: the chevron, collapsed (the bar + the PREVIEW strip), the strip, a title being renamed, the right-click menu */
.nodes-chev { display: grid; place-items: center; width: 16px; height: 16px; margin-left: -4px; padding: 0; border: 0; background: transparent; box-shadow: none; color: var(--fg-soft); cursor: pointer; }
.nodes-chev svg { width: 12px; height: 12px; transition: rotate .15s; }
.nodes-chev[aria-expanded="false"] svg { rotate: -90deg; }
.nodes-card.fold { padding-bottom: 6px; }
.nodes-card.fold > .nodes-body { display: none; }
.nodes-strip { display: block; width: 100%; height: 10px; margin: -2px 0 6px; border-radius: 2px; box-shadow: 0 0 0 1px var(--glass-hairline); }
.nodes-rename { flex: 1 1 auto; min-width: 0; height: 18px; padding: 0 4px; font: inherit; letter-spacing: inherit; }
/* 020 X3 · the flags: the eye (VIEW HERE) and SOLO lit in the accent; SOLO shows on a hover or while lit; a card past the view dims; graph off */
:is(.nodes-eye, .nodes-solo) { display: grid; place-items: center; width: 18px; height: 18px; padding: 0; border: 0; background: transparent; box-shadow: none; color: var(--fg-soft); opacity: .55; cursor: pointer; }
:is(.nodes-eye, .nodes-solo) svg { width: 14px; height: 14px; }
:is(.nodes-eye, .nodes-solo, .nodes-tools button)[aria-pressed="true"] { color: var(--acc); opacity: 1; }
.nodes-card:not(:hover) .nodes-solo:not([aria-pressed="true"]) { display: none; }
.nodes-card.past { opacity: .4; }
.nodes-passes > span + span::before { content: ' · '; }
.nodes-off .nodes-wires { opacity: .3; }
/* 020 X4 · the foot fold: FADE · MASK · SOFT under the knobs; lit while either is off home */
.nodes-foot { margin-top: 6px; border-top: 1px solid var(--glass-hairline); }
.nodes-foot-t { display: block; width: 100%; padding: 5px 0 0; border: 0; background: transparent; box-shadow: none; cursor: pointer; font: var(--w-bold) var(--fs-micro) / 1 var(--font-ui); letter-spacing: var(--tr-wide); color: var(--fg-soft); }
.nodes-foot-t.on, .nodes-foot-t:hover { color: var(--acc); }
.nodes-foot > .nodes-knobs { padding-top: 4px; }
.nodes-card.fold > .nodes-foot { display: none; }
.nodes-box { display: none; position: absolute; z-index: 1; pointer-events: none; border: 1px dashed var(--acc); background: color-mix(in srgb, var(--acc) 8%, transparent); }
.nodes-menu { position: absolute; left: 6px; top: 36px; z-index: 2; display: flex; flex-direction: column; min-width: 200px; max-height: calc(100% - 44px); overflow: auto; padding: 4px; border-radius: var(--r-md); }   /* 022 P3: a menu pane (.glass[data-mir-surface=menu]) — the skin's, no control's raise */
.nodes-item { padding: 6px 12px; border: 0; background: transparent; box-shadow: none; color: var(--fg); font: var(--w-bold) var(--fs-micro) / 1 var(--font-ui);
  letter-spacing: var(--tr-wide); text-align: left; cursor: pointer; }
.nodes-item:hover:not(:disabled) { color: var(--acc); }
.nodes-item:disabled { opacity: .45; cursor: default; }
/* 019 N5 · the + menu by class (each class's cost mark), the graphs, the foot's passes, the rack card's column */
.nodes-head { display: flex; gap: 6px; padding: 4px 12px 2px; font: var(--w-bold) var(--fs-micro) / 1 var(--font-ui); letter-spacing: var(--tr-wider, .12em); color: var(--fg-soft); }
.nodes-item { display: flex; align-items: center; gap: 8px; }
.nodes-item .nodes-mark { margin-left: auto; }
/* 020 X0 · the + menu is one list: a search line, a hairline with the class's icon between classes (no word), the empty graph's one line */
.nodes-sep { display: flex; align-items: center; gap: 6px; padding: 6px 12px 2px; color: var(--fg-soft); }
.nodes-sep::after { content: ''; flex: 1 1 auto; border-top: 1px solid var(--glass-hairline); }
.nodes-find { margin: 2px 4px 4px; padding: 5px 8px; border: 1px solid var(--glass-hairline); border-radius: var(--r-sm); background: var(--glass-well); color: var(--fg); box-shadow: var(--relief-well, var(--neu-inset)); font: var(--fs-tiny) / 1.2 var(--font-ui); }
.nodes-empty { position: absolute; translate: -50% 0; z-index: 1; padding: 3px 8px; border-radius: var(--r-sm); background: var(--glass-well); white-space: nowrap; pointer-events: none; font: var(--fs-tiny) / 1 var(--font-ui); letter-spacing: var(--tr-wide); color: var(--ink-faint); opacity: .7; }
.nodes-column .nodes-empty { position: static; translate: none; align-self: center; }
.nodes-heavy { font-style: normal; font-size: .8em; color: var(--acc); }
.nodes-menu .sp-prex { margin-left: auto; }
.nodes-passes { position: absolute; left: 8px; bottom: 6px; z-index: 1; pointer-events: none; font: var(--w-bold) var(--fs-micro) / 1 var(--font-ui); letter-spacing: var(--tr-wide); color: var(--fg-soft); }
.dev .nodes-ground.nodes-column { height: auto; cursor: default; }
.nodes-column .nodes-plane { position: static; width: auto; height: auto; display: flex; flex-direction: column; gap: 18px; padding: 40px 8px 26px; translate: none !important; }
.nodes-column .nodes-card { position: relative; left: auto !important; top: auto !important; width: auto; }
.nodes-column .nodes-title { cursor: default; }
.nodes-column .nodes-wires { display: none; }
.nodes-column .nodes-card + .nodes-card::before { content: ''; position: absolute; left: 50%; top: -19px; height: 18px; border-left: 2px solid var(--acc); opacity: .75; }
.nodes-host > .note { flex: none; }
[data-mir-window="nodes"] .mir-win-body { display: flex; flex-direction: column; min-height: 0; }
/* 019 N3 · the LAYER host (lab/node-layers.js): over the stage canvases, under the atom labels (9), the stage text (20) and the racks; never a pointer */
#nodeLayers { position: absolute; inset: 0; z-index: 8; overflow: hidden; pointer-events: none; }
.node-layer { position: absolute; inset: 0; }
canvas.node-layer { width: 100%; height: 100%; }   /* 024 S: a SHADER node's canvas (lab/node-shader.js), the stage's pixels stretched over it */
.node-layer[data-type="grain"] { inset: -50% 0 0 -50%; animation: node-grain .5s step-end infinite; will-change: transform; }   /* 1.5 × the stage: a jump of up to a third of it never shows an edge */
@keyframes node-grain { 0.0% { transform: translate(0%, 0%); } 8.3% { transform: translate(12.2%, 23.4%); } 16.7% { transform: translate(27.1%, 4.3%); } 25.0% { transform: translate(6.3%, 15.8%); } 33.3% { transform: translate(21.1%, 30.4%); } 41.7% { transform: translate(1.7%, 9.6%); } 50.0% { transform: translate(30.0%, 18.8%); } 58.3% { transform: translate(14.2%, 2.0%); } 66.7% { transform: translate(8.9%, 27.4%); } 75.0% { transform: translate(25.1%, 12.5%); } 83.3% { transform: translate(19.1%, 21.8%); } 91.7% { transform: translate(4.0%, 32.0%); } }   /* percentages, no var(): the compositor runs it, no style recalc a step */
@media (prefers-reduced-motion: reduce) { .node-layer[data-type="grain"] { animation: none; } }
/* 021 V3 · GRAIN rests while nothing plays (the "nothing playing ⇒ no frame" law; body.lw-playing is THE PLAY's, shell/transport.js); the chevron
   turns at once under reduced motion */
body:not(.lw-playing) .node-layer[data-type="grain"] { animation-play-state: paused; }
@media (prefers-reduced-motion: reduce) { .nodes-chev svg { transition: none; } }
:root:is([data-motion="reduced"], [data-motion="off"]) .nodes-chev svg { transition: none; }
