/* ==========================================================================
   MAHIRA SELECT - product.css
   Single product page. Loaded on product pages only.

   The whole page is built on one measure and one spacing scale, both declared
   at the top of this file. Every band from the hero down to recently viewed
   uses .ms-pdp-wrap, so nothing on the page can drift out of alignment with
   anything else.
   ========================================================================== */

.ms-pdp{
  /*
   * One measure for the entire page, and it is the site measure. The header,
   * the top bar and the footer all sit on --ms-container, so anything narrower
   * here puts the product's left edge inboard of the logo above it. Taken from
   * the token rather than repeated as a number, so the page follows if the
   * container is ever retuned.
   */
  --pdp-max:var(--ms-container);
  /* Vertical rhythm. Bands step between these two values and nothing else. */
  --pdp-band:clamp(52px,6vw,92px);
  --pdp-band-tight:clamp(38px,4vw,60px);
  /*
   * Ceiling for the editorial gallery frame on desktop. It exists to stop the
   * hero from running away on a tall window, not to protect the fold: the
   * purchase panel sits beside the picture, not under it, so add to bag holds
   * its position however tall the image gets. Generous enough that a 4:5 crop
   * usually clears it untouched and the frame stays portrait.
   */
  --pdp-stage:clamp(560px,88vh,940px);
  /*
   * One size for every price on the page, so the hero price and the price a
   * variation swaps in can never disagree. Floor 27px: on a phone the price
   * has to out-rank the 24px title, because it is the number the customer
   * came for. Ceiling 36px: the desktop title tops out at 34px and the price
   * was losing to it at the old 28px.
   */
  --pdp-price-fs:clamp(1.6875rem,1.45rem + .95vw,2.25rem);
}

/* The single alignment primitive. Everything on the page sits inside one. */
.ms-pdp-wrap{
  width:100%;
  max-width:var(--pdp-max);
  margin-inline:auto;
  padding-inline:var(--ms-gutter);
}

/*
 * The breadcrumb is printed by the page wrapper, outside .ms-pdp, so it takes
 * the site container on its own. It is deliberately not overridden here: doing
 * so is what gave the page a third left edge, one for the header, one for the
 * breadcrumb and one for the product itself.
 */

/* ==========================================================================
   1. Hero
   ========================================================================== */
/* Opens straight under the header now that the breadcrumb bar has gone, so it
   carries the air that bar used to occupy. */
.ms-pdp__hero{
  padding-block:clamp(26px,3vw,48px) var(--pdp-band-tight);
}

.ms-pdp__grid{
  display:grid;
  grid-template-columns:1fr;
  gap:clamp(26px,3.5vw,54px);
}
/*
 * The hero splits at 760, not at the desktop breakpoint. Stacked, the gallery
 * is a full width 4:5 frame: on a 900px tablet that is over 1000px tall, so
 * the customer scrolls a whole screen of photograph before reaching the title.
 * Two columns from tablet up keeps the picture and the price on the same view.
 */
@media (min-width:760px){
  .ms-pdp__grid{
    grid-template-columns:minmax(0,1.1fr) minmax(296px,1fr);
    gap:clamp(24px,3vw,40px);
    /* start, never centre: both columns must begin on the same line. */
    align-items:start;
  }
}
@media (min-width:1000px){
  .ms-pdp__grid{
    /*
     * Roughly 58 / 42 once the gap is taken out, which keeps the image
     * dominant without starving the purchase panel. Both tracks are
     * proportional on purpose: a flat pixel cap on the panel holds its full
     * size as the window narrows, and by 1024 it would have taken more of the
     * row than the gallery. The percentage inside min() is what keeps the
     * split honest down there; the pixel value only bites on a large screen.
     */
    grid-template-columns:minmax(0,1.33fr) minmax(340px,min(540px,42%));
    gap:clamp(26px,3.5vw,54px);
  }
}

/*
 * Past this width both columns stop growing and the surplus becomes air
 * between them. On the site measure a purely proportional split would hand the
 * gallery an 850px stage, which under the height ceiling below stops being a
 * portrait photograph and turns into a letterbox, and would leave the purchase
 * panel far wider than its own text wants to be. The columns still meet the
 * container edges, so the hero stays flush with the header.
 */
@media (min-width:1560px){
  .ms-pdp__grid{
    grid-template-columns:minmax(0,860px) minmax(340px,540px);
    justify-content:space-between;
    column-gap:60px;
  }
}

/* ==========================================================================
   2. Gallery
   ========================================================================== */
.ms-gallery{
  display:grid;grid-template-columns:1fr;
  gap:10px;position:relative;min-width:0;
}
@media (min-width:1000px){
  .ms-gallery{grid-template-columns:84px minmax(0,1fr);gap:16px;}
  .ms-gallery--single{grid-template-columns:minmax(0,1fr);}
}

/* ------------------------------------------------------------- Thumbnails */
.ms-gallery__rail{order:2;min-width:0;}
@media (min-width:1000px){ .ms-gallery__rail{order:1;} }

.ms-gallery__thumbs{
  display:flex;gap:8px;
  overflow-x:auto;overscroll-behavior-x:contain;scrollbar-width:none;
  scroll-snap-type:x proximity;
  padding-block:2px;
}
.ms-gallery__thumbs::-webkit-scrollbar{display:none;}
@media (min-width:1000px){
  .ms-gallery__thumbs{
    flex-direction:column;gap:10px;
    overflow-y:auto;overflow-x:visible;
    max-height:var(--pdp-stage);
    padding-inline:2px;
  }
}

.ms-gallery__thumb{
  flex:0 0 auto;width:70px;padding:0;border:0;background:var(--ms-sand);
  position:relative;aspect-ratio:4/5;overflow:hidden;cursor:pointer;
  scroll-snap-align:start;
  opacity:.55;
  outline:1px solid transparent;outline-offset:-1px;
  transition:opacity var(--ms-t) var(--ms-ease),outline-color var(--ms-t) var(--ms-ease);
}
@media (min-width:1000px){ .ms-gallery__thumb{width:100%;} }
.ms-gallery__thumb img{
  position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;object-position:center top;
}
.ms-gallery__thumb:hover{opacity:.85;}
.ms-gallery__thumb.is-on{opacity:1;outline-color:var(--ms-ink);}
.ms-gallery__thumb:focus-visible{outline:2px solid var(--ms-focus);outline-offset:2px;}

/* ------------------------------------------------------------------ Stage */
.ms-gallery__stage{
  order:1;position:relative;min-width:0;
  background:var(--ms-sand);
  overflow:hidden;
}
@media (min-width:1000px){ .ms-gallery__stage{order:2;} }

.ms-gallery__track{
  display:flex;
  overflow-x:auto;overscroll-behavior-x:contain;
  scroll-snap-type:x mandatory;scrollbar-width:none;
  scroll-behavior:smooth;
}
.ms-gallery__track::-webkit-scrollbar{display:none;}
.ms-gallery__track.is-dragging,
.ms-gallery__track.is-dragging .ms-gallery__slide{cursor:grabbing;}
.ms-gallery__track.is-dragging{user-select:none;}
/* A native image drag would take the gesture away from the strip. */
.ms-gallery__img{-webkit-user-drag:none;user-select:none;}
/* One image is not a strip: it is only ever a way into the lightbox. */
.ms-gallery--single .ms-gallery__slide{cursor:zoom-in;}
.ms-gallery__track:focus-visible{outline:2px solid var(--ms-focus);outline-offset:-2px;}

/*
 * grab, not zoom-in. The strip can be dragged with a mouse as well as swiped
 * with a thumb, and the cursor is the only thing that says so; the plus
 * control in the corner is the explicit way into the lightbox, and a plain
 * click on the photograph still opens it.
 */
.ms-gallery__slide{
  flex:0 0 100%;margin:0;position:relative;
  aspect-ratio:4/5;scroll-snap-align:center;cursor:grab;
  overflow:hidden;
  /* A ceiling for landscape and for short windows, where a 4:5 frame would
     otherwise be taller than the screen it has to fit in. */
  max-height:82vh;
}
@media (min-width:1000px){
  /*
   * A 4:5 editorial frame, but ceilinged. The ratio alone would stand over
   * 900px tall at this column width and push add to bag under the fold; the
   * ceiling alone would draw a narrow 1:2 slot on a small laptop. Together
   * they give a portrait frame that follows the column and still clears the
   * fold on every screen.
   */
  .ms-gallery__slide{aspect-ratio:4/5;height:auto;max-height:var(--pdp-stage);}
}

/*
 * Cropped from the top rather than the centre. These are full length model
 * shots in a tall frame, and a centred crop takes the head off the top and the
 * hem off the bottom in equal measure. Anchoring the top keeps the face and
 * the neckline, which is what the customer looks at first.
 */
/*
 * Qualified with the slide rather than left as a bare class. WooCommerce's own
 * stylesheet still loads here and carries .woocommerce img{height:auto}, which
 * outranks a single class by one element name: without the extra weight the
 * image falls back to its intrinsic ratio and stops filling the frame, leaving
 * a block of bare sand under it on any screen where the frame is taller than
 * the picture.
 */
.ms-gallery__slide .ms-gallery__img{
  position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;object-position:center top;
  transition:transform var(--ms-t-slow) var(--ms-ease);
}
@media (hover:hover){
  .ms-gallery__slide:hover .ms-gallery__img{transform:scale(1.035);}
}

/* --------------------------------------------------------------- Controls */
.ms-gallery__nav{
  position:absolute;top:50%;z-index:3;
  width:42px;height:42px;padding:0;border:0;cursor:pointer;
  background:rgba(245,242,234,.9);color:var(--ms-ink);
  display:none;align-items:center;justify-content:center;
  opacity:0;
  transition:opacity var(--ms-t) var(--ms-ease),background var(--ms-t) var(--ms-ease);
}
.ms-gallery__nav--prev{left:16px;transform:translateY(-50%) rotate(90deg);}
.ms-gallery__nav--next{right:16px;transform:translateY(-50%) rotate(-90deg);}
.ms-gallery__nav:hover{background:var(--ms-white);}
.ms-gallery__nav[disabled]{opacity:0!important;pointer-events:none;}
@media (min-width:1000px){
  .ms-gallery__nav{display:flex;}
  .ms-gallery__stage:hover .ms-gallery__nav,
  .ms-gallery__nav:focus-visible{opacity:1;}
}

.ms-gallery__tools{
  position:absolute;right:14px;bottom:14px;z-index:3;
  display:flex;align-items:center;gap:8px;
}
/* The "1 / 3" counter that sat beside this button, and the row of dots that
   sat under it, were dropped from parts/product/gallery.php on the client's
   instruction (2026-09-13) and their rules went with them. The thumbnail rail
   is the only place the gallery counts itself now. */

.ms-gallery__expand{
  width:38px;height:38px;border:0;cursor:pointer;
  background:rgba(245,242,234,.9);color:var(--ms-ink);
  display:flex;align-items:center;justify-content:center;
  transition:background var(--ms-t) var(--ms-ease);
}
.ms-gallery__expand:hover{background:var(--ms-white);}

.ms-gallery__badges{
  position:absolute;top:14px;left:14px;z-index:3;
  display:flex;flex-direction:column;align-items:flex-start;gap:6px;
  pointer-events:none;
}

.ms-gallery__empty{position:relative;aspect-ratio:4/5;overflow:hidden;}
@media (min-width:1000px){ .ms-gallery__empty{max-height:var(--pdp-stage);} }

/* ------------------------------------------------------------------ Video */
/*
 * The video is a slide in the same strip as the photographs, in the same 4:5
 * frame, on ink instead of sand.
 *
 * The frame is the fixed thing, not the video. The strip's whole geometry
 * rests on every slide being exactly one frame wide, so the picture is fitted
 * into the frame rather than the frame to the picture: object-fit is contain,
 * so nothing is ever cropped, and the ink ground carries whatever is left
 * over. A vertical or square video fills it; a 16:9 one bands above and
 * below, which the Video panel in the editor says in as many words rather
 * than leaving it to be discovered.
 */
.ms-gallery__slide--video{background:var(--ms-ink);cursor:auto;}
/* Overrides the zoom-in the single slide case sets: there is no lightbox
   behind a video, so the cursor must not offer one. */
.ms-gallery--single .ms-gallery__slide--video{cursor:auto;}

/*
 * Qualified with the slide rather than left as bare classes, for the same
 * reason .ms-gallery__img above is: WooCommerce's own stylesheet carries
 * .woocommerce img{height:auto}, which outranks a single class.
 */
.ms-gallery__slide .ms-gallery__video,
.ms-gallery__slide .ms-gallery__vposter,
.ms-gallery__slide .ms-gallery__embed{
  position:absolute;inset:0;width:100%;height:100%;border:0;
}
.ms-gallery__slide .ms-gallery__video{object-fit:contain;background:var(--ms-ink);}
/* The still is a product photograph, so it is cropped like one. */
.ms-gallery__slide .ms-gallery__vposter{object-fit:cover;object-position:center top;}

.ms-gallery__play{
  position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);
  z-index:4;width:72px;height:72px;border:0;cursor:pointer;border-radius:50%;
  background:rgba(245,242,234,.92);color:var(--ms-ink);
  display:flex;align-items:center;justify-content:center;
  /* A triangle's optical centre sits left of its box. */
  padding:0 0 0 5px;
  transition:background var(--ms-t) var(--ms-ease),transform var(--ms-t) var(--ms-ease),opacity var(--ms-t) var(--ms-ease);
}
.ms-gallery__play:hover{background:var(--ms-white);transform:translate(-50%,-50%) scale(1.06);}
.ms-gallery__play:focus-visible{outline:2px solid var(--ms-focus);outline-offset:3px;}
/* Out of the way while the file runs, back on pause and at the end. The
   native controls stay, so nothing is lost while it is hidden. */
.ms-gallery__slide.is-playing .ms-gallery__play{opacity:0;pointer-events:none;}

/*
 * The still steps aside the first time the video is played and stays aside.
 * Bringing it back on pause would cover the frame the viewer stopped on, and
 * hide the scrubber they were reaching for. visibility, not opacity alone, so
 * it stops intercepting the clicks meant for the controls underneath.
 */
.ms-gallery__slide--video .ms-gallery__vposter{
  z-index:2;transition:opacity var(--ms-t) var(--ms-ease);
}
.ms-gallery__slide--video.has-started .ms-gallery__vposter{opacity:0;visibility:hidden;}

/* Nothing behind it on this slide: the lightbox is photographs only, and a
   video is watched in the stage, where its own controls are. */
.ms-gallery.is-video .ms-gallery__expand{display:none;}

.ms-gallery__thumb--video{background:var(--ms-ink);}
.ms-gallery__thumb--video .ms-gallery__vposter{
  position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;object-position:center top;
}
/* A scrim under the mark, so it holds on a pale still as well as a dark one
   and the rail reads as "one of these is a video" at a glance. */
.ms-gallery__thumbplay{
  position:absolute;inset:0;z-index:2;
  display:flex;align-items:center;justify-content:center;
  padding-left:2px;
  color:var(--ms-cream);background:rgba(13,13,13,.30);
}

/* --------------------------------------------------------------- Lightbox */
/*
 * The display:flex below is an author rule, and author rules beat the user
 * agent's [hidden]{display:none} whatever their specificity. Without the two
 * rules underneath it the closed lightbox stays laid out: a full viewport
 * sheet at z-index 1300 that is invisible at opacity 0 but still hit tested,
 * so every click on the product page, including add to bag and the header,
 * lands on it instead.
 */
.ms-lightbox{
  position:fixed;inset:0;z-index:1300;
  background:rgba(13,13,13,.95);
  display:flex;align-items:center;justify-content:center;
  opacity:0;pointer-events:none;
  transition:opacity var(--ms-t) var(--ms-ease);
  /* The swipe in product.js needs the horizontal axis handed to it, or the
     browser claims the gesture and stops sending pointermove. The vertical
     axis and the pinch stay with the browser: neither is this script's to
     take, and a pinch on a photograph is the one thing a customer looking at
     fabric will reach for. */
  touch-action:pan-y pinch-zoom;
}
.ms-lightbox[hidden]{display:none;}
.ms-lightbox.is-open{opacity:1;pointer-events:auto;}
.ms-lightbox__stage{
  max-width:min(92vw,1100px);max-height:88vh;
  display:flex;align-items:center;justify-content:center;
}
.ms-lightbox__img{
  max-width:100%;max-height:88vh;width:auto;height:auto;
  cursor:zoom-in;transition:transform var(--ms-t-slow) var(--ms-ease);
  /* A drag across the photograph is a swipe. Without these the browser starts
     its own image drag on a mouse and a text selection on a trackpad, and the
     gesture never reaches the handler. */
  user-select:none;-webkit-user-select:none;
  -webkit-user-drag:none;
}
.ms-lightbox__img.is-zoomed{transform:scale(1.9);cursor:zoom-out;}
.ms-lightbox__close,.ms-lightbox__nav{
  position:absolute;z-index:2;
  width:48px;height:48px;border:0;cursor:pointer;
  background:rgba(245,242,234,.1);color:var(--ms-cream);
  display:flex;align-items:center;justify-content:center;
  transition:background var(--ms-t) var(--ms-ease);
}
.ms-lightbox__close:hover,.ms-lightbox__nav:hover{background:rgba(245,242,234,.22);}
.ms-lightbox__close{top:18px;right:18px;}
.ms-lightbox__nav--prev{left:18px;top:50%;transform:translateY(-50%) rotate(90deg);}
.ms-lightbox__nav--next{right:18px;top:50%;transform:translateY(-50%) rotate(-90deg);}
.ms-lightbox__count{
  position:absolute;bottom:20px;left:0;right:0;text-align:center;
  color:rgba(245,242,234,.62);font-size:var(--ms-fs-xs);margin:0;max-width:none;
  font-variant-numeric:tabular-nums;
}
@media (max-width:700px){
  .ms-lightbox__nav{width:40px;height:40px;}
  .ms-lightbox__nav--prev{left:8px;}
  .ms-lightbox__nav--next{right:8px;}
}

/* ==========================================================================
   3. Purchase panel
   ========================================================================== */
.ms-pdp__panel{min-width:0;}
@media (min-width:1000px){
  .ms-pdp__panel{
    position:sticky;
    top:calc(var(--ms-header-h-compact) + 20px);
  }
  /* Padding rather than margin, so the sticky offset above stays honest. */
  .ms-pdp__panelinner{padding-left:clamp(0px,1.2vw,20px);}
}

.ms-pdp__kicker{
  font-size:var(--ms-fs-micro);letter-spacing:.16em;
  text-transform:uppercase;color:var(--ms-muted);
  margin:0 0 12px;
}

.ms-pdp__title{
  /* Poppins, not the display serif. The client rejected Playfair for product
     names, prices and document headings on 2026-09-02; it stays on editorial
     display headings only. */
  font-family:var(--ms-font-body);
  /* A geometric sans reads optically larger than the serif at the same size,
     and sets wider, so the ceiling comes down and the measure goes up. */
  font-size:clamp(1.5rem,1.2rem + 1.15vw,2.125rem);
  font-weight:500;
  line-height:1.28;letter-spacing:-.015em;
  margin:0 0 14px;
  max-width:22ch;
}

/* ------------------------------------------------------------------ Rating */
.ms-pdp__rating{
  display:inline-flex;align-items:center;gap:8px;
  font-size:var(--ms-fs-xs);color:var(--ms-muted);
  margin-bottom:18px;
  padding-bottom:2px;
  border-bottom:1px solid transparent;
  transition:color var(--ms-t) var(--ms-ease),border-color var(--ms-t) var(--ms-ease);
}
.ms-pdp__rating:hover{color:var(--ms-ink);border-bottom-color:var(--ms-gold-line);}
.ms-pdp__ratingnum{color:var(--ms-ink);font-weight:500;}
.ms-pdp__ratingsep{color:var(--ms-border);}
.ms-pdp__rating--none{color:var(--ms-muted);}

.ms-stars{display:inline-flex;gap:2px;color:var(--ms-border);line-height:0;}
.ms-stars svg{stroke-width:1.1;}
.ms-stars svg.is-on{color:var(--ms-gold);fill:currentColor;}

/* -------------------------------------------------------------- Description */
.ms-pdp__excerpt{
  margin-bottom:24px;
  color:var(--ms-muted);
  font-size:var(--ms-fs-sm);line-height:1.72;
}
.ms-pdp__excerpt p{max-width:46ch;margin:0;}
.ms-pdp__excerpt p + p{margin-top:.7em;}

/* ------------------------------------------------------------------- Price */
/* The box carries the rule, not the tax note, which a store may not print. */
.ms-pdp__pricebox{
  margin-bottom:26px;padding-bottom:24px;
  border-bottom:var(--ms-hairline);
}
.ms-pdp__pricing{
  display:flex;align-items:baseline;gap:14px;flex-wrap:wrap;
}
.ms-pdp__price{
  /* Poppins, not the display serif. The client rejected Playfair for product
     names, prices and document headings on 2026-09-02; it stays on editorial
     display headings only. */
  font-family:var(--ms-font-body);
  font-size:var(--pdp-price-fs);
  font-weight:600;line-height:1.08;
  /* Poppins sets its figures loose; at this size they need pulling in. */
  letter-spacing:-.015em;
  color:var(--ms-ink);
}
.ms-pdp__price .amount{font-variant-numeric:tabular-nums;}
.ms-pdp__price del{
  color:var(--ms-muted);
  /* Lighter as well as greyer: at 600 the struck original was pulling as much
     weight as the number that matters. */
  font-weight:400;
  font-size:.58em;
  letter-spacing:0;
  margin-right:.4em;
  text-decoration-thickness:1px;
  text-underline-offset:.1em;
}
.ms-pdp__price ins{text-decoration:none;color:var(--ms-ink);}
.ms-pdp__price .woocommerce-Price-currencySymbol{font-size:.8em;padding-right:.05em;}

/* Restrained rather than shouty: a hairline chip, not a red starburst. */
.ms-pdp__off{
  align-self:center;
  /* Grown with the price beside it; an 11px chip next to a 36px figure reads
     as a leftover rather than as its pair. */
  padding:6px 11px;
  font-size:.75rem;font-weight:500;
  letter-spacing:.1em;text-transform:uppercase;
  color:var(--ms-gold-ink);
  background:var(--ms-gold-soft);
  white-space:nowrap;
}

.ms-pdp__tax{
  font-size:var(--ms-fs-micro);color:var(--ms-muted);
  margin:7px 0 0;letter-spacing:.02em;
}

/* ==========================================================================
   4. Variation options
   ========================================================================== */
.ms-pdp .variations{width:100%;margin:0 0 22px;border:0;}
.ms-pdp .variations tbody,
.ms-pdp .variations tr,
.ms-pdp .variations th,
.ms-pdp .variations td{display:block;padding:0;border:0;text-align:left;width:auto;}
.ms-pdp .variations tr{margin-bottom:20px;}
.ms-pdp .variations label{
  display:block;font-size:var(--ms-fs-micro);font-weight:500;
  letter-spacing:var(--ms-track-micro);text-transform:uppercase;
  color:var(--ms-muted);margin-bottom:11px;
}
.ms-optgroup__chosen{
  margin-left:8px;color:var(--ms-ink);text-transform:none;letter-spacing:0;
  font-weight:400;font-size:var(--ms-fs-sm);
}

/* The real select stays in the DOM for WooCommerce, out of sight. */
.ms-opt-native{display:none!important;}

.ms-optgroup{display:flex;flex-wrap:wrap;gap:8px;}
.ms-opt{
  min-height:44px;min-width:52px;padding:0 16px;
  background:transparent;color:var(--ms-ink);
  border:1px solid var(--ms-border);border-radius:var(--ms-radius-btn);
  font-family:var(--ms-font-body);font-size:var(--ms-fs-sm);
  cursor:pointer;
  transition:border-color var(--ms-t) var(--ms-ease),background var(--ms-t) var(--ms-ease),color var(--ms-t) var(--ms-ease);
}
.ms-opt:hover{border-color:var(--ms-ink);}
.ms-opt.is-on{border-color:var(--ms-ink);background:var(--ms-ink);color:var(--ms-cream);}
.ms-opt.is-off{opacity:.34;cursor:not-allowed;text-decoration:line-through;}
.ms-opt.is-off:hover{border-color:var(--ms-border);}

.ms-optgroup--swatch{gap:10px;}
.ms-opt--swatch{
  width:36px;height:36px;min-width:0;min-height:0;padding:0;border-radius:50%;
  background:var(--sw,var(--ms-sand));
  border:1px solid var(--ms-border);
  outline:2px solid transparent;outline-offset:2px;
}
.ms-opt--swatch:hover{border-color:var(--ms-muted);}
.ms-opt--swatch.is-on{outline-color:var(--ms-ink);background:var(--sw,var(--ms-sand));}
.ms-opt--swatch.is-off{opacity:.3;text-decoration:none;}

.ms-pdp .reset_variations{
  display:inline-block;margin-top:11px;
  font-size:var(--ms-fs-xs);color:var(--ms-muted);
  text-decoration:underline;text-underline-offset:.2em;
  transition:color var(--ms-t) var(--ms-ease);
}
.ms-pdp .reset_variations:hover{color:var(--ms-ink);}
/*
 * The chosen variation's price. WooCommerce colours its own .price span from
 * its stylesheet, which puts an olive green in the middle of the purchase
 * panel, so the colour is claimed back here along with the hero's treatment of
 * a struck through original.
 */
.ms-pdp .woocommerce-variation-price,
.ms-pdp .woocommerce-variation-price .price,
.ms-pdp.product .woocommerce-variation-price span.price,
.ms-pdp.product .ms-pdp__price span.price{
  font-family:var(--ms-font-body);font-size:var(--pdp-price-fs);font-weight:600;
  letter-spacing:-.015em;
  color:var(--ms-ink);margin-bottom:12px;
}
.ms-pdp .woocommerce-variation-price .price{margin:0;display:inline;}
.ms-pdp .woocommerce-variation-price del{
  color:var(--ms-muted);font-weight:400;font-size:.58em;letter-spacing:0;
  margin-right:.4em;text-decoration-thickness:1px;
}
.ms-pdp .woocommerce-variation-price ins{text-decoration:none;color:var(--ms-ink);}
.ms-pdp .woocommerce-variation-price .amount{font-variant-numeric:tabular-nums;}
.ms-pdp .woocommerce-variation-availability{font-size:var(--ms-fs-xs);color:var(--ms-muted);margin-bottom:10px;}
.ms-pdp .woocommerce-variation-description{font-size:var(--ms-fs-sm);color:var(--ms-muted);margin-bottom:12px;}

/* ==========================================================================
   5. Quantity and the two buy buttons
   ========================================================================== */
.ms-pdp form.cart{margin:0;display:block;}

.ms-buy__label{
  font-size:var(--ms-fs-micro);font-weight:500;
  letter-spacing:var(--ms-track-micro);text-transform:uppercase;
  color:var(--ms-muted);margin:0 0 10px;max-width:none;
}

/*
 * Quantity and add to bag on one line. Stacked, the stepper sat alone on a row
 * with the whole panel width empty beside it. The stepper keeps its natural
 * width and add to bag takes the rest, aligned on their shared bottom edge so
 * the label above the stepper does not push the button out of line.
 *
 * The button carries a 150px flex basis, which is what "Add to bag" needs to
 * set without crushing. A 375px phone clears it with room to spare and keeps
 * the pair on one line; anything narrower drops the button to its own full
 * width line rather than squeezing the label.
 */
.ms-buy__row{
  display:flex;align-items:flex-end;flex-wrap:wrap;
  gap:10px;margin:0 0 10px;
}
.ms-buy__qty{flex:0 0 auto;}
/*
 * `form.cart` is in the selector to outweigh the button block further down,
 * whose `margin:0 0 10px` would otherwise survive into the row and lift the
 * button ten pixels clear of the stepper it is supposed to line up with.
 */
.ms-pdp form.cart .ms-buy__row .single_add_to_cart_button,
.ms-pdp form.cart .ms-buy__row .button{
  flex:1 1 150px;width:auto;margin:0;
}

/* Sold individually: WooCommerce hides its own stepper, so the row has one
   column and the button simply takes the panel. */
.ms-buy__row--noqty{display:block;}

/*
 * WooCommerce's own stylesheet sets margin:0 4px 0 0 on this element at
 * .woocommerce div.product form.cart div.quantity, which outweighs a plain
 * .ms-pdp .quantity, so the gap is claimed at matching specificity. Without
 * the first selector the stepper sits flush against the buy buttons.
 */
.woocommerce div.product form.cart div.quantity,
.ms-pdp form.cart div.quantity,
.ms-pdp .quantity{
  display:inline-flex;align-items:stretch;
  height:56px;
  border:1px solid var(--ms-border);
  border-radius:var(--ms-radius-buy);
  overflow:hidden;
  margin:0;
  transition:border-color var(--ms-t) var(--ms-ease);
}
.ms-pdp .quantity:focus-within{border-color:var(--ms-ink);}
.ms-pdp .quantity .qty,
.ms-pdp .qty{
  width:46px;min-height:0;height:auto;align-self:stretch;text-align:center;
  padding:0;border:0;background:transparent;
  font-size:var(--ms-fs-sm);
  font-variant-numeric:tabular-nums;
  -moz-appearance:textfield;appearance:textfield;
}
.ms-pdp .qty:focus{outline:none;}
.ms-pdp .qty::-webkit-outer-spin-button,
.ms-pdp .qty::-webkit-inner-spin-button{-webkit-appearance:none;margin:0;}
/*
 * The stepper buttons take the full height of the pill. base.css gives
 * .ms-qty__btn a fixed 32px square for the cart page, and a fixed cross size
 * is exactly what stops `align-items:stretch` from doing its job here: the
 * buttons stayed 32px inside a 48px row and both icons sat eight pixels above
 * the number they belonged to. Height is handed back to the flex line.
 */
.ms-pdp .ms-qty__btn{
  width:42px;height:auto;align-self:stretch;
  padding:0;border:0;background:transparent;cursor:pointer;color:var(--ms-ink);
  display:flex;align-items:center;justify-content:center;
  transition:background var(--ms-t) var(--ms-ease),color var(--ms-t) var(--ms-ease);
}
.ms-pdp .ms-qty__btn:hover{background:var(--ms-sand);}
/* Dimmed, not erased. A disabled control the customer cannot see at all
   reads as a broken stepper rather than one that has hit its floor. */
.ms-pdp .ms-qty__btn:disabled{opacity:.3;cursor:not-allowed;background:transparent;}

/* ---------------------------------------------------- The two calls to action */
.ms-pdp form.cart .button,
.ms-pdp .single_add_to_cart_button,
.ms-pdp .ms-buynow{
  display:flex;align-items:center;justify-content:center;gap:10px;
  width:100%;min-height:56px;padding:0 24px;margin:0 0 10px;
  font-family:var(--ms-font-body);
  font-size:.75rem;font-weight:500;
  letter-spacing:var(--ms-track-btn);text-transform:uppercase;
  border:1px solid var(--ms-ink);border-radius:var(--ms-radius-buy);
  background:var(--ms-ink);color:var(--ms-cream);
  cursor:pointer;text-align:center;
  transition:background var(--ms-t) var(--ms-ease),color var(--ms-t) var(--ms-ease),border-color var(--ms-t) var(--ms-ease);
}
.ms-pdp form.cart .button:hover,
.ms-pdp .single_add_to_cart_button:hover{background:var(--ms-ink-hover);border-color:var(--ms-ink-hover);}

/*
 * Buy now is deliberately outlined rather than filled. Two solid buttons of
 * the same size read as one indecisive choice; the gold hairline keeps the
 * brand accent while leaving add to bag the obvious primary action.
 */
.ms-pdp .ms-buynow{
  min-height:50px;margin-bottom:0;
  background:transparent;color:var(--ms-gold-ink);
  border-color:var(--ms-gold-line);
  font-weight:500;
}
.ms-pdp .ms-buynow:hover{
  background:var(--ms-gold);color:var(--ms-ink);border-color:var(--ms-gold);
}

/*
 * A disabled add to bag, which is what an out of stock variation produces.
 * WooCommerce styles this state at .woocommerce button.button.alt.disabled and
 * paints it its own purple, so the selector below carries enough weight to win:
 * the button stays the brand's black and simply dims.
 */
.ms-pdp form.cart .button:disabled,
.ms-pdp form.cart .button.disabled,
.ms-pdp form.cart button.button.alt.disabled,
.ms-pdp form.cart button.button.alt:disabled,
.ms-pdp form.cart button.button.alt.disabled:hover{
  background:var(--ms-ink);border-color:var(--ms-ink);color:var(--ms-cream);
  opacity:.34;cursor:not-allowed;
}
/* Buy now cannot outlive add to bag: the same variation is unavailable. */
.ms-pdp .ms-buynow[disabled],
.ms-pdp .ms-buynow:disabled{
  opacity:.34;cursor:not-allowed;
  background:transparent;color:var(--ms-gold-ink);border-color:var(--ms-gold-line);
}

/* Feedback while the add is in flight and once it lands. */
.ms-pdp .single_add_to_cart_button.is-busy{
  opacity:.72;pointer-events:none;
  background:var(--ms-ink);color:var(--ms-cream);
}
.ms-pdp .single_add_to_cart_button.is-done{
  background:var(--ms-earth);color:var(--ms-white);border-color:var(--ms-earth);
}
.ms-pdp .woocommerce-variation-add-to-cart{display:block;}
.ms-pdp .stock.out-of-stock{
  color:var(--ms-sale);font-size:var(--ms-fs-sm);margin:0 0 14px;
}

/* ------------------------------------------------------------ Panel actions */
.ms-pdp__actions{
  display:flex;align-items:center;gap:26px;flex-wrap:wrap;
  margin-top:22px;padding-top:20px;
  border-top:var(--ms-hairline);
}
.ms-pdp__act{
  display:inline-flex;align-items:center;gap:8px;
  background:none;border:0;padding:0;cursor:pointer;
  font-family:var(--ms-font-body);font-size:var(--ms-fs-xs);
  color:var(--ms-muted);
  transition:color var(--ms-t) var(--ms-ease);
}
.ms-pdp__act:hover{color:var(--ms-ink);}
.ms-pdp__act svg{transition:transform var(--ms-t) var(--ms-ease);}
.ms-pdp__act:hover svg{transform:scale(1.12);}
.ms-pdp__wish.is-active{color:var(--ms-sale);}
.ms-pdp__wish.is-active svg{fill:currentColor;}
.ms-pdp__help:hover{color:var(--ms-wa-green-dark);}

/* ==========================================================================
   5b. Share panel
   --------------------------------------------------------------------------
   Opened by the Share control in the row above. A centred panel rather than a
   drawer: it is a short list read once and dismissed, and the drawer language
   on this site belongs to the bag and the menu.

   It sits outside .ms-pdp__panel in the markup because that column is
   position:sticky on desktop, which creates a stacking context a descendant
   with position:fixed cannot escape - nested there, the scrim would have
   covered the column and nothing else.
   ========================================================================== */
.ms-share{position:fixed;inset:0;z-index:1250;}
.ms-share[hidden]{display:none;}
.ms-share__scrim{
  position:absolute;inset:0;
  background:rgba(21,18,14,.46);
  opacity:0;transition:opacity var(--ms-t) var(--ms-ease);
}
.ms-share.is-open .ms-share__scrim{opacity:1;}
.ms-share__panel{
  position:absolute;left:50%;top:50%;
  transform:translate(-50%,-48%);
  width:min(420px,calc(100vw - 32px));
  max-height:calc(100dvh - 48px);overflow-y:auto;
  background:var(--ms-surface);
  border:var(--ms-hairline);
  border-radius:var(--ms-radius-media);
  box-shadow:0 24px 60px rgba(13,13,13,.26);
  padding:clamp(20px,2.4vw,26px);
  opacity:0;
  transition:opacity var(--ms-t) var(--ms-ease),transform var(--ms-t) var(--ms-ease);
}
.ms-share.is-open .ms-share__panel{opacity:1;transform:translate(-50%,-50%);}
@media (prefers-reduced-motion:reduce){
  .ms-share__scrim,.ms-share__panel{transition:none;}
  .ms-share__panel{transform:translate(-50%,-50%);}
}

.ms-share__head{
  display:flex;align-items:center;justify-content:space-between;gap:12px;
  margin-bottom:4px;
}
.ms-share__title{
  margin:0;font-family:var(--ms-font-heading);
  font-size:1.25rem;font-weight:500;color:var(--ms-ink);
}
.ms-share__close{
  flex:0 0 auto;width:34px;height:34px;
  display:grid;place-items:center;
  background:none;border:0;padding:0;cursor:pointer;
  color:var(--ms-muted);border-radius:50%;
  transition:color var(--ms-t) var(--ms-ease),background var(--ms-t) var(--ms-ease);
}
.ms-share__close:hover{color:var(--ms-ink);background:var(--ms-cream);}
.ms-share__product{
  margin:0 0 16px;max-width:none;
  font-size:var(--ms-fs-xs);color:var(--ms-muted);line-height:1.5;
}

/* The system share sheet, shown only where the browser has one. */
.ms-share__native{
  display:flex;align-items:center;justify-content:center;gap:9px;
  width:100%;min-height:46px;margin:0 0 16px;
  background:var(--ms-ink);color:var(--ms-cream);
  border:0;border-radius:var(--ms-radius-buy);cursor:pointer;
  font-family:var(--ms-font-body);font-size:var(--ms-fs-xs);font-weight:500;
  letter-spacing:var(--ms-track-btn);text-transform:uppercase;
  transition:opacity var(--ms-t) var(--ms-ease);
}
.ms-share__native:hover{opacity:.88;}
.ms-share__native[hidden]{display:none;}

.ms-share__list{
  list-style:none;margin:0 0 18px;padding:0;
  display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px;
}
.ms-share__net{
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;
  min-height:84px;padding:12px 6px;
  border:var(--ms-hairline);border-radius:var(--ms-radius-media);
  color:var(--ms-muted);text-align:center;
  transition:border-color var(--ms-t) var(--ms-ease),color var(--ms-t) var(--ms-ease),background var(--ms-t) var(--ms-ease);
}
.ms-share__net:hover,.ms-share__net:focus-visible{
  border-color:var(--ms-gold-line);color:var(--ms-ink);background:var(--ms-cream);
}
.ms-share__mark{display:grid;place-items:center;width:34px;height:34px;}
.ms-share__net-label{font-size:var(--ms-fs-micro);letter-spacing:.06em;}
/* Each mark in its own colour on hover, so the row reads as the networks it
   is rather than as six grey glyphs. */
.ms-share__net--whatsapp:hover .ms-share__mark{color:var(--ms-wa-green-dark);}
.ms-share__net--facebook:hover .ms-share__mark{color:#1877F2;}
.ms-share__net--x:hover .ms-share__mark{color:var(--ms-ink);}
.ms-share__net--pinterest:hover .ms-share__mark{color:#BD081C;}
.ms-share__net--telegram:hover .ms-share__mark{color:#229ED9;}

.ms-share__copy{
  display:flex;align-items:stretch;gap:8px;
  padding-top:16px;border-top:var(--ms-hairline);
}
.ms-share__url{
  flex:1 1 auto;min-width:0;min-height:44px;
  border-radius:var(--ms-radius-buy);
  font-size:var(--ms-fs-xs);color:var(--ms-muted);
  text-overflow:ellipsis;
}
.ms-share__copybtn{
  flex:0 0 auto;
  display:inline-flex;align-items:center;gap:7px;
  min-height:44px;padding:0 15px;
  background:var(--ms-cream);border:var(--ms-hairline);
  border-radius:var(--ms-radius-buy);cursor:pointer;
  font-family:var(--ms-font-body);font-size:var(--ms-fs-xs);
  color:var(--ms-ink);white-space:nowrap;
  transition:border-color var(--ms-t) var(--ms-ease),color var(--ms-t) var(--ms-ease);
}
.ms-share__copybtn:hover{border-color:var(--ms-gold-line);}
.ms-share__copybtn.is-done{color:var(--ms-earth);border-color:var(--ms-gold-line);}

@media (max-width:380px){
  .ms-share__list{grid-template-columns:repeat(2,minmax(0,1fr));}
}

/* ==========================================================================
   6. Purchase reassurance
   ========================================================================== */
.ms-assure{
  border-top:var(--ms-hairline);
  border-bottom:var(--ms-hairline);
}
.ms-assure__list{
  display:grid;
  grid-template-columns:repeat(2,minmax(0,1fr));
}
@media (min-width:860px){
  .ms-assure__list[data-count="4"]{grid-template-columns:repeat(4,minmax(0,1fr));}
  .ms-assure__list[data-count="3"]{grid-template-columns:repeat(3,minmax(0,1fr));}
}
.ms-assure__item{min-width:0;}

/* Hairline dividers between the points rather than boxes around them. */
.ms-assure__item + .ms-assure__item{box-shadow:inset 1px 0 0 var(--ms-border);}
@media (min-width:641px) and (max-width:859px){
  .ms-assure__list > .ms-assure__item:nth-child(odd){box-shadow:none;}
  .ms-assure__list > .ms-assure__item:nth-child(n+3){box-shadow:inset 1px 0 0 var(--ms-border),inset 0 1px 0 var(--ms-border);}
  .ms-assure__list > .ms-assure__item:nth-child(odd):nth-child(n+3){box-shadow:inset 0 1px 0 var(--ms-border);}
}

.ms-assure__inner{
  display:flex;align-items:center;gap:13px;
  padding:20px clamp(10px,1.6vw,22px);
  min-width:0;height:100%;
}
/* The outer edges sit flush with the measure, so the band lines up with the
   hero above it instead of looking inset by its own padding. */
.ms-assure__item:first-child .ms-assure__inner{padding-left:0;}
.ms-assure__item:last-child .ms-assure__inner{padding-right:0;}
@media (min-width:641px) and (max-width:859px){
  .ms-assure__list > .ms-assure__item:nth-child(odd) .ms-assure__inner{padding-left:0;}
  .ms-assure__list > .ms-assure__item:nth-child(even) .ms-assure__inner{padding-right:0;}
}
/*
 * On a phone the two column grid forces almost every label to wrap, and the
 * hairlines turn four short statements into four small boxes. One point per
 * row with no dividers reads as a list instead. The two column rules above
 * are held off this width rather than overridden, so they stay legible.
 */
@media (max-width:640px){
  .ms-assure__list{grid-template-columns:minmax(0,1fr);}
  .ms-assure__item + .ms-assure__item{box-shadow:none;}
  .ms-assure__inner{padding:15px 0;}
}
.ms-assure__icon{
  flex:0 0 auto;width:38px;height:38px;border-radius:50%;
  display:flex;align-items:center;justify-content:center;
  border:1px solid var(--ms-gold-line);
  color:var(--ms-earth);
  transition:background var(--ms-t) var(--ms-ease),border-color var(--ms-t) var(--ms-ease);
}
.ms-assure__text{display:flex;flex-direction:column;gap:3px;min-width:0;}
.ms-assure__title{
  font-size:var(--ms-fs-xs);font-weight:500;color:var(--ms-ink);line-height:1.3;
}
.ms-assure__copy{
  font-size:var(--ms-fs-micro);color:var(--ms-muted);line-height:1.4;
}
a.ms-assure__inner:hover .ms-assure__icon{
  background:var(--ms-gold-soft);border-color:var(--ms-gold);
}
a.ms-assure__inner:hover .ms-assure__title{color:var(--ms-gold-ink);}

/* ==========================================================================
   7. Product information
   ========================================================================== */
.ms-info{
  background:var(--ms-surface);
  padding-block:var(--pdp-band);
}
.ms-info__head{margin-bottom:clamp(26px,3vw,42px);}
.ms-info__head .ms-eyebrow{margin-bottom:10px;}
.ms-info__title{
  font-size:clamp(1.5rem,1.2rem + 1.1vw,2.125rem);
  font-weight:400;margin:0;
}

.ms-info__grid{
  display:grid;grid-template-columns:1fr;
  gap:clamp(32px,4vw,64px);
  align-items:start;
}
@media (min-width:960px){
  .ms-info__grid{grid-template-columns:minmax(0,1fr) minmax(272px,380px);}
  /* No specification data means no second column, so the prose takes a
     comfortable measure instead of stretching to fill the gap. */
  .ms-info__grid--single{grid-template-columns:minmax(0,1fr);}
  .ms-info__grid--single .ms-info__main{max-width:76ch;}
}
.ms-info__main{min-width:0;}

/* --------------------------------------------------------------- Tabs */
.ms-tabs__list{
  display:flex;gap:clamp(24px,3vw,44px);
  border-bottom:1px solid var(--ms-border);
  overflow-x:auto;scrollbar-width:none;
}
.ms-tabs__list::-webkit-scrollbar{display:none;}
.ms-tabs__tab{
  flex:0 0 auto;
  background:none;border:0;padding:0 0 16px;cursor:pointer;
  font-family:var(--ms-font-body);
  font-size:var(--ms-fs-xs);font-weight:500;
  letter-spacing:.11em;text-transform:uppercase;
  color:var(--ms-muted);
  border-bottom:2px solid transparent;margin-bottom:-1px;
  transition:color var(--ms-t) var(--ms-ease),border-color var(--ms-t) var(--ms-ease);
}
.ms-tabs__tab:hover{color:var(--ms-ink);}
/*
 * The selected tab carries weight as well as a rule under it. Colour alone was
 * doing all the work, and at this size the difference between the muted and the
 * ink greys is not enough to say which panel you are reading.
 */
.ms-tabs__tab.is-on{
  color:var(--ms-ink);font-weight:700;
  border-bottom-color:var(--ms-ink);
}
.ms-tabs__tab:focus-visible{outline:2px solid var(--ms-focus);outline-offset:3px;}
/* Reserves the bold width so the strip does not jump when the tab changes. */
.ms-tabs__tab::after{
  content:attr(data-label);
  display:block;height:0;overflow:hidden;visibility:hidden;
  font-weight:700;
}

/* Content driven height, never a fixed one. */
.ms-tabs__panel{padding-top:clamp(24px,3vw,34px);}
.ms-tabs__panel[hidden]{display:none;}
.ms-tabs__panel.is-on{animation:ms-tabfade var(--ms-t) var(--ms-ease);}
@keyframes ms-tabfade{from{opacity:0;transform:translateY(4px);}to{opacity:1;transform:none;}}
@media (prefers-reduced-motion:reduce){
  .ms-tabs__panel.is-on{animation:none;}
}

/*
 * Prose inside a tab.
 *
 * .ms-prose is defined in pages.css, and pages.css deliberately never loads on
 * a product page, so every rule the shipping and returns copy depends on has to
 * be restated here. Without them the panel renders as unspaced blocks: bullets
 * with no markers, a policy link welded to the last list item, and the callout
 * reading as another loose paragraph.
 */
.ms-tabs__panel .ms-prose{
  padding-bottom:0;
  font-size:var(--ms-fs-body);
  line-height:1.75;
  color:var(--ms-ink);
}
.ms-tabs__panel .ms-prose > * + *{margin-top:1.2em;}
.ms-tabs__panel .ms-prose > *:first-child{margin-top:0;}
.ms-tabs__panel .ms-prose > *:last-child{margin-bottom:0;}
.ms-tabs__panel .ms-prose p{max-width:64ch;margin-bottom:0;}
.ms-tabs__panel .ms-prose p + p{margin-top:1em;}

.ms-tabs__panel .ms-prose h3{
  font-family:var(--ms-font-body);font-weight:600;letter-spacing:-.005em;
  font-size:1.1875rem;font-weight:500;
  letter-spacing:0;text-transform:none;color:var(--ms-ink);
  margin-top:2.1em;margin-bottom:.75em;
}
.ms-tabs__panel .ms-prose > h3:first-child{margin-top:0;}
/* The margin above is on the heading, so the pair must not double it. */
.ms-tabs__panel .ms-prose h3 + *{margin-top:0;}

.ms-tabs__panel .ms-prose ul,
.ms-tabs__panel .ms-prose ol{padding-left:1.3em;max-width:64ch;}
.ms-tabs__panel .ms-prose ul{list-style:disc;}
.ms-tabs__panel .ms-prose ol{list-style:decimal;}
.ms-tabs__panel .ms-prose li{margin:0;}
.ms-tabs__panel .ms-prose li + li{margin-top:.55em;}
.ms-tabs__panel .ms-prose li::marker{color:var(--ms-gold);}

.ms-tabs__panel .ms-prose a,
.ms-tabs__panel .ms-prose .ms-link{
  color:var(--ms-gold-ink);
  text-decoration:underline;text-underline-offset:.22em;
  text-decoration-thickness:1px;text-decoration-color:var(--ms-gold-line);
  transition:color var(--ms-t) var(--ms-ease),text-decoration-color var(--ms-t) var(--ms-ease);
}
.ms-tabs__panel .ms-prose a:hover,
.ms-tabs__panel .ms-prose .ms-link:hover{
  color:var(--ms-ink);text-decoration-color:var(--ms-ink);
}
.ms-tabs__panel .ms-prose strong{font-weight:600;}

/* The part of the returns policy a customer must not skim past. */
.ms-tabs__panel .ms-callout{
  margin-top:1.6em;padding:22px 24px;
  background:var(--ms-cream);
  border-left:2px solid var(--ms-gold);
  max-width:64ch;
}
.ms-tabs__panel .ms-callout__title{
  font-family:var(--ms-font-body);
  font-size:var(--ms-fs-micro);font-weight:600;
  letter-spacing:var(--ms-track-micro);text-transform:uppercase;
  color:var(--ms-gold-ink);
  margin:0 0 9px;max-width:none;
}
.ms-tabs__panel .ms-callout p{margin:0;max-width:none;}
.ms-tabs__panel .ms-callout p + p{margin-top:.7em;}

/* --------------------------------------------------- Specification panel */
.ms-info__aside{min-width:0;}
.ms-spec{
  background:var(--ms-cream);
  padding:clamp(22px,2.4vw,30px);
}
.ms-spec__title{
  font-family:var(--ms-font-body);
  font-size:var(--ms-fs-micro);font-weight:600;
  letter-spacing:var(--ms-track-micro);text-transform:uppercase;
  color:var(--ms-ink);
  margin:0 0 8px;
}
.ms-spec__list{margin:0;}
.ms-spec__row{
  display:grid;grid-template-columns:minmax(84px,38%) minmax(0,1fr);
  gap:14px;
  padding:13px 0;
  border-bottom:var(--ms-hairline);
}
.ms-spec__row:last-child{border-bottom:0;padding-bottom:0;}
.ms-spec__row dt{
  font-size:var(--ms-fs-micro);color:var(--ms-muted);
  letter-spacing:.03em;line-height:1.5;
}
.ms-spec__row dd{
  margin:0;font-size:var(--ms-fs-xs);color:var(--ms-ink);line-height:1.5;
  overflow-wrap:anywhere;
}
.ms-spec__row dd p{margin:0;max-width:none;}

/* ==========================================================================
   8. Customer reviews
   ========================================================================== */
.ms-reviews{
  padding-block:var(--pdp-band);
  scroll-margin-top:calc(var(--ms-header-h-compact) + 16px);
}
.ms-reviews__head{margin-bottom:clamp(24px,3vw,36px);}
.ms-reviews__head .ms-eyebrow{margin-bottom:10px;}
.ms-reviews__title{
  font-size:clamp(1.5rem,1.2rem + 1.1vw,2.125rem);
  font-weight:400;margin:0;
}

/* ------------------------------------------------------------- Summary */
.ms-revsum{
  display:grid;grid-template-columns:1fr;
  gap:clamp(26px,3vw,48px);
  padding-block:clamp(26px,3vw,38px);
  border-top:var(--ms-hairline);
  border-bottom:var(--ms-hairline);
  margin-bottom:clamp(30px,4vw,48px);
}
@media (min-width:820px){
  .ms-revsum{
    grid-template-columns:minmax(150px,auto) minmax(0,1fr) minmax(0,auto);
    align-items:center;
    gap:clamp(32px,5vw,72px);
  }
  .ms-revsum--empty{grid-template-columns:minmax(0,1fr) auto;}
}

.ms-revsum__score{display:flex;flex-direction:column;gap:8px;align-items:flex-start;}
.ms-revsum__avg{
  font-family:var(--ms-font-heading);
  font-size:clamp(2.75rem,2.2rem + 2vw,3.75rem);
  font-weight:500;line-height:.95;margin:0;
  font-variant-numeric:tabular-nums;
  letter-spacing:-.02em;
}
.ms-revsum__count,
.ms-revsum__none,
.ms-revsum__lead,
.ms-revsum__gate{margin:0;}
.ms-revsum__count{font-size:var(--ms-fs-xs);color:var(--ms-muted);}
.ms-revsum__none{
  font-family:var(--ms-font-heading);font-size:1.25rem;font-weight:500;margin-top:2px;
}
.ms-revsum__lead{font-size:var(--ms-fs-sm);color:var(--ms-muted);max-width:52ch;line-height:1.7;}
.ms-revsum__gate{font-size:var(--ms-fs-xs);color:var(--ms-muted);max-width:34ch;}

/* Distribution bars */
.ms-revsum__bars{display:flex;flex-direction:column;gap:7px;min-width:0;}
.ms-revbar{
  display:grid;grid-template-columns:34px minmax(0,1fr) 30px;
  align-items:center;gap:12px;
}
.ms-revbar__label{
  display:inline-flex;align-items:center;gap:3px;
  font-size:var(--ms-fs-micro);color:var(--ms-muted);
  font-variant-numeric:tabular-nums;
}
.ms-revbar__label svg{color:var(--ms-gold);fill:currentColor;stroke-width:1.1;}
.ms-revbar__track{
  display:block;height:5px;background:var(--ms-sand);overflow:hidden;
}
.ms-revbar__fill{
  display:block;height:100%;width:var(--pct,0%);
  background:var(--ms-gold);
  transform-origin:left center;
}
.ms-revbar__n{
  font-size:var(--ms-fs-micro);color:var(--ms-muted);text-align:right;
  font-variant-numeric:tabular-nums;
}

.ms-revsum__cta{display:flex;justify-content:flex-start;}
@media (min-width:820px){ .ms-revsum__cta{justify-content:flex-end;} }

/*
 * No reviews yet. Same two part shape as the populated summary, statement on
 * the left and the invitation on the right, so the section keeps its rhythm
 * whichever state it is in. The form folds away behind the button, which is
 * what keeps this state from becoming a tall form under two lines of text.
 */
/* The one gap between the summary and the form is declared here, so there is
   a single place to tune it. */
.ms-revsum--none{align-items:center;margin-bottom:clamp(28px,3vw,40px);}
@media (min-width:820px){
  .ms-revsum--none{grid-template-columns:minmax(0,1fr) minmax(0,auto);}
}
/*
 * One gap between the summary and the form, not three. The summary's own
 * bottom margin, the wrapper's column gap and a margin on the form were all
 * landing in the same place and opening 134px of nothing.
 */
.ms-reviews--empty .ms-revform{margin-top:0;}

/* -------------------------------------------------------------- The list */
.ms-revwrap{display:flex;flex-direction:column;gap:clamp(30px,4vw,48px);}
/* A list with no reviews in it is removed from the flow, gap and all. */
.ms-revlist.is-empty{display:none;}

#ms-reviews .commentlist{
  list-style:none;padding:0;margin:0;
  display:grid;gap:16px;
  grid-template-columns:1fr;
}
@media (min-width:700px){
  #ms-reviews .commentlist{grid-template-columns:repeat(2,minmax(0,1fr));}
}
@media (min-width:1080px){
  #ms-reviews .commentlist{grid-template-columns:repeat(3,minmax(0,1fr));}
}
#ms-reviews .commentlist > li{display:flex;padding:0;border:0;margin:0;}
#ms-reviews .commentlist .children{display:none;}

.ms-review__card{
  flex:1 1 auto;display:flex;flex-direction:column;gap:12px;
  background:var(--ms-surface);
  border:1px solid var(--ms-border);
  padding:clamp(20px,2vw,26px);
  transition:border-color var(--ms-t) var(--ms-ease);
}
.ms-review__card:hover{border-color:var(--ms-beige-deep);}
.ms-review__top{
  display:flex;align-items:center;justify-content:space-between;
  gap:12px;flex-wrap:wrap;
}
.ms-review__verified{
  display:inline-flex;align-items:center;gap:5px;
  font-size:var(--ms-fs-micro);color:var(--ms-earth);
  letter-spacing:.02em;
}
.ms-review__verified svg{stroke-width:1.9;}
.ms-review__text{
  font-size:var(--ms-fs-sm);line-height:1.72;color:var(--ms-ink-80);
  flex:1 1 auto;
}
.ms-review__text p{margin:0;max-width:none;}
.ms-review__text p + p{margin-top:.7em;}
.ms-review__meta{
  display:flex;align-items:center;gap:8px;flex-wrap:wrap;
  padding-top:12px;border-top:var(--ms-hairline);
  font-size:var(--ms-fs-micro);color:var(--ms-muted);
}
.ms-review__author{color:var(--ms-ink);font-weight:500;}
.ms-review__sep{color:var(--ms-border);}
.ms-review__pending{font-size:var(--ms-fs-micro);color:var(--ms-earth);margin:0;}

.ms-revlist__pages{margin-top:26px;}
.ms-revlist__pages ul{display:flex;gap:6px;list-style:none;padding:0;margin:0;}
.ms-revlist__pages a,
.ms-revlist__pages span{
  display:flex;align-items:center;justify-content:center;
  min-width:38px;height:38px;padding:0 10px;
  border:1px solid var(--ms-border);font-size:var(--ms-fs-xs);
}
.ms-revlist__pages .current{background:var(--ms-ink);color:var(--ms-cream);border-color:var(--ms-ink);}

/* -------------------------------------------------------------- The form */
.ms-revform{
  background:var(--ms-surface);
  border:1px solid var(--ms-border);
  padding:clamp(26px,3vw,44px);
  max-width:820px;
  scroll-margin-top:calc(var(--ms-header-h-compact) + 20px);
}
.ms-revform.is-collapsed{display:none;}
.ms-revform__gate{
  font-size:var(--ms-fs-sm);color:var(--ms-muted);
  padding:20px 0 0;border-top:var(--ms-hairline);max-width:60ch;
}
/*
 * WooCommerce zeroes this at .woocommerce #reviews h3, which carries an id and
 * an element name and so outranks a plain class. Matched at two ids here, or
 * the form heading sits directly on top of the first field label.
 */
#ms-reviews #respond .ms-revform__title,
#ms-reviews #respond .comment-reply-title,
#ms-reviews .comment-reply-title,
.ms-revform__title{
  display:block;font-family:var(--ms-font-heading);
  font-size:1.375rem;font-weight:500;line-height:1.2;
  margin:0 0 26px;
}
#ms-reviews .comment-form{display:grid;gap:18px;}
@media (min-width:640px){
  #ms-reviews .comment-form{grid-template-columns:repeat(2,minmax(0,1fr));}
  #ms-reviews .comment-form > *{grid-column:1 / -1;}
  #ms-reviews .comment-form-author{grid-column:1 / 2;}
  #ms-reviews .comment-form-email{grid-column:2 / 3;}
}
#ms-reviews .comment-form p{margin:0;max-width:none;}
#ms-reviews .ms-field label,
#ms-reviews .ms-field__label{
  display:block;font-size:var(--ms-fs-micro);font-weight:500;
  letter-spacing:var(--ms-track-micro);text-transform:uppercase;
  color:var(--ms-muted);margin-bottom:9px;
}
#ms-reviews .ms-field__hint{
  display:block;margin-top:7px;
  font-size:var(--ms-fs-micro);color:var(--ms-muted);
}
#ms-reviews .required{color:var(--ms-sale);}

#ms-reviews input[type="text"],
#ms-reviews input[type="email"],
#ms-reviews textarea,
#ms-reviews select#rating{
  width:100%;
  min-height:48px;padding:12px 14px;
  background:var(--ms-cream);
  border:1px solid var(--ms-border);border-radius:var(--ms-radius-btn);
  font-family:var(--ms-font-body);font-size:var(--ms-fs-sm);color:var(--ms-ink);
  transition:border-color var(--ms-t) var(--ms-ease),background var(--ms-t) var(--ms-ease);
}
#ms-reviews textarea{min-height:132px;resize:vertical;line-height:1.65;}
#ms-reviews input:focus,
#ms-reviews textarea:focus,
#ms-reviews select#rating:focus{
  outline:none;border-color:var(--ms-ink);background:var(--ms-surface);
}
#ms-reviews input::placeholder,
#ms-reviews textarea::placeholder{color:var(--ms-muted);opacity:.7;}

/*
 * WooCommerce swaps the select for this star row from its own script. Drawn
 * larger and in a tone that actually reads: at the border colour the rating,
 * which is the one field a review cannot be posted without, was the palest
 * thing on the form.
 */
#ms-reviews p.stars{margin:0;display:flex;gap:4px;}
#ms-reviews p.stars a{
  position:relative;display:inline-block;width:1.35em;height:1.35em;
  font-size:1.5rem;
  text-indent:-999em;color:var(--ms-gold);text-decoration:none;
}
#ms-reviews p.stars a:focus-visible{outline:2px solid var(--ms-focus);outline-offset:2px;}
#ms-reviews p.stars a::before{
  content:"\2606";
  position:absolute;inset:0;
  text-indent:0;font-size:1em;line-height:1.35;
  text-align:center;
  color:var(--ms-beige-deep);
  transition:color var(--ms-t-fast) var(--ms-ease);
}
#ms-reviews p.stars:hover a::before,
#ms-reviews p.stars.selected a.active::before,
#ms-reviews p.stars.selected a:not(.active)::before{content:"\2605";color:var(--ms-gold);}
#ms-reviews p.stars a:hover ~ a::before{content:"\2606";color:var(--ms-beige-deep);}
#ms-reviews p.stars.selected a.active ~ a::before{content:"\2606";color:var(--ms-beige-deep);}

#ms-reviews .form-submit{margin:0;}
/*
 * WooCommerce's own stylesheet still loads on product pages and styles this
 * button at .woocommerce #respond input#submit, which carries an id and beats
 * any plain class selector. The id is matched here so the submit button is not
 * the one grey control on an otherwise finished page.
 */
#ms-reviews #respond input#submit,
#ms-reviews input#submit,
#ms-reviews .comment-form .submit,
.ms-revform__submit{
  display:inline-flex;align-items:center;justify-content:center;
  width:auto;min-height:52px;padding:0 34px;
  font-family:var(--ms-font-body);
  font-size:.75rem;font-weight:500;line-height:1;
  letter-spacing:var(--ms-track-btn);text-transform:uppercase;
  background:var(--ms-ink);color:var(--ms-cream);
  border:1px solid var(--ms-ink);border-radius:var(--ms-radius-btn);cursor:pointer;
  transition:background var(--ms-t) var(--ms-ease),border-color var(--ms-t) var(--ms-ease);
}
#ms-reviews #respond input#submit:hover,
#ms-reviews input#submit:hover,
#ms-reviews .comment-form .submit:hover{
  background:var(--ms-ink-hover);border-color:var(--ms-ink-hover);color:var(--ms-cream);
}
#ms-reviews .woocommerce-noreviews{color:var(--ms-muted);font-size:var(--ms-fs-sm);margin:0;}
#ms-reviews .comment-form-cookies-consent{display:flex;align-items:center;gap:10px;}
#ms-reviews .comment-form-cookies-consent label{margin:0;text-transform:none;letter-spacing:0;font-size:var(--ms-fs-xs);}

/* ==========================================================================
   9. Discovery: you may also like, recently viewed
   ========================================================================== */
.ms-related{
  padding-block:var(--pdp-band);
  background:var(--ms-sand);
}
.ms-related--alt{padding-bottom:var(--pdp-band-tight);}
.ms-related--last{
  padding-top:var(--pdp-band-tight);
  border-top:1px solid var(--ms-sand-deep);
}
.ms-related .ms-shead{margin-bottom:clamp(26px,3vw,40px);}

/*
 * A short row is centred rather than left hanging in an empty four column
 * grid. The card keeps exactly the width it would have had in a full row,
 * computed from the same gap .ms-grid uses, so nothing about the card itself
 * changes: only where the row sits.
 */
.ms-related .ms-grid[data-count="1"]{--n:1;}
.ms-related .ms-grid[data-count="2"]{--n:2;}
.ms-related .ms-grid[data-count="3"]{--n:3;}

@media (min-width:1024px){
  .ms-related .ms-grid[data-count="1"],
  .ms-related .ms-grid[data-count="2"],
  .ms-related .ms-grid[data-count="3"]{
    grid-template-columns:repeat(var(--n),minmax(0,calc((100% - 3 * clamp(12px,1.6vw,26px)) / 4)));
    justify-content:center;
  }
}
@media (min-width:640px) and (max-width:1023px){
  .ms-related .ms-grid[data-count="1"],
  .ms-related .ms-grid[data-count="2"]{
    grid-template-columns:repeat(var(--n),minmax(0,calc((100% - 2 * clamp(12px,1.6vw,26px)) / 3)));
    justify-content:center;
  }
}
@media (max-width:639px){
  .ms-related .ms-grid[data-count="1"]{
    grid-template-columns:minmax(0,calc((100% - clamp(12px,1.6vw,26px)) / 2));
    justify-content:center;
  }
}

/* ==========================================================================
   10. Sticky mobile buy bar
   ========================================================================== */
.ms-buybar{
  position:fixed;left:0;right:0;bottom:60px;z-index:875;
  display:flex;align-items:center;gap:14px;
  padding:11px 16px calc(11px + env(safe-area-inset-bottom));
  background:var(--ms-cream);
  border-top:var(--ms-hairline);
  box-shadow:0 -10px 30px rgba(21,18,14,.07);
  transform:translateY(130%);
  visibility:hidden;
  transition:transform var(--ms-t) var(--ms-ease),visibility 0s linear var(--ms-t);
}
.ms-buybar.is-visible{
  transform:translateY(0);
  visibility:visible;
  transition:transform var(--ms-t) var(--ms-ease),visibility 0s;
}
.ms-buybar__info{flex:1 1 auto;min-width:0;}
.ms-buybar__title{
  font-size:var(--ms-fs-micro);color:var(--ms-muted);line-height:1.3;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;margin:0;
}
.ms-buybar__price{
  /* The sticky bar is height constrained, so it does not take the page price
     size; one step up is all the bar can give without growing. */
  font-family:var(--ms-font-body);font-size:1.125rem;font-weight:600;margin:1px 0 0;
  line-height:1.2;
}
.ms-buybar__price .amount{font-variant-numeric:tabular-nums;}
.ms-buybar__price del{font-size:.75em;color:var(--ms-muted);margin-right:.3em;}
.ms-buybar__price ins{text-decoration:none;}
.ms-buybar__btn{flex:0 0 auto;min-width:142px;}
@media (min-width:1000px){ .ms-buybar{display:none;} }

/* ==========================================================================
   11. Small screens
   ========================================================================== */
@media (max-width:999px){
  .ms-pdp__hero{padding-top:6px;}
  .ms-pdp__title{max-width:none;}
  .ms-pdp__panelinner{padding-top:4px;}
  /* The buy bar overlaps the foot of the page, so the last band clears it. */
  .ms-related--last{padding-bottom:calc(var(--pdp-band) + 46px);}
}

@media (max-width:640px){
  /*
   * The page keeps the site gutter here rather than tightening its own. A
   * narrower one bought a little width for the copy and cost the alignment
   * with the header directly above it, which is the more valuable of the two.
   * The gallery still runs edge to edge, by pulling against that same gutter.
   */
  .ms-gallery{gap:8px;}
  .ms-gallery__stage{
    /* Edge to edge on a phone: the image is the product. */
    margin-inline:calc(var(--ms-gutter) * -1);
  }
  .ms-gallery__thumb{width:58px;}
  .ms-gallery__tools{right:10px;bottom:10px;}
  .ms-gallery__badges{top:10px;left:10px;}
  .ms-gallery__play{width:62px;height:62px;}
  .ms-pdp__actions{gap:18px;}
  .ms-revbar{grid-template-columns:30px minmax(0,1fr) 26px;gap:9px;}
  .ms-revsum__cta .ms-btn{width:100%;}
}

/* Comfortable targets on touch. */
@media (hover:none){
  .ms-pdp__act{min-height:44px;}
  .ms-gallery__thumb{min-height:44px;}
  /* The only control left on the photograph, so it is the one that has to be
     a finger's size rather than an icon's. */
  .ms-gallery__expand{width:44px;height:44px;}
}
