/* The active background: every dark green band on a marketing page carries this, except the
   footer, which is flat. The band itself is the rail box (web-max-w, inside the two rails), and
   the satin is clipped to it, so the moving light never runs past the rails.

   Ported from the Arclite marketing site's satin treatment. Soft white light bands, blurred,
   drift across the band on long loops and lean toward the pointer. Colours and blur come
   from dist/arclite-tokens.css; the geometry (where each band sits, how far it travels, how
   long a loop takes) is the component's own and is not a token.

   Markup:

     <section class="band band-gradient web-band-active">
       <div class="web-band-satin" aria-hidden="true">
         <span></span><span></span><span></span>              three bands: a how-it-works band, a closing band
         <span></span><span></span><span></span>              three more: the hero, which is tall enough to need light through its middle
       </div>
       ...the band's content...
     </section>

   Load band-active.js once per page. It writes the pointer position and the idle wander into
   custom properties on .web-band-satin, and adds .is-live while the band is on screen.
   Without the script the bands hold still. With prefers-reduced-motion the satin is not
   drawn at all and the band is its static gradient. */

.web-band-active {
  position: relative;
  overflow: hidden;
  isolation: isolate;
}
.web-band-active > :not(.web-band-satin) {
  position: relative;
  z-index: 1;
}

.web-band-satin {
  position: absolute;
  inset: -35%;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
  /* Four lag tiers, written by band-active.js. Tier 1 reaches the pointer first, tier 4 is
     still on its way, and every band picks one. Pointer speed writes --flow and --swirl. */
  --mx1: 0; --my1: 0;
  --mx2: 0; --my2: 0;
  --mx3: 0; --my3: 0;
  --mx4: 0; --my4: 0;
  --flow: 0;
  --swirl: 0;
}

/* Pointer response lives on the individual translate, rotate and scale properties so the drift
   keyframes keep transform to themselves. --tx and --ty pick the lag tier; --px and --py set how
   far this band travels toward the pointer. */
.web-band-satin > span {
  position: absolute;
  left: -30%;
  width: 160%;
  height: 26%;
  border-radius: var(--radius-round);
  --blur: var(--web-band-sheen-blur);
  --sheen: var(--web-band-sheen);
  --tx: var(--mx1);
  --ty: var(--my1);
  translate: calc(var(--tx) * var(--px, 60px)) calc(var(--ty) * var(--py, 44px));
  rotate: calc(var(--swirl) * var(--rr, 4deg));
  /* Stretch along the band and pinch across it as the pointer speeds up, so it reads as light
     moving rather than a bar growing. */
  scale: calc(1 + var(--flow) * 0.09) calc(1 - var(--flow) * 0.05);
  transform: rotate(var(--rot, -24deg));
  will-change: transform, translate, rotate, scale;
}

/* The blur lives on a still child, painted once; the band moves a finished texture. */
.web-band-satin > span::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: var(--sheen);
  filter: blur(var(--blur));
}

/* The drift runs only while the band is on screen. */
.web-band-active:not(.is-live) .web-band-satin > span {
  animation-play-state: paused;
}

/* Lite mode: band-active.js sets html.lite on a device with two cores or fewer, or 2GB of
   memory or less. The sheen stays, still. */
.lite .web-band-satin > span {
  animation: none !important;
}

.web-band-satin > span:nth-child(1) {
  top: 8%;
  --tx: var(--mx1); --ty: var(--my1);
  --px: 178px; --py: 112px; --rr: 5deg;
  animation: web-drift-a 50s ease-in-out infinite alternate;
}
.web-band-satin > span:nth-child(2) {
  top: 42%;
  height: 20%;
  opacity: 0.75;
  --tx: var(--mx3); --ty: var(--my3);
  --px: -124px; --py: 88px; --rr: -4deg;
  animation: web-drift-b 60s ease-in-out infinite alternate;
  animation-delay: -22s;
}
.web-band-satin > span:nth-child(3) {
  top: 66%;
  height: 30%;
  --sheen: var(--web-band-sheen-dark);
  --tx: var(--mx4); --ty: var(--my4);
  --px: 104px; --py: -108px; --rr: 3deg;
  animation: web-drift-c 76s ease-in-out infinite alternate;
  animation-delay: -38s;
}
/* Fourth band: wider, softer and slower, between the highlights for depth. */
.web-band-satin > span:nth-child(4) {
  top: 24%;
  height: 36%;
  opacity: 0.45;
  --blur: var(--web-band-sheen-blur-soft);
  --sheen: var(--web-band-sheen-soft);
  --tx: var(--mx4); --ty: var(--my4);
  --px: -152px; --py: -82px; --rr: -2.5deg;
  animation: web-drift-b 90s ease-in-out infinite alternate-reverse;
  animation-delay: -55s;
}
/* Bands 5 and 6 sit in the middle strip of a tall band and travel across rather than up and
   down, so light reads as passing through the middle. */
.web-band-satin > span:nth-child(5) {
  top: 34%;
  height: 16%;
  --rot: -9deg;
  --tx: var(--mx2); --ty: var(--my2);
  --px: 216px; --py: -70px; --rr: 6deg;
  animation: web-drift-d 34s ease-in-out infinite alternate;
  animation-delay: -11s;
}
.web-band-satin > span:nth-child(6) {
  top: 46%;
  height: 13%;
  opacity: 0.8;
  --rot: 11deg;
  --tx: var(--mx3); --ty: var(--my3);
  --px: -202px; --py: 78px; --rr: -6.5deg;
  animation: web-drift-e 44s ease-in-out infinite alternate-reverse;
  animation-delay: -18s;
}

/* Idle wander, CSS only. Once the pointer has left and the springs have settled, band-active.js
   stops writing custom properties and adds .is-idle, and these keyframes keep the field
   breathing without any main-thread work. --phase is set per band by the script so two bands on
   one page never breathe in step. */
.web-band-active { --phase: 0s; }

@keyframes web-wander-1 { 0%, 100% { translate: 0 0; } 25% { translate: 5% 3%; } 75% { translate: -5% -3%; } }
@keyframes web-wander-2 { 0%, 100% { translate: 0 0; } 25% { translate: -3.5% 2.5%; } 75% { translate: 3.5% -2.5%; } }
@keyframes web-wander-3 { 0%, 100% { translate: 0 0; } 25% { translate: 3% -3%; } 75% { translate: -3% 3%; } }
@keyframes web-wander-4 { 0%, 100% { translate: 0 0; } 25% { translate: -4.5% -2%; } 75% { translate: 4.5% 2%; } }
@keyframes web-wander-5 { 0%, 100% { translate: 0 0; } 25% { translate: 6% -2%; } 75% { translate: -6% 2%; } }
@keyframes web-wander-6 { 0%, 100% { translate: 0 0; } 25% { translate: -5.5% 2%; } 75% { translate: 5.5% -2%; } }

.web-band-active.is-idle .web-band-satin > span:nth-child(1) {
  animation-name: web-drift-a, web-wander-1; animation-duration: 50s, 65s;
  animation-timing-function: ease-in-out, ease-in-out; animation-iteration-count: infinite, infinite;
  animation-direction: alternate, normal; animation-delay: 0s, var(--phase);
}
.web-band-active.is-idle .web-band-satin > span:nth-child(2) {
  animation-name: web-drift-b, web-wander-2; animation-duration: 60s, 65s;
  animation-timing-function: ease-in-out, ease-in-out; animation-iteration-count: infinite, infinite;
  animation-direction: alternate, normal; animation-delay: -22s, var(--phase);
}
.web-band-active.is-idle .web-band-satin > span:nth-child(3) {
  animation-name: web-drift-c, web-wander-3; animation-duration: 76s, 65s;
  animation-timing-function: ease-in-out, ease-in-out; animation-iteration-count: infinite, infinite;
  animation-direction: alternate, normal; animation-delay: -38s, var(--phase);
}
.web-band-active.is-idle .web-band-satin > span:nth-child(4) {
  animation-name: web-drift-b, web-wander-4; animation-duration: 90s, 65s;
  animation-timing-function: ease-in-out, ease-in-out; animation-iteration-count: infinite, infinite;
  animation-direction: alternate-reverse, normal; animation-delay: -55s, var(--phase);
}
.web-band-active.is-idle .web-band-satin > span:nth-child(5) {
  animation-name: web-drift-d, web-wander-5; animation-duration: 34s, 65s;
  animation-timing-function: ease-in-out, ease-in-out; animation-iteration-count: infinite, infinite;
  animation-direction: alternate, normal; animation-delay: -11s, var(--phase);
}
.web-band-active.is-idle .web-band-satin > span:nth-child(6) {
  animation-name: web-drift-e, web-wander-6; animation-duration: 44s, 65s;
  animation-timing-function: ease-in-out, ease-in-out; animation-iteration-count: infinite, infinite;
  animation-direction: alternate-reverse, normal; animation-delay: -18s, var(--phase);
}

/* Slow diagonal drift. Each keyframe keeps the rotation so the bands never snap upright. */
@keyframes web-drift-a {
  0% { transform: translate3d(-9%, -4.5%, 0) rotate(-24deg); opacity: 0.85; }
  35% { transform: translate3d(1%, 2.5%, 0) rotate(-21deg); }
  70% { transform: translate3d(6%, -2%, 0) rotate(-26deg); opacity: 1; }
  100% { transform: translate3d(10%, 5%, 0) rotate(-22deg); opacity: 0.8; }
}
@keyframes web-drift-b {
  0% { transform: translate3d(10%, 3%, 0) rotate(-24deg); }
  40% { transform: translate3d(2%, -4%, 0) rotate(-27deg); }
  100% { transform: translate3d(-11%, 4.5%, 0) rotate(-21deg); }
}
@keyframes web-drift-c {
  0% { transform: translate3d(6%, 3.5%, 0) rotate(-24deg); opacity: 1; }
  50% { transform: translate3d(-3%, -2%, 0) rotate(-22deg); opacity: 0.78; }
  100% { transform: translate3d(-9%, -5%, 0) rotate(-26deg); opacity: 1; }
}
/* Centre bands: mostly lateral, with a small lift and an opacity swell, so the pass reads as
   light moving rather than a bar sliding. */
@keyframes web-drift-d {
  0% { transform: translate3d(-15%, 1.5%, 0) rotate(-9deg); opacity: 0.55; }
  45% { transform: translate3d(-1%, -2%, 0) rotate(-11deg); opacity: 0.95; }
  100% { transform: translate3d(14%, 2.5%, 0) rotate(-7deg); opacity: 0.6; }
}
@keyframes web-drift-e {
  0% { transform: translate3d(13%, -2%, 0) rotate(11deg); opacity: 0.5; }
  55% { transform: translate3d(0%, 2.5%, 0) rotate(13deg); opacity: 0.9; }
  100% { transform: translate3d(-14%, -1%, 0) rotate(9deg); opacity: 0.55; }
}

/* Reduced motion: no satin at all. The band is its static gradient token. */
@media (prefers-reduced-motion: reduce) {
  .web-band-satin {
    display: none;
  }
}
