/** Shopify CDN: Minification failed

Line 149:0 Unexpected "}"

**/
/* "See them on your car".

   Every value here is a token. The panel takes the structural hairline and the
   theme's block radius, the buttons are the theme's buttons untouched, and the
   type comes off the body scale. There is no colour, corner or spacing in this
   file that the rest of the storefront does not already use, which is the point:
   the widget has to look like it shipped with the theme. */

/* The steps are flex containers, and a class that sets `display: flex` beats
   the UA stylesheet's `[hidden] { display: none }`. Without this every step
   renders at once: the picker, the render buttons and an empty result frame,
   all stacked. Scoped to this component rather than set globally, because
   changing what `hidden` means across a whole theme is not a small change. */
.wheel-visualizer [hidden] {
  display: none !important;
}

/* The trigger sits on the main product image, top left.

   Against <media-gallery>, which is the positioned ancestor here. The inset is
   the theme's own 1.6rem gutter so it lines up with the padding used everywhere
   else, and z-index clears the swiper, which sits at 0.

   Type is a step under the body size. The button is sitting on a photograph
   rather than in a row of controls, so it wants to read as a label on the image
   and not compete with the product title.

   Note the arithmetic. --font-body-size is a length (1.6rem), not a bare
   number, so `calc(var(--font-body-size) * 1px - 2px)` multiplies a length by a
   length, which is invalid and gets the whole declaration thrown away with no
   error anywhere. .btn--large in theme.css does exactly that, so its font-size
   has never done anything. Copying that line was how this got written wrong the
   first time; the harness caught it because it compares against the body size
   rather than eyeballing the button. */
.product__media-gallery .wheel-visualizer__trigger {
  position: absolute;
  top: 1.6rem;
  inset-inline-start: 1.6rem;
  z-index: 2;
  margin: 0;
  font-size: calc(var(--font-body-size) - 0.2rem);
}

/* Blue, because the two colours already on this page were not working.

   Brand red put a second red button in a viewport that already has Add to cart,
   and black disappeared into the wheels, which are usually photographed dark on
   white. Blue is the only thing here that is neither the brand nor the product.

   One variable. Change the triple and the button, its border and its hover wipe
   all follow, so this is a one line decision to revisit rather than a hunt.
   Named as an RGB triple, not a hex, because every colour in this theme is
   consumed through rgb(var(--token)) and mixing the two conventions is how a
   later alpha tweak breaks.

   Contrast against white text is 5.8:1, which clears AA for body text. Do not
   lighten it much without rechecking that. The white is written out rather than
   taken from a token because this theme has no white token: --color-background
   is scheme dependent and goes dark, which would put dark text on this blue. */
.wheel-visualizer__trigger {
  --wheel-visualizer-trigger: 23 92 220;
  --color-border: var(--wheel-visualizer-trigger);
  background: rgb(var(--wheel-visualizer-trigger));
  color: rgb(255 255 255);

  /* An explicit width, not just a colour.

     The theme's buttons resolve --buttons-border-width to 0 under the owner's
     button style, so colouring the border did nothing: there was no border to
     colour. That only showed on hover, where the fill wipes to white and the
     button vanished into a wheel photographed on a white background. Two pixels
     of blue, present at rest as well so the button does not change size when a
     cursor arrives.

     The wipe cannot cover it: .btn carries overflow: hidden, which clips the
     ::before to the padding box and leaves the border painting on its own. */
  border-width: 2px;
  border-style: solid;
  border-color: rgb(var(--wheel-visualizer-trigger));
}
/* The theme paints a button's hover as a wipe drawn in ::before. Left alone it
   would wipe in --color-button, which is the black we just moved away from. */
.wheel-visualizer__trigger::before {
  background-color: rgb(255 255 255);
}
@media (hover: hover) {
  .wheel-visualizer__trigger:hover {
    color: rgb(var(--wheel-visualizer-trigger));
  }
}

@media (max-width: 767.98px) {
  /* Tighter on a phone, where the image runs closer to the screen edge, and
     never so wide that it covers the product it is sitting on. */
  .product__media-gallery .wheel-visualizer__trigger {
    top: 1.2rem;
    inset-inline-start: 1.2rem;
    max-width: calc(100% - 2.4rem);
  }
}

.wheel-visualizer__content {
  padding-block-end: 0.4rem;
}
.wheel-visualizer__intro {
  color: rgba(var(--color-foreground), 0.7);
}

/* The drop target is a label wrapping a hidden input, so the whole panel is the
   control: one big tap target, which is what a phone in a garage needs. */
.wheel-visualizer__drop {
  padding: 4rem 2rem;
  border: var(--stroke-width) dashed rgba(var(--stroke-color), var(--stroke-alpha, 1));
  border-radius: var(--blocks-radius, 0);
  cursor: pointer;
  transition: border-color var(--duration-default) ease, background-color var(--duration-default) ease;
}
.wheel-visualizer__drop:hover,
.wheel-visualizer__drop:focus-within {
  border-color: rgb(var(--color-primary));
  background-color: rgba(var(--color-primary), 0.04);
}
.wheel-visualizer__drop-mark {
  width: 5.6rem;
  height: 5.6rem;
  border: var(--stroke-width) solid rgb(var(--color-foreground));
  border-radius: 50%;
}
.wheel-visualizer__drop-mark .icon {
  width: 2.4rem;
  height: 2.4rem;
}
.wheel-visualizer__drop-hint {
  color: rgba(var(--color-foreground), 0.6);
}

/* Where they are, in three segments.

   The bar itself now lives in component-step-bar.css, shared with the fitment
   picker, because the owner asked that the two read as one system. Bars rather
   than a labelled stepper here: labels would cost two more lines on a phone and
   this panel is already fighting for height. The step names are on
   visually-hidden spans, which is where a screen reader reads them anyway. */
}

/* Both the staged photo and the render sit in the same frame, so the panel does
   not jump when one replaces the other. */
.wheel-visualizer__frame {
  overflow: hidden;
  border: var(--stroke-width) solid rgba(var(--stroke-color), var(--stroke-alpha, 1));
  border-radius: var(--blocks-radius, 0);
  background-color: rgba(var(--color-foreground), 0.04);
}
.wheel-visualizer__frame img {
  display: block;
  width: 100%;
  height: auto;
}

/* The wait.

   A render takes roughly fifteen seconds, and fifteen seconds of a greyed out
   button with a small spinner in it reads as broken rather than busy. So the
   wait shows the shopper their own photo with a light band travelling across
   it, which is the visual language of something being worked on rather than
   something being fetched.

   The band is decorative. The status line under it is what actually says what
   is happening, and it is the thing a screen reader gets. */
.wheel-visualizer__frame--working {
  position: relative;
}
.wheel-visualizer__frame--working img {
  /* Held back so the sweep reads over the top of it, and so the finished render
     arriving at full contrast lands as an obvious change. */
  opacity: 0.55;
  filter: saturate(0.7);
}
.wheel-visualizer__sweep {
  position: absolute;
  inset-block: 0;
  inset-inline-start: 0;
  width: 45%;
  pointer-events: none;
  background: linear-gradient(
    100deg,
    rgba(var(--color-background), 0) 0%,
    rgba(var(--color-background), 0.55) 50%,
    rgba(var(--color-background), 0) 100%
  );
  animation: wheel-visualizer-sweep 1.8s ease-in-out infinite;
}
@keyframes wheel-visualizer-sweep {
  from {
    transform: translateX(-120%);
  }
  to {
    transform: translateX(320%);
  }
}
.wheel-visualizer__status {
  /* Two lines that belong together: what is happening, then how long. */
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}
/* The rotating line holds its own height so the panel does not jump every three
   seconds as one message replaces a shorter one. Keep the messages short enough
   to sit on one line at 390px and this never has to grow. */
.wheel-visualizer__status-line {
  display: block;
  min-height: 2.4rem;
}
.wheel-visualizer__status-hint {
  color: rgba(var(--color-foreground), 0.6);
}

/* A travelling highlight is exactly the kind of motion that causes trouble for
   people who ask for less of it, so they get a slow breath instead of a sweep.
   Something still has to move: the whole point is showing the thing is alive. */
@media (prefers-reduced-motion: reduce) {
  .wheel-visualizer__sweep {
    display: none;
  }
  .wheel-visualizer__frame--working img {
    animation: wheel-visualizer-breathe 2.4s ease-in-out infinite;
  }
  @keyframes wheel-visualizer-breathe {
    0%,
    100% {
      opacity: 0.45;
    }
    50% {
      opacity: 0.8;
    }
  }
}

.wheel-visualizer__disclaimer {
  color: rgba(var(--color-foreground), 0.6);
}

/* Wider than the theme's 50rem default, because the content is a photograph and
   a photograph wants width. --modal-width is the theme's own knob for this: the
   quick view sets it to 82rem and 120rem on larger screens, so this is the
   established way to size a modal rather than a new one. Below 767.98px the
   modal is already the full screen less its 1.6rem gutter, so there is nothing
   to widen there. */
@media (min-width: 768px) {
  .wheel-visualizer.modal .drawer__inner {
    --modal-width: 72rem;
  }
}

@media (max-width: 767.98px) {
  /* The whole panel has to fit a phone without scrolling inside itself.
     Scrolling within a modal that is itself over a scrolling page is a bad
     feel: the shopper cannot tell which surface their thumb is on, and the
     buttons they want are the ones that fall off the bottom.

     So the height is budgeted rather than left to chance. Everything that is
     not the picture is fixed and small, the picture takes what is left, and the
     gaps between them come down. On a 375x667 phone, which is the smallest
     thing we design for, that fits with the disclaimer visible. */
  .wheel-visualizer__content {
    gap: 1.2rem;
  }
  .wheel-visualizer__app {
    gap: 1.2rem;
  }
  .wheel-visualizer__pick,
  .wheel-visualizer__working,
  .wheel-visualizer__staged,
  .wheel-visualizer__result {
    gap: 1.2rem;
  }

  .wheel-visualizer__drop {
    padding: 2.4rem 1.6rem;
  }
  .wheel-visualizer__drop-mark {
    width: 4.4rem;
    height: 4.4rem;
  }

  /* width:auto and margin:auto rather than object-fit, so the picture keeps its
     own aspect ratio and centres in the frame instead of being letterboxed by a
     box that has already decided how wide it is. */
  .wheel-visualizer__frame img {
    width: auto;
    max-width: 100%;
    max-height: 38dvh;
    margin-inline: auto;
  }

  /* Full width buttons on a phone: two half-width buttons in a modal are a
     smaller target than they look once a thumb is involved. */
  .wheel-visualizer__actions .btn {
    width: 100%;
    flex-grow: 1;
  }

  .wheel-visualizer__disclaimer {
    line-height: 1.4;
  }
}
