[object Object]

← back to Dw Validator Debug TK11314

Sync 5 _cw* theme.liquid mirrors to v2 variant-button block (matches deployed dev theme) + add mirror-sync script

c33264743c651908cfba5ffc613c30e2542eb5ea · 2026-06-21 19:35:22 -0700 · Steve Abrams

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

Files touched

Diff

commit c33264743c651908cfba5ffc613c30e2542eb5ea
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Sun Jun 21 19:35:22 2026 -0700

    Sync 5 _cw* theme.liquid mirrors to v2 variant-button block (matches deployed dev theme) + add mirror-sync script
    
    Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---
 shopify/_cwFIX/layout/theme.liquid    |  76 +++++++++++++++++---------
 shopify/_cwLIVE/layout/theme.liquid   |  76 +++++++++++++++++---------
 shopify/_cwLIVE2/layout/theme.liquid  |  76 +++++++++++++++++---------
 shopify/_cwLIVE3/layout/theme.liquid  |  76 +++++++++++++++++---------
 shopify/_cwVERIFY/layout/theme.liquid |  76 +++++++++++++++++---------
 shopify/sync-mirrors-variant-ux.py    | 100 ++++++++++++++++++++++++++++++++++
 6 files changed, 345 insertions(+), 135 deletions(-)

diff --git a/shopify/_cwFIX/layout/theme.liquid b/shopify/_cwFIX/layout/theme.liquid
index 24b6cb4a..c9b1ab8d 100644
--- a/shopify/_cwFIX/layout/theme.liquid
+++ b/shopify/_cwFIX/layout/theme.liquid
@@ -515,7 +515,7 @@
 <!-- /DW -->
 
 {% if template contains 'product' %}
-<!-- DW: variant option buttons — replace native dropdown with side-by-side name-only buttons (2026-06-21) -->
+<!-- DW: variant option buttons v2 — side-by-side name-only buttons; Sample button on every SKU (2026-06-21) -->
 <style>
   .dw-variant-btns{display:flex;gap:10px;margin:10px 0 4px;flex-wrap:wrap}
   .dw-variant-btns button{flex:1 1 0;min-width:120px;padding:12px 14px;border:1px solid #111;
@@ -528,36 +528,58 @@
 </style>
 <script>
 (function(){
-  function build(){
-    var sels=document.querySelectorAll('.single-option-selector,[id^="single-option-"]');
-    Array.prototype.forEach.call(sels,function(sel){
-      if(sel.dataset.dwBtnDone) return;
-      if(!sel.options||sel.options.length<2){ sel.dataset.dwBtnDone='1'; return; }
-      sel.dataset.dwBtnDone='1';
+  function nameOnly(t){ return (t||'').split(/\s+[-–]\s+\$/)[0].replace(/\s+/g,' ').trim(); }
+  function press(wrap,btn){ Array.prototype.forEach.call(wrap.querySelectorAll('button'),function(x){x.setAttribute('aria-pressed', x===btn?'true':'false');}); }
+  function hostOf(el){ return el.closest('.select-wrapper')||el.closest('.selector-wrapper')||el.parentElement; }
+  function mk(sel, onClick){
+    if(sel.dataset.dwBtnDone||!sel.options||sel.options.length<2) return false;
+    sel.dataset.dwBtnDone='1';
+    var wrap=document.createElement('div'); wrap.className='dw-variant-btns';
+    Array.prototype.forEach.call(sel.options,function(opt){
+      var b=document.createElement('button'); b.type='button';
+      b.textContent=nameOnly(opt.text); b.setAttribute('data-value',opt.value);
+      b.setAttribute('aria-pressed', opt.selected?'true':'false');
+      b.addEventListener('click',function(){ onClick(sel,opt); press(wrap,b); });
+      wrap.appendChild(b);
+    });
+    var host=hostOf(sel); host.classList.add('dw-hide-native'); host.parentElement.insertBefore(wrap,host);
+    return true;
+  }
+  function isSampleVar(v){ return /(^|[-_ ])sample\b/i.test(v.sku||'') || /sample/i.test(v.title||''); }
+  function fallbackFromJson(){
+    if(window.__dwVbDone||document.querySelector('.dw-variant-btns')) return; window.__dwVbDone=1;
+    fetch(location.pathname.split('?')[0]+'.js').then(function(r){return r.json();}).then(function(p){
+      if(document.querySelector('.dw-variant-btns')||!p||!p.variants||!p.variants.length) return;
+      var idSel=document.querySelector('select[name="id"],[id^="product-select-"]');
+      var atc=document.querySelector('button[name="add"],[type="submit"][name="add"]')||
+              [].slice.call(document.querySelectorAll('button,input[type=submit]')).filter(function(b){return /add to cart/i.test(b.textContent||b.value||'');})[0];
+      var qty=document.querySelector('input[name="quantity"],input[type="number"]');
+      var anchor=(idSel&&hostOf(idSel))|| (qty&&(qty.closest('.product-form__input,.selector-wrapper,div')||qty)) || atc || document.querySelector('form[action*="/cart"]');
+      if(!anchor) return;
       var wrap=document.createElement('div'); wrap.className='dw-variant-btns';
-      Array.prototype.forEach.call(sel.options,function(opt){
-        var b=document.createElement('button');
-        b.type='button';
-        b.textContent=(opt.text||'').trim();          /* NAME ONLY, dynamic per product */
-        b.setAttribute('data-value',opt.value);
-        b.setAttribute('aria-pressed', opt.selected?'true':'false');
-        b.addEventListener('click',function(){
-          sel.value=opt.value;
-          sel.dispatchEvent(new Event('change',{bubbles:true}));
-          Array.prototype.forEach.call(wrap.querySelectorAll('button'),function(x){
-            x.setAttribute('aria-pressed', x===b?'true':'false');
-          });
-        });
+      p.variants.forEach(function(v){
+        var b=document.createElement('button'); b.type='button';
+        b.textContent=isSampleVar(v)?'Sample':nameOnly(v.title||v.name||'');
+        b.setAttribute('aria-pressed', String(p.variants.length===1));
+        b.addEventListener('click',function(){ var u=new URL(location.href); u.searchParams.set('variant',v.id); location.href=u.toString(); });
         wrap.appendChild(b);
       });
-      var host=sel.closest('.select-wrapper')||sel.closest('.selector-wrapper')||sel.parentElement;
-      host.classList.add('dw-hide-native');
-      host.parentElement.insertBefore(wrap,host);
-    });
+      if(idSel) hostOf(idSel).classList.add('dw-hide-native');
+      if(anchor.parentElement) anchor.parentElement.insertBefore(wrap,anchor); else anchor.appendChild(wrap);
+    }).catch(function(){});
+  }
+  function build(){
+    if(location.pathname.indexOf('/products/')===-1) return;
+    var rows=document.querySelectorAll('.single-option-selector,[id^="single-option-"]');
+    if(rows.length){ Array.prototype.forEach.call(rows,function(sel){ mk(sel,function(s,opt){ s.value=opt.value; s.dispatchEvent(new Event('change',{bubbles:true})); }); }); }
+    if(!document.querySelector('.dw-variant-btns')){
+      var idSel=document.querySelector('select[name="id"],[id^="product-select-"]');
+      if(idSel) mk(idSel,function(s,opt){ s.value=opt.value; s.dispatchEvent(new Event('change',{bubbles:true}));
+        try{ var u=new URL(location.href); u.searchParams.set('variant',opt.value); history.replaceState({},'',u); }catch(e){} });
+    }
   }
-  function init(){ build(); setTimeout(build,400); setTimeout(build,1200); }
-  if(document.readyState!=='loading') init();
-  else document.addEventListener('DOMContentLoaded',init);
+  function init(){ build(); setTimeout(build,400); setTimeout(function(){ build(); fallbackFromJson(); },1200); }
+  if(document.readyState!=='loading') init(); else document.addEventListener('DOMContentLoaded',init);
 })();
 </script>
 <!-- /DW variant buttons -->
diff --git a/shopify/_cwLIVE/layout/theme.liquid b/shopify/_cwLIVE/layout/theme.liquid
index 274f332b..fe72ea3a 100644
--- a/shopify/_cwLIVE/layout/theme.liquid
+++ b/shopify/_cwLIVE/layout/theme.liquid
@@ -515,7 +515,7 @@
 <!-- /DW -->
 
 {% if template contains 'product' %}
-<!-- DW: variant option buttons — replace native dropdown with side-by-side name-only buttons (2026-06-21) -->
+<!-- DW: variant option buttons v2 — side-by-side name-only buttons; Sample button on every SKU (2026-06-21) -->
 <style>
   .dw-variant-btns{display:flex;gap:10px;margin:10px 0 4px;flex-wrap:wrap}
   .dw-variant-btns button{flex:1 1 0;min-width:120px;padding:12px 14px;border:1px solid #111;
@@ -528,36 +528,58 @@
 </style>
 <script>
 (function(){
-  function build(){
-    var sels=document.querySelectorAll('.single-option-selector,[id^="single-option-"]');
-    Array.prototype.forEach.call(sels,function(sel){
-      if(sel.dataset.dwBtnDone) return;
-      if(!sel.options||sel.options.length<2){ sel.dataset.dwBtnDone='1'; return; }
-      sel.dataset.dwBtnDone='1';
+  function nameOnly(t){ return (t||'').split(/\s+[-–]\s+\$/)[0].replace(/\s+/g,' ').trim(); }
+  function press(wrap,btn){ Array.prototype.forEach.call(wrap.querySelectorAll('button'),function(x){x.setAttribute('aria-pressed', x===btn?'true':'false');}); }
+  function hostOf(el){ return el.closest('.select-wrapper')||el.closest('.selector-wrapper')||el.parentElement; }
+  function mk(sel, onClick){
+    if(sel.dataset.dwBtnDone||!sel.options||sel.options.length<2) return false;
+    sel.dataset.dwBtnDone='1';
+    var wrap=document.createElement('div'); wrap.className='dw-variant-btns';
+    Array.prototype.forEach.call(sel.options,function(opt){
+      var b=document.createElement('button'); b.type='button';
+      b.textContent=nameOnly(opt.text); b.setAttribute('data-value',opt.value);
+      b.setAttribute('aria-pressed', opt.selected?'true':'false');
+      b.addEventListener('click',function(){ onClick(sel,opt); press(wrap,b); });
+      wrap.appendChild(b);
+    });
+    var host=hostOf(sel); host.classList.add('dw-hide-native'); host.parentElement.insertBefore(wrap,host);
+    return true;
+  }
+  function isSampleVar(v){ return /(^|[-_ ])sample\b/i.test(v.sku||'') || /sample/i.test(v.title||''); }
+  function fallbackFromJson(){
+    if(window.__dwVbDone||document.querySelector('.dw-variant-btns')) return; window.__dwVbDone=1;
+    fetch(location.pathname.split('?')[0]+'.js').then(function(r){return r.json();}).then(function(p){
+      if(document.querySelector('.dw-variant-btns')||!p||!p.variants||!p.variants.length) return;
+      var idSel=document.querySelector('select[name="id"],[id^="product-select-"]');
+      var atc=document.querySelector('button[name="add"],[type="submit"][name="add"]')||
+              [].slice.call(document.querySelectorAll('button,input[type=submit]')).filter(function(b){return /add to cart/i.test(b.textContent||b.value||'');})[0];
+      var qty=document.querySelector('input[name="quantity"],input[type="number"]');
+      var anchor=(idSel&&hostOf(idSel))|| (qty&&(qty.closest('.product-form__input,.selector-wrapper,div')||qty)) || atc || document.querySelector('form[action*="/cart"]');
+      if(!anchor) return;
       var wrap=document.createElement('div'); wrap.className='dw-variant-btns';
-      Array.prototype.forEach.call(sel.options,function(opt){
-        var b=document.createElement('button');
-        b.type='button';
-        b.textContent=(opt.text||'').trim();          /* NAME ONLY, dynamic per product */
-        b.setAttribute('data-value',opt.value);
-        b.setAttribute('aria-pressed', opt.selected?'true':'false');
-        b.addEventListener('click',function(){
-          sel.value=opt.value;
-          sel.dispatchEvent(new Event('change',{bubbles:true}));
-          Array.prototype.forEach.call(wrap.querySelectorAll('button'),function(x){
-            x.setAttribute('aria-pressed', x===b?'true':'false');
-          });
-        });
+      p.variants.forEach(function(v){
+        var b=document.createElement('button'); b.type='button';
+        b.textContent=isSampleVar(v)?'Sample':nameOnly(v.title||v.name||'');
+        b.setAttribute('aria-pressed', String(p.variants.length===1));
+        b.addEventListener('click',function(){ var u=new URL(location.href); u.searchParams.set('variant',v.id); location.href=u.toString(); });
         wrap.appendChild(b);
       });
-      var host=sel.closest('.select-wrapper')||sel.closest('.selector-wrapper')||sel.parentElement;
-      host.classList.add('dw-hide-native');
-      host.parentElement.insertBefore(wrap,host);
-    });
+      if(idSel) hostOf(idSel).classList.add('dw-hide-native');
+      if(anchor.parentElement) anchor.parentElement.insertBefore(wrap,anchor); else anchor.appendChild(wrap);
+    }).catch(function(){});
+  }
+  function build(){
+    if(location.pathname.indexOf('/products/')===-1) return;
+    var rows=document.querySelectorAll('.single-option-selector,[id^="single-option-"]');
+    if(rows.length){ Array.prototype.forEach.call(rows,function(sel){ mk(sel,function(s,opt){ s.value=opt.value; s.dispatchEvent(new Event('change',{bubbles:true})); }); }); }
+    if(!document.querySelector('.dw-variant-btns')){
+      var idSel=document.querySelector('select[name="id"],[id^="product-select-"]');
+      if(idSel) mk(idSel,function(s,opt){ s.value=opt.value; s.dispatchEvent(new Event('change',{bubbles:true}));
+        try{ var u=new URL(location.href); u.searchParams.set('variant',opt.value); history.replaceState({},'',u); }catch(e){} });
+    }
   }
-  function init(){ build(); setTimeout(build,400); setTimeout(build,1200); }
-  if(document.readyState!=='loading') init();
-  else document.addEventListener('DOMContentLoaded',init);
+  function init(){ build(); setTimeout(build,400); setTimeout(function(){ build(); fallbackFromJson(); },1200); }
+  if(document.readyState!=='loading') init(); else document.addEventListener('DOMContentLoaded',init);
 })();
 </script>
 <!-- /DW variant buttons -->
diff --git a/shopify/_cwLIVE2/layout/theme.liquid b/shopify/_cwLIVE2/layout/theme.liquid
index 8bd96f57..93f20a49 100644
--- a/shopify/_cwLIVE2/layout/theme.liquid
+++ b/shopify/_cwLIVE2/layout/theme.liquid
@@ -515,7 +515,7 @@
 <!-- /DW -->
 
 {% if template contains 'product' %}
-<!-- DW: variant option buttons — replace native dropdown with side-by-side name-only buttons (2026-06-21) -->
+<!-- DW: variant option buttons v2 — side-by-side name-only buttons; Sample button on every SKU (2026-06-21) -->
 <style>
   .dw-variant-btns{display:flex;gap:10px;margin:10px 0 4px;flex-wrap:wrap}
   .dw-variant-btns button{flex:1 1 0;min-width:120px;padding:12px 14px;border:1px solid #111;
@@ -528,36 +528,58 @@
 </style>
 <script>
 (function(){
-  function build(){
-    var sels=document.querySelectorAll('.single-option-selector,[id^="single-option-"]');
-    Array.prototype.forEach.call(sels,function(sel){
-      if(sel.dataset.dwBtnDone) return;
-      if(!sel.options||sel.options.length<2){ sel.dataset.dwBtnDone='1'; return; }
-      sel.dataset.dwBtnDone='1';
+  function nameOnly(t){ return (t||'').split(/\s+[-–]\s+\$/)[0].replace(/\s+/g,' ').trim(); }
+  function press(wrap,btn){ Array.prototype.forEach.call(wrap.querySelectorAll('button'),function(x){x.setAttribute('aria-pressed', x===btn?'true':'false');}); }
+  function hostOf(el){ return el.closest('.select-wrapper')||el.closest('.selector-wrapper')||el.parentElement; }
+  function mk(sel, onClick){
+    if(sel.dataset.dwBtnDone||!sel.options||sel.options.length<2) return false;
+    sel.dataset.dwBtnDone='1';
+    var wrap=document.createElement('div'); wrap.className='dw-variant-btns';
+    Array.prototype.forEach.call(sel.options,function(opt){
+      var b=document.createElement('button'); b.type='button';
+      b.textContent=nameOnly(opt.text); b.setAttribute('data-value',opt.value);
+      b.setAttribute('aria-pressed', opt.selected?'true':'false');
+      b.addEventListener('click',function(){ onClick(sel,opt); press(wrap,b); });
+      wrap.appendChild(b);
+    });
+    var host=hostOf(sel); host.classList.add('dw-hide-native'); host.parentElement.insertBefore(wrap,host);
+    return true;
+  }
+  function isSampleVar(v){ return /(^|[-_ ])sample\b/i.test(v.sku||'') || /sample/i.test(v.title||''); }
+  function fallbackFromJson(){
+    if(window.__dwVbDone||document.querySelector('.dw-variant-btns')) return; window.__dwVbDone=1;
+    fetch(location.pathname.split('?')[0]+'.js').then(function(r){return r.json();}).then(function(p){
+      if(document.querySelector('.dw-variant-btns')||!p||!p.variants||!p.variants.length) return;
+      var idSel=document.querySelector('select[name="id"],[id^="product-select-"]');
+      var atc=document.querySelector('button[name="add"],[type="submit"][name="add"]')||
+              [].slice.call(document.querySelectorAll('button,input[type=submit]')).filter(function(b){return /add to cart/i.test(b.textContent||b.value||'');})[0];
+      var qty=document.querySelector('input[name="quantity"],input[type="number"]');
+      var anchor=(idSel&&hostOf(idSel))|| (qty&&(qty.closest('.product-form__input,.selector-wrapper,div')||qty)) || atc || document.querySelector('form[action*="/cart"]');
+      if(!anchor) return;
       var wrap=document.createElement('div'); wrap.className='dw-variant-btns';
-      Array.prototype.forEach.call(sel.options,function(opt){
-        var b=document.createElement('button');
-        b.type='button';
-        b.textContent=(opt.text||'').trim();          /* NAME ONLY, dynamic per product */
-        b.setAttribute('data-value',opt.value);
-        b.setAttribute('aria-pressed', opt.selected?'true':'false');
-        b.addEventListener('click',function(){
-          sel.value=opt.value;
-          sel.dispatchEvent(new Event('change',{bubbles:true}));
-          Array.prototype.forEach.call(wrap.querySelectorAll('button'),function(x){
-            x.setAttribute('aria-pressed', x===b?'true':'false');
-          });
-        });
+      p.variants.forEach(function(v){
+        var b=document.createElement('button'); b.type='button';
+        b.textContent=isSampleVar(v)?'Sample':nameOnly(v.title||v.name||'');
+        b.setAttribute('aria-pressed', String(p.variants.length===1));
+        b.addEventListener('click',function(){ var u=new URL(location.href); u.searchParams.set('variant',v.id); location.href=u.toString(); });
         wrap.appendChild(b);
       });
-      var host=sel.closest('.select-wrapper')||sel.closest('.selector-wrapper')||sel.parentElement;
-      host.classList.add('dw-hide-native');
-      host.parentElement.insertBefore(wrap,host);
-    });
+      if(idSel) hostOf(idSel).classList.add('dw-hide-native');
+      if(anchor.parentElement) anchor.parentElement.insertBefore(wrap,anchor); else anchor.appendChild(wrap);
+    }).catch(function(){});
+  }
+  function build(){
+    if(location.pathname.indexOf('/products/')===-1) return;
+    var rows=document.querySelectorAll('.single-option-selector,[id^="single-option-"]');
+    if(rows.length){ Array.prototype.forEach.call(rows,function(sel){ mk(sel,function(s,opt){ s.value=opt.value; s.dispatchEvent(new Event('change',{bubbles:true})); }); }); }
+    if(!document.querySelector('.dw-variant-btns')){
+      var idSel=document.querySelector('select[name="id"],[id^="product-select-"]');
+      if(idSel) mk(idSel,function(s,opt){ s.value=opt.value; s.dispatchEvent(new Event('change',{bubbles:true}));
+        try{ var u=new URL(location.href); u.searchParams.set('variant',opt.value); history.replaceState({},'',u); }catch(e){} });
+    }
   }
-  function init(){ build(); setTimeout(build,400); setTimeout(build,1200); }
-  if(document.readyState!=='loading') init();
-  else document.addEventListener('DOMContentLoaded',init);
+  function init(){ build(); setTimeout(build,400); setTimeout(function(){ build(); fallbackFromJson(); },1200); }
+  if(document.readyState!=='loading') init(); else document.addEventListener('DOMContentLoaded',init);
 })();
 </script>
 <!-- /DW variant buttons -->
diff --git a/shopify/_cwLIVE3/layout/theme.liquid b/shopify/_cwLIVE3/layout/theme.liquid
index 4f1d09a0..15f2dd94 100644
--- a/shopify/_cwLIVE3/layout/theme.liquid
+++ b/shopify/_cwLIVE3/layout/theme.liquid
@@ -515,7 +515,7 @@
 <!-- /DW -->
 
 {% if template contains 'product' %}
-<!-- DW: variant option buttons — replace native dropdown with side-by-side name-only buttons (2026-06-21) -->
+<!-- DW: variant option buttons v2 — side-by-side name-only buttons; Sample button on every SKU (2026-06-21) -->
 <style>
   .dw-variant-btns{display:flex;gap:10px;margin:10px 0 4px;flex-wrap:wrap}
   .dw-variant-btns button{flex:1 1 0;min-width:120px;padding:12px 14px;border:1px solid #111;
@@ -528,36 +528,58 @@
 </style>
 <script>
 (function(){
-  function build(){
-    var sels=document.querySelectorAll('.single-option-selector,[id^="single-option-"]');
-    Array.prototype.forEach.call(sels,function(sel){
-      if(sel.dataset.dwBtnDone) return;
-      if(!sel.options||sel.options.length<2){ sel.dataset.dwBtnDone='1'; return; }
-      sel.dataset.dwBtnDone='1';
+  function nameOnly(t){ return (t||'').split(/\s+[-–]\s+\$/)[0].replace(/\s+/g,' ').trim(); }
+  function press(wrap,btn){ Array.prototype.forEach.call(wrap.querySelectorAll('button'),function(x){x.setAttribute('aria-pressed', x===btn?'true':'false');}); }
+  function hostOf(el){ return el.closest('.select-wrapper')||el.closest('.selector-wrapper')||el.parentElement; }
+  function mk(sel, onClick){
+    if(sel.dataset.dwBtnDone||!sel.options||sel.options.length<2) return false;
+    sel.dataset.dwBtnDone='1';
+    var wrap=document.createElement('div'); wrap.className='dw-variant-btns';
+    Array.prototype.forEach.call(sel.options,function(opt){
+      var b=document.createElement('button'); b.type='button';
+      b.textContent=nameOnly(opt.text); b.setAttribute('data-value',opt.value);
+      b.setAttribute('aria-pressed', opt.selected?'true':'false');
+      b.addEventListener('click',function(){ onClick(sel,opt); press(wrap,b); });
+      wrap.appendChild(b);
+    });
+    var host=hostOf(sel); host.classList.add('dw-hide-native'); host.parentElement.insertBefore(wrap,host);
+    return true;
+  }
+  function isSampleVar(v){ return /(^|[-_ ])sample\b/i.test(v.sku||'') || /sample/i.test(v.title||''); }
+  function fallbackFromJson(){
+    if(window.__dwVbDone||document.querySelector('.dw-variant-btns')) return; window.__dwVbDone=1;
+    fetch(location.pathname.split('?')[0]+'.js').then(function(r){return r.json();}).then(function(p){
+      if(document.querySelector('.dw-variant-btns')||!p||!p.variants||!p.variants.length) return;
+      var idSel=document.querySelector('select[name="id"],[id^="product-select-"]');
+      var atc=document.querySelector('button[name="add"],[type="submit"][name="add"]')||
+              [].slice.call(document.querySelectorAll('button,input[type=submit]')).filter(function(b){return /add to cart/i.test(b.textContent||b.value||'');})[0];
+      var qty=document.querySelector('input[name="quantity"],input[type="number"]');
+      var anchor=(idSel&&hostOf(idSel))|| (qty&&(qty.closest('.product-form__input,.selector-wrapper,div')||qty)) || atc || document.querySelector('form[action*="/cart"]');
+      if(!anchor) return;
       var wrap=document.createElement('div'); wrap.className='dw-variant-btns';
-      Array.prototype.forEach.call(sel.options,function(opt){
-        var b=document.createElement('button');
-        b.type='button';
-        b.textContent=(opt.text||'').trim();          /* NAME ONLY, dynamic per product */
-        b.setAttribute('data-value',opt.value);
-        b.setAttribute('aria-pressed', opt.selected?'true':'false');
-        b.addEventListener('click',function(){
-          sel.value=opt.value;
-          sel.dispatchEvent(new Event('change',{bubbles:true}));
-          Array.prototype.forEach.call(wrap.querySelectorAll('button'),function(x){
-            x.setAttribute('aria-pressed', x===b?'true':'false');
-          });
-        });
+      p.variants.forEach(function(v){
+        var b=document.createElement('button'); b.type='button';
+        b.textContent=isSampleVar(v)?'Sample':nameOnly(v.title||v.name||'');
+        b.setAttribute('aria-pressed', String(p.variants.length===1));
+        b.addEventListener('click',function(){ var u=new URL(location.href); u.searchParams.set('variant',v.id); location.href=u.toString(); });
         wrap.appendChild(b);
       });
-      var host=sel.closest('.select-wrapper')||sel.closest('.selector-wrapper')||sel.parentElement;
-      host.classList.add('dw-hide-native');
-      host.parentElement.insertBefore(wrap,host);
-    });
+      if(idSel) hostOf(idSel).classList.add('dw-hide-native');
+      if(anchor.parentElement) anchor.parentElement.insertBefore(wrap,anchor); else anchor.appendChild(wrap);
+    }).catch(function(){});
+  }
+  function build(){
+    if(location.pathname.indexOf('/products/')===-1) return;
+    var rows=document.querySelectorAll('.single-option-selector,[id^="single-option-"]');
+    if(rows.length){ Array.prototype.forEach.call(rows,function(sel){ mk(sel,function(s,opt){ s.value=opt.value; s.dispatchEvent(new Event('change',{bubbles:true})); }); }); }
+    if(!document.querySelector('.dw-variant-btns')){
+      var idSel=document.querySelector('select[name="id"],[id^="product-select-"]');
+      if(idSel) mk(idSel,function(s,opt){ s.value=opt.value; s.dispatchEvent(new Event('change',{bubbles:true}));
+        try{ var u=new URL(location.href); u.searchParams.set('variant',opt.value); history.replaceState({},'',u); }catch(e){} });
+    }
   }
-  function init(){ build(); setTimeout(build,400); setTimeout(build,1200); }
-  if(document.readyState!=='loading') init();
-  else document.addEventListener('DOMContentLoaded',init);
+  function init(){ build(); setTimeout(build,400); setTimeout(function(){ build(); fallbackFromJson(); },1200); }
+  if(document.readyState!=='loading') init(); else document.addEventListener('DOMContentLoaded',init);
 })();
 </script>
 <!-- /DW variant buttons -->
diff --git a/shopify/_cwVERIFY/layout/theme.liquid b/shopify/_cwVERIFY/layout/theme.liquid
index 24b6cb4a..c9b1ab8d 100644
--- a/shopify/_cwVERIFY/layout/theme.liquid
+++ b/shopify/_cwVERIFY/layout/theme.liquid
@@ -515,7 +515,7 @@
 <!-- /DW -->
 
 {% if template contains 'product' %}
-<!-- DW: variant option buttons — replace native dropdown with side-by-side name-only buttons (2026-06-21) -->
+<!-- DW: variant option buttons v2 — side-by-side name-only buttons; Sample button on every SKU (2026-06-21) -->
 <style>
   .dw-variant-btns{display:flex;gap:10px;margin:10px 0 4px;flex-wrap:wrap}
   .dw-variant-btns button{flex:1 1 0;min-width:120px;padding:12px 14px;border:1px solid #111;
@@ -528,36 +528,58 @@
 </style>
 <script>
 (function(){
-  function build(){
-    var sels=document.querySelectorAll('.single-option-selector,[id^="single-option-"]');
-    Array.prototype.forEach.call(sels,function(sel){
-      if(sel.dataset.dwBtnDone) return;
-      if(!sel.options||sel.options.length<2){ sel.dataset.dwBtnDone='1'; return; }
-      sel.dataset.dwBtnDone='1';
+  function nameOnly(t){ return (t||'').split(/\s+[-–]\s+\$/)[0].replace(/\s+/g,' ').trim(); }
+  function press(wrap,btn){ Array.prototype.forEach.call(wrap.querySelectorAll('button'),function(x){x.setAttribute('aria-pressed', x===btn?'true':'false');}); }
+  function hostOf(el){ return el.closest('.select-wrapper')||el.closest('.selector-wrapper')||el.parentElement; }
+  function mk(sel, onClick){
+    if(sel.dataset.dwBtnDone||!sel.options||sel.options.length<2) return false;
+    sel.dataset.dwBtnDone='1';
+    var wrap=document.createElement('div'); wrap.className='dw-variant-btns';
+    Array.prototype.forEach.call(sel.options,function(opt){
+      var b=document.createElement('button'); b.type='button';
+      b.textContent=nameOnly(opt.text); b.setAttribute('data-value',opt.value);
+      b.setAttribute('aria-pressed', opt.selected?'true':'false');
+      b.addEventListener('click',function(){ onClick(sel,opt); press(wrap,b); });
+      wrap.appendChild(b);
+    });
+    var host=hostOf(sel); host.classList.add('dw-hide-native'); host.parentElement.insertBefore(wrap,host);
+    return true;
+  }
+  function isSampleVar(v){ return /(^|[-_ ])sample\b/i.test(v.sku||'') || /sample/i.test(v.title||''); }
+  function fallbackFromJson(){
+    if(window.__dwVbDone||document.querySelector('.dw-variant-btns')) return; window.__dwVbDone=1;
+    fetch(location.pathname.split('?')[0]+'.js').then(function(r){return r.json();}).then(function(p){
+      if(document.querySelector('.dw-variant-btns')||!p||!p.variants||!p.variants.length) return;
+      var idSel=document.querySelector('select[name="id"],[id^="product-select-"]');
+      var atc=document.querySelector('button[name="add"],[type="submit"][name="add"]')||
+              [].slice.call(document.querySelectorAll('button,input[type=submit]')).filter(function(b){return /add to cart/i.test(b.textContent||b.value||'');})[0];
+      var qty=document.querySelector('input[name="quantity"],input[type="number"]');
+      var anchor=(idSel&&hostOf(idSel))|| (qty&&(qty.closest('.product-form__input,.selector-wrapper,div')||qty)) || atc || document.querySelector('form[action*="/cart"]');
+      if(!anchor) return;
       var wrap=document.createElement('div'); wrap.className='dw-variant-btns';
-      Array.prototype.forEach.call(sel.options,function(opt){
-        var b=document.createElement('button');
-        b.type='button';
-        b.textContent=(opt.text||'').trim();          /* NAME ONLY, dynamic per product */
-        b.setAttribute('data-value',opt.value);
-        b.setAttribute('aria-pressed', opt.selected?'true':'false');
-        b.addEventListener('click',function(){
-          sel.value=opt.value;
-          sel.dispatchEvent(new Event('change',{bubbles:true}));
-          Array.prototype.forEach.call(wrap.querySelectorAll('button'),function(x){
-            x.setAttribute('aria-pressed', x===b?'true':'false');
-          });
-        });
+      p.variants.forEach(function(v){
+        var b=document.createElement('button'); b.type='button';
+        b.textContent=isSampleVar(v)?'Sample':nameOnly(v.title||v.name||'');
+        b.setAttribute('aria-pressed', String(p.variants.length===1));
+        b.addEventListener('click',function(){ var u=new URL(location.href); u.searchParams.set('variant',v.id); location.href=u.toString(); });
         wrap.appendChild(b);
       });
-      var host=sel.closest('.select-wrapper')||sel.closest('.selector-wrapper')||sel.parentElement;
-      host.classList.add('dw-hide-native');
-      host.parentElement.insertBefore(wrap,host);
-    });
+      if(idSel) hostOf(idSel).classList.add('dw-hide-native');
+      if(anchor.parentElement) anchor.parentElement.insertBefore(wrap,anchor); else anchor.appendChild(wrap);
+    }).catch(function(){});
+  }
+  function build(){
+    if(location.pathname.indexOf('/products/')===-1) return;
+    var rows=document.querySelectorAll('.single-option-selector,[id^="single-option-"]');
+    if(rows.length){ Array.prototype.forEach.call(rows,function(sel){ mk(sel,function(s,opt){ s.value=opt.value; s.dispatchEvent(new Event('change',{bubbles:true})); }); }); }
+    if(!document.querySelector('.dw-variant-btns')){
+      var idSel=document.querySelector('select[name="id"],[id^="product-select-"]');
+      if(idSel) mk(idSel,function(s,opt){ s.value=opt.value; s.dispatchEvent(new Event('change',{bubbles:true}));
+        try{ var u=new URL(location.href); u.searchParams.set('variant',opt.value); history.replaceState({},'',u); }catch(e){} });
+    }
   }
-  function init(){ build(); setTimeout(build,400); setTimeout(build,1200); }
-  if(document.readyState!=='loading') init();
-  else document.addEventListener('DOMContentLoaded',init);
+  function init(){ build(); setTimeout(build,400); setTimeout(function(){ build(); fallbackFromJson(); },1200); }
+  if(document.readyState!=='loading') init(); else document.addEventListener('DOMContentLoaded',init);
 })();
 </script>
 <!-- /DW variant buttons -->
diff --git a/shopify/sync-mirrors-variant-ux.py b/shopify/sync-mirrors-variant-ux.py
new file mode 100644
index 00000000..9cd26534
--- /dev/null
+++ b/shopify/sync-mirrors-variant-ux.py
@@ -0,0 +1,100 @@
+#!/usr/bin/env python3
+# Sync the 5 local _cw* theme.liquid mirrors to the v2 variant-button block
+# (matches what push-variant-ux-to-dev-theme.sh deploys to the dev theme).
+import re, sys, pathlib
+
+MIRRORS = ["_cwLIVE", "_cwLIVE2", "_cwLIVE3", "_cwFIX", "_cwVERIFY"]
+BASE = pathlib.Path(__file__).parent
+
+BLOCK = r"""
+{% if template contains 'product' %}
+<!-- DW: variant option buttons v2 — side-by-side name-only buttons; Sample button on every SKU (2026-06-21) -->
+<style>
+  .dw-variant-btns{display:flex;gap:10px;margin:10px 0 4px;flex-wrap:wrap}
+  .dw-variant-btns button{flex:1 1 0;min-width:120px;padding:12px 14px;border:1px solid #111;
+    background:#fff;color:#111;font:inherit;letter-spacing:.04em;text-transform:uppercase;
+    font-size:12px;cursor:pointer;border-radius:2px;transition:background .12s,color .12s}
+  .dw-variant-btns button:hover{background:#f2f2f2}
+  .dw-variant-btns button[aria-pressed="true"],
+  .dw-variant-btns button[aria-pressed="true"]:hover{background:#111;color:#fff}
+  .dw-hide-native{display:none !important}
+</style>
+<script>
+(function(){
+  function nameOnly(t){ return (t||'').split(/\s+[-–]\s+\$/)[0].replace(/\s+/g,' ').trim(); }
+  function press(wrap,btn){ Array.prototype.forEach.call(wrap.querySelectorAll('button'),function(x){x.setAttribute('aria-pressed', x===btn?'true':'false');}); }
+  function hostOf(el){ return el.closest('.select-wrapper')||el.closest('.selector-wrapper')||el.parentElement; }
+  function mk(sel, onClick){
+    if(sel.dataset.dwBtnDone||!sel.options||sel.options.length<2) return false;
+    sel.dataset.dwBtnDone='1';
+    var wrap=document.createElement('div'); wrap.className='dw-variant-btns';
+    Array.prototype.forEach.call(sel.options,function(opt){
+      var b=document.createElement('button'); b.type='button';
+      b.textContent=nameOnly(opt.text); b.setAttribute('data-value',opt.value);
+      b.setAttribute('aria-pressed', opt.selected?'true':'false');
+      b.addEventListener('click',function(){ onClick(sel,opt); press(wrap,b); });
+      wrap.appendChild(b);
+    });
+    var host=hostOf(sel); host.classList.add('dw-hide-native'); host.parentElement.insertBefore(wrap,host);
+    return true;
+  }
+  function isSampleVar(v){ return /(^|[-_ ])sample\b/i.test(v.sku||'') || /sample/i.test(v.title||''); }
+  function fallbackFromJson(){
+    if(window.__dwVbDone||document.querySelector('.dw-variant-btns')) return; window.__dwVbDone=1;
+    fetch(location.pathname.split('?')[0]+'.js').then(function(r){return r.json();}).then(function(p){
+      if(document.querySelector('.dw-variant-btns')||!p||!p.variants||!p.variants.length) return;
+      var idSel=document.querySelector('select[name="id"],[id^="product-select-"]');
+      var atc=document.querySelector('button[name="add"],[type="submit"][name="add"]')||
+              [].slice.call(document.querySelectorAll('button,input[type=submit]')).filter(function(b){return /add to cart/i.test(b.textContent||b.value||'');})[0];
+      var qty=document.querySelector('input[name="quantity"],input[type="number"]');
+      var anchor=(idSel&&hostOf(idSel))|| (qty&&(qty.closest('.product-form__input,.selector-wrapper,div')||qty)) || atc || document.querySelector('form[action*="/cart"]');
+      if(!anchor) return;
+      var wrap=document.createElement('div'); wrap.className='dw-variant-btns';
+      p.variants.forEach(function(v){
+        var b=document.createElement('button'); b.type='button';
+        b.textContent=isSampleVar(v)?'Sample':nameOnly(v.title||v.name||'');
+        b.setAttribute('aria-pressed', String(p.variants.length===1));
+        b.addEventListener('click',function(){ var u=new URL(location.href); u.searchParams.set('variant',v.id); location.href=u.toString(); });
+        wrap.appendChild(b);
+      });
+      if(idSel) hostOf(idSel).classList.add('dw-hide-native');
+      if(anchor.parentElement) anchor.parentElement.insertBefore(wrap,anchor); else anchor.appendChild(wrap);
+    }).catch(function(){});
+  }
+  function build(){
+    if(location.pathname.indexOf('/products/')===-1) return;
+    var rows=document.querySelectorAll('.single-option-selector,[id^="single-option-"]');
+    if(rows.length){ Array.prototype.forEach.call(rows,function(sel){ mk(sel,function(s,opt){ s.value=opt.value; s.dispatchEvent(new Event('change',{bubbles:true})); }); }); }
+    if(!document.querySelector('.dw-variant-btns')){
+      var idSel=document.querySelector('select[name="id"],[id^="product-select-"]');
+      if(idSel) mk(idSel,function(s,opt){ s.value=opt.value; s.dispatchEvent(new Event('change',{bubbles:true}));
+        try{ var u=new URL(location.href); u.searchParams.set('variant',opt.value); history.replaceState({},'',u); }catch(e){} });
+    }
+  }
+  function init(){ build(); setTimeout(build,400); setTimeout(function(){ build(); fallbackFromJson(); },1200); }
+  if(document.readyState!=='loading') init(); else document.addEventListener('DOMContentLoaded',init);
+})();
+</script>
+<!-- /DW variant buttons -->
+{% endif %}
+"""
+
+STRIP = re.compile(r"\n*\{%-?\s*if template contains 'product'\s*-?%\}.*?<!-- /DW variant buttons -->\s*\{%-?\s*endif\s*-?%\}\n*", re.S)
+
+for m in MIRRORS:
+    f = BASE / m / "layout" / "theme.liquid"
+    if not f.exists():
+        print(f"skip {m} (no theme.liquid)"); continue
+    src = f.read_text()
+    orig = src
+    src = STRIP.sub("\n", src)                       # remove any prior block (v1/v2)
+    if "<!-- /DW -->" in src:
+        src = src.replace("<!-- /DW -->", "<!-- /DW -->\n" + BLOCK, 1)
+    elif "</head>" in src:
+        src = src.replace("</head>", BLOCK + "\n</head>", 1)
+    else:
+        print(f"WARN {m}: no anchor"); continue
+    if src != orig:
+        f.write_text(src); print(f"synced {m}: v2 block ({src.count('dw-variant-btns')} markers)")
+    else:
+        print(f"{m}: already v2")

← a048effe Variant buttons v2: Sample button guaranteed on every SKU (J  ·  back to Dw Validator Debug TK11314  ·  auto-save: 2026-06-21T20:01:45 (1 files) — shopify/scripts/d 7f24f962 →