/* 网络探索器 · 共用样式（v2 设计系统）
   与主站共用令牌：深墨蓝单一交互色、铜色只作证据/关卡编码、系统字体栈、mono 承担仪表读数。
   图元语义色（层级 / 关系 / 证据层）由 network_explorer.js 内联提供，此处不覆盖 ——
   那是数据编码，不是 chrome。 */
:root {
  /* 与主站同一套暖白表面：探索器嵌在米白纸面里，chrome 必须跟着走，
     否则冷灰面板会在暖纸上显出一块生硬的灰。图元语义色不动。 */
  --bg:          #ECE9E2;
  --panel-bg:    #FBFAF6;
  --border:      #DDD8CD;
  --border-soft: #E8E3DA;
  --text:        #18191B;
  --text-2:      #3A3B3F;
  --text-dim:    #63646A;
  --text-mute:   #82858D;

  /* 唯一交互色 */
  --accent:      #16457A;
  --accent-deep: #0E3057;
  --accent-tint: rgba(22, 69, 122, .07);
  --accent-line: rgba(22, 69, 122, .26);

  /* 唯一编码色：铜（关卡 / critical / 证据层标记） */
  --gate:        #9A5B1F;
  --gate-tint:   rgba(154, 91, 31, .08);

  --chip-bg:     #F4F2EC;
  --glass-bg:    rgba(252, 251, 247, .86);
  --glass-blur:  saturate(180%) blur(20px);

  --sh-1: 0 1px 2px rgba(28, 26, 22, .06);
  --sh-2: 0 2px 10px rgba(28, 26, 22, .07), 0 1px 2px rgba(28, 26, 22, .05);
  --sh-3: 0 8px 28px rgba(28, 26, 22, .15), 0 2px 6px rgba(28, 26, 22, .07);

  --r-xs: 5px;
  --r-sm: 8px;
  --r-md: 11px;
  --r-pill: 999px;

  /* 与主站同一份字体栈：拉丁在前、中文在后，栈首不用 system-ui */
  --font-sans:
    -apple-system, BlinkMacSystemFont, "Segoe UI", "Helvetica Neue", Arial,
    "PingFang SC", "Heiti SC", "HarmonyOS Sans SC",
    "MiSans", "OPPO Sans", "vivo Sans",
    "Microsoft YaHei", "微软雅黑",
    "Noto Sans CJK SC", "Source Han Sans SC", "Noto Sans SC",
    sans-serif;
  --font-mono:
    ui-monospace, "SF Mono", SFMono-Regular, Menlo, "Cascadia Mono", Consolas,
    "PingFang SC", "Microsoft YaHei", monospace;

  --ease: cubic-bezier(.22, .61, .36, 1);
}

* { box-sizing: border-box; margin: 0; padding: 0; }
html, body { height: 100%; }
body.nx-body {
  font-family: var(--font-sans);
  background: var(--bg);
  color: var(--text-2);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  /* 不写 -webkit-font-smoothing: antialiased —— 中文笔画会发虚（排版规格 §1.6） */
}
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 3px; }

/* ---------- 顶栏 ---------- */
.nx-header {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 16px;
  background: var(--glass-bg);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  border-bottom: 1px solid var(--border-soft);
  flex-wrap: wrap;
  justify-content: flex-end;
  z-index: 20;
}
.nx-title {
  font-size: 14.5px; font-weight: 600; color: var(--text);
  letter-spacing: -.01em; white-space: nowrap;
}
.nx-subtitle {
  font-family: var(--font-mono);
  font-size: 11px; letter-spacing: .06em; color: var(--text-mute);
  white-space: nowrap; font-variant-numeric: tabular-nums;
}
.nx-header .spacer { flex: 1; }

.nx-search-wrap { position: relative; }
.nx-search {
  width: 210px; padding: 7px 30px 7px 12px;
  border: 1px solid var(--border); border-radius: var(--r-pill);
  font-size: 13px; font-family: inherit;
  background: var(--panel-bg); color: var(--text);
  outline: none;
  transition: border-color .16s linear, box-shadow .16s linear;
}
.nx-search::placeholder { color: var(--text-mute); }
.nx-search:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-tint);
}
.nx-search-clear {
  position: absolute; right: 8px; top: 50%; transform: translateY(-50%);
  border: none; background: none; color: var(--text-mute);
  cursor: pointer; font-size: 14px; display: none; line-height: 1;
}
.nx-search-clear:hover { color: var(--text); }
.nx-search-hits {
  position: absolute; top: calc(100% + 6px); left: 0; width: 300px;
  background: var(--panel-bg); border: 1px solid var(--border-soft);
  border-radius: var(--r-md);
  box-shadow: var(--sh-3); z-index: 30;
  max-height: 280px; overflow-y: auto; display: none;
  padding: 4px;
}
.nx-search-hits .hit {
  padding: 7px 10px; font-size: 13px; cursor: pointer; border-radius: var(--r-xs);
  display: flex; justify-content: space-between; gap: 8px;
}
.nx-search-hits .hit:hover, .nx-search-hits .hit.active {
  background: var(--accent-tint); color: var(--accent-deep);
}
.nx-search-hits .hit .sub { color: var(--text-dim); font-size: 11.5px; }

.nx-btn {
  padding: 6px 13px; font-size: 12.5px; font-family: inherit;
  border: 1px solid var(--border);
  border-radius: var(--r-sm); background: var(--panel-bg); color: var(--text-2);
  cursor: pointer; white-space: nowrap;
  transition: background .16s linear, border-color .16s linear, color .16s linear,
              transform .1s var(--ease);
}
.nx-btn:hover { background: var(--chip-bg); color: var(--text); }
.nx-btn:active { transform: scale(.96); }
.nx-btn.primary { border-color: var(--accent-line); color: var(--accent); }
.nx-btn.primary:hover { background: var(--accent-tint); }

/* ---------- 主体三栏 ---------- */
.nx-main { flex: 1; display: flex; min-height: 0; }

/* 左侧图例 / 筛选 */
.nx-legend {
  width: 252px; flex: none; overflow-y: auto;
  background: var(--panel-bg); border-right: 1px solid var(--border-soft);
  padding: 12px 12px 28px;
  scrollbar-width: thin;
}
.nx-legend h3 {
  font-family: var(--font-mono);
  font-size: 10.5px; color: var(--text-mute); font-weight: 600;
  margin: 20px 0 7px; letter-spacing: .12em;
  display: flex; align-items: center; justify-content: space-between;
}
.nx-legend h3:first-child { margin-top: 2px; }
.nx-legend .hint {
  font-size: 11.5px; color: var(--text-dim); line-height: 1.65;
  background: var(--chip-bg); border-radius: var(--r-sm);
  padding: 9px 11px; margin-bottom: 4px;
}
.nx-chip {
  display: flex; align-items: center; gap: 8px;
  padding: 5px 8px; margin: 2px 0; border-radius: var(--r-sm);
  font-size: 12.5px; cursor: pointer; border: 1px solid transparent;
  user-select: none; line-height: 1.35;
  transition: background .14s linear, opacity .14s linear;
}
.nx-chip:hover { background: var(--chip-bg); }
.nx-chip.focus {
  background: var(--accent-tint); border-color: var(--accent-line);
  color: var(--accent-deep); font-weight: 600;
}
.nx-chip.hidden-cat { opacity: .4; }
.nx-chip.hidden-cat .nx-chip-label { text-decoration: line-through; }
.nx-chip-swatch { flex: none; width: 14px; height: 14px; border-radius: 4px; position: relative; }
.nx-chip-swatch.line { height: 0; border-top-width: 3px; border-top-style: solid; border-radius: 0; }
.nx-chip-swatch.line.dashed { border-top-style: dashed; }
.nx-chip-swatch.ring { border-radius: 50%; background: #fff; border: 2.5px solid; }
.nx-chip-swatch.diamond { transform: rotate(45deg) scale(.82); }
.nx-chip-label { flex: 1; }
.nx-chip-count {
  font-family: var(--font-mono); font-size: 10.5px; color: var(--text-mute);
  font-variant-numeric: tabular-nums;
}
.nx-chip-eye {
  flex: none; border: none; background: none; cursor: pointer;
  font-size: 13px; color: var(--text-mute); padding: 0 2px; line-height: 1;
  opacity: 0; transition: opacity .14s;
}
.nx-chip:hover .nx-chip-eye, .nx-chip.hidden-cat .nx-chip-eye { opacity: 1; }
.nx-group-reset {
  border: none; background: none; color: var(--accent); cursor: pointer;
  font-size: 11px; padding: 0; font-family: var(--font-sans); letter-spacing: 0;
  font-weight: 400;
}
.nx-group-reset:hover { text-decoration: underline; }

/* 画布 */
.nx-canvas-wrap { flex: 1; position: relative; min-width: 0; background: var(--bg); }
.nx-svg { width: 100%; height: 100%; display: block; cursor: grab; }
.nx-svg.panning { cursor: grabbing; }
.nx-zoombar {
  position: absolute; left: 14px; bottom: 14px; display: flex; flex-direction: column; gap: 6px;
}
.nx-zoombar .nx-btn {
  width: 32px; height: 32px; padding: 0; font-size: 15px;
  background: var(--glass-bg);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  box-shadow: var(--sh-1);
}
.nx-status {
  position: absolute; left: 14px; top: 12px;
  font-family: var(--font-mono);
  font-size: 11px; letter-spacing: .04em; color: var(--text-dim);
  font-variant-numeric: tabular-nums;
  background: var(--glass-bg);
  -webkit-backdrop-filter: var(--glass-blur);
  backdrop-filter: var(--glass-blur);
  border: 1px solid var(--border-soft);
  border-radius: var(--r-sm); padding: 5px 11px; pointer-events: none;
  max-width: 65%; box-shadow: var(--sh-1);
}
.nx-tooltip {
  position: absolute; pointer-events: none; z-index: 40; display: none;
  background: rgba(20, 23, 28, .92);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  color: #fff; font-size: 12px;
  padding: 6px 10px; border-radius: var(--r-xs); max-width: 300px; line-height: 1.55;
  box-shadow: 0 6px 20px rgba(0, 0, 0, .28);
}

/* 右侧详情 */
.nx-detail {
  width: 322px; flex: none; overflow-y: auto;
  background: var(--panel-bg); border-left: 1px solid var(--border-soft);
  padding: 16px 18px 32px; display: none;
  scrollbar-width: thin;
}
.nx-detail.open { display: block; }
.nx-detail .close-btn {
  float: right; border: none; background: none; font-size: 16px;
  color: var(--text-mute); cursor: pointer; line-height: 1;
}
.nx-detail .close-btn:hover { color: var(--text); }
.nx-detail h2 {
  font-size: 16px; font-weight: 600; color: var(--text);
  letter-spacing: -.015em; margin-bottom: 3px; padding-right: 24px;
}
.nx-detail .sub { font-size: 12px; color: var(--text-dim); margin-bottom: 12px; }
.nx-detail .tags { display: flex; flex-wrap: wrap; gap: 5px; margin-bottom: 14px; }
.nx-detail .tag {
  font-size: 11px; padding: 3px 9px; border-radius: var(--r-pill);
  background: var(--chip-bg); color: var(--text-2);
}
/* 关卡 / critical 语义走铜色，与主站证据栏同一编码 */
.nx-detail .tag.warn { background: var(--gate-tint); color: var(--gate); }
.nx-detail .tag.blue { background: var(--accent-tint); color: var(--accent); }
.nx-detail h4 {
  font-family: var(--font-mono);
  font-size: 10.5px; color: var(--text-mute); font-weight: 600; letter-spacing: .12em;
  margin: 20px 0 8px; border-bottom: 1px solid var(--border-soft); padding-bottom: 6px;
}
.nx-metric-grid {
  display: grid; grid-template-columns: 1fr 1fr; gap: 7px 8px; font-size: 12.5px;
}
.nx-metric-grid .m {
  background: var(--chip-bg); border-radius: var(--r-sm); padding: 8px 10px;
}
.nx-metric-grid .m b {
  display: block; font-family: var(--font-mono);
  font-size: 15px; font-weight: 600; color: var(--text);
  font-variant-numeric: tabular-nums; letter-spacing: -.01em;
}
.nx-metric-grid .m span { color: var(--text-dim); font-size: 10.5px; }
.nx-nbr-list { list-style: none; font-size: 12.5px; }
.nx-nbr-list li {
  display: flex; align-items: baseline; gap: 6px; padding: 4px 6px;
  border-radius: var(--r-xs); cursor: pointer;
  transition: background .14s linear;
}
.nx-nbr-list li:hover { background: var(--chip-bg); }
.nx-nbr-list .rel { color: var(--text-mute); font-size: 11px; flex: none; }
.nx-nbr-list .nm { color: var(--accent); }
.nx-nbr-list .ev {
  margin-left: auto; font-family: var(--font-mono);
  font-size: 10px; letter-spacing: .04em; color: var(--text-mute); flex: none;
}
.nx-kv { font-size: 12.5px; line-height: 1.75; }
.nx-kv dt {
  color: var(--text-mute); float: left; width: 84px; clear: left;
  font-family: var(--font-mono); font-size: 11px; letter-spacing: .06em;
  line-height: 1.95;
}
.nx-kv dd { margin-left: 92px; overflow-wrap: break-word; }
.nx-empty { font-size: 12px; color: var(--text-mute); padding: 4px; }

/* ---------- SVG 元素状态 ---------- */
.nx-edge-path { fill: none; transition: opacity .15s; cursor: pointer; }
.nx-edge-hit { fill: none; stroke: transparent; stroke-width: 11; cursor: pointer; }
.nx-edge-arrow { transition: opacity .15s; }
.nx-node { cursor: pointer; }
.nx-node-shape { transition: opacity .15s; }
.nx-label {
  font-size: 11px; fill: #18191B; pointer-events: none;
  paint-order: stroke; stroke: rgba(236, 233, 226, .90); stroke-width: 2.6px;
}
.nx-label.key { font-weight: 700; font-size: 12.5px; }
g.dim { opacity: .13; }
g.dim .nx-label { display: none; }
g.hide { display: none; }
/* 选中高亮用交互色，与主站链接同色 */
g.hl-node .nx-node-shape { filter: drop-shadow(0 0 5px rgba(22, 69, 122, .85)); }
g.hl-edge .nx-edge-path { filter: drop-shadow(0 0 3px rgba(22, 69, 122, .8)); }
.nx-band-label { font-size: 13px; font-weight: 600; fill: #8C94A2; pointer-events: none; }
.nx-band-rect { pointer-events: none; }
/* 断供叉：数据语义，保留告警红 */
.nx-severed-x { font-size: 15px; font-weight: 700; fill: #A3262F; pointer-events: none; }
.nx-bundle-badge { font-size: 10px; font-weight: 700; fill: #fff; pointer-events: none; }

@media (max-width: 900px) {
  .nx-legend { width: 200px; }
  .nx-detail { width: 270px; }
  .nx-search { width: 180px; }
}

/* 窄栏嵌入（报告正文栏只有 40em ≈ 680px）：详情栏改为浮在画布上的浮层，
   不再从画布里抠走 300px。否则三栏并排后画布只剩两百多像素，网络看不成。 */
@media (max-width: 860px) {
  .nx-main { position: relative; }
  .nx-detail {
    position: absolute; right: 0; top: 0; bottom: 0; z-index: 15;
    width: min(300px, 62%);
    box-shadow: -8px 0 24px rgba(20, 23, 28, .10);
    border-left: 1px solid var(--border);
  }
}
/* 图例再窄就会把「L1 材料/设备/EDA/封测」折成四行，图例比画布还高。
   宁可让图例保持能放下一行标签的宽度，画布不够就靠缩放与拖拽。 */
@media (max-width: 860px) {
  .nx-legend { width: 190px; padding: 10px 9px 24px; }
  .nx-chip { font-size: 11.5px; gap: 6px; padding: 4px 6px; }
  .nx-legend .hint { font-size: 10.5px; line-height: 1.55; padding: 7px 9px; }
  .nx-legend h3 { font-size: 10px; margin: 16px 0 6px; }
  .nx-search { width: 150px; }
  .nx-metric-grid { grid-template-columns: 1fr; }
}
@media (max-width: 700px) {
  .nx-legend { width: 168px; padding: 10px 8px 24px; }
  .nx-detail { padding: 14px 12px 28px; }
  .nx-search { width: 140px; }
}

/* 手机：图例并排会吃掉将近一半的宽度，网络只剩两百来像素。改成上下叠：
   画布占上半屏拿到整幅宽度，图例移到下面自己滚动。 */
@media (max-width: 560px) {
  .nx-main { flex-direction: column; }
  /* 画布在上：图才是主角，不该让读者先划过一屏图例才看到网络 */
  .nx-canvas-wrap { order: 1; flex: 0 0 58%; min-height: 0; }
  .nx-legend {
    order: 2;
    width: 100%; flex: 1 1 auto; min-height: 0;
    border-right: 0; border-top: 1px solid var(--border);
    padding: 10px 12px 20px;
  }
  .nx-legend h3 { margin-top: 14px; }
  .nx-detail { width: min(300px, 78%); }
  .nx-header { padding: 8px 12px; }
  .nx-title { font-size: 14px; }
  .nx-subtitle { display: none; }   /* 数字读数在窄屏挤掉搜索框，隐掉 */
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    transition-duration: .001ms !important;
  }
}

/* 次要节点的标签默认不画出来。节点数上到几百之后，全部标注会把画面糊成一片，
   而这些节点多数只有一条边，名字对通读没有帮助。悬停在它上面、或点选与它
   相连的主体时，标签照常显示。 */
.nx-label.minor { display: none; }
.nx-node:hover .nx-label.minor,
.nx-node.hl-node .nx-label.minor { display: inline; }
