← back to Designer Wallcoverings
Theme fix: color-dots makeDot 'c is not defined' scoping bug (aborts init → breaks MOQ qty enforcement); staged on dev theme 144105013299
a1e11baf5f2db538484f1cacae861d47b630379f · 2026-06-30 19:53:57 -0700 · Steve
Files touched
A shopify/theme-fixes/color-dots-c-scope-2026-06-30/blast.cjsA shopify/theme-fixes/color-dots-c-scope-2026-06-30/color-dots.FIXED.liquidA shopify/theme-fixes/color-dots-c-scope-2026-06-30/color-dots.ORIGINAL.liquidA shopify/theme-fixes/color-dots-c-scope-2026-06-30/color-dots.diffA shopify/theme-fixes/color-dots-c-scope-2026-06-30/verify.cjsA shopify/theme-fixes/color-dots-c-scope-2026-06-30/verify2.cjsA shopify/theme-fixes/color-dots-c-scope-2026-06-30/verify3.cjs
Diff
commit a1e11baf5f2db538484f1cacae861d47b630379f
Author: Steve <steve@designerwallcoverings.com>
Date: Tue Jun 30 19:53:57 2026 -0700
Theme fix: color-dots makeDot 'c is not defined' scoping bug (aborts init → breaks MOQ qty enforcement); staged on dev theme 144105013299
---
.../color-dots-c-scope-2026-06-30/blast.cjs | 37 ++++
.../color-dots.FIXED.liquid | 245 +++++++++++++++++++++
.../color-dots.ORIGINAL.liquid | 240 ++++++++++++++++++++
.../color-dots-c-scope-2026-06-30/color-dots.diff | 78 +++++++
.../color-dots-c-scope-2026-06-30/verify.cjs | 57 +++++
.../color-dots-c-scope-2026-06-30/verify2.cjs | 65 ++++++
.../color-dots-c-scope-2026-06-30/verify3.cjs | 39 ++++
7 files changed, 761 insertions(+)
diff --git a/shopify/theme-fixes/color-dots-c-scope-2026-06-30/blast.cjs b/shopify/theme-fixes/color-dots-c-scope-2026-06-30/blast.cjs
new file mode 100644
index 00000000..8f88d872
--- /dev/null
+++ b/shopify/theme-fixes/color-dots-c-scope-2026-06-30/blast.cjs
@@ -0,0 +1,37 @@
+const { chromium } = require('/Users/stevestudio2/Projects/Designer-Wallcoverings/node_modules/playwright');
+(async () => {
+// spot-check across vendors — grab varied handles from storefront
+const handles = [
+ 'dwtt-80064-designer-wallcoverings-los-angeles', // Thibaut (MOQ)
+ 'tova-ochre-dwdx-220476', // control
+];
+const browser = await chromium.launch();
+// fetch a few more handles from products.json for vendor variety
+const p0 = await (await browser.newContext()).newPage();
+const extra = await p0.evaluate(async ()=>{
+ const r = await fetch('https://www.designerwallcoverings.com/products.json?limit=30');
+ const j = await r.json();
+ return j.products.map(p=>p.handle);
+}).catch(()=>[]);
+await p0.context().close();
+// pick 3 distinct non-sample handles
+for (const h of extra) { if(handles.length>=5) break; if(!/sample/i.test(h) && !handles.includes(h)) handles.push(h); }
+
+const themes = [{label:'BUGGY',id:144076931123},{label:'FIXED',id:144105013299}];
+const table=[];
+for (const t of themes) {
+ const ctx = await browser.newContext();
+ const s = await ctx.newPage();
+ await s.goto(`https://www.designerwallcoverings.com/?preview_theme_id=${t.id}`,{waitUntil:'domcontentloaded',timeout:60000}); await s.waitForTimeout(1000); await s.close();
+ for (const h of handles) {
+ const pg = await ctx.newPage(); const errs=[]; pg.on('pageerror',e=>errs.push(String(e)));
+ try { await pg.goto(`https://www.designerwallcoverings.com/products/${h}?preview_theme_id=${t.id}`,{waitUntil:'domcontentloaded',timeout:60000}); } catch(e){errs.push('goto');}
+ await pg.waitForTimeout(2500);
+ table.push({ theme:t.label, handle:h.slice(0,42), cIsNotDefined: errs.filter(e=>/c is not defined/.test(e)).length });
+ await pg.close();
+ }
+ await ctx.close();
+}
+await browser.close();
+console.log(JSON.stringify(table,null,2));
+})();
diff --git a/shopify/theme-fixes/color-dots-c-scope-2026-06-30/color-dots.FIXED.liquid b/shopify/theme-fixes/color-dots-c-scope-2026-06-30/color-dots.FIXED.liquid
new file mode 100644
index 00000000..3b97e2c2
--- /dev/null
+++ b/shopify/theme-fixes/color-dots-c-scope-2026-06-30/color-dots.FIXED.liquid
@@ -0,0 +1,245 @@
+{% assign color_dots_json_val = product.metafields.custom.color_dots_json.value %}
+{% assign color_details_val = product.metafields.custom.color_details.value %}
+{% if color_dots_json_val != blank %}
+ {% assign color_details_raw = color_dots_json_val | json %}
+{% elsif color_details_val != blank %}
+ {% assign color_details_raw = color_details_val | json %}
+{% else %}
+ {% assign color_details_raw = blank %}
+{% endif %}
+{% assign color_hex = product.metafields.custom.color_hex.value %}
+{% assign primary_hex = product.metafields.custom.primary_color_hex.value %}
+{% assign ai_colors_raw = product.metafields.dwc.ai_generated_colors.value | json %}
+{% assign color_name = product.metafields.custom.color_name.value %}
+
+{%- comment -%}
+ Color Dots v3 — 3-tier color system
+ Tier 1: color_details metafield (Gemini-enriched)
+ Tier 2: primary_color_hex + ai_generated_colors
+ Tier 3: Canvas pixel extraction from product image (onload)
+{%- endcomment -%}
+
+<div class="dw-color-dots" id="dw-color-dots-wrapper" style="display:flex;justify-content:center;gap:10px;padding:12px 0 8px;flex-wrap:wrap;min-height:30px;">
+ <div id="dw-color-dots-container" style="display:flex;justify-content:center;gap:10px;flex-wrap:wrap;"
+ {% if color_details_raw != blank and color_details_raw != 'null' %}data-colors='{{ color_details_raw | json }}'{% endif %}
+ {% if primary_hex != blank %}data-primary-hex="{{ primary_hex }}"{% endif %}
+ {% if ai_colors_raw != blank and ai_colors_raw != 'null' %}data-ai-colors='{{ ai_colors_raw }}'{% endif %}
+ {% if color_name != blank %}data-color-name="{{ color_name }}"{% endif %}
+ {% if color_hex != blank %}data-color-hex="{{ color_hex }}"{% endif %}
+ {% if product.featured_image %}data-product-image="{{ product.featured_image | img_url: '200x200' }}"{% endif %}
+ ></div>
+</div>
+
+<script>
+(function(){
+ function init() {
+ try {
+ var container = document.getElementById('dw-color-dots-container');
+ if (!container || container.dataset.rendered) return;
+ container.dataset.rendered = '1';
+
+ var C = {
+ 'red':'red-wallpaper-collection','crimson':'red-wallpaper-collection','burgundy':'red-wallpaper-collection','wine':'red-wallpaper-collection','maroon':'red-wallpaper-collection',
+ 'blue':'blue-wallpaper-collection','navy':'blue-wallpaper-collection','cobalt':'blue-wallpaper-collection','indigo':'blue-wallpaper-collection','sky blue':'blue-wallpaper-collection','steel blue':'blue-wallpaper-collection','royal blue':'blue-wallpaper-collection',
+ 'green':'green-wallpaper-collection','sage':'green-wallpaper-collection','olive':'green-wallpaper-collection','forest green':'green-wallpaper-collection','emerald':'green-wallpaper-collection','mint':'green-wallpaper-collection','moss':'green-wallpaper-collection',
+ 'gold':'gold-wallpaper','golden':'gold-wallpaper','amber':'gold-wallpaper',
+ 'yellow':'yellow-wallpaper-collection','mustard':'yellow-wallpaper-collection',
+ 'orange':'orange','rust':'orange','terracotta':'orange',
+ 'pink':'pink-wallcovering-2','blush':'pink-wallcovering-2','rose':'pink-wallcovering-2','salmon':'pink-wallcovering-2','fuchsia':'pink-wallcovering-2',
+ 'purple':'purple','violet':'purple','plum':'purple','lavender':'purple','lilac':'purple','mauve':'purple',
+ 'black':'black','charcoal':'black','ebony':'black','onyx':'black',
+ 'white':'white-wallpaper-collection','ivory':'white-wallpaper-collection','cream':'white-wallpaper-collection','pearl':'white-wallpaper-collection','off-white':'white-wallpaper-collection',
+ 'gray':'grey-wallcovering','grey':'grey-wallcovering','silver':'grey-silver','slate':'grey-wallcovering',
+ 'brown':'brown-wallpaper-collection','chocolate':'brown-wallpaper-collection','espresso':'brown-wallpaper-collection','walnut':'brown-wallpaper-collection','mocha':'brown-wallpaper-collection','sienna':'brown-wallpaper-collection',
+ 'beige':'beige-cream-wallpaper-collection','tan':'beige-cream-wallpaper-collection','taupe':'beige-cream-wallpaper-collection','sand':'beige-cream-wallpaper-collection','khaki':'beige-cream-wallpaper-collection','camel':'beige-cream-wallpaper-collection','oatmeal':'beige-cream-wallpaper-collection','linen':'beige-cream-wallpaper-collection',
+ 'coral':'coral','peach':'coral',
+ 'teal':'turquoise','aqua':'turquoise','turquoise':'turquoise','cyan':'turquoise',
+ 'metallic':'metallic-wallpaper-collections','copper':'metallic-wallpaper-collections','bronze':'metallic-wallpaper-collections'
+ };
+
+ var N = {
+ 'red':'#DC2626','crimson':'#DC143C','burgundy':'#800020','wine':'#722F37','maroon':'#800000',
+ 'blue':'#2563EB','navy':'#1B2A4A','cobalt':'#0047AB','indigo':'#3F51B5','sky blue':'#87CEEB','steel blue':'#4682B4','royal blue':'#4169E1',
+ 'green':'#16A34A','sage':'#87AE73','olive':'#808000','forest green':'#228B22','emerald':'#50C878','mint':'#98FF98','moss':'#8A9A5B',
+ 'gold':'#D4AF37','golden':'#FFD700','amber':'#FFBF00',
+ 'yellow':'#EAB308','mustard':'#FFDB58',
+ 'orange':'#EA580C','rust':'#B7410E','terracotta':'#E2725B',
+ 'pink':'#EC4899','blush':'#DE5D83','rose':'#FF007F','salmon':'#FA8072','fuchsia':'#FF00FF',
+ 'purple':'#9333EA','violet':'#7C3AED','plum':'#8E4585','lavender':'#E6E6FA','lilac':'#C8A2C8','mauve':'#E0B0FF',
+ 'black':'#1A1A1A','charcoal':'#36454F','ebony':'#555D50','onyx':'#353839',
+ 'white':'#FAFAFA','ivory':'#FFFFF0','cream':'#FFFDD0','pearl':'#F0EAD6','off-white':'#FAF9F6',
+ 'gray':'#6B7280','grey':'#6B7280','silver':'#C0C0C0','slate':'#708090',
+ 'brown':'#92400E','chocolate':'#7B3F00','espresso':'#3C1414','walnut':'#5C3A1D','mocha':'#967969','sienna':'#A0522D',
+ 'beige':'#F5F5DC','tan':'#D2B48C','taupe':'#483C32','sand':'#C2B280','khaki':'#F0E68C','camel':'#C19A6B','oatmeal':'#B8AB8C','linen':'#FAF0E6',
+ 'coral':'#FF6F61','peach':'#FFCBA4',
+ 'teal':'#0D9488','aqua':'#00FFFF','turquoise':'#40E0D0','cyan':'#06B6D4',
+ 'metallic':'#AAA9AD','copper':'#B87333','bronze':'#CD7F32',
+ 'deep indigo':'#1B2A4A','dark navy':'#1B2A4A','midnight':'#191970'
+ };
+
+ function findColl(name) {
+ var l = (name||'').toLowerCase();
+ if (C[l]) return C[l];
+ for (var k in C) { if (l.indexOf(k) > -1) return C[k]; }
+ return null;
+ }
+
+ function makeDot(hex, name, pct) {
+ try {
+ var coll = findColl(name);
+ var a = document.createElement('a');
+ a.href = coll ? '/collections/' + coll + '?sort_by=created-descending' : '/search?q=' + encodeURIComponent(name||hex) + '&sort_by=created-descending';
+ a.title = (coll?'Shop ':'Search ') + (name||'color') + ' (' + hex + ')';
+ a.style.textDecoration = 'none';
+ var d = document.createElement('div');
+ var p = (pct == null ? 20 : pct);
+ var sz=Math.max(22,Math.min(52,16+p*0.6));d.style.cssText='width:'+sz+'px;height:'+sz+'px;border-radius:50%;background:'+hex+';border:2px solid #eee;box-shadow:0 1px 3px rgba(0,0,0,0.1);cursor:pointer;transition:transform 0.15s,box-shadow 0.15s;flex-shrink:0;';
+ d.onmouseenter = function(){this.style.transform='scale(1.3)';this.style.boxShadow='0 2px 8px rgba(0,0,0,0.2)';};
+ d.onmouseleave = function(){this.style.transform='scale(1)';this.style.boxShadow='0 1px 3px rgba(0,0,0,0.1)';};
+ a.appendChild(d);
+ return a;
+ } catch(e) { return null; }
+ }
+
+ function renderDots(colors) {
+ colors.forEach(function(c){ var el = makeDot(c.hex, c.name, (c.pct || c.percentage)); if (el) container.appendChild(el); });
+ }
+
+ /* Canvas color refs */
+ var REF = {
+ 'red':[220,38,38],'navy':[27,42,74],'blue':[37,99,235],'green':[22,163,74],'sage':[135,174,115],
+ 'gold':[212,175,55],'yellow':[234,179,8],'orange':[234,88,12],'pink':[236,72,153],
+ 'purple':[147,51,234],'black':[26,26,26],'charcoal':[54,69,79],'white':[250,250,250],
+ 'ivory':[255,255,240],'cream':[255,253,208],'gray':[107,114,128],'silver':[192,192,192],
+ 'brown':[146,64,14],'beige':[245,245,220],'tan':[210,180,140],'taupe':[72,60,50],
+ 'teal':[13,148,136],'coral':[255,111,97],'olive':[128,128,0],'rust':[183,65,14],
+ 'burgundy':[128,0,32],'slate':[112,128,144],'sand':[194,178,128],'mint':[152,255,152],
+ 'turquoise':[64,224,208],'copper':[184,115,51],'bronze':[205,127,50],'mauve':[224,176,255]
+ };
+
+ function closestName(r,g,b) {
+ var best='',bestD=1e9;
+ for(var n in REF){var c=REF[n],d=Math.sqrt(Math.pow(r-c[0],2)+Math.pow(g-c[1],2)+Math.pow(b-c[2],2));if(d<bestD){bestD=d;best=n;}}
+ return best;
+ }
+ function rgbHex(r,g,b){return '#'+[r,g,b].map(function(x){return x.toString(16).padStart(2,'0');}).join('');}
+
+ function extractFromCanvas(imgUrl) {
+ var img = new Image();
+ img.crossOrigin = 'anonymous';
+ img.onload = function() {
+ try {
+ var cv = document.createElement('canvas'), sz = 50;
+ cv.width=sz; cv.height=sz;
+ var ctx=cv.getContext('2d');
+ ctx.drawImage(img,0,0,sz,sz);
+ var px=ctx.getImageData(0,0,sz,sz).data;
+ var bk={};
+ for(var i=0;i<px.length;i+=4){
+ var kr=Math.round(px[i]/32)*32,kg=Math.round(px[i+1]/32)*32,kb=Math.round(px[i+2]/32)*32;
+ var key=kr+','+kg+','+kb;
+ if(!bk[key])bk[key]={r:0,g:0,b:0,n:0};
+ bk[key].r+=px[i];bk[key].g+=px[i+1];bk[key].b+=px[i+2];bk[key].n++;
+ }
+ var sorted=Object.values(bk).sort(function(a,b){return b.n-a.n;});
+ var tot=sz*sz,colors=[],seen={};
+ for(var j=0;j<Math.min(sorted.length,8);j++){
+ var s=sorted[j],ar=Math.round(s.r/s.n),ag=Math.round(s.g/s.n),ab=Math.round(s.b/s.n);
+ var nm=closestName(ar,ag,ab);
+ if(seen[nm])continue; seen[nm]=true;
+ colors.push({name:nm,hex:rgbHex(ar,ag,ab),percentage:Math.round(s.n/tot*100)});
+ if(colors.length>=5)break;
+ }
+ if(colors.length>0) renderDots(colors);
+ } catch(e) {
+ /* CORS or canvas security error — try without crossOrigin */
+ var img2 = new Image();
+ img2.onload = function() {
+ try {
+ var cv2 = document.createElement('canvas'), sz2 = 50;
+ cv2.width=sz2; cv2.height=sz2;
+ var ctx2=cv2.getContext('2d');
+ ctx2.drawImage(img2,0,0,sz2,sz2);
+ /* Cannot getImageData without CORS — use image dominant color via 1x1 scale */
+ cv2.width=1; cv2.height=1;
+ ctx2.drawImage(img2,0,0,1,1);
+ var p=ctx2.getImageData(0,0,1,1).data;
+ var nm=closestName(p[0],p[1],p[2]);
+ renderDots([{name:nm,hex:rgbHex(p[0],p[1],p[2]),percentage:100}]);
+ } catch(e2) {}
+ };
+ img2.src = imgUrl;
+ }
+ };
+ img.onerror = function(){};
+ img.src = imgUrl;
+ }
+
+ function getImageUrl() {
+ var url = container.dataset.productImage;
+ if (url && url.length > 5) return url.indexOf('//') === 0 ? 'https:' + url : url;
+ var sels = [
+ '.product-gallery--viewport img[src]',
+ '.product-gallery img[src]',
+ '[data-product-gallery] img[src]',
+ '.product-gallery--viewport--figure img[src]',
+ '.product__media img[src]',
+ '.product-single__photo img[src]'
+ ];
+ for (var i = 0; i < sels.length; i++) {
+ var el = document.querySelector(sels[i]);
+ if (el && el.src) return el.src;
+ }
+ return null;
+ }
+
+ /* ── Tier 1: color_details metafield ── */
+ var colorsData = container.dataset.colors;
+ if (colorsData) {
+ try {
+ /* Fix Shopify Liquid Ruby hash syntax: => becomes : */
+ var fixed = colorsData.replace(/=>/g, ':');
+ renderDots(JSON.parse(fixed));
+ return;
+ } catch(e) {}
+ }
+
+ /* ── Tier 2: primary_color_hex + ai_generated_colors ── */
+ var ph = container.dataset.primaryHex;
+ var aiRaw = container.dataset.aiColors;
+ if (ph || aiRaw) {
+ var added = {};
+ if (ph) { var pd=makeDot(ph, container.dataset.colorName||'primary'); if(pd)container.appendChild(pd); added[ph.toLowerCase()]=true; }
+ try {
+ var ai = JSON.parse((aiRaw||'[]').replace(/=>/g, ':'));
+ ai.forEach(function(nm){ var h=N[nm.toLowerCase()]; if(h&&!added[h.toLowerCase()]){var ad=makeDot(h,nm); if(ad)container.appendChild(ad);added[h.toLowerCase()]=true;} });
+ } catch(e) {}
+ if (container.children.length > 0) return;
+ }
+
+ /* ── Tier 2.5: single color_hex ── */
+ var sh = container.dataset.colorHex;
+ if (sh) { var shd=makeDot(sh, container.dataset.colorName||'color'); if(shd)container.appendChild(shd); return; }
+
+ /* ── Tier 3: Canvas extraction from product image ── */
+ var imgUrl = getImageUrl();
+ if (imgUrl) {
+ extractFromCanvas(imgUrl);
+ } else {
+ var obs = new MutationObserver(function(m, o) {
+ var url = getImageUrl();
+ if (url) { o.disconnect(); extractFromCanvas(url); }
+ });
+ obs.observe(document.body, { childList: true, subtree: true });
+ setTimeout(function(){ obs.disconnect(); }, 5000);
+ }
+ } catch(e) { /* never let color-dot rendering abort other page init */ }
+ }
+
+ if (document.readyState === 'loading') {
+ document.addEventListener('DOMContentLoaded', init);
+ } else {
+ init();
+ }
+})();
+</script>
diff --git a/shopify/theme-fixes/color-dots-c-scope-2026-06-30/color-dots.ORIGINAL.liquid b/shopify/theme-fixes/color-dots-c-scope-2026-06-30/color-dots.ORIGINAL.liquid
new file mode 100644
index 00000000..2210815f
--- /dev/null
+++ b/shopify/theme-fixes/color-dots-c-scope-2026-06-30/color-dots.ORIGINAL.liquid
@@ -0,0 +1,240 @@
+{% assign color_dots_json_val = product.metafields.custom.color_dots_json.value %}
+{% assign color_details_val = product.metafields.custom.color_details.value %}
+{% if color_dots_json_val != blank %}
+ {% assign color_details_raw = color_dots_json_val | json %}
+{% elsif color_details_val != blank %}
+ {% assign color_details_raw = color_details_val | json %}
+{% else %}
+ {% assign color_details_raw = blank %}
+{% endif %}
+{% assign color_hex = product.metafields.custom.color_hex.value %}
+{% assign primary_hex = product.metafields.custom.primary_color_hex.value %}
+{% assign ai_colors_raw = product.metafields.dwc.ai_generated_colors.value | json %}
+{% assign color_name = product.metafields.custom.color_name.value %}
+
+{%- comment -%}
+ Color Dots v3 — 3-tier color system
+ Tier 1: color_details metafield (Gemini-enriched)
+ Tier 2: primary_color_hex + ai_generated_colors
+ Tier 3: Canvas pixel extraction from product image (onload)
+{%- endcomment -%}
+
+<div class="dw-color-dots" id="dw-color-dots-wrapper" style="display:flex;justify-content:center;gap:10px;padding:12px 0 8px;flex-wrap:wrap;min-height:30px;">
+ <div id="dw-color-dots-container" style="display:flex;justify-content:center;gap:10px;flex-wrap:wrap;"
+ {% if color_details_raw != blank and color_details_raw != 'null' %}data-colors='{{ color_details_raw | json }}'{% endif %}
+ {% if primary_hex != blank %}data-primary-hex="{{ primary_hex }}"{% endif %}
+ {% if ai_colors_raw != blank and ai_colors_raw != 'null' %}data-ai-colors='{{ ai_colors_raw }}'{% endif %}
+ {% if color_name != blank %}data-color-name="{{ color_name }}"{% endif %}
+ {% if color_hex != blank %}data-color-hex="{{ color_hex }}"{% endif %}
+ {% if product.featured_image %}data-product-image="{{ product.featured_image | img_url: '200x200' }}"{% endif %}
+ ></div>
+</div>
+
+<script>
+(function(){
+ function init() {
+ var container = document.getElementById('dw-color-dots-container');
+ if (!container || container.dataset.rendered) return;
+ container.dataset.rendered = '1';
+
+ var C = {
+ 'red':'red-wallpaper-collection','crimson':'red-wallpaper-collection','burgundy':'red-wallpaper-collection','wine':'red-wallpaper-collection','maroon':'red-wallpaper-collection',
+ 'blue':'blue-wallpaper-collection','navy':'blue-wallpaper-collection','cobalt':'blue-wallpaper-collection','indigo':'blue-wallpaper-collection','sky blue':'blue-wallpaper-collection','steel blue':'blue-wallpaper-collection','royal blue':'blue-wallpaper-collection',
+ 'green':'green-wallpaper-collection','sage':'green-wallpaper-collection','olive':'green-wallpaper-collection','forest green':'green-wallpaper-collection','emerald':'green-wallpaper-collection','mint':'green-wallpaper-collection','moss':'green-wallpaper-collection',
+ 'gold':'gold-wallpaper','golden':'gold-wallpaper','amber':'gold-wallpaper',
+ 'yellow':'yellow-wallpaper-collection','mustard':'yellow-wallpaper-collection',
+ 'orange':'orange','rust':'orange','terracotta':'orange',
+ 'pink':'pink-wallcovering-2','blush':'pink-wallcovering-2','rose':'pink-wallcovering-2','salmon':'pink-wallcovering-2','fuchsia':'pink-wallcovering-2',
+ 'purple':'purple','violet':'purple','plum':'purple','lavender':'purple','lilac':'purple','mauve':'purple',
+ 'black':'black','charcoal':'black','ebony':'black','onyx':'black',
+ 'white':'white-wallpaper-collection','ivory':'white-wallpaper-collection','cream':'white-wallpaper-collection','pearl':'white-wallpaper-collection','off-white':'white-wallpaper-collection',
+ 'gray':'grey-wallcovering','grey':'grey-wallcovering','silver':'grey-silver','slate':'grey-wallcovering',
+ 'brown':'brown-wallpaper-collection','chocolate':'brown-wallpaper-collection','espresso':'brown-wallpaper-collection','walnut':'brown-wallpaper-collection','mocha':'brown-wallpaper-collection','sienna':'brown-wallpaper-collection',
+ 'beige':'beige-cream-wallpaper-collection','tan':'beige-cream-wallpaper-collection','taupe':'beige-cream-wallpaper-collection','sand':'beige-cream-wallpaper-collection','khaki':'beige-cream-wallpaper-collection','camel':'beige-cream-wallpaper-collection','oatmeal':'beige-cream-wallpaper-collection','linen':'beige-cream-wallpaper-collection',
+ 'coral':'coral','peach':'coral',
+ 'teal':'turquoise','aqua':'turquoise','turquoise':'turquoise','cyan':'turquoise',
+ 'metallic':'metallic-wallpaper-collections','copper':'metallic-wallpaper-collections','bronze':'metallic-wallpaper-collections'
+ };
+
+ var N = {
+ 'red':'#DC2626','crimson':'#DC143C','burgundy':'#800020','wine':'#722F37','maroon':'#800000',
+ 'blue':'#2563EB','navy':'#1B2A4A','cobalt':'#0047AB','indigo':'#3F51B5','sky blue':'#87CEEB','steel blue':'#4682B4','royal blue':'#4169E1',
+ 'green':'#16A34A','sage':'#87AE73','olive':'#808000','forest green':'#228B22','emerald':'#50C878','mint':'#98FF98','moss':'#8A9A5B',
+ 'gold':'#D4AF37','golden':'#FFD700','amber':'#FFBF00',
+ 'yellow':'#EAB308','mustard':'#FFDB58',
+ 'orange':'#EA580C','rust':'#B7410E','terracotta':'#E2725B',
+ 'pink':'#EC4899','blush':'#DE5D83','rose':'#FF007F','salmon':'#FA8072','fuchsia':'#FF00FF',
+ 'purple':'#9333EA','violet':'#7C3AED','plum':'#8E4585','lavender':'#E6E6FA','lilac':'#C8A2C8','mauve':'#E0B0FF',
+ 'black':'#1A1A1A','charcoal':'#36454F','ebony':'#555D50','onyx':'#353839',
+ 'white':'#FAFAFA','ivory':'#FFFFF0','cream':'#FFFDD0','pearl':'#F0EAD6','off-white':'#FAF9F6',
+ 'gray':'#6B7280','grey':'#6B7280','silver':'#C0C0C0','slate':'#708090',
+ 'brown':'#92400E','chocolate':'#7B3F00','espresso':'#3C1414','walnut':'#5C3A1D','mocha':'#967969','sienna':'#A0522D',
+ 'beige':'#F5F5DC','tan':'#D2B48C','taupe':'#483C32','sand':'#C2B280','khaki':'#F0E68C','camel':'#C19A6B','oatmeal':'#B8AB8C','linen':'#FAF0E6',
+ 'coral':'#FF6F61','peach':'#FFCBA4',
+ 'teal':'#0D9488','aqua':'#00FFFF','turquoise':'#40E0D0','cyan':'#06B6D4',
+ 'metallic':'#AAA9AD','copper':'#B87333','bronze':'#CD7F32',
+ 'deep indigo':'#1B2A4A','dark navy':'#1B2A4A','midnight':'#191970'
+ };
+
+ function findColl(name) {
+ var l = (name||'').toLowerCase();
+ if (C[l]) return C[l];
+ for (var k in C) { if (l.indexOf(k) > -1) return C[k]; }
+ return null;
+ }
+
+ function makeDot(hex, name) {
+ var coll = findColl(name);
+ var a = document.createElement('a');
+ a.href = coll ? '/collections/' + coll + '?sort_by=created-descending' : '/search?q=' + encodeURIComponent(name||hex) + '&sort_by=created-descending';
+ a.title = (coll?'Shop ':'Search ') + (name||'color') + ' (' + hex + ')';
+ a.style.textDecoration = 'none';
+ var d = document.createElement('div');
+ var sz=Math.max(22,Math.min(52,16+(c.pct||c.percentage||20)*0.6));d.style.cssText='width:'+sz+'px;height:'+sz+'px;border-radius:50%;background:'+hex+';border:2px solid #eee;box-shadow:0 1px 3px rgba(0,0,0,0.1);cursor:pointer;transition:transform 0.15s,box-shadow 0.15s;flex-shrink:0;';
+ d.onmouseenter = function(){this.style.transform='scale(1.3)';this.style.boxShadow='0 2px 8px rgba(0,0,0,0.2)';};
+ d.onmouseleave = function(){this.style.transform='scale(1)';this.style.boxShadow='0 1px 3px rgba(0,0,0,0.1)';};
+ a.appendChild(d);
+ return a;
+ }
+
+ function renderDots(colors) {
+ colors.forEach(function(c){ container.appendChild(makeDot(c.hex, c.name)); });
+ }
+
+ /* Canvas color refs */
+ var REF = {
+ 'red':[220,38,38],'navy':[27,42,74],'blue':[37,99,235],'green':[22,163,74],'sage':[135,174,115],
+ 'gold':[212,175,55],'yellow':[234,179,8],'orange':[234,88,12],'pink':[236,72,153],
+ 'purple':[147,51,234],'black':[26,26,26],'charcoal':[54,69,79],'white':[250,250,250],
+ 'ivory':[255,255,240],'cream':[255,253,208],'gray':[107,114,128],'silver':[192,192,192],
+ 'brown':[146,64,14],'beige':[245,245,220],'tan':[210,180,140],'taupe':[72,60,50],
+ 'teal':[13,148,136],'coral':[255,111,97],'olive':[128,128,0],'rust':[183,65,14],
+ 'burgundy':[128,0,32],'slate':[112,128,144],'sand':[194,178,128],'mint':[152,255,152],
+ 'turquoise':[64,224,208],'copper':[184,115,51],'bronze':[205,127,50],'mauve':[224,176,255]
+ };
+
+ function closestName(r,g,b) {
+ var best='',bestD=1e9;
+ for(var n in REF){var c=REF[n],d=Math.sqrt(Math.pow(r-c[0],2)+Math.pow(g-c[1],2)+Math.pow(b-c[2],2));if(d<bestD){bestD=d;best=n;}}
+ return best;
+ }
+ function rgbHex(r,g,b){return '#'+[r,g,b].map(function(x){return x.toString(16).padStart(2,'0');}).join('');}
+
+ function extractFromCanvas(imgUrl) {
+ var img = new Image();
+ img.crossOrigin = 'anonymous';
+ img.onload = function() {
+ try {
+ var cv = document.createElement('canvas'), sz = 50;
+ cv.width=sz; cv.height=sz;
+ var ctx=cv.getContext('2d');
+ ctx.drawImage(img,0,0,sz,sz);
+ var px=ctx.getImageData(0,0,sz,sz).data;
+ var bk={};
+ for(var i=0;i<px.length;i+=4){
+ var kr=Math.round(px[i]/32)*32,kg=Math.round(px[i+1]/32)*32,kb=Math.round(px[i+2]/32)*32;
+ var key=kr+','+kg+','+kb;
+ if(!bk[key])bk[key]={r:0,g:0,b:0,n:0};
+ bk[key].r+=px[i];bk[key].g+=px[i+1];bk[key].b+=px[i+2];bk[key].n++;
+ }
+ var sorted=Object.values(bk).sort(function(a,b){return b.n-a.n;});
+ var tot=sz*sz,colors=[],seen={};
+ for(var j=0;j<Math.min(sorted.length,8);j++){
+ var s=sorted[j],ar=Math.round(s.r/s.n),ag=Math.round(s.g/s.n),ab=Math.round(s.b/s.n);
+ var nm=closestName(ar,ag,ab);
+ if(seen[nm])continue; seen[nm]=true;
+ colors.push({name:nm,hex:rgbHex(ar,ag,ab),percentage:Math.round(s.n/tot*100)});
+ if(colors.length>=5)break;
+ }
+ if(colors.length>0) renderDots(colors);
+ } catch(e) {
+ /* CORS or canvas security error — try without crossOrigin */
+ var img2 = new Image();
+ img2.onload = function() {
+ try {
+ var cv2 = document.createElement('canvas'), sz2 = 50;
+ cv2.width=sz2; cv2.height=sz2;
+ var ctx2=cv2.getContext('2d');
+ ctx2.drawImage(img2,0,0,sz2,sz2);
+ /* Cannot getImageData without CORS — use image dominant color via 1x1 scale */
+ cv2.width=1; cv2.height=1;
+ ctx2.drawImage(img2,0,0,1,1);
+ var p=ctx2.getImageData(0,0,1,1).data;
+ var nm=closestName(p[0],p[1],p[2]);
+ renderDots([{name:nm,hex:rgbHex(p[0],p[1],p[2]),percentage:100}]);
+ } catch(e2) {}
+ };
+ img2.src = imgUrl;
+ }
+ };
+ img.onerror = function(){};
+ img.src = imgUrl;
+ }
+
+ function getImageUrl() {
+ var url = container.dataset.productImage;
+ if (url && url.length > 5) return url.indexOf('//') === 0 ? 'https:' + url : url;
+ var sels = [
+ '.product-gallery--viewport img[src]',
+ '.product-gallery img[src]',
+ '[data-product-gallery] img[src]',
+ '.product-gallery--viewport--figure img[src]',
+ '.product__media img[src]',
+ '.product-single__photo img[src]'
+ ];
+ for (var i = 0; i < sels.length; i++) {
+ var el = document.querySelector(sels[i]);
+ if (el && el.src) return el.src;
+ }
+ return null;
+ }
+
+ /* ── Tier 1: color_details metafield ── */
+ var colorsData = container.dataset.colors;
+ if (colorsData) {
+ try {
+ /* Fix Shopify Liquid Ruby hash syntax: => becomes : */
+ var fixed = colorsData.replace(/=>/g, ':');
+ renderDots(JSON.parse(fixed));
+ return;
+ } catch(e) {}
+ }
+
+ /* ── Tier 2: primary_color_hex + ai_generated_colors ── */
+ var ph = container.dataset.primaryHex;
+ var aiRaw = container.dataset.aiColors;
+ if (ph || aiRaw) {
+ var added = {};
+ if (ph) { container.appendChild(makeDot(ph, container.dataset.colorName||'primary')); added[ph.toLowerCase()]=true; }
+ try {
+ var ai = JSON.parse((aiRaw||'[]').replace(/=>/g, ':'));
+ ai.forEach(function(nm){ var h=N[nm.toLowerCase()]; if(h&&!added[h.toLowerCase()]){container.appendChild(makeDot(h,nm));added[h.toLowerCase()]=true;} });
+ } catch(e) {}
+ if (container.children.length > 0) return;
+ }
+
+ /* ── Tier 2.5: single color_hex ── */
+ var sh = container.dataset.colorHex;
+ if (sh) { container.appendChild(makeDot(sh, container.dataset.colorName||'color')); return; }
+
+ /* ── Tier 3: Canvas extraction from product image ── */
+ var imgUrl = getImageUrl();
+ if (imgUrl) {
+ extractFromCanvas(imgUrl);
+ } else {
+ var obs = new MutationObserver(function(m, o) {
+ var url = getImageUrl();
+ if (url) { o.disconnect(); extractFromCanvas(url); }
+ });
+ obs.observe(document.body, { childList: true, subtree: true });
+ setTimeout(function(){ obs.disconnect(); }, 5000);
+ }
+ }
+
+ if (document.readyState === 'loading') {
+ document.addEventListener('DOMContentLoaded', init);
+ } else {
+ init();
+ }
+})();
+</script>
diff --git a/shopify/theme-fixes/color-dots-c-scope-2026-06-30/color-dots.diff b/shopify/theme-fixes/color-dots-c-scope-2026-06-30/color-dots.diff
new file mode 100644
index 00000000..a5240270
--- /dev/null
+++ b/shopify/theme-fixes/color-dots-c-scope-2026-06-30/color-dots.diff
@@ -0,0 +1,78 @@
+--- /Users/stevestudio2/Projects/Designer-Wallcoverings/shopify/theme-fixes/color-dots-c-scope-2026-06-30/color-dots.ORIGINAL.liquid 2026-06-30 19:53:47
++++ /Users/stevestudio2/Projects/Designer-Wallcoverings/shopify/theme-fixes/color-dots-c-scope-2026-06-30/color-dots.FIXED.liquid 2026-06-30 19:53:47
+@@ -33,6 +33,7 @@
+ <script>
+ (function(){
+ function init() {
++ try {
+ var container = document.getElementById('dw-color-dots-container');
+ if (!container || container.dataset.rendered) return;
+ container.dataset.rendered = '1';
+@@ -83,22 +84,25 @@
+ return null;
+ }
+
+- function makeDot(hex, name) {
+- var coll = findColl(name);
+- var a = document.createElement('a');
+- a.href = coll ? '/collections/' + coll + '?sort_by=created-descending' : '/search?q=' + encodeURIComponent(name||hex) + '&sort_by=created-descending';
+- a.title = (coll?'Shop ':'Search ') + (name||'color') + ' (' + hex + ')';
+- a.style.textDecoration = 'none';
+- var d = document.createElement('div');
+- var sz=Math.max(22,Math.min(52,16+(c.pct||c.percentage||20)*0.6));d.style.cssText='width:'+sz+'px;height:'+sz+'px;border-radius:50%;background:'+hex+';border:2px solid #eee;box-shadow:0 1px 3px rgba(0,0,0,0.1);cursor:pointer;transition:transform 0.15s,box-shadow 0.15s;flex-shrink:0;';
+- d.onmouseenter = function(){this.style.transform='scale(1.3)';this.style.boxShadow='0 2px 8px rgba(0,0,0,0.2)';};
+- d.onmouseleave = function(){this.style.transform='scale(1)';this.style.boxShadow='0 1px 3px rgba(0,0,0,0.1)';};
+- a.appendChild(d);
+- return a;
++ function makeDot(hex, name, pct) {
++ try {
++ var coll = findColl(name);
++ var a = document.createElement('a');
++ a.href = coll ? '/collections/' + coll + '?sort_by=created-descending' : '/search?q=' + encodeURIComponent(name||hex) + '&sort_by=created-descending';
++ a.title = (coll?'Shop ':'Search ') + (name||'color') + ' (' + hex + ')';
++ a.style.textDecoration = 'none';
++ var d = document.createElement('div');
++ var p = (pct == null ? 20 : pct);
++ var sz=Math.max(22,Math.min(52,16+p*0.6));d.style.cssText='width:'+sz+'px;height:'+sz+'px;border-radius:50%;background:'+hex+';border:2px solid #eee;box-shadow:0 1px 3px rgba(0,0,0,0.1);cursor:pointer;transition:transform 0.15s,box-shadow 0.15s;flex-shrink:0;';
++ d.onmouseenter = function(){this.style.transform='scale(1.3)';this.style.boxShadow='0 2px 8px rgba(0,0,0,0.2)';};
++ d.onmouseleave = function(){this.style.transform='scale(1)';this.style.boxShadow='0 1px 3px rgba(0,0,0,0.1)';};
++ a.appendChild(d);
++ return a;
++ } catch(e) { return null; }
+ }
+
+ function renderDots(colors) {
+- colors.forEach(function(c){ container.appendChild(makeDot(c.hex, c.name)); });
++ colors.forEach(function(c){ var el = makeDot(c.hex, c.name, (c.pct || c.percentage)); if (el) container.appendChild(el); });
+ }
+
+ /* Canvas color refs */
+@@ -205,17 +209,17 @@
+ var aiRaw = container.dataset.aiColors;
+ if (ph || aiRaw) {
+ var added = {};
+- if (ph) { container.appendChild(makeDot(ph, container.dataset.colorName||'primary')); added[ph.toLowerCase()]=true; }
++ if (ph) { var pd=makeDot(ph, container.dataset.colorName||'primary'); if(pd)container.appendChild(pd); added[ph.toLowerCase()]=true; }
+ try {
+ var ai = JSON.parse((aiRaw||'[]').replace(/=>/g, ':'));
+- ai.forEach(function(nm){ var h=N[nm.toLowerCase()]; if(h&&!added[h.toLowerCase()]){container.appendChild(makeDot(h,nm));added[h.toLowerCase()]=true;} });
++ ai.forEach(function(nm){ var h=N[nm.toLowerCase()]; if(h&&!added[h.toLowerCase()]){var ad=makeDot(h,nm); if(ad)container.appendChild(ad);added[h.toLowerCase()]=true;} });
+ } catch(e) {}
+ if (container.children.length > 0) return;
+ }
+
+ /* ── Tier 2.5: single color_hex ── */
+ var sh = container.dataset.colorHex;
+- if (sh) { container.appendChild(makeDot(sh, container.dataset.colorName||'color')); return; }
++ if (sh) { var shd=makeDot(sh, container.dataset.colorName||'color'); if(shd)container.appendChild(shd); return; }
+
+ /* ── Tier 3: Canvas extraction from product image ── */
+ var imgUrl = getImageUrl();
+@@ -229,6 +233,7 @@
+ obs.observe(document.body, { childList: true, subtree: true });
+ setTimeout(function(){ obs.disconnect(); }, 5000);
+ }
++ } catch(e) { /* never let color-dot rendering abort other page init */ }
+ }
+
+ if (document.readyState === 'loading') {
diff --git a/shopify/theme-fixes/color-dots-c-scope-2026-06-30/verify.cjs b/shopify/theme-fixes/color-dots-c-scope-2026-06-30/verify.cjs
new file mode 100644
index 00000000..9bd3cbd2
--- /dev/null
+++ b/shopify/theme-fixes/color-dots-c-scope-2026-06-30/verify.cjs
@@ -0,0 +1,57 @@
+const { chromium } = require('/Users/stevestudio2/Projects/Designer-Wallcoverings/node_modules/playwright');
+(async () => {
+const DEV_ID = 144105013299;
+const products = [
+ { label: 'MOQ (dwtt-80064)', handle: 'dwtt-80064-designer-wallcoverings-los-angeles' },
+ { label: 'CONTROL (tova-ochre)', handle: 'tova-ochre-dwdx-220476' },
+];
+const browser = await chromium.launch();
+const ctx = await browser.newContext();
+// Seed preview cookie: first hit the homepage with preview param so Shopify sets the preview session
+const seed = await ctx.newPage();
+await seed.goto(`https://www.designerwallcoverings.com/?preview_theme_id=${DEV_ID}`, { waitUntil:'domcontentloaded', timeout:60000 });
+await seed.waitForTimeout(1500);
+await seed.close();
+
+const results = [];
+for (const p of products) {
+ const page = await ctx.newPage();
+ const pageErrors = [];
+ page.on('pageerror', e => pageErrors.push(String(e)));
+ const url = `https://www.designerwallcoverings.com/products/${p.handle}?preview_theme_id=${DEV_ID}`;
+ try {
+ await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 60000 });
+ } catch (e) { pageErrors.push('goto: ' + e.message); }
+ await page.waitForTimeout(4000);
+ const html = await page.content();
+ const themeMarker = html.includes('function makeDot(hex, name, pct)') ? 'DEV-FIXED'
+ : html.includes('function makeDot(hex, name)') ? 'OLD-BUGGY' : 'unknown';
+ const themeId = await page.evaluate(() => (window.Shopify && Shopify.theme && Shopify.theme.id) || null);
+ const cErr = pageErrors.filter(e => /c is not defined/.test(e));
+ const dotsRendered = await page.evaluate(() => {
+ const c = document.getElementById('dw-color-dots-container');
+ return c ? c.children.length : -1;
+ });
+ const qty = await page.evaluate(() => {
+ const inp = document.querySelector('.mm_quantity input[name="quantity"]') || document.querySelector('input[name="quantity"]');
+ if (!inp) return { found:false };
+ return { found:true, value:inp.value, min:inp.getAttribute('min'), step:inp.getAttribute('step') };
+ });
+ // find visible plus button inside a visible mm_quantity
+ let afterPlus = null, plusInfo=null;
+ try {
+ plusInfo = await page.evaluate(() => {
+ const btns = Array.from(document.querySelectorAll('.mm_quantity .plus, .plus, [data-qty-plus], button.qty-plus'));
+ return btns.map(b => ({ cls:b.className, vis: !!(b.offsetParent) }));
+ });
+ const vis = await page.$('.mm_quantity:not(.hidden) .plus');
+ if (vis) { await vis.click(); await page.waitForTimeout(400); await vis.click(); await page.waitForTimeout(400);
+ afterPlus = await page.evaluate(() => { const inp=document.querySelector('.mm_quantity:not(.hidden) input[name="quantity"]')||document.querySelector('input[name="quantity"]'); return inp?inp.value:null; });
+ } else afterPlus='no-visible-plus';
+ } catch(e) { afterPlus='err:'+e.message.slice(0,60); }
+ results.push({ label:p.label, themeMarker, themeId, cErrCount:cErr.length, cErrSample:cErr[0]||null, dotsRendered, qty, afterPlus, plusInfo, otherErrors: pageErrors.filter(e=>!/c is not defined/.test(e)).map(e=>e.slice(0,80)).slice(0,3) });
+ await page.close();
+}
+await browser.close();
+console.log(JSON.stringify(results, null, 2));
+})();
diff --git a/shopify/theme-fixes/color-dots-c-scope-2026-06-30/verify2.cjs b/shopify/theme-fixes/color-dots-c-scope-2026-06-30/verify2.cjs
new file mode 100644
index 00000000..69f51115
--- /dev/null
+++ b/shopify/theme-fixes/color-dots-c-scope-2026-06-30/verify2.cjs
@@ -0,0 +1,65 @@
+const { chromium } = require('/Users/stevestudio2/Projects/Designer-Wallcoverings/node_modules/playwright');
+(async () => {
+const DEV_ID = 144105013299;
+const products = [
+ { label: 'MOQ (dwtt-80064)', handle: 'dwtt-80064-designer-wallcoverings-los-angeles' },
+ { label: 'CONTROL (tova-ochre)', handle: 'tova-ochre-dwdx-220476' },
+];
+const browser = await chromium.launch();
+const ctx = await browser.newContext();
+const seed = await ctx.newPage();
+await seed.goto(`https://www.designerwallcoverings.com/?preview_theme_id=${DEV_ID}`, { waitUntil:'domcontentloaded', timeout:60000 });
+await seed.waitForTimeout(1500); await seed.close();
+
+const results = [];
+for (const p of products) {
+ const page = await ctx.newPage();
+ const perr = [];
+ page.on('pageerror', e => perr.push(String(e)));
+ await page.goto(`https://www.designerwallcoverings.com/products/${p.handle}?preview_theme_id=${DEV_ID}`, { waitUntil:'domcontentloaded', timeout:60000 });
+ await page.waitForTimeout(3500);
+
+ // Select the NON-sample variant so mm_quantity is visible
+ const variantPick = await page.evaluate(() => {
+ // radio/button variant selectors
+ const opts = Array.from(document.querySelectorAll('.single-option-selector option, .product-select option'));
+ let picked=null;
+ // try select dropdown: choose an option whose text isn't "Sample"
+ const sel = document.querySelector('select.single-option-selector, select.product-select');
+ if (sel) {
+ for (const o of sel.options) { if (!/sample/i.test(o.text)) { sel.value=o.value; sel.dispatchEvent(new Event('change',{bubbles:true})); picked='select:'+o.text; break; } }
+ }
+ // try variant buttons (name-only buttons)
+ if (!picked) {
+ const btns = Array.from(document.querySelectorAll('.variant-button, [data-variant-btn], .single-option-selector ~ * button'));
+ for (const b of btns) { if (!/sample/i.test(b.textContent)) { b.click(); picked='btn:'+b.textContent.trim().slice(0,20); break; } }
+ }
+ return picked;
+ });
+ await page.waitForTimeout(1500);
+
+ const state = await page.evaluate(() => {
+ const wrap = document.querySelector('.mm_quantity');
+ const inp = document.querySelector('.mm_quantity input[name="quantity"]') || document.querySelector('input[name="quantity"]');
+ const plus = document.querySelector('.mm_quantity .plus');
+ return {
+ mmHidden: wrap ? wrap.classList.contains('hidden') : 'no-wrap',
+ plusVisible: plus ? !!plus.offsetParent : 'no-plus',
+ qtyVal: inp ? inp.value : null, qtyMin: inp?inp.getAttribute('min'):null, qtyStep: inp?inp.getAttribute('step'):null
+ };
+ });
+
+ // click plus twice if visible
+ let afterPlus=state.qtyVal;
+ const plus = await page.$('.mm_quantity:not(.hidden) .plus');
+ if (plus && await plus.isVisible().catch(()=>false)) {
+ await plus.click(); await page.waitForTimeout(400); await plus.click(); await page.waitForTimeout(400);
+ afterPlus = await page.evaluate(()=>{const i=document.querySelector('.mm_quantity:not(.hidden) input[name="quantity"]');return i?i.value:null;});
+ }
+ const cErr = perr.filter(e=>/c is not defined/.test(e)).length;
+ results.push({ label:p.label, cErr, variantPick, state, afterPlusClicks: afterPlus });
+ await page.close();
+}
+await browser.close();
+console.log(JSON.stringify(results, null, 2));
+})();
diff --git a/shopify/theme-fixes/color-dots-c-scope-2026-06-30/verify3.cjs b/shopify/theme-fixes/color-dots-c-scope-2026-06-30/verify3.cjs
new file mode 100644
index 00000000..95f6ff58
--- /dev/null
+++ b/shopify/theme-fixes/color-dots-c-scope-2026-06-30/verify3.cjs
@@ -0,0 +1,39 @@
+const { chromium } = require('/Users/stevestudio2/Projects/Designer-Wallcoverings/node_modules/playwright');
+(async () => {
+const themes = [
+ { label:'DEV-FIXED', id:144105013299 },
+ { label:'LIVE-BUGGY', id:144076931123 },
+];
+const handle='dwtt-80064-designer-wallcoverings-los-angeles';
+const browser = await chromium.launch();
+const out=[];
+for (const t of themes) {
+ const ctx = await browser.newContext();
+ const seed = await ctx.newPage();
+ await seed.goto(`https://www.designerwallcoverings.com/?preview_theme_id=${t.id}`, { waitUntil:'domcontentloaded', timeout:60000 });
+ await seed.waitForTimeout(1200); await seed.close();
+ const page = await ctx.newPage();
+ const perr=[]; page.on('pageerror',e=>perr.push(String(e)));
+ await page.goto(`https://www.designerwallcoverings.com/products/${handle}?preview_theme_id=${t.id}`, { waitUntil:'domcontentloaded', timeout:60000 });
+ await page.waitForTimeout(3500);
+ // select roll variant
+ await page.evaluate(()=>{const s=document.querySelector('select.single-option-selector, select.product-select'); if(s){for(const o of s.options){if(!/sample/i.test(o.text)){s.value=o.value;s.dispatchEvent(new Event('change',{bubbles:true}));break;}}}});
+ await page.waitForTimeout(1200);
+ const themeMarker = (await page.content()).includes('function makeDot(hex, name, pct)')?'DEV-FIXED':(await page.content()).includes('function makeDot(hex, name)')?'OLD':'?';
+ const cErr = perr.filter(e=>/c is not defined/.test(e)).length;
+ // behavior 2: type 3 into qty, blur, read value
+ const typed = await page.evaluate(async ()=>{
+ const inp = document.querySelector('.mm_quantity:not(.hidden) input[name="quantity"]') || document.querySelector('input[name="quantity"]');
+ if(!inp) return 'no-input';
+ inp.focus(); inp.value='3'; inp.dispatchEvent(new Event('input',{bubbles:true})); inp.dispatchEvent(new Event('change',{bubbles:true})); inp.blur();
+ await new Promise(r=>setTimeout(r,700));
+ return inp.value;
+ });
+ // read hquantity + step/min after
+ const meta = await page.evaluate(()=>{const i=document.querySelector('.mm_quantity:not(.hidden) input[name="quantity"]');const h=document.querySelector('.mm_quantity:not(.hidden) .hquantity');return {qty:i?i.value:null,min:i?i.getAttribute('min'):null,step:i?i.getAttribute('step'):null,hq:h?h.value:(h?h.getAttribute('value'):null)};});
+ out.push({ theme:t.label, themeMarker, cErr, typedThenBlur: typed, meta });
+ await ctx.close();
+}
+await browser.close();
+console.log(JSON.stringify(out,null,2));
+})();
← 87ce255a auto-save: 2026-06-30T19:42:55 (5 files) — pending-approval/
·
back to Designer Wallcoverings
·
auto-save: 2026-06-30T20:13:04 (3 files) — pending-approval/ 67ffd784 →