/* 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;
  }
}

/* ---------------------------------------------------------------------------
   Social links
   The row of icons in the footer, one per account a shop has filled in under
   Admin → Settings → Social. Named parts, neutral paint: the colour comes from
   whatever the footer already sets, so a shop with a dark footer inherits its
   own text colour instead of a grey that only suits the template.

   The touch target is 2.5rem square rather than the glyph's own size. At the
   icon's natural bounds these sit below the 24px minimum and land next to each
   other, which is how a thumb aiming for Instagram opens TikTok.
   --------------------------------------------------------------------------- */
.social-links {
  /* Pulled left by the padding inside the first link, so the row of glyphs
     lines up with the text above it rather than sitting indented from it. */
  margin-top: 0.75rem;
  margin-left: -0.625rem;
}

.social-links__link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  font-size: 1.25rem;
  color: inherit;
  text-decoration: none;
  opacity: 0.7;
  transition: opacity 0.15s ease-in-out;
}

.social-links__link:hover,
.social-links__link:focus-visible {
  color: inherit;
  opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
  .social-links__link {
    transition: none;
  }
}
