/* The shop's own pages, and the customer's account inside them.
 *
 * Structure and neutral defaults. Every component is named so a shop's
 * brand.css can paint it without fighting a Bootstrap utility for specificity
 * — that is what "named parts" means throughout.
 *
 * The account portal loads this too, deliberately: someone clicking "My
 * orders" from a shop page should not land on staff chrome.
 *
 * ---------------------------------------------------------------------------
 * OWNED BY THE TEMPLATE. A shop does not edit this file.
 * --------------------------------------------------------------------------- */

/* ---------------------------------------------------------------------------
   Storefront
   Bootstrap 5.3 has no dashed-border utility, and the empty catalog state
   wants one. Everything else on the storefront uses stock Bootstrap.
   --------------------------------------------------------------------------- */
.border-dashed {
  border-style: dashed !important;
}

/* ---------------------------------------------------------------------------
   Cart drawer backdrop
   Bootstrap injects `.offcanvas-backdrop` from its JavaScript, and that bundle
   is no longer loaded — the drawer is offcanvas_controller.js now. The element
   is in the markup instead, and this is what shows and hides it.
   --------------------------------------------------------------------------- */
.offcanvas-backdrop {
  display: none;
}

.cart-drawer--open .offcanvas-backdrop {
  display: block;
  opacity: 0.5;
}

/* The line a customer has just added, tinted for as long as it takes to find
   it and then left alone. The drawer opening answers "did that work"; this
   answers "which one", which is the question with five things in the basket.

   The animation runs on its own: the drawer's markup is replaced on every
   basket change, so this element is new every time and a CSS animation on a
   newly inserted element plays without anything having to start it. */
.cart-line--added {
  animation: cart-line-added 2s ease-out;
}

@keyframes cart-line-added {
  from { background-color: rgba(25, 135, 84, 0.16); }
  to   { background-color: transparent; }
}

@media (prefers-reduced-motion: reduce) {
  .cart-line--added {
    animation: none;
  }
}

/* ---------------------------------------------------------------------------
   Basket and checkout
   The parts a shop will want to paint, named so it can. Everything here is
   structure and a neutral default — the same division as the product card.

   The grand total and the applied coupon are named for the same reason the
   flag below is: the obvious Bootstrap classes for them (fw-semibold,
   text-bg-success) either say too little or set colour with !important.
   --------------------------------------------------------------------------- */
.order-totals__total {
  font-size: 1rem;
}

.coupon-tag {
  display: inline-block;
  padding: 0.2em 0.6em;
  border-radius: 999px;
  background: var(--bs-success);
  color: #fff;
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.02em;
}

/* A shipping method is a decision that changes the total, so the whole row is
   the target rather than the 16px radio inside it. */
.shipping-option {
  padding: 0.5rem 0.5rem 0.5rem 2rem;
  border-radius: var(--bs-border-radius);
}

.shipping-option:hover {
  background: var(--bs-tertiary-bg);
}

/* Named rather than built out of Bootstrap's badge utilities, which set colour
   and border with !important and so cannot be repainted by a shop's own
   stylesheet. Structure and a neutral default here; the colour is the shop's. */
.cart-line__flag {
  display: inline-block;
  margin-left: 0.25rem;
  padding: 0.15em 0.6em;
  border: 1px solid var(--bs-border-color);
  border-radius: 999px;
  background: var(--bs-tertiary-bg);
  color: var(--bs-secondary-color);
  font-size: 0.7rem;
  font-weight: 400;
  vertical-align: middle;
  white-space: nowrap;
}

/* ---------------------------------------------------------------------------
   Home page slider
   Structure only. A shop's own stylesheet colours it — this is the part every
   clone needs and none of them should have to rebuild.

   The track is a scroll-snap strip, so with JavaScript off it stays a usable
   horizontally scrollable list of slides rather than collapsing to one. The
   Stimulus controller adds the dots, arrows and auto-advance on top.
   --------------------------------------------------------------------------- */
.slider {
  position: relative;
}

.slider__track {
  display: flex;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
}

.slider__track::-webkit-scrollbar {
  display: none;
}

/* The slide sets its own shape rather than inheriting the artwork's. Without
   this a square upload produces a square hero — as tall as the page is wide —
   and the shop discovers it only after uploading. object-fit crops to fit.
   Portrait on a phone, because a 3:1 band there is a letterbox slot with
   nothing legible in it. */
.slider__slide {
  position: relative;
  flex: 0 0 100%;
  scroll-snap-align: start;
  aspect-ratio: 4 / 5;
  min-height: 320px;
  max-height: 80svh;
  display: grid;
  /* One row that takes the slide's height rather than the image's. Without it
     the row is sized by the artwork's natural height, the box is sized by
     aspect-ratio, and the caption ends up below the visible slide — which
     looks exactly like a caption that failed to render. */
  grid-template-rows: 1fr;
}

@media (min-width: 768px) {
  .slider__slide {
    aspect-ratio: 3 / 1;
  }
}

/* One cell, so the picture fills the slide however the slide is shaped. */
.slider__slide > picture,
.slider__link {
  grid-area: 1 / 1;
  /* Grid items default to min-height: auto, which lets their content push the
     row taller than the track. */
  min-height: 0;
  min-width: 0;
}

.slider__slide > picture,
.slider__link {
  overflow: hidden;
}

.slider__link {
  display: block;
}

.slider__image {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.slider__controls {
  position: absolute;
  right: 1rem;
  bottom: 1rem;
  display: flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.25rem;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.9);
}

.slider__arrow {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: #151515;
}

.slider__arrow:hover,
.slider__arrow:focus-visible {
  background: rgba(0, 0, 0, 0.08);
}

.slider__dots {
  display: flex;
  gap: 0.375rem;
  padding-inline: 0.25rem;
}

.slider__dot {
  width: 9px;
  height: 9px;
  padding: 0;
  border: 1px solid #151515;
  border-radius: 50%;
  background: transparent;
}

.slider__dot.is-current {
  background: #151515;
}

/* Every control is at least 44px of hit area even though the dot is 9px, which
   is the part that makes this usable on a phone. */
.slider__dot::before {
  content: "";
  position: absolute;
  width: 44px;
  height: 44px;
  transform: translate(-50%, -50%);
}

.slider__dots { position: relative; }
.slider__dot { position: relative; }

/* ---------------------------------------------------------------------------
   Collection cards
   Structure and a neutral default. A shop's own stylesheet colours them.

   Deliberately not built from `bg-body-tertiary` and `fw-semibold`: Bootstrap's
   utilities carry !important, so a component wearing them can only be restyled
   by a clone shouting back with more !important. Naming the parts instead
   leaves the override an ordinary rule.
   --------------------------------------------------------------------------- */
.collection-card__media {
  background: var(--bs-secondary-bg, #f8f9fa);
}

.collection-card__title {
  font-weight: 600;
}

/* ---------------------------------------------------------------------------
   Product quick view
   Structure only; a shop's own stylesheet colours it. Hidden with the `hidden`
   attribute rather than a class, so it is out of the accessibility tree and
   out of the tab order before anything is loaded into it — not merely
   invisible.
   --------------------------------------------------------------------------- */
.quick-view {
  position: fixed;
  inset: 0;
  z-index: 1060;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
}

.quick-view[hidden] {
  display: none;
}

.quick-view__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.5);
}

.quick-view__panel {
  position: relative;
  width: min(64rem, 100%);
  max-height: 90svh;
  overflow-y: auto;
  background: #fff;
  border-radius: 0.5rem;
  padding: 1.5rem;
}

.quick-view__close {
  position: absolute;
  top: 0.75rem;
  right: 0.75rem;
  z-index: 1;
}

/* The detail column is laid out for a page two-thirds the width of a screen.
   Inside a dialog there is no sidebar competing with it, so the columns stack
   later than they would in the page. */
@media (max-width: 991.98px) {
  .quick-view__panel {
    padding: 1rem;
  }
}
