/* ==========================================================================
   STARS BACKGROUND — the site's global background animation

   A translation of the supplied stars.tsx into this project's architecture.
   There is no React, no Tailwind and no build step here (no package.json, no
   node_modules), so `motion` could not be installed and the component is used
   as the reference it is. The mechanism is reproduced exactly:

     * one small element per layer whose `box-shadow` is repeated hundreds of
       times at random offsets — that is the whole star field, and it is why
       this is cheap: three elements, not sixteen hundred
     * each layer duplicated 2000px below itself, so when the layer has
       travelled its own height the copy is exactly where the original began
       and the loop is seamless
     * the layer translated 0 → -2000px on a linear loop
     * three layers at different sizes and speeds, giving parallax depth

   What is deliberately NOT taken from the reference: its
   `radial-gradient(ellipse at bottom, #262626, #000)` backdrop. This site's
   background is the club's navy and that is the source of truth — the stars
   are laid over it, not in place of it.

   Replaces initBackground() in /js/three-bg.js. That file keeps its two hero
   features; only the page background moved.
   ========================================================================== */

/* Fixed, so the field is a steady atmosphere the page scrolls over rather than
   something that scrolls away — and so a page ten screens tall is covered
   without the layer having to know how tall it is.

   z-index 0 with the page's own content above it. It is not negative: a
   negative z-index would put it behind `body`'s background, which on this site
   is the navy the stars are supposed to sit on, and they would vanish. */
.stars-bg {
  position: fixed;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;          /* the page stays entirely clickable */
  /* Nothing is painted here. The club's navy already comes from <body>; this
     layer only adds stars to it. */
  background: transparent;
}

/* The parallax offset. Written by the script as two numbers and applied here,
   so the transform lives in one place and the layers' own animation is not
   fighting it — the layers translate inside this, it translates around them.

   The transition is the spring: the reference uses Motion's useSpring at
   stiffness 50 / damping 20, which reads as a soft catch-up rather than a
   snap. A long ease-out transition on a transform is the same feeling for
   this purpose and costs no JavaScript per frame. */
.stars-bg-parallax {
  position: absolute;
  inset: 0;
  transform: translate3d(var(--stars-x, 0px), var(--stars-y, 0px), 0);
  transition: transform 1.1s cubic-bezier(0.22, 1, 0.36, 1);
  will-change: transform;
}

/* One layer. The box-shadow that makes the stars is written by the script,
   because it is hundreds of random coordinates and CSS cannot generate them. */
.stars-layer {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 2000px;
  animation: stars-drift var(--stars-speed, 50s) linear infinite;
}

/* The two dots per layer: the field, and its copy one layer-height below.
   `top: 2000px` on the second is what makes the loop seamless.

   The shadows carry no colour of their own — the script emits coordinates only
   — so each one paints in `currentColor`, inherited from the layer. That is
   what makes the field themeable at all: one colour change repaints 1400 stars
   with no JavaScript and no regeneration. */
.stars-dot {
  position: absolute;
  top: 0;
  left: 0;
  width: var(--stars-size, 1px);
  height: var(--stars-size, 1px);
  border-radius: 50%;
  background: transparent;       /* the element itself is invisible… */
  box-shadow: var(--stars-shadow, none);   /* …its shadows are the stars */
}
.stars-dot.is-repeat { top: 2000px; }

@keyframes stars-drift {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(0, -2000px, 0); }
}

/* ---------- the three layers ----------
   Small and many, large and few, each slower than the last. The speed
   difference between them is the depth cue — the big near stars pass slowly,
   the small far ones stream.

   `color` here is the star colour: the shadows inherit it. The values are
   tokens so the two themes can be different things rather than one being a
   washed-out version of the other — see tokens.css. */
.stars-layer-1 { --stars-size: 1px; --stars-speed: 50s;  color: var(--stars-ink-1); }
.stars-layer-2 { --stars-size: 2px; --stars-speed: 100s; color: var(--stars-ink-2); }
.stars-layer-3 { --stars-size: 3px; --stars-speed: 150s; color: var(--stars-ink-3); }

/* ---------- the page sits above the stars ----------
   The field is fixed at z-index 0 and is the first child of <body>, so any
   positioned sibling after it paints above it — z-index 0 is enough, it does
   not need to be raised.

   These are restated at the same values style.css already gives them, purely
   so this file does not depend on that one for the field to sit behind the
   page. Nothing here changes a value the site had.

   header.site-header is deliberately NOT in this list. It is `position:
   sticky; z-index: 500` (style.css:160, :2373) so that the nav dropdown, at
   z-index 600, opens over the page. An earlier version of this rule named the
   header and set it to `position: relative; z-index: 1` — `body >
   header.site-header` outranks the site's own `header.site-header`, so it
   silently took the header off sticky and dropped it below <main>, and the
   Activities dropdown opened *behind* the page content. The header already
   has its own stacking; this file leaves it alone. */
body > main,
body > footer,
body > .page-hero { position: relative; z-index: 0; }

/* ---------- pausing ----------
   A hidden tab should not be animating a star field. One class toggle, and a
   paused CSS animation costs nothing. */
body.stars-idle .stars-layer { animation-play-state: paused; }

/* ---------- phones ----------
   The star counts are reduced by the script, not here; what this does is drop
   the parallax transition, because on a touch device there is no pointer to
   follow and the transform never changes. */
@media (max-width: 700px) {
  .stars-bg-parallax { transition: none; will-change: auto; }
}

@media (forced-colors: active) {
  .stars-bg { display: none; }
}

/* ---------- reduced motion ----------
   The field stays — an empty navy page is not the goal — it simply stops
   moving. The drift is switched off and the parallax with it, leaving a
   still, deep starfield. */
@media (prefers-reduced-motion: reduce) {
  .stars-layer { animation: none; }
  .stars-bg-parallax { transform: none; transition: none; }
}
