/*
 * Cloud Topology — scroll-driven SVG story.
 * Markup + behaviour live in inc/shortcodes/topology.php and js/topology.js.
 */

.topology {
  position: relative;
}

.topology .story-track {
  position: relative;
  min-height: 100vh;
  /* js/topology.js hands the pinned scroll room back when the story ends
     and corrects the scroll position itself; browser scroll anchoring
     would correct for the same shift a second time. */
  overflow-anchor: none;
}

/* the story has played out — the frame stops sticking and the track keeps
   only the height the diagram itself needs */
.topology .story-track.is-done {
  min-height: 0;
}

.topology .story-track.is-done .sticky-frame {
  position: static;
}

/* How far below the sticky chrome (site header + top bar, plus the page
   nav where the template has one) the pinned frame sits. Registered as a
   <length> so the calc() inside the theme's stack variables computes to a
   real px value that js/topology.js can read back — it follows the same
   breakpoints as every other sticky element in the theme. */
@property --topology-pin-top {
  syntax: "<length>";
  inherits: false;
  initial-value: 0px;
}

.topology .sticky-frame {
  --topology-pin-top: var(--top-stack-height);
  position: sticky;
  top: var(--topology-pin-top);
  max-width: 1290px;
  margin: 0 auto;
  overflow: hidden;

  @media (min-width: 1025px) {
    --topology-pin-top: var(--top-stack-height-with-page-nav);
  }
}

.topology .frame {
  position: relative;
  width: 100%;
  border-radius: 22px;
}

.topology .frame__viewport {
  position: relative;
  width: 100%;
  aspect-ratio: 1290 / 740;
}

/* the markup gives the diagram a fixed 1290×740; scale it to the frame instead */
.topology .topology-diagram {
  display: block;
  width: 100%;
  height: auto;
}


.topology [id$="Bg"],
.topology [id$="Bd"],
.topology [id$="Dot"] {
  transition: fill .05s linear, stroke .05s linear;
}

/* Hidden at first paint so nothing flashes into view before JS takes over.
   The vm B chip is six overlapping elements in the source (two full
   rect+border sets plus two text variants), all driven as one unit. */
#elVmBChipBg,
#elVmBChipBd,
#elVmBChipBg2,
#elVmBChipBd2,
#elVmBChipText1,
#elVmBChipText2 { opacity: 0; }

#elVmCBg,
#elVmCBd,
#elVmCText { transform: translateX(52px); }

#elMainISPIconNew { opacity: 0; }

.topology circle[fill="#3BDB00"] {
  animation: topologyStatusDotPulse 1.8s ease-in-out infinite;
  transform-box: fill-box;
  transform-origin: center;
}

/* set by js/topology.js once a dot stops reporting healthy — the pulse
   above is keyed on the fill attribute, which JS never rewrites */
.topology circle.is-offline {
  animation: none;
  filter: none;
}

@keyframes topologyStatusDotPulse {
  0%, 100% { opacity: 1; filter: drop-shadow(0 0 0 rgba(59, 219, 0, 0)); }
  50%      { opacity: .65; filter: drop-shadow(0 0 4px rgba(59, 219, 0, .85)); }
}

/* ddos_attack="0": no banner claims the white band, so its label sits centred in it (0–52)
   rather than low, where the protection bar's line would touch it */
.topology .story-track[data-no-attack] #elExternalEnvLabel {
  transform: translateY(-18px);
}
