/* ============================================================
   Canvas nodes — image / video / audio / text / script / table / grid
   ============================================================ */

.node {
  position: absolute;
  z-index: 3;
  cursor: default;
  will-change: left, top;
}
.node.is-dragging { cursor: grabbing; z-index: 40; }
.node.is-selected { z-index: 5; }

.node-label {
  position: absolute;
  left: 1px;
  top: -23px;
  height: 17px;
  display: flex;
  align-items: center;
  gap: 5px;
  font-size: 11.5px;
  color: #a6a6ad;
  white-space: nowrap;
  max-width: calc(100% + 40px);
  pointer-events: none;
}
.node-label .ic { color: #8e8e95; opacity: 0.9; }
.node-label .label-text {
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 220px;
  pointer-events: auto;
  cursor: text;
  border-radius: 3px;
  outline: none;
}
.node-label .label-text:hover { color: #d6d6da; }
.node-label .label-text[contenteditable="true"] {
  background: #1c1c1e;
  color: #fff;
  box-shadow: 0 0 0 1px rgba(255,255,255,0.14);
  padding: 1px 4px;
  margin: -1px -4px;
}
.node.is-selected .node-label { color: #d2d2d7; }
.node.is-selected .node-label .ic { color: #c8c8ce; }
.label-spinner {
  width: 8px; height: 8px;
  border-radius: 50%;
  border: 1.5px solid rgba(120,170,255,0.3);
  border-top-color: #7fb0ff;
  animation: spin 0.8s linear infinite;
  margin-left: 2px;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ---------- generic media node ---------- */
.node-image, .node-video, .node-grid { width: 340px; }
.node-shell { position: relative; }

.media-wrap {
  position: relative;
  border-radius: 4px;
  overflow: visible;
  background: #151516;
}
.media-frame {
  position: relative;
  width: 100%;
  border-radius: 4px;
  overflow: hidden;
  background: #131314;
  box-shadow: inset 0 0 0 1px rgba(255,255,255,0.06), 0 14px 34px rgba(0,0,0,0.34);
}
.media-frame::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.07), inset 0 0 0 1px rgba(0,0,0,0.35);
  pointer-events: none;
}
.media-frame > img, .media-frame > video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.node-image.is-selected .media-empty,
.node-video.is-selected .media-empty {
  box-shadow: inset 0 0 0 1px #fff;
}
.node-image.is-selected .media-frame,
.node-video.is-selected .media-frame,
.node-grid.is-selected .media-frame {
  box-shadow: 0 0 0 1px #fff, 0 18px 40px rgba(0,0,0,0.5);
}

/* stacked results (deck) */
.stack-layer {
  position: absolute;
  inset: 0;
  border-radius: 4px;
  overflow: hidden;
  background: #111;
  box-shadow: 0 0 0 1px rgba(255,255,255,0.05);
  pointer-events: none;
  z-index: -1;
}
.stack-layer img { width: 100%; height: 100%; object-fit: cover; display: block; }
.stack-layer.l1 { transform: translate(7px, 0); opacity: 0.78; }
.stack-layer.l2 { transform: translate(14px, 0); opacity: 0.5; }
.stack-layer.l3 { transform: translate(21px, 0); opacity: 0.3; }

.stack-count {
  position: absolute;
  top: 8px; right: 8px;
  height: 22px;
  padding: 0 7px;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  border-radius: 5px;
  background: rgba(12,12,13,0.58);
  backdrop-filter: blur(10px);
  font-size: 10.5px;
  color: #ececef;
  box-shadow: inset 0 0 0 1px rgba(255,255,255,0.1);
  opacity: 0;
  transition: opacity 0.14s;
}
.node:hover .stack-count, .node.is-selected .stack-count { opacity: 1; }
.stack-count:hover { background: rgba(12,12,13,0.8); }

.media-play {
  position: absolute;
  left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  width: 44px; height: 44px;
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: rgba(10,10,11,0.5);
  backdrop-filter: blur(8px);
  box-shadow: inset 0 0 0 1px rgba(255,255,255,0.2);
  color: #fff;
  opacity: 0;
  transition: opacity 0.18s, transform 0.18s;
}
.node-video:hover .media-play, .node-video.is-selected .media-play { opacity: 1; }
.media-play:hover { transform: translate(-50%, -50%) scale(1.05); background: rgba(10,10,11,0.68); }

/* ---------- empty state ---------- */
.media-empty {
  position: relative;
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background: #171718;
  border-radius: 4px;
  box-shadow: inset 0 0 0 1px rgba(255,255,255,0.085);
  color: #46464c;
  overflow: hidden;
}
.media-empty .mountain { color: #3d3d43; }
.media-empty .tries {
  position: absolute;
  left: 12px;
  bottom: 10px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  align-items: flex-start;
  text-align: left;
}
.media-empty .tries .tries-label {
  font-size: 10px;
  color: #56565d;
  margin-bottom: 3px;
}
.try-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 24px;
  padding: 0 6px;
  margin-left: -6px;
  border-radius: 5px;
  font-size: 11px;
  color: #9a9aa1;
  transition: background 0.13s, color 0.13s;
}
.try-btn .ic { color: #7f7f87; }
.try-btn:hover { background: #232326; color: #eee; }
.try-btn:hover .ic { color: #d4d4da; }

.upload-pill {
  position: absolute;
  left: 8px;
  top: 8px;
  height: 26px;
  padding: 0 9px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border-radius: 7px;
  background: #1c1c1e;
  box-shadow: 0 8px 22px rgba(0,0,0,0.45), inset 0 0 0 1px rgba(255,255,255,0.1);
  font-size: 11.5px;
  color: #d9d9dd;
  opacity: 0;
  transition: opacity 0.15s, background 0.15s;
  z-index: 12;
}
.node:hover .upload-pill, .node.is-selected .upload-pill, .node.is-empty .upload-pill { opacity: 1; }
.upload-pill:hover { background: #28282b; }

.upload-pill.is-inline {
  position: static;
  transform: none;
  height: 21px;
  padding: 0 6px;
  gap: 4px;
  border-radius: 5px;
  font-size: 9.5px;
  background: #202023;
  box-shadow: inset 0 0 0 1px rgba(255,255,255,0.07);
  opacity: 1;
  margin-left: auto;
  margin-right: 4px;
  color: #a8a8b0;
}
.upload-pill.is-inline .ic { color: #8c8c94; }
.upload-pill.is-inline:hover { background: #2a2a2e; color: #e4e4e8; }
.audio-head .dur { margin-left: 0; }

/* ---------- ports ---------- */
.port {
  position: absolute;
  top: 50%;
  width: 13px;
  height: 13px;
  margin-top: -6.5px;
  border-radius: 50%;
  background: #141415;
  box-shadow: 0 0 0 1px #48484f, 0 2px 6px rgba(0,0,0,0.4);
  color: #9a9aa2;
  font-size: 9px;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 8;
  transition: transform 0.12s, box-shadow 0.12s, color 0.12s, background 0.12s;
  opacity: 0.9;
}
.port:hover {
  transform: scale(1.18);
  box-shadow: 0 0 0 1px #8db6f0, 0 0 12px rgba(90,150,255,0.45);
  color: #dceaff;
  background: #1b2330;
}
.port-in { left: -7px; }
.port-out { right: -7px; }
.port.connecting { box-shadow: 0 0 0 1px #8db6f0, 0 0 0 5px rgba(90,150,255,0.14); }

/* ---------- progress ---------- */
.node-progress {
  position: absolute;
  inset: 0;
  border-radius: 4px;
  background: rgba(9,9,10,0.72);
  backdrop-filter: blur(3px);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  z-index: 10;
  cursor: default;
}
.progress-ring {
  width: 26px; height: 26px;
  border-radius: 50%;
  border: 2px solid rgba(255,255,255,0.14);
  border-top-color: #e9e9ec;
  animation: spin 0.9s linear infinite;
}
.node-progress .p-label { font-size: 11.5px; color: #e2e2e6; letter-spacing: 0.01em; }
.node-progress .p-sub { font-size: 10px; color: #92929a; }
.progress-bar {
  width: 132px; height: 2px;
  border-radius: 2px;
  background: rgba(255,255,255,0.13);
  overflow: hidden;
}
.progress-bar i {
  display: block; height: 100%; width: 0%;
  background: #e8e8ea;
  border-radius: 2px;
  transition: width 0.32s var(--ease);
}
.node-progress .cancel {
  margin-top: 2px;
  font-size: 10.5px;
  color: #a8a8b0;
  padding: 4px 8px;
  border-radius: 5px;
  background: rgba(255,255,255,0.06);
}
.node-progress .cancel:hover { background: rgba(255,255,255,0.12); color: #fff; }

/* ---------- video player bar ---------- */
.video-bar {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 34px;
  padding: 0 9px;
  display: flex;
  align-items: center;
  gap: 8px;
  background: linear-gradient(0deg, rgba(0,0,0,0.68), rgba(0,0,0,0));
  opacity: 0;
  transition: opacity 0.16s;
  z-index: 6;
}
.node-video:hover .video-bar, .node-video.is-selected .video-bar, .node-video.is-playing .video-bar { opacity: 1; }
.video-bar .icon-btn { width: 20px; height: 20px; color: #f0f0f2; }
.video-bar .time { font-size: 9.5px; color: #e6e6e8; font-variant-numeric: tabular-nums; }
.video-progress {
  position: relative;
  flex: 1;
  height: 14px;
  display: flex;
  align-items: center;
  cursor: pointer;
}
.video-progress::before {
  content: "";
  position: absolute;
  left: 0; right: 0; height: 2px;
  background: rgba(255,255,255,0.25);
  border-radius: 2px;
}
.video-progress i {
  position: absolute;
  left: 0; height: 2px;
  width: 0%;
  background: #fff;
  border-radius: 2px;
}
.video-progress b {
  position: absolute;
  width: 6px; height: 6px;
  border-radius: 50%;
  background: #fff;
  left: 0;
  transform: translateX(-3px);
  box-shadow: 0 0 0 2px rgba(0,0,0,0.25);
}

/* ---------- audio node ---------- */
.node-audio { width: 336px; }
.audio-card {
  position: relative;
  padding: 12px 13px 10px;
  border-radius: 9px;
  background: #141415;
  box-shadow: inset 0 0 0 1px rgba(255,255,255,0.1);
  overflow: hidden;
}
.node-audio.is-selected .audio-card { box-shadow: inset 0 0 0 1px #fff, 0 18px 40px rgba(0,0,0,0.5); }
.audio-head {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 11px;
  color: #9d9da5;
  margin-bottom: 10px;
}
.audio-head .name { color: #dedee2; font-size: 11.5px; }
.audio-head .dur { margin-left: auto; font-variant-numeric: tabular-nums; font-size: 10px; color: #77777f; }
.waveform {
  display: flex;
  align-items: center;
  gap: 2px;
  height: 38px;
  cursor: pointer;
}
.waveform i {
  flex: 1;
  min-width: 1px;
  background: #4b4b52;
  border-radius: 1px;
  transition: background 0.12s;
}
.waveform i.on { background: #dfe0e5; }
.audio-foot {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 6px;
}
.audio-play {
  width: 26px; height: 26px;
  border-radius: 50%;
  background: #efeff1;
  color: #131314;
  display: flex; align-items: center; justify-content: center;
  flex: none;
}
.audio-play:hover { background: #fff; }
.audio-meta { font-size: 10px; color: #77777f; }

/* ---------- text node ---------- */
.node-text { width: 300px; }
.text-card {
  position: relative;
  padding: 14px 15px;
  border-radius: 10px;
  background: #141415;
  box-shadow: inset 0 0 0 1px rgba(255,255,255,0.11);
  font-size: 12.8px;
  line-height: 1.72;
  color: #d5d5da;
  min-height: 96px;
  white-space: pre-wrap;
  word-break: break-word;
  outline: none;
  cursor: text;
  transition: box-shadow 0.15s;
}
.node-text.is-selected .text-card { box-shadow: inset 0 0 0 1px #fff, 0 18px 40px rgba(0,0,0,0.5); }
.text-card:empty::before {
  content: "输入文本，或从上游节点引用内容…";
  color: #55555c;
}
.text-card .resize-handle { position: absolute; right: 0; bottom: 0; }

/* ---------- script node ---------- */
.node-script { width: 380px; }
.script-card {
  border-radius: 10px;
  background: #141415;
  box-shadow: inset 0 0 0 1px rgba(255,255,255,0.11);
  overflow: hidden;
}
.node-script.is-selected .script-card { box-shadow: inset 0 0 0 1px #fff, 0 18px 40px rgba(0,0,0,0.5); }
.script-head {
  height: 38px;
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 0 12px;
  border-bottom: 1px solid rgba(255,255,255,0.055);
  font-size: 11.5px;
  color: #cfcfd4;
}
.script-head .meta { color: #74747c; font-size: 10.5px; }
.script-head .icon-btn { width: 24px; height: 24px; margin-left: auto; }
.script-rows { padding: 4px; }
.script-row {
  display: flex;
  gap: 9px;
  padding: 8px 8px;
  border-radius: 5px;
  font-size: 11px;
  line-height: 1.5;
  color: #a7a7ae;
}
.script-row:hover { background: rgba(255,255,255,0.035); }
.script-row .no {
  flex: none;
  width: 16px;
  color: #6a6a72;
  font-variant-numeric: tabular-nums;
}
.script-row .desc {
  color: #c6c6cc;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.script-row .len { flex: none; margin-left: auto; color: #68686f; font-size: 10px; }
.script-more {
  width: 100%;
  height: 28px;
  font-size: 10.5px;
  color: #7c7c84;
  border-top: 1px solid rgba(255,255,255,0.05);
}
.script-more:hover { color: #d0d0d5; background: rgba(255,255,255,0.03); }

/* ---------- table node ---------- */
.node-table { width: 660px; }
.table-card {
  border-radius: 10px;
  background: #131314;
  box-shadow: inset 0 0 0 1px rgba(255,255,255,0.1);
  overflow: hidden;
}
.node-table.is-selected .table-card { box-shadow: inset 0 0 0 1px #fff, 0 18px 40px rgba(0,0,0,0.5); }
.table-head {
  height: 40px;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 0 12px;
  border-bottom: 1px solid rgba(255,255,255,0.06);
}
.table-head .t { font-size: 12px; color: #e2e2e6; }
.table-head .view {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 10.5px;
  color: #8e8e96;
}
.table-grid {
  display: table;
  width: 100%;
  border-collapse: collapse;
  table-layout: fixed;
  font-size: 10px;
}
.table-grid .tr { display: table-row; }
.table-grid .th, .table-grid .td {
  display: table-cell;
  padding: 7px 8px;
  border-bottom: 1px solid rgba(255,255,255,0.045);
  border-right: 1px solid rgba(255,255,255,0.035);
  color: #9b9ba3;
  vertical-align: top;
  line-height: 1.5;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.table-grid .th {
  color: #74747c;
  font-weight: 400;
  background: rgba(255,255,255,0.015);
  font-size: 9.5px;
  padding-top: 6px;
  padding-bottom: 6px;
}
.table-grid .td.num { color: #c3c3c9; font-variant-numeric: tabular-nums; }
.table-grid .td.desc { white-space: normal; display: table-cell; }
.table-scroll { max-height: 330px; overflow: hidden; }

/* ---------- grid node ---------- */
.grid-card {
  padding: 3px;
  border-radius: 5px;
  background: #1a1a1c;
  display: grid;
  gap: 2px;
}
.grid-card .cell {
  position: relative;
  overflow: hidden;
  border-radius: 2px;
  background: #101011;
  cursor: zoom-in;
}
.grid-card .cell img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform 0.18s var(--ease); }
.grid-card .cell:hover { box-shadow: inset 0 0 0 1px rgba(255,255,255,0.45); }
.grid-card .cell:hover img { transform: scale(1.04); }

/* ---------- resize handle ---------- */
.resize-handle {
  position: absolute;
  right: -3px; bottom: -3px;
  width: 12px; height: 12px;
  cursor: nwse-resize;
  z-index: 9;
  opacity: 0;
}
.node.is-selected .resize-handle { opacity: 1; }
.resize-handle::after {
  content: "";
  position: absolute;
  right: 3px; bottom: 3px;
  width: 5px; height: 5px;
  border-right: 1px solid rgba(255,255,255,0.7);
  border-bottom: 1px solid rgba(255,255,255,0.7);
}

/* ---------- node quick actions ---------- */
.node-hover-actions {
  position: absolute;
  right: -1px;
  top: -36px;
  display: flex;
  gap: 2px;
  padding: 3px;
  border-radius: 7px;
  background: #1c1c1e;
  box-shadow: 0 8px 22px rgba(0,0,0,0.45), inset 0 0 0 1px rgba(255,255,255,0.09);
  opacity: 0;
  transform: translateY(2px);
  transition: opacity 0.14s, transform 0.14s;
  z-index: 12;
}
.node:hover .node-hover-actions { opacity: 1; transform: none; }
.node-hover-actions .icon-btn { width: 24px; height: 24px; color: #a8a8af; }

/* ---------- misc node states ---------- */
.node.is-error .media-frame { box-shadow: 0 0 0 1px rgba(255,107,107,0.7); }
.node-error-bar {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  padding: 6px 9px;
  font-size: 10px;
  color: #ffb4b4;
  background: rgba(70, 15, 15, 0.85);
  border-radius: 0 0 4px 4px;
}


/* slow ken-burns for mock video playback */
@keyframes kenburns {
  from { transform: scale(1) translate(0, 0); }
  to { transform: scale(1.08) translate(-1.2%, -1%); }
}
.node-video.is-playing .video-poster { animation: kenburns 8s ease-out forwards; }
.node-video .video-poster { transform-origin: 55% 45%; }

/* lock indicator */
.node-label .lock-ic {
  color: #cfcfd6;
  opacity: 0.7;
  display: inline-flex;
  align-items: center;
}


/* ---------- focus / subject regions ---------- */
.region-box {
  position: absolute;
  border: 1px dashed rgba(120, 178, 255, 0.95);
  background: rgba(90, 150, 255, 0.07);
  pointer-events: none;
  z-index: 3;
}
.region-box.mark {
  border-color: rgba(255, 196, 120, 0.95);
  background: rgba(255, 180, 90, 0.07);
}
.region-box span {
  position: absolute;
  left: -1px; top: -15px;
  height: 14px;
  padding: 0 4px;
  border-radius: 3px 3px 3px 0;
  font-size: 8.5px;
  line-height: 14px;
  color: #0c0c0d;
  background: #8fc0ff;
  white-space: nowrap;
}
.region-box.mark span { background: #ffc478; }
.style-tag {
  height: 15px;
  padding: 0 5px;
  border-radius: 3px;
  font-size: 9px;
  line-height: 15px;
  color: #b9cbe6;
  background: rgba(110, 168, 255, 0.14);
  box-shadow: inset 0 0 0 1px rgba(110, 168, 255, 0.22);
}


.timeline-tag {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  height: 15px;
  padding: 0 5px;
  border-radius: 3px;
  font-size: 9px;
  line-height: 15px;
  color: #d9c8a8;
  background: rgba(233, 201, 141, 0.12);
  box-shadow: inset 0 0 0 1px rgba(233, 201, 141, 0.2);
}

.node-error-bar {
  display: flex;
  align-items: center;
  gap: 8px;
}
.node-error-bar span { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.node-error-bar button {
  flex: none;
  height: 20px;
  padding: 0 6px;
  border-radius: 4px;
  font-size: 9.5px;
  color: #ffd7d7;
  background: rgba(255,255,255,0.08);
}
.node-error-bar button:hover { background: rgba(255,255,255,0.16); }


.script-row { cursor: pointer; }
.table-head { cursor: pointer; }

/* ---------- reference strip ---------- */
.node-refs {
  position: absolute;
  left: 0;
  top: calc(100% + 6px);
  display: flex;
  align-items: center;
  gap: 5px;
  height: 26px;
  max-width: 100%;
  z-index: 5;
}
.node-refs.is-empty { opacity: 0; transition: opacity 0.14s var(--ease); }
.node:hover .node-refs.is-empty,
.node.is-selected .node-refs.is-empty,
.node-refs.is-empty:focus-within { opacity: 1; }

.refs-count { font-size: 9px; color: #63636b; letter-spacing: 0.02em; }
.ref-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  height: 26px;
  padding: 0 7px 0 4px;
  border-radius: 6px;
  background: #171719;
  box-shadow: inset 0 0 0 1px rgba(255,255,255,0.09);
  font-size: 9.5px;
  color: #b9b9c1;
  max-width: 118px;
  transition: background 0.12s, box-shadow 0.12s;
}
.ref-chip:hover { background: #212124; box-shadow: inset 0 0 0 1px rgba(255,255,255,0.18); }
.ref-chip img { width: 18px; height: 18px; border-radius: 3px; object-fit: cover; display: block; }
.ref-chip b { font-weight: 400; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ref-txt {
  width: 18px;
  height: 18px;
  border-radius: 3px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 8.5px;
  background: rgba(110,168,255,0.16);
  color: #9dc2ff;
}
.ref-chip.ref-audio .ref-txt { background: rgba(126,231,168,0.14); color: #8fe0b4; }
.ref-chip.ref-video .ref-txt { background: rgba(255,196,120,0.14); color: #f0c184; }
.ref-more { font-size: 9px; color: #77777f; }
.ref-add {
  height: 22px;
  min-width: 22px;
  padding: 0 5px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 3px;
  border-radius: 5px;
  background: #1b1b1e;
  box-shadow: inset 0 0 0 1px rgba(255,255,255,0.08);
  color: #8c8c94;
  font-size: 9px;
}
.ref-add:hover { color: #e6e6ea; background: #26262a; }

/* ---------- 评论徽标 ---------- */
.comment-badge {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  height: 16px;
  padding: 0 5px;
  border-radius: 4px;
  font-size: 8.5px;
  color: #d8c89a;
  background: rgba(216,200,154,0.14);
  box-shadow: inset 0 0 0 1px rgba(216,200,154,0.22);
}
.comment-badge:hover { background: rgba(216,200,154,0.24); }
