@import "./quantity-motion.css";

/*
 * Swatch motion contract (free/shared).
 *
 * Shape/selected-style transitions, the fixed select pop, and the swatch hover
 * animations are part of the free contract and are rendered by the SAME swatch
 * components on the storefront and in the admin settings Live Preview. The
 * rules live here so both stylesheets can import one source of truth:
 *
 *   - src/frontend/index.css (storefront, free + Pro)
 *   - src/admin/index.css    (settings page, free + Pro)
 *
 * Keeping the rules only in the storefront sheet leaves the Live Preview
 * without any hover animation CSS, so unsaved animation changes never show.
 */

/*
 * Swatch shape + selected-outline transitions.
 *
 * Shape and selected-style transitions live in the shared stylesheet so every
 * renderer can use the same class names and animate shape + outline changes
 * consistently.
 *
 * Cascade note: this file is imported before the shared utility sheet, so the
 * generated `bwvs:transition-all` utility (all / 150ms) comes later in the
 * bundle. Swatches carry both classes, so the selectors below are doubled to
 * raise specificity (0,2,0) and keep the explicit property list + 300ms timing
 * winning by specificity rather than source order. No `!important` here: the
 * prefers-reduced-motion reset further down must still override this.
 */
.b3-wvs-shape-transition.b3-wvs-shape-transition {
  transition:
    border-radius 0.3s cubic-bezier(0.4, 0, 0.2, 1),
    clip-path 0.3s cubic-bezier(0.4, 0, 0.2, 1),
    box-shadow 0.3s cubic-bezier(0.4, 0, 0.2, 1),
    border-color 0.3s cubic-bezier(0.4, 0, 0.2, 1),
    background-color 0.3s cubic-bezier(0.4, 0, 0.2, 1),
    transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

.b3-wvs-clippath-outline-transition.b3-wvs-clippath-outline-transition {
  transition:
    clip-path 0.3s cubic-bezier(0.4, 0, 0.2, 1),
    opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

@media (prefers-reduced-motion: reduce) {
  .b3-wvs-shape-transition,
  .b3-wvs-clippath-outline-transition {
    transition: none !important;
  }
}

/* Glow is visual state rather than movement, so the persistent selected halo
 * remains available when reduced motion is requested. */
@media (prefers-reduced-motion: no-preference) {
  @media (hover: hover) and (pointer: fine) {
    .b3-wvs-swatch-glow:hover {
      box-shadow: 0 0 calc(var(--b3-wvs-glow-radius, 15px) * 1.5) 4px
        var(--b3-wvs-glow-color, #46a5e5);
    }
  }
}

[data-b3-wvs-glow-always="true"] [role="radio"][aria-checked="true"] {
  box-shadow: 0 0 var(--b3-wvs-glow-radius, 15px) 2px
    var(--b3-wvs-glow-color, #46a5e5);
}

/*
 * One fixed select micro-interaction. Selection is also conveyed by
 * aria-checked + the live region + the static selected indicator, so motion is
 * never the only signal (WCAG 1.4.1). React adds the class on user selection
 * only; reduced-motion is honored here as defense-in-depth alongside the JS guard.
 */
@keyframes b3-wvs-swatch-pop {
  0% {
    transform: scale(1);
  }
  40% {
    transform: scale(1.14);
  }
  100% {
    transform: scale(1);
  }
}

.b3-wvs-swatch-pop {
  animation: b3-wvs-swatch-pop 0.26s cubic-bezier(0.34, 1.56, 0.64, 1);
}

@media (prefers-reduced-motion: reduce) {
  .b3-wvs-swatch-pop {
    animation: none !important;
  }
}

/*
 * Swatch hover animations. `animation_type` picks one; it plays on hover via
 * pure CSS (no JS handlers, no extra render work) on hover-capable fine
 * pointers and is disabled under prefers-reduced-motion. "lift" is the simple
 * default. The `.b3-wvs-animate-*` variant is the JS-applied form used by
 * richer renderers; the `:hover` variant is what the base renderer attaches via
 * a persistent class. Selection always has a static indicator + aria-checked +
 * live region, so motion is never the only signal (WCAG 1.4.1).
 */
@media (hover: hover) and (pointer: fine) {
  .b3-wvs-swatch-scale:hover {
    transform: scale(1.05);
  }

  .b3-wvs-swatch-scale:active {
    transform: scale(0.95);
  }

  .b3-wvs-swatch-hover-target:hover .b3-wvs-swatch-lift-visual,
  .b3-wvs-swatch-lift-visual:hover {
    transform: translateY(-4px);
    box-shadow:
      0 10px 15px -3px rgb(0 0 0 / 0.1),
      0 4px 6px -4px rgb(0 0 0 / 0.1);
  }

  /* Direct-rendered segments do not have an outer target. Retain their
   * original lower hit area while the visual moves upward. */
  .b3-wvs-swatch-lift-visual::after {
    position: absolute;
    inset: 0;
    content: "";
    transform: translateY(4px);
  }
}

@keyframes b3-wvs-swatch-bounce {
  0% {
    transform: translateY(0);
  }
  35% {
    transform: translateY(-4px);
  }
  60% {
    transform: translateY(0);
  }
  80% {
    transform: translateY(-2px);
  }
  100% {
    transform: translateY(0);
  }
}

.b3-wvs-animate-swatch-bounce {
  animation: b3-wvs-swatch-bounce 380ms cubic-bezier(0.22, 1, 0.36, 1);
}

@media (hover: hover) and (pointer: fine) {
  .b3-wvs-swatch-bounce:hover {
    animation: b3-wvs-swatch-bounce 380ms cubic-bezier(0.22, 1, 0.36, 1);
  }
}

@keyframes b3-wvs-swatch-jiggle {
  0% {
    transform: rotate(0deg);
  }
  25% {
    transform: rotate(-3deg);
  }
  50% {
    transform: rotate(3deg);
  }
  75% {
    transform: rotate(-1deg);
  }
  100% {
    transform: rotate(0deg);
  }
}

.b3-wvs-animate-swatch-jiggle {
  animation: b3-wvs-swatch-jiggle 0.4s ease-in-out;
}

@media (hover: hover) and (pointer: fine) {
  .b3-wvs-swatch-jiggle:hover {
    animation: b3-wvs-swatch-jiggle 0.4s ease-in-out;
  }
}

@keyframes b3-wvs-swatch-wobble {
  0% {
    transform: translateX(0%);
  }
  15% {
    transform: translateX(-5%) rotate(-2deg);
  }
  30% {
    transform: translateX(4%) rotate(2deg);
  }
  45% {
    transform: translateX(-3%) rotate(-1deg);
  }
  60% {
    transform: translateX(2%) rotate(1deg);
  }
  75% {
    transform: translateX(-1%) rotate(-0.5deg);
  }
  100% {
    transform: translateX(0%);
  }
}

.b3-wvs-animate-swatch-wobble {
  animation: b3-wvs-swatch-wobble 0.6s ease-in-out;
}

@media (hover: hover) and (pointer: fine) {
  .b3-wvs-swatch-wobble:hover {
    animation: b3-wvs-swatch-wobble 0.6s ease-in-out;
  }
}

@keyframes b3-wvs-swatch-flip {
  0% {
    transform: perspective(400px) rotateY(0);
  }
  100% {
    transform: perspective(400px) rotateY(360deg);
  }
}

.b3-wvs-animate-swatch-flip {
  animation: b3-wvs-swatch-flip 0.6s ease-in-out;
}

@media (hover: hover) and (pointer: fine) {
  .b3-wvs-swatch-flip:hover {
    animation: b3-wvs-swatch-flip 0.6s ease-in-out;
  }
}

@media (prefers-reduced-motion: reduce) {
  .b3-wvs-swatch-scale:hover,
  .b3-wvs-swatch-scale:active,
  .b3-wvs-swatch-hover-target:hover .b3-wvs-swatch-lift-visual,
  .b3-wvs-swatch-lift-visual:hover {
    transform: none !important;
  }

  /*
   * Drop the lift's own hover shadow only, and WITHOUT `!important`. The
   * selected-style indicator (outline ring / background halo) is an inline
   * box-shadow on this same element; an `!important` reset here outranks the
   * inline style and erases the selected indicator while the swatch is
   * hovered. Plain source-order override removes the hover shadow and leaves
   * the selected indicator intact.
   */
  .b3-wvs-swatch-hover-target:hover .b3-wvs-swatch-lift-visual,
  .b3-wvs-swatch-lift-visual:hover {
    box-shadow: none;
  }

  .b3-wvs-animate-swatch-bounce,
  .b3-wvs-animate-swatch-jiggle,
  .b3-wvs-animate-swatch-wobble,
  .b3-wvs-animate-swatch-flip,
  .b3-wvs-swatch-bounce:hover,
  .b3-wvs-swatch-jiggle:hover,
  .b3-wvs-swatch-wobble:hover,
  .b3-wvs-swatch-flip:hover {
    animation: none !important;
  }
}
/* Flow uses the same coverflow interaction in the admin preview and storefront. */
.b3-wvs-flow-layout {
  position: relative;
  min-height: 80px;
  overflow: visible;
  perspective: 1200px;
  perspective-origin: center;
}

.b3-wvs-flow-layout > * {
  position: relative;
  transform-style: preserve-3d;
}

@media (hover: hover) and (pointer: fine) {
  .b3-wvs-flow-layout > * {
    transition:
      transform 0.3s ease-out,
      opacity 0.3s ease-out,
      z-index 0s;
  }
}

@media (prefers-reduced-motion: reduce) {
  .b3-wvs-flow-layout > * {
    transition: none !important;
    transform: none !important;
  }
}
