/* ==========================================================================
   selfLove.Yoga — Taste & Motion System (v2, "impeccable" pass)
   Implements /TASTE-AND-MOTION-SYSTEM.md literally for style 10 (Boutique
   Studio Academy). Loads after Tailwind CDN + styles.css so these rules can
   override ad hoc utility-only hovers/reveals with the prescribed tokens.
   ========================================================================== */

:root {
  /* ---- Motion tokens (spec §4) — the only easing curves/durations used site-wide ---- */
  --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);      /* entrances: fast start, gentle settle */
  --ease-in-out-quart: cubic-bezier(0.76, 0, 0.24, 1);  /* state changes: toggles, modals */
  --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);     /* gesture-driven: drag/swipe/select, approximated spring */
  --duration-fast: 150ms;   /* hover, button press */
  --duration-base: 250ms;   /* card reveals, dropdowns */
  --duration-slow: 400ms;   /* modals, page-level transitions */
  --duration-spring: 350ms; /* paired with --ease-spring */
}

@media (prefers-reduced-motion: reduce) {
  :root {
    --duration-fast: 1ms;
    --duration-base: 1ms;
    --duration-slow: 1ms;
    --duration-spring: 1ms;
  }
}

/* ==========================================================================
   1. Transform-only hover utility (spec: "150ms, transform-only,
      translateY(-2px) + shadow, never color-only on cards")
   ========================================================================== */
.tst-hover {
  transition: transform var(--duration-fast) var(--ease-out-expo),
              box-shadow var(--duration-fast) var(--ease-out-expo);
  will-change: transform;
}
.tst-hover:hover,
.tst-hover:focus-visible {
  transform: translateY(-2px);
  box-shadow: 0 12px 24px -10px rgba(38, 51, 43, 0.28);
}
.tst-hover:active {
  transform: translateY(-1px);
  transition-duration: calc(var(--duration-fast) / 2);
}

/* Bring the site's existing hover-styled components onto the token system
   verbatim (was: ad hoc .3s/.25s/.4s ease + cubic-bezier(.2,.7,.2,1)). */
.btn-gold,
.btn-outline,
.btn-outline-light {
  transition: background-color var(--duration-fast) var(--ease-out-expo),
              color var(--duration-fast) var(--ease-out-expo),
              border-color var(--duration-fast) var(--ease-out-expo),
              transform var(--duration-fast) var(--ease-out-expo),
              box-shadow var(--duration-fast) var(--ease-out-expo);
}
.btn-gold:hover,
.btn-outline:hover,
.btn-outline-light:hover {
  transform: translateY(-2px);
}
.btn-gold:hover {
  box-shadow: 0 12px 24px -10px rgba(176, 141, 87, 0.55);
}
.btn-gold:active,
.btn-outline:active,
.btn-outline-light:active {
  transform: translateY(-1px);
}

.sly-card {
  transition: transform var(--duration-base) var(--ease-out-expo),
              box-shadow var(--duration-base) var(--ease-out-expo),
              border-color var(--duration-base) var(--ease-out-expo);
}
.sly-card:hover,
.sly-card:focus-within {
  transform: translateY(-6px);
  box-shadow: 0 30px 45px -25px rgba(38, 51, 43, 0.28);
  border-color: rgba(176, 141, 87, 0.5);
}

/* Generic clickable-card / tile hover for any element opting in without the
   full .sly-card treatment (blog tiles, shop tiles, schedule rows, etc). */
.tst-hover-card {
  transition: transform var(--duration-base) var(--ease-out-expo),
              box-shadow var(--duration-base) var(--ease-out-expo);
}
.tst-hover-card:hover,
.tst-hover-card:focus-within {
  transform: translateY(-4px);
  box-shadow: 0 24px 40px -22px rgba(38, 51, 43, 0.25);
}

/* Nav underline / icon links keep color transitions (text links are exempt
   from the "cards/buttons" transform rule) but snap to token duration. */
.sly-nav-link::after {
  transition: width var(--duration-fast) var(--ease-out-expo);
}
a, button, .transition-colors {
  transition-duration: var(--duration-fast);
}

/* Toggle / open-close state changes use the quart in-out curve (spec §4) */
#sly-mobile-menu,
#sly-hamburger span,
.sly-modal-panel,
[data-accordion-panel],
[data-accordion-icon] {
  transition-timing-function: var(--ease-in-out-quart) !important;
}
#sly-mobile-menu { transition-duration: var(--duration-slow), var(--duration-base); }
.sly-modal-panel { transition-duration: var(--duration-base); }
#sly-hamburger span { transition-duration: var(--duration-fast); }
[data-accordion-panel] { transition-duration: var(--duration-base); }

/* Snap every Tailwind transition utility in the markup onto the token
   system too — Tailwind's own .duration-*/.transition-* utilities ship
   their own ad hoc cubic-bezier(.4,0,.2,1) timing + arbitrary durations
   (300/500/700ms), which is exactly the kind of un-arted-directed default
   the spec calls out. !important guards against Tailwind CDN's runtime
   style injection reordering the cascade. */
.transition-all,
.transition-colors,
.transition-transform,
.transition-opacity,
.transition-shadow {
  transition-timing-function: var(--ease-out-expo) !important;
}
.duration-300 { transition-duration: var(--duration-base) !important; }
.duration-500 { transition-duration: var(--duration-slow) !important; }
.duration-700 { transition-duration: var(--duration-slow) !important; }

/* Ambient background motion (hero Ken Burns) is intentionally outside the
   fast/base/slow interaction taxonomy — it's a continuous 22s loop, not an
   entrance/state-change/hover — but still gated by reduced-motion below. */

/* Photographic zoom-on-hover (.sly-img-zoom gallery images) — snap to
   duration-slow + ease-out-expo instead of the old ad hoc .7s cubic-bezier
   ad hoc curve declared in styles.css. */
.sly-img-zoom img {
  transition-duration: var(--duration-slow) !important;
  transition-timing-function: var(--ease-out-expo) !important;
}

/* Nav scroll-shadow state change → quart, not the old .35s ease */
#sly-nav {
  transition-duration: var(--duration-base) !important;
  transition-timing-function: var(--ease-in-out-quart) !important;
}

/* Gesture-ish, physically-interactive controls (calendar day-select, cart
   qty steppers) get the spring signature instead of a flat ease. */
.tst-spring,
[data-cal-day],
.sly-qty-btn {
  transition: transform var(--duration-spring) var(--ease-spring),
              background-color var(--duration-fast) var(--ease-out-expo),
              border-color var(--duration-fast) var(--ease-out-expo);
}
.tst-spring:active,
[data-cal-day]:active,
.sly-qty-btn:active {
  transform: scale(0.94);
}

/* ==========================================================================
   2. Staggered reveal animations (spec: entrances use --ease-out-expo,
      stagger children 40–60ms, cap at 6, animate transform+opacity only)
   ========================================================================== */

/* Upgrade the existing .reveal system in place — same class names the JS
   IntersectionObserver already toggles, now running on spec tokens instead
   of the old ad hoc .8s cubic-bezier(.2,.7,.2,1). */
.reveal {
  opacity: 0;
  transform: translateY(20px);
  transition: opacity var(--duration-slow) var(--ease-out-expo),
              transform var(--duration-slow) var(--ease-out-expo);
}
.reveal-visible {
  opacity: 1;
  transform: translateY(0);
}
.reveal-delay-1 { transition-delay: 50ms; }
.reveal-delay-2 { transition-delay: 100ms; }
.reveal-delay-3 { transition-delay: 150ms; }
.reveal-delay-4 { transition-delay: 200ms; }
.reveal-delay-5 { transition-delay: 250ms; }
.reveal-delay-6 { transition-delay: 300ms; }

/* New explicit "tst-reveal" family for recomposed/flagship markup —
   identical mechanics, distinct name so intent is legible in markup. */
.tst-reveal {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity var(--duration-slow) var(--ease-out-expo),
              transform var(--duration-slow) var(--ease-out-expo);
}
.tst-reveal-visible {
  opacity: 1;
  transform: translateY(0);
}
.tst-reveal-scale {
  opacity: 0;
  transform: translateY(16px) scale(0.98);
  transition: opacity var(--duration-slow) var(--ease-out-expo),
              transform var(--duration-slow) var(--ease-out-expo);
}
.tst-reveal-scale.tst-reveal-visible {
  opacity: 1;
  transform: translateY(0) scale(1);
}
.tst-stagger-1 { transition-delay: 40ms; }
.tst-stagger-2 { transition-delay: 80ms; }
.tst-stagger-3 { transition-delay: 120ms; }
.tst-stagger-4 { transition-delay: 160ms; }
.tst-stagger-5 { transition-delay: 200ms; }
.tst-stagger-6 { transition-delay: 240ms; }

/* ==========================================================================
   3. Photo / video color-grade overlay (spec §6): a single, consistent
      brand-tinted gradient over every photo at ~8-15% opacity.
      Two variants so we never fight Tailwind's own `position` utilities:
        .tst-grade     — sets position:relative itself (use on a plain,
                          non-positioned wrapper div around an <img>/<video>)
        .tst-grade-bg  — no position change (use on a wrapper that is
                          already `absolute`/`fixed`/`relative`, e.g. a
                          full-bleed hero or section background)
   ========================================================================== */
.tst-grade { position: relative; }
.tst-grade::after,
.tst-grade-bg::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(165deg,
    rgba(176, 141, 87, 0.16) 0%,
    rgba(38, 51, 43, 0.07) 45%,
    rgba(176, 141, 87, 0.12) 100%);
  mix-blend-mode: multiply;
  pointer-events: none;
}
.tst-grade > img,
.tst-grade > video,
.tst-grade-bg > img,
.tst-grade-bg > video {
  display: block;
}

/* Used when the <img>/<video> itself is already absolutely positioned
   (full-bleed hero/background media) — applied as a sibling overlay div
   rather than a wrapper, so we never touch the media's own containing
   block. See script.js:tstApplyPhotoGrade(). */
.tst-grade-overlay {
  background: linear-gradient(165deg,
    rgba(176, 141, 87, 0.16) 0%,
    rgba(38, 51, 43, 0.07) 45%,
    rgba(176, 141, 87, 0.12) 100%);
  mix-blend-mode: multiply;
  pointer-events: none;
}

/* Card-context photo frame: rounded corner + 1px inset border, layered
   under the grade overlay (spec §6 — "never show a photo at its native
   crop in a card without at least a subtle treatment"). */
.tst-photo-frame {
  position: relative;
  overflow: hidden;
  border-radius: 4px;
}
.tst-photo-frame::before {
  content: '';
  position: absolute;
  inset: 1px;
  border: 1px solid rgba(247, 245, 242, 0.4);
  pointer-events: none;
}

/* ==========================================================================
   Non-negotiable: respect reduced motion globally for anything not already
   covered by the token overrides above.
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    scroll-behavior: auto !important;
  }
  .reveal, .tst-reveal, .tst-reveal-scale {
    transition: none !important;
    opacity: 1 !important;
    transform: none !important;
  }
}
