[object Object]

← back to Designer Wallcoverings

cadence: Quadrille-house 54-inch rule → Fabric (Steve 2026-07-09)

e3b55716a27e340d4d7482c0cc20265070850fe2 · 2026-07-09 13:54:48 -0700 · Steve

Any Quadrille-house sample-only product 54" wide is FABRIC (54"=textile bolt
width; wallcovering rolls are narrower). buildSampleOnlyInput now computes an
effType that overrides cfg.productType→Fabric when row.width is 54 INCHES,
scoped to the quadrille_house_catalog table (never PJ/Pierre Frey) and guarded
against 54cm. Drives title word, product_type tag, and productType. Live audit
found 0 QH products currently 54"+wallcovering — catalog already compliant; this
is the go-forward guard so a 54" Grasscloth row can't be born as wallcovering.

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

Files touched

Diff

commit e3b55716a27e340d4d7482c0cc20265070850fe2
Author: Steve <steve@designerwallcoverings.com>
Date:   Thu Jul 9 13:54:48 2026 -0700

    cadence: Quadrille-house 54-inch rule → Fabric (Steve 2026-07-09)
    
    Any Quadrille-house sample-only product 54" wide is FABRIC (54"=textile bolt
    width; wallcovering rolls are narrower). buildSampleOnlyInput now computes an
    effType that overrides cfg.productType→Fabric when row.width is 54 INCHES,
    scoped to the quadrille_house_catalog table (never PJ/Pierre Frey) and guarded
    against 54cm. Drives title word, product_type tag, and productType. Live audit
    found 0 QH products currently 54"+wallcovering — catalog already compliant; this
    is the go-forward guard so a 54" Grasscloth row can't be born as wallcovering.
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
 shopify/scripts/cadence/cadence-import.js          |  17 ++-
 shopify/scripts/cadence/data/cadence-cursor.json   |   2 +-
 .../cadence/data/cadence-plan-pm-2026-07-09.json   | 162 ++++++++++-----------
 .../cadence/data/upload-restore-2026-07-09.jsonl   |   2 +
 .../snippets/color-palette.liquid                  |  44 +++++-
 5 files changed, 133 insertions(+), 94 deletions(-)

diff --git a/shopify/scripts/cadence/cadence-import.js b/shopify/scripts/cadence/cadence-import.js
index 3a62f00d..2a35c28b 100644
--- a/shopify/scripts/cadence/cadence-import.js
+++ b/shopify/scripts/cadence/cadence-import.js
@@ -462,11 +462,20 @@ function buildSampleOnlyInput(vendor, cfg, row, activate) {
   // Title core: "Pattern, Color" → "Color" (when no pattern) → pattern → dw_sku. NEVER mfr_sku, NEVER Unknown.
   let core = (pattern && color) ? `${pattern}, ${color}` : (pattern || color);
   if (!core) core = row.dw_sku;
-  // type-aware title word: Quadrille-house lines are mostly FABRIC (Alan Campbell, Quadrille,
+  // Effective product type. Quadrille-house lines are mostly FABRIC (Alan Campbell, Quadrille,
   // Home Couture, Plains…) — only Grasscloth is genuinely wallcovering. Respect cfg.productType
   // so a Fabric line is never titled "Wallcoverings" (mirrors the roll path @ ~L612). Fixing this
   // at birth stops the recurring Alan-Campbell wallcovering→fabric re-sweep (4th cleanup, 2026-07-09).
-  const isFabric = /fabric/i.test(cfg.productType || '');
+  // Steve's width rule (2026-07-09): ANY Quadrille-house product 54" wide is FABRIC (54" = textile
+  // bolt width; wallcovering rolls are narrower). Overrides cfg.productType so a 54" Grasscloth row
+  // flips to Fabric at birth. Scoped to the QH staging table (never PJ / Pierre Frey, which are
+  // legitimately wallcovering) and guarded to INCHES (54" not 54 cm ≈ 21").
+  const _w = String(row.width || '');
+  const _is54inch = cfg.table === 'quadrille_house_catalog'
+    && /(?:^|[^0-9])54(?:[^0-9]|$)/.test(_w)
+    && !/\b(?:cm|mm|centim|millim|met(?:re|er))\b/i.test(_w);
+  const effType = _is54inch ? 'Fabric' : (cfg.productType || 'Wallcovering');
+  const isFabric = /fabric/i.test(effType);
   const typeWord = isFabric ? 'Fabric' : 'Wallcoverings';
   const title = `${core} ${typeWord} | ${vendor}`.replace(/wallpaper/gi,'Wallcovering');
   const handle = (`${core}-${row.dw_sku}`).toLowerCase().replace(/[^a-z0-9]+/g,'-').replace(/^-+|-+$/g,'').slice(0,100);
@@ -529,11 +538,11 @@ function buildSampleOnlyInput(vendor, cfg, row, activate) {
   // positives on the sample-only image set and tags a spurious Needs-Image. We keep every OTHER
   // gate flag (Needs-Specs / Needs-Description / Needs-Width) — only the false Needs-Image is dropped.
   const gateTags = gate.tags.filter(t => String(t).toLowerCase() !== 'needs-image');
-  const tagSet = [vendor, cfg.productType, 'Sample Only', 'display_variant', 'Quadrille House',
+  const tagSet = [vendor, effType, 'Sample Only', 'display_variant', 'Quadrille House',
     ...(row.collection?[`Collection: ${row.collection}`]:[]), ...(color?[color]:[]), ...gateTags];
 
   const input = {
-    title, handle, vendor, productType: cfg.productType,
+    title, handle, vendor, productType: effType,
     status: willActivate ? 'ACTIVE' : 'DRAFT',
     tags: [...new Set(tagSet.filter(Boolean))],
     descriptionHtml,
diff --git a/shopify/scripts/cadence/data/cadence-cursor.json b/shopify/scripts/cadence/data/cadence-cursor.json
index a32d96fc..c687f93c 100644
--- a/shopify/scripts/cadence/data/cadence-cursor.json
+++ b/shopify/scripts/cadence/data/cadence-cursor.json
@@ -1,5 +1,5 @@
 {
- "idx": 5,
+ "idx": 2,
  "lastSlot": "pm",
  "lastRun": "2026-07-09"
 }
\ No newline at end of file
diff --git a/shopify/scripts/cadence/data/cadence-plan-pm-2026-07-09.json b/shopify/scripts/cadence/data/cadence-plan-pm-2026-07-09.json
index ce362c15..5316794a 100644
--- a/shopify/scripts/cadence/data/cadence-plan-pm-2026-07-09.json
+++ b/shopify/scripts/cadence/data/cadence-plan-pm-2026-07-09.json
@@ -1,154 +1,152 @@
 [
  {
-  "vendor": "Romo",
-  "dw_sku": "DWRM-240167",
-  "cost": 1364,
-  "retail": 2468.78,
+  "vendor": "Kravet",
+  "dw_sku": "DWKK-103165",
+  "cost": 130.2,
+  "retail": 195.3,
   "sample": "4.25",
   "sampleOnly": false,
-  "title": "Bakbak, Indigo Wallcoverings | Romo",
+  "title": "Kravet Design, White Wallcoverings | Kravet",
   "willActivate": true
  },
  {
-  "vendor": "Romo",
-  "dw_sku": "DWRM-240187",
-  "cost": 490.6,
-  "retail": 887.96,
+  "vendor": "Kravet",
+  "dw_sku": "DWKK-103166",
+  "cost": 145.95,
+  "retail": 218.93,
   "sample": "4.25",
   "sampleOnly": false,
-  "title": "Suru, Typhoon Wallcoverings | Romo",
+  "title": "Kravet Design, Beige Wallcoverings | Kravet",
   "willActivate": true
  },
  {
-  "vendor": "Romo",
-  "dw_sku": "DWRM-240194",
-  "cost": 451,
-  "retail": 816.29,
+  "vendor": "Kravet",
+  "dw_sku": "DWKK-103167",
+  "cost": 145.95,
+  "retail": 218.93,
   "sample": "4.25",
   "sampleOnly": false,
-  "title": "Palm, Harvest Wallcoverings | Romo",
+  "title": "Kravet Design, Beige Wallcoverings | Kravet",
   "willActivate": true
  },
  {
-  "vendor": "Thibaut",
-  "dw_sku": "DWTT-73908",
-  "cost": 41.4,
-  "retail": 74.93,
+  "vendor": "Schumacher",
+  "dw_sku": "DWLK-809740",
+  "cost": 28,
+  "retail": 50.68,
   "sample": "4.25",
   "sampleOnly": false,
-  "title": "T-Square, Spa Blue Wallcoverings | Thibaut",
+  "title": "Fancy Beast, Sky Blue Wallcoverings | Schumacher",
   "willActivate": true
  },
  {
-  "vendor": "Thibaut",
-  "dw_sku": "DWTT-73909",
-  "cost": 41.4,
-  "retail": 74.93,
+  "vendor": "Schumacher",
+  "dw_sku": "DWLK-809750",
+  "cost": 28,
+  "retail": 50.68,
   "sample": "4.25",
   "sampleOnly": false,
-  "title": "T-Square, Light Green Wallcoverings | Thibaut",
+  "title": "Fancy Beast, Sand Wallcoverings | Schumacher",
   "willActivate": true
  },
  {
-  "vendor": "Thibaut",
-  "dw_sku": "DWTT-73910",
-  "cost": 181.8,
-  "retail": 329.05,
+  "vendor": "Schumacher",
+  "dw_sku": "DWLK-809760",
+  "cost": 32,
+  "retail": 57.92,
   "sample": "4.25",
   "sampleOnly": false,
-  "title": "La Palma, Charcoal Wallcoverings | Thibaut",
+  "title": "Trellis, Indigo Wallcoverings | Schumacher",
   "willActivate": true
  },
  {
-  "vendor": "Designtex",
-  "dw_sku": "DWDX-220516",
-  "cost": 58,
-  "retail": 104.98,
+  "vendor": "Quadrille",
+  "dw_sku": "DWQC-600446",
+  "cost": 0,
+  "retail": 0,
   "sample": "4.25",
-  "sampleOnly": false,
-  "title": "Fragments, New York Wallcoverings | Designtex",
-  "willActivate": true,
-  "held": true,
-  "heldReason": "\"York Wallcoverings\" is a banned front-facing trade-parent name"
+  "sampleOnly": true,
+  "title": "Tulips Multicolor, Pinks Green on White Linen Fabric | Quadrille",
+  "willActivate": true
  },
  {
-  "vendor": "Designtex",
-  "dw_sku": "DWDX-220684",
-  "cost": 31,
-  "retail": 56.11,
+  "vendor": "Quadrille",
+  "dw_sku": "DWQC-600447",
+  "cost": 0,
+  "retail": 0,
   "sample": "4.25",
-  "sampleOnly": false,
-  "title": "Cambric, Shale Wallcoverings | Designtex",
-  "willActivate": false
+  "sampleOnly": true,
+  "title": "Tulips Multicolor, Pale Green Pale Pink on White Fabric | Quadrille",
+  "willActivate": true
  },
  {
-  "vendor": "Designtex",
-  "dw_sku": "DWDX-220685",
-  "cost": 31,
-  "retail": 56.11,
+  "vendor": "Quadrille",
+  "dw_sku": "DWQC-600448",
+  "cost": 0,
+  "retail": 0,
   "sample": "4.25",
-  "sampleOnly": false,
-  "title": "Cambric, Pumice Wallcoverings | Designtex",
+  "sampleOnly": true,
+  "title": "Cherry Branch, Multi on Creme Linen Cotton Fabric | Quadrille",
   "willActivate": false
  },
  {
-  "vendor": "Newwall",
-  "dw_sku": "DWXW-1006081",
-  "cost": 232,
-  "retail": 419.91,
+  "vendor": "Romo",
+  "dw_sku": "DWRM-240167",
+  "cost": 1364,
+  "retail": 2468.78,
   "sample": "4.25",
   "sampleOnly": false,
-  "title": "Majorelle Velvet Petrol, Yard Wallcoverings | Newwall",
+  "title": "Bakbak, Indigo Wallcoverings | Romo",
   "willActivate": true
  },
  {
-  "vendor": "Newwall",
-  "dw_sku": "DWXW-1006082",
-  "cost": 232,
-  "retail": 419.91,
+  "vendor": "Romo",
+  "dw_sku": "DWRM-240187",
+  "cost": 490.6,
+  "retail": 887.96,
   "sample": "4.25",
   "sampleOnly": false,
-  "title": "Zeus Velvet Tobacco, Yard Wallcoverings | Newwall",
+  "title": "Suru, Typhoon Wallcoverings | Romo",
   "willActivate": true
  },
  {
-  "vendor": "Newwall",
-  "dw_sku": "DWXW-1006083",
-  "cost": 232,
-  "retail": 419.91,
+  "vendor": "Romo",
+  "dw_sku": "DWRM-240194",
+  "cost": 451,
+  "retail": 816.29,
   "sample": "4.25",
   "sampleOnly": false,
-  "title": "Mey Meh Velvet Blush, Yard Wallcoverings | Newwall",
+  "title": "Palm, Harvest Wallcoverings | Romo",
   "willActivate": true
  },
  {
-  "vendor": "Brewster & York",
-  "dw_sku": "DWBR-171124",
-  "cost": 70,
-  "retail": 126.7,
+  "vendor": "Thibaut",
+  "dw_sku": "DWTT-73911",
+  "cost": 41.4,
+  "retail": 74.93,
   "sample": "4.25",
   "sampleOnly": false,
-  "title": "Elan, Grey Wallcoverings | Malibu Wallcovering",
+  "title": "T-Square, Navy Wallcoverings | Thibaut",
   "willActivate": true
  },
  {
-  "vendor": "Brewster & York",
-  "dw_sku": "DWBR-171125",
-  "cost": 70,
-  "retail": 126.7,
+  "vendor": "Thibaut",
+  "dw_sku": "DWTT-73912",
+  "cost": 181.8,
+  "retail": 329.05,
   "sample": "4.25",
   "sampleOnly": false,
-  "title": "Elan, Blue Wallcoverings | Malibu Wallcovering",
+  "title": "La Palma, Seagreen Wallcoverings | Thibaut",
   "willActivate": true
  },
  {
-  "vendor": "Brewster & York",
-  "dw_sku": "DWBR-171126",
-  "cost": 70,
-  "retail": 126.7,
+  "vendor": "Thibaut",
+  "dw_sku": "DWTT-73913",
+  "cost": 181.8,
+  "retail": 329.05,
   "sample": "4.25",
   "sampleOnly": false,
-  "title": "Elan, Sea Green Wallcoverings | Malibu Wallcovering",
+  "title": "La Palma, Bark Wallcoverings | Thibaut",
   "willActivate": true
  }
 ]
\ No newline at end of file
diff --git a/shopify/scripts/cadence/data/upload-restore-2026-07-09.jsonl b/shopify/scripts/cadence/data/upload-restore-2026-07-09.jsonl
index f50fc2de..a047f80a 100644
--- a/shopify/scripts/cadence/data/upload-restore-2026-07-09.jsonl
+++ b/shopify/scripts/cadence/data/upload-restore-2026-07-09.jsonl
@@ -242,3 +242,5 @@
 {"table":"quadrille_house_catalog","mfr_sku":"020070M-01W","dw_sku":"DWQC-600447","shopify_product_id":"7879917076531","action":"created","activated":true,"published":true,"sampleOnly":true,"status":"ACTIVE","batch_id":"upload-pm-2026-07-09T20-40-05-279Z","ts":"2026-07-09T20:40:36.588Z"}
 {"table":"quadrille_house_catalog","mfr_sku":"306503F","dw_sku":"DWQC-600448","shopify_product_id":"7879917109299","action":"created","activated":false,"published":false,"sampleOnly":true,"status":"DRAFT","batch_id":"upload-pm-2026-07-09T20-40-05-279Z","ts":"2026-07-09T20:40:38.593Z"}
 {"table":"thibaut_catalog","mfr_sku":"T20866","dw_sku":"DWTT-73911","shopify_product_id":"7879917142067","action":"created","activated":true,"published":true,"sampleOnly":false,"status":"ACTIVE","batch_id":"upload-pm-2026-07-09T20-40-05-279Z","ts":"2026-07-09T20:40:46.486Z"}
+{"table":"thibaut_catalog","mfr_sku":"T24049","dw_sku":"DWTT-73912","shopify_product_id":"7879917174835","action":"created","activated":true,"published":true,"sampleOnly":false,"status":"ACTIVE","batch_id":"upload-pm-2026-07-09T20-40-05-279Z","ts":"2026-07-09T20:40:49.928Z"}
+{"table":"thibaut_catalog","mfr_sku":"T24052","dw_sku":"DWTT-73913","shopify_product_id":"7879917207603","action":"created","activated":true,"published":true,"sampleOnly":false,"status":"ACTIVE","batch_id":"upload-pm-2026-07-09T20-40-05-279Z","ts":"2026-07-09T20:40:53.447Z"}
diff --git a/shopify/theme-LIVE-591-freshpull-20260709/snippets/color-palette.liquid b/shopify/theme-LIVE-591-freshpull-20260709/snippets/color-palette.liquid
index 1ac4d6b5..da3c2cb7 100644
--- a/shopify/theme-LIVE-591-freshpull-20260709/snippets/color-palette.liquid
+++ b/shopify/theme-LIVE-591-freshpull-20260709/snippets/color-palette.liquid
@@ -1,7 +1,10 @@
 {% comment %}
   color-palette — "Colors In This Pattern" swatch spectrum.
-  Shows the pattern's real colors AND ~20 interpolated colors between each pair,
-  laid out as uniform swatches centered in even rows.
+  Shows the pattern's real colors AND interpolated in-between colors, laid out as
+  uniform swatches centered in even rows. The TOTAL rendered dots are HARD-capped
+  at MAX_SWATCHES = 20 (Steve 2026-07-09c: "only show a total of 20 dots"): every
+  real base color is kept, and the remaining budget of interpolated dots is spread
+  EVENLY across the gaps (never truncating one end of the spectrum).
 
   DOT CLICK TARGET (Steve 2026-07-09b): "bring up an index of many images, not
   just that exact hex. tolerance 10% for color to pull more." A swatch click now
@@ -290,7 +293,27 @@
       var r=Math.round(ca[0]+(cb[0]-ca[0])*t),g=Math.round(ca[1]+(cb[1]-ca[1])*t),bl=Math.round(ca[2]+(cb[2]-ca[2])*t);
       return '#'+[r,g,bl].map(function(x){return x.toString(16).padStart(2,'0');}).join('');
     }
-    var STEPS = 20; /* interpolated colors served BETWEEN each pair (Steve 2026-07-08) */
+    /* TOTAL rendered dots are HARD-capped at MAX_SWATCHES (Steve 2026-07-09c:
+       "only show a total of 20 dots"). We keep EVERY real base color, then spend
+       whatever budget is left on interpolated in-between dots, distributed EVENLY
+       across the gaps (never truncating one end of the spectrum). See buildSteps. */
+    var MAX_SWATCHES = 20; /* HARD total-dot cap (base + interpolated) */
+
+    /* Given the base-color count, return the number of interpolated dots to place
+       in EACH of the (n-1) gaps, so that base + sum(steps) <= MAX_SWATCHES and the
+       leftover is spread across the earliest gaps (keeps the spectrum balanced,
+       left-to-right, rather than starving the tail). */
+    function buildSteps(n){
+      var gaps = n - 1;
+      if(gaps <= 0) return [];
+      var budget = MAX_SWATCHES - n;            // interpolated dots we can afford
+      if(budget < 0) budget = 0;
+      var per = Math.floor(budget / gaps);
+      var extra = budget - per * gaps;          // spread +1 across the first `extra` gaps
+      var out = [];
+      for(var g=0; g<gaps; g++){ out.push(per + (g < extra ? 1 : 0)); }
+      return out;
+    }
 
     /* Build one swatch. Left-click opens the IN-PAGE index of many products
        within 10% of that hue (onSwatchClick → openIndex); the href is the family
@@ -334,15 +357,22 @@
       if(!list.length) return false;
       var hasPct = list.some(function(c){return c.pct!=null;});
       if(hasPct) list.sort(function(a,b){return (b.pct||0)-(a.pct||0);});
-      list = list.slice(0,8);
+      /* Keep the real base colors. Legacy cap was 8; the total-dot cap
+         (MAX_SWATCHES) is now the real limiter, but if bases alone ever exceed it
+         (they're sorted pct-desc) keep only the MAX_SWATCHES most-dominant. */
+      list = list.slice(0, Math.min(8, MAX_SWATCHES));
 
-      /* Build the spectrum: base color, then STEPS interpolated to the next base. */
+      /* Build the spectrum: each real base color, then an EVENLY-DISTRIBUTED number
+         of interpolated dots to the next base, so the TOTAL rendered dots
+         (base + interpolated) never exceeds MAX_SWATCHES. (Steve 2026-07-09c) */
+      var stepsPerGap = buildSteps(list.length);
       var frag=document.createDocumentFragment();
       for(var i=0;i<list.length;i++){
         frag.appendChild(makeSwatch(list[i].hex,{base:true,name:list[i].name,pct:list[i].pct}));
         if(i<list.length-1){
-          for(var k=1;k<=STEPS;k++){
-            var t=k/(STEPS+1);
+          var steps = stepsPerGap[i] || 0;
+          for(var k=1;k<=steps;k++){
+            var t=k/(steps+1);
             frag.appendChild(makeSwatch(mix(list[i].hex,list[i+1].hex,t),{base:false}));
           }
         }

← 9a0496ce auto-save: 2026-07-09T13:40:43 (3 files) — pending-approval/  ·  back to Designer Wallcoverings  ·  stage: 20-dot color-palette cap — LIVE push script + pending 83701d75 →