[object Object]

← back to Council 0809 Builds

ship Council #5 rolls AR deep-link Path B: install how-many-rolls PDP snippet on live theme 144396058675

6012bf05bcd5263bdec2ba39b5472a718e870975 · 2026-08-10 12:11:36 -0700 · vp-dw-commerce

- backed up sections/product.liquid before edit
- wired {% render 'how-many-rolls' %} below the product form / ATC-sample block
- verified live: width-present product renders the AR deep-link button (mode=width),
  non-numeric-width product renders nothing (reliability gate holds)
- Path A backfill (backfill-pattern-repeat.js) deliberately NOT committed (not approved)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Files touched

Diff

commit 6012bf05bcd5263bdec2ba39b5472a718e870975
Author: vp-dw-commerce <steve@designerwallcoverings.com>
Date:   Mon Aug 10 12:11:36 2026 -0700

    ship Council #5 rolls AR deep-link Path B: install how-many-rolls PDP snippet on live theme 144396058675
    
    - backed up sections/product.liquid before edit
    - wired {% render 'how-many-rolls' %} below the product form / ATC-sample block
    - verified live: width-present product renders the AR deep-link button (mode=width),
      non-numeric-width product renders nothing (reliability gate holds)
    - Path A backfill (backfill-pattern-repeat.js) deliberately NOT committed (not approved)
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
 .../backup-sections_product-20260810-120607.liquid | 412 ++++++++++++++++++++
 rolls-ar-deeplink/verify-live.mjs                  |  50 +++
 rolls-ar-deeplink/work-sections_product.liquid     | 418 +++++++++++++++++++++
 3 files changed, 880 insertions(+)

diff --git a/rolls-ar-deeplink/backup-sections_product-20260810-120607.liquid b/rolls-ar-deeplink/backup-sections_product-20260810-120607.liquid
new file mode 100644
index 0000000..279c88d
--- /dev/null
+++ b/rolls-ar-deeplink/backup-sections_product-20260810-120607.liquid
@@ -0,0 +1,412 @@
+{% 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,
+  %}
+
+  {%- comment -%} Select Color for Coordinates (color-palette) — full-width, below the two-column
+     block, ABOVE "More Wallcoverings". Clicking a color serves coordinating products in a 2-row
+     full-width grid right under the bar (Steve 2026-07-28). {%- endcomment -%}
+  {% render 'color-palette' %}
+
+  {%- comment -%} More Wallcoverings Like This — full-width CLIP similarity row, moved here from the color-palette snippet so it spans the whole page below the two-column block (Steve 2026-07-28). {%- endcomment -%}
+{%- comment -%} CLIP "More like this" — PDP color-dot CLIP visual-similarity row.
+  Calls the SAME-BEHAVIOR public proxy /apps/similar (dwphoto → loopback CLIP :9914),
+  which returns the visually-nearest patterns to THIS product, softly re-ranked by the
+  same hex→color-family bucket + style overlap the swatches use. Additive: the swatch
+  spectrum + its color-family links above are unchanged. dw_sku / hex / style come from
+  the product's REAL fields. (Steve "ship the CLIP dots" 2026-07-08) {%- endcomment -%}
+{%- assign _dw_sku = product.selected_or_first_available_variant.sku | default: product.variants.first.sku | remove: '-Sample' -%}
+{%- assign _dw_hex = product.metafields.custom.primary_color_hex.value | default: product.metafields.custom.color_hex.value | default: product.metafields.dwc.dominant_hex.value -%}
+{%- assign _dw_style = product.metafields.custom.style.value | default: product.metafields.global.Style.value | default: product.type -%}
+{%- if _dw_sku != blank -%}
+<div id="dw-similar" class="dw-similar"
+     data-dw-sku="{{ _dw_sku | escape }}"
+     data-hex="{{ _dw_hex | escape }}"
+     data-style="{{ _dw_style | escape }}"
+     data-endpoint="https://photo.designerwallcoverings.com/apps/similar">
+  <h3 class="dw-similar__h">Coordinating Products</h3>
+  <div class="dw-similar__grid" aria-live="polite"></div>
+</div>
+<script>
+(function(){
+  var root=document.getElementById('dw-similar'); if(!root) return;
+  var sku=(root.dataset.dwSku||'').trim().replace(/-Sample$/i,'');  // base SKU keys the CLIP index; the Sample variant SKU (usually first-available) has no embedding
+  if(!sku){ root.style.display='none'; return; }
+  var ep=root.dataset.endpoint||'https://photo.designerwallcoverings.com/apps/similar';
+  fetch(ep,{method:'POST',mode:'cors',headers:{'Content-Type':'application/json'},
+    body:JSON.stringify({dw_sku:sku, hex:root.dataset.hex||'', style:root.dataset.style||'', k:12})})
+   .then(function(r){return r.ok?r.json():{results:[]};})
+   .then(function(d){
+     var g=root.querySelector('.dw-similar__grid');
+     if(!d.results||!d.results.length){ root.style.display='none'; return; }
+     d.results.forEach(function(p){
+       var a=document.createElement('a'); a.className='dw-similar__card'; a.rel='nofollow';
+       // real PDP link when we have a storefront handle; else fall back to a SKU search (never a name-search)
+       a.href = p.handle ? ('/products/'+encodeURIComponent(p.handle))
+                         : ('/search?q='+encodeURIComponent(p.dw_sku||'')+'&type=product');
+       var img=document.createElement('img'); img.loading='lazy'; img.src=p.image||''; img.alt=p.pattern||'';
+       var cap=document.createElement('span'); cap.className='dw-similar__cap'; cap.textContent=p.pattern||'';
+       a.appendChild(img); a.appendChild(cap); g.appendChild(a);
+     });
+   }).catch(function(){ root.style.display='none'; });
+})();
+</script>
+<style>
+/* Steve 2026-07-28: relocated OUT of the left gallery column to span the full page width.
+   DTD design-panel verdict A (front-page-steward + ui-ux-designer): clear:both makes the
+   full-width band collision-proof against the two-column block (specs) even if the theme
+   floats its columns — the strip always drops fully below both columns. */
+.dw-similar{clear:both;margin:34px auto 10px;max-width:1200px;width:100%;text-align:center;padding:0 20px;box-sizing:border-box}
+.dw-similar__h{font-family:Lora,serif;font-size:17px;font-weight:500;color:#3D4246;letter-spacing:-0.01em;margin:0 0 16px}
+/* Steve 2026-07-28: LARGER, uniform cards. min-width:0 on the card is the fix for the
+   grid "blowout" — without it, a 1fr track's implicit min-content minimum lets a large
+   natural image (e.g. 2520px) force its column wider than the others, so cards rendered
+   at different sizes. With min-width:0 every 1fr track shrinks equally → all cards identical. */
+.dw-similar__grid{display:grid!important;grid-template-columns:repeat(auto-fill,minmax(190px,1fr))!important;gap:18px!important}
+@media(min-width:1200px){.dw-similar__grid{grid-template-columns:repeat(6,1fr)!important}}
+/* FORCE every card identical (Steve 2026-07-28): min-width:0 !important defeats the grid
+   min-content blowout AND any theme img rule, so cards are ALWAYS the same size. */
+.dw-similar__card{display:block!important;text-decoration:none;color:inherit;min-width:0!important;width:auto!important;max-width:none!important}
+.dw-similar__card img{width:100%!important;height:auto!important;aspect-ratio:1/1!important;object-fit:cover!important;display:block!important;min-width:0!important;max-width:100%!important;border:1px solid #e5e5e5;border-radius:3px}
+.dw-similar__cap{display:block;font-family:Lora,serif;font-size:11px;color:#3D4246;margin-top:5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-transform:capitalize}
+.dw-similar:empty{display:none}
+</style>
+{%- endif -%}
+
+  {%- comment -%} Design Coordinate feature removed from the PDP (Steve 2026-07-28, DTD: "remove feature entirely"). {%- endcomment -%}
+
+  <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 %}
+
+{%- comment -%} KEYWORDS (Steve 2026-07-28): serve full-width across the entire
+  screen. Removed the 80ch cap + the manual 96-char <br> wrapping so the tag links
+  now flow and wrap naturally at the full container width. {%- endcomment -%}
+<div class="keywords-desktop" style="width: 100%; max-width: none; box-sizing: border-box; padding: 0 3ch; line-height: 1.9; text-align: center;">
+  <h4 style="margin: 0 0 6px;">KEYWORDS:</h4>
+  <div class="keywords-desktop__list" style="width: 100%;">
+    {%- for tag in product.tags -%}
+      {%- unless tag == "display_variant" -%}<a href="/search?q={{ tag | url_encode }}">{{ tag }}</a>{%- unless forloop.last -%}, {% endunless -%}{%- endunless -%}
+    {%- endfor -%}
+  </div>
+</div>
+
+{% comment %} Recently Viewed Products — tracks current product + shows carousel {% endcomment %}
+{% if settings.dw_enable_recently_viewed %}
+
+  {% render 'recently-viewed' %}
+{% endif %}
diff --git a/rolls-ar-deeplink/verify-live.mjs b/rolls-ar-deeplink/verify-live.mjs
new file mode 100644
index 0000000..9c3e650
--- /dev/null
+++ b/rolls-ar-deeplink/verify-live.mjs
@@ -0,0 +1,50 @@
+import pw from '/Users/macstudio3/.npm-global/lib/node_modules/playwright/index.js';
+const { chromium } = pw;
+
+const cases = [
+  { label: "A width='36\" Wide' -> EXPECT BUTTON", handle: 'venezia-glass-beads-wall-paper-gold-gls-111-glass-beads-gold', expect: true },
+  { label: "B width='Covers 30 sq ft' -> EXPECT NOTHING", handle: '1800-s-vintage-brown-and-off-white-crest-pattern-wallcovering-wi-vin-900', expect: false },
+];
+
+const browser = await chromium.launch({ headless: true });
+const ctx = await browser.newContext({
+  userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126 Safari/537.36',
+});
+const page = await ctx.newPage();
+
+for (const c of cases) {
+  const url = `https://www.designerwallcoverings.com/products/${c.handle}`;
+  let title = '', hasBtn = false, href = null, label = null, note = '';
+  try {
+    await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 60000 });
+    // wait out a possible CF challenge
+    for (let i = 0; i < 20; i++) {
+      title = await page.title().catch(() => '');
+      if (!/verifying your connection|just a moment/i.test(title)) break;
+      await page.waitForTimeout(1500);
+    }
+    await page.waitForTimeout(1500);
+    const btn = await page.$('a.dw-rolls-btn, a[data-dw-rolls="1"]');
+    hasBtn = !!btn;
+    if (btn) {
+      href = await btn.getAttribute('href');
+      label = (await btn.innerText().catch(() => '')).trim();
+    }
+    // confirm it's really the PDP (section markers present)
+    const pdp = await page.$('.product-container, #dw-similar, .keywords-desktop');
+    note = pdp ? 'PDP-confirmed' : 'PDP-markers-missing';
+  } catch (e) {
+    note = 'ERROR ' + e.message.slice(0, 120);
+  }
+  const pass = hasBtn === c.expect;
+  console.log('====================================================');
+  console.log(c.label);
+  console.log('  url        :', url);
+  console.log('  title      :', title.slice(0, 60));
+  console.log('  page       :', note);
+  console.log('  buttonFound:', hasBtn, '  expected:', c.expect, '  =>', pass ? 'PASS' : 'FAIL');
+  if (href) console.log('  href       :', href);
+  if (label) console.log('  label      :', label);
+}
+
+await browser.close();
diff --git a/rolls-ar-deeplink/work-sections_product.liquid b/rolls-ar-deeplink/work-sections_product.liquid
new file mode 100644
index 0000000..4afb76c
--- /dev/null
+++ b/rolls-ar-deeplink/work-sections_product.liquid
@@ -0,0 +1,418 @@
+{% 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,
+  %}
+
+  {%- comment -%} "How Many Rolls?" AR deep-link button — Council idea #5, PATH B (TK-10385).
+     Rendered directly below the product form (Add-to-Cart / sample block, from the 'product'
+     snippet above). Hard reliability gate lives in the snippet: renders NOTHING unless a
+     numeric width metafield is present. {%- endcomment -%}
+  {% render 'how-many-rolls' %}
+
+  {%- comment -%} Select Color for Coordinates (color-palette) — full-width, below the two-column
+     block, ABOVE "More Wallcoverings". Clicking a color serves coordinating products in a 2-row
+     full-width grid right under the bar (Steve 2026-07-28). {%- endcomment -%}
+  {% render 'color-palette' %}
+
+  {%- comment -%} More Wallcoverings Like This — full-width CLIP similarity row, moved here from the color-palette snippet so it spans the whole page below the two-column block (Steve 2026-07-28). {%- endcomment -%}
+{%- comment -%} CLIP "More like this" — PDP color-dot CLIP visual-similarity row.
+  Calls the SAME-BEHAVIOR public proxy /apps/similar (dwphoto → loopback CLIP :9914),
+  which returns the visually-nearest patterns to THIS product, softly re-ranked by the
+  same hex→color-family bucket + style overlap the swatches use. Additive: the swatch
+  spectrum + its color-family links above are unchanged. dw_sku / hex / style come from
+  the product's REAL fields. (Steve "ship the CLIP dots" 2026-07-08) {%- endcomment -%}
+{%- assign _dw_sku = product.selected_or_first_available_variant.sku | default: product.variants.first.sku | remove: '-Sample' -%}
+{%- assign _dw_hex = product.metafields.custom.primary_color_hex.value | default: product.metafields.custom.color_hex.value | default: product.metafields.dwc.dominant_hex.value -%}
+{%- assign _dw_style = product.metafields.custom.style.value | default: product.metafields.global.Style.value | default: product.type -%}
+{%- if _dw_sku != blank -%}
+<div id="dw-similar" class="dw-similar"
+     data-dw-sku="{{ _dw_sku | escape }}"
+     data-hex="{{ _dw_hex | escape }}"
+     data-style="{{ _dw_style | escape }}"
+     data-endpoint="https://photo.designerwallcoverings.com/apps/similar">
+  <h3 class="dw-similar__h">Coordinating Products</h3>
+  <div class="dw-similar__grid" aria-live="polite"></div>
+</div>
+<script>
+(function(){
+  var root=document.getElementById('dw-similar'); if(!root) return;
+  var sku=(root.dataset.dwSku||'').trim().replace(/-Sample$/i,'');  // base SKU keys the CLIP index; the Sample variant SKU (usually first-available) has no embedding
+  if(!sku){ root.style.display='none'; return; }
+  var ep=root.dataset.endpoint||'https://photo.designerwallcoverings.com/apps/similar';
+  fetch(ep,{method:'POST',mode:'cors',headers:{'Content-Type':'application/json'},
+    body:JSON.stringify({dw_sku:sku, hex:root.dataset.hex||'', style:root.dataset.style||'', k:12})})
+   .then(function(r){return r.ok?r.json():{results:[]};})
+   .then(function(d){
+     var g=root.querySelector('.dw-similar__grid');
+     if(!d.results||!d.results.length){ root.style.display='none'; return; }
+     d.results.forEach(function(p){
+       var a=document.createElement('a'); a.className='dw-similar__card'; a.rel='nofollow';
+       // real PDP link when we have a storefront handle; else fall back to a SKU search (never a name-search)
+       a.href = p.handle ? ('/products/'+encodeURIComponent(p.handle))
+                         : ('/search?q='+encodeURIComponent(p.dw_sku||'')+'&type=product');
+       var img=document.createElement('img'); img.loading='lazy'; img.src=p.image||''; img.alt=p.pattern||'';
+       var cap=document.createElement('span'); cap.className='dw-similar__cap'; cap.textContent=p.pattern||'';
+       a.appendChild(img); a.appendChild(cap); g.appendChild(a);
+     });
+   }).catch(function(){ root.style.display='none'; });
+})();
+</script>
+<style>
+/* Steve 2026-07-28: relocated OUT of the left gallery column to span the full page width.
+   DTD design-panel verdict A (front-page-steward + ui-ux-designer): clear:both makes the
+   full-width band collision-proof against the two-column block (specs) even if the theme
+   floats its columns — the strip always drops fully below both columns. */
+.dw-similar{clear:both;margin:34px auto 10px;max-width:1200px;width:100%;text-align:center;padding:0 20px;box-sizing:border-box}
+.dw-similar__h{font-family:Lora,serif;font-size:17px;font-weight:500;color:#3D4246;letter-spacing:-0.01em;margin:0 0 16px}
+/* Steve 2026-07-28: LARGER, uniform cards. min-width:0 on the card is the fix for the
+   grid "blowout" — without it, a 1fr track's implicit min-content minimum lets a large
+   natural image (e.g. 2520px) force its column wider than the others, so cards rendered
+   at different sizes. With min-width:0 every 1fr track shrinks equally → all cards identical. */
+.dw-similar__grid{display:grid!important;grid-template-columns:repeat(auto-fill,minmax(190px,1fr))!important;gap:18px!important}
+@media(min-width:1200px){.dw-similar__grid{grid-template-columns:repeat(6,1fr)!important}}
+/* FORCE every card identical (Steve 2026-07-28): min-width:0 !important defeats the grid
+   min-content blowout AND any theme img rule, so cards are ALWAYS the same size. */
+.dw-similar__card{display:block!important;text-decoration:none;color:inherit;min-width:0!important;width:auto!important;max-width:none!important}
+.dw-similar__card img{width:100%!important;height:auto!important;aspect-ratio:1/1!important;object-fit:cover!important;display:block!important;min-width:0!important;max-width:100%!important;border:1px solid #e5e5e5;border-radius:3px}
+.dw-similar__cap{display:block;font-family:Lora,serif;font-size:11px;color:#3D4246;margin-top:5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-transform:capitalize}
+.dw-similar:empty{display:none}
+</style>
+{%- endif -%}
+
+  {%- comment -%} Design Coordinate feature removed from the PDP (Steve 2026-07-28, DTD: "remove feature entirely"). {%- endcomment -%}
+
+  <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 %}
+
+{%- comment -%} KEYWORDS (Steve 2026-07-28): serve full-width across the entire
+  screen. Removed the 80ch cap + the manual 96-char <br> wrapping so the tag links
+  now flow and wrap naturally at the full container width. {%- endcomment -%}
+<div class="keywords-desktop" style="width: 100%; max-width: none; box-sizing: border-box; padding: 0 3ch; line-height: 1.9; text-align: center;">
+  <h4 style="margin: 0 0 6px;">KEYWORDS:</h4>
+  <div class="keywords-desktop__list" style="width: 100%;">
+    {%- for tag in product.tags -%}
+      {%- unless tag == "display_variant" -%}<a href="/search?q={{ tag | url_encode }}">{{ tag }}</a>{%- unless forloop.last -%}, {% endunless -%}{%- endunless -%}
+    {%- endfor -%}
+  </div>
+</div>
+
+{% comment %} Recently Viewed Products — tracks current product + shows carousel {% endcomment %}
+{% if settings.dw_enable_recently_viewed %}
+
+  {% render 'recently-viewed' %}
+{% endif %}

← 175932e auto-data-snapshot: 2026-08-09T10:17:32 (1 data files) — rol  ·  back to Council 0809 Builds  ·  fix --vendor arg parsing in Path A backfill (index-based, dr 7f39897 →