/* ============================================================
   ZIRYVO — Atmosphere
   A slow, non-repeating field of accent light on black.

   Two colours only: the page black and the brand lime. Depth comes from
   intensity and scale rather than a second hue.

   Each body carries a small, bright core and a long fade rather than an
   even wash. An even wash at this hue turns the whole frame olive and
   flat; a tight core keeps most of the frame black and lets the lime
   read as light rather than as paint.

   Intensity is capped deliberately. Two bodies overlapping land near
   G=127, which still holds ~4.7:1 against white type. A third would drop
   that under 3.5:1, so the strong one sits low, away from the headline.
   Composited from: a drifting radial gradient bed, four soft
   light bodies on mutually prime durations, grain, and a vignette.
   Only transform / opacity / background-position animate.
   ============================================================ */

.atmos {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  background: #000;
  z-index: 0;
}

/* --- 1. The bed: layered radials drifting via background-position ---- */
.atmos__bed {
  position: absolute;
  inset: -10%;
  background:
    radial-gradient(at 18% 28%, rgba(184, 255, 61, 0.075) 0px, transparent 55%),
    radial-gradient(at 82% 18%, rgba(184, 255, 61, 0.05) 0px, transparent 50%),
    radial-gradient(at 72% 78%, rgba(0, 0, 0, 0.90) 0px, transparent 55%),
    radial-gradient(at 28% 74%, rgba(184, 255, 61, 0.055) 0px, transparent 50%),
    radial-gradient(at 55% 50%, rgba(184, 255, 61, 0.04) 0px, transparent 45%),
    #000;
  background-size: 220% 220%, 200% 200%, 240% 240%, 200% 200%, 180% 180%, auto;
  animation: atmos-bed 71s cubic-bezier(0.45, 0, 0.55, 1) infinite;
}

@keyframes atmos-bed {
  0%   { background-position:  0%  0%, 100%   0%, 100% 100%,   0% 100%, 50% 50%, 0 0; }
  23%  { background-position: 42% 18%,  58%  44%,  66%  74%,  34%  66%, 28% 62%, 0 0; }
  47%  { background-position: 74% 52%,  26%  72%,  38%  36%,  62%  28%, 72% 38%, 0 0; }
  71%  { background-position: 28% 82%,  74%  26%,  18%  62%,  82%  44%, 38% 74%, 0 0; }
  100% { background-position:  0%  0%, 100%   0%, 100% 100%,   0% 100%, 50% 50%, 0 0; }
}

/* --- 2. Light bodies -------------------------------------------------
   No filter: blur() — the gradients are already soft, which keeps this
   cheap enough to stay at 60fps on integrated graphics.               */
.atmos__body {
  position: absolute;
  border-radius: 50%;
  will-change: transform, opacity;
  mix-blend-mode: screen;
}

.atmos__body--a {
  width: 128vw;
  height: 128vw;
  top: -48vw;
  left: -34vw;
  background: radial-gradient(circle at 50% 50%,
    rgba(184, 255, 61, 0.52) 0%,
    rgba(184, 255, 61, 0.34) 10%,
    rgba(184, 255, 61, 0.15) 24%,
    rgba(184, 255, 61, 0.05) 44%,
    rgba(184, 255, 61, 0.014) 68%,
    transparent 90%);
  animation: drift-a 53s ease-in-out infinite;
}

.atmos__body--b {
  width: 104vw;
  height: 104vw;
  top: -6vh;
  right: -36vw;
  background: radial-gradient(circle at 50% 50%,
    rgba(184, 255, 61, 0.42) 0%,
    rgba(184, 255, 61, 0.26) 11%,
    rgba(184, 255, 61, 0.10) 28%,
    rgba(184, 255, 61, 0.028) 52%,
    transparent 84%);
  animation: drift-b 67s ease-in-out infinite;
}

.atmos__body--c {
  width: 140vw;
  height: 86vw;
  bottom: -44vw;
  left: -6vw;
  background: radial-gradient(ellipse at 50% 50%,
    rgba(184, 255, 61, 0.34) 0%,
    rgba(184, 255, 61, 0.20) 12%,
    rgba(184, 255, 61, 0.07) 32%,
    rgba(184, 255, 61, 0.02) 58%,
    transparent 86%);
  animation: drift-c 89s ease-in-out infinite;
}

/* The dominant body. It sits low and right of centre rather than behind
   the headline: that keeps the brightest part of the field away from the
   type, which is what makes the strong core affordable. */
.atmos__body--d {
  width: 108vw;
  height: 88vw;
  top: 34vh;
  left: 2vw;
  background: radial-gradient(ellipse at 50% 50%,
    rgba(184, 255, 61, 0.66) 0%,
    rgba(184, 255, 61, 0.44) 9%,
    rgba(184, 255, 61, 0.21) 21%,
    rgba(184, 255, 61, 0.075) 40%,
    rgba(184, 255, 61, 0.02) 64%,
    transparent 88%);
  animation: drift-d 43s ease-in-out infinite;
}

/* Durations 53 / 67 / 89 / 43s are mutually prime: the composite
   pattern does not visibly repeat within a session. Keyframes are
   deliberately asymmetric so no body reads as a left-right slide. */
@keyframes drift-a {
  0%   { transform: translate3d(0, 0, 0) scale(1);          opacity: 0.85; }
  27%  { transform: translate3d(12vw, 7vh, 0) scale(1.18);  opacity: 1;    }
  58%  { transform: translate3d(4vw, 18vh, 0) scale(0.94);  opacity: 0.62; }
  81%  { transform: translate3d(-7vw, 6vh, 0) scale(1.08);  opacity: 0.9;  }
  100% { transform: translate3d(0, 0, 0) scale(1);          opacity: 0.85; }
}

@keyframes drift-b {
  0%   { transform: translate3d(0, 0, 0) scale(1.05);        opacity: 0.7;  }
  31%  { transform: translate3d(-14vw, 12vh, 0) scale(0.88); opacity: 0.95; }
  62%  { transform: translate3d(-5vw, -8vh, 0) scale(1.22);  opacity: 0.55; }
  84%  { transform: translate3d(-18vw, 4vh, 0) scale(1);     opacity: 0.8;  }
  100% { transform: translate3d(0, 0, 0) scale(1.05);        opacity: 0.7;  }
}

@keyframes drift-c {
  0%   { transform: translate3d(0, 0, 0) scale(1);           opacity: 0.6;  }
  24%  { transform: translate3d(-16vw, -6vh, 0) scale(1.14); opacity: 0.85; }
  55%  { transform: translate3d(8vw, -14vh, 0) scale(0.92);  opacity: 0.45; }
  79%  { transform: translate3d(14vw, -3vh, 0) scale(1.06);  opacity: 0.72; }
  100% { transform: translate3d(0, 0, 0) scale(1);           opacity: 0.6;  }
}

@keyframes drift-d {
  0%   { transform: translate3d(0, 0, 0) scale(0.95);        opacity: 0.72; }
  35%  { transform: translate3d(-7vw, 7vh, 0) scale(1.18);   opacity: 0.42; }
  68%  { transform: translate3d(9vw, -4vh, 0) scale(1.04);   opacity: 0.9;  }
  100% { transform: translate3d(0, 0, 0) scale(0.95);        opacity: 0.72; }
}

/* An almost subliminal accent warmth, well under the threshold where the
   eye names a colour. Kept as its own layer so it can be removed cleanly. */
.atmos__tint {
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse 70% 55% at 62% 34%,
    rgba(184, 255, 61, 0.045) 0%,
    rgba(184, 255, 61, 0.016) 38%,
    transparent 72%);
  mix-blend-mode: screen;
  animation: drift-b 79s ease-in-out infinite;
}

/* --- 3. Grain --------------------------------------------------------
   feTurbulence baked to a data URI; tiled and nudged so it never sits
   perfectly still against the moving light.                           */
.atmos__grain {
  position: absolute;
  inset: -200px;
  opacity: 0.16;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.82' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='220' height='220' filter='url(%23n)' opacity='0.55'/%3E%3C/svg%3E");
  animation: grain-shift 8s steps(6) infinite;
  will-change: transform;
}

@keyframes grain-shift {
  0%   { transform: translate3d(0, 0, 0); }
  17%  { transform: translate3d(-9px, 5px, 0); }
  34%  { transform: translate3d(6px, -11px, 0); }
  51%  { transform: translate3d(-13px, -4px, 0); }
  68%  { transform: translate3d(10px, 8px, 0); }
  85%  { transform: translate3d(-4px, 12px, 0); }
  100% { transform: translate3d(0, 0, 0); }
}

/* --- 4. Vignette: protects type contrast at the edges ---------------- */
.atmos__vignette {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(ellipse 96% 74% at 50% 50%,
      transparent 14%,
      rgba(0, 0, 0, 0.30) 46%,
      rgba(0, 0, 0, 0.68) 76%,
      rgba(0, 0, 0, 0.88) 100%),
    linear-gradient(to bottom, rgba(0, 0, 0, 0.30) 0%, transparent 20%, transparent 72%, rgba(0, 0, 0, 0.78) 100%);
}

/* --- Responsive / accessibility degradation -------------------------- */
@media (max-width: 768px) {
  /* Two bodies instead of four; grain held still. Keeps mid-range
     phones from dropping frames without losing the character. */
  .atmos__body--c,
  .atmos__body--d { display: none; }
  .atmos__body--a { width: 165vw; height: 165vw; left: -46vw; top: -60vw; }
  .atmos__body--b { width: 150vw; height: 150vw; right: -56vw; }
  .atmos__grain { animation: none; opacity: 0.12; }
  .atmos__bed { animation-duration: 95s; }
}

@media (prefers-reduced-motion: reduce) {
  .atmos__bed,
  .atmos__body,
  .atmos__grain { animation: none !important; }
  .atmos__body { opacity: 0.7; }
}
