[object Object]

← back to Designer Wallcoverings

auto-save: 2026-06-30T20:13:04 (3 files) — pending-approval/boost-filter-consolidation-2026-06-25 vendor-scrapers/china-seas-refresh shopify/theme-fixes/custom-js-qty-2026-06-30/

67ffd7848b1b13c0fe9aa1ebe6c8b1a0566fba57 · 2026-06-30 20:13:10 -0700 · Steve Abrams

Files touched

Diff

commit 67ffd7848b1b13c0fe9aa1ebe6c8b1a0566fba57
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Tue Jun 30 20:13:10 2026 -0700

    auto-save: 2026-06-30T20:13:04 (3 files) — pending-approval/boost-filter-consolidation-2026-06-25 vendor-scrapers/china-seas-refresh shopify/theme-fixes/custom-js-qty-2026-06-30/
---
 .../theme-fixes/custom-js-qty-2026-06-30/custom.js | 511 +++++++++++++
 .../theme-fixes/custom-js-qty-2026-06-30/diag.cjs  |  52 ++
 .../element.quantity-selector.js                   |  93 +++
 ...locks___section-flex-pdp-quantity-picker.liquid |  15 +
 .../liquid/snippets__product-form-content.liquid   | 800 +++++++++++++++++++++
 ...ippets__section.flex-pdp.quantity-picker.liquid |  70 ++
 .../theme-fixes/custom-js-qty-2026-06-30/probe.cjs |  72 ++
 .../theme-fixes/custom-js-qty-2026-06-30/trace.cjs |  45 ++
 8 files changed, 1658 insertions(+)

diff --git a/shopify/theme-fixes/custom-js-qty-2026-06-30/custom.js b/shopify/theme-fixes/custom-js-qty-2026-06-30/custom.js
new file mode 100644
index 00000000..64d9005e
--- /dev/null
+++ b/shopify/theme-fixes/custom-js-qty-2026-06-30/custom.js
@@ -0,0 +1,511 @@
+/*========== 020 Custom js for quantity ===================*/
+
+function mm_refresh_quantity_increments() {  
+    jQuery("div.mm_quantity:not(.mm_buttons_added), td.mm_quantity:not(.mm_buttons_added)").each(function(a, b) {
+        var c = jQuery(b);
+        c.addClass("mm_buttons_added"), c.children().first().before('<input type="button" value="-" class="minus" />'), c.children().last().after('<input type="button" value="+" class="plus" />')
+    })
+}
+String.prototype.getDecimals || (String.prototype.getDecimals = function() {
+    var a = this,
+        b = ("" + a).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);
+    return b ? Math.max(0, (b[1] ? b[1].length : 0) - (b[2] ? +b[2] : 0)) : 0
+}), jQuery(document).ready(function() {
+    mm_refresh_quantity_increments()
+
+    // Custom popup contact form (moved from snippets/product.liquid)
+    if (jQuery('.custom-popup-contact-form').length > 0) {
+      jQuery('.custom-popup-contact-form').on('click', function (e) {
+        e.preventDefault();
+        jQuery('#custom-popup-overlay').show();
+      });
+    }
+
+    if (jQuery('#custom-popup-overlay .custom-close').length > 0) {
+      jQuery('#custom-popup-overlay .custom-close').on('click', function () {
+        jQuery('#custom-popup-overlay').hide();
+      });
+    }
+
+    if (jQuery('#custom-popup-overlay .success-message').length > 0) {
+      jQuery('.custom-contact-message').html('Thank you. We will respond to your message shortly.');
+    }
+
+    if (jQuery('#custom-popup-overlay .error-message').length > 0) {
+      jQuery('.custom-contact-message').html(jQuery('#custom-popup-overlay .error-message').html());
+    }
+}), jQuery(document).on("updated_wc_div", function() {
+    mm_refresh_quantity_increments()
+}), jQuery(document).on("click", ".plus, .minus", async function(event) {
+    event.preventDefault();
+    
+    var a = jQuery(this).closest(".mm_quantity").find(".qty"),
+        b = parseFloat(a.val()),
+        c = parseFloat(a.attr("max")),
+        d = parseFloat(a.attr("min")),
+        e = a.attr("step");
+    //b && "" !== b && "NaN" !== b || (b = 0), "" !== c && "NaN" !== c || (c = ""), "" !== d && "NaN" !== d || (d = 0), "any" !== e && "" !== e && void 0 !== e && "NaN" !== parseFloat(e) || (e = 1), jQuery(this).is(".plus") ? c && b >= c ? a.val(c) : a.val((b + parseFloat(e)).toFixed(e.getDecimals())) : d && b <= d ? a.val(d) : b > 0 && a.val((b - parseFloat(e)).toFixed(e.getDecimals())), a.trigger("change")
+     b && "" !== b && "NaN" !== b || (b = 0), "" !== c && "NaN" !== c || (c = ""), "" !== d && "NaN" !== d || (d = 0), "any" !== e && "" !== e && void 0 !== e && "NaN" !== parseFloat(e) || (e = 1), jQuery(this).is(".plus") ? c && b >= c ? a.val(c) : a.val((b + parseFloat(e)).toFixed(e.getDecimals())) : d && b <= d ? a.val(d) : b > 0 && a.val((b - parseFloat(e)).toFixed(e.getDecimals()))
+     
+     //alert();
+     const quantity=jQuery(this).closest(".mm_quantity").find(".qty").val();
+     jQuery(this).closest(".mm_quantity").find(".hquantity").attr('value',quantity);
+
+     if($(this).hasClass('cart-page-quantity-value')){
+      const variantId=jQuery(this).closest(".mm_quantity").find(".hquantity").attr('variantid');
+      console.log('-----', variantId)
+      await updateItem(variantId, quantity)
+      window.location.href="/cart"
+     }
+    
+     
+});
+
+async function updateItem(variantId, quantity,  properties={}){
+  const result = await fetch("/cart/change.json", {
+    method:"post",
+    headers: {
+        "Content-type": "application/json",
+        "Accept": "application/json"
+    },
+    body: JSON.stringify({
+        id: variantId,
+        quantity: quantity,
+        properties: properties
+    })
+  })
+  return result.json();
+}
+
+function mm_validate(evt) {
+  var theEvent = evt || window.event;
+	theEvent.preventDefault()
+	/*
+  if (theEvent.type === 'paste') {
+      key = event.clipboardData.getData('text/plain');
+  } else {  
+      var key = theEvent.keyCode || theEvent.which;
+      key = String.fromCharCode(key);
+  }
+  var regex = /[0-9]|\./;
+	
+  if( !regex.test(key) ) {
+    theEvent.returnValue = false;
+    if(theEvent.preventDefault) theEvent.preventDefault();
+  }*/
+}
+
+
+/* for variant sample */
+jQuery(document).on('change', '.shopify-product-form .single-option-selector, .shopify-product-form .product-select', function () {
+  var $form = jQuery(this).closest('.shopify-product-form');
+
+  var isOptionSelector = jQuery(this).hasClass('single-option-selector');
+
+  var run = function () {
+    var $variantSelect = $form.find('.product-select');
+    var $selected;
+    var selectedSku = '';
+    var optionText = '';
+
+    if ($variantSelect.length && $variantSelect.is('select')) {
+      $selected = $variantSelect.find(':selected');
+      selectedSku = ($selected.attr('data-sku') || '').toString();
+      optionText = ($selected.text() || '').toString();
+    } else if ($variantSelect.length && $variantSelect.is('input')) {
+      // 1-variant products: .product-select is a hidden input
+      selectedSku = ($variantSelect.attr('data-sku') || '').toString();
+      optionText = ($variantSelect.attr('data-variant-title') || '').toString();
+    } else {
+      $selected = jQuery(this).find(':selected');
+      selectedSku = ($selected.attr('data-sku') || '').toString();
+      optionText = ($selected.text() || '').toString();
+    }
+
+    // If we can't determine anything, don't flip the UI.
+    if (!selectedSku && !optionText) return;
+
+    var isSkuSample = /-+sample$/i.test(selectedSku);
+    var isTextSample = /\bsample\b/i.test(optionText);
+    var isPureSample = /^sample(\b|[^a-z])/i.test(optionText.trim());
+    var isSample = isSkuSample || isTextSample;
+
+    var $qty = $form.find('.mm_quantity .qty');
+    var $qtyWrapper = $form.find('.mm_quantity');
+    var originalMin = $qty.data('min');
+    var originalStep = $qty.data('step');
+
+    if (!originalMin) {
+      originalMin = parseFloat($qty.attr('min')) || 1;
+      $qty.data('min', originalMin);
+    }
+    if (!originalStep) {
+      originalStep = parseFloat($qty.attr('step')) || 1;
+      $qty.data('step', originalStep);
+    }
+
+    // Sample request buttons are always available (hide/show is variant-driven only)
+    $form.find('.dl-sample-btn, .dl-second-sample-btn').show();
+
+    if (isSample) {
+      $qty.val(1);
+      $qty.attr({ step: 1, min: 1, max: 1 });
+      $qtyWrapper.find('.plus, .minus').prop('disabled', true);
+      $qtyWrapper.find('.hquantity').attr('value', 1);
+
+      $form.find('.product-option-quantity-label').addClass('hidden').hide();
+      $qtyWrapper.addClass('hidden').hide();
+      $form.find('.add-to-cart').addClass('hidden').hide();
+
+      if (!isPureSample) {
+        $form.find('.dl-second-sample-btn').removeClass('unavailable');
+      } else if (!$form.find('.dl-second-sample-btn').hasClass('unavailable')) {
+        $form.find('.dl-second-sample-btn').addClass('unavailable');
+      }
+    } else {
+      $form.find('.product-option-quantity-label').removeClass('hidden').show();
+      $qtyWrapper.removeClass('hidden').show();
+      $form.find('.add-to-cart').removeClass('hidden').show();
+
+      var minValue = originalMin;
+      var currentValue = parseFloat($qty.val()) || 0;
+      if (currentValue < minValue) {
+        $qty.val(minValue);
+        $qtyWrapper.find('.hquantity').attr('value', minValue);
+      }
+      $qty.attr({ step: originalStep, min: minValue });
+      $qty.removeAttr('max');
+      $qtyWrapper.find('.plus, .minus').prop('disabled', false);
+    }
+
+    // Update the SKU display
+    var displaySku = selectedSku
+      .replace(/-+sample$/i, '')
+      .replace(/-+$/g, '');
+    jQuery('.product-sku-value').text(displaySku);
+
+    // Trade discount text
+    if (jQuery('#customer_tag').val() === 'trade') {
+      requestAnimationFrame(function () {
+        requestAnimationFrame(function () {
+          if (isSample) {
+            jQuery('.product-price-discount').text('Complimentary Sample');
+          } else {
+            // Use the currently displayed currency (symbol/code) from the UI, not hardcoded USD.
+            // Also support both "298,95" and "298.95" style decimals.
+            function dlParseDisplayedNumber(numStr) {
+              var s = (numStr || '').toString().replace(/\s/g, '');
+              var lastComma = s.lastIndexOf(',');
+              var lastDot = s.lastIndexOf('.');
+
+              // No separators: plain number
+              if (lastComma === -1 && lastDot === -1) {
+                var plain = parseFloat(s.replace(/[^\d.-]/g, ''));
+                return isFinite(plain) ? plain : NaN;
+              }
+
+              // Decide decimal separator by whichever comes last
+              var decimalSep = lastComma > lastDot ? ',' : '.';
+              var otherSep = decimalSep === ',' ? '.' : ',';
+
+              var parts = s.split(decimalSep);
+              if (!parts.length) return NaN;
+              var intPart = (parts[0] || '').replace(new RegExp('[\\' + otherSep + ']', 'g'), '').replace(/[^\d-]/g, '');
+              var fracPart = (parts[1] || '').replace(/[^\d]/g, '');
+              var normalized = intPart + (fracPart ? ('.' + fracPart) : '');
+              var val = parseFloat(normalized);
+              return isFinite(val) ? val : NaN;
+            }
+
+            function dlFormatLike(numStr, value) {
+              var s = (numStr || '').toString().replace(/\s/g, '');
+              var lastComma = s.lastIndexOf(',');
+              var lastDot = s.lastIndexOf('.');
+              var decimalSep = lastComma === -1 && lastDot === -1 ? '.' : (lastComma > lastDot ? ',' : '.');
+              var thousandsSep = decimalSep === ',' ? '.' : ',';
+
+              var hasThousands = false;
+              if (lastComma !== -1 || lastDot !== -1) {
+                var decIndex = decimalSep === ',' ? lastComma : lastDot;
+                var intStr = s.slice(0, decIndex);
+                hasThousands = intStr.indexOf(thousandsSep) !== -1;
+              }
+
+              var fixed = (Math.round(value * 100) / 100).toFixed(2);
+              var fixedParts = fixed.split('.');
+              var intPart = fixedParts[0];
+              var fracPart = fixedParts[1] || '00';
+
+              if (hasThousands) {
+                intPart = intPart.replace(/\B(?=(\d{3})+(?!\d))/g, thousandsSep);
+              }
+
+              return intPart + decimalSep + fracPart;
+            }
+
+            var priceText = (jQuery('.product-price-minimum').first().text() || '').trim();
+            var re = /[\d.,]+/;
+            var m = re.exec(priceText);
+            if (!m) return;
+
+            var numberStr = m[0];
+            var prefix = priceText.slice(0, m.index);
+            var suffix = priceText.slice(m.index + numberStr.length);
+
+            var priceValue = dlParseDisplayedNumber(numberStr);
+            if (!isFinite(priceValue)) return;
+
+            var discountedValue = priceValue * 0.85;
+            var formattedNumber = dlFormatLike(numberStr, discountedValue);
+            jQuery('.product-price-discount').text(prefix + formattedNumber + suffix);
+          }
+        });
+      });
+    }
+  }.bind(this);
+
+  var schedule = function () {
+    requestAnimationFrame(function () {
+      requestAnimationFrame(run);
+    });
+  };
+
+  if (isOptionSelector) {
+    setTimeout(schedule, 60);
+  } else {
+    schedule();
+  }
+});
+
+
+//hide ddl and show last variant
+
+if($('#has_display_variant').length>0 && $('#has_display_variant').val() == "no"){
+  $('.last_variant').hide(); 
+  if ( $( ".shopify-product-form .single-option-selector" ).length ) {
+    
+    $('.shopify-product-form .single-option-selector').hide();
+    
+    setTimeout(function(){ 
+      $('.product-options .select-wrapper').hide();
+    }, 500);
+    
+    $('.last_variant').show();
+
+    var single_opt_ind=0;
+    $('.shopify-product-form .single-option-selector option').each(function(index, option){
+     single_opt_ind=index;
+    });  
+
+    
+    /* DW deep-link honor (vp-dw-commerce 2026-06-24) */
+    // Honor an explicit ?variant=<id> deep-link: if the URL names a variant that
+    // matches one of the options, select THAT option instead of the computed default,
+    // so a link to the Sample renders $4.25 and a link to the Roll renders the roll price.
+    try {
+      var dlWanted = new URLSearchParams(window.location.search).get('variant');
+      if (dlWanted) {
+        $dlOpts.each(function(index, option){
+          var ov = (option.value || '').toString();
+          var dv = (option.getAttribute && option.getAttribute('data-variant-id') || '').toString();
+          if (ov === dlWanted || dv === dlWanted) { single_opt_ind = index; }
+        });
+      }
+    } catch (e) {}
+    /* /DW deep-link honor */
+    $(".shopify-product-form .single-option-selector").prop('selectedIndex', single_opt_ind).trigger('change');
+  }  
+}
+//--------------------------------
+
+// Prevent rapid multi-clicks from adding multiple samples before mini-cart UI updates
+function dlGetSampleBtns(variantId) {
+  return $(".dl-sample-btn[data-dlvid='" + variantId + "'], .dl-second-sample-btn[data-dlvid='" + variantId + "']");
+}
+function dlIsSampleLocked(variantId) {
+  return dlGetSampleBtns(variantId).first().attr("data-dl-locked") === "1";
+}
+function dlLockSampleBtns(variantId) {
+  var $btns = dlGetSampleBtns(variantId);
+  $btns.attr("data-dl-locked", "1").addClass("dl-click-locked").attr("aria-disabled", "true");
+  $btns.each(function() {
+    var $b = $(this);
+    if ($b.is("button, input")) $b.prop("disabled", true);
+  });
+}
+function dlUnlockSampleBtns(variantId) {
+  var $btns = dlGetSampleBtns(variantId);
+  $btns.removeAttr("data-dl-locked").removeClass("dl-click-locked").removeAttr("aria-disabled");
+  $btns.each(function() {
+    var $b = $(this);
+    if ($b.is("button, input")) $b.prop("disabled", false);
+  });
+}
+function dlUnlockSampleBtnsWhenInCart(variantId, maxMs) {
+  var start = Date.now();
+  var timer = setInterval(function() {
+    if ($(".mini-cart-item-wrapper [data-variant='" + variantId + "']").length > 0) {
+      clearInterval(timer);
+      dlUnlockSampleBtns(variantId);
+      return;
+    }
+    if (Date.now() - start >= (maxMs || 20000)) {
+      clearInterval(timer);
+      dlUnlockSampleBtns(variantId);
+    }
+  }, 250);
+}
+
+
+$(document).on("click", ".dl-sample-btn", function(e) {
+  e.preventDefault()
+  var $btn = $(this);
+  var $form = $btn.closest("form");
+  var id = $btn.attr("data-dlvid");
+  //check if the sample was added already
+  if($(".mini-cart-item-wrapper [data-variant='"+id+"']").length == 0) {
+    if (dlIsSampleLocked(id)) return;
+    dlLockSampleBtns(id);
+    dlUnlockSampleBtnsWhenInCart(id, 20000);
+
+    var product_id = $(this).attr("data-product-id");
+    var $productSelect = $form.find("#product-select-"+product_id);
+    if (!$productSelect.length) $productSelect = $form.find(".product-select");
+    var first_selected_id = $productSelect.is("select") ? $productSelect.find(":selected").val() : $productSelect.val();
+    $productSelect.val(id).trigger('change');
+    //
+    var $qtyInput = $form.find(".input-text.qty");
+    var default_quantity = $qtyInput.val();
+    $qtyInput.val(1);
+    $form.find(".add-to-cart.cowlendar-add-to-cart").trigger("click");
+
+    //go back to original selected status
+    
+    $qtyInput.val(default_quantity);
+    if (first_selected_id && first_selected_id !== id) {
+      $productSelect.val(first_selected_id).trigger('change');
+    }
+  } else {
+    //alert("1 sample only");
+    if($(".product-message").hasClass("success-message") || $(".mini-cart-item-wrapper [data-variant='"+id+"']").length > 0) {
+      $(".product-message").removeClass("success-message").addClass("error-message");
+      $(".product-message").text("1 Sample per SKU");
+    }    
+  }  
+});
+$(document).on("click", ".dl-second-sample-btn", function(e) {
+  e.preventDefault()
+  var $btn = $(this);
+  var $form = $btn.closest("form");
+  var id = $btn.attr("data-dlvid");
+  //check if the sample was added already
+  if($(".mini-cart-item-wrapper [data-variant='"+id+"']").length == 0) {
+    if (dlIsSampleLocked(id)) return;
+    dlLockSampleBtns(id);
+    dlUnlockSampleBtnsWhenInCart(id, 20000);
+
+    //
+    var $qtyInput = $form.find(".input-text.qty");
+    var default_quantity = $qtyInput.val();
+    $qtyInput.val(1);
+    $form.find(".add-to-cart.cowlendar-add-to-cart").trigger("click");
+
+    //go back to original selected status
+    
+    $qtyInput.val(default_quantity);
+  } else {
+    //alert("1 sample only");
+    if($(".product-message").hasClass("success-message") || $(".mini-cart-item-wrapper [data-variant='"+id+"']").length > 0) {
+      $(".product-message").removeClass("success-message").addClass("error-message");
+      $(".product-message").text("1 Sample per SKU");
+    }    
+  }  
+});
+
+//add the remove functionality on the mini-cart
+$(document).on("click", ".remove-item", function(e) {
+  e.preventDefault();
+    var variantId = $(this).closest('.mini-cart-item').attr("data-variant");
+    var quantity = parseInt($(this).closest(".mini-cart-item").find(".mini-cart-item-quantity").find("span").text());
+    var cart_num = parseInt($(".cart-count .cart-count-number").text());
+    var reminder_num = cart_num - quantity;
+    $.ajax({
+        type: "POST",
+        url: "/cart/change.js",
+        dataType: "json",
+        data: {
+          id: parseFloat(variantId),
+          quantity: 0,
+        },
+    }).then((data) => {
+        console.log("success");
+        $(this).closest('.mini-cart-item').remove();
+        dlUnlockSampleBtns(variantId);
+        $(".cart-count .cart-count-number").text(parseInt(reminder_num));
+        if(reminder_num == 0) {
+          $(".mini-cart").hide();
+        }
+    });
+});
+
+$(document).on("click", ".upsell-add-to-cart", function() {
+  var id = $(this).attr("data-item-id");
+  var num = parseInt($(this).attr("data-num"));
+  $.ajax({
+      type: 'POST',
+      url: '/cart/add.js',
+      dataType: 'json',
+      data: {
+          items: [
+              {
+                  quantity: num,
+                  id: id
+              }
+          ]
+      },
+      success: function (data){
+          location.href= "/cart";
+      }
+    });
+});
+
+/* Custom code for sascha */
+function showMiniCartIfReady() {
+  if (window.innerWidth <= 767) {
+    return;
+  }
+  var $miniCart = $(".mini-cart");
+  if ($miniCart.length && !$miniCart.hasClass("empty")) {
+    $(".mini-cart-wrapper").addClass("is-open");
+  }
+}
+
+function watchMiniCartUpdates() {
+  var target = document.querySelector(".mini-cart-item-wrapper");
+  if (!target || !window.MutationObserver) {
+    return;
+  }
+  var observer = new MutationObserver(function() {
+    showMiniCartIfReady();
+  });
+  observer.observe(target, { childList: true, subtree: true });
+}
+
+$(document).ready(function() {
+  watchMiniCartUpdates();
+});
+
+$(document).on("click", ".add-to-cart.cowlendar-add-to-cart", function() {
+  showMiniCartIfReady();
+});
+
+$(document).on("click", function(event) {
+  var $target = $(event.target);
+  if ($target.closest(".mini-cart, .mini-cart-wrapper").length === 0) {
+    $(".mini-cart-wrapper").removeClass("is-open");
+  }
+});
+
+$(document).on("mouseleave", ".mini-cart-wrapper", function() {
+  $(this).removeClass("is-open");
+});
\ No newline at end of file
diff --git a/shopify/theme-fixes/custom-js-qty-2026-06-30/diag.cjs b/shopify/theme-fixes/custom-js-qty-2026-06-30/diag.cjs
new file mode 100644
index 00000000..b80c1c17
--- /dev/null
+++ b/shopify/theme-fixes/custom-js-qty-2026-06-30/diag.cjs
@@ -0,0 +1,52 @@
+// Diagnose the DOM structure around the qty picker on a theme.
+const { chromium } = require(require('path').join(process.env.HOME, 'Projects/Designer-Wallcoverings/node_modules/playwright'));
+const THEME = process.argv[2];
+const HANDLE = process.argv[3] || 'dwtt-80064-designer-wallcoverings-los-angeles';
+const URL = `https://designer-laboratory-sandbox.myshopify.com/products/${HANDLE}?preview_theme_id=${THEME}`;
+
+(async () => {
+  const browser = await chromium.launch();
+  const page = await (await browser.newContext()).newPage();
+  await page.goto(URL, { waitUntil: 'domcontentloaded', timeout: 60000 });
+  await page.waitForSelector('.mm_quantity input[name="quantity"]', { state: 'attached', timeout: 30000 });
+  await page.waitForTimeout(1800);
+
+  // select roll variant
+  await page.evaluate(() => {
+    const sel = document.querySelector('.product-select');
+    if (sel && sel.tagName === 'SELECT') {
+      const opts = Array.from(sel.options);
+      const roll = opts.find(o => !/sample/i.test(o.textContent) && !/-sample$/i.test(o.getAttribute('data-sku')||'')) || opts[0];
+      sel.value = roll.value; sel.dispatchEvent(new Event('change', { bubbles: true }));
+      if (window.jQuery) window.jQuery(sel).trigger('change');
+    }
+  });
+  await page.waitForTimeout(1500);
+
+  const info = await page.evaluate(() => {
+    const blocks = Array.from(document.querySelectorAll('.mm_quantity')).map((b, i) => {
+      const q = b.querySelector('input[name="quantity"]');
+      const h = b.querySelector('.hquantity');
+      const rect = b.getBoundingClientRect();
+      const style = getComputedStyle(b);
+      return {
+        i,
+        className: b.className,
+        visible: style.display !== 'none' && style.visibility !== 'hidden' && rect.width > 0 && rect.height > 0,
+        display: style.display,
+        qtyVal: q ? q.value : null,
+        qtyStep: q ? q.getAttribute('step') : null,
+        qtyMin: q ? q.getAttribute('min') : null,
+        qtyDataStep: q ? q.getAttribute('data-step') : null,
+        qtyDataMin: q ? q.getAttribute('data-min') : null,
+        hVal: h ? h.value : null,
+        plus: b.querySelectorAll('.plus').length,
+        minus: b.querySelectorAll('.minus').length,
+        plusVisible: Array.from(b.querySelectorAll('.plus')).map(p => getComputedStyle(p).display !== 'none' && p.getBoundingClientRect().width>0),
+      };
+    });
+    return { blockCount: blocks.length, blocks };
+  });
+  console.log(JSON.stringify(info, null, 2));
+  await browser.close();
+})().catch(e => { console.error('FATAL', e); process.exit(1); });
diff --git a/shopify/theme-fixes/custom-js-qty-2026-06-30/element.quantity-selector.js b/shopify/theme-fixes/custom-js-qty-2026-06-30/element.quantity-selector.js
new file mode 100644
index 00000000..efb77b0b
--- /dev/null
+++ b/shopify/theme-fixes/custom-js-qty-2026-06-30/element.quantity-selector.js
@@ -0,0 +1,93 @@
+const selectors = {
+  input: '.element-quantity-selector__input',
+  plus: '.element-quantity-selector__button--plus',
+  minus: '.element-quantity-selector__button--minus'
+}
+
+class QuantitySelector extends HTMLElement {
+  connectedCallback() {
+    this.abortController = new AbortController()
+
+    this.plus = this.querySelector(selectors.plus)
+    this.minus = this.querySelector(selectors.minus)
+    this.input = this.querySelector(selectors.input)
+    this.minValue = this.input.getAttribute('min') || 1
+    this.maxValue = this.input.getAttribute('max')
+
+    this.plus.addEventListener(
+      'click',
+      function () {
+        let qty = this._getQty()
+        this._change(qty + 1)
+      }.bind(this),
+      { signal: this.abortController.signal }
+    )
+
+    this.minus.addEventListener(
+      'click',
+      function () {
+        let qty = this._getQty()
+        this._change(qty - 1)
+      }.bind(this),
+      { signal: this.abortController.signal }
+    )
+
+    this.input.addEventListener(
+      'input',
+      function (evt) {
+        this._change(this._getQty())
+      }.bind(this),
+      { signal: this.abortController.signal }
+    )
+  }
+
+  disconnectedCallback() {
+    this.abortController.abort()
+  }
+
+  _getQty() {
+    let qty = this.input.value
+    if (parseFloat(qty) == parseInt(qty) && !isNaN(qty)) {
+      // We have a valid number!
+    } else {
+      // Not a number. Default to 1.
+      qty = 1
+    }
+    return parseInt(qty)
+  }
+
+  _change(qty) {
+    if (qty <= this.minValue) {
+      qty = this.minValue
+    }
+
+    if (this.maxValue && qty > this.maxValue) {
+      qty = this.maxValue
+    }
+
+    this.input.value = qty
+    this.style.setProperty('--digit-count', `${qty.toString().length}ch`)
+
+    if (this.key && this.key !== '') {
+      this.dispatchEvent(
+        new CustomEvent('cart:quantity', {
+          bubbles: true,
+          detail: [this.key, qty, this]
+        })
+      )
+    } else {
+      this.dispatchEvent(
+        new CustomEvent('quantity:change', {
+          detail: {
+            qty: qty
+          }
+        })
+      )
+    }
+  }
+  get key() {
+    return this.getAttribute('key')
+  }
+}
+
+customElements.define('quantity-selector', QuantitySelector)
diff --git a/shopify/theme-fixes/custom-js-qty-2026-06-30/liquid/blocks___section-flex-pdp-quantity-picker.liquid b/shopify/theme-fixes/custom-js-qty-2026-06-30/liquid/blocks___section-flex-pdp-quantity-picker.liquid
new file mode 100644
index 00000000..8fd3130b
--- /dev/null
+++ b/shopify/theme-fixes/custom-js-qty-2026-06-30/liquid/blocks___section-flex-pdp-quantity-picker.liquid
@@ -0,0 +1,15 @@
+{% render 'section.flex-pdp.quantity-picker',
+  product: closest.product,
+  show_inventory_status: false
+%}
+
+{% schema %}
+{
+  "name": "t:flex_pdp.blocks.quantity_picker.name",
+  "presets": [
+    {
+      "name": "t:flex_pdp.blocks.quantity_picker.name"
+    }
+  ]
+}
+{% endschema %}
\ No newline at end of file
diff --git a/shopify/theme-fixes/custom-js-qty-2026-06-30/liquid/snippets__product-form-content.liquid b/shopify/theme-fixes/custom-js-qty-2026-06-30/liquid/snippets__product-form-content.liquid
new file mode 100644
index 00000000..598116d0
--- /dev/null
+++ b/shopify/theme-fixes/custom-js-qty-2026-06-30/liquid/snippets__product-form-content.liquid
@@ -0,0 +1,800 @@
+{% comment %}
+  @param product {Product}
+
+  @param show_social_media_icons {Boolean}
+
+  @param show_payment_button {Boolean}
+    Show the DPBs in the product form
+{% endcomment %}
+
+{% assign product_id = product.id %}
+{% assign selected_variant = product.selected_or_first_available_variant %}
+
+{%- liquid
+  assign _selected_variant_sku = selected_variant.sku | default: '' | downcase
+  assign _selected_variant_title = selected_variant.title | default: '' | downcase
+
+  assign _selected_variant_sku_suffix = _selected_variant_sku | slice: -7, 7
+
+  assign is_sample_sku = false
+  if _selected_variant_sku != blank and _selected_variant_sku_suffix == '-sample'
+    assign is_sample_sku = true
+  endif
+
+  assign is_sample_title = false
+  if _selected_variant_title contains 'sample'
+    assign is_sample_title = true
+  endif
+
+  assign is_sample_like = false
+  if is_sample_sku
+    assign is_sample_like = true
+  elsif is_sample_title and selected_variant.price == 0
+    assign is_sample_like = true
+  endif
+-%}
+
+<!-- -----------020------------ -->
+{% assign prods_quantity_order_min = 1 %}
+
+{% if product.metafields['global']['v_prods_quantity_order_min'] %}
+  {% if product.metafields['global']['v_prods_quantity_order_min'] != '' %}
+    {% assign prods_quantity_order_min = product.metafields['global']['v_prods_quantity_order_min'] %}
+  {% endif %}
+{% endif %}
+
+{% assign prods_quantity_order_units = 1 %}
+
+{% if product.metafields['global']['v_prods_quantity_order_units'] %}
+  {% if product.metafields['global']['v_prods_quantity_order_units'] != '' %}
+    {% assign prods_quantity_order_units = product.metafields['global']['v_prods_quantity_order_units'] %}
+  {% endif %}
+{% endif %}
+
+<!-- Minimum order quantity from custom metafields (e.g. Ralph Lauren fabrics) -->
+{% assign min_order_qty = product.metafields.custom.minimum_order_quantity | default: nil %}
+{% assign min_order_unit = product.metafields.custom.minimum_order_unit | default: '' %}
+{% assign has_min_order = false %}
+{% if min_order_qty != nil and min_order_qty != blank and min_order_qty > 1 %}
+  {% assign has_min_order = true %}
+  {% assign min_order_qty_num = min_order_qty | plus: 0 %}
+  {% if min_order_qty_num > prods_quantity_order_min %}
+    {% assign prods_quantity_order_min = min_order_qty_num %}
+  {% endif %}
+{% endif %}
+
+<!-- -------------------------- -->
+<script>
+  setTimeout(function () {
+    const qtySelector = document.querySelector('.mm_quantity .input-text.qty');
+    if (qtySelector) {
+      qtySelector.value = {{ prods_quantity_order_min }};
+    }
+  }, 1000);
+</script>
+
+{% if has_min_order %}
+<!-- Minimum order notice and validation -->
+<style>
+  .min-order-notice {
+    background: #fff3cd;
+    border: 1px solid #ffc107;
+    border-radius: 4px;
+    padding: 8px 12px;
+    margin: 10px 0;
+    font-size: 14px;
+    font-weight: 600;
+    color: #856404;
+    display: flex;
+    align-items: center;
+    gap: 6px;
+  }
+  .min-order-notice svg {
+    flex-shrink: 0;
+  }
+  .min-order-error {
+    background: #f8d7da;
+    border: 1px solid #f5c6cb;
+    color: #721c24;
+    border-radius: 4px;
+    padding: 8px 12px;
+    margin: 8px 0 0;
+    font-size: 13px;
+    display: none;
+  }
+</style>
+<div class="min-order-notice" data-min-order-notice>
+  <svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor"><path d="M8 1a7 7 0 100 14A7 7 0 008 1zm0 2.5a.75.75 0 01.75.75v4a.75.75 0 01-1.5 0v-4A.75.75 0 018 3.5zm0 8a.75.75 0 100-1.5.75.75 0 000 1.5z"/></svg>
+  Minimum order: {{ min_order_qty }} {{ min_order_unit }}
+</div>
+<script>
+  (function() {
+    var MIN_QTY = {{ min_order_qty }};
+    var MIN_UNIT = {{ min_order_unit | json }};
+
+    document.addEventListener('DOMContentLoaded', function() {
+      // Find the product form (could be either .shopify-product-form or form with data-product-form)
+      var forms = document.querySelectorAll('form[action*="/cart/add"], form[data-product-form]');
+      forms.forEach(function(form) {
+        form.addEventListener('submit', function(e) {
+          var qtyInput = form.querySelector('.mm_quantity .input-text.qty') || form.querySelector('input[name="quantity"]');
+          if (!qtyInput) return;
+
+          var qty = parseInt(qtyInput.value, 10);
+          if (isNaN(qty) || qty < MIN_QTY) {
+            e.preventDefault();
+            e.stopImmediatePropagation();
+
+            // Show error message
+            var errorDiv = form.querySelector('.min-order-error');
+            if (!errorDiv) {
+              errorDiv = document.createElement('div');
+              errorDiv.className = 'min-order-error';
+              var addToCartBtn = form.querySelector('.product-add-to-cart');
+              if (addToCartBtn) {
+                addToCartBtn.appendChild(errorDiv);
+              }
+            }
+            errorDiv.textContent = 'Please enter a quantity of at least ' + MIN_QTY + ' ' + MIN_UNIT + '.';
+            errorDiv.style.display = 'block';
+
+            // Also fix the value
+            qtyInput.value = MIN_QTY;
+            var hqty = form.querySelector('.hquantity');
+            if (hqty) hqty.value = MIN_QTY;
+
+            // Hide error after 5s
+            setTimeout(function() { errorDiv.style.display = 'none'; }, 5000);
+            return false;
+          }
+        });
+      });
+
+      // Also enforce min on the minus button - prevent going below minimum
+      jQuery(document).on('click', '.minus', function() {
+        var $qty = jQuery(this).closest('.mm_quantity').find('.qty');
+        var currentVal = parseInt($qty.val(), 10);
+        if (currentVal < MIN_QTY) {
+          $qty.val(MIN_QTY);
+          jQuery(this).closest('.mm_quantity').find('.hquantity').attr('value', MIN_QTY);
+        }
+      });
+
+      // Enforce min on blur (manual typing)
+      jQuery(document).on('blur', '.mm_quantity .input-text.qty', function() {
+        var currentVal = parseInt(jQuery(this).val(), 10);
+        if (isNaN(currentVal) || currentVal < MIN_QTY) {
+          jQuery(this).val(MIN_QTY);
+          jQuery(this).closest('.mm_quantity').find('.hquantity').attr('value', MIN_QTY);
+        }
+      });
+
+      // Hide notice when sample variant is selected
+      jQuery(document).on('change', '.product-select, .single-option-selector', function() {
+        var $form = jQuery(this).closest('form, [data-product-form]');
+        var $selected = $form.find('.product-select option:selected, .product-select[type="hidden"]');
+        var selectedText = ($selected.text() || $selected.attr('data-variant-title') || '').toLowerCase();
+        var selectedSku = ($selected.attr('data-sku') || '').toLowerCase();
+        var isSample = /sample/i.test(selectedText) || /-sample$/i.test(selectedSku);
+
+        var $notice = jQuery('.min-order-notice[data-min-order-notice]');
+        if (isSample) {
+          $notice.hide();
+        } else {
+          $notice.show();
+        }
+      });
+    });
+  })();
+</script>
+{% endif %}
+
+{% for block in section.blocks %}
+  {% case block.type %}
+    {% when 'vendor' %}
+      <a class="product-vendor" href="{{ product.vendor | url_for_vendor }}" {{ block.shopify_attributes }}>{{ product.vendor }}</a>
+
+    {% when 'title' %}
+      <h1 class="product-title" {{ block.shopify_attributes }}>
+        {% if product != blank %}
+          {% if link_to %}
+            <a href="{{ product.url }}">
+              {{ product.title }}
+            </a>
+          {% else %}
+            {% comment %}{{ product.title }} {% endcomment %}
+            <a href="https://designer-laboratory-sandbox.myshopify.com/search?q={{ product.title }}">
+              {{ product.title }}
+            </a>
+          {% endif %}
+        {% else %}
+          {{ 'products.product.onboarding.title' | t }}
+        {% endif %}
+      </h1>
+      <span class="product-sku-label">SKU: </span>
+      {%- liquid
+        assign sku_raw = product.selected_or_first_available_variant.sku | default: ''
+        assign sku_display = sku_raw | replace: '-Sample', '' | replace: '-SAMPLE', '' | replace: '-sample', ''
+        assign sku_display = sku_display | replace: '--', '-' | replace: '--', '-'
+        assign sku_last_char = sku_display | slice: -1, 1
+        if sku_display != blank and sku_last_char == '-'
+          assign sku_display = sku_display | remove_last: '-'
+        endif
+      -%}
+      <span class="product-sku-value">{{ sku_display }}</span>
+    {% when '@app' %}
+      <div class="product-app" {{ block.shopify_attributes }}>
+        {% render block %}
+      </div>
+
+    {% when 'custom-liquid' %}
+      {% if block.settings.custom_liquid != blank %}
+        <div class="product__custom-liquid" {{ block.shopify_attributes }}>
+          {{ block.settings.custom_liquid }}
+        </div>
+      {% endif %}
+
+    {% when 'collapsible-tab' %}
+      {% if block.settings.collapsible_tab_heading != blank %}
+        <details class="collapsible-tab" {{ block.shopify_attributes }}>
+          <summary class="collapsible-tab__heading">
+            <span>{{ block.settings.collapsible_tab_heading | escape }}</span>
+            {%
+              render 'icons',
+              id: 'chevron-right',
+            %}
+          </summary>
+
+          {% if block.settings.collapsible_tab_text != blank %}
+            <div class="collapsible-tab__text rte">
+              {{ block.settings.collapsible_tab_text }}
+            </div>
+          {% endif %}
+        </details>
+      {% endif %}
+
+    {% when 'tabs' %}
+      {% assign tab_counter = 1 %}
+      <div class="product-tabs" {{ block.shopify_attributes }}>
+        {% if block.settings.show_product_description %}
+          <input
+            class="product-tabs__radio"
+            id="product-tabs__radio-{{ section.id }}"
+            name="{{ section.id }}"
+            tabindex="0"
+            type="radio"
+            checked="checked"
+          >
+
+          <label class="product-tabs__label" for="product-tabs__radio-{{ section.id }}">
+            {{ 'onboarding.tab_title'| t }}
+          </label>
+
+          <div class="product-tabs__panel rte" tabindex="0">
+            {% if onboarding %}
+              {{ 'onboarding.tab_content'| t }}
+            {% else %}
+              {% if product.description != blank %}
+                {{ product.description }}
+              {% else %}
+                {{ 'onboarding.tab_content'| t }}
+              {% endif %}
+            {% endif %}
+          </div>
+        {% endif %}
+
+        {% for i in (1..3) %}
+          {% assign tab_text_key = 'tab_text_' | append: i %}
+          {% assign tab_heading_key = 'tab_heading_' | append: i %}
+          {% assign tab_heading_value = block.settings[tab_heading_key] %}
+          {% assign tab_text_value = block.settings[tab_text_key] %}
+
+          {% if tab_heading_value != blank %}
+            <input
+              class="product-tabs__radio"
+              id="product-tabs__radio-{{ i }}-{{ section.id }}"
+              name="{{ section.id }}"
+              tabindex="0"
+              type="radio"
+              {% if tab_counter == 1 and block.settings.show_product_description == false %}
+                checked
+              {% endif %}
+            >
+
+            <label class="product-tabs__label" for="product-tabs__radio-{{ i }}-{{ section.id }}">
+              {{ tab_heading_value | escape }}
+            </label>
+
+            <div class="product-tabs__panel rte" tabindex="0">
+              {{ tab_text_value }}
+            </div>
+
+            {% assign tab_counter = tab_counter | plus: 1 %}
+          {% endif %}
+        {% endfor %}
+      </div>
+
+    {% when 'price' %}
+      <div class="product__price" {{ block.shopify_attributes }}>
+        {%- comment -%}
+          DW trade/designer pricing tiers (2026-06-11): any customer carrying one of these
+          professional tags sees the trade price display (15% off, ×0.85). This restores the
+          pre-app behavior where every designer/trade tier got the discount — not just 'trade'.
+          Matches *any* tag containing 'designer' (interior_designer, commercial_designer, …)
+          plus the explicit tiers below. Add new tiers to the explicit list as needed.
+        {%- endcomment -%}
+        {%- assign dw_is_trade = false -%}
+        {%- for dw_t in customer.tags -%}
+          {%- assign dw_tl = dw_t | downcase | strip -%}
+          {%- if dw_tl contains 'designer' or dw_tl == 'trade' or dw_tl == 'architect' or dw_tl == 'stager' or dw_tl == 'hospitality' or dw_tl == 'retailer' -%}
+            {%- assign dw_is_trade = true -%}
+            {%- break -%}
+          {%- endif -%}
+        {%- endfor -%}
+        <input type="hidden" id="customer_tag" value="{% if dw_is_trade %}trade{% endif %}">
+        <p class="product-price">
+          {% comment %} SA Wholesale (saw_/wbuyx/"WHO") app removed 2026-06-11 — it left the price span blank. Render native variant price unconditionally. {% endcomment %}
+            <!-- native price markup -->
+            <meta itemprop="price" content="{{ selected_variant.price | money_without_currency }}">
+            <span class="product-price-minimum money {% if dw_is_trade %}original{% endif %}">
+              {% if product != blank %}
+                {{ selected_variant.price | money }}
+              {% else %}
+                {{ 'products.product.onboarding.price' | t }}
+              {% endif %}
+            </span>
+            {% if dw_is_trade %}
+              <span
+                class="product-price-discount"
+              >
+                {% assign target_product = selected_variant %}
+                {% assign com_selected_variant_title = selected_variant.title | capitalize %}
+                {% assign com_selected_variant_sku = selected_variant.sku | default: '' | downcase %}
+                {% if com_selected_variant_title == "Sample" or com_selected_variant_sku contains "sample" %}
+                  {% comment %} {% render 'money', value: 0 %} {% endcomment %}
+                  Complimentary Sample
+                {% else %}
+                  {% assign com_variant_first_title = product.variants[0].title | capitalize %}
+                  {% if com_variant_first_title == "Sample" and product.variants[1] != blank  %}
+                    {% assign target_product = product.variants[1] %}
+                  {% endif  %}
+                  {% assign discounted_price = target_product.price | times:0.85 | round: 2 %}
+                  {% render 'money', value: discounted_price %}
+                {% endif %}
+
+              </span>
+            {% endif %}
+           {% comment %}
+            <span
+              class="product-price-compare money original {% if selected_variant.compare_at_price > selected_variant.price %}visible{% endif %}"
+            >
+              {{ selected_variant.compare_at_price | money }}
+            </span>
+           {% endcomment %}
+        </p>
+
+        {% assign variant_for_unit_price = selected_variant %}
+        {% comment %}Inject unit-price begin{% endcomment %}
+        {% comment %}
+          @param variant_for_unit_price
+            Product variant for price
+          @param tax_text
+            String containing 'tax included' text
+        {% endcomment %}
+
+        {% capture total_quantity %}
+          <span class="product-price__unit-price-total-quantity" data-unit-price-quantity>
+            {{ variant_for_unit_price.unit_price_measurement.quantity_value }}{{ variant_for_unit_price.unit_price_measurement.quantity_unit }}
+          </span>
+        {% endcapture %}
+
+
+        {% capture unit_price %}
+          <span class="product-price__unit-price-amount money" data-unit-price-amount>
+            {{ variant_for_unit_price.unit_price | money }}
+          </span>
+        {% endcapture %}
+        {% capture unit_measure %}
+          <span class="product-price__unit-price-measure" data-unit-price-measure>
+            {%- if variant_for_unit_price.unit_price_measurement.reference_value != 1 -%}
+              {{ variant_for_unit_price.unit_price_measurement.reference_value }}
+            {%- endif %}
+            {{ variant_for_unit_price.unit_price_measurement.reference_unit }}
+          </span>
+        {% endcapture %}
+
+        <div
+          class="
+            product-price__unit-price
+            {% unless variant_for_unit_price.unit_price_measurement %}hidden{% endunless %}
+          "
+          data-unit-price
+        >
+          {{ 'products.product.price_per_unit_html' | t: total_quantity: total_quantity, unit_price: unit_price, unit_measure: unit_measure | strip_newlines }}
+        </div>
+
+        {% assign variant_for_unit_price = blank %}
+        {% comment %}Inject unit-price end{% endcomment %}
+
+
+        {%- capture tax_text -%}
+        {{ 'products.product.tax_line_html' | t }}
+        {%- endcapture -%}
+
+        {%- if tax_text != blank -%}
+          <div class="
+            product-price__tax
+            {% unless selected_variant.taxable %}hidden{% endunless %}
+            "
+            data-tax-line
+          >
+            {{ tax_text }}
+          </div>
+        {%- endif -%}
+
+        {{ form | payment_terms }}
+      </div>
+
+    {% when 'form' %}
+
+      <div class="product__form" {{ block.shopify_attributes }}>
+
+        {% unless product.has_only_default_variant %}
+          <div class="product-options">
+            {%-
+              render 'product-options-dropdown',
+              product: product,
+              form_id: product_id
+            -%}
+
+            <label
+              class="
+                product-option-column-1
+                product-option-row-4
+                product-option-quantity-label
+                {% if is_sample_like %}hidden{% endif %}
+              "
+              for="default-variant-quantity-input"
+            >
+              <strong>{{ 'general.general.quantity' | t }}:</strong>
+            </label>
+            {% comment %}
+            <input
+              class="product-option-quantity"
+              id="default-variant-quantity-input"
+              data-product-quantity-input
+              type="number"
+              inputmode="numeric"
+              name="quantity"
+              value="1"
+            >
+            {% endcomment %}
+            <!-- 020 -->
+            <div class="mm_quantity mm_buttons_added product-option-row-4 {% if is_sample_like %}hidden{% endif %}">
+              <input type="hidden" class="hquantity" name="hquantity" value="{{ prods_quantity_order_min }}">
+              <input type="button" value="-" class="minus">
+              <input
+                type="text"
+                step="{{ prods_quantity_order_units }}"
+                min="{{ prods_quantity_order_min }}"
+                max=""
+                name="quantity"
+                value="{{ prods_quantity_order_min }}"
+                title="Qty"
+                class="input-text qty text"
+                size="4"
+                pattern=""
+                inputmode=""
+                onkeypress="mm_validate(event)"
+              >
+              <input type="button" value="+" class="plus">
+            </div>
+            <!--  -->
+
+            <div class="selector-wrapper no-js-required">
+              <label for="product-select-{{ product_id }}"></label>
+              <select
+                class="product-select"
+                name="id"
+                id="product-select-{{ product_id }}"
+                data-select-ignore
+              >
+                {% for variant in product.variants %}
+                  {% if variant.available %}
+                    {% assign com_variant_title = variant.title | capitalize %}
+                    {% if com_variant_title == "Sample" %}
+                      {% assign dl_sample_variant = variant.id %}
+                      {% assign dl_sample_variant_title = product.title | append: ' - ' | append: variant.title %}
+                      {% assign dl_sample = 'small_sample' %}
+                    {% endif %}
+
+                    {% if com_variant_title == "Large Sample" %}
+                      {% assign dl_sample_variant2 = variant.id %}
+                      {% assign dl_sample_variant_title2 = product.title | append: ' - ' | append: variant.title %}
+                      {% assign dl_sample2 = 'large_sample' %}
+                    {% endif %}
+
+                    <option
+                      {% if variant == selected_variant %}selected="selected"{% endif %}
+                      value="{{ variant.id }}"
+                      data-variant-id="{{ variant.id }}"
+                      data-sku="{{ variant.sku }}"
+                      data-vprice="{{ variant.price }}"
+                    >
+                      {{ variant.title }} - {{ variant.price | money }}
+                    </option>
+                  {% else %}
+                    <option 
+                    disabled="disabled" 
+                    data-variant-id="{{ variant.id }}" 
+                    value="{{ variant.id }}"
+                    data-sku="{{ variant.sku }}">
+                      {{ variant.title }} - {{ 'products.product.sold_out' | t }}
+                    </option>
+                  {% endif %}
+                {% endfor %}
+              </select>
+            </div>
+          </div>
+        {% else %}
+          <div class="product-options product-options-default-only">
+            <input
+              class="product-select"
+              name="id"
+              value="{{ product.variants[0].id }}"
+              type="hidden"
+              data-variant-title="{{ product.variants[0].title }}"
+              data-sku="{{ product.variants[0].sku }}"
+              data-vprice="{{ product.variants[0].price }}"
+            />
+
+            <label
+              class="
+                product-option-column-1
+                product-option-row-1
+                product-option-quantity-label
+                {% if is_sample_like %}hidden{% endif %}
+              "
+              for="quantity-input"
+            >
+              <strong>{{ 'general.general.quantity' | t }}:</strong>
+            </label>
+
+<!--             <input
+              class="product-option-quantity"
+              id="quantity-input"
+              data-product-quantity-input
+              type="number"
+              inputmode="numeric"
+              name="quantity"
+              value="1"
+            > -->
+            <!-- 020 -->
+            <div class="mm_quantity mm_buttons_added product-option-row-1 {% if is_sample_like %}hidden{% endif %}">
+              <input type="hidden" class="hquantity" name="hquantity" value="{{ prods_quantity_order_min }}">
+              <input type="button" value="-" class="minus">
+              <input
+                type="text"
+                step="{{ prods_quantity_order_units }}"
+                min="{{ prods_quantity_order_min }}"
+                max=""
+                name="quantity"
+                value="{{ prods_quantity_order_min }}"
+                title="Qty"
+                class="input-text qty text"
+                size="4"
+                pattern=""
+                inputmode=""
+                onkeypress="mm_validate(event)"
+              >
+              <input type="button" value="+" class="plus">
+            </div>
+            <!--  -->
+          </div>
+        {% endunless %}
+
+        {% for tag in product.tags %}
+          {% if tag contains 'custom mural' %}
+            <!-- Custom Price Calculator -->
+            <div id="custom-calculator" style="display:none" data-calculatorid="62388fabd48c8"></div>
+            <script>
+              document.querySelector(".product-options .last_variant").innerHTML = "Custom Sizes";
+
+              var appendCalc = setInterval(moveCalc, 300);
+
+              function moveCalc() {
+                var calc = document.getElementById("calculator");
+                if (calc) {
+                  document
+                    .querySelector(".product-options")
+                    .insertBefore(
+                      document.getElementById("calculator"),
+                      document.querySelector(".product-options").children[2]
+                    );
+                  clearInterval(appendCalc);
+                }
+              }
+            </script>
+            <style>
+              .product-options {
+                display: flex;
+                flex-direction: column;
+                align-items: baseline;
+                margin-left: 0;
+              }
+              .product-options .product-option-quantity-label,
+              .mm_quantity.mm_buttons_added {
+                display: none !important;
+              }
+            </style>
+          {% endif %}
+        {% endfor %}
+
+        {% if product.available %}
+          <div id="infiniteoptions-container"></div>
+          <div id="uploadery-container"></div>
+        {% endif %}
+
+        <!-- Print PDF button -->
+        {% render 'button-product-pdf-print' %}
+
+        <div
+          class="
+            product-add-to-cart
+            {% if product != blank and show_payment_button %}
+              product-smart-payments
+            {% endif %}
+          "
+        >
+          {% if selected_variant.available and template.name != 'password' %}
+            <!-- 020 -->
+            <div class="custom-contact-message"></div>
+
+            <a
+              href="#"
+              class="dl-contact-btn custom-popup-contact-form"
+              {% if variant.price == 0 %}
+                style="display:inline-block;"
+              {% else %}
+                style="display:none;"
+              {% endif %}
+            >
+              Contact Us
+            </a>
+
+            {% assign title = 'Request Sample' %}
+            {% assign showonly = blank %}
+            {% if product.tags contains "Showroom only" and product.price == 0 %}
+              {% assign showonly = 'showonly' %}
+            {% endif %}
+            {% if product.tags contains "Showroom Only" and product.price == 0 %}
+              {% assign showonly = 'showonly' %}
+            {% endif %}
+
+            {% if is_sample_sku and dl_sample == blank and dl_sample2 == blank %}
+              <a
+                href=""
+                data-dlvid="{{ selected_variant.id }}"
+                data-dlvtitle="{{ product.title | append: ' - Sample' }}"
+                class="dl-sample-btn {{ showonly }}"
+                data-product-id="{{ product.id }}"
+              >
+                {{ title }}
+              </a>
+            {% endif %}
+
+            {% if dl_sample != blank and dl_sample2 != blank and dl_sample == 'small_sample' and dl_sample2 == 'large_sample' %}
+              {% assign title = 'Small Sample' %}
+            {% endif %}
+
+            {% if dl_sample == 'small_sample' and dl_sample_variant !='' and  dl_sample_variant_title != '' %}
+              <a
+                href=""
+                data-dlvid="{{ dl_sample_variant }}"
+                data-dlvtitle="{{ dl_sample_variant_title }}"
+                class="dl-sample-btn {{ showonly }}"
+                data-product-id="{{ product.id }}"
+              >
+                {{ title }}
+              </a>
+            {% endif %}
+
+            {% if dl_sample2 == 'large_sample' and dl_sample_variant2 !='' and  dl_sample_variant_title2 != '' %}
+              <a
+                href=""
+                data-dlvid="{{ dl_sample_variant2 }}"
+                data-dlvtitle="{{ dl_sample_variant_title2 }}"
+                class="dl-sample-btn {{ showonly }}"
+                data-product-id="{{ product.id }}"
+              >
+                Large Sample
+              </a>
+            {% endif %}
+            {% for variant_item in product.variants %}
+              {% if variant_item.price == 0 and variant_item.title contains "Sample" and variant_item.title != "Sample" %}
+                {% assign showing_title = variant_item.title %}
+                {% if showing_title == "Textured Vinyl Sample" %}
+                  {% assign showing_title = "Vinyl Sample" %}
+                {% endif %}
+                <a
+                  href=""
+                  data-dlvid="{{ variant_item.id }}"
+                  data-dlvtitle="{{ variant_item.title }}"
+                  class="dl-second-sample-btn {% if variant_item.id != product.selected_or_first_available_variant.id %}unavailable{% endif %} {{ showonly }}"
+                  data-product-id="{{ product.id }}"
+                >
+                  Request {{ showing_title }}
+                </a>
+              {% endif %}
+            {% endfor %}
+
+            {% render 'spec-sheet-button' %}
+
+<!--             <input class="add-to-cart" type="submit" value="{{ 'products.product.add_to_cart' | t }}" /> -->
+            {% assign com_first_variant_title = product.selected_or_first_available_variant.title | capitalize %}
+            <input class="add-to-cart {% if is_sample_like %}hidden{% endif %} {% if product.variants.size == 1 and com_first_variant_title == "Sample" %}hidden{% endif %} {% if product.selected_or_first_available_variant.price == 0 %}unavailable{% endif %}" type="submit" value="{{ 'products.product.add_to_cart' | t }}"/>
+          {% else %}
+            <input class="add-to-cart disabled" type="submit" value="{{ 'products.product.sold_out' | t }}" disabled/>
+          {% endif %}
+
+          <!--020 -->
+          {% for t in product.tags %}
+             {% if t == 'Customize' %}
+                    <a href="#" class="dl-customize-btn custom-popup-contact-form">Customize this Pattern</a>
+             {% endif %}
+          {% endfor %}
+
+          {% if show_payment_button %}
+            {{ form | payment_button }}
+          {% endif %}
+
+          {% capture the_snippet_fave %}{% include 'socialshopwave-widget-fave' %}{% endcapture %}
+          {% unless the_snippet_fave contains 'Liquid error' %}
+          {{ the_snippet_fave }}
+          {% endunless %}
+        </div>
+        <div class="product-message"></div>
+
+        <div data-surface-pick-up></div>
+        {%-
+          render 'modal',
+          modal_id: 'surface-pick-up',
+          modal_class: 'surface-pick-up-modal',
+        -%}
+      </div>
+
+    {% when 'social' %}
+      <div class="product__social" {{ block.shopify_attributes }}>
+        {% render 'share-buttons' %}
+      </div>
+
+    {% when 'description' %}
+      {% if product != blank and product.description != blank %}
+        <div class="product-description rte" {{ block.shopify_attributes }}>
+          {{ product.description }}
+        </div>
+      {% elsif product == blank %}
+        <div class="product-description rte" {{ block.shopify_attributes }}>
+          {{ 'products.product.onboarding.description' | t }}
+        </div>
+      {% endif %}
+
+    {%- when 'rating' -%}
+      {%- if product.metafields.reviews.rating.value != blank -%}
+        <div class="product__rating rating" {{ block.shopify_attributes }}>
+          {%
+            render 'rating-stars',
+            value: product.metafields.reviews.rating.value.rating,
+            scale_max: product.metafields.reviews.rating.value.scale_max,
+          %}
+          <p class="rating__text">
+            <span aria-hidden="true">{{ product.metafields.reviews.rating.value }} / {{ product.metafields.reviews.rating.value.scale_max }}</span>
+          </p>
+          <p class="rating__count">
+            <span aria-hidden="true">({{ product.metafields.reviews.rating_count }})</span>
+            <span class="visually-hidden">{{ product.metafields.reviews.rating_count }} {{ "general.accessibility.total_reviews" | t }}</span>
+          </p>
+        </div>
+      {%- endif -%}
+  {% endcase %}
+{% endfor %}
diff --git a/shopify/theme-fixes/custom-js-qty-2026-06-30/liquid/snippets__section.flex-pdp.quantity-picker.liquid b/shopify/theme-fixes/custom-js-qty-2026-06-30/liquid/snippets__section.flex-pdp.quantity-picker.liquid
new file mode 100644
index 00000000..c4848b56
--- /dev/null
+++ b/shopify/theme-fixes/custom-js-qty-2026-06-30/liquid/snippets__section.flex-pdp.quantity-picker.liquid
@@ -0,0 +1,70 @@
+{% doc %}
+  Copyright © 2025 Archetype Themes LP. All rights reserved.
+
+  Renders a quantity selector with optional inventory status display.
+
+  This component provides a quantity input field with increment/decrement buttons
+  and can optionally display inventory status information. It respects inventory
+  limits when inventory management is enabled and shows appropriate maximum values.
+
+  @param {boolean} [show_inventory_status] - Whether to show inventory status below quantity selector (default: true)
+  @param {number} [inventory_threshold] - The inventory level at which to show low stock warning (default: 10)
+
+  @example
+  {% render 'section.flex-pdp.quantity-picker', show_inventory_status: true, inventory_threshold: 5, product: closest.product %}
+{% enddoc %}
+
+{%- liquid
+  assign form_id = 'section.flex-pdp.form-' | append: section.id
+  assign show_inventory_status = show_inventory_status | default: block.settings.show_inventory_status, allow_false: true | default: true, allow_false: true
+  assign inventory_threshold = inventory_threshold | default: block.settings.inventory_threshold | default: 10
+  assign current_variant = product.selected_or_first_available_variant
+-%}
+
+{% capture product_inventory %}
+  {% render 'section.flex-pdp._inventory-text', product: product, inventory_threshold: inventory_threshold %}
+{% endcapture %}
+
+{% capture quantity_selector_label %}
+  {% capture quantity_selector_attributes %}
+    for="{% render 'utility.id', name: product.id %}"
+  {% endcapture -%}
+
+  {% if show_inventory_status %}
+    {%  capture quantity_selector_label_beginning %}
+      {%- render 'utility.translate', key: 'labels.quantity', fallback: 'Quantity' -%}
+    {% endcapture %}
+    {% assign quantity_selector_label_beginning = quantity_selector_label_beginning | strip | append: ':' %}
+    {%  capture quantity_selector_label_content %}
+      {% render 'element.text', as: 'span', text: quantity_selector_label_beginning, style: 'font-weight: 600;' %}
+      {% render 'element.text', as: 'span', text: product_inventory, style: 'opacity: 0.75;' %}
+    {% endcapture %}
+    {% render 'element.text', as: 'label', variant: 'body-sm', text: quantity_selector_label_content, attributes: quantity_selector_attributes %}
+  {% else %}
+    {% render 'element.text', as: 'label', variant: 'body-sm', locale: 'labels.quantity', text: 'Quantity', style: 'font-weight: 600;', attributes: quantity_selector_attributes %}
+  {% endif %}
+{% endcapture %}
+
+{% capture quantity_selector_stack %}
+  {% assign value = 1 %}
+  {% assign max = '' %}
+  {% assign min = 1 %}
+  {% assign disabled = false %}
+
+  {% if current_variant.inventory_management == 'shopify' and current_variant.inventory_policy != 'continue' and show_inventory_status %}
+    {% assign max = current_variant.inventory_quantity %}
+  {% endif %}
+
+  {% unless current_variant.available %}
+    {% assign max = 0 %}
+    {% assign min = 0 %}
+    {% assign value = 0 %}
+    {% assign disabled = true %}
+  {% endunless %}
+
+  {% render 'layout.stack', gap: 'xs', horizontal: true, slot: quantity_selector_label %}
+  {% render 'element.quantity-selector', product: product, form_id: form_id, max: max, value: value, min: min, disabled: disabled %}
+{% endcapture %}
+
+{% render 'layout.stack', gap: 'xs', slot: quantity_selector_stack %}
+
diff --git a/shopify/theme-fixes/custom-js-qty-2026-06-30/probe.cjs b/shopify/theme-fixes/custom-js-qty-2026-06-30/probe.cjs
new file mode 100644
index 00000000..5318ca83
--- /dev/null
+++ b/shopify/theme-fixes/custom-js-qty-2026-06-30/probe.cjs
@@ -0,0 +1,72 @@
+// Probe the +/- stepper on a given theme. Usage: node probe.cjs <themeId> <label>
+const { chromium } = require(require('path').join(process.env.HOME, 'Projects/Designer-Wallcoverings/node_modules/playwright'));
+
+const THEME = process.argv[2];
+const LABEL = process.argv[3] || THEME;
+const HANDLE = process.argv[4] || 'dwtt-80064-designer-wallcoverings-los-angeles';
+const BASE = 'https://designer-laboratory-sandbox.myshopify.com/products/' + HANDLE;
+const URL = THEME ? `${BASE}?preview_theme_id=${THEME}` : BASE;
+
+(async () => {
+  const browser = await chromium.launch();
+  const ctx = await browser.newContext();
+  const page = await ctx.newPage();
+  let out_pick = null;
+  const errors = [];
+  page.on('pageerror', e => errors.push('PAGEERROR: ' + e.message));
+  page.on('console', m => { if (m.type() === 'error') errors.push('CONSOLE.error: ' + m.text()); });
+
+  await page.goto(URL, { waitUntil: 'domcontentloaded', timeout: 60000 });
+  await page.waitForSelector('.mm_quantity input[name="quantity"]', { state: 'attached', timeout: 30000 });
+  await page.waitForTimeout(1800);
+
+  // Select the ROLL (non-sample) variant so the qty picker is shown.
+  const picked = await page.evaluate(() => {
+    const sel = document.querySelector('.product-select');
+    if (!sel || sel.tagName !== 'SELECT') return { ok: false, reason: 'no <select> (single-variant?)' };
+    const opts = Array.from(sel.options);
+    // pick first option whose text/sku is NOT a sample
+    const roll = opts.find(o => {
+      const t = (o.textContent || '').toLowerCase();
+      const sku = (o.getAttribute('data-sku') || '').toLowerCase();
+      return !/sample/.test(t) && !/-sample$/.test(sku);
+    }) || opts[0];
+    sel.value = roll.value;
+    sel.dispatchEvent(new Event('change', { bubbles: true }));
+    // jQuery change too
+    if (window.jQuery) window.jQuery(sel).trigger('change');
+    return { ok: true, chosen: roll.textContent.trim(), sku: roll.getAttribute('data-sku') };
+  });
+  out_pick = picked;
+  await page.waitForTimeout(1500);
+
+  const getState = async () => page.evaluate(() => {
+    const q = document.querySelector('.mm_quantity .input-text.qty, .mm_quantity input[name="quantity"]');
+    const h = document.querySelector('.mm_quantity .hquantity, input[name="hquantity"]');
+    return {
+      qtyVal: q ? q.value : null,
+      qtyStep: q ? q.getAttribute('step') : null,
+      qtyMin: q ? q.getAttribute('min') : null,
+      qtyMax: q ? q.getAttribute('max') : null,
+      hVal: h ? h.value : null,
+      hAttr: h ? h.getAttribute('value') : null,
+      plusCount: document.querySelectorAll('.mm_quantity .plus').length,
+      minusCount: document.querySelectorAll('.mm_quantity .minus').length,
+    };
+  });
+
+  const clickPlus = async () => { await page.click('.mm_quantity .plus'); await page.waitForTimeout(300); };
+  const clickMinus = async () => { await page.click('.mm_quantity .minus'); await page.waitForTimeout(300); };
+
+  const out = { label: LABEL, url: URL, variantPicked: out_pick, steps: [] };
+  out.steps.push(['initial', await getState()]);
+  await clickPlus(); out.steps.push(['after +1', await getState()]);
+  await clickPlus(); out.steps.push(['after +2', await getState()]);
+  await clickMinus(); out.steps.push(['after -1', await getState()]);
+  await clickMinus(); out.steps.push(['after -2', await getState()]);
+  await clickMinus(); out.steps.push(['after -3 (floor test)', await getState()]);
+  out.errors = errors;
+
+  console.log(JSON.stringify(out, null, 2));
+  await browser.close();
+})().catch(e => { console.error('FATAL', e); process.exit(1); });
diff --git a/shopify/theme-fixes/custom-js-qty-2026-06-30/trace.cjs b/shopify/theme-fixes/custom-js-qty-2026-06-30/trace.cjs
new file mode 100644
index 00000000..41115718
--- /dev/null
+++ b/shopify/theme-fixes/custom-js-qty-2026-06-30/trace.cjs
@@ -0,0 +1,45 @@
+const { chromium } = require(require('path').join(process.env.HOME, 'Projects/Designer-Wallcoverings/node_modules/playwright'));
+const THEME = process.argv[2];
+const HANDLE = 'dwtt-80064-designer-wallcoverings-los-angeles';
+const URL = `https://designer-laboratory-sandbox.myshopify.com/products/${HANDLE}?preview_theme_id=${THEME}`;
+(async () => {
+  const browser = await chromium.launch();
+  const page = await (await browser.newContext()).newPage();
+  const errs = [];
+  page.on('pageerror', e => errs.push('PAGEERROR: ' + e.message));
+  await page.goto(URL, { waitUntil: 'domcontentloaded', timeout: 60000 });
+  await page.waitForSelector('.mm_quantity input[name="quantity"]', { state: 'attached', timeout: 30000 });
+  await page.waitForTimeout(1800);
+  await page.evaluate(() => {
+    const sel = document.querySelector('.product-select');
+    if (sel && sel.tagName === 'SELECT') {
+      const opts = Array.from(sel.options);
+      const roll = opts.find(o => !/sample/i.test(o.textContent) && !/-sample$/i.test(o.getAttribute('data-sku')||'')) || opts[0];
+      sel.value = roll.value; sel.dispatchEvent(new Event('change', { bubbles: true }));
+      if (window.jQuery) window.jQuery(sel).trigger('change');
+    }
+  });
+  await page.waitForTimeout(1500);
+
+  // Manually replicate the plus-handler math and report each intermediate.
+  const trace = await page.evaluate(() => {
+    const $ = window.jQuery;
+    const btn = document.querySelector('.mm_quantity .plus');
+    const a = $(btn).closest('.mm_quantity').find('.qty');
+    const before = a.val();
+    const b = parseFloat(a.val());
+    const c = parseFloat(a.attr('max'));
+    const d = parseFloat(a.attr('min'));
+    const e = a.attr('step');
+    // compute what the handler would set
+    let target;
+    const eNum = ('any'!==e && ''!==e && e!==undefined && !isNaN(parseFloat(e))) ? e : '1';
+    const decimals = (function(s){var m=(''+s).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);return m?Math.max(0,(m[1]?m[1].length:0)-(m[2]?+m[2]:0)):0;})(eNum);
+    target = (b + parseFloat(eNum)).toFixed(decimals);
+    a.val(target);
+    const afterSet = a.val();
+    return { before, b, c: isNaN(c)?'NaN':c, d, e, eNum, decimals, target, afterSet, elemCount: a.length };
+  });
+  console.log(JSON.stringify({ trace, errs }, null, 2));
+  await browser.close();
+})().catch(e => { console.error('FATAL', e); process.exit(1); });

← a1e11baf Theme fix: color-dots makeDot 'c is not defined' scoping bug  ·  back to Designer Wallcoverings  ·  DWTT qty stepper fix: repair +/- increment/decrement in cust b77fe370 →