/**
 * scroll-motion.css — companion to js/scroll-motion.js
 *
 * Ported from the colleague's GSAP animation library to CSS scroll-driven
 * animation so it needs no JS scroll loop and no library.
 *
 * Safety model:
 *   - Motion rules are scoped under `.js-anim` (added by the script only when
 *     the visitor accepts motion) AND behind `@supports (animation-timeline:…)`.
 *   - Pinned stack and horizontal strip DEGRADE to usable static layouts when
 *     scroll-driven animation is unavailable: the stack becomes a normal grid,
 *     the strip becomes a swipeable row. Content is never trapped off-screen.
 *   - Only transform and opacity animate. Both composite on the GPU.
 */

/* ============================ 1. Reveals ============================ */
.js-anim .sm-reveal { opacity: 0; transform: translate3d(0, 16px, 0); }
.js-anim .sm-reveal.is-in {
  opacity: 1;
  transform: none;
  transition:
    opacity 620ms cubic-bezier(0.16, 1, 0.3, 1) var(--sm-delay, 0ms),
    transform 620ms cubic-bezier(0.16, 1, 0.3, 1) var(--sm-delay, 0ms);
}

/* ======================= 2. Scroll progress bar ==================== */
.js-anim .sm-progress {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 60;
  height: 3px;
  transform: scaleX(0);
  transform-origin: 0 50%;
  background: var(--color-orange, currentColor);
  pointer-events: none;
}
@supports (animation-timeline: scroll()) {
  @media (prefers-reduced-motion: no-preference) {
    .js-anim .sm-progress {
      animation: sm-progress-grow linear both;
      animation-timeline: scroll(root block);
    }
  }
}
@keyframes sm-progress-grow { to { transform: scaleX(1); } }

/* =========================== 3. Parallax =========================== *
 * Wrap an image in .sm-parallax-frame (overflow hidden) and give the image
 * .sm-parallax. It drifts vertically as the frame crosses the viewport. */
.sm-parallax-frame { overflow: hidden; }
.sm-parallax-frame .sm-parallax { will-change: transform; }
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .js-anim .sm-parallax-frame .sm-parallax {
      height: 118%;                 /* headroom so the drift never exposes an edge */
      object-fit: cover;
      animation: sm-parallax linear both;
      animation-timeline: view(block);
      animation-range: cover;
    }
  }
}
@keyframes sm-parallax {
  from { transform: translateY(-9%); }
  to   { transform: translateY(9%); }
}

/* ======================= 4. Pinned card stack ====================== *
 * Fallback (no scroll-driven support): a normal responsive grid of cards.
 * Enhanced: the section grows tall, an inner layer pins, and each card fans
 * up from below one after another as the section scrolls through. */
.sm-stack__head { margin-bottom: var(--space-6); }
.sm-stack__cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: var(--space-5);
}
/* Card visuals shared by the demo and by live cards that opt into this look. */
.sm-stack-card, .sm-strip-card {
  background: var(--color-white, #fff);
  border-radius: var(--radius-lg, 24px);
  box-shadow: var(--shadow-card);
  overflow: hidden;
}
.sm-stack-card__accent, .sm-strip-card__accent { height: 8px; }
.sm-stack-card__body, .sm-strip-card__body { padding: var(--space-6); }
.sm-stack-card__body h3, .sm-strip-card__body h3 { font-size: 1.2rem; margin-bottom: var(--space-3); }
.sm-stack-card__body p, .sm-strip-card__body p { color: var(--text-muted, #6b6454); font-size: 0.95rem; line-height: 1.6; }

@supports (animation-timeline: view()) {
  @media (min-width: 900px) and (prefers-reduced-motion: no-preference) {
    .js-anim .sm-stack {
      position: relative;
      /* Scroll runway per card after the first. Kept modest so the completed
         fan holds on screen rather than scrolling away the moment it lands. */
      height: calc(100vh + (var(--sm-card-count, 3) - 1) * 90vh);
      view-timeline-name: --sm-stack;
      view-timeline-axis: block;
    }
    .js-anim .sm-stack__pin {
      position: sticky;
      top: 0;
      height: 100vh;
      display: flex;
      flex-direction: column;
      justify-content: center;
      overflow: hidden;
    }
    .js-anim .sm-stack__cards {
      display: block;
      position: relative;
      height: min(64vh, 520px);
    }
    /* Fanned like a hand of cards: every card pivots from its bottom centre and
       is offset sideways, so the tops spread apart and each card's title stays
       legible instead of piling on top of the one before. Cards are shorter
       than the area and bottom-anchored so the gentle rotation has headroom and
       no top clips out of the pinned viewport. */
    /* Fanned like a hand of cards: pivot from bottom centre, offset sideways so
       tops spread and each title stays legible. Cards are shorter than the area
       and bottom-anchored so the rotation has headroom. */
    .js-anim .sm-stack-card {
      position: absolute;
      bottom: 0;
      left: 50%;
      /* Spread unit: scales with viewport so the fan opens wider on big screens
         (more legible) but never overflows a narrow one. */
      --u: clamp(84px, 8.4vw, 138px);
      width: clamp(206px, 18vw, 250px);
      height: min(48vh, 372px);
      transform-origin: 50% 100%;
      transform: translateX(calc(-50% + var(--fan-x, 0px))) rotate(var(--fan-rot, 0deg));
    }
    /* A card's own :hover lift would fight the fan transform; hold the fan. */
    .js-anim .sm-stack-card:hover {
      transform: translateX(calc(-50% + var(--fan-x, 0px))) rotate(var(--fan-rot, 0deg));
    }
    /* Offsets in units of --u, spread wide enough that each card's title and
       first lines stay clear of the card in front. */
    .js-anim .sm-stack-card:nth-child(1) { --fan-x: calc(var(--u) * -3); --fan-rot: -12deg; z-index: 1; }
    .js-anim .sm-stack-card:nth-child(2) { --fan-x: calc(var(--u) * -1); --fan-rot:  -4deg; z-index: 2; }
    .js-anim .sm-stack-card:nth-child(3) { --fan-x: calc(var(--u) *  1); --fan-rot:   4deg; z-index: 3; }
    .js-anim .sm-stack-card:nth-child(4) { --fan-x: calc(var(--u) *  3); --fan-rot:  12deg; z-index: 4; }
    .js-anim .sm-stack-card:nth-child(5) { --fan-x: calc(var(--u) *  5); --fan-rot:  20deg; z-index: 5; }
    .js-anim .sm-stack-card:not(:first-child) {
      opacity: 0;
      transform: translateX(calc(-50% + var(--fan-x))) translateY(120%) rotate(var(--fan-rot));
      animation: sm-stack-in linear both;
      animation-timeline: --sm-stack;
    }
    .js-anim .sm-stack-card:nth-child(2) { animation-range: 25% 35%; }
    .js-anim .sm-stack-card:nth-child(3) { animation-range: 34% 44%; }
    .js-anim .sm-stack-card:nth-child(4) { animation-range: 43% 53%; }
    .js-anim .sm-stack-card:nth-child(5) { animation-range: 52% 62%; }
  }
}
@keyframes sm-stack-in {
  to {
    opacity: 1;
    transform: translateX(calc(-50% + var(--fan-x))) translateY(0) rotate(var(--fan-rot));
  }
}

/* ====================== 5. Horizontal scroll strip ================= *
 * Fallback: a horizontally swipeable row (overflow-x auto).
 * Enhanced: the section pins and the track slides left as you scroll down. */
.sm-strip__head { margin-bottom: var(--space-5); }
.sm-strip__track {
  display: flex;
  gap: var(--space-5);
  overflow-x: auto;
  padding-bottom: var(--space-4);
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
}
.sm-strip-card {
  scroll-snap-align: start;
  flex: 0 0 clamp(280px, 78vw, 360px);
}

@supports (animation-timeline: view()) {
  @media (min-width: 900px) and (prefers-reduced-motion: no-preference) {
    .js-anim .sm-strip {
      position: relative;
      height: calc(100vh + var(--sm-strip-scroll, 160vh));
      view-timeline-name: --sm-strip;
      view-timeline-axis: block;
    }
    .js-anim .sm-strip__pin {
      position: sticky;
      top: 0;
      height: 100vh;
      display: flex;
      flex-direction: column;
      justify-content: center;
      overflow: hidden;
    }
    .js-anim .sm-strip__track {
      overflow: visible;
      width: max-content;
      padding-bottom: 0;
      animation: sm-strip-slide linear both;
      animation-timeline: --sm-strip;
      animation-range: contain;
    }
    /* Large cards on purpose: the track must be well wider than the viewport
       for the horizontal slide to be a real journey (not a 100px nudge), and
       bigger cards read more clearly. */
    .js-anim .sm-strip-card { flex: 0 0 clamp(360px, 40vw, 540px); }
  }
}
@keyframes sm-strip-slide {
  /* Slide left until the track's right edge meets the viewport's right edge.
     100% = track width, so (100vw - 100% - padding) is exactly that distance,
     adapting to any card count and viewport with no magic number. */
  to { transform: translateX(calc(100vw - 100% - 48px)); }
}

/* =========================== 6. Auto carousel ===================== */
.sm-carousel__viewport {
  position: relative;
  overflow: hidden;
  min-height: 240px;
}
/* Centre a single card in the viewport and keep it a readable width, since a
   card designed for a 3-up grid would otherwise stretch full width. */
.sm-carousel__slide { display: flex; align-items: center; justify-content: center; }
.sm-carousel .testimonial-card { max-width: 640px; margin: 0 auto; }
.sm-carousel__slide {
  position: absolute;
  inset: 0;
  opacity: 0;
  transform: translateY(28px) scale(0.98);
  pointer-events: none;
  transition: opacity 420ms ease, transform 420ms ease;
}
.sm-carousel__slide.from-left  { transform: translateY(-28px) scale(0.98); }
.sm-carousel__slide.from-right { transform: translateY(28px) scale(0.98); }
.sm-carousel__slide.is-active {
  position: relative;
  opacity: 1;
  transform: none;
  pointer-events: auto;
}
.sm-carousel__controls {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-5);
  margin-top: var(--space-6);
}
.sm-carousel__arrow {
  width: 42px;
  height: 42px;
  border-radius: 999px;
  border: 1.5px solid var(--border-soft, #e4d9bd);
  background: transparent;
  color: var(--color-near-black, #141210);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  opacity: 0.55;
  transition: opacity 200ms ease, transform 200ms ease, border-color 200ms ease;
}
.sm-carousel__arrow:hover { opacity: 1; border-color: var(--color-orange, #d65826); }
.sm-carousel__arrow:active { transform: scale(0.94); }
.sm-carousel__arrow:focus-visible { outline: 2px solid var(--color-orange, #d65826); outline-offset: 2px; opacity: 1; }
.sm-carousel__dots { display: flex; align-items: center; gap: var(--space-2); }
.sm-carousel__dot {
  width: 10px;
  height: 10px;
  border-radius: 999px;
  border: none;
  padding: 0;
  background: rgba(20, 18, 16, 0.2);
  cursor: pointer;
  transition: width 300ms ease, background 300ms ease;
}
.sm-carousel__dot:hover { background: rgba(20, 18, 16, 0.4); }
.sm-carousel__dot.is-active { width: 30px; background: var(--color-orange, #d65826); }
.sm-carousel__dot:focus-visible { outline: 2px solid var(--color-orange, #d65826); outline-offset: 2px; }

/* ============================ Reduced motion ====================== */
@media (prefers-reduced-motion: reduce) {
  .js-anim .sm-reveal,
  .js-anim .sm-reveal.is-in { opacity: 1; transform: none; transition: none; }
  .js-anim .sm-progress { display: none; }
  .sm-carousel__slide { transition: none; }
}
