/* Site-wide motion effects (assets/js/fx.js). Nothing here applies until the script adds its class, so without
   JavaScript, or with reduced motion (the script then does nothing), every page looks exactly as it did. */

/* ---- odometer: a rolling digit keeps the line's baseline (inline-block with no overflow), and clip-path -- which
   leaves the baseline alone -- hides the glyphs sliding in and out of its slot */
.pl-odo { font-variant-numeric: tabular-nums; }
.pl-odo__d { position: relative; display: inline-block; clip-path: inset(0 -0.2em); }
.pl-odo__d.is-roll .pl-odo__t { visibility: hidden; }
.pl-odo__d.is-roll::before, .pl-odo__d.is-roll::after { position: absolute; left: 0; right: 0; top: 0; text-align: center; animation: .6s cubic-bezier(.2, .9, .25, 1) var(--dl, 0ms) both; }
.pl-odo__d.is-roll::before { content: attr(data-o); content: attr(data-o) / ""; animation-name: pl-odo-out; }   /* "/ ''": the digit is already in the text; */
.pl-odo__d.is-roll::after { content: attr(data-n); content: attr(data-n) / ""; animation-name: pl-odo-in; }      /* screen readers skip the rolling copies */
.pl-odo.is-down .pl-odo__d.is-roll::before { animation-name: pl-odo-out-down; }
.pl-odo.is-down .pl-odo__d.is-roll::after { animation-name: pl-odo-in-down; }
@keyframes pl-odo-out { to { transform: translateY(-105%); } }
@keyframes pl-odo-in { from { transform: translateY(105%); } }
@keyframes pl-odo-out-down { to { transform: translateY(105%); } }
@keyframes pl-odo-in-down { from { transform: translateY(-105%); } }

/* ---- beading: a canvas behind the card's own content */
.pl-fx-beads { position: relative; isolation: isolate; }
.pl-fx-beads > .pl-fx-beads__cv { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 0; pointer-events: none; border-radius: inherit; }
.pl-fx-beads > :not(.pl-fx-beads__cv) { position: relative; z-index: 1; }

/* ---- squeegee wipe: a fogged, beaded film over the section, cleared behind a rubber blade as it scrolls in */
.pl-fx-wipe { position: relative; }
/* (2026-10-14: film and blade stay inside the section's width -- -10px either side made phones scroll sideways) */
.pl-fx-wipe__film { position: absolute; inset: -10px 0; z-index: 4; pointer-events: none; border-radius: 18px;
  -webkit-backdrop-filter: blur(6px) saturate(.85); backdrop-filter: blur(6px) saturate(.85);
  background:
    radial-gradient(circle at 30% 35%, rgba(255, 255, 255, .85) 0 1.6px, rgba(160, 200, 230, .35) 2.4px, transparent 3.2px) 0 0 / 37px 43px,
    radial-gradient(circle at 65% 70%, rgba(255, 255, 255, .8) 0 2.4px, rgba(160, 200, 230, .3) 3.4px, transparent 4.4px) 11px 7px / 61px 53px,
    radial-gradient(circle at 50% 50%, rgba(255, 255, 255, .7) 0 1px, transparent 1.8px) 5px 19px / 23px 29px,
    linear-gradient(180deg, rgba(225, 238, 248, .55), rgba(205, 225, 242, .45));
  clip-path: inset(0 0 0 var(--wipe, 0%)); transition: opacity .4s; }
.pl-fx-wipe__blade { position: absolute; top: -14px; bottom: -14px; left: min(var(--wipe, 0%), calc(100% - 8px)); width: 12px; margin-left: -4px; z-index: 5; pointer-events: none; border-radius: 6px;
  background: linear-gradient(90deg, #A9B6C6 0 30%, #D7DFE8 30% 62%, #1F2A3D 62%);     /* metal channel trailing, rubber edge leading */
  box-shadow: 12px 0 16px -8px rgba(127, 227, 245, .6), -3px 0 10px rgba(10, 31, 68, .2); transition: opacity .4s; }   /* water pushed ahead */
.pl-fx-wipe.is-wiped .pl-fx-wipe__film, .pl-fx-wipe.is-wiped .pl-fx-wipe__blade { opacity: 0; }

/* ---- holographic card: a sheen that follows the pointer / tilt, and a slight 3D lean */
.pl-fx-tilt { transform: perspective(900px) rotateX(calc(var(--rx, 0deg) * .5)) rotateY(calc(var(--ry, 0deg) * .5)); transition: transform .25s ease-out; }
.pl-fx-holo { position: relative; isolation: isolate; transform: perspective(900px) rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg));
  transition: transform .25s ease-out; will-change: transform; }
.pl-fx-holo::after { content: ""; position: absolute; inset: 0; z-index: 2; border-radius: inherit; pointer-events: none; mix-blend-mode: soft-light; opacity: .9;
  background: linear-gradient(115deg, transparent 22%, rgba(127, 227, 245, .55) 38%, rgba(181, 140, 255, .5) 47%, rgba(255, 201, 60, .45) 56%, transparent 72%)
    var(--hx, 50%) var(--hy, 50%) / 260% 260% no-repeat; transition: background-position .25s ease-out; }

/* ---- hero droplets: a canvas behind the hero's own content */
.pl-fx-droplets-host { position: relative; isolation: isolate; }
.pl-fx-droplets { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 0; pointer-events: none; }
.pl-fx-droplets-host > :not(.pl-fx-droplets):not(.pl-fx-season) { position: relative; z-index: 1; }   /* the canvases overlay; they are never laid out */

/* ---- rinse-in headings: a wet highlight sweeps across once; the text is never hidden (both ends are its own colour) */
.pl-fx-rinse { background: linear-gradient(100deg, var(--rinse-c) 0 38%, #7FE3F5 46%, #FFFFFF 50%, #7FE3F5 54%, var(--rinse-c) 62% 100%) 100% 0 / 300% 100% no-repeat;
  -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; animation: pl-fx-rinse 1.1s cubic-bezier(.3, .6, .2, 1) both; }
@keyframes pl-fx-rinse { from { background-position: 100% 0; filter: blur(1.5px); } 60% { filter: none; } to { background-position: 0 0; } }
.pl-fx-droplets-host > .pl-fx-season { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 2; pointer-events: none; }

