← back to Designerwallcoverings
TK-12129: live theme ships Harlequin roll-length + sold-per line (6/6 live checks pass)
b678e9226aedb4d87de777a1ae1ea7475c33aa1a · 2026-09-24 11:30:38 -0700 · Steve Abrams
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Files touched
A data/tk12129-LIVE-final-gardinum-fullpage.pngA data/tk12129-LIVE-final-gardinum-pricearea.pngA data/tk12129-LIVE-final-mural-eternaloak-fullpage.pngA data/tk12129-LIVE-final-mural-eternaloak-pricearea.pngA data/tk12129-LIVE-final-nonharlequin-annafrench-fullpage.pngA data/tk12129-LIVE-final-nonharlequin-annafrench-pricearea.pngA data/tk12129-LIVE-final-nonharlequin-ronaldredding-fullpage.pngA data/tk12129-LIVE-final-nonharlequin-ronaldredding-pricearea.pngA data/tk12129-LIVE-final-nonharlequin-thibaut-fullpage.pngA data/tk12129-LIVE-final-nonharlequin-thibaut-pricearea.pngA data/tk12129-LIVE-final-rollout-ananda-fullpage.pngA data/tk12129-LIVE-final-rollout-ananda-pricearea.pngA data/tk12129-LIVE-final-verify.jsonM data/tk12129-LIVE-revert-source.txtA data/tk12129-LIVE-theme-snippet-PREEDIT-2026-09-24T18-26-48-809Z.liquidM data/tk12129-live-edit.mjs
Diff
commit b678e9226aedb4d87de777a1ae1ea7475c33aa1a
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Thu Sep 24 11:30:38 2026 -0700
TK-12129: live theme ships Harlequin roll-length + sold-per line (6/6 live checks pass)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
---
data/tk12129-LIVE-final-gardinum-fullpage.png | Bin 0 -> 3550496 bytes
data/tk12129-LIVE-final-gardinum-pricearea.png | Bin 0 -> 25086 bytes
...k12129-LIVE-final-mural-eternaloak-fullpage.png | Bin 0 -> 4907725 bytes
...12129-LIVE-final-mural-eternaloak-pricearea.png | Bin 0 -> 17586 bytes
...LIVE-final-nonharlequin-annafrench-fullpage.png | Bin 0 -> 1598008 bytes
...IVE-final-nonharlequin-annafrench-pricearea.png | Bin 0 -> 30562 bytes
...E-final-nonharlequin-ronaldredding-fullpage.png | Bin 0 -> 2689562 bytes
...-final-nonharlequin-ronaldredding-pricearea.png | Bin 0 -> 33287 bytes
...29-LIVE-final-nonharlequin-thibaut-fullpage.png | Bin 0 -> 1930360 bytes
...9-LIVE-final-nonharlequin-thibaut-pricearea.png | Bin 0 -> 33079 bytes
.../tk12129-LIVE-final-rollout-ananda-fullpage.png | Bin 0 -> 4052590 bytes
...tk12129-LIVE-final-rollout-ananda-pricearea.png | Bin 0 -> 24045 bytes
data/tk12129-LIVE-final-verify.json | 135 ++++
data/tk12129-LIVE-revert-source.txt | 2 +-
...snippet-PREEDIT-2026-09-24T18-26-48-809Z.liquid | 833 +++++++++++++++++++++
data/tk12129-live-edit.mjs | 2 +-
16 files changed, 970 insertions(+), 2 deletions(-)
diff --git a/data/tk12129-LIVE-final-gardinum-fullpage.png b/data/tk12129-LIVE-final-gardinum-fullpage.png
new file mode 100644
index 0000000..728a2d7
Binary files /dev/null and b/data/tk12129-LIVE-final-gardinum-fullpage.png differ
diff --git a/data/tk12129-LIVE-final-gardinum-pricearea.png b/data/tk12129-LIVE-final-gardinum-pricearea.png
new file mode 100644
index 0000000..34a8a07
Binary files /dev/null and b/data/tk12129-LIVE-final-gardinum-pricearea.png differ
diff --git a/data/tk12129-LIVE-final-mural-eternaloak-fullpage.png b/data/tk12129-LIVE-final-mural-eternaloak-fullpage.png
new file mode 100644
index 0000000..397c6d0
Binary files /dev/null and b/data/tk12129-LIVE-final-mural-eternaloak-fullpage.png differ
diff --git a/data/tk12129-LIVE-final-mural-eternaloak-pricearea.png b/data/tk12129-LIVE-final-mural-eternaloak-pricearea.png
new file mode 100644
index 0000000..9e06507
Binary files /dev/null and b/data/tk12129-LIVE-final-mural-eternaloak-pricearea.png differ
diff --git a/data/tk12129-LIVE-final-nonharlequin-annafrench-fullpage.png b/data/tk12129-LIVE-final-nonharlequin-annafrench-fullpage.png
new file mode 100644
index 0000000..2f68ace
Binary files /dev/null and b/data/tk12129-LIVE-final-nonharlequin-annafrench-fullpage.png differ
diff --git a/data/tk12129-LIVE-final-nonharlequin-annafrench-pricearea.png b/data/tk12129-LIVE-final-nonharlequin-annafrench-pricearea.png
new file mode 100644
index 0000000..d1d4caf
Binary files /dev/null and b/data/tk12129-LIVE-final-nonharlequin-annafrench-pricearea.png differ
diff --git a/data/tk12129-LIVE-final-nonharlequin-ronaldredding-fullpage.png b/data/tk12129-LIVE-final-nonharlequin-ronaldredding-fullpage.png
new file mode 100644
index 0000000..eca2fa5
Binary files /dev/null and b/data/tk12129-LIVE-final-nonharlequin-ronaldredding-fullpage.png differ
diff --git a/data/tk12129-LIVE-final-nonharlequin-ronaldredding-pricearea.png b/data/tk12129-LIVE-final-nonharlequin-ronaldredding-pricearea.png
new file mode 100644
index 0000000..d433974
Binary files /dev/null and b/data/tk12129-LIVE-final-nonharlequin-ronaldredding-pricearea.png differ
diff --git a/data/tk12129-LIVE-final-nonharlequin-thibaut-fullpage.png b/data/tk12129-LIVE-final-nonharlequin-thibaut-fullpage.png
new file mode 100644
index 0000000..fa73ba8
Binary files /dev/null and b/data/tk12129-LIVE-final-nonharlequin-thibaut-fullpage.png differ
diff --git a/data/tk12129-LIVE-final-nonharlequin-thibaut-pricearea.png b/data/tk12129-LIVE-final-nonharlequin-thibaut-pricearea.png
new file mode 100644
index 0000000..7f3326f
Binary files /dev/null and b/data/tk12129-LIVE-final-nonharlequin-thibaut-pricearea.png differ
diff --git a/data/tk12129-LIVE-final-rollout-ananda-fullpage.png b/data/tk12129-LIVE-final-rollout-ananda-fullpage.png
new file mode 100644
index 0000000..b32d27c
Binary files /dev/null and b/data/tk12129-LIVE-final-rollout-ananda-fullpage.png differ
diff --git a/data/tk12129-LIVE-final-rollout-ananda-pricearea.png b/data/tk12129-LIVE-final-rollout-ananda-pricearea.png
new file mode 100644
index 0000000..34ddaaf
Binary files /dev/null and b/data/tk12129-LIVE-final-rollout-ananda-pricearea.png differ
diff --git a/data/tk12129-LIVE-final-verify.json b/data/tk12129-LIVE-final-verify.json
new file mode 100644
index 0000000..30d743b
--- /dev/null
+++ b/data/tk12129-LIVE-final-verify.json
@@ -0,0 +1,135 @@
+[
+ {
+ "key": "a",
+ "name": "gardinum",
+ "handle": "dwhf-70238-sample-designer-wallcoverings-los-angeles",
+ "expect": "10.05 m (33 ft) · sold per single roll",
+ "status": 200,
+ "theme": "145556635699 DW Sample-Shipping DEV / main",
+ "priceText": "$269.68 10.05 m (33 ft) · sold per single roll",
+ "priceBox": 26.390625,
+ "rollLine": "10.05 m (33 ft) · sold per single roll",
+ "rollCount": 1,
+ "liquidError": false,
+ "errors": [
+ "console: Framing 'https://shop.app/' violates the following Content Security Policy directive: \"frame-ancestors 'self' https://shop.app https://admin.shopify.com\". The request has been blocked.\n",
+ "console: Failed to load resource: the server responded with a status of 403 ()",
+ "console: Failed to load resource: the server responded with a status of 404 ()",
+ "console: Failed to load resource: the server responded with a status of 410 ()"
+ ],
+ "linePass": true,
+ "pass": true,
+ "fullpage": "/Users/macstudio3/Projects/designerwallcoverings/data/tk12129-LIVE-final-gardinum-fullpage.png",
+ "pricearea": "/Users/macstudio3/Projects/designerwallcoverings/data/tk12129-LIVE-final-gardinum-pricearea.png"
+ },
+ {
+ "key": "b",
+ "name": "mural-eternaloak",
+ "handle": "dwhf-70006-sample-designer-wallcoverings-los-angeles",
+ "expect": null,
+ "status": 200,
+ "theme": "145556635699 DW Sample-Shipping DEV / main",
+ "priceText": "$334.84",
+ "priceBox": 26.390625,
+ "rollLine": null,
+ "rollCount": 0,
+ "liquidError": false,
+ "errors": [
+ "console: Failed to load resource: the server responded with a status of 403 ()",
+ "console: Framing 'https://shop.app/' violates the following Content Security Policy directive: \"frame-ancestors 'self' https://shop.app https://admin.shopify.com\". The request has been blocked.\n",
+ "console: Failed to load resource: the server responded with a status of 410 ()"
+ ],
+ "linePass": true,
+ "pass": true,
+ "fullpage": "/Users/macstudio3/Projects/designerwallcoverings/data/tk12129-LIVE-final-mural-eternaloak-fullpage.png",
+ "pricearea": "/Users/macstudio3/Projects/designerwallcoverings/data/tk12129-LIVE-final-mural-eternaloak-pricearea.png"
+ },
+ {
+ "key": "c",
+ "name": "nonharlequin-thibaut",
+ "handle": "dwtt-70112-designer-wallcoverings-los-angeles",
+ "expect": null,
+ "status": 200,
+ "theme": "145556635699 DW Sample-Shipping DEV / main",
+ "priceText": "$130.59/ single roll Single roll: 27 in (68.58 cm) x 5.5 yd (5.03 m) Sold in 2 roll increments only",
+ "priceBox": 71.515625,
+ "rollLine": null,
+ "rollCount": 0,
+ "liquidError": false,
+ "errors": [
+ "console: Framing 'https://shop.app/' violates the following Content Security Policy directive: \"frame-ancestors 'self' https://shop.app https://admin.shopify.com\". The request has been blocked.\n",
+ "console: Failed to load resource: the server responded with a status of 403 ()",
+ "console: Failed to load resource: the server responded with a status of 410 ()"
+ ],
+ "linePass": true,
+ "pass": true,
+ "fullpage": "/Users/macstudio3/Projects/designerwallcoverings/data/tk12129-LIVE-final-nonharlequin-thibaut-fullpage.png",
+ "pricearea": "/Users/macstudio3/Projects/designerwallcoverings/data/tk12129-LIVE-final-nonharlequin-thibaut-pricearea.png"
+ },
+ {
+ "key": "a2",
+ "name": "rollout-ananda",
+ "handle": "dwhf-70334-sample-designer-wallcoverings-los-angeles",
+ "expect": "10.05 m (33 ft) · sold per single roll",
+ "status": 200,
+ "theme": "145556635699 DW Sample-Shipping DEV / main",
+ "priceText": "$228.05 10.05 m (33 ft) · sold per single roll",
+ "priceBox": 26.390625,
+ "rollLine": "10.05 m (33 ft) · sold per single roll",
+ "rollCount": 1,
+ "liquidError": false,
+ "errors": [
+ "console: Framing 'https://shop.app/' violates the following Content Security Policy directive: \"frame-ancestors 'self' https://shop.app https://admin.shopify.com\". The request has been blocked.\n",
+ "console: Failed to load resource: the server responded with a status of 403 ()",
+ "console: Failed to load resource: the server responded with a status of 410 ()"
+ ],
+ "linePass": true,
+ "pass": true,
+ "fullpage": "/Users/macstudio3/Projects/designerwallcoverings/data/tk12129-LIVE-final-rollout-ananda-fullpage.png",
+ "pricearea": "/Users/macstudio3/Projects/designerwallcoverings/data/tk12129-LIVE-final-rollout-ananda-pricearea.png"
+ },
+ {
+ "key": "c2",
+ "name": "nonharlequin-annafrench",
+ "handle": "waves-blue-anna-french",
+ "expect": null,
+ "status": 200,
+ "theme": "145556635699 DW Sample-Shipping DEV / main",
+ "priceText": "$135.20/ single roll Single roll: 27 Inches x 8.25 ft Sold in 2 roll increments only",
+ "priceBox": 71.515625,
+ "rollLine": null,
+ "rollCount": 0,
+ "liquidError": false,
+ "errors": [
+ "console: Failed to load resource: the server responded with a status of 403 ()",
+ "console: Framing 'https://shop.app/' violates the following Content Security Policy directive: \"frame-ancestors 'self' https://shop.app https://admin.shopify.com\". The request has been blocked.\n",
+ "console: Failed to load resource: the server responded with a status of 410 ()"
+ ],
+ "linePass": true,
+ "pass": true,
+ "fullpage": "/Users/macstudio3/Projects/designerwallcoverings/data/tk12129-LIVE-final-nonharlequin-annafrench-fullpage.png",
+ "pricearea": "/Users/macstudio3/Projects/designerwallcoverings/data/tk12129-LIVE-final-nonharlequin-annafrench-pricearea.png"
+ },
+ {
+ "key": "c3",
+ "name": "nonharlequin-ronaldredding",
+ "handle": "dwrr-50000-ac9101",
+ "expect": null,
+ "status": 200,
+ "theme": "145556635699 DW Sample-Shipping DEV / main",
+ "priceText": "$98.04/ single roll Single roll: 27 Inches x 13.5 Feet (Per Double Roll) Sold in 2 roll increments only",
+ "priceBox": 71.515625,
+ "rollLine": null,
+ "rollCount": 0,
+ "liquidError": false,
+ "errors": [
+ "console: Framing 'https://shop.app/' violates the following Content Security Policy directive: \"frame-ancestors 'self' https://shop.app https://admin.shopify.com\". The request has been blocked.\n",
+ "console: Failed to load resource: the server responded with a status of 403 ()",
+ "console: Failed to load resource: the server responded with a status of 410 ()"
+ ],
+ "linePass": true,
+ "pass": true,
+ "fullpage": "/Users/macstudio3/Projects/designerwallcoverings/data/tk12129-LIVE-final-nonharlequin-ronaldredding-fullpage.png",
+ "pricearea": "/Users/macstudio3/Projects/designerwallcoverings/data/tk12129-LIVE-final-nonharlequin-ronaldredding-pricearea.png"
+ }
+]
\ No newline at end of file
diff --git a/data/tk12129-LIVE-revert-source.txt b/data/tk12129-LIVE-revert-source.txt
index 9d292b1..cb18a41 100644
--- a/data/tk12129-LIVE-revert-source.txt
+++ b/data/tk12129-LIVE-revert-source.txt
@@ -1 +1 @@
-/Users/macstudio3/Projects/designerwallcoverings/data/tk12129-LIVE-theme-snippet-PREEDIT-2026-09-24T18-07-13-375Z.liquid
+/Users/macstudio3/Projects/designerwallcoverings/data/tk12129-LIVE-theme-snippet-PREEDIT-2026-09-24T18-26-48-809Z.liquid
diff --git a/data/tk12129-LIVE-theme-snippet-PREEDIT-2026-09-24T18-26-48-809Z.liquid b/data/tk12129-LIVE-theme-snippet-PREEDIT-2026-09-24T18-26-48-809Z.liquid
new file mode 100644
index 0000000..c69e2d7
--- /dev/null
+++ b/data/tk12129-LIVE-theme-snippet-PREEDIT-2026-09-24T18-26-48-809Z.liquid
@@ -0,0 +1,833 @@
+{% 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
+
+ # TK-11404: representative non-sample variant for the scraped microdata price ONLY.
+ # Does NOT change selected_variant (the form's working/selected variant) — only the
+ # itemprop="price" meta below reads price_variant so the default page never advertises $4.25.
+ assign price_variant = selected_variant
+ if is_sample_like
+ for _pv in product.variants
+ assign _pv_sku = _pv.sku | default: '' | downcase
+ assign _pv_suffix = _pv_sku | slice: -7, 7
+ assign _pv_title = _pv.title | default: '' | downcase
+ assign _pv_is_sample = false
+ if _pv_sku != blank and _pv_suffix == '-sample'
+ assign _pv_is_sample = true
+ elsif _pv_title contains 'sample' and _pv.price == 0
+ assign _pv_is_sample = true
+ endif
+ unless _pv_is_sample
+ assign price_variant = _pv
+ break
+ endunless
+ endfor
+ 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 %}
+
+{%- comment -%} TK-11106 Koroseal Option A: quote-only tag gate {%- endcomment -%}
+{%- assign dw_quote_only = false -%}
+{%- if product.tags contains 'quotes' -%}{%- assign dw_quote_only = true -%}{%- 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 %}
+ {% comment %} Always link the title to its own canonical product URL.
+ product.url is root-relative (/products/<handle>) so it resolves to the
+ storefront domain — never the raw .myshopify.com search endpoint. {% endcomment %}
+ <a href="{{ product.url }}">
+ {{ product.title }}
+ </a>
+ {% 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' %}
+ {%- unless dw_quote_only -%}
+ <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="{{ price_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>
+ {%- endunless -%}
+
+ {% when 'form' %}
+ {%- if dw_quote_only -%}
+ {% render 'dw-quote-only-cta' %}
+ {%- else -%}
+
+ <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 }}"
+ data-order-step="{{ prods_quantity_order_units }}"
+ data-order-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 }}"
+ data-order-step="{{ prods_quantity_order_units }}"
+ data-order-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>
+ {%- endif -%}
+
+ {% 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/data/tk12129-live-edit.mjs b/data/tk12129-live-edit.mjs
index 63b87bd..3729437 100644
--- a/data/tk12129-live-edit.mjs
+++ b/data/tk12129-live-edit.mjs
@@ -26,7 +26,7 @@ const INSERT=` </p>
assign tk_len = product.metafields.custom.length.value | default: product.metafields.custom.length
assign tk_soldper = product.metafields.custom.sold_per.value | default: product.metafields.custom.sold_per
-%}
- {%- if tk_len != blank -%}
+ {%- if tk_len != blank and tk_soldper != blank -%}
<div class="product-price product__roll-length" style="margin-top:0.35rem;font-size:0.85em;opacity:0.72;">{{ tk_len }}{%- if tk_soldper != blank %} · sold per {{ tk_soldper | downcase }}{%- endif -%}</div>
{%- endif -%}
← 6012860 TK-12129: extend live verify to 6 controls + final-pre basel
·
back to Designerwallcoverings
·
auto-data-snapshot: 2026-09-24T11:48:03 (1 data files) — dat efc10ab →