@charset "UTF-8";

/*
 * The texture pass. Loaded only when the switch in functions.php is on, and every rule
 * hangs off body.has-texture, so turning it off removes all of it.
 *
 * 1. Grain: a fine animated film grain over everything, blended so it darkens the darks
 *    and lifts the lights a touch. The layer is three viewports wide and steps through
 *    eight offsets by transform, so it costs the compositor and nothing else.
 * 2. Depth: four large out-of-focus bubbles on a fixed layer behind the content, drifting
 *    on their own and moving at different rates with scroll (texture.js). Sections that
 *    paint their own background (hero, journey, footer, cards) cover them, so they only
 *    show through the page colour between.
 * 3. Surfaces: the scrolled header frosts what passes under it.
 */

/* The html element carries the page colour too, so without a stacking context on the
   body the depth layer (z-index -1) would paint beneath the body's own background. */
body.has-texture {
  isolation: isolate;
}

/* Grain ----------------------------------------------------------------------- */

.has-texture .grain {
  position: fixed;
  z-index: 900;
  inset: -100%;
  width: 300%;
  height: 300%;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 240px 240px;
  opacity: 0.075;
  pointer-events: none;
  mix-blend-mode: overlay;
  animation: grain 0.9s steps(8) infinite;
  will-change: transform;
}

@keyframes grain {
  0% {
    transform: translate3d(0, 0, 0);
  }

  12.5% {
    transform: translate3d(-4%, -6%, 0);
  }

  25% {
    transform: translate3d(3%, -2%, 0);
  }

  37.5% {
    transform: translate3d(-6%, 4%, 0);
  }

  50% {
    transform: translate3d(5%, 6%, 0);
  }

  62.5% {
    transform: translate3d(-2%, 3%, 0);
  }

  75% {
    transform: translate3d(6%, -5%, 0);
  }

  87.5% {
    transform: translate3d(-5%, 1%, 0);
  }

  100% {
    transform: translate3d(0, 0, 0);
  }
}

/* Depth field ------------------------------------------------------------------ */

.has-texture .depth {
  position: fixed;
  z-index: -1;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
}

/* On dark pages the orbs add light (screen); on light pages they tint the page like light
   through soap film (multiply), where they need more opacity to register. The theme engine
   sets html.is-light past the midpoint of a dark-to-light blend. */
.has-texture .depth__orb {
  --orb-opacity: 0.16;
  --orb-boost: 1;
  position: absolute;
  aspect-ratio: 1;
  opacity: calc(var(--orb-opacity) * var(--orb-boost));
  transform: translate3d(0, var(--scroll-shift, 0px), 0);
  mix-blend-mode: screen;
  will-change: transform;
}

html.is-light .has-texture .depth__orb {
  --orb-boost: 2.2;
  mix-blend-mode: multiply;
}

html.is-light .has-texture .grain {
  opacity: 0.055;
}

/* Under long reading the wash stays quieter. */
html.is-light body.single.has-texture .depth__orb {
  --orb-boost: 1.4;
}

.has-texture .depth__orb img {
  display: block;
  width: 100%;
  height: 100%;
  animation: depth-drift 52s ease-in-out infinite alternate;
}

.has-texture .depth__orb--1 {
  inset-inline-start: -18vw;
  inset-block-start: 8vh;
  width: 62vw;
}

.has-texture .depth__orb--2 {
  inset-inline-end: -22vw;
  inset-block-start: 38vh;
  width: 74vw;
  --orb-opacity: 0.12;
}

.has-texture .depth__orb--2 img {
  animation-duration: 70s;
  animation-delay: -20s;
}

.has-texture .depth__orb--3 {
  inset-inline-start: 22vw;
  inset-block-end: -30vh;
  width: 48vw;
  --orb-opacity: 0.2;
}

.has-texture .depth__orb--3 img {
  animation-duration: 44s;
  animation-delay: -9s;
}

.has-texture .depth__orb--4 {
  inset-inline-end: 8vw;
  inset-block-start: -34vh;
  width: 40vw;
  --orb-opacity: 0.14;
}

.has-texture .depth__orb--4 img {
  animation-duration: 61s;
  animation-delay: -33s;
}

@keyframes depth-drift {
  0% {
    transform: translate3d(0, 0, 0) rotate(0deg) scale(1);
  }

  50% {
    transform: translate3d(3%, -4%, 0) rotate(5deg) scale(1.04);
  }

  100% {
    transform: translate3d(-2%, 3%, 0) rotate(-4deg) scale(0.98);
  }
}

/* Surfaces ------------------------------------------------------------------- */

.has-texture .site-header::before {
  backdrop-filter: blur(10px) saturate(130%);
  -webkit-backdrop-filter: blur(10px) saturate(130%);
}

/* Off the phone GPU budget and away from reduced motion. -------------------------- */

@media (max-width: 47.99rem) {
  .has-texture .grain {
    animation: none;
    opacity: 0.06;
  }

  .has-texture .depth__orb--2,
  .has-texture .depth__orb--4 {
    display: none;
  }

  .has-texture .depth__orb img {
    animation: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .has-texture .grain {
    animation: none;
  }

  .has-texture .depth__orb img {
    animation: none;
  }
}

@media (forced-colors: active) {
  .has-texture .grain,
  .has-texture .depth {
    display: none;
  }
}
