/* motion/topology.css — 运行拓扑：舞台、图例、SVG 节点/连线与入场·循环动画。 */

.topology-section {
  background: var(--bg-deep);
  border-top: 1px solid var(--line);
}

/* -------------------------------------------------------------------------- */
/* 舞台：无 JS 时保持塌缩，避免空盒子；SVG 注入后按比例撑开。                 */
/* -------------------------------------------------------------------------- */

.topology-stage {
  max-width: 960px;
  margin: 0 auto;
}

.topology-stage:not(:empty) {
  margin-bottom: 36px;
}

.topology-stage .topo-svg {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
  pointer-events: none;
  user-select: none;
  font-family: ui-monospace, SFMono-Regular, Menlo, "PingFang SC", "Microsoft YaHei", monospace;
}

/* -------------------------------------------------------------------------- */
/* 图例：编辑风四列；入场错峰交给 [data-stagger]，这里只排版。                 */
/* -------------------------------------------------------------------------- */

.topology-legend {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  margin: 0;
  padding: 0;
  list-style: none;
  border-top: 1px solid var(--line);
  border-left: 1px solid var(--line);
}

.topology-legend li {
  padding: 22px 24px;
  border-right: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}

.topology-legend strong {
  display: block;
  color: var(--text);
  font-size: 14px;
  font-weight: 700;
}

.topology-legend span {
  display: block;
  margin-top: 6px;
  color: var(--muted);
  font-size: 12px;
  line-height: 1.55;
}

@media (max-width: 980px) {
  .topology-legend {
    grid-template-columns: 1fr 1fr;
  }
}

@media (max-width: 760px) {
  .topology-legend {
    grid-template-columns: 1fr;
  }

  .topology-legend li {
    padding: 18px 16px;
  }
}

/* -------------------------------------------------------------------------- */
/* SVG 静态外观                                                                */
/* -------------------------------------------------------------------------- */

.topo-boundary {
  fill: none;
  stroke: var(--amber);
  stroke-width: 1;
  stroke-dasharray: 5 5;
  stroke-opacity: 0.38;
}

.topo-boundary-label {
  fill: var(--amber);
  font-size: 11px;
  letter-spacing: 0.04em;
}

.topo-link-exec {
  stroke: var(--line-strong);
  stroke-width: 1;
  stroke-linecap: round;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
}

.topo-link-monitor {
  stroke: #7d8f87;
  stroke-width: 1;
  stroke-linecap: round;
  stroke-dasharray: 4 4;
  opacity: 0;
}

.topo-flow {
  stroke: var(--mint-strong);
  stroke-width: 1.55;
  stroke-linecap: round;
  stroke-dasharray: 0.08 0.92;
  stroke-dashoffset: 0;
  opacity: 0;
  pointer-events: none;
}

.topo-node {
  transform-box: fill-box;
  transform-origin: center;
  opacity: 0;
  transform: scale(0.92);
}

.topo-node-hub .topo-node-shape {
  fill: rgba(185, 248, 211, 0.06);
  stroke: var(--mint);
  stroke-width: 1.25;
}

.topo-node-exec .topo-node-shape {
  fill: rgba(255, 255, 255, 0.02);
  stroke: var(--line-strong);
  stroke-width: 1;
}

.topo-node-monitor .topo-node-shape {
  fill: rgba(255, 255, 255, 0.015);
  stroke: #6d7f77;
  stroke-width: 1;
}

.topo-label {
  font-size: 13px;
  font-weight: 650;
}

.topo-node-hub .topo-label-title {
  fill: var(--mint);
  font-size: 14px;
  font-weight: 750;
}

.topo-node-hub .topo-label-sub {
  fill: var(--muted);
  font-size: 11px;
  font-weight: 500;
}

.topo-node-exec .topo-label {
  fill: var(--text);
}

.topo-node-monitor .topo-label {
  fill: var(--muted);
  font-size: 12px;
  font-weight: 600;
}

.topo-monitor-tag {
  fill: #7a8c84;
  font-size: 11px;
  font-weight: 500;
}

.topo-boundary,
.topo-boundary-label {
  opacity: 0;
}

/* -------------------------------------------------------------------------- */
/* 入场：.topo-in 一次触发。线用 pathLength=1 生长；监测虚线只淡入。           */
/* -------------------------------------------------------------------------- */

.topology-stage.topo-in .topo-boundary {
  animation: topo-fade 0.7s ease forwards;
}

.topology-stage.topo-in .topo-boundary-label {
  animation: topo-fade-label 0.7s ease forwards;
}

.topology-stage.topo-in .topo-link-exec {
  animation: topo-draw 0.72s cubic-bezier(0.22, 1, 0.36, 1) forwards;
}

.topology-stage.topo-in .topo-link-exec[data-i="0"] { animation-delay: 0ms; }
.topology-stage.topo-in .topo-link-exec[data-i="1"] { animation-delay: 120ms; }
.topology-stage.topo-in .topo-link-exec[data-i="2"] { animation-delay: 240ms; }
.topology-stage.topo-in .topo-link-exec[data-i="3"] { animation-delay: 360ms; }

.topology-stage.topo-in .topo-link-monitor {
  opacity: 0.55;
  transition: opacity 0.65s ease;
}

.topology-stage.topo-in .topo-link-monitor[data-i="4"] { transition-delay: 480ms; }
.topology-stage.topo-in .topo-link-monitor[data-i="5"] { transition-delay: 600ms; }

.topology-stage.topo-in .topo-node {
  animation: topo-pop 0.5s cubic-bezier(0.22, 1, 0.36, 1) forwards;
}

.topology-stage.topo-in .topo-node[data-i="0"] { animation-delay: 300ms; }
.topology-stage.topo-in .topo-node[data-i="1"] { animation-delay: 420ms; }
.topology-stage.topo-in .topo-node[data-i="2"] { animation-delay: 540ms; }
.topology-stage.topo-in .topo-node[data-i="3"] { animation-delay: 660ms; }
.topology-stage.topo-in .topo-node[data-i="4"] { animation-delay: 780ms; }
.topology-stage.topo-in .topo-node[data-i="5"] { animation-delay: 900ms; }
.topology-stage.topo-in .topo-node[data-i="6"] { animation-delay: 1020ms; }

@keyframes topo-draw {
  to { stroke-dashoffset: 0; }
}

@keyframes topo-pop {
  to {
    opacity: 1;
    transform: scale(1);
  }
}

@keyframes topo-fade {
  to { opacity: 1; }
}

@keyframes topo-fade-label {
  to { opacity: 0.72; }
}

/* -------------------------------------------------------------------------- */
/* 循环：仅 .topo-live 作用域内开 animation；离屏/后台由 JS 摘类即停。         */
/* -------------------------------------------------------------------------- */

.topology-stage.topo-live .topo-flow {
  opacity: 0.8;
  animation-name: topo-flow;
  animation-timing-function: linear;
  animation-iteration-count: infinite;
}

.topology-stage.topo-live .topo-flow[data-i="0"] {
  animation-duration: 6.4s;
  animation-delay: -2.1s;
}

.topology-stage.topo-live .topo-flow[data-i="1"] {
  animation-duration: 7.2s;
  animation-delay: -4.8s;
}

.topology-stage.topo-live .topo-flow[data-i="2"] {
  animation-duration: 8.1s;
  animation-delay: -1.3s;
}

.topology-stage.topo-live .topo-flow[data-i="3"] {
  animation-duration: 8.8s;
  animation-delay: -5.6s;
}

.topology-stage.topo-live .topo-node-hub .topo-node-shape {
  animation: topo-hub-breathe 4.8s ease-in-out infinite;
}

.topology-stage.topo-live .topo-link-monitor {
  animation: topo-monitor-breathe 8.5s ease-in-out infinite;
}

@keyframes topo-flow {
  to { stroke-dashoffset: -1; }
}

@keyframes topo-hub-breathe {
  0%, 100% {
    stroke-opacity: 0.72;
    filter: drop-shadow(0 0 0 transparent);
  }
  50% {
    stroke-opacity: 1;
    filter: drop-shadow(0 0 5px rgba(112, 233, 164, 0.22));
  }
}

@keyframes topo-monitor-breathe {
  0%, 100% { opacity: 0.38; }
  50% { opacity: 0.62; }
}

/* -------------------------------------------------------------------------- */
/* 降级：减少动态效果时直接终态；无运动基建时避免节点停在 opacity:0。         */
/* -------------------------------------------------------------------------- */

html.motion-reduced .topology-stage .topo-boundary,
html.motion-reduced .topology-stage .topo-link-exec,
html.motion-reduced .topology-stage .topo-link-monitor,
html.motion-reduced .topology-stage .topo-node,
html.motion-reduced .topology-stage .topo-node-hub .topo-node-shape,
html.motion-reduced .topology-stage .topo-flow,
html:not(.has-motion) .topology-stage .topo-boundary,
html:not(.has-motion) .topology-stage .topo-link-exec,
html:not(.has-motion) .topology-stage .topo-link-monitor,
html:not(.has-motion) .topology-stage .topo-node,
html:not(.has-motion) .topology-stage .topo-node-hub .topo-node-shape {
  animation: none;
  transition: none;
  opacity: 1;
  transform: none;
  filter: none;
  stroke-dashoffset: 0;
  stroke-opacity: 1;
}

html.motion-reduced .topology-stage .topo-boundary-label,
html:not(.has-motion) .topology-stage .topo-boundary-label {
  animation: none;
  opacity: 0.72;
}

html.motion-reduced .topology-stage .topo-link-monitor,
html:not(.has-motion) .topology-stage .topo-link-monitor {
  opacity: 0.55;
}

html.motion-reduced .topology-stage .topo-flow,
html:not(.has-motion) .topology-stage .topo-flow {
  opacity: 0;
}
