/* Affinix motion kit (goes with motion.js; markup in tools/motion/demo.html). Phones first.
   Override the tokens in the site's own CSS to give each site its own feel: a crisp salon might use a faster
   --m-dur, a calm spa a longer one. Everything here is off under prefers-reduced-motion. */
:root {
  --m-ease: cubic-bezier(.16, 1, .3, 1);      /* long, soft landing */
  --m-ease-io: cubic-bezier(.65, 0, .35, 1);  /* wipes and cross-fades */
  --m-dur: .95s;
  --m-rise: 32px;
  --m-word: 55ms;                             /* delay between words in a "words" heading */
}
/* Phones: shorter distances and quicker timing. A thumb-scroll is fast, and a long, far-travelling reveal
   on a small screen reads as lag, not polish. */
@media (max-width: 719px) {
  :root { --m-dur: .75s; --m-rise: 18px; --m-word: 38ms; }
}

/* ---------- reveals ---------- */
@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
  /* Hidden until revealed, only when scripts run, so visitors without JavaScript see everything. */
  @media (scripting: enabled) {
    [data-reveal] {
      opacity: 0;
      transform: translate3d(0, var(--m-rise), 0);
      transition: opacity var(--m-dur) var(--m-ease) var(--d, 0ms), transform var(--m-dur) var(--m-ease) var(--d, 0ms),
        clip-path calc(var(--m-dur) * 1.25) var(--m-ease-io) var(--d, 0ms), scale calc(var(--m-dur) * 1.6) var(--m-ease) var(--d, 0ms);
    }
    [data-reveal="fade"] { transform: none; }
    [data-reveal="scale"] { transform: scale(.94); }
    [data-reveal="settle"] { opacity: 1; transform: none; scale: 1.08; }
    [data-reveal="mask"] { opacity: 1; transform: none; clip-path: inset(0 0 100% 0); }
    [data-reveal="mask-left"] { opacity: 1; transform: none; clip-path: inset(0 100% 0 0); }
    [data-reveal="words"] { opacity: 1; transform: none; }
    [data-reveal="words"]:not([data-m-split]) { opacity: 0; }
    [data-reveal="words"] .m-w { display: inline-block; overflow: hidden; vertical-align: top; padding-bottom: .1em; margin-bottom: -.1em; }
    [data-reveal="words"] .m-wi { display: inline-block; transform: translate3d(0, 110%, 0); transition: transform var(--m-dur) var(--m-ease) calc(var(--d, 0ms) + var(--i, 0) * var(--m-word)); }
    /* The finished clip reaches past the edges so shadows aren't cut off. */
    [data-reveal].is-in { opacity: 1; transform: none; clip-path: inset(-120px); scale: 1; }
    [data-reveal="words"].is-in .m-wi { transform: none; }
    /* If the script never runs, show everything after a moment rather than leave the page blank. */
    html:not(.m-on) [data-reveal], html:not(.m-on) [data-reveal] .m-wi { animation: m-show 0s 1.8s forwards; }
  }
}
@keyframes m-show { to { opacity: 1; transform: none; clip-path: none; scale: 1; } }

/* ---------- parallax ---------- */
.m-frame { position: relative; overflow: hidden; }
.m-frame > img[data-parallax], .m-frame > picture > img[data-parallax] { scale: 1.16; will-change: translate; }
.m-frame img { display: block; width: 100%; height: 100%; object-fit: cover; }
/* Tied to scrolling by the browser itself where it can (smooth on phones); motion.js sets --m-par per element. */
@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    .m-par-css { animation: m-par linear both; animation-timeline: view(); }
  }
}
@keyframes m-par { from { translate: 0 calc(var(--m-par, 0px) * -1); } to { translate: 0 var(--m-par, 0px); } }

/* ---------- slideshow ---------- */
[data-slideshow] { position: relative; overflow: hidden; }
[data-slideshow] > img, [data-slideshow] > picture, [data-slideshow] > figure { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; object-fit: cover; opacity: 0; transition: opacity 1.6s var(--m-ease-io); }
[data-slideshow] > picture img, [data-slideshow] > figure img { width: 100%; height: 100%; object-fit: cover; }
[data-slideshow]:not(.m-live) > :first-child, [data-slideshow] > .is-active { opacity: 1; }
@media (prefers-reduced-motion: no-preference) {
  [data-slideshow].m-live > .is-active { animation: m-drift 10s linear both; }
}
@keyframes m-drift { from { scale: 1 } to { scale: 1.07 } }
.m-pause { position: absolute; z-index: 2; right: 12px; bottom: 12px; width: 44px; height: 44px; border: 0; border-radius: 50%; background: rgba(0, 0, 0, .45); color: #fff; cursor: pointer; display: grid; place-items: center; -webkit-tap-highlight-color: transparent; }
.m-pause::before { content: ""; width: 12px; height: 14px; border-inline: 4px solid currentColor; box-sizing: border-box; }
.m-pause.is-paused::before { width: 0; height: 0; border-inline: 0; border-block: 7px solid transparent; border-left: 12px solid currentColor; translate: 2px 0; }
.m-pause:focus-visible { outline: 3px solid #fff; outline-offset: 2px; }

/* ---------- carousel ---------- */
[data-carousel] .m-track {
  display: grid; grid-auto-flow: column; grid-auto-columns: var(--m-item, min(82%, 420px)); gap: var(--m-gap, 14px);
  overflow-x: auto; overscroll-behavior-x: contain; scroll-snap-type: x mandatory; scroll-padding-inline: var(--m-pad, 0px);
  padding-inline: var(--m-pad, 0px); scrollbar-width: none; -webkit-overflow-scrolling: touch;
}
@media (hover: hover) { [data-carousel] .m-track { cursor: grab; } }
[data-carousel] .m-track::-webkit-scrollbar { display: none; }
[data-carousel] .m-track > * { scroll-snap-align: start; }
[data-carousel] .m-track.is-drag { scroll-snap-type: none; cursor: grabbing; user-select: none; }
[data-carousel] .m-track.is-drag img { pointer-events: none; }
[data-carousel] .m-track:focus-visible { outline: 3px solid currentColor; outline-offset: 4px; }
[data-carousel] [data-prev]:disabled, [data-carousel] [data-next]:disabled { opacity: .35; cursor: default; }
[data-dots] { display: flex; justify-content: center; gap: 2px; margin-top: 12px; }
[data-dots] button { width: 28px; height: 28px; padding: 0; border: 0; background: none; color: inherit; display: grid; place-items: center; cursor: pointer; -webkit-tap-highlight-color: transparent; }
[data-dots] button::before { content: ""; width: 7px; height: 7px; border-radius: 4px; background: currentColor; opacity: .3; transition: opacity .3s ease, width .4s var(--m-ease); }
[data-dots] button.is-active::before { width: 20px; opacity: 1; }
[data-dots] button:focus-visible { outline: 2px solid currentColor; outline-offset: -2px; border-radius: 6px; }

/* ---------- before / after ---------- */
[data-compare] { --pos: 50%; position: relative; overflow: hidden; user-select: none; touch-action: pan-y; cursor: ew-resize; -webkit-tap-highlight-color: transparent; }
[data-compare] img { display: block; width: 100%; height: 100%; object-fit: cover; pointer-events: none; }
[data-compare] .m-after { position: absolute; inset: 0; clip-path: inset(0 0 0 var(--pos)); }
[data-compare]::after { content: ""; position: absolute; top: 0; bottom: 0; left: var(--pos); width: 2px; translate: -1px 0; background: #fff; box-shadow: 0 0 0 1px rgba(0, 0, 0, .12); pointer-events: none; }
/* The range input stays for keyboards and screen readers but doesn't sit over the photo (on a phone it would
   catch the swipes meant to scroll the page). */
[data-compare] .m-range { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; border: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
[data-compare] .m-knob { position: absolute; z-index: 1; top: 50%; left: var(--pos); translate: -50% -50%; width: 48px; height: 48px; border-radius: 50%; background: #fff; box-shadow: 0 4px 18px rgba(0, 0, 0, .25); pointer-events: none; display: grid; place-items: center; }
[data-compare] .m-knob::before { content: "\2039\00a0\203A"; font: 600 20px/1 system-ui, sans-serif; color: #222; }
[data-compare] .m-range:focus-visible ~ .m-knob { outline: 3px solid #fff; outline-offset: 3px; }
[data-compare] .m-tag { position: absolute; z-index: 1; top: 12px; padding: 4px 10px; font-size: 13px; font-weight: 600; color: #fff; background: rgba(0, 0, 0, .5); pointer-events: none; }
[data-compare] .m-tag.before { left: 12px; }
[data-compare] .m-tag.after { right: 12px; }

/* ---------- preview list ---------- */
[data-preview-target] { position: relative; overflow: hidden; }
[data-preview-target] > * { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: 0; scale: 1.05; transition: opacity .7s var(--m-ease), scale 1.4s var(--m-ease); }
[data-preview-target]:not(.m-live) > :first-child, [data-preview-target] > .is-active { opacity: 1; scale: 1; }
/* On touch the figure sits right under the chosen item, at full width. It overrides the site's desktop layout
   for the figure (sticky column, tall ratio), hence the !important on size and position only. */
[data-preview-target].m-inline { position: relative !important; inset: auto !important; top: auto !important; width: 100% !important; height: auto !important; max-width: none !important; aspect-ratio: 4 / 3 !important; margin: 2px 0 14px !important; }
[data-preview-list] [data-preview] { -webkit-tap-highlight-color: transparent; }

/* ---------- header and phone action bar ---------- */
[data-header] { transition: translate .5s var(--m-ease), background-color .35s ease, box-shadow .35s ease; }
[data-header].is-hidden { translate: 0 -100%; }
[data-actionbar] { transition: translate .5s var(--m-ease); }
html.m-on [data-actionbar]:not(.is-shown) { translate: 0 calc(100% + 24px); }

/* ---------- small interactions (opt in with a class) ---------- */
/* Hover effects only where there is a real hover (a mouse or trackpad). On phones a tap would leave them stuck
   on, so touch gets press feedback instead. */
.m-link { text-decoration: none; background: linear-gradient(currentColor, currentColor) 0 100% / 0 1.5px no-repeat; transition: background-size .5s var(--m-ease); -webkit-tap-highlight-color: transparent; }
.m-link:focus-visible, .m-link:active { background-size: 100% 1.5px; }
.m-btn { position: relative; overflow: hidden; isolation: isolate; transition: color .4s var(--m-ease), border-color .4s var(--m-ease), scale .2s ease; -webkit-tap-highlight-color: transparent; }
.m-btn::before { content: ""; position: absolute; inset: 0; z-index: -1; background: var(--m-fill, rgba(255, 255, 255, .16)); translate: -101% 0; transition: translate .55s var(--m-ease); }
.m-btn:focus-visible::before, .m-btn:active::before { translate: 0 0; }
.m-btn:active { scale: .97; }
.m-nudge { transition: translate .4s var(--m-ease); }
a:focus-visible > .m-nudge { translate: 4px 0; }
.m-zoom { overflow: hidden; }
.m-zoom img { transition: scale 1.3s var(--m-ease); }
@media (hover: hover) {
  .m-link:hover { background-size: 100% 1.5px; }
  .m-btn:hover::before { translate: 0 0; }
  a:hover > .m-nudge, button:hover > .m-nudge { translate: 4px 0; }
  .m-zoom:hover img, .m-zoom:focus-within img { scale: 1.05; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; scroll-behavior: auto !important; }
}
