#MainContent {
  background-color: #F2F4F7;
}

.product__details-wrapper {
  margin-top: 0;
}
.product__details-container summary {
  align-items: center;
}
.product__details-container summary .icon-accordion {
  width: 24px;
  height: 24px;
}
.product__details-container summary .icon-accordion svg {
  width: 24px;
  height: 24px;
}
.product__details-container summary .accordion__title {
  line-height: 24px;
}
/* Product info */
product-info {
  display: block; /* custom elements default to inline; block for sane measurement */
}
.product__info-container > * + * {
  margin: 10px 0;
}
/* keep the title→price gap inside the pinned-header wrapper (they're no
   longer direct children of .product__info-container) */
.pdp-info-sticky-header > * + * {
  margin: 10px 0;
}
.product__info-container .product__info-description {
  max-width: 100%;
  overflow-x: auto;
}
@media screen and (min-width: 960px) {
  .product__column-sticky {
    display: block;
    position: sticky;
    top: 20px;
    z-index: 2;
  }

  /* product_image_pc_position */
  .product--left .product__info-wrapper {
    padding-left: 60px;
  }

  .product--left .product__media-wrapper {
    padding-right: 0px;
  }

  .product--right .product__info-wrapper {
    padding-right: 60px;
  }

  .product--right .product__media-wrapper {
    padding-left: 0px;
  }

  /* product_image_size */
  .product--large .product__media-wrapper {
    max-width: 66%;
    width: 66%;
  }

  .product--large .product__info-wrapper {
    max-width: 34%;
    width: 34%;
  }

  .product--medium .product__media-wrapper,
  .product--medium .product__info-wrapper {
    max-width: 50%;
    width: 50%;
  }

  .product--small .product__media-wrapper {
    max-width: 34%;
    width: 34%;
  }

  .product--small .product__info-wrapper {
    max-width: 66%;
    width: 66%;
  }
}
@media screen and (max-width: 959px) {
  .product__media-wrapper {
    padding: 0;
    max-width: calc(100% + 20px);
  }
}
/* Product form */
.product-form {
  display: block;
}
.product-form .product-form__error-message-wrapper:not([hidden]) {
  display: flex;
  align-items: center;
  margin-bottom: 10px;
  color: rgb(var(--color-discount-tag-background));
}
.product-form .product-form__error-message-wrapper:not([hidden]) .icon-error {
  margin-right: 5px;
}
.product-form .product-form__buttons > * {
  margin-bottom: 10px;
}
.product-form .product-form__buttons .pay-button-buy-now {
  overflow: unset;
}
/* Matched to .pdp-variant-label so the buy column has ONE label style. It was the odd
   one out: 14px against their 12px, no colour of its own, and floated, which is why it
   sat differently from the option labels directly above it. The float has to go with
   the rest or the label no longer sits on its own line at 12px. */
.quantity-input-label {
  display: block;
  font-size: 12px;
  font-weight: normal !important;
  color: #0A2749;
  letter-spacing: 0;
  margin-bottom: 6px;
}
/* Form Elements */
.product-form__input {
  flex: 0 0 100%;
  padding: 0;
  margin: 0 0 20px 0;
  max-width: 100%;
  min-width: fit-content;
  border: none;
}
variant-radios .product-form__input {
  margin-bottom: 10px;
}
variant-radios,
variant-selects,
.variant-selects {
  display: block;
}
fieldset.product-form__input .form__label {
  margin-bottom: 10px;
}
/* variant-radios */
.product-form__input input[type="radio"] {
  clip: rect(0, 0, 0, 0);
  overflow: hidden;
  position: absolute;
  height: 1px;
  width: 1px;
}
.product-form__input input[type="radio"] + label {
  border: var(--sku-selector-border-thickness) solid
    rgba(var(--color-text), var(--sku-selector-border-opacity));
  background-color: rgb(var(--color-page-background));
  color: rgba(var(--color-text));
  border-radius: var(--sku-selector-border-radius);
  display: inline-block;
  margin-right: 6px;
  padding: 7.5px 15px;
  text-align: center;
  cursor: pointer;
  position: relative;
  margin-bottom: 10px;
}
.product-form__input input[type="radio"] + label::before {
  content: "";
  position: absolute;
  top: 0px;
  left: 0px;
  width: 100%;
  height: 100%;
  border-radius: var(--sku-selector-border-radius);
  box-shadow: var(--sku-selector-shadow-offset-x)
    var(--sku-selector-shadow-offset-y) var(--sku-selector-shadow-blur)
    rgba(var(--color-text), var(--sku-selector-shadow-opacity));
  z-index: -1;
}
.product-form__input input[type="radio"] + label::after {
  content: "";
  width: calc(100% + 2px + var(--sku-selector-border-thickness) * 2);
  height: calc(100% + 2px + var(--sku-selector-border-thickness) * 2);
  position: absolute;
  top: calc(var(--sku-selector-border-thickness) * -1 - 1px);
  left: calc(var(--sku-selector-border-thickness) * -1 - 1px);
  border: 1px solid transparent;
  border-radius: var(--sku-selector-border-radius-outset);
}
.product-form__input input[type="radio"] + label:hover::after {
  border-color: rgba(var(--color-text), var(--sku-selector-border-opacity));
}
.product-form__input input[type="radio"]:checked + label {
  background-color: rgba(var(--color-button-background));
  color: rgba(var(--color-button-text));
}
.product-form__input input[type="radio"]:checked + label:hover::after {
  border-color: transparent;
}
.product-form__input input[type="radio"]:disabled + label {
  opacity: 0.25;
  cursor: not-allowed;
  text-decoration: line-through;
}
.product-form__input input[type="radio"]:disabled + label:hover::after {
  border-color: transparent;
}
/* variant-selects */
variant-selects option:disabled,
.variant-selects option:disabled {
  color: rgba(10, 39, 73, 0.3);
}
variant-selects .field::after,
variant-selects .field:hover::after,
variant-selects .field:focus::after,
variant-selects .field:focus-within::after,
.variant-selects .field::after,
.variant-selects .field:hover::after,
.variant-selects .field:focus::after,
.variant-selects .field:focus-within::after {
  border-color: rgba(var(--color-text));
}
.product-sell-info {
  margin-bottom: 0 !important;
}
.product-sell-info .product-sell-box {
  display: flex;
  align-items: center;
  margin-bottom: 16px;
}
.product-sell-info .product-sell-box:last-child {
  margin-bottom: 0;
}
.product-sell-info .product-sell-icon {
  width: 24px;
  height: 24px;
  display: flex;
  align-items: center;
  color: var(--color-text);
  stroke: currentColor;
  line-height: 1;
}
.product-sell-info .product-sell-icon svg {
  width: 100%;
}
@media screen and (max-width: 959px) {
  .product-sell-info .product-sell-icon {
    width: 20px;
    height: 20px;
  }
}
.product-sell-info .product-sell-text {
  margin-left: 16px;
  color: var(--color-text);
}
/* Product popup */
.product-popup-modal {
  box-sizing: border-box;
  opacity: 0;
  position: fixed;
  visibility: hidden;
  z-index: -1;
  margin: 0 auto;
  top: 0;
  left: 0;
  overflow: auto;
  width: 100%;
  background-color: rgba(var(--color-text), 0.3);
  height: 100%;
}
.product-popup-modal[open] {
  opacity: 1;
  visibility: visible;
  z-index: 101;
}
.product-popup-modal__content {
  border-radius: var(--menu-modal-border-radius);
  background-color: rgb(var(--color-page-background));
  overflow: auto;
  height: calc(100% - 120px);
  position: absolute;
  top: 60px;
  left: 50%;
  transform: translateX(-50%);
  width: 90%;
  max-width: 1200px;
  padding: 40px 60px 40px 40px;
  border-color: rgba(var(--color-text), var(--menu-modal-border-opacity));
  border-style: solid;
  border-width: var(--menu-modal-border-thickness);
  box-shadow: var(--menu-modal-shadow-offset-x)
    var(--menu-modal-shadow-offset-y) var(--menu-modal-shadow-blur)
    rgba(var(--color-text), var(--menu-modal-shadow-opacity));
}
@media screen and (max-width: 959px) {
  .product-popup-modal__content {
    padding: 20px 40px 20px 20px;
    width: 335px;
    height: 60%;
    max-height: 380px;
  }
}
.product-popup-modal__content img {
  max-width: 100%;
}
@media screen and (max-width: 959px) {
  .product-popup-modal__content table {
    display: block;
    max-width: fit-content;
    overflow-x: auto;
    white-space: nowrap;
    margin: 0;
  }
}
.product-popup-modal__content-info > * {
  height: auto;
  margin: 0 auto;
  max-width: 100%;
  width: 100%;
}
@media screen and (max-width: 959px) {
  .product-popup-modal__content-info > * {
    max-height: 100%;
  }
}
.product-popup-modal__toggle {
  background-color: rgb(var(--color-page-background));
  border: 1px solid rgba(var(--color-text), 0.05);
  border-radius: 50%;
  color: rgba(var(--color-text), 1);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  position: absolute;
  z-index: 2;
  top: 20px;
  right: 20px;
  padding: 14px;
  width: 40px;
}
@media screen and (max-width: 959px) {
  .product-popup-modal__toggle {
    top: 10px;
    right: 10px;
    padding: 9px;
    width: 30px;
  }
}
.product-popup-modal__toggle:hover {
  color: rgba(var(--color-text), 0.75);
}
.product__inventory {
  float: right;
  font-weight: 700;
  text-transform: uppercase;
  font-size: 13px;
  letter-spacing: 0;
  margin-bottom: 15px;
}

.product__inventory .low-stock,
.product__inventory .in-stock,
.product__inventory .out-stock {
  display: inline-flex;
  align-items: flex-start;
}
.product__inventory .low-stock::before,
.product__inventory .in-stock::before,
.product__inventory .out-stock::before {
  --icon-size: 10px;
  content: "";
  display: block;
  width: var(--icon-size);
  height: var(--icon-size);
  border-radius: 50%;
  background-color: currentColor;
  margin: calc((1em * var(--body-line-height) - var(--icon-size)) / 2) 0;
  margin-right: 8px;
  flex-shrink: 0;
  border: 1px solid #ffffff;
}
.product__inventory .low-stock::before {
  background-color: #fe9e0f;
  box-shadow: 0px 0px 2px #fe9e0f;
}
.product__inventory .in-stock::before {
  background-color: #35c08e;
  box-shadow: 0px 0px 2px #35c08e;
}
.product__inventory .out-stock::before {
  color: #f86140;
  box-shadow: 0px 0px 2px #f86140;
}

#Quantity-Form-main-product-info {
  clear: both;
}


/* ─── PDP two-column layout ──────────────────────────────────────────────────
   The page is two independent columns, each paired with the content that belongs
   beneath it:

     .pdp-col--media   cover image + thumbnails, then Product Info / specs / reviews
     .pdp-col--buy     price and Add to Cart, then the Buy Together card

   They were previously three siblings on one wrapping flex line (media, buy area,
   and a full-width block below). A wrapped line starts below the TALLEST item on
   the line, so the lower block had to wait for the buy area — leaving a gap under
   the thumbnails on option-heavy products, which got worse once the cover image was
   capped. Pairing the columns lets the left side flow straight on.

   Both columns stretch to the container height on purpose (no align-items here):
   .pdp-description-sticky and .pdp-additional-side are position: sticky, and a
   sticky element can only travel inside its own parent. Letting the wrappers stay
   full height keeps them pinning for the whole page rather than stopping early. */
.pdp-container {
  display: flex;
  flex-wrap: nowrap;
  flex-direction: column;
}

/* Stacked default. Must sit BEFORE the media queries below, which zero this margin
   on desktop — same specificity, so whichever comes last would win. */
.pdp-description {
  width: 100%;
  margin-top: 30px;
}

@media (min-width: 959px) {
  .pdp-container {
    flex-direction: row;
  }

  /* Both columns are flex containers, not plain blocks. Their children used to be
     flex items of .pdp-container, which gave each an independent formatting context;
     as children of a plain block wrapper their first child's top margin would collapse
     through instead, dropping the buy area ~10px below the image. */
  .pdp-col--media,
  .pdp-col--buy {
    display: flex;
    flex-direction: column;
  }

  .pdp-col--media {
    flex: 1;
    min-width: 0;
    max-width: 614px;
    margin-right: 50px;
  }

  .pdp-col--buy {
    flex: 0 0 350px;
    width: 350px;
  }

  /* Widths live on the wrappers now, so the blocks inside simply fill them. */
  .pdp-images,
  .pdp-additional-main,
  .pdp-description,
  .pdp-additional-side {
    width: 100%;
    max-width: none;
    margin-left: 0;
    margin-right: 0;
  }

  .pdp-images {
    overflow: hidden;
  }

  .pdp-description {
    margin-top: 0;
  }

  .pdp-additional-main,
  .pdp-additional-side {
    margin-top: 20px;
  }

  .pdp-additional-side {
    /* follows the viewport while the longer copy column scrolls */
    position: sticky;
    top: 20px;
  }
}

/* ─── Sticky gallery (products with a Buy Together card only) ─────────────────
   The complaint this answers: scrolling down to read Customers Also Purchased, the LEFT
   column keeps producing fresh content — Product Info, specs, reviews — and the eye
   follows it instead. The two columns compete for attention at exactly the moment the
   card should have it.

   Fix: on these products the gallery PINS and the copy leaves the media column, so the
   left side stops changing while the right is being read. The copy moves to a full-width
   row underneath.

   Grid with named areas, so the change is placement rather than two DOM shapes:

       gallery  buy
       copy     .

   The copy sits in the GALLERY's column, not across both. Spanning the full width was the
   first pass and it broke the vertical line the page is built on — the copy started at the
   page edge while the gallery above it started 30px in, so nothing lined up. Sharing the
   column gives it the gallery's width and its left edge for free, at every breakpoint,
   because the column IS the gallery's max-width.

   `align-self: start` on the gallery is what gives sticky somewhere to go: the grid AREA
   is the full row height while the gallery keeps its natural height, and the difference is
   the travel. Stretching it, which is the grid default, would leave nothing to travel.

   The cost is real and measured (.local/exp/restructure-probe.mjs): the travel and the
   empty column beneath the gallery are the SAME number, so the Mortlake bath gains 1,091px
   of pinning and carries 1,111px of empty left column, with the page growing 4,556 ->
   5,519px. That is the gap the column pairing was built to avoid, which is why this is
   gated on the card rather than applied everywhere. */
@media (min-width: 959px) {
  .pdp-container--sticky-gallery {
    display: grid;
    grid-template-columns: minmax(0, 614px) 350px;
    grid-template-areas:
      "gallery buy"
      "copy    .";
    column-gap: 50px;
    /* no align-items: the columns must STRETCH to the row height, because the difference
       between that and the gallery's own height is the only room the gallery has to
       travel. Setting `start` here collapsed it to nothing. */
  }

  .pdp-container--sticky-gallery .pdp-col--media {
    grid-area: gallery;
    display: block;
    width: auto;
    max-width: none;
    margin-right: 0;
  }

  /* Sticky inside the COLUMN, not the grid. The column is a real element ending with its
     own row, so the gallery releases when the row does. `display: contents` on the column
     was tried first and is wrong: dissolving it made the grid container the containing
     block, and the gallery kept travelling 700px past the row, straight over Product
     Info. */
  .pdp-container--sticky-gallery .pdp-images {
    position: sticky;
    top: 20px;
    width: 100%;
    max-width: 614px;
  }

  .pdp-container--sticky-gallery .pdp-col--buy {
    grid-area: buy;
    width: auto;
  }

  /* Customers Also Purchased sits flush against the buy area rather than 20px below it, so
     the two white panels read as one card with the recommendations as its closing section
     instead of a separate block that happens to follow.

     Scoped to this layout, but that costs nothing in practice: the sticky-gallery class and
     the card share exactly the same condition, so a product has both or neither. The 20px
     it overrides is shared with .pdp-additional-main, which still wants it. */
  .pdp-container--sticky-gallery .pdp-additional-side {
    margin-top: 0;
  }

  .pdp-container--sticky-gallery .pdp-additional-main {
    grid-area: copy;
    width: 100%;
    max-width: none;   /* the grid column already caps it at the gallery's width */
    margin-left: 0;
    margin-top: 20px;
  }
}

@media (min-width: 1198px) {
  .pdp-container--sticky-gallery {
    grid-template-columns: minmax(0, 706px) 600px;
  }

  .pdp-container--sticky-gallery .pdp-images {
    max-width: 706px;
  }
}

@media (min-width: 1400px) {
  .pdp-container--sticky-gallery {
    grid-template-columns: minmax(0, 802px) 600px;
  }

  .pdp-container--sticky-gallery .pdp-images {
    max-width: 802px;
  }

  /* From 1400px the thumbnail rail moves to the LEFT of the cover, so the gallery column
     no longer starts where the picture does — the rail is 130px plus its 20px gap. The
     copy indents to match the COVER, not the column, which is the line the eye follows.
     Measured: below 1400 the rail sits under the image and the offset is 0, so this
     applies at this breakpoint only.

     `width: auto` is required. The >=959px rule sets these blocks to 100%, and 100% plus
     a 150px left margin would push the copy 150px past the column's right edge.

     The non-sticky layout already does exactly this further down the file; that rule is
     only overridden here because `.pdp-container--sticky-gallery .pdp-additional-main`
     outranks it. */
  .pdp-container--sticky-gallery .pdp-additional-main {
    width: auto;
    margin-left: 150px;
  }
}

/* The buy area sits on a white panel, matching .pdp-buy-together below it and the
   Product Info panels underneath — same white, same 20px padding, no border or radius,
   so the column reads as one set of cards against the grey page.

   NO media query, deliberately. This was gated to >=959px, which left the buy area as the
   only block on a narrow screen without a panel: .pdp-buy-together and .pdp-collapsible
   both carry theirs at every width (20px padding each, the same 20px these use), so on
   mobile the stack ran white card, bare grey buy area, white card. Unwrapping the query is
   the whole fix.

   It costs 40px of content width below 959px — the card is inset inside .page-width's own
   padding rather than bleeding to the edges, exactly as the panels above and below it are,
   which is what keeps the stack aligned down one edge. */
.pdp-description {
  background-color: #ffffff;
  padding: 20px;
}

/* The buy column is 600px from 1198px up, whichever way the gallery is arranged. */
@media (min-width: 1198px) {
  .pdp-col--buy {
    flex-basis: 600px;
    width: 600px;
  }

  .pdp-col--media {
    max-width: 706px;
  }
}

/* 1198–1399: cover image with the thumbnail strip beneath it. Three columns do not
   earn their place here — at a 1140px container the rail plus a 600px buy column
   would squeeze the cover to about 360px, smaller than the buy area beside it. */
@media (min-width: 1198px) and (max-width: 1399.98px) {
  .pdp-images {
    display: flex;
    flex-direction: column;
  }

  .pdp-cover-image {
    order: 1;
  }

  .pdp-thumbnails {
    order: 2;
    width: 100%;
    /* Explicit, not auto: the thumbnails are lazy-loaded and measure 0x0 until they
       load, so an auto height collapses the strip to nothing and it never opens. */
    height: 84px;
    flex: 0 0 auto;
    max-height: none;
    margin: 14px 0 0;
    padding: 0;
  }

  /* Specificity, not order — see the note on the same selector in the 1400px block. */
  .swiper.pdp-thumbnails .swiper-slide {
    width: auto;
    height: 100%;
    max-height: none;
  }
}

/* 1400px and up: the rail returns to the LEFT of the cover — rail, image, buy area.
   802 = 130 rail + 20 gap + 652 cover; with the 50px gutter and the 600px buy column
   that is 1452, exactly the container's content width at the 1512px page maximum. */
@media (min-width: 1400px) {
  .pdp-images {
    display: flex;
    flex-direction: row;
    align-items: flex-start;
    gap: 20px;
  }

  .pdp-col--media {
    max-width: 802px;
  }

  .pdp-thumbnails {
    order: 1;
    /* Fixed, so the cover takes the remaining width and absorbs any shrinking.
       130px is chosen to match the slide height: the vertical swiper divides the
       rail's height by slidesPerView (4), so a 560px rail gives ~132px slides. Any
       narrower and object-fit: cover crops the photo into a tall portrait sliver. */
    flex: 0 0 130px;
    width: 130px;
    max-height: none;
    margin: 0;
    padding: 0;
  }

  /* `.swiper` is on the same element, so this scores 0,3,0 and beats the base
     `.pdp-thumbnails .swiper-slide { width: 25% }` at 0,2,0 — which sits further down
     the file and would otherwise win on order, squeezing each slide to 33px. */
  .swiper.pdp-thumbnails .swiper-slide {
    width: 100%;
    /* Keeps the tile square-ish even on a product whose buy column is short enough
       to pull the cover — and so the rail — below 560px. */
    max-height: 130px;
  }

  .pdp-cover-image {
    order: 2;
    flex: 1;
    min-width: 0;
  }

  /* Indented to start under the cover image rather than the rail: 110px rail + its
     20px gap. `width: auto` matters — the ≥959px rule sets these blocks to 100%, and
     100% plus a left margin would push the block past the column's right edge.
     Only at this breakpoint; below it the rail sits under the image, so there is
     nothing to clear and the block runs flush with the column. */
  .pdp-additional-main {
    width: auto;
    margin-left: 150px;
  }
}

/* Stacked layout. The wrappers are dissolved so all four blocks become direct
   children of .pdp-container again, then `order` restores the sequence the columns
   would otherwise break:

     image, buy area, Customers Also Purchased, Product Info + specs, Reviews

   .pdp-additional-main is dissolved too so Reviews can be ordered on its own. */
@media (max-width: 958.98px) {
  .pdp-col,
  .pdp-additional-main {
    display: contents;
  }

  /* `display: contents` above generates no box for .pdp-additional-main, so the
     `margin-top: 20px` it carries at >=959px is discarded along with it, and the first
     Product Info panel came to rest flush against the buy column — its white card
     starting on the very pixel the "Secure checkout / Official supplier / SKU" line
     ended, which read as the trust row sitting inside the panel. The wrapper cannot
     hold the gap any more, so the column below it does.

     20px, not the 30px above the buy column: these panels are 20px apart from each
     other (.pdp-collapsible margin-bottom), and matching that makes the card stack one
     evenly spaced group rather than something set slightly adrift from it. */
  .pdp-description {
    margin-bottom: 20px;
  }

  /* Everything is shifted one place NEGATIVE of where it was so that
     .pdp-additional-side — the Customers Also Purchased card — can take -1 and land
     directly under the buy area. It used to be order 1, which put it after the Product
     Info and specs panels; on desktop it sits immediately below the buy area in the same
     column, and stacking it anywhere else broke that adjacency.

     `order` is an integer, so there is no slot between the buy area's old -1 and the
     unset 0 the copy panels sit on. Renumbering was the only way to open one, rather
     than pushing the copy panels positive and having to name every one of them. */
  .pdp-images {
    order: -3;
  }

  .pdp-description {
    order: -2;
  }

  .pdp-additional-side {
    order: -1;
  }

  .pdp-additional-main > .pdp-reviews {
    order: 2;
  }
}

/* No panel of its own any more. The card used to be a separate white block in
   .pdp-additional-side, below everything; it now sits INSIDE the buy area, which is
   already a white panel with its own padding, so a second background and another
   20px inset would draw a box inside a box. */
.pdp-buy-together {
  /* More room above than there was under the heading: with no heading of its own, the
     first group's label would otherwise sit as close to the option axis above it as it
     does to its own dropdown, and read as part of that block. */
  margin: 18px 0;
}

/* Ruled off, because the card now butts against the buy area above it. Sharing one white
   panel is what makes the recommendations read as part of the Add to Cart block, but it
   also removed the boundary that used to say where one section ended and the next began.
   The heading carries it instead.

   Same 1px #d5dbe1 as the option axis labels and the family boundaries inside this list,
   so every divider on the page is the same idea drawn the same way. */
/* The card has no heading at all now — see the note in snippets/buy-together.html.
   What it used to say lives on each dropdown's own label instead. */

/* "Optional" after the group name, as a small filled chip.

   It was "(optional)" in quiet grey, and that was the wrong call: read quickly, a
   labelled dropdown above an Add to Cart button looks like something you must
   answer, and a footnote saying otherwise is easy to miss. Someone could stall
   there. This is the one label on the card that has to land.

   Loud enough to be seen, quiet enough not to be a warning: the pale blue-grey
   ground already used for the "+5" preview tile, navy-grey text, and 11px — it
   still reads as metadata beside a 13px navy label rather than competing with it.
   No red, no border, no exclamation. */
.pdp-bt-optional {
  display: inline-block;
  margin-left: 2px;
  /* Tight vertical padding: the chip should read as part of the line, not as an
     object parked on it. 1px keeps the filled box inside the label's own ascender
     and descender band instead of standing proud of it. */
  padding: 1px 6px;
  border-radius: 3px;
  background-color: #eef1f5;
  color: #41546E;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.2px;
  line-height: 1.35;
  white-space: nowrap;
  /* Sits ON the label's baseline. An earlier `vertical-align: 1px` lifted it a
     fraction and it read as floating above the words. Default baseline alignment is
     what "inline with the label" means: the chip's own text shares the label's
     baseline, and its padding grows either side of that. Nothing to nudge. */
  vertical-align: baseline;
}

.pdp-buy-together-list {
  list-style: none;
  margin: 0 0 15px;
  padding: 0;
}

/* Rows are deliberately tight. At an 84px thumbnail, two lines of text and 16px between
   them, a card of fifteen ran past 1,500px and comparing three finishes meant scrolling
   between them — the opposite of what grouping is for. A 40px thumbnail, name and SKU on
   one line, and closed-up gaps put a row at 40px against roughly 100px. */
.pdp-buy-together-list li {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  margin-bottom: 6px;
}

/* The row proper is a <label> around the checkbox, so the whole line is the hit area for
   selecting. Only the open-in-a-new-tab button sits outside it. */
.pdp-buy-together-row {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: 1;
  min-width: 0;
  cursor: pointer;
  padding: 2px 4px;
  margin: -2px -4px;              /* pull the hit area out to the row edges, not the text */
  border-radius: 4px;
  transition: background-color 0.12s ease;
}

.pdp-buy-together-row:hover {
  background-color: #f4f7fa;
}

.pdp-buy-together-list li.is-unavailable .pdp-buy-together-row {
  cursor: default;
}

.pdp-buy-together-list li.is-unavailable .pdp-buy-together-row:hover {
  background-color: transparent;
}

/* Sibling rows — the same product in different finishes — pull together into a block, with
   a wider gap left between blocks. Adjacent margins collapse to the larger, so a group
   start after a grouped row still gets the full gap while rows inside a group stay tight. */
.pdp-buy-together-list li.is-grouped {
  margin-bottom: 4px;
}

/* A hairline at every group boundary. Spacing alone (6px inside a cluster against 16px
   between) was too quiet to read as grouping at a glance. The rule matches the one under
   the option axis labels, so the two groupings on the page look like the same idea.
   Applied to one-row groups too, so every boundary is drawn and a solo row does not appear
   to belong to the cluster above it. */
.pdp-buy-together-list li.is-group-start {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid #d5dbe1;
}

/* Collection heading. An <li> so it can be appended into the same list the script is
   reordering; role="presentation" keeps it out of the list semantics. `display: block`
   overrides the flex the row rule sets, and the rule above it is what separates one
   collection from the last. */
.pdp-buy-together-list li.pdp-buy-together-group-title {
  display: block;
  margin: 24px 0 10px;
  padding-top: 16px;
  border-top: 1px solid #d5dbe1;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: #767676;
}

.pdp-buy-together-list li.pdp-buy-together-group-title:first-child {
  margin-top: 0;
  padding-top: 0;
  border-top: 0;
}

.pdp-buy-together-list li.is-group-start:first-child {
  margin-top: 0;
  padding-top: 0;
  border-top: 0;
}









.pdp-buy-together-thumb {
  position: relative;
  width: 40px;
  height: 40px;
  border: 1px solid #e5e5e5;
  border-radius: 4px;
  overflow: hidden;
  flex-shrink: 0;
}

.pdp-buy-together-thumb::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: var(--bt-thumb);
  background-size: cover;
  background-position: center;
  /* scaled up so the blur doesn't expose transparent edges */
  transform: scale(1.2);
  /* blur scales with the tile — 8px on a 48px thumb washed the whole thing out */
  filter: blur(5px);
  opacity: 0.35;
}

.pdp-buy-together-thumb img {
  position: relative;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

/* One line: name, then SKU beside it. `min-width: 0` lets a long name ellipsise rather
   than shove the price off the end. */
.pdp-buy-together-info {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: baseline;
  gap: 8px;
}

.pdp-buy-together-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.pdp-buy-together-sku {
  flex-shrink: 0;
}

/* Open the product in a new tab. Outside the label so it never toggles selection. */
.pdp-buy-together-open {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 28px;
  height: 28px;
  color: #767676;
  border: 1px solid #d5dbe1;
  border-radius: 4px;
  text-decoration: none;
  transition: color 0.12s ease, border-color 0.12s ease;
}

.pdp-buy-together-open:hover,
.pdp-buy-together-open:focus-visible {
  color: #0A2749;
  border-color: #0A2749;
}


.pdp-buy-together-sku {
  font-size: 11px;
  color: #767676;
  text-transform: uppercase;
  letter-spacing: 0.3px;
  white-space: nowrap;
}

.pdp-buy-together-price,
.pdp-buy-together-oos {
  flex-shrink: 0;
}

.pdp-buy-together-price {
  font-weight: 700;
  font-size: 14px;
  white-space: nowrap;
}

/* ─── Customers Also Purchased: the dropdowns ─────────────────────────────────
   Each group is one control asking "which of these, or none". The rows above are
   what the server renders and what a customer with JS off keeps; the script in
   snippets/buy-together.html replaces them with these, reusing the
   .pdp-variant-* shapes from the cross-product option picker further up this same
   column. Deliberate: it is the same control answering the same kind of question,
   so it should not be a second visual language on one page. Only what differs
   from that picker is written here. */

/* Space above each label, not below the control it belongs to, so a label always
   sits closer to its own dropdown than to the one above — five groups at 12px read
   as one undifferentiated stack. The bottom margin is gone: the running total that
   used to follow went with the bundle builder, so it was only padding the card's
   own 20px. */
.pdp-buy-together-groups {
  margin: 14px 0 0;
}

.pdp-bt-group + .pdp-bt-group {
  margin-top: 20px;
}

/* Type comes from .pdp-variant-label, which the element also carries — the same
   rule that draws "Colour" and "Size" over the option axes up this column.

   The RULE UNDER IT is dropped here, and only here. An axis or two on the buy card
   can each carry a hairline; this card runs to five groups, and with the heading's
   own rule that was six horizontal lines stacked in one panel, which read as a
   table rather than a set of controls. The axes above keep theirs.

   Two classes, because .pdp-variant-label sits FURTHER DOWN this file — a
   single-class override ties on specificity and loses on source order, and the
   rule stays put with nothing appearing to have changed. */
.pdp-bt-group .pdp-bt-group-label {
  border-bottom: none;
  margin-bottom: 4px;
}

/* Closed, the control shows the PRODUCTS in the group rather than the words "Not
   required" — which said only what the customer had not yet done. A strip of
   thumbnails says what the question is about and is the reason to open it. Once
   something is chosen the strip gives way to that item's name, navy and bold like
   the rest of the buy column. */
.pdp-bt-select .pdp-bt-value {
  display: flex;
  align-items: center;
  min-width: 0;
}

.pdp-bt-preview {
  display: flex;
  align-items: center;
  gap: 4px;
  min-width: 0;
  /* clipped, never wrapped: the strip must not push the count or the chevron */
  overflow: hidden;
}

.pdp-bt-preview-img {
  width: 30px;
  height: 30px;
  flex: none;
  object-fit: contain;
  border: 1px solid #e5e5e5;
  border-radius: 3px;
  background: #fff;
}

/* Stands in for a product with no photograph, so the strip shows as many tiles as
   the count promises. */
.pdp-bt-preview-blank {
  background: #f2f4f6;
}

/* Last tile on a group too long to preview: "+8". Without it the strip simply
   stopped, and four thumbnails beside "12 options" read as a fault — the picture
   and the count disagreeing. Quieter than a thumbnail, since it is a note about
   the strip rather than another product in it. */
.pdp-bt-preview-more {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  font-weight: 700;
  color: #41546E;
  background: #eef1f5;
  border-color: #d5dbe1;
}

/* Normal weight, like the value in the option picker's own summary. Bold made a
   chosen extra shout louder than the product's actual Colour and Size above it,
   and on a five-group card several bold lines in a row read as a warning. The navy
   against the strip's grey, and the summary's navy border, already say chosen. */
/* The chosen item, shown the way the open list showed it: thumbnail, name, SKU,
   price. Same row shape as .pdp-bt-preview it replaces, so the control does not
   change height when something is picked. */
.pdp-bt-chosen {
  display: none;
  align-items: center;
  gap: 8px;
  min-width: 0;
  color: #0A2749;
  font-weight: normal;
}

/* The name is the only part allowed to shrink — the thumbnail, SKU and price are
   each short and each carry information the name does not. */
.pdp-bt-chosen-name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.pdp-bt-chosen .pdp-buy-together-sku,
.pdp-bt-chosen-price {
  flex: none;
}

/* 30px, matching .pdp-bt-preview-img rather than the 40px the option rows use. The
   clone comes from a row, so it arrives at 40 and the control would grow 12px the
   moment anything was picked — a stack of dropdowns visibly reflowing as you work
   down it. Same size as the tiles it replaces means the height never moves. */
.pdp-bt-chosen .pdp-buy-together-thumb {
  flex: none;
  width: 30px;
  height: 30px;
}

.pdp-bt-select.has-selection .pdp-bt-preview {
  display: none;
}

.pdp-bt-select.has-selection .pdp-bt-chosen {
  display: flex;
}

/* On a phone the summary has ~310px for all of this before it runs under the
   count. The SKU is the first thing to go: the thumbnail and the price carry more
   at a glance, and the SKU is still there inside the open sheet. */
@media (max-width: 958.98px) {
  .pdp-bt-chosen .pdp-buy-together-sku {
    display: none;
  }

  /* And the count goes once something is chosen. On 310px the name was down to
     "Eastbrook R…" while "9 options" held 90px beside it — but the question the
     count answers ("are there others?") is already answered by the chevron, and it
     is answered again the moment the sheet opens. What the customer picked is worth
     more than how many they did not. Desktop keeps both; it has the room. */
  .pdp-bt-select.has-selection .pdp-variant-more {
    display: none;
  }
}

/* A chosen group keeps the full navy border after the dropdown closes, so a filled
   control is picked out down a stack of untouched ones. Works again now the resting
   border is only a fifth opacity; while every border was solid navy this said
   nothing. The value is the stronger cue either way — thumbnails mean untouched, a
   product name means chosen. */
.pdp-bt-select.has-selection .pdp-variant-summary {
  border-color: #0A2749;
}

/* The count sits ON TOP of the thumbnails and always wins. The strip is allowed to
   run under it and fade out, so however many tiles there are, "9 options" and the
   chevron are never crowded out — the negative margin pulls the label over the
   strip and the gradient dissolves the tile beneath it.

   ONLY while the strip is showing. With an item chosen the thing next to the count
   is that item's PRICE, and the same overlap ate its last digit — "£225.88" arriving
   as "£225.8" half faded. A tile losing its edge is the point; a price losing a digit
   is a different matter entirely. The chosen row is built to fit instead, with the
   name as the only part that shrinks. */
.pdp-bt-select:not(.has-selection) .pdp-variant-more {
  position: relative;
  z-index: 1;
  margin-left: -22px;
  padding-left: 22px;
  background: linear-gradient(to right, rgba(255, 255, 255, 0), #ffffff 20px);
}

/* The option row carries the open-in-a-new-tab link BESIDE the choose button,
   not inside it — a button cannot contain a link. */
.pdp-bt-option {
  display: flex;
  align-items: center;
  gap: 2px;
}

/* button, where the picker uses an anchor: these select, they don't navigate */
.pdp-bt-choice {
  flex: 1;
  min-width: 0;
  width: 100%;
  border: 0;
  background: none;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.pdp-bt-choice:hover:not([disabled]) {
  background: #f6f8fa;
}

.pdp-bt-choice:focus-visible {
  outline: 2px solid #C09955;
  outline-offset: -2px;
}

.pdp-bt-choice[disabled] {
  cursor: not-allowed;
}

/* Chosen option: the same gold tick over the thumbnail the variant picker uses for
   the product you are on. .pdp-variant-item.is-current supplies both the panel and
   the tick, but sizes the tick to a 44px image — these rows carry
   .pdp-buy-together-thumb, which is 40px. */
.pdp-bt-choice.is-current {
  background: rgba(192, 153, 85, 0.12);
  box-shadow: inset 0 0 0 1px #C09955;
}

/* Three classes, not two. The rule being adjusted is .pdp-variant-item.is-current
   and it lives FURTHER DOWN this file, so a two-class selector here ties on
   specificity and loses on source order — the tick keeps its 44px and nothing
   appears to happen. Both overrides below name the button's third class to win
   outright rather than depending on where in the file they sit. */
.pdp-variant-item.pdp-bt-choice.is-current::after {
  width: 40px;
  height: 40px;
  font-size: 20px;
}

/* Normal weight even when it is the current choice, matching every other option in
   the list and the picker's own .pdp-variant-item. The gold panel and tick mark the
   selection; weight on top of those was a third signal saying the same thing. */
.pdp-bt-none {
  font-size: 13px;
  font-weight: normal;
  color: #0A2749;
}

/* An empty square standing in for the thumbnail every other option has, so "Not
   required" begins on the same text column as the products below it instead of
   hanging out to the left. It also gives the chosen-option tick a tile to sit on,
   which is why this row no longer suppresses it. */
.pdp-bt-none-box {
  border-style: dashed;
  border-color: #d5dbe1;
  background: #fbfcfd;
}

.pdp-bt-option .pdp-buy-together-thumb {
  flex: none;
}

/* A column of the row, not a word on its second line. In the sub-line it rode with
   the SKU and shifted up or down as the title above wrapped to one line or two, so
   a scan down the prices zig-zagged. As a direct child of the centred flex row it
   sits on the row's middle, level with the open-in-a-new-tab button beside it. */
.pdp-bt-option .pdp-variant-item-price {
  margin-left: auto;
  padding-left: 10px;
  flex: none;
  align-self: center;
  white-space: nowrap;
}

/* SKU stays visible inside the open dropdown: trade customers order by it, and
   on a finish family it is the only part of the row that is unambiguous. */
.pdp-bt-option .pdp-buy-together-sku {
  flex: none;
}

/* ─── Dropping UP when there is no room below ─────────────────────────────────
   A native select never opens off the bottom of the screen; it picks the side
   with room. This card sits low in a long page, so opening downward from the
   last group routinely put half the options past the fold — reachable only by
   scrolling the page, which on a short list looked like the options were simply
   missing. The script measures the space above and below the control and adds
   this class when up is the better side; it also sets an inline max-height so
   the list fits whichever side it took. */
.pdp-bt-select.drops-up .pdp-variant-list {
  top: auto;
  bottom: 100%;
  border-top: 1px solid #0A2749;
  border-bottom: none;
  border-radius: 6px 6px 0 0;
  box-shadow: 0 -8px 20px rgba(10, 39, 73, 0.12);
}

/* The join moves to the top edge with the list, so the summary keeps its border
   whole on the side the list is NOT attached to. */
.pdp-bt-select.drops-up[open] .pdp-variant-summary {
  border-top-color: #0A2749;
}

/* ─── Mobile: a bottom sheet, the way a phone opens a select ───────────────────
   Below 959px the same absolutely-positioned overlay was the whole problem: it
   opened inside a column barely wider than the text, ran off the bottom of the
   screen, and left the page scrolling behind it. A phone answers a "choose one"
   with a sheet from the bottom edge — big targets, its own scroll, a backdrop,
   and a title saying which question you are answering. That is what this is; the
   markup and the styling of the rows are unchanged, only where the list goes. */
@media (max-width: 958.98px) {
  /* 44px of tap target rather than 40 */
  .pdp-bt-select .pdp-variant-summary {
    padding: 12px;
  }

  .pdp-bt-select[open]::before {
    content: "";
    position: fixed;
    inset: 0;
    z-index: 90;
    background: rgba(10, 39, 73, 0.45);
    animation: pdp-bt-fade 0.2s ease;
  }

  /* Escapes the column entirely — position: fixed, so the sticky/overflow rules
     on the product columns cannot clip it. */
  .pdp-bt-select[open] .pdp-variant-list {
    position: fixed;
    z-index: 91;
    top: auto;
    left: 0;
    right: 0;
    bottom: 0;
    /* the inline max-height the desktop measurement sets is cleared by the
       script below 959px, so this is the only one in play */
    max-height: 72vh;
    padding: 0 8px calc(8px + env(safe-area-inset-bottom, 0px));
    border: none;
    border-radius: 14px 14px 0 0;
    box-shadow: 0 -10px 30px rgba(10, 39, 73, 0.25);
    animation: pdp-bt-sheet-in 0.22s ease;
    overscroll-behavior: contain;
  }

  /* Sticky so the group name stays legible while the options scroll under it —
     a sheet covering the page has to say what it is asking. */
  .pdp-bt-sheet-head {
    display: flex;
    align-items: center;
    gap: 10px;
    position: sticky;
    top: 0;
    z-index: 1;
    margin: 0 -8px;
    padding: 16px 14px 10px;
    background: #fff;
    border-bottom: 1px solid #d5dbe1;
  }

  /* the grab bar every mobile sheet has */
  .pdp-bt-sheet-head::before {
    content: "";
    position: absolute;
    top: 6px;
    left: 50%;
    transform: translateX(-50%);
    width: 36px;
    height: 4px;
    border-radius: 2px;
    background: #d5dbe1;
  }

  .pdp-bt-sheet-title {
    flex: 1;
    min-width: 0;
    font-size: 14px;
    font-weight: 700;
    color: #0A2749;
  }

  .pdp-bt-sheet-close {
    flex: none;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    margin: 0;
    padding: 0;
    border: 0;
    background: none;
    color: #41546E;
    cursor: pointer;
  }

  /* Roomier rows: a 40px thumbnail and one line of text is a 50px target on a
     desktop pointer and a cramped one under a thumb. */
  .pdp-bt-option .pdp-variant-item {
    padding: 9px 8px;
  }

  .pdp-bt-none {
    padding-top: 14px;
    padding-bottom: 14px;
    font-size: 14px;
  }
}

/* Desktop keeps the sheet furniture out of the list entirely. */
@media (min-width: 959px) {
  .pdp-bt-sheet-head {
    display: none;
  }
}

@keyframes pdp-bt-sheet-in {
  from { transform: translateY(100%); }
  to { transform: translateY(0); }
}

@keyframes pdp-bt-fade {
  from { opacity: 0; }
  to { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .pdp-bt-select[open] .pdp-variant-list,
  .pdp-bt-select[open]::before {
    animation: none;
  }
}

/* fallback (no Buy Together): the main CTA column follows the viewport */
@media (min-width: 959px) {
  /* The whole buy card — title, price, variants, quantity, buy button — pins
     and follows the viewport as one unit. The sticky-top script in
     main-product.html sets `top` so the buy controls dock just below the
     re-appearing site header (top = headerHeight − title/price bottom offset),
     so the header covers only the title + price on scroll-up. */
  .pdp-description-sticky {
    position: sticky;
    top: 20px; /* overridden inline by the sticky-top script */
    align-self: flex-start;
    transition: top 0.25s ease; /* smooth the shift as the card tracks the header */
  }

  /* panel painted on a pseudo-element so the white box can extend past the
     content without shifting the column's layout */
  .pdp-description-sticky::before {
    content: "";
    position: absolute;
    inset: -10px -20px -12px;
    z-index: -1;
    background-color: transparent;
    transition: background-color 0.2s ease, box-shadow 0.2s ease;
  }

  .pdp-description-sticky.is-stuck::before {
    background-color: #ffffff;
    box-shadow: 0 6px 20px rgba(10, 39, 73, 0.08);
  }

  /* while pinned the title collapses to a single ellipsised line so the card
     stays compact; at rest (not stuck) it wraps in full */
  .pdp-description-sticky.is-stuck .pdp-info-sticky-header h1 {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  /* Buy Together card gets the same raised treatment while pinned */
  .pdp-additional-side .pdp-buy-together {
    transition: box-shadow 0.2s ease;
  }

  .pdp-additional-side.is-stuck .pdp-buy-together {
    box-shadow: 0 6px 20px rgba(10, 39, 73, 0.08);
  }

  /* The card pins only while it FITS. snippets/buy-together.html measures it against the
     viewport and sets this class when it doesn't — a card taller than the screen would
     otherwise pin with its bottom rows and the add button permanently out of reach, since
     this column has no inner scroll. Unpinned it simply scrolls with the page, and because
     main-product.html has already withheld the buy area's sticky class, nothing pins at
     all on those products. The second rule drops the raised-panel shadow, which the
     shared is-stuck script would otherwise still apply to a column that isn't pinned. */
  .pdp-additional-side.is-too-tall {
    position: static;
  }

  .pdp-additional-side.is-too-tall .pdp-buy-together {
    box-shadow: none;
  }
}

/* ─── Pinning is currently OFF ────────────────────────────────────────────────
   Both the buy card and the Buy Together card scroll away with the page instead
   of following the viewport. Everything that pinned them is left intact above —
   this block just overrides the position, and both scripts in main-product.html
   check the computed position before doing any work, so no JS changes hands with
   this. It has to sit AFTER those rules: same specificity, so the last one wins.
   Delete this block to switch pinning back on. */
@media (min-width: 959px) {
  /* `relative`, not `static`. Both stop the column pinning, but the raised panel is a
     ::before with `position: absolute; left: -20px; right: -20px`, and an absolute box
     resolves against its nearest POSITIONED ancestor. `sticky` was providing that;
     `static` is not positioned, so the panel jumped to a far wider ancestor, stretched
     to ~1560px and pushed the whole page into a 20px horizontal scroll. `relative` keeps
     the column as the containing block without pinning it.
     Both scripts in main-product.html compare against 'sticky', so they still no-op. */
  .pdp-description-sticky,
  .pdp-additional-side {
    position: relative;
    /* `top` must be cleared too. Both rules above set `top: 20px` for pinning, which a
       static box ignores — but a relative one honours, nudging the column 20px down and
       out of line with the image beside it. */
    top: auto;
  }
}

.pdp-product-details h3 {
  font-size: 1rem;
  margin-top: 2rem;
}

.pdp-product-details ul {
  list-style: none;
  padding-left: 0;
  margin: 10px 0 0;
}

.pdp-product-details ul li {
  position: relative;
  padding-left: 26px;
  margin-bottom: 6px;
}

.pdp-product-details ul li::before {
  content: "\2713";
  position: absolute;
  left: 0;
  top: 1px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  font-size: 10px;
  font-weight: 700;
  line-height: 16px;
  text-align: center;
  background-color: #daeeeb;
  color: #00B67A;
}

.pdp-delivery-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.pdp-delivery-item {
  position: relative;
  padding-left: 26px;
  margin-bottom: 8px;
  font-size: 13px;
}

.pdp-delivery-item:last-child {
  margin-bottom: 0;
}

.pdp-delivery-item::before {
  position: absolute;
  left: 0;
  top: 1px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  font-size: 10px;
  font-weight: 700;
  line-height: 16px;
  text-align: center;
}

.pdp-delivery-item.is-yes::before {
  content: "\2713";
  background-color: #daeeeb;
  color: #00B67A;
}

.pdp-delivery-item.is-no::before {
  content: "\2715";
  background-color: #fdecec;
  color: #c0392b;
}

.pdp-delivery-item.is-info::before {
  content: "i";
  background-color: #eef1f4;
  color: #767676;
}






/* EXPERIMENT (branch pdp-buy-above-options) — every icon in the row is #0A2749, the navy
   supplier.svg is already drawn in and the same navy as the price above.

   delivery.svg (#00B67A fill) and in-store.svg (#00B67A stroke) could not be recoloured as
   background-images — CSS cannot reach inside a raster or SVG background — and editing the
   files was not an option while other sections may use them. Masking sidesteps it: the file
   supplies only its alpha, background-color supplies the colour. Applies to supplier.svg
   too, so all three take one declaration rather than the navy one being a happy accident.

   `.background-image` and its three sizing rules were deleted with this: those spans were
   its only three uses anywhere in sections/, snippets/ and assets/. */
.pdp-trust-icon {
  display: inline-block;
  flex: 0 0 auto;
  width: 15px;
  height: 12px;
  background-color: #0A2749;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
}

/* The lock is inline SVG stroked with currentColor, so it takes the same navy from `color`
   rather than from a mask. Its label stays #767676 — only the icon changes. */
.pdp-secure-checkout svg {
  width: 12px;
  height: 12px;
  flex-shrink: 0;
  color: #0A2749;
}

/* EXPERIMENT (branch pdp-buy-above-options) — "Secure checkout" and "OFFICIAL SUPPLIER"
   close the reassurance block, on the line under the two green panels. The layout lives on
   the row itself rather than being scoped to .pdp-cta-footer, INCLUDING `overflow: hidden`:
   the pipe dividers below are painted into the gap to each item's left, and only that clip
   stops the item starting a line from opening with a stray "|".

   `flex-basis: 100%` claims its own line inside the footer's wrap — without it the row
   would try to squeeze in beside the panels. */
.pdp-trust-buy {
  /* was .pdp-cta-footer's; sits directly under Add to basket and should read as part of it */
  margin-top: 8px;
  margin-bottom: 4px;
}

.pdp-trust-row {
  flex: 0 0 100%;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  column-gap: 11px;
  row-gap: 4px;
  overflow: hidden;
}

/* each item paints its own divider into the column gap on its left; .pdp-trust-row's
   overflow:hidden clips it whenever the item starts a line, so wrapped lines
   never open with a stray "|" */
.pdp-trust-row > * {
  position: relative;
  min-width: 0;
}

.pdp-trust-row > *::before {
  content: "";
  position: absolute;
  left: -6px;
  top: 50%;
  transform: translateY(-50%);
  width: 1px;
  height: 10px;
  background-color: #cfd5db;
}


.pdp-sku-info {
  margin: 0;
  font-size: 10px;
  font-weight: 400;
  color: #767676;
  text-transform: uppercase;
  overflow-wrap: anywhere;
}

.pdp-sku-info:has(> span:empty) {
  display: none;
}

/* EXPERIMENT (branch pdp-buy-above-options) — the SKU leads the card on its own line, above
   the title. It keeps .pdp-sku-info's 10px uppercase grey and its empty-SKU hide; only the
   spacing is new. It is no longer inside .pdp-trust-row, so the divider rule below cannot
   reach it and needs no unsetting. */
.pdp-sku-top {
  margin-bottom: 8px !important;
}


/* discount pricing (real sale): red sale price, struck regular price and a
   Save pill all on one line. line-height: 1 so box bottoms equal glyph bottoms
   (digits have no descenders), then flex-end lines them up exactly */
/* discount pricing — recreates the approved mock layout: red sale price inline
   with a struck regular price and a green Save pill. The struck price + pill are
   injected by JS as siblings OUTSIDE .price, so they inherit normal dark text
   (not the theme's gold light-text) instead of fighting the price component. */
.pdp-price-deal {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  column-gap: 10px;
}

.pdp-price-deal .price-item--sale {
  color: #0A2749;
  font-size: 22px;
  font-weight: 700;
  letter-spacing: 0;
  line-height: 1;
  margin: 0;
}

/* hide the theme's own inline struck price; we render our own sibling instead */
.pdp-price-deal .price__sale .price-item--regular {
  display: none;
}

/* nudge the price number down so its baseline matches the sibling pill/struck */
.pdp-price-deal .price__sale {
  transform: translateY(5px);
}

.pdp-price-compare {
  text-decoration: line-through;
  opacity: 0.6;
  font-size: 15px;
  line-height: 1;
}

.pdp-price-save-label {
  display: inline-block;
  background-color: rgb(0 182 122);
  color: #ffffff;
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0;
  line-height: 1;
  padding: 3px 6px;
  border-radius: 2px;
}

.pdp-line-total {
  font-size: 13px;
  margin-bottom: 10px;
  text-align: right;
}

/* Says what a quantity above one does to the chosen Buy Together extras, and where to
   change it. Right-aligned under the line total it explains, and quiet — it is a
   footnote to a number, not a warning about one. The link is underlined because a
   sentence that names the fix has to be the thing you can click. */
/* Quieter than the figures either side of it — it qualifies the multiplication
   rather than being part of it. */
.pdp-line-total-incl {
  color: #41546E;
  font-size: 11.5px;
  white-space: nowrap;
}

.pdp-extras-qty-note {
  font-size: 12px;
  line-height: 1.45;
  color: #41546E;
  margin-top: -6px;
  margin-bottom: 10px;
  text-align: right;
}

.pdp-extras-qty-note a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 2px;
}

.pdp-stock-status {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 12px;
  font-weight: 400;
  margin-bottom: 6px;
}

.pdp-stock-status::before {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background-color: #35c08e;
  box-shadow: 0 0 2px #35c08e;
  flex-shrink: 0;
}

.pdp-stock-status.is-out::before {
  background-color: #c0392b;
  box-shadow: none;
}

.pdp-cutoff {
  font-size: 12px;
  color: #767676;
  margin-bottom: 4px;
}

.pdp-cutoff strong {
  color: #e5484d;
  font-weight: 300 !important;
  font-variant-numeric: tabular-nums;
}

/* Sticky add-to-basket bar — EVERY width now. It used to be display:none with the whole
   thing rebuilt inside @media (max-width: 958.98px), so it was a phone-only bar. The
   IntersectionObserver in main-product.html that toggles .is-visible was never gated by
   width, so desktop was already computing it; only the CSS held it back.

   It earns its place on desktop for the same reason it does on a phone: the buy area
   scrolls away. Nothing on this page pins any more — see the "Pinning is currently OFF"
   block above — so past the first screenful there is no way to buy without scrolling back.

   Off-screen rather than absent: translateY(100%) parks it below the viewport, so it can
   slide rather than pop, and it intercepts nothing while hidden. */
.pdp-sticky-atc {
  display: flex;
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 90;
  /* horizontal padding belongs to the inner wrapper — the white bar itself is full-bleed */
  padding: 10px 0 calc(10px + env(safe-area-inset-bottom, 0px));
  background-color: #ffffff;
  box-shadow: 0 -4px 12px rgba(0, 0, 0, 0.1);
  transform: translateY(100%);
  transition: transform 0.25s ease;
}

.pdp-sticky-atc.is-visible {
  transform: translateY(0);
}

.pdp-sticky-atc-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  width: 100%;
  /* 15px, not --page-padding: this is the phone bar's existing inset, kept exactly */
  padding: 0 15px;
}

/* Thumbnail + title + price. Below 959px the first two are hidden and this collapses to
   the price alone, which is exactly the strip the phone bar already was. */
.pdp-sticky-atc-product {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}

.pdp-sticky-atc-thumb,
.pdp-sticky-atc-title,
.pdp-sticky-atc-sep {
  display: none;
}

/* Says what the bar's figure covers once Buy Together extras are chosen. Shown at
   EVERY width, unlike the thumbnail and title above: below 959px the bar is a
   price-and-button strip with no product context at all, so a grown price there has
   nothing but this to explain it. flex: none because it must never be the thing
   that gets clipped — a price with the explanation cut off is worse than no
   explanation. */
.pdp-sticky-atc-extras-note {
  flex: none;
  font-size: 12.5px;
  color: #41546E;
}

/* Desktop only, matching the thumbnail and title it sits beside. */
.pdp-sticky-atc-extra-thumbs {
  display: none;
}

.pdp-sticky-atc-price {
  flex-shrink: 0;
  font-weight: 700;
}

.pdp-sticky-atc-price:empty {
  display: none;
}

.pdp-sticky-atc .button {
  flex: 1;
}

@media (min-width: 959px) {
  /* Contents track .page-width so the bar lines up with the page behind it, and the button
     stops being a 1452px-wide slab.

     CENTRED, not pushed right to mirror the buy column. Tawk.to's launcher is fixed to the
     bottom-right corner and is hardcoded into theme.html, and at 1440px the .page-width
     right edge sits only 15px from the viewport edge — a right-aligned button would land
     underneath it. Centring clears the corner at every width without depending on a
     third-party widget's dimensions. */
  .pdp-sticky-atc-inner {
    max-width: var(--page-width);
    margin: 0 auto;
    gap: 20px;
    /* Plain page padding on both sides, so the button's right edge lands on the SAME
       line as the buy panel's right edge at every width — the panel ends at the page
       container's content edge, and so now does the button.

       This replaced a calc that reserved 76px in the bottom-right corner for Tawk.to's
       launcher. It only bit below 1604px (= --page-width 1512 + 2 x (76 - 30)), where the
       page has no gutter left to absorb the reservation, and there it pushed the button
       46px off the panel edge — visibly out of line with the alignment held above that
       width. Chosen deliberately (2 Sep 2026): consistent alignment is worth more than
       the corner. If the launcher does collide on the live site — it does not load on the
       dev server, so this cannot be checked locally — the fix is Tawk's own offset
       setting rather than reintroducing the gap here. */
    padding-inline: var(--page-padding);
  }

  .pdp-sticky-atc-thumb {
    display: block;
    width: 48px;
    height: 48px;
    flex-shrink: 0;
    object-fit: contain;
    background-color: #ffffff;
  }

  .pdp-sticky-atc-title {
    display: block;
    min-width: 0;
    /* one line, clipped — catalogue titles run long ("Eastbrook Imperia 2 Column
       Radiator 600 x 1145mm Gloss White"), and a bar that grows a second line would
       shift the page under it every time the product changed */
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 14px;
    font-weight: 500;
    color: #0A2749;
  }

  /* The chosen extras, after the product's own thumbnail and behind a "+", so the
     bar shows three things where the price counts three things. Smaller than the
     48px product tile on purpose — these are what is going WITH it. */
  .pdp-sticky-atc-extra-thumbs {
    display: flex;
    align-items: center;
    gap: 4px;
    flex: none;
  }

  /* display: flex above beats the UA stylesheet's [hidden] { display: none }, so with
     nothing selected the "+" would sit there on its own. Stated explicitly. */
  .pdp-sticky-atc-extra-thumbs[hidden] {
    display: none;
  }

  .pdp-sticky-atc-plus {
    flex: none;
    font-size: 15px;
    line-height: 1;
    color: #41546E;
  }

  .pdp-sticky-atc-extra-thumb {
    width: 32px;
    height: 32px;
    flex: none;
    object-fit: contain;
    border: 1px solid #e5e5e5;
    border-radius: 3px;
    background-color: #ffffff;
  }

  .pdp-sticky-atc-extra-thumb.is-blank {
    background-color: #f2f4f6;
  }

  /* Montirex's `square-separator--subdued` between title and price */
  .pdp-sticky-atc-sep {
    display: block;
    width: 4px;
    height: 4px;
    flex-shrink: 0;
    background-color: #c9cdd3;
  }

  .pdp-sticky-atc-price {
    font-size: 16px;
  }

  .pdp-sticky-atc .button {
    flex: 0 0 260px;
  }
}

.pdp-cover-counter {
  display: none;
}

@media (max-width: 958.98px) {
  .pdp-cover-counter {
    display: block;
    position: absolute;
    z-index: 10;
    top: auto;
    left: auto;
    right: 10px;
    bottom: 40px;
    width: auto;
    padding: 2px 10px;
    border-radius: 12px;
    background-color: rgba(10, 39, 73, 0.7);
    color: #ffffff;
    font-size: 12px;
  }

  .pdp-breadcrumb .breadcrumb-item.active {
    display: inline-block;
    max-width: 60vw;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    vertical-align: bottom;
  }
}

.pdp-recently-viewed {
  margin-top: 50px;
}

/* Width comes from the .page-width wrapper in the markup, the same container
   "You may also like" uses, so the two rows line up. The hand-set max-widths and
   the 165px left offset that used to live here are gone: the offset cleared the old
   vertical thumbnail rail, which no longer sits beside the image. */

/* "You may also like": full-width row of 5 cards */
@media (min-width: 959px) {
  .product-recommendations product-recommendations {
    display: block;
  }

  .product-recommendations .grid {
    grid-template-columns: repeat(5, minmax(0, 1fr));
  }

  .product-recommendations .grid > li:nth-child(n+6) {
    display: none;
  }
}

/* keep mobile at its previous four cards (2 x 2) */
@media (max-width: 958.98px) {
  .product-recommendations .grid > li:nth-child(n+5) {
    display: none;
  }
}

/* Size, family and weight now come from .title4 / .product-carousel-title on the
   heading itself, matching "You may also like". Only the spacing below it is set
   here — .title4 zeroes margin-bottom, which would butt the cards against it. */
.pdp-recently-viewed h2 {
  margin: 0 0 20px;
}

/* Cards use the same product-card markup as "You may also like" (styled by
   component-card.css); this just lays them out in a matching grid. */
.pdp-recently-viewed-list {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 15px;
}

@media (min-width: 959px) {
  .pdp-recently-viewed-list {
    grid-template-columns: repeat(5, minmax(0, 1fr));
  }
}

/* match "You may also like": 2 x 2 on mobile */
@media (max-width: 958.98px) {
  .pdp-recently-viewed-list > *:nth-child(n + 5) {
    display: none;
  }
}

/* these cards have no .card__info row, so drop the bottom space component-card.css
   reserves for it (53/40/30px on .product-card-link by breakpoint) */
.pdp-recently-viewed .product-card-link {
  margin-bottom: 0;
}

@media print {
  header,
  footer,
  iframe,
  .pdp-sticky-atc,
  .pdp-whishlist,
  .pdp-thumbnails,
  .pdp-illustration-only,
  .pdp-cover-counter,
  .pdp-cover-blur,
  .pdp-reviews,
  .pdp-recently-viewed,
  .swiper-button-next,
  .swiper-button-prev {
    display: none !important;
  }

  .pdp-description-sticky,
  .pdp-additional-side {
    position: static !important;
  }

  .pdp-description-sticky::before {
    display: none !important;
  }

  /* collapsed sections still print their content */
  .pdp-collapse + div {
    height: auto !important;
    overflow: visible !important;
    padding: 0 20px 30px !important;
  }
}

h1.product__info-item {
  font-size: 20px;
  font-weight: 700;
  margin-top: 0;
  margin-bottom: 30px;
  line-height: 30px;
  letter-spacing: 0px;
}

.pdp-product-rating .product-plugin-comment-rate-star {
  margin: 0 0 20px !important;
  gap: 14px;
  text-decoration: underline;
}

.pdp-product-rating a {
  text-decoration: underline;
}

.pdp-product-price .price__regular .price-item--regular {
  font-size: 20px;
  font-weight: 700;
  margin-bottom: 30px;
  line-height: 30px;
  color: #0A2749;
}

/* Quantity stepper and Add to cart share one row, so the buy controls take ~50px
   less height and the button sits higher up the card. The two are separate theme
   blocks with the stock line rendered between them, so they are brought together
   with `order` rather than markup — everything above the quantity keeps the default
   order 0 and stays put, and the stock line is pushed below the row.
   Desktop only: at narrow widths a full-width button is easier to hit. */
@media (min-width: 959px) {
  .product__info-container {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
  }

  /* Everything stacks full width by default; the two row items opt out below. */
  .product__info-container > * {
    width: 100%;
  }

  /* Turning this container into a flex parent stops its children's vertical margins
     collapsing into each other, so spacing that used to overlap now adds up. The
     !important flags below undo margins set on the elements themselves; without them
     the run from the options down to the button gains about 60px, which is most of
     what putting the two controls on one line was meant to save. */
  .product__info-container > .product__inventory {
    /* Holds only whitespace unless there is an inventory message, so it is invisible
       but was still contributing 25px of margin. */
    margin-top: 0 !important;
    margin-bottom: 0 !important;
  }

  .quantity-input-label {
    order: 1;
    margin-top: 0 !important;
    margin-bottom: 6px;
  }

  .pdp-quantity {
    order: 2;
    flex: 0 0 140px;   /* 42px button + input + 42px button */
    width: 140px;
    margin: 0 12px 0 0 !important;
  }

  .pdp-buy-item {
    order: 2;
    flex: 1 1 auto;
    width: auto;
    min-width: 0;
    margin-top: 0 !important;
    margin-bottom: 0 !important;
  }

  /* Height comes from the button's own rule further down, which carries !important
     on an ID selector; only the vertical margins need clearing for the row. */
  .pdp-buy-item button.product-form__submit {
    margin-top: 0 !important;
    margin-bottom: 0 !important;
  }

  .pdp-line-total,
  .pdp-extras-qty-note,
  .pdp-stock-status,
  .pdp-cutoff,
  .pdp-trust-buy {
    order: 3;
  }

  .pdp-stock-status {
    margin-top: 12px;
  }

  /* The options are NOT re-ordered. They sit where `block_order` in templates/product.json
     puts them — above the quantity and Add to basket row — which is where they were before
     this branch and where they are again.

     This block briefly carried `order: 4` on .variant-selects, .pdp-options-item and
     .product__inventory to push the option list BELOW the buy controls, the experiment this
     branch is named for. Reverted on request: the options are a cross-product picker where
     every value is a link to another product, so a customer could add to basket and only
     then meet the size and colour they were supposed to choose first.

     The order values above still stand. They do a different job — pairing the quantity
     stepper with the button on one row — and are unaffected by where the options sit. */
}

.pdp-quantity quantity-input.quantity{
  width: 100%;
  height: 50px;
}

.pdp-quantity .quantity__button {
  width: 42px;
}

.pdp-quantity .quantity__input {
  border-left: 1px solid #ced4db;
  border-right: 1px solid #ced4db;
}

/* 50px matches the quantity stepper, which the buy button now sits beside on desktop.
   The !important is inherited from the original rule — an ID selector carrying it,
   which is why a plain height further down could not win. */
.pdp-product-container #product-form-main-product-info-submit,
.pdp-product-container .pay-button-buy-now {
  margin: 20px 0;
  height: 50px !important;
  width: 100%;
}

/* The out-of-stock notice takes the same slot as Add to cart, so it matches. */
.pdp-product-container button[class*="indexstyle__NoticeBtn"] {
  margin: 10px 0;
  height: 50px !important;
  width: 100%;
}

.pdp-product-container #wishlist-notice {
  margin: 0 !important;
}

.pdp-product-container #product-form-main-product-info-submit:disabled {
  display: none;
}

.pdp-product-container .shopline-payment-button-wrapper {
  display: none;
}


.pdp-product-container variant-selects .form__label,
.pdp-product-container .variant-selects .form__label,
.pdp-product-container variant-radios .form__label {
  margin-bottom: 6px;
  font-size: 12px;
  color: #0A2749;
  font-weight: normal !important;
  letter-spacing: 0;
  display: inline-block;
  margin-top: 20px;
}

variant-selects select,
.variant-selects select {
  font-size: 15px;
  white-space: pre-wrap;
}

/* The native option dropdowns are styled to match the cross-product picker
   (.pdp-variant-summary) so the two read as one control where they stack. */
.pdp-product-container variant-selects .field,
.pdp-product-container .variant-selects .field {
  border: 1px solid #d5dbe1;
  border-radius: 0;
  background: #fff;
  transition: border-color 0.15s ease;
}

/* The theme paints this border with an inset ::after overlay, which sits outside the
   border-box and would leave the two controls 2px different in height. */
.pdp-product-container variant-selects .field::after,
.pdp-product-container .variant-selects .field::after {
  content: none;
}

.pdp-product-container variant-selects .field:hover,
.pdp-product-container variant-selects .field:focus-within,
.pdp-product-container .variant-selects .field:hover,
.pdp-product-container .variant-selects .field:focus-within {
  border-color: #0A2749;
}

.pdp-product-container variant-selects select.field__input--classic,
.pdp-product-container .variant-selects select.field__input--classic {
  height: auto;
  padding: 10px 40px 10px 12px;
  font-size: 14px;
  line-height: 1.6;
  cursor: pointer;
}

.pdp-product-container variant-selects select.field__input--classic + .field__suffix,
.pdp-product-container .variant-selects select.field__input--classic + .field__suffix {
  right: 12px;
  padding: 0;
}

.pdp-product-container variant-selects .field__suffix .icon-arrow,
.pdp-product-container .variant-selects .field__suffix .icon-arrow {
  width: 16px;
  height: 16px;
}

/* EXPERIMENT (branch pdp-buy-above-options) — the four facts in .pdp-trust-row, styled
   ONCE. They were three separate rules in three places, alike bar an inconsistency each:
   .pdp-supplier-badge carried font-weight 600, .pdp-secure-checkout carried no margin
   reset, and .pdp-delivery-info was a mint-green bordered panel (#daeeeb on #00B67A,
   12px/700, its own padding and radius) before this branch flattened it. One block now, so
   the row cannot drift apart again; the three class names stay only to say which fact is
   which. All three elements are <div>s too — .pdp-supplier-badge was the lone <p>, which
   is why it needed the margin reset the others did not.

   No font-weight is declared at all: they inherit, which is what "Secure checkout" always
   did and is now what all four do.

   `white-space: nowrap` keeps the row wrapping BETWEEN facts, never through one.

   Trade-off worth knowing: green made "Delivery Available" and "FREE in-store collection"
   read as positives at a glance. In grey they are statements of fact, level with the rest
   of the row. That was the ask, not an oversight. */
.pdp-delivery-info,
.pdp-secure-checkout,
.pdp-supplier-badge {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 0;
  font-size: 10px;
  color: #767676;
  text-transform: uppercase;
  white-space: nowrap;
}

/* Nothing left to recolour now the panel is gone — the label itself ("Not Available for
   Delivery – Pickup Only") carries the meaning, and its icon is the navy the rest are. */


.pdp-key-features {
  margin-bottom: 30px;
}

.pdp-key-features h3 {
  font-size: 16px;
  font-weight: 700;
  margin-bottom: 5px;
}

.pdp-key-features ul {
  list-style: none;
  padding: 0;
  margin-top: 0;
}

.pdp-key-features ul li {
  font-size: 14px;
  font-weight: 400;
  padding-left: 30px;
  position: relative;
  margin-bottom: 5px;
}

.pdp-key-features ul li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 5px;
  display: inline-block;
  width: 16px;
  height: 12px;
  background-repeat: no-repeat;
}

.swiper-slide {
  text-align: center;
  font-size: 18px;
  background: #ffffff;
  display: flex;
  justify-content: center;
  align-items: center;
}

.swiper-slide img {
  display: block;
  width: 100%;
  height: 100%;

}

.swiper-thumbs .swiper-slide img{
  object-fit: contain;
}

.pdp-thumbnails .swiper-slide {
  opacity: 0.6;
  transition: opacity 0.15s ease;
}

.pdp-thumbnails .swiper-slide-thumb-active {
  opacity: 1;
  outline: 2px solid rgb(var(--color-discount));
  outline-offset: -2px;
  border-radius: 4px;
}

.swiper {
  width: 100%;
  height: 400px;
  margin-left: auto;
  margin-right: auto;
}

.pdp-cover-image {
  width: 100%;
  height: 500px;
  /* Mirrors PDP_MAX_COVER_HEIGHT in main-product.html. That script sets an inline
     height to match the info column; max-height still caps an inline height, so this
     holds the ceiling even if the script has not run yet. Keep the two in step. */
  max-height: 560px;
}

.pdp-cover-image .swiper-slide {
  overflow: hidden;
}

.pdp-cover-blur {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* scaled up so the blur doesn't expose transparent edges */
  transform: scale(1.1);
  filter: blur(20px);
  opacity: 0.35;
  pointer-events: none;
}

.pdp-cover-image .swiper-zoom-container {
  position: relative;
  z-index: 1;
  cursor: zoom-in;
}

.pdp-cover-image .swiper-slide-zoomed .swiper-zoom-container {
  cursor: zoom-out;
}

@media (max-width: 958.98px) {
  .pdp-cover-image .swiper-slide {
    height: auto;
  }

  .pdp-cover-image .swiper-zoom-container {
    height: auto;
  }

  .pdp-cover-image .swiper-zoom-container img {
    width: 100%;
    height: auto;
    max-height: 70vh;
    object-fit: contain;
  }
}

.pdp-thumbnails {
  height: 20%;
  box-sizing: border-box;
  padding: 10px 0;
}

/* The thumbnail rail deliberately breaks out of the page gutter to sit edge-to-edge.
   The bleed MUST equal `.page-width`'s side padding — it is a negative margin, so any
   mismatch pushes the rail past the right edge and gives the whole page a horizontal
   scroll. Kept as one variable per breakpoint so the two can't drift again. */
@media (max-width: 958px) {
  .pdp-thumbnails {
    --pdp-rail-bleed: 20px; /* matches --page-padding at this breakpoint */
    margin-left: calc(-1 * var(--pdp-rail-bleed));
    width: calc(100% + (var(--pdp-rail-bleed) * 2));
    padding-left: var(--pdp-rail-bleed);
  }
}

/* base.css narrows .page-width to a hardcoded 5px here (it does NOT use --page-padding,
   which stays 20px), so the rail has to narrow with it. At 20px it overhung the right
   edge by 15px, which is exactly the sliver of sideways scroll seen at 375px and below. */
@media (max-width: 376px) {
  .pdp-thumbnails {
    --pdp-rail-bleed: 5px;
  }
}

.pdp-thumbnails .swiper-slide {
  width: 25%;
  height: 100%;
  opacity: 0.4;
}

.pdp-thumbnails .swiper-slide-thumb-active {
  opacity: 1;
}

/* Thumbnail images fill their slide whichever way the rail is running. The layout
   itself — rail beside the cover from 1400px, strip beneath it between 1198 and
   1399 — is set further up alongside the column widths, so the two stay together. */
@media (min-width: 1198px) {
  .pdp-thumbnails .swiper-slide img {
    width: 100%;
    height: 100%;
    object-fit: cover;
  }
}

/* Product with no images at all: the cover swiper holds a single slide with the
   shared "Photo on the way" panel (see snippets/coming-soon-image), the thumbnail
   rail is hidden, and the counter / "illustration only" note are suppressed —
   neither says anything useful about a product that has no photos. */
.pdp-thumbnails--empty {
  display: none;
}

@media (min-width: 1198px) {
  /* Here the rail is a 145px column to the LEFT of the cover, so removing it
     would let the placeholder slide across into that space and sit out of line
     with every other PDP. Keep the column's footprint, just hide its contents. */
  .pdp-thumbnails--empty {
    display: block;
    visibility: hidden;
  }
}

.pdp-cover-image--empty .pdp-cover-counter,
.pdp-cover-image--empty .pdp-illustration-only {
  display: none;
}

/* The placeholder absolutely fills its positioned parent; on desktop the slide
   inherits the cover's height, but below 959px slides are height:auto (see the
   .pdp-cover-image .swiper-slide rule above), so give it a square footprint. */
.pdp-cover-empty {
  position: relative;
}

@media (max-width: 958.98px) {
  .pdp-cover-empty {
    aspect-ratio: 1 / 1;
    max-height: 70vh;
  }
}

.pdp-whishlist {
  display: block !important;
  /* golden heart (theme gold, same as star ratings) */
  color: rgb(var(--color-discount)) !important;
}

.pdp-whishlist svg *:not([fill="none"]) {
  fill: rgb(var(--color-discount)) !important;
}

.pdp-whishlist svg [stroke]:not([stroke="none"]) {
  stroke: rgb(var(--color-discount)) !important;
}

.pdp-illustration-only {
  position: absolute;
  z-index: 10;
  bottom: 5px;
  left: 5px;
  background-color: rgba(255, 255, 255, 0.89);
  right: 5px;
  padding: 4px 5px;
  font-size: 12px;
  font-weight: 500;
  line-height: 16px;
  border-radius: 2px;
  text-align: center;
}

.swiper-button-disabled {
  opacity: 0 !important;
}

.swiper-button-next, .swiper-button-prev {
  width: 12.27px;
  height: 20px;
  margin-top: -10px;
  color: #0A2749;
}

/* Gallery arrows — a small navy chevron in a white disc, so the control reads over a
   photograph without covering much of it. Shared by the cover image and the thumbnail
   strip; only the diameter differs, because the strip is 84px tall and a full-size
   disc would swallow it. Scoped by parent for the same reason the swiper navigation
   options are (see main-product.html). */
.pdp-cover-image .swiper-button-next,
.pdp-cover-image .swiper-button-prev,
.pdp-thumbnails .swiper-button-next,
.pdp-thumbnails .swiper-button-prev {
  border-radius: 50%;
  background: #ffffff;
  box-shadow: 0 1px 4px rgba(10, 39, 73, 0.2);
  color: #0A2749;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background-color 0.15s ease, box-shadow 0.15s ease;
}

.pdp-cover-image .swiper-button-next:hover,
.pdp-cover-image .swiper-button-prev:hover,
.pdp-thumbnails .swiper-button-next:hover,
.pdp-thumbnails .swiper-button-prev:hover {
  box-shadow: 0 2px 8px rgba(10, 39, 73, 0.28);
}

/* margin-top is always minus half the height, to sit on the vertical centre */
.pdp-cover-image .swiper-button-next,
.pdp-cover-image .swiper-button-prev {
  width: 34px;
  height: 34px;
  margin-top: -17px;
}

.pdp-cover-image .swiper-button-prev {
  left: 14px;
}

.pdp-cover-image .swiper-button-next {
  right: 14px;
}

.pdp-cover-image .swiper-button-next:after,
.pdp-cover-image .swiper-button-prev:after {
  font-size: 13px;
  font-weight: 700;
}

.pdp-thumbnails .swiper-button-next,
.pdp-thumbnails .swiper-button-prev {
  width: 26px;
  height: 26px;
  margin-top: -13px;
}

.pdp-thumbnails .swiper-button-prev {
  left: 6px;
}

.pdp-thumbnails .swiper-button-next {
  right: 6px;
}

/* Vertical rail only (1400px up): the arrows move to the top and bottom edges and the
   chevrons turn with them. `margin-top` is Swiper's own vertical centring, which has to
   go or the top arrow sits half off the rail. Below this the strip runs horizontally
   and keeps the default left/right arrows. */
@media (min-width: 1400px) {
  .pdp-thumbnails .swiper-button-prev,
  .pdp-thumbnails .swiper-button-next {
    left: 50%;
    right: auto;
    margin-top: 0;
    transform: translateX(-50%);
  }

  .pdp-thumbnails .swiper-button-prev {
    top: 4px;
    bottom: auto;
  }

  .pdp-thumbnails .swiper-button-next {
    top: auto;
    bottom: 4px;
  }

  .pdp-thumbnails .swiper-button-prev:after,
  .pdp-thumbnails .swiper-button-next:after {
    transform: rotate(90deg);
  }
}

.pdp-thumbnails .swiper-button-next:after,
.pdp-thumbnails .swiper-button-prev:after {
  font-size: 11px;
  font-weight: 700;
}

.swiper-button-next:after, .swiper-button-prev:after {
  font-size: 20px;
}

/* The desktop thumbnail rail used to run vertically, so its arrows were rotated 90deg
   and pinned to the top and bottom edges. The rail is horizontal at every width now,
   so the arrows keep Swiper's own left/right placement — the same as on mobile. */

.pdp-collapsible {
  margin-bottom: 20px;
  background-color: #ffffff;
}

.pdp-collapsible > h2,
.pdp-collapsible > h3 {
  font-size: 16px;
  font-weight: 700;
  margin-bottom: 0;
  cursor: pointer;
  padding: 20px 20px;
  display: flex;
  justify-content: space-between;
  transition: background-color 0.15s ease;
}

.pdp-collapsible > h2:hover,
.pdp-collapsible > h3:hover {
  background-color: #f6f8fa;
}

.pdp-collapsible > h2:focus-visible,
.pdp-collapsible > h3:focus-visible {
  outline: 2px solid #0A2749;
  outline-offset: -2px;
}

.pdp-collapsible > div {
  padding: 0px 20px 30px 20px;
  transition: max-height 0.3s ease, padding 0.3s ease; 
}

.pdp-collapsible p {
  margin: 0;
}

.pdp-expand + div {
  height: auto;
}

.pdp-collapse + div {
  height: 0 !important;
  padding: 0px 20px 0px 20px;
  overflow: hidden;
}

.pdp-expand::after {
  content: "\2013";
}

.pdp-collapse::after {
  content: "+";
}

.plugin-product-comment-list-wrap {
  margin: 0 !important;
}

.plugin-product-comment-title {
  display: none !important;
}

.isv-web-btn--lg:not(.isv-web-btn-text) {
  padding: 12px 35px !important;
}

.plugin-product-comment-extraConfigWarp {
  margin: 0px auto;
}

@media (max-width: 749.98px) {
  .plugin-product-comment-CommentList, .plugin-product-comment-TabCommentList {
      margin: 0;
  }
  .pdp-reviews > div {
    padding-top: 0;
  }
}

.pdp-product-spec-block {
  display: flex;
  flex-wrap: wrap;
  flex-direction: row;
  margin-top: 20px;
  gap: 15px;
}

.pdp-product-spec-block div {
  width: 48%;
  display: flex;
  justify-content: flex-start;
  font-size: 12px;
  gap: 15px;
}

@media (max-width: 579px) {
  .pdp-product-spec-block div {
    font-size: 13px;
  }
}

@media (max-width: 896px) {
  .pdp-product-spec-block > div {
    width: 100%;
    word-break: break-word;
  }
}

.pdp-product-spec-block > div > div:first-child  {
  font-weight: 700;
}

.pdp-product-spec > div {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 40px 50px;
}

.pdp-product-spec > div > p {
  grid-column: 1 / -1;
  font-size: 12px;
  font-style: italic;
  color: #767676;
}

/* metafield-driven fallback (products without hardcoded spec groups) spans both columns */
.pdp-product-spec > div > .pdp-product-spec-block {
  grid-column: 1 / -1;
}

@media (max-width: 896px) {
  .pdp-product-spec > div {
    grid-template-columns: 1fr;
  }
}

.pdp-spec-group .pdp-product-spec-block {
  margin-top: 10px;
}

.pdp-spec-group .pdp-product-spec-block > div {
  width: 100%;
  display: grid;
  grid-template-columns: 40% 1fr;
  align-items: start;
  column-gap: 15px;
  border-bottom: 1px solid #edf0f3;
  padding-bottom: 8px;
}

.pdp-spec-group .pdp-product-spec-block > div:last-child {
  border-bottom: none;
  padding-bottom: 0;
}

/* label + value both left-aligned; override the generic 48%/flex rule above */
.pdp-spec-group .pdp-product-spec-block > div > div {
  width: auto;
  display: block;
  text-align: left;
}

.pdp-spec-group-title {
  font-size: 14px;
  font-weight: 700;
  margin: 0 0 20px;
  padding-bottom: 10px;
  border-bottom: 1px solid #edf0f3;
  color: #0A2749;
}

/* Technical line drawing — a compact thumbnail; clicking opens the
   full-resolution image in a modal dialog, which is where it's actually read.
   Renders as a group inside Product Specifications, so it spans both spec columns. */
.pdp-product-spec > div > .pdp-dimension-drawing {
  grid-column: 1 / -1;
}

/* HIB spec section isn't a grid — space it off the spec table above instead */
.hib-spec-raw + .pdp-dimension-drawing {
  margin-top: 28px;
}

/* left-aligned so it lines up with the spec group labels above it */
.pdp-dimension-stack {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
}

.pdp-dimension-figure {
  margin: 0;
  text-align: left;
}

.pdp-dimension-zoom {
  display: inline-block;
  max-width: 220px;
  padding: 8px;
  border: 1px solid #e5e7eb;
  border-radius: 6px;
  background: #fff;
  cursor: zoom-in;
  line-height: 0;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.pdp-dimension-zoom:hover,
.pdp-dimension-zoom:focus-visible {
  border-color: #C09955;
  box-shadow: 0 4px 14px rgba(10, 39, 73, 0.1);
}

.pdp-dimension-zoom img {
  display: block;
  max-width: 100%;
  height: auto;
}

.pdp-dimension-label {
  display: block;
  margin-top: 10px;
  font-size: 0.85rem;
  font-weight: 700;
  color: #0A2749;
}

.pdp-dimension-hint {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 10px;
  font-size: 0.8rem;
  color: #6b7280;
}

.pdp-dimension-label + .pdp-dimension-hint {
  margin-top: 4px;
}

.pdp-dimension-hint svg {
  flex: 0 0 auto;
  width: 14px;
  height: 14px;
}

/* enlarged view */
.pdp-dimension-dialog {
  padding: 48px 20px 20px;
  border: none;
  border-radius: 8px;
  background: #fff;
  max-width: 92vw;
  max-height: 92vh;
}

.pdp-dimension-dialog::backdrop {
  background: rgba(10, 39, 73, 0.72);
}

.pdp-dimension-dialog img {
  display: block;
  max-width: 100%;
  max-height: 78vh;
  width: auto;
  height: auto;
  margin: 0 auto;
}

.pdp-dimension-dialog-close {
  position: absolute;
  top: 8px;
  right: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: #0A2749;
  color: #fff;
  font-size: 24px;
  line-height: 1;
  cursor: pointer;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
}

.pdp-dimension-dialog-close:hover {
  background: #C09955;
}

/* Cross-product "variant" dropdowns in the buy area */
/* Gap above the picker — matches the original select's 20px top spacing */
.pdp-product-container .variant-selects {
  margin-top: 20px;
}

.pdp-variants {
  display: flex;
  flex-direction: column;
  gap: 22px;
  margin-bottom: 18px;
}

/* 13px, not 12. Bumped for the Buy Together card, whose labels are sentences
   ("Select Your Waste & Traps") rather than the one word the option axes carry, and
   read cramped at 12. Changed HERE rather than only on the card so the two stay
   identical — they sit in the same column asking the same kind of question, and a
   1px difference between them is visible. */
.pdp-variant-label {
  display: block;
  font-size: 13px;
  font-weight: normal;
  color: #0A2749;
  margin-bottom: 6px;
  border-bottom: 1px solid #d5dbe1;
}

/* Text swatches — short, non-colour option axes (Power, Material, Hand, Finish,
   and size lists under the cut-off) render every value as a button instead of
   hiding them inside the dropdown. Borders and type match .pdp-variant-summary
   so a buttoned axis and a dropdown axis sit together without clashing. */
.pdp-variant-buttons {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.pdp-variant-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 10px 14px;
  border: 1px solid #d5dbe1;
  border-radius: 0;
  background: #fff;
  color: #0A2749;
  font-size: 14px;
  line-height: 1.3;
  text-align: center;
  text-decoration: none;
  transition: border-color 0.15s ease, background-color 0.15s ease;
}

a.pdp-variant-btn:hover {
  border-color: #0A2749;
}

/* The :hover half is not redundant. base.css carries
   `a:not(.button):hover { color: rgba(var(--color-text)) }`, which scores 0,2,1 against
   this rule's 0,2,0 — so hovering the selected button repainted its white text navy,
   the same colour as its own fill, and the label vanished. Naming the anchor and the
   hover state here takes it to 0,3,1 and keeps the text white. */
.pdp-variant-btn.is-current,
a.pdp-variant-btn.is-current:hover {
  background: #0A2749;
  border-color: #0A2749;
  color: #ffffff;
  cursor: default;
}

.pdp-variant-btn:focus-visible {
  outline: 2px solid #0A2749;
  outline-offset: 2px;
}

/* ─── Colour swatches ─────────────────────────────────────────────────────────
   A colour chip with its name underneath, no price. The colours are named here
   rather than sampled from the product photography: the shots are room scenes, so
   an average comes out as the room, not the finish — measured across 163 of them,
   two photos of the same finish differ from each other by more than two different
   finishes do, and the naive average returns a LIGHTER colour for Matt Black than
   for Gloss White.
   The chip carries the product image as an inline background; every finish named
   below clears it with `background-image: none !important`, which outranks an inline
   style. So an unnamed finish keeps the photo — right for flooring and tiles, where
   the photo IS the finish — and a named one gets its flat colour.
   The list below covers about 97% of colour rows in the catalogue. */
.pdp-colour-swatches {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}

.pdp-colour-item {
  width: 68px;
  text-decoration: none;
  color: #0A2749;
  /* Left, not centred: the chip is narrower than the cell the label needs, so
     centring pushed the first chip 12px in from the label above it. */
  text-align: left;
}

.pdp-colour-dot {
  display: block;
  position: relative; /* containing block for the selected tick */
  width: 44px;
  height: 44px;
  margin: 0;
  border: 1px solid #000000;
  border-radius: 0;
  background-color: #f2f4f7;
  background-size: cover;
  background-position: center;
  transition: outline-color 0.15s ease;
  outline: 2px solid transparent;
  outline-offset: 2px;
}

/* Hover uses an outline rather than a thicker border, so the hairline stays exactly 1px
   and nothing shifts by a pixel as you move across the row. Grey, not navy — navy read as
   a hard black line against the chip's own border. */
a.pdp-colour-item:hover .pdp-colour-dot {
  outline-color: #c6d0da;
}

/* SELECTED — a navy tick with a white border, sitting directly on the chip. This replaced
   a darker grey ring on the outside; with an outline on hover as well, the two states
   differed only in the shade of the ring, which is a weak signal for the one thing on the
   page you most need to be sure of. The label under the chip still goes bold, so selection
   reads twice.

   It has to survive ANY chip. Flat colours run the full range here — Gloss White through
   Bare Metal's mid grey to Matt Black — and a finish with no colour mapped in this
   stylesheet falls back to `background-image` on the PRODUCT PHOTO (see
   .local/audit-colours.mjs), which can be any tones at all. Navy plus a white border
   covers both directions: on a light chip the navy reads and the border is invisible; on a
   dark one the navy sinks in and the border carries the shape.

   TWO STACKED TICKS, not a filter. The obvious way to outline a shape is chained
   drop-shadows, and it does not work here: each shadow is cast by the RESULT of the one
   before, so the white shadows shadow each other and the outline grows far past its
   nominal width — at 1px per pass the tick already read as solid white on Matt Black, with
   the navy core swallowed. Two elements make both widths exact instead of emergent.

   The geometry is the part worth keeping. Both boxes are concentric — same anchor, same
   `translate(-50%, -50%)` — and a border-box draws its border INSIDE the edge, so equal
   boxes would leave the two strokes flush on the outside with white showing only on the
   inner side. Centring the navy stroke within the white one needs the navy box smaller by
   exactly the difference in border widths:

     W_navy = W_white - B_white + B_navy    10 - 5 + 3 = 8
     H_navy = H_white - B_white + B_navy    18 - 5 + 3 = 16

   which leaves (5 - 3) / 2 = 1px of white on every side.

   Those numbers also have to keep the shape reading as a TICK. The box's width is the
   short arm, its height the long arm, and the border is the stroke — so the stroke has to
   stay well under the arms. A first pass at 9x16 with a 6px border put the stroke at
   two-thirds of the short arm: the white filled its own box and the result read as a
   square outline with a tick inside it. Roughly stroke <= H/6 and W ~ H/2 holds the
   checkmark shape.

   The nudge is on `top`, in pixels, NOT on the translate: a percentage translate resolves
   against each element's OWN height, so -60% would move the two boxes by different amounts
   and pull them off centre. 2px up, because a checkmark's visual centre sits above its box
   centre.

   `mix-blend-mode: difference` was the tempting one-liner and is wrong for the same job: it
   inverts, so a mid grey like Bare Metal maps to almost exactly itself and the tick
   vanishes at the one value it most needs to work at. */
.pdp-colour-item.is-current .pdp-colour-dot::before,
.pdp-colour-item.is-current .pdp-colour-dot::after {
  content: "";
  position: absolute;
  left: 50%;
  top: calc(50% - 2px);
  border-style: solid;
  transform: translate(-50%, -50%) rotate(45deg);
}

/* the white border, underneath */
.pdp-colour-item.is-current .pdp-colour-dot::before {
  width: 10px;
  height: 18px;
  border-color: #ffffff;
  border-width: 0 5px 5px 0;
}

/* the navy tick, on top — ::after paints over ::before */
.pdp-colour-item.is-current .pdp-colour-dot::after {
  width: 8px;
  height: 16px;
  border-color: #0A2749;
  border-width: 0 3px 3px 0;
}

.pdp-colour-label {
  display: block;
  margin-top: 8px;
  font-size: 11px;
  line-height: 1.3;
  color: #41546E;
}

.pdp-colour-item.is-current .pdp-colour-label {
  font-weight: 700;
  color: #0A2749;
}

.pdp-colour-item:focus-visible {
  outline: 2px solid #0A2749;
  outline-offset: 2px;
}

/* Named finishes drop the photo. */
.pdp-colour-dot[data-colour="matt black"],
.pdp-colour-dot[data-colour="black"],
.pdp-colour-dot[data-colour="matt anthracite"],
.pdp-colour-dot[data-colour="anthracite"],
.pdp-colour-dot[data-colour="gloss white"],
.pdp-colour-dot[data-colour="high gloss white"],
.pdp-colour-dot[data-colour="white"],
.pdp-colour-dot[data-colour="matt white"],
.pdp-colour-dot[data-colour="matt grey"],
.pdp-colour-dot[data-colour="grey"],
.pdp-colour-dot[data-colour="matt cappuccino"],
.pdp-colour-dot[data-colour="cappuccino"],
.pdp-colour-dot[data-colour="cashmere"],
.pdp-colour-dot[data-colour="matt cobalt blue"],
.pdp-colour-dot[data-colour="bare metal"],
.pdp-colour-dot[data-colour="sage green"],
.pdp-colour-dot[data-colour="savannah green"],
.pdp-colour-dot[data-colour="sahara"],
.pdp-colour-dot[data-colour="black high gloss"],
.pdp-colour-dot[data-colour="black effect"],
.pdp-colour-dot[data-colour="blue"] {
  background-image: none !important;
}

.pdp-colour-dot[data-colour="matt black"] { background-color: #1C1C1E; }
.pdp-colour-dot[data-colour="black"] { background-color: #1A1A1A; }
.pdp-colour-dot[data-colour="matt anthracite"],
.pdp-colour-dot[data-colour="anthracite"] { background-color: #3E4245; }
.pdp-colour-dot[data-colour="gloss white"],
.pdp-colour-dot[data-colour="high gloss white"] { background-color: #FFFFFF; }
.pdp-colour-dot[data-colour="white"] { background-color: #FCFCFA; }
.pdp-colour-dot[data-colour="matt white"] { background-color: #F2F2EE; }
.pdp-colour-dot[data-colour="matt grey"] { background-color: #8C9297; }
.pdp-colour-dot[data-colour="grey"] { background-color: #9AA0A5; }
.pdp-colour-dot[data-colour="matt cappuccino"] { background-color: #B9A894; }
.pdp-colour-dot[data-colour="cashmere"] { background-color: #E0D8C8; }
.pdp-colour-dot[data-colour="matt cobalt blue"] { background-color: #2B4C7E; }

/* Metallics are a gradient, so they set background-image rather than clearing it. */
.pdp-colour-dot[data-colour="chrome"],
.pdp-colour-dot[data-colour="mirror polished"] {
  background-image: linear-gradient(135deg, #F4F7F9, #B4BDC4 42%, #EDF1F4 58%, #98A2AA) !important;
}

.pdp-colour-dot[data-colour="brushed"] {
  background-image: linear-gradient(135deg, #E8EBEE, #B9C0C6 45%, #DCE1E5 60%, #A8B0B7) !important;
}

.pdp-colour-dot[data-colour="brushed brass"] {
  background-image: linear-gradient(135deg, #E6CD7C, #B8912F 55%, #D9BC63) !important;
}

.pdp-colour-dot[data-colour="brushed bronze"],
.pdp-colour-dot[data-colour="bronze effect"] {
  background-image: linear-gradient(135deg, #C89B6A, #8C5A2B 55%, #B98552) !important;
}

.pdp-colour-dot[data-colour="black gold"] {
  background-image: linear-gradient(135deg, #3A3A3A, #1C1C1E 45%, #C9A227) !important;
}

/* ── Added Aug 2026 from .local/audit-colours.mjs ─────────────────────────────
   Every finish below appeared on a row alongside already-named colours, so each
   was showing a photo next to flat chips. Only plain finishes are named here —
   the patterns the audit also found (Carrara, Loft Concrete, Onyx, Classic Oak,
   Marble White and the rest) deliberately keep their photo, because a flat colour
   cannot stand in for a marble vein or a wood grain. Re-run the audit after
   editing to see what is left. */
.pdp-colour-dot[data-colour="bare metal"] { background-color: #8A8D8F; }
.pdp-colour-dot[data-colour="sage green"] { background-color: #9CA98C; }
.pdp-colour-dot[data-colour="savannah green"] { background-color: #7D8B6A; }
.pdp-colour-dot[data-colour="sahara"] { background-color: #C9B393; }
.pdp-colour-dot[data-colour="cappuccino"] { background-color: #B9A894; }
.pdp-colour-dot[data-colour="black high gloss"] { background-color: #0E0E0E; }
.pdp-colour-dot[data-colour="black effect"] { background-color: #1A1A1A; }
.pdp-colour-dot[data-colour="blue"] { background-color: #2F5A8C; }

/* Metallics — gradients, so they overwrite the photo rather than clearing it. */
.pdp-colour-dot[data-colour="brushed gunmetal"] {
  background-image: linear-gradient(135deg, #7A7F83, #4A4E52 50%, #6A6F73) !important;
}

.pdp-colour-dot[data-colour="polished stainless steel"],
.pdp-colour-dot[data-colour="stainless steel"],
.pdp-colour-dot[data-colour="polished aluminium"],
.pdp-colour-dot[data-colour="bright silver"],
.pdp-colour-dot[data-colour="silver effect"],
.pdp-colour-dot[data-colour="silver/frosted"],
.pdp-colour-dot[data-colour="chrome effect"] {
  background-image: linear-gradient(135deg, #F4F7F9, #B4BDC4 42%, #EDF1F4 58%, #98A2AA) !important;
}

.pdp-colour-dot[data-colour="brushed nickel"],
.pdp-colour-dot[data-colour="brushed stainless steel"],
.pdp-colour-dot[data-colour="satin nickel"],
.pdp-colour-dot[data-colour="satin silver"] {
  background-image: linear-gradient(135deg, #DAD6CF, #ADA79E 50%, #C8C3BA) !important;
}

.pdp-colour-dot[data-colour="brass effect"],
.pdp-colour-dot[data-colour="gold/brushed brass"] {
  background-image: linear-gradient(135deg, #E6CD7C, #B8912F 55%, #D9BC63) !important;
}

.pdp-variant-select {
  position: relative;
}

.pdp-variant-summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 10px 12px;
  /* The quantity stepper's border, exactly: it draws a 1px ring in
     rgba(var(--color-text), var(--input-border-opacity)) from a ::after, which
     resolves to rgba(10, 39, 73, 0.2) — navy at a fifth. Solid navy was tried and
     is too heavy: it gives an input the weight of the Add to Cart button, and five
     of them stacked fights the one control that should be loudest on the page. */
  border: 1px solid rgba(10, 39, 73, 0.2);
  border-radius: 0;
  font-size: 14px;
  background: #fff;
  transition: border-color 0.15s ease;
}

.pdp-variant-summary::-webkit-details-marker {
  display: none;
}

/* Resting at a fifth opacity, hover and open go to the full navy — the same
   darken-on-approach the control had before, and now visible again. */
.pdp-variant-summary:hover,
.pdp-variant-select[open] .pdp-variant-summary {
  border-color: #0A2749;
}

.pdp-variant-select[open] .pdp-variant-summary {
  border-bottom-left-radius: 0;
  border-bottom-right-radius: 0;
}

.pdp-variant-summary-value {
  font-weight: normal;
  /* Takes the slack so the count and chevron sit together on the right, rather than
     space-between spreading all three evenly across the control. */
  flex: 1;
  min-width: 0;
}

/* How many choices are hidden behind a closed dropdown. Smaller and grey, and now
   normal weight too: it is a footnote about the control, and semibold made it
   compete with the value it sits beside — most visibly on the Buy Together card,
   where the value is a row of thumbnails and the count was the loudest thing in
   the control. */
.pdp-variant-more {
  flex: 0 0 auto;
  font-size: 12.5px;
  font-weight: normal;
  color: #41546E;
  white-space: nowrap;
}

.pdp-variant-chevron {
  width: 16px;
  height: 16px;
  flex: none;
  transition: transform 0.15s ease;
}

.pdp-variant-select[open] .pdp-variant-chevron {
  transform: rotate(180deg);
}

.pdp-variant-list {
  position: absolute;
  z-index: 20;
  top: 100%;
  left: 0;
  right: 0;
  margin: 0;
  padding: 4px;
  list-style: none;
  max-height: 320px;
  overflow-y: auto;
  background: #fff;
  border: 1px solid #0A2749;
  border-top: none;
  border-radius: 0 0 6px 6px;
  box-shadow: 0 8px 20px rgba(10, 39, 73, 0.12);
}

.pdp-variant-item {
  position: relative;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 5px;
  border-radius: 4px;
  text-decoration: none;
  color: inherit;
}

a.pdp-variant-item:hover {
  background: #f6f8fa;
}

.pdp-variant-item.is-current {
  background: rgba(192, 153, 85, 0.12);
  box-shadow: inset 0 0 0 1px #C09955;
  cursor: default;
}

.pdp-variant-item-img {
  width: 44px;
  height: 44px;
  flex: none;
  object-fit: cover;
  border-radius: 4px;
  background: #f2f4f6;
}

/* Broken drive.google.com image → "Photo on the way" placeholder, shrunk to the
   44px thumbnail slot (title/sub hidden — no room for text at this size).
   Must stay position:relative so it is the containing block for its own
   absolutely-positioned shimmer/grid/frame pseudo-elements — otherwise they
   escape the 44px box, resolve against the full-width row, and the shimmer's
   translateX(100%) overflows the overflow-y:auto list, forcing a horizontal
   scrollbar (visible on hover in Chrome/Safari overlay scrollbars). */
.pdp-variant-item .coming-soon-image {
  position: relative;
  flex: none;
  width: 44px;
  height: 44px;
  min-width: 44px;
  aspect-ratio: 1 / 1;
  padding: 0;
  gap: 0;
  border-radius: 4px;
  overflow: hidden;
}

.pdp-variant-item .coming-soon-image__title,
.pdp-variant-item .coming-soon-image__sub {
  display: none;
}

.pdp-variant-item .coming-soon-image__frame {
  inset: 3px;
  border-radius: 4px;
}

.pdp-variant-item-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex: 1;
  min-width: 0;
}

.pdp-variant-item-name {
  font-size: 13px;
  font-weight: normal;
  color: #0A2749;
}

/* Selected item: big gold tick overlaid on the thumbnail. Needs a z-index above
   the "Photo on the way" placeholder, which keeps z-index: 1 from
   .coming-soon-image--fill and would otherwise paint over the tick on rows whose
   product has no image (or only a dead Drive one). */
.pdp-variant-item.is-current::after {
  content: "\2714";
  position: absolute;
  z-index: 2;
  top: 50%;
  left: 5px;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 4px;
  background: rgba(192, 153, 85, 0.6);
  color: #fff;
  font-size: 22px;
  line-height: 1;
  pointer-events: none;
}

.pdp-variant-item-sub {
  display: flex;
  align-items: baseline;
  gap: 8px;
  font-size: 12px;
  color: #767676;
}

/* Two lines, not one. The row's option name can repeat across siblings (two
   products both named "Black", differing only by upgrade tier), so this title
   is what tells them apart — and the distinguishing part sits at the END of it.
   Catalogue titles run 42 chars at the median and 62 at p90, while this column
   fits roughly 41 at a typical desktop buy-column width; 224 sibling groups are
   character-identical for their first 38+. A single-line ellipsis therefore
   clips exactly the part that disambiguates, collapsing e.g.
   "Cirque Illuminated Magnifying Bathroom Mirror - Black" and
   "…- Brushed Brass" into the same visible string. */
.pdp-variant-item-desc {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: normal;
  min-width: 0;
}

.pdp-variant-item-price {
  margin-left: auto;
  flex: none;
  white-space: nowrap;
  font-weight: normal;
  color: #0A2749;
}

/* Under the price, once a Buy Together extra is chosen: says what the figure above
   now includes and what the product costs on its own. The price changing silently
   would be the worse outcome — the customer has to be able to see why. Quiet, since
   it is a footnote to the price rather than a second price. */
.pdp-price-extras {
  margin-top: 4px;
  font-size: 12.5px;
  color: #41546E;
}

/* ─── A chosen extra's photograph, in the product's own gallery ────────────────
   Appended after the product's own media when a Buy Together dropdown is set, and
   removed when it goes back to "Not required". */

/* contain, not cover. The product's own slides may crop to fill; an accessory shot
   is a single plain photograph of a small object and cropping it loses the object. */
.pdp-extra-slide {
  display: flex;
  align-items: center;
  justify-content: center;
}

.pdp-extra-slide .swiper-zoom-container img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

/* Names whose photograph this is. A trap or a set of legs sitting among a bath's own
   shots otherwise reads as part of the bath — which is the one thing a product gallery
   must not say.

   TOP-left. The bottom edge is already taken: .pdp-illustration-only runs across it and
   the slide counter sits there too, and the caption landed underneath both. Top-left is
   clear — the wishlist heart is top-RIGHT. */
.pdp-extra-slide-caption {
  position: absolute;
  z-index: 2;
  left: 12px;
  top: 12px;
  max-width: calc(100% - 24px);
  padding: 4px 10px;
  border-radius: 3px;
  background-color: rgba(255, 255, 255, 0.92);
  font-size: 12px;
  color: #41546E;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Marks the extras apart in the thumbnail rail, so the run of the product's own
   images stays readable as one set. */
.pdp-extra-thumb {
  position: relative;
}

.pdp-extra-thumb::after {
  content: "";
  position: absolute;
  inset: 0;
  border: 1px dashed rgba(10, 39, 73, 0.35);
  pointer-events: none;
}

.pdp-extra-thumb img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.pdp-breadcrumb {
  margin-bottom: 20px;
}

footer {
  padding-top: 80px !important;
}

/* The ipad end responds to the mobile end in vertical screen */
/* @custom-media --tablet (max-width: 959px); */
/* @custom-media --gt-mobile (min-width: 751px); */
/* detectingScreen need to consider the configuration of the tablet */

/* ─── Option pickers below the three-column layout ────────────────────────────
   Everything above this line was written and measured against the 600px buy
   panel the >=1198px layout gives it. Under that the column is much narrower,
   and in two different ways, so this block covers both:

     959 - 1197px   a FIXED 310px column — narrower than a phone gets, and the
                    worst rendering of the picker anywhere. The 17-value
                    Malmesbury size axis falls to 8 rows of 2-3 here.
     below 959px    full page width: 365px at a 375px viewport, because
                    base.css:120 drops .page-width padding to 5px a side under
                    376px.

   Both pickers switch from flex to an even-column grid. As flex rows they were
   content-width, so no two rows started at the same x and a size list read as a
   ragged pile rather than a grid — the Malmesbury axis had rows starting at
   5/104/203, then 5/104/211, then 5/112/219. Measured over CDP against the
   preview theme at 320/375/414/768/960/1100px; the numbers below are from that
   run, and 1200px and up are byte-identical to before. */
@media (max-width: 1197.98px) {
  .pdp-variant-buttons {
    display: grid;
    /* The column floor comes from the axis's OWN banded label length, published
       as --pdp-btn-min by product-picker-option.html. A single fixed floor cannot
       serve both ends: a flat 104px aligns "600 x 1040" nicely but forces a four-across
       axis of short values down to three, which cost 56px of height on the
       Portland panel. Driven off the band, that axis keeps its four. */
    grid-template-columns: repeat(auto-fill, minmax(var(--pdp-btn-min, 104px), 1fr));
  }

  /* 40px was under the 44px touch minimum. This is the only height these rules
     add — every measured axis grew by exactly 4px per button row and nothing
     else. */
  .pdp-variant-btn {
    min-height: 44px;
    padding: 10px 8px;
  }

  .pdp-colour-swatches {
    display: grid;
    /* 68px is the desktop item width, so the columns never get narrower than the
       44px chip plus its breathing room — but as a 1fr track each column takes a
       share of the leftover instead of leaving it as dead gap, which widens the
       label and stops the longer finish names wrapping to a third line. Worth
       57px on the 13-value Satinpanel axis (412px -> 355px). */
    grid-template-columns: repeat(auto-fill, minmax(68px, 1fr));
    /* Rows size to their own tallest label rather than the tallest in the block. */
    align-items: start;
  }

  /* The grid track sets the width now; leaving the fixed 68px on the item would
     pin it to the left of a wider column and re-open the gap this is closing. */
  .pdp-colour-item {
    width: auto;
  }

  /* 22px between option groups was set when a product had two or three of them. The
     fourth slot makes it four, and 22px x 4 is 88px of gap on a phone. Measured at
     425px on the live pages: Addington II (Colour/Orientation/Size/Type) put Add to
     cart 610px below the top of the options, so on a 650px screen its bottom edge was
     clipped by 8px. At 18px it lands at 598 and fits, with Imperia at 584 and Guardia
     at 549 — every page gains 12px and none is worse.

     18 rather than 16: it is the smallest step that clears the one page that was
     clipped, and the groups still read as separate blocks. A 320px phone still needs a
     scroll on the four-picker pages, which is expected — that screen is 568px tall, so
     even the three-picker pages do not fit it. */
  .pdp-variants {
    gap: 18px;
  }
}

/* ─── Row cap ──────────────────────────────────────────────────────
   WIDTH IS THE WRONG THING TO KEY ON, so this block covers everything under the
   1198px desktop layout and section-main-product.js decides per axis, on the rows
   it actually renders (MIN_ROWS). Width alone gets it wrong in both directions:

     1400px   4 rows / 208px   fine — the buy panel is 600px, outside this block
     1100px   6 rows / 329px   the TALLEST the picker renders anywhere, because the
                               column is a fixed 310px here, narrower than a phone
      768px   3 rows / 173px   already short; capping would hide half to save 38px
      425px   6 rows / 135px   capped

   A phones-only cut (767.98px) was tried first and left 1100px — the worst case in
   the theme — untouched while capping 768px, which did not need it. Four rows or
   more is the line, wherever it happens. */
@media (max-width: 1197.98px) {
  .pdp-variant-buttons.is-capped {
    overflow: hidden;

    --pdp-fade: linear-gradient(to bottom,
      rgba(0, 0, 0, 1)       0%,
      rgba(0, 0, 0, 0.9904)  6.25%,
      rgba(0, 0, 0, 0.9619) 12.5%,
      rgba(0, 0, 0, 0.9157) 18.75%,
      rgba(0, 0, 0, 0.8536) 25%,
      rgba(0, 0, 0, 0.7778) 31.25%,
      rgba(0, 0, 0, 0.6913) 37.5%,
      rgba(0, 0, 0, 0.5976) 43.75%,
      rgba(0, 0, 0, 0.5)    50%,
      rgba(0, 0, 0, 0.4025) 56.25%,
      rgba(0, 0, 0, 0.3087) 62.5%,
      rgba(0, 0, 0, 0.2222) 68.75%,
      rgba(0, 0, 0, 0.1464) 75%,
      rgba(0, 0, 0, 0.0843) 81.25%,
      rgba(0, 0, 0, 0.0381) 87.5%,
      rgba(0, 0, 0, 0.0096) 93.75%,
      rgba(0, 0, 0, 0)     100%);

    -webkit-mask-image: linear-gradient(#000, #000), var(--pdp-fade);
            mask-image: linear-gradient(#000, #000), var(--pdp-fade);
    -webkit-mask-size: 100% var(--pdp-solid, 100%), 100% var(--pdp-peek, 0px);
            mask-size: 100% var(--pdp-solid, 100%), 100% var(--pdp-peek, 0px);
    -webkit-mask-position: left top, left bottom;
            mask-position: left top, left bottom;
    -webkit-mask-repeat: no-repeat;
            mask-repeat: no-repeat;
  }

  /* The selected value echoed into the label — "Size: 600 x 470". Mobile only, and
     only on a capped axis, where the chosen button is often scrolled out of the peek.
     Colour is exempt for the same reason it is never capped, and a dropdown axis
     already names its value in the summary, so neither gets one.

     Weight rather than colour carries it: the label is 12px navy at normal weight, and
     the value sits on the same line one step heavier. Anything stronger competes with
     the buttons underneath, which are the thing to look at. */
  .pdp-variant-current {
    font-weight: 600;
  }

  .pdp-variant-current::before {
    content: ': ';
    font-weight: normal;
  }

  /* A text link, not a full-width button. Measured on the Addington vertical axis:
     a 48px button costs more height than three-row capping saves, which puts Add to
     cart back off the screen and undoes the whole thing. This is 28px with its
     margin. */
  .pdp-option-more {
    display: block;
    /* Full width so text-align can do the centring — the button is only as wide as
       its text otherwise, and centring a shrink-wrapped block does nothing. */
    width: 100%;
    /* 8px sat the link tight under the fade, which made it read as part of the
       clipped row rather than a control. The gap between option groups is 22px, so
       16px keeps it clearly attached to its own axis while giving the fade room to
       finish. */
    margin-top: 16px;
    padding: 0;
    border: 0;
    background: none;
    font: inherit;
    font-size: 12px;
    font-weight: 500;
    line-height: 20px;
    text-transform: uppercase;
    /* Capitals were drawn to sit at lowercase density, so uppercase at 12px reads
       cramped without tracking. This is the only uppercase text in the buy column. */
    letter-spacing: 0.06em;
    /* No text-indent to compensate for the trailing letter-space: measured across
       0 to 0.06em at 425px, zero indent already lands the ink on centre (-0.003px)
       and every non-zero value pushes it right. Chrome is already accounting for it. */
    color: #0A2749;
    text-align: center;
    text-decoration: underline;
    text-underline-offset: 3px;
    cursor: pointer;
  }

  .pdp-option-more:hover {
    text-decoration-thickness: 2px;
  }

  .pdp-option-more:focus-visible {
    outline: 2px solid #0A2749;
    outline-offset: 2px;
  }

  /* `display: block` above outranks the UA stylesheet's rule for the hidden
     attribute, so an axis short enough not to need the toggle would still show one.
     Without JS no toggle is created at all, so there is nothing to fall back to. */
  .pdp-option-more[hidden],
  .pdp-variant-current[hidden] {
    display: none;
  }
}

/* Above the desktop breakpoint the buy panel is 600px and no axis runs long enough
   to need this — off, including on a resize from narrow to wide before the JS
   re-runs. */
@media (min-width: 1198px) {
  .pdp-option-more,
  .pdp-variant-current {
    display: none;
  }

  .pdp-variant-buttons {
    max-height: none;
    overflow: visible;
  }
}
