/* Part 3 motion layer (2026-10-28). Loaded after dark.css on every page; js/motion.js adds the classes.
   His words: "the background animated, the words animated, the box with the words animated, the photos animated,
   gradient backgrounds that are animated and moving constantly, even when I'm not scrolling ... still readable".
   3b (his words the same day): "I would like just the background gradients to do a rotation or movement where the
   gradients are moving in the back around. I think if that's the only thing that moves when you're not scrolling".
   So the gradients circle on their own; edge lights, photo pans and dots follow the scroll; glints, sheens and the light
   band play once on arrival. Edge lights sit exactly on each box's own border (Mobbin check: lights never outside it).
   Readability: every moving layer sits behind the content at low strength, cards keep their solid fill, body text
   never moves once it has arrived. Only bands on screen animate; reduced motion gets none of this (motion.js stops). */


/* 1. Moving gradient backgrounds, behind every band */
/* 3g (his Safari screen, two straight lines round "Businesses that trust us"): his Safari read overflow-x: clip as clipping
   top and bottom too, which cut the fades that reach past a band's edges. Nothing in a band is wider than the page
   (the glows are clipped inside .mx-bg and the fixed field), so bands no longer clip at all. */
.mx .mx-band { position: relative; isolation: isolate; overflow: visible; }
/* 3e: a photo page top keeps its own crop (letting it spill showed ~100 px of full-strength photo below it) */
.mx .page-hero.mx-band:not(.plain) { overflow: hidden; }
.mx-bg { position: absolute; inset: 0; z-index: -1; pointer-events: none; overflow: clip; }
/* the moving layer is pinned to the screen while its band passes, so tall bands never scroll it out of view */
.mx-stage { position: sticky; top: 0; height: 100vh; max-height: 100%; overflow: clip; }
/* each glow sits off-centre inside a layer that turns slowly, so the glows circle round behind the content */
.mx-orb { position: absolute; inset: -12%; animation: mx-turn 34s linear infinite; }
.mx-orb2 { animation-duration: 46s; animation-direction: reverse; }
.mx-orb3 { animation-duration: 27s; }
@keyframes mx-turn { to { transform: rotate(1turn); } }
.mx-b {
  position: absolute; width: min(78vmax, 1150px); aspect-ratio: 1; border-radius: 50%; transform: translate(-50%, -50%);
  background: radial-gradient(closest-side, var(--c), color-mix(in srgb, var(--c) 45%, transparent) 50%, transparent 100%);
}
.mx-b1 { --c: rgba(241,104,35,0.30); left: 20%; top: 22%; }
.mx-b2 { --c: rgba(64,118,170,0.36); left: 80%; top: 70%; }
.mx-b3 { --c: rgba(241,104,35,0.18); left: 52%; top: 90%; }
.mx-bg[data-k="1"] .mx-orb1 { animation-delay: -12s; }
.mx-bg[data-k="2"] .mx-orb1 { animation-delay: -22s; } .mx-bg[data-k="2"] .mx-orb2 { animation-delay: -18s; }
.mx-bg[data-k="3"] .mx-orb2 { animation-delay: -30s; } .mx-bg[data-k="3"] .mx-orb3 { animation-delay: -9s; }
.mx-dots {
  position: absolute; inset: -64px;
  background-image: radial-gradient(rgba(255,255,255,0.075) 1.3px, transparent 1.8px);
  background-size: 32px 32px;
  -webkit-mask-image: linear-gradient(115deg, transparent 5%, #000 45%, transparent 95%); mask-image: linear-gradient(115deg, transparent 5%, #000 45%, transparent 95%);
  transform: translate3d(var(--mxd, 0px), var(--mxd, 0px), 0);   /* drifts with the scroll (motion.js), still when you stop */
}
/* a band of light that crosses the section once when it first comes into view */
.mx-ray {
  position: absolute; top: -20%; bottom: -20%; left: 0; width: 38%;
  background: linear-gradient(100deg, transparent, rgba(255,255,255,0.07) 45%, rgba(241,104,35,0.10) 55%, transparent);
  transform: translateX(-120%) skewX(-14deg);
}
.mx-band.mx-seen .mx-ray { animation: mx-ray 2.8s cubic-bezier(0.45, 0, 0.2, 1) 0.3s 1 both; }
/* light bands (reviews, estimator page parts): softer, cooler blobs, darker dots */
.mx-bg[data-tone="light"] .mx-b1 { --c: rgba(241,104,35,0.20); }
.mx-bg[data-tone="light"] .mx-b2 { --c: rgba(90,140,190,0.24); }
.mx-bg[data-tone="light"] .mx-dots { background-image: radial-gradient(rgba(0,0,0,0.08) 1.3px, transparent 1.8px); }
.mx-bg[data-tone="light"] .mx-ray { background: linear-gradient(100deg, transparent, rgba(255,255,255,0.55) 50%, transparent); }
/* the orange closing band: stays orange, the blobs shift it between a lighter and a deeper orange */
.mx-bg[data-tone="orange"] .mx-b1 { --c: rgba(255,160,100,0.75); }
.mx-bg[data-tone="orange"] .mx-b2 { --c: rgba(200,70,10,0.2); }   /* kept weak: the dark text on orange must stay above 4.5:1 */
.mx-bg[data-tone="orange"] .mx-b3 { --c: rgba(255,190,140,0.45); }
.mx-bg[data-tone="orange"] .mx-dots { background-image: radial-gradient(rgba(0,0,0,0.09) 1.3px, transparent 1.8px); }
.mx-bg[data-tone="orange"] .mx-ray { background: linear-gradient(100deg, transparent, rgba(255,255,255,0.22) 50%, transparent); }
/* off-screen bands: nothing runs, no layers kept */
.mx-band:not(.mx-live) .mx-orb { animation: none; }
.mx-field.mx-off .mx-orb { animation-play-state: paused; }

@keyframes mx-o3 { 0% { transform: translate(0, 0) scale(1); } 100% { transform: translate(-34%, -22%) scale(1.25); } }
@keyframes mx-ray { from { transform: translateX(-120%) skewX(-14deg); } to { transform: translateX(380%) skewX(-14deg); } }

/* the hero: a warm glow circling behind the headline (the dusk film and mist already move) */
.mx .hero .hero-pin::after {
  content: ""; position: absolute; left: -10%; top: 10%; width: 70%; height: 90%; pointer-events: none; z-index: 0;
  background: radial-gradient(closest-side, rgba(241,104,35,0.20), transparent);
  transform-origin: 70% 40%; animation: mx-turn 30s linear infinite;
}
.mx .hero .wrap { position: relative; z-index: 2; }

/* 2. Words: headings arrive word by word, then a glint of light passes along them once */
.mx-w { display: inline-block; overflow: clip; padding: 0.06em 0.04em 0.12em; margin: -0.06em -0.04em -0.12em; vertical-align: top; }
/* 3c: the word keeps its own solid colour and shadow (his note: the hero headline looked grey). The glint is a copy of
   the word laid over it, see-through except for the band of light, so nothing can ever tint the word itself. */
.mx-wi {
  display: inline-block; position: relative; transform: translateY(105%) rotate(4deg); opacity: 0;
  transition: transform 0.85s cubic-bezier(0.2, 0.75, 0.15, 1), opacity 0.5s ease-out;
  transition-delay: calc(var(--i) * 55ms + var(--d0, 0ms));
}
.mx-wi::after {
  content: attr(data-t); position: absolute; left: 0; top: 0; pointer-events: none; white-space: nowrap;
  color: transparent; -webkit-text-fill-color: transparent; text-shadow: none;
  background-image: linear-gradient(100deg, transparent 0 40%, var(--glint, rgba(255,226,206,0.95)) 50%, transparent 60% 100%);
  background-size: 360% 100%; background-position: 100% 0; background-repeat: no-repeat;
  -webkit-background-clip: text; background-clip: text;
}
.mx-now .mx-wi { transition: none; }
.mx-in .mx-wi { transform: none; opacity: 1; }
.mx-in .mx-wi::after { animation: mx-glint 2.2s ease-in-out 1 both; animation-delay: calc(0.7s + var(--i) * 90ms); }
.flip .mx-wi, .closing .mx-wi, .est .mx-wi { --glint: #f16823; }
.closing .mx-wi { --glint: rgba(255, 255, 255, 0.4); }   /* a soft light over the black letters, never a white cut through them */
@keyframes mx-glint { from { background-position: 100% 0; } to { background-position: 0% 0; } }

/* body text and lists: a soft arrival, then still */
.mx-tx { opacity: 0; transform: translateY(18px); filter: blur(6px); transition: opacity 0.7s ease-out, transform 0.8s cubic-bezier(0.2, 0.75, 0.15, 1), filter 0.7s ease-out; transition-delay: var(--d, 0ms); }
.mx-tx.mx-in { opacity: 1; transform: none; filter: none; }
/* bold phrases get an orange underline drawn under them on arrival */
.mx .ticks b, .mx .facts-line b { background: linear-gradient(var(--orange), var(--orange)) 0 100% / 0 2px no-repeat; transition: background-size 0.9s 0.5s cubic-bezier(0.2, 0.75, 0.15, 1); }
.mx .mx-in .ticks b, .mx .ticks .mx-in b, .mx .mx-in.ticks b { background-size: 100% 2px; }

/* 3. Boxes: they tip up into place, a light runs round their edge as you scroll, and on a computer they lean toward the pointer */
.mx-box { position: relative; }
html.fx .mx-box.rv:not(.in), .mx-box.mx-pre:not(.mx-in) { opacity: 0; transform: perspective(1000px) rotateX(18deg) translateY(56px) scale(0.94); }
html.fx .mx-box.rv.in { transition: opacity 0.7s ease-out, transform 0.95s cubic-bezier(0.2, 0.75, 0.15, 1), box-shadow 0.2s; transition-delay: var(--d, 0s); }
.mx-box.mx-pre.mx-in { transition: opacity 0.7s ease-out, transform 0.95s cubic-bezier(0.2, 0.75, 0.15, 1), box-shadow 0.2s; transition-delay: var(--d, 0s); }
/* the light is drawn exactly on the box's own border (motion.js sets the inset and the width from it), never outside */
.mx-edge {
  position: absolute; inset: var(--ei, -2px); border-radius: var(--er, inherit); padding: var(--ew, 2px); pointer-events: none; z-index: 2;
  background: conic-gradient(from calc(var(--mxa, 0) * 1deg + var(--eo, 0deg)), transparent 0 64%, rgba(241,104,35,0) 66%, #f16823 78%, #ffd0b0 82%, transparent 90% 100%);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0);
}
.mx-glare { position: absolute; inset: 0; border-radius: inherit; pointer-events: none; z-index: 1; opacity: 0; transition: opacity 0.3s;
  background: radial-gradient(240px circle at var(--gx, 50%) var(--gy, 50%), rgba(255,255,255,0.13), transparent 70%); }
.mx-box.mx-tilt .mx-glare { opacity: 1; }
.mx-box.mx-tilt { transform: perspective(900px) rotateX(var(--ry, 0deg)) rotateY(var(--rx, 0deg)) translate(-3px, -3px) !important; transition: transform 0.12s linear, box-shadow 0.2s !important; }

/* buttons: a sheen passes across the orange ones once when they come into view, and on hover */
.mx .btn-orange { background-image: linear-gradient(110deg, transparent 35%, rgba(255,255,255,0.42) 50%, transparent 65%); background-size: 260% 100%; background-position: 130% 0; background-repeat: no-repeat; }
.mx .btn-orange.mx-in { animation: mx-btn 1.3s ease-in-out 0.5s 1 both; }
.mx .btn-orange.mx-in:hover { animation: mx-btn2 0.9s ease-in-out 1 both; }
@keyframes mx-btn { from { background-position: 130% 0; } to { background-position: -30% 0; } }
@keyframes mx-btn2 { from { background-position: 130% 0; } to { background-position: -30% 0; } }

/* 4. Photos: they open from a wipe, then pan inside their frame as you scroll past (motion.js) */
.mx-ph { clip-path: inset(0 0 100% 0 round 12px); transform: scale(1.06); transition: clip-path 1.1s cubic-bezier(0.65, 0, 0.2, 1), transform 1.4s cubic-bezier(0.2, 0.75, 0.15, 1); transition-delay: var(--d, 0ms); }
.mx-ph.mx-in { clip-path: inset(0 0 0 0 round 12px); transform: none; }
/* photos that sit behind a figure label get a light passing over them once as they open */
.mx .work figure, .mx .rev-photo { position: relative; }
.mx .work figure::after, .mx .rev-photo::after {
  content: ""; position: absolute; inset: 0 0 auto 0; height: var(--phh, 100%); pointer-events: none; border-radius: 12px;
  background: linear-gradient(100deg, transparent 40%, rgba(255,255,255,0.16) 50%, transparent 60%) 0 0 / 300% 100% no-repeat;
  background-position: 120% 0;
}
.mx .work figure:has(.mx-ph.mx-in)::after, .mx .rev-photo:has(.mx-ph.mx-in)::after { animation: mx-btn 1.4s ease-in-out 1.1s 1 both; }

/* spacing (Mobbin check, 3b): the heading sits clear of the lit boxes below it, and review cards use the same 24 px gap as every other grid */
.mx .section-head:has(+ :is(.svc, .rev-grid, .cards, .pair, .work, .towns)) { margin-bottom: 40px; }
.mx .rev-small { gap: 24px; }
@media (max-width: 760px) { .mx .section-head:has(+ :is(.svc, .rev-grid, .cards, .pair, .work, .towns)) { margin-bottom: 28px; } }

@media (prefers-reduced-motion: reduce) {
  .mx-bg, .mx-edge, .mx-glare, .mx .hero .hero-pin::after { display: none; }
  .mx-wi, .mx-tx, .mx-ph, .mx-box { opacity: 1 !important; transform: none !important; filter: none !important; clip-path: none !important; animation: none !important; }
}

/* 3c fixes from his look at the computer walkthrough (2026-10-28) */
/* Nothing may cover the hero's buttons or the estimator's button: the "Businesses that trust us" strip was pulled 72 px
   up into the bottom of the first screen (64 px on phones), right over them. It now starts below the hero. */
.clients { margin-top: 0; }
/* Drea sat under the floating menu on computers up to 1536 px wide: she now overlaps the card's dark top band instead of
   standing 112 px above it, and the pinned hero leaves a little more room under the menu. */
@media (min-width: 981px) {
  .hero .drea, .page-hero .drea { top: -46px; right: -52px; width: 150px; }
  html.fx .hero.scrub .hero-pin > .wrap { padding-top: 140px; }
}
/* Service-area lists (Mobbin: Fresha, ClassPass, Airtasker group places under a bold region name with a clear gap):
   each state is its own box with real padding, the name 14 px above its towns, the towns evenly spaced. */
.towns { gap: 20px; }
.towns > div:not(.callout) { background: var(--paper); border: 2px solid var(--wash-line); border-radius: 14px; padding: 22px 24px 24px; }
.towns h3 { margin: 0 0 14px; line-height: 1.1; }
.towns ul { gap: 10px 8px; }
.flip .towns > div:not(.callout), .closing .towns > div:not(.callout) { background: #fff; }
@media (max-width: 760px) { .towns > div:not(.callout) { padding: 18px 18px 20px; } }

/* the price form's choices: simple line icons (his choice, 2026-10-28) instead of the colour pictures */
.ptiles .q-icon { background: #fff; }
.ptiles .q-icon svg { width: 52px; height: 52px; stroke: #000; stroke-width: 1.7; }
.ptiles .tile label:hover .q-icon svg, .ptiles .tile input:checked + label .q-icon svg { stroke: var(--orange); }

/* 3c seams: one gradient field behind the whole page; coloured sections on skins with soft, curved ends */
.mx-field { position: fixed; inset: 0; z-index: -1; pointer-events: none; overflow: hidden; }
.mx-field .mx-stage { position: absolute; inset: 0; height: auto; max-height: none; }
.mx-skin {
  position: absolute; left: 0; right: 0; top: calc(-1 * var(--ft, 0px)); bottom: calc(-1 * var(--fb, 0px)); z-index: -1; pointer-events: none;
  background: var(--sc);
  /* top and bottom ends: a wide ellipse, so the colour arrives in a shallow arc rather than a straight line */
  -webkit-mask-image: radial-gradient(150% 100% at 50% 100%, #000 40%, transparent 100%), linear-gradient(#000, #000), radial-gradient(150% 100% at 50% 0%, #000 40%, transparent 100%);
          mask-image: radial-gradient(150% 100% at 50% 100%, #000 40%, transparent 100%), linear-gradient(#000, #000), radial-gradient(150% 100% at 50% 0%, #000 40%, transparent 100%);
  -webkit-mask-size: 100% calc(2 * var(--ft, 0px)), 100% calc(100% - 2 * var(--ft, 0px) - 2 * var(--fb, 0px) + 2px), 100% calc(2 * var(--fb, 0px));
          mask-size: 100% calc(2 * var(--ft, 0px)), 100% calc(100% - 2 * var(--ft, 0px) - 2 * var(--fb, 0px) + 2px), 100% calc(2 * var(--fb, 0px));
  -webkit-mask-position: 0 0, 0 calc(2 * var(--ft, 0px) - 1px), 0 100%; mask-position: 0 0, 0 calc(2 * var(--ft, 0px) - 1px), 0 100%;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
}
.mx-skin > .mx-bg { z-index: 0; }
.mx-fade { position: absolute; left: 0; right: 0; top: 0; height: var(--fh, 140px); z-index: -1; pointer-events: none; background: linear-gradient(#000, rgba(0, 0, 0, 0)); }
/* 3e: photo page tops fade to pure black at the bottom, so the next section's fade starts from the same black */
.mx-phfade { position: absolute; left: 0; right: 0; bottom: 0; height: min(240px, 30%); z-index: -1; pointer-events: none; background: linear-gradient(rgba(0, 0, 0, 0), #000 92%); }


/* 3d: on laptop screens the first screen's headline column and form shrink to fit under the menu (motion.js sets --hz) */
.hero.scrub .hero-copy, .hero.scrub .est-holder { zoom: var(--hz, 1); }

/* 3f (his Safari screen): Safari drew the moving photo (a canvas) over the dark shading at the bottom of the first
   screen, so the photo stayed bright to its edge. Give each layer an explicit place: photo, then shading, then words. */
.hero .scene-bg { z-index: 0; }
.hero .scene-canvas { z-index: 0; }
.hero .scene-shade { z-index: 1; }
.hero .fogs { z-index: 1; }
.hero .hero-pin > .wrap { position: relative; z-index: 2; }

/* 3h test (his note 2026-10-29) ------------------------------------------------------------------------------------ */
/* the moving background reads as one gradient: five large glows, overlapping, that drift as well as circle */
.mx-b { width: min(115vmax, 1800px); }
.mx-b1 { --c: rgba(241,104,35,0.34); }
.mx-b4 { --c: rgba(190,70,20,0.30); left: 88%; top: 14%; }
.mx-b5 { --c: rgba(40,92,150,0.34); left: 8%; top: 84%; }
.mx-orb4 { animation-duration: 39s; animation-direction: reverse; }
.mx-orb5 { animation-duration: 52s; }
.mx-b { animation: mx-drift 23s ease-in-out infinite alternate; }
.mx-b2 { animation-duration: 29s; animation-delay: -7s; }
.mx-b3 { animation-duration: 19s; animation-delay: -11s; }
.mx-b4 { animation-duration: 31s; animation-delay: -3s; }
.mx-b5 { animation-duration: 26s; animation-delay: -15s; }
@keyframes mx-drift { 0% { translate: -14% 8%; scale: 0.9; } 50% { translate: 10% -12%; scale: 1.12; } 100% { translate: 16% 14%; scale: 0.96; } }
.mx-band:not(.mx-live) .mx-b { animation: none; }
.mx-field.mx-off .mx-b { animation-play-state: paused; }
.mx-bg[data-tone="light"] .mx-b4 { --c: rgba(241,104,35,0.14); } .mx-bg[data-tone="light"] .mx-b5 { --c: rgba(90,140,190,0.18); }
/* the price band is water (3h, blue since 3k): a photographed waterline on top (motion.js), the same water's light
   below, slowly drifting, with the words on a dark glass panel; a straight line into the footer */
.mx .closing.mx-water { position: relative; background: transparent; border-top-color: transparent; }
.mx-caus {
  position: absolute; inset: 0; z-index: -1; pointer-events: none; overflow: hidden; background: #2087cb;
  -webkit-mask-image: linear-gradient(transparent, #000 var(--wd, 30px)); mask-image: linear-gradient(transparent, #000 var(--wd, 30px));
}
.mx-caus::after { content: ""; position: absolute; inset: 0; background: rgba(32,135,203,0.5); }
.mx-caus > i {
  position: absolute; inset: -12% -8%; background: url(/assets/water/blue/caustic-1200.webp) center / cover;
  animation: mx-caus 22s ease-in-out infinite alternate;
}
@media (min-width: 1100px), (min-resolution: 2dppx) { .mx-caus > i { background-image: url(/assets/water/blue/caustic-2400.webp); } }
@keyframes mx-caus { from { transform: translate3d(-3%, -2%, 0) scale(1.02); } to { transform: translate3d(3%, 2%, 0) scale(1.07); } }
.mx-band:not(.mx-live) .mx-caus > i { animation-play-state: paused; }
.mx-water-orange .mx-caus { background: #F16823; }
.mx-water-orange .mx-caus::after { background: rgba(241,104,35,0.5); }
.mx-water-orange .mx-caus > i { background-image: url(/assets/water/caustic-2400.webp); }
/* the words sit on a dark glass panel, in white (his note: the black words on the water were hard to read) */
.mx .closing.mx-water .wrap {
  background: rgba(6,10,16,0.66); border: 1px solid rgba(255,255,255,0.14); border-radius: 14px;
  padding: 44px 52px; box-shadow: 0 18px 50px rgba(0,20,50,0.35);
}
.mx .closing.mx-water h2 { color: #fff; }
.mx .closing.mx-water p { color: rgba(255,255,255,0.9); }
/* on blue water the main button turns the brand orange, so the band still says Driftless */
.mx .closing.mx-water .btn-ink { background: var(--orange); color: var(--ink); border-color: var(--ink); box-shadow: 4px 4px 0 #000; }
.mx .closing.mx-water-orange .btn-ink { background: var(--ink); color: var(--paper); border-color: #fff; box-shadow: 4px 4px 0 var(--orange); }
@media (max-width: 760px) { .mx .closing.mx-water .wrap { padding: 24px 22px; width: calc(100% - 32px); } }
.mx-surf { position: absolute; left: 0; width: 100%; z-index: -2; pointer-events: none; }
/* 3j (his note: edges should look intentional): where a photo meets the dark background, a thin light line marks the
   edge, like a frame, instead of the photo just stopping */
/* 3l (his pick of the edge ideas, 2026-10-29: "a mix between number six, number four and number two"):
   - photo edges and the water's bottom: the Driftless trim, a black edge with an orange stripe (idea 4)
   - light sections: a raised panel floating above the gradient (idea 6), with the gradient's soft shadow falling onto
     the white at its top and bottom (idea 2) */
.mx-trim {
  position: absolute; left: 0; right: 0; bottom: 0; height: 12px; z-index: 6; pointer-events: none;
  background: linear-gradient(#000 0 3px, #F16823 3px 9px, #000 9px);
}
.mx-skin[data-tone="light"] {
  left: 22px; right: 22px; border-radius: 28px; overflow: hidden;
  -webkit-mask: none; mask: none;
  box-shadow: 0 30px 70px rgba(0,0,0,0.7), 0 -10px 40px rgba(0,0,0,0.4),
              inset 0 26px 30px -16px rgba(0,0,0,0.38), inset 0 -26px 30px -16px rgba(0,0,0,0.38);
}
@media (max-width: 760px) {
  .mx-skin[data-tone="light"] { left: 8px; right: 8px; border-radius: 20px; }
  .mx .mx-band:has(> .mx-skin[data-tone="light"]) > .wrap { padding-left: 24px; padding-right: 24px; }
}
.mx-fade, .mx-phfade { display: none; }   /* no see-through fades anywhere */

/* 3m (his phone note: "the drop shadow on the back is all blocky"): each word sits in its own clipping box so it can
   rise into place, and that box cut the headline's soft shadow into squares. The shadow is now drawn for the whole
   headline at once, around the letters themselves. */
.mx .mx-w, .mx .mx-wi { text-shadow: none; }
.mx .hero h1[data-mx-split], .mx .page-hero:not(.plain) h1[data-mx-split] { filter: drop-shadow(0 2px 12px rgba(0,0,0,0.75)); }

/* 10b (his note after UPDATE-10: the light round the boxes "is not smooth with my scroll"): where the browser can tie an
   animation to the scroll itself (Safari 26 and later, Chrome), the edge lights and the dot grain follow the scroll from
   here, in step with it; motion.js only drives them in older browsers. About the same speed as before on the home page. */
@property --mxa { syntax: "<number>"; inherits: true; initial-value: 0; }
@supports (animation-timeline: scroll()) {
  .mx-edge { animation: mx-edge-run linear both; animation-duration: auto; animation-timeline: scroll(root block); }
  .mx-dots { animation: mx-dots-run linear both; animation-duration: auto; animation-iteration-count: 34; animation-timeline: scroll(root block); }
}
@keyframes mx-edge-run { from { --mxa: 0; } to { --mxa: 2700; } }
@keyframes mx-dots-run { from { transform: translate3d(0, 0, 0); } to { transform: translate3d(32px, 32px, 0); } }
