/**
 * FilterX Animation Engine
 * GPU-accelerated entrance, hover, filter-transition & skeleton animations.
 * All animations use transform + opacity only (compositor-thread safe).
 *
 * @package FilterX
 * @since   2.1.0
 */

/* ═══════════════════════════════════════════════════════════
   §1  ACCESSIBILITY — Respect prefers-reduced-motion
   ═══════════════════════════════════════════════════════════ */
@media (prefers-reduced-motion: reduce) {
  .filterx-grid__item,
  .filterx-card,
  .filterx-card__block,
  .filterx-skeleton__item {
    animation: none !important;
    transition: none !important;
    opacity: 1 !important;
    transform: none !important;
  }
  .filterx-skeleton__shimmer::after {
    animation: none !important;
  }
}

/* ═══════════════════════════════════════════════════════════
   §2  ENTRANCE ANIMATION KEYFRAMES
   ═══════════════════════════════════════════════════════════ */

/* ── fadeIn ── */
@keyframes fx-fadeIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* ── fadeInUp ── */
@keyframes fx-fadeInUp {
  from { opacity: 0; transform: translate3d(0, 30px, 0); }
  to   { opacity: 1; transform: translate3d(0, 0, 0); }
}

/* ── fadeInDown ── */
@keyframes fx-fadeInDown {
  from { opacity: 0; transform: translate3d(0, -30px, 0); }
  to   { opacity: 1; transform: translate3d(0, 0, 0); }
}

/* ── fadeInLeft ── */
@keyframes fx-fadeInLeft {
  from { opacity: 0; transform: translate3d(-40px, 0, 0); }
  to   { opacity: 1; transform: translate3d(0, 0, 0); }
}

/* ── fadeInRight ── */
@keyframes fx-fadeInRight {
  from { opacity: 0; transform: translate3d(40px, 0, 0); }
  to   { opacity: 1; transform: translate3d(0, 0, 0); }
}

/* ── scaleIn ── */
@keyframes fx-scaleIn {
  from { opacity: 0; transform: scale3d(0.85, 0.85, 1); }
  to   { opacity: 1; transform: scale3d(1, 1, 1); }
}

/* ── scaleInUp ── */
@keyframes fx-scaleInUp {
  from { opacity: 0; transform: scale3d(0.9, 0.9, 1) translate3d(0, 20px, 0); }
  to   { opacity: 1; transform: scale3d(1, 1, 1) translate3d(0, 0, 0); }
}

/* ── flipInX ── */
@keyframes fx-flipInX {
  from { opacity: 0; transform: perspective(800px) rotateX(-60deg); }
  60%  { opacity: 1; transform: perspective(800px) rotateX(10deg); }
  80%  { transform: perspective(800px) rotateX(-5deg); }
  to   { opacity: 1; transform: perspective(800px) rotateX(0); }
}

/* ── flipInY ── */
@keyframes fx-flipInY {
  from { opacity: 0; transform: perspective(800px) rotateY(-60deg); }
  60%  { opacity: 1; transform: perspective(800px) rotateY(10deg); }
  80%  { transform: perspective(800px) rotateY(-5deg); }
  to   { opacity: 1; transform: perspective(800px) rotateY(0); }
}

/* ── bounceIn ── */
@keyframes fx-bounceIn {
  0%   { opacity: 0; transform: scale3d(0.3, 0.3, 1); }
  20%  { transform: scale3d(1.1, 1.1, 1); }
  40%  { transform: scale3d(0.9, 0.9, 1); }
  60%  { opacity: 1; transform: scale3d(1.03, 1.03, 1); }
  80%  { transform: scale3d(0.97, 0.97, 1); }
  100% { opacity: 1; transform: scale3d(1, 1, 1); }
}

/* ── slideInUp ── */
@keyframes fx-slideInUp {
  from { transform: translate3d(0, 100%, 0); visibility: visible; }
  to   { transform: translate3d(0, 0, 0); }
}

/* ── rotateIn ── */
@keyframes fx-rotateIn {
  from { opacity: 0; transform: rotate(-15deg) scale3d(0.9, 0.9, 1); }
  to   { opacity: 1; transform: rotate(0) scale3d(1, 1, 1); }
}

/* ── zoomInBounce ── */
@keyframes fx-zoomInBounce {
  0%   { opacity: 0; transform: scale3d(0.5, 0.5, 1); }
  50%  { opacity: 0.8; transform: scale3d(1.05, 1.05, 1); }
  70%  { transform: scale3d(0.98, 0.98, 1); }
  100% { opacity: 1; transform: scale3d(1, 1, 1); }
}

/* ── blurIn ── */
@keyframes fx-blurIn {
  from { opacity: 0; filter: blur(8px); transform: scale3d(0.95, 0.95, 1); }
  to   { opacity: 1; filter: blur(0); transform: scale3d(1, 1, 1); }
}

/* ═══════════════════════════════════════════════════════════
   §3  EXIT / FILTER-OUT KEYFRAMES
   ═══════════════════════════════════════════════════════════ */

@keyframes fx-fadeOut {
  from { opacity: 1; }
  to   { opacity: 0; }
}

@keyframes fx-fadeOutDown {
  from { opacity: 1; transform: translate3d(0, 0, 0); }
  to   { opacity: 0; transform: translate3d(0, 20px, 0); }
}

@keyframes fx-fadeOutUp {
  from { opacity: 1; transform: translate3d(0, 0, 0); }
  to   { opacity: 0; transform: translate3d(0, -20px, 0); }
}

@keyframes fx-scaleOut {
  from { opacity: 1; transform: scale3d(1, 1, 1); }
  to   { opacity: 0; transform: scale3d(0.85, 0.85, 1); }
}

/* ═══════════════════════════════════════════════════════════
   §4  ENTRANCE ANIMATION CLASSES
   Items start hidden, animate on trigger.
   ═══════════════════════════════════════════════════════════ */

.fx-animate-ready {
  opacity: 0;
  will-change: transform, opacity;
}

/* Preset classes — applied by JS after IntersectionObserver fires */
.fx-animated.fx-fadeIn         { animation-name: fx-fadeIn; }
.fx-animated.fx-fadeInUp       { animation-name: fx-fadeInUp; }
.fx-animated.fx-fadeInDown     { animation-name: fx-fadeInDown; }
.fx-animated.fx-fadeInLeft     { animation-name: fx-fadeInLeft; }
.fx-animated.fx-fadeInRight    { animation-name: fx-fadeInRight; }
.fx-animated.fx-scaleIn        { animation-name: fx-scaleIn; }
.fx-animated.fx-scaleInUp      { animation-name: fx-scaleInUp; }
.fx-animated.fx-flipInX        { animation-name: fx-flipInX; }
.fx-animated.fx-flipInY        { animation-name: fx-flipInY; }
.fx-animated.fx-bounceIn       { animation-name: fx-bounceIn; }
.fx-animated.fx-slideInUp      { animation-name: fx-slideInUp; }
.fx-animated.fx-rotateIn       { animation-name: fx-rotateIn; }
.fx-animated.fx-zoomInBounce   { animation-name: fx-zoomInBounce; }
.fx-animated.fx-blurIn         { animation-name: fx-blurIn; }

/* Default duration, easing & fill-mode — overridden by CSS custom properties.
   fill-mode: both ensures the final keyframe state (opacity:1) persists even
   after fx-animate-ready is removed during cleanup. */
.fx-animated {
  animation-duration: var(--fx-anim-duration, 0.6s);
  animation-timing-function: var(--fx-anim-easing, cubic-bezier(0.25, 0.46, 0.45, 0.94));
  animation-delay: var(--fx-anim-delay, 0s);
  animation-fill-mode: both;
}

/* ═══════════════════════════════════════════════════════════
   §5  HOVER EFFECT PRESETS (card-level)
   ═══════════════════════════════════════════════════════════ */

.fx-hover-lift {
  transition: transform var(--fx-hover-duration, 0.3s) var(--fx-hover-easing, ease),
              box-shadow var(--fx-hover-duration, 0.3s) var(--fx-hover-easing, ease);
}
.fx-hover-lift:hover {
  transform: translateY(-6px);
  box-shadow: 0 12px 24px rgba(0, 0, 0, 0.12);
}

.fx-hover-grow {
  transition: transform var(--fx-hover-duration, 0.3s) var(--fx-hover-easing, ease);
}
.fx-hover-grow:hover {
  transform: scale(1.04);
}

.fx-hover-glow {
  transition: box-shadow var(--fx-hover-duration, 0.3s) var(--fx-hover-easing, ease);
}
.fx-hover-glow:hover {
  box-shadow: 0 0 20px rgba(124, 58, 237, 0.3), 0 0 40px rgba(124, 58, 237, 0.1);
}

.fx-hover-tilt3d {
  transition: transform var(--fx-hover-duration, 0.3s) var(--fx-hover-easing, ease);
  transform-style: preserve-3d;
}
/* JS handles the actual tilt — this provides the transition */

.fx-hover-border-reveal {
  position: relative;
  overflow: hidden;
}
.fx-hover-border-reveal::before {
  content: '';
  position: absolute;
  inset: 0;
  border: 2px solid var(--fx-hover-border-color, #7c3aed);
  border-radius: inherit;
  opacity: 0;
  transition: opacity var(--fx-hover-duration, 0.3s) var(--fx-hover-easing, ease);
  pointer-events: none;
  z-index: 2;
}
.fx-hover-border-reveal:hover::before {
  opacity: 1;
}

.fx-hover-shadow-pop {
  transition: box-shadow var(--fx-hover-duration, 0.3s) var(--fx-hover-easing, ease),
              transform var(--fx-hover-duration, 0.3s) var(--fx-hover-easing, ease);
}
.fx-hover-shadow-pop:hover {
  transform: translateY(-3px);
  box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15);
}

/* ═══════════════════════════════════════════════════════════
   §6  FILTER TRANSITION CLASSES
   Applied during AJAX filter swap
   ═══════════════════════════════════════════════════════════ */

/* Crossfade: old items fade out, new items fade in */
.fx-filter-crossfade .filterx-grid__items {
  transition: opacity 0.3s ease;
}
.fx-filter-crossfade.fx-filtering-out .filterx-grid__items {
  opacity: 0;
}

/* Slide swap: items slide out, new slide in */
.fx-filter-slide .filterx-grid__items {
  transition: transform 0.35s cubic-bezier(0.25, 0.46, 0.45, 0.94),
              opacity 0.35s ease;
}
.fx-filter-slide.fx-filtering-out .filterx-grid__items {
  opacity: 0;
  transform: translate3d(0, 15px, 0);
}

/* Scale morph: items scale out, new scale in */
.fx-filter-morph .filterx-grid__items {
  transition: transform 0.3s ease, opacity 0.3s ease;
}
.fx-filter-morph.fx-filtering-out .filterx-grid__items {
  opacity: 0;
  transform: scale3d(0.96, 0.96, 1);
}

/* ═══════════════════════════════════════════════════════════
   §7  SKELETON PRELOADER
   Card-shaped placeholders with shimmer gradient
   ═══════════════════════════════════════════════════════════ */

.filterx-skeleton {
  display: grid;
  gap: var(--filterx-gap-h, var(--filterx-gap, 20px));
  row-gap: var(--filterx-gap-v, var(--filterx-gap, 20px));
}

.filterx-skeleton--grid {
  grid-template-columns: repeat(var(--filterx-columns-desktop, 3), 1fr);
}

@media (max-width: 768px) {
  .filterx-skeleton--grid {
    grid-template-columns: repeat(var(--filterx-columns-mobile, 1), 1fr);
  }
}

@media (min-width: 769px) and (max-width: 1024px) {
  .filterx-skeleton--grid {
    grid-template-columns: repeat(var(--filterx-columns-tablet, 2), 1fr);
  }
}

.filterx-skeleton__item {
  border-radius: var(--filterx-radius, 8px);
  overflow: hidden;
  background: #f3f4f6;
}

.filterx-skeleton__image {
  width: 100%;
  aspect-ratio: 16 / 9;
  background: #e5e7eb;
  position: relative;
  overflow: hidden;
}

.filterx-skeleton__body {
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.filterx-skeleton__line {
  height: 12px;
  background: #e5e7eb;
  border-radius: 6px;
}

.filterx-skeleton__line--title {
  height: 16px;
  width: 70%;
}

.filterx-skeleton__line--text {
  width: 100%;
}

.filterx-skeleton__line--text-short {
  width: 55%;
}

.filterx-skeleton__line--price {
  height: 18px;
  width: 30%;
  margin-top: 4px;
}

/* Shimmer animation */
.filterx-skeleton__shimmer {
  position: relative;
  overflow: hidden;
}

.filterx-skeleton__shimmer::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(
    90deg,
    transparent 0%,
    rgba(255, 255, 255, 0.5) 50%,
    transparent 100%
  );
  animation: fx-shimmer 1.5s ease-in-out infinite;
  transform: translate3d(-100%, 0, 0);
}

@keyframes fx-shimmer {
  0%   { transform: translate3d(-100%, 0, 0); }
  100% { transform: translate3d(100%, 0, 0); }
}

/* Pulse variant (simpler, less distracting) */
.filterx-skeleton--pulse .filterx-skeleton__image,
.filterx-skeleton--pulse .filterx-skeleton__line {
  animation: fx-pulse 1.8s ease-in-out infinite;
}

@keyframes fx-pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.5; }
}

/* ═══════════════════════════════════════════════════════════
   §8  LOADING OVERLAY PRESETS (replacing default spinner)
   ═══════════════════════════════════════════════════════════ */

/* Blur overlay — blurs existing content instead of opacity fade */
.fx-preloader-blur.filterx-loading {
  opacity: 1;
  filter: blur(3px);
}
.fx-preloader-blur.filterx-loading::after {
  display: none; /* Hide default spinner */
}

/* Skeleton overlay — shows skeleton on top of blurred grid */
.fx-preloader-skeleton.filterx-loading {
  opacity: 1;
}
.fx-preloader-skeleton.filterx-loading > .filterx-grid {
  opacity: 0.3;
}
.fx-preloader-skeleton.filterx-loading::after {
  display: none;
}

/* Progress bar — thin bar at top of grid */
.fx-preloader-progress.filterx-loading {
  opacity: 0.7;
}
.fx-preloader-progress.filterx-loading::after {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 3px;
  margin: 0;
  border: none;
  border-radius: 0;
  background: var(--filterx-primary, #7c3aed);
  animation: fx-progress 1.2s ease-in-out infinite;
  z-index: 10;
}

@keyframes fx-progress {
  0%   { transform: translate3d(-100%, 0, 0); }
  100% { transform: translate3d(100%, 0, 0); }
}

/* Dots loader */
.fx-preloader-dots.filterx-loading::after {
  content: '';
  display: flex;
  width: auto;
  height: auto;
  margin: 0;
  border: none;
  border-radius: 0;
  animation: none;
  background: transparent;
}
