/* AI Constellation — the `AIConstellation` artboard that `sec07.html` imports.

   The stage is a fixed 1100x620 box scaled to its container by the script, so
   every measurement below is in the artboard's own pixels and none of them need
   a breakpoint. `.zp-ai-constellation__fit` carries the aspect ratio, which is
   what reserves the space before the script runs and stops the band collapsing
   if it never does. */

.zp-ai-constellation__fit { position:relative; width:100%; aspect-ratio:1100/620; }
.zp-ai-constellation__stage { position:absolute; left:0; top:0; width:1100px; height:620px; transform-origin:top left; }
.zp-ai-constellation__canvas { position:absolute; inset:0; display:block; width:100%; height:100%; }

/* Every node starts at the centre at zero opacity; the script moves it to its
   point and fades it in on the animation's own clock. With no script the field
   is simply empty, which is why the whole thing is aria-hidden and summarised. */
.zp-ai-constellation__node { position:absolute; left:50%; top:50%; transform:translate(-50%,-50%); opacity:0; pointer-events:none; white-space:nowrap; color:var(--zip-white); }

.zp-ai-constellation__node--core { display:flex; flex-direction:column; align-items:center; gap:3px; padding:13px 24px; border-radius:16px; border:1px solid rgba(255,215,72,.55); background:rgba(4,10,26,.74); -webkit-backdrop-filter:blur(10px); backdrop-filter:blur(10px); box-shadow:0 0 52px rgba(255,215,72,.34); }
.zp-ai-constellation__core-title { font-size:clamp(16px,1.6vw,21px); font-weight:900; letter-spacing:-.01em; color:var(--zip-white); }
.zp-ai-constellation__core-sub { font-size:9px; font-weight:800; letter-spacing:.16em; text-transform:uppercase; color:var(--zip-yellow); }

.zp-ai-constellation__node--app { display:flex; align-items:center; gap:8px; padding:8px 13px; border-radius:var(--r-pill); border:1px solid rgba(255,255,255,.16); background:rgba(8,16,38,.66); -webkit-backdrop-filter:blur(8px); backdrop-filter:blur(8px); font-size:11px; font-weight:800; letter-spacing:.08em; text-transform:uppercase; }
.zp-ai-constellation__node--app img { width:auto; display:block; flex:0 0 auto; }

.zp-ai-constellation__node--store { display:flex; align-items:center; gap:10px; padding:11px 18px; border-radius:var(--r-pill); border:1px solid rgba(255,215,72,.55); background:rgba(255,215,72,.1); -webkit-backdrop-filter:blur(8px); backdrop-filter:blur(8px); font-size:13px; font-weight:800; letter-spacing:.06em; box-shadow:0 0 28px rgba(255,215,72,.22); }
.zp-ai-constellation__pulse { width:9px; height:9px; border-radius:50%; background:var(--zip-yellow); box-shadow:0 0 16px var(--zip-yellow); animation:zipPulse 2.4s ease-in-out infinite; }

@keyframes zipPulse { 0%, 100% { opacity:.55; transform:scale(1); } 50% { opacity:1; transform:scale(1.12); } }

/* The script holds the field at a settled frame and stops advancing its clock
   under reduced motion, so only the store dot needs turning off here. */
@media (prefers-reduced-motion: reduce) {
  .zp-ai-constellation__pulse { animation:none; }
}

/* Native fit — the Zipify AI hero. The fit box is the artboard's `stageBox`
   (the hero's right column, same min-height); the stage bleeds past it so the
   particle field spreads across the band the way the artboard's full-bleed
   canvas does. The band's `overflow:clip` crops the bleed. The script sizes the
   canvas to the stage and lays the nodes out inside the fit box. */
.zp-ai-constellation--native .zp-ai-constellation__fit { aspect-ratio:auto; min-height:clamp(360px,52vh,620px); }
.zp-ai-constellation--native .zp-ai-constellation__stage { inset:-16% -22% -16% -10%; width:auto; height:auto; transform:none; pointer-events:none; }

@media (max-width:899.98px) {
  .zp-ai-constellation:not(.zp-ai-constellation--native) { margin:0 -40px -28px; width:calc(100% + 80px); }
}
