/* ============================================================
   Nova FX · atmos.css — "atmosphere" standing-ambient pack
   Always-on background life for the Nova Wallet site.
   Pure CSS + vanilla JS (atmos.js). Zero external requests.
   Every selector is namespaced .ax-*; keyframes are ax-*.
   All continuous motion is transform/opacity only and honors
   prefers-reduced-motion (everything settles into a calm,
   composed static frame — the scene never disappears).

   Components:
     .ax-aurora     layered aurora ribbons (JS injects .ax-band)
     .ax-nebula     slow radial-drift nebula color clouds
     .ax-grain      feTurbulence film-grain overlay (pure CSS)
     .ax-meteors    occasional shooting-star streaks (JS spawns)
     [data-ax-depth]  lerped mouse-parallax for background layers

   Placement rule of thumb: an atmosphere layer is the FIRST
   child of a position:relative section (.hero, section are
   already relative) and carries aria-hidden="true".
   ============================================================ */

/* ---------- tokens (inherit nova.css vars when present) ---------- */
:root{
  --ax-bg:   var(--bg,   #04091a);
  --ax-acc:  var(--acc,  #2f6bff);
  --ax-acc2: var(--acc2, #38bdf8);
  --ax-vio:  #7c5cff;
  --ax-vio2: var(--vio,  #7c8cff);
  --ax-ice:  #a8d8ff;
}

/* ============================================================
   1 · .ax-aurora — layered drifting aurora ribbons
   ------------------------------------------------------------
   Host is an absolute (or .ax-fixed = viewport-fixed) layer.
   JS injects three <i class="ax-band"> ribbons; each is a wide,
   heavily feathered gradient with an asymmetric organic
   silhouette (static border-radius) that drifts on its own
   long, non-round clock — 57s / 73s / 89s, one reversed — so
   the interference pattern between bands never visibly loops.

   Usage:
     <div class="ax-aurora" aria-hidden="true"></div>
     <div class="ax-aurora ax-fixed" aria-hidden="true"></div>
   ============================================================ */
.ax-aurora{
  position:absolute;inset:0;overflow:hidden;pointer-events:none;z-index:0;
  opacity:var(--ax-o,1);
  /* soften the section edges so ribbons fade instead of clipping */
  -webkit-mask-image:linear-gradient(180deg,transparent 0,#000 15%,#000 84%,transparent 100%);
          mask-image:linear-gradient(180deg,transparent 0,#000 15%,#000 84%,transparent 100%);
}
/* viewport-fixed variant: sits behind ALL content (z:-1 paints
   above the page background but under every ancestor box —
   sections here have no background, so it shows through) */
.ax-aurora.ax-fixed{position:fixed;z-index:-1;
  -webkit-mask-image:none;mask-image:none}

/* faint horizon glow pooled at the bottom of the layer */
.ax-aurora::after{
  content:"";position:absolute;left:8%;right:8%;bottom:-26%;height:55%;
  background:radial-gradient(52% 100% at 50% 100%,rgba(47,107,255,.13),transparent 72%);
  filter:blur(10px);
}

/* ribbon base — overscan width so drift never exposes an edge;
   the 90deg mask feathers both tips of the band */
.ax-band{
  position:absolute;left:-38%;width:176%;pointer-events:none;
  will-change:transform;
  -webkit-mask-image:linear-gradient(90deg,transparent 1%,#000 22%,#000 78%,transparent 99%);
          mask-image:linear-gradient(90deg,transparent 1%,#000 22%,#000 78%,transparent 99%);
}

/* band 1 · high cyan veil, tilted -8°, slowest-visible layer */
.ax-b1{
  top:-22%;height:58%;
  border-radius:52% 48% 46% 54%/58% 62% 38% 42%;
  background:
    linear-gradient(97deg,transparent 4%,rgba(56,189,248,.16) 26%,rgba(96,140,255,.20) 46%,rgba(47,107,255,.15) 66%,transparent 94%),
    linear-gradient(93deg,transparent 30%,rgba(160,225,255,.10) 52%,transparent 72%);
  filter:blur(34px);opacity:.9;
  transform:rotate(-8deg);
  animation:ax-drift-a 57s cubic-bezier(.37,.16,.41,.84) infinite;
}
@keyframes ax-drift-a{
  0%  {transform:rotate(-8deg)   translate3d(-2.5%,0,0)    scaleY(1)}
  27% {transform:rotate(-6.4deg) translate3d(3.2%,3.8%,0)  scaleY(1.09)}
  53% {transform:rotate(-9.6deg) translate3d(-.8%,6.5%,0)  scaleY(.93)}
  79% {transform:rotate(-7.2deg) translate3d(2.1%,1.6%,0)  scaleY(1.04)}
  100%{transform:rotate(-8deg)   translate3d(-2.5%,0,0)    scaleY(1)}
}

/* band 2 · violet curtain, counter-phase (reverse), widest blur */
.ax-b2{
  top:2%;height:46%;
  border-radius:46% 54% 60% 40%/44% 38% 62% 56%;
  background:
    linear-gradient(84deg,transparent 8%,rgba(124,92,255,.14) 34%,rgba(86,110,255,.18) 58%,rgba(56,189,248,.10) 80%,transparent 96%),
    linear-gradient(88deg,transparent 18%,rgba(176,140,255,.08) 47%,transparent 76%);
  filter:blur(40px);opacity:.75;
  transform:rotate(5.5deg);
  animation:ax-drift-b 73s cubic-bezier(.41,.12,.36,.88) infinite reverse;
}
@keyframes ax-drift-b{
  0%  {transform:rotate(5.5deg) translate3d(2%,0,0)      scaleX(1)}
  31% {transform:rotate(7.4deg) translate3d(-3.6%,-4%,0) scaleX(1.07)}
  58% {transform:rotate(4.1deg) translate3d(-1%,-6.8%,0) scaleX(.95)}
  83% {transform:rotate(6.2deg) translate3d(-2.4%,-2%,0) scaleX(1.03)}
  100%{transform:rotate(5.5deg) translate3d(2%,0,0)      scaleX(1)}
}

/* band 3 · thin ice-blue highlight low in the frame */
.ax-b3{
  top:38%;height:30%;
  border-radius:50% 50% 48% 52%/64% 60% 40% 36%;
  background:
    linear-gradient(92deg,transparent 12%,rgba(56,189,248,.12) 40%,rgba(140,200,255,.16) 55%,rgba(47,107,255,.10) 74%,transparent 92%);
  filter:blur(26px);opacity:.5;
  transform:rotate(-3.5deg);
  animation:ax-drift-c 89s cubic-bezier(.38,.18,.44,.82) infinite;
}
@keyframes ax-drift-c{
  0%  {transform:rotate(-3.5deg) translate3d(-1%,0,0)}
  22% {transform:rotate(-5deg)   translate3d(2.6%,-3%,0) scaleY(1.15)}
  49% {transform:rotate(-2.6deg) translate3d(4.4%,2%,0)  scaleY(.9)}
  76% {transform:rotate(-4.4deg) translate3d(-2.8%,-1%,0) scaleY(1.06)}
  100%{transform:rotate(-3.5deg) translate3d(-1%,0,0)}
}

/* ============================================================
   2 · .ax-nebula — slow radial-drift color clouds
   ------------------------------------------------------------
   Larger, softer and far slower than the hero .orbs: four
   elliptical gradient blobs on 83s–121s non-looping-looking
   drift paths, each with a baked-in rotation so the ellipse
   reads as an organic morphing shape without ever repainting
   border-radius. JS injects the clouds; CSS-only fallback is
   to paste the <i> markup yourself.

   Usage:
     <div class="ax-nebula" aria-hidden="true"></div>
   ============================================================ */
.ax-nebula{
  position:absolute;inset:0;overflow:hidden;pointer-events:none;z-index:0;
  opacity:var(--ax-o,1);
  -webkit-mask-image:linear-gradient(180deg,transparent 0,#000 12%,#000 88%,transparent 100%);
          mask-image:linear-gradient(180deg,transparent 0,#000 12%,#000 88%,transparent 100%);
}
.ax-nebula.ax-fixed{position:fixed;z-index:-1;
  -webkit-mask-image:none;mask-image:none}

.ax-cloud{
  position:absolute;pointer-events:none;border-radius:50%;
  filter:blur(36px);will-change:transform;
}
.ax-c1{
  left:-10%;top:-16%;width:64vmin;height:46vmin;opacity:.55;
  background:radial-gradient(closest-side,rgba(124,92,255,.34),rgba(124,92,255,.10) 55%,transparent 78%);
  transform:rotate(-14deg);
  animation:ax-neb-a 97s cubic-bezier(.40,.13,.36,.87) infinite;
}
@keyframes ax-neb-a{
  0%  {transform:rotate(-14deg) translate3d(0,0,0)     scale(1)}
  24% {transform:rotate(-10deg) translate3d(11%,-7%,0) scale(1.12)}
  51% {transform:rotate(-17deg) translate3d(6%,8%,0)   scale(.94)}
  76% {transform:rotate(-12deg) translate3d(-6%,3%,0)  scale(1.06)}
  100%{transform:rotate(-14deg) translate3d(0,0,0)     scale(1)}
}
.ax-c2{
  left:46%;top:18%;width:72vmin;height:54vmin;opacity:.5;
  background:radial-gradient(closest-side,rgba(47,107,255,.30),rgba(56,120,255,.09) 58%,transparent 78%);
  transform:rotate(9deg);
  animation:ax-neb-b 121s cubic-bezier(.43,.11,.38,.89) infinite reverse;
}
@keyframes ax-neb-b{
  0%  {transform:rotate(9deg)  translate3d(0,0,0)      scale(1)}
  19% {transform:rotate(13deg) translate3d(-9%,6%,0)   scale(1.1)}
  47% {transform:rotate(6deg)  translate3d(-5%,-8%,0)  scale(.92)}
  71% {transform:rotate(11deg) translate3d(7%,-3%,0)   scale(1.07)}
  100%{transform:rotate(9deg)  translate3d(0,0,0)      scale(1)}
}
.ax-c3{
  left:14%;top:46%;width:52vmin;height:40vmin;opacity:.42;
  background:radial-gradient(closest-side,rgba(56,189,248,.26),rgba(56,189,248,.07) 56%,transparent 76%);
  transform:rotate(18deg);
  animation:ax-neb-c 83s cubic-bezier(.39,.17,.45,.83) infinite;
}
@keyframes ax-neb-c{
  0%  {transform:rotate(18deg)  translate3d(0,0,0)     scale(1)}
  29% {transform:rotate(14deg)  translate3d(8%,9%,0)   scale(1.14)}
  57% {transform:rotate(21deg)  translate3d(-7%,5%,0)  scale(.9)}
  82% {transform:rotate(16deg)  translate3d(3%,-6%,0)  scale(1.05)}
  100%{transform:rotate(18deg)  translate3d(0,0,0)     scale(1)}
}
.ax-c4{
  left:64%;top:-10%;width:46vmin;height:36vmin;opacity:.4;
  background:radial-gradient(closest-side,rgba(96,80,255,.28),rgba(124,92,255,.08) 57%,transparent 78%);
  transform:rotate(-22deg);
  animation:ax-neb-d 109s cubic-bezier(.36,.15,.42,.85) infinite reverse;
}
@keyframes ax-neb-d{
  0%  {transform:rotate(-22deg) translate3d(0,0,0)     scale(1)}
  26% {transform:rotate(-18deg) translate3d(-8%,7%,0)  scale(1.11)}
  54% {transform:rotate(-25deg) translate3d(5%,4%,0)   scale(.93)}
  78% {transform:rotate(-20deg) translate3d(9%,-5%,0)  scale(1.06)}
  100%{transform:rotate(-22deg) translate3d(0,0,0)     scale(1)}
}

/* ============================================================
   3 · .ax-grain — film-grain overlay (pure CSS, no JS)
   ------------------------------------------------------------
   Fixed, oversized (inset:-60%) tile of monochrome
   feTurbulence noise blended `overlay` at ~3.8% opacity —
   deviations around mid-gray gently lighten/darken whatever
   is beneath, like film grain. The 1.15s steps() jitter jumps
   transform between 8 hand-placed offsets (GPU-composited,
   never repaints the noise tile).

   Usage: <div class="ax-grain" aria-hidden="true"></div>
   — anywhere inside <body>; .ax-grain.flat disables the blend.
   Tune strength with --ax-grain-o (default .038).
   ============================================================ */
.ax-grain{
  position:fixed;inset:-60%;z-index:9980;pointer-events:none;
  opacity:var(--ax-grain-o,.038);
  mix-blend-mode:overlay;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='260' height='260'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.78' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='260' height='260' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size:260px 260px;
  animation:ax-grain-j 1.15s steps(1,end) infinite;
}
@keyframes ax-grain-j{
  0%,100%{transform:translate3d(0,0,0)}
  12.5%  {transform:translate3d(-1.8%, 1.2%,0)}
  25%    {transform:translate3d( 1.4%,-1.6%,0)}
  37.5%  {transform:translate3d(-1%,  -2.2%,0)}
  50%    {transform:translate3d( 2.2%, 1.6%,0)}
  62.5%  {transform:translate3d(-2.4%, 0.8%,0)}
  75%    {transform:translate3d( 1%,   2.4%,0)}
  87.5%  {transform:translate3d(-1.4%,-1%,0)}
}
/* plain-alpha fallback for low-power contexts */
.ax-grain.flat{mix-blend-mode:normal;opacity:calc(var(--ax-grain-o,.038)*1.5)}

/* ============================================================
   4 · .ax-meteors — occasional shooting-star streaks
   ------------------------------------------------------------
   JS spawns .ax-meteor streaks from a single radiant region
   (upper-left sky) on a jittered ~7–15s clock, roughly a
   quarter of them as dim ".faint" companions. Each streak is
   a rotated gradient bar: it ignites (scaleX grows tailward
   from the glowing head), holds, and burns out mid-flight —
   ~0.9–1.5s total, transform+opacity only.

   Usage: <div class="ax-meteors" aria-hidden="true"></div>
   — typically inside .hero, after the star/orb layers.
   ============================================================ */
.ax-meteors{position:absolute;inset:0;overflow:hidden;pointer-events:none;z-index:1}

.ax-meteor{
  position:absolute;top:0;left:0;
  width:var(--ax-len,140px);height:2px;border-radius:3px;
  transform-origin:100% 50%;
  opacity:0;will-change:transform,opacity;
  background:linear-gradient(90deg,
    rgba(150,205,255,0) 0%,rgba(150,205,255,.14) 22%,
    rgba(190,228,255,.5) 68%,rgba(240,250,255,.95) 100%);
  box-shadow:0 0 6px rgba(140,205,255,.25);
  animation:ax-meteor-fly var(--ax-dur,1.15s) cubic-bezier(.32,.08,.62,.42) forwards;
}
/* glowing head riding the leading (right) edge */
.ax-meteor::after{
  content:"";position:absolute;right:-2px;top:-2px;width:6px;height:6px;
  border-radius:50%;
  background:radial-gradient(circle,#fff,rgba(190,228,255,.9) 55%,transparent 75%);
  box-shadow:0 0 10px 2px rgba(160,215,255,.75),0 0 22px 6px rgba(80,150,255,.3);
}
/* dimmer, smaller companion streak */
.ax-meteor.faint{
  background:linear-gradient(90deg,
    rgba(150,205,255,0),rgba(170,215,255,.32) 70%,rgba(230,245,255,.7));
  box-shadow:none;
}
.ax-meteor.faint::after{
  width:4px;height:4px;top:-1px;right:-1px;
  box-shadow:0 0 7px 1px rgba(160,215,255,.5);
}
@keyframes ax-meteor-fly{
  0%  {opacity:0;transform:rotate(var(--ax-ang,22deg)) translate3d(0,0,0) scaleX(.22)}
  9%  {opacity:var(--ax-peak,1)}
  58% {opacity:var(--ax-peak,1)}
  100%{opacity:0;transform:rotate(var(--ax-ang,22deg)) translate3d(var(--ax-travel,60vw),0,0) scaleX(1)}
}

/* ============================================================
   5 · [data-ax-depth] — lerped mouse-parallax (JS-driven)
   ------------------------------------------------------------
   Any element carrying data-ax-depth="<px>" drifts toward the
   pointer by up to <px> on X (and data-ax-depth-y or 55% of
   that on Y), smoothed at ~5.5%/frame — buttery, never jumpy.
   Negative values drift against the pointer.
   atmos.js writes transform:translate3d on the element itself,
   so only put it on layers whose transform isn't animated
   (.stars / .orbs / .afx-pnet / .ax-aurora / .ax-nebula are
   safe — their motion lives on children or opacity).

   The rule below gives known absolute background layers a
   44px overscan bleed so a parallax shift never exposes the
   section edge.
   ============================================================ */
[data-ax-depth]{will-change:transform}
.stars[data-ax-depth],
.orbs[data-ax-depth],
.sparks[data-ax-depth],
.afx-pnet[data-ax-depth],
.afx-grid[data-ax-depth],
.ax-aurora[data-ax-depth],
.ax-nebula[data-ax-depth],
.ax-meteors[data-ax-depth]{inset:-44px}
.ax-grain[data-ax-depth]{inset:-64%}

/* ============================================================
   Reduced motion — the sky stays, the motion stops.
   Bands and clouds hold their composed resting transforms;
   grain goes static; meteors simply never spawn (JS) and are
   hidden outright here as belt-and-braces.
   ============================================================ */
@media (prefers-reduced-motion:reduce){
  .ax-band,.ax-cloud,.ax-grain,.ax-meteor{animation:none!important}
  .ax-meteor{display:none!important}
}

/* ============================================================
   Small screens — fewer composited layers, no meteors.
   (JS also refuses to spawn meteors on coarse pointers.)
   ============================================================ */
@media (max-width:860px){
  .ax-b3{display:none}            /* aurora: 3 ribbons -> 2  */
  .ax-c3,.ax-c4{display:none}     /* nebula: 4 clouds -> 2   */
  .ax-meteor{display:none}
}
