/* ── canvas + infinite grid ───────────────────────────── */
#canvas{flex:1;position:relative;overflow:hidden;background:var(--bg);cursor:default}
#gridLayer{
  position:absolute;inset:-600px;pointer-events:none;
  background-image:
    radial-gradient(circle,var(--dot-hi) 1.1px,transparent 1.5px),
    radial-gradient(circle,var(--dot-lo) 1px,transparent 1.4px);
}
#world{position:absolute;left:0;top:0;transform-origin:0 0;width:0;height:0}
#edgeSvg{position:absolute;left:0;top:0;width:1px;height:1px;overflow:visible}
#zonesLayer,#packetsLayer,#groupsLayer,#nodesLayer,#labelsLayer{position:absolute;left:0;top:0}

/* ── nodes ────────────────────────────────────────────── */
.node{position:absolute;width:180px;height:64px;cursor:grab;touch-action:none}
.node .card{
  position:relative;height:100%;display:flex;align-items:center;gap:10px;padding:0 12px;
  background:linear-gradient(180deg,var(--card1),var(--card2));
  border:1px solid var(--line2);border-radius:11px;
  box-shadow:0 6px 18px #00000030;
  transition:border-color .15s,box-shadow .15s,transform .15s;
}
.node:hover .card{border-color:var(--line3);transform:translateY(-1px)}
.node.sel .card{border-color:var(--sel);box-shadow:0 0 0 1px var(--sel),0 0 22px color-mix(in srgb,var(--sel) 20%,transparent),0 8px 22px #00000030}
.node.drop-ok .card{border-color:var(--acc);box-shadow:0 0 0 2px color-mix(in srgb,var(--acc) 40%,transparent)}

.node .plate{
  position:absolute;inset:0;border-radius:11px;background:var(--plate);
  border:1px solid var(--line2);border-color:color-mix(in srgb,var(--c) 38%,var(--mix));
  transform:translate(calc(var(--i)*5px),calc(var(--i)*5px));
}
.n-icon{
  flex:none;width:34px;height:34px;border-radius:9px;display:grid;place-items:center;
  background:var(--c);color:#0d1117;box-shadow:0 0 14px color-mix(in srgb,var(--c) 45%,transparent);
}
.n-icon svg{width:20px;height:20px}
.n-meta{min-width:0;flex:1}
.n-name{font-family:var(--fd);font-weight:600;font-size:12.5px;line-height:1.2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.n-type{font-family:var(--fm);font-size:8px;letter-spacing:1.6px;color:var(--dim);margin-top:3px}
.n-count{
  position:absolute;top:-9px;right:-8px;font-family:var(--fm);font-size:10px;font-weight:700;
  background:var(--chip);border:1px solid var(--line2);border-radius:6px;padding:1px 6px;color:var(--c);
}

/* connection ports */
.port{
  position:absolute;width:12px;height:12px;border-radius:50%;z-index:3;
  background:var(--bg);border:2px solid var(--c);cursor:crosshair;
  opacity:0;transform:translate(-50%,-50%) scale(.4);transition:all .18s cubic-bezier(.34,1.56,.64,1);
}
.port[data-side=n]{left:50%;top:0}.port[data-side=s]{left:50%;top:100%}
.port[data-side=w]{left:0;top:50%}.port[data-side=e]{left:100%;top:50%}
.node:hover .port,.node.sel .port{opacity:1;transform:translate(-50%,-50%) scale(1)}
.port:hover{transform:translate(-50%,-50%) scale(1.45) !important;box-shadow:0 0 10px var(--c)}

/* ── groups ───────────────────────────────────────────── */
.group{position:absolute;border:1px solid color-mix(in srgb,var(--c) 42%,var(--mix));border-radius:15px;pointer-events:none;transition:box-shadow .15s; background: color-mix(in srgb, var(--c) 20%, transparent);}
.group.sel{box-shadow:0 0 0 1px var(--sel),inset 0 0 40px color-mix(in srgb,var(--c) 7%,transparent)}
.group-tag{
  position:absolute;top:-12px;left:14px;pointer-events:auto;cursor:grab;touch-action:none;
  display:flex;align-items:center;gap:7px;padding:2px 9px;border-radius:6px;
  background:var(--solid);border:1px solid color-mix(in srgb,var(--c) 45%,var(--mix));
  font-family:var(--fm);font-size:12px;letter-spacing:1.8px;color:var(--c);
}
.group-tag .gt-n{color:var(--dim)}
.group.sel .group-tag{border-color:var(--sel)}

/* collapsed group (super-node) */
.group.collapsed{
  pointer-events:auto;cursor:grab;
  display:flex;align-items:center;gap:10px;padding:0 13px;
  background:
    repeating-linear-gradient(45deg,
      color-mix(in srgb,var(--c) 13%,transparent) 0 6px,
      transparent 6px 14px),
    linear-gradient(180deg,var(--card1),var(--card2));
  border:1px solid var(--line2);border-color:color-mix(in srgb,var(--c) 45%,var(--mix));
  border-radius:12px;box-shadow:0 8px 22px #00000030;
  transition:border-color .15s, box-shadow .15s;
}
.group.collapsed:hover{border-color:color-mix(in srgb,var(--c) 70%,var(--mix))}
.group.collapsed.sel{border-color:var(--sel);box-shadow:0 0 0 1px var(--sel),0 8px 22px #00000030}
.gc-ic{flex:none;width:36px;height:36px;border-radius:9px;display:grid;place-items:center;color:#0d1117;background:var(--c)}
.gc-ic svg{width:20px;height:20px}
.gc-meta{min-width:0;flex:1}
.gc-name{font-family:var(--fd);font-weight:600;font-size:12.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.gc-sub{font-family:var(--fm);font-size:8px;letter-spacing:1.5px;color:var(--dim);margin-top:3px;display:flex;align-items:center;gap:6px}
.gc-dots{display:inline-flex;gap:3px}
.gc-dots i{width:6px;height:6px;border-radius:2px}

/* ── edges ────────────────────────────────────────────── */
.edge{pointer-events:none}
.edge .edge-hit{fill:none;stroke:transparent;stroke-width:16;pointer-events:stroke;cursor:pointer}
.edge .edge-line{fill:none;stroke:var(--edge);stroke-width:1.75;transition:stroke .15s}
.edge .flow-line{fill:none;stroke:var(--edge-flow);stroke-width:2;stroke-dasharray:2 12;stroke-linecap:round;opacity:.45;animation:march 1.1s linear infinite}
.edge polygon{fill:var(--edge)}
.edge:hover .edge-line{stroke:var(--edge-hi)}
.edge.sel .edge-line{stroke:var(--sel);stroke-width:2.2}
.edge.sel polygon{fill:var(--sel)}
.edge.sel .flow-line{stroke:var(--edge-flow);opacity:.9}
.edge.off .edge-line{stroke:var(--edge-off);stroke-dasharray:7 5;opacity:.65}
.edge.off .flow-line{display:none}
.edge.off polygon{fill:var(--edge-off);opacity:.65}
@keyframes march{to{stroke-dashoffset:-14}}

.ghost-path{fill:none;stroke:var(--acc);stroke-width:2;stroke-dasharray:6 5;opacity:.9}

.edge-label{
  position:absolute;transform:translate(-50%,-50%);pointer-events:none;
  font-family:var(--fm);font-size:12px;letter-spacing:.5px;color:var(--mut);
  background:var(--float);border:1px solid var(--line2);border-radius:5px;padding:2px 7px;white-space:nowrap;
}
.edge-label.sel{border-color:var(--sel);color:var(--sel)}

/* ── traffic dots ─────────────────────────────────────── */
.fdot{
  position:absolute;left:0;top:0;width:5px;height:5px;border-radius:50%;
  pointer-events:none;background:#5ee6d5;
  box-shadow:0 0 4px 2px rgba(94,230,213,.45), 0 0 3px 1px rgba(94,230,213,.9);
}
.fdot.rev{
  background:#f5c76a;
  box-shadow:0 0 4px 2px rgba(245,199,106,.4), 0 0 3px 1px rgba(245,199,106,.9);
}



/* ── zones: pure annotations ──────────────────────────── */
.zone{
  position:absolute;pointer-events:none;border-radius:14px;
  border:1.5px dashed color-mix(in srgb,var(--c) 55%,var(--mix));
  background: color-mix(in srgb, var(--c) 30%, transparent);   /* ← bg вместо transparent */
  
}
.zone-tab{
  position:absolute;top:-11px;left:14px;pointer-events:auto;cursor:grab;touch-action:none;
  background:var(--solid);border:1px dashed color-mix(in srgb,var(--c) 55%,var(--mix));
  border-radius:6px;padding:2px 9px;
  font-family:var(--fm);font-size:12px;letter-spacing:1.8px;color:var(--c);
}
.zone.sel{border-color:var(--sel);box-shadow:0 0 0 1px color-mix(in srgb,var(--sel) 25%,transparent)}
.zone.sel .zone-tab{border-color:var(--sel)}
.zh{position:absolute;pointer-events:auto}
.zh-n{top:-5px;left:8px;right:8px;height:10px;cursor:ns-resize}
.zh-s{bottom:-5px;left:8px;right:8px;height:10px;cursor:ns-resize}
.zh-w{left:-5px;top:8px;bottom:8px;width:10px;cursor:ew-resize}
.zh-e{right:-5px;top:8px;bottom:8px;width:10px;cursor:ew-resize}


/* ── sticky notes ─────────────────────────────────────── */
.node.note{width:180px;height:auto;min-height:56px}
.node.note .card{
  display:block;height:auto;padding:11px 13px;border:none;border-radius:3px 3px 3px 14px;
  background:var(--c);color:#141821;
  box-shadow:0 10px 24px #00000040;
}
.node.note .card::after{
  content:'';position:absolute;right:0;bottom:0;width:15px;height:15px;
  background:linear-gradient(315deg, var(--bg) 44%, #00000045 50%, transparent 56%);
}
.node.note.sel .card{box-shadow:0 0 0 2px var(--sel),0 10px 24px #00000040}
.note-text{
  font-size:13px;font-weight:500;line-height:1.45;outline:none;
  white-space:pre-wrap;word-break:break-word;
}
.note-text[contenteditable="true"]{
  cursor:text;user-select:text;overflow:auto;
  box-shadow:inset 0 0 0 1.5px #00000045;border-radius:4px;
}

/* ── marquee ──────────────────────────────────────────── */
#marquee{position:absolute;border:1px solid var(--sel);background:color-mix(in srgb,var(--sel) 10%,transparent);border-radius:3px;pointer-events:none;z-index:20}

/* ── canvas hint ──────────────────────────────────────── */
.canvas-hint{
  position:absolute;left:50%;bottom:16px;transform:translateX(-50%);pointer-events:none;
  font-family:var(--fm);font-size:9.5px;letter-spacing:1.2px;color:var(--dim);
  background:color-mix(in srgb,var(--solid) 80%,transparent);border:1px solid var(--line);border-radius:20px;padding:5px 14px;
  transition:opacity .3s;white-space:nowrap;
}

/* touch: не отдаём жесты браузеру на drag-элементах */
.p-item, .zh, .port, .group.collapsed{touch-action:none}
#canvas{touch-action:none}

/* ── annotations: heading ─────────────────────────────── */
.node.head{width:max-content;height:auto;min-width:40px}
.node.head .card{background:none;border:none;box-shadow:none;height:auto;padding:2px 4px}
.head-text{
  font-family:var(--fd);font-weight:700;font-size:15px;letter-spacing:1.5px;
  color:var(--c);white-space:pre-wrap;max-width:420px;outline:none;
}
.node.head.sel .head-text{box-shadow:0 0 0 1.5px var(--sel);border-radius:4px}

/* ── annotations: spec card ───────────────────────────── */
.node.spec{width:max-content;min-width:220px;max-width:340px;height:auto}
.node.spec .card{
  display:block;height:auto;padding:0;overflow:hidden;border-radius:10px;
  background:var(--card1);border:1px solid var(--line2);box-shadow:0 8px 20px #00000030;
}
.spec-title{
  font-family:var(--fd);font-weight:600;font-size:11px;letter-spacing:1.2px;outline:none;
  padding:7px 11px;color:var(--c);
  background:color-mix(in srgb,var(--c) 18%,var(--card1));border-bottom:1px solid var(--line2);
}
.spec-body{
  font-family:var(--fm);font-size:10px;line-height:1.6;color:var(--mut);
  padding:8px 11px;white-space:pre-wrap;word-break:break-word;outline:none;
}
.node.spec.sel .card{border-color:var(--sel);box-shadow:0 0 0 1px var(--sel)}

/* ── annotations: metric chip ─────────────────────────── */
.node.chip{width:max-content;height:auto}
.node.chip .card{
  height:auto;display:flex;align-items:center;gap:6px;padding:4px 10px;border-radius:20px;
  background:color-mix(in srgb,var(--c) 10%,var(--card1));
  border:1px solid color-mix(in srgb,var(--c) 45%,var(--mix));
}
.chip-dot{width:7px;height:7px;border-radius:50%;background:var(--c);flex:none}
.chip-text{font-family:var(--fm);font-size:10px;font-weight:700;letter-spacing:.4px;color:var(--text);white-space:nowrap;outline:none}
.node.chip.sel .card{border-color:var(--sel);box-shadow:0 0 0 1px var(--sel)}

/* ports never exist on annotations */
.node.head .port,.node.spec .port,.node.chip .port,.node.note .port{display:none}

/* ── process node ─────────────────────────────────────── */
.node.process{width:220px;height:auto;min-height:80px}
.node.process .card{display:block;height:auto;padding:0;overflow:hidden;border-radius:11px}
.proc-head{display:flex;align-items:center;gap:10px;padding:10px 12px;border-bottom:1px solid var(--line)}
.proc-head .n-icon{width:30px;height:30px;border-radius:8px}
.proc-head .n-icon svg{width:17px;height:17px}
.st-list{padding:8px 10px 10px}
.st-row{display:flex;align-items:center;gap:8px;padding:4px 2px}
.st-dot{flex:none;width:7px;height:7px;border-radius:50%;background:var(--dim);opacity:.5;transition:all .2s}
.st-name{flex:1;min-width:0;font-size:10.5px;font-weight:500;color:var(--dim);transition:color .2s;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.st-bar{flex:none;width:52px;height:3px;border-radius:2px;background:color-mix(in srgb,var(--dim) 25%,transparent);overflow:hidden}
.st-bar i{display:block;height:100%;background:var(--c);transform:scaleX(0);transform-origin:0 50%}
.st-row.on .st-dot{background:var(--c);opacity:1;box-shadow:0 0 8px color-mix(in srgb,var(--c) 70%,transparent)}
.st-row.on .st-name{color:var(--text)}
.st-row.done .st-dot{background:var(--c);opacity:.7}
.st-row.done .st-name{color:var(--mut)}

/* arrival ping */
.node.process .card::after{content:'';position:absolute;inset:0;border-radius:11px;pointer-events:none}
.node.process.ping .card::after{animation:ping .5s ease-out}
@keyframes ping{
  0%{box-shadow:0 0 0 0 color-mix(in srgb,var(--c) 55%,transparent)}
  100%{box-shadow:0 0 0 14px color-mix(in srgb,var(--c) 0%,transparent)}
}

/* ── queue with topics ────────────────────────────────── */
.node.queue{width:240px;height:auto;min-height:90px}
.node.queue .card{display:block;height:auto;padding:0;overflow:hidden;border-radius:11px}
.node.queue .port{display:none}                 /* топики — единственные порты */
.queue-head{display:flex;align-items:center;gap:10px;height:52px;padding:0 12px;box-sizing:border-box;border-bottom:1px solid var(--line)}
.queue-head .n-icon{width:30px;height:30px;border-radius:8px}
.queue-head .n-icon svg{width:17px;height:17px}
.topic-list{padding:6px 10px 8px}               /* отступы от обеих границ */
.topic-row{display:flex;align-items:center;height:28px;border-radius:7px}
.topic-row:hover{background:color-mix(in srgb,var(--c) 8%,transparent)}
.topic-name{
  flex:none;max-width:110px;padding:0 6px;
  font-family:var(--fm);font-size:10px;letter-spacing:.3px;color:var(--mut);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.topic-track{
  flex:1;min-width:12px;height:0;margin:0 7px;
  border-top:1.5px dashed color-mix(in srgb,var(--c) 55%,var(--dim));
  opacity:.55;transition:opacity .15s;
}
.topic-row:hover .topic-track{opacity:.95}
.topic-anchor{
  flex:none;width:11px;height:11px;border-radius:50%;position:relative;z-index:6;
  background:var(--bg);border:2px solid var(--c);cursor:crosshair;
  transition:transform .15s, box-shadow .15s;
}
.topic-anchor:hover{transform:scale(1.4);box-shadow:0 0 8px color-mix(in srgb,var(--c) 60%,transparent)}


#storyBtn.on{color:var(--acc);border-color:var(--acc)}

#canvas.story-focus .node, #canvas.story-focus .edge,
#canvas.story-focus .group, #canvas.story-focus .edge-label{transition:opacity .3s}
#canvas.story-focus .node:not(.shi):not(.svis){opacity:.35}
#canvas.story-focus .edge:not(.shi){opacity:.22}
#canvas.story-focus .group:not(.shi):not(.svis){opacity:.4}
#canvas.story-focus .edge-label:not(.shi){opacity:.15}
#canvas.story-focus .fdot{opacity:.12}

.node.shi .card{box-shadow:0 0 0 2px var(--sel),0 0 18px color-mix(in srgb,var(--sel) 45%,transparent)}
.node.svis .card{box-shadow:0 0 0 1px color-mix(in srgb,var(--sel) 55%,transparent)}
.group.shi,.group.svis{box-shadow:0 0 0 2px var(--sel)}
.edge.shi .edge-line{stroke:var(--acc);stroke-width:2.4}
.edge.shi .arrow-a,.edge.shi .arrow-b{fill:var(--acc)}
.edge-label.shi{opacity:1;color:var(--acc)}

.story-dot{
  position:absolute;left:0;top:0;width:12px;height:12px;border-radius:50%;
  background:var(--acc);box-shadow:0 0 12px var(--acc),0 0 4px var(--acc);
  pointer-events:none;z-index:5;
}
.node.sping .card{animation:sping .45s ease-out}
@keyframes sping{
  0%{box-shadow:0 0 0 0 color-mix(in srgb,var(--sel) 60%,transparent)}
  100%{box-shadow:0 0 0 16px color-mix(in srgb,var(--sel) 0%,transparent)}
}

/* story-seq: помеченные связи читаются сразу */
.edge.seq .edge-line{stroke:color-mix(in srgb,var(--acc) 70%,var(--line3))}
.edge.seq .arrow-a,.edge.seq .arrow-b{fill:color-mix(in srgb,var(--acc) 70%,var(--line3))}
.seq-badge{
  position:absolute;transform:translate(-50%,-50%);
  min-width:16px;height:16px;padding:0 4px;border-radius:8px;
  background:var(--acc);color:#04241d;
  font-family:var(--fm);font-size:9px;font-weight:700;
  display:flex;align-items:center;justify-content:center;
  box-shadow:0 2px 8px #00000050;pointer-events:none;z-index:4;
}

/* ── icon node ───────────────────────────────────────── */
.node.icon{width:auto;height:auto}
.node.icon .card{
  width:var(--sz,96px);height:var(--sz,96px);padding:0;
  display:flex;align-items:center;justify-content:center;border-radius:16px;
}
.node.icon .big-ico{width:58%;height:58%;display:flex;align-items:center;justify-content:center;pointer-events:none}
.node.icon .big-ico svg{width:100%;height:100%;stroke:var(--c);fill:none;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round}
.icon-label{
  position:absolute;top:100%;left:50%;transform:translateX(-50%);
  margin-top:6px;text-align:center;pointer-events:none;
  font-family:var(--fm);font-size:9px;letter-spacing:1.2px;color:var(--mut);
  max-width:var(--sz,96px);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.n-rz{
  position:absolute;right:-5px;bottom:-5px;width:12px;height:12px;border-radius:4px;
  background:var(--sel);border:2px solid var(--bg);cursor:nwse-resize;
  opacity:0;transition:opacity .15s;z-index:5;
}
.node.sel .n-rz{opacity:1}

/* icon picker in inspector */
.glyph-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:6px}
.glyph-btn{
  height:40px;border-radius:8px;background:var(--panel2);border:1px solid var(--line2);
  display:flex;align-items:center;justify-content:center;color:var(--mut);transition:all .12s;
}
.glyph-btn svg{width:20px;height:20px;stroke:currentColor;fill:none;stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round}
.glyph-btn:hover{color:var(--txt)}
.glyph-btn.on{color:var(--acc);border-color:var(--acc)}

svg.brand{stroke:none !important}