[object Object]

← 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

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 →