/* ==========================================================================
   page-bg.css — animated backdrop for pages that have no hero

   The home page takes its motion from the hero's two canvases. Any page that
   opens straight onto a section would otherwise sit flat, so it gets this
   instead: drifting brand orbs over a dot grid that creeps diagonally, with a
   veil on top so text keeps its contrast.

   Deliberately a CSS relative of the hero rather than a copy of it — no
   canvas, no JS, no pointer tracking. The layer is fixed, so it is one
   composited surface that the page scrolls over, and only transforms animate.

   Usage: put `.has-page-bg` on <body> and `.page-bg` in as an early child.
   ========================================================================== */

/* The layer sits at z-index -1, which paints above the page colour <html>
   propagates to the canvas but below every in-flow descendant. body's own
   background would otherwise cover it, so it steps aside here. */
.has-page-bg {
  background-color: transparent;
}

.page-bg {
  position: fixed;
  inset: 0;
  z-index: -1;
  overflow: hidden;
  pointer-events: none;
}

/* --- orbs ----------------------------------------------------------------- */

.page-bg__orb {
  position: absolute;
  border-radius: 50%;
  filter: blur(60px);
  will-change: transform;
}

/* Three orbs on three different paths and periods, so the field never lands
   back in an obviously repeating arrangement. Sized in vmax so the
   composition holds at any aspect ratio. */
.page-bg__orb--1 {
  top: -16vmax;
  left: -12vmax;
  width: 56vmax;
  height: 46vmax;
  background: radial-gradient(
    circle at 50% 50%,
    rgba(69, 137, 255, 0.32) 0%,
    rgba(69, 137, 255, 0) 68%
  );
  animation: page-bg-drift-1 31s var(--ds-ease-in-out) infinite alternate;
}

.page-bg__orb--2 {
  top: -8vmax;
  right: -16vmax;
  width: 48vmax;
  height: 42vmax;
  background: radial-gradient(
    circle at 50% 50%,
    rgba(138, 63, 252, 0.26) 0%,
    rgba(138, 63, 252, 0) 66%
  );
  animation: page-bg-drift-2 43s var(--ds-ease-in-out) infinite alternate;
}

.page-bg__orb--3 {
  bottom: -22vmax;
  left: 22%;
  width: 52vmax;
  height: 40vmax;
  background: radial-gradient(
    circle at 50% 50%,
    rgba(17, 146, 232, 0.2) 0%,
    rgba(17, 146, 232, 0) 70%
  );
  animation: page-bg-drift-3 37s var(--ds-ease-in-out) infinite alternate;
}

@keyframes page-bg-drift-1 {
  from {
    transform: translate3d(0, 0, 0) scale(1);
  }
  to {
    transform: translate3d(14%, 9%, 0) scale(1.12);
  }
}

@keyframes page-bg-drift-2 {
  from {
    transform: translate3d(0, 0, 0) scale(1.08);
  }
  to {
    transform: translate3d(-11%, 13%, 0) scale(1);
  }
}

@keyframes page-bg-drift-3 {
  from {
    transform: translate3d(0, 0, 0) scale(1);
  }
  to {
    transform: translate3d(-9%, -10%, 0) scale(1.14);
  }
}

/* --- dot grid ------------------------------------------------------------- */

/* Inset past the edges so the loop translate never drags an edge into view,
   and masked to an ellipse so the texture fades out rather than stopping. */
.page-bg__grid {
  position: absolute;
  inset: -40px;
  background-image: radial-gradient(
    circle at center,
    rgba(255, 255, 255, 0.1) 1px,
    transparent 1px
  );
  background-size: 26px 26px;
  mask-image: radial-gradient(ellipse 85% 70% at 50% 38%, #000 15%, transparent 80%);
  -webkit-mask-image: radial-gradient(ellipse 85% 70% at 50% 38%, #000 15%, transparent 80%);
  will-change: transform;
  animation: page-bg-creep 46s linear infinite;
}

/* Travels exactly one cell, so the loop is seamless. */
@keyframes page-bg-creep {
  from {
    transform: translate3d(0, 0, 0);
  }
  to {
    transform: translate3d(26px, 26px, 0);
  }
}

/* --- veil ---------------------------------------------------------------- */

/* Keeps the orbs readable as texture rather than as competing shapes. Heavier
   toward the bottom, where the card content sits. */
.page-bg__veil {
  position: absolute;
  inset: 0;
  background: linear-gradient(
    180deg,
    rgba(10, 10, 10, 0.1) 0%,
    rgba(10, 10, 10, 0.34) 45%,
    rgba(10, 10, 10, 0.72) 100%
  );
}

/* --- adaptations --------------------------------------------------------- */

/* Narrow viewports are usually the weakest hardware. Two large blurred
   surfaces is plenty there. */
@media (max-width: 43.75rem) {
  .page-bg__orb--3 {
    display: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .page-bg__orb,
  .page-bg__grid {
    animation: none;
  }
}

@media print {
  .page-bg {
    display: none !important;
  }
}
