/* ==========================================================================
   Atlas Insights — floating sky background
   --------------------------------------------------------------------------
   A north-polar star chart that drifts about the celestial pole behind page
   content. Built by "Brand kit/Background/build_sky.py" — retune there, not
   by hand-editing the SVGs.

   Markup:
     <section class="sky-host">
       <div class="atlas-sky" data-sky></div>
       ... content ...
     </section>

   Works with no JavaScript at all: the disc is a background-image and spins.
   With sky-background.js the SVG is inlined instead and the brightest ~90
   stars gain an independent twinkle. Nothing below depends on that upgrade.

   Tunable per instance:
     --sky-opacity   layer opacity                       (default .42)
     --sky-spin      seconds for one full revolution     (default 900s)
     --sky-size      disc diameter                       (default min(190vmax,2400px))
     --sky-src       which texture variant to load
   ========================================================================== */

.sky-host {
  position: relative;
  isolation: isolate;
}
.sky-host > *:not(.atlas-sky) {
  position: relative;
  z-index: 1;
}

.atlas-sky {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
  /* Deliberately faint: the chart is paper grain behind content, not an
     illustration. 0.14-0.20 on white is the band where it reads as texture. */
  opacity: var(--sky-opacity, 0.18);

  --sky-spin: 900s;
  /* Sized so the graticule reads. The outermost ring sits at 0.77 of the disc
     radius, so at 130vmax that ring spans roughly the full viewport width —
     zoom in much past this and the chart loses its rings and becomes a plain
     scatter of dots. */
  --sky-size: min(130vmax, 2600px);
  --sky-src: url("sky-texture.svg");
  /* Pointer parallax offsets, written by sky-background.js. */
  --sky-px: 0px;
  --sky-py: 0px;
}

/* Carries the drift and the pointer parallax, so neither fights the spin. */
.atlas-sky__float {
  position: absolute;
  top: 50%;
  left: 50%;
  width: var(--sky-size);
  aspect-ratio: 1;
  margin: calc(var(--sky-size) / -2) 0 0 calc(var(--sky-size) / -2);
  will-change: transform;
  animation: atlas-sky-float 74s ease-in-out infinite;
}

/* Carries the rotation only. */
.atlas-sky__disc {
  width: 100%;
  height: 100%;
  background: var(--sky-src) center / contain no-repeat;
  will-change: transform;
  animation: atlas-sky-spin var(--sky-spin) linear infinite;
}

/* When the SVG has been inlined, drop the background-image duplicate. */
.atlas-sky--inlined .atlas-sky__disc {
  background: none;
}
.atlas-sky__disc > svg {
  display: block;
  width: 100%;
  height: 100%;
}

@keyframes atlas-sky-spin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}

/* A slow lift-and-settle, offset from the spin period so the two never
   resolve into a visible loop. */
@keyframes atlas-sky-float {
  0%, 100% { transform: translate3d(var(--sky-px), var(--sky-py), 0); }
  50%      { transform: translate3d(calc(var(--sky-px) + 1.1%),
                                    calc(var(--sky-py) - 1.5%), 0); }
}

/* Twinkle. Multiplies with each star's baked-in fill-opacity, so bright stars
   stay bright; --td/--tp are emitted per star by the generator. */
.atlas-sky .tw {
  animation: atlas-sky-twinkle var(--tp, 8s) ease-in-out infinite;
  animation-delay: var(--td, 0s);
}
@keyframes atlas-sky-twinkle {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.45; }
}

/* Motion is ambient and instrumental — never decorative. If the reader has
   asked for stillness, the chart is simply a static texture. */
@media (prefers-reduced-motion: reduce) {
  .atlas-sky__float,
  .atlas-sky__disc,
  .atlas-sky .tw {
    animation: none;
  }
  .atlas-sky__float {
    transform: none;
  }
}
