← back to Designer Wallcoverings
Theme MOQ fix: custom PDP quantity reads order-min metafields (min/step/value + clamp script) — staged section + live/dev backups
0bc56eb7e5116774f218296589962466bc83514d · 2026-06-22 13:55:46 -0700 · Steve Abrams
Files touched
A shopify/theme-moq/sections-product.DEV-original.liquidA shopify/theme-moq/sections-product.FIXED.liquidA shopify/theme-moq/sections-product.LIVE-original.liquid
Diff
commit 0bc56eb7e5116774f218296589962466bc83514d
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Mon Jun 22 13:55:46 2026 -0700
Theme MOQ fix: custom PDP quantity reads order-min metafields (min/step/value + clamp script) — staged section + live/dev backups
---
.../theme-moq/sections-product.DEV-original.liquid | 322 +++++++++++++++++
shopify/theme-moq/sections-product.FIXED.liquid | 380 +++++++++++++++++++++
.../sections-product.LIVE-original.liquid | 333 ++++++++++++++++++
3 files changed, 1035 insertions(+)
diff --git a/shopify/theme-moq/sections-product.DEV-original.liquid b/shopify/theme-moq/sections-product.DEV-original.liquid
new file mode 100644
index 00000000..4f20d4ab
--- /dev/null
+++ b/shopify/theme-moq/sections-product.DEV-original.liquid
@@ -0,0 +1,322 @@
+{% render 'breadcrumbs' %}
+
+{% liquid
+ assign enable_zoom = section.settings.enable_zoom
+ assign enable_cart_redirection = section.settings.enable_cart_redirection
+ assign images_layout = section.settings.images_layout
+ assign enable_video_autoplay = section.settings.enable_video_autoplay
+ assign enable_video_looping = section.settings.enable_video_looping
+ assign enable_linked_options = true
+ assign show_vendor = settings.show_vendor
+ assign show_social_media_icons = section.settings.show_social_media_icons
+ assign show_payment_button = section.settings.show_payment_button
+
+ for block in section.blocks
+ if block.type == 'complementary_products'
+ assign product_recommendation_limit = block.settings.product_recommendation_limit
+ break
+ endif
+ endfor
+%}
+
+{% if images_layout == 'masonry' %}
+ {% comment %}Related products in masonry grid must be below product{% endcomment %}
+ {% assign related_products_position_right = false %}
+{% endif %}
+
+<script
+ type="application/json"
+ data-section-type="product"
+ data-section-id="{{ section.id }}"
+ data-section-data
+>
+ {
+ "product": {{ product | json }},
+ "product_settings": {
+ "addToCartText": {{ 'products.product.add_to_cart' | t | json }},
+ "enableHistory": true,
+ "processingText": {{ 'products.product.processing' | t | json }},
+ "setQuantityText": {{ 'products.product.set_quantity' | t | json }},
+ "soldOutText": {{ 'products.product.sold_out' | t | json }},
+ "unavailableText": {{ 'products.product.unavailable' | t | json }}
+ },
+ "images_layout": {{ images_layout | json }},
+ "enable_zoom": {{ enable_zoom | json }},
+ "enable_video_autoplay": {{ enable_video_autoplay | json }},
+ "enable_video_looping": {{ enable_video_looping | json }},
+ "enable_cart_redirection": {{ enable_cart_redirection | json }},
+ "enable_fixed_positioning": true,
+ "product_recommendation_limit": {{ product_recommendation_limit | json }}
+ }
+</script>
+
+{% render 'product-success-labels' %}
+<section class="product-container">
+ {%
+ render 'product',
+ product: product,
+ enable_zoom: enable_zoom,
+ images_layout: images_layout,
+ enable_linked_options: enable_linked_options,
+ show_vendor: show_vendor,
+ show_social_media_icons: show_social_media_icons,
+ show_payment_button: show_payment_button,
+ %}
+
+ <div
+ class="product-recommendations-wrapper--right"
+ data-product-recommendations-right
+ >
+ </div>
+</section>
+
+{% schema %}
+{
+ "name": "Product pages",
+ "settings": [
+ {
+ "type": "checkbox",
+ "id": "enable_cart_redirection",
+ "label": "Enable cart redirection",
+ "info": "Automatically sends users to the Cart page after adding a product.",
+ "default": false
+ },
+ {
+ "type": "checkbox",
+ "id": "show_payment_button",
+ "label": "Show dynamic checkout button",
+ "info": "Each customer will see their preferred payment method from those available on your store, such as PayPal or Apple Pay. [Learn more](https://help.shopify.com/manual/using-themes/change-the-layout/dynamic-checkout)",
+ "default": true
+ },
+ {
+ "type": "header",
+ "content": "Media"
+ },
+ {
+ "type": "paragraph",
+ "content": "Learn more about [media types](https://help.shopify.com/en/manual/products/product-media/product-media-types)"
+ },
+ {
+ "type": "select",
+ "id": "images_layout",
+ "label": "Layout",
+ "options": [
+ {
+ "label": "Slideshow",
+ "value": "slideshow"
+ },
+ {
+ "label": "List",
+ "value": "list"
+ },
+ {
+ "label": "Masonry",
+ "value": "masonry"
+ }
+ ],
+ "default": "slideshow"
+ },
+ {
+ "type": "checkbox",
+ "id": "enable_zoom",
+ "label": "Enable image zoom",
+ "info": "Zoom only works with the slideshow image layout"
+ },
+ {
+ "type": "checkbox",
+ "id": "enable_video_autoplay",
+ "label": "Enable video autoplay",
+ "default": true
+ },
+ {
+ "type": "checkbox",
+ "id": "enable_video_looping",
+ "label": "Enable video looping"
+ }
+ ],
+ "blocks": [
+ {
+ "type": "@app"
+ },
+ {
+ "type": "collapsible-tab",
+ "name": "Collapsible tab",
+ "settings": [
+ {
+ "type": "text",
+ "id": "collapsible_tab_heading",
+ "label": "Heading",
+ "default": "Collapsible tab"
+ },
+ {
+ "type": "richtext",
+ "id": "collapsible_tab_text",
+ "label": "Text",
+ "default": "<p>Use this text to share information about your product.</p>"
+ }
+ ]
+ },
+ {
+ "type": "custom-liquid",
+ "name": "Custom liquid",
+ "settings": [
+ {
+ "type": "liquid",
+ "id": "custom_liquid",
+ "label": "Custom liquid",
+ "info": "Add app snippets or other Liquid code to create advanced customizations."
+ }
+ ]
+ },
+ {
+ "type": "tabs",
+ "name": "Tabs",
+ "limit": 1,
+ "settings": [
+ {
+ "type": "checkbox",
+ "id": "show_product_description",
+ "label": "Show product description",
+ "default": false
+ },
+ {
+ "type": "header",
+ "content": "Tab"
+ },
+ {
+ "type": "text",
+ "id": "tab_heading_1",
+ "label": "Heading",
+ "default": "Tab 1"
+ },
+ {
+ "type": "richtext",
+ "id": "tab_text_1",
+ "label": "Text",
+ "default": "<p>Tab 1 content goes here.</p>"
+ },
+ {
+ "type": "header",
+ "content": "Tab"
+ },
+ {
+ "type": "text",
+ "id": "tab_heading_2",
+ "label": "Heading",
+ "default": "Tab 2"
+ },
+ {
+ "type": "richtext",
+ "id": "tab_text_2",
+ "label": "Text",
+ "default": "<p>Tab 2 content goes here.</p>"
+ },
+ {
+ "type": "header",
+ "content": "Tab"
+ },
+ {
+ "type": "text",
+ "id": "tab_heading_3",
+ "label": "Heading",
+ "default": "Tab 3"
+ },
+ {
+ "type": "richtext",
+ "id": "tab_text_3",
+ "label": "Text",
+ "default": "<p>Tab 3 content goes here.</p>"
+ }
+ ]
+ },
+ {
+ "type": "title",
+ "name": "Title",
+ "limit": 1
+ },
+ {
+ "type": "vendor",
+ "name": "Vendor",
+ "limit": 1
+ },
+ {
+ "type": "social",
+ "name": "Social",
+ "limit": 1
+ },
+ {
+ "type": "description",
+ "name": "Description",
+ "limit": 1
+ },
+ {
+ "type": "price",
+ "name": "Price",
+ "limit": 1
+ },
+ {
+ "type": "form",
+ "name": "Form",
+ "limit": 1,
+ "settings": [
+ {
+ "type": "paragraph",
+ "content": "Customize form features for the product in the products portion of the theme settings."
+ },
+ {
+ "type": "checkbox",
+ "id": "show_gift_card_recipient_form",
+ "label": "t:sections.product.blocks.form.show_gift_card_recipient_form.label",
+ "info": "t:sections.product.blocks.form.show_gift_card_recipient_form.info",
+ "default": false
+ }
+ ]
+ },
+ {
+ "type": "rating",
+ "name": "Product rating",
+ "limit": 1,
+ "settings": [
+ {
+ "type": "paragraph",
+ "content": "To display a rating, add a product rating app. [Learn more](https://apps.shopify.com/product-reviews)"
+ }
+ ]
+ },
+ {
+ "type": "complementary_products",
+ "name": "Complementary products",
+ "limit": 1,
+ "settings": [
+ {
+ "type": "paragraph",
+ "content": "To select complementary products, add the Search & Discovery app. [Learn more](https:\/\/shopify.dev\/themes\/product-merchandising\/recommendations)"
+ },
+ {
+ "type": "text",
+ "id": "heading",
+ "label": "Heading",
+ "default": "Pairs well with"
+ },
+ {
+ "type": "range",
+ "id": "product_recommendation_limit",
+ "label": "Maximum products to show",
+ "min": 1,
+ "max": 10,
+ "default": 5
+ },
+ {
+ "type": "range",
+ "id": "products_per_slide",
+ "label": "Number of products per page",
+ "min": 1,
+ "max": 3,
+ "default": 2
+ }
+ ]
+ }
+ ]
+}
+
+{% endschema %}
\ No newline at end of file
diff --git a/shopify/theme-moq/sections-product.FIXED.liquid b/shopify/theme-moq/sections-product.FIXED.liquid
new file mode 100644
index 00000000..2df9e130
--- /dev/null
+++ b/shopify/theme-moq/sections-product.FIXED.liquid
@@ -0,0 +1,380 @@
+<section class="product-section">
+ <div class="product-container">
+ <div class="breadcrumb">
+ <a href="/">HOME</a> / <a href="/collections/products">PRODUCTS</a> / {{ product.vendor | upcase }} | {{ product.title | upcase }}
+ </div>
+
+ <div class="product-grid">
+ <!-- LEFT: Product Image -->
+ <div class="product-gallery">
+ {% if product.featured_image %}
+ <img src="{{ product.featured_image | img_url: '600x600' }}" alt="{{ product.title }}" class="product-main-image">
+ {% endif %}
+
+ <!-- Color swatches -->
+ {% if product.images.size > 1 %}
+ <div class="product-swatches">
+ <p class="swatch-label">Other Colorways</p>
+ <div class="swatch-grid">
+ {% for image in product.images %}
+ <img src="{{ image | img_url: '100x100' }}" alt="{{ product.title }}" class="swatch-image">
+ {% endfor %}
+ </div>
+ </div>
+ {% endif %}
+ </div>
+
+ <!-- RIGHT: Product Details -->
+ <div class="product-details">
+ <div class="product-header">
+ <p class="brand">{{ product.vendor }}</p>
+ <h1 class="product-title">{{ product.title }}</h1>
+ </div>
+
+ <!-- SKU & Price -->
+ <div class="product-meta">
+ {% if product.selected_or_first_available_variant.sku %}
+ <p class="sku"><strong>SKU:</strong> {{ product.selected_or_first_available_variant.sku }}</p>
+ {% endif %}
+ <p class="price"><strong>PRICE:</strong> {{ product.selected_or_first_available_variant.price | money }}</p>
+ </div>
+
+ <!-- Form -->
+ <form method="post" action="/cart/add" id="product-form">
+ <!-- Size/Variant Selector -->
+ {% if product.available %}
+ <div class="form-group">
+ <label class="form-label">SIZE:</label>
+ <div class="variant-buttons">
+ {% for variant in product.variants %}
+ <button type="button" class="variant-btn {% if variant == product.selected_or_first_available_variant %}active{% endif %}" data-variant-id="{{ variant.id }}">
+ {{ variant.title }}
+ </button>
+ {% endfor %}
+ </div>
+ </div>
+
+ <!-- Quantity (DW MOQ 2026-06-22: read order-min metafields) -->
+ {%- liquid
+ assign moq_min_raw = product.metafields.global.v_prods_quantity_order_min
+ assign moq_step_raw = product.metafields.global.v_prods_quantity_order_units
+ if moq_min_raw.value
+ assign moq_min_raw = moq_min_raw.value
+ endif
+ if moq_step_raw.value
+ assign moq_step_raw = moq_step_raw.value
+ endif
+ assign moq_min = moq_min_raw | plus: 0
+ assign moq_step = moq_step_raw | plus: 0
+ if moq_min < 1
+ assign moq_min = 1
+ endif
+ if moq_step < 1
+ assign moq_step = 1
+ endif
+ -%}
+ <div class="form-group">
+ <label class="form-label">QUANTITY:{% if moq_min > 1 %} <span class="moq-note">(min {{ moq_min }}{% if moq_step > 1 %}, in {{ moq_step }}s{% endif %})</span>{% endif %}</label>
+ <div class="quantity-control">
+ <button type="button" class="qty-btn minus">−</button>
+ <input type="number" name="quantity" value="{{ moq_min }}" min="{{ moq_min }}" step="{{ moq_step }}" data-min="{{ moq_min }}" data-step="{{ moq_step }}" class="qty-input">
+ <button type="button" class="qty-btn plus">+</button>
+ </div>
+ </div>
+
+ <!-- Buttons -->
+ <div class="form-actions">
+ <button type="button" class="btn btn-secondary">REQUEST SAMPLE</button>
+ <button type="button" class="btn btn-secondary">SPEC SHEET</button>
+ </div>
+ <button type="submit" class="btn btn-primary" id="add-to-cart">ADD TO CART</button>
+
+ <input type="hidden" name="id" value="{{ product.selected_or_first_available_variant.id }}">
+ {% endif %}
+ </form>
+
+ <!-- Specifications -->
+ <div class="specifications">
+ <h3>SPECIFICATIONS</h3>
+ <dl>
+ {% if product.metafields.custom.width %}
+ <dt>Width</dt>
+ <dd>{{ product.metafields.custom.width }}</dd>
+ {% endif %}
+ {% if product.metafields.custom.length %}
+ <dt>Length</dt>
+ <dd>{{ product.metafields.custom.length }}</dd>
+ {% endif %}
+ {% if product.metafields.custom.material %}
+ <dt>Material</dt>
+ <dd>{{ product.metafields.custom.material }}</dd>
+ {% endif %}
+ {% if product.vendor %}
+ <dt>Designer</dt>
+ <dd>{{ product.vendor }}</dd>
+ {% endif %}
+ {% if product.metafields.custom.unit %}
+ <dt>Unit</dt>
+ <dd>{{ product.metafields.custom.unit }}</dd>
+ {% endif %}
+ </dl>
+ </div>
+ </div>
+ </div>
+ </div>
+</section>
+
+<style>
+.product-section {
+ padding: 2rem;
+ max-width: 1400px;
+ margin: 0 auto;
+}
+
+.breadcrumb {
+ font-size: 0.875rem;
+ margin-bottom: 2rem;
+ color: #666;
+}
+
+.breadcrumb a {
+ color: #333;
+ text-decoration: none;
+}
+
+.product-grid {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: 4rem;
+ margin-bottom: 3rem;
+}
+
+.product-gallery {
+ display: flex;
+ flex-direction: column;
+ gap: 2rem;
+}
+
+.product-main-image {
+ width: 100%;
+ height: auto;
+ display: block;
+}
+
+.swatch-label {
+ font-size: 0.875rem;
+ font-weight: 600;
+ margin-bottom: 1rem;
+}
+
+.swatch-grid {
+ display: grid;
+ grid-template-columns: repeat(4, 1fr);
+ gap: 1rem;
+}
+
+.swatch-image {
+ width: 100%;
+ height: auto;
+ cursor: pointer;
+ border: 2px solid #eee;
+ transition: border-color 0.2s;
+}
+
+.swatch-image:hover {
+ border-color: #333;
+}
+
+.product-header {
+ margin-bottom: 1.5rem;
+}
+
+.brand {
+ font-size: 0.875rem;
+ color: #999;
+ margin: 0 0 0.5rem 0;
+}
+
+.product-title {
+ font-size: 1.5rem;
+ font-weight: 400;
+ margin: 0;
+ line-height: 1.2;
+}
+
+.product-meta {
+ display: grid;
+ gap: 0.5rem;
+ margin-bottom: 2rem;
+ font-size: 0.95rem;
+}
+
+.product-meta p {
+ margin: 0;
+}
+
+.form-group {
+ margin-bottom: 1.5rem;
+}
+
+.form-label {
+ display: block;
+ font-weight: 600;
+ font-size: 0.875rem;
+ margin-bottom: 0.75rem;
+}
+
+.variant-buttons {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: 1rem;
+}
+
+.variant-btn {
+ padding: 1rem;
+ border: 2px solid #333;
+ background: white;
+ color: #333;
+ font-weight: 600;
+ cursor: pointer;
+ transition: all 0.2s;
+ font-size: 0.875rem;
+}
+
+.variant-btn.active {
+ background: #333;
+ color: white;
+}
+
+.quantity-control {
+ display: grid;
+ grid-template-columns: auto 1fr auto;
+ gap: 0.5rem;
+ max-width: 200px;
+}
+
+.qty-btn {
+ background: white;
+ border: 1px solid #ddd;
+ width: 2.5rem;
+ height: 2.5rem;
+ cursor: pointer;
+ font-size: 1.2rem;
+}
+
+.qty-input {
+ border: 1px solid #ddd;
+ text-align: center;
+ font-weight: 600;
+}
+
+.moq-note { font-weight: 400; color: #888; font-size: 0.8em; }
+
+.form-actions {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: 1rem;
+ margin-bottom: 1rem;
+}
+
+.btn {
+ padding: 1rem;
+ border: none;
+ border-radius: 50px;
+ font-weight: 600;
+ font-size: 0.875rem;
+ cursor: pointer;
+ transition: all 0.2s;
+}
+
+.btn-primary {
+ background: #333;
+ color: white;
+ width: 100%;
+}
+
+.btn-primary:hover {
+ background: #000;
+}
+
+.btn-secondary {
+ background: #333;
+ color: white;
+}
+
+.btn-secondary:hover {
+ background: #000;
+}
+
+.specifications {
+ margin-top: 3rem;
+ border-top: 1px solid #eee;
+ padding-top: 2rem;
+}
+
+.specifications h3 {
+ font-size: 0.875rem;
+ font-weight: 700;
+ margin-bottom: 1.5rem;
+ letter-spacing: 0.05em;
+}
+
+.specifications dl {
+ display: grid;
+ grid-template-columns: auto 1fr;
+ gap: 1rem 2rem;
+}
+
+.specifications dt {
+ font-weight: 600;
+ font-size: 0.875rem;
+}
+
+.specifications dd {
+ margin: 0;
+ font-size: 0.875rem;
+ color: #666;
+}
+
+@media (max-width: 768px) {
+ .product-grid {
+ grid-template-columns: 1fr;
+ gap: 2rem;
+ }
+
+ .variant-buttons {
+ grid-template-columns: 1fr;
+ }
+
+ .form-actions {
+ grid-template-columns: 1fr;
+ }
+}
+</style>
+
+
+<script>
+/* DW MOQ 2026-06-22: enforce order minimum + increment on the custom PDP quantity box.
+ Conflict-safe: re-clamps to data-min / data-step after any +/- click, on change/blur,
+ and before form submit — regardless of any other handlers. */
+(function(){
+ var q = document.querySelector('.quantity-control .qty-input');
+ if(!q) return;
+ var min = parseInt(q.getAttribute('data-min'),10) || 1;
+ var step = parseInt(q.getAttribute('data-step'),10) || 1;
+ function clamp(){
+ var v = parseInt(q.value,10);
+ if(isNaN(v) || v < min){ v = min; }
+ var r = (v - min) % step;
+ if(r !== 0){ v = v - r + step; }
+ q.value = v;
+ }
+ clamp();
+ var ctrl = q.closest('.quantity-control');
+ if(ctrl){ ctrl.addEventListener('click', function(){ setTimeout(clamp, 0); }); }
+ q.addEventListener('change', clamp);
+ q.addEventListener('blur', clamp);
+ var form = document.getElementById('product-form');
+ if(form){ form.addEventListener('submit', clamp, true); }
+})();
+</script>
diff --git a/shopify/theme-moq/sections-product.LIVE-original.liquid b/shopify/theme-moq/sections-product.LIVE-original.liquid
new file mode 100644
index 00000000..68ba1bc9
--- /dev/null
+++ b/shopify/theme-moq/sections-product.LIVE-original.liquid
@@ -0,0 +1,333 @@
+<section class="product-section">
+ <div class="product-container">
+ <div class="breadcrumb">
+ <a href="/">HOME</a> / <a href="/collections/products">PRODUCTS</a> / {{ product.vendor | upcase }} | {{ product.title | upcase }}
+ </div>
+
+ <div class="product-grid">
+ <!-- LEFT: Product Image -->
+ <div class="product-gallery">
+ {% if product.featured_image %}
+ <img src="{{ product.featured_image | img_url: '600x600' }}" alt="{{ product.title }}" class="product-main-image">
+ {% endif %}
+
+ <!-- Color swatches -->
+ {% if product.images.size > 1 %}
+ <div class="product-swatches">
+ <p class="swatch-label">Other Colorways</p>
+ <div class="swatch-grid">
+ {% for image in product.images %}
+ <img src="{{ image | img_url: '100x100' }}" alt="{{ product.title }}" class="swatch-image">
+ {% endfor %}
+ </div>
+ </div>
+ {% endif %}
+ </div>
+
+ <!-- RIGHT: Product Details -->
+ <div class="product-details">
+ <div class="product-header">
+ <p class="brand">{{ product.vendor }}</p>
+ <h1 class="product-title">{{ product.title }}</h1>
+ </div>
+
+ <!-- SKU & Price -->
+ <div class="product-meta">
+ {% if product.selected_or_first_available_variant.sku %}
+ <p class="sku"><strong>SKU:</strong> {{ product.selected_or_first_available_variant.sku }}</p>
+ {% endif %}
+ <p class="price"><strong>PRICE:</strong> {{ product.selected_or_first_available_variant.price | money }}</p>
+ </div>
+
+ <!-- Form -->
+ <form method="post" action="/cart/add" id="product-form">
+ <!-- Size/Variant Selector -->
+ {% if product.available %}
+ <div class="form-group">
+ <label class="form-label">SIZE:</label>
+ <div class="variant-buttons">
+ {% for variant in product.variants %}
+ <button type="button" class="variant-btn {% if variant == product.selected_or_first_available_variant %}active{% endif %}" data-variant-id="{{ variant.id }}">
+ {{ variant.title }}
+ </button>
+ {% endfor %}
+ </div>
+ </div>
+
+ <!-- Quantity -->
+ <div class="form-group">
+ <label class="form-label">QUANTITY:</label>
+ <div class="quantity-control">
+ <button type="button" class="qty-btn minus">−</button>
+ <input type="number" name="quantity" value="1" min="1" class="qty-input">
+ <button type="button" class="qty-btn plus">+</button>
+ </div>
+ </div>
+
+ <!-- Buttons -->
+ <div class="form-actions">
+ <button type="button" class="btn btn-secondary">REQUEST SAMPLE</button>
+ <button type="button" class="btn btn-secondary">SPEC SHEET</button>
+ </div>
+ <button type="submit" class="btn btn-primary" id="add-to-cart">ADD TO CART</button>
+
+ <input type="hidden" name="id" value="{{ product.selected_or_first_available_variant.id }}">
+ {% endif %}
+ </form>
+
+ <!-- Specifications -->
+ <div class="specifications">
+ <h3>SPECIFICATIONS</h3>
+ <dl>
+ {% if product.metafields.custom.width %}
+ <dt>Width</dt>
+ <dd>{{ product.metafields.custom.width }}</dd>
+ {% endif %}
+ {% if product.metafields.custom.length %}
+ <dt>Length</dt>
+ <dd>{{ product.metafields.custom.length }}</dd>
+ {% endif %}
+ {% if product.metafields.custom.material %}
+ <dt>Material</dt>
+ <dd>{{ product.metafields.custom.material }}</dd>
+ {% endif %}
+ {% if product.vendor %}
+ <dt>Designer</dt>
+ <dd>{{ product.vendor }}</dd>
+ {% endif %}
+ {% if product.metafields.custom.unit %}
+ <dt>Unit</dt>
+ <dd>{{ product.metafields.custom.unit }}</dd>
+ {% endif %}
+ </dl>
+ </div>
+ </div>
+ </div>
+ </div>
+</section>
+
+<style>
+.product-section {
+ padding: 2rem;
+ max-width: 1400px;
+ margin: 0 auto;
+}
+
+.breadcrumb {
+ font-size: 0.875rem;
+ margin-bottom: 2rem;
+ color: #666;
+}
+
+.breadcrumb a {
+ color: #333;
+ text-decoration: none;
+}
+
+.product-grid {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: 4rem;
+ margin-bottom: 3rem;
+}
+
+.product-gallery {
+ display: flex;
+ flex-direction: column;
+ gap: 2rem;
+}
+
+.product-main-image {
+ width: 100%;
+ height: auto;
+ display: block;
+}
+
+.swatch-label {
+ font-size: 0.875rem;
+ font-weight: 600;
+ margin-bottom: 1rem;
+}
+
+.swatch-grid {
+ display: grid;
+ grid-template-columns: repeat(4, 1fr);
+ gap: 1rem;
+}
+
+.swatch-image {
+ width: 100%;
+ height: auto;
+ cursor: pointer;
+ border: 2px solid #eee;
+ transition: border-color 0.2s;
+}
+
+.swatch-image:hover {
+ border-color: #333;
+}
+
+.product-header {
+ margin-bottom: 1.5rem;
+}
+
+.brand {
+ font-size: 0.875rem;
+ color: #999;
+ margin: 0 0 0.5rem 0;
+}
+
+.product-title {
+ font-size: 1.5rem;
+ font-weight: 400;
+ margin: 0;
+ line-height: 1.2;
+}
+
+.product-meta {
+ display: grid;
+ gap: 0.5rem;
+ margin-bottom: 2rem;
+ font-size: 0.95rem;
+}
+
+.product-meta p {
+ margin: 0;
+}
+
+.form-group {
+ margin-bottom: 1.5rem;
+}
+
+.form-label {
+ display: block;
+ font-weight: 600;
+ font-size: 0.875rem;
+ margin-bottom: 0.75rem;
+}
+
+.variant-buttons {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: 1rem;
+}
+
+.variant-btn {
+ padding: 1rem;
+ border: 2px solid #333;
+ background: white;
+ color: #333;
+ font-weight: 600;
+ cursor: pointer;
+ transition: all 0.2s;
+ font-size: 0.875rem;
+}
+
+.variant-btn.active {
+ background: #333;
+ color: white;
+}
+
+.quantity-control {
+ display: grid;
+ grid-template-columns: auto 1fr auto;
+ gap: 0.5rem;
+ max-width: 200px;
+}
+
+.qty-btn {
+ background: white;
+ border: 1px solid #ddd;
+ width: 2.5rem;
+ height: 2.5rem;
+ cursor: pointer;
+ font-size: 1.2rem;
+}
+
+.qty-input {
+ border: 1px solid #ddd;
+ text-align: center;
+ font-weight: 600;
+}
+
+.form-actions {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: 1rem;
+ margin-bottom: 1rem;
+}
+
+.btn {
+ padding: 1rem;
+ border: none;
+ border-radius: 50px;
+ font-weight: 600;
+ font-size: 0.875rem;
+ cursor: pointer;
+ transition: all 0.2s;
+}
+
+.btn-primary {
+ background: #333;
+ color: white;
+ width: 100%;
+}
+
+.btn-primary:hover {
+ background: #000;
+}
+
+.btn-secondary {
+ background: #333;
+ color: white;
+}
+
+.btn-secondary:hover {
+ background: #000;
+}
+
+.specifications {
+ margin-top: 3rem;
+ border-top: 1px solid #eee;
+ padding-top: 2rem;
+}
+
+.specifications h3 {
+ font-size: 0.875rem;
+ font-weight: 700;
+ margin-bottom: 1.5rem;
+ letter-spacing: 0.05em;
+}
+
+.specifications dl {
+ display: grid;
+ grid-template-columns: auto 1fr;
+ gap: 1rem 2rem;
+}
+
+.specifications dt {
+ font-weight: 600;
+ font-size: 0.875rem;
+}
+
+.specifications dd {
+ margin: 0;
+ font-size: 0.875rem;
+ color: #666;
+}
+
+@media (max-width: 768px) {
+ .product-grid {
+ grid-template-columns: 1fr;
+ gap: 2rem;
+ }
+
+ .variant-buttons {
+ grid-template-columns: 1fr;
+ }
+
+ .form-actions {
+ grid-template-columns: 1fr;
+ }
+}
+</style>
← d9616965 Apply compact layout fix to all theme variants
·
back to Designer Wallcoverings
·
Harden MOQ Liquid: use append-coercion for legacy global met f9ca2f62 →