/* ===========================================================================
   Integrations hub.
   ---------------------------------------------------------------------------
   Trabbly in the middle, partners on an ellipse around it, wavy cubics between.
   Node positions and curve endpoints come from the same trigonometry in the
   generator, so every line lands on its node rather than near it.
   =========================================================================== */

.hub-wrap {
  background: var(--paper-2);
  padding: 104px 0 96px;
  overflow: hidden;
}

.hub {
  position: relative;
  margin-top: 40px;
  aspect-ratio: 960 / 560;
}

/* ── Wires ───────────────────────────────────────────────────────────────── */
.hub__wires {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
}
.hub__wire {
  fill: none;
  stroke: rgba(20, 112, 106, 0.3);
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-dasharray: 900;
  stroke-dashoffset: 900;
}
.hub.is-on .hub__wire {
  animation: hub-draw 1.15s cubic-bezier(0.3, 0.8, 0.3, 1) forwards;
  animation-delay: calc(var(--i) * 90ms);
}
@keyframes hub-draw {
  to {
    stroke-dashoffset: 0;
  }
}

/* Pulses travelling outward along each wire, so the diagram reads as data
   moving rather than as a static wiring chart. Motion comes from
   <animateMotion> in the markup, which follows the path by reference — the dot
   and the line therefore cannot drift apart the way a duplicated CSS
   offset-path would. Held back until the wires have finished drawing. */
.hub__pulse {
  fill: var(--spring);
  opacity: 0;
  filter: drop-shadow(0 0 5px rgba(99, 231, 127, 0.9));
  visibility: hidden;
}
.hub.is-on .hub__pulse {
  visibility: visible;
}

/* ── Core ────────────────────────────────────────────────────────────────── */
.hub__core {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  display: grid;
  justify-items: center;
  gap: 8px;
  width: 168px;
  height: 168px;
  align-content: center;
  border-radius: 50%;
  background: radial-gradient(circle at 50% 38%, #0d5c57, var(--ink) 72%);
  box-shadow:
    0 0 0 10px rgba(99, 231, 127, 0.07),
    0 0 0 22px rgba(99, 231, 127, 0.04),
    0 26px 50px -22px rgba(4, 35, 31, 0.6);
  z-index: 2;
}
.hub__core img {
  width: 42px;
  height: auto;
  position: relative;
  z-index: 1;
}
.hub__name {
  font-size: 0.76rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: #fff;
  position: relative;
  z-index: 1;
}

/* A ring expanding out of the core on a slow loop — the source the pulses are
   leaving from. */
.hub__ring {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 1.5px solid rgba(99, 231, 127, 0.55);
  opacity: 0;
}
.hub.is-on .hub__ring {
  animation: core-ring 3.8s ease-out infinite;
}
@keyframes core-ring {
  0% {
    transform: scale(0.9);
    opacity: 0.55;
  }
  70%,
  100% {
    transform: scale(1.5);
    opacity: 0;
  }
}

/* ── Pins ────────────────────────────────────────────────────────────────── */
.pin {
  position: absolute;
  transform: translate(-50%, -50%);
  display: grid;
  justify-items: center;
  gap: 5px;
  width: 132px;
  text-align: center;
  z-index: 3;
  opacity: 0;
}
.hub.is-on .pin {
  animation: pin-in 0.5s cubic-bezier(0.2, 1.2, 0.4, 1) forwards;
  animation-delay: calc(0.45s + var(--i) * 90ms);
}
@keyframes pin-in {
  from {
    opacity: 0;
    transform: translate(-50%, -50%) scale(0.7);
  }
  to {
    opacity: 1;
    transform: translate(-50%, -50%) scale(1);
  }
}

.pin__disc {
  position: relative;
  display: grid;
  place-items: center;
  width: 58px;
  height: 58px;
  border-radius: 19px;
  background: #fff;
  border: 1px solid var(--line);
  color: var(--muted);
  box-shadow: 0 12px 24px -14px rgba(4, 35, 31, 0.35);
  transition:
    transform 0.26s cubic-bezier(0.2, 0.8, 0.3, 1),
    border-color 0.26s,
    color 0.26s;
}
.pin__fallback {
  width: 25px;
  height: 25px;
}

/* The partner's real mark, laid over the drawn fallback. A missing file paints
   nothing, so the icon underneath simply stays visible — the row is never a
   line of broken images while logos are being collected. */
.pin__logo {
  position: absolute;
  inset: 13px;
  background-repeat: no-repeat;
  background-position: center;
  background-size: contain;
}

/* Each pin drifts on its own offset, so the ring breathes instead of sitting
   there. Small numbers — this is behind the reading, not in front of it. */
.pin__disc {
  animation: pin-float 6.5s ease-in-out infinite;
  animation-delay: calc(var(--i) * -0.9s);
}
@keyframes pin-float {
  0%,
  100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-6px);
  }
}
.pin:hover .pin__disc {
  animation-play-state: paused;
  transform: translateY(-5px) scale(1.06);
  border-color: var(--teal);
  color: var(--teal);
}

/* Built today gets the brand colour. Planned stays grey — the difference is
   the whole point of showing status at all. */
.pin--live .pin__disc {
  border-color: rgba(20, 112, 106, 0.4);
  color: var(--teal);
  background: linear-gradient(150deg, rgba(99, 231, 127, 0.18), #fff 65%);
}

.pin__name {
  font-size: 0.84rem;
  font-weight: 800;
  color: var(--ink);
  line-height: 1.2;
}
.pin__what {
  font-size: 0.68rem;
  color: var(--muted);
  line-height: 1.3;
}

/* ── Key ─────────────────────────────────────────────────────────────────── */
.hub__key {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  margin-top: 26px;
  font-size: 0.78rem;
  color: var(--muted);
}
.hub__dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--teal);
  margin-left: 14px;
}
.hub__dot:first-child {
  margin-left: 0;
}
.hub__dot--soon {
  background: var(--line);
}

/* ── Responsive ──────────────────────────────────────────────────────────
   Below tablet the ellipse stops working — the pins collide with the core.
   Falls back to a plain grid, which is honest about what it is. */
@media (max-width: 900px) {
  .hub {
    aspect-ratio: auto;
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 26px 12px;
    margin-top: 34px;
  }
  .hub__wires {
    display: none;
  }
  .hub__core {
    position: static;
    transform: none;
    grid-column: 1 / -1;
    width: 100%;
    height: auto;
    border-radius: 20px;
    padding: 26px;
    flex-direction: row;
  }
  .pin {
    position: static;
    transform: none;
    width: auto;
    opacity: 1;
  }
  .hub.is-on .pin {
    animation: none;
  }
}

@media (max-width: 480px) {
  .pin__name {
    font-size: 0.78rem;
  }
}

@media (prefers-reduced-motion: reduce) {
  .hub__wire {
    stroke-dashoffset: 0;
    animation: none !important;
  }
  .pin {
    opacity: 1;
    animation: none !important;
  }
}
