/* Noir Node — component styles. Every value comes from tokens.css. */

/* ---------- Canvas ---------- */
.nn-canvas {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
  color: var(--ink);
  font-family: var(--font-sans);
  background-color: var(--canvas-bg);
  background-image: radial-gradient(ellipse 75% 65% at 50% 42%, var(--canvas-glow), var(--canvas-bg) 72%);
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  outline: none;
}
.nn-canvas.is-panning { cursor: grabbing; }
.nn-world { position: absolute; left: 0; top: 0; transform-origin: 0 0; }
.nn-wires { position: absolute; left: 0; top: 0; width: 1px; height: 1px; overflow: visible; pointer-events: none; }

.nn-crumb {
  position: absolute; left: var(--space-4); top: var(--space-3);
  padding: 5px 12px; border-radius: var(--radius-pill);
  background: linear-gradient(180deg, var(--control-top), var(--control-bottom));
  border: 1px solid var(--control-edge); box-shadow: var(--shadow-control);
  color: var(--ink-muted); pointer-events: none; z-index: 1;
}
.nn-hud, .nn-hint { position: absolute; bottom: var(--space-3); color: var(--ink-muted); pointer-events: none; z-index: 1; }
.nn-hud { left: var(--space-4); }
.nn-hint { right: var(--space-4); text-align: right; max-width: 60%; }

/* ---------- Wire ---------- */
.nn-wire__hit { fill: none; stroke: var(--wire); stroke-opacity: 0; stroke-width: var(--wire-hit); pointer-events: stroke; cursor: pointer; }
.nn-wire__glow { fill: none; stroke: var(--wire); stroke-opacity: 0.07; stroke-width: var(--wire-glow); stroke-linecap: round; transition: stroke-opacity .2s; }
.nn-wire__line { fill: none; stroke: var(--wire); stroke-width: var(--wire-stroke); stroke-linecap: round; transition: stroke .2s, stroke-width .2s; }
.nn-wire:hover .nn-wire__line,
.nn-wire--live .nn-wire__line { stroke: var(--wire-hot); }
.nn-wire:hover .nn-wire__glow { stroke-opacity: 0.16; }
.nn-wire--live .nn-wire__glow { stroke-opacity: 0.22; }
.nn-wire--selected .nn-wire__line { stroke: var(--wire-hot); stroke-width: 2.2px; }
.nn-wire--selected .nn-wire__glow { stroke-opacity: 0.2; }
.nn-wire--pending .nn-wire__hit { pointer-events: none; }
.nn-wire--pending .nn-wire__line { stroke: var(--wire-pending); stroke-dasharray: 4 5; animation: nn-dash .5s linear infinite; }
.nn-wire--pending .nn-wire__glow { stroke-opacity: 0; }
.nn-wire--snap .nn-wire__line { stroke: var(--wire-hot); stroke-dasharray: none; animation: none; }
.nn-wire--snap .nn-wire__glow { stroke-opacity: 0.16; }
.nn-wire--dying { opacity: 0; transition: opacity .26s ease-out; }
.nn-wire--dying .nn-wire__hit { pointer-events: none; }
.nn-signal__core { fill: var(--wire-hot); }
.nn-signal__halo { fill: var(--wire-hot); fill-opacity: 0.14; }
@keyframes nn-dash { to { stroke-dashoffset: -9; } }

/* ---------- Node ---------- */
.nn-node {
  position: absolute; left: 0; top: 0;
  width: 320px;
  border-radius: var(--radius-node);
  border: 1px solid var(--node-edge);
  background: linear-gradient(180deg, var(--node-body-top), var(--node-body-bottom));
  box-shadow: var(--shadow-node);
  color: var(--ink);
  transition: border-color .18s, box-shadow .25s;
}
.nn-node:hover { border-color: var(--node-edge-hi); }
.nn-node.is-selected { border-color: var(--node-select); }
.nn-node.is-dragging { box-shadow: var(--shadow-node-lift); }
/* viscous pickup: while the node still clings to the canvas it brightens a touch */
.nn-node.is-stuck { filter: brightness(1.08); }
.nn-node.is-entering { animation: nn-enter .32s ease-out; }
.nn-node--static { position: relative; }
@keyframes nn-enter { from { opacity: 0; } to { opacity: 1; } }

.nn-node__head {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
  height: var(--head-height);
  padding: 0 var(--space-6);
  border-radius: var(--radius-node) var(--radius-node) 0 0;
  background: linear-gradient(180deg, var(--node-top), var(--node-head));
  border-bottom: 1px solid var(--divider);
  box-shadow: 0 1px 0 rgba(255,255,255,0.03);
  cursor: grab;
}
.nn-node.is-dragging .nn-node__head { cursor: grabbing; }
.nn-node__title { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.nn-node__body:empty { display: none; }
.nn-node--compact .nn-node__head { height: 34px; padding: 0 var(--space-4); }
.nn-node--compact .nn-params { padding: 2px var(--space-4) var(--space-3); }
.nn-node--compact .nn-param { margin: 0 calc(-1 * var(--space-4)); padding: 0 var(--space-4); }

/* ---------- LED ---------- */
.nn-led { flex: none; width: 10px; height: 10px; border-radius: 50%; background: var(--led-off); box-shadow: inset 0 1px 1px rgba(0,0,0,0.5); transition: background .2s, box-shadow .2s; }
.nn-led--head { width: 13px; height: 13px; }
.nn-led--on { background: var(--led-on); box-shadow: var(--shadow-led); }
.nn-led--pulse { background: var(--led-on); box-shadow: var(--shadow-led); animation: nn-pulse 1.1s ease-in-out infinite; }
@keyframes nn-pulse { 50% { opacity: .25; box-shadow: none; } }

/* ---------- Params & ports ---------- */
.nn-params { display: flex; flex-direction: column; gap: 0; padding: var(--space-1) var(--space-6) var(--space-4); }
.nn-params:empty { display: none; }
.nn-param { position: relative; display: flex; gap: 6px; margin: 0 calc(-1 * var(--space-6)); padding: 0 var(--space-6); white-space: nowrap; }
.nn-param__k { color: var(--ink-muted); }
.nn-param__v { color: var(--ink); overflow: hidden; text-overflow: ellipsis; }

.nn-port {
  position: absolute; top: 50%; width: 18px; height: 18px; margin-top: -9px;
  display: grid; place-items: center; cursor: crosshair; z-index: 1;
}
.nn-port--in { left: -10px; }
.nn-port--out { right: -10px; }
.nn-port::after {
  content: ""; width: 8px; height: 8px; border-radius: 50%;
  background: var(--port-idle);
  transition: transform .16s cubic-bezier(.3,1.6,.5,1), background .16s, box-shadow .2s;
}
.nn-port:hover::after { transform: scale(1.4); background: var(--ink); }
.nn-port--linked::after { background: var(--port-live); box-shadow: var(--shadow-port-live); transform: scale(1.2); }
.nn-port--snap::after { transform: scale(1.75); background: var(--wire-hot); box-shadow: var(--shadow-port-live); }
.nn-port--flash::after { animation: nn-flash .5s ease-out; }
@keyframes nn-flash { 0% { transform: scale(2.2); box-shadow: 0 0 18px rgba(255,255,255,0.9); } }

/* ---------- Button ---------- */
.nn-btn {
  appearance: none; -webkit-appearance: none;
  display: inline-flex; align-items: center; gap: var(--space-2);
  height: var(--control-height); min-width: 132px; padding: 0 22px 0 16px;
  border-radius: var(--radius-pill);
  border: 1px solid var(--control-edge);
  background: linear-gradient(180deg, var(--control-top), var(--control-bottom));
  box-shadow: var(--shadow-control);
  color: var(--ink); font-family: var(--font-sans); text-transform: uppercase;
  cursor: pointer;
  transition: border-color .15s, transform .08s, filter .15s;
}
.nn-btn:hover { border-color: var(--node-edge-hi); filter: brightness(1.15); }
.nn-btn:active { transform: translateY(1px); }
.nn-btn:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.nn-btn__label { flex: 1; text-align: center; }
.nn-btn.is-fired .nn-led { animation: nn-fire .6s ease-out; }
@keyframes nn-fire { 0% { background: var(--led-on); box-shadow: 0 0 14px rgba(255,255,255,0.9); } }

/* ---------- Bodies ---------- */
.nn-input { display: flex; flex-direction: column; padding: var(--space-4) var(--space-6) var(--space-3); }
.nn-field {
  width: 100%; min-height: 128px; resize: none; box-sizing: border-box;
  padding: 0; border: 0; outline: 0; background: transparent; color: var(--ink);
  font-family: var(--font-sans); user-select: text; -webkit-user-select: text;
}
.nn-field::placeholder { color: var(--ink-placeholder); }
.nn-actions { display: flex; justify-content: flex-end; gap: var(--space-3); padding-top: var(--space-3); }

.nn-viewer { padding: var(--space-3) var(--space-3) var(--space-1); }
.nn-viewer__frame { position: relative; border-radius: var(--radius-field); overflow: hidden; background: var(--well); border: 1px solid var(--divider); aspect-ratio: 4 / 5; }
.nn-viewer__frame canvas { display: block; width: 100%; height: 100%; transition: opacity .35s, filter .35s; }
.nn-viewer__frame.is-rendering canvas { opacity: .25; filter: blur(3px); }
.nn-viewer__frame canvas, .nn-viewer__img { object-fit: cover; }
.nn-viewer__img { display: block; width: 100%; height: 100%; user-select: none; -webkit-user-drag: none; }

/* ---------- Shaped nodes: the whole window keeps 1:1, 9:16 or 16:9 ---------- */
.nn-node--shaped { display: flex; flex-direction: column; }
.nn-node--shaped > .nn-node__head, .nn-node--shaped > .nn-params { flex: none; }
.nn-node--shaped > .nn-node__body { flex: 1 1 0; min-height: 0; display: flex; flex-direction: column; }
.nn-node--shaped > .nn-node__body > * { flex: 1 1 0; min-height: 0; display: flex; flex-direction: column; }
.nn-node--shaped .nn-viewer__frame { flex: 1 1 0; min-height: 0; aspect-ratio: auto; }
.nn-node--shaped .nn-well, .nn-node--shaped .nn-quote { flex: 1 1 0; min-height: 0; height: auto; }

.nn-output { padding: var(--space-3) var(--space-3) var(--space-1); }
.nn-well {
  height: 132px; box-sizing: border-box; padding: var(--space-3) 14px;
  border-radius: var(--radius-field); background: var(--well); border: 1px solid var(--divider);
  color: var(--ink); white-space: pre-wrap; word-break: break-word;
  user-select: text; -webkit-user-select: text;
}
.nn-well.is-empty { color: var(--ink-placeholder); }
/* text node + quote node frames never scroll: text that does not fit swaps the node for a long text node */
.nn-well, .nn-quote { overflow: hidden !important; scrollbar-width: none; }
.nn-well::-webkit-scrollbar, .nn-quote::-webkit-scrollbar { display: none; }
/* text node + quote node: Helvetica Light only (t-text / t-quote). Never override per node. */
.nn-well, .nn-quote, .nn-well *, .nn-quote * { font-family: var(--font-light); }

/* quote node: no well — the text sits on the node body, set like the input field */
.nn-output--quote { padding: var(--space-4) var(--space-6) var(--space-3); }
.nn-quote {
  height: 128px; box-sizing: border-box; color: var(--ink); white-space: pre-wrap; word-break: break-word;
  user-select: text; -webkit-user-select: text;
}
.nn-quote.is-empty { color: var(--ink-placeholder); }
.nn-caret { display: inline-block; width: 7px; height: 1em; margin-left: 2px; vertical-align: -2px; background: var(--ink); animation: nn-pulse .9s steps(1) infinite; }

.nn-value { padding: var(--space-3) var(--space-4) 0; font-variant-numeric: tabular-nums; }
.nn-value__unit { color: var(--ink-muted); margin-left: 6px; font-size: 13px; letter-spacing: .1em; }

/* ---------- Diagram (in-node operator viewer) ---------- */
.nn-diagram { padding: var(--space-3) var(--space-3) var(--space-1); }
.nn-diagram__frame { position: relative; border-radius: var(--radius-field); overflow: hidden; background: var(--well); border: 1px solid var(--divider); }
.nn-diagram__svg, .nn-diagram__tex { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.nn-diagram__band { fill: var(--diagram-fill); }
.nn-diagram__edge { fill: none; stroke: var(--diagram-edge); stroke-width: 1; vector-effect: non-scaling-stroke; }
.nn-diagram__grid { stroke: var(--diagram-grid); stroke-width: 1; stroke-dasharray: 3 4; vector-effect: non-scaling-stroke; }
.nn-diagram__mark { fill: var(--diagram-edge); }
.nn-diagram__label { position: absolute; top: 6px; left: 0; right: 0; text-align: center; color: var(--ink); pointer-events: none; }

/* ---------- Reference link (dotted dependency arrow) ---------- */
.nn-ref__line { fill: none; stroke: var(--wire-ref); stroke-width: 2px; stroke-dasharray: 2 5; stroke-linecap: round; }
.nn-ref__head { fill: var(--wire-ref); }

/* Generic surface used by previews to show controls on a node body */
.nn-surface { padding: var(--space-6); border-radius: var(--radius-node); border: 1px solid var(--node-edge); background: linear-gradient(180deg, var(--node-body-top), var(--node-body-bottom)); box-shadow: var(--shadow-node); }
.nn-node--shaped .nn-viewer__frame canvas, .nn-node--shaped .nn-viewer__img { position: absolute; inset: 0; }

/* ---------- Long text node: pure grey gradient, height follows text, 3:4 → 9:16 cap ---------- */
.nn-node--long {
  display: flex; flex-direction: column;
  background: linear-gradient(180deg, var(--longtext-top), var(--longtext-bottom));
  border-color: var(--longtext-edge);
  transition: border-color .18s, max-height .42s cubic-bezier(.22,.8,.26,1);
}
.nn-node--long:hover { border-color: var(--node-select); }
.nn-node--long.is-selected { border-color: var(--ink); }
.nn-long__head {
  position: relative; flex: none;
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
  height: var(--head-height); padding: 0 var(--space-6);
  cursor: grab;
}
.nn-node--long.is-dragging .nn-long__head { cursor: grabbing; }
.nn-node--long .nn-port::after { background: var(--longtext-port); }
.nn-node--long .nn-port--linked::after, .nn-node--long .nn-port--snap::after { background: var(--port-live); }
.nn-long__text {
  flex: 0 1 auto; min-height: 0; overflow: hidden;
  padding: 0 var(--space-6) var(--space-4);
  color: var(--ink); white-space: pre-wrap; word-break: break-word;
  user-select: text; -webkit-user-select: text;
}
.nn-long__text.is-empty { color: var(--longtext-muted); }
.nn-node--long.is-expanded .nn-long__text { overflow-y: auto; scrollbar-width: thin; scrollbar-color: var(--longtext-muted) transparent; }
.nn-node--long.is-clipped .nn-long__text {
  -webkit-mask-image: linear-gradient(180deg, #000 calc(100% - 56px), transparent);
          mask-image: linear-gradient(180deg, #000 calc(100% - 56px), transparent);
}
.nn-long__foot { flex: none; display: none; justify-content: flex-end; padding: 0 var(--space-6) var(--space-3); }
.nn-node--long.has-toggle .nn-long__foot { display: flex; }
.nn-long__toggle {
  appearance: none; border: 0; background: none; cursor: pointer;
  width: 24px; height: 24px; margin-right: -6px; padding: 0;
  display: grid; place-items: center;
  color: var(--longtext-muted); font-family: var(--font-sans); font-size: 24px; line-height: 1; font-weight: 300;
  transition: color .15s, transform .2s;
}
.nn-long__toggle:hover { color: var(--ink); transform: scale(1.15); }
.nn-long__toggle:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; border-radius: 2px; }

/* ---------- File artifact: document silhouette for any linked file ---------- */
.nn-node--file { background: none; border: 0; box-shadow: none; border-radius: 0; }
.nn-node--file:hover, .nn-node--file.is-selected { border: 0; }
.nn-file__svg { position: absolute; inset: 0; overflow: visible; pointer-events: none; }
.nn-file__shape { stroke: var(--file-edge); stroke-width: 1; transition: stroke .18s; }
.nn-node--file:hover .nn-file__shape { stroke: var(--node-edge-hi); }
.nn-node--file.is-selected .nn-file__shape { stroke: var(--node-select); }
.nn-file__fold { stroke: var(--file-edge); stroke-width: 1; stroke-linejoin: round; }
.nn-file__perf { stroke: var(--file-perf); stroke-width: 1; stroke-dasharray: 3 4; }
.nn-file__ext, .nn-file__stamp {
  position: absolute; font-family: var(--font-sans); font-weight: 800; text-transform: uppercase;
  color: var(--file-deboss); text-shadow: 0 1px 0 rgba(255,255,255,0.07), 0 -1px 0 rgba(0,0,0,0.35);
  white-space: nowrap; overflow: hidden; pointer-events: none; user-select: none;
}
.nn-file__ext { left: var(--space-6); top: calc(var(--fw, 240) * 0.075px); font-size: calc(var(--fw, 240) * 0.14px); line-height: 1.15; letter-spacing: 0.02em; }
.nn-file__window {
  position: absolute; left: var(--space-6); right: var(--space-6); top: 21%; height: 40%;
  border-radius: var(--radius-field); background: var(--well); border: 1px solid var(--divider);
  box-shadow: inset 0 1px 0 rgba(0,0,0,0.6), 0 1px 0 rgba(255,255,255,0.05);
  overflow: hidden;
}
.nn-file__led { position: absolute; top: 8px; right: 8px; width: 8px; height: 8px; z-index: 1; }
.nn-file__preview, .nn-file__preview > * { position: absolute; inset: 0; }
.nn-file__preview .nn-viewer, .nn-file__preview .nn-diagram { padding: 0; }
.nn-file__preview .nn-viewer__frame, .nn-file__preview .nn-diagram__frame { position: absolute; inset: 0; border: 0; border-radius: 0; aspect-ratio: auto !important; }
.nn-file__preview .nn-viewer__frame canvas, .nn-file__preview .nn-viewer__img { position: absolute; inset: 0; }
.nn-file__excerpt {
  padding: 12px 22px 12px 14px; font-size: 10.5px; line-height: 15px; color: var(--ink-muted);
  white-space: pre-wrap; word-break: break-word; overflow: hidden;
  -webkit-mask-image: linear-gradient(180deg, #000 55%, transparent); mask-image: linear-gradient(180deg, #000 55%, transparent);
}
.nn-file__row {
  position: absolute; left: 0; right: 0; top: calc(61% + 10px);
  display: flex; gap: var(--space-2); align-items: baseline; padding: 0 var(--space-6); white-space: nowrap;
}
.nn-file__name { color: var(--ink); overflow: hidden; text-overflow: ellipsis; }
.nn-file__size { color: var(--ink-muted); margin-left: auto; }
.nn-file__stamp { left: 0; right: 0; display: grid; place-items: center; font-size: calc(var(--fw, 240) * 0.11px); letter-spacing: 0.04em; }

/* ---------- Focus: a clicked window grows in place on the canvas ---------- */
.nn-ghost { position: absolute !important; left: 0; top: 0; margin: 0; pointer-events: none; will-change: transform, opacity; }
.nn-node.is-focused { will-change: transform; }
.nn-node--long.is-fixed .nn-long__text { flex: 1 1 auto; overflow-y: auto; scrollbar-width: thin; scrollbar-color: var(--longtext-muted) transparent; }
.nn-node--long.is-fixed .nn-long__foot { display: none; }
.nn-node { cursor: default; }
.nn-hud, .nn-hint, .nn-crumb { transition: opacity .3s; }
/* decode: characters not yet resolved */
.nn-decode { color: var(--decode-noise); }
.nn-long__params { flex: none; padding-top: var(--space-2); }
.nn-node--long .nn-long__params .nn-param__k { color: var(--longtext-muted); }

/* ---------- Hover dwell halo: lights up slowly, then breathes ---------- */
.nn-node::after {
  content: ""; position: absolute; inset: -7px; pointer-events: none;
  border-radius: calc(var(--radius-node) + 7px);
  border: 1px solid var(--halo);
  box-shadow: 0 0 16px 1px var(--halo-glow), inset 0 0 12px var(--halo-glow);
  opacity: 0; transition: opacity .45s ease-out;
}
.nn-node.is-dwell::after { opacity: 1; transition: opacity .9s ease-in; animation: nn-breathe 2.6s ease-in-out .9s infinite; }
@keyframes nn-breathe {
  50% { border-color: var(--halo-dim); box-shadow: 0 0 6px 0 var(--halo-glow-dim), inset 0 0 4px var(--halo-glow-dim); }
}
/* the file card glows along its own silhouette instead of a rectangle */
.nn-node--file::after { display: none; }
.nn-node--file .nn-file__svg { transition: filter .45s ease-out; }
.nn-node--file.is-dwell .nn-file__svg { filter: drop-shadow(0 0 7px var(--halo-glow)); transition: filter .9s ease-in; animation: nn-breathe-file 2.6s ease-in-out .9s infinite; }
.nn-node--file.is-dwell .nn-file__shape { stroke: var(--halo); }
@keyframes nn-breathe-file { 50% { filter: drop-shadow(0 0 2px var(--halo-glow-dim)); } }
.nn-ghost::after { display: none; }
@media (prefers-reduced-motion: reduce) { .nn-node.is-dwell::after, .nn-node--file.is-dwell .nn-file__svg { animation: none; } }

/* ---------- Term node: one word or phrase ---------- */
.nn-node--term { width: auto; min-width: 96px; max-width: 320px; }
.nn-term {
  display: flex; align-items: center; gap: var(--space-3);
  height: var(--head-height); padding: 0 var(--space-6) 0 var(--space-6);
  border-radius: var(--radius-node);
  background: linear-gradient(180deg, var(--node-top), var(--node-head));
  cursor: grab;
}
.nn-node--term.is-dragging .nn-term { cursor: grabbing; }
.nn-term__text { min-width: 0; margin: 0 auto; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.nn-node--term > .nn-port { top: 50%; }
