/*
 * xircuit-ground.css — the ambient background.
 *
 * Two layers over the base colour:
 *   1. a linear wash carrying the organisation colour down from the top edge,
 *      so the page reads as a continuation of the full-colour app bar;
 *   2. a nebula of six soft bodies at different sizes, hues and drift periods,
 *      blurred into one another.
 *
 * The nebula is not decoration. Glass only reads as glass when there is
 * something varied behind it to refract — a flat ground gives a frosted panel
 * nothing to work with.
 *
 * Mount once, in MainLayout, before the app content.
 */

/* The host for the runtime --org custom properties.
   display:contents so it publishes the cascade without introducing a box —
   MudLayout computes its own geometry and must not see an extra wrapper. */
.x-shell { display: contents; }

.x-ground,
.x-nebula,
.x-dust,
.x-grain {
  position: fixed;
  pointer-events: none;
}

/* ── 1. Organisation wash ──────────────────────────────────────────────── */
.x-ground {
  inset: -25%;
  z-index: -4;
  background: linear-gradient(178deg,
    color-mix(in oklab, var(--org) 92%, var(--base)) 0%,
    color-mix(in oklab, var(--org) 62%, var(--base)) 14%,
    color-mix(in oklab, var(--org) 26%, var(--base)) 34%,
    var(--base) 58%,
    var(--base-deep) 100%);
  transition: background var(--slow) ease;
}

/* ── 2. Nebula ─────────────────────────────────────────────────────────── */
.x-nebula {
  inset: -35%;
  z-index: -3;
  filter: blur(84px) saturate(165%);
  opacity: .92;
}

.x-nebula > i {
  position: absolute;
  display: block;
  border-radius: 50%;
  will-change: transform;
}

/* Bodies 2 and 4 shift hue away from the org colour. Real nebulae are not
   monochrome, and a single-hue blur reads as a smear rather than cloud. */
.x-nebula > .b1 {
  width: 62%; height: 54%; left: -6%; top: -8%;
  background: radial-gradient(circle at 38% 38%,
    color-mix(in oklab, var(--org) 90%, #ffffff 18%) 0%,
    color-mix(in oklab, var(--org) 62%, transparent) 46%, transparent 72%);
  animation: x-drift-1 46s ease-in-out infinite alternate;
}
.x-nebula > .b2 {
  width: 54%; height: 46%; right: -10%; top: -4%;
  background: radial-gradient(circle at 55% 45%,
    color-mix(in oklab, var(--org) 74%, #7fd3ff 26%) 0%,
    color-mix(in oklab, var(--org) 40%, transparent) 48%, transparent 74%);
  animation: x-drift-2 58s ease-in-out infinite alternate;
}
.x-nebula > .b3 {
  width: 70%; height: 52%; left: 8%; top: 20%;
  background: radial-gradient(circle at 45% 50%,
    color-mix(in oklab, var(--org) 52%, #ffffff 22%) 0%,
    color-mix(in oklab, var(--org) 24%, transparent) 50%, transparent 76%);
  animation: x-drift-3 67s ease-in-out infinite alternate;
}
.x-nebula > .b4 {
  width: 46%; height: 40%; right: 4%; top: 40%;
  background: radial-gradient(circle at 50% 50%,
    color-mix(in oklab, var(--org) 46%, #b98cff 30%) 0%, transparent 66%);
  animation: x-drift-4 53s ease-in-out infinite alternate;
}
.x-nebula > .b5 {
  width: 80%; height: 46%; left: -4%; bottom: -12%;
  background: radial-gradient(circle at 50% 46%,
    color-mix(in oklab, var(--org) 30%, transparent) 0%, transparent 70%);
  animation: x-drift-5 74s ease-in-out infinite alternate;
}
.x-nebula > .b6 {
  width: 34%; height: 30%; left: 44%; top: 8%;
  opacity: .5;
  background: radial-gradient(circle at 50% 50%,
    color-mix(in oklab, #ffffff 66%, var(--org)) 0%, transparent 62%);
  animation: x-drift-6 41s ease-in-out infinite alternate;
}

/* Periods are mutually non-harmonic on purpose: shared or multiple periods
   resolve into a visible pulse. */
@keyframes x-drift-1 { from { transform: translate3d(0,0,0) scale(1);    } to { transform: translate3d(7%, 5%, 0)   scale(1.16); } }
@keyframes x-drift-2 { from { transform: translate3d(0,0,0) scale(1.08); } to { transform: translate3d(-9%, 8%, 0)  scale(.94);  } }
@keyframes x-drift-3 { from { transform: translate3d(0,0,0) scale(.96);  } to { transform: translate3d(5%, -7%, 0)  scale(1.14); } }
@keyframes x-drift-4 { from { transform: translate3d(0,0,0) scale(1);    } to { transform: translate3d(-11%, -6%, 0) scale(1.2); } }
@keyframes x-drift-5 { from { transform: translate3d(0,0,0) scale(1.05); } to { transform: translate3d(8%, -4%, 0)  scale(.92);  } }
@keyframes x-drift-6 { from { transform: translate3d(0,0,0) scale(.9);   } to { transform: translate3d(-14%, 11%, 0) scale(1.25);} }

/* ── 3. Dust and grain ─────────────────────────────────────────────────── */
/* Low-frequency fractal noise reads as interstellar dust; high-frequency grain
   breaks up gradient banding, which is what otherwise gives a large CSS
   gradient away as CSS. */
/*
 * width/height are load-bearing, not redundant with inset:0. These two layers are
 * <svg> elements, and an <svg> is a REPLACED element: `width: auto` resolves to the
 * CSS intrinsic default of 300x150 and `inset` cannot stretch it. Without these the
 * noise renders as a 300x150 rectangle pinned to the top-left corner at every
 * resolution — measured at 3840x2160, confirmed fixed by these two declarations.
 *
 * No viewBox on either svg, so user units map 1:1 to CSS pixels and feTurbulence
 * renders at native resolution: the noise gains area instead of being upscaled.
 */
.x-dust  { inset: 0; width: 100%; height: 100%; z-index: -2; opacity: .50; mix-blend-mode: soft-light; }
.x-grain { inset: 0; width: 100%; height: 100%; z-index: -1; opacity: .16; mix-blend-mode: overlay; }

@media (prefers-reduced-motion: reduce) {
  .x-nebula > i { animation: none; }
}
