:root {
  --bg: #07080a;
  --ink: #e8ecf1;
  --cycle: 8s;
}

* { margin: 0; padding: 0; box-sizing: border-box; }

html, body { height: 100%; }

body {
  background: var(--bg);
  overflow: hidden;
  display: grid;
  place-items: center;
  cursor: default;
}

/* faint dot grid that fades toward the edges */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  background-image: radial-gradient(rgba(232, 236, 241, 0.07) 1px, transparent 1px);
  background-size: 28px 28px;
  mask-image: radial-gradient(ellipse at center, #000 10%, transparent 65%);
  -webkit-mask-image: radial-gradient(ellipse at center, #000 10%, transparent 65%);
  pointer-events: none;
}

/* soft ambient glow behind the mark */
body::after {
  content: "";
  position: fixed;
  width: 70vmin;
  height: 70vmin;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  background: radial-gradient(circle, rgba(124, 243, 255, 0.07), rgba(155, 140, 255, 0.04) 40%, transparent 70%);
  filter: blur(20px);
  animation: ambient 12s ease-in-out infinite;
  pointer-events: none;
}

.stage {
  width: min(68vmin, 520px);
  aspect-ratio: 1;
  perspective: 900px;
  position: relative;
  z-index: 1;
}

.mark {
  width: 100%;
  height: 100%;
  transform-style: preserve-3d;
  transition: transform 0.6s cubic-bezier(0.2, 0.7, 0.2, 1);
  animation: float 10s ease-in-out infinite;
}

svg { width: 100%; height: 100%; overflow: visible; display: block; }

/* stagger: each step is a quarter of the packet's 8s lap */
.d0 { --d: 0s; } .d1 { --d: 1s; } .d2 { --d: 2s; } .d3 { --d: 3s; }
.d4 { --d: 4s; } .d5 { --d: 5s; } .d6 { --d: 6s; } .d7 { --d: 7s; }

.shape .outline {
  fill: none;
  stroke: url(#ink);
  stroke-width: 1.5;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
  animation: flare var(--cycle) cubic-bezier(0.2, 0.6, 0.2, 1) infinite;
  animation-delay: var(--d);
}

.shape .core {
  fill: url(#glow);
  opacity: 0.08;
  transform-box: fill-box;
  transform-origin: center;
  animation: pulse var(--cycle) cubic-bezier(0.2, 0.6, 0.2, 1) infinite;
  animation-delay: var(--d);
}

.shape .spin {
  transform-box: fill-box;
  transform-origin: center;
  animation: spin 60s linear infinite;
}
.shape:nth-child(even) .spin { animation-direction: reverse; }

.rail {
  fill: none;
  stroke: rgba(232, 236, 241, 0.08);
  stroke-width: 1;
  stroke-dasharray: 2 6;
}

.packet {
  fill: none;
  stroke: url(#ink);
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-dasharray: 40 680;
  stroke-dashoffset: 40;
  animation: travel var(--cycle) linear infinite;
  filter: url(#bloom);
}

.node {
  fill: var(--ink);
  opacity: 0.25;
  animation: node var(--cycle) ease-out infinite;
  animation-delay: var(--d);
}

@keyframes travel {
  to { stroke-dashoffset: -680; }
}

@keyframes pulse {
  0%   { opacity: 0.08; transform: scale(1); }
  4%   { opacity: 0.5;  transform: scale(1.06); }
  30%  { opacity: 0.08; transform: scale(1); }
  100% { opacity: 0.08; transform: scale(1); }
}

@keyframes flare {
  0%   { stroke-width: 1.5; filter: none; }
  4%   { stroke-width: 2.2; filter: drop-shadow(0 0 6px rgba(124, 243, 255, 0.6)); }
  30%  { stroke-width: 1.5; filter: none; }
  100% { stroke-width: 1.5; filter: none; }
}

@keyframes node {
  0%   { opacity: 0.25; }
  3%   { opacity: 1; }
  25%  { opacity: 0.25; }
  100% { opacity: 0.25; }
}

@keyframes spin { to { transform: rotate(360deg); } }

@keyframes float {
  0%, 100% { translate: 0 0; }
  50%      { translate: 0 -8px; }
}

@keyframes ambient {
  0%, 100% { opacity: 0.7; transform: translate(-50%, -50%) scale(1); }
  50%      { opacity: 1;   transform: translate(-50%, -50%) scale(1.08); }
}

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