[object Object]

← back to Designer Wallcoverings

snapshot: 334 file(s) changed, +48 new, ~286 modified

9fea93cbedcd0b38d52d113651bf5e0f9316fa2d · 2026-05-13 08:57:51 -0700 · Steve

Files touched

Diff

commit 9fea93cbedcd0b38d52d113651bf5e0f9316fa2d
Author: Steve <steve@designerwallcoverings.com>
Date:   Wed May 13 08:57:51 2026 -0700

    snapshot: 334 file(s) changed, +48 new, ~286 modified
---
 CLAUDE.md.pre-scrub-2026-05-07.bak                 |  942 +++++++++
 COMPLETED-PROCESSES.md                             |    2 +-
 COMPLETED-PROCESSES.md.pre-scrub-2026-05-07.bak    |  250 +++
 DW-Agents/.gitignore                               |    2 +
 .../agent-digital-samples/digital-samples-agent.ts |    2 +-
 .../dw-agents/agent-marketing/marketing-agent.ts   |    2 +-
 .../purchasing-office-agent.ts                     |    2 +-
 .../dw-agents/agent-security/security-agent.ts     |    2 +-
 DW-Agents/dw-agents/agent-slack/slack-agent.js     |    4 +-
 DW-Agents/dw-agents/agent-slack/slack-agent.ts     |    4 +-
 .../agent-task-orchestrator/ecosystem.config.js    |    2 +-
 .../agent-thibaut-updater/thibaut-updater-agent.ts |    2 +-
 .../agent-zendesk-chat/zendesk-chat-agent.ts       |    2 +-
 DW-Agents/dw-agents/digital-samples-agent.ts       |    2 +-
 DW-Agents/dw-agents/dw-instagram-agent/server.js   |    2 +-
 DW-Agents/dw-agents/ecosystem-complete.config.js   |    2 +-
 DW-Agents/dw-agents/get-amazon-api-credentials.sh  |    2 +-
 DW-Agents/dw-agents/marketing-agent.ts             |    2 +-
 DW-Agents/dw-agents/purchasing-office-agent.ts     |    2 +-
 DW-Agents/dw-agents/shared-executive-core.ts       |    2 +-
 .../versions/v1.1.110725/ecosystem.config.js       |    2 +-
 DW-Agents/dw-agents/zendesk-chat-agent.ts          |    2 +-
 DW-Agents/ecosystem.config.js                      |   16 +-
 DW-MCP/.gitignore                                  |    7 +
 DW-MCP/wine-tracker-config.md                      |    2 +-
 DW-Product-Pages/.gitignore                        |   12 +
 DW-Programming/.gitignore                          |   12 +
 .../ImportNewSkufromURL/dwjs-ai-retag.ts           |    4 +-
 .../dwjs-comprehensive-update.ts                   |    2 +-
 .../dwjs-interior-design-update.js                 |    2 +-
 .../dwjs-interior-design-update.ts                 |    2 +-
 .../ImportNewSkufromURL/fix-all-dwpd-colors.ts     |    2 +-
 .../ImportNewSkufromURL/fix-color-tags.ts          |    2 +-
 .../ImportNewSkufromURL/fix-dwjs-red-tags.ts       |    2 +-
 .../ImportNewSkufromURL/fix-lod-descriptions.ts    |    2 +-
 .../koroseal-architectural-bulk-update.js          |    2 +-
 .../ImportNewSkufromURL/lib/slack-notify.ts        |    2 +-
 .../temp-clone/.github/workflows/claude.yml        |    2 +-
 .../plugins/code-review/commands/code-review.md    |    2 +-
 .../scripts/koroseal-enrichment.ts                 |    4 +-
 .../scripts/rwltd-gemini-cron.js                   |    2 +-
 DW-Programming/ImportNewSkufromURL/tag-dwpd-ai.ts  |    2 +-
 .../universal-completion-notifier.ts               |    2 +-
 DW-Programming/KravetDesignTagger/server.js        |    2 +-
 DW-Programming/LINCRUSTA_PROJECT_MEMORY.md         |    2 +-
 .../PhillipeRomanoTagger/bulk-update-pr.js         |    2 +-
 .../PhillipeRomanoTagger/consolidate-pr-vendors.js |    2 +-
 DW-Programming/PhillipeRomanoTagger/server.js      |    2 +-
 .../RemoveDuplicatesInShopify/auto-tag-groups.js   |    2 +-
 .../RemoveDuplicatesInShopify/recrawl-all-tags.js  |    2 +-
 DW-Programming/RemoveDuplicatesInShopify/server.js |    2 +-
 .../tag-schumacher-products.ts                     |    2 +-
 .../RemoveDuplicatesInShopify/test-tagging.ts      |    2 +-
 .../scripts/rescan-scheduled-posts.ts              |    2 +-
 .../src/app/api/analyze-product/route.ts           |    2 +-
 .../src/app/api/generate-ai-content/route.ts       |    2 +-
 DW-Programming/ThibautTagger/server.js             |    2 +-
 DW-Programming/activate-versace-drafts.js          |    4 +-
 DW-Programming/activate-versace-vi.js              |    4 +-
 DW-Programming/anna-french-ai-enrich.js            |    4 +-
 DW-Programming/anna-french-room-settings.js        |    2 +-
 DW-Programming/anna-french-shopify-push.js         |    2 +-
 DW-Programming/archive-hollywood-discontinued.js   |    2 +-
 DW-Programming/archive-thibaut-discontinued.js     |    2 +-
 DW-Programming/as-creation-shopify-push.js         |    2 +-
 DW-Programming/china-seas-design-tagger.js         |    4 +-
 DW-Programming/china-seas-hex-colors.js            |    4 +-
 DW-Programming/color-batch-cleaner.py              |    2 +-
 DW-Programming/color-collection-cleaner.js         |    2 +-
 DW-Programming/command54-shopify-push.js           |    2 +-
 DW-Programming/crop-grs-fix-top-logo.js            |    2 +-
 DW-Programming/crop-grs-images.js                  |    2 +-
 DW-Programming/enrich-anna-french-specs.js         |    2 +-
 DW-Programming/enrich-anna-french.js               |    2 +-
 DW-Programming/enrich-grahambrown-width.js         |    2 +-
 DW-Programming/enrich-launched-products.py         |    2 +-
 DW-Programming/fix-blue-collection.js              |    2 +-
 DW-Programming/fix-phillipe-romano-vendors.js      |    2 +-
 DW-Programming/generate-justindavid-rooms.py       |    2 +-
 DW-Programming/generate-maya-room-settings.js      |    2 +-
 DW-Programming/gls-gemini-retry.js                 |    2 +-
 DW-Programming/gls-product-cleanup.js              |    4 +-
 DW-Programming/gls-product-processor.js            |    4 +-
 DW-Programming/gls-product-updater.js              |    4 +-
 DW-Programming/gls-retry-failed.js                 |    2 +-
 DW-Programming/hex-color-blitz.js                  |    4 +-
 DW-Programming/hollywood-hex-and-tags.js           |    4 +-
 DW-Programming/hollywood-hex-extract.js            |    2 +-
 DW-Programming/hollywood-shopify-push.js           |    2 +-
 DW-Programming/interior-design-ai-tagger.js        |    4 +-
 DW-Programming/interior-design-tagger.js           |    4 +-
 DW-Programming/jd-room-batch.js                    |    2 +-
 DW-Programming/justindavid-shopify-push.js         |    2 +-
 DW-Programming/launch-versace-vi.js                |    2 +-
 .../maya-romanoff-updater/maya-romanoff-updater.js |    4 +-
 DW-Programming/maya-romanoff-updater/server.js     |    4 +-
 DW-Programming/migrate-dwkk-to-dwpr.js             |    2 +-
 .../app/api/analyze-image/route.ts                 |    4 +-
 .../nextjs-liquid-app/app/api/bulk-import/route.ts |    2 +-
 .../nextjs-liquid-app/app/api/oldest-skus/route.ts |    2 +-
 .../nextjs-liquid-app/update-mckenzie-titles.js    |    2 +-
 DW-Programming/phase3-ai-enrich-100.js             |    4 +-
 DW-Programming/phase3-ai-enrich-batch.js           |    4 +-
 DW-Programming/phase3-ai-enrich-batch.py           |    2 +-
 DW-Programming/phase3-ai-enrich-batch.sh           |    2 +-
 DW-Programming/phase3-ai-enrich-run.js             |    2 +-
 DW-Programming/phase3-ai-enrichment.js             |    2 +-
 DW-Programming/phillipe-romano-vendor-fix.js       |    2 +-
 DW-Programming/pj-tearsheet-scraper.js             |    2 +-
 DW-Programming/pr-logo-crop.py                     |    2 +-
 DW-Programming/prl-ai-enrich.js                    |    4 +-
 DW-Programming/push-maya-romanoff-to-shopify.js    |    2 +-
 DW-Programming/push-versace-vi.js                  |    2 +-
 DW-Programming/ralph-lauren-fabric-updater-9899.js |    2 +-
 DW-Programming/ralph-lauren-fabric-updater-9899.ts |    2 +-
 DW-Programming/remove-damask-from-florals.js       |    2 +-
 .../app/api/analyze-pattern/route.ts               |    2 +-
 .../room-setting-app/batch-room-gen-v2.py          |    2 +-
 .../room-setting-app/batch-room-generator.py       |    2 +-
 .../room-setting-app/batch-room-settings.py        |    2 +-
 .../room-setting-app/ecosystem.config.js           |    2 +-
 .../generate-phillipe-romano-rooms.py              |    2 +-
 .../room-setting-app/lib/gemini-room-generator.ts  |    4 +-
 .../scripts/batch-room-generator.js                |    2 +-
 .../scripts/batch-room-generator.py                |    2 +-
 DW-Programming/schumacher-dwsw-full-updater.ts     |    2 +-
 DW-Programming/scrape-versa-evo-pvcfree.js         |    2 +-
 DW-Programming/scrape-versace-images.js            |    2 +-
 DW-Programming/update-specific-schumacher.ts       |    2 +-
 .../vendor-crawlers/lib/crawler-tracker.js         |    2 +-
 .../vendor-crawlers/scripts/crawl-all.sh           |    2 +-
 .../scripts/monthly-vendor-update.sh               |    2 +-
 DW-Programming/versace-image-scraper.js            |    2 +-
 DW-Programming/versace-image-uploader.js           |    2 +-
 DW-Programming/zoffany-ai-enrich.js                |    4 +-
 DW-Skills-Output/.gitignore                        |   12 +
 DW-Skills/.gitignore                               |   12 +
 DW-Websites/.gitignore                             |   12 +
 DW-Websites/DesignerWallcoverings-product.liquid   |  185 ++
 DW-Websites/GoldLeafWallpaper/index.html           |   99 +
 DW-Websites/GrassclothWallpaper.com/index.html     |  100 +
 DW-Websites/LosAngelesFabrics                      |    1 +
 DW-Websites/_shared/deploy-fleet-nav.sh            |   87 +
 DW-Websites/flockedwallpaper-mobile/index.html     |  100 +
 DW-Websites/flockedwallpaper/agenda.html           |    2 +-
 DW-Websites/flockedwallpaper/index.html            |  100 +
 DW-Websites/shop-by-color/index.html               |   99 +
 DW-Websites/site-watchdog.sh                       |    2 +-
 DW-Websites/steve-hourly-report.sh                 |    2 +-
 OLD_/.gitignore                                    |   12 +
 US-001-IMPLEMENTATION.md                           |    2 +-
 US-001-IMPLEMENTATION.md.pre-scrub-2026-05-07.bak  |  194 ++
 admin/.gitignore                                   |   12 +
 ai-enrich-arte-fix.js                              |    2 +-
 ai-enrich-arte-fix.js.pre-scrub-2026-05-07.bak     |  116 ++
 ai-enrich-gaps2.js                                 |    2 +-
 ai-enrich-gaps2.js.pre-scrub-2026-05-07.bak        |  133 ++
 arte-fill-tags.js                                  |    2 +-
 arte-fill-tags.js.pre-scrub-2026-05-07.bak         |  123 ++
 backups/.gitignore                                 |   12 +
 brand-router/.gitignore                            |   12 +
 components/.gitignore                              |   12 +
 docs/.gitignore                                    |   12 +
 enrich-arte-fix.js                                 |    2 +-
 enrich-arte-fix.js.pre-scrub-2026-05-07.bak        |  139 ++
 enrich-arte-gaps.js                                |    2 +-
 enrich-arte-gaps.js.pre-scrub-2026-05-07.bak       |  124 ++
 enrich-arte-puppeteer.js                           |    2 +-
 enrich-arte-puppeteer.js.pre-scrub-2026-05-07.bak  |  164 ++
 enrich-remaining-13.js                             |    2 +-
 enrich-remaining-13.js.pre-scrub-2026-05-07.bak    |  136 ++
 gemini-classify-texture.js                         |    2 +-
 ...ni-classify-texture.js.pre-scrub-2026-05-07.bak |  112 ++
 gemini-enrich-arte.js                              |    2 +-
 gemini-enrich-arte.js.pre-scrub-2026-05-07.bak     |  120 ++
 gemini-enrich-arte9.js                             |    2 +-
 gemini-enrich-arte9.js.pre-scrub-2026-05-07.bak    |  152 ++
 gemini-enrich-gaps.js                              |    2 +-
 gemini-enrich-gaps.js.pre-scrub-2026-05-07.bak     |  175 ++
 lib/.gitignore                                     |   12 +
 mailers/scalamandre-pillows-launch.html            |  206 ++
 mockups/.gitignore                                 |   12 +
 output/.gitignore                                  |   12 +
 output/us-007-implementation-summary.md            |    2 +-
 scripts/.gitignore                                 |   12 +
 scripts/US-007-USAGE.md                            |    2 +-
 scripts/activate-koroseal-product.js               |    2 +-
 scripts/ai-enrich-arte-gaps.js                     |    2 +-
 scripts/ai-enrich-gaps.js                          |    2 +-
 scripts/batch-room-generator.py                    |    2 +-
 scripts/batch-room-settings.py                     |    2 +-
 scripts/brand-mckenzie-ai-analysis.ts              |    2 +-
 scripts/brand-mckenzie-full-scrape.ts              |    2 +-
 scripts/brand-mckenzie-full-update.ts              |    2 +-
 scripts/build-collections-directory.js             |    2 +-
 scripts/collection-consolidation-phase2.js         |    2 +-
 scripts/collection-description-writer.js           |    2 +-
 scripts/collections-cover-images.js                |    2 +-
 scripts/enrich-remaining-13.js                     |    2 +-
 scripts/feed-room-queue.js                         |    2 +-
 scripts/fix-fabric-wallcovering-v3.js              |    2 +-
 scripts/grs-image-crop.js                          |    2 +-
 scripts/import-fmpro-to-postgres.js                |    2 +-
 scripts/interior-design-tags.js                    |    4 +-
 scripts/justindavid-daily-cron.sh                  |    2 +-
 scripts/justindavid-room-settings.js               |    2 +-
 scripts/kill-wallpaper-word.js                     |    2 +-
 scripts/koroseal-architectural-bulk-update.js      |    2 +-
 scripts/lib/slack-progress-notify.ts               |    2 +-
 scripts/mfr-sku-bulk-update.js                     |    2 +-
 .../audit-as-dedupe-2026-05-06T18-38-04.json       |  126 ++
 .../audit-pr-dedupe-2026-05-06T17-59-26.json       |  330 +++
 .../audit-rename-2026-05-06T17-35-58.json          | 2094 ++++++++++++++++++++
 .../audit-rename-2026-05-06T17-44-04.json          | 2087 +++++++++++++++++++
 scripts/ncw-cleanup/build-full-table.js            |   69 +
 scripts/ncw-cleanup/dedupe-as-creation.js          |   61 +
 scripts/ncw-cleanup/dedupe-pr.js                   |   72 +
 scripts/ncw-cleanup/ncw-active-full-table.csv      |  319 +++
 scripts/ncw-cleanup/ncw-active-full-table.md       |  320 +++
 scripts/ncw-cleanup/ncw-old-to-new-sku-mapping.txt |  124 ++
 scripts/ncw-cleanup/rename-variant-skus.js         |  100 +
 scripts/prl-ai-enrich.js                           |    4 +-
 scripts/push-mfr-to-shopify.js                     |    2 +-
 scripts/ralph/prd-ralph-lauren-fabrics.json        |    2 +-
 scripts/run-wallpaper-cleanup-remaining.sh         |    2 +-
 scripts/rw-drapery-daily-cron.sh                   |    2 +-
 scripts/rw-drapery-room-settings.js                |    2 +-
 scripts/standardize-product-types-bulk.js          |    2 +-
 scripts/standardize-product-types.js               |    2 +-
 scripts/supplier-mfr-bulk-push.js                  |    2 +-
 scripts/texture-repeat-classifier.js               |    4 +-
 scripts/us-007-ai-product-quality-analyzer.ts      |    2 +-
 shopify/.gitignore                                 |    6 +
 shopify/scripts/add-missing-samples-v2.js          |    2 +-
 shopify/scripts/arte-dashboard/server.js           |    2 +-
 shopify/scripts/batch-room-settings.py             |    2 +-
 .../batch-room-settings/batch-room-generator.js    |    6 +-
 shopify/scripts/bespoke-updater/server.js          |    2 +-
 shopify/scripts/classify-texture-pattern.js        |    2 +-
 shopify/scripts/cron-create-sample-variants.sh     |    2 +-
 shopify/scripts/fix-missing-samples.js             |    2 +-
 shopify/scripts/fix-sample-inventory-only.js       |    2 +-
 shopify/scripts/fix-samples-graphql.js             |    2 +-
 shopify/scripts/fix-zero-inventory-samples.js      |    2 +-
 shopify/scripts/gemini-catalog-tagger.js           |    4 +-
 shopify/scripts/gemini-tag-engine/index.js         |    4 +-
 shopify/scripts/import-missing-dwrr.ts             |    2 +-
 shopify/scripts/interior-design-tagger.js          |    4 +-
 shopify/scripts/koroseal-complete-update.ts        |    2 +-
 shopify/scripts/koroseal-enhanced-update.js        |    2 +-
 shopify/scripts/koroseal-update.js                 |    2 +-
 .../scripts/migrate-mckenzie-global-to-custom.js   |  136 ++
 shopify/scripts/prl-ai-enrich.js                   |    4 +-
 shopify/scripts/push-fire-rating-metafields.js     |    2 +-
 shopify/scripts/push-pattern-repeat-metafields.js  |    2 +-
 shopify/scripts/resume-sample-variant-creation.js  |    2 +-
 shopify/scripts/revert-dwcy-pass2.js               |    2 +-
 shopify/scripts/revert-dwcy-to-dwc.js              |    2 +-
 shopify/scripts/review-dwqw-images-descriptions.ts |    2 +-
 shopify/scripts/romo-lookup.js                     |    2 +-
 shopify/scripts/schumacher-price-scraper.js        |    2 +-
 shopify/scripts/set-texture-repeat-zero.js         |    4 +-
 shopify/scripts/texture-repeat-fixer.js            |    4 +-
 shopify/scripts/thibaut-repeat-scraper.js          |    2 +-
 shopify/scripts/update-all-malibu-architectural.ts |    2 +-
 shopify/scripts/update-dwk-full-details.js         |    2 +-
 shopify/scripts/update-dwk-slow-seo.js             |    2 +-
 shopify/scripts/update-dwqw-complete.ts            |    2 +-
 .../scripts/update-dwqw-malibu-architectural.ts    |    2 +-
 .../scripts/update-dwrr-descriptions-quantities.ts |    2 +-
 shopify/scripts/update-dwrr-gemini.ts              |    2 +-
 shopify/scripts/update-koroseal-gemini.ts          |    2 +-
 shopify/scripts/update-mckenzie-delivery.js        |   94 +
 shopify/scripts/update-rop-mfr.py                  |    2 +-
 shopify/scripts/wolf-gordon-shopify-push.js        |    2 +-
 shopify/scripts/zoffany-full-monty-20.js           |    4 +-
 tasks/.gitignore                                   |   12 +
 vendor-logos/.gitignore                            |   12 +
 278 files changed, 10273 insertions(+), 265 deletions(-)

diff --git a/CLAUDE.md.pre-scrub-2026-05-07.bak b/CLAUDE.md.pre-scrub-2026-05-07.bak
new file mode 100644
index 00000000..377e96e2
--- /dev/null
+++ b/CLAUDE.md.pre-scrub-2026-05-07.bak
@@ -0,0 +1,942 @@
+- all vendors need this fix so we are always savinf data #memory
+- **CRITICAL DATABASE**: ALWAYS use `dw_unified` database - NEVER create new databases! Connection string lives in `.env` (DATABASE_URL); use `dw_admin@127.0.0.1:5432/dw_unified`. NEVER commit credentials to docs.
+
+## Shopify Plus — 100K+ Product Push Strategy
+
+### Why Plus (vs Standard)
+| Capability | Standard | Plus |
+|---|---|---|
+| REST req/s | 2/s (40 bucket) | 20/s (400 bucket) — **10x** |
+| GraphQL pts/s | 100 pts/s | 1,000 pts/s — **10x** |
+| Daily variant limit | 1,000/day (>50K variants) | **REMOVED** |
+| Bulk mutations concurrent | 1 | 5 (API 2026-01+) |
+| Shopify Flow | No | Yes |
+| Launchpad (scheduled publishes) | No | Yes |
+| B2B / wholesale | No | Yes |
+| Price | — | $2,300-$2,500/mo |
+
+### Migration: Same-store upgrade, ~24 hours, no data migration. SEO preserved.
+
+### Bulk Operation Pipeline (100K products)
+1. **Generate JSONL** — one JSON object per product line, max 100MB per file (~30K-50K products)
+2. **stagedUploadsCreate** — reserve upload space (resource: BULK_MUTATION_VARIABLES, mime: text/jsonl)
+3. **Upload JSONL** — POST multipart form to staged URL
+4. **bulkOperationRunMutation** — submit async (NOT rate-limited)
+5. **Poll or webhook** — BULK_OPERATION_FINISH webhook fires on completion
+6. **Results** — JSONL download available 7 days
+
+### Time Estimates for 100K Products on Plus
+| Method | Time |
+|---|---|
+| REST API (20 req/s) | 5-10 hours |
+| GraphQL single mutations | 2-5 hours |
+| GraphQL bulk ops (1 concurrent) | 30 min - 3 hours |
+| GraphQL bulk ops (5 parallel, 2026-01) | **10 min - 1 hour** |
+
+### Image Strategy: Use external CDN URLs in JSONL `images: [{src: "https://..."}]`. Shopify fetches async. Do NOT pre-stage 100K images individually.
+
+### Constraints
+- JSONL max: 100MB per file
+- Max operation runtime: 24 hours
+- Max images per product: 250
+- Single query cap: 1,000 points (all plans)
+- Results available: 7 days
+
+## CRITICAL: Discontinued Products → ARCHIVE (Never Draft, Never Delete) #memory
+
+**When a vendor discontinues a product, ARCHIVE it on Shopify. Never draft, never delete.**
+
+### Rules
+1. **Discontinued = ARCHIVE** — Set `status: "archived"` via Shopify Admin API
+2. **Never use draft** for discontinued products — draft is for unpublished new products
+3. **Never delete** discontinued products — archived products preserve SEO and order history
+4. **Detection**: If vendor product URL returns 301/404/redirect to category page → product is discontinued
+5. **Update both**: Set `status: 'archived'` in PostgreSQL catalog table AND Shopify
+
+### API Call
+```javascript
+// Archive a discontinued product on Shopify
+PUT /admin/api/2024-01/products/{product_id}.json
+{ "product": { "id": product_id, "status": "archived" } }
+```
+
+## CRITICAL: NEVER Use "Unknown" as a Pattern Name #memory
+
+**🚫 "UNKNOWN" MUST NEVER APPEAR IN A SHOPIFY PRODUCT TITLE — EVER!**
+
+### Rules
+1. **If no pattern name is found from scraping** — do NOT set pattern to "Unknown"
+2. **If pattern name cannot be determined** — use the MFR SKU as the pattern name instead (e.g. `T10958 Blue | Thibaut`)
+3. **If MFR SKU is also missing** — use only the color name (e.g. `Blue | Thibaut`)
+4. **NEVER publish a product with "Unknown" in the title** — block it from the schedule
+5. **Always scrape vendor website FIRST** and save pattern name to PostgreSQL BEFORE setting Shopify title
+6. **Tag products for review** if pattern name cannot be found — add `Needs-Pattern-Name` tag
+
+### Fallback Order for Pattern Name
+1. Vendor website scrape (thibautdesign.com, koroseal.com, etc.)
+2. Spreadsheet data (TAK, Type II Vinyl, etc.)
+3. Metafields from Shopify (global.Pattern, custom.name_of_pattern)
+4. MFR SKU as pattern name (last resort before "Unknown")
+5. **NEVER "Unknown"** — skip the pattern entirely if nothing found
+
+### Validation Check (MANDATORY before Shopify title update)
+```javascript
+function validateTitle(title) {
+  if (!title || title.toLowerCase().includes('unknown')) {
+    throw new Error('BLOCKED: Title contains "Unknown" - fix pattern name first');
+  }
+  return title;
+}
+```
+
+## CRITICAL: Sample Variant Required for ALL Products #memory
+
+**🏷️ EVERY PRODUCT MUST HAVE A "SAMPLE" VARIANT - NO EXCEPTIONS!**
+
+### Sample Variant Requirements
+| Field | Value | Notes |
+|-------|-------|-------|
+| **Title** | `Sample` | Always "Sample" |
+| **SKU** | `{DW_SKU}-Sample` | DW SKU + "-Sample" suffix |
+| **Price** | `$4.25` | Standard sample price for most vendors |
+| **Inventory** | `null` | No inventory tracking |
+
+### DW SKU Assignment Rules
+1. **Assign at FIRST IMPORT ONLY** - Never change once assigned
+2. **Format**: `DW{XX}-{NUMBER}` — DW + 2 random letters + dash + sequential number
+3. **NEVER reference vendor name** in prefix — too easy to identify vendor
+4. **NEVER use numbers** in prefix — letters only
+5. **FORBIDDEN letters** (hard to hear on phone): **B, D, S, F, M, N, V**
+6. **ALLOWED letters**: A, C, E, G, H, I, J, K, L, O, P, Q, R, T, U, W, X, Y, Z (19 chars)
+7. Each vendor gets a **unique** 2-letter code from allowed set
+8. **VCC auto-generates compliant prefixes** via `generateCompliantPrefix()` on first SKU assignment
+9. **Sequential numbering** - Each vendor's range starts 5000 ahead of the last
+10. **Store in PostgreSQL** - Save to vendor catalog table `dw_sku` column
+11. **Legacy prefixes** (DWSC, DWTT, etc.) — leave existing, only apply new rules going forward
+
+### Product Variant Structure (MANDATORY)
+```javascript
+variants: [
+  {
+    title: 'Sample',
+    sku: `${dwSku}-Sample`,  // e.g., "DWK-040251-Sample"
+    price: '4.25',
+    inventory_management: null
+  }
+]
+```
+
+### Implementation in Shopify Product Creation
+```javascript
+// Generate DW SKU FIRST
+const dwSku = await generateDwSku(vendorPrefix, vendorName, mfrSku);
+
+// Create product with Sample variant
+const productData = {
+  product: {
+    title: productTitle,
+    variants: [{
+      title: 'Sample',
+      sku: `${dwSku}-Sample`,
+      price: '4.25',
+      inventory_management: null
+    }],
+    // ... other fields
+  }
+};
+```
+
+### Why This Matters
+- Customers need to order samples before full rolls
+- DW SKU provides unique identifier across all vendors
+- Sample pricing is standardized at $4.25
+- SKU format enables easy tracking and reordering
+
+---
+
+## CRITICAL: Never Activate SKU Without Width AND Image #memory
+
+**🚫 NEVER set a Shopify product to `status: "active"` unless it has BOTH:**
+1. **A width metafield** — `global.width` or `custom.width` must be set (not null/empty)
+2. **At least one product image** — `product.images.length >= 1`
+
+### Rules
+1. **Products missing width OR image remain as `draft`** — do not activate them
+2. **Check BEFORE any status change** — validate both fields before calling Shopify API
+3. **Bulk imports**: Skip activation for products that fail this check; tag them `Needs-Width` or `Needs-Image`
+4. **Width sources** (in priority order): vendor website scrape, spreadsheet data, metafield sync
+5. **Image sources**: vendor CDN, uploaded images, room settings
+
+### Validation Code (MANDATORY before activation)
+```javascript
+function canActivateProduct(product) {
+  const hasImage = product.images && product.images.length > 0;
+  const hasWidth = product.metafields?.some(m =>
+    (m.namespace === 'global' || m.namespace === 'custom') &&
+    m.key === 'width' && m.value && m.value.trim() !== ''
+  );
+  if (!hasImage) console.warn(`BLOCKED: ${product.title} has no images`);
+  if (!hasWidth) console.warn(`BLOCKED: ${product.title} has no width metafield`);
+  return hasImage && hasWidth;
+}
+```
+
+### Why This Matters
+- Products without width confuse trade buyers who need to calculate coverage
+- Products without images get zero engagement and hurt SEO
+- Better to keep as draft until complete than show incomplete listings
+
+---
+
+## CRITICAL: SKU Registry for New Product Imports #memory
+
+**🔢 BEFORE CREATING ANY NEW PRODUCT IN SHOPIFY - CHECK FOR DUPLICATES!**
+
+### Import the SKU Registry Module
+```javascript
+const { checkDuplicate, registerSku, updateShopifyInfo } = require('./lib/sku-registry');
+// Located: /root/Projects/Designer-Wallcoverings/shopify/scripts/lib/sku-registry.js
+```
+
+### Mandatory Workflow for New Products
+```javascript
+async function importNewProduct(vendorPrefix, vendorName, mfrSku, productData) {
+  // Step 1: CHECK for duplicate
+  const dup = await checkDuplicate(vendorPrefix, mfrSku);
+  if (dup.exists) {
+    console.log(`⚠️ SKIP: ${mfrSku} already exists as ${dup.existingSku}`);
+    return null;
+  }
+
+  // Step 2: REGISTER before Shopify creation
+  const dwSku = await registerSku(vendorPrefix, vendorName, mfrSku);
+  if (!dwSku) return null;
+
+  // Step 3: CREATE in Shopify with DW SKU
+  const shopifyProduct = await createShopifyProduct({ ...productData, sku: dwSku });
+
+  // Step 4: UPDATE registry with Shopify info
+  await updateShopifyInfo(dwSku, shopifyProduct.id, shopifyProduct.handle);
+
+  return { dwSku, shopifyId: shopifyProduct.id };
+}
+```
+
+### Vendor Prefix Quick Reference
+| Prefix | Vendor | Prefix | Vendor |
+|--------|--------|--------|--------|
+| DWK- | Koroseal | DWMR- | Maya Romanoff |
+| DWC-Arte- | Arte | DWCC- | Novasuede |
+| DWTT- | Thibaut | DWKK- | Kravet |
+| DWRR- | Ralph Lauren | DWSC- | Schumacher |
+| DWJS- | York | DWPJ- | Phillip Jeffries |
+| DWWC- | Default/Generic | | |
+
+**Database**: `dw_unified` → Table: `dw_sku_registry`
+
+---
+
+## CRITICAL: AI Analysis MUST Be Saved (Analyze + Accept) #memory
+
+**🎨 AI ANALYSIS REQUIRES TWO STEPS - ANALYZE THEN ACCEPT!**
+
+The `/api/analyze-image` endpoint only RETURNS analysis - it does NOT save to database!
+You MUST call `/api/accept-analysis` to actually SAVE the results.
+
+### API Endpoints (Arte Dashboard - Port 9955)
+
+| Endpoint | Purpose | Saves to DB? |
+|----------|---------|--------------|
+| `POST /api/analyze-image` | Run Gemini AI analysis on image | ❌ NO - Returns only |
+| `POST /api/accept-analysis` | Save analysis to PostgreSQL | ✅ YES - Saves data |
+| `POST /api/scrape-arte` | Fetch MFR data from Arte website | ❌ NO - Returns only |
+
+### Complete AI Analysis Workflow
+
+```bash
+AUTH="Basic ***REMOVED***"
+API="http://localhost:9955"
+
+# Step 1: AI Analyze (returns but does NOT save)
+AI_RESULT=$(curl -s -X POST "$API/api/analyze-image" \
+  -H "Authorization: $AUTH" \
+  -H "Content-Type: application/json" \
+  -d '{"imageUrl":"IMAGE_URL","title":"Pattern Color"}')
+
+# Step 2: Extract FULL analysis object
+ANALYSIS=$(echo "$AI_RESULT" | jq '.analysis')
+
+# Step 3: SAVE to database - aiAnalysis MUST be nested object!
+curl -s -X POST "$API/api/accept-analysis" \
+  -H "Authorization: $AUTH" \
+  -H "Content-Type: application/json" \
+  -d "{\"arteSku\":\"$SKU\",\"aiAnalysis\":$ANALYSIS}"
+```
+
+**⚠️ CRITICAL: The `aiAnalysis` parameter MUST be a nested object containing:**
+- `colors` (array)
+- `tags` (array)
+- `description` (string)
+- `backgroundColor` (string)
+- `styles` (array)
+- `patterns` (array)
+
+### Database Columns Updated by Accept
+
+| Column | Type | Description |
+|--------|------|-------------|
+| `ai_colors` | text[] | Array of detected colors |
+| `ai_tags` | text[] | Interior design tags |
+| `ai_description` | text | 2-sentence commercial description |
+| `ai_background_color` | text | Dominant background color |
+| `ai_styles` | text[] | Style periods (Contemporary, Art Deco, etc.) |
+| `ai_patterns` | text[] | Pattern types (Geometric, Floral, etc.) |
+
+### Gemini 3.0 Prompt (Interior Design Tagger)
+
+```javascript
+const GEMINI_API_KEY = process.env.GEMINI_API_KEY  /* 2026-05-05 SCRUB: was hardcoded; rotate via /secrets */;
+
+// NEVER put example values in prompt - AI will return them!
+// BAD: "backgroundColor": "Navy"
+// GOOD: "backgroundColor": "<actual color you see>"
+```
+
+### Scheduling Products (Calendar API - Port 9958)
+
+```bash
+CAL="http://localhost:9958"
+
+curl -s -X POST "$CAL/api/schedule" \
+  -H "Authorization: $AUTH" \
+  -H "Content-Type: application/json" \
+  -d '{
+    "productId": "SKU",
+    "productTitle": "Pattern Color",
+    "vendorChannelId": 1,
+    "scheduledDate": "2026-02-04T12:00:00",
+    "imageUrl": "IMAGE_URL",
+    "mfrSku": "SKU"
+  }'
+```
+
+### UI Card Turns Purple When Scheduled
+
+The card at http://45.61.58.125:9660/ automatically turns purple when scheduled:
+```javascript
+background: scheduled ? 'linear-gradient(135deg, #7c3aed 0%, #6d28d9 100%)' : 'white'
+```
+
+## CRITICAL: PostgreSQL BEFORE Shopify #memory
+
+**🔴 ALWAYS UPDATE POSTGRESQL FIRST, THEN SHOPIFY!**
+
+When updating ANY product data:
+1. **FIRST**: Scrape vendor website for ALL data (colors, specs, images, SKUs)
+2. **SECOND**: Save ALL data to PostgreSQL (vendor_catalog or arte_catalog table)
+3. **THIRD**: Only THEN update Shopify from PostgreSQL data
+
+**Why PostgreSQL First?**
+- PostgreSQL is the source of truth for ALL vendor data
+- Prevents data loss if Shopify API fails
+- Enables bulk operations and rollback
+- Allows verification before pushing to Shopify
+- Manufacturer color names MUST come from scraped data, not AI
+
+**Never skip PostgreSQL!** Even for single product updates.
+
+## CRITICAL: BANNED WORD "WALLPAPER" - NEVER USE! #memory
+
+**🚨 The word "WALLPAPER" is BANNED from ALL product titles, descriptions, and AI output.**
+
+| ❌ NEVER Use | ✅ ALWAYS Use |
+|-------------|--------------|
+| Wallpaper | Wallcovering |
+| Wallpapers | Wallcoverings |
+| Walls Wallpaper | Wallcoverings |
+
+**Applies to ALL vendors:**
+- DW Bespoke Studios (all variants)
+- Koroseal
+- Maya Romanoff
+- Thibaut
+- Arte
+- All other architectural vendors
+
+**Post-processing cleanup (MANDATORY in all updaters):**
+```javascript
+const cleanWallpaper = (str) => {
+  if (!str) return str;
+  return str
+    .replace(/\bWallpaper\b/gi, 'Wallcovering')
+    .replace(/\bWalls Wallpaper\b/gi, 'Wallcoverings')
+    .replace(/\bWallpapers\b/gi, 'Wallcoverings');
+};
+```
+
+---
+
+## CRITICAL: Product Title Formatting Rules #memory
+
+**🏷️ ALL PRODUCT TITLES MUST BE IN TITLE CASE**
+
+### Title Format
+```
+Pattern Name Real Color Name | Brand Name
+```
+
+### DW Bespoke Vendors - INCLUDE AI STYLE IN TITLE #memory
+**🎨 For DW Bespoke vendors ONLY, include Gemini AI-detected style in the title:**
+
+```
+Design Name [AI Style] | Architectural Wallcoverings
+```
+
+**DW Bespoke Vendors:**
+- DW Bespoke Studios (all variants)
+- DW Bespoke Studio To Go
+- DW Bespoke Murals
+- Retro DW Bespoke Studios To Go
+
+**Examples:**
+- `1917 Deco Kitchen Art Deco | Architectural Wallcoverings` (AI: Art Deco)
+- `1970's Funky Geometrics Retro | Architectural Wallcoverings` (AI: Retro)
+- `Tropical Palm Pop Art | Architectural Wallcoverings` (AI: Pop Art)
+- `Vintage Floral Mid-Century Modern | Architectural Wallcoverings` (AI: Mid-Century Modern)
+
+**Implementation:**
+```javascript
+// For DW Bespoke vendors ONLY:
+const aiStyles = geminiAnalysis.styles; // e.g., ["Art Deco", "Traditional"]
+const bespokeTitle = `${designName} ${aiStyles[0]} | Architectural Wallcoverings`;
+```
+
+### Title Case Rules
+- **Capitalize** first letter of every word
+- **Exceptions**: articles (a, an, the), prepositions (in, on, at, for), conjunctions (and, but, or) - unless first word
+- Use `toTitleCase()` function on all title components
+
+### Real Color Names (NOT AI Colors)
+- **Maya Romanoff**: Use creative names like "Let's Be Platinum", "Walking in the Woods", "Clear Midnight Sky"
+- **Koroseal**: Use spreadsheet colors like "Gold", "Copper", "Pearl Silver"
+- **AI colors (Blue, Gray, etc.)** → TAGS ONLY, never in titles
+
+### Title Examples
+| ✅ Correct | ❌ Wrong |
+|-----------|---------|
+| Ajiro Burst Of Happiness Let's Be Platinum \| Maya Romanoff | ajiro burst of happiness let's be platinum \| maya romanoff |
+| Opulent Leaf Gold \| Architectural Wallcoverings | OPULENT LEAF GOLD \| ARCHITECTURAL WALLCOVERINGS |
+| Palm Beach Blue Green \| Thibaut | Palm beach blue green \| thibaut |
+
+### Metafields for Real Color Names
+```javascript
+// Save REAL color name to custom metafields:
+metafields.push({ namespace: 'custom', key: 'color', value: realColorName, type: 'single_line_text_field' });
+metafields.push({ namespace: 'custom', key: 'real_color_name', value: realColorName, type: 'single_line_text_field' });
+metafields.push({ namespace: 'dwc', key: 'color', value: realColorName, type: 'single_line_text_field' });
+metafields.push({ namespace: 'global', key: 'Color-Way', value: realColorName, type: 'single_line_text_field' });
+```
+
+### SEO Title Format (Commercial/Architect Focus)
+```
+Shop [Pattern Name] in [Real Color Name] | [Brand]
+```
+Example: "Shop Ajiro Burst Of Happiness in Clear Midnight Sky | Maya Romanoff"
+
+---
+
+## CRITICAL: Git Commits Every Session #memory
+**At the END of every session, ALWAYS:**
+1. Commit all changes to git with descriptive message
+2. Update `/root/.claude/SESSION-LEARNINGS.md` with session summary
+3. Include key learnings, fixes applied, and pending tasks
+
+## CRITICAL: Always Update Manufacturer SKU in Metafields #memory
+
+**🏷️ MANDATORY FOR ALL SHOPIFY PRODUCT UPDATES:**
+- **ALWAYS** set `custom.manufacturer_sku` metafield with the MFR SKU
+- **ALWAYS** set `dwc.manufacturer_sku` metafield as backup
+- Extract MFR SKU from product tags (patterns like `ABH-1109`, `TAK-CA01-01`, `AL21-15`)
+- This is the PRIMARY identifier for vendor product lookups
+
+```javascript
+// ALWAYS include these metafields in every product update:
+metafields.push({ namespace: 'custom', key: 'manufacturer_sku', value: mfrSku, type: 'single_line_text_field' });
+metafields.push({ namespace: 'dwc', key: 'manufacturer_sku', value: mfrSku, type: 'single_line_text_field' });
+```
+
+**Why Critical:**
+- MFR SKU is needed for website scraping (Koroseal, Maya Romanoff, etc.)
+- Links Shopify products to vendor catalogs
+- Required for spec lookups and updates
+- Used by multiple automation scripts
+
+---
+
+## Gemini for Image Analysis
+Gemini API keys and endpoints are in the global `/root/.claude/CLAUDE.md`. Use `gemini-2.0-flash` for all image analysis.
+
+## CRITICAL: Koroseal Product Spreadsheets #memory
+
+**🚨 USE BOTH SPREADSHEETS - NEVER GUESS COLORS!**
+
+### 1. TAK Specialty Products (PRIORITY FOR TAK-* SKUs)
+- **URL**: https://docs.google.com/spreadsheets/d/1EjqtPSo9hqTai_UHW-iLVzaglOTHUdQxDmbjz3vnU8A/edit?usp=sharing
+- **CSV**: `https://docs.google.com/spreadsheets/d/1EjqtPSo9hqTai_UHW-iLVzaglOTHUdQxDmbjz3vnU8A/gviz/tq?tqx=out:csv`
+- **Contains**: TAK-AA01 through TAK-GA01 specialty products (foils, cork, raffia, etc.)
+- **Key Columns**:
+  - `Manufacturer Number` = TAK-AA04-02
+  - `V-NAME` = Pattern name (Opulent Leaf)
+  - `color` = **ACTUAL COLOR** (Gold, Copper, Pearl Silver, Taupe Grey)
+  - `Content` = Material type (Foil Leaf, Cork, Raffia)
+
+### 2. Type 2 Vinyl Products
+- **URL**: https://docs.google.com/spreadsheets/d/1FYG7TGUUiim_RL25YJx5R9tBcgL3ilFlLy3dQISVSMo/edit?usp=sharing
+- **CSV**: `https://docs.google.com/spreadsheets/d/1FYG7TGUUiim_RL25YJx5R9tBcgL3ilFlLy3dQISVSMo/gviz/tq?tqx=out:csv`
+- **Contains**: SE81, SG13, AL21, etc. Type 2 Vinyl products
+
+### Color Priority Chain (MANDATORY ORDER)
+1. **TAK Specialty Spreadsheet** (for TAK-* SKUs) - ALWAYS FIRST!
+2. **Type 2 Vinyl Spreadsheet** (for other SKUs)
+3. Scraped colorName from Koroseal website
+4. AI analysis (ONLY if no spreadsheet data exists)
+
+**⚠️ NEVER use AI/Gemini for colors when spreadsheet has the data!**
+
+### Type II Vinyl Scraping - Prefix Search Fallback #memory
+If full SKU search fails (e.g., SG13-02 not found), try prefix search:
+- `SG13-02` → search `SG13` at https://koroseal.com/search-results?searchtext=SG13
+- `AL21-15` → search `AL21`
+- Pattern: `/^[A-Z]{1,2}\d{2,3}-\d+$/i`
+
+**NEVER SKIP products** - if Koroseal page not found, still update using spreadsheet data!
+
+### Example Color Mappings (from TAK spreadsheet)
+| MFR SKU | Pattern | Color | Content |
+|---------|---------|-------|---------|
+| TAK-AA04-01 | Opulent Leaf | Gold | Foil Leaf |
+| TAK-AA04-02 | Opulent Leaf | Copper | Foil Leaf |
+| TAK-AA08-01 | Languid Leaf | Pearl Silver | Foil Leaf |
+| TAK-AA08-02 | Languid Leaf | Gold | Foil Leaf |
+
+## Brewster / York Vendor Login Credentials #memory
+
+**🔐 Trade Portal Access for Brewster & York Wallcoverings**
+
+| Field | Value |
+|-------|-------|
+| **Login URL** | https://www.yorkwall.com/Login/ |
+| **Username** | `6003784` |
+| **Password** | `*Brewsteraccess911*` |
+| **Covers** | Both Brewster and York brands (same parent company) |
+
+### Usage
+- Use for scraping product data, specs, images, pricing from trade portal
+- York and Brewster share the same login system at yorkwall.com
+- Required for accessing full product catalog, room settings, and spec sheets
+- Vendor codes in crossref: `BRE` (Brewster), `yor`/`YOR` (York)
+
+---
+
+## Site Status & Port Assignments
+
+### Production Sites (Fixed for Cloudflare - DO NOT CHANGE PORTS)
+- **flockedwallpaper.com** - Port 3200 (PM2: flockedwallpaper)
+- **glassbeadedwallpaper.com** - Port 9888 (PM2: glassbeadedwallpaper)  
+- **grassclothwallcoverings.com** - Ports 8080/9080 (PM2: grassclothwallcoverings-8080/9080)
+- **grassclothwallpaper.com** - Port 7123 (PM2: grassclothwallpaper) - Fixed 12/08 after crash
+- **novasuede.com** - Port 9878 (PM2: novasuede-website)
+- **bubbe.ai** - Port 3011 (PM2: bubbe)
+
+### Steve's Monitoring Reports
+- Runs at 6am, 12pm, 6pm daily via cron
+- Sends to Slack #claude-to-steve channel
+- Monitors all 6 sites above
+- Script: /root/Projects/Designer-Wallcoverings/DW-Websites/steve-hourly-report.sh
+
+## CRITICAL: Notify Steve on Process Completion #memory
+
+**🔔 ALWAYS send Slack notification to Steve when ANY process completes!**
+
+When a script, scrape, update, or any automated process finishes:
+1. Send summary to Slack #claude-to-steve channel
+2. Include: process name, products processed, success/fail count, duration
+
+```bash
+# Slack webhook for #claude-to-steve
+SLACK_WEBHOOK="https://hooks.slack.com/services/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"
+
+# Send completion notification
+curl -X POST -H 'Content-type: application/json' \
+  --data '{"text":"✅ *Process Complete*\n• Name: Brand McKenzie Scrape\n• Processed: 115 products\n• Saved to PostgreSQL: 115\n• Duration: 25 min"}' \
+  $SLACK_WEBHOOK
+```
+
+**Always notify on:**
+- Vendor scrapes/recrawls
+- AI analysis batches
+- Shopify bulk updates
+- Database migrations
+- Any long-running process
+- always look for the .md scraper and ts file for every vendor
+## Shopify Store Configuration
+- **Store**: designer-laboratory-sandbox
+- **Admin URL**: https://admin.shopify.com/store/designer-laboratory-sandbox/
+- **API Domain**: designer-laboratory-sandbox.myshopify.com
+- **Access Token**: ***REMOVED***
+- **API Version**: 2024-10
+- **Note**: This token lacks `read_customers`/`write_customers` scope. Need Full Access API token from Shopify Admin for customer operations.
+- **GraphQL Endpoint**: `https://designer-laboratory-sandbox.myshopify.com/admin/api/2024-01/graphql.json`
+
+## Shopify Metafield Manager - Global Namespace Fields #memory
+
+**CRITICAL: Use `global` namespace for these product metafields (type: single_line_text_field unless noted)**
+
+### Core Specs (ALWAYS UPDATE FOR WALLPAPER)
+| Key | Description | Example |
+|-----|-------------|---------|
+| `width` | Roll width | "27 Inches" |
+| `length` | Roll length | "27 Feet" |
+| `repeat` | Pattern repeat | "25.25 Inches" |
+| `v_prods_quantity_order_min` | Minimum order qty | "2" |
+| `v_prods_quantity_order_units` | Qty increment/step | "2" |
+| `unit_of_measure` | Pricing unit | "Priced Per Single Roll" |
+| `lead_time` | Lead time | "3-5 Business Days" |
+| `packaged` | Packaging info | "Double Roll" |
+
+### Product Info
+```
+title_tag, title, description_tag, color, Brand, SubBrand
+Book_Name, Book-Name, Book_Number, Book-Number, BOOK_NUMBER
+Collection, Country, Country-of-Origin, COUNTRY_OF_ORIGIN
+Style, Style1, Style2, DESIGN_STYLE, Type, Type1, Type2
+Color-Way, Color-of-Pattern, Color-1, Color-2, Color-3, Color_1
+```
+
+### Specifications
+```
+Contents, Content, Construction, Finish, FINISH, Finishing
+Weight, Durability, Cleaning, Cleaning-Code, Clean-Code, CARECODE
+Usage, Use, FABRIC_USAGE, Direction, MATCH, MATCH_TYPE
+ADDITIONAL_CARE_INSTRUCTIONS_E
+```
+
+### Pattern Repeats
+```
+Vert-Rpt, Vert-Repeat, PATTERN_REPEAT_VERTICAL
+Horz-Rpt, Horz-Repeat, PATTERN_REPEAT_HORIZONTAL
+VERTICAL_HALFDROP, HORIZONTAL_HALFDROP
+```
+
+### Commercial/Contract
+```
+Class-Description, FLAMMABILITY, Wyzenbeek-#, Martindale-#
+SURFACE_ABRASION_COUNT, SURFACE_ABRASION_TEST
+CONTRACT, CA-TB117, UFAC, Prop-65
+```
+
+### Dimensions & Coverage
+```
+Panel-Height, Design-Height, Panel-Count
+COVERAGE_AREA_SQ_FT, COVERAGE_UNIT, YARDS_PER_DR
+Wallcover-Length(YD), EMBROIDERED_WIDTH, WIDTH_EXTENDABLE, AVAILABLE_SIZES
+```
+
+### Fabric-Specific
+```
+FABRIC_TYPE, TRIM_TYPE, WALLCOVERING_TYPE, WEIGHTED_HEM
+BLACKOUT, DIMOUT, RAILROADED, REVERSIBLE
+WASHABLE, HI_TEMP_WASHABLE, ECO_FRIENDLY
+```
+
+### Strength Testing
+```
+SEAMSLIPPAGEWARP, SEAMSLIPPAGEFILLING
+BREAKINGSTRENGTHWARP, BREAKINGSTRENGTHFILLING
+TEARSTRENGTHWARP, TEARSTRENGTHFILLING
+```
+
+### Internal/Trade
+```
+discount_trade, WHLS-Price, js_internal_number, vendor_name_internal
+mfr-pattern-number, Exclusive, SoldPerMeta, Sold-Per, Minimum
+```
+
+### Inventory & Display
+```
+Display-Status, Inventory-Available, Image-exists
+Image-File-Name---LO-RES, seohidden (Integer)
+```
+
+### Marketing/SEO
+```
+Bullet-Point-1, Bullet-Point-2, Bullet-Point-3
+```
+
+### Shipping
+```
+Ship-From, Lead-Time-in-Days, Memo-Sample-Available, DOMESTIC
+```
+
+### Variant-Level
+```
+SKU, Variant-Sku, Title, Color
+```
+
+### Special Types
+```
+color_swatches (Custom Object)
+seohidden (Integer)
+```
+
+### DWC Namespace (Custom Fields)
+| Key | Description |
+|-----|-------------|
+| `dwc.order_unit` | Order unit (text field) |
+| `dwc.manufacturer_sku` | Manufacturer SKU |
+| `dwc.pattern_name` | Pattern name |
+| `dwc.color` | Color |
+| `dwc.background_color` | Background color |
+| `dwc.brand` | Brand |
+| `dwc.real_vendor` | Real vendor name |
+| `dwc.ai_generated_colors` | AI colors (list) |
+| `dwc.ai_generated_tags` | AI tags (list) |
+
+**CRITICAL - ALWAYS USE GRAPHQL API** #memory
+- REST API pagination through 145K+ products is too slow (600+ pages)
+- GraphQL `shop { productVendors }` returns all vendors in ONE call
+- GraphQL `products(query: "vendor:X")` for filtering
+- Example vendor query:
+```graphql
+{ shop { productVendors(first: 250) { edges { node } } } }
+```
+
+**CRITICAL - NEVER USE**: `designerwallcoverings.myshopify.com` - This domain does NOT work for API calls!
+**ALWAYS USE**: `designer-laboratory-sandbox.myshopify.com` - This is the correct API domain for the live store.
+
+## Architectural Wallcoverings Update Agent
+- **URL**: http://45.61.58.125:9897
+- **Auth**: admin / ***REMOVED***
+- **PM2**: dw-architectural-update
+- **Directory**: /root/Projects/Designer-Wallcoverings/DW-Agents/dw-agents/
+- **Progress File**: /root/Projects/Designer-Wallcoverings/DW-Agents/dw-agents/ARCHITECTURAL-UPDATE-PROGRESS.md
+- **Title Format**: `Pattern Name Color (Real-MFR#) | Architectural Wallcoverings`
+- **Data Priority**: Handle > Tags > SKU Mappings
+- **IMPORTANT**: Always read progress file at start of session for context #memory
+
+### Title Rules #memory
+- **ALWAYS remove `-SAMPLE` from titles** - Never include "-SAMPLE" suffix in product titles
+- **No hardcoded vendor tags** - Use actual vendor name, not "Koroseal" for all products
+- **No automatic Type II tags** - Only add Type II if confirmed from product specs
+- **NEVER REMOVE `display_variant` TAG** - This tag controls variant display on the website. If `display_variant` exists in product tags, NEVER delete it! Example: https://www.designerwallcoverings.com/products/yeeha-1950s-cowboy-wallpaper-pine-green-1?variant=44019770458163
+
+### Koroseal SKU Patterns
+- `AL21-15`, `C921-10`, `2R15-21`, `TAK-DA01-01`
+
+### Handle Formats
+- LIVE: `dwk-XXXXX-vendor-...-sku-pattern-color`
+- SANDBOX: `pattern-color-wallcovering-sku-sample-...`
+
+## Room Setting App
+- **URL**: http://45.61.58.125:3075
+- **PM2**: room-setting-app
+- **Directory**: /root/Projects/Designer-Wallcoverings/DW-Programming/room-setting-app
+- **Skill**: ~/.claude/skills/room-setting-generator/SKILL.md
+- **IMPORTANT**: When updating the Room Setting App, ALWAYS update the skill file too #memory
+
+## Ralph Automation
+- **UI**: http://45.61.58.125:7300 (Letsbegin app)
+- **IMPORTANT**: Always CONTINUE Ralph from where it left off - never restart from scratch #memory
+- **Continue API**: POST /api/ralph/continue - only runs PENDING stories
+- **Start API**: POST /api/ralph/run - restarts everything (use sparingly)
+- **Buttons**: CONTINUE (primary) = resume pending, RESTART (secondary) = start fresh
+
+---
+
+## Git Repository Privacy Guidelines
+
+**CRITICAL: All new repositories MUST be set to private by default**
+
+### GitHub Privacy Settings
+
+When creating repositories on GitHub:
+
+1. **Set to Private During Creation**:
+   ```bash
+   # Using GitHub CLI
+   gh repo create my-repo --private --source=. --remote=origin
+
+   # Or set after creation
+   gh repo edit owner/repo --visibility private
+   ```
+
+2. **Verify Privacy Status**:
+   ```bash
+   # Check if repository is private
+   gh repo view owner/repo --json isPrivate
+
+   # Should return: {"isPrivate": true}
+   ```
+
+3. **Repository Settings Checklist**:
+   - Repository visibility: Private ✅
+   - Branch protection rules: Enabled for main/master
+   - Require pull request reviews: Enabled
+   - Disable force pushes: Enabled
+   - Disable repository deletion: Enabled
+
+### GitLab Privacy Settings
+
+When creating repositories on GitLab:
+
+1. **Set to Private During Creation**:
+   ```bash
+   # Using GitLab CLI
+   glab repo create my-repo --private
+
+   # Or using API
+   curl --request POST "https://gitlab.com/api/v4/projects" \
+     --header "PRIVATE-TOKEN: <your_access_token>" \
+     --data "name=my-repo&visibility=private"
+   ```
+
+2. **Verify Privacy Status**:
+   ```bash
+   # Check repository visibility
+   glab repo view owner/repo --json visibility
+
+   # Should return: {"visibility": "private"}
+   ```
+
+3. **Repository Settings Checklist**:
+   - Visibility level: Private ✅
+   - Merge request approvals: Required
+   - Protected branches: Enabled for main/master
+   - Push rules: Configured
+   - Repository mirroring: Disabled (unless needed)
+
+### Verification Commands
+
+**Pre-Push Verification Script**:
+```bash
+#!/bin/bash
+# Save as: /root/scripts/verify-repo-privacy.sh
+
+REPO_URL=$(git config --get remote.origin.url)
+
+if [[ $REPO_URL == *"github.com"* ]]; then
+  REPO=$(echo $REPO_URL | sed 's/.*github.com[:/]\(.*\)\.git/\1/')
+  PRIVACY=$(gh repo view $REPO --json isPrivate -q .isPrivate)
+  if [ "$PRIVACY" != "true" ]; then
+    echo "❌ ERROR: Repository is PUBLIC! Aborting push."
+    exit 1
+  fi
+  echo "✅ Repository is private"
+elif [[ $REPO_URL == *"gitlab.com"* ]]; then
+  REPO=$(echo $REPO_URL | sed 's/.*gitlab.com[:/]\(.*\)\.git/\1/')
+  VISIBILITY=$(glab repo view $REPO --json visibility -q .visibility)
+  if [ "$VISIBILITY" != "private" ]; then
+    echo "❌ ERROR: Repository is PUBLIC! Aborting push."
+    exit 1
+  fi
+  echo "✅ Repository is private"
+fi
+```
+
+**Git Pre-Push Hook** (automatic verification):
+```bash
+# Add to .git/hooks/pre-push in each repository
+#!/bin/bash
+/root/scripts/verify-repo-privacy.sh || exit 1
+```
+
+### Security Best Practices
+
+1. **Never Commit Sensitive Data**:
+   - API keys, tokens, passwords
+   - Database credentials
+   - SSL certificates
+   - Customer data
+   - Use `.gitignore` and environment variables
+
+2. **Audit Repository Access**:
+   ```bash
+   # GitHub: List collaborators
+   gh api repos/owner/repo/collaborators
+
+   # GitLab: List project members
+   glab api projects/:id/members
+   ```
+
+3. **Regular Privacy Audits**:
+   - Review repository visibility monthly
+   - Check collaborator access levels
+   - Verify branch protection rules
+   - Scan for exposed secrets: `git-secrets --scan`
+
+4. **Emergency Response**:
+   - If repository accidentally made public: Make private immediately
+   - Rotate all credentials that may have been exposed
+   - Review commit history for sensitive data
+   - Use `git filter-repo` to remove secrets from history if needed
+
+### Default Repository Template
+
+Create new repositories using this template:
+
+```bash
+#!/bin/bash
+# Usage: ./create-private-repo.sh <repo-name>
+
+REPO_NAME=$1
+
+# Create private GitHub repository
+gh repo create $REPO_NAME --private --source=. --remote=origin
+
+# Add .gitignore
+cat > .gitignore << 'EOF'
+.env
+.env.local
+*.key
+*.pem
+node_modules/
+.DS_Store
+secrets/
+EOF
+
+# Set up branch protection
+gh api repos/$(gh repo view --json nameWithOwner -q .nameWithOwner)/branches/main/protection \
+  -X PUT \
+  -f required_status_checks='null' \
+  -f enforce_admins=true \
+  -f required_pull_request_reviews='{"required_approving_review_count":1}' \
+  -f restrictions='null'
+
+echo "✅ Private repository created with security settings"
+```
+
+### Verification Checklist
+
+Before pushing code to any repository, verify:
+
+- [ ] Repository is set to private
+- [ ] No API keys or credentials in code
+- [ ] `.gitignore` includes sensitive files
+- [ ] Branch protection enabled
+- [ ] Only authorized collaborators have access
+- [ ] Pre-push hook configured (optional but recommended)
+
+**REMEMBER: Security is not optional. Always verify privacy settings before the first push.**
+
+### Pattern Name Extraction Rule #memory
+- **Pattern name is often the first word in the old title** - For single-word patterns like "Damier", extract from existing title before "-Wallcovering"
+- Example: "Damier Wallcovering | Innovationsusa" → Pattern = "Damier"
+
+### Title Color Rules (CRITICAL) #memory
+- **AI colors go to TAGS ONLY, never in titles** - If no spreadsheet/PDF color exists, title has NO color
+- **NEVER tag a title as "Page Not Found"** - Always validate pattern names are real names, not error messages
+- **Color Priority Chain**: SPREADSHEET → Scraped → PDF → (NO AI in titles!)
+- **AI colors**: Add to product tags as "Background Color X" and individual color tags
+- **Invalid patterns**: page not found, 404, error, not found, undefined, null → Use "Wallcovering" fallback
+- **Add "Review" tag if SKU not found on Koroseal site** - Flags products needing manual review
+- **Save skipped/failed products to PostgreSQL** - Table: `koroseal_update_logs` with timestamp
diff --git a/COMPLETED-PROCESSES.md b/COMPLETED-PROCESSES.md
index d930c2a2..84b51a8e 100644
--- a/COMPLETED-PROCESSES.md
+++ b/COMPLETED-PROCESSES.md
@@ -187,7 +187,7 @@ Example: `Travelers Palm Green (T10127) | Architectural Wallcoverings`
 
 ### Gemini 3.0 Configuration
 ```typescript
-const GEMINI_API_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_API_KEY = '${GOOGLE_API_KEY}';
 const GEMINI_MODEL = 'gemini-2.0-flash';
 const GEMINI_ENDPOINT = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent';
 ```
diff --git a/COMPLETED-PROCESSES.md.pre-scrub-2026-05-07.bak b/COMPLETED-PROCESSES.md.pre-scrub-2026-05-07.bak
new file mode 100644
index 00000000..d930c2a2
--- /dev/null
+++ b/COMPLETED-PROCESSES.md.pre-scrub-2026-05-07.bak
@@ -0,0 +1,250 @@
+# Completed Processes & Learnings
+
+**Last Updated:** 2026-02-01 19:40:00 UTC
+
+---
+
+## Summary
+
+| Metric | Value |
+|--------|-------|
+| Total Processes | 5 |
+| Total Products Updated | 3,107+ |
+| Completed | 2 |
+| Ongoing | 2 |
+| Partial | 1 |
+| Active Vendors | Thibaut, Koroseal, Maya Romanoff, Ralph Lauren |
+
+---
+
+## Process Reference (IDs for API calls)
+
+| ID | Name | Vendor |
+|----|------|--------|
+| `thibaut-bulk-update` | Thibaut Wallcoverings Bulk Update | Thibaut |
+| `koroseal-enhanced-update` | Koroseal Enhanced Product Update | Koroseal |
+| `koroseal-activation` | Koroseal Product Activation | Koroseal |
+| `architectural-wallcoverings-update` | Architectural Wallcoverings Bulk Update | Multiple |
+| `ralph-lauren-fabric-update` | Ralph Lauren Fabric Update | Ralph Lauren |
+
+---
+
+## Process History
+
+### 1. Thibaut Wallcoverings Bulk Update
+
+| Property | Value |
+|----------|-------|
+| **ID** | `thibaut-bulk-update` |
+| **Status** | ✅ COMPLETED |
+| **Vendor** | Thibaut |
+| **Products Updated** | 2,539 |
+| **Duration** | ~10 hours |
+| **Completed At** | 2026-01-31 06:01:55 UTC |
+| **Agent** | dw-thibaut-updater (Port 9902) |
+
+#### Title Format
+```
+{Pattern} {Colorway} | Thibaut Wallcoverings
+```
+Example: `Travelers Palm Green | Thibaut Wallcoverings`
+
+#### SEO Title Format
+```
+{Pattern} {Colorway} ({MFR-SKU}) | Architectural Wallcoverings
+```
+Example: `Travelers Palm Green (T10127) | Architectural Wallcoverings`
+
+#### Color Source Priority
+1. **Thibaut website `<title>` tag** (most reliable)
+   - Format: `PATTERN Wallcoverings (SKU) – COLORWAY | Thibaut`
+2. Fallback to handle parsing
+3. AI color analysis (Gemini 3.0) for tags only
+
+#### Key Learnings
+- Extract colorways from `<title>` tag, NOT from img alt attributes
+- Use pagination (20 pages max, 250 per page) to fetch all 3,371 Thibaut products
+- Skip already-updated SKUs using local JSON tracking file
+- Convert "all" batch size to 10000 limit in API handler
+- Title Case all pattern names and colorways
+- Gemini 3.0 for AI color/style analysis
+- Playwright for website scraping
+
+#### Metafields Updated
+- `custom.manufacturer_sku`
+- `dwc.manufacturer_sku`
+- `dwc.pattern_name`
+- `dwc.color`
+- `dwc.background_color`
+- `global.title_tag`
+- `global.description_tag`
+- `dwc.ai_generated_colors` (list)
+- `dwc.ai_generated_tags` (list)
+- `dwc.ai_generated_description`
+
+#### Errors
+- 4 products failed (network timeouts/scrape failures)
+
+---
+
+### 2. Koroseal Enhanced Product Update
+
+| Property | Value |
+|----------|-------|
+| **ID** | `koroseal-enhanced-update` |
+| **Status** | 🔄 ONGOING (Cron) |
+| **Vendor** | Koroseal |
+| **Products Updated** | Varies |
+| **Schedule** | Every 20 minutes |
+| **Agent** | koroseal-enhanced-update (Port 9897) |
+
+#### Title Format
+```
+{Pattern} {Color} ({MFR-SKU}) | Architectural Wallcoverings
+```
+
+#### Color Source Priority (CRITICAL)
+1. **TAK Specialty Spreadsheet** (for TAK-* SKUs) - ALWAYS FIRST
+2. **Type II Vinyl Spreadsheet** (for other SKUs)
+3. Scraped colorName from Koroseal website
+4. AI analysis (ONLY if no spreadsheet data exists)
+
+#### Spreadsheet URLs
+- **TAK Specialty**: https://docs.google.com/spreadsheets/d/1EjqtPSo9hqTai_UHW-iLVzaglOTHUdQxDmbjz3vnU8A
+- **Type II Vinyl**: https://docs.google.com/spreadsheets/d/1FYG7TGUUiim_RL25YJx5R9tBcgL3ilFlLy3dQISVSMo
+
+#### Key Learnings
+- NEVER use AI/Gemini for colors when spreadsheet has the data
+- Prefix search fallback: `SG13-02` not found → search `SG13`
+- Add "Review" tag if SKU not found on Koroseal website
+- Title Case conversion for all pattern/color names
+- Save skipped/failed products to PostgreSQL for review
+
+---
+
+### 3. Koroseal Product Activation
+
+| Property | Value |
+|----------|-------|
+| **ID** | `koroseal-activation` |
+| **Status** | 🔄 ONGOING |
+| **Vendor** | Koroseal |
+| **Products Activated** | 91 |
+| **Progress** | 91/91 |
+| **Schedule** | Cron (every 20 min) |
+
+#### Key Learnings
+- Activate draft Koroseal products after verification
+- Check against TAK/Type II spreadsheets before activation
+- Add to active collection after activation
+
+---
+
+### 4. Architectural Wallcoverings Bulk Update
+
+| Property | Value |
+|----------|-------|
+| **ID** | `architectural-wallcoverings-update` |
+| **Status** | 🔄 ONGOING |
+| **Vendor** | Multiple (Koroseal, etc.) |
+| **Products Updated** | 244 |
+
+#### Title Format
+```
+{Pattern} {Color} ({MFR-SKU}) | Architectural Wallcoverings
+```
+
+#### Key Learnings
+- Handle parsing priority: Tags > SKU patterns
+- Use Google Spreadsheets for TAK/Type II colors
+- Add "Review" tag for products not found on vendor site
+
+---
+
+### 5. Ralph Lauren Fabric Update
+
+| Property | Value |
+|----------|-------|
+| **ID** | `ralph-lauren-fabric-update` |
+| **Status** | ✅ COMPLETED |
+| **Vendor** | Ralph Lauren |
+| **Products Updated** | 233 |
+| **User Stories** | US-001 through US-010 completed |
+
+#### Title Format
+```
+{Pattern} {Color} | Ralph Lauren Fabrics
+```
+
+#### Key Learnings
+- Extract fabric specifications from Ralph Lauren website
+- Handle wide-width and narrow-width fabric variants
+- Update content/material composition metafields
+
+---
+
+## Technical Reference
+
+### Gemini 3.0 Configuration
+```typescript
+const GEMINI_API_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_MODEL = 'gemini-2.0-flash';
+const GEMINI_ENDPOINT = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent';
+```
+
+### Shopify Configuration
+```typescript
+const SHOPIFY_STORE = 'designer-laboratory-sandbox.myshopify.com';
+const SHOPIFY_API_VERSION = '2024-01';
+```
+
+### PostgreSQL Database
+```
+Host: 127.0.0.1
+Database: dw_unified
+User: dw_admin
+```
+
+---
+
+## Agent Ports Reference
+
+| Agent | Port | URL |
+|-------|------|-----|
+| Thibaut Updater | 9902 | http://45.61.58.125:9902 |
+| Koroseal Enhanced | 9897 | http://45.61.58.125:9897 |
+| Maya Romanoff | 9903 | http://45.61.58.125:9903 |
+| Architectural Updater | 9897 | http://45.61.58.125:9897 |
+
+**Auth:** admin / ***REMOVED***
+
+---
+
+## API Endpoint
+
+**View All Completed Processes:**
+```bash
+curl http://45.61.58.125:7400/api/completed-processes
+```
+
+**Response Fields:**
+- `processes[]` - Array of process objects
+- `processes[].id` - Unique process ID (use for reference)
+- `processes[].name` - Human-readable name
+- `processes[].vendor` - Vendor name
+- `processes[].status` - completed | ongoing | partial
+- `processes[].progress` - X/Y format for ongoing processes
+- `processes[].productsUpdated` - Count of products updated
+- `processes[].learnings[]` - Array of key learnings
+- `totals` - Summary statistics
+
+---
+
+## Dashboard
+
+View all completed processes in DW Central:
+**http://45.61.58.125:7400** → "Completed Processes & Learnings" section
+
+---
+
+*This file is auto-generated and updated when processes complete.*
diff --git a/DW-Agents/.gitignore b/DW-Agents/.gitignore
index 8c12b163..9da1c03e 100644
--- a/DW-Agents/.gitignore
+++ b/DW-Agents/.gitignore
@@ -47,3 +47,5 @@ temp/
 
 # PM2
 .pm2/
+.next/
+*.bak
diff --git a/DW-Agents/dw-agents/agent-digital-samples/digital-samples-agent.ts b/DW-Agents/dw-agents/agent-digital-samples/digital-samples-agent.ts
index ed0b77a2..5794abf1 100644
--- a/DW-Agents/dw-agents/agent-digital-samples/digital-samples-agent.ts
+++ b/DW-Agents/dw-agents/agent-digital-samples/digital-samples-agent.ts
@@ -53,7 +53,7 @@ const SHOPIFY_TOKEN = process.env.SHOPIFY_ACCESS_TOKEN || 'shpat_b2a369f17298946
 const API_VERSION = '2024-07';
 
 // Slack configuration
-const SLACK_BOT_TOKEN = process.env.SLACK_BOT_TOKEN || 'xoxb-3958182050256-9814366234406-HiR1ybK6HT8JViWDEpjXpmsq';
+const SLACK_BOT_TOKEN = process.env.SLACK_BOT_TOKEN || '${SLACK_BOT_TOKEN}';
 const SLACK_CHANNEL = 'new-products-on-shopify';
 const slackClient = new WebClient(SLACK_BOT_TOKEN);
 
diff --git a/DW-Agents/dw-agents/agent-marketing/marketing-agent.ts b/DW-Agents/dw-agents/agent-marketing/marketing-agent.ts
index e121132e..148daaed 100644
--- a/DW-Agents/dw-agents/agent-marketing/marketing-agent.ts
+++ b/DW-Agents/dw-agents/agent-marketing/marketing-agent.ts
@@ -64,7 +64,7 @@ const CC_ACCESS_TOKEN = process.env.CONSTANT_CONTACT_ACCESS_TOKEN || '';
 
 // Anthropic Claude
 const anthropic = new Anthropic({
-  apiKey: process.env.ANTHROPIC_API_KEY || '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',
+  apiKey: process.env.ANTHROPIC_API_KEY || "${ANTHROPIC_API_KEY}",
 });
 
 // Stats tracking
diff --git a/DW-Agents/dw-agents/agent-purchasing-office/purchasing-office-agent.ts b/DW-Agents/dw-agents/agent-purchasing-office/purchasing-office-agent.ts
index 0af3e82d..d436aa12 100755
--- a/DW-Agents/dw-agents/agent-purchasing-office/purchasing-office-agent.ts
+++ b/DW-Agents/dw-agents/agent-purchasing-office/purchasing-office-agent.ts
@@ -36,7 +36,7 @@ const AMAZON_BUSINESS_EMAIL = 'info@designerwallcoverings.com';
 const AMAZON_BUSINESS_PASSWORD = '*Amazonaccess911*';
 
 // Anthropic Claude
-const ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY || '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';
+const ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY || "${ANTHROPIC_API_KEY}";
 const anthropic = new Anthropic({
   apiKey: ANTHROPIC_API_KEY,
 });
diff --git a/DW-Agents/dw-agents/agent-security/security-agent.ts b/DW-Agents/dw-agents/agent-security/security-agent.ts
index 90664b4a..8438a6dd 100644
--- a/DW-Agents/dw-agents/agent-security/security-agent.ts
+++ b/DW-Agents/dw-agents/agent-security/security-agent.ts
@@ -50,7 +50,7 @@ app.use(chatMiddleware({
 
 // Anthropic AI client
 const anthropic = new Anthropic({
-  apiKey: process.env.ANTHROPIC_API_KEY || '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',
+  apiKey: process.env.ANTHROPIC_API_KEY || "${ANTHROPIC_API_KEY}",
 });
 
 // Middleware
diff --git a/DW-Agents/dw-agents/agent-slack/slack-agent.js b/DW-Agents/dw-agents/agent-slack/slack-agent.js
index 10975f20..a030568b 100644
--- a/DW-Agents/dw-agents/agent-slack/slack-agent.js
+++ b/DW-Agents/dw-agents/agent-slack/slack-agent.js
@@ -9,9 +9,9 @@ import cookieParser from 'cookie-parser';
 import session from 'express-session';
 import { Pool } from 'pg';
 const PORT = parseInt(process.env.PORT || '9887');
-const SLACK_BOT_TOKEN = process.env.SLACK_BOT_TOKEN || 'xoxb-3958182050256-9852565284259-8kfXhJQWVsf515doMRI67AHQ';
+const SLACK_BOT_TOKEN = process.env.SLACK_BOT_TOKEN || '${SLACK_BOT_TOKEN}';
 const SLACK_SIGNING_SECRET = process.env.SLACK_SIGNING_SECRET || 'b1b92b95a310728b7f2f26373da10ba3';
-const SLACK_WEBHOOK = process.env.SLACK_WEBHOOK || 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = process.env.SLACK_WEBHOOK || '${SLACK_WEBHOOK_URL}';
 const STEVE_USER_ID = 'U03TV3UC2V7';
 const ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY || '';
 const DB_URL = 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified';
diff --git a/DW-Agents/dw-agents/agent-slack/slack-agent.ts b/DW-Agents/dw-agents/agent-slack/slack-agent.ts
index 906228e9..46c6537d 100644
--- a/DW-Agents/dw-agents/agent-slack/slack-agent.ts
+++ b/DW-Agents/dw-agents/agent-slack/slack-agent.ts
@@ -11,9 +11,9 @@ import session from 'express-session';
 import { Pool } from 'pg';
 
 const PORT = parseInt(process.env.PORT || '9887');
-const SLACK_BOT_TOKEN = process.env.SLACK_BOT_TOKEN || 'xoxb-3958182050256-9852565284259-8kfXhJQWVsf515doMRI67AHQ';
+const SLACK_BOT_TOKEN = process.env.SLACK_BOT_TOKEN || '${SLACK_BOT_TOKEN}';
 const SLACK_SIGNING_SECRET = process.env.SLACK_SIGNING_SECRET || 'b1b92b95a310728b7f2f26373da10ba3';
-const SLACK_WEBHOOK = process.env.SLACK_WEBHOOK || 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = process.env.SLACK_WEBHOOK || '${SLACK_WEBHOOK_URL}';
 const STEVE_USER_ID = 'U03TV3UC2V7';
 const ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY || '';
 const DB_URL = 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified';
diff --git a/DW-Agents/dw-agents/agent-task-orchestrator/ecosystem.config.js b/DW-Agents/dw-agents/agent-task-orchestrator/ecosystem.config.js
index bdbec351..90007844 100644
--- a/DW-Agents/dw-agents/agent-task-orchestrator/ecosystem.config.js
+++ b/DW-Agents/dw-agents/agent-task-orchestrator/ecosystem.config.js
@@ -40,7 +40,7 @@ module.exports = {
       env: {
         NODE_ENV: 'production',
         PORT: 9879,
-        SLACK_BOT_TOKEN: 'xoxb-3958182050256-9814366234406-HiR1ybK6HT8JViWDEpjXpmsq',
+        SLACK_BOT_TOKEN: '${SLACK_BOT_TOKEN}',
         SHOPIFY_STORE_DOMAIN: 'designer-laboratory-sandbox.myshopify.com',
         SHOPIFY_ACCESS_TOKEN: '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'
       },
diff --git a/DW-Agents/dw-agents/agent-thibaut-updater/thibaut-updater-agent.ts b/DW-Agents/dw-agents/agent-thibaut-updater/thibaut-updater-agent.ts
index 54251830..e2ea9cde 100644
--- a/DW-Agents/dw-agents/agent-thibaut-updater/thibaut-updater-agent.ts
+++ b/DW-Agents/dw-agents/agent-thibaut-updater/thibaut-updater-agent.ts
@@ -47,7 +47,7 @@ const app = express();
 const PORT = 9902;
 
 // Gemini 3.0 Configuration (MANDATORY - per CLAUDE.md)
-const GEMINI_API_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_API_KEY = '${GOOGLE_API_KEY}';
 const GEMINI_ENDPOINT = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent';
 
 // Middleware
diff --git a/DW-Agents/dw-agents/agent-zendesk-chat/zendesk-chat-agent.ts b/DW-Agents/dw-agents/agent-zendesk-chat/zendesk-chat-agent.ts
index 135fdd23..479c716a 100644
--- a/DW-Agents/dw-agents/agent-zendesk-chat/zendesk-chat-agent.ts
+++ b/DW-Agents/dw-agents/agent-zendesk-chat/zendesk-chat-agent.ts
@@ -38,7 +38,7 @@ app.use(chatMiddleware({
 
 // Anthropic AI client
 const anthropic = new Anthropic({
-  apiKey: process.env.ANTHROPIC_API_KEY || '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',
+  apiKey: process.env.ANTHROPIC_API_KEY || "${ANTHROPIC_API_KEY}",
 });
 
 // Chat configuration (No paid services required - using local data)
diff --git a/DW-Agents/dw-agents/digital-samples-agent.ts b/DW-Agents/dw-agents/digital-samples-agent.ts
index 520111c3..82990117 100644
--- a/DW-Agents/dw-agents/digital-samples-agent.ts
+++ b/DW-Agents/dw-agents/digital-samples-agent.ts
@@ -43,7 +43,7 @@ const SHOPIFY_TOKEN = process.env.SHOPIFY_ACCESS_TOKEN || 'shpat_b2a369f17298946
 const API_VERSION = '2024-07';
 
 // Slack configuration
-const SLACK_BOT_TOKEN = process.env.SLACK_BOT_TOKEN || 'xoxb-3958182050256-9814366234406-HiR1ybK6HT8JViWDEpjXpmsq';
+const SLACK_BOT_TOKEN = process.env.SLACK_BOT_TOKEN || '${SLACK_BOT_TOKEN}';
 const SLACK_CHANNEL = 'new-products-on-shopify';
 const slackClient = new WebClient(SLACK_BOT_TOKEN);
 
diff --git a/DW-Agents/dw-agents/dw-instagram-agent/server.js b/DW-Agents/dw-agents/dw-instagram-agent/server.js
index fafd4b8b..98d565c5 100644
--- a/DW-Agents/dw-agents/dw-instagram-agent/server.js
+++ b/DW-Agents/dw-agents/dw-instagram-agent/server.js
@@ -259,7 +259,7 @@ ${CORE_HASHTAGS} ${locationTags} ${vendorTags} ${industryTags}`;
 // -------------------------------------------------------------------
 // Slack Notification (uses HTTPS for hooks.slack.com)
 // -------------------------------------------------------------------
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
 function sendSlackNotification(message) {
   const data = JSON.stringify({ text: message });
diff --git a/DW-Agents/dw-agents/ecosystem-complete.config.js b/DW-Agents/dw-agents/ecosystem-complete.config.js
index 5c67d569..fd3ce7ee 100644
--- a/DW-Agents/dw-agents/ecosystem-complete.config.js
+++ b/DW-Agents/dw-agents/ecosystem-complete.config.js
@@ -182,7 +182,7 @@ module.exports = {
     createAgentConfig('thibaut-updater', 9902, 'agent-thibaut-updater/thibaut-updater-agent.ts', {
       SHOPIFY_STORE_DOMAIN: process.env.SHOPIFY_STORE_DOMAIN,
       SHOPIFY_ACCESS_TOKEN: process.env.SHOPIFY_ACCESS_TOKEN,
-      GEMINI_API_KEY: 'REDACTED_GEMINI_KEY'
+      GEMINI_API_KEY: '${GOOGLE_API_KEY}'
     })
   ]
 };
diff --git a/DW-Agents/dw-agents/get-amazon-api-credentials.sh b/DW-Agents/dw-agents/get-amazon-api-credentials.sh
index 996afbe7..4162894b 100755
--- a/DW-Agents/dw-agents/get-amazon-api-credentials.sh
+++ b/DW-Agents/dw-agents/get-amazon-api-credentials.sh
@@ -78,7 +78,7 @@ PAAPI_HOST=webservices.amazon.com
 PAAPI_REGION=us-east-1
 
 # Anthropic API Key
-ANTHROPIC_API_KEY=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
+ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
 EOF
 
 echo "✅ Credentials saved!"
diff --git a/DW-Agents/dw-agents/marketing-agent.ts b/DW-Agents/dw-agents/marketing-agent.ts
index d5850ccc..9a147fab 100644
--- a/DW-Agents/dw-agents/marketing-agent.ts
+++ b/DW-Agents/dw-agents/marketing-agent.ts
@@ -130,7 +130,7 @@ const CC_ACCESS_TOKEN = process.env.CONSTANT_CONTACT_ACCESS_TOKEN || '';
 
 // Anthropic Claude
 const anthropic = new Anthropic({
-  apiKey: process.env.ANTHROPIC_API_KEY || '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'
+  apiKey: process.env.ANTHROPIC_API_KEY || "${ANTHROPIC_API_KEY}"
 });
 
 // Types for Shopify orders
diff --git a/DW-Agents/dw-agents/purchasing-office-agent.ts b/DW-Agents/dw-agents/purchasing-office-agent.ts
index 5cfb4641..9621e8cd 100644
--- a/DW-Agents/dw-agents/purchasing-office-agent.ts
+++ b/DW-Agents/dw-agents/purchasing-office-agent.ts
@@ -48,7 +48,7 @@ const AMAZON_BUSINESS_EMAIL = 'info@designerwallcoverings.com';
 const AMAZON_BUSINESS_PASSWORD = '*Amazonaccess911*';
 
 // Anthropic Claude
-const ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY || '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';
+const ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY || "${ANTHROPIC_API_KEY}";
 const anthropic = new Anthropic({
   apiKey: ANTHROPIC_API_KEY,
 });
diff --git a/DW-Agents/dw-agents/shared-executive-core.ts b/DW-Agents/dw-agents/shared-executive-core.ts
index 3d35dd4d..be72051d 100644
--- a/DW-Agents/dw-agents/shared-executive-core.ts
+++ b/DW-Agents/dw-agents/shared-executive-core.ts
@@ -26,7 +26,7 @@ export const DB_URL = 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_
 export const SHOPIFY_STORE = 'designer-laboratory-sandbox.myshopify.com';
 export const SHOPIFY_TOKEN = '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';
 export const SHOPIFY_API_VERSION = '2024-07';
-export const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+export const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 export const SERVER_IP = '45.61.58.125';
 
 export const EXECUTIVE_AGENTS: Record<string, { port: number; name: string; role: string; emoji: string }> = {
diff --git a/DW-Agents/dw-agents/versions/v1.1.110725/ecosystem.config.js b/DW-Agents/dw-agents/versions/v1.1.110725/ecosystem.config.js
index 238c14fc..f3dd4e22 100644
--- a/DW-Agents/dw-agents/versions/v1.1.110725/ecosystem.config.js
+++ b/DW-Agents/dw-agents/versions/v1.1.110725/ecosystem.config.js
@@ -40,7 +40,7 @@ module.exports = {
       env: {
         NODE_ENV: 'production',
         PORT: 9879,
-        SLACK_BOT_TOKEN: 'xoxb-3958182050256-9814366234406-HiR1ybK6HT8JViWDEpjXpmsq',
+        SLACK_BOT_TOKEN: '${SLACK_BOT_TOKEN}',
         SHOPIFY_STORE_DOMAIN: 'designer-laboratory-sandbox.myshopify.com',
         SHOPIFY_ACCESS_TOKEN: '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'
       },
diff --git a/DW-Agents/dw-agents/zendesk-chat-agent.ts b/DW-Agents/dw-agents/zendesk-chat-agent.ts
index 43be196c..4c97432d 100644
--- a/DW-Agents/dw-agents/zendesk-chat-agent.ts
+++ b/DW-Agents/dw-agents/zendesk-chat-agent.ts
@@ -26,7 +26,7 @@ const PORT = 9884;
 
 // Anthropic AI client
 const anthropic = new Anthropic({
-  apiKey: process.env.ANTHROPIC_API_KEY || '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',
+  apiKey: process.env.ANTHROPIC_API_KEY || "${ANTHROPIC_API_KEY}",
 });
 
 // Chat configuration (No paid services required - using local data)
diff --git a/DW-Agents/ecosystem.config.js b/DW-Agents/ecosystem.config.js
index bf5f29b2..0d614ff6 100644
--- a/DW-Agents/ecosystem.config.js
+++ b/DW-Agents/ecosystem.config.js
@@ -42,7 +42,7 @@ module.exports = {
         NODE_ENV: 'production',
         PORT: 9879,
         NODE_OPTIONS: '--import tsx',
-        SLACK_BOT_TOKEN: 'xoxb-3958182050256-9814366234406-HiR1ybK6HT8JViWDEpjXpmsq',
+        SLACK_BOT_TOKEN: '${SLACK_BOT_TOKEN}',
         SHOPIFY_STORE_DOMAIN: 'designer-laboratory-sandbox.myshopify.com',
         SHOPIFY_ACCESS_TOKEN: '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'
       },
@@ -89,7 +89,7 @@ module.exports = {
         NODE_ENV: 'production',
         PORT: 9880,
         NODE_OPTIONS: '--import tsx',
-        ANTHROPIC_API_KEY: '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'
+        ANTHROPIC_API_KEY: "${ANTHROPIC_API_KEY}"
       },
       error_file: '/root/DW-Agents/logs/purchasing-error.log',
       out_file: '/root/DW-Agents/logs/purchasing-out.log',
@@ -111,7 +111,7 @@ module.exports = {
         NODE_OPTIONS: '--import tsx',
         SHOPIFY_STORE_DOMAIN: 'designer-laboratory-sandbox.myshopify.com',
         SHOPIFY_ACCESS_TOKEN: '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',
-        ANTHROPIC_API_KEY: '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'
+        ANTHROPIC_API_KEY: "${ANTHROPIC_API_KEY}"
       },
       error_file: '/root/DW-Agents/logs/marketing-error.log',
       out_file: '/root/DW-Agents/logs/marketing-out.log',
@@ -151,7 +151,7 @@ module.exports = {
         NODE_ENV: 'production',
         PORT: 9885,
         NODE_OPTIONS: '--import tsx',
-        ANTHROPIC_API_KEY: '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'
+        ANTHROPIC_API_KEY: "${ANTHROPIC_API_KEY}"
       },
       error_file: '/root/DW-Agents/logs/accounting-error.log',
       out_file: '/root/DW-Agents/logs/accounting-out.log',
@@ -171,7 +171,7 @@ module.exports = {
         NODE_ENV: 'production',
         PORT: 9884,
         NODE_OPTIONS: '--import tsx',
-        ANTHROPIC_API_KEY: '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',
+        ANTHROPIC_API_KEY: "${ANTHROPIC_API_KEY}",
         ZENDESK_EMAIL: 'steve@designer-laboratory.com',
         ZENDESK_TOKEN: 'jJlpGPXwsJKzORTBiMJ40PEvZ0l0wt6XU0KPfRJT',
         ZENDESK_SUBDOMAIN: 'designerwallcoverings'
@@ -232,7 +232,7 @@ module.exports = {
         NODE_ENV: 'production',
         PORT: 9883,
         NODE_OPTIONS: '--import tsx',
-        ANTHROPIC_API_KEY: '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'
+        ANTHROPIC_API_KEY: "${ANTHROPIC_API_KEY}"
       },
       error_file: '/root/DW-Agents/logs/trend-research-error.log',
       out_file: '/root/DW-Agents/logs/trend-research-out.log',
@@ -491,9 +491,9 @@ module.exports = {
         NODE_ENV: 'production',
         PORT: 9887,
         NODE_OPTIONS: '--import tsx',
-        SLACK_BOT_TOKEN: 'xoxb-3958182050256-9852565284259-8kfXhJQWVsf515doMRI67AHQ',
+        SLACK_BOT_TOKEN: '${SLACK_BOT_TOKEN}',
         SLACK_SIGNING_SECRET: 'b1b92b95a310728b7f2f26373da10ba3',
-        ANTHROPIC_API_KEY: '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'
+        ANTHROPIC_API_KEY: "${ANTHROPIC_API_KEY}"
       },
       error_file: '/root/DW-Agents/logs/slack-agent-error.log',
       out_file: '/root/DW-Agents/logs/slack-agent-out.log',
diff --git a/DW-MCP/.gitignore b/DW-MCP/.gitignore
index a760af57..8c1cb485 100644
--- a/DW-MCP/.gitignore
+++ b/DW-MCP/.gitignore
@@ -103,3 +103,10 @@ dist
 *.swp
 *.swo
 *~
+.env.local
+.env.*.local
+.env.*
+tmp/
+dist/
+.next/
+*.bak
diff --git a/DW-MCP/wine-tracker-config.md b/DW-MCP/wine-tracker-config.md
index 8f08771e..5a8f8805 100644
--- a/DW-MCP/wine-tracker-config.md
+++ b/DW-MCP/wine-tracker-config.md
@@ -15,7 +15,7 @@
 
 ### Option A: Use Existing Slack App
 You already have these Slack credentials in `/root/DW-MCP/.env`:
-- SLACK_BOT_TOKEN: `xoxb-3958182050256-9814366234406-HiR1ybK6HT8JViWDEpjXpmsq`
+- SLACK_BOT_TOKEN: `${SLACK_BOT_TOKEN}`
 - SLACK_APP_ID: `A09PYA21JLE`
 
 To enable webhooks for this app:
diff --git a/DW-Product-Pages/.gitignore b/DW-Product-Pages/.gitignore
new file mode 100644
index 00000000..7e6a9c3e
--- /dev/null
+++ b/DW-Product-Pages/.gitignore
@@ -0,0 +1,12 @@
+node_modules/
+.env
+.env.local
+.env.*.local
+.env.*
+tmp/
+*.log
+.DS_Store
+dist/
+build/
+.next/
+*.bak
diff --git a/DW-Programming/.gitignore b/DW-Programming/.gitignore
new file mode 100644
index 00000000..7e6a9c3e
--- /dev/null
+++ b/DW-Programming/.gitignore
@@ -0,0 +1,12 @@
+node_modules/
+.env
+.env.local
+.env.*.local
+.env.*
+tmp/
+*.log
+.DS_Store
+dist/
+build/
+.next/
+*.bak
diff --git a/DW-Programming/ImportNewSkufromURL/dwjs-ai-retag.ts b/DW-Programming/ImportNewSkufromURL/dwjs-ai-retag.ts
index 6ac9ef5c..86aff4e1 100644
--- a/DW-Programming/ImportNewSkufromURL/dwjs-ai-retag.ts
+++ b/DW-Programming/ImportNewSkufromURL/dwjs-ai-retag.ts
@@ -18,10 +18,10 @@ import * as fs from 'fs';
 const SHOPIFY_STORE = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_ACCESS_TOKEN = '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';
 const SHOPIFY_API_VERSION = '2024-07';
-const ANTHROPIC_API_KEY = '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';
+const ANTHROPIC_API_KEY = "${ANTHROPIC_API_KEY}";
 
 // Slack config for completion notification
-const SLACK_BOT_TOKEN = 'xoxb-3958182050256-9814366234406-HiR1ybK6HT8JViWDEpjXpmsq';
+const SLACK_BOT_TOKEN = '${SLACK_BOT_TOKEN}';
 const STEVE_USER_ID = 'U03TV3UC2V7';
 
 const anthropic = new Anthropic({ apiKey: ANTHROPIC_API_KEY });
diff --git a/DW-Programming/ImportNewSkufromURL/dwjs-comprehensive-update.ts b/DW-Programming/ImportNewSkufromURL/dwjs-comprehensive-update.ts
index 84f7f655..f8417c14 100644
--- a/DW-Programming/ImportNewSkufromURL/dwjs-comprehensive-update.ts
+++ b/DW-Programming/ImportNewSkufromURL/dwjs-comprehensive-update.ts
@@ -18,7 +18,7 @@ import * as fs from 'fs';
 
 const SHOPIFY_STORE = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_TOKEN = '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';
-const GEMINI_API_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_API_KEY = '${GOOGLE_API_KEY}';
 
 // Progress tracking
 const PROGRESS_FILE = './dwjs-comprehensive-progress.json';
diff --git a/DW-Programming/ImportNewSkufromURL/dwjs-interior-design-update.js b/DW-Programming/ImportNewSkufromURL/dwjs-interior-design-update.js
index f525c788..4de569e6 100644
--- a/DW-Programming/ImportNewSkufromURL/dwjs-interior-design-update.js
+++ b/DW-Programming/ImportNewSkufromURL/dwjs-interior-design-update.js
@@ -19,7 +19,7 @@ const fs = require('fs');
 
 const SHOPIFY_STORE = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_TOKEN = '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';
-const GEMINI_API_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_API_KEY = '${GOOGLE_API_KEY}';
 
 // Progress tracking
 const PROGRESS_FILE = './dwjs-interior-design-progress.json';
diff --git a/DW-Programming/ImportNewSkufromURL/dwjs-interior-design-update.ts b/DW-Programming/ImportNewSkufromURL/dwjs-interior-design-update.ts
index 5d0ceb4e..441a81c2 100644
--- a/DW-Programming/ImportNewSkufromURL/dwjs-interior-design-update.ts
+++ b/DW-Programming/ImportNewSkufromURL/dwjs-interior-design-update.ts
@@ -19,7 +19,7 @@ import * as fs from 'fs';
 
 const SHOPIFY_STORE = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_TOKEN = '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';
-const GEMINI_API_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_API_KEY = '${GOOGLE_API_KEY}';
 
 // Progress tracking
 const PROGRESS_FILE = './dwjs-interior-design-progress.json';
diff --git a/DW-Programming/ImportNewSkufromURL/fix-all-dwpd-colors.ts b/DW-Programming/ImportNewSkufromURL/fix-all-dwpd-colors.ts
index c78f745c..7191f09b 100644
--- a/DW-Programming/ImportNewSkufromURL/fix-all-dwpd-colors.ts
+++ b/DW-Programming/ImportNewSkufromURL/fix-all-dwpd-colors.ts
@@ -12,7 +12,7 @@ import fetch from 'node-fetch';
 const SHOPIFY_STORE = process.env.SHOPIFY_STORE_DOMAIN || 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_ACCESS_TOKEN = process.env.SHOPIFY_ADMIN_ACCESS_TOKEN || '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';
 const SHOPIFY_API_VERSION = '2024-07';
-const ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY || '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';
+const ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY || "${ANTHROPIC_API_KEY}";
 
 const anthropic = new Anthropic({ apiKey: ANTHROPIC_API_KEY });
 
diff --git a/DW-Programming/ImportNewSkufromURL/fix-color-tags.ts b/DW-Programming/ImportNewSkufromURL/fix-color-tags.ts
index fb2c1bfd..2b667117 100644
--- a/DW-Programming/ImportNewSkufromURL/fix-color-tags.ts
+++ b/DW-Programming/ImportNewSkufromURL/fix-color-tags.ts
@@ -11,7 +11,7 @@ import fetch from 'node-fetch';
 const SHOPIFY_STORE = process.env.SHOPIFY_STORE_DOMAIN || 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_ACCESS_TOKEN = process.env.SHOPIFY_ADMIN_ACCESS_TOKEN || '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';
 const SHOPIFY_API_VERSION = '2024-07';
-const ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY || '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';
+const ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY || "${ANTHROPIC_API_KEY}";
 
 const anthropic = new Anthropic({ apiKey: ANTHROPIC_API_KEY });
 
diff --git a/DW-Programming/ImportNewSkufromURL/fix-dwjs-red-tags.ts b/DW-Programming/ImportNewSkufromURL/fix-dwjs-red-tags.ts
index 75b6a84d..170356f6 100644
--- a/DW-Programming/ImportNewSkufromURL/fix-dwjs-red-tags.ts
+++ b/DW-Programming/ImportNewSkufromURL/fix-dwjs-red-tags.ts
@@ -14,7 +14,7 @@ import fetch from 'node-fetch';
 const SHOPIFY_STORE = process.env.SHOPIFY_STORE_DOMAIN || 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_ACCESS_TOKEN = process.env.SHOPIFY_ADMIN_ACCESS_TOKEN || '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';
 const SHOPIFY_API_VERSION = '2024-07';
-const ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY || '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';
+const ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY || "${ANTHROPIC_API_KEY}";
 
 const anthropic = new Anthropic({ apiKey: ANTHROPIC_API_KEY });
 
diff --git a/DW-Programming/ImportNewSkufromURL/fix-lod-descriptions.ts b/DW-Programming/ImportNewSkufromURL/fix-lod-descriptions.ts
index bf9b88a0..ce31c0d3 100644
--- a/DW-Programming/ImportNewSkufromURL/fix-lod-descriptions.ts
+++ b/DW-Programming/ImportNewSkufromURL/fix-lod-descriptions.ts
@@ -12,7 +12,7 @@ import fetch from 'node-fetch';
 const SHOPIFY_STORE = process.env.SHOPIFY_STORE_DOMAIN || 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_ACCESS_TOKEN = process.env.SHOPIFY_ADMIN_ACCESS_TOKEN || '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';
 const SHOPIFY_API_VERSION = '2024-07';
-const ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY || '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';
+const ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY || "${ANTHROPIC_API_KEY}";
 
 const anthropic = new Anthropic({ apiKey: ANTHROPIC_API_KEY });
 
diff --git a/DW-Programming/ImportNewSkufromURL/koroseal-architectural-bulk-update.js b/DW-Programming/ImportNewSkufromURL/koroseal-architectural-bulk-update.js
index 86ba9af8..98f94415 100644
--- a/DW-Programming/ImportNewSkufromURL/koroseal-architectural-bulk-update.js
+++ b/DW-Programming/ImportNewSkufromURL/koroseal-architectural-bulk-update.js
@@ -14,7 +14,7 @@ const shopify = new Shopify({
   apiVersion: '2024-01'
 });
 
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 const SEO_PREFIX = 'Architectural wallcoverings for commercial and high-end interiors. Specification-grade materials from your one stop resource for over 20 years. ';
 const TARGET_TYPE = 'Architectural Wallcoverings';
 const TARGET_CATEGORY = 'Home & Garden > Building Materials';
diff --git a/DW-Programming/ImportNewSkufromURL/lib/slack-notify.ts b/DW-Programming/ImportNewSkufromURL/lib/slack-notify.ts
index 13d11a61..15e2c55b 100644
--- a/DW-Programming/ImportNewSkufromURL/lib/slack-notify.ts
+++ b/DW-Programming/ImportNewSkufromURL/lib/slack-notify.ts
@@ -4,7 +4,7 @@
 
 import { WebClient } from '@slack/web-api';
 
-const SLACK_BOT_TOKEN = process.env.SLACK_BOT_TOKEN || 'xoxb-3958182050256-9814366234406-HiR1ybK6HT8JViWDEpjXpmsq';
+const SLACK_BOT_TOKEN = process.env.SLACK_BOT_TOKEN || '${SLACK_BOT_TOKEN}';
 const CHANNEL = 'new-products-on-shopify';
 
 let client: WebClient | null = null;
diff --git a/DW-Programming/ImportNewSkufromURL/plugins/temp-clone/.github/workflows/claude.yml b/DW-Programming/ImportNewSkufromURL/plugins/temp-clone/.github/workflows/claude.yml
index ab28f5fc..d21c301d 100644
--- a/DW-Programming/ImportNewSkufromURL/plugins/temp-clone/.github/workflows/claude.yml
+++ b/DW-Programming/ImportNewSkufromURL/plugins/temp-clone/.github/workflows/claude.yml
@@ -25,7 +25,7 @@ jobs:
       id-token: write
     steps:
       - name: Checkout repository
-        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683  # v4
+        uses: actions/checkout@${CLOUDFLARE_API_TOKEN}  # v4
         with:
           fetch-depth: 1
 
diff --git a/DW-Programming/ImportNewSkufromURL/plugins/temp-clone/plugins/code-review/commands/code-review.md b/DW-Programming/ImportNewSkufromURL/plugins/temp-clone/plugins/code-review/commands/code-review.md
index 51d1d779..694a1c08 100644
--- a/DW-Programming/ImportNewSkufromURL/plugins/temp-clone/plugins/code-review/commands/code-review.md
+++ b/DW-Programming/ImportNewSkufromURL/plugins/temp-clone/plugins/code-review/commands/code-review.md
@@ -101,7 +101,7 @@ No issues found. Checked for bugs and CLAUDE.md compliance.
 
 ---
 
-- When linking to code in inline comments, follow the following format precisely, otherwise the Markdown preview won't render correctly: https://github.com/anthropics/claude-code/blob/c21d3c10bc8e898b7ac1a2d745bdc9bc4e423afe/package.json#L10-L15
+- When linking to code in inline comments, follow the following format precisely, otherwise the Markdown preview won't render correctly: https://github.com/anthropics/claude-code/blob/${CLOUDFLARE_API_TOKEN}/package.json#L10-L15
   - Requires full git sha
   - You must provide the full sha. Commands like `https://github.com/owner/repo/blob/$(git rev-parse HEAD)/foo/bar` will not work, since your comment will be directly rendered in Markdown.
   - Repo name must match the repo you're code reviewing
diff --git a/DW-Programming/ImportNewSkufromURL/scripts/koroseal-enrichment.ts b/DW-Programming/ImportNewSkufromURL/scripts/koroseal-enrichment.ts
index 3e9daecf..410c8559 100644
--- a/DW-Programming/ImportNewSkufromURL/scripts/koroseal-enrichment.ts
+++ b/DW-Programming/ImportNewSkufromURL/scripts/koroseal-enrichment.ts
@@ -14,8 +14,8 @@ import https from 'https';
 // Configuration
 const SHOPIFY_STORE = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_TOKEN = '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';
-const ANTHROPIC_API_KEY = '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';
-const GEMINI_API_KEY = 'REDACTED_GEMINI_KEY';
+const ANTHROPIC_API_KEY = "${ANTHROPIC_API_KEY}";
+const GEMINI_API_KEY = '${GOOGLE_API_KEY}';
 
 interface Product {
   id: number;
diff --git a/DW-Programming/ImportNewSkufromURL/scripts/rwltd-gemini-cron.js b/DW-Programming/ImportNewSkufromURL/scripts/rwltd-gemini-cron.js
index 17623161..4ddefc66 100644
--- a/DW-Programming/ImportNewSkufromURL/scripts/rwltd-gemini-cron.js
+++ b/DW-Programming/ImportNewSkufromURL/scripts/rwltd-gemini-cron.js
@@ -9,7 +9,7 @@ const { Pool } = require('pg');
 const https = require('https');
 
 const pool = new Pool({ connectionString: 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified' });
-const GEMINI_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_KEY = '${GOOGLE_API_KEY}';
 const SHOP = 'designer-laboratory-sandbox.myshopify.com';
 const TOKEN = '***REMOVED***';
 
diff --git a/DW-Programming/ImportNewSkufromURL/tag-dwpd-ai.ts b/DW-Programming/ImportNewSkufromURL/tag-dwpd-ai.ts
index 51c62979..77481a4b 100644
--- a/DW-Programming/ImportNewSkufromURL/tag-dwpd-ai.ts
+++ b/DW-Programming/ImportNewSkufromURL/tag-dwpd-ai.ts
@@ -14,7 +14,7 @@ import fetch from 'node-fetch';
 const SHOPIFY_STORE = process.env.SHOPIFY_STORE_DOMAIN || 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_ACCESS_TOKEN = process.env.SHOPIFY_ADMIN_ACCESS_TOKEN || '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';
 const SHOPIFY_API_VERSION = '2024-07';
-const ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY || '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';
+const ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY || "${ANTHROPIC_API_KEY}";
 
 const anthropic = new Anthropic({ apiKey: ANTHROPIC_API_KEY });
 
diff --git a/DW-Programming/ImportNewSkufromURL/universal-completion-notifier.ts b/DW-Programming/ImportNewSkufromURL/universal-completion-notifier.ts
index e5f1612a..407160ba 100644
--- a/DW-Programming/ImportNewSkufromURL/universal-completion-notifier.ts
+++ b/DW-Programming/ImportNewSkufromURL/universal-completion-notifier.ts
@@ -6,7 +6,7 @@
 import { WebClient } from '@slack/web-api';
 import fetch from 'node-fetch';
 
-const SLACK_BOT_TOKEN = 'xoxb-3958182050256-9814366234406-HiR1ybK6HT8JViWDEpjXpmsq';
+const SLACK_BOT_TOKEN = '${SLACK_BOT_TOKEN}';
 const SLACK_CHANNEL_GENERAL = '#general';
 const SLACK_CHANNEL_PROGRESS = '#new-products-on-shopify';
 const CHECK_INTERVAL = 120000; // Check every 2 minutes
diff --git a/DW-Programming/KravetDesignTagger/server.js b/DW-Programming/KravetDesignTagger/server.js
index abfff2b6..3822afa0 100644
--- a/DW-Programming/KravetDesignTagger/server.js
+++ b/DW-Programming/KravetDesignTagger/server.js
@@ -9,7 +9,7 @@ const PORT = 3851;
 const SHOPIFY_STORE = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_ACCESS_TOKEN = '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';
 const API_VERSION = '2024-01';
-const ANTHROPIC_API_KEY = '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';
+const ANTHROPIC_API_KEY = "${ANTHROPIC_API_KEY}";
 
 const fs = require('fs');
 
diff --git a/DW-Programming/LINCRUSTA_PROJECT_MEMORY.md b/DW-Programming/LINCRUSTA_PROJECT_MEMORY.md
index 1fc4221e..144c6ede 100644
--- a/DW-Programming/LINCRUSTA_PROJECT_MEMORY.md
+++ b/DW-Programming/LINCRUSTA_PROJECT_MEMORY.md
@@ -135,7 +135,7 @@ These products need correct manufacturer URLs:
 - **Shopify Store:** designer-laboratory-sandbox.myshopify.com
 - **API Version:** 2024-07
 - **Access Token:** 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
-- **Anthropic API Key:** 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
+- **Anthropic API Key:** ${ANTHROPIC_API_KEY}
 
 ### Data Schema Used
 From `/root/DW-Programming/ImportNewSkufromURL/lib/types.ts`:
diff --git a/DW-Programming/PhillipeRomanoTagger/bulk-update-pr.js b/DW-Programming/PhillipeRomanoTagger/bulk-update-pr.js
index f81a409e..118d6c6a 100644
--- a/DW-Programming/PhillipeRomanoTagger/bulk-update-pr.js
+++ b/DW-Programming/PhillipeRomanoTagger/bulk-update-pr.js
@@ -16,7 +16,7 @@ const https = require('https');
 const SHOPIFY_DOMAIN = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_TOKEN = '***REMOVED***';
 const API_VERSION = '2024-01';
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
 // --- Vendor Classification Map ---
 // vendor suffix → { productType, tag }
diff --git a/DW-Programming/PhillipeRomanoTagger/consolidate-pr-vendors.js b/DW-Programming/PhillipeRomanoTagger/consolidate-pr-vendors.js
index bf700975..1741f4af 100644
--- a/DW-Programming/PhillipeRomanoTagger/consolidate-pr-vendors.js
+++ b/DW-Programming/PhillipeRomanoTagger/consolidate-pr-vendors.js
@@ -18,7 +18,7 @@ const https = require('https');
 const SHOPIFY_DOMAIN = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_TOKEN = '***REMOVED***';
 const API_VERSION = '2024-01';
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
 const CANONICAL_VENDOR = 'Phillipe Romano';
 const VARIANT_VENDORS = [
diff --git a/DW-Programming/PhillipeRomanoTagger/server.js b/DW-Programming/PhillipeRomanoTagger/server.js
index 0e33b539..cae25f54 100644
--- a/DW-Programming/PhillipeRomanoTagger/server.js
+++ b/DW-Programming/PhillipeRomanoTagger/server.js
@@ -84,7 +84,7 @@ function recordProductUpdate(productId, handle, title, tagsBefore, tagsAfter, ai
 console.log('✓ SQLite database initialized for tracking updates');
 
 // ============ GEMINI AI SETUP ============
-const GEMINI_API_KEY = process.env.GEMINI_API_KEY || 'REDACTED_GEMINI_KEY';
+const GEMINI_API_KEY = process.env.GEMINI_API_KEY || '${GOOGLE_API_KEY}';
 let gemini = null;
 
 try {
diff --git a/DW-Programming/RemoveDuplicatesInShopify/auto-tag-groups.js b/DW-Programming/RemoveDuplicatesInShopify/auto-tag-groups.js
index d2b71391..cf3329ab 100644
--- a/DW-Programming/RemoveDuplicatesInShopify/auto-tag-groups.js
+++ b/DW-Programming/RemoveDuplicatesInShopify/auto-tag-groups.js
@@ -4,7 +4,7 @@ const path = require('path');
 const SHOPIFY_STORE = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_ACCESS_TOKEN = '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';
 const API_VERSION = '2024-07';
-const ANTHROPIC_API_KEY = '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';
+const ANTHROPIC_API_KEY = "${ANTHROPIC_API_KEY}";
 
 // Load product data
 const data = JSON.parse(fs.readFileSync(path.join(__dirname, 'schumacher-full.json')));
diff --git a/DW-Programming/RemoveDuplicatesInShopify/recrawl-all-tags.js b/DW-Programming/RemoveDuplicatesInShopify/recrawl-all-tags.js
index 0ecb7fb2..acbee4c8 100644
--- a/DW-Programming/RemoveDuplicatesInShopify/recrawl-all-tags.js
+++ b/DW-Programming/RemoveDuplicatesInShopify/recrawl-all-tags.js
@@ -4,7 +4,7 @@ const path = require('path');
 const SHOPIFY_STORE = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_ACCESS_TOKEN = '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';
 const API_VERSION = '2024-07';
-const ANTHROPIC_API_KEY = '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';
+const ANTHROPIC_API_KEY = "${ANTHROPIC_API_KEY}";
 const TRACKING_FILE = path.join(__dirname, 'updated-products.json');
 
 // Load product data
diff --git a/DW-Programming/RemoveDuplicatesInShopify/server.js b/DW-Programming/RemoveDuplicatesInShopify/server.js
index 172b1fea..ae7fc34c 100644
--- a/DW-Programming/RemoveDuplicatesInShopify/server.js
+++ b/DW-Programming/RemoveDuplicatesInShopify/server.js
@@ -6,7 +6,7 @@ const SHOPIFY_STORE = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_ACCESS_TOKEN = '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';
 const API_VERSION = '2024-07';
 const PORT = 8779;
-const ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY || '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';
+const ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY || "${ANTHROPIC_API_KEY}";
 const EXCLUDED_FILE = path.join(__dirname, 'excluded-products.json');
 
 // Save excluded product to local file
diff --git a/DW-Programming/RemoveDuplicatesInShopify/tag-schumacher-products.ts b/DW-Programming/RemoveDuplicatesInShopify/tag-schumacher-products.ts
index 55836d5f..b743a7d4 100644
--- a/DW-Programming/RemoveDuplicatesInShopify/tag-schumacher-products.ts
+++ b/DW-Programming/RemoveDuplicatesInShopify/tag-schumacher-products.ts
@@ -14,7 +14,7 @@ import fetch from 'node-fetch';
 const SHOPIFY_STORE = process.env.SHOPIFY_STORE_DOMAIN || 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_ACCESS_TOKEN = process.env.SHOPIFY_ADMIN_ACCESS_TOKEN || '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';
 const SHOPIFY_API_VERSION = '2024-07';
-const ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY || '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';
+const ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY || "${ANTHROPIC_API_KEY}";
 
 const anthropic = new Anthropic({ apiKey: ANTHROPIC_API_KEY });
 
diff --git a/DW-Programming/RemoveDuplicatesInShopify/test-tagging.ts b/DW-Programming/RemoveDuplicatesInShopify/test-tagging.ts
index 1824b315..9e268f3d 100644
--- a/DW-Programming/RemoveDuplicatesInShopify/test-tagging.ts
+++ b/DW-Programming/RemoveDuplicatesInShopify/test-tagging.ts
@@ -8,7 +8,7 @@ import fetch from 'node-fetch';
 const SHOPIFY_STORE = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_ACCESS_TOKEN = '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';
 const SHOPIFY_API_VERSION = '2024-07';
-const ANTHROPIC_API_KEY = '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';
+const ANTHROPIC_API_KEY = "${ANTHROPIC_API_KEY}";
 
 const anthropic = new Anthropic({ apiKey: ANTHROPIC_API_KEY });
 
diff --git a/DW-Programming/ShopifyCalendarNext/scripts/rescan-scheduled-posts.ts b/DW-Programming/ShopifyCalendarNext/scripts/rescan-scheduled-posts.ts
index 3dcd1fce..0e91f39a 100644
--- a/DW-Programming/ShopifyCalendarNext/scripts/rescan-scheduled-posts.ts
+++ b/DW-Programming/ShopifyCalendarNext/scripts/rescan-scheduled-posts.ts
@@ -1,6 +1,6 @@
 import { Pool } from 'pg';
 
-const GEMINI_API_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_API_KEY = '${GOOGLE_API_KEY}';
 
 const pool = new Pool({
   connectionString: 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified'
diff --git a/DW-Programming/ShopifyCalendarNext/src/app/api/analyze-product/route.ts b/DW-Programming/ShopifyCalendarNext/src/app/api/analyze-product/route.ts
index 9e63a1a3..f3798e2e 100644
--- a/DW-Programming/ShopifyCalendarNext/src/app/api/analyze-product/route.ts
+++ b/DW-Programming/ShopifyCalendarNext/src/app/api/analyze-product/route.ts
@@ -11,7 +11,7 @@ const pool = new Pool({
 
 const SHOPIFY_DOMAIN = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_TOKEN = '***REMOVED***';
-const GEMINI_API_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_API_KEY = '${GOOGLE_API_KEY}';
 
 // Fetch product from Shopify
 async function fetchShopifyProduct(productId: string) {
diff --git a/DW-Programming/ShopifyCalendarNext/src/app/api/generate-ai-content/route.ts b/DW-Programming/ShopifyCalendarNext/src/app/api/generate-ai-content/route.ts
index b7ea6c9e..01129f88 100644
--- a/DW-Programming/ShopifyCalendarNext/src/app/api/generate-ai-content/route.ts
+++ b/DW-Programming/ShopifyCalendarNext/src/app/api/generate-ai-content/route.ts
@@ -1,6 +1,6 @@
 import { NextRequest, NextResponse } from 'next/server';
 
-const GEMINI_API_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_API_KEY = '${GOOGLE_API_KEY}';
 
 export async function POST(request: NextRequest) {
   try {
diff --git a/DW-Programming/ThibautTagger/server.js b/DW-Programming/ThibautTagger/server.js
index f9c025f8..c44d361e 100644
--- a/DW-Programming/ThibautTagger/server.js
+++ b/DW-Programming/ThibautTagger/server.js
@@ -9,7 +9,7 @@ const PORT = 3850;
 const SHOPIFY_STORE = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_ACCESS_TOKEN = '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';
 const API_VERSION = '2024-07';
-const ANTHROPIC_API_KEY = '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';
+const ANTHROPIC_API_KEY = "${ANTHROPIC_API_KEY}";
 
 const fs = require('fs');
 
diff --git a/DW-Programming/activate-versace-drafts.js b/DW-Programming/activate-versace-drafts.js
index 821d5c9a..317d9981 100644
--- a/DW-Programming/activate-versace-drafts.js
+++ b/DW-Programming/activate-versace-drafts.js
@@ -9,11 +9,11 @@
 
 const SHOPIFY_DOMAIN = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_TOKEN = '***REMOVED***';
-const GEMINI_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_KEY = '${GOOGLE_API_KEY}';
 const GEMINI_MODEL = 'gemini-2.0-flash';
 const SILAS_URL = 'http://127.0.0.1:9674/api/validate-activation';
 const PG_CONN = 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified';
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
 const { Client } = require('pg');
 
diff --git a/DW-Programming/activate-versace-vi.js b/DW-Programming/activate-versace-vi.js
index c47069e4..dbd0d969 100644
--- a/DW-Programming/activate-versace-vi.js
+++ b/DW-Programming/activate-versace-vi.js
@@ -17,10 +17,10 @@ const { Client } = require('pg');
 // ── Config ──────────────────────────────────────────────────────────────
 const SHOPIFY_STORE = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_TOKEN = '***REMOVED***';
-const GEMINI_API_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_API_KEY = '${GOOGLE_API_KEY}';
 const GEMINI_MODEL = 'gemini-2.0-flash';
 const SILAS_URL = 'http://127.0.0.1:9674/api/validate-activation';
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 const PG_URI = 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified';
 
 // ── Stats ───────────────────────────────────────────────────────────────
diff --git a/DW-Programming/anna-french-ai-enrich.js b/DW-Programming/anna-french-ai-enrich.js
index f9ac5daf..8e092817 100644
--- a/DW-Programming/anna-french-ai-enrich.js
+++ b/DW-Programming/anna-french-ai-enrich.js
@@ -15,9 +15,9 @@ const { Pool } = require('pg');
 const https = require('https');
 const http = require('http');
 
-const GEMINI_API_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_API_KEY = '${GOOGLE_API_KEY}';
 const GEMINI_URL = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${GEMINI_API_KEY}`;
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
 const pool = new Pool({
   connectionString: 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified'
diff --git a/DW-Programming/anna-french-room-settings.js b/DW-Programming/anna-french-room-settings.js
index befd36e9..cada4bfa 100644
--- a/DW-Programming/anna-french-room-settings.js
+++ b/DW-Programming/anna-french-room-settings.js
@@ -22,7 +22,7 @@ const ROOM_API_BASE = 'http://45.61.58.125:3075';
 const SHOPIFY_STORE = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_TOKEN = '***REMOVED***';
 const API_VERSION = '2024-10';
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
 const pool = new Pool({
   connectionString: 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified'
diff --git a/DW-Programming/anna-french-shopify-push.js b/DW-Programming/anna-french-shopify-push.js
index 8db59378..057cbcc8 100644
--- a/DW-Programming/anna-french-shopify-push.js
+++ b/DW-Programming/anna-french-shopify-push.js
@@ -20,7 +20,7 @@ const https = require('https');
 const SHOPIFY_STORE = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_TOKEN = '***REMOVED***';
 const API_VERSION = '2024-10';
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
 const pool = new Pool({
   connectionString: 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified'
diff --git a/DW-Programming/archive-hollywood-discontinued.js b/DW-Programming/archive-hollywood-discontinued.js
index d44c227a..fc33fdc8 100644
--- a/DW-Programming/archive-hollywood-discontinued.js
+++ b/DW-Programming/archive-hollywood-discontinued.js
@@ -11,7 +11,7 @@ const https = require('https');
 const SHOPIFY_TOKEN = '***REMOVED***';
 const SHOPIFY_STORE = 'designer-laboratory-sandbox.myshopify.com';
 const API_VERSION = '2024-10';
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
 // Rate limit: 2 req/s for REST standard, with buffer
 const DELAY_MS = 550;
diff --git a/DW-Programming/archive-thibaut-discontinued.js b/DW-Programming/archive-thibaut-discontinued.js
index dcdccb6c..7a4399c2 100644
--- a/DW-Programming/archive-thibaut-discontinued.js
+++ b/DW-Programming/archive-thibaut-discontinued.js
@@ -16,7 +16,7 @@ const SHOPIFY_TOKEN = '***REMOVED***';
 const API_VERSION = '2024-10';
 const PG_URL = 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified';
 
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 const LOG_FILE = '/root/DW-Agents/logs/thibaut-archive.log';
 const fs = require('fs');
 
diff --git a/DW-Programming/as-creation-shopify-push.js b/DW-Programming/as-creation-shopify-push.js
index 7c1e4c02..b7eadf10 100644
--- a/DW-Programming/as-creation-shopify-push.js
+++ b/DW-Programming/as-creation-shopify-push.js
@@ -35,7 +35,7 @@ const VENDOR_CODE = 'as_creation';
 const VENDOR_DISPLAY = 'AS Creation';
 const DEFAULT_FIRE_RATING = 'Inquire for more Information';
 const LAUNCH_PAD_BATCH = 25;
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
 // Brand prefixes to strip from pattern_name to get the clean collection/pattern name
 const BRAND_PREFIXES = [
diff --git a/DW-Programming/china-seas-design-tagger.js b/DW-Programming/china-seas-design-tagger.js
index 6b299cef..c97212e9 100644
--- a/DW-Programming/china-seas-design-tagger.js
+++ b/DW-Programming/china-seas-design-tagger.js
@@ -10,11 +10,11 @@ const http = require('http');
 const { Pool } = require('pg');
 
 // --- Config ---
-const GEMINI_API_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_API_KEY = '${GOOGLE_API_KEY}';
 const GEMINI_URL = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${GEMINI_API_KEY}`;
 const SHOPIFY_TOKEN = '***REMOVED***';
 const SHOPIFY_STORE = 'designer-laboratory-sandbox.myshopify.com';
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 const BATCH_SIZE = 100;
 
 const pool = new Pool({
diff --git a/DW-Programming/china-seas-hex-colors.js b/DW-Programming/china-seas-hex-colors.js
index 1602690b..d3f2d1fa 100644
--- a/DW-Programming/china-seas-hex-colors.js
+++ b/DW-Programming/china-seas-hex-colors.js
@@ -13,11 +13,11 @@ const pool = new Pool({
   connectionString: 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified'
 });
 
-const GEMINI_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_KEY = '${GOOGLE_API_KEY}';
 const GEMINI_URL = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${GEMINI_KEY}`;
 const BATCH_SIZE = 50;
 const DELAY_MS = 650; // ~90 RPM to stay under Gemini rate limits
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
 let stats = { processed: 0, updated: 0, failed: 0, skipped: 0 };
 
diff --git a/DW-Programming/color-batch-cleaner.py b/DW-Programming/color-batch-cleaner.py
index aaa6ca0f..e184e9b1 100644
--- a/DW-Programming/color-batch-cleaner.py
+++ b/DW-Programming/color-batch-cleaner.py
@@ -26,7 +26,7 @@ GEMINI_KEY = os.environ.get('GEMINI_API_KEY', '')
 SHOPIFY_DOMAIN = 'designer-laboratory-sandbox.myshopify.com'
 SHOPIFY_TOKEN = '***REMOVED***'
 API_VERSION = '2024-01'
-SLACK_WEBHOOK = 'https://hooks.slack.com/services/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'
+SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}'
 
 WORK_DIR = Path('/tmp/color-batch-cleaner')
 WORK_DIR.mkdir(exist_ok=True)
diff --git a/DW-Programming/color-collection-cleaner.js b/DW-Programming/color-collection-cleaner.js
index 9e5c13b9..f67e96f5 100644
--- a/DW-Programming/color-collection-cleaner.js
+++ b/DW-Programming/color-collection-cleaner.js
@@ -12,7 +12,7 @@ const https = require('https');
 const SHOPIFY_DOMAIN = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_TOKEN = '***REMOVED***';
 const API_VERSION = '2024-01';
-const GEMINI_KEY = 'REDACTED_GEMINI_KEY'; // billed key - free tier quota exceeded
+const GEMINI_KEY = '${GOOGLE_API_KEY}'; // billed key - free tier quota exceeded
 
 const args = process.argv.slice(2);
 const DRY_RUN = args.includes('--dry-run');
diff --git a/DW-Programming/command54-shopify-push.js b/DW-Programming/command54-shopify-push.js
index 1ff680da..3c1f6b6f 100644
--- a/DW-Programming/command54-shopify-push.js
+++ b/DW-Programming/command54-shopify-push.js
@@ -28,7 +28,7 @@ const VENDOR_DISPLAY = 'Phillipe Romano';
 const COLLECTION_NAME = 'Hollywood Vinyls Vol. 1';
 const DEFAULT_FIRE_RATING = 'Class A Fire Rated : Passes ASTM E84';
 const LAUNCH_PAD_BATCH = 25;
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
 // --- Private Label Sanitization ---
 
diff --git a/DW-Programming/crop-grs-fix-top-logo.js b/DW-Programming/crop-grs-fix-top-logo.js
index cdd0adbd..183dbc59 100644
--- a/DW-Programming/crop-grs-fix-top-logo.js
+++ b/DW-Programming/crop-grs-fix-top-logo.js
@@ -250,7 +250,7 @@ async function main() {
   const slackBody = JSON.stringify({
     text: `✂️ *GRS Top Logo Fix Complete*\n• Processed: ${stats.processed}\n• Fixed: ${stats.fixed}\n• Skipped: ${stats.skipped}\n• Errors: ${stats.errors}\n• Duration: ${totalTime} min`
   });
-  const slackUrl = new URL('https://hooks.slack.com/services/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');
+  const slackUrl = new URL('${SLACK_WEBHOOK_URL}');
   await new Promise((resolve) => {
     const req = https.request({ hostname: slackUrl.hostname, path: slackUrl.pathname, method: 'POST', headers: { 'Content-Type': 'application/json' } }, resolve);
     req.write(slackBody);
diff --git a/DW-Programming/crop-grs-images.js b/DW-Programming/crop-grs-images.js
index afe7c665..88017a59 100644
--- a/DW-Programming/crop-grs-images.js
+++ b/DW-Programming/crop-grs-images.js
@@ -379,7 +379,7 @@ async function main() {
 function sendSlack(text) {
   return new Promise((resolve, reject) => {
     const body = JSON.stringify({ text });
-    const url = new URL('https://hooks.slack.com/services/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');
+    const url = new URL('${SLACK_WEBHOOK_URL}');
     const options = {
       hostname: url.hostname,
       path: url.pathname,
diff --git a/DW-Programming/enrich-anna-french-specs.js b/DW-Programming/enrich-anna-french-specs.js
index 9dde311b..faceea7a 100644
--- a/DW-Programming/enrich-anna-french-specs.js
+++ b/DW-Programming/enrich-anna-french-specs.js
@@ -511,7 +511,7 @@ async function main() {
   try {
     const slackData = JSON.stringify(slackMsg);
     await new Promise((resolve, reject) => {
-      const slackUrl = new URL('https://hooks.slack.com/services/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');
+      const slackUrl = new URL('${SLACK_WEBHOOK_URL}');
       const req = https.request({
         hostname: slackUrl.hostname,
         path: slackUrl.pathname,
diff --git a/DW-Programming/enrich-anna-french.js b/DW-Programming/enrich-anna-french.js
index 79159d14..5d3a1075 100644
--- a/DW-Programming/enrich-anna-french.js
+++ b/DW-Programming/enrich-anna-french.js
@@ -17,7 +17,7 @@ const https = require('https');
 const { Pool } = require('pg');
 
 const DB_URL = 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified';
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 const BASE_DELAY_MS = 800;
 const MAX_DELAY_MS = 12000;
 const PROGRESS_EVERY = 25;
diff --git a/DW-Programming/enrich-grahambrown-width.js b/DW-Programming/enrich-grahambrown-width.js
index 84103f33..cdb4526f 100644
--- a/DW-Programming/enrich-grahambrown-width.js
+++ b/DW-Programming/enrich-grahambrown-width.js
@@ -18,7 +18,7 @@ const { Pool } = require('pg');
 // --- Config ---
 const DB_URL = 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified';
 const DELAY_MS = 2000; // 2s between requests (polite rate limit)
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
 // Parse args
 const args = process.argv.slice(2);
diff --git a/DW-Programming/enrich-launched-products.py b/DW-Programming/enrich-launched-products.py
index 88df2903..5f7ada9c 100644
--- a/DW-Programming/enrich-launched-products.py
+++ b/DW-Programming/enrich-launched-products.py
@@ -6,7 +6,7 @@ Downloads images, sends to Gemini, outputs JSON with descriptions.
 
 import requests, json, base64, sys, time
 
-GEMINI_KEY = "REDACTED_GEMINI_KEY"
+GEMINI_KEY = "${GOOGLE_API_KEY}"
 GEMINI_URL = f"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key={GEMINI_KEY}"
 
 products = [
diff --git a/DW-Programming/fix-blue-collection.js b/DW-Programming/fix-blue-collection.js
index 5dc58463..354b3a4a 100644
--- a/DW-Programming/fix-blue-collection.js
+++ b/DW-Programming/fix-blue-collection.js
@@ -10,7 +10,7 @@ const https = require('https');
 const SHOPIFY_DOMAIN = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_TOKEN = '***REMOVED***';
 const API_VERSION = '2024-01';
-const GEMINI_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_KEY = '${GOOGLE_API_KEY}';
 const COLLECTION_ID = 95278104641;
 
 const BLUE_TAGS = ['blue', 'navy', 'sky', 'indigo', 'cobalt', 'azure', 'cerulean', 'teal'];
diff --git a/DW-Programming/fix-phillipe-romano-vendors.js b/DW-Programming/fix-phillipe-romano-vendors.js
index f0f1648d..d235da9c 100644
--- a/DW-Programming/fix-phillipe-romano-vendors.js
+++ b/DW-Programming/fix-phillipe-romano-vendors.js
@@ -413,7 +413,7 @@ async function main() {
       text: `✅ *Phillipe Romano Vendor Fix Complete*\n• Total checked: ${stats.totalChecked}\n• Vendor names fixed: ${stats.vendorFixed}\n• Duplicates archived: ${stats.duplicatesArchived}\n• Errors: ${stats.errors}\n• Duration: ${elapsed} min`
     };
     try {
-      await fetch('https://hooks.slack.com/services/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', {
+      await fetch('${SLACK_WEBHOOK_URL}', {
         method: 'POST',
         headers: { 'Content-Type': 'application/json' },
         body: JSON.stringify(slackMsg),
diff --git a/DW-Programming/generate-justindavid-rooms.py b/DW-Programming/generate-justindavid-rooms.py
index 3ad9a19c..d48b2e93 100644
--- a/DW-Programming/generate-justindavid-rooms.py
+++ b/DW-Programming/generate-justindavid-rooms.py
@@ -28,7 +28,7 @@ from concurrent.futures import ThreadPoolExecutor, as_completed
 
 ROOM_API = "http://127.0.0.1:3075/api/generate-room"
 DB_CONN = "postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified"
-SLACK_WEBHOOK = "https://hooks.slack.com/services/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"
+SLACK_WEBHOOK = "${SLACK_WEBHOOK_URL}"
 PRODUCTS_JSON = "/tmp/justindavid-rooms-products.json"
 PROGRESS_FILE = "/tmp/justindavid-rooms-progress.json"
 IMAGE_DIR = "/root/Projects/Designer-Wallcoverings/room-settings/justindavid/residential"
diff --git a/DW-Programming/generate-maya-room-settings.js b/DW-Programming/generate-maya-room-settings.js
index 3fcfc5a3..1acbaa3f 100644
--- a/DW-Programming/generate-maya-room-settings.js
+++ b/DW-Programming/generate-maya-room-settings.js
@@ -20,7 +20,7 @@ const path = require('path');
 const DB_URL = 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified';
 const ROOM_API = 'http://45.61.58.125:3075/api/generate-room';
 const OUTPUT_DIR = '/root/DW-Agents/room-settings/maya-romanoff';
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
 const ROOM_CONFIGS = [
   { roomType: 'living_room', angle: 'straight_on', cameraDistance: 8, label: 'Living Room' },
diff --git a/DW-Programming/gls-gemini-retry.js b/DW-Programming/gls-gemini-retry.js
index 0b28953b..6614728a 100644
--- a/DW-Programming/gls-gemini-retry.js
+++ b/DW-Programming/gls-gemini-retry.js
@@ -9,7 +9,7 @@ const sharp = require('sharp');
 
 const SHOPIFY_STORE = 'designer-laboratory-sandbox.myshopify.com';
 const ACCESS_TOKEN = '***REMOVED***';
-const GEMINI_API_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_API_KEY = '${GOOGLE_API_KEY}';
 const GEMINI_URL = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${GEMINI_API_KEY}`;
 
 const sleep = ms => new Promise(r => setTimeout(r, ms));
diff --git a/DW-Programming/gls-product-cleanup.js b/DW-Programming/gls-product-cleanup.js
index 9c112849..afbca601 100644
--- a/DW-Programming/gls-product-cleanup.js
+++ b/DW-Programming/gls-product-cleanup.js
@@ -16,10 +16,10 @@ const sharp = require('sharp');
 // ─── Config ───────────────────────────────────────────────────────────────────
 const SHOPIFY_STORE = 'designer-laboratory-sandbox.myshopify.com';
 const ACCESS_TOKEN = '***REMOVED***';
-const GEMINI_API_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_API_KEY = '${GOOGLE_API_KEY}';
 const GEMINI_URL = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${GEMINI_API_KEY}`;
 const API_VERSION = '2024-01';
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
 // Rate limiting
 const DELAY_BETWEEN_PRODUCTS = 2500; // ms between Shopify calls
diff --git a/DW-Programming/gls-product-processor.js b/DW-Programming/gls-product-processor.js
index f889dd3c..a6ec40a6 100644
--- a/DW-Programming/gls-product-processor.js
+++ b/DW-Programming/gls-product-processor.js
@@ -15,9 +15,9 @@ const path = require('path');
 // Config
 const SHOPIFY_DOMAIN = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_TOKEN = '***REMOVED***';
-const GEMINI_API_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_API_KEY = '${GOOGLE_API_KEY}';
 const GEMINI_URL = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${GEMINI_API_KEY}`;
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
 const TAGS_TO_REMOVE = ['brand vinyl', 'composition vinyl', 'vinyl'];
 
diff --git a/DW-Programming/gls-product-updater.js b/DW-Programming/gls-product-updater.js
index 2d489a4a..02cd271d 100644
--- a/DW-Programming/gls-product-updater.js
+++ b/DW-Programming/gls-product-updater.js
@@ -16,9 +16,9 @@ const { execFileSync } = require('child_process');
 // ── Config ───────────────────────────────────────────────────────────
 const SHOPIFY_API = 'https://designer-laboratory-sandbox.myshopify.com/admin/api/2024-01';
 const SHOPIFY_TOKEN = '***REMOVED***';
-const GEMINI_API_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_API_KEY = '${GOOGLE_API_KEY}';
 const GEMINI_URL = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${GEMINI_API_KEY}`;
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
 const DELAY_MS = 1500; // delay between products to respect rate limits
 const sleep = ms => new Promise(r => setTimeout(r, ms));
diff --git a/DW-Programming/gls-retry-failed.js b/DW-Programming/gls-retry-failed.js
index 45a41c6e..fc0ff523 100644
--- a/DW-Programming/gls-retry-failed.js
+++ b/DW-Programming/gls-retry-failed.js
@@ -9,7 +9,7 @@ const sharp = require('sharp');
 
 const SHOPIFY_DOMAIN = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_TOKEN = '***REMOVED***';
-const GEMINI_API_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_API_KEY = '${GOOGLE_API_KEY}';
 const GEMINI_URL = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${GEMINI_API_KEY}`;
 
 const TAGS_TO_REMOVE = ['brand vinyl', 'composition vinyl', 'vinyl'];
diff --git a/DW-Programming/hex-color-blitz.js b/DW-Programming/hex-color-blitz.js
index c1c461a3..c8cac4a3 100644
--- a/DW-Programming/hex-color-blitz.js
+++ b/DW-Programming/hex-color-blitz.js
@@ -22,13 +22,13 @@ const pool = new Pool({
   connectionString: 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified'
 });
 
-const GEMINI_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_KEY = '${GOOGLE_API_KEY}';
 const GEMINI_URL = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${GEMINI_KEY}`;
 const BATCH_SIZE = 50;
 const DELAY_MS = 200;  // Reduced — concurrency handles rate pacing
 const CONCURRENCY = 3; // Process 3 images in parallel
 const MAX_RETRIES = 2;
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
 // ─── CLI Args ───────────────────────────────────────────────────────────────
 const DRY_RUN = process.argv.includes('--dry-run');
diff --git a/DW-Programming/hollywood-hex-and-tags.js b/DW-Programming/hollywood-hex-and-tags.js
index 9ac7da70..1cbee732 100644
--- a/DW-Programming/hollywood-hex-and-tags.js
+++ b/DW-Programming/hollywood-hex-and-tags.js
@@ -14,11 +14,11 @@ const pool = new Pool({
   connectionString: 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified'
 });
 
-const GEMINI_API_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_API_KEY = '${GOOGLE_API_KEY}';
 const GEMINI_MODEL = 'gemini-2.0-flash';
 const GEMINI_URL = `https://generativelanguage.googleapis.com/v1beta/models/${GEMINI_MODEL}:generateContent?key=${GEMINI_API_KEY}`;
 
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
 // Rate limiting: max 10 req/s
 const RATE_LIMIT_MS = 120; // ~8 req/s to be safe
diff --git a/DW-Programming/hollywood-hex-extract.js b/DW-Programming/hollywood-hex-extract.js
index 2def59fc..44a95208 100644
--- a/DW-Programming/hollywood-hex-extract.js
+++ b/DW-Programming/hollywood-hex-extract.js
@@ -1,7 +1,7 @@
 const https = require('https');
 const { Client } = require('pg');
 
-const GEMINI_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_KEY = '${GOOGLE_API_KEY}';
 const GEMINI_MODEL = 'gemini-2.0-flash';
 const DB_URL = 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified';
 
diff --git a/DW-Programming/hollywood-shopify-push.js b/DW-Programming/hollywood-shopify-push.js
index 9571ae87..3eab3774 100644
--- a/DW-Programming/hollywood-shopify-push.js
+++ b/DW-Programming/hollywood-shopify-push.js
@@ -34,7 +34,7 @@ const VENDOR_CODE = 'hollywood';
 const VENDOR_DISPLAY = 'Hollywood Wallcoverings';
 const DEFAULT_FIRE_RATING = 'Class A Fire Rated : Passes ASTM E84';
 const LAUNCH_PAD_BATCH = 25;
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
 // --- Helpers ---
 
diff --git a/DW-Programming/interior-design-ai-tagger.js b/DW-Programming/interior-design-ai-tagger.js
index ef7347a8..c436a768 100644
--- a/DW-Programming/interior-design-ai-tagger.js
+++ b/DW-Programming/interior-design-ai-tagger.js
@@ -23,14 +23,14 @@ const https = require('https');
 const http = require('http');
 
 // ─── Config ───────────────────────────────────────────────────────────────────
-const GEMINI_API_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_API_KEY = '${GOOGLE_API_KEY}';
 const GEMINI_URL = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${GEMINI_API_KEY}`;
 
 const SHOPIFY_STORE = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_TOKEN = '***REMOVED***';
 const SHOPIFY_API_VERSION = '2024-10';
 
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
 const pool = new Pool({
   connectionString: 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified'
diff --git a/DW-Programming/interior-design-tagger.js b/DW-Programming/interior-design-tagger.js
index f533885d..a5dfadb9 100644
--- a/DW-Programming/interior-design-tagger.js
+++ b/DW-Programming/interior-design-tagger.js
@@ -29,8 +29,8 @@ const path = require('path');
 
 const SHOPIFY_DOMAIN = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_TOKEN  = '***REMOVED***';
-const GEMINI_API_KEY = 'REDACTED_GEMINI_KEY';
-const SLACK_WEBHOOK  = 'https://hooks.slack.com/services/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';
+const GEMINI_API_KEY = '${GOOGLE_API_KEY}';
+const SLACK_WEBHOOK  = '${SLACK_WEBHOOK_URL}';
 const API_VERSION    = '2024-10';
 
 const STATE_FILE = path.join(__dirname, 'state/interior-tagger-state.json');
diff --git a/DW-Programming/jd-room-batch.js b/DW-Programming/jd-room-batch.js
index d7ec4112..0ea710cf 100644
--- a/DW-Programming/jd-room-batch.js
+++ b/DW-Programming/jd-room-batch.js
@@ -16,7 +16,7 @@ import https from 'https';
 const ROOM_SETTING_APP = 'http://127.0.0.1:3075';
 const OUTPUT_BASE = '/root/Projects/Designer-Wallcoverings/room-settings/justindavid';
 const PUBLIC_URL_BASE = 'http://45.61.58.125/room-settings/justindavid';
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
 const BATCH_SIZE = 50;               // Products per DB query
 const MIN_REQUEST_INTERVAL = 12000;  // 12s between Gemini requests (~5 RPM, well under 10 RPM limit)
diff --git a/DW-Programming/justindavid-shopify-push.js b/DW-Programming/justindavid-shopify-push.js
index a6278484..cf090ea7 100644
--- a/DW-Programming/justindavid-shopify-push.js
+++ b/DW-Programming/justindavid-shopify-push.js
@@ -26,7 +26,7 @@ const pool = new Pool({
 });
 
 const SOURCE_AGENT = 'jd-p8-push';
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
 // --- Helpers ---
 
diff --git a/DW-Programming/launch-versace-vi.js b/DW-Programming/launch-versace-vi.js
index b72ba79b..684f0118 100644
--- a/DW-Programming/launch-versace-vi.js
+++ b/DW-Programming/launch-versace-vi.js
@@ -16,7 +16,7 @@ const SHOPIFY_DOMAIN = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_TOKEN = '***REMOVED***';
 const SILAS_URL = 'http://127.0.0.1:9674/api/validate-push';
 const DB_URL = 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified';
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
 // Rate limiting: Shopify standard = 4 req/s, Silas check + product create = 2 calls each
 // Need ~1200ms per product to stay under limit
diff --git a/DW-Programming/maya-romanoff-updater/maya-romanoff-updater.js b/DW-Programming/maya-romanoff-updater/maya-romanoff-updater.js
index a6a873a4..5a26d433 100644
--- a/DW-Programming/maya-romanoff-updater/maya-romanoff-updater.js
+++ b/DW-Programming/maya-romanoff-updater/maya-romanoff-updater.js
@@ -21,12 +21,12 @@ const { Pool } = require('pg');
 const CONFIG = {
   SHOPIFY_STORE: 'designer-laboratory-sandbox.myshopify.com',
   SHOPIFY_TOKEN: '***REMOVED***',
-  GEMINI_API_KEY: 'REDACTED_GEMINI_KEY',
+  GEMINI_API_KEY: '${GOOGLE_API_KEY}',
   SPREADSHEET_CSV: 'https://docs.google.com/spreadsheets/d/1hPTMFkX762hftpEAxWTvEl9rNzhd4mBITnpkYuDgMLg/gviz/tq?tqx=out:csv',
   MAYA_SEARCH_URL: 'https://www.mayaromanoff.com/search?q=',
   MAYA_BASE_URL: 'https://www.mayaromanoff.com',
   POSTGRES_URL: 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified',
-  SLACK_WEBHOOK: 'https://hooks.slack.com/services/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',
+  SLACK_WEBHOOK: '${SLACK_WEBHOOK_URL}',
   NEXT_SKU_START: 50000, // DWYA-50000+
   WAIT_TIME: 6000 // 6 seconds wait for page load
 };
diff --git a/DW-Programming/maya-romanoff-updater/server.js b/DW-Programming/maya-romanoff-updater/server.js
index b06ecb15..c5a5db43 100644
--- a/DW-Programming/maya-romanoff-updater/server.js
+++ b/DW-Programming/maya-romanoff-updater/server.js
@@ -27,10 +27,10 @@ const CONFIG = {
   SHOPIFY_STORE: 'designer-laboratory-sandbox.myshopify.com',
   SHOPIFY_TOKEN: '***REMOVED***',
   API_VERSION: '2024-01',
-  GEMINI_API_KEY: 'REDACTED_GEMINI_KEY',
+  GEMINI_API_KEY: '${GOOGLE_API_KEY}',
   MAYA_BASE_URL: 'https://www.mayaromanoff.com',
   POSTGRES_URL: 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified',
-  SLACK_WEBHOOK: 'https://hooks.slack.com/services/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',
+  SLACK_WEBHOOK: '${SLACK_WEBHOOK_URL}',
   SPREADSHEET_CSV: 'https://docs.google.com/spreadsheets/d/1hPTMFkX762hftpEAxWTvEl9rNzhd4mBITnpkYuDgMLg/gviz/tq?tqx=out:csv',
   SPREADSHEET_CSV_2: 'https://docs.google.com/spreadsheets/d/1mQ08UJZ5T_qVTHOW8o1s-zbz5l93AUN9c46meup6uO0/gviz/tq?tqx=out:csv'
 };
diff --git a/DW-Programming/migrate-dwkk-to-dwpr.js b/DW-Programming/migrate-dwkk-to-dwpr.js
index 514a87fb..fd69d2b7 100644
--- a/DW-Programming/migrate-dwkk-to-dwpr.js
+++ b/DW-Programming/migrate-dwkk-to-dwpr.js
@@ -23,7 +23,7 @@ const SHOPIFY_DOMAIN = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_TOKEN = '***REMOVED***';
 const API_VERSION = '2024-10';
 const DB_URL = 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified';
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 const RATE_LIMIT_MS = 2000; // 0.5 req/s
 const NEW_PREFIX = 'DWPR';
 
diff --git a/DW-Programming/nextjs-liquid-app/app/api/analyze-image/route.ts b/DW-Programming/nextjs-liquid-app/app/api/analyze-image/route.ts
index 44cfaf1c..53fe525a 100644
--- a/DW-Programming/nextjs-liquid-app/app/api/analyze-image/route.ts
+++ b/DW-Programming/nextjs-liquid-app/app/api/analyze-image/route.ts
@@ -1,7 +1,7 @@
 import { NextRequest, NextResponse } from 'next/server';
 
-const GEMINI_API_KEY = 'REDACTED_GEMINI_KEY'; // Billed account (same as furniture-scene-agent)
-const GEMINI_API_KEY_FREE = 'REDACTED_GEMINI_KEY'; // Free tier fallback
+const GEMINI_API_KEY = '${GOOGLE_API_KEY}'; // Billed account (same as furniture-scene-agent)
+const GEMINI_API_KEY_FREE = '${GOOGLE_API_KEY}'; // Free tier fallback
 
 function checkAuth(req: NextRequest): boolean {
   const authHeader = req.headers.get('authorization');
diff --git a/DW-Programming/nextjs-liquid-app/app/api/bulk-import/route.ts b/DW-Programming/nextjs-liquid-app/app/api/bulk-import/route.ts
index a160da38..41316d76 100644
--- a/DW-Programming/nextjs-liquid-app/app/api/bulk-import/route.ts
+++ b/DW-Programming/nextjs-liquid-app/app/api/bulk-import/route.ts
@@ -3,7 +3,7 @@ import { dbQuery } from '@/lib/db';
 
 const SHOPIFY_STORE = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_TOKEN = '***REMOVED***';
-const GEMINI_API_KEY = 'REDACTED_GEMINI_KEY'; // Billed Tier 1 key
+const GEMINI_API_KEY = '${GOOGLE_API_KEY}'; // Billed Tier 1 key
 
 // All 14 sales channels - publish to ALL on product creation
 const ALL_PUBLICATION_IDS = [
diff --git a/DW-Programming/nextjs-liquid-app/app/api/oldest-skus/route.ts b/DW-Programming/nextjs-liquid-app/app/api/oldest-skus/route.ts
index 884ee8ad..ba9445ba 100644
--- a/DW-Programming/nextjs-liquid-app/app/api/oldest-skus/route.ts
+++ b/DW-Programming/nextjs-liquid-app/app/api/oldest-skus/route.ts
@@ -1,7 +1,7 @@
 import { NextRequest, NextResponse } from 'next/server';
 import { dbQuery } from '@/lib/db';
 
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
 function checkAuth(req: NextRequest): boolean {
   const authHeader = req.headers.get('authorization');
diff --git a/DW-Programming/nextjs-liquid-app/update-mckenzie-titles.js b/DW-Programming/nextjs-liquid-app/update-mckenzie-titles.js
index 945b7ce3..15097745 100644
--- a/DW-Programming/nextjs-liquid-app/update-mckenzie-titles.js
+++ b/DW-Programming/nextjs-liquid-app/update-mckenzie-titles.js
@@ -69,7 +69,7 @@ async function main() {
   console.log(`\n\nComplete: ${updated} updated, ${errors} errors`);
 
   // Send Slack notification
-  const slack = 'https://hooks.slack.com/services/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';
+  const slack = '${SLACK_WEBHOOK_URL}';
   await fetch(slack, {
     method: 'POST',
     headers: { 'Content-Type': 'application/json' },
diff --git a/DW-Programming/phase3-ai-enrich-100.js b/DW-Programming/phase3-ai-enrich-100.js
index 3d6ca2f3..1ba459dd 100644
--- a/DW-Programming/phase3-ai-enrich-100.js
+++ b/DW-Programming/phase3-ai-enrich-100.js
@@ -14,11 +14,11 @@ const pool = new Pool({
   connectionString: 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified'
 });
 
-const GEMINI_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_KEY = '${GOOGLE_API_KEY}';
 const GEMINI_URL = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${GEMINI_KEY}`;
 const BATCH_LIMIT = 100;
 const RATE_DELAY_MS = 2000; // 2s between requests
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
 const PROMPT = `Analyze this wallcovering product image. Return ONLY valid JSON (no markdown, no backticks) with this exact structure:
 {
diff --git a/DW-Programming/phase3-ai-enrich-batch.js b/DW-Programming/phase3-ai-enrich-batch.js
index d1e6bfb6..9cd71068 100644
--- a/DW-Programming/phase3-ai-enrich-batch.js
+++ b/DW-Programming/phase3-ai-enrich-batch.js
@@ -13,10 +13,10 @@ const pool = new Pool({
   connectionString: 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified'
 });
 
-const GEMINI_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_KEY = '${GOOGLE_API_KEY}';
 const GEMINI_URL = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${GEMINI_KEY}`;
 const BATCH_LIMIT = 20;
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
 // Tables to enrich, ordered by priority (smallest gaps first for quick wins)
 const TABLES = [
diff --git a/DW-Programming/phase3-ai-enrich-batch.py b/DW-Programming/phase3-ai-enrich-batch.py
index 380e32ff..9410bb99 100644
--- a/DW-Programming/phase3-ai-enrich-batch.py
+++ b/DW-Programming/phase3-ai-enrich-batch.py
@@ -15,7 +15,7 @@ from datetime import datetime, timezone, timedelta
 import psycopg2
 
 DB_DSN = "postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified"
-GEMINI_KEY = "REDACTED_GEMINI_KEY"
+GEMINI_KEY = "${GOOGLE_API_KEY}"
 GEMINI_URL = f"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key={GEMINI_KEY}"
 BATCH_SIZE = 20
 
diff --git a/DW-Programming/phase3-ai-enrich-batch.sh b/DW-Programming/phase3-ai-enrich-batch.sh
index a2889f4c..291bbca3 100644
--- a/DW-Programming/phase3-ai-enrich-batch.sh
+++ b/DW-Programming/phase3-ai-enrich-batch.sh
@@ -3,7 +3,7 @@
 # Downloads product images, sends to Gemini Vision, updates PostgreSQL
 set -euo pipefail
 
-GEMINI_KEY="REDACTED_GEMINI_KEY"
+GEMINI_KEY="${GOOGLE_API_KEY}"
 GEMINI_URL="https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${GEMINI_KEY}"
 DB="postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified"
 TMPDIR="/tmp/ai-enrich-$$"
diff --git a/DW-Programming/phase3-ai-enrich-run.js b/DW-Programming/phase3-ai-enrich-run.js
index 9039da08..5b56ec87 100644
--- a/DW-Programming/phase3-ai-enrich-run.js
+++ b/DW-Programming/phase3-ai-enrich-run.js
@@ -8,7 +8,7 @@ const { Pool } = require('pg');
 const https = require('https');
 const http = require('http');
 
-const GEMINI_API_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_API_KEY = '${GOOGLE_API_KEY}';
 const GEMINI_URL = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${GEMINI_API_KEY}`;
 
 const pool = new Pool({
diff --git a/DW-Programming/phase3-ai-enrichment.js b/DW-Programming/phase3-ai-enrichment.js
index a23e2eb2..b4a5e6ae 100644
--- a/DW-Programming/phase3-ai-enrichment.js
+++ b/DW-Programming/phase3-ai-enrichment.js
@@ -12,7 +12,7 @@ const pool = new Pool({
   connectionString: 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified'
 });
 
-const GEMINI_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_KEY = '${GOOGLE_API_KEY}';
 const GEMINI_URL = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${GEMINI_KEY}`;
 
 const BATCH_SIZE = 20;
diff --git a/DW-Programming/phillipe-romano-vendor-fix.js b/DW-Programming/phillipe-romano-vendor-fix.js
index 93dbe8e2..809bf134 100644
--- a/DW-Programming/phillipe-romano-vendor-fix.js
+++ b/DW-Programming/phillipe-romano-vendor-fix.js
@@ -31,7 +31,7 @@ const VARIANT_VENDORS = [
   'Phillipe Romano Fabrics',
   'Phillipe Romano Vinyls',
 ];
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 const DRY_RUN = !process.argv.includes('--execute');
 const CONCURRENCY = 4;
 const THROTTLE_MS = 300; // ms between batches
diff --git a/DW-Programming/pj-tearsheet-scraper.js b/DW-Programming/pj-tearsheet-scraper.js
index 15f0f862..a4ed605e 100644
--- a/DW-Programming/pj-tearsheet-scraper.js
+++ b/DW-Programming/pj-tearsheet-scraper.js
@@ -220,7 +220,7 @@ async function main() {
   const slackMsg = `*PJ Tear-Sheet Scraper Complete*\n- Success: ${ok}\n- Failed: ${fail}\n- Duration: ${mins} min`;
   try {
     const slackData = JSON.stringify({ text: slackMsg });
-    const slackReq = https.request('https://hooks.slack.com/services/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', {
+    const slackReq = https.request('${SLACK_WEBHOOK_URL}', {
       method: 'POST',
       headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(slackData) }
     });
diff --git a/DW-Programming/pr-logo-crop.py b/DW-Programming/pr-logo-crop.py
index 2e143469..e2299f03 100644
--- a/DW-Programming/pr-logo-crop.py
+++ b/DW-Programming/pr-logo-crop.py
@@ -34,7 +34,7 @@ import psycopg2.extras
 DB_URL = "postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified"
 CROP_DIR = "/root/DW-Agents/image-crops/phillipe-romano"
 LOG_FILE = "/tmp/pr-logo-crop.log"
-SLACK_WEBHOOK = "https://hooks.slack.com/services/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"
+SLACK_WEBHOOK = "${SLACK_WEBHOOK_URL}"
 BATCH_SIZE = 100
 DELAY_BETWEEN = 0.5  # 500ms between downloads
 TEMP_ORIG = "/tmp/pr-scan.jpg"
diff --git a/DW-Programming/prl-ai-enrich.js b/DW-Programming/prl-ai-enrich.js
index 2c7cd652..7391f55b 100644
--- a/DW-Programming/prl-ai-enrich.js
+++ b/DW-Programming/prl-ai-enrich.js
@@ -17,9 +17,9 @@ const { Pool } = require('pg');
 const https = require('https');
 const http = require('http');
 
-const GEMINI_API_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_API_KEY = '${GOOGLE_API_KEY}';
 const GEMINI_URL = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${GEMINI_API_KEY}`;
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
 const pool = new Pool({
   connectionString: 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified'
diff --git a/DW-Programming/push-maya-romanoff-to-shopify.js b/DW-Programming/push-maya-romanoff-to-shopify.js
index edc3f2ce..56274e70 100644
--- a/DW-Programming/push-maya-romanoff-to-shopify.js
+++ b/DW-Programming/push-maya-romanoff-to-shopify.js
@@ -18,7 +18,7 @@ const CONFIG = {
   SHOPIFY_TOKEN: '***REMOVED***',
   API_VERSION: '2024-10',
   POSTGRES_URL: 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified',
-  SLACK_WEBHOOK: 'https://hooks.slack.com/services/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',
+  SLACK_WEBHOOK: '${SLACK_WEBHOOK_URL}',
   DELAY_MS: 650,
   RETRY_DELAY_MS: 35000,
   MAX_RETRIES: 3
diff --git a/DW-Programming/push-versace-vi.js b/DW-Programming/push-versace-vi.js
index 9b51292e..25c493fd 100644
--- a/DW-Programming/push-versace-vi.js
+++ b/DW-Programming/push-versace-vi.js
@@ -17,7 +17,7 @@ const DB_URL = 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified
 const SHOPIFY_STORE = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_TOKEN = '***REMOVED***';
 const SILAS_URL = 'http://127.0.0.1:9674';
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
 const pool = new Pool({ connectionString: DB_URL });
 
diff --git a/DW-Programming/ralph-lauren-fabric-updater-9899.js b/DW-Programming/ralph-lauren-fabric-updater-9899.js
index cb6e9d5f..964d90a7 100644
--- a/DW-Programming/ralph-lauren-fabric-updater-9899.js
+++ b/DW-Programming/ralph-lauren-fabric-updater-9899.js
@@ -24,7 +24,7 @@ const SHOPIFY_STORE = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_TOKEN = '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';
 const API_VERSION = '2024-01';
 // Gemini Configuration (MANDATORY - No Claude Vision)
-const GEMINI_API_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_API_KEY = '${GOOGLE_API_KEY}';
 const GEMINI_MODEL = 'gemini-2.0-flash';
 // Authentication credentials
 const AUTH_USER = 'admin';
diff --git a/DW-Programming/ralph-lauren-fabric-updater-9899.ts b/DW-Programming/ralph-lauren-fabric-updater-9899.ts
index 56b72792..e8139823 100644
--- a/DW-Programming/ralph-lauren-fabric-updater-9899.ts
+++ b/DW-Programming/ralph-lauren-fabric-updater-9899.ts
@@ -23,7 +23,7 @@ const SHOPIFY_TOKEN = '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';
 const API_VERSION = '2024-01';
 
 // Gemini Configuration (MANDATORY - No Claude Vision)
-const GEMINI_API_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_API_KEY = '${GOOGLE_API_KEY}';
 const GEMINI_MODEL = 'gemini-2.0-flash';
 
 // Authentication credentials
diff --git a/DW-Programming/remove-damask-from-florals.js b/DW-Programming/remove-damask-from-florals.js
index 30ef1e08..b90014b1 100644
--- a/DW-Programming/remove-damask-from-florals.js
+++ b/DW-Programming/remove-damask-from-florals.js
@@ -183,7 +183,7 @@ async function main() {
   const slackMsg = `✅ *Damask Removal from Botanicals & Florals Complete*\n• Damask products found: ${damaskProducts.length}\n• Tags removed: ${updatedCount} products\n• Skipped (no matching tags): ${skippedCount}\n• Tags targeted: Floral, botanical, BOTANICAL/FLORALS`;
 
   try {
-    await fetch('https://hooks.slack.com/services/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', {
+    await fetch('${SLACK_WEBHOOK_URL}', {
       method: 'POST',
       headers: { 'Content-Type': 'application/json' },
       body: JSON.stringify({ text: slackMsg })
diff --git a/DW-Programming/room-setting-app/app/api/analyze-pattern/route.ts b/DW-Programming/room-setting-app/app/api/analyze-pattern/route.ts
index 361d7d32..c95289e7 100644
--- a/DW-Programming/room-setting-app/app/api/analyze-pattern/route.ts
+++ b/DW-Programming/room-setting-app/app/api/analyze-pattern/route.ts
@@ -1,7 +1,7 @@
 import { NextRequest, NextResponse } from 'next/server';
 
 // Gemini Vision API for pattern analysis
-const GEMINI_ANALYSIS_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_ANALYSIS_KEY = '${GOOGLE_API_KEY}';
 const GEMINI_ANALYSIS_MODEL = 'gemini-2.0-flash';
 const GEMINI_ENDPOINT = `https://generativelanguage.googleapis.com/v1beta/models/${GEMINI_ANALYSIS_MODEL}:generateContent?key=${GEMINI_ANALYSIS_KEY}`;
 
diff --git a/DW-Programming/room-setting-app/batch-room-gen-v2.py b/DW-Programming/room-setting-app/batch-room-gen-v2.py
index fc624000..779bd1a4 100644
--- a/DW-Programming/room-setting-app/batch-room-gen-v2.py
+++ b/DW-Programming/room-setting-app/batch-room-gen-v2.py
@@ -33,7 +33,7 @@ ROOM_API = "http://127.0.0.1:3075/api/generate-room"
 SHOPIFY_BASE = "https://designer-laboratory-sandbox.myshopify.com/admin/api/2024-01"
 SHOPIFY_TOKEN = "***REMOVED***"
 DB_CONN = "postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified"
-SLACK_WEBHOOK = "https://hooks.slack.com/services/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"
+SLACK_WEBHOOK = "${SLACK_WEBHOOK_URL}"
 
 PROGRESS_FILE = "/tmp/batch-room-progress.json"
 
diff --git a/DW-Programming/room-setting-app/batch-room-generator.py b/DW-Programming/room-setting-app/batch-room-generator.py
index 7bb37a3b..18aa95bb 100644
--- a/DW-Programming/room-setting-app/batch-room-generator.py
+++ b/DW-Programming/room-setting-app/batch-room-generator.py
@@ -27,7 +27,7 @@ ROOM_API = "http://127.0.0.1:3075/api/generate-room"
 SHOPIFY_BASE = "https://designer-laboratory-sandbox.myshopify.com/admin/api/2024-01"
 SHOPIFY_TOKEN = "***REMOVED***"
 DB_CONN = "postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified"
-SLACK_WEBHOOK = "https://hooks.slack.com/services/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"
+SLACK_WEBHOOK = "${SLACK_WEBHOOK_URL}"
 
 PROGRESS_FILE = "/tmp/batch-room-progress.json"
 BATCH_SIZE = int(sys.argv[1]) if len(sys.argv) > 1 else 500  # products per run, override via CLI
diff --git a/DW-Programming/room-setting-app/batch-room-settings.py b/DW-Programming/room-setting-app/batch-room-settings.py
index b539d3fc..a19b22a4 100644
--- a/DW-Programming/room-setting-app/batch-room-settings.py
+++ b/DW-Programming/room-setting-app/batch-room-settings.py
@@ -37,7 +37,7 @@ ROOM_API = "http://127.0.0.1:3075/api/generate-room"
 SHOPIFY_BASE = "https://designer-laboratory-sandbox.myshopify.com/admin/api/2024-01"
 SHOPIFY_TOKEN = "***REMOVED***"
 DB_CONN = "postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified"
-SLACK_WEBHOOK = "https://hooks.slack.com/services/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"
+SLACK_WEBHOOK = "${SLACK_WEBHOOK_URL}"
 PROGRESS_FILE = "/tmp/batch-room-settings-progress.json"
 
 # Commercial vendors get hotel_lobby + office rooms
diff --git a/DW-Programming/room-setting-app/ecosystem.config.js b/DW-Programming/room-setting-app/ecosystem.config.js
index 525e3d58..2e908e71 100644
--- a/DW-Programming/room-setting-app/ecosystem.config.js
+++ b/DW-Programming/room-setting-app/ecosystem.config.js
@@ -9,7 +9,7 @@ module.exports = {
     env: {
       PORT: 3075,
       NODE_ENV: 'production',
-      GEMINI_API_KEY: process.env.GEMINI_API_KEY || 'REDACTED_GEMINI_KEY'
+      GEMINI_API_KEY: process.env.GEMINI_API_KEY || '${GOOGLE_API_KEY}'
     },
     max_memory_restart: '500M',
     instances: 1,
diff --git a/DW-Programming/room-setting-app/generate-phillipe-romano-rooms.py b/DW-Programming/room-setting-app/generate-phillipe-romano-rooms.py
index 4bdcfd12..f0c57baa 100644
--- a/DW-Programming/room-setting-app/generate-phillipe-romano-rooms.py
+++ b/DW-Programming/room-setting-app/generate-phillipe-romano-rooms.py
@@ -26,7 +26,7 @@ ROOM_API = "http://127.0.0.1:3075/api/generate-room"
 SHOPIFY_BASE = "https://designer-laboratory-sandbox.myshopify.com/admin/api/2024-01"
 SHOPIFY_TOKEN = "***REMOVED***"
 DB_CONN = "postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified"
-SLACK_WEBHOOK = "https://hooks.slack.com/services/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"
+SLACK_WEBHOOK = "${SLACK_WEBHOOK_URL}"
 PRODUCTS_JSON = "/tmp/phillipe-romano-rooms-products.json"
 PROGRESS_FILE = "/tmp/phillipe-romano-rooms-progress.json"
 
diff --git a/DW-Programming/room-setting-app/lib/gemini-room-generator.ts b/DW-Programming/room-setting-app/lib/gemini-room-generator.ts
index fd81dd0a..839e7466 100644
--- a/DW-Programming/room-setting-app/lib/gemini-room-generator.ts
+++ b/DW-Programming/room-setting-app/lib/gemini-room-generator.ts
@@ -888,7 +888,7 @@ export class GeminiRoomGenerator {
     // Analysis key for the standard model
     this.gemini = new GoogleGenerativeAI(apiKey);
     // Billed key for image generation model
-    const generationKey = 'REDACTED_GEMINI_KEY';
+    const generationKey = '${GOOGLE_API_KEY}';
     this.generationGemini = new GoogleGenerativeAI(generationKey);
     console.log('GeminiRoomGenerator initialized with gemini-2.5-flash-image (billed)');
   }
@@ -1344,7 +1344,7 @@ let generatorInstance: GeminiRoomGenerator | null = null;
 export function getGeminiGenerator(): GeminiRoomGenerator {
   if (!generatorInstance) {
     // Use the analysis key as default; the constructor also sets the generation key internally
-    const apiKey = process.env.GEMINI_API_KEY || 'REDACTED_GEMINI_KEY';
+    const apiKey = process.env.GEMINI_API_KEY || '${GOOGLE_API_KEY}';
     generatorInstance = new GeminiRoomGenerator(apiKey);
   }
   return generatorInstance;
diff --git a/DW-Programming/room-setting-app/scripts/batch-room-generator.js b/DW-Programming/room-setting-app/scripts/batch-room-generator.js
index a2d6b6a6..11f5b41c 100644
--- a/DW-Programming/room-setting-app/scripts/batch-room-generator.js
+++ b/DW-Programming/room-setting-app/scripts/batch-room-generator.js
@@ -24,7 +24,7 @@ const DB_URL = 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified
 const ROOM_API = 'http://localhost:3075/api/generate-room';
 const SHOPIFY_STORE = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_TOKEN = '***REMOVED***';
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
 // Commercial vendors get hotel_lobby + office rooms
 const COMMERCIAL_VENDORS = new Set([
diff --git a/DW-Programming/room-setting-app/scripts/batch-room-generator.py b/DW-Programming/room-setting-app/scripts/batch-room-generator.py
index 92dee485..949eb486 100644
--- a/DW-Programming/room-setting-app/scripts/batch-room-generator.py
+++ b/DW-Programming/room-setting-app/scripts/batch-room-generator.py
@@ -35,7 +35,7 @@ ROOM_API = "http://127.0.0.1:3075/api/generate-room"
 SHOPIFY_BASE = "https://designer-laboratory-sandbox.myshopify.com/admin/api/2024-01"
 SHOPIFY_TOKEN = "***REMOVED***"
 DB_CONN = "postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified"
-SLACK_WEBHOOK = "https://hooks.slack.com/services/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"
+SLACK_WEBHOOK = "${SLACK_WEBHOOK_URL}"
 PROGRESS_FILE = "/tmp/batch-room-generator-progress.json"
 
 # Commercial vendors — use hotel_lobby + corporate_office
diff --git a/DW-Programming/schumacher-dwsw-full-updater.ts b/DW-Programming/schumacher-dwsw-full-updater.ts
index 2b7c5191..edc8f4bf 100644
--- a/DW-Programming/schumacher-dwsw-full-updater.ts
+++ b/DW-Programming/schumacher-dwsw-full-updater.ts
@@ -16,7 +16,7 @@ const SKU_COUNTER_PATH = '/root/Projects/Designer-Wallcoverings/DW-Programming/I
 
 // Initialize Anthropic with API key
 const anthropic = new Anthropic({
-  apiKey: process.env.ANTHROPIC_API_KEY || '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'
+  apiKey: process.env.ANTHROPIC_API_KEY || "${ANTHROPIC_API_KEY}"
 });
 
 // Parse CLI args
diff --git a/DW-Programming/scrape-versa-evo-pvcfree.js b/DW-Programming/scrape-versa-evo-pvcfree.js
index ae1c9683..f31de3cb 100644
--- a/DW-Programming/scrape-versa-evo-pvcfree.js
+++ b/DW-Programming/scrape-versa-evo-pvcfree.js
@@ -12,7 +12,7 @@ const BASE_URL = 'https://www.versadesignedsurfaces.com';
 const LISTING_URL = `${BASE_URL}/north-america/products/all-products?collection%5B0%5D=Versa%2020%20oz.%20Evo%C2%AE%20PVC-free`;
 const COLLECTION = 'Versa 20 oz. Evo® PVC-free';
 const BRAND = 'Versa Designed Surfaces';
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
 const pool = new Pool({
   connectionString: 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified'
diff --git a/DW-Programming/scrape-versace-images.js b/DW-Programming/scrape-versace-images.js
index 7abd734d..c8786ea0 100644
--- a/DW-Programming/scrape-versace-images.js
+++ b/DW-Programming/scrape-versace-images.js
@@ -21,7 +21,7 @@ const PG_CONN = 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unifie
 const SHOPIFY_DOMAIN = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_TOKEN = '***REMOVED***';
 const SILAS_URL = 'http://127.0.0.1:9674/api/validate-activation';
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
 const pool = new Pool({ connectionString: PG_CONN });
 
diff --git a/DW-Programming/update-specific-schumacher.ts b/DW-Programming/update-specific-schumacher.ts
index 63861398..145726a1 100644
--- a/DW-Programming/update-specific-schumacher.ts
+++ b/DW-Programming/update-specific-schumacher.ts
@@ -10,7 +10,7 @@ const SHOPIFY_CONFIG = {
 };
 
 const anthropic = new Anthropic({
-  apiKey: process.env.ANTHROPIC_API_KEY || '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'
+  apiKey: process.env.ANTHROPIC_API_KEY || "${ANTHROPIC_API_KEY}"
 });
 
 const SKU_COUNTER_PATH = '/root/Projects/Designer-Wallcoverings/DW-Programming/ImportNewSkufromURL/.sku-counter.json';
diff --git a/DW-Programming/vendor-crawlers/lib/crawler-tracker.js b/DW-Programming/vendor-crawlers/lib/crawler-tracker.js
index 3f26c0c5..14d414d6 100644
--- a/DW-Programming/vendor-crawlers/lib/crawler-tracker.js
+++ b/DW-Programming/vendor-crawlers/lib/crawler-tracker.js
@@ -10,7 +10,7 @@ const pool = new Pool({
 });
 
 // Slack webhook for #claude-to-steve channel
-const SLACK_WEBHOOK_URL = process.env.SLACK_WEBHOOK_URL || 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK_URL = process.env.SLACK_WEBHOOK_URL || '${SLACK_WEBHOOK_URL}';
 
 /**
  * Send Slack notification
diff --git a/DW-Programming/vendor-crawlers/scripts/crawl-all.sh b/DW-Programming/vendor-crawlers/scripts/crawl-all.sh
index 502ab69d..11e7b568 100755
--- a/DW-Programming/vendor-crawlers/scripts/crawl-all.sh
+++ b/DW-Programming/vendor-crawlers/scripts/crawl-all.sh
@@ -21,7 +21,7 @@ LOG_FILE="$LOG_DIR/crawl-all-${MODE}-${TIMESTAMP}.log"
 AUTH="***REMOVED***"  # admin:***REMOVED***
 
 # Slack webhook for #claude-to-steve
-SLACK_WEBHOOK="https://hooks.slack.com/services/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"
+SLACK_WEBHOOK="${SLACK_WEBHOOK_URL}"
 
 # Vendor crawlers: name|port (excluding cowtan)
 VENDORS=(
diff --git a/DW-Programming/vendor-crawlers/scripts/monthly-vendor-update.sh b/DW-Programming/vendor-crawlers/scripts/monthly-vendor-update.sh
index dbc6aa20..db82f567 100755
--- a/DW-Programming/vendor-crawlers/scripts/monthly-vendor-update.sh
+++ b/DW-Programming/vendor-crawlers/scripts/monthly-vendor-update.sh
@@ -19,7 +19,7 @@ LOG_FILE="$LOG_DIR/monthly-update-$TIMESTAMP.log"
 AUTH="***REMOVED***"  # admin:***REMOVED***
 
 # Slack webhook for #claude-to-steve
-SLACK_WEBHOOK="https://hooks.slack.com/services/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"
+SLACK_WEBHOOK="${SLACK_WEBHOOK_URL}"
 
 notify_slack() {
   curl -s -X POST -H 'Content-type: application/json' \
diff --git a/DW-Programming/versace-image-scraper.js b/DW-Programming/versace-image-scraper.js
index 298bdc1a..674230fc 100644
--- a/DW-Programming/versace-image-scraper.js
+++ b/DW-Programming/versace-image-scraper.js
@@ -11,7 +11,7 @@ const fs = require('fs');
 const DB_URL = 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified';
 const SHOPIFY_DOMAIN = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_TOKEN = '***REMOVED***';
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
 // Step 1: Load sitemap URLs and match against our MFR SKUs
 async function matchSitemapToProducts() {
diff --git a/DW-Programming/versace-image-uploader.js b/DW-Programming/versace-image-uploader.js
index f9d94071..44c9be75 100644
--- a/DW-Programming/versace-image-uploader.js
+++ b/DW-Programming/versace-image-uploader.js
@@ -12,7 +12,7 @@ const { Pool } = require('pg');
 // === CONFIG ===
 const SHOPIFY_DOMAIN = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_TOKEN = '***REMOVED***';
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
 const pool = new Pool({
   connectionString: 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified'
diff --git a/DW-Programming/zoffany-ai-enrich.js b/DW-Programming/zoffany-ai-enrich.js
index 105aff47..c5a7a2e2 100644
--- a/DW-Programming/zoffany-ai-enrich.js
+++ b/DW-Programming/zoffany-ai-enrich.js
@@ -16,9 +16,9 @@ const { Pool } = require('pg');
 const https = require('https');
 const http = require('http');
 
-const GEMINI_API_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_API_KEY = '${GOOGLE_API_KEY}';
 const GEMINI_URL = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${GEMINI_API_KEY}`;
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
 const pool = new Pool({
   connectionString: 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified'
diff --git a/DW-Skills-Output/.gitignore b/DW-Skills-Output/.gitignore
new file mode 100644
index 00000000..7e6a9c3e
--- /dev/null
+++ b/DW-Skills-Output/.gitignore
@@ -0,0 +1,12 @@
+node_modules/
+.env
+.env.local
+.env.*.local
+.env.*
+tmp/
+*.log
+.DS_Store
+dist/
+build/
+.next/
+*.bak
diff --git a/DW-Skills/.gitignore b/DW-Skills/.gitignore
new file mode 100644
index 00000000..7e6a9c3e
--- /dev/null
+++ b/DW-Skills/.gitignore
@@ -0,0 +1,12 @@
+node_modules/
+.env
+.env.local
+.env.*.local
+.env.*
+tmp/
+*.log
+.DS_Store
+dist/
+build/
+.next/
+*.bak
diff --git a/DW-Websites/.gitignore b/DW-Websites/.gitignore
new file mode 100644
index 00000000..7e6a9c3e
--- /dev/null
+++ b/DW-Websites/.gitignore
@@ -0,0 +1,12 @@
+node_modules/
+.env
+.env.local
+.env.*.local
+.env.*
+tmp/
+*.log
+.DS_Store
+dist/
+build/
+.next/
+*.bak
diff --git a/DW-Websites/DesignerWallcoverings-product.liquid b/DW-Websites/DesignerWallcoverings-product.liquid
index c67a8d37..8ff300ec 100644
--- a/DW-Websites/DesignerWallcoverings-product.liquid
+++ b/DW-Websites/DesignerWallcoverings-product.liquid
@@ -164,7 +164,192 @@ select[name="options[Size]"]{ min-width:52ch !important; }
   <!-- AI Color Key Block: moved below main image -->
 <div id="ai-color-key-container" style="margin-top: 1em; margin-bottom: 1em;"></div>
 
+  {%- comment -%}
+    Design Coordinate — inline expanding grid of 6 coordinating patterns.
+    Internal aliases: "Pairs Well With This Design" (concept), pairs-well-with
+    (skill), dw-pairs-well (service). Endpoint configurable via
+    data-pairs-endpoint. The pairs-well__* CSS class names are kept as the
+    internal namespace — only the button TEXT is "Design Coordinate".
+  {%- endcomment -%}
+  <section
+    id="pairs-well-with"
+    data-pairs-endpoint="https://pairs.designerwallcoverings.com/api/pairs"
+    data-product-handle="{{ product.handle }}"
+    data-product-sku="{{ product.metafields.custom.manufacturer_sku | default: product.selected_or_first_available_variant.sku | escape }}"
+    style="margin: 1.5em 0 2em; clear: both;"
+    hidden
+  >
+    <button
+      type="button"
+      class="pairs-well__cta"
+      aria-expanded="false"
+      aria-controls="pairs-well-grid"
+    >
+      <span class="pairs-well__cta-text">Design Coordinate</span>
+      <span class="pairs-well__cta-icon" aria-hidden="true">+</span>
+    </button>
+    <div
+      id="pairs-well-grid"
+      class="pairs-well__grid"
+      aria-live="polite"
+      hidden
+    ></div>
+  </section>
+
+  <style>
+    /* Pairs Well — inline grid below product image */
+    #pairs-well-with { font-family: inherit; }
+    .pairs-well__cta {
+      display: flex; align-items: center; justify-content: space-between;
+      width: 100%; padding: 18px 24px; margin: 0;
+      background: #111; color: #fff;
+      border: 0; border-radius: 999px;
+      font-size: 15px; font-weight: 500; letter-spacing: 0.06em;
+      text-transform: uppercase; cursor: pointer;
+      transition: background 160ms ease, transform 120ms ease;
+    }
+    .pairs-well__cta:hover  { background: #2a2a2a; }
+    .pairs-well__cta:active { transform: scale(0.995); }
+    .pairs-well__cta[aria-expanded="true"] .pairs-well__cta-icon { transform: rotate(45deg); }
+    .pairs-well__cta-icon {
+      display: inline-block; font-size: 22px; line-height: 1;
+      transition: transform 200ms ease;
+    }
+    .pairs-well__grid {
+      display: grid; gap: 16px; margin-top: 18px;
+      grid-template-columns: repeat(3, minmax(0, 1fr));
+    }
+    @media (max-width: 900px)  { .pairs-well__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
+    @media (max-width: 540px)  { .pairs-well__grid { grid-template-columns: 1fr; } }
+    .pairs-well__card {
+      display: block; text-decoration: none; color: inherit;
+      background: #fff; border: 1px solid #e7e7e7; border-radius: 6px;
+      overflow: hidden; transition: box-shadow 160ms ease, transform 160ms ease;
+    }
+    .pairs-well__card:hover { box-shadow: 0 6px 20px rgba(0,0,0,0.08); transform: translateY(-2px); }
+    .pairs-well__img-wrap {
+      aspect-ratio: 1 / 1; background: #f4f4f4; overflow: hidden;
+    }
+    .pairs-well__img {
+      width: 100%; height: 100%; object-fit: cover; display: block;
+    }
+    .pairs-well__meta { padding: 12px 14px 14px; }
+    .pairs-well__title {
+      margin: 0 0 4px; font-size: 14px; font-weight: 600; line-height: 1.3;
+      display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
+      overflow: hidden;
+    }
+    .pairs-well__vendor {
+      margin: 0 0 8px; font-size: 12px; color: #777; letter-spacing: 0.04em;
+      text-transform: uppercase;
+    }
+    .pairs-well__why {
+      display: inline-block; padding: 3px 8px; background: #f4ede4;
+      color: #5a4628; border-radius: 999px;
+      font-size: 11px; line-height: 1.4;
+    }
+    .pairs-well__skeleton {
+      background: linear-gradient(90deg, #eee 0%, #f6f6f6 50%, #eee 100%);
+      background-size: 200% 100%; animation: pwShim 1.2s linear infinite;
+      aspect-ratio: 1 / 1; border-radius: 6px;
+    }
+    @keyframes pwShim { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }
+    .pairs-well__empty { padding: 18px; color: #777; font-size: 14px; }
+  </style>
+
+  <script>
+    (function () {
+      var root = document.getElementById('pairs-well-with');
+      if (!root) return;
+
+      var endpoint = root.getAttribute('data-pairs-endpoint');
+      var handle   = root.getAttribute('data-product-handle');
+      var sku      = root.getAttribute('data-product-sku');
+      var btn      = root.querySelector('.pairs-well__cta');
+      var grid     = root.querySelector('.pairs-well__grid');
+      var loaded   = false;
+
+      // Reveal the section only if we have a usable identifier
+      if ((sku && sku.length) || (handle && handle.length)) {
+        root.hidden = false;
+      } else {
+        return;
+      }
 
+      function renderSkeletons(n) {
+        var html = '';
+        for (var i = 0; i < n; i++) html += '<div class="pairs-well__skeleton"></div>';
+        grid.innerHTML = html;
+      }
+
+      function esc(s) {
+        return String(s == null ? '' : s)
+          .replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')
+          .replace(/"/g, '&quot;').replace(/'/g, '&#39;');
+      }
+
+      function renderCards(pairs) {
+        if (!pairs || !pairs.length) {
+          grid.innerHTML = '<div class="pairs-well__empty">No design coordinates found yet for this pattern.</div>';
+          return;
+        }
+        grid.innerHTML = pairs.map(function (p) {
+          var img = p.image_url ? esc(p.image_url) : '';
+          var why = (p.why && p.why[0]) ? esc(p.why[0]) : '';
+          return ''
+            + '<a class="pairs-well__card" href="' + esc(p.url || ('/products/' + p.handle)) + '" title="' + esc((p.why || []).join(' · ')) + '">'
+            +   '<div class="pairs-well__img-wrap">'
+            +     (img ? '<img class="pairs-well__img" src="' + img + '" alt="' + esc(p.title) + '" loading="lazy">' : '')
+            +   '</div>'
+            +   '<div class="pairs-well__meta">'
+            +     '<p class="pairs-well__title">' + esc(p.title || '') + '</p>'
+            +     '<p class="pairs-well__vendor">' + esc(p.vendor || '') + '</p>'
+            +     (why ? '<span class="pairs-well__why">' + why + '</span>' : '')
+            +   '</div>'
+            + '</a>';
+        }).join('');
+      }
+
+      function buildUrl() {
+        var qs = [];
+        if (sku)    qs.push('dw_sku=' + encodeURIComponent(sku));
+        if (handle) qs.push('handle=' + encodeURIComponent(handle));
+        return endpoint + '?' + qs.join('&');
+      }
+
+      function load() {
+        if (loaded) return Promise.resolve();
+        renderSkeletons(6);
+        return fetch(buildUrl(), { credentials: 'omit' })
+          .then(function (r) { return r.ok ? r.json() : Promise.reject(new Error('http ' + r.status)); })
+          .then(function (data) {
+            if (!data || data.ok === false) throw new Error((data && data.error) || 'bad payload');
+            renderCards(data.pairs || []);
+            loaded = true;
+            if (!(data.pairs || []).length) {
+              // No pairs available — hide the whole section so we never leave a dead button
+              root.hidden = true;
+            }
+          })
+          .catch(function () {
+            // Soft fail — hide the button rather than show a broken UI
+            root.hidden = true;
+          });
+      }
+
+      btn.addEventListener('click', function () {
+        var open = btn.getAttribute('aria-expanded') === 'true';
+        if (open) {
+          btn.setAttribute('aria-expanded', 'false');
+          grid.hidden = true;
+          return;
+        }
+        btn.setAttribute('aria-expanded', 'true');
+        grid.hidden = false;
+        load();
+      });
+    })();
+  </script>
 
   <div
     class="product-recommendations-wrapper--right"
diff --git a/DW-Websites/GoldLeafWallpaper/index.html b/DW-Websites/GoldLeafWallpaper/index.html
index f921fe6e..65d6ca70 100644
--- a/DW-Websites/GoldLeafWallpaper/index.html
+++ b/DW-Websites/GoldLeafWallpaper/index.html
@@ -440,5 +440,104 @@
 </script>
 <script src="/dw-fleet-nav.js" defer></script>
 
+<!-- DW-HAMBURGER-NAV v1 (canonical 2026-05-10) -->
+<style id="dw-hamburger-styles">
+  /* Canonical hamburger nav — always visible top-right, all viewports.
+     Standing rule (Steve, 2026-05-08): hamburger is the primary nav. */
+  .dw-burger-btn {
+    position: fixed; top: 18px; right: 18px; z-index: 9999;
+    width: 44px; height: 44px;
+    background: rgba(20,20,20,0.78); color: #f5f1e8;
+    backdrop-filter: blur(8px) saturate(140%);
+    -webkit-backdrop-filter: blur(8px) saturate(140%);
+    border: 1px solid rgba(245,241,232,0.18); border-radius: 50%;
+    cursor: pointer; padding: 0;
+    display: flex; flex-direction: column; align-items: center; justify-content: center;
+    gap: 4px;
+    box-shadow: 0 6px 20px rgba(0,0,0,0.35);
+    transition: background 200ms, transform 200ms;
+  }
+  .dw-burger-btn:hover { background: rgba(20,20,20,0.92); }
+  .dw-burger-btn span {
+    display: block; width: 20px; height: 1.5px; background: currentColor;
+    transition: transform 220ms, opacity 220ms;
+  }
+  .dw-burger-btn[aria-expanded="true"] span:nth-child(1) {
+    transform: translateY(5.5px) rotate(45deg);
+  }
+  .dw-burger-btn[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
+  .dw-burger-btn[aria-expanded="true"] span:nth-child(3) {
+    transform: translateY(-5.5px) rotate(-45deg);
+  }
+  .dw-burger-panel {
+    position: fixed; top: 72px; right: 18px; z-index: 9998;
+    min-width: 240px; max-width: 88vw;
+    background: rgba(15,15,15,0.96);
+    backdrop-filter: blur(14px) saturate(140%);
+    -webkit-backdrop-filter: blur(14px) saturate(140%);
+    border: 1px solid rgba(245,241,232,0.12);
+    border-radius: 14px;
+    box-shadow: 0 18px 50px rgba(0,0,0,0.55);
+    padding: 10px 0;
+    display: none;
+    font-family: -apple-system, "SF Pro Text", system-ui, sans-serif;
+  }
+  .dw-burger-panel.open { display: block; }
+  .dw-burger-panel a,
+  .dw-burger-panel button {
+    display: block; width: 100%;
+    padding: 13px 22px;
+    color: #f5f1e8 !important;
+    background: transparent; border: 0; cursor: pointer;
+    text-decoration: none !important;
+    font-size: 15px; font-weight: 400;
+    text-align: left;
+    letter-spacing: 0;
+    border-bottom: 1px solid rgba(245,241,232,0.06);
+    transition: background 160ms, color 160ms;
+    box-sizing: border-box;
+  }
+  .dw-burger-panel a:last-child,
+  .dw-burger-panel button:last-child { border-bottom: 0; }
+  .dw-burger-panel a:hover,
+  .dw-burger-panel button:hover {
+    background: rgba(245,241,232,0.06);
+    color: #ffffff !important;
+  }
+  @media (max-width: 480px) {
+    .dw-burger-btn { top: 12px; right: 12px; width: 40px; height: 40px; }
+    .dw-burger-panel { top: 62px; right: 12px; }
+  }
+  /* Avoid double-print on sites already adopting a top-of-page header
+     that overlaps z-index. Reserve safe space near top-right. */
+</style>
+<button type="button" class="dw-burger-btn" id="dwBurgerBtn"
+        aria-label="Toggle menu" aria-controls="dwBurgerPanel"
+        aria-expanded="false">
+  <span></span><span></span><span></span>
+</button>
+<nav class="dw-burger-panel" id="dwBurgerPanel" aria-label="Primary">
+  <a href="tel:8883734564">Contact</a>
+  <a href="mailto:info@GoldLeafWallpaper.com">Contact</a>
+</nav>
+<script>
+(function(){
+  var btn = document.getElementById('dwBurgerBtn');
+  var panel = document.getElementById('dwBurgerPanel');
+  if (!btn || !panel) return;
+  function close(){ panel.classList.remove('open'); btn.setAttribute('aria-expanded','false'); }
+  function toggle(){
+    var open = panel.classList.toggle('open');
+    btn.setAttribute('aria-expanded', open ? 'true' : 'false');
+  }
+  btn.addEventListener('click', function(e){ e.stopPropagation(); toggle(); });
+  document.addEventListener('click', function(e){
+    if (panel.classList.contains('open') && !panel.contains(e.target) && e.target !== btn) close();
+  });
+  document.addEventListener('keydown', function(e){ if (e.key === 'Escape') close(); });
+})();
+</script>
+<!-- /DW-HAMBURGER-NAV v1 -->
+
 </body>
 </html>
diff --git a/DW-Websites/GrassclothWallpaper.com/index.html b/DW-Websites/GrassclothWallpaper.com/index.html
index a2321006..b69e2719 100644
--- a/DW-Websites/GrassclothWallpaper.com/index.html
+++ b/DW-Websites/GrassclothWallpaper.com/index.html
@@ -1582,5 +1582,105 @@
     <!-- End of Zendesk Widget script -->
 <script src="/dw-fleet-nav.js" defer></script>
 
+<!-- DW-HAMBURGER-NAV v1 (canonical 2026-05-10) -->
+<style id="dw-hamburger-styles">
+  /* Canonical hamburger nav — always visible top-right, all viewports.
+     Standing rule (Steve, 2026-05-08): hamburger is the primary nav. */
+  .dw-burger-btn {
+    position: fixed; top: 18px; right: 18px; z-index: 9999;
+    width: 44px; height: 44px;
+    background: rgba(20,20,20,0.78); color: #f5f1e8;
+    backdrop-filter: blur(8px) saturate(140%);
+    -webkit-backdrop-filter: blur(8px) saturate(140%);
+    border: 1px solid rgba(245,241,232,0.18); border-radius: 50%;
+    cursor: pointer; padding: 0;
+    display: flex; flex-direction: column; align-items: center; justify-content: center;
+    gap: 4px;
+    box-shadow: 0 6px 20px rgba(0,0,0,0.35);
+    transition: background 200ms, transform 200ms;
+  }
+  .dw-burger-btn:hover { background: rgba(20,20,20,0.92); }
+  .dw-burger-btn span {
+    display: block; width: 20px; height: 1.5px; background: currentColor;
+    transition: transform 220ms, opacity 220ms;
+  }
+  .dw-burger-btn[aria-expanded="true"] span:nth-child(1) {
+    transform: translateY(5.5px) rotate(45deg);
+  }
+  .dw-burger-btn[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
+  .dw-burger-btn[aria-expanded="true"] span:nth-child(3) {
+    transform: translateY(-5.5px) rotate(-45deg);
+  }
+  .dw-burger-panel {
+    position: fixed; top: 72px; right: 18px; z-index: 9998;
+    min-width: 240px; max-width: 88vw;
+    background: rgba(15,15,15,0.96);
+    backdrop-filter: blur(14px) saturate(140%);
+    -webkit-backdrop-filter: blur(14px) saturate(140%);
+    border: 1px solid rgba(245,241,232,0.12);
+    border-radius: 14px;
+    box-shadow: 0 18px 50px rgba(0,0,0,0.55);
+    padding: 10px 0;
+    display: none;
+    font-family: -apple-system, "SF Pro Text", system-ui, sans-serif;
+  }
+  .dw-burger-panel.open { display: block; }
+  .dw-burger-panel a,
+  .dw-burger-panel button {
+    display: block; width: 100%;
+    padding: 13px 22px;
+    color: #f5f1e8 !important;
+    background: transparent; border: 0; cursor: pointer;
+    text-decoration: none !important;
+    font-size: 15px; font-weight: 400;
+    text-align: left;
+    letter-spacing: 0;
+    border-bottom: 1px solid rgba(245,241,232,0.06);
+    transition: background 160ms, color 160ms;
+    box-sizing: border-box;
+  }
+  .dw-burger-panel a:last-child,
+  .dw-burger-panel button:last-child { border-bottom: 0; }
+  .dw-burger-panel a:hover,
+  .dw-burger-panel button:hover {
+    background: rgba(245,241,232,0.06);
+    color: #ffffff !important;
+  }
+  @media (max-width: 480px) {
+    .dw-burger-btn { top: 12px; right: 12px; width: 40px; height: 40px; }
+    .dw-burger-panel { top: 62px; right: 12px; }
+  }
+  /* Avoid double-print on sites already adopting a top-of-page header
+     that overlaps z-index. Reserve safe space near top-right. */
+</style>
+<button type="button" class="dw-burger-btn" id="dwBurgerBtn"
+        aria-label="Toggle menu" aria-controls="dwBurgerPanel"
+        aria-expanded="false">
+  <span></span><span></span><span></span>
+</button>
+<nav class="dw-burger-panel" id="dwBurgerPanel" aria-label="Primary">
+  <a href="/">Home</a>
+  <a href="/about">About</a>
+  <a href="mailto:info@GrassclothWallpaper.com.com">Contact</a>
+</nav>
+<script>
+(function(){
+  var btn = document.getElementById('dwBurgerBtn');
+  var panel = document.getElementById('dwBurgerPanel');
+  if (!btn || !panel) return;
+  function close(){ panel.classList.remove('open'); btn.setAttribute('aria-expanded','false'); }
+  function toggle(){
+    var open = panel.classList.toggle('open');
+    btn.setAttribute('aria-expanded', open ? 'true' : 'false');
+  }
+  btn.addEventListener('click', function(e){ e.stopPropagation(); toggle(); });
+  document.addEventListener('click', function(e){
+    if (panel.classList.contains('open') && !panel.contains(e.target) && e.target !== btn) close();
+  });
+  document.addEventListener('keydown', function(e){ if (e.key === 'Escape') close(); });
+})();
+</script>
+<!-- /DW-HAMBURGER-NAV v1 -->
+
 </body>
 </html>
\ No newline at end of file
diff --git a/DW-Websites/LosAngelesFabrics b/DW-Websites/LosAngelesFabrics
new file mode 160000
index 00000000..173470e4
--- /dev/null
+++ b/DW-Websites/LosAngelesFabrics
@@ -0,0 +1 @@
+Subproject commit 173470e45d45e3f7809434695a7eb566cace3d5c
diff --git a/DW-Websites/_shared/deploy-fleet-nav.sh b/DW-Websites/_shared/deploy-fleet-nav.sh
new file mode 100755
index 00000000..97715076
--- /dev/null
+++ b/DW-Websites/_shared/deploy-fleet-nav.sh
@@ -0,0 +1,87 @@
+#!/bin/bash
+# deploy-fleet-nav.sh — push the dw-fleet-nav widget to all 9 Kamatera sister sites.
+#
+# Honors Steve's standing rules:
+#   - sets Cache-Control: no-store on the edited index.html (CF caches HTML)
+#   - rsync only the two files we touched (widget + index.html)
+#   - no-op if remote already has identical files
+#   - aborts on first failure
+#
+# Run:  bash ~/Projects/Designer-Wallcoverings/DW-Websites/_shared/deploy-fleet-nav.sh
+
+set -euo pipefail
+
+KAM=root@45.61.58.125
+DWW=$HOME/Projects/Designer-Wallcoverings/DW-Websites
+WIDGET=$DWW/_shared/dw-fleet-nav.js
+
+# site_name : kamatera_path : local_path
+declare -a SITES=(
+  "flockedwallpaper.com:/var/www/flockedwallpaper.com:$DWW/flockedwallpaper"
+  "glassbeadedwallpaper.com:/var/www/glassbeadedwallpaper.com:$DWW/glassbeadedwallpaper"
+  "goldleafwallpaper.com:/var/www/goldleafwallpaper.com:$DWW/GoldLeafWallpaper"
+  "grassclothwallcoverings.com:/var/www/grassclothwallcoverings.com:$DWW/GrassclothWallcoverings"
+  "grassclothwallpaper.com:/var/www/grassclothwallpaper.com:$DWW/GrassclothWallpaper.com"
+  "losangelesfabrics.com:/var/www/losangelesfabrics.com:$DWW/LosAngelesFabrics"
+  "shopbycolor.com:/var/www/shopbycolor.com:$DWW/shop-by-color"
+  "hospitalitywallpaper.com:/var/www/hospitalitywallpaper.com:$HOME/Projects/hospitalitywallpaper/public"
+  "museumpublicdomain.com:/var/www/museumpublicdomain.com:$HOME/Projects/museumwallpaper/public"
+)
+
+for entry in "${SITES[@]}"; do
+  IFS=':' read -r DOMAIN REMOTE LOCAL <<< "$entry"
+  echo ""
+  echo "=== $DOMAIN ==="
+
+  # Skip if local files don't exist
+  if [ ! -f "$LOCAL/dw-fleet-nav.js" ] || [ ! -f "$LOCAL/index.html" ]; then
+    echo "  SKIP — local files missing at $LOCAL"
+    continue
+  fi
+
+  # Probe remote path — must exist; if not, error and continue
+  if ! ssh -o ConnectTimeout=8 "$KAM" "test -d $REMOTE" 2>/dev/null; then
+    echo "  SKIP — remote path missing: $REMOTE"
+    continue
+  fi
+
+  # Detect docroot — could be REMOTE itself, REMOTE/public, or REMOTE/htdocs
+  DOCROOT=""
+  for cand in "$REMOTE/public" "$REMOTE/htdocs" "$REMOTE"; do
+    if ssh "$KAM" "test -f $cand/index.html" 2>/dev/null; then
+      DOCROOT=$cand
+      break
+    fi
+  done
+  if [ -z "$DOCROOT" ]; then
+    echo "  SKIP — no index.html under $REMOTE/{public,htdocs,/}"
+    continue
+  fi
+  echo "  docroot = $DOCROOT"
+
+  # Backup remote files (one-time per deploy)
+  STAMP=$(date +%Y%m%d-%H%M%S)
+  ssh "$KAM" "cp -p $DOCROOT/index.html $DOCROOT/index.html.bak.fleetnav-$STAMP 2>/dev/null || true"
+
+  # Push the widget + edited index.html
+  rsync -t --partial "$LOCAL/dw-fleet-nav.js" "$KAM:$DOCROOT/dw-fleet-nav.js"
+  rsync -t --partial "$LOCAL/index.html"      "$KAM:$DOCROOT/index.html"
+
+  echo "  ✓ pushed dw-fleet-nav.js + index.html"
+done
+
+echo ""
+echo "=== Cache-Control no-store sweep (per CF-HTML-caching memory) ==="
+ssh "$KAM" "if [ -x /var/www/admin-console/scripts/add-cache-header.py ]; then python3 /var/www/admin-console/scripts/add-cache-header.py --apply --sites flockedwallpaper.com,glassbeadedwallpaper.com,goldleafwallpaper.com,grassclothwallcoverings.com,grassclothwallpaper.com,losangelesfabrics.com,shopbycolor.com,hospitalitywallpaper.com,museumpublicdomain.com 2>&1 | tail -10; else echo 'add-cache-header.py not found — please run manually'; fi"
+
+echo ""
+echo "=== nginx reload ==="
+ssh "$KAM" "nginx -t && nginx -s reload" 2>&1 | tail -3
+
+echo ""
+echo "=== smoke test: each domain returns the script tag ==="
+for entry in "${SITES[@]}"; do
+  DOMAIN=$(echo "$entry" | cut -d: -f1)
+  N=$(curl -sL --max-time 6 "https://$DOMAIN/" 2>/dev/null | grep -c "dw-fleet-nav.js" || echo 0)
+  if [ "$N" -gt 0 ]; then echo "  ✓ $DOMAIN ($N refs)"; else echo "  ✗ $DOMAIN — no script tag served"; fi
+done
diff --git a/DW-Websites/flockedwallpaper-mobile/index.html b/DW-Websites/flockedwallpaper-mobile/index.html
index ccd1e4cb..0337c19b 100644
--- a/DW-Websites/flockedwallpaper-mobile/index.html
+++ b/DW-Websites/flockedwallpaper-mobile/index.html
@@ -267,5 +267,105 @@ init();
 
 <!-- Zendesk Widget -->
 <script id="ze-snippet" src="https://static.zdassets.com/ekr/snippet.js?key=4d4f52ea-1e3e-4837-8859-51f9abd5a82b"></script>
+<!-- DW-HAMBURGER-NAV v1 (canonical 2026-05-10) -->
+<style id="dw-hamburger-styles">
+  /* Canonical hamburger nav — always visible top-right, all viewports.
+     Standing rule (Steve, 2026-05-08): hamburger is the primary nav. */
+  .dw-burger-btn {
+    position: fixed; top: 18px; right: 18px; z-index: 9999;
+    width: 44px; height: 44px;
+    background: rgba(20,20,20,0.78); color: #f5f1e8;
+    backdrop-filter: blur(8px) saturate(140%);
+    -webkit-backdrop-filter: blur(8px) saturate(140%);
+    border: 1px solid rgba(245,241,232,0.18); border-radius: 50%;
+    cursor: pointer; padding: 0;
+    display: flex; flex-direction: column; align-items: center; justify-content: center;
+    gap: 4px;
+    box-shadow: 0 6px 20px rgba(0,0,0,0.35);
+    transition: background 200ms, transform 200ms;
+  }
+  .dw-burger-btn:hover { background: rgba(20,20,20,0.92); }
+  .dw-burger-btn span {
+    display: block; width: 20px; height: 1.5px; background: currentColor;
+    transition: transform 220ms, opacity 220ms;
+  }
+  .dw-burger-btn[aria-expanded="true"] span:nth-child(1) {
+    transform: translateY(5.5px) rotate(45deg);
+  }
+  .dw-burger-btn[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
+  .dw-burger-btn[aria-expanded="true"] span:nth-child(3) {
+    transform: translateY(-5.5px) rotate(-45deg);
+  }
+  .dw-burger-panel {
+    position: fixed; top: 72px; right: 18px; z-index: 9998;
+    min-width: 240px; max-width: 88vw;
+    background: rgba(15,15,15,0.96);
+    backdrop-filter: blur(14px) saturate(140%);
+    -webkit-backdrop-filter: blur(14px) saturate(140%);
+    border: 1px solid rgba(245,241,232,0.12);
+    border-radius: 14px;
+    box-shadow: 0 18px 50px rgba(0,0,0,0.55);
+    padding: 10px 0;
+    display: none;
+    font-family: -apple-system, "SF Pro Text", system-ui, sans-serif;
+  }
+  .dw-burger-panel.open { display: block; }
+  .dw-burger-panel a,
+  .dw-burger-panel button {
+    display: block; width: 100%;
+    padding: 13px 22px;
+    color: #f5f1e8 !important;
+    background: transparent; border: 0; cursor: pointer;
+    text-decoration: none !important;
+    font-size: 15px; font-weight: 400;
+    text-align: left;
+    letter-spacing: 0;
+    border-bottom: 1px solid rgba(245,241,232,0.06);
+    transition: background 160ms, color 160ms;
+    box-sizing: border-box;
+  }
+  .dw-burger-panel a:last-child,
+  .dw-burger-panel button:last-child { border-bottom: 0; }
+  .dw-burger-panel a:hover,
+  .dw-burger-panel button:hover {
+    background: rgba(245,241,232,0.06);
+    color: #ffffff !important;
+  }
+  @media (max-width: 480px) {
+    .dw-burger-btn { top: 12px; right: 12px; width: 40px; height: 40px; }
+    .dw-burger-panel { top: 62px; right: 12px; }
+  }
+  /* Avoid double-print on sites already adopting a top-of-page header
+     that overlaps z-index. Reserve safe space near top-right. */
+</style>
+<button type="button" class="dw-burger-btn" id="dwBurgerBtn"
+        aria-label="Toggle menu" aria-controls="dwBurgerPanel"
+        aria-expanded="false">
+  <span></span><span></span><span></span>
+</button>
+<nav class="dw-burger-panel" id="dwBurgerPanel" aria-label="Primary">
+  <a href="/">Home</a>
+  <a href="/about">About</a>
+  <a href="mailto:info@flockedwallpaper-mobile.com">Contact</a>
+</nav>
+<script>
+(function(){
+  var btn = document.getElementById('dwBurgerBtn');
+  var panel = document.getElementById('dwBurgerPanel');
+  if (!btn || !panel) return;
+  function close(){ panel.classList.remove('open'); btn.setAttribute('aria-expanded','false'); }
+  function toggle(){
+    var open = panel.classList.toggle('open');
+    btn.setAttribute('aria-expanded', open ? 'true' : 'false');
+  }
+  btn.addEventListener('click', function(e){ e.stopPropagation(); toggle(); });
+  document.addEventListener('click', function(e){
+    if (panel.classList.contains('open') && !panel.contains(e.target) && e.target !== btn) close();
+  });
+  document.addEventListener('keydown', function(e){ if (e.key === 'Escape') close(); });
+})();
+</script>
+<!-- /DW-HAMBURGER-NAV v1 -->
+
 </body>
 </html>
diff --git a/DW-Websites/flockedwallpaper/agenda.html b/DW-Websites/flockedwallpaper/agenda.html
index 8567e377..d7aaa15f 100644
--- a/DW-Websites/flockedwallpaper/agenda.html
+++ b/DW-Websites/flockedwallpaper/agenda.html
@@ -142,7 +142,7 @@ body{font-family:'Inter',sans-serif;background:#F5F0EB;min-height:100vh;padding:
 <script>
 const votes = {};
 const TOTAL = 6;
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
 function vote(id, decision) {
   votes[id] = decision;
diff --git a/DW-Websites/flockedwallpaper/index.html b/DW-Websites/flockedwallpaper/index.html
index 6ed58c2b..ce14e30e 100644
--- a/DW-Websites/flockedwallpaper/index.html
+++ b/DW-Websites/flockedwallpaper/index.html
@@ -269,5 +269,105 @@ init();
 <script id="ze-snippet" src="https://static.zdassets.com/ekr/snippet.js?key=4d4f52ea-1e3e-4837-8859-51f9abd5a82b"></script>
 <script src="/dw-fleet-nav.js" defer></script>
 
+<!-- DW-HAMBURGER-NAV v1 (canonical 2026-05-10) -->
+<style id="dw-hamburger-styles">
+  /* Canonical hamburger nav — always visible top-right, all viewports.
+     Standing rule (Steve, 2026-05-08): hamburger is the primary nav. */
+  .dw-burger-btn {
+    position: fixed; top: 18px; right: 18px; z-index: 9999;
+    width: 44px; height: 44px;
+    background: rgba(20,20,20,0.78); color: #f5f1e8;
+    backdrop-filter: blur(8px) saturate(140%);
+    -webkit-backdrop-filter: blur(8px) saturate(140%);
+    border: 1px solid rgba(245,241,232,0.18); border-radius: 50%;
+    cursor: pointer; padding: 0;
+    display: flex; flex-direction: column; align-items: center; justify-content: center;
+    gap: 4px;
+    box-shadow: 0 6px 20px rgba(0,0,0,0.35);
+    transition: background 200ms, transform 200ms;
+  }
+  .dw-burger-btn:hover { background: rgba(20,20,20,0.92); }
+  .dw-burger-btn span {
+    display: block; width: 20px; height: 1.5px; background: currentColor;
+    transition: transform 220ms, opacity 220ms;
+  }
+  .dw-burger-btn[aria-expanded="true"] span:nth-child(1) {
+    transform: translateY(5.5px) rotate(45deg);
+  }
+  .dw-burger-btn[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
+  .dw-burger-btn[aria-expanded="true"] span:nth-child(3) {
+    transform: translateY(-5.5px) rotate(-45deg);
+  }
+  .dw-burger-panel {
+    position: fixed; top: 72px; right: 18px; z-index: 9998;
+    min-width: 240px; max-width: 88vw;
+    background: rgba(15,15,15,0.96);
+    backdrop-filter: blur(14px) saturate(140%);
+    -webkit-backdrop-filter: blur(14px) saturate(140%);
+    border: 1px solid rgba(245,241,232,0.12);
+    border-radius: 14px;
+    box-shadow: 0 18px 50px rgba(0,0,0,0.55);
+    padding: 10px 0;
+    display: none;
+    font-family: -apple-system, "SF Pro Text", system-ui, sans-serif;
+  }
+  .dw-burger-panel.open { display: block; }
+  .dw-burger-panel a,
+  .dw-burger-panel button {
+    display: block; width: 100%;
+    padding: 13px 22px;
+    color: #f5f1e8 !important;
+    background: transparent; border: 0; cursor: pointer;
+    text-decoration: none !important;
+    font-size: 15px; font-weight: 400;
+    text-align: left;
+    letter-spacing: 0;
+    border-bottom: 1px solid rgba(245,241,232,0.06);
+    transition: background 160ms, color 160ms;
+    box-sizing: border-box;
+  }
+  .dw-burger-panel a:last-child,
+  .dw-burger-panel button:last-child { border-bottom: 0; }
+  .dw-burger-panel a:hover,
+  .dw-burger-panel button:hover {
+    background: rgba(245,241,232,0.06);
+    color: #ffffff !important;
+  }
+  @media (max-width: 480px) {
+    .dw-burger-btn { top: 12px; right: 12px; width: 40px; height: 40px; }
+    .dw-burger-panel { top: 62px; right: 12px; }
+  }
+  /* Avoid double-print on sites already adopting a top-of-page header
+     that overlaps z-index. Reserve safe space near top-right. */
+</style>
+<button type="button" class="dw-burger-btn" id="dwBurgerBtn"
+        aria-label="Toggle menu" aria-controls="dwBurgerPanel"
+        aria-expanded="false">
+  <span></span><span></span><span></span>
+</button>
+<nav class="dw-burger-panel" id="dwBurgerPanel" aria-label="Primary">
+  <a href="/">Home</a>
+  <a href="/about">About</a>
+  <a href="mailto:info@flockedwallpaper.com">Contact</a>
+</nav>
+<script>
+(function(){
+  var btn = document.getElementById('dwBurgerBtn');
+  var panel = document.getElementById('dwBurgerPanel');
+  if (!btn || !panel) return;
+  function close(){ panel.classList.remove('open'); btn.setAttribute('aria-expanded','false'); }
+  function toggle(){
+    var open = panel.classList.toggle('open');
+    btn.setAttribute('aria-expanded', open ? 'true' : 'false');
+  }
+  btn.addEventListener('click', function(e){ e.stopPropagation(); toggle(); });
+  document.addEventListener('click', function(e){
+    if (panel.classList.contains('open') && !panel.contains(e.target) && e.target !== btn) close();
+  });
+  document.addEventListener('keydown', function(e){ if (e.key === 'Escape') close(); });
+})();
+</script>
+<!-- /DW-HAMBURGER-NAV v1 -->
+
 </body>
 </html>
diff --git a/DW-Websites/shop-by-color/index.html b/DW-Websites/shop-by-color/index.html
index 27ff4eb7..e1b22ce4 100644
--- a/DW-Websites/shop-by-color/index.html
+++ b/DW-Websites/shop-by-color/index.html
@@ -597,5 +597,104 @@ init();
 </script>
 <script src="/dw-fleet-nav.js" defer></script>
 
+<!-- DW-HAMBURGER-NAV v1 (canonical 2026-05-10) -->
+<style id="dw-hamburger-styles">
+  /* Canonical hamburger nav — always visible top-right, all viewports.
+     Standing rule (Steve, 2026-05-08): hamburger is the primary nav. */
+  .dw-burger-btn {
+    position: fixed; top: 18px; right: 18px; z-index: 9999;
+    width: 44px; height: 44px;
+    background: rgba(20,20,20,0.78); color: #f5f1e8;
+    backdrop-filter: blur(8px) saturate(140%);
+    -webkit-backdrop-filter: blur(8px) saturate(140%);
+    border: 1px solid rgba(245,241,232,0.18); border-radius: 50%;
+    cursor: pointer; padding: 0;
+    display: flex; flex-direction: column; align-items: center; justify-content: center;
+    gap: 4px;
+    box-shadow: 0 6px 20px rgba(0,0,0,0.35);
+    transition: background 200ms, transform 200ms;
+  }
+  .dw-burger-btn:hover { background: rgba(20,20,20,0.92); }
+  .dw-burger-btn span {
+    display: block; width: 20px; height: 1.5px; background: currentColor;
+    transition: transform 220ms, opacity 220ms;
+  }
+  .dw-burger-btn[aria-expanded="true"] span:nth-child(1) {
+    transform: translateY(5.5px) rotate(45deg);
+  }
+  .dw-burger-btn[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
+  .dw-burger-btn[aria-expanded="true"] span:nth-child(3) {
+    transform: translateY(-5.5px) rotate(-45deg);
+  }
+  .dw-burger-panel {
+    position: fixed; top: 72px; right: 18px; z-index: 9998;
+    min-width: 240px; max-width: 88vw;
+    background: rgba(15,15,15,0.96);
+    backdrop-filter: blur(14px) saturate(140%);
+    -webkit-backdrop-filter: blur(14px) saturate(140%);
+    border: 1px solid rgba(245,241,232,0.12);
+    border-radius: 14px;
+    box-shadow: 0 18px 50px rgba(0,0,0,0.55);
+    padding: 10px 0;
+    display: none;
+    font-family: -apple-system, "SF Pro Text", system-ui, sans-serif;
+  }
+  .dw-burger-panel.open { display: block; }
+  .dw-burger-panel a,
+  .dw-burger-panel button {
+    display: block; width: 100%;
+    padding: 13px 22px;
+    color: #f5f1e8 !important;
+    background: transparent; border: 0; cursor: pointer;
+    text-decoration: none !important;
+    font-size: 15px; font-weight: 400;
+    text-align: left;
+    letter-spacing: 0;
+    border-bottom: 1px solid rgba(245,241,232,0.06);
+    transition: background 160ms, color 160ms;
+    box-sizing: border-box;
+  }
+  .dw-burger-panel a:last-child,
+  .dw-burger-panel button:last-child { border-bottom: 0; }
+  .dw-burger-panel a:hover,
+  .dw-burger-panel button:hover {
+    background: rgba(245,241,232,0.06);
+    color: #ffffff !important;
+  }
+  @media (max-width: 480px) {
+    .dw-burger-btn { top: 12px; right: 12px; width: 40px; height: 40px; }
+    .dw-burger-panel { top: 62px; right: 12px; }
+  }
+  /* Avoid double-print on sites already adopting a top-of-page header
+     that overlaps z-index. Reserve safe space near top-right. */
+</style>
+<button type="button" class="dw-burger-btn" id="dwBurgerBtn"
+        aria-label="Toggle menu" aria-controls="dwBurgerPanel"
+        aria-expanded="false">
+  <span></span><span></span><span></span>
+</button>
+<nav class="dw-burger-panel" id="dwBurgerPanel" aria-label="Primary">
+  <a href="https://www.designerwallcoverings.com">Visit Store &rarr;</a>
+  <a href="mailto:info@shop-by-color.com">Contact</a>
+</nav>
+<script>
+(function(){
+  var btn = document.getElementById('dwBurgerBtn');
+  var panel = document.getElementById('dwBurgerPanel');
+  if (!btn || !panel) return;
+  function close(){ panel.classList.remove('open'); btn.setAttribute('aria-expanded','false'); }
+  function toggle(){
+    var open = panel.classList.toggle('open');
+    btn.setAttribute('aria-expanded', open ? 'true' : 'false');
+  }
+  btn.addEventListener('click', function(e){ e.stopPropagation(); toggle(); });
+  document.addEventListener('click', function(e){
+    if (panel.classList.contains('open') && !panel.contains(e.target) && e.target !== btn) close();
+  });
+  document.addEventListener('keydown', function(e){ if (e.key === 'Escape') close(); });
+})();
+</script>
+<!-- /DW-HAMBURGER-NAV v1 -->
+
 </body>
 </html>
diff --git a/DW-Websites/site-watchdog.sh b/DW-Websites/site-watchdog.sh
index d4517a5e..e187dbd3 100755
--- a/DW-Websites/site-watchdog.sh
+++ b/DW-Websites/site-watchdog.sh
@@ -5,7 +5,7 @@
 # and sends Slack notification on recovery or persistent failure.
 # =============================================================================
 
-WEBHOOK_URL="https://hooks.slack.com/services/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"
+WEBHOOK_URL="${SLACK_WEBHOOK_URL}"
 LOG_FILE="/root/Projects/Designer-Wallcoverings/DW-Websites/logs/watchdog.log"
 mkdir -p "$(dirname "$LOG_FILE")"
 
diff --git a/DW-Websites/steve-hourly-report.sh b/DW-Websites/steve-hourly-report.sh
index 696079e3..1025ea16 100755
--- a/DW-Websites/steve-hourly-report.sh
+++ b/DW-Websites/steve-hourly-report.sh
@@ -3,7 +3,7 @@
 # Steve's Hourly Site Status Report Script
 # Sends text notifications about all DW website statuses
 
-WEBHOOK_URL="https://hooks.slack.com/services/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"
+WEBHOOK_URL="${SLACK_WEBHOOK_URL}"
 SLACK_SCRIPT="/root/Projects/Designer-Wallcoverings/DW-MCP/send-site-report.js"
 LOG_FILE="/root/Projects/Designer-Wallcoverings/DW-Websites/logs/steve-reports.log"
 
diff --git a/OLD_/.gitignore b/OLD_/.gitignore
new file mode 100644
index 00000000..7e6a9c3e
--- /dev/null
+++ b/OLD_/.gitignore
@@ -0,0 +1,12 @@
+node_modules/
+.env
+.env.local
+.env.*.local
+.env.*
+tmp/
+*.log
+.DS_Store
+dist/
+build/
+.next/
+*.bak
diff --git a/US-001-IMPLEMENTATION.md b/US-001-IMPLEMENTATION.md
index 749b276f..2f786478 100644
--- a/US-001-IMPLEMENTATION.md
+++ b/US-001-IMPLEMENTATION.md
@@ -168,7 +168,7 @@ SHOPIFY_ADMIN_ACCESS_TOKEN=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
 
 ## Git Commit
 ```
-commit 0c06e65fe7611bd09009af9ea14043b7c7d79a27
+commit ${CLOUDFLARE_API_TOKEN}
 Author: Ralph <ralph@designer-wallcoverings.com>
 Date:   Thu Jan 22 15:27:05 2026 +0000
 
diff --git a/US-001-IMPLEMENTATION.md.pre-scrub-2026-05-07.bak b/US-001-IMPLEMENTATION.md.pre-scrub-2026-05-07.bak
new file mode 100644
index 00000000..749b276f
--- /dev/null
+++ b/US-001-IMPLEMENTATION.md.pre-scrub-2026-05-07.bak
@@ -0,0 +1,194 @@
+# US-001: Shopify API Integration Service - Implementation Summary
+
+## Status: ✅ COMPLETED
+
+## Story Details
+**Title:** Create Shopify API Integration Service
+**Description:** As a system, I want a service to connect to Shopify Admin API so that I can retrieve and update product information programmatically.
+
+## Acceptance Criteria - All Met ✅
+- ✅ Service connects to Shopify Admin API with proper authentication
+- ✅ Can fetch product lists by vendor with pagination
+- ✅ Can update individual product fields (title, description, tags, type, category)
+- ✅ Handles API rate limiting with appropriate delays
+- ✅ Typecheck passes
+
+## Implementation Details
+
+### Files Modified
+1. **lib/shopify-client.ts** - Enhanced with new update methods
+   - Added `updateProductTitle(productId, title)` - Update product title
+   - Added `updateProductDescription(productId, description)` - Update product description (body_html)
+   - Added `updateProductType(productId, productType)` - Update product type
+   - Added `updateProduct(productId, updates)` - Batch update multiple fields
+   - Enhanced `ShopifyProduct` interface to include `body_html` field
+   - Existing methods: `getProducts()`, `getAllProducts()`, `updateProductTags()`
+
+2. **scripts/test-us-001-shopify-service.ts** - Comprehensive test suite
+   - Tests authentication and connection
+   - Tests vendor filtering with pagination
+   - Tests automatic pagination (getAllProducts)
+   - Verifies rate limiting (2 calls/second max)
+   - Documents all update methods
+
+### Key Features
+
+#### Authentication
+- Uses environment variables: `SHOPIFY_ADMIN_ACCESS_TOKEN`, `SHOPIFY_STORE_DOMAIN`, `SHOPIFY_ADMIN_API_VERSION`
+- Secure token-based authentication via X-Shopify-Access-Token header
+- Configuration in `.env` file
+
+#### Rate Limiting
+- Enforces 500ms minimum between requests (2 calls/second max)
+- Automatic delay insertion between consecutive API calls
+- Prevents API rate limit errors
+
+#### Pagination
+- Manual pagination via `getProducts({ vendor, limit, sinceId })`
+- Automatic pagination via `getAllProducts(vendor)` - retrieves all products
+- Uses `since_id` parameter for cursor-based pagination
+- Maximum 250 products per request (Shopify limit)
+
+#### Update Methods
+1. **Single Field Updates:**
+   ```typescript
+   await client.updateProductTitle(productId, 'New Title');
+   await client.updateProductDescription(productId, '<p>New description</p>');
+   await client.updateProductTags(productId, ['Tag1', 'Tag2']);
+   await client.updateProductType(productId, 'Wallcovering');
+   ```
+
+2. **Batch Updates:**
+   ```typescript
+   await client.updateProduct(productId, {
+     title: 'New Title',
+     description: '<p>New description</p>',
+     tags: ['Tag1', 'Tag2'],
+     product_type: 'Wallcovering'
+   });
+   ```
+
+#### Error Handling
+- Typed error responses via `ShopifyApiError` interface
+- Network error detection and reporting
+- HTTP status code checking
+- Detailed error messages
+
+## Test Results
+
+### Test Run Output (Jan 22, 2026)
+```
+=== US-001: Shopify API Integration Service Test ===
+
+Test 1: Connection and authentication
+✅ Successfully connected to Shopify API
+   Retrieved 1 product(s)
+
+Test 2: Fetch products by vendor with pagination
+✅ Successfully fetched 10 products for vendor "Koroseal"
+   First product: "() | (DWK-31482-Sample) | Architectural Wallcoverings" (ID: 7584976699443)
+
+Test 3: Automatic pagination (getAllProducts)
+✅ Successfully fetched all products with pagination
+   Total products for "Phillipe Romano": 1527
+
+Test 4: Rate limiting verification
+   Making 5 consecutive requests to verify rate limiting...
+✅ Rate limiting working correctly (2170ms elapsed, expected >=2000ms)
+
+Test 5: Update methods verification
+   Available update methods:
+   ✅ updateProductTitle(productId, title)
+   ✅ updateProductDescription(productId, description)
+   ✅ updateProductTags(productId, tags[])
+   ✅ updateProductType(productId, productType)
+   ✅ updateProduct(productId, { title, description, tags, product_type })
+```
+
+### TypeScript Compilation
+```bash
+$ npm run build
+> designer-wallcoverings@1.0.0 build
+> tsc --noEmit
+
+# No errors - typecheck passes ✅
+```
+
+## Usage Examples
+
+### Fetch Products by Vendor
+```typescript
+import { ShopifyClient } from './lib/shopify-client';
+
+const client = new ShopifyClient();
+
+// Get first 10 products from a vendor
+const products = await client.getProducts({
+  vendor: 'Koroseal',
+  limit: 10
+});
+
+// Get all products from a vendor (with automatic pagination)
+const allProducts = await client.getAllProducts('Phillipe Romano');
+console.log(`Total products: ${allProducts.length}`);
+```
+
+### Update Product Fields
+```typescript
+import { ShopifyClient } from './lib/shopify-client';
+
+const client = new ShopifyClient();
+const productId = 7584976699443;
+
+// Update single field
+await client.updateProductTitle(productId, 'New Product Title');
+
+// Update multiple fields at once
+await client.updateProduct(productId, {
+  title: 'Updated Title',
+  description: '<p>Updated description with HTML</p>',
+  tags: ['Azure', 'Modern', 'Pattern'],
+  product_type: 'Wallcovering'
+});
+```
+
+## API Configuration
+
+### Environment Variables (.env)
+```bash
+SHOPIFY_STORE_DOMAIN=designer-laboratory-sandbox.myshopify.com
+SHOPIFY_ADMIN_API_VERSION=2024-01
+SHOPIFY_ADMIN_ACCESS_TOKEN=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
+```
+
+### Shopify API Endpoints Used
+- `GET /admin/api/2024-01/products.json` - List products
+- `GET /admin/api/2024-01/products/{id}.json` - Get single product
+- `PUT /admin/api/2024-01/products/{id}.json` - Update product
+
+## Git Commit
+```
+commit 0c06e65fe7611bd09009af9ea14043b7c7d79a27
+Author: Ralph <ralph@designer-wallcoverings.com>
+Date:   Thu Jan 22 15:27:05 2026 +0000
+
+    feat(US-001): Create Shopify API Integration Service
+
+    - Enhanced ShopifyClient with comprehensive update methods
+    - Added updateProductTitle() for title updates
+    - Added updateProductDescription() for description updates
+    - Added updateProductType() for product type updates
+    - Added updateProduct() for batch field updates
+    - Existing functionality: vendor filtering, pagination, rate limiting
+    - All acceptance criteria met and verified
+    - Typecheck passes
+
+    Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
+
+ lib/shopify-client.ts                  | 103 +++++++++++++++++++++++++++
+ scripts/test-us-001-shopify-service.ts |  99 ++++++++++++++++++++++++++
+ 2 files changed, 202 insertions(+)
+```
+
+## Next Steps
+US-001 is complete and ready for US-002.
diff --git a/admin/.gitignore b/admin/.gitignore
new file mode 100644
index 00000000..7e6a9c3e
--- /dev/null
+++ b/admin/.gitignore
@@ -0,0 +1,12 @@
+node_modules/
+.env
+.env.local
+.env.*.local
+.env.*
+tmp/
+*.log
+.DS_Store
+dist/
+build/
+.next/
+*.bak
diff --git a/ai-enrich-arte-fix.js b/ai-enrich-arte-fix.js
index c8b391e9..5a014743 100644
--- a/ai-enrich-arte-fix.js
+++ b/ai-enrich-arte-fix.js
@@ -1,7 +1,7 @@
 const https = require('https');
 const { Client } = require('pg');
 
-const GEMINI_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_KEY = '${GOOGLE_API_KEY}';
 const GEMINI_URL = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${GEMINI_KEY}`;
 
 const PRODUCTS = [
diff --git a/ai-enrich-arte-fix.js.pre-scrub-2026-05-07.bak b/ai-enrich-arte-fix.js.pre-scrub-2026-05-07.bak
new file mode 100644
index 00000000..c8b391e9
--- /dev/null
+++ b/ai-enrich-arte-fix.js.pre-scrub-2026-05-07.bak
@@ -0,0 +1,116 @@
+const https = require('https');
+const { Client } = require('pg');
+
+const GEMINI_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_URL = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${GEMINI_KEY}`;
+
+const PRODUCTS = [
+  {id:123,sku:'19433',name:'Horus Desert Sun',img:'https://edge.arte-international.com/media/4960d9f1-bc0a-4bcb-9a82-c09d9e5e7d98/conversions/EssentialsLuxor_Horus_19436_Roomshot_Web_LR-medium-two-thirds.jpg'},
+  {id:16,sku:'23401',name:'Amarna Bister',img:'https://edge.arte-international.com/media/cc56d30c-5e1c-4b22-878e-b437681e6f1b/conversions/Memphis_Amarna_23400_Roomshot_Web_LR-medium-two-thirds.jpg'},
+  {id:15,sku:'23412',name:'Sakkara Antique Gold',img:'https://edge.arte-international.com/media/a580214f-25ff-472e-b88c-6a2bd8dfab64/conversions/Memphis_Sakkara_23410_Roomshot_Web_LR-medium-two-thirds.jpg'},
+  {id:172,sku:'23413',name:'Sakkara Off-white',img:'https://edge.arte-international.com/media/a580214f-25ff-472e-b88c-6a2bd8dfab64/conversions/Memphis_Sakkara_23410_Roomshot_Web_LR-medium-two-thirds.jpg'},
+  {id:72,sku:'23421',name:'Ibis Biscuit',img:'https://edge.arte-international.com/media/2183e2bc-0620-43c4-81ae-6364abed3937/conversions/Memphis_Ibis_23420_Roomshot_Web_LR-medium-two-thirds.jpg'},
+  {id:75,sku:'23422',name:'Ibis Chestnut',img:'https://edge.arte-international.com/media/2183e2bc-0620-43c4-81ae-6364abed3937/conversions/Memphis_Ibis_23420_Roomshot_Web_LR-medium-two-thirds.jpg'},
+  {id:78,sku:'23431',name:'Siwa Bone',img:'https://edge.arte-international.com/media/428898de-d288-40f3-b463-1714c59de939/conversions/Memphis_Siwa_23432_Roomshot_Web_LR-medium-two-thirds.jpg'},
+  {id:83,sku:'23433',name:'Siwa Biscuit',img:'https://edge.arte-international.com/media/428898de-d288-40f3-b463-1714c59de939/conversions/Memphis_Siwa_23432_Roomshot_Web_LR-medium-two-thirds.jpg'},
+  {id:183,sku:'29221',name:'Galon Grey Linen',img:'https://edge.arte-international.com/media/8571da7a-7bf9-4abc-adf0-76863cee5413/conversions/Allures_Galon9224_1_Roomshot_Web_LR-medium-two-thirds.jpg'},
+];
+
+const PROMPT = `You are an interior design wallcovering product analyst. Analyze this wallcovering image and return ONLY valid JSON (no markdown, no backticks):
+{
+  "colors": ["<list 3-6 actual colors you see, e.g. Warm Beige, Soft Gold>"],
+  "backgroundColor": "<the single dominant background color>",
+  "styles": ["<1-3 design styles, e.g. Contemporary, Art Deco, Minimalist>"],
+  "patterns": ["<1-2 pattern types, e.g. Geometric, Textured, Striped>"],
+  "tags": ["<5-8 interior design tags, e.g. luxury, neutral, organic>"],
+  "description": "<2 sentences describing this wallcovering for a commercial interior designer>"
+}`;
+
+function fetchImage(url) {
+  return new Promise((resolve, reject) => {
+    https.get(url, { headers: { 'User-Agent': 'Mozilla/5.0' } }, (res) => {
+      if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
+        return fetchImage(res.headers.location).then(resolve).catch(reject);
+      }
+      if (res.statusCode !== 200) return reject(new Error(`HTTP ${res.statusCode}`));
+      const chunks = [];
+      res.on('data', c => chunks.push(c));
+      res.on('end', () => resolve(Buffer.concat(chunks)));
+      res.on('error', reject);
+    }).on('error', reject);
+  });
+}
+
+function callGemini(b64, name) {
+  const body = JSON.stringify({
+    contents: [{ parts: [
+      { text: `Product: ${name}\n\n${PROMPT}` },
+      { inlineData: { mimeType: 'image/jpeg', data: b64 } }
+    ]}],
+    generationConfig: { temperature: 0.2, maxOutputTokens: 1024 }
+  });
+  return new Promise((resolve, reject) => {
+    const url = new URL(GEMINI_URL);
+    const req = https.request({ hostname: url.hostname, path: url.pathname + url.search, method: 'POST', headers: { 'Content-Type': 'application/json' } }, (res) => {
+      let data = '';
+      res.on('data', c => data += c);
+      res.on('end', () => {
+        try {
+          const json = JSON.parse(data);
+          if (json.error) return reject(new Error(json.error.message));
+          const text = json.candidates?.[0]?.content?.parts?.[0]?.text || '';
+          resolve(JSON.parse(text.replace(/```json\n?/g, '').replace(/```\n?/g, '').trim()));
+        } catch (e) { reject(new Error(`Parse: ${e.message}`)); }
+      });
+    });
+    req.on('error', reject);
+    req.write(body);
+    req.end();
+  });
+}
+
+async function main() {
+  const db = new Client({ connectionString: 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified' });
+  await db.connect();
+  let ok = 0, fail = 0;
+
+  for (let i = 0; i < PRODUCTS.length; i++) {
+    const p = PRODUCTS[i];
+    console.log(`\n[${i+1}/9] ${p.sku} - ${p.name}`);
+    try {
+      const imgBuf = await fetchImage(p.img);
+      console.log(`  Image: ${(imgBuf.length/1024).toFixed(0)}KB`);
+      const ai = await callGemini(imgBuf.toString('base64'), p.name);
+      console.log(`  Colors: ${ai.colors.join(', ')} | BG: ${ai.backgroundColor}`);
+
+      // vendor_catalog: text columns - stringify arrays as JSON strings
+      await db.query(`
+        UPDATE vendor_catalog SET
+          ai_colors = $1, ai_background_color = $2, ai_styles = $3,
+          ai_patterns = $4, ai_tags = $5, ai_description = $6
+        WHERE id = $7
+      `, [JSON.stringify(ai.colors), ai.backgroundColor, JSON.stringify(ai.styles),
+          JSON.stringify(ai.patterns), JSON.stringify(ai.tags), ai.description, p.id]);
+
+      // arte_catalog: jsonb columns - also stringify for jsonb
+      const arteRes = await db.query(`
+        UPDATE arte_catalog SET
+          ai_colors = $1::jsonb, ai_background_color = $2, ai_styles = $3::jsonb,
+          ai_patterns = $4::jsonb, ai_tags = $5::jsonb, ai_description = $6
+        WHERE arte_sku = $7
+      `, [JSON.stringify(ai.colors), ai.backgroundColor, JSON.stringify(ai.styles),
+          JSON.stringify(ai.patterns), JSON.stringify(ai.tags), ai.description, p.sku]);
+
+      console.log(`  Saved vendor_catalog + arte_catalog (${arteRes.rowCount} arte row)`);
+      ok++;
+    } catch (err) {
+      console.log(`  FAIL: ${err.message}`);
+      fail++;
+    }
+    if (i < PRODUCTS.length - 1) await new Promise(r => setTimeout(r, 1200));
+  }
+
+  await db.end();
+  console.log(`\nDONE: ${ok}/9 success, ${fail} failed`);
+}
+main().catch(console.error);
diff --git a/ai-enrich-gaps2.js b/ai-enrich-gaps2.js
index 1302da2f..1560e1ca 100644
--- a/ai-enrich-gaps2.js
+++ b/ai-enrich-gaps2.js
@@ -2,7 +2,7 @@ const https = require('https');
 const http = require('http');
 const { Client } = require('pg');
 
-const GEMINI_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_KEY = '${GOOGLE_API_KEY}';
 const GEMINI_URL = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${GEMINI_KEY}`;
 
 const PRODUCTS = [
diff --git a/ai-enrich-gaps2.js.pre-scrub-2026-05-07.bak b/ai-enrich-gaps2.js.pre-scrub-2026-05-07.bak
new file mode 100644
index 00000000..1302da2f
--- /dev/null
+++ b/ai-enrich-gaps2.js.pre-scrub-2026-05-07.bak
@@ -0,0 +1,133 @@
+const https = require('https');
+const http = require('http');
+const { Client } = require('pg');
+
+const GEMINI_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_URL = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${GEMINI_KEY}`;
+
+const PRODUCTS = [
+  {id:123,vendor:'arte',sku:'19433',name:'Horus Desert Sun',img:'https://edge.arte-international.com/media/4960d9f1-bc0a-4bcb-9a82-c09d9e5e7d98/conversions/EssentialsLuxor_Horus_19436_Roomshot_Web_LR-medium-two-thirds.jpg'},
+  {id:16,vendor:'arte',sku:'23401',name:'Amarna Bister',img:'https://edge.arte-international.com/media/cc56d30c-5e1c-4b22-878e-b437681e6f1b/conversions/Memphis_Amarna_23400_Roomshot_Web_LR-medium-two-thirds.jpg'},
+  {id:15,vendor:'arte',sku:'23412',name:'Sakkara Antique Gold',img:'https://edge.arte-international.com/media/a580214f-25ff-472e-b88c-6a2bd8dfab64/conversions/Memphis_Sakkara_23410_Roomshot_Web_LR-medium-two-thirds.jpg'},
+  {id:172,vendor:'arte',sku:'23413',name:'Sakkara Off-white',img:'https://edge.arte-international.com/media/a580214f-25ff-472e-b88c-6a2bd8dfab64/conversions/Memphis_Sakkara_23410_Roomshot_Web_LR-medium-two-thirds.jpg'},
+  {id:72,vendor:'arte',sku:'23421',name:'Ibis Biscuit',img:'https://edge.arte-international.com/media/2183e2bc-0620-43c4-81ae-6364abed3937/conversions/Memphis_Ibis_23420_Roomshot_Web_LR-medium-two-thirds.jpg'},
+  {id:75,vendor:'arte',sku:'23422',name:'Ibis Chestnut',img:'https://edge.arte-international.com/media/2183e2bc-0620-43c4-81ae-6364abed3937/conversions/Memphis_Ibis_23420_Roomshot_Web_LR-medium-two-thirds.jpg'},
+  {id:78,vendor:'arte',sku:'23431',name:'Siwa Bone',img:'https://edge.arte-international.com/media/428898de-d288-40f3-b463-1714c59de939/conversions/Memphis_Siwa_23432_Roomshot_Web_LR-medium-two-thirds.jpg'},
+  {id:83,vendor:'arte',sku:'23433',name:'Siwa Biscuit',img:'https://edge.arte-international.com/media/428898de-d288-40f3-b463-1714c59de939/conversions/Memphis_Siwa_23432_Roomshot_Web_LR-medium-two-thirds.jpg'},
+  {id:183,vendor:'arte',sku:'29221',name:'Galon Grey Linen',img:'https://edge.arte-international.com/media/8571da7a-7bf9-4abc-adf0-76863cee5413/conversions/Allures_Galon9224_1_Roomshot_Web_LR-medium-two-thirds.jpg'},
+  {id:1751,vendor:'black_edition',sku:'W924/01',name:'Mizumi Panel Carbon',img:'https://static.theromogroup.com/rb/cache/image/720x720/catalog/product/W/9/W924-01FP-mizumi-panel-charcoal_00.jpg'},
+  {id:1752,vendor:'black_edition',sku:'W924/02',name:'Mizumi Panel Midnight',img:'https://static.theromogroup.com/rb/cache/image/720x720/catalog/product/W/9/W924-02FP-mizumi-panel-midnight_00.jpg'},
+  {id:1753,vendor:'black_edition',sku:'W924/03',name:'Mizumi Panel Basalt',img:'https://static.theromogroup.com/rb/cache/image/720x720/catalog/product/W/9/W924-03FP-mizumi-panel-stone_00.jpg'},
+  {id:1754,vendor:'black_edition',sku:'W924/04',name:'Mizumi Panel Viridian',img:'https://static.theromogroup.com/rb/cache/image/720x720/catalog/product/W/9/W924-04FP-mizumi-panel-teal_02.jpg'},
+];
+
+const PROMPT = `You are an interior design wallcovering product analyst. Analyze this wallcovering image and return ONLY valid JSON (no markdown, no backticks):
+{
+  "colors": ["<list 3-6 actual colors you see, e.g. Warm Beige, Soft Gold>"],
+  "backgroundColor": "<the single dominant background color>",
+  "styles": ["<1-3 design styles, e.g. Contemporary, Art Deco, Minimalist>"],
+  "patterns": ["<1-2 pattern types, e.g. Geometric, Textured, Striped>"],
+  "tags": ["<5-8 interior design tags, e.g. luxury, neutral, organic>"],
+  "description": "<2 sentences describing this wallcovering for a commercial interior designer>"
+}`;
+
+function fetchImage(url) {
+  const mod = url.startsWith('https') ? https : http;
+  return new Promise((resolve, reject) => {
+    mod.get(url, { headers: { 'User-Agent': 'Mozilla/5.0' } }, (res) => {
+      if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
+        return fetchImage(res.headers.location).then(resolve).catch(reject);
+      }
+      if (res.statusCode !== 200) return reject(new Error(`HTTP ${res.statusCode}`));
+      const chunks = [];
+      res.on('data', c => chunks.push(c));
+      res.on('end', () => resolve(Buffer.concat(chunks)));
+      res.on('error', reject);
+    }).on('error', reject);
+  });
+}
+
+function callGemini(b64, productName) {
+  const body = JSON.stringify({
+    contents: [{ parts: [
+      { text: `Product: ${productName}\n\n${PROMPT}` },
+      { inlineData: { mimeType: 'image/jpeg', data: b64 } }
+    ]}],
+    generationConfig: { temperature: 0.2, maxOutputTokens: 1024 }
+  });
+
+  return new Promise((resolve, reject) => {
+    const url = new URL(GEMINI_URL);
+    const req = https.request({
+      hostname: url.hostname, path: url.pathname + url.search,
+      method: 'POST',
+      headers: { 'Content-Type': 'application/json' }
+    }, (res) => {
+      let data = '';
+      res.on('data', c => data += c);
+      res.on('end', () => {
+        try {
+          const json = JSON.parse(data);
+          if (json.error) return reject(new Error(json.error.message));
+          const text = json.candidates?.[0]?.content?.parts?.[0]?.text || '';
+          const clean = text.replace(/```json\n?/g, '').replace(/```\n?/g, '').trim();
+          resolve(JSON.parse(clean));
+        } catch (e) { reject(new Error(`Parse: ${e.message}`)); }
+      });
+    });
+    req.on('error', reject);
+    req.write(body);
+    req.end();
+  });
+}
+
+async function main() {
+  const db = new Client({ connectionString: 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified' });
+  await db.connect();
+
+  let success = 0, fail = 0;
+
+  for (let i = 0; i < PRODUCTS.length; i++) {
+    const p = PRODUCTS[i];
+    console.log(`\n[${i+1}/13] ${p.vendor} ${p.sku} - ${p.name}`);
+
+    try {
+      const imgBuf = await fetchImage(p.img);
+      console.log(`  Image: ${(imgBuf.length/1024).toFixed(0)}KB`);
+      const b64 = imgBuf.toString('base64');
+
+      const ai = await callGemini(b64, p.name);
+      console.log(`  Colors: ${(ai.colors||[]).join(', ')}`);
+      console.log(`  BG: ${ai.backgroundColor} | Styles: ${(ai.styles||[]).join(', ')}`);
+
+      const res = await db.query(`
+        UPDATE vendor_catalog SET
+          ai_colors = $1, ai_background_color = $2, ai_styles = $3,
+          ai_patterns = $4, ai_tags = $5, ai_description = $6
+        WHERE id = $7
+      `, [ai.colors, ai.backgroundColor, ai.styles, ai.patterns, ai.tags, ai.description, p.id]);
+
+      if (p.vendor === 'arte') {
+        await db.query(`
+          UPDATE arte_catalog SET
+            ai_colors = $1, ai_background_color = $2, ai_styles = $3,
+            ai_patterns = $4, ai_tags = $5, ai_description = $6
+          WHERE arte_sku = $7
+        `, [ai.colors, ai.backgroundColor, ai.styles, ai.patterns, ai.tags, ai.description, p.sku]);
+      }
+
+      console.log(`  Saved (${res.rowCount} row)`);
+      success++;
+    } catch (err) {
+      console.log(`  FAIL: ${err.message}`);
+      fail++;
+    }
+
+    if (i < PRODUCTS.length - 1) await new Promise(r => setTimeout(r, 1200));
+  }
+
+  await db.end();
+  console.log(`\nDONE: ${success} success, ${fail} failed out of 13`);
+}
+
+main().catch(console.error);
diff --git a/arte-fill-tags.js b/arte-fill-tags.js
index 978ced98..94a23adb 100644
--- a/arte-fill-tags.js
+++ b/arte-fill-tags.js
@@ -2,7 +2,7 @@ const https = require('https');
 const http = require('http');
 const { Client } = require('pg');
 
-const GEMINI_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_KEY = '${GOOGLE_API_KEY}';
 const GEMINI_MODEL = 'gemini-2.0-flash';
 const DB = 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified';
 
diff --git a/arte-fill-tags.js.pre-scrub-2026-05-07.bak b/arte-fill-tags.js.pre-scrub-2026-05-07.bak
new file mode 100644
index 00000000..978ced98
--- /dev/null
+++ b/arte-fill-tags.js.pre-scrub-2026-05-07.bak
@@ -0,0 +1,123 @@
+const https = require('https');
+const http = require('http');
+const { Client } = require('pg');
+
+const GEMINI_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_MODEL = 'gemini-2.0-flash';
+const DB = 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified';
+
+async function geminiAnalyze(imageUrl, patternName) {
+  const prompt = `You are an interior design wallcovering tagger. Analyze this wallcovering image.
+
+Product: ${patternName}
+
+Return ONLY a JSON object with:
+{
+  "tags": ["tag1", "tag2", ...] // 5-10 interior design tags (e.g., "Botanical", "Luxury", "Traditional", "Textured", "Neutral Palette", "Organic", "Nature-Inspired")
+}
+
+Tags should describe: style, mood, pattern type, texture, suitable rooms, design era. Be specific to wallcoverings/interior design.`;
+
+  const body = JSON.stringify({
+    contents: [{
+      parts: [
+        { text: prompt },
+        { inline_data: { mime_type: 'image/jpeg', data: await fetchImageBase64(imageUrl) } }
+      ]
+    }],
+    generationConfig: { temperature: 0.2, maxOutputTokens: 300 }
+  });
+
+  return new Promise((resolve, reject) => {
+    const url = `https://generativelanguage.googleapis.com/v1beta/models/${GEMINI_MODEL}:generateContent?key=${GEMINI_KEY}`;
+    const parsed = new URL(url);
+    const req = https.request({
+      hostname: parsed.hostname,
+      path: parsed.pathname + parsed.search,
+      method: 'POST',
+      headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(body) }
+    }, (res) => {
+      let data = '';
+      res.on('data', c => data += c);
+      res.on('end', () => {
+        try {
+          const json = JSON.parse(data);
+          const text = json.candidates?.[0]?.content?.parts?.[0]?.text || '';
+          const cleaned = text.replace(/```json\n?/g, '').replace(/```\n?/g, '').trim();
+          resolve(JSON.parse(cleaned));
+        } catch(e) { reject(new Error(`Parse error: ${e.message} raw: ${data.substring(0,200)}`)); }
+      });
+    });
+    req.on('error', reject);
+    req.write(body);
+    req.end();
+  });
+}
+
+function fetchImageBase64(imageUrl) {
+  return new Promise((resolve, reject) => {
+    const mod = imageUrl.startsWith('https') ? https : http;
+    mod.get(imageUrl, { headers: { 'User-Agent': 'Mozilla/5.0' } }, (res) => {
+      if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
+        return fetchImageBase64(res.headers.location).then(resolve).catch(reject);
+      }
+      const chunks = [];
+      res.on('data', c => chunks.push(c));
+      res.on('end', () => resolve(Buffer.concat(chunks).toString('base64')));
+    }).on('error', reject);
+  });
+}
+
+function sleep(ms) { return new Promise(r => setTimeout(r, ms)); }
+
+async function main() {
+  const db = new Client(DB);
+  await db.connect();
+
+  const { rows } = await db.query(`
+    SELECT id, mfr_sku, pattern_name, image_url
+    FROM vendor_catalog 
+    WHERE vendor_code = 'arte' 
+      AND (ai_tags IS NULL OR ai_tags = '[]'::jsonb)
+      AND image_url IS NOT NULL AND image_url != ''
+    ORDER BY mfr_sku
+  `);
+
+  console.log(`Processing ${rows.length} Arte products for ai_tags...`);
+  let success = 0, fail = 0;
+
+  for (const row of rows) {
+    try {
+      console.log(`  [${success+fail+1}/${rows.length}] ${row.mfr_sku} ${row.pattern_name}...`);
+      const result = await geminiAnalyze(row.image_url, row.pattern_name);
+      
+      if (result.tags && Array.isArray(result.tags) && result.tags.length > 0) {
+        await db.query(
+          `UPDATE vendor_catalog SET ai_tags = $1 WHERE id = $2`,
+          [JSON.stringify(result.tags), row.id]
+        );
+        console.log(`    ✓ ${result.tags.length} tags: ${result.tags.join(', ')}`);
+        success++;
+      } else {
+        console.log(`    ✗ No tags returned`);
+        fail++;
+      }
+      await sleep(1200); // rate limit
+    } catch(e) {
+      console.log(`    ✗ Error: ${e.message}`);
+      fail++;
+    }
+  }
+
+  // Handle 67403 (no image) - mark for review
+  await db.query(`
+    UPDATE vendor_catalog 
+    SET ai_tags = '["Needs-Image-Review"]'::jsonb
+    WHERE vendor_code = 'arte' AND mfr_sku = '67403' AND ai_colors IS NULL
+  `);
+
+  console.log(`\nDone! Success: ${success}, Failed: ${fail}, Skipped (no image): 1`);
+  await db.end();
+}
+
+main().catch(e => { console.error(e); process.exit(1); });
diff --git a/backups/.gitignore b/backups/.gitignore
new file mode 100644
index 00000000..7e6a9c3e
--- /dev/null
+++ b/backups/.gitignore
@@ -0,0 +1,12 @@
+node_modules/
+.env
+.env.local
+.env.*.local
+.env.*
+tmp/
+*.log
+.DS_Store
+dist/
+build/
+.next/
+*.bak
diff --git a/brand-router/.gitignore b/brand-router/.gitignore
new file mode 100644
index 00000000..7e6a9c3e
--- /dev/null
+++ b/brand-router/.gitignore
@@ -0,0 +1,12 @@
+node_modules/
+.env
+.env.local
+.env.*.local
+.env.*
+tmp/
+*.log
+.DS_Store
+dist/
+build/
+.next/
+*.bak
diff --git a/components/.gitignore b/components/.gitignore
new file mode 100644
index 00000000..7e6a9c3e
--- /dev/null
+++ b/components/.gitignore
@@ -0,0 +1,12 @@
+node_modules/
+.env
+.env.local
+.env.*.local
+.env.*
+tmp/
+*.log
+.DS_Store
+dist/
+build/
+.next/
+*.bak
diff --git a/docs/.gitignore b/docs/.gitignore
new file mode 100644
index 00000000..7e6a9c3e
--- /dev/null
+++ b/docs/.gitignore
@@ -0,0 +1,12 @@
+node_modules/
+.env
+.env.local
+.env.*.local
+.env.*
+tmp/
+*.log
+.DS_Store
+dist/
+build/
+.next/
+*.bak
diff --git a/enrich-arte-fix.js b/enrich-arte-fix.js
index 5b3c484d..753d3afa 100644
--- a/enrich-arte-fix.js
+++ b/enrich-arte-fix.js
@@ -1,7 +1,7 @@
 const https = require('https');
 const { Client } = require('pg');
 
-const GEMINI_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_KEY = '${GOOGLE_API_KEY}';
 const GEMINI_URL = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${GEMINI_KEY}`;
 const DB_URL = 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified';
 
diff --git a/enrich-arte-fix.js.pre-scrub-2026-05-07.bak b/enrich-arte-fix.js.pre-scrub-2026-05-07.bak
new file mode 100644
index 00000000..5b3c484d
--- /dev/null
+++ b/enrich-arte-fix.js.pre-scrub-2026-05-07.bak
@@ -0,0 +1,139 @@
+const https = require('https');
+const { Client } = require('pg');
+
+const GEMINI_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_URL = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${GEMINI_KEY}`;
+const DB_URL = 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified';
+
+const PRODUCTS = [
+  { id: 123, sku: '19433', pattern: 'Horus', color: 'Desert Sun', img: 'https://edge.arte-international.com/media/4960d9f1-bc0a-4bcb-9a82-c09d9e5e7d98/conversions/EssentialsLuxor_Horus_19436_Roomshot_Web_LR-medium-two-thirds.jpg' },
+  { id: 16, sku: '23401', pattern: 'Amarna', color: 'Bister', img: 'https://edge.arte-international.com/media/cc56d30c-5e1c-4b22-878e-b437681e6f1b/conversions/Memphis_Amarna_23400_Roomshot_Web_LR-medium-two-thirds.jpg' },
+  { id: 15, sku: '23412', pattern: 'Sakkara', color: 'Antique Gold', img: 'https://edge.arte-international.com/media/a580214f-25ff-472e-b88c-6a2bd8dfab64/conversions/Memphis_Sakkara_23410_Roomshot_Web_LR-medium-two-thirds.jpg' },
+  { id: 172, sku: '23413', pattern: 'Sakkara', color: 'Off-white', img: 'https://edge.arte-international.com/media/a580214f-25ff-472e-b88c-6a2bd8dfab64/conversions/Memphis_Sakkara_23410_Roomshot_Web_LR-medium-two-thirds.jpg' },
+  { id: 72, sku: '23421', pattern: 'Ibis', color: 'Biscuit', img: 'https://edge.arte-international.com/media/2183e2bc-0620-43c4-81ae-6364abed3937/conversions/Memphis_Ibis_23420_Roomshot_Web_LR-medium-two-thirds.jpg' },
+  { id: 75, sku: '23422', pattern: 'Ibis', color: 'Chestnut', img: 'https://edge.arte-international.com/media/2183e2bc-0620-43c4-81ae-6364abed3937/conversions/Memphis_Ibis_23420_Roomshot_Web_LR-medium-two-thirds.jpg' },
+  { id: 78, sku: '23431', pattern: 'Siwa', color: 'Bone', img: 'https://edge.arte-international.com/media/428898de-d288-40f3-b463-1714c59de939/conversions/Memphis_Siwa_23432_Roomshot_Web_LR-medium-two-thirds.jpg' },
+  { id: 83, sku: '23433', pattern: 'Siwa', color: 'Biscuit', img: 'https://edge.arte-international.com/media/428898de-d288-40f3-b463-1714c59de939/conversions/Memphis_Siwa_23432_Roomshot_Web_LR-medium-two-thirds.jpg' },
+  { id: 183, sku: '29221', pattern: 'Galon', color: 'Grey Linen', img: 'https://edge.arte-international.com/media/8571da7a-7bf9-4abc-adf0-76863cee5413/conversions/Allures_Galon9224_1_Roomshot_Web_LR-medium-two-thirds.jpg' },
+];
+
+function downloadImage(url) {
+  return new Promise((resolve, reject) => {
+    https.get(url, { headers: { 'User-Agent': 'Mozilla/5.0' } }, (res) => {
+      if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
+        return downloadImage(res.headers.location).then(resolve).catch(reject);
+      }
+      const chunks = [];
+      res.on('data', c => chunks.push(c));
+      res.on('end', () => resolve(Buffer.concat(chunks)));
+      res.on('error', reject);
+    }).on('error', reject);
+  });
+}
+
+function callGemini(b64, mime, prompt) {
+  return new Promise((resolve, reject) => {
+    const body = JSON.stringify({
+      contents: [{ parts: [
+        { text: prompt },
+        { inline_data: { mime_type: mime, data: b64 } }
+      ]}]
+    });
+    const url = new URL(GEMINI_URL);
+    const req = https.request({
+      hostname: url.hostname,
+      path: url.pathname + url.search,
+      method: 'POST',
+      headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(body) },
+      timeout: 30000
+    }, (res) => {
+      const chunks = [];
+      res.on('data', c => chunks.push(c));
+      res.on('end', () => {
+        try { resolve(JSON.parse(Buffer.concat(chunks).toString())); }
+        catch(e) { reject(e); }
+      });
+    });
+    req.on('error', reject);
+    req.on('timeout', () => { req.destroy(); reject(new Error('timeout')); });
+    req.write(body);
+    req.end();
+  });
+}
+
+function parseGeminiJson(text) {
+  let clean = text.replace(/^```(?:json)?\s*/m, '').replace(/\s*```\s*$/m, '').trim();
+  return JSON.parse(clean);
+}
+
+// For vendor_catalog (text columns): PostgreSQL array literal
+function toPgArray(arr) {
+  if (!arr || !arr.length) return '{}';
+  return '{' + arr.map(s => '"' + s.replace(/"/g, '\\"') + '"').join(',') + '}';
+}
+
+async function main() {
+  const db = new Client({ connectionString: DB_URL });
+  await db.connect();
+  let success = 0, fail = 0;
+
+  for (let i = 0; i < PRODUCTS.length; i++) {
+    const p = PRODUCTS[i];
+    console.log(`\n━━━ [${i+1}/9] arte ${p.sku} (${p.pattern} - ${p.color}) ━━━`);
+    try {
+      const imgBuf = await downloadImage(p.img);
+      if (!imgBuf.length) throw new Error('Empty image');
+      const b64 = imgBuf.toString('base64');
+      console.log(`  Downloaded: ${(imgBuf.length / 1024).toFixed(0)}KB`);
+
+      const prompt = `You are an interior design wallcovering expert. Analyze this wallcovering image. The vendor color name is "${p.color}" and the pattern is "${p.pattern}".
+
+Return ONLY valid JSON with no markdown formatting:
+{
+  "colors": ["list 3-6 actual colors visible in the wallcovering"],
+  "backgroundColor": "the dominant background color",
+  "tags": ["5-8 interior design tags like Luxury, Textured, Modern, Elegant"],
+  "styles": ["1-3 design period styles like Contemporary, Art Deco, Mid-Century"],
+  "patterns": ["1-3 pattern types like Geometric, Textured, Striped, Floral"],
+  "description": "Two-sentence commercial description for an architectural wallcovering retailer. Never use the word wallpaper."
+}`;
+
+      const resp = await callGemini(b64, 'image/jpeg', prompt);
+      const text = resp?.candidates?.[0]?.content?.parts?.[0]?.text;
+      if (!text) throw new Error('No Gemini text: ' + JSON.stringify(resp?.error || 'unknown').slice(0, 200));
+
+      const data = parseGeminiJson(text);
+      console.log(`  Colors: ${data.colors?.join(', ')}`);
+      console.log(`  BG: ${data.backgroundColor}`);
+      console.log(`  Tags: ${data.tags?.join(', ')}`);
+
+      // vendor_catalog uses TEXT columns (pg array format)
+      await db.query(`UPDATE vendor_catalog SET ai_colors=$1, ai_background_color=$2, ai_tags=$3, ai_styles=$4, ai_patterns=$5, ai_description=$6 WHERE id=$7`,
+        [toPgArray(data.colors), data.backgroundColor||'', toPgArray(data.tags), toPgArray(data.styles), toPgArray(data.patterns), data.description||'', p.id]);
+
+      // arte_catalog uses JSONB columns (JSON format)
+      await db.query(`UPDATE arte_catalog SET ai_colors=$1::jsonb, ai_background_color=$2, ai_tags=$3::jsonb, ai_styles=$4::jsonb, ai_patterns=$5::jsonb, ai_description=$6 WHERE arte_sku=$7`,
+        [JSON.stringify(data.colors), data.backgroundColor||'', JSON.stringify(data.tags), JSON.stringify(data.styles), JSON.stringify(data.patterns), data.description||'', p.sku]);
+
+      // Verify both
+      const v1 = await db.query('SELECT ai_colors FROM vendor_catalog WHERE id=$1', [p.id]);
+      const v2 = await db.query('SELECT ai_colors FROM arte_catalog WHERE arte_sku=$1', [p.sku]);
+      const ok1 = v1.rows[0]?.ai_colors && v1.rows[0].ai_colors !== '{}';
+      const ok2 = v2.rows[0]?.ai_colors && JSON.stringify(v2.rows[0].ai_colors) !== '[]';
+      if (ok1 && ok2) {
+        console.log(`  ✅ Saved (vendor_catalog + arte_catalog)`); success++;
+      } else {
+        console.log(`  ⚠️ Partial: vc=${ok1}, ac=${ok2}`); fail++;
+      }
+    } catch (err) {
+      console.log(`  ❌ Error: ${err.message}`); fail++;
+    }
+    await new Promise(r => setTimeout(r, 1200));
+  }
+
+  await db.end();
+  console.log(`\n━━━━━━━━━━━━━━━━━━━━━━`);
+  console.log(`RESULTS: ✅ ${success}  ❌ ${fail}  (of 9)`);
+}
+
+main().catch(e => { console.error(e); process.exit(1); });
diff --git a/enrich-arte-gaps.js b/enrich-arte-gaps.js
index 6f275bff..406ae261 100644
--- a/enrich-arte-gaps.js
+++ b/enrich-arte-gaps.js
@@ -1,7 +1,7 @@
 const https = require('https');
 const { Client } = require('pg');
 
-const GEMINI_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_KEY = '${GOOGLE_API_KEY}';
 const GEMINI_URL = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${GEMINI_KEY}`;
 const pgClient = new Client('postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified');
 
diff --git a/enrich-arte-gaps.js.pre-scrub-2026-05-07.bak b/enrich-arte-gaps.js.pre-scrub-2026-05-07.bak
new file mode 100644
index 00000000..6f275bff
--- /dev/null
+++ b/enrich-arte-gaps.js.pre-scrub-2026-05-07.bak
@@ -0,0 +1,124 @@
+const https = require('https');
+const { Client } = require('pg');
+
+const GEMINI_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_URL = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${GEMINI_KEY}`;
+const pgClient = new Client('postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified');
+
+const PROMPT = `You are an interior design wallcovering analyst. Analyze this wallcovering product image.
+
+Return ONLY valid JSON with these fields:
+{
+  "colors": ["<list 3-6 colors visible, e.g. Gold, Cream, Charcoal>"],
+  "backgroundColor": "<the single dominant background color>",
+  "tags": ["<5-8 interior design tags, e.g. Luxury, Textured, Hospitality, Modern>"],
+  "styles": ["<1-3 design styles, e.g. Contemporary, Art Deco, Minimalist>"],
+  "patterns": ["<1-3 pattern types, e.g. Geometric, Solid, Striped, Textured>"],
+  "description": "<2 sentence commercial description for architects and interior designers>"
+}
+
+Do NOT include markdown formatting. Return raw JSON only.`;
+
+const ARTE = [
+  { sku:'19433', url:'https://edge.arte-international.com/media/a0686a22-83f6-46a5-86fe-b17566b88245/conversions/EssentialsLuxor_Horus_19433_Packshot_Web_LR-medium-two-thirds.jpg' },
+  { sku:'23401', url:'https://edge.arte-international.com/media/d4610242-66e0-4b12-8723-df90ddb40e04/conversions/Memphis_Amarna_23401_Packshot_Web_HR-medium-two-thirds.jpg' },
+  { sku:'23412', url:'https://edge.arte-international.com/media/6fe8a7ec-ecdd-49c4-b398-223293c48eed/conversions/Memphis_Sakkara_23412_Packshot_Web_HR-medium-two-thirds.jpg' },
+  { sku:'23413', url:'https://edge.arte-international.com/media/a45badcf-d133-44b1-bcd6-1d74b4f13141/conversions/Memphis_Sakkara_23413_Packshot_Web_HR-medium-two-thirds.jpg' },
+  { sku:'23421', url:'https://edge.arte-international.com/media/fb1738af-4e34-4d36-9a3e-7392f590381a/conversions/Memphis_Ibis_23421_Packshot_Web_LR-medium-two-thirds.jpg' },
+  { sku:'23422', url:'https://edge.arte-international.com/media/2899330e-abba-481e-9098-ffd76f1731cf/conversions/Memphis_Ibis_23422_Packshot_Web_LR-medium-two-thirds.jpg' },
+  { sku:'23431', url:'https://edge.arte-international.com/media/2ef17968-181d-4da5-8c8a-59f719a3c0fd/conversions/Memphis_Siwa_23431_Packshot_Web_LR-medium-two-thirds.jpg' },
+  { sku:'23433', url:'https://edge.arte-international.com/media/fac5d958-0b0e-437f-abbe-a07a2c147676/conversions/Memphis_Siwa_23433_Packshot_Web_LR-medium-two-thirds.jpg' },
+  { sku:'29221', url:'https://edge.arte-international.com/media/f92ad97a-a59b-431c-84ad-0a7520995f6a/conversions/Allures_Galon_29221_Flatshot_Web_LR-medium-two-thirds.jpg' },
+];
+
+function fetchB64(url) {
+  return new Promise((resolve, reject) => {
+    const opts = new URL(url);
+    const req = https.get({
+      hostname: opts.hostname, path: opts.pathname + opts.search,
+      timeout: 15000,
+      headers: {
+        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
+        'Accept': 'image/webp,image/apng,image/*,*/*;q=0.8',
+        'Referer': 'https://www.arte-international.com/',
+      }
+    }, (res) => {
+      if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location)
+        return fetchB64(res.headers.location).then(resolve).catch(reject);
+      if (res.statusCode !== 200) return reject(new Error(`HTTP ${res.statusCode}`));
+      const c = []; res.on('data', d => c.push(d));
+      res.on('end', () => resolve(Buffer.concat(c).toString('base64')));
+      res.on('error', reject);
+    });
+    req.on('error', reject);
+  });
+}
+
+function callGemini(b64) {
+  const body = JSON.stringify({
+    contents: [{ parts: [
+      { text: PROMPT },
+      { inline_data: { mime_type: 'image/jpeg', data: b64 } }
+    ]}],
+    generationConfig: { temperature: 0.2, maxOutputTokens: 1024 }
+  });
+  return new Promise((resolve, reject) => {
+    const u = new URL(GEMINI_URL);
+    const req = https.request({
+      hostname: u.hostname, path: u.pathname + u.search,
+      method: 'POST', headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(body) },
+      timeout: 30000,
+    }, (res) => {
+      const c = []; res.on('data', d => c.push(d));
+      res.on('end', () => {
+        try {
+          const data = JSON.parse(Buffer.concat(c).toString());
+          if (data.error) return reject(new Error(data.error.message));
+          const text = data.candidates?.[0]?.content?.parts?.[0]?.text || '';
+          const clean = text.replace(/```json\n?/g,'').replace(/```\n?/g,'').trim();
+          resolve(JSON.parse(clean));
+        } catch(e) { reject(e); }
+      });
+    });
+    req.on('error', reject); req.write(body); req.end();
+  });
+}
+
+const sleep = ms => new Promise(r => setTimeout(r, ms));
+
+async function main() {
+  await pgClient.connect();
+  let ok = 0, fail = 0;
+
+  for (const p of ARTE) {
+    try {
+      process.stdout.write(`Arte ${p.sku}... `);
+      const b64 = await fetchB64(p.url);
+      const ai = await callGemini(b64);
+      
+      // Update vendor_catalog
+      await pgClient.query(`UPDATE vendor_catalog SET
+        ai_colors=$1, ai_background_color=$2, ai_styles=$3,
+        ai_patterns=$4, ai_tags=$5, ai_description=$6
+        WHERE vendor_code='arte' AND mfr_sku=$7`,
+        [JSON.stringify(ai.colors), ai.backgroundColor, JSON.stringify(ai.styles),
+         JSON.stringify(ai.patterns), JSON.stringify(ai.tags), ai.description, p.sku]);
+      
+      // Update arte_catalog
+      await pgClient.query(`UPDATE arte_catalog SET
+        ai_colors=$1::jsonb, ai_background_color=$2, ai_styles=$3::jsonb,
+        ai_patterns=$4::jsonb, ai_tags=$5::jsonb, ai_description=$6, ai_accepted_at=NOW()
+        WHERE arte_sku=$7`,
+        [JSON.stringify(ai.colors), ai.backgroundColor, JSON.stringify(ai.styles),
+         JSON.stringify(ai.patterns), JSON.stringify(ai.tags), ai.description, p.sku]);
+      
+      console.log(`OK  colors=[${ai.colors.join(', ')}] bg=${ai.backgroundColor}`);
+      ok++; await sleep(1200);
+    } catch(e) { console.log(`FAIL ${e.message}`); fail++; }
+  }
+
+  console.log(`\nDONE: ${ok}/9 Arte enriched, ${fail} failed`);
+  await pgClient.end();
+}
+
+main().catch(e => { console.error(e); process.exit(1); });
diff --git a/enrich-arte-puppeteer.js b/enrich-arte-puppeteer.js
index c4c59c52..5480b0e1 100644
--- a/enrich-arte-puppeteer.js
+++ b/enrich-arte-puppeteer.js
@@ -2,7 +2,7 @@ const puppeteer = require('puppeteer');
 const https = require('https');
 const { Client } = require('pg');
 
-const GEMINI_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_KEY = '${GOOGLE_API_KEY}';
 const GEMINI_MODEL = 'gemini-2.0-flash';
 const PG_URL = 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified';
 
diff --git a/enrich-arte-puppeteer.js.pre-scrub-2026-05-07.bak b/enrich-arte-puppeteer.js.pre-scrub-2026-05-07.bak
new file mode 100644
index 00000000..c4c59c52
--- /dev/null
+++ b/enrich-arte-puppeteer.js.pre-scrub-2026-05-07.bak
@@ -0,0 +1,164 @@
+const puppeteer = require('puppeteer');
+const https = require('https');
+const { Client } = require('pg');
+
+const GEMINI_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_MODEL = 'gemini-2.0-flash';
+const PG_URL = 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified';
+
+const ARTE_PRODUCTS = [
+  { vc_id: 123, sku: '19433', name: 'Horus Desert Sun', url: 'https://www.arte-international.com/en/collections/essentials-luxor/horus/19433' },
+  { vc_id: 16,  sku: '23401', name: 'Amarna Bister', url: 'https://www.arte-international.com/en/collections/memphis/amarna/23401' },
+  { vc_id: 15,  sku: '23412', name: 'Sakkara Antique Gold', url: 'https://www.arte-international.com/en/collections/memphis/sakkara/23412' },
+  { vc_id: 172, sku: '23413', name: 'Sakkara Off-white', url: 'https://www.arte-international.com/en/collections/memphis/sakkara/23413' },
+  { vc_id: 72,  sku: '23421', name: 'Ibis Biscuit', url: 'https://www.arte-international.com/en/collections/memphis/ibis/23421' },
+  { vc_id: 75,  sku: '23422', name: 'Ibis Chestnut', url: 'https://www.arte-international.com/en/collections/memphis/ibis/23422' },
+  { vc_id: 78,  sku: '23431', name: 'Siwa Bone', url: 'https://www.arte-international.com/en/collections/memphis/siwa/23431' },
+  { vc_id: 83,  sku: '23433', name: 'Siwa Biscuit', url: 'https://www.arte-international.com/en/collections/memphis/siwa/23433' },
+  { vc_id: 183, sku: '29221', name: 'Galon Grey Linen', url: 'https://www.arte-international.com/en/collections/allures/galon/29221' },
+];
+
+const PROMPT = `You are an interior design color analyst for luxury wallcoverings.
+
+Analyze this wallcovering image and return a JSON object with these fields:
+- "colors": array of 3-6 prominent colors visible (e.g. ["Gold", "Ivory", "Charcoal"])
+- "backgroundColor": the single dominant background color (e.g. "Ivory")
+- "styles": array of 1-3 design styles (e.g. ["Contemporary", "Art Deco"])
+- "patterns": array of 1-2 pattern types (e.g. ["Geometric", "Textured"])
+- "tags": array of 4-8 interior design tags (e.g. ["luxury", "metallic", "hospitality", "accent wall"])
+- "description": a 2-sentence commercial description for an interior designer audience. NEVER use the word "wallpaper" — always say "wallcovering".
+
+Return ONLY the JSON object, no markdown fences, no explanation.`;
+
+function callGemini(imageBase64, mimeType) {
+  return new Promise((resolve, reject) => {
+    const body = JSON.stringify({
+      contents: [{ parts: [
+        { text: PROMPT },
+        { inline_data: { mime_type: mimeType || 'image/jpeg', data: imageBase64 } }
+      ]}],
+      generationConfig: { temperature: 0.3, maxOutputTokens: 1024 }
+    });
+    const url = new URL(`https://generativelanguage.googleapis.com/v1beta/models/${GEMINI_MODEL}:generateContent?key=${GEMINI_KEY}`);
+    const opts = { method: 'POST', hostname: url.hostname, path: url.pathname + url.search, headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(body) } };
+    const req = https.request(opts, (res) => {
+      const chunks = [];
+      res.on('data', c => chunks.push(c));
+      res.on('end', () => {
+        try {
+          const data = JSON.parse(Buffer.concat(chunks).toString());
+          if (data.error) return reject(new Error(data.error.message));
+          let text = data.candidates?.[0]?.content?.parts?.[0]?.text || '';
+          text = text.replace(/```json\n?/g, '').replace(/```\n?/g, '').trim();
+          resolve(JSON.parse(text));
+        } catch (e) { reject(e); }
+      });
+    });
+    req.on('error', reject);
+    req.write(body);
+    req.end();
+  });
+}
+
+function sleep(ms) { return new Promise(r => setTimeout(r, ms)); }
+
+async function main() {
+  const browser = await puppeteer.launch({ headless: 'new', args: ['--no-sandbox', '--disable-setuid-sandbox'] });
+  const db = new Client({ connectionString: PG_URL });
+  await db.connect();
+  
+  let success = 0, failed = 0;
+  
+  for (const p of ARTE_PRODUCTS) {
+    const page = await browser.newPage();
+    try {
+      console.log(`[arte] Navigating to ${p.sku} — ${p.name}...`);
+      await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36');
+      await page.goto(p.url, { waitUntil: 'networkidle2', timeout: 30000 });
+      await sleep(2000);
+      
+      // Find the packshot/product image on the page
+      const imgSrc = await page.evaluate(() => {
+        // Look for the main product image - Arte uses various selectors
+        const selectors = [
+          'img[src*="Packshot"]',
+          'img[src*="packshot"]', 
+          'img[src*="Flatshot"]',
+          '.product-image img',
+          '.product-detail img',
+          '[class*="product"] img[src*="arte-international"]',
+          'img[src*="edge.arte-international.com"]'
+        ];
+        for (const sel of selectors) {
+          const img = document.querySelector(sel);
+          if (img && img.src) return img.src;
+        }
+        // Fallback: find the largest image on page with arte domain
+        const allImgs = Array.from(document.querySelectorAll('img[src*="arte-international"]'));
+        if (allImgs.length) {
+          return allImgs.sort((a, b) => (b.naturalWidth || 0) - (a.naturalWidth || 0))[0]?.src;
+        }
+        return null;
+      });
+      
+      if (!imgSrc) {
+        // Fallback: take a screenshot of the product area
+        console.log(`  No image found, taking page screenshot...`);
+        const screenshot = await page.screenshot({ type: 'jpeg', quality: 85 });
+        const ai = await callGemini(screenshot.toString('base64'), 'image/jpeg');
+        await saveToDb(db, p, ai);
+        success++;
+        console.log(`  ✅ (screenshot) Colors: ${(ai.colors||[]).join(', ')}`);
+      } else {
+        console.log(`  Found image: ${imgSrc.substring(0, 80)}...`);
+        // Fetch the image through puppeteer's page context (inherits cookies/referer)
+        const imgB64 = await page.evaluate(async (src) => {
+          const resp = await fetch(src);
+          const blob = await resp.blob();
+          return new Promise((resolve) => {
+            const reader = new FileReader();
+            reader.onloadend = () => resolve(reader.result.split(',')[1]);
+            reader.readAsDataURL(blob);
+          });
+        }, imgSrc);
+        
+        const ai = await callGemini(imgB64, 'image/jpeg');
+        await saveToDb(db, p, ai);
+        success++;
+        console.log(`  ✅ Colors: ${(ai.colors||[]).join(', ')} | BG: ${ai.backgroundColor}`);
+      }
+      await sleep(1500);
+    } catch (err) {
+      console.error(`  ❌ FAILED ${p.sku}: ${err.message}`);
+      failed++;
+    } finally {
+      await page.close();
+    }
+  }
+  
+  await browser.close();
+  await db.end();
+  console.log(`\nDone: ${success} enriched, ${failed} failed out of ${ARTE_PRODUCTS.length}`);
+}
+
+async function saveToDb(db, p, ai) {
+  const colorsStr = (ai.colors || []).join(', ');
+  const stylesStr = (ai.styles || []).join(', ');
+  const patternsStr = (ai.patterns || []).join(', ');
+  const tagsStr = (ai.tags || []).join(', ');
+  
+  await db.query(`UPDATE vendor_catalog SET 
+    ai_colors = $1, ai_background_color = $2, ai_styles = $3, 
+    ai_patterns = $4, ai_tags = $5, ai_description = $6 
+    WHERE id = $7`, 
+    [colorsStr, ai.backgroundColor, stylesStr, patternsStr, tagsStr, ai.description, p.vc_id]);
+  
+  await db.query(`UPDATE arte_catalog SET 
+    ai_colors = $1, ai_background_color = $2, ai_styles = $3, 
+    ai_patterns = $4, ai_tags = $5, ai_description = $6, ai_accepted_at = NOW() 
+    WHERE arte_sku = $7`,
+    [JSON.stringify(ai.colors), ai.backgroundColor, JSON.stringify(ai.styles), 
+     JSON.stringify(ai.patterns), JSON.stringify(ai.tags), ai.description, p.sku]);
+}
+
+main().catch(console.error);
diff --git a/enrich-remaining-13.js b/enrich-remaining-13.js
index ac73925a..355bc5c2 100644
--- a/enrich-remaining-13.js
+++ b/enrich-remaining-13.js
@@ -2,7 +2,7 @@ const https = require('https');
 const http = require('http');
 const { Client } = require('pg');
 
-const GEMINI_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_KEY = '${GOOGLE_API_KEY}';
 const GEMINI_MODEL = 'gemini-2.0-flash';
 const PG_URL = 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified';
 
diff --git a/enrich-remaining-13.js.pre-scrub-2026-05-07.bak b/enrich-remaining-13.js.pre-scrub-2026-05-07.bak
new file mode 100644
index 00000000..ac73925a
--- /dev/null
+++ b/enrich-remaining-13.js.pre-scrub-2026-05-07.bak
@@ -0,0 +1,136 @@
+const https = require('https');
+const http = require('http');
+const { Client } = require('pg');
+
+const GEMINI_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_MODEL = 'gemini-2.0-flash';
+const PG_URL = 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified';
+
+const PRODUCTS = [
+  // Arte — use packshot_url from arte_catalog
+  { vc_id: 123, vendor: 'arte', sku: '19433', name: 'Horus Desert Sun', img: 'https://edge.arte-international.com/media/a0686a22-83f6-46a5-86fe-b17566b88245/conversions/EssentialsLuxor_Horus_19433_Packshot_Web_LR-medium-two-thirds.jpg' },
+  { vc_id: 16,  vendor: 'arte', sku: '23401', name: 'Amarna Bister', img: 'https://edge.arte-international.com/media/d4610242-66e0-4b12-8723-df90ddb40e04/conversions/Memphis_Amarna_23401_Packshot_Web_HR-medium-two-thirds.jpg' },
+  { vc_id: 15,  vendor: 'arte', sku: '23412', name: 'Sakkara Antique Gold', img: 'https://edge.arte-international.com/media/6fe8a7ec-ecdd-49c4-b398-223293c48eed/conversions/Memphis_Sakkara_23412_Packshot_Web_HR-medium-two-thirds.jpg' },
+  { vc_id: 172, vendor: 'arte', sku: '23413', name: 'Sakkara Off-white', img: 'https://edge.arte-international.com/media/a45badcf-d133-44b1-bcd6-1d74b4f13141/conversions/Memphis_Sakkara_23413_Packshot_Web_HR-medium-two-thirds.jpg' },
+  { vc_id: 72,  vendor: 'arte', sku: '23421', name: 'Ibis Biscuit', img: 'https://edge.arte-international.com/media/fb1738af-4e34-4d36-9a3e-7392f590381a/conversions/Memphis_Ibis_23421_Packshot_Web_LR-medium-two-thirds.jpg' },
+  { vc_id: 75,  vendor: 'arte', sku: '23422', name: 'Ibis Chestnut', img: 'https://edge.arte-international.com/media/2899330e-abba-481e-9098-ffd76f1731cf/conversions/Memphis_Ibis_23422_Packshot_Web_LR-medium-two-thirds.jpg' },
+  { vc_id: 78,  vendor: 'arte', sku: '23431', name: 'Siwa Bone', img: 'https://edge.arte-international.com/media/2ef17968-181d-4da5-8c8a-59f719a3c0fd/conversions/Memphis_Siwa_23431_Packshot_Web_LR-medium-two-thirds.jpg' },
+  { vc_id: 83,  vendor: 'arte', sku: '23433', name: 'Siwa Biscuit', img: 'https://edge.arte-international.com/media/fac5d958-0b0e-437f-abbe-a07a2c147676/conversions/Memphis_Siwa_23433_Packshot_Web_LR-medium-two-thirds.jpg' },
+  { vc_id: 183, vendor: 'arte', sku: '29221', name: 'Galon Grey Linen', img: 'https://edge.arte-international.com/media/f92ad97a-a59b-431c-84ad-0a7520995f6a/conversions/Allures_Galon_29221_Flatshot_Web_LR-medium-two-thirds.jpg' },
+  // Black Edition — use vendor_catalog image_url
+  { vc_id: 1751, vendor: 'black_edition', sku: 'W924/01', name: 'Mizumi Panel Carbon', img: 'https://static.theromogroup.com/rb/cache/image/720x720/catalog/product/W/9/W924-01FP-mizumi-panel-charcoal_00.jpg' },
+  { vc_id: 1752, vendor: 'black_edition', sku: 'W924/02', name: 'Mizumi Panel Midnight', img: 'https://static.theromogroup.com/rb/cache/image/720x720/catalog/product/W/9/W924-02FP-mizumi-panel-midnight_00.jpg' },
+  { vc_id: 1753, vendor: 'black_edition', sku: 'W924/03', name: 'Mizumi Panel Basalt', img: 'https://static.theromogroup.com/rb/cache/image/720x720/catalog/product/W/9/W924-03FP-mizumi-panel-stone_00.jpg' },
+  { vc_id: 1754, vendor: 'black_edition', sku: 'W924/04', name: 'Mizumi Panel Viridian', img: 'https://static.theromogroup.com/rb/cache/image/720x720/catalog/product/W/9/W924-04FP-mizumi-panel-teal_02.jpg' },
+];
+
+const PROMPT = `You are an interior design color analyst for luxury wallcoverings.
+
+Analyze this wallcovering image and return a JSON object with these fields:
+- "colors": array of 3-6 prominent colors visible (e.g. ["Gold", "Ivory", "Charcoal"])
+- "backgroundColor": the single dominant background color (e.g. "Ivory")
+- "styles": array of 1-3 design styles (e.g. ["Contemporary", "Art Deco"])
+- "patterns": array of 1-2 pattern types (e.g. ["Geometric", "Textured"])
+- "tags": array of 4-8 interior design tags (e.g. ["luxury", "metallic", "hospitality", "accent wall"])
+- "description": a 2-sentence commercial description for an interior designer audience. NEVER use the word "wallpaper" — always say "wallcovering".
+
+Return ONLY the JSON object, no markdown fences, no explanation.`;
+
+function fetchImageBase64(url) {
+  return new Promise((resolve, reject) => {
+    const mod = url.startsWith('https') ? https : http;
+    mod.get(url, { headers: { 'User-Agent': 'Mozilla/5.0' } }, (res) => {
+      if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
+        return fetchImageBase64(res.headers.location).then(resolve).catch(reject);
+      }
+      if (res.statusCode !== 200) return reject(new Error(`HTTP ${res.statusCode} for ${url}`));
+      const chunks = [];
+      res.on('data', c => chunks.push(c));
+      res.on('end', () => resolve(Buffer.concat(chunks).toString('base64')));
+      res.on('error', reject);
+    }).on('error', reject);
+  });
+}
+
+function callGemini(imageBase64, mimeType) {
+  return new Promise((resolve, reject) => {
+    const body = JSON.stringify({
+      contents: [{
+        parts: [
+          { text: PROMPT },
+          { inline_data: { mime_type: mimeType || 'image/jpeg', data: imageBase64 } }
+        ]
+      }],
+      generationConfig: { temperature: 0.3, maxOutputTokens: 1024 }
+    });
+    const url = new URL(`https://generativelanguage.googleapis.com/v1beta/models/${GEMINI_MODEL}:generateContent?key=${GEMINI_KEY}`);
+    const opts = { method: 'POST', hostname: url.hostname, path: url.pathname + url.search, headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(body) } };
+    const req = https.request(opts, (res) => {
+      const chunks = [];
+      res.on('data', c => chunks.push(c));
+      res.on('end', () => {
+        try {
+          const data = JSON.parse(Buffer.concat(chunks).toString());
+          if (data.error) return reject(new Error(data.error.message));
+          let text = data.candidates?.[0]?.content?.parts?.[0]?.text || '';
+          text = text.replace(/```json\n?/g, '').replace(/```\n?/g, '').trim();
+          resolve(JSON.parse(text));
+        } catch (e) { reject(e); }
+      });
+    });
+    req.on('error', reject);
+    req.write(body);
+    req.end();
+  });
+}
+
+function sleep(ms) { return new Promise(r => setTimeout(r, ms)); }
+
+async function main() {
+  const db = new Client({ connectionString: PG_URL });
+  await db.connect();
+  
+  let success = 0, failed = 0;
+  
+  for (const p of PRODUCTS) {
+    try {
+      console.log(`[${p.vendor}] Analyzing ${p.sku} — ${p.name}...`);
+      const imgB64 = await fetchImageBase64(p.img);
+      const ai = await callGemini(imgB64);
+      
+      const colorsStr = (ai.colors || []).join(', ');
+      const stylesStr = (ai.styles || []).join(', ');
+      const patternsStr = (ai.patterns || []).join(', ');
+      const tagsStr = (ai.tags || []).join(', ');
+      
+      // Update vendor_catalog
+      await db.query(`UPDATE vendor_catalog SET 
+        ai_colors = $1, ai_background_color = $2, ai_styles = $3, 
+        ai_patterns = $4, ai_tags = $5, ai_description = $6 
+        WHERE id = $7`, 
+        [colorsStr, ai.backgroundColor, stylesStr, patternsStr, tagsStr, ai.description, p.vc_id]);
+      
+      // Also update arte_catalog if Arte
+      if (p.vendor === 'arte') {
+        await db.query(`UPDATE arte_catalog SET 
+          ai_colors = $1, ai_background_color = $2, ai_styles = $3, 
+          ai_patterns = $4, ai_tags = $5, ai_description = $6, ai_accepted_at = NOW() 
+          WHERE arte_sku = $7`,
+          [JSON.stringify(ai.colors), ai.backgroundColor, JSON.stringify(ai.styles), 
+           JSON.stringify(ai.patterns), JSON.stringify(ai.tags), ai.description, p.sku]);
+      }
+      
+      console.log(`  ✅ Colors: ${colorsStr} | BG: ${ai.backgroundColor}`);
+      success++;
+      await sleep(1200); // rate limit
+    } catch (err) {
+      console.error(`  ❌ FAILED ${p.sku}: ${err.message}`);
+      failed++;
+    }
+  }
+  
+  await db.end();
+  console.log(`\nDone: ${success} enriched, ${failed} failed out of ${PRODUCTS.length}`);
+}
+
+main().catch(console.error);
diff --git a/gemini-classify-texture.js b/gemini-classify-texture.js
index 6d0f7fab..ca1ee579 100644
--- a/gemini-classify-texture.js
+++ b/gemini-classify-texture.js
@@ -3,7 +3,7 @@ const { Client } = require('pg');
 const https = require('https');
 const http = require('http');
 
-const GEMINI_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_KEY = '${GOOGLE_API_KEY}';
 const GEMINI_URL = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${GEMINI_KEY}`;
 const PROMPT = `Is this wallcovering image a repeating pattern or a non-repeating texture? If it's a texture (grasscloth, linen, plain, solid, stucco, metallic, stone, concrete, weave, etc.), respond 'TEXTURE'. If it has a visible repeating pattern (florals, stripes, damask, geometric, medallion, toile, scenic, mural, etc.), respond 'PATTERN'. Respond with only one word: TEXTURE or PATTERN.`;
 
diff --git a/gemini-classify-texture.js.pre-scrub-2026-05-07.bak b/gemini-classify-texture.js.pre-scrub-2026-05-07.bak
new file mode 100644
index 00000000..6d0f7fab
--- /dev/null
+++ b/gemini-classify-texture.js.pre-scrub-2026-05-07.bak
@@ -0,0 +1,112 @@
+#!/usr/bin/env node
+const { Client } = require('pg');
+const https = require('https');
+const http = require('http');
+
+const GEMINI_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_URL = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${GEMINI_KEY}`;
+const PROMPT = `Is this wallcovering image a repeating pattern or a non-repeating texture? If it's a texture (grasscloth, linen, plain, solid, stucco, metallic, stone, concrete, weave, etc.), respond 'TEXTURE'. If it has a visible repeating pattern (florals, stripes, damask, geometric, medallion, toile, scenic, mural, etc.), respond 'PATTERN'. Respond with only one word: TEXTURE or PATTERN.`;
+
+const db = new Client({ connectionString: 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified' });
+const products = require('/tmp/thibaut_remaining.json');
+const stats = { texture: 0, pattern: 0, error: 0, total: products.length };
+
+function sleep(ms) { return new Promise(r => setTimeout(r, ms)); }
+
+function downloadImage(url) {
+  return new Promise((resolve, reject) => {
+    const request = (targetUrl, redirectCount = 0) => {
+      if (redirectCount > 5) return reject(new Error('Too many redirects'));
+      const client = targetUrl.startsWith('https') ? https : http;
+      client.get(targetUrl, { timeout: 15000 }, (res) => {
+        if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
+          return request(res.headers.location, redirectCount + 1);
+        }
+        if (res.statusCode !== 200) { res.resume(); return reject(new Error(`HTTP ${res.statusCode}`)); }
+        const chunks = [];
+        res.on('data', chunk => chunks.push(chunk));
+        res.on('end', () => {
+          const buf = Buffer.concat(chunks);
+          const ct = res.headers['content-type'] || 'image/jpeg';
+          resolve({ base64: buf.toString('base64'), mimeType: ct.split(';')[0].trim() });
+        });
+        res.on('error', reject);
+      }).on('error', reject).on('timeout', function() { this.destroy(); reject(new Error('timeout')); });
+    };
+    request(url);
+  });
+}
+
+function classifyWithGemini(base64, mimeType) {
+  const payload = {
+    contents: [{ parts: [
+      { text: PROMPT },
+      { inline_data: { mime_type: mimeType, data: base64 } }
+    ]}],
+    generationConfig: { temperature: 0.1, maxOutputTokens: 10 }
+  };
+  return new Promise((resolve, reject) => {
+    const url = new URL(GEMINI_URL);
+    const postData = JSON.stringify(payload);
+    const req = https.request({
+      hostname: url.hostname, path: url.pathname + url.search, method: 'POST',
+      headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(postData) },
+      timeout: 30000
+    }, (res) => {
+      let data = '';
+      res.on('data', chunk => data += chunk);
+      res.on('end', () => {
+        try {
+          const json = JSON.parse(data);
+          if (json.error) return reject(new Error(json.error.message));
+          const text = json.candidates?.[0]?.content?.parts?.[0]?.text?.trim().toUpperCase() || '';
+          if (text.includes('TEXTURE')) resolve('TEXTURE');
+          else if (text.includes('PATTERN')) resolve('PATTERN');
+          else resolve('UNKNOWN');
+        } catch (e) { reject(e); }
+      });
+    });
+    req.on('error', reject);
+    req.on('timeout', () => { req.destroy(); reject(new Error('gemini timeout')); });
+    req.write(postData); req.end();
+  });
+}
+
+async function run() {
+  await db.connect();
+  console.log(`Classifying ${products.length} thibaut products with Gemini Vision (base64)...`);
+  const startTime = Date.now();
+
+  for (let i = 0; i < products.length; i++) {
+    const p = products[i];
+    try {
+      const { base64, mimeType } = await downloadImage(p.image_url);
+      const result = await classifyWithGemini(base64, mimeType);
+
+      if (result === 'TEXTURE') {
+        await db.query(`UPDATE thibaut_catalog SET repeat_h = '0', match_type = COALESCE(match_type, 'Texture'), updated_at = NOW() WHERE id = $1`, [p.id]);
+        stats.texture++;
+      } else if (result === 'PATTERN') {
+        await db.query(`UPDATE thibaut_catalog SET match_type = COALESCE(match_type, 'Unknown Pattern'), updated_at = NOW() WHERE id = $1`, [p.id]);
+        stats.pattern++;
+      } else { stats.error++; }
+
+      const pct = ((i + 1) / products.length * 100).toFixed(0);
+      if ((i + 1) % 5 === 0 || i === products.length - 1)
+        console.log(`  [${pct}%] ${i + 1}/${products.length} — T:${stats.texture} P:${stats.pattern} E:${stats.error} | ${p.pattern_name} → ${result}`);
+      await sleep(200);
+    } catch (err) {
+      stats.error++;
+      console.log(`  [ERR] #${p.id} ${p.pattern_name}: ${err.message.substring(0, 80)}`);
+      await sleep(500);
+    }
+  }
+
+  const elapsed = ((Date.now() - startTime) / 1000).toFixed(0);
+  console.log(`\n=== GEMINI CLASSIFICATION COMPLETE (${elapsed}s) ===`);
+  console.log(`Total: ${stats.total} | Texture: ${stats.texture} | Pattern: ${stats.pattern} | Errors: ${stats.error}`);
+  await db.end();
+  require('fs').writeFileSync('/tmp/gemini_classify_stats.json', JSON.stringify(stats));
+}
+
+run().catch(err => { console.error('Fatal:', err); process.exit(1); });
diff --git a/gemini-enrich-arte.js b/gemini-enrich-arte.js
index 3c281f6b..8888b233 100644
--- a/gemini-enrich-arte.js
+++ b/gemini-enrich-arte.js
@@ -1,7 +1,7 @@
 const https = require('https');
 const { Client } = require('pg');
 
-const GEMINI_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_KEY = '${GOOGLE_API_KEY}';
 const GEMINI_URL = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${GEMINI_KEY}`;
 
 const products = [
diff --git a/gemini-enrich-arte.js.pre-scrub-2026-05-07.bak b/gemini-enrich-arte.js.pre-scrub-2026-05-07.bak
new file mode 100644
index 00000000..3c281f6b
--- /dev/null
+++ b/gemini-enrich-arte.js.pre-scrub-2026-05-07.bak
@@ -0,0 +1,120 @@
+const https = require('https');
+const { Client } = require('pg');
+
+const GEMINI_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_URL = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${GEMINI_KEY}`;
+
+const products = [
+  { id: 123, sku: '19433', name: 'Horus Desert Sun', img: 'https://edge.arte-international.com/media/4960d9f1-bc0a-4bcb-9a82-c09d9e5e7d98/conversions/EssentialsLuxor_Horus_19436_Roomshot_Web_LR-medium-two-thirds.jpg' },
+  { id: 16, sku: '23401', name: 'Amarna Bister', img: 'https://edge.arte-international.com/media/cc56d30c-5e1c-4b22-878e-b437681e6f1b/conversions/Memphis_Amarna_23400_Roomshot_Web_LR-medium-two-thirds.jpg' },
+  { id: 15, sku: '23412', name: 'Sakkara Antique Gold', img: 'https://edge.arte-international.com/media/a580214f-25ff-472e-b88c-6a2bd8dfab64/conversions/Memphis_Sakkara_23410_Roomshot_Web_LR-medium-two-thirds.jpg' },
+  { id: 172, sku: '23413', name: 'Sakkara Off-white', img: 'https://edge.arte-international.com/media/a580214f-25ff-472e-b88c-6a2bd8dfab64/conversions/Memphis_Sakkara_23410_Roomshot_Web_LR-medium-two-thirds.jpg' },
+  { id: 72, sku: '23421', name: 'Ibis Biscuit', img: 'https://edge.arte-international.com/media/2183e2bc-0620-43c4-81ae-6364abed3937/conversions/Memphis_Ibis_23420_Roomshot_Web_LR-medium-two-thirds.jpg' },
+  { id: 75, sku: '23422', name: 'Ibis Chestnut', img: 'https://edge.arte-international.com/media/2183e2bc-0620-43c4-81ae-6364abed3937/conversions/Memphis_Ibis_23420_Roomshot_Web_LR-medium-two-thirds.jpg' },
+  { id: 78, sku: '23431', name: 'Siwa Bone', img: 'https://edge.arte-international.com/media/428898de-d288-40f3-b463-1714c59de939/conversions/Memphis_Siwa_23432_Roomshot_Web_LR-medium-two-thirds.jpg' },
+  { id: 83, sku: '23433', name: 'Siwa Biscuit', img: 'https://edge.arte-international.com/media/428898de-d288-40f3-b463-1714c59de939/conversions/Memphis_Siwa_23432_Roomshot_Web_LR-medium-two-thirds.jpg' },
+  { id: 183, sku: '29221', name: 'Galon Grey Linen', img: 'https://edge.arte-international.com/media/8571da7a-7bf9-4abc-adf0-76863cee5413/conversions/Allures_Galon9224_1_Roomshot_Web_LR-medium-two-thirds.jpg' },
+];
+
+function downloadImage(url) {
+  return new Promise((resolve, reject) => {
+    const get = (u, redirects = 0) => {
+      if (redirects > 5) return reject(new Error('Too many redirects'));
+      https.get(u, { headers: { 'User-Agent': 'Mozilla/5.0' } }, res => {
+        if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
+          return get(res.headers.location, redirects + 1);
+        }
+        if (res.statusCode !== 200) return reject(new Error(`HTTP ${res.statusCode}`));
+        const chunks = [];
+        res.on('data', c => chunks.push(c));
+        res.on('end', () => resolve(Buffer.concat(chunks)));
+      }).on('error', reject);
+    };
+    get(url);
+  });
+}
+
+function callGemini(body) {
+  return new Promise((resolve, reject) => {
+    const data = JSON.stringify(body);
+    const req = https.request(GEMINI_URL, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(data) } }, res => {
+      let buf = '';
+      res.on('data', c => buf += c);
+      res.on('end', () => { try { resolve(JSON.parse(buf)); } catch(e) { reject(new Error(buf.slice(0,500))); } });
+    });
+    req.on('error', reject);
+    req.write(data);
+    req.end();
+  });
+}
+
+const PROMPT = `You are an interior design wallcovering analyst. Analyze this wallcovering image and return ONLY valid JSON (no markdown, no backticks):
+{
+  "colors": ["<list 3-6 dominant colors you actually see>"],
+  "backgroundColor": "<the single dominant background color>",
+  "styles": ["<1-3 design styles>"],
+  "patterns": ["<1-3 pattern types>"],
+  "tags": ["<5-10 interior design tags>"],
+  "description": "<2-sentence commercial description>"
+}
+The product is: PRODUCT_NAME. Focus on what you actually see.`;
+
+async function analyzeOne(product) {
+  console.log(`  Downloading image...`);
+  const imgBuf = await downloadImage(product.img);
+  console.log(`  Downloaded ${(imgBuf.length/1024).toFixed(0)}KB, calling Gemini...`);
+  const b64 = imgBuf.toString('base64');
+  
+  const body = {
+    contents: [{
+      parts: [
+        { text: PROMPT.replace('PRODUCT_NAME', product.name) },
+        { inlineData: { mimeType: 'image/jpeg', data: b64 } }
+      ]
+    }],
+    generationConfig: { temperature: 0.2 }
+  };
+  
+  const res = await callGemini(body);
+  if (res.error) throw new Error(res.error.message);
+  const text = res.candidates?.[0]?.content?.parts?.[0]?.text || '';
+  return JSON.parse(text.replace(/```json\n?/g, '').replace(/```\n?/g, '').trim());
+}
+
+async function main() {
+  const client = new Client({ connectionString: 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified' });
+  await client.connect();
+  console.log('Processing 9 Arte products with base64 image download...\n');
+  
+  let success = 0, failed = 0;
+  
+  for (const p of products) {
+    console.log(`[${success+failed+1}/9] ${p.sku} (${p.name})`);
+    try {
+      const a = await analyzeOne(p);
+      const colors = a.colors?.join(', ') || '';
+      const bg = a.backgroundColor || '';
+      const styles = a.styles?.join(', ') || '';
+      const patterns = a.patterns?.join(', ') || '';
+      const tags = a.tags?.join(', ') || '';
+      const desc = a.description || '';
+      
+      await client.query(`UPDATE vendor_catalog SET ai_colors=$1, ai_background_color=$2, ai_styles=$3, ai_patterns=$4, ai_tags=$5, ai_description=$6 WHERE id=$7`,
+        [colors, bg, styles, patterns, tags, desc, p.id]);
+      await client.query(`UPDATE arte_catalog SET ai_colors=$1, ai_background_color=$2, ai_styles=$3, ai_patterns=$4, ai_tags=$5, ai_description=$6 WHERE arte_sku=$7`,
+        [colors, bg, styles, patterns, tags, desc, p.sku]);
+      
+      console.log(`  ✅ Colors: ${colors}`);
+      success++;
+    } catch(e) {
+      console.log(`  ❌ ${e.message}`);
+      failed++;
+    }
+    await new Promise(r => setTimeout(r, 300));
+  }
+  
+  console.log(`\nDone: ${success} succeeded, ${failed} failed`);
+  await client.end();
+}
+
+main().catch(e => { console.error(e); process.exit(1); });
diff --git a/gemini-enrich-arte9.js b/gemini-enrich-arte9.js
index 40f41186..97ffed8e 100644
--- a/gemini-enrich-arte9.js
+++ b/gemini-enrich-arte9.js
@@ -1,7 +1,7 @@
 const https = require('https');
 const { Client } = require('pg');
 
-const GEMINI_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_KEY = '${GOOGLE_API_KEY}';
 const GEMINI_URL = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${GEMINI_KEY}`;
 
 const db = new Client({ connectionString: 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified' });
diff --git a/gemini-enrich-arte9.js.pre-scrub-2026-05-07.bak b/gemini-enrich-arte9.js.pre-scrub-2026-05-07.bak
new file mode 100644
index 00000000..40f41186
--- /dev/null
+++ b/gemini-enrich-arte9.js.pre-scrub-2026-05-07.bak
@@ -0,0 +1,152 @@
+const https = require('https');
+const { Client } = require('pg');
+
+const GEMINI_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_URL = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${GEMINI_KEY}`;
+
+const db = new Client({ connectionString: 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified' });
+
+const PROMPT = `You are an interior design wallcovering analyst. Analyze this wallcovering product image (it may be a room setting showing the wallcovering installed on walls).
+Focus on the WALLCOVERING itself, not furniture or decor.
+Return ONLY valid JSON with these fields:
+{
+  "colors": ["<list of 3-6 dominant colors in the wallcovering, e.g. Gold, Cream, Charcoal>"],
+  "backgroundColor": "<the single dominant background color of the wallcovering>",
+  "tags": ["<5-8 interior design tags, e.g. Luxury, Textured, Organic, Hospitality>"],
+  "styles": ["<1-3 design style periods, e.g. Contemporary, Art Deco, Mid-Century Modern>"],
+  "patterns": ["<1-3 pattern types, e.g. Geometric, Abstract, Textural, Striped>"],
+  "description": "<2 sentence commercial description for an architect or interior designer>"
+}
+No markdown, no code fences, just raw JSON.`;
+
+// Use vendor_catalog room shot URLs (confirmed working 200 OK)
+const products = [
+  { id: 123, sku: '19433', name: 'Horus Desert Sun', img: 'https://edge.arte-international.com/media/4960d9f1-bc0a-4bcb-9a82-c09d9e5e7d98/conversions/EssentialsLuxor_Horus_19436_Roomshot_Web_LR-medium-two-thirds.jpg' },
+  { id: 16, sku: '23401', name: 'Amarna Bister', img: 'https://edge.arte-international.com/media/cc56d30c-5e1c-4b22-878e-b437681e6f1b/conversions/Memphis_Amarna_23400_Roomshot_Web_LR-medium-two-thirds.jpg' },
+  { id: 15, sku: '23412', name: 'Sakkara Antique Gold', img: 'https://edge.arte-international.com/media/a580214f-25ff-472e-b88c-6a2bd8dfab64/conversions/Memphis_Sakkara_23410_Roomshot_Web_LR-medium-two-thirds.jpg' },
+  { id: 172, sku: '23413', name: 'Sakkara Off-white', img: 'https://edge.arte-international.com/media/a580214f-25ff-472e-b88c-6a2bd8dfab64/conversions/Memphis_Sakkara_23410_Roomshot_Web_LR-medium-two-thirds.jpg' },
+  { id: 72, sku: '23421', name: 'Ibis Biscuit', img: 'https://edge.arte-international.com/media/2183e2bc-0620-43c4-81ae-6364abed3937/conversions/Memphis_Ibis_23420_Roomshot_Web_LR-medium-two-thirds.jpg' },
+  { id: 75, sku: '23422', name: 'Ibis Chestnut', img: 'https://edge.arte-international.com/media/2183e2bc-0620-43c4-81ae-6364abed3937/conversions/Memphis_Ibis_23420_Roomshot_Web_LR-medium-two-thirds.jpg' },
+  { id: 78, sku: '23431', name: 'Siwa Bone', img: 'https://edge.arte-international.com/media/428898de-d288-40f3-b463-1714c59de939/conversions/Memphis_Siwa_23432_Roomshot_Web_LR-medium-two-thirds.jpg' },
+  { id: 83, sku: '23433', name: 'Siwa Biscuit', img: 'https://edge.arte-international.com/media/428898de-d288-40f3-b463-1714c59de939/conversions/Memphis_Siwa_23432_Roomshot_Web_LR-medium-two-thirds.jpg' },
+  { id: 183, sku: '29221', name: 'Galon Grey Linen', img: 'https://edge.arte-international.com/media/8571da7a-7bf9-4abc-adf0-76863cee5413/conversions/Allures_Galon9224_1_Roomshot_Web_LR-medium-two-thirds.jpg' },
+];
+
+function fetchImageAsBase64(url) {
+  return new Promise((resolve, reject) => {
+    https.get(url, { headers: { 'User-Agent': 'Mozilla/5.0' } }, res => {
+      if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
+        return fetchImageAsBase64(res.headers.location).then(resolve).catch(reject);
+      }
+      if (res.statusCode !== 200) {
+        return reject(new Error(`HTTP ${res.statusCode} for ${url}`));
+      }
+      const chunks = [];
+      res.on('data', c => chunks.push(c));
+      res.on('end', () => {
+        const buf = Buffer.concat(chunks);
+        if (buf.length < 1000) return reject(new Error(`Image too small: ${buf.length} bytes`));
+        resolve(buf.toString('base64'));
+      });
+      res.on('error', reject);
+    }).on('error', reject);
+  });
+}
+
+function callGemini(b64, productName) {
+  return new Promise((resolve, reject) => {
+    const payload = JSON.stringify({
+      contents: [{
+        parts: [
+          { text: `Product: ${productName}\n\n${PROMPT}` },
+          { inline_data: { mime_type: 'image/jpeg', data: b64 } }
+        ]
+      }]
+    });
+    
+    const url = new URL(GEMINI_URL);
+    const options = {
+      hostname: url.hostname,
+      path: url.pathname + url.search,
+      method: 'POST',
+      headers: { 'Content-Type': 'application/json' }
+    };
+    
+    const req = https.request(options, res => {
+      let data = '';
+      res.on('data', chunk => data += chunk);
+      res.on('end', () => {
+        try {
+          const json = JSON.parse(data);
+          if (json.error) return reject(new Error(json.error.message));
+          const text = json.candidates?.[0]?.content?.parts?.[0]?.text || '';
+          const cleaned = text.replace(/```json\n?/g, '').replace(/```\n?/g, '').trim();
+          resolve(JSON.parse(cleaned));
+        } catch (e) {
+          reject(new Error(`Parse: ${e.message} — ${data.substring(0, 200)}`));
+        }
+      });
+    });
+    req.on('error', reject);
+    req.write(payload);
+    req.end();
+  });
+}
+
+async function updateDB(product, analysis) {
+  // vendor_catalog uses text columns — postgres array literal
+  const pgArr = arr => `{${arr.map(c => `"${c.replace(/"/g, '')}"`).join(',')}}`;
+  const vc_colors = pgArr(analysis.colors || []);
+  const vc_tags = pgArr(analysis.tags || []);
+  const vc_styles = pgArr(analysis.styles || []);
+  const vc_patterns = pgArr(analysis.patterns || []);
+
+  // arte_catalog uses jsonb columns — JSON array
+  const ac_colors = JSON.stringify(analysis.colors || []);
+  const ac_tags = JSON.stringify(analysis.tags || []);
+  const ac_styles = JSON.stringify(analysis.styles || []);
+  const ac_patterns = JSON.stringify(analysis.patterns || []);
+
+  // Update vendor_catalog (text columns)
+  await db.query(`
+    UPDATE vendor_catalog SET
+      ai_colors = $1, ai_background_color = $2, ai_tags = $3,
+      ai_styles = $4, ai_patterns = $5, ai_description = $6
+    WHERE id = $7
+  `, [vc_colors, analysis.backgroundColor, vc_tags, vc_styles, vc_patterns, analysis.description, product.id]);
+
+  // Update arte_catalog (jsonb columns)
+  await db.query(`
+    UPDATE arte_catalog SET
+      ai_colors = $1::jsonb, ai_background_color = $2, ai_tags = $3::jsonb,
+      ai_styles = $4::jsonb, ai_patterns = $5::jsonb, ai_description = $6
+    WHERE arte_sku = $7
+  `, [ac_colors, analysis.backgroundColor, ac_tags, ac_styles, ac_patterns, analysis.description, product.sku]);
+}
+
+async function main() {
+  await db.connect();
+  console.log('Connected. Processing 9 Arte products...\n');
+  let ok = 0, fail = 0;
+  
+  for (const p of products) {
+    try {
+      process.stdout.write(`${p.sku} ${p.name}... `);
+      const b64 = await fetchImageAsBase64(p.img);
+      console.log(`img ${Math.round(b64.length/1024)}KB`);
+      const analysis = await callGemini(b64, p.name);
+      console.log(`  ✅ ${analysis.colors.join(', ')} | bg: ${analysis.backgroundColor}`);
+      await updateDB(p, analysis);
+      ok++;
+      await new Promise(r => setTimeout(r, 1000));
+    } catch (e) {
+      console.log(`  ❌ ${e.message}`);
+      fail++;
+    }
+  }
+  
+  console.log(`\nDone: ${ok}/9 succeeded, ${fail} failed`);
+  await db.end();
+}
+
+main().catch(e => { console.error(e); process.exit(1); });
diff --git a/gemini-enrich-gaps.js b/gemini-enrich-gaps.js
index e43977c3..b81c6c0b 100644
--- a/gemini-enrich-gaps.js
+++ b/gemini-enrich-gaps.js
@@ -2,7 +2,7 @@ const https = require('https');
 const http = require('http');
 const { Client } = require('pg');
 
-const GEMINI_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_KEY = '${GOOGLE_API_KEY}';
 const GEMINI_MODEL = 'gemini-2.0-flash';
 const GEMINI_URL = `https://generativelanguage.googleapis.com/v1beta/models/${GEMINI_MODEL}:generateContent?key=${GEMINI_KEY}`;
 
diff --git a/gemini-enrich-gaps.js.pre-scrub-2026-05-07.bak b/gemini-enrich-gaps.js.pre-scrub-2026-05-07.bak
new file mode 100644
index 00000000..e43977c3
--- /dev/null
+++ b/gemini-enrich-gaps.js.pre-scrub-2026-05-07.bak
@@ -0,0 +1,175 @@
+const https = require('https');
+const http = require('http');
+const { Client } = require('pg');
+
+const GEMINI_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_MODEL = 'gemini-2.0-flash';
+const GEMINI_URL = `https://generativelanguage.googleapis.com/v1beta/models/${GEMINI_MODEL}:generateContent?key=${GEMINI_KEY}`;
+
+const DB = 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified';
+
+// Products to process — using arte_catalog packshot images for Arte, vendor_catalog images for Black Edition
+const products = [
+  // Arte (9) — packshot images from arte_catalog
+  { id: 123, vendor: 'arte', sku: '19433', name: 'Horus Desert Sun', img: 'https://edge.arte-international.com/media/a0686a22-83f6-46a5-86fe-b17566b88245/conversions/EssentialsLuxor_Horus_19433_Packshot_Web_LR-thumb-two-thirds.jpg' },
+  { id: 16,  vendor: 'arte', sku: '23401', name: 'Amarna Bister', img: 'https://edge.arte-international.com/media/d4610242-66e0-4b12-8723-df90ddb40e04/conversions/Memphis_Amarna_23401_Packshot_Web_HR-thumb-two-thirds.jpg' },
+  { id: 15,  vendor: 'arte', sku: '23412', name: 'Sakkara Antique Gold', img: 'https://edge.arte-international.com/media/6fe8a7ec-ecdd-49c4-b398-223293c48eed/conversions/Memphis_Sakkara_23412_Packshot_Web_HR-thumb-two-thirds.jpg' },
+  { id: 172, vendor: 'arte', sku: '23413', name: 'Sakkara Off-white', img: 'https://edge.arte-international.com/media/a45badcf-d133-44b1-bcd6-1d74b4f13141/conversions/Memphis_Sakkara_23413_Packshot_Web_HR-thumb-two-thirds.jpg' },
+  { id: 72,  vendor: 'arte', sku: '23421', name: 'Ibis Biscuit', img: 'https://edge.arte-international.com/media/fb1738af-4e34-4d36-9a3e-7392f590381a/conversions/Memphis_Ibis_23421_Packshot_Web_LR-thumb-two-thirds.jpg' },
+  { id: 75,  vendor: 'arte', sku: '23422', name: 'Ibis Chestnut', img: 'https://edge.arte-international.com/media/2899330e-abba-481e-9098-ffd76f1731cf/conversions/Memphis_Ibis_23422_Packshot_Web_LR-thumb-two-thirds.jpg' },
+  { id: 78,  vendor: 'arte', sku: '23431', name: 'Siwa Bone', img: 'https://edge.arte-international.com/media/2ef17968-181d-4da5-8c8a-59f719a3c0fd/conversions/Memphis_Siwa_23431_Packshot_Web_LR-thumb-two-thirds.jpg' },
+  { id: 83,  vendor: 'arte', sku: '23433', name: 'Siwa Biscuit', img: 'https://edge.arte-international.com/media/fac5d958-0b0e-437f-abbe-a07a2c147676/conversions/Memphis_Siwa_23433_Packshot_Web_LR-thumb-two-thirds.jpg' },
+  { id: 183, vendor: 'arte', sku: '29221', name: 'Galon Grey Linen', img: 'https://edge.arte-international.com/media/f92ad97a-a59b-431c-84ad-0a7520995f6a/conversions/Allures_Galon_29221_Flatshot_Web_LR-thumb-two-thirds.jpg' },
+  // Black Edition (4)
+  { id: 1751, vendor: 'black_edition', sku: 'W924/01', name: 'Mizumi Panel Carbon', img: 'https://static.theromogroup.com/rb/cache/image/720x720/catalog/product/W/9/W924-01FP-mizumi-panel-charcoal_00.jpg' },
+  { id: 1752, vendor: 'black_edition', sku: 'W924/02', name: 'Mizumi Panel Midnight', img: 'https://static.theromogroup.com/rb/cache/image/720x720/catalog/product/W/9/W924-02FP-mizumi-panel-midnight_00.jpg' },
+  { id: 1753, vendor: 'black_edition', sku: 'W924/03', name: 'Mizumi Panel Basalt', img: 'https://static.theromogroup.com/rb/cache/image/720x720/catalog/product/W/9/W924-03FP-mizumi-panel-stone_00.jpg' },
+  { id: 1754, vendor: 'black_edition', sku: 'W924/04', name: 'Mizumi Panel Viridian', img: 'https://static.theromogroup.com/rb/cache/image/720x720/catalog/product/W/9/W924-04FP-mizumi-panel-teal_02.jpg' },
+];
+
+const PROMPT = `You are an interior design wallcovering analyst. Analyze this wallcovering product image and return ONLY a JSON object (no markdown, no code fences) with these fields:
+
+{
+  "colors": ["<list 3-6 dominant colors you actually see, e.g. Warm Gold, Ivory, Charcoal>"],
+  "backgroundColor": "<the single most dominant background color>",
+  "styles": ["<1-3 design styles, e.g. Contemporary, Art Deco, Mid-Century Modern>"],
+  "patterns": ["<1-3 pattern types, e.g. Geometric, Textured, Floral, Abstract>"],
+  "tags": ["<5-10 interior design tags for search, e.g. luxury, metallic, neutral, organic, minimalist>"],
+  "description": "<2 sentences describing the wallcovering for a commercial buyer>"
+}
+
+Product: PRODUCT_NAME
+Return ONLY the JSON object.`;
+
+function fetchJSON(url, body) {
+  return new Promise((resolve, reject) => {
+    const data = JSON.stringify(body);
+    const parsed = new URL(url);
+    const req = https.request({
+      hostname: parsed.hostname,
+      path: parsed.pathname + parsed.search,
+      method: 'POST',
+      headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(data) }
+    }, (res) => {
+      let chunks = [];
+      res.on('data', c => chunks.push(c));
+      res.on('end', () => {
+        try { resolve(JSON.parse(Buffer.concat(chunks).toString())); }
+        catch(e) { reject(new Error('JSON parse error: ' + Buffer.concat(chunks).toString().slice(0, 500))); }
+      });
+    });
+    req.on('error', reject);
+    req.write(data);
+    req.end();
+  });
+}
+
+async function analyzeWithGemini(product) {
+  const prompt = PROMPT.replace('PRODUCT_NAME', product.name);
+  const body = {
+    contents: [{
+      parts: [
+        { text: prompt },
+        { inlineData: undefined },
+        { fileData: undefined }
+      ]
+    }],
+    generationConfig: { temperature: 0.2, maxOutputTokens: 1024 }
+  };
+  // Use image URL reference
+  body.contents[0].parts = [
+    { text: prompt },
+    { text: `Image URL for reference: ${product.img}` }
+  ];
+  
+  // Actually fetch the image and send inline
+  const imgBuf = await fetchImage(product.img);
+  if (imgBuf) {
+    body.contents[0].parts = [
+      { text: prompt },
+      { inlineData: { mimeType: 'image/jpeg', data: imgBuf.toString('base64') } }
+    ];
+  }
+
+  const resp = await fetchJSON(GEMINI_URL, body);
+  if (resp.error) throw new Error(resp.error.message);
+  
+  const text = resp.candidates?.[0]?.content?.parts?.[0]?.text || '';
+  // Strip markdown fences if present
+  const clean = text.replace(/```json\s*/g, '').replace(/```\s*/g, '').trim();
+  return JSON.parse(clean);
+}
+
+function fetchImage(url) {
+  return new Promise((resolve) => {
+    const mod = url.startsWith('https') ? https : http;
+    mod.get(url, { headers: { 'User-Agent': 'Mozilla/5.0' } }, (res) => {
+      if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
+        return fetchImage(res.headers.location).then(resolve);
+      }
+      if (res.statusCode !== 200) { resolve(null); return; }
+      let chunks = [];
+      res.on('data', c => chunks.push(c));
+      res.on('end', () => resolve(Buffer.concat(chunks)));
+    }).on('error', () => resolve(null));
+  });
+}
+
+async function main() {
+  const db = new Client({ connectionString: DB });
+  await db.connect();
+  
+  let success = 0, failed = 0;
+  
+  for (const p of products) {
+    try {
+      console.log(`[${p.vendor}] Analyzing ${p.sku} - ${p.name}...`);
+      const ai = await analyzeWithGemini(p);
+      
+      const colorsStr = (ai.colors || []).join(', ');
+      const tagsStr = (ai.tags || []).join(', ');
+      const stylesStr = (ai.styles || []).join(', ');
+      const patternsStr = (ai.patterns || []).join(', ');
+      
+      // Update vendor_catalog
+      await db.query(`
+        UPDATE vendor_catalog SET
+          ai_colors = $1,
+          ai_background_color = $2,
+          ai_styles = $3,
+          ai_patterns = $4,
+          ai_tags = $5,
+          ai_description = $6
+        WHERE id = $7
+      `, [colorsStr, ai.backgroundColor, stylesStr, patternsStr, tagsStr, ai.description, p.id]);
+      
+      // Also update arte_catalog if Arte vendor
+      if (p.vendor === 'arte') {
+        await db.query(`
+          UPDATE arte_catalog SET
+            ai_colors = $1,
+            ai_background_color = $2,
+            ai_styles = $3,
+            ai_patterns = $4,
+            ai_tags = $5,
+            ai_description = $6
+          WHERE arte_sku = $7
+        `, [colorsStr, ai.backgroundColor, stylesStr, patternsStr, tagsStr, ai.description, p.sku]);
+      }
+      
+      console.log(`  ✅ ${p.sku}: colors=[${colorsStr}] bg=${ai.backgroundColor}`);
+      success++;
+      
+      // Rate limit: ~300ms between calls
+      await new Promise(r => setTimeout(r, 300));
+    } catch (err) {
+      console.error(`  ❌ ${p.sku}: ${err.message}`);
+      failed++;
+    }
+  }
+  
+  console.log(`\nDone: ${success} succeeded, ${failed} failed out of ${products.length}`);
+  await db.end();
+}
+
+main().catch(e => { console.error(e); process.exit(1); });
diff --git a/lib/.gitignore b/lib/.gitignore
new file mode 100644
index 00000000..7e6a9c3e
--- /dev/null
+++ b/lib/.gitignore
@@ -0,0 +1,12 @@
+node_modules/
+.env
+.env.local
+.env.*.local
+.env.*
+tmp/
+*.log
+.DS_Store
+dist/
+build/
+.next/
+*.bak
diff --git a/mailers/scalamandre-pillows-launch.html b/mailers/scalamandre-pillows-launch.html
new file mode 100644
index 00000000..691a5f3d
--- /dev/null
+++ b/mailers/scalamandre-pillows-launch.html
@@ -0,0 +1,206 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<title>The Scalamandre Pillow Collection — Now at Designer Wallcoverings</title>
+<style type="text/css">
+  /* Reset + email-safe base */
+  body, table, td, p, a, li, blockquote { -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; }
+  body { margin: 0 !important; padding: 0 !important; width: 100% !important; background: #f4f1ec; font-family: Georgia, 'Times New Roman', serif; color: #2a2724; }
+  table { border-collapse: collapse !important; }
+  img { -ms-interpolation-mode: bicubic; border: 0; outline: none; text-decoration: none; display: block; }
+  a { color: #1a1a1a; text-decoration: none; }
+  .wrap { width: 100%; background: #f4f1ec; padding: 0; }
+  .container { max-width: 620px; margin: 0 auto; background: #ffffff; }
+  .hero-img { width: 100%; height: auto; display: block; }
+  .thumb-img { width: 100%; height: auto; display: block; }
+  .h1 { font-size: 30px; line-height: 36px; letter-spacing: 0.5px; font-weight: 400; margin: 0; color: #1a1a1a; }
+  .lede { font-size: 15px; line-height: 22px; color: #5a544c; margin: 12px 0 0; }
+  .cta-btn { display: inline-block; padding: 14px 28px; background: #1a1a1a; color: #ffffff !important; font-family: Helvetica, Arial, sans-serif; font-size: 12px; letter-spacing: 2.5px; text-transform: uppercase; text-decoration: none; }
+  .cat-label { font-family: Helvetica, Arial, sans-serif; font-size: 11px; letter-spacing: 2px; text-transform: uppercase; color: #1a1a1a; margin: 0; }
+  .cat-count { font-family: Helvetica, Arial, sans-serif; font-size: 10px; letter-spacing: 1.5px; text-transform: uppercase; color: #8d8478; margin: 4px 0 0; }
+  .footer-text { font-family: Helvetica, Arial, sans-serif; font-size: 11px; line-height: 18px; color: #8d8478; }
+  @media only screen and (max-width: 620px) {
+    .stack { display: block !important; width: 100% !important; }
+    .h1 { font-size: 24px !important; line-height: 30px !important; }
+  }
+</style>
+</head>
+<body style="margin:0;padding:0;background:#f4f1ec;">
+<table role="presentation" class="wrap" width="100%" cellspacing="0" cellpadding="0" border="0">
+<tr><td align="center" style="padding: 20px 0;">
+
+  <!-- ============ CONTAINER ============ -->
+  <table role="presentation" class="container" width="620" cellspacing="0" cellpadding="0" border="0" style="background:#ffffff;">
+
+    <!-- ============ DW BANNER ============ -->
+    <tr><td align="center" style="padding: 28px 0 14px; border-bottom: 1px solid #e8e2d6;">
+      <a href="https://designerwallcoverings.com" target="_blank" style="text-decoration:none;color:#1a1a1a;">
+        <div style="font-family: Georgia, 'Times New Roman', serif; font-size: 26px; letter-spacing: 6px; font-weight: 400; color: #1a1a1a; text-transform: uppercase;">Designer Wallcoverings</div>
+        <div style="font-family: Helvetica, Arial, sans-serif; font-size: 9px; letter-spacing: 4px; color: #8d8478; margin-top: 4px; text-transform: uppercase;">est. 2003 · to the trade</div>
+      </a>
+    </td></tr>
+
+    <!-- ============ NAV ============ -->
+    <tr><td align="center" style="padding: 12px 0 16px; border-bottom: 1px solid #e8e2d6; font-family: Helvetica, Arial, sans-serif; font-size: 10px; letter-spacing: 2px; text-transform: uppercase;">
+      <a href="https://designerwallcoverings.com/collections/wallcoverings" style="color:#1a1a1a; padding: 0 12px;">Wallcoverings</a>
+      <span style="color:#d4cdb8;">|</span>
+      <a href="https://designerwallcoverings.com/collections/fabrics" style="color:#1a1a1a; padding: 0 12px;">Fabrics</a>
+      <span style="color:#d4cdb8;">|</span>
+      <a href="https://designerwallcoverings.com/collections/scalamandre-pillows" style="color:#9a7b3f; padding: 0 12px; font-weight: 600;">Pillows · New</a>
+      <span style="color:#d4cdb8;">|</span>
+      <a href="https://designerwallcoverings.com/pages/trade" style="color:#1a1a1a; padding: 0 12px;">Trade</a>
+    </td></tr>
+
+    <!-- ============ HERO IMAGE ============ -->
+    <tr><td style="padding: 0;">
+      <a href="https://designerwallcoverings.com/search?q=heatherton+pillow+scalamandre" target="_blank">
+        <img src="https://s7d2.scene7.com/is/image/starkcarpet/HN_0014BADK27333?$Full%5FImages$" alt="Heatherton Pillow by Scalamandre" class="hero-img" width="620" style="width:100%; max-width:620px; height:auto;">
+      </a>
+    </td></tr>
+
+    <!-- ============ HERO COPY ============ -->
+    <tr><td style="padding: 36px 36px 8px;" align="center">
+      <p class="h1" style="font-family: Georgia, 'Times New Roman', serif; font-size: 30px; line-height: 36px; margin: 0; color: #1a1a1a;">The Scalamandre Pillow Collection</p>
+      <p style="font-family: Helvetica, Arial, sans-serif; font-size: 11px; letter-spacing: 3px; text-transform: uppercase; color: #9a7b3f; margin: 14px 0 0;">New Arrivals · 1,500+ Pieces</p>
+      <p class="lede" style="font-family: Georgia, 'Times New Roman', serif; font-size: 15px; line-height: 22px; color: #5a544c; margin: 18px 32px 0; max-width: 480px;">
+        From the same atelier that has dressed America's most considered interiors since 1929 — Scalamandre pillows, now stocked at Designer Wallcoverings. Bolsters, lumbars, spheres, and squares in two hundred and sixty patterns.
+      </p>
+      <p style="margin: 28px 0 0;">
+        <a href="https://designerwallcoverings.com/search?q=scalamandre+pillow" target="_blank" class="cta-btn" style="display:inline-block; padding:14px 36px; background:#1a1a1a; color:#ffffff; font-family: Helvetica, Arial, sans-serif; font-size:11px; letter-spacing:3px; text-transform:uppercase; text-decoration:none;">Shop the Collection</a>
+      </p>
+    </td></tr>
+
+    <!-- ============ 3 THUMBS ============ -->
+    <tr><td style="padding: 48px 24px 16px;" align="center">
+      <p style="font-family: Helvetica, Arial, sans-serif; font-size: 10px; letter-spacing: 3px; text-transform: uppercase; color: #8d8478; margin: 0 0 24px;">Featured Patterns</p>
+      <table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0">
+        <tr>
+          <td class="stack" width="33%" valign="top" style="padding: 0 6px;" align="center">
+            <a href="https://designerwallcoverings.com/search?q=petal+velvet+pillow" target="_blank">
+              <img src="https://s7d2.scene7.com/is/image/starkcarpet/HN_0005SDDK27332?$Full%5FImages$" alt="Petal Velvet Pillow" class="thumb-img" width="180" style="width:100%; max-width:180px; height:auto;">
+              <p style="font-family: Georgia, serif; font-size: 13px; color: #1a1a1a; margin: 12px 0 2px;">Petal Velvet</p>
+              <p style="font-family: Helvetica, Arial, sans-serif; font-size: 10px; letter-spacing: 1.5px; color: #8d8478; margin: 0;">32 colorways · from $470</p>
+            </a>
+          </td>
+          <td class="stack" width="33%" valign="top" style="padding: 0 6px;" align="center">
+            <a href="https://designerwallcoverings.com/search?q=persia+pillow" target="_blank">
+              <img src="https://s7d2.scene7.com/is/image/starkcarpet/SC_0006LBDK1627M?$Full%5FImages$" alt="Persia Pillow" class="thumb-img" width="180" style="width:100%; max-width:180px; height:auto;">
+              <p style="font-family: Georgia, serif; font-size: 13px; color: #1a1a1a; margin: 12px 0 2px;">Persia</p>
+              <p style="font-family: Helvetica, Arial, sans-serif; font-size: 10px; letter-spacing: 1.5px; color: #8d8478; margin: 0;">30 colorways · from $294</p>
+            </a>
+          </td>
+          <td class="stack" width="33%" valign="top" style="padding: 0 6px;" align="center">
+            <a href="https://designerwallcoverings.com/search?q=torino+velvet+pillow" target="_blank">
+              <img src="https://s7d2.scene7.com/is/image/starkcarpet/MT_0004TORIPILL?$Full%5FImages$" alt="Torino Velvet Pillow" class="thumb-img" width="180" style="width:100%; max-width:180px; height:auto;">
+              <p style="font-family: Georgia, serif; font-size: 13px; color: #1a1a1a; margin: 12px 0 2px;">Torino Velvet</p>
+              <p style="font-family: Helvetica, Arial, sans-serif; font-size: 10px; letter-spacing: 1.5px; color: #8d8478; margin: 0;">25 colorways · from $390</p>
+            </a>
+          </td>
+        </tr>
+      </table>
+    </td></tr>
+
+    <!-- ============ CATEGORIES (PHILLIP JEFFRIES STYLE) ============ -->
+    <tr><td style="padding: 56px 24px 24px;" align="center">
+      <p style="font-family: Helvetica, Arial, sans-serif; font-size: 10px; letter-spacing: 3px; text-transform: uppercase; color: #8d8478; margin: 0 0 4px;">Shop by</p>
+      <p style="font-family: Georgia, serif; font-size: 22px; color: #1a1a1a; margin: 0 0 28px;">Shape</p>
+      <table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0">
+        <tr>
+          <td class="stack" width="25%" valign="top" align="center" style="padding: 0 4px;">
+            <a href="https://designerwallcoverings.com/search?q=scalamandre+square+pillow" target="_blank" style="text-decoration:none;">
+              <div style="background:#f4f1ec; padding: 38px 0; border:1px solid #e8e2d6;">
+                <p class="cat-label" style="font-family: Helvetica, Arial, sans-serif; font-size: 12px; letter-spacing: 2px; text-transform: uppercase; color: #1a1a1a; margin: 0;">Square</p>
+                <p class="cat-count" style="font-family: Helvetica, Arial, sans-serif; font-size: 10px; letter-spacing: 1.5px; text-transform: uppercase; color: #8d8478; margin: 6px 0 0;">576 Pieces</p>
+              </div>
+            </a>
+          </td>
+          <td class="stack" width="25%" valign="top" align="center" style="padding: 0 4px;">
+            <a href="https://designerwallcoverings.com/search?q=scalamandre+lumbar+pillow" target="_blank" style="text-decoration:none;">
+              <div style="background:#f4f1ec; padding: 38px 0; border:1px solid #e8e2d6;">
+                <p class="cat-label" style="font-family: Helvetica, Arial, sans-serif; font-size: 12px; letter-spacing: 2px; text-transform: uppercase; color: #1a1a1a; margin: 0;">Lumbar</p>
+                <p class="cat-count" style="font-family: Helvetica, Arial, sans-serif; font-size: 10px; letter-spacing: 1.5px; text-transform: uppercase; color: #8d8478; margin: 6px 0 0;">250 Pieces</p>
+              </div>
+            </a>
+          </td>
+          <td class="stack" width="25%" valign="top" align="center" style="padding: 0 4px;">
+            <a href="https://designerwallcoverings.com/search?q=scalamandre+bolster+pillow" target="_blank" style="text-decoration:none;">
+              <div style="background:#f4f1ec; padding: 38px 0; border:1px solid #e8e2d6;">
+                <p class="cat-label" style="font-family: Helvetica, Arial, sans-serif; font-size: 12px; letter-spacing: 2px; text-transform: uppercase; color: #1a1a1a; margin: 0;">Bolster</p>
+                <p class="cat-count" style="font-family: Helvetica, Arial, sans-serif; font-size: 10px; letter-spacing: 1.5px; text-transform: uppercase; color: #8d8478; margin: 6px 0 0;">102 Pieces</p>
+              </div>
+            </a>
+          </td>
+          <td class="stack" width="25%" valign="top" align="center" style="padding: 0 4px;">
+            <a href="https://designerwallcoverings.com/search?q=scalamandre+sphere+pillow" target="_blank" style="text-decoration:none;">
+              <div style="background:#f4f1ec; padding: 38px 0; border:1px solid #e8e2d6;">
+                <p class="cat-label" style="font-family: Helvetica, Arial, sans-serif; font-size: 12px; letter-spacing: 2px; text-transform: uppercase; color: #1a1a1a; margin: 0;">Sphere</p>
+                <p class="cat-count" style="font-family: Helvetica, Arial, sans-serif; font-size: 10px; letter-spacing: 1.5px; text-transform: uppercase; color: #8d8478; margin: 6px 0 0;">65 Pieces</p>
+              </div>
+            </a>
+          </td>
+        </tr>
+      </table>
+
+      <p style="font-family: Helvetica, Arial, sans-serif; font-size: 10px; letter-spacing: 3px; text-transform: uppercase; color: #8d8478; margin: 44px 0 4px;">Shop by</p>
+      <p style="font-family: Georgia, serif; font-size: 22px; color: #1a1a1a; margin: 0 0 28px;">Style</p>
+      <table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0">
+        <tr>
+          <td class="stack" width="33%" valign="top" align="center" style="padding: 0 4px;">
+            <a href="https://designerwallcoverings.com/search?q=scalamandre+pillow+velvet" target="_blank" style="text-decoration:none;">
+              <div style="background:#f4f1ec; padding: 32px 0; border:1px solid #e8e2d6;">
+                <p class="cat-label" style="font-family: Helvetica, Arial, sans-serif; font-size: 12px; letter-spacing: 2px; text-transform: uppercase; color: #1a1a1a; margin: 0;">Velvet</p>
+              </div>
+            </a>
+          </td>
+          <td class="stack" width="33%" valign="top" align="center" style="padding: 0 4px;">
+            <a href="https://designerwallcoverings.com/search?q=scalamandre+pillow+linen" target="_blank" style="text-decoration:none;">
+              <div style="background:#f4f1ec; padding: 32px 0; border:1px solid #e8e2d6;">
+                <p class="cat-label" style="font-family: Helvetica, Arial, sans-serif; font-size: 12px; letter-spacing: 2px; text-transform: uppercase; color: #1a1a1a; margin: 0;">Linen</p>
+              </div>
+            </a>
+          </td>
+          <td class="stack" width="33%" valign="top" align="center" style="padding: 0 4px;">
+            <a href="https://designerwallcoverings.com/search?q=scalamandre+pillow+silk" target="_blank" style="text-decoration:none;">
+              <div style="background:#f4f1ec; padding: 32px 0; border:1px solid #e8e2d6;">
+                <p class="cat-label" style="font-family: Helvetica, Arial, sans-serif; font-size: 12px; letter-spacing: 2px; text-transform: uppercase; color: #1a1a1a; margin: 0;">Silk</p>
+              </div>
+            </a>
+          </td>
+        </tr>
+      </table>
+    </td></tr>
+
+    <!-- ============ CLOSING CTA ============ -->
+    <tr><td align="center" style="padding: 48px 36px 24px; border-top: 1px solid #e8e2d6;">
+      <p style="font-family: Georgia, serif; font-size: 14px; line-height: 22px; color: #5a544c; margin: 0;">
+        Every pattern available in your choice of <em>square, lumbar, bolster, or sphere</em>.<br>
+        Memo samples on request. Trade pricing available with verified account.
+      </p>
+      <p style="margin: 24px 0 0;">
+        <a href="https://designerwallcoverings.com/search?q=scalamandre+pillow" target="_blank" class="cta-btn" style="display:inline-block; padding:14px 36px; background:#1a1a1a; color:#ffffff; font-family: Helvetica, Arial, sans-serif; font-size:11px; letter-spacing:3px; text-transform:uppercase; text-decoration:none;">Browse All 1,500+</a>
+      </p>
+    </td></tr>
+
+    <!-- ============ FOOTER ============ -->
+    <tr><td align="center" style="padding: 32px 36px; background: #f4f1ec; border-top: 1px solid #e8e2d6;">
+      <p class="footer-text" style="font-family: Helvetica, Arial, sans-serif; font-size: 11px; line-height: 18px; color: #8d8478; margin: 0 0 8px;">
+        <strong style="color:#5a544c; letter-spacing: 1px;">DESIGNER WALLCOVERINGS</strong><br>
+        15442 Ventura Boulevard #102 · Sherman Oaks, CA 91403<br>
+        steve@designerwallcoverings.com · designerwallcoverings.com
+      </p>
+      <p class="footer-text" style="font-family: Helvetica, Arial, sans-serif; font-size: 10px; line-height: 16px; color: #8d8478; margin: 16px 0 0;">
+        You're receiving this email because you've shopped or registered with Designer Wallcoverings.<br>
+        <a href="{{unsubscribe_url}}" style="color:#8d8478; text-decoration: underline;">Unsubscribe</a> ·
+        <a href="{{update_preferences_url}}" style="color:#8d8478; text-decoration: underline;">Update preferences</a>
+      </p>
+    </td></tr>
+
+  </table>
+  <!-- ============ /CONTAINER ============ -->
+
+</td></tr>
+</table>
+</body>
+</html>
diff --git a/mockups/.gitignore b/mockups/.gitignore
new file mode 100644
index 00000000..7e6a9c3e
--- /dev/null
+++ b/mockups/.gitignore
@@ -0,0 +1,12 @@
+node_modules/
+.env
+.env.local
+.env.*.local
+.env.*
+tmp/
+*.log
+.DS_Store
+dist/
+build/
+.next/
+*.bak
diff --git a/output/.gitignore b/output/.gitignore
new file mode 100644
index 00000000..7e6a9c3e
--- /dev/null
+++ b/output/.gitignore
@@ -0,0 +1,12 @@
+node_modules/
+.env
+.env.local
+.env.*.local
+.env.*
+tmp/
+*.log
+.DS_Store
+dist/
+build/
+.next/
+*.bak
diff --git a/output/us-007-implementation-summary.md b/output/us-007-implementation-summary.md
index 0629ee2a..5c55b9c9 100644
--- a/output/us-007-implementation-summary.md
+++ b/output/us-007-implementation-summary.md
@@ -220,7 +220,7 @@ Generate Quality Summary Report
 
 ## Technical Notes
 
-- **Gemini API Key**: REDACTED_GEMINI_KEY
+- **Gemini API Key**: ${GOOGLE_API_KEY}
 - **Model**: gemini-2.0-flash (fast, cost-effective)
 - **Temperature**: 0.1 (consistent, deterministic results)
 - **Max Tokens**: 800 (sufficient for detailed analysis)
diff --git a/scripts/.gitignore b/scripts/.gitignore
new file mode 100644
index 00000000..7e6a9c3e
--- /dev/null
+++ b/scripts/.gitignore
@@ -0,0 +1,12 @@
+node_modules/
+.env
+.env.local
+.env.*.local
+.env.*
+tmp/
+*.log
+.DS_Store
+dist/
+build/
+.next/
+*.bak
diff --git a/scripts/US-007-USAGE.md b/scripts/US-007-USAGE.md
index 3936a8ac..145cbb30 100644
--- a/scripts/US-007-USAGE.md
+++ b/scripts/US-007-USAGE.md
@@ -83,7 +83,7 @@ If AI analysis fails:
 
 ### Gemini 3.0 Configuration
 - **Endpoint**: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent
-- **API Key**: REDACTED_GEMINI_KEY
+- **API Key**: ${GOOGLE_API_KEY}
 - **Model**: gemini-2.0-flash
 - **Temperature**: 0.1 (consistent results)
 - **Max Tokens**: 800
diff --git a/scripts/activate-koroseal-product.js b/scripts/activate-koroseal-product.js
index a61a84a9..ea98a25b 100755
--- a/scripts/activate-koroseal-product.js
+++ b/scripts/activate-koroseal-product.js
@@ -9,7 +9,7 @@ const fs = require('fs');
 
 const SHOPIFY_TOKEN = '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';
 const SHOPIFY_SHOP = 'designer-laboratory-sandbox.myshopify.com';
-const SLACK_BOT_TOKEN = 'xoxb-3958182050256-9814366234406-HiR1ybK6HT8JViWDEpjXpmsq';
+const SLACK_BOT_TOKEN = '${SLACK_BOT_TOKEN}';
 const SLACK_CHANNEL = 'C09SW7VQ0RK';
 const PROGRESS_FILE = '/root/Projects/Designer-Wallcoverings/scripts/koroseal-activation-progress.json';
 
diff --git a/scripts/ai-enrich-arte-gaps.js b/scripts/ai-enrich-arte-gaps.js
index 6d97132a..951faa97 100644
--- a/scripts/ai-enrich-arte-gaps.js
+++ b/scripts/ai-enrich-arte-gaps.js
@@ -7,7 +7,7 @@
 
 const { Client } = require('pg');
 
-const GEMINI_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_KEY = '${GOOGLE_API_KEY}';
 const GEMINI_URL = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${GEMINI_KEY}`;
 
 const PROMPT = `You are an interior design product analyst. Analyze this wallcovering product image and return a JSON object with these fields:
diff --git a/scripts/ai-enrich-gaps.js b/scripts/ai-enrich-gaps.js
index cba17173..94a5303e 100644
--- a/scripts/ai-enrich-gaps.js
+++ b/scripts/ai-enrich-gaps.js
@@ -9,7 +9,7 @@
 
 const { Client } = require('pg');
 
-const GEMINI_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_KEY = '${GOOGLE_API_KEY}';
 const GEMINI_URL = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${GEMINI_KEY}`;
 
 const PROMPT = `You are an interior design product analyst. Analyze this wallcovering product image and return a JSON object with these fields:
diff --git a/scripts/batch-room-generator.py b/scripts/batch-room-generator.py
index 32ddcb96..089b0d1a 100644
--- a/scripts/batch-room-generator.py
+++ b/scripts/batch-room-generator.py
@@ -27,7 +27,7 @@ ROOM_APP_URL = "http://localhost:3075/api/generate-room"
 SHOPIFY_DOMAIN = "designer-laboratory-sandbox.myshopify.com"
 SHOPIFY_TOKEN = "***REMOVED***"
 SHOPIFY_API_VER = "2024-10"
-SLACK_WEBHOOK = "https://hooks.slack.com/services/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"
+SLACK_WEBHOOK = "${SLACK_WEBHOOK_URL}"
 
 COMMERCIAL_VENDORS = {
     "koroseal", "york_contract", "knoll", "designtex", "versa",
diff --git a/scripts/batch-room-settings.py b/scripts/batch-room-settings.py
index 41f36b83..f127160d 100644
--- a/scripts/batch-room-settings.py
+++ b/scripts/batch-room-settings.py
@@ -21,7 +21,7 @@ DB_URL = "postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified"
 ROOM_API = "http://localhost:3075/api/generate-room"
 SHOPIFY_STORE = "designer-laboratory-sandbox.myshopify.com"
 SHOPIFY_TOKEN = "***REMOVED***"
-SLACK_WEBHOOK = "https://hooks.slack.com/services/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"
+SLACK_WEBHOOK = "${SLACK_WEBHOOK_URL}"
 
 BATCH_SIZE = 500
 DELAY_BETWEEN_ROOMS = 4  # seconds between Gemini calls
diff --git a/scripts/brand-mckenzie-ai-analysis.ts b/scripts/brand-mckenzie-ai-analysis.ts
index 9958f991..8a117d44 100644
--- a/scripts/brand-mckenzie-ai-analysis.ts
+++ b/scripts/brand-mckenzie-ai-analysis.ts
@@ -8,7 +8,7 @@ import 'dotenv/config';
 
 const SHOPIFY_STORE = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_TOKEN = process.env.SHOPIFY_ADMIN_ACCESS_TOKEN || '***REMOVED***';
-const GEMINI_API_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_API_KEY = '${GOOGLE_API_KEY}';
 
 interface AIAnalysis {
   backgroundColor: string;
diff --git a/scripts/brand-mckenzie-full-scrape.ts b/scripts/brand-mckenzie-full-scrape.ts
index a87b9075..492b19f0 100644
--- a/scripts/brand-mckenzie-full-scrape.ts
+++ b/scripts/brand-mckenzie-full-scrape.ts
@@ -9,7 +9,7 @@ import { Pool } from 'pg';
 
 const SHOPIFY_STORE = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_TOKEN = process.env.SHOPIFY_ADMIN_ACCESS_TOKEN || '***REMOVED***';
-const GEMINI_API_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_API_KEY = '${GOOGLE_API_KEY}';
 
 // PostgreSQL connection
 const pool = new Pool({
diff --git a/scripts/brand-mckenzie-full-update.ts b/scripts/brand-mckenzie-full-update.ts
index 42e7c982..5f2e2b80 100644
--- a/scripts/brand-mckenzie-full-update.ts
+++ b/scripts/brand-mckenzie-full-update.ts
@@ -13,7 +13,7 @@ import puppeteer from 'puppeteer';
 
 const SHOPIFY_STORE = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_TOKEN = process.env.SHOPIFY_ADMIN_ACCESS_TOKEN || '***REMOVED***';
-const GEMINI_API_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_API_KEY = '${GOOGLE_API_KEY}';
 
 // Known Brand McKenzie collections
 const COLLECTIONS = [
diff --git a/scripts/build-collections-directory.js b/scripts/build-collections-directory.js
index ba3d7dcf..d57706bd 100644
--- a/scripts/build-collections-directory.js
+++ b/scripts/build-collections-directory.js
@@ -14,7 +14,7 @@ const PAGES_TOKEN = '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';
 const API_VERSION = '2024-10';
 const DELAY_MS = 1050;
 
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
 // ─── Category definitions with display order ───
 const CATEGORIES = [
diff --git a/scripts/collection-consolidation-phase2.js b/scripts/collection-consolidation-phase2.js
index cbc48be5..8866d06c 100644
--- a/scripts/collection-consolidation-phase2.js
+++ b/scripts/collection-consolidation-phase2.js
@@ -16,7 +16,7 @@ const API_VERSION = '2024-07';
 const COLLECTIONS_API = 'http://localhost:9501/api/collections';
 const AUTH = Buffer.from('admin:***REMOVED***').toString('base64');
 const RATE_LIMIT_MS = 650;
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
 // Load pattern names from file
 const patternNames = new Set(
diff --git a/scripts/collection-description-writer.js b/scripts/collection-description-writer.js
index ae2908b0..824bfc40 100644
--- a/scripts/collection-description-writer.js
+++ b/scripts/collection-description-writer.js
@@ -10,7 +10,7 @@ const fs = require('fs');
 
 const SHOPIFY_TOKEN = '***REMOVED***';
 const SHOPIFY_DOMAIN = 'designer-laboratory-sandbox.myshopify.com';
-const GEMINI_API_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_API_KEY = '${GOOGLE_API_KEY}';
 const GEMINI_MODEL = 'gemini-2.0-flash';
 
 const INPUT_FILE = '/tmp/needs_descriptions.json';
diff --git a/scripts/collections-cover-images.js b/scripts/collections-cover-images.js
index 8256f17b..66d66a39 100644
--- a/scripts/collections-cover-images.js
+++ b/scripts/collections-cover-images.js
@@ -378,7 +378,7 @@ async function main() {
     `• Duration: ${Math.floor(duration / 60)}m ${duration % 60}s`;
 
   try {
-    await fetch('https://hooks.slack.com/services/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', {
+    await fetch('${SLACK_WEBHOOK_URL}', {
       method: 'POST',
       headers: { 'Content-Type': 'application/json' },
       body: JSON.stringify({ text: slackMsg })
diff --git a/scripts/enrich-remaining-13.js b/scripts/enrich-remaining-13.js
index 5baa6356..c9720725 100644
--- a/scripts/enrich-remaining-13.js
+++ b/scripts/enrich-remaining-13.js
@@ -13,7 +13,7 @@ const pool = new Pool({
   connectionString: 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified'
 });
 
-const GEMINI_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_KEY = '${GOOGLE_API_KEY}';
 const GEMINI_MODEL = 'gemini-2.0-flash';
 const GEMINI_URL = `https://generativelanguage.googleapis.com/v1beta/models/${GEMINI_MODEL}:generateContent?key=${GEMINI_KEY}`;
 
diff --git a/scripts/feed-room-queue.js b/scripts/feed-room-queue.js
index 81ae97d7..aaac7100 100644
--- a/scripts/feed-room-queue.js
+++ b/scripts/feed-room-queue.js
@@ -18,7 +18,7 @@ const pool = new Pool({
   max: 5,
 });
 
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
 // Vendor configs: catalog table, shopify vendor name, width/repeat columns
 const VENDORS = {
diff --git a/scripts/fix-fabric-wallcovering-v3.js b/scripts/fix-fabric-wallcovering-v3.js
index 1645de16..ad79cf4e 100644
--- a/scripts/fix-fabric-wallcovering-v3.js
+++ b/scripts/fix-fabric-wallcovering-v3.js
@@ -21,7 +21,7 @@ const TOKEN = '***REMOVED***';
 const API_VERSION = '2024-10';
 const DELAY_MS = 500;
 
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
 function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); }
 
diff --git a/scripts/grs-image-crop.js b/scripts/grs-image-crop.js
index 82a396f2..dd880a89 100644
--- a/scripts/grs-image-crop.js
+++ b/scripts/grs-image-crop.js
@@ -16,7 +16,7 @@ const SHOPIFY_STORE = 'designer-laboratory-sandbox.myshopify.com';
 const ACCESS_TOKEN = '***REMOVED***';
 const API_VERSION = '2024-01';
 const REST_BASE = `https://${SHOPIFY_STORE}/admin/api/${API_VERSION}`;
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
 const TEMP_DIR = '/tmp/grs-crops';
 const LOG_FILE = '/tmp/grs-crop-progress.log';
diff --git a/scripts/import-fmpro-to-postgres.js b/scripts/import-fmpro-to-postgres.js
index b61ce01f..3c9f0106 100644
--- a/scripts/import-fmpro-to-postgres.js
+++ b/scripts/import-fmpro-to-postgres.js
@@ -103,7 +103,7 @@ async function run() {
   console.log(`   Duration: ${Math.round((Date.now() - startTime) / 1000)}s`);
 
   // Slack
-  fetch('https://hooks.slack.com/services/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', {
+  fetch('${SLACK_WEBHOOK_URL}', {
     method: 'POST', headers: { 'Content-Type': 'application/json' },
     body: JSON.stringify({ text: `✅ *FMPro Import*: ${s.crossref} records, ${s.matched} Shopify matches, ${updateResult.rowCount} updated, ${pct}% coverage` })
   }).catch(() => {});
diff --git a/scripts/interior-design-tags.js b/scripts/interior-design-tags.js
index 9f34c00b..7e7a51b4 100644
--- a/scripts/interior-design-tags.js
+++ b/scripts/interior-design-tags.js
@@ -25,14 +25,14 @@ const https = require('https');
 const http = require('http');
 
 // ─── Config ────────────────────────────────────────────────────────────────────
-const GEMINI_API_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_API_KEY = '${GOOGLE_API_KEY}';
 const GEMINI_URL = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${GEMINI_API_KEY}`;
 
 const SHOPIFY_DOMAIN = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_TOKEN = '***REMOVED***';
 const SHOPIFY_API_VERSION = '2024-10';
 
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
 const pool = new Pool({
   connectionString: 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified',
diff --git a/scripts/justindavid-daily-cron.sh b/scripts/justindavid-daily-cron.sh
index 80fa3b16..227b5144 100755
--- a/scripts/justindavid-daily-cron.sh
+++ b/scripts/justindavid-daily-cron.sh
@@ -5,7 +5,7 @@
 
 SCRIPT_DIR="/root/Projects/Designer-Wallcoverings/scripts"
 LOG="/tmp/justindavid-roomsettings-$(date +%Y%m%d).log"
-SLACK_WEBHOOK="https://hooks.slack.com/services/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"
+SLACK_WEBHOOK="${SLACK_WEBHOOK_URL}"
 
 echo "=== JustinDavid Room Settings $(date) ===" >> "$LOG"
 
diff --git a/scripts/justindavid-room-settings.js b/scripts/justindavid-room-settings.js
index 07e3178b..d7dc5fa0 100644
--- a/scripts/justindavid-room-settings.js
+++ b/scripts/justindavid-room-settings.js
@@ -20,7 +20,7 @@ const pool = new Pool({
   connectionString: "postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified",
 });
 
-const GEMINI_KEY = "REDACTED_GEMINI_KEY";
+const GEMINI_KEY = "${GOOGLE_API_KEY}";
 const IMAGEN_MODEL = "imagen-4.0-generate-001";
 
 const BASE_DIR = "/root/Projects/Designer-Wallcoverings/room-settings/justindavid";
diff --git a/scripts/kill-wallpaper-word.js b/scripts/kill-wallpaper-word.js
index 00f4818e..7dca7c79 100644
--- a/scripts/kill-wallpaper-word.js
+++ b/scripts/kill-wallpaper-word.js
@@ -15,7 +15,7 @@ const { Client } = require('pg');
 const SHOPIFY_STORE = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_TOKEN = '***REMOVED***';
 const PG_URI = 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified';
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
 const DELAY_MS = 350; // between GraphQL mutations
 const BODY_DELAY_MS = 500; // slower for body_html (larger payloads)
diff --git a/scripts/koroseal-architectural-bulk-update.js b/scripts/koroseal-architectural-bulk-update.js
index cfda31f5..7545a9c4 100644
--- a/scripts/koroseal-architectural-bulk-update.js
+++ b/scripts/koroseal-architectural-bulk-update.js
@@ -14,7 +14,7 @@ const shopify = new Shopify({
   apiVersion: '2024-01'
 });
 
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 const SEO_PREFIX = 'Architectural wallcoverings for commercial and high-end interiors. Specification-grade materials from your one stop resource for over 20 years. ';
 const TARGET_TYPE = 'Architectural Wallcoverings';
 const TARGET_CATEGORY = 'Home & Garden > Building Materials';
diff --git a/scripts/lib/slack-progress-notify.ts b/scripts/lib/slack-progress-notify.ts
index 282310c8..1181be8c 100644
--- a/scripts/lib/slack-progress-notify.ts
+++ b/scripts/lib/slack-progress-notify.ts
@@ -5,7 +5,7 @@
 
 import { WebClient } from '@slack/web-api';
 
-const SLACK_BOT_TOKEN = process.env.SLACK_BOT_TOKEN || 'xoxb-3958182050256-9814366234406-HiR1ybK6HT8JViWDEpjXpmsq';
+const SLACK_BOT_TOKEN = process.env.SLACK_BOT_TOKEN || '${SLACK_BOT_TOKEN}';
 const STEVE_CHANNEL = '#claude-to-steve';
 
 let client: WebClient | null = null;
diff --git a/scripts/mfr-sku-bulk-update.js b/scripts/mfr-sku-bulk-update.js
index d7dc8924..3a982527 100755
--- a/scripts/mfr-sku-bulk-update.js
+++ b/scripts/mfr-sku-bulk-update.js
@@ -131,7 +131,7 @@ async function run() {
   
   // Send Slack notification
   try {
-    await fetch('https://hooks.slack.com/services/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', {
+    await fetch('${SLACK_WEBHOOK_URL}', {
       method: 'POST',
       headers: { 'Content-Type': 'application/json' },
       body: JSON.stringify({
diff --git a/scripts/ncw-cleanup/audit-as-dedupe-2026-05-06T18-38-04.json b/scripts/ncw-cleanup/audit-as-dedupe-2026-05-06T18-38-04.json
new file mode 100644
index 00000000..9beab3d5
--- /dev/null
+++ b/scripts/ncw-cleanup/audit-as-dedupe-2026-05-06T18-38-04.json
@@ -0,0 +1,126 @@
+{
+  "archived": 20,
+  "errors": 0,
+  "audit": [
+    {
+      "ok": true,
+      "sku": "DWAC-1010004-Sample",
+      "archived_id": "gid://shopify/Product/7817249783859",
+      "kept_id": "gid://shopify/Product/7817941876787"
+    },
+    {
+      "ok": true,
+      "sku": "DWAC-1011628-Sample",
+      "archived_id": "gid://shopify/Product/7817249488947",
+      "kept_id": "gid://shopify/Product/7817941319731"
+    },
+    {
+      "ok": true,
+      "sku": "DWAC-1011653-Sample",
+      "archived_id": "gid://shopify/Product/7817249554483",
+      "kept_id": "gid://shopify/Product/7817941385267"
+    },
+    {
+      "ok": true,
+      "sku": "DWAC-1011657-Sample",
+      "archived_id": "gid://shopify/Product/7817249587251",
+      "kept_id": "gid://shopify/Product/7817941516339"
+    },
+    {
+      "ok": true,
+      "sku": "DWAC-1011662-Sample",
+      "archived_id": "gid://shopify/Product/7817249620019",
+      "kept_id": "gid://shopify/Product/7817941549107"
+    },
+    {
+      "ok": true,
+      "sku": "DWAC-1011684-Sample",
+      "archived_id": "gid://shopify/Product/7817249718323",
+      "kept_id": "gid://shopify/Product/7817941712947"
+    },
+    {
+      "ok": true,
+      "sku": "DWAC-1011691-Sample",
+      "archived_id": "gid://shopify/Product/7817249751091",
+      "kept_id": "gid://shopify/Product/7817941844019"
+    },
+    {
+      "ok": true,
+      "sku": "DWAC-1014613-Sample",
+      "archived_id": "gid://shopify/Product/7817249685555",
+      "kept_id": "gid://shopify/Product/7817941647411"
+    },
+    {
+      "ok": true,
+      "sku": "DWAC-1014903-Sample",
+      "archived_id": "gid://shopify/Product/7817249128499",
+      "kept_id": "gid://shopify/Product/7817940795443"
+    },
+    {
+      "ok": true,
+      "sku": "DWAC-1014904-Sample",
+      "archived_id": "gid://shopify/Product/7817249161267",
+      "kept_id": "gid://shopify/Product/7817940828211"
+    },
+    {
+      "ok": true,
+      "sku": "DWAC-1014906-Sample",
+      "archived_id": "gid://shopify/Product/7817249226803",
+      "kept_id": "gid://shopify/Product/7817940959283"
+    },
+    {
+      "ok": true,
+      "sku": "DWAC-1014912-Sample",
+      "archived_id": "gid://shopify/Product/7817249259571",
+      "kept_id": "gid://shopify/Product/7817941024819"
+    },
+    {
+      "ok": true,
+      "sku": "DWAC-1014923-Sample",
+      "archived_id": "gid://shopify/Product/7817249292339",
+      "kept_id": "gid://shopify/Product/7817941090355"
+    },
+    {
+      "ok": true,
+      "sku": "DWAC-1014925-Sample",
+      "archived_id": "gid://shopify/Product/7817249325107",
+      "kept_id": "gid://shopify/Product/7817940762675"
+    },
+    {
+      "ok": true,
+      "sku": "DWAC-1014926-Sample",
+      "archived_id": "gid://shopify/Product/7817249357875",
+      "kept_id": "gid://shopify/Product/7817941188659"
+    },
+    {
+      "ok": true,
+      "sku": "DWAC-1015437-Sample",
+      "archived_id": "gid://shopify/Product/7817249390643",
+      "kept_id": "gid://shopify/Product/7817941221427"
+    },
+    {
+      "ok": true,
+      "sku": "DWAC-1015556-Sample",
+      "archived_id": "gid://shopify/Product/7817249423411",
+      "kept_id": "gid://shopify/Product/7817941254195"
+    },
+    {
+      "ok": true,
+      "sku": "DWAC-1015607-Sample",
+      "archived_id": "gid://shopify/Product/7817249456179",
+      "kept_id": "gid://shopify/Product/7817941286963"
+    },
+    {
+      "ok": true,
+      "sku": "DWAC-1015949-Sample",
+      "archived_id": "gid://shopify/Product/7817249652787",
+      "kept_id": "gid://shopify/Product/7817941581875"
+    },
+    {
+      "ok": true,
+      "sku": "DWAC-1016019-Sample",
+      "archived_id": "gid://shopify/Product/7817248112691",
+      "kept_id": "gid://shopify/Product/7817940729907"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/scripts/ncw-cleanup/audit-pr-dedupe-2026-05-06T17-59-26.json b/scripts/ncw-cleanup/audit-pr-dedupe-2026-05-06T17-59-26.json
new file mode 100644
index 00000000..e684531f
--- /dev/null
+++ b/scripts/ncw-cleanup/audit-pr-dedupe-2026-05-06T17-59-26.json
@@ -0,0 +1,330 @@
+{
+  "archived": 54,
+  "errors": 0,
+  "audit": [
+    {
+      "ok": true,
+      "sku": "DWPR-426700",
+      "archived_id": "gid://shopify/Product/7792235380787",
+      "kept_id": "gid://shopify/Product/7791173599283"
+    },
+    {
+      "ok": true,
+      "sku": "DWPR-426705",
+      "archived_id": "gid://shopify/Product/7792235577395",
+      "kept_id": "gid://shopify/Product/7791174320179"
+    },
+    {
+      "ok": true,
+      "sku": "DWPR-426706",
+      "archived_id": "gid://shopify/Product/7792235642931",
+      "kept_id": "gid://shopify/Product/7791174352947"
+    },
+    {
+      "ok": true,
+      "sku": "DWPR-426711",
+      "archived_id": "gid://shopify/Product/7792235839539",
+      "kept_id": "gid://shopify/Product/7791174516787"
+    },
+    {
+      "ok": true,
+      "sku": "DWPR-426716",
+      "archived_id": "gid://shopify/Product/7792236036147",
+      "kept_id": "gid://shopify/Product/7791174680627"
+    },
+    {
+      "ok": true,
+      "sku": "DWPR-426717",
+      "archived_id": "gid://shopify/Product/7792236068915",
+      "kept_id": "gid://shopify/Product/7791174713395"
+    },
+    {
+      "ok": true,
+      "sku": "DWPR-426724",
+      "archived_id": "gid://shopify/Product/7792236396595",
+      "kept_id": "gid://shopify/Product/7791175106611"
+    },
+    {
+      "ok": true,
+      "sku": "DWPR-426733",
+      "archived_id": "gid://shopify/Product/7792236429363",
+      "kept_id": "gid://shopify/Product/7791175204915"
+    },
+    {
+      "ok": true,
+      "sku": "DWPR-426743",
+      "archived_id": "gid://shopify/Product/7792236789811",
+      "kept_id": "gid://shopify/Product/7791175565363"
+    },
+    {
+      "ok": true,
+      "sku": "DWPR-426815",
+      "archived_id": "gid://shopify/Product/7792237084723",
+      "kept_id": "gid://shopify/Product/7791177465907"
+    },
+    {
+      "ok": true,
+      "sku": "DWPR-426816",
+      "archived_id": "gid://shopify/Product/7792237117491",
+      "kept_id": "gid://shopify/Product/7791177629747"
+    },
+    {
+      "ok": true,
+      "sku": "DWPR-426825",
+      "archived_id": "gid://shopify/Product/7792237412403",
+      "kept_id": "gid://shopify/Product/7791178842163"
+    },
+    {
+      "ok": true,
+      "sku": "DWPR-426827",
+      "archived_id": "gid://shopify/Product/7792237477939",
+      "kept_id": "gid://shopify/Product/7791179137075"
+    },
+    {
+      "ok": true,
+      "sku": "DWPX-500051-Sample",
+      "archived_id": "gid://shopify/Product/7813312544819",
+      "kept_id": "gid://shopify/Product/7813310971955"
+    },
+    {
+      "ok": true,
+      "sku": "DWPX-500052-Sample",
+      "archived_id": "gid://shopify/Product/7813312577587",
+      "kept_id": "gid://shopify/Product/7813311004723"
+    },
+    {
+      "ok": true,
+      "sku": "DWPX-500053-Sample",
+      "archived_id": "gid://shopify/Product/7813312610355",
+      "kept_id": "gid://shopify/Product/7813311037491"
+    },
+    {
+      "ok": true,
+      "sku": "DWPX-500054-Sample",
+      "archived_id": "gid://shopify/Product/7813312643123",
+      "kept_id": "gid://shopify/Product/7813311070259"
+    },
+    {
+      "ok": true,
+      "sku": "DWPX-500055-Sample",
+      "archived_id": "gid://shopify/Product/7813312675891",
+      "kept_id": "gid://shopify/Product/7813311103027"
+    },
+    {
+      "ok": true,
+      "sku": "DWPX-500056-Sample",
+      "archived_id": "gid://shopify/Product/7813312708659",
+      "kept_id": "gid://shopify/Product/7813311135795"
+    },
+    {
+      "ok": true,
+      "sku": "DWPX-500057-Sample",
+      "archived_id": "gid://shopify/Product/7813312741427",
+      "kept_id": "gid://shopify/Product/7813311168563"
+    },
+    {
+      "ok": true,
+      "sku": "DWPX-500058-Sample",
+      "archived_id": "gid://shopify/Product/7813312872499",
+      "kept_id": "gid://shopify/Product/7813311201331"
+    },
+    {
+      "ok": true,
+      "sku": "DWPX-500059-Sample",
+      "archived_id": "gid://shopify/Product/7813312970803",
+      "kept_id": "gid://shopify/Product/7813311234099"
+    },
+    {
+      "ok": true,
+      "sku": "DWPX-500060-Sample",
+      "archived_id": "gid://shopify/Product/7813313069107",
+      "kept_id": "gid://shopify/Product/7813311266867"
+    },
+    {
+      "ok": true,
+      "sku": "DWPX-500061-Sample",
+      "archived_id": "gid://shopify/Product/7813313167411",
+      "kept_id": "gid://shopify/Product/7813311299635"
+    },
+    {
+      "ok": true,
+      "sku": "DWPX-500062-Sample",
+      "archived_id": "gid://shopify/Product/7813313298483",
+      "kept_id": "gid://shopify/Product/7813311365171"
+    },
+    {
+      "ok": true,
+      "sku": "DWPX-500063-Sample",
+      "archived_id": "gid://shopify/Product/7813313429555",
+      "kept_id": "gid://shopify/Product/7813311397939"
+    },
+    {
+      "ok": true,
+      "sku": "DWPX-500064-Sample",
+      "archived_id": "gid://shopify/Product/7813313560627",
+      "kept_id": "gid://shopify/Product/7813311430707"
+    },
+    {
+      "ok": true,
+      "sku": "DWPX-500065-Sample",
+      "archived_id": "gid://shopify/Product/7813313658931",
+      "kept_id": "gid://shopify/Product/7813311463475"
+    },
+    {
+      "ok": true,
+      "sku": "DWPX-500066-Sample",
+      "archived_id": "gid://shopify/Product/7813313757235",
+      "kept_id": "gid://shopify/Product/7813311496243"
+    },
+    {
+      "ok": true,
+      "sku": "DWPX-500067-Sample",
+      "archived_id": "gid://shopify/Product/7813313790003",
+      "kept_id": "gid://shopify/Product/7813311529011"
+    },
+    {
+      "ok": true,
+      "sku": "DWPX-500068-Sample",
+      "archived_id": "gid://shopify/Product/7813313822771",
+      "kept_id": "gid://shopify/Product/7813311561779"
+    },
+    {
+      "ok": true,
+      "sku": "DWPX-500069-Sample",
+      "archived_id": "gid://shopify/Product/7813313855539",
+      "kept_id": "gid://shopify/Product/7813311594547"
+    },
+    {
+      "ok": true,
+      "sku": "DWPX-500070-Sample",
+      "archived_id": "gid://shopify/Product/7813313888307",
+      "kept_id": "gid://shopify/Product/7813311627315"
+    },
+    {
+      "ok": true,
+      "sku": "DWPX-500071-Sample",
+      "archived_id": "gid://shopify/Product/7813313921075",
+      "kept_id": "gid://shopify/Product/7813311660083"
+    },
+    {
+      "ok": true,
+      "sku": "DWPX-500072-Sample",
+      "archived_id": "gid://shopify/Product/7813313953843",
+      "kept_id": "gid://shopify/Product/7813311692851"
+    },
+    {
+      "ok": true,
+      "sku": "DWPX-500073-Sample",
+      "archived_id": "gid://shopify/Product/7813313986611",
+      "kept_id": "gid://shopify/Product/7813311725619"
+    },
+    {
+      "ok": true,
+      "sku": "DWPX-500074-Sample",
+      "archived_id": "gid://shopify/Product/7813314019379",
+      "kept_id": "gid://shopify/Product/7813311758387"
+    },
+    {
+      "ok": true,
+      "sku": "DWPX-500075-Sample",
+      "archived_id": "gid://shopify/Product/7813314052147",
+      "kept_id": "gid://shopify/Product/7813311791155"
+    },
+    {
+      "ok": true,
+      "sku": "DWPX-500076-Sample",
+      "archived_id": "gid://shopify/Product/7813314084915",
+      "kept_id": "gid://shopify/Product/7813311823923"
+    },
+    {
+      "ok": true,
+      "sku": "DWPX-500077-Sample",
+      "archived_id": "gid://shopify/Product/7813314117683",
+      "kept_id": "gid://shopify/Product/7813311856691"
+    },
+    {
+      "ok": true,
+      "sku": "DWPX-500078-Sample",
+      "archived_id": "gid://shopify/Product/7813314150451",
+      "kept_id": "gid://shopify/Product/7813311889459"
+    },
+    {
+      "ok": true,
+      "sku": "DWPX-500079-Sample",
+      "archived_id": "gid://shopify/Product/7813314183219",
+      "kept_id": "gid://shopify/Product/7813311922227"
+    },
+    {
+      "ok": true,
+      "sku": "DWPX-500080-Sample",
+      "archived_id": "gid://shopify/Product/7813314215987",
+      "kept_id": "gid://shopify/Product/7813311954995"
+    },
+    {
+      "ok": true,
+      "sku": "DWPX-500081-Sample",
+      "archived_id": "gid://shopify/Product/7813314281523",
+      "kept_id": "gid://shopify/Product/7813311987763"
+    },
+    {
+      "ok": true,
+      "sku": "DWPX-500082-Sample",
+      "archived_id": "gid://shopify/Product/7813314314291",
+      "kept_id": "gid://shopify/Product/7813312020531"
+    },
+    {
+      "ok": true,
+      "sku": "DWPX-500083-Sample",
+      "archived_id": "gid://shopify/Product/7813314347059",
+      "kept_id": "gid://shopify/Product/7813312053299"
+    },
+    {
+      "ok": true,
+      "sku": "DWPX-500084-Sample",
+      "archived_id": "gid://shopify/Product/7813314379827",
+      "kept_id": "gid://shopify/Product/7813312086067"
+    },
+    {
+      "ok": true,
+      "sku": "DWPX-500085-Sample",
+      "archived_id": "gid://shopify/Product/7813314412595",
+      "kept_id": "gid://shopify/Product/7813312118835"
+    },
+    {
+      "ok": true,
+      "sku": "DWPX-500086-Sample",
+      "archived_id": "gid://shopify/Product/7813314445363",
+      "kept_id": "gid://shopify/Product/7813312151603"
+    },
+    {
+      "ok": true,
+      "sku": "DWPX-500087-Sample",
+      "archived_id": "gid://shopify/Product/7813314478131",
+      "kept_id": "gid://shopify/Product/7813312184371"
+    },
+    {
+      "ok": true,
+      "sku": "DWPX-500088-Sample",
+      "archived_id": "gid://shopify/Product/7813314510899",
+      "kept_id": "gid://shopify/Product/7813312217139"
+    },
+    {
+      "ok": true,
+      "sku": "DWPX-500089-Sample",
+      "archived_id": "gid://shopify/Product/7813314543667",
+      "kept_id": "gid://shopify/Product/7813312249907"
+    },
+    {
+      "ok": true,
+      "sku": "DWPX-500090-Sample",
+      "archived_id": "gid://shopify/Product/7813314609203",
+      "kept_id": "gid://shopify/Product/7813312282675"
+    },
+    {
+      "ok": true,
+      "sku": "MAD-20015-sample",
+      "archived_id": "gid://shopify/Product/6796637601843",
+      "kept_id": "gid://shopify/Product/4578109882419"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/scripts/ncw-cleanup/audit-rename-2026-05-06T17-35-58.json b/scripts/ncw-cleanup/audit-rename-2026-05-06T17-35-58.json
new file mode 100644
index 00000000..aa957b13
--- /dev/null
+++ b/scripts/ncw-cleanup/audit-rename-2026-05-06T17-35-58.json
@@ -0,0 +1,2094 @@
+{
+  "renamed": 298,
+  "alreadyEur": 20,
+  "missing": 0,
+  "errors": 0,
+  "audit": [
+    {
+      "ok": true,
+      "dw": "EUR-80109",
+      "from": "DWC-NCW4106",
+      "to": "EUR-80109-Sample",
+      "title": "Oakley Hall 5 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80110",
+      "from": "DWC-NCW4107",
+      "to": "EUR-80110-Sample",
+      "title": "Wilmington 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80111",
+      "from": "DWC-NCW4107",
+      "to": "EUR-80111-Sample",
+      "title": "Wilmington 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80112",
+      "from": "DWC-NCW4120",
+      "to": "EUR-80112-Sample",
+      "title": "Holmwood 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80116",
+      "from": "DWC-NCW4121",
+      "to": "EUR-80116-Sample",
+      "title": "Bothwell 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80117",
+      "from": "DWC-NCW4121",
+      "to": "EUR-80117-Sample",
+      "title": "Bothwell 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80118",
+      "from": "DWC-NCW4121",
+      "to": "EUR-80118-Sample",
+      "title": "Bothwell 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80119",
+      "from": "DWC-NCW4121",
+      "to": "EUR-80119-Sample",
+      "title": "Bothwell 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80120",
+      "from": "DWC-NCW4122",
+      "to": "EUR-80120-Sample",
+      "title": "Elcho 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80121",
+      "from": "DWC-NCW4122",
+      "to": "EUR-80121-Sample",
+      "title": "Elcho 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80122",
+      "from": "DWC-NCW4123",
+      "to": "EUR-80122-Sample",
+      "title": "Abbotsford 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80123",
+      "from": "DWC-NCW4123",
+      "to": "EUR-80123-Sample",
+      "title": "Abbotsford 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80124",
+      "from": "DWC-NCW4123",
+      "to": "EUR-80124-Sample",
+      "title": "Abbotsford 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80125",
+      "from": "DWC-NCW4123",
+      "to": "EUR-80125-Sample",
+      "title": "Abbotsford 06 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80126",
+      "from": "DWC-NCW4123",
+      "to": "EUR-80126-Sample",
+      "title": "Abbotsford 07 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80127",
+      "from": "DWC-NCW4125",
+      "to": "EUR-80127-Sample",
+      "title": "Rothesay 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80128",
+      "from": "DWC-NCW4125",
+      "to": "EUR-80128-Sample",
+      "title": "Rothesay 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80129",
+      "from": "DWC-NCW4125",
+      "to": "EUR-80129-Sample",
+      "title": "Rothesay 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80130",
+      "from": "DWC-NCW4126",
+      "to": "EUR-80130-Sample",
+      "title": "Huntly 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80131",
+      "from": "DWC-NCW4126",
+      "to": "EUR-80131-Sample",
+      "title": "Huntly 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80132",
+      "from": "DWC-NCW4126",
+      "to": "EUR-80132-Sample",
+      "title": "Huntly 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80133",
+      "from": "DWC-NCW4126",
+      "to": "EUR-80133-Sample",
+      "title": "Huntly 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80134",
+      "from": "DWC-NCW4126",
+      "to": "EUR-80134-Sample",
+      "title": "Huntly 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80135",
+      "from": "DWC-NCW4126",
+      "to": "EUR-80135-Sample",
+      "title": "Huntly 06 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80136",
+      "from": "DWC-NCW4126",
+      "to": "EUR-80136-Sample",
+      "title": "Huntly 07 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80139",
+      "from": "DWC-NCW4127",
+      "to": "EUR-80139-Sample",
+      "title": "Strome 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80140",
+      "from": "DWC-NCW4127",
+      "to": "EUR-80140-Sample",
+      "title": "Strome 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80141",
+      "from": "DWC-NCW4127",
+      "to": "EUR-80141-Sample",
+      "title": "Strome 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80142",
+      "from": "DWC-NCW4127",
+      "to": "EUR-80142-Sample",
+      "title": "Strome 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80143",
+      "from": "DWC-NCW4150",
+      "to": "EUR-80143-Sample",
+      "title": "Rosslyn 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80144",
+      "from": "DWC-NCW4150",
+      "to": "EUR-80144-Sample",
+      "title": "Rosslyn 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80145",
+      "from": "DWC-NCW4150",
+      "to": "EUR-80145-Sample",
+      "title": "Rosslyn 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80146",
+      "from": "DWC-NCW4150",
+      "to": "EUR-80146-Sample",
+      "title": "Rosslyn 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80147",
+      "from": "DWC-NCW4150",
+      "to": "EUR-80147-Sample",
+      "title": "Rosslyn 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80148",
+      "from": "DWC-NCW4151",
+      "to": "EUR-80148-Sample",
+      "title": "Torosay 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80149",
+      "from": "DWC-NCW4151",
+      "to": "EUR-80149-Sample",
+      "title": "Torosay 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80150",
+      "from": "DWC-NCW4151",
+      "to": "EUR-80150-Sample",
+      "title": "Torosay 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80151",
+      "from": "DWC-NCW4151",
+      "to": "EUR-80151-Sample",
+      "title": "Torosay 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80152",
+      "from": "DWC-NCW4151",
+      "to": "EUR-80152-Sample",
+      "title": "Torosay 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80153",
+      "from": "DWC-NCW4151",
+      "to": "EUR-80153-Sample",
+      "title": "Torosay 06 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80154",
+      "from": "DWC-NCW4152",
+      "to": "EUR-80154-Sample",
+      "title": "Lochwood 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80155",
+      "from": "DWC-NCW4152",
+      "to": "EUR-80155-Sample",
+      "title": "Lochwood 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80156",
+      "from": "DWC-NCW4152",
+      "to": "EUR-80156-Sample",
+      "title": "Lochwood 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80157",
+      "from": "DWC-NCW4152",
+      "to": "EUR-80157-Sample",
+      "title": "Lochwood 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80158",
+      "from": "DWC-NCW4152",
+      "to": "EUR-80158-Sample",
+      "title": "Lochwood 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80159",
+      "from": "DWC-NCW4154",
+      "to": "EUR-80159-Sample",
+      "title": "Mey Fern 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80160",
+      "from": "DWC-NCW4154",
+      "to": "EUR-80160-Sample",
+      "title": "Mey Fern 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80161",
+      "from": "DWC-NCW4154",
+      "to": "EUR-80161-Sample",
+      "title": "Mey Fern 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80162",
+      "from": "DWC-NCW4154",
+      "to": "EUR-80162-Sample",
+      "title": "Mey Fern 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80163",
+      "from": "DWC-NCW4155",
+      "to": "EUR-80163-Sample",
+      "title": "Kelburn 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80164",
+      "from": "DWC-NCW4155",
+      "to": "EUR-80164-Sample",
+      "title": "Kelburn 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80165",
+      "from": "DWC-NCW4155",
+      "to": "EUR-80165-Sample",
+      "title": "Kelburn 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80166",
+      "from": "DWC-NCW4155",
+      "to": "EUR-80166-Sample",
+      "title": "Kelburn 06 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80167",
+      "from": "DWC-NCW4156",
+      "to": "EUR-80167-Sample",
+      "title": "Montrose 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80168",
+      "from": "DWC-NCW4156",
+      "to": "EUR-80168-Sample",
+      "title": "Montrose 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80169",
+      "from": "DWC-NCW4156",
+      "to": "EUR-80169-Sample",
+      "title": "Montrose 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80170",
+      "from": "DWC-NCW4156",
+      "to": "EUR-80170-Sample",
+      "title": "Montrose 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80171",
+      "from": "DWC-NCW4156",
+      "to": "EUR-80171-Sample",
+      "title": "Montrose 06 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80172",
+      "from": "DWC-NCW4180",
+      "to": "EUR-80172-Sample",
+      "title": "Cathay Parade 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80173",
+      "from": "DWC-NCW4180",
+      "to": "EUR-80173-Sample",
+      "title": "Cathay Parade 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80183",
+      "from": "DWC-NCW4182 -01",
+      "to": "EUR-80183-Sample",
+      "title": "Penglai 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80184",
+      "from": "DWC-NCW4182-02",
+      "to": "EUR-80184-Sample",
+      "title": "Penglai 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80185",
+      "from": "DWC-NCW4182/03",
+      "to": "EUR-80185-Sample",
+      "title": "Penglai 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80186",
+      "from": "DWC-NCW4182",
+      "to": "EUR-80186-Sample",
+      "title": "Penglai 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80188",
+      "from": "DWC-NCW4183",
+      "to": "EUR-80188-Sample",
+      "title": "Pamir 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80189",
+      "from": "DWC-NCW4183",
+      "to": "EUR-80189-Sample",
+      "title": "Pamir 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80190",
+      "from": "DWC-NCW4183",
+      "to": "EUR-80190-Sample",
+      "title": "Pamir 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80191",
+      "from": "DWC-NCW4183",
+      "to": "EUR-80191-Sample",
+      "title": "Pamir 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80192",
+      "from": "DWC-NCW4183",
+      "to": "EUR-80192-Sample",
+      "title": "Pamir 06 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80193",
+      "from": "DWC-NCW4183",
+      "to": "EUR-80193-Sample",
+      "title": "Pamir 07 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80195",
+      "from": "DWC-NCW4184",
+      "to": "EUR-80195-Sample",
+      "title": "Suzhou 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80196",
+      "from": "DWC-NCW4184",
+      "to": "EUR-80196-Sample",
+      "title": "Suzhou 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80197",
+      "from": "DWC-NCW4184",
+      "to": "EUR-80197-Sample",
+      "title": "Suzhou 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80198",
+      "from": "DWC-NCW4185",
+      "to": "EUR-80198-Sample",
+      "title": "Mahayana 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80199",
+      "from": "DWC-NCW4185",
+      "to": "EUR-80199-Sample",
+      "title": "Mahayana 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80200",
+      "from": "DWC-NCW4185",
+      "to": "EUR-80200-Sample",
+      "title": "Mahayana 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80201",
+      "from": "DWC-NCW4185",
+      "to": "EUR-80201-Sample",
+      "title": "Mahayana 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80202",
+      "from": "DWC-NCW4185",
+      "to": "EUR-80202-Sample",
+      "title": "Mahayana 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80203",
+      "from": "DWC-NCW4185",
+      "to": "EUR-80203-Sample",
+      "title": "Mahayana 06 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80211",
+      "from": "DWC-NCW4186",
+      "to": "EUR-80211-Sample",
+      "title": "Khitan 08 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80214",
+      "from": "DWC-NCW4186",
+      "to": "EUR-80214-Sample",
+      "title": "Khitan 11 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80216",
+      "from": "DWC-NCW4200",
+      "to": "EUR-80216-Sample",
+      "title": "Keightley's Folio 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80217",
+      "from": "DWC-NCW4200",
+      "to": "EUR-80217-Sample",
+      "title": "Keightley's Folio 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80218",
+      "from": "DWC-NCW4200",
+      "to": "EUR-80218-Sample",
+      "title": "Keightley's Folio 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80219",
+      "from": "DWC-NCW4201",
+      "to": "EUR-80219-Sample",
+      "title": "Belem 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80224",
+      "from": "DWC-NCW4202",
+      "to": "EUR-80224-Sample",
+      "title": "Estella 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80225",
+      "from": "DWC-NCW4202",
+      "to": "EUR-80225-Sample",
+      "title": "Estella 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80226",
+      "from": "DWC-NCW4202",
+      "to": "EUR-80226-Sample",
+      "title": "Estella 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80227",
+      "from": "DWC-NCW4202",
+      "to": "EUR-80227-Sample",
+      "title": "Estella 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80228",
+      "from": "DWC-NCW4202",
+      "to": "EUR-80228-Sample",
+      "title": "Estella 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80229",
+      "from": "DWC-NCW4202",
+      "to": "EUR-80229-Sample",
+      "title": "Estella 06 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80231",
+      "from": "DWC-NCW4204",
+      "to": "EUR-80231-Sample",
+      "title": "Kershaw Plain 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80232",
+      "from": "DWC-NCW4204",
+      "to": "EUR-80232-Sample",
+      "title": "Kershaw Plain 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80233",
+      "from": "DWC-NCW4204",
+      "to": "EUR-80233-Sample",
+      "title": "Kershaw Plain 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80234",
+      "from": "DWC-NCW4204",
+      "to": "EUR-80234-Sample",
+      "title": "Kershaw Plain 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80235",
+      "from": "DWC-NCW4204",
+      "to": "EUR-80235-Sample",
+      "title": "Kershaw Plain 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80236",
+      "from": "DWC-NCW4204",
+      "to": "EUR-80236-Sample",
+      "title": "Kershaw Plain 06 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80237",
+      "from": "DWC-NCW4204",
+      "to": "EUR-80237-Sample",
+      "title": "Kershaw Plain 07 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80239",
+      "from": "DWC-NCW4205",
+      "to": "EUR-80239-Sample",
+      "title": "Barbary Toile 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80241",
+      "from": "DWC-NCW4205",
+      "to": "EUR-80241-Sample",
+      "title": "Barbary Toile 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80242",
+      "from": "DWC-NCW4205",
+      "to": "EUR-80242-Sample",
+      "title": "Barbary Toile 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80243",
+      "from": "DWC-NCW4205",
+      "to": "EUR-80243-Sample",
+      "title": "Barbary Toile 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80245",
+      "from": "DWC-NCW4206",
+      "to": "EUR-80245-Sample",
+      "title": "Tagus 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80254",
+      "from": "DWC-NCW4207",
+      "to": "EUR-80254-Sample",
+      "title": "Fontibre 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80255",
+      "from": "DWC-NCW4207-02",
+      "to": "EUR-80255-Sample",
+      "title": "Fontibre 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80256",
+      "from": "DWC-NCW4207-03",
+      "to": "EUR-80256-Sample",
+      "title": "Fontibre 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80257",
+      "from": "DWC-NCW4207",
+      "to": "EUR-80257-Sample",
+      "title": "Fontibre 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80258",
+      "from": "DWC-NCW4207",
+      "to": "EUR-80258-Sample",
+      "title": "Fontibre 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80259",
+      "from": "DWC-NCW4270",
+      "to": "EUR-80259-Sample",
+      "title": "Coromandel 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80260",
+      "from": "DWC-NCW4270",
+      "to": "EUR-80260-Sample",
+      "title": "Coromandel 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80261",
+      "from": "DWC-NCW4270-03",
+      "to": "EUR-80261-Sample",
+      "title": "Coromandel 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80262",
+      "from": "DWC-NCW4270",
+      "to": "EUR-80262-Sample",
+      "title": "Coromandel 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80263",
+      "from": "DWC-NCW4270 -05",
+      "to": "EUR-80263-Sample",
+      "title": "Coromandel 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80264",
+      "from": "DWC-NCW4270",
+      "to": "EUR-80264-Sample",
+      "title": "Coromandel 06 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80265",
+      "from": "DWC-NCW4271",
+      "to": "EUR-80265-Sample",
+      "title": "Vignola 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80266",
+      "from": "DWC-NCW4271",
+      "to": "EUR-80266-Sample",
+      "title": "Vignola 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80267",
+      "from": "DWC-NCW4272",
+      "to": "EUR-80267-Sample",
+      "title": "Pavilion Garden 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80268",
+      "from": "DWC-NCW4272",
+      "to": "EUR-80268-Sample",
+      "title": "Pavilion Garden 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80269",
+      "from": "DWC-NCW4272",
+      "to": "EUR-80269-Sample",
+      "title": "Pavilion Garden 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80270",
+      "from": "DWC-NCW4272",
+      "to": "EUR-80270-Sample",
+      "title": "Pavilion Garden 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80274",
+      "from": "DWC-NCW4273 -04",
+      "to": "EUR-80274-Sample",
+      "title": "Gioconda Flock Velvet 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80277",
+      "from": "DWC-NCW4275",
+      "to": "EUR-80277-Sample",
+      "title": "Concertina 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80278",
+      "from": "DWC-NCW4274",
+      "to": "EUR-80278-Sample",
+      "title": "Palmetto 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80279",
+      "from": "DWC-NCW4274",
+      "to": "EUR-80279-Sample",
+      "title": "Palmetto 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80280",
+      "from": "DWC-NCW4274",
+      "to": "EUR-80280-Sample",
+      "title": "Palmetto 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80281",
+      "from": "DWC-NCW4274",
+      "to": "EUR-80281-Sample",
+      "title": "Palmetto 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80282",
+      "from": "DWC-NCW4274",
+      "to": "EUR-80282-Sample",
+      "title": "Palmetto 06 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80283",
+      "from": "DWC-NCW4274",
+      "to": "EUR-80283-Sample",
+      "title": "Palmetto 07 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80285",
+      "from": "DWC-NCW4276",
+      "to": "EUR-80285-Sample",
+      "title": "Perdana 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80286",
+      "from": "DWC-NCW4276",
+      "to": "EUR-80286-Sample",
+      "title": "Perdana 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80287",
+      "from": "DWC-NCW4276",
+      "to": "EUR-80287-Sample",
+      "title": "Perdana 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80288",
+      "from": "DWC-NCW4276",
+      "to": "EUR-80288-Sample",
+      "title": "Perdana 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80289",
+      "from": "DWC-NCW4276",
+      "to": "EUR-80289-Sample",
+      "title": "Perdana 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80291",
+      "from": "DWC-NCW4277",
+      "to": "EUR-80291-Sample",
+      "title": "Meredith 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80292",
+      "from": "DWC-NCW4277",
+      "to": "EUR-80292-Sample",
+      "title": "Meredith 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80293",
+      "from": "DWC-NCW4277",
+      "to": "EUR-80293-Sample",
+      "title": "Meredith 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80294",
+      "from": "DWC-NCW4277",
+      "to": "EUR-80294-Sample",
+      "title": "Meredith 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80295",
+      "from": "DWC-NCW4277",
+      "to": "EUR-80295-Sample",
+      "title": "Meredith 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80296",
+      "from": "DWC-NCW4277",
+      "to": "EUR-80296-Sample",
+      "title": "Meredith 06 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80297",
+      "from": "DWC-NCW4277",
+      "to": "EUR-80297-Sample",
+      "title": "Meredith 07 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80299",
+      "from": "DWC-NCW4300-01",
+      "to": "EUR-80299-Sample",
+      "title": "Collioure 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80300",
+      "from": "DWC-NCW4300-02",
+      "to": "EUR-80300-Sample",
+      "title": "Collioure 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80301",
+      "from": "DWC-NCW4300-03",
+      "to": "EUR-80301-Sample",
+      "title": "Collioure 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80302",
+      "from": "DWC-NCW4300-04",
+      "to": "EUR-80302-Sample",
+      "title": "Collioure 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80303",
+      "from": "DWC-NCW4300-05",
+      "to": "EUR-80303-Sample",
+      "title": "Collioure 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80304",
+      "from": "DWC-NCW4301",
+      "to": "EUR-80304-Sample",
+      "title": "Beau Rivage 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80305",
+      "from": "DWC-NCW4301-02",
+      "to": "EUR-80305-Sample",
+      "title": "Beau Rivage 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80306",
+      "from": "DWC-NCW4301-03",
+      "to": "EUR-80306-Sample",
+      "title": "Beau Rivage 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80307",
+      "from": "DWC-NCW4301-04",
+      "to": "EUR-80307-Sample",
+      "title": "Beau Rivage 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80308",
+      "from": "DWC-NCW4301-05",
+      "to": "EUR-80308-Sample",
+      "title": "Beau Rivage 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80309",
+      "from": "DWC-NCW4301-06",
+      "to": "EUR-80309-Sample",
+      "title": "Beau Rivage 06 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80311",
+      "from": "DWC-NCW4302-01",
+      "to": "EUR-80311-Sample",
+      "title": "Mourlot 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80312",
+      "from": "DWC-NCW4302-02",
+      "to": "EUR-80312-Sample",
+      "title": "Mourlot 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80313",
+      "from": "DWC-NCW4302-03",
+      "to": "EUR-80313-Sample",
+      "title": "Mourlot 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80314",
+      "from": "DWC-NCW4302-04",
+      "to": "EUR-80314-Sample",
+      "title": "Mourlot 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80315",
+      "from": "DWC-NCW4303-01",
+      "to": "EUR-80315-Sample",
+      "title": "Camille 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80316",
+      "from": "DWC-NCW4303-02",
+      "to": "EUR-80316-Sample",
+      "title": "Camille 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80317",
+      "from": "DWC-NCW4303-03",
+      "to": "EUR-80317-Sample",
+      "title": "Camille 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80318",
+      "from": "DWC-NCW4303-04",
+      "to": "EUR-80318-Sample",
+      "title": "Camille 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80319",
+      "from": "DWC-NCW4303-05",
+      "to": "EUR-80319-Sample",
+      "title": "Camille 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80320",
+      "from": "DWC-NCW4304-01",
+      "to": "EUR-80320-Sample",
+      "title": "Marguerite Damask 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80321",
+      "from": "DWC-NCW4304-02",
+      "to": "EUR-80321-Sample",
+      "title": "Marguerite Damask 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80322",
+      "from": "DWC-NCW4304-03",
+      "to": "EUR-80322-Sample",
+      "title": "Marguerite Damask 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80323",
+      "from": "DWC-NCW4304-04",
+      "to": "EUR-80323-Sample",
+      "title": "Marguerite Damask 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80324",
+      "from": "DWC-NCW4304-05",
+      "to": "EUR-80324-Sample",
+      "title": "Marguerite Damask 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80325",
+      "from": "DWC-NCW4304-06",
+      "to": "EUR-80325-Sample",
+      "title": "Marguerite Damask 06 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80326",
+      "from": "DWC-NCW4305-01",
+      "to": "EUR-80326-Sample",
+      "title": "Pampelonne 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80327",
+      "from": "DWC-NCW4305-02",
+      "to": "EUR-80327-Sample",
+      "title": "Pampelonne 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80328",
+      "from": "DWC-NCW4305-03",
+      "to": "EUR-80328-Sample",
+      "title": "Pampelonne 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80329",
+      "from": "DWC-NCW4305-04",
+      "to": "EUR-80329-Sample",
+      "title": "Pampelonne 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80330",
+      "from": "DWC-NCW4305-05",
+      "to": "EUR-80330-Sample",
+      "title": "Pampelonne 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80331",
+      "from": "DWC-NCW4306",
+      "to": "EUR-80331-Sample",
+      "title": "Belle Ile Stripe 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80332",
+      "from": "DWC-NCW4306-02",
+      "to": "EUR-80332-Sample",
+      "title": "Belle Ile Stripe 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80333",
+      "from": "DWC-NCW4306-03",
+      "to": "EUR-80333-Sample",
+      "title": "Belle Ile Stripe 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80334",
+      "from": "DWC-NCW4306-04",
+      "to": "EUR-80334-Sample",
+      "title": "Belle Ile Stripe 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80335",
+      "from": "DWC-NCW4306-05",
+      "to": "EUR-80335-Sample",
+      "title": "Belle Ile Stripe 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80336",
+      "from": "DWC-NCW4307-01",
+      "to": "EUR-80336-Sample",
+      "title": "Dormiers Stripe 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80337",
+      "from": "DWC-NCW4307-02",
+      "to": "EUR-80337-Sample",
+      "title": "Dormiers Stripe 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80338",
+      "from": "DWC-NCW4307-03",
+      "to": "EUR-80338-Sample",
+      "title": "Dormiers Stripe 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80339",
+      "from": "DWC-NCW4307-04",
+      "to": "EUR-80339-Sample",
+      "title": "Dormiers Stripe 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80340",
+      "from": "DWC-NCW4308-01",
+      "to": "EUR-80340-Sample",
+      "title": "Portavo Damask 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80341",
+      "from": "DWC-NCW4308-02",
+      "to": "EUR-80341-Sample",
+      "title": "Portavo Damask 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80342",
+      "from": "DWC-NCW4308-03",
+      "to": "EUR-80342-Sample",
+      "title": "Portavo Damask 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80343",
+      "from": "DWC-NCW4308-04",
+      "to": "EUR-80343-Sample",
+      "title": "Portavo Damask 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80344",
+      "from": "DWC-NCW4350-01",
+      "to": "EUR-80344-Sample",
+      "title": "Les Indiennes Paisley Damask 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80345",
+      "from": "DWC-NCW4350-02",
+      "to": "EUR-80345-Sample",
+      "title": "Les Indiennes Paisley Damask 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80346",
+      "from": "DWC-NCW4350-03",
+      "to": "EUR-80346-Sample",
+      "title": "Les Indiennes Paisley Damask 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80347",
+      "from": "DWC-NCW4350-04",
+      "to": "EUR-80347-Sample",
+      "title": "Les Indiennes Paisley Damask 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80348",
+      "from": "DWC-NCW4350-05",
+      "to": "EUR-80348-Sample",
+      "title": "Les Indiennes Paisley Damask 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80349",
+      "from": "DWC-NCW4350-06",
+      "to": "EUR-80349-Sample",
+      "title": "Les Indiennes Paisley Damask 06 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80351",
+      "from": "DWC-NCW4351-01",
+      "to": "EUR-80351-Sample",
+      "title": "Baville 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80352",
+      "from": "DWC-NCW4351-02",
+      "to": "EUR-80352-Sample",
+      "title": "Baville 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80353",
+      "from": "DWC-NCW4351-03",
+      "to": "EUR-80353-Sample",
+      "title": "Baville 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80354",
+      "from": "DWC-NCW4351-04",
+      "to": "EUR-80354-Sample",
+      "title": "Baville 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80355",
+      "from": "DWC-NCW4351-05",
+      "to": "EUR-80355-Sample",
+      "title": "Baville 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80356",
+      "from": "DWC-NCW4351-06",
+      "to": "EUR-80356-Sample",
+      "title": "Baville 06 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80357",
+      "from": "DWC-NCW4352-01",
+      "to": "EUR-80357-Sample",
+      "title": "Bonnelles Diamond 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80358",
+      "from": "DWC-NCW4352-02",
+      "to": "EUR-80358-Sample",
+      "title": "Bonnelles Diamond 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80359",
+      "from": "DWC-NCW4352-03",
+      "to": "EUR-80359-Sample",
+      "title": "Bonnelles Diamond 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80360",
+      "from": "DWC-NCW4352-04",
+      "to": "EUR-80360-Sample",
+      "title": "Bonnelles Diamond 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80361",
+      "from": "DWC-NCW4352-05",
+      "to": "EUR-80361-Sample",
+      "title": "Bonnelles Diamond 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80362",
+      "from": "DWC-NCW4352-06",
+      "to": "EUR-80362-Sample",
+      "title": "Bonnelles Diamond 06 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80365",
+      "from": "DWC-NCW4353-01",
+      "to": "EUR-80365-Sample",
+      "title": "Colbert 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80366",
+      "from": "DWC-NCW4353-02",
+      "to": "EUR-80366-Sample",
+      "title": "Colbert 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80367",
+      "from": "DWC-NCW4353-03",
+      "to": "EUR-80367-Sample",
+      "title": "Colbert 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80368",
+      "from": "DWC-NCW4353-04",
+      "to": "EUR-80368-Sample",
+      "title": "Colbert 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80369",
+      "from": "DWC-NCW4353-05",
+      "to": "EUR-80369-Sample",
+      "title": "Colbert 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80370",
+      "from": "DWC-NCW4353-06",
+      "to": "EUR-80370-Sample",
+      "title": "Colbert 06 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80371",
+      "from": "DWC-NCW4354-01",
+      "to": "EUR-80371-Sample",
+      "title": "Garance 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80372",
+      "from": "DWC-NCW4354-02",
+      "to": "EUR-80372-Sample",
+      "title": "Garance 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80373",
+      "from": "DWC-NCW4354-03",
+      "to": "EUR-80373-Sample",
+      "title": "Garance 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80374",
+      "from": "DWC-NCW4354-04",
+      "to": "EUR-80374-Sample",
+      "title": "Garance 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80375",
+      "from": "DWC-NCW4354-05",
+      "to": "EUR-80375-Sample",
+      "title": "Garance 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80377",
+      "from": "DWC-NCW4355-01",
+      "to": "EUR-80377-Sample",
+      "title": "Arles 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80378",
+      "from": "DWC-NCW4355-02",
+      "to": "EUR-80378-Sample",
+      "title": "Arles 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80379",
+      "from": "DWC-NCW4355-03",
+      "to": "EUR-80379-Sample",
+      "title": "Arles 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80380",
+      "from": "DWC-NCW4356-01",
+      "to": "EUR-80380-Sample",
+      "title": "Fortoiseau 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80381",
+      "from": "DWC-NCW4356-02",
+      "to": "EUR-80381-Sample",
+      "title": "Fortoiseau 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80382",
+      "from": "DWC-NCW4356-03",
+      "to": "EUR-80382-Sample",
+      "title": "Fortoiseau 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80383",
+      "from": "DWC-NCW4356-04",
+      "to": "EUR-80383-Sample",
+      "title": "Fortoiseau 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80384",
+      "from": "DWC-NCW4356-05",
+      "to": "EUR-80384-Sample",
+      "title": "Fortoiseau 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80386",
+      "from": "DWC-NCW4390-01",
+      "to": "EUR-80386-Sample",
+      "title": "Pomegranate Trail 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80387",
+      "from": "DWC-NCW4390-02",
+      "to": "EUR-80387-Sample",
+      "title": "Pomegranate Trail 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80388",
+      "from": "DWC-NCW4390-03",
+      "to": "EUR-80388-Sample",
+      "title": "Pomegranate Trail 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80389",
+      "from": "DWC-NCW4390-04",
+      "to": "EUR-80389-Sample",
+      "title": "Pomegranate Trail 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80390",
+      "from": "DWC-NCW4390-05",
+      "to": "EUR-80390-Sample",
+      "title": "Pomegranate Trail 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80391",
+      "from": "DWC-NCW4391-01",
+      "to": "EUR-80391-Sample",
+      "title": "Cloisters 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80392",
+      "from": "DWC-NCW4391-02",
+      "to": "EUR-80392-Sample",
+      "title": "Cloisters 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80393",
+      "from": "DWC-NCW4391-03",
+      "to": "EUR-80393-Sample",
+      "title": "Cloisters 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80394",
+      "from": "DWC-NCW4391-04",
+      "to": "EUR-80394-Sample",
+      "title": "Cloisters 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80395",
+      "from": "DWC-NCW4392-01",
+      "to": "EUR-80395-Sample",
+      "title": "Chelwood Floral Damask 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80396",
+      "from": "DWC-NCW4392-02",
+      "to": "EUR-80396-Sample",
+      "title": "Chelwood Floral Damask 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80397",
+      "from": "DWC-NCW4392-04",
+      "to": "EUR-80397-Sample",
+      "title": "Chelwood Floral Damask 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80398",
+      "from": "DWC-NCW4392-04",
+      "to": "EUR-80398-Sample",
+      "title": "Chelwood Floral Damask 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80399",
+      "from": "DWC-NCW4392-05",
+      "to": "EUR-80399-Sample",
+      "title": "Chelwood Floral Damask 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80400",
+      "from": "DWC-NCW4393-01",
+      "to": "EUR-80400-Sample",
+      "title": "Benmore 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80401",
+      "from": "DWC-NCW4393-02",
+      "to": "EUR-80401-Sample",
+      "title": "Benmore 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80402",
+      "from": "DWC-NCW4393-03",
+      "to": "EUR-80402-Sample",
+      "title": "Benmore 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80403",
+      "from": "DWC-NCW4393-04",
+      "to": "EUR-80403-Sample",
+      "title": "Benmore 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80404",
+      "from": "DWC-NCW4393-05",
+      "to": "EUR-80404-Sample",
+      "title": "Benmore 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80405",
+      "from": "DWC-NCW4393-06",
+      "to": "EUR-80405-Sample",
+      "title": "Benmore 06 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80406",
+      "from": "DWC-NCW4394-01",
+      "to": "EUR-80406-Sample",
+      "title": "Posingford Leaves 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80407",
+      "from": "DWC-NCW4394-02",
+      "to": "EUR-80407-Sample",
+      "title": "Posingford Leaves 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80408",
+      "from": "DWC-NCW4394-03",
+      "to": "EUR-80408-Sample",
+      "title": "Posingford Leaves 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80409",
+      "from": "DWC-NCW4394-04",
+      "to": "EUR-80409-Sample",
+      "title": "Posingford Leaves 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80410",
+      "from": "DWC-NCW4394-05",
+      "to": "EUR-80410-Sample",
+      "title": "Posingford Leaves 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80411",
+      "from": "DWC-NCW4395-01",
+      "to": "EUR-80411-Sample",
+      "title": "Kingsley Fans 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80412",
+      "from": "DWC-NCW4395-02",
+      "to": "EUR-80412-Sample",
+      "title": "Kingsley Fans 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80413",
+      "from": "DWC-NCW4395-03",
+      "to": "EUR-80413-Sample",
+      "title": "Kingsley Fans 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80414",
+      "from": "DWC-NCW4395-04",
+      "to": "EUR-80414-Sample",
+      "title": "Kingsley Fans 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80415",
+      "from": "DWC-NCW4395-05",
+      "to": "EUR-80415-Sample",
+      "title": "Kingsley Fans 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80416",
+      "from": "DWC-NCW4395-06",
+      "to": "EUR-80416-Sample",
+      "title": "Kingsley Fans 06 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80417",
+      "from": "DWC-NCW4396-01",
+      "to": "EUR-80417-Sample",
+      "title": "Brideshead Scroll Damask 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80418",
+      "from": "DWC-NCW4396-02",
+      "to": "EUR-80418-Sample",
+      "title": "Brideshead Scroll Damask 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80419",
+      "from": "DWC-NCW4396-03",
+      "to": "EUR-80419-Sample",
+      "title": "Brideshead Scroll Damask 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80420",
+      "from": "DWC-NCW4396-04",
+      "to": "EUR-80420-Sample",
+      "title": "Brideshead Scroll Damask 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80421",
+      "from": "DWC-NCW4490-01",
+      "to": "EUR-80421-Sample",
+      "title": "Foret 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80422",
+      "from": "DWC-NCW4490-02",
+      "to": "EUR-80422-Sample",
+      "title": "Foret 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80423",
+      "from": "DWC-NCW4490-03",
+      "to": "EUR-80423-Sample",
+      "title": "Foret 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80424",
+      "from": "DWC-NCW4490-04",
+      "to": "EUR-80424-Sample",
+      "title": "Foret 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80425",
+      "from": "DWC-NCW4490-05",
+      "to": "EUR-80425-Sample",
+      "title": "Foret 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80426",
+      "from": "DWC-NCW4491-01",
+      "to": "EUR-80426-Sample",
+      "title": "Almora 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80427",
+      "from": "DWC-NCW4491-02",
+      "to": "EUR-80427-Sample",
+      "title": "Almora 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80428",
+      "from": "DWC-NCW4491-03",
+      "to": "EUR-80428-Sample",
+      "title": "Almora 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80429",
+      "from": "DWC-NCW4491-04",
+      "to": "EUR-80429-Sample",
+      "title": "Almora 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80430",
+      "from": "DWC-NCW4491-05",
+      "to": "EUR-80430-Sample",
+      "title": "Almora 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80431",
+      "from": "DWC-NCW4492-01",
+      "to": "EUR-80431-Sample",
+      "title": "Sackville Stripe 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80432",
+      "from": "DWC-NCW4492-02",
+      "to": "EUR-80432-Sample",
+      "title": "Sackville Stripe 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80433",
+      "from": "DWC-NCW4492-03",
+      "to": "EUR-80433-Sample",
+      "title": "Sackville Stripe 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80434",
+      "from": "DWC-NCW4492-04",
+      "to": "EUR-80434-Sample",
+      "title": "Sackville Stripe 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80435",
+      "from": "DWC-NCW4492-05",
+      "to": "EUR-80435-Sample",
+      "title": "Sackville Stripe 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80436",
+      "from": "DWC-NCW4493-01",
+      "to": "EUR-80436-Sample",
+      "title": "Petit Dapuri Stripe 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80437",
+      "from": "DWC-NCW4493-02",
+      "to": "EUR-80437-Sample",
+      "title": "Petit Dapuri Stripe 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80438",
+      "from": "DWC-NCW4493-03",
+      "to": "EUR-80438-Sample",
+      "title": "Petit Dapuri Stripe 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80439",
+      "from": "DWC-NCW4493-04",
+      "to": "EUR-80439-Sample",
+      "title": "Petit Dapuri Stripe 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80441",
+      "from": "DWC-NCW4494-01",
+      "to": "EUR-80441-Sample",
+      "title": "Meridor Stripe 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80442",
+      "from": "DWC-NCW4494-02",
+      "to": "EUR-80442-Sample",
+      "title": "Meridor Stripe 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80443",
+      "from": "DWC-NCW4494-03",
+      "to": "EUR-80443-Sample",
+      "title": "Meridor Stripe 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80444",
+      "from": "DWC-NCW4494-04",
+      "to": "EUR-80444-Sample",
+      "title": "Meridor Stripe 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80445",
+      "from": "DWC-NCW4494-05",
+      "to": "EUR-80445-Sample",
+      "title": "Meridor Stripe 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80446",
+      "from": "DWC-NCW4494-06",
+      "to": "EUR-80446-Sample",
+      "title": "Meridor Stripe 06 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80447",
+      "from": "DWC-NCW4495-01",
+      "to": "EUR-80447-Sample",
+      "title": "Arber Lattice Trellis 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80448",
+      "from": "DWC-NCW4495-02",
+      "to": "EUR-80448-Sample",
+      "title": "Arber Lattice Trellis 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80449",
+      "from": "DWC-NCW4495-03",
+      "to": "EUR-80449-Sample",
+      "title": "Arber Lattice Trellis 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80450",
+      "from": "DWC-NCW4495-04",
+      "to": "EUR-80450-Sample",
+      "title": "Arber Lattice Trellis 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80451",
+      "from": "DWC-NCW4496-01",
+      "to": "EUR-80451-Sample",
+      "title": "Plumier Stripe 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80452",
+      "from": "DWC-NCW4496-02",
+      "to": "EUR-80452-Sample",
+      "title": "Plumier Stripe 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80453",
+      "from": "DWC-NCW4496-03",
+      "to": "EUR-80453-Sample",
+      "title": "Plumier Stripe 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80454",
+      "from": "DWC-NCW4496-04",
+      "to": "EUR-80454-Sample",
+      "title": "Plumier Stripe 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80455",
+      "from": "DWC-NCW4496-05",
+      "to": "EUR-80455-Sample",
+      "title": "Plumier Stripe 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80456",
+      "from": "DWC-NCW4496-06",
+      "to": "EUR-80456-Sample",
+      "title": "Plumier Stripe 06 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80457",
+      "from": "DWC-NCW4497-01",
+      "to": "EUR-80457-Sample",
+      "title": "Toile Chinoise 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80458",
+      "from": "DWC-NCW4497-02",
+      "to": "EUR-80458-Sample",
+      "title": "Toile Chinoise 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80459",
+      "from": "DWC-NCW4497-03",
+      "to": "EUR-80459-Sample",
+      "title": "Toile Chinoise 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80460",
+      "from": "DWC-NCW4498-01",
+      "to": "EUR-80460-Sample",
+      "title": "Poiteau Bamboo Ferns 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80461",
+      "from": "DWC-NCW4498-02",
+      "to": "EUR-80461-Sample",
+      "title": "Poiteau Bamboo Ferns 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80462",
+      "from": "DWC-NCW4498-03",
+      "to": "EUR-80462-Sample",
+      "title": "Poiteau Bamboo Ferns 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80463",
+      "from": "DWC-NCW4498-04",
+      "to": "EUR-80463-Sample",
+      "title": "Poiteau Bamboo Ferns 04 | Nina Campbell Europe"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/scripts/ncw-cleanup/audit-rename-2026-05-06T17-44-04.json b/scripts/ncw-cleanup/audit-rename-2026-05-06T17-44-04.json
new file mode 100644
index 00000000..bba6ca7d
--- /dev/null
+++ b/scripts/ncw-cleanup/audit-rename-2026-05-06T17-44-04.json
@@ -0,0 +1,2087 @@
+{
+  "renamed": 297,
+  "alreadyEur": 21,
+  "missing": 0,
+  "errors": 0,
+  "audit": [
+    {
+      "ok": true,
+      "dw": "EUR-80109",
+      "from": "DWC-NCW4106",
+      "to": "EUR-80109-Sample",
+      "title": "Oakley Hall 5 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80110",
+      "from": "DWC-NCW4107",
+      "to": "EUR-80110-Sample",
+      "title": "Wilmington 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80111",
+      "from": "DWC-NCW4107",
+      "to": "EUR-80111-Sample",
+      "title": "Wilmington 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80112",
+      "from": "DWC-NCW4120",
+      "to": "EUR-80112-Sample",
+      "title": "Holmwood 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80116",
+      "from": "DWC-NCW4121",
+      "to": "EUR-80116-Sample",
+      "title": "Bothwell 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80117",
+      "from": "DWC-NCW4121",
+      "to": "EUR-80117-Sample",
+      "title": "Bothwell 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80118",
+      "from": "DWC-NCW4121",
+      "to": "EUR-80118-Sample",
+      "title": "Bothwell 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80119",
+      "from": "DWC-NCW4121",
+      "to": "EUR-80119-Sample",
+      "title": "Bothwell 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80120",
+      "from": "DWC-NCW4122",
+      "to": "EUR-80120-Sample",
+      "title": "Elcho 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80121",
+      "from": "DWC-NCW4122",
+      "to": "EUR-80121-Sample",
+      "title": "Elcho 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80122",
+      "from": "DWC-NCW4123",
+      "to": "EUR-80122-Sample",
+      "title": "Abbotsford 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80123",
+      "from": "DWC-NCW4123",
+      "to": "EUR-80123-Sample",
+      "title": "Abbotsford 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80124",
+      "from": "DWC-NCW4123",
+      "to": "EUR-80124-Sample",
+      "title": "Abbotsford 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80125",
+      "from": "DWC-NCW4123",
+      "to": "EUR-80125-Sample",
+      "title": "Abbotsford 06 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80126",
+      "from": "DWC-NCW4123",
+      "to": "EUR-80126-Sample",
+      "title": "Abbotsford 07 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80127",
+      "from": "DWC-NCW4125",
+      "to": "EUR-80127-Sample",
+      "title": "Rothesay 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80128",
+      "from": "DWC-NCW4125",
+      "to": "EUR-80128-Sample",
+      "title": "Rothesay 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80129",
+      "from": "DWC-NCW4125",
+      "to": "EUR-80129-Sample",
+      "title": "Rothesay 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80130",
+      "from": "DWC-NCW4126",
+      "to": "EUR-80130-Sample",
+      "title": "Huntly 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80131",
+      "from": "DWC-NCW4126",
+      "to": "EUR-80131-Sample",
+      "title": "Huntly 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80132",
+      "from": "DWC-NCW4126",
+      "to": "EUR-80132-Sample",
+      "title": "Huntly 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80133",
+      "from": "DWC-NCW4126",
+      "to": "EUR-80133-Sample",
+      "title": "Huntly 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80134",
+      "from": "DWC-NCW4126",
+      "to": "EUR-80134-Sample",
+      "title": "Huntly 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80135",
+      "from": "DWC-NCW4126",
+      "to": "EUR-80135-Sample",
+      "title": "Huntly 06 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80136",
+      "from": "DWC-NCW4126",
+      "to": "EUR-80136-Sample",
+      "title": "Huntly 07 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80139",
+      "from": "DWC-NCW4127",
+      "to": "EUR-80139-Sample",
+      "title": "Strome 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80140",
+      "from": "DWC-NCW4127",
+      "to": "EUR-80140-Sample",
+      "title": "Strome 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80141",
+      "from": "DWC-NCW4127",
+      "to": "EUR-80141-Sample",
+      "title": "Strome 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80142",
+      "from": "DWC-NCW4127",
+      "to": "EUR-80142-Sample",
+      "title": "Strome 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80143",
+      "from": "DWC-NCW4150",
+      "to": "EUR-80143-Sample",
+      "title": "Rosslyn 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80144",
+      "from": "DWC-NCW4150",
+      "to": "EUR-80144-Sample",
+      "title": "Rosslyn 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80145",
+      "from": "DWC-NCW4150",
+      "to": "EUR-80145-Sample",
+      "title": "Rosslyn 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80146",
+      "from": "DWC-NCW4150",
+      "to": "EUR-80146-Sample",
+      "title": "Rosslyn 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80147",
+      "from": "DWC-NCW4150",
+      "to": "EUR-80147-Sample",
+      "title": "Rosslyn 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80148",
+      "from": "DWC-NCW4151",
+      "to": "EUR-80148-Sample",
+      "title": "Torosay 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80149",
+      "from": "DWC-NCW4151",
+      "to": "EUR-80149-Sample",
+      "title": "Torosay 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80150",
+      "from": "DWC-NCW4151",
+      "to": "EUR-80150-Sample",
+      "title": "Torosay 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80151",
+      "from": "DWC-NCW4151",
+      "to": "EUR-80151-Sample",
+      "title": "Torosay 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80152",
+      "from": "DWC-NCW4151",
+      "to": "EUR-80152-Sample",
+      "title": "Torosay 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80153",
+      "from": "DWC-NCW4151",
+      "to": "EUR-80153-Sample",
+      "title": "Torosay 06 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80154",
+      "from": "DWC-NCW4152",
+      "to": "EUR-80154-Sample",
+      "title": "Lochwood 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80155",
+      "from": "DWC-NCW4152",
+      "to": "EUR-80155-Sample",
+      "title": "Lochwood 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80156",
+      "from": "DWC-NCW4152",
+      "to": "EUR-80156-Sample",
+      "title": "Lochwood 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80157",
+      "from": "DWC-NCW4152",
+      "to": "EUR-80157-Sample",
+      "title": "Lochwood 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80158",
+      "from": "DWC-NCW4152",
+      "to": "EUR-80158-Sample",
+      "title": "Lochwood 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80159",
+      "from": "DWC-NCW4154",
+      "to": "EUR-80159-Sample",
+      "title": "Mey Fern 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80160",
+      "from": "DWC-NCW4154",
+      "to": "EUR-80160-Sample",
+      "title": "Mey Fern 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80161",
+      "from": "DWC-NCW4154",
+      "to": "EUR-80161-Sample",
+      "title": "Mey Fern 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80162",
+      "from": "DWC-NCW4154",
+      "to": "EUR-80162-Sample",
+      "title": "Mey Fern 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80163",
+      "from": "DWC-NCW4155",
+      "to": "EUR-80163-Sample",
+      "title": "Kelburn 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80164",
+      "from": "DWC-NCW4155",
+      "to": "EUR-80164-Sample",
+      "title": "Kelburn 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80165",
+      "from": "DWC-NCW4155",
+      "to": "EUR-80165-Sample",
+      "title": "Kelburn 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80166",
+      "from": "DWC-NCW4155",
+      "to": "EUR-80166-Sample",
+      "title": "Kelburn 06 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80167",
+      "from": "DWC-NCW4156",
+      "to": "EUR-80167-Sample",
+      "title": "Montrose 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80168",
+      "from": "DWC-NCW4156",
+      "to": "EUR-80168-Sample",
+      "title": "Montrose 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80169",
+      "from": "DWC-NCW4156",
+      "to": "EUR-80169-Sample",
+      "title": "Montrose 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80170",
+      "from": "DWC-NCW4156",
+      "to": "EUR-80170-Sample",
+      "title": "Montrose 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80171",
+      "from": "DWC-NCW4156",
+      "to": "EUR-80171-Sample",
+      "title": "Montrose 06 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80172",
+      "from": "DWC-NCW4180",
+      "to": "EUR-80172-Sample",
+      "title": "Cathay Parade 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80173",
+      "from": "DWC-NCW4180",
+      "to": "EUR-80173-Sample",
+      "title": "Cathay Parade 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80183",
+      "from": "DWC-NCW4182 -01",
+      "to": "EUR-80183-Sample",
+      "title": "Penglai 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80184",
+      "from": "DWC-NCW4182-02",
+      "to": "EUR-80184-Sample",
+      "title": "Penglai 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80185",
+      "from": "DWC-NCW4182/03",
+      "to": "EUR-80185-Sample",
+      "title": "Penglai 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80186",
+      "from": "DWC-NCW4182",
+      "to": "EUR-80186-Sample",
+      "title": "Penglai 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80188",
+      "from": "DWC-NCW4183",
+      "to": "EUR-80188-Sample",
+      "title": "Pamir 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80189",
+      "from": "DWC-NCW4183",
+      "to": "EUR-80189-Sample",
+      "title": "Pamir 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80190",
+      "from": "DWC-NCW4183",
+      "to": "EUR-80190-Sample",
+      "title": "Pamir 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80191",
+      "from": "DWC-NCW4183",
+      "to": "EUR-80191-Sample",
+      "title": "Pamir 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80192",
+      "from": "DWC-NCW4183",
+      "to": "EUR-80192-Sample",
+      "title": "Pamir 06 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80193",
+      "from": "DWC-NCW4183",
+      "to": "EUR-80193-Sample",
+      "title": "Pamir 07 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80195",
+      "from": "DWC-NCW4184",
+      "to": "EUR-80195-Sample",
+      "title": "Suzhou 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80196",
+      "from": "DWC-NCW4184",
+      "to": "EUR-80196-Sample",
+      "title": "Suzhou 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80197",
+      "from": "DWC-NCW4184",
+      "to": "EUR-80197-Sample",
+      "title": "Suzhou 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80198",
+      "from": "DWC-NCW4185",
+      "to": "EUR-80198-Sample",
+      "title": "Mahayana 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80199",
+      "from": "DWC-NCW4185",
+      "to": "EUR-80199-Sample",
+      "title": "Mahayana 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80200",
+      "from": "DWC-NCW4185",
+      "to": "EUR-80200-Sample",
+      "title": "Mahayana 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80201",
+      "from": "DWC-NCW4185",
+      "to": "EUR-80201-Sample",
+      "title": "Mahayana 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80202",
+      "from": "DWC-NCW4185",
+      "to": "EUR-80202-Sample",
+      "title": "Mahayana 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80203",
+      "from": "DWC-NCW4185",
+      "to": "EUR-80203-Sample",
+      "title": "Mahayana 06 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80211",
+      "from": "DWC-NCW4186",
+      "to": "EUR-80211-Sample",
+      "title": "Khitan 08 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80214",
+      "from": "DWC-NCW4186",
+      "to": "EUR-80214-Sample",
+      "title": "Khitan 11 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80216",
+      "from": "DWC-NCW4200",
+      "to": "EUR-80216-Sample",
+      "title": "Keightley's Folio 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80217",
+      "from": "DWC-NCW4200",
+      "to": "EUR-80217-Sample",
+      "title": "Keightley's Folio 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80218",
+      "from": "DWC-NCW4200",
+      "to": "EUR-80218-Sample",
+      "title": "Keightley's Folio 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80219",
+      "from": "DWC-NCW4201",
+      "to": "EUR-80219-Sample",
+      "title": "Belem 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80225",
+      "from": "DWC-NCW4202",
+      "to": "EUR-80225-Sample",
+      "title": "Estella 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80226",
+      "from": "DWC-NCW4202",
+      "to": "EUR-80226-Sample",
+      "title": "Estella 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80227",
+      "from": "DWC-NCW4202",
+      "to": "EUR-80227-Sample",
+      "title": "Estella 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80228",
+      "from": "DWC-NCW4202",
+      "to": "EUR-80228-Sample",
+      "title": "Estella 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80229",
+      "from": "DWC-NCW4202",
+      "to": "EUR-80229-Sample",
+      "title": "Estella 06 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80231",
+      "from": "DWC-NCW4204",
+      "to": "EUR-80231-Sample",
+      "title": "Kershaw Plain 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80232",
+      "from": "DWC-NCW4204",
+      "to": "EUR-80232-Sample",
+      "title": "Kershaw Plain 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80233",
+      "from": "DWC-NCW4204",
+      "to": "EUR-80233-Sample",
+      "title": "Kershaw Plain 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80234",
+      "from": "DWC-NCW4204",
+      "to": "EUR-80234-Sample",
+      "title": "Kershaw Plain 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80235",
+      "from": "DWC-NCW4204",
+      "to": "EUR-80235-Sample",
+      "title": "Kershaw Plain 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80236",
+      "from": "DWC-NCW4204",
+      "to": "EUR-80236-Sample",
+      "title": "Kershaw Plain 06 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80237",
+      "from": "DWC-NCW4204",
+      "to": "EUR-80237-Sample",
+      "title": "Kershaw Plain 07 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80239",
+      "from": "DWC-NCW4205",
+      "to": "EUR-80239-Sample",
+      "title": "Barbary Toile 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80241",
+      "from": "DWC-NCW4205",
+      "to": "EUR-80241-Sample",
+      "title": "Barbary Toile 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80242",
+      "from": "DWC-NCW4205",
+      "to": "EUR-80242-Sample",
+      "title": "Barbary Toile 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80243",
+      "from": "DWC-NCW4205",
+      "to": "EUR-80243-Sample",
+      "title": "Barbary Toile 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80245",
+      "from": "DWC-NCW4206",
+      "to": "EUR-80245-Sample",
+      "title": "Tagus 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80254",
+      "from": "DWC-NCW4207",
+      "to": "EUR-80254-Sample",
+      "title": "Fontibre 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80255",
+      "from": "DWC-NCW4207-02",
+      "to": "EUR-80255-Sample",
+      "title": "Fontibre 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80256",
+      "from": "DWC-NCW4207-03",
+      "to": "EUR-80256-Sample",
+      "title": "Fontibre 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80257",
+      "from": "DWC-NCW4207",
+      "to": "EUR-80257-Sample",
+      "title": "Fontibre 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80258",
+      "from": "DWC-NCW4207",
+      "to": "EUR-80258-Sample",
+      "title": "Fontibre 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80259",
+      "from": "DWC-NCW4270",
+      "to": "EUR-80259-Sample",
+      "title": "Coromandel 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80260",
+      "from": "DWC-NCW4270",
+      "to": "EUR-80260-Sample",
+      "title": "Coromandel 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80261",
+      "from": "DWC-NCW4270-03",
+      "to": "EUR-80261-Sample",
+      "title": "Coromandel 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80262",
+      "from": "DWC-NCW4270",
+      "to": "EUR-80262-Sample",
+      "title": "Coromandel 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80263",
+      "from": "DWC-NCW4270 -05",
+      "to": "EUR-80263-Sample",
+      "title": "Coromandel 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80264",
+      "from": "DWC-NCW4270",
+      "to": "EUR-80264-Sample",
+      "title": "Coromandel 06 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80265",
+      "from": "DWC-NCW4271",
+      "to": "EUR-80265-Sample",
+      "title": "Vignola 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80266",
+      "from": "DWC-NCW4271",
+      "to": "EUR-80266-Sample",
+      "title": "Vignola 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80267",
+      "from": "DWC-NCW4272",
+      "to": "EUR-80267-Sample",
+      "title": "Pavilion Garden 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80268",
+      "from": "DWC-NCW4272",
+      "to": "EUR-80268-Sample",
+      "title": "Pavilion Garden 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80269",
+      "from": "DWC-NCW4272",
+      "to": "EUR-80269-Sample",
+      "title": "Pavilion Garden 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80270",
+      "from": "DWC-NCW4272",
+      "to": "EUR-80270-Sample",
+      "title": "Pavilion Garden 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80274",
+      "from": "DWC-NCW4273 -04",
+      "to": "EUR-80274-Sample",
+      "title": "Gioconda Flock Velvet 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80277",
+      "from": "DWC-NCW4275",
+      "to": "EUR-80277-Sample",
+      "title": "Concertina 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80278",
+      "from": "DWC-NCW4274",
+      "to": "EUR-80278-Sample",
+      "title": "Palmetto 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80279",
+      "from": "DWC-NCW4274",
+      "to": "EUR-80279-Sample",
+      "title": "Palmetto 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80280",
+      "from": "DWC-NCW4274",
+      "to": "EUR-80280-Sample",
+      "title": "Palmetto 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80281",
+      "from": "DWC-NCW4274",
+      "to": "EUR-80281-Sample",
+      "title": "Palmetto 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80282",
+      "from": "DWC-NCW4274",
+      "to": "EUR-80282-Sample",
+      "title": "Palmetto 06 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80283",
+      "from": "DWC-NCW4274",
+      "to": "EUR-80283-Sample",
+      "title": "Palmetto 07 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80285",
+      "from": "DWC-NCW4276",
+      "to": "EUR-80285-Sample",
+      "title": "Perdana 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80286",
+      "from": "DWC-NCW4276",
+      "to": "EUR-80286-Sample",
+      "title": "Perdana 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80287",
+      "from": "DWC-NCW4276",
+      "to": "EUR-80287-Sample",
+      "title": "Perdana 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80288",
+      "from": "DWC-NCW4276",
+      "to": "EUR-80288-Sample",
+      "title": "Perdana 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80289",
+      "from": "DWC-NCW4276",
+      "to": "EUR-80289-Sample",
+      "title": "Perdana 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80291",
+      "from": "DWC-NCW4277",
+      "to": "EUR-80291-Sample",
+      "title": "Meredith 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80292",
+      "from": "DWC-NCW4277",
+      "to": "EUR-80292-Sample",
+      "title": "Meredith 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80293",
+      "from": "DWC-NCW4277",
+      "to": "EUR-80293-Sample",
+      "title": "Meredith 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80294",
+      "from": "DWC-NCW4277",
+      "to": "EUR-80294-Sample",
+      "title": "Meredith 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80295",
+      "from": "DWC-NCW4277",
+      "to": "EUR-80295-Sample",
+      "title": "Meredith 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80296",
+      "from": "DWC-NCW4277",
+      "to": "EUR-80296-Sample",
+      "title": "Meredith 06 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80297",
+      "from": "DWC-NCW4277",
+      "to": "EUR-80297-Sample",
+      "title": "Meredith 07 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80299",
+      "from": "DWC-NCW4300-01",
+      "to": "EUR-80299-Sample",
+      "title": "Collioure 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80300",
+      "from": "DWC-NCW4300-02",
+      "to": "EUR-80300-Sample",
+      "title": "Collioure 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80301",
+      "from": "DWC-NCW4300-03",
+      "to": "EUR-80301-Sample",
+      "title": "Collioure 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80302",
+      "from": "DWC-NCW4300-04",
+      "to": "EUR-80302-Sample",
+      "title": "Collioure 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80303",
+      "from": "DWC-NCW4300-05",
+      "to": "EUR-80303-Sample",
+      "title": "Collioure 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80304",
+      "from": "DWC-NCW4301",
+      "to": "EUR-80304-Sample",
+      "title": "Beau Rivage 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80305",
+      "from": "DWC-NCW4301-02",
+      "to": "EUR-80305-Sample",
+      "title": "Beau Rivage 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80306",
+      "from": "DWC-NCW4301-03",
+      "to": "EUR-80306-Sample",
+      "title": "Beau Rivage 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80307",
+      "from": "DWC-NCW4301-04",
+      "to": "EUR-80307-Sample",
+      "title": "Beau Rivage 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80308",
+      "from": "DWC-NCW4301-05",
+      "to": "EUR-80308-Sample",
+      "title": "Beau Rivage 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80309",
+      "from": "DWC-NCW4301-06",
+      "to": "EUR-80309-Sample",
+      "title": "Beau Rivage 06 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80311",
+      "from": "DWC-NCW4302-01",
+      "to": "EUR-80311-Sample",
+      "title": "Mourlot 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80312",
+      "from": "DWC-NCW4302-02",
+      "to": "EUR-80312-Sample",
+      "title": "Mourlot 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80313",
+      "from": "DWC-NCW4302-03",
+      "to": "EUR-80313-Sample",
+      "title": "Mourlot 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80314",
+      "from": "DWC-NCW4302-04",
+      "to": "EUR-80314-Sample",
+      "title": "Mourlot 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80315",
+      "from": "DWC-NCW4303-01",
+      "to": "EUR-80315-Sample",
+      "title": "Camille 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80316",
+      "from": "DWC-NCW4303-02",
+      "to": "EUR-80316-Sample",
+      "title": "Camille 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80317",
+      "from": "DWC-NCW4303-03",
+      "to": "EUR-80317-Sample",
+      "title": "Camille 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80318",
+      "from": "DWC-NCW4303-04",
+      "to": "EUR-80318-Sample",
+      "title": "Camille 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80319",
+      "from": "DWC-NCW4303-05",
+      "to": "EUR-80319-Sample",
+      "title": "Camille 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80320",
+      "from": "DWC-NCW4304-01",
+      "to": "EUR-80320-Sample",
+      "title": "Marguerite Damask 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80321",
+      "from": "DWC-NCW4304-02",
+      "to": "EUR-80321-Sample",
+      "title": "Marguerite Damask 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80322",
+      "from": "DWC-NCW4304-03",
+      "to": "EUR-80322-Sample",
+      "title": "Marguerite Damask 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80323",
+      "from": "DWC-NCW4304-04",
+      "to": "EUR-80323-Sample",
+      "title": "Marguerite Damask 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80324",
+      "from": "DWC-NCW4304-05",
+      "to": "EUR-80324-Sample",
+      "title": "Marguerite Damask 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80325",
+      "from": "DWC-NCW4304-06",
+      "to": "EUR-80325-Sample",
+      "title": "Marguerite Damask 06 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80326",
+      "from": "DWC-NCW4305-01",
+      "to": "EUR-80326-Sample",
+      "title": "Pampelonne 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80327",
+      "from": "DWC-NCW4305-02",
+      "to": "EUR-80327-Sample",
+      "title": "Pampelonne 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80328",
+      "from": "DWC-NCW4305-03",
+      "to": "EUR-80328-Sample",
+      "title": "Pampelonne 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80329",
+      "from": "DWC-NCW4305-04",
+      "to": "EUR-80329-Sample",
+      "title": "Pampelonne 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80330",
+      "from": "DWC-NCW4305-05",
+      "to": "EUR-80330-Sample",
+      "title": "Pampelonne 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80331",
+      "from": "DWC-NCW4306",
+      "to": "EUR-80331-Sample",
+      "title": "Belle Ile Stripe 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80332",
+      "from": "DWC-NCW4306-02",
+      "to": "EUR-80332-Sample",
+      "title": "Belle Ile Stripe 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80333",
+      "from": "DWC-NCW4306-03",
+      "to": "EUR-80333-Sample",
+      "title": "Belle Ile Stripe 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80334",
+      "from": "DWC-NCW4306-04",
+      "to": "EUR-80334-Sample",
+      "title": "Belle Ile Stripe 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80335",
+      "from": "DWC-NCW4306-05",
+      "to": "EUR-80335-Sample",
+      "title": "Belle Ile Stripe 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80336",
+      "from": "DWC-NCW4307-01",
+      "to": "EUR-80336-Sample",
+      "title": "Dormiers Stripe 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80337",
+      "from": "DWC-NCW4307-02",
+      "to": "EUR-80337-Sample",
+      "title": "Dormiers Stripe 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80338",
+      "from": "DWC-NCW4307-03",
+      "to": "EUR-80338-Sample",
+      "title": "Dormiers Stripe 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80339",
+      "from": "DWC-NCW4307-04",
+      "to": "EUR-80339-Sample",
+      "title": "Dormiers Stripe 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80340",
+      "from": "DWC-NCW4308-01",
+      "to": "EUR-80340-Sample",
+      "title": "Portavo Damask 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80341",
+      "from": "DWC-NCW4308-02",
+      "to": "EUR-80341-Sample",
+      "title": "Portavo Damask 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80342",
+      "from": "DWC-NCW4308-03",
+      "to": "EUR-80342-Sample",
+      "title": "Portavo Damask 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80343",
+      "from": "DWC-NCW4308-04",
+      "to": "EUR-80343-Sample",
+      "title": "Portavo Damask 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80344",
+      "from": "DWC-NCW4350-01",
+      "to": "EUR-80344-Sample",
+      "title": "Les Indiennes Paisley Damask 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80345",
+      "from": "DWC-NCW4350-02",
+      "to": "EUR-80345-Sample",
+      "title": "Les Indiennes Paisley Damask 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80346",
+      "from": "DWC-NCW4350-03",
+      "to": "EUR-80346-Sample",
+      "title": "Les Indiennes Paisley Damask 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80347",
+      "from": "DWC-NCW4350-04",
+      "to": "EUR-80347-Sample",
+      "title": "Les Indiennes Paisley Damask 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80348",
+      "from": "DWC-NCW4350-05",
+      "to": "EUR-80348-Sample",
+      "title": "Les Indiennes Paisley Damask 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80349",
+      "from": "DWC-NCW4350-06",
+      "to": "EUR-80349-Sample",
+      "title": "Les Indiennes Paisley Damask 06 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80351",
+      "from": "DWC-NCW4351-01",
+      "to": "EUR-80351-Sample",
+      "title": "Baville 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80352",
+      "from": "DWC-NCW4351-02",
+      "to": "EUR-80352-Sample",
+      "title": "Baville 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80353",
+      "from": "DWC-NCW4351-03",
+      "to": "EUR-80353-Sample",
+      "title": "Baville 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80354",
+      "from": "DWC-NCW4351-04",
+      "to": "EUR-80354-Sample",
+      "title": "Baville 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80355",
+      "from": "DWC-NCW4351-05",
+      "to": "EUR-80355-Sample",
+      "title": "Baville 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80356",
+      "from": "DWC-NCW4351-06",
+      "to": "EUR-80356-Sample",
+      "title": "Baville 06 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80357",
+      "from": "DWC-NCW4352-01",
+      "to": "EUR-80357-Sample",
+      "title": "Bonnelles Diamond 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80358",
+      "from": "DWC-NCW4352-02",
+      "to": "EUR-80358-Sample",
+      "title": "Bonnelles Diamond 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80359",
+      "from": "DWC-NCW4352-03",
+      "to": "EUR-80359-Sample",
+      "title": "Bonnelles Diamond 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80360",
+      "from": "DWC-NCW4352-04",
+      "to": "EUR-80360-Sample",
+      "title": "Bonnelles Diamond 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80361",
+      "from": "DWC-NCW4352-05",
+      "to": "EUR-80361-Sample",
+      "title": "Bonnelles Diamond 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80362",
+      "from": "DWC-NCW4352-06",
+      "to": "EUR-80362-Sample",
+      "title": "Bonnelles Diamond 06 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80365",
+      "from": "DWC-NCW4353-01",
+      "to": "EUR-80365-Sample",
+      "title": "Colbert 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80366",
+      "from": "DWC-NCW4353-02",
+      "to": "EUR-80366-Sample",
+      "title": "Colbert 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80367",
+      "from": "DWC-NCW4353-03",
+      "to": "EUR-80367-Sample",
+      "title": "Colbert 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80368",
+      "from": "DWC-NCW4353-04",
+      "to": "EUR-80368-Sample",
+      "title": "Colbert 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80369",
+      "from": "DWC-NCW4353-05",
+      "to": "EUR-80369-Sample",
+      "title": "Colbert 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80370",
+      "from": "DWC-NCW4353-06",
+      "to": "EUR-80370-Sample",
+      "title": "Colbert 06 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80371",
+      "from": "DWC-NCW4354-01",
+      "to": "EUR-80371-Sample",
+      "title": "Garance 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80372",
+      "from": "DWC-NCW4354-02",
+      "to": "EUR-80372-Sample",
+      "title": "Garance 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80373",
+      "from": "DWC-NCW4354-03",
+      "to": "EUR-80373-Sample",
+      "title": "Garance 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80374",
+      "from": "DWC-NCW4354-04",
+      "to": "EUR-80374-Sample",
+      "title": "Garance 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80375",
+      "from": "DWC-NCW4354-05",
+      "to": "EUR-80375-Sample",
+      "title": "Garance 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80377",
+      "from": "DWC-NCW4355-01",
+      "to": "EUR-80377-Sample",
+      "title": "Arles 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80378",
+      "from": "DWC-NCW4355-02",
+      "to": "EUR-80378-Sample",
+      "title": "Arles 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80379",
+      "from": "DWC-NCW4355-03",
+      "to": "EUR-80379-Sample",
+      "title": "Arles 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80380",
+      "from": "DWC-NCW4356-01",
+      "to": "EUR-80380-Sample",
+      "title": "Fortoiseau 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80381",
+      "from": "DWC-NCW4356-02",
+      "to": "EUR-80381-Sample",
+      "title": "Fortoiseau 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80382",
+      "from": "DWC-NCW4356-03",
+      "to": "EUR-80382-Sample",
+      "title": "Fortoiseau 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80383",
+      "from": "DWC-NCW4356-04",
+      "to": "EUR-80383-Sample",
+      "title": "Fortoiseau 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80384",
+      "from": "DWC-NCW4356-05",
+      "to": "EUR-80384-Sample",
+      "title": "Fortoiseau 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80386",
+      "from": "DWC-NCW4390-01",
+      "to": "EUR-80386-Sample",
+      "title": "Pomegranate Trail 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80387",
+      "from": "DWC-NCW4390-02",
+      "to": "EUR-80387-Sample",
+      "title": "Pomegranate Trail 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80388",
+      "from": "DWC-NCW4390-03",
+      "to": "EUR-80388-Sample",
+      "title": "Pomegranate Trail 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80389",
+      "from": "DWC-NCW4390-04",
+      "to": "EUR-80389-Sample",
+      "title": "Pomegranate Trail 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80390",
+      "from": "DWC-NCW4390-05",
+      "to": "EUR-80390-Sample",
+      "title": "Pomegranate Trail 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80391",
+      "from": "DWC-NCW4391-01",
+      "to": "EUR-80391-Sample",
+      "title": "Cloisters 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80392",
+      "from": "DWC-NCW4391-02",
+      "to": "EUR-80392-Sample",
+      "title": "Cloisters 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80393",
+      "from": "DWC-NCW4391-03",
+      "to": "EUR-80393-Sample",
+      "title": "Cloisters 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80394",
+      "from": "DWC-NCW4391-04",
+      "to": "EUR-80394-Sample",
+      "title": "Cloisters 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80395",
+      "from": "DWC-NCW4392-01",
+      "to": "EUR-80395-Sample",
+      "title": "Chelwood Floral Damask 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80396",
+      "from": "DWC-NCW4392-02",
+      "to": "EUR-80396-Sample",
+      "title": "Chelwood Floral Damask 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80397",
+      "from": "DWC-NCW4392-04",
+      "to": "EUR-80397-Sample",
+      "title": "Chelwood Floral Damask 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80398",
+      "from": "DWC-NCW4392-04",
+      "to": "EUR-80398-Sample",
+      "title": "Chelwood Floral Damask 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80399",
+      "from": "DWC-NCW4392-05",
+      "to": "EUR-80399-Sample",
+      "title": "Chelwood Floral Damask 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80400",
+      "from": "DWC-NCW4393-01",
+      "to": "EUR-80400-Sample",
+      "title": "Benmore 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80401",
+      "from": "DWC-NCW4393-02",
+      "to": "EUR-80401-Sample",
+      "title": "Benmore 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80402",
+      "from": "DWC-NCW4393-03",
+      "to": "EUR-80402-Sample",
+      "title": "Benmore 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80403",
+      "from": "DWC-NCW4393-04",
+      "to": "EUR-80403-Sample",
+      "title": "Benmore 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80404",
+      "from": "DWC-NCW4393-05",
+      "to": "EUR-80404-Sample",
+      "title": "Benmore 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80405",
+      "from": "DWC-NCW4393-06",
+      "to": "EUR-80405-Sample",
+      "title": "Benmore 06 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80406",
+      "from": "DWC-NCW4394-01",
+      "to": "EUR-80406-Sample",
+      "title": "Posingford Leaves 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80407",
+      "from": "DWC-NCW4394-02",
+      "to": "EUR-80407-Sample",
+      "title": "Posingford Leaves 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80408",
+      "from": "DWC-NCW4394-03",
+      "to": "EUR-80408-Sample",
+      "title": "Posingford Leaves 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80409",
+      "from": "DWC-NCW4394-04",
+      "to": "EUR-80409-Sample",
+      "title": "Posingford Leaves 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80410",
+      "from": "DWC-NCW4394-05",
+      "to": "EUR-80410-Sample",
+      "title": "Posingford Leaves 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80411",
+      "from": "DWC-NCW4395-01",
+      "to": "EUR-80411-Sample",
+      "title": "Kingsley Fans 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80412",
+      "from": "DWC-NCW4395-02",
+      "to": "EUR-80412-Sample",
+      "title": "Kingsley Fans 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80413",
+      "from": "DWC-NCW4395-03",
+      "to": "EUR-80413-Sample",
+      "title": "Kingsley Fans 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80414",
+      "from": "DWC-NCW4395-04",
+      "to": "EUR-80414-Sample",
+      "title": "Kingsley Fans 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80415",
+      "from": "DWC-NCW4395-05",
+      "to": "EUR-80415-Sample",
+      "title": "Kingsley Fans 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80416",
+      "from": "DWC-NCW4395-06",
+      "to": "EUR-80416-Sample",
+      "title": "Kingsley Fans 06 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80417",
+      "from": "DWC-NCW4396-01",
+      "to": "EUR-80417-Sample",
+      "title": "Brideshead Scroll Damask 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80418",
+      "from": "DWC-NCW4396-02",
+      "to": "EUR-80418-Sample",
+      "title": "Brideshead Scroll Damask 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80419",
+      "from": "DWC-NCW4396-03",
+      "to": "EUR-80419-Sample",
+      "title": "Brideshead Scroll Damask 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80420",
+      "from": "DWC-NCW4396-04",
+      "to": "EUR-80420-Sample",
+      "title": "Brideshead Scroll Damask 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80421",
+      "from": "DWC-NCW4490-01",
+      "to": "EUR-80421-Sample",
+      "title": "Foret 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80422",
+      "from": "DWC-NCW4490-02",
+      "to": "EUR-80422-Sample",
+      "title": "Foret 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80423",
+      "from": "DWC-NCW4490-03",
+      "to": "EUR-80423-Sample",
+      "title": "Foret 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80424",
+      "from": "DWC-NCW4490-04",
+      "to": "EUR-80424-Sample",
+      "title": "Foret 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80425",
+      "from": "DWC-NCW4490-05",
+      "to": "EUR-80425-Sample",
+      "title": "Foret 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80426",
+      "from": "DWC-NCW4491-01",
+      "to": "EUR-80426-Sample",
+      "title": "Almora 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80427",
+      "from": "DWC-NCW4491-02",
+      "to": "EUR-80427-Sample",
+      "title": "Almora 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80428",
+      "from": "DWC-NCW4491-03",
+      "to": "EUR-80428-Sample",
+      "title": "Almora 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80429",
+      "from": "DWC-NCW4491-04",
+      "to": "EUR-80429-Sample",
+      "title": "Almora 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80430",
+      "from": "DWC-NCW4491-05",
+      "to": "EUR-80430-Sample",
+      "title": "Almora 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80431",
+      "from": "DWC-NCW4492-01",
+      "to": "EUR-80431-Sample",
+      "title": "Sackville Stripe 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80432",
+      "from": "DWC-NCW4492-02",
+      "to": "EUR-80432-Sample",
+      "title": "Sackville Stripe 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80433",
+      "from": "DWC-NCW4492-03",
+      "to": "EUR-80433-Sample",
+      "title": "Sackville Stripe 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80434",
+      "from": "DWC-NCW4492-04",
+      "to": "EUR-80434-Sample",
+      "title": "Sackville Stripe 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80435",
+      "from": "DWC-NCW4492-05",
+      "to": "EUR-80435-Sample",
+      "title": "Sackville Stripe 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80436",
+      "from": "DWC-NCW4493-01",
+      "to": "EUR-80436-Sample",
+      "title": "Petit Dapuri Stripe 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80437",
+      "from": "DWC-NCW4493-02",
+      "to": "EUR-80437-Sample",
+      "title": "Petit Dapuri Stripe 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80438",
+      "from": "DWC-NCW4493-03",
+      "to": "EUR-80438-Sample",
+      "title": "Petit Dapuri Stripe 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80439",
+      "from": "DWC-NCW4493-04",
+      "to": "EUR-80439-Sample",
+      "title": "Petit Dapuri Stripe 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80441",
+      "from": "DWC-NCW4494-01",
+      "to": "EUR-80441-Sample",
+      "title": "Meridor Stripe 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80442",
+      "from": "DWC-NCW4494-02",
+      "to": "EUR-80442-Sample",
+      "title": "Meridor Stripe 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80443",
+      "from": "DWC-NCW4494-03",
+      "to": "EUR-80443-Sample",
+      "title": "Meridor Stripe 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80444",
+      "from": "DWC-NCW4494-04",
+      "to": "EUR-80444-Sample",
+      "title": "Meridor Stripe 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80445",
+      "from": "DWC-NCW4494-05",
+      "to": "EUR-80445-Sample",
+      "title": "Meridor Stripe 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80446",
+      "from": "DWC-NCW4494-06",
+      "to": "EUR-80446-Sample",
+      "title": "Meridor Stripe 06 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80447",
+      "from": "DWC-NCW4495-01",
+      "to": "EUR-80447-Sample",
+      "title": "Arber Lattice Trellis 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80448",
+      "from": "DWC-NCW4495-02",
+      "to": "EUR-80448-Sample",
+      "title": "Arber Lattice Trellis 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80449",
+      "from": "DWC-NCW4495-03",
+      "to": "EUR-80449-Sample",
+      "title": "Arber Lattice Trellis 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80450",
+      "from": "DWC-NCW4495-04",
+      "to": "EUR-80450-Sample",
+      "title": "Arber Lattice Trellis 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80451",
+      "from": "DWC-NCW4496-01",
+      "to": "EUR-80451-Sample",
+      "title": "Plumier Stripe 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80452",
+      "from": "DWC-NCW4496-02",
+      "to": "EUR-80452-Sample",
+      "title": "Plumier Stripe 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80453",
+      "from": "DWC-NCW4496-03",
+      "to": "EUR-80453-Sample",
+      "title": "Plumier Stripe 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80454",
+      "from": "DWC-NCW4496-04",
+      "to": "EUR-80454-Sample",
+      "title": "Plumier Stripe 04 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80455",
+      "from": "DWC-NCW4496-05",
+      "to": "EUR-80455-Sample",
+      "title": "Plumier Stripe 05 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80456",
+      "from": "DWC-NCW4496-06",
+      "to": "EUR-80456-Sample",
+      "title": "Plumier Stripe 06 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80457",
+      "from": "DWC-NCW4497-01",
+      "to": "EUR-80457-Sample",
+      "title": "Toile Chinoise 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80458",
+      "from": "DWC-NCW4497-02",
+      "to": "EUR-80458-Sample",
+      "title": "Toile Chinoise 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80459",
+      "from": "DWC-NCW4497-03",
+      "to": "EUR-80459-Sample",
+      "title": "Toile Chinoise 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80460",
+      "from": "DWC-NCW4498-01",
+      "to": "EUR-80460-Sample",
+      "title": "Poiteau Bamboo Ferns 01 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80461",
+      "from": "DWC-NCW4498-02",
+      "to": "EUR-80461-Sample",
+      "title": "Poiteau Bamboo Ferns 02 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80462",
+      "from": "DWC-NCW4498-03",
+      "to": "EUR-80462-Sample",
+      "title": "Poiteau Bamboo Ferns 03 | Nina Campbell Europe"
+    },
+    {
+      "ok": true,
+      "dw": "EUR-80463",
+      "from": "DWC-NCW4498-04",
+      "to": "EUR-80463-Sample",
+      "title": "Poiteau Bamboo Ferns 04 | Nina Campbell Europe"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/scripts/ncw-cleanup/build-full-table.js b/scripts/ncw-cleanup/build-full-table.js
new file mode 100644
index 00000000..d40e5b5d
--- /dev/null
+++ b/scripts/ncw-cleanup/build-full-table.js
@@ -0,0 +1,69 @@
+#!/usr/bin/env node
+// Pull live state of all active NCW products and emit a markdown table + CSV.
+const path = require('path');
+const fs = require('fs');
+const envText = fs.readFileSync(path.join(__dirname, '../../.env'), 'utf8');
+const env = Object.fromEntries(envText.split('\n').map(l => l.match(/^([A-Z0-9_]+)=(.*)$/)).filter(Boolean).map(m => [m[1], m[2]]));
+const GQL = `https://${env.SHOPIFY_STORE_DOMAIN}/admin/api/2024-10/graphql.json`;
+const TOKEN = env.SHOPIFY_ADMIN_ACCESS_TOKEN;
+
+async function gql(q, v = {}) {
+  const r = await fetch(GQL, {
+    method: 'POST',
+    headers: { 'X-Shopify-Access-Token': TOKEN, 'Content-Type': 'application/json' },
+    body: JSON.stringify({ query: q, variables: v }),
+  });
+  return r.json();
+}
+
+(async () => {
+  let cursor = null;
+  const rows = [];
+  for (;;) {
+    const j = await gql(`{
+      products(first: 100, query: "vendor:'Nina Campbell' OR vendor:'Nina Campbell Wallcoverings'"${cursor ? `, after: "${cursor}"` : ''}) {
+        edges { cursor node {
+          id title status handle tags
+          variants(first:1){ nodes{ sku } }
+          mfrCustom: metafield(namespace:"custom", key:"manufacturer_sku"){ value }
+        } }
+        pageInfo { hasNextPage }
+      }
+    }`);
+    const edges = j.data.products.edges;
+    for (const e of edges) {
+      const p = e.node;
+      const mfr = p.mfrCustom?.value || '';
+      if (!/^NCW\d/i.test(mfr) || p.status !== 'ACTIVE') continue;
+      const variantSku = p.variants?.nodes?.[0]?.sku || '';
+      const eurSku = variantSku.replace(/-sample$/i, '');
+      const colorTag = (p.tags || []).find(t => /^color\s*:/i.test(t));
+      rows.push({
+        mfr,
+        eurSku,
+        color: colorTag ? colorTag.replace(/^color\s*:\s*/i, '').trim() : '',
+        title: p.title,
+      });
+    }
+    if (!j.data.products.pageInfo.hasNextPage) break;
+    cursor = edges[edges.length - 1].cursor;
+    await new Promise(r => setTimeout(r, 200));
+  }
+
+  rows.sort((a, b) => a.mfr.localeCompare(b.mfr, undefined, { numeric: true }));
+
+  const md = ['| MFR SKU | EUR SKU | Color | Full Title |', '|---|---|---|---|'];
+  for (const r of rows) {
+    md.push(`| ${r.mfr} | ${r.eurSku} | ${r.color || '—'} | ${r.title.replace(/\|/g, '\\|')} |`);
+  }
+  const mdOut = path.join(__dirname, 'ncw-active-full-table.md');
+  fs.writeFileSync(mdOut, md.join('\n') + '\n');
+
+  const csv = ['mfr_sku,eur_sku,color,title'];
+  for (const r of rows) csv.push(`"${r.mfr}","${r.eurSku}","${r.color}","${r.title.replace(/"/g, '""')}"`);
+  const csvOut = path.join(__dirname, 'ncw-active-full-table.csv');
+  fs.writeFileSync(csvOut, csv.join('\n') + '\n');
+
+  console.error(`Wrote ${rows.length} rows → ${mdOut}`);
+  console.error(`Wrote CSV       → ${csvOut}`);
+})();
diff --git a/scripts/ncw-cleanup/dedupe-as-creation.js b/scripts/ncw-cleanup/dedupe-as-creation.js
new file mode 100644
index 00000000..a0be0490
--- /dev/null
+++ b/scripts/ncw-cleanup/dedupe-as-creation.js
@@ -0,0 +1,61 @@
+#!/usr/bin/env node
+// AS Creation: archive the EARLIER (Apr 13) copy of each shared-SKU dup pair.
+// Keep Apr 14 (more enriched: ~2x tag length, cleaner title format with hyphen).
+const path = require('path');
+const fs = require('fs');
+const envText = fs.readFileSync(path.join(__dirname, '../../.env'), 'utf8');
+const env = Object.fromEntries(envText.split('\n').map(l => l.match(/^([A-Z0-9_]+)=(.*)$/)).filter(Boolean).map(m => [m[1], m[2]]));
+const TOKEN = env.SHOPIFY_ADMIN_ACCESS_TOKEN;
+const GQL = `https://${env.SHOPIFY_STORE_DOMAIN}/admin/api/2024-10/graphql.json`;
+
+async function gql(q, v = {}) {
+  const r = await fetch(GQL, {
+    method: 'POST',
+    headers: { 'X-Shopify-Access-Token': TOKEN, 'Content-Type': 'application/json' },
+    body: JSON.stringify({ query: q, variables: v }),
+  });
+  return r.json();
+}
+const sleep = ms => new Promise(r => setTimeout(r, ms));
+
+(async () => {
+  const { Client } = require('pg');
+  const pg = new Client({ user: 'stevestudio2', database: 'dw_unified', host: '/tmp' });
+  await pg.connect();
+
+  // For AS Creation: keep LATER (higher shopify_id = Apr 14), archive EARLIER (Apr 13)
+  const { rows } = await pg.query(`
+    WITH dup_pairs AS (
+      SELECT sku, ARRAY_AGG(shopify_id ORDER BY shopify_id) AS ids
+      FROM shopify_products
+      WHERE vendor='AS Creation' AND status='ACTIVE' AND sku IS NOT NULL AND sku != ''
+      GROUP BY sku HAVING COUNT(*) > 1
+    )
+    SELECT sku, ids[1] AS earlier_id, ids[2] AS keeper_id FROM dup_pairs ORDER BY sku;
+  `);
+
+  console.log(`# AS Creation dedupe — ${rows.length} pairs (archiving earlier Apr 13 copies, keeping Apr 14)`);
+  let archived = 0, errors = 0;
+  const audit = [];
+  for (const r of rows) {
+    try {
+      const m = await gql(
+        `mutation($i:ProductInput!){productUpdate(input:$i){product{id status} userErrors{message}}}`,
+        { i: { id: r.earlier_id, status: 'ARCHIVED' } }
+      );
+      const ue = m.data?.productUpdate?.userErrors || [];
+      if (ue.length) { errors++; audit.push({ ok:false, sku:r.sku, archived_id:r.earlier_id, err:ue }); console.log(`  ! ${r.sku}: ${JSON.stringify(ue)}`); }
+      else {
+        archived++;
+        audit.push({ ok:true, sku:r.sku, archived_id:r.earlier_id, kept_id:r.keeper_id });
+        await pg.query(`UPDATE shopify_products SET status='ARCHIVED' WHERE shopify_id=$1`, [r.earlier_id]);
+      }
+      if (archived % 5 === 0) process.stdout.write(`  archived ${archived}/${rows.length}\n`);
+      await sleep(250);
+    } catch (e) { errors++; audit.push({ ok:false, sku:r.sku, err:e.message }); }
+  }
+  console.log(`\n## Done: archived=${archived}/${rows.length} errors=${errors}`);
+  const ts = new Date().toISOString().replace(/[:.]/g,'-').slice(0,19);
+  fs.writeFileSync(path.join(__dirname, `audit-as-dedupe-${ts}.json`), JSON.stringify({ archived, errors, audit }, null, 2));
+  await pg.end();
+})();
diff --git a/scripts/ncw-cleanup/dedupe-pr.js b/scripts/ncw-cleanup/dedupe-pr.js
new file mode 100644
index 00000000..c9b01e23
--- /dev/null
+++ b/scripts/ncw-cleanup/dedupe-pr.js
@@ -0,0 +1,72 @@
+#!/usr/bin/env node
+// Phillipe Romano: archive the LATER copy of each shared-SKU dup pair (54 dupes).
+const path = require('path');
+const fs = require('fs');
+const envText = fs.readFileSync(path.join(__dirname, '../../.env'), 'utf8');
+const env = Object.fromEntries(envText.split('\n').map(l => l.match(/^([A-Z0-9_]+)=(.*)$/)).filter(Boolean).map(m => [m[1], m[2]]));
+const TOKEN = env.SHOPIFY_ADMIN_ACCESS_TOKEN;
+const GQL = `https://${env.SHOPIFY_STORE_DOMAIN}/admin/api/2024-10/graphql.json`;
+
+async function gql(q, v = {}) {
+  const r = await fetch(GQL, {
+    method: 'POST',
+    headers: { 'X-Shopify-Access-Token': TOKEN, 'Content-Type': 'application/json' },
+    body: JSON.stringify({ query: q, variables: v }),
+  });
+  return r.json();
+}
+const sleep = ms => new Promise(r => setTimeout(r, ms));
+
+(async () => {
+  const { Client } = require('pg');
+  const pg = new Client({ user: 'stevestudio2', database: 'dw_unified', host: '/tmp' });
+  await pg.connect();
+
+  // Pick the later copy per dup-sku (higher shopify_id) — the Mar 4 one
+  const { rows } = await pg.query(`
+    WITH dup_pairs AS (
+      SELECT sku, ARRAY_AGG(shopify_id ORDER BY shopify_id) AS ids
+      FROM shopify_products
+      WHERE vendor='Phillipe Romano' AND status='ACTIVE' AND sku IS NOT NULL AND sku != ''
+      GROUP BY sku HAVING COUNT(*) > 1
+    )
+    SELECT sku, ids[2] AS later_id, ids[1] AS keeper_id
+    FROM dup_pairs
+    ORDER BY sku;
+  `);
+
+  console.log(`# Phillipe Romano dedupe — ${rows.length} pairs`);
+  let archived = 0, errors = 0;
+  const audit = [];
+
+  for (const r of rows) {
+    try {
+      const m = await gql(
+        `mutation($i:ProductInput!){productUpdate(input:$i){product{id status} userErrors{message}}}`,
+        { i: { id: r.later_id, status: 'ARCHIVED' } }
+      );
+      const ue = m.data?.productUpdate?.userErrors || [];
+      if (ue.length) {
+        errors++;
+        audit.push({ ok: false, sku: r.sku, archived_id: r.later_id, kept_id: r.keeper_id, err: ue });
+        console.log(`  ! ${r.sku}: ${JSON.stringify(ue)}`);
+      } else {
+        archived++;
+        audit.push({ ok: true, sku: r.sku, archived_id: r.later_id, kept_id: r.keeper_id });
+        await pg.query(`UPDATE shopify_products SET status='ARCHIVED' WHERE shopify_id=$1`, [r.later_id]);
+      }
+      if (archived % 10 === 0) process.stdout.write(`  archived ${archived}/${rows.length}\n`);
+      await sleep(280);
+    } catch (e) {
+      errors++;
+      audit.push({ ok: false, sku: r.sku, err: e.message });
+    }
+  }
+
+  console.log(`\n## Done: archived=${archived}/${rows.length} errors=${errors}`);
+  const ts = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
+  const out = path.join(__dirname, `audit-pr-dedupe-${ts}.json`);
+  fs.writeFileSync(out, JSON.stringify({ archived, errors, audit }, null, 2));
+  console.log(`  audit: ${out}`);
+  await pg.end();
+})();
diff --git a/scripts/ncw-cleanup/ncw-active-full-table.csv b/scripts/ncw-cleanup/ncw-active-full-table.csv
new file mode 100644
index 00000000..1169e93d
--- /dev/null
+++ b/scripts/ncw-cleanup/ncw-active-full-table.csv
@@ -0,0 +1,319 @@
+mfr_sku,eur_sku,color,title
+"NCW4106-05","EUR-80109","Grey","Oakley Hall 5 - Cool Gray Wallcovering | Nina Campbell"
+"NCW4107-03","EUR-80110","White","Wilmington 03 - Off-White Wallcovering | Nina Campbell"
+"NCW4107-05","EUR-80111","Beige","Wilmington 05 - Greige Wallcovering | Nina Campbell"
+"NCW4120-01","EUR-80112","Grey","Holmwood 01 - Pale Gray Wallcovering | Nina Campbell"
+"NCW4120-02","EUR-80113","Beige","Holmwood 02 | Nina Campbell Europe"
+"NCW4120-03","EUR-80114","White","Holmwood 03 | Nina Campbell Europe"
+"NCW4120-04","EUR-80115","Grey","Holmwood 04 | Nina Campbell Europe"
+"NCW4121-01","EUR-80116","White","Bothwell 01 - Ecru Wallcovering | Nina Campbell"
+"NCW4121-02","EUR-80117","White","Bothwell 02 - Off-White Wallcovering | Nina Campbell"
+"NCW4121-03","EUR-80118","Pink","Bothwell 03 - Rose Quartz Wallcovering | Nina Campbell"
+"NCW4121-05","EUR-80119","Grey","Bothwell 05 - Cool Gray Wallcovering | Nina Campbell"
+"NCW4122-02","EUR-80120","Blue","Elcho 02 - Powder Blue Wallcovering | Nina Campbell"
+"NCW4122-04","EUR-80121","White","Elcho 04 - Off-White Wallcovering | Nina Campbell"
+"NCW4123-01","EUR-80122","White","Abbotsford 01 - Off-White Wallcovering | Nina Campbell"
+"NCW4123-04","EUR-80123","White","Abbotsford 04 - Off-White Wallcovering | Nina Campbell"
+"NCW4123-05","EUR-80124","Green","Abbotsford 05 - Pale Green Wallcovering | Nina Campbell"
+"NCW4123-06","EUR-80125","White","Abbotsford 06 - Off-White Wallcovering | Nina Campbell"
+"NCW4123-07","EUR-80126","Grey","Abbotsford 07 - Cool Gray Wallcovering | Nina Campbell"
+"NCW4125-01","EUR-80127","Grey","Rothesay 01 - Cool Gray Wallcovering | Nina Campbell"
+"NCW4125-02","EUR-80128","Blue","Rothesay 02 - Pale Blue Wallcovering | Nina Campbell"
+"NCW4125-03","EUR-80129","Green","Rothesay 03 - Celadon Green Wallcovering | Nina Campbell"
+"NCW4126-01","EUR-80130","Grey","Huntly 01 - Pale Gray Wallcovering | Nina Campbell"
+"NCW4126-02","EUR-80131","White","Huntly 02 - Off-White Wallcovering | Nina Campbell"
+"NCW4126-03","EUR-80132","Green","Huntly 03 - Chartreuse Wallcovering | Nina Campbell"
+"NCW4126-04","EUR-80133","White","Huntly 04 - Off-White Wallcovering | Nina Campbell"
+"NCW4126-05","EUR-80134","White","Huntly 05 - Off-White Wallcovering | Nina Campbell"
+"NCW4126-06","EUR-80135","Grey","Huntly 06 - Pale Gray Wallcovering | Nina Campbell"
+"NCW4126-07","EUR-80136","Grey","Huntly 07 - Cool Gray Wallcovering | Nina Campbell"
+"NCW4127-01","EUR-80139","White","Strome 01 - Off-White Wallcovering | Nina Campbell"
+"NCW4127-02","EUR-80140","White","Strome 02 - Off-White Wallcovering | Nina Campbell"
+"NCW4127-03","EUR-80141","White","Strome 03 - Off-White Wallcovering | Nina Campbell"
+"NCW4127-04","EUR-80142","White","Strome 04 - Off-White Wallcovering | Nina Campbell"
+"NCW4150-01","EUR-80143","Grey","Rosslyn 01 - Neutral Gray Wallcovering | Nina Campbell"
+"NCW4150-02","EUR-80144","Grey","Rosslyn 02 - Warm Gray Wallcovering | Nina Campbell"
+"NCW4150-03","EUR-80145","Beige","Rosslyn 03 - Neutral Beige Wallcovering | Nina Campbell"
+"NCW4150-04","EUR-80146","Grey","Rosslyn 04 - Soft Gray Wallcovering | Nina Campbell"
+"NCW4150-05","EUR-80147","White","Rosslyn 05 - Ecru Wallcovering | Nina Campbell"
+"NCW4151-01","EUR-80148","White","Torosay 01 - Off-White Wallcovering | Nina Campbell"
+"NCW4151-02","EUR-80149","White","Torosay 02 - Off-White Wallcovering | Nina Campbell"
+"NCW4151-03","EUR-80150","White","Torosay 03 - Off-White Wallcovering | Nina Campbell"
+"NCW4151-04","EUR-80151","White","Torosay 04 - Off-White Wallcovering | Nina Campbell"
+"NCW4151-05","EUR-80152","White","Torosay 05 - Off-White Wallcovering | Nina Campbell"
+"NCW4151-06","EUR-80153","White","Torosay 06 - Off-White Wallcovering | Nina Campbell"
+"NCW4152-01","EUR-80154","Green","Lochwood 01 - Celadon Green Wallcovering | Nina Campbell"
+"NCW4152-02","EUR-80155","White","Lochwood 02 - Off-White Wallcovering | Nina Campbell"
+"NCW4152-03","EUR-80156","Green","Lochwood 03 - Celadon Green Wallcovering | Nina Campbell"
+"NCW4152-04","EUR-80157","White","Lochwood 04 - Off-White Wallcovering | Nina Campbell"
+"NCW4152-05","EUR-80158","White","Lochwood 05 - Soft White Wallcovering | Nina Campbell"
+"NCW4154-01","EUR-80159","Green","Mey Fern 01 - Khaki Wallcovering | Nina Campbell"
+"NCW4154-02","EUR-80160","Green","Mey Fern 02 - Taupe Wallcovering | Nina Campbell"
+"NCW4154-03","EUR-80161","Green","Mey Fern 03 - Celadon Green Wallcovering | Nina Campbell"
+"NCW4154-04","EUR-80162","White","Mey Fern 04 - Off-White Wallcovering | Nina Campbell"
+"NCW4155-01","EUR-80163","Green","Kelburn 01 - Celadon Green Wallcovering | Nina Campbell"
+"NCW4155-02","EUR-80164","Turquoise","Kelburn 02 - Pale Aqua Wallcovering | Nina Campbell"
+"NCW4155-03","EUR-80165","White","Kelburn 03 - Off-White Wallcovering | Nina Campbell"
+"NCW4155-06","EUR-80166","Grey","Kelburn 06 - Charcoal Gray Wallcovering | Nina Campbell"
+"NCW4156-02","EUR-80167","Turquoise","Montrose 02 - Pale Aqua Wallcovering | Nina Campbell"
+"NCW4156-03","EUR-80168","White","Montrose 03 - Off-White Wallcovering | Nina Campbell"
+"NCW4156-04","EUR-80169","White","Montrose 04 - Off-White Wallcovering | Nina Campbell"
+"NCW4156-05","EUR-80170","Green","Montrose 05 - Pale Chartreuse Wallcovering | Nina Campbell"
+"NCW4156-06","EUR-80171","Gold","Montrose 06 - Antique Gold Wallcovering | Nina Campbell"
+"NCW4180-01","EUR-80172","White","Cathay Parade 01 - Pale Ecru Wallcovering | Nina Campbell"
+"NCW4180-02","EUR-80173","White","Cathay Parade 02 - Off-White Wallcovering | Nina Campbell"
+"NCW4181-01","EUR-80174","Beige","Sansui 01 | Nina Campbell Europe"
+"NCW4181-02","EUR-80175","Grey","Sansui 02 | Nina Campbell Europe"
+"NCW4181-03","EUR-80176","Green","Sansui 03 | Nina Campbell Europe"
+"NCW4181-04","EUR-80177","Green","Sansui 04 | Nina Campbell Europe"
+"NCW4181-05","EUR-80178","White","Sansui 05 | Nina Campbell Europe"
+"NCW4181-06","EUR-80179","Beige","Sansui 06 | Nina Campbell Europe"
+"NCW4181-07","EUR-80180","Grey","Sansui 07 | Nina Campbell Europe"
+"NCW4181-08","EUR-80181","Red","Sansui 08 | Nina Campbell Europe"
+"NCW4182-01","EUR-80183","Green","Penglai 01 - Pastel Green Wallcovering | Nina Campbell"
+"NCW4182-02","EUR-80184","Grey","Cathay Penglai Charcoal/Sage/Coral - Green Wallcovering | Nina Campbell"
+"NCW4182-03","EUR-80185","Blue","Penglai 03 - Pale Blue Wallcovering | Nina Campbell"
+"NCW4182-04","EUR-80186","White","Penglai 04 - Soft White Wallcovering | Nina Campbell"
+"NCW4183-02","EUR-80188","White","Pamir 02 - Off-White Wallcovering | Nina Campbell"
+"NCW4183-03","EUR-80189","Beige","Pamir 03 - Neutral Wallcovering | Nina Campbell"
+"NCW4183-04","EUR-80190","Turquoise","Pamir 04 - Seafoam Green Wallcovering | Nina Campbell"
+"NCW4183-05","EUR-80191","Yellow","Pamir 05 - Goldenrod Wallcovering | Nina Campbell"
+"NCW4183-06","EUR-80192","Pink","Pamir 06 - Coral Pink Wallcovering | Nina Campbell"
+"NCW4183-07","EUR-80193","Grey","Pamir 07 - Neutral Gray Wallcovering | Nina Campbell"
+"NCW4184-02","EUR-80195","Grey","Suzhou 02 - Deep Charcoal Wallcovering | Nina Campbell"
+"NCW4184-03","EUR-80196","White","Suzhou 03 - Off-White Wallcovering | Nina Campbell"
+"NCW4184-04","EUR-80197","White","Suzhou 04 - Off-White Wallcovering | Nina Campbell"
+"NCW4185-01","EUR-80198","Red","Mahayana 01 - Cardinal Red Wallcovering | Nina Campbell"
+"NCW4185-02","EUR-80199","Beige","Mahayana 02 - Neutral Beige Wallcovering | Nina Campbell"
+"NCW4185-03","EUR-80200","Grey","Mahayana 03 - Cool Gray Wallcovering | Nina Campbell"
+"NCW4185-04","EUR-80201","Turquoise","Mahayana 04 - Seafoam Green Wallcovering | Nina Campbell"
+"NCW4185-05","EUR-80202","White","Mahayana 05 - Off-White Wallcovering | Nina Campbell"
+"NCW4185-06","EUR-80203","Black","Mahayana 06 - Onyx Wallcovering | Nina Campbell"
+"NCW4186-01","EUR-80204","Black","Khitan 01 | Nina Campbell Europe"
+"NCW4186-02","EUR-80205","Grey","Khitan 02 | Nina Campbell Europe"
+"NCW4186-03","EUR-80206","Gold","Khitan 03 | Nina Campbell Europe"
+"NCW4186-04","EUR-80207","Turquoise","Khitan 04 | Nina Campbell Europe"
+"NCW4186-05","EUR-80208","Blue","Khitan 05 | Nina Campbell Europe"
+"NCW4186-06","EUR-80209","Gold","Khitan 06 | Nina Campbell Europe"
+"NCW4186-07","EUR-80210","Blue","Khitan 07 | Nina Campbell Europe"
+"NCW4186-08","EUR-80211","White","Khitan 08 - Off-White Wallcovering | Nina Campbell"
+"NCW4186-09","EUR-80212","Grey","Khitan 09 | Nina Campbell Europe"
+"NCW4186-10","EUR-80213","Pink","Khitan 10 | Nina Campbell Europe"
+"NCW4186-11","EUR-80214","Pink","Khitan 11 - Fuchsia Wallcovering | Nina Campbell"
+"NCW4200-01","EUR-80216","Multi","Keightley's Folio 01 - Pastel Wallcovering | Nina Campbell"
+"NCW4200-02","EUR-80217","Grey","Keightley's Folio 02 - Cool Gray Wallcovering | Nina Campbell"
+"NCW4200-03","EUR-80218","Grey","Keightley's Folio 03 - Cool Gray Wallcovering | Nina Campbell"
+"NCW4201-01","EUR-80219","White","Belem 01 - Ecru Wallcovering | Nina Campbell"
+"NCW4202-01","EUR-80224","Blue","Estella 01 - Azure Wallcovering | Nina Campbell"
+"NCW4202-02","EUR-80225","Grey","Estella 02 - Cool Gray Wallcovering | Nina Campbell"
+"NCW4202-03","EUR-80226","Turquoise","Estella 03 - Seafoam Green Wallcovering | Nina Campbell"
+"NCW4202-04","EUR-80227","White","Estella 04 - Ecru Wallcovering | Nina Campbell"
+"NCW4202-05","EUR-80228","White","Estella 05 - Off-White Wallcovering | Nina Campbell"
+"NCW4202-06","EUR-80229","Pink","Estella 06 - Dusty Rose Wallcovering | Nina Campbell"
+"NCW4204-01","EUR-80231","White","Kershaw Plain 01 - Off-White Wallcovering | Nina Campbell"
+"NCW4204-02","EUR-80232","White","Kershaw Plain 02 - Cool White Wallcovering | Nina Campbell"
+"NCW4204-03","EUR-80233","Pink","Kershaw Plain 03 - Pale Blush Wallcovering | Nina Campbell"
+"NCW4204-04","EUR-80234","Orange","Kershaw Plain 04 - Terracotta Wallcovering | Nina Campbell"
+"NCW4204-05","EUR-80235","Turquoise","Kershaw Plain 05 - Seafoam Green Wallcovering | Nina Campbell"
+"NCW4204-06","EUR-80236","Green","Kershaw Plain 06 - Emerald Wallcovering | Nina Campbell"
+"NCW4204-07","EUR-80237","Blue","Kershaw Plain 07 - Sapphire Blue Wallcovering | Nina Campbell"
+"NCW4205-01","EUR-80239","White","Barbary Toile 01 - Off-White Wallcovering | Nina Campbell"
+"NCW4205-03","EUR-80241","Blue","Barbary Toile 03 - Airy Blue Wallcovering | Nina Campbell"
+"NCW4205-04","EUR-80242","Pink","Barbary Toile 04 - Rose Madder Wallcovering | Nina Campbell"
+"NCW4205-05","EUR-80243","White","Barbary Toile 05 - Off-White Wallcovering | Nina Campbell"
+"NCW4206-02","EUR-80245","White","Tagus 02 - Off-White Wallcovering | Nina Campbell"
+"NCW4207-01","EUR-80254","Beige","Fontibre 01 - Neutral Beige Wallcovering | Nina Campbell"
+"NCW4207-02","EUR-80255","Beige","Fontibre 02 - Warm Neutral Wallcovering | Nina Campbell"
+"NCW4207-03","EUR-80256","Green","Fontibre Fontibre Blue/Green - Blue Wallcovering | Nina Campbell"
+"NCW4207-04","EUR-80257","Beige","Fontibre 04 - Soft Beige Wallcovering | Nina Campbell"
+"NCW4207-05","EUR-80258","Beige","Fontibre 05 - Neutral Beige Wallcovering | Nina Campbell"
+"NCW4270-01","EUR-80259","Grey","Coromandel 01 - Charcoal Wallcovering | Nina Campbell"
+"NCW4270-02","EUR-80260","Pink","Coromandel 02 - Coral Pink Wallcovering | Nina Campbell"
+"NCW4270-03","EUR-80261","White","Coromandel 03 - Off-White Wallcovering | Nina Campbell"
+"NCW4270-04","EUR-80262","Grey","Coromandel 04 - Charcoal Gray Wallcovering | Nina Campbell"
+"NCW4270-05","EUR-80263","White","Coromandel 05 - Off-White Wallcovering | Nina Campbell"
+"NCW4270-06","EUR-80264","Green","Coromandel 06 - Deep Forest Wallcovering | Nina Campbell"
+"NCW4271-01","EUR-80265","Grey","Vignola 01 - Cool Gray Wallcovering | Nina Campbell"
+"NCW4271-02","EUR-80266","Yellow","Vignola 02 - Creamy Yellow Wallcovering | Nina Campbell"
+"NCW4272-01","EUR-80267","Blue","Pavilion Garden 01 - Midnight Blue Wallcovering | Nina Campbell"
+"NCW4272-02","EUR-80268","Grey","Pavilion Garden 02 - Pale Gray Wallcovering | Nina Campbell"
+"NCW4272-03","EUR-80269","Blue","Pavilion Garden 03 - Powder Blue Wallcovering | Nina Campbell"
+"NCW4272-04","EUR-80270","Black","Pavilion Garden 04 - Onyx Wallcovering | Nina Campbell"
+"NCW4273-04","EUR-80274","White","Gioconda Flock Velvet 04 - Off-White Wallcovering | Nina Campbell"
+"NCW4274-02","EUR-80278","Turquoise","Palmetto 02 - Pale Aqua Wallcovering | Nina Campbell"
+"NCW4274-03","EUR-80279","White","Palmetto 03 - Off-White Wallcovering | Nina Campbell"
+"NCW4274-04","EUR-80280","White","Palmetto 04 - Off-White Wallcovering | Nina Campbell"
+"NCW4274-05","EUR-80281","Beige","Palmetto 05 - Warm Neutral Wallcovering | Nina Campbell"
+"NCW4274-06","EUR-80282","White","Palmetto 06 - Ecru Wallcovering | Nina Campbell"
+"NCW4274-07","EUR-80283","Pink","Palmetto 07 - Blush Pink Wallcovering | Nina Campbell"
+"NCW4275-01","EUR-80277","Turquoise","Concertina 01 - Seafoam Green Wallcovering | Nina Campbell"
+"NCW4276-01","EUR-80285","Purple","Perdana 01 - Aubergine Wallcovering | Nina Campbell"
+"NCW4276-02","EUR-80286","White","Perdana 02 - Off-White Wallcovering | Nina Campbell"
+"NCW4276-03","EUR-80287","Purple","Perdana 03 - Orchid Tint Wallcovering | Nina Campbell"
+"NCW4276-04","EUR-80288","Blue","Perdana 04 - Airy Blue Wallcovering | Nina Campbell"
+"NCW4276-05","EUR-80289","Beige","Perdana 05 - Greige Wallcovering | Nina Campbell"
+"NCW4277-01","EUR-80291","White","Meredith 01 - Off-White Wallcovering | Nina Campbell"
+"NCW4277-02","EUR-80292","Grey","Meredith 02 - Neutral Gray Wallcovering | Nina Campbell"
+"NCW4277-03","EUR-80293","Brown","Meredith 03 - Taupe Wallcovering | Nina Campbell"
+"NCW4277-04","EUR-80294","Pink","Meredith 04 - Coral Pink Wallcovering | Nina Campbell"
+"NCW4277-05","EUR-80295","Green","Meredith 05 - Celadon Green Wallcovering | Nina Campbell"
+"NCW4277-06","EUR-80296","Turquoise","Meredith 06 - Aqua Blue Wallcovering | Nina Campbell"
+"NCW4277-07","EUR-80297","Blue","Meredith 07 - Delft Blue Wallcovering | Nina Campbell"
+"NCW4300-01","EUR-80299","White","Collioure 01 - Off-White Wallcovering | Nina Campbell"
+"NCW4300-02","EUR-80300","Brown","Collioure 02 - Brown Wallcovering | Nina Campbell"
+"NCW4300-03","EUR-80301","Turquoise","Collioure 03 - Aqua Green Wallcovering | Nina Campbell"
+"NCW4300-04","EUR-80302","Blue","Collioure 04 - Blue Wallcovering | Nina Campbell"
+"NCW4300-05","EUR-80303","Brown","Collioure 05 - Brown Wallcovering | Nina Campbell"
+"NCW4301-01","EUR-80304","Turquoise","Beau Rivage 01 - Aqua Wallcovering | Nina Campbell"
+"NCW4301-02","EUR-80305","Pink","Beau Rivage 02 - Pink Wallcovering | Nina Campbell"
+"NCW4301-03","EUR-80306","Gold","Beau Rivage 03 - Gold Wallcovering | Nina Campbell"
+"NCW4301-04","EUR-80307","Brown","Beau Rivage 04 - Brown Wallcovering | Nina Campbell"
+"NCW4301-05","EUR-80308","Green","Beau Rivage 05 - Chartreuse Green Wallcovering | Nina Campbell"
+"NCW4301-06","EUR-80309","Blue","Beau Rivage 06 - Blue Wallcovering | Nina Campbell"
+"NCW4302-01","EUR-80311","Grey","Mourlot 01 - Grey Wallcovering | Nina Campbell"
+"NCW4302-02","EUR-80312","Grey","Mourlot 02 - Grey Wallcovering | Nina Campbell"
+"NCW4302-03","EUR-80313","Green","Mourlot 03 - Celadon Green Wallcovering | Nina Campbell"
+"NCW4302-04","EUR-80314","Blue","Mourlot 04 - Blue Wallcovering | Nina Campbell"
+"NCW4303-01","EUR-80315","Blue","Camille 01 - Blue Wallcovering | Nina Campbell"
+"NCW4303-02","EUR-80316","Green","Camille 02 - Green Wallcovering | Nina Campbell"
+"NCW4303-03","EUR-80317","Blue","Camille 03 - Blue Wallcovering | Nina Campbell"
+"NCW4303-04","EUR-80318","Brown","Camille 04 - Brown Wallcovering | Nina Campbell"
+"NCW4303-05","EUR-80319","Pink","Camille 05 - Pink Wallcovering | Nina Campbell"
+"NCW4304-01","EUR-80320","White","Les RêVes Marguerite Green/Ivory - Green Wallcovering | Nina Campbell"
+"NCW4304-02","EUR-80321","Grey","Marguerite Damask 02 - Grey Wallcovering | Nina Campbell"
+"NCW4304-03","EUR-80322","Grey","Marguerite Damask 03 - Grey Wallcovering | Nina Campbell"
+"NCW4304-04","EUR-80323","Brown","Marguerite Damask 04 - Brown Wallcovering | Nina Campbell"
+"NCW4304-05","EUR-80324","Blue","Marguerite Damask 05 - Blue Wallcovering | Nina Campbell"
+"NCW4304-06","EUR-80325","Blue","Marguerite Damask 06 - Blue Wallcovering | Nina Campbell"
+"NCW4305-01","EUR-80326","White","Pampelonne 01 - Off-White Wallcovering | Nina Campbell"
+"NCW4305-02","EUR-80327","Grey","Pampelonne 02 - Grey Wallcovering | Nina Campbell"
+"NCW4305-03","EUR-80328","Brown","Pampelonne 03 - Brown Wallcovering | Nina Campbell"
+"NCW4305-04","EUR-80329","Blue","Pampelonne 04 - Blue Wallcovering | Nina Campbell"
+"NCW4305-05","EUR-80330","Blue","Pampelonne 05 - Blue Wallcovering | Nina Campbell"
+"NCW4306-01","EUR-80331","Pink","Belle Ile Stripe 01 - Rose Quartz Wallcovering | Nina Campbell"
+"NCW4306-02","EUR-80332","Brown","Belle Ile Stripe 02 - Brown Wallcovering | Nina Campbell"
+"NCW4306-03","EUR-80333","Green","Belle Ile Stripe 03 - Celadon Green Wallcovering | Nina Campbell"
+"NCW4306-04","EUR-80334","Blue","Belle Ile Stripe 04 - Blue Wallcovering | Nina Campbell"
+"NCW4306-05","EUR-80335","Blue","Belle Ile Stripe 05 - Denim Blue Wallcovering | Nina Campbell"
+"NCW4307-01","EUR-80336","Black","Dormiers Stripe 01 - Black Wallcovering | Nina Campbell"
+"NCW4307-02","EUR-80337","Grey","Dormiers Stripe 02 - Grey Wallcovering | Nina Campbell"
+"NCW4307-03","EUR-80338","Blue","Dormiers Stripe 03 - Blue Wallcovering | Nina Campbell"
+"NCW4307-04","EUR-80339","Blue","Dormiers Stripe 04 - Blue Wallcovering | Nina Campbell"
+"NCW4308-01","EUR-80340","Brown","Portavo Damask 01 - Brown Wallcovering | Nina Campbell"
+"NCW4308-02","EUR-80341","Grey","Portavo Damask 02 - Grey Wallcovering | Nina Campbell"
+"NCW4308-03","EUR-80342","Blue","Portavo Damask 03 - Blue Wallcovering | Nina Campbell"
+"NCW4308-04","EUR-80343","Orange","Portavo Damask 04 - Orange Wallcovering | Nina Campbell"
+"NCW4350-01","EUR-80344","Multi","Les Indiennes Paisley Damask 01 - Multi Wallcovering | Nina Campbell"
+"NCW4350-02","EUR-80345","Grey","Les Indiennes Paisley Damask 02 - Grey Wallcovering | Nina Campbell"
+"NCW4350-03","EUR-80346","Blue","Les Indiennes Paisley Damask 03 - Blue Wallcovering | Nina Campbell"
+"NCW4350-04","EUR-80347","Black","Les Indiennes Paisley Damask 04 - Black Wallcovering | Nina Campbell"
+"NCW4350-05","EUR-80348","Blue","Les Indiennes Paisley Damask 05 - Blue Wallcovering | Nina Campbell"
+"NCW4350-06","EUR-80349","Black","Les Indiennes Paisley Damask 06 - Black Wallcovering | Nina Campbell"
+"NCW4351-01","EUR-80351","Beige","Baville 01 - Neutral Wallcovering | Nina Campbell"
+"NCW4351-02","EUR-80352","White","Baville 02 - Off-White Wallcovering | Nina Campbell"
+"NCW4351-03","EUR-80353","Blue","Baville 03 - Blue Wallcovering | Nina Campbell"
+"NCW4351-04","EUR-80354","Green","Baville 04 - Green Wallcovering | Nina Campbell"
+"NCW4351-05","EUR-80355","Blue","Baville 05 - Blue Wallcovering | Nina Campbell"
+"NCW4351-06","EUR-80356","Grey","Baville 06 - Grey Wallcovering | Nina Campbell"
+"NCW4352-01","EUR-80357","White","Bonnelles Diamond 01 - Off-White Wallcovering | Nina Campbell"
+"NCW4352-02","EUR-80358","Grey","Bonnelles Diamond 02 - Pale Gray Wallcovering | Nina Campbell"
+"NCW4352-03","EUR-80359","Blue","Bonnelles Diamond 03 - Blue Wallcovering | Nina Campbell"
+"NCW4352-04","EUR-80360","Beige","Bonnelles Diamond 04 - Bisque Wallcovering | Nina Campbell"
+"NCW4352-05","EUR-80361","White","Les Indiennes Bonnelles Green/Ivory - Green Wallcovering | Nina Campbell"
+"NCW4352-06","EUR-80362","Black","Bonnelles Diamond 06 - Black Wallcovering | Nina Campbell"
+"NCW4353-01","EUR-80365","Blue","Colbert 01 - Blue Wallcovering | Nina Campbell"
+"NCW4353-02","EUR-80366","Grey","Colbert 02 - Grey Wallcovering | Nina Campbell"
+"NCW4353-03","EUR-80367","White","Colbert 03 - Off-White Wallcovering | Nina Campbell"
+"NCW4353-04","EUR-80368","Green","Colbert 04 - Chartreuse Green Wallcovering | Nina Campbell"
+"NCW4353-05","EUR-80369","Blue","Colbert 05 - Cerulean Blue Wallcovering | Nina Campbell"
+"NCW4353-06","EUR-80370","Grey","Colbert 06 - Grey Wallcovering | Nina Campbell"
+"NCW4354-01","EUR-80371","Pink","Garance 01 - Pink Wallcovering | Nina Campbell"
+"NCW4354-02","EUR-80372","Turquoise","Garance 02 - Aqua Tint Wallcovering | Nina Campbell"
+"NCW4354-03","EUR-80373","Grey","Garance 03 - Grey Wallcovering | Nina Campbell"
+"NCW4354-04","EUR-80374","Green","Garance 04 - Chartreuse Green Wallcovering | Nina Campbell"
+"NCW4354-05","EUR-80375","Black","Garance 05 - Black Wallcovering | Nina Campbell"
+"NCW4355-01","EUR-80377","Gold","Arles 01 - Gold Wallcovering | Nina Campbell"
+"NCW4355-02","EUR-80378","Grey","Arles 02 - Grey Wallcovering | Nina Campbell"
+"NCW4355-03","EUR-80379","White","Arles 03 - Off-White Wallcovering | Nina Campbell"
+"NCW4356-01","EUR-80380","Gold","Fortoiseau 01 - Gold Wallcovering | Nina Campbell"
+"NCW4356-02","EUR-80381","Brown","Fortoiseau 02 - Brown Wallcovering | Nina Campbell"
+"NCW4356-03","EUR-80382","Grey","Fortoiseau 03 - Cool Gray Wallcovering | Nina Campbell"
+"NCW4356-04","EUR-80383","Blue","Fortoiseau 04 - Pale Blue Wallcovering | Nina Campbell"
+"NCW4356-05","EUR-80384","Black","Fortoiseau 05 - Onyx Wallcovering | Nina Campbell"
+"NCW4390-01","EUR-80386","Blue","Ashdown Pomegranate Trail Indigo/Blue - Blue Wallcovering | Nina Campbell"
+"NCW4390-02","EUR-80387","Turquoise","Pomegranate Trail 02 - Aqua Wallcovering | Nina Campbell"
+"NCW4390-03","EUR-80388","Green","Pomegranate Trail 03 - Green Wallcovering | Nina Campbell"
+"NCW4390-04","EUR-80389","Green","Pomegranate Trail 04 - Chartreuse Wallcovering | Nina Campbell"
+"NCW4390-05","EUR-80390","Pink","Pomegranate Trail 05 - Pink Wallcovering | Nina Campbell"
+"NCW4391-01","EUR-80391","Brown","Cloisters 01 - Brown Wallcovering | Nina Campbell"
+"NCW4391-02","EUR-80392","Blue","Cloisters 02 - Blue Wallcovering | Nina Campbell"
+"NCW4391-03","EUR-80393","Green","Cloisters 03 - Green Wallcovering | Nina Campbell"
+"NCW4391-04","EUR-80394","Blue","Cloisters 04 - Blue Wallcovering | Nina Campbell"
+"NCW4392-01","EUR-80395","Blue","Chelwood Floral Damask 01 - Blue Wallcovering | Nina Campbell"
+"NCW4392-02","EUR-80396","Pink","Chelwood Floral Damask 02 - Pink Wallcovering | Nina Campbell"
+"NCW4392-03","EUR-80397","Green","Chelwood Floral Damask 03 - Green Wallcovering | Nina Campbell"
+"NCW4392-04","EUR-80398","Green","Chelwood Floral Damask 04 - Green Wallcovering | Nina Campbell"
+"NCW4392-05","EUR-80399","Blue","Chelwood Floral Damask 05 - Blue Wallcovering | Nina Campbell"
+"NCW4393-01","EUR-80400","Black","Benmore 01 - Black Wallcovering | Nina Campbell"
+"NCW4393-02","EUR-80401","Green","Benmore 02 - Green Wallcovering | Nina Campbell"
+"NCW4393-03","EUR-80402","Blue","Benmore 03 - Blue Wallcovering | Nina Campbell"
+"NCW4393-04","EUR-80403","Brown","Benmore 04 - Brown Wallcovering | Nina Campbell"
+"NCW4393-05","EUR-80404","Grey","Benmore 05 - Grey Wallcovering | Nina Campbell"
+"NCW4393-06","EUR-80405","Grey","Benmore 06 - Grey Wallcovering | Nina Campbell"
+"NCW4394-01","EUR-80406","Pink","Posingford Leaves 01 - Blush Pink Wallcovering | Nina Campbell"
+"NCW4394-02","EUR-80407","White","Posingford Leaves 02 - Ecru Wallcovering | Nina Campbell"
+"NCW4394-03","EUR-80408","Turquoise","Posingford Leaves 03 - Seafoam Green Wallcovering | Nina Campbell"
+"NCW4394-04","EUR-80409","Brown","Posingford Leaves 04 - Brown Wallcovering | Nina Campbell"
+"NCW4394-05","EUR-80410","Green","Posingford Leaves 05 - Green Wallcovering | Nina Campbell"
+"NCW4395-01","EUR-80411","Blue","Kingsley Fans 01 - Blue Wallcovering | Nina Campbell"
+"NCW4395-02","EUR-80412","Brown","Kingsley Fans 02 - Umber Wallcovering | Nina Campbell"
+"NCW4395-03","EUR-80413","Gold","Kingsley Fans 03 - Gold Wallcovering | Nina Campbell"
+"NCW4395-04","EUR-80414","Beige","Kingsley Fans 04 - Neutral Wallcovering | Nina Campbell"
+"NCW4395-05","EUR-80415","Grey","Kingsley Fans 05 - Grey Wallcovering | Nina Campbell"
+"NCW4395-06","EUR-80416","Blue","Kingsley Fans 06 - Blue Wallcovering | Nina Campbell"
+"NCW4396-01","EUR-80417","Grey","Ashdown Brideshead Grey - Grey Wallcovering | Nina Campbell"
+"NCW4396-02","EUR-80418","Grey","Brideshead Scroll Damask 02 - Grey Wallcovering | Nina Campbell"
+"NCW4396-03","EUR-80419","Blue","Brideshead Scroll Damask 03 - Blue Wallcovering | Nina Campbell"
+"NCW4396-04","EUR-80420","White","Brideshead Scroll Damask 04 - Ecru Wallcovering | Nina Campbell"
+"NCW4490-01","EUR-80421","Yellow","Foret 01 - Yellow Wallcovering | Nina Campbell"
+"NCW4490-02","EUR-80422","Brown","Foret 02 - Brown Wallcovering | Nina Campbell"
+"NCW4490-03","EUR-80423","Blue","Foret 03 - Blue Wallcovering | Nina Campbell"
+"NCW4490-04","EUR-80424","Green","Foret 04 - Green Wallcovering | Nina Campbell"
+"NCW4490-05","EUR-80425","Green","Foret 05 - Green Wallcovering | Nina Campbell"
+"NCW4491-01","EUR-80426","Green","Almora 01 - Green Wallcovering | Nina Campbell"
+"NCW4491-02","EUR-80427","Green","Almora 02 - Green Wallcovering | Nina Campbell"
+"NCW4491-03","EUR-80428","Green","Almora 03 - Green Wallcovering | Nina Campbell"
+"NCW4491-04","EUR-80429","Blue","Almora 04 - Blue Wallcovering | Nina Campbell"
+"NCW4491-05","EUR-80430","Turquoise","Almora 05 - Seafoam Green Wallcovering | Nina Campbell"
+"NCW4492-01","EUR-80431","Green","Sackville Stripe 01 - Green Wallcovering | Nina Campbell"
+"NCW4492-02","EUR-80432","Blue","Sackville Stripe 02 - Blue Wallcovering | Nina Campbell"
+"NCW4492-03","EUR-80433","White","Sackville Stripe 03 - White Wallcovering | Nina Campbell"
+"NCW4492-04","EUR-80434","Brown","Sackville Stripe 04 - Brown Wallcovering | Nina Campbell"
+"NCW4492-05","EUR-80435","Blue","Sackville Stripe 05 - Blue Wallcovering | Nina Campbell"
+"NCW4493-01","EUR-80436","Green","Petit Dapuri Stripe 01 - Green Wallcovering | Nina Campbell"
+"NCW4493-02","EUR-80437","Green","Petit Dapuri Stripe 02 - Green Wallcovering | Nina Campbell"
+"NCW4493-03","EUR-80438","Blue","Petit Dapuri Stripe 03 - Blue Wallcovering | Nina Campbell"
+"NCW4493-04","EUR-80439","Green","Petit Dapuri Stripe 04 - Green Wallcovering | Nina Campbell"
+"NCW4494-01","EUR-80441","Brown","Meridor Stripe 01 - Brown Wallcovering | Nina Campbell"
+"NCW4494-02","EUR-80442","Blue","Meridor Stripe 02 - Blue Wallcovering | Nina Campbell"
+"NCW4494-03","EUR-80443","Green","Signature Meridor - Green Wallcovering | Nina Campbell"
+"NCW4494-04","EUR-80444","Beige","Meridor Stripe 04 - Neutral Wallcovering | Nina Campbell"
+"NCW4494-05","EUR-80445","Blue","Meridor Stripe 05 - Blue Wallcovering | Nina Campbell"
+"NCW4494-06","EUR-80446","Blue","Meridor Stripe 06 - Blue Wallcovering | Nina Campbell"
+"NCW4495-01","EUR-80447","Green","Signature Arber - Green Wallcovering | Nina Campbell"
+"NCW4495-02","EUR-80448","Green","Arber Lattice Trellis 02 - Green Wallcovering | Nina Campbell"
+"NCW4495-03","EUR-80449","Blue","Arber Lattice Trellis 03 - Blue Wallcovering | Nina Campbell"
+"NCW4495-04","EUR-80450","Blue","Arber Lattice Trellis 04 - Blue Wallcovering | Nina Campbell"
+"NCW4496-01","EUR-80451","Blue","Plumier Stripe 01 - Blue Wallcovering | Nina Campbell"
+"NCW4496-02","EUR-80452","Blue","Plumier Stripe 02 - Blue Wallcovering | Nina Campbell"
+"NCW4496-03","EUR-80453","Brown","Plumier Stripe 03 - Brown Wallcovering | Nina Campbell"
+"NCW4496-04","EUR-80454","Brown","Plumier Stripe 04 - Brown Wallcovering | Nina Campbell"
+"NCW4496-05","EUR-80455","Beige","Plumier Stripe 05 - Neutral Wallcovering | Nina Campbell"
+"NCW4496-06","EUR-80456","Brown","Plumier Stripe 06 - Brown Wallcovering | Nina Campbell"
+"NCW4497-01","EUR-80457","Brown","Toile Chinoise 01 - Brown Wallcovering | Nina Campbell"
+"NCW4497-02","EUR-80458","Brown","Toile Chinoise 02 - Brown Wallcovering | Nina Campbell"
+"NCW4497-03","EUR-80459","Blue","Toile Chinoise 03 - Blue Wallcovering | Nina Campbell"
+"NCW4498-01","EUR-80460","Blue","Poiteau Bamboo Ferns 01 - Blue Wallcovering | Nina Campbell"
+"NCW4498-02","EUR-80461","White","Poiteau Bamboo Ferns 02 - White Wallcovering | Nina Campbell"
+"NCW4498-03","EUR-80462","Green","Poiteau Bamboo Ferns 03 - Green Wallcovering | Nina Campbell"
+"NCW4498-04","EUR-80463","Blue","Poiteau Bamboo Ferns 04 - Blue Wallcovering | Nina Campbell"
diff --git a/scripts/ncw-cleanup/ncw-active-full-table.md b/scripts/ncw-cleanup/ncw-active-full-table.md
new file mode 100644
index 00000000..f00ad918
--- /dev/null
+++ b/scripts/ncw-cleanup/ncw-active-full-table.md
@@ -0,0 +1,320 @@
+| MFR SKU | EUR SKU | Color | Full Title |
+|---|---|---|---|
+| NCW4106-05 | EUR-80109 | Grey | Oakley Hall 5 - Cool Gray Wallcovering \| Nina Campbell |
+| NCW4107-03 | EUR-80110 | White | Wilmington 03 - Off-White Wallcovering \| Nina Campbell |
+| NCW4107-05 | EUR-80111 | Beige | Wilmington 05 - Greige Wallcovering \| Nina Campbell |
+| NCW4120-01 | EUR-80112 | Grey | Holmwood 01 - Pale Gray Wallcovering \| Nina Campbell |
+| NCW4120-02 | EUR-80113 | Beige | Holmwood 02 \| Nina Campbell Europe |
+| NCW4120-03 | EUR-80114 | White | Holmwood 03 \| Nina Campbell Europe |
+| NCW4120-04 | EUR-80115 | Grey | Holmwood 04 \| Nina Campbell Europe |
+| NCW4121-01 | EUR-80116 | White | Bothwell 01 - Ecru Wallcovering \| Nina Campbell |
+| NCW4121-02 | EUR-80117 | White | Bothwell 02 - Off-White Wallcovering \| Nina Campbell |
+| NCW4121-03 | EUR-80118 | Pink | Bothwell 03 - Rose Quartz Wallcovering \| Nina Campbell |
+| NCW4121-05 | EUR-80119 | Grey | Bothwell 05 - Cool Gray Wallcovering \| Nina Campbell |
+| NCW4122-02 | EUR-80120 | Blue | Elcho 02 - Powder Blue Wallcovering \| Nina Campbell |
+| NCW4122-04 | EUR-80121 | White | Elcho 04 - Off-White Wallcovering \| Nina Campbell |
+| NCW4123-01 | EUR-80122 | White | Abbotsford 01 - Off-White Wallcovering \| Nina Campbell |
+| NCW4123-04 | EUR-80123 | White | Abbotsford 04 - Off-White Wallcovering \| Nina Campbell |
+| NCW4123-05 | EUR-80124 | Green | Abbotsford 05 - Pale Green Wallcovering \| Nina Campbell |
+| NCW4123-06 | EUR-80125 | White | Abbotsford 06 - Off-White Wallcovering \| Nina Campbell |
+| NCW4123-07 | EUR-80126 | Grey | Abbotsford 07 - Cool Gray Wallcovering \| Nina Campbell |
+| NCW4125-01 | EUR-80127 | Grey | Rothesay 01 - Cool Gray Wallcovering \| Nina Campbell |
+| NCW4125-02 | EUR-80128 | Blue | Rothesay 02 - Pale Blue Wallcovering \| Nina Campbell |
+| NCW4125-03 | EUR-80129 | Green | Rothesay 03 - Celadon Green Wallcovering \| Nina Campbell |
+| NCW4126-01 | EUR-80130 | Grey | Huntly 01 - Pale Gray Wallcovering \| Nina Campbell |
+| NCW4126-02 | EUR-80131 | White | Huntly 02 - Off-White Wallcovering \| Nina Campbell |
+| NCW4126-03 | EUR-80132 | Green | Huntly 03 - Chartreuse Wallcovering \| Nina Campbell |
+| NCW4126-04 | EUR-80133 | White | Huntly 04 - Off-White Wallcovering \| Nina Campbell |
+| NCW4126-05 | EUR-80134 | White | Huntly 05 - Off-White Wallcovering \| Nina Campbell |
+| NCW4126-06 | EUR-80135 | Grey | Huntly 06 - Pale Gray Wallcovering \| Nina Campbell |
+| NCW4126-07 | EUR-80136 | Grey | Huntly 07 - Cool Gray Wallcovering \| Nina Campbell |
+| NCW4127-01 | EUR-80139 | White | Strome 01 - Off-White Wallcovering \| Nina Campbell |
+| NCW4127-02 | EUR-80140 | White | Strome 02 - Off-White Wallcovering \| Nina Campbell |
+| NCW4127-03 | EUR-80141 | White | Strome 03 - Off-White Wallcovering \| Nina Campbell |
+| NCW4127-04 | EUR-80142 | White | Strome 04 - Off-White Wallcovering \| Nina Campbell |
+| NCW4150-01 | EUR-80143 | Grey | Rosslyn 01 - Neutral Gray Wallcovering \| Nina Campbell |
+| NCW4150-02 | EUR-80144 | Grey | Rosslyn 02 - Warm Gray Wallcovering \| Nina Campbell |
+| NCW4150-03 | EUR-80145 | Beige | Rosslyn 03 - Neutral Beige Wallcovering \| Nina Campbell |
+| NCW4150-04 | EUR-80146 | Grey | Rosslyn 04 - Soft Gray Wallcovering \| Nina Campbell |
+| NCW4150-05 | EUR-80147 | White | Rosslyn 05 - Ecru Wallcovering \| Nina Campbell |
+| NCW4151-01 | EUR-80148 | White | Torosay 01 - Off-White Wallcovering \| Nina Campbell |
+| NCW4151-02 | EUR-80149 | White | Torosay 02 - Off-White Wallcovering \| Nina Campbell |
+| NCW4151-03 | EUR-80150 | White | Torosay 03 - Off-White Wallcovering \| Nina Campbell |
+| NCW4151-04 | EUR-80151 | White | Torosay 04 - Off-White Wallcovering \| Nina Campbell |
+| NCW4151-05 | EUR-80152 | White | Torosay 05 - Off-White Wallcovering \| Nina Campbell |
+| NCW4151-06 | EUR-80153 | White | Torosay 06 - Off-White Wallcovering \| Nina Campbell |
+| NCW4152-01 | EUR-80154 | Green | Lochwood 01 - Celadon Green Wallcovering \| Nina Campbell |
+| NCW4152-02 | EUR-80155 | White | Lochwood 02 - Off-White Wallcovering \| Nina Campbell |
+| NCW4152-03 | EUR-80156 | Green | Lochwood 03 - Celadon Green Wallcovering \| Nina Campbell |
+| NCW4152-04 | EUR-80157 | White | Lochwood 04 - Off-White Wallcovering \| Nina Campbell |
+| NCW4152-05 | EUR-80158 | White | Lochwood 05 - Soft White Wallcovering \| Nina Campbell |
+| NCW4154-01 | EUR-80159 | Green | Mey Fern 01 - Khaki Wallcovering \| Nina Campbell |
+| NCW4154-02 | EUR-80160 | Green | Mey Fern 02 - Taupe Wallcovering \| Nina Campbell |
+| NCW4154-03 | EUR-80161 | Green | Mey Fern 03 - Celadon Green Wallcovering \| Nina Campbell |
+| NCW4154-04 | EUR-80162 | White | Mey Fern 04 - Off-White Wallcovering \| Nina Campbell |
+| NCW4155-01 | EUR-80163 | Green | Kelburn 01 - Celadon Green Wallcovering \| Nina Campbell |
+| NCW4155-02 | EUR-80164 | Turquoise | Kelburn 02 - Pale Aqua Wallcovering \| Nina Campbell |
+| NCW4155-03 | EUR-80165 | White | Kelburn 03 - Off-White Wallcovering \| Nina Campbell |
+| NCW4155-06 | EUR-80166 | Grey | Kelburn 06 - Charcoal Gray Wallcovering \| Nina Campbell |
+| NCW4156-02 | EUR-80167 | Turquoise | Montrose 02 - Pale Aqua Wallcovering \| Nina Campbell |
+| NCW4156-03 | EUR-80168 | White | Montrose 03 - Off-White Wallcovering \| Nina Campbell |
+| NCW4156-04 | EUR-80169 | White | Montrose 04 - Off-White Wallcovering \| Nina Campbell |
+| NCW4156-05 | EUR-80170 | Green | Montrose 05 - Pale Chartreuse Wallcovering \| Nina Campbell |
+| NCW4156-06 | EUR-80171 | Gold | Montrose 06 - Antique Gold Wallcovering \| Nina Campbell |
+| NCW4180-01 | EUR-80172 | White | Cathay Parade 01 - Pale Ecru Wallcovering \| Nina Campbell |
+| NCW4180-02 | EUR-80173 | White | Cathay Parade 02 - Off-White Wallcovering \| Nina Campbell |
+| NCW4181-01 | EUR-80174 | Beige | Sansui 01 \| Nina Campbell Europe |
+| NCW4181-02 | EUR-80175 | Grey | Sansui 02 \| Nina Campbell Europe |
+| NCW4181-03 | EUR-80176 | Green | Sansui 03 \| Nina Campbell Europe |
+| NCW4181-04 | EUR-80177 | Green | Sansui 04 \| Nina Campbell Europe |
+| NCW4181-05 | EUR-80178 | White | Sansui 05 \| Nina Campbell Europe |
+| NCW4181-06 | EUR-80179 | Beige | Sansui 06 \| Nina Campbell Europe |
+| NCW4181-07 | EUR-80180 | Grey | Sansui 07 \| Nina Campbell Europe |
+| NCW4181-08 | EUR-80181 | Red | Sansui 08 \| Nina Campbell Europe |
+| NCW4182-01 | EUR-80183 | Green | Penglai 01 - Pastel Green Wallcovering \| Nina Campbell |
+| NCW4182-02 | EUR-80184 | Grey | Cathay Penglai Charcoal/Sage/Coral - Green Wallcovering \| Nina Campbell |
+| NCW4182-03 | EUR-80185 | Blue | Penglai 03 - Pale Blue Wallcovering \| Nina Campbell |
+| NCW4182-04 | EUR-80186 | White | Penglai 04 - Soft White Wallcovering \| Nina Campbell |
+| NCW4183-02 | EUR-80188 | White | Pamir 02 - Off-White Wallcovering \| Nina Campbell |
+| NCW4183-03 | EUR-80189 | Beige | Pamir 03 - Neutral Wallcovering \| Nina Campbell |
+| NCW4183-04 | EUR-80190 | Turquoise | Pamir 04 - Seafoam Green Wallcovering \| Nina Campbell |
+| NCW4183-05 | EUR-80191 | Yellow | Pamir 05 - Goldenrod Wallcovering \| Nina Campbell |
+| NCW4183-06 | EUR-80192 | Pink | Pamir 06 - Coral Pink Wallcovering \| Nina Campbell |
+| NCW4183-07 | EUR-80193 | Grey | Pamir 07 - Neutral Gray Wallcovering \| Nina Campbell |
+| NCW4184-02 | EUR-80195 | Grey | Suzhou 02 - Deep Charcoal Wallcovering \| Nina Campbell |
+| NCW4184-03 | EUR-80196 | White | Suzhou 03 - Off-White Wallcovering \| Nina Campbell |
+| NCW4184-04 | EUR-80197 | White | Suzhou 04 - Off-White Wallcovering \| Nina Campbell |
+| NCW4185-01 | EUR-80198 | Red | Mahayana 01 - Cardinal Red Wallcovering \| Nina Campbell |
+| NCW4185-02 | EUR-80199 | Beige | Mahayana 02 - Neutral Beige Wallcovering \| Nina Campbell |
+| NCW4185-03 | EUR-80200 | Grey | Mahayana 03 - Cool Gray Wallcovering \| Nina Campbell |
+| NCW4185-04 | EUR-80201 | Turquoise | Mahayana 04 - Seafoam Green Wallcovering \| Nina Campbell |
+| NCW4185-05 | EUR-80202 | White | Mahayana 05 - Off-White Wallcovering \| Nina Campbell |
+| NCW4185-06 | EUR-80203 | Black | Mahayana 06 - Onyx Wallcovering \| Nina Campbell |
+| NCW4186-01 | EUR-80204 | Black | Khitan 01 \| Nina Campbell Europe |
+| NCW4186-02 | EUR-80205 | Grey | Khitan 02 \| Nina Campbell Europe |
+| NCW4186-03 | EUR-80206 | Gold | Khitan 03 \| Nina Campbell Europe |
+| NCW4186-04 | EUR-80207 | Turquoise | Khitan 04 \| Nina Campbell Europe |
+| NCW4186-05 | EUR-80208 | Blue | Khitan 05 \| Nina Campbell Europe |
+| NCW4186-06 | EUR-80209 | Gold | Khitan 06 \| Nina Campbell Europe |
+| NCW4186-07 | EUR-80210 | Blue | Khitan 07 \| Nina Campbell Europe |
+| NCW4186-08 | EUR-80211 | White | Khitan 08 - Off-White Wallcovering \| Nina Campbell |
+| NCW4186-09 | EUR-80212 | Grey | Khitan 09 \| Nina Campbell Europe |
+| NCW4186-10 | EUR-80213 | Pink | Khitan 10 \| Nina Campbell Europe |
+| NCW4186-11 | EUR-80214 | Pink | Khitan 11 - Fuchsia Wallcovering \| Nina Campbell |
+| NCW4200-01 | EUR-80216 | Multi | Keightley's Folio 01 - Pastel Wallcovering \| Nina Campbell |
+| NCW4200-02 | EUR-80217 | Grey | Keightley's Folio 02 - Cool Gray Wallcovering \| Nina Campbell |
+| NCW4200-03 | EUR-80218 | Grey | Keightley's Folio 03 - Cool Gray Wallcovering \| Nina Campbell |
+| NCW4201-01 | EUR-80219 | White | Belem 01 - Ecru Wallcovering \| Nina Campbell |
+| NCW4202-01 | EUR-80224 | Blue | Estella 01 - Azure Wallcovering \| Nina Campbell |
+| NCW4202-02 | EUR-80225 | Grey | Estella 02 - Cool Gray Wallcovering \| Nina Campbell |
+| NCW4202-03 | EUR-80226 | Turquoise | Estella 03 - Seafoam Green Wallcovering \| Nina Campbell |
+| NCW4202-04 | EUR-80227 | White | Estella 04 - Ecru Wallcovering \| Nina Campbell |
+| NCW4202-05 | EUR-80228 | White | Estella 05 - Off-White Wallcovering \| Nina Campbell |
+| NCW4202-06 | EUR-80229 | Pink | Estella 06 - Dusty Rose Wallcovering \| Nina Campbell |
+| NCW4204-01 | EUR-80231 | White | Kershaw Plain 01 - Off-White Wallcovering \| Nina Campbell |
+| NCW4204-02 | EUR-80232 | White | Kershaw Plain 02 - Cool White Wallcovering \| Nina Campbell |
+| NCW4204-03 | EUR-80233 | Pink | Kershaw Plain 03 - Pale Blush Wallcovering \| Nina Campbell |
+| NCW4204-04 | EUR-80234 | Orange | Kershaw Plain 04 - Terracotta Wallcovering \| Nina Campbell |
+| NCW4204-05 | EUR-80235 | Turquoise | Kershaw Plain 05 - Seafoam Green Wallcovering \| Nina Campbell |
+| NCW4204-06 | EUR-80236 | Green | Kershaw Plain 06 - Emerald Wallcovering \| Nina Campbell |
+| NCW4204-07 | EUR-80237 | Blue | Kershaw Plain 07 - Sapphire Blue Wallcovering \| Nina Campbell |
+| NCW4205-01 | EUR-80239 | White | Barbary Toile 01 - Off-White Wallcovering \| Nina Campbell |
+| NCW4205-03 | EUR-80241 | Blue | Barbary Toile 03 - Airy Blue Wallcovering \| Nina Campbell |
+| NCW4205-04 | EUR-80242 | Pink | Barbary Toile 04 - Rose Madder Wallcovering \| Nina Campbell |
+| NCW4205-05 | EUR-80243 | White | Barbary Toile 05 - Off-White Wallcovering \| Nina Campbell |
+| NCW4206-02 | EUR-80245 | White | Tagus 02 - Off-White Wallcovering \| Nina Campbell |
+| NCW4207-01 | EUR-80254 | Beige | Fontibre 01 - Neutral Beige Wallcovering \| Nina Campbell |
+| NCW4207-02 | EUR-80255 | Beige | Fontibre 02 - Warm Neutral Wallcovering \| Nina Campbell |
+| NCW4207-03 | EUR-80256 | Green | Fontibre Fontibre Blue/Green - Blue Wallcovering \| Nina Campbell |
+| NCW4207-04 | EUR-80257 | Beige | Fontibre 04 - Soft Beige Wallcovering \| Nina Campbell |
+| NCW4207-05 | EUR-80258 | Beige | Fontibre 05 - Neutral Beige Wallcovering \| Nina Campbell |
+| NCW4270-01 | EUR-80259 | Grey | Coromandel 01 - Charcoal Wallcovering \| Nina Campbell |
+| NCW4270-02 | EUR-80260 | Pink | Coromandel 02 - Coral Pink Wallcovering \| Nina Campbell |
+| NCW4270-03 | EUR-80261 | White | Coromandel 03 - Off-White Wallcovering \| Nina Campbell |
+| NCW4270-04 | EUR-80262 | Grey | Coromandel 04 - Charcoal Gray Wallcovering \| Nina Campbell |
+| NCW4270-05 | EUR-80263 | White | Coromandel 05 - Off-White Wallcovering \| Nina Campbell |
+| NCW4270-06 | EUR-80264 | Green | Coromandel 06 - Deep Forest Wallcovering \| Nina Campbell |
+| NCW4271-01 | EUR-80265 | Grey | Vignola 01 - Cool Gray Wallcovering \| Nina Campbell |
+| NCW4271-02 | EUR-80266 | Yellow | Vignola 02 - Creamy Yellow Wallcovering \| Nina Campbell |
+| NCW4272-01 | EUR-80267 | Blue | Pavilion Garden 01 - Midnight Blue Wallcovering \| Nina Campbell |
+| NCW4272-02 | EUR-80268 | Grey | Pavilion Garden 02 - Pale Gray Wallcovering \| Nina Campbell |
+| NCW4272-03 | EUR-80269 | Blue | Pavilion Garden 03 - Powder Blue Wallcovering \| Nina Campbell |
+| NCW4272-04 | EUR-80270 | Black | Pavilion Garden 04 - Onyx Wallcovering \| Nina Campbell |
+| NCW4273-04 | EUR-80274 | White | Gioconda Flock Velvet 04 - Off-White Wallcovering \| Nina Campbell |
+| NCW4274-02 | EUR-80278 | Turquoise | Palmetto 02 - Pale Aqua Wallcovering \| Nina Campbell |
+| NCW4274-03 | EUR-80279 | White | Palmetto 03 - Off-White Wallcovering \| Nina Campbell |
+| NCW4274-04 | EUR-80280 | White | Palmetto 04 - Off-White Wallcovering \| Nina Campbell |
+| NCW4274-05 | EUR-80281 | Beige | Palmetto 05 - Warm Neutral Wallcovering \| Nina Campbell |
+| NCW4274-06 | EUR-80282 | White | Palmetto 06 - Ecru Wallcovering \| Nina Campbell |
+| NCW4274-07 | EUR-80283 | Pink | Palmetto 07 - Blush Pink Wallcovering \| Nina Campbell |
+| NCW4275-01 | EUR-80277 | Turquoise | Concertina 01 - Seafoam Green Wallcovering \| Nina Campbell |
+| NCW4276-01 | EUR-80285 | Purple | Perdana 01 - Aubergine Wallcovering \| Nina Campbell |
+| NCW4276-02 | EUR-80286 | White | Perdana 02 - Off-White Wallcovering \| Nina Campbell |
+| NCW4276-03 | EUR-80287 | Purple | Perdana 03 - Orchid Tint Wallcovering \| Nina Campbell |
+| NCW4276-04 | EUR-80288 | Blue | Perdana 04 - Airy Blue Wallcovering \| Nina Campbell |
+| NCW4276-05 | EUR-80289 | Beige | Perdana 05 - Greige Wallcovering \| Nina Campbell |
+| NCW4277-01 | EUR-80291 | White | Meredith 01 - Off-White Wallcovering \| Nina Campbell |
+| NCW4277-02 | EUR-80292 | Grey | Meredith 02 - Neutral Gray Wallcovering \| Nina Campbell |
+| NCW4277-03 | EUR-80293 | Brown | Meredith 03 - Taupe Wallcovering \| Nina Campbell |
+| NCW4277-04 | EUR-80294 | Pink | Meredith 04 - Coral Pink Wallcovering \| Nina Campbell |
+| NCW4277-05 | EUR-80295 | Green | Meredith 05 - Celadon Green Wallcovering \| Nina Campbell |
+| NCW4277-06 | EUR-80296 | Turquoise | Meredith 06 - Aqua Blue Wallcovering \| Nina Campbell |
+| NCW4277-07 | EUR-80297 | Blue | Meredith 07 - Delft Blue Wallcovering \| Nina Campbell |
+| NCW4300-01 | EUR-80299 | White | Collioure 01 - Off-White Wallcovering \| Nina Campbell |
+| NCW4300-02 | EUR-80300 | Brown | Collioure 02 - Brown Wallcovering \| Nina Campbell |
+| NCW4300-03 | EUR-80301 | Turquoise | Collioure 03 - Aqua Green Wallcovering \| Nina Campbell |
+| NCW4300-04 | EUR-80302 | Blue | Collioure 04 - Blue Wallcovering \| Nina Campbell |
+| NCW4300-05 | EUR-80303 | Brown | Collioure 05 - Brown Wallcovering \| Nina Campbell |
+| NCW4301-01 | EUR-80304 | Turquoise | Beau Rivage 01 - Aqua Wallcovering \| Nina Campbell |
+| NCW4301-02 | EUR-80305 | Pink | Beau Rivage 02 - Pink Wallcovering \| Nina Campbell |
+| NCW4301-03 | EUR-80306 | Gold | Beau Rivage 03 - Gold Wallcovering \| Nina Campbell |
+| NCW4301-04 | EUR-80307 | Brown | Beau Rivage 04 - Brown Wallcovering \| Nina Campbell |
+| NCW4301-05 | EUR-80308 | Green | Beau Rivage 05 - Chartreuse Green Wallcovering \| Nina Campbell |
+| NCW4301-06 | EUR-80309 | Blue | Beau Rivage 06 - Blue Wallcovering \| Nina Campbell |
+| NCW4302-01 | EUR-80311 | Grey | Mourlot 01 - Grey Wallcovering \| Nina Campbell |
+| NCW4302-02 | EUR-80312 | Grey | Mourlot 02 - Grey Wallcovering \| Nina Campbell |
+| NCW4302-03 | EUR-80313 | Green | Mourlot 03 - Celadon Green Wallcovering \| Nina Campbell |
+| NCW4302-04 | EUR-80314 | Blue | Mourlot 04 - Blue Wallcovering \| Nina Campbell |
+| NCW4303-01 | EUR-80315 | Blue | Camille 01 - Blue Wallcovering \| Nina Campbell |
+| NCW4303-02 | EUR-80316 | Green | Camille 02 - Green Wallcovering \| Nina Campbell |
+| NCW4303-03 | EUR-80317 | Blue | Camille 03 - Blue Wallcovering \| Nina Campbell |
+| NCW4303-04 | EUR-80318 | Brown | Camille 04 - Brown Wallcovering \| Nina Campbell |
+| NCW4303-05 | EUR-80319 | Pink | Camille 05 - Pink Wallcovering \| Nina Campbell |
+| NCW4304-01 | EUR-80320 | White | Les RêVes Marguerite Green/Ivory - Green Wallcovering \| Nina Campbell |
+| NCW4304-02 | EUR-80321 | Grey | Marguerite Damask 02 - Grey Wallcovering \| Nina Campbell |
+| NCW4304-03 | EUR-80322 | Grey | Marguerite Damask 03 - Grey Wallcovering \| Nina Campbell |
+| NCW4304-04 | EUR-80323 | Brown | Marguerite Damask 04 - Brown Wallcovering \| Nina Campbell |
+| NCW4304-05 | EUR-80324 | Blue | Marguerite Damask 05 - Blue Wallcovering \| Nina Campbell |
+| NCW4304-06 | EUR-80325 | Blue | Marguerite Damask 06 - Blue Wallcovering \| Nina Campbell |
+| NCW4305-01 | EUR-80326 | White | Pampelonne 01 - Off-White Wallcovering \| Nina Campbell |
+| NCW4305-02 | EUR-80327 | Grey | Pampelonne 02 - Grey Wallcovering \| Nina Campbell |
+| NCW4305-03 | EUR-80328 | Brown | Pampelonne 03 - Brown Wallcovering \| Nina Campbell |
+| NCW4305-04 | EUR-80329 | Blue | Pampelonne 04 - Blue Wallcovering \| Nina Campbell |
+| NCW4305-05 | EUR-80330 | Blue | Pampelonne 05 - Blue Wallcovering \| Nina Campbell |
+| NCW4306-01 | EUR-80331 | Pink | Belle Ile Stripe 01 - Rose Quartz Wallcovering \| Nina Campbell |
+| NCW4306-02 | EUR-80332 | Brown | Belle Ile Stripe 02 - Brown Wallcovering \| Nina Campbell |
+| NCW4306-03 | EUR-80333 | Green | Belle Ile Stripe 03 - Celadon Green Wallcovering \| Nina Campbell |
+| NCW4306-04 | EUR-80334 | Blue | Belle Ile Stripe 04 - Blue Wallcovering \| Nina Campbell |
+| NCW4306-05 | EUR-80335 | Blue | Belle Ile Stripe 05 - Denim Blue Wallcovering \| Nina Campbell |
+| NCW4307-01 | EUR-80336 | Black | Dormiers Stripe 01 - Black Wallcovering \| Nina Campbell |
+| NCW4307-02 | EUR-80337 | Grey | Dormiers Stripe 02 - Grey Wallcovering \| Nina Campbell |
+| NCW4307-03 | EUR-80338 | Blue | Dormiers Stripe 03 - Blue Wallcovering \| Nina Campbell |
+| NCW4307-04 | EUR-80339 | Blue | Dormiers Stripe 04 - Blue Wallcovering \| Nina Campbell |
+| NCW4308-01 | EUR-80340 | Brown | Portavo Damask 01 - Brown Wallcovering \| Nina Campbell |
+| NCW4308-02 | EUR-80341 | Grey | Portavo Damask 02 - Grey Wallcovering \| Nina Campbell |
+| NCW4308-03 | EUR-80342 | Blue | Portavo Damask 03 - Blue Wallcovering \| Nina Campbell |
+| NCW4308-04 | EUR-80343 | Orange | Portavo Damask 04 - Orange Wallcovering \| Nina Campbell |
+| NCW4350-01 | EUR-80344 | Multi | Les Indiennes Paisley Damask 01 - Multi Wallcovering \| Nina Campbell |
+| NCW4350-02 | EUR-80345 | Grey | Les Indiennes Paisley Damask 02 - Grey Wallcovering \| Nina Campbell |
+| NCW4350-03 | EUR-80346 | Blue | Les Indiennes Paisley Damask 03 - Blue Wallcovering \| Nina Campbell |
+| NCW4350-04 | EUR-80347 | Black | Les Indiennes Paisley Damask 04 - Black Wallcovering \| Nina Campbell |
+| NCW4350-05 | EUR-80348 | Blue | Les Indiennes Paisley Damask 05 - Blue Wallcovering \| Nina Campbell |
+| NCW4350-06 | EUR-80349 | Black | Les Indiennes Paisley Damask 06 - Black Wallcovering \| Nina Campbell |
+| NCW4351-01 | EUR-80351 | Beige | Baville 01 - Neutral Wallcovering \| Nina Campbell |
+| NCW4351-02 | EUR-80352 | White | Baville 02 - Off-White Wallcovering \| Nina Campbell |
+| NCW4351-03 | EUR-80353 | Blue | Baville 03 - Blue Wallcovering \| Nina Campbell |
+| NCW4351-04 | EUR-80354 | Green | Baville 04 - Green Wallcovering \| Nina Campbell |
+| NCW4351-05 | EUR-80355 | Blue | Baville 05 - Blue Wallcovering \| Nina Campbell |
+| NCW4351-06 | EUR-80356 | Grey | Baville 06 - Grey Wallcovering \| Nina Campbell |
+| NCW4352-01 | EUR-80357 | White | Bonnelles Diamond 01 - Off-White Wallcovering \| Nina Campbell |
+| NCW4352-02 | EUR-80358 | Grey | Bonnelles Diamond 02 - Pale Gray Wallcovering \| Nina Campbell |
+| NCW4352-03 | EUR-80359 | Blue | Bonnelles Diamond 03 - Blue Wallcovering \| Nina Campbell |
+| NCW4352-04 | EUR-80360 | Beige | Bonnelles Diamond 04 - Bisque Wallcovering \| Nina Campbell |
+| NCW4352-05 | EUR-80361 | White | Les Indiennes Bonnelles Green/Ivory - Green Wallcovering \| Nina Campbell |
+| NCW4352-06 | EUR-80362 | Black | Bonnelles Diamond 06 - Black Wallcovering \| Nina Campbell |
+| NCW4353-01 | EUR-80365 | Blue | Colbert 01 - Blue Wallcovering \| Nina Campbell |
+| NCW4353-02 | EUR-80366 | Grey | Colbert 02 - Grey Wallcovering \| Nina Campbell |
+| NCW4353-03 | EUR-80367 | White | Colbert 03 - Off-White Wallcovering \| Nina Campbell |
+| NCW4353-04 | EUR-80368 | Green | Colbert 04 - Chartreuse Green Wallcovering \| Nina Campbell |
+| NCW4353-05 | EUR-80369 | Blue | Colbert 05 - Cerulean Blue Wallcovering \| Nina Campbell |
+| NCW4353-06 | EUR-80370 | Grey | Colbert 06 - Grey Wallcovering \| Nina Campbell |
+| NCW4354-01 | EUR-80371 | Pink | Garance 01 - Pink Wallcovering \| Nina Campbell |
+| NCW4354-02 | EUR-80372 | Turquoise | Garance 02 - Aqua Tint Wallcovering \| Nina Campbell |
+| NCW4354-03 | EUR-80373 | Grey | Garance 03 - Grey Wallcovering \| Nina Campbell |
+| NCW4354-04 | EUR-80374 | Green | Garance 04 - Chartreuse Green Wallcovering \| Nina Campbell |
+| NCW4354-05 | EUR-80375 | Black | Garance 05 - Black Wallcovering \| Nina Campbell |
+| NCW4355-01 | EUR-80377 | Gold | Arles 01 - Gold Wallcovering \| Nina Campbell |
+| NCW4355-02 | EUR-80378 | Grey | Arles 02 - Grey Wallcovering \| Nina Campbell |
+| NCW4355-03 | EUR-80379 | White | Arles 03 - Off-White Wallcovering \| Nina Campbell |
+| NCW4356-01 | EUR-80380 | Gold | Fortoiseau 01 - Gold Wallcovering \| Nina Campbell |
+| NCW4356-02 | EUR-80381 | Brown | Fortoiseau 02 - Brown Wallcovering \| Nina Campbell |
+| NCW4356-03 | EUR-80382 | Grey | Fortoiseau 03 - Cool Gray Wallcovering \| Nina Campbell |
+| NCW4356-04 | EUR-80383 | Blue | Fortoiseau 04 - Pale Blue Wallcovering \| Nina Campbell |
+| NCW4356-05 | EUR-80384 | Black | Fortoiseau 05 - Onyx Wallcovering \| Nina Campbell |
+| NCW4390-01 | EUR-80386 | Blue | Ashdown Pomegranate Trail Indigo/Blue - Blue Wallcovering \| Nina Campbell |
+| NCW4390-02 | EUR-80387 | Turquoise | Pomegranate Trail 02 - Aqua Wallcovering \| Nina Campbell |
+| NCW4390-03 | EUR-80388 | Green | Pomegranate Trail 03 - Green Wallcovering \| Nina Campbell |
+| NCW4390-04 | EUR-80389 | Green | Pomegranate Trail 04 - Chartreuse Wallcovering \| Nina Campbell |
+| NCW4390-05 | EUR-80390 | Pink | Pomegranate Trail 05 - Pink Wallcovering \| Nina Campbell |
+| NCW4391-01 | EUR-80391 | Brown | Cloisters 01 - Brown Wallcovering \| Nina Campbell |
+| NCW4391-02 | EUR-80392 | Blue | Cloisters 02 - Blue Wallcovering \| Nina Campbell |
+| NCW4391-03 | EUR-80393 | Green | Cloisters 03 - Green Wallcovering \| Nina Campbell |
+| NCW4391-04 | EUR-80394 | Blue | Cloisters 04 - Blue Wallcovering \| Nina Campbell |
+| NCW4392-01 | EUR-80395 | Blue | Chelwood Floral Damask 01 - Blue Wallcovering \| Nina Campbell |
+| NCW4392-02 | EUR-80396 | Pink | Chelwood Floral Damask 02 - Pink Wallcovering \| Nina Campbell |
+| NCW4392-03 | EUR-80397 | Green | Chelwood Floral Damask 03 - Green Wallcovering \| Nina Campbell |
+| NCW4392-04 | EUR-80398 | Green | Chelwood Floral Damask 04 - Green Wallcovering \| Nina Campbell |
+| NCW4392-05 | EUR-80399 | Blue | Chelwood Floral Damask 05 - Blue Wallcovering \| Nina Campbell |
+| NCW4393-01 | EUR-80400 | Black | Benmore 01 - Black Wallcovering \| Nina Campbell |
+| NCW4393-02 | EUR-80401 | Green | Benmore 02 - Green Wallcovering \| Nina Campbell |
+| NCW4393-03 | EUR-80402 | Blue | Benmore 03 - Blue Wallcovering \| Nina Campbell |
+| NCW4393-04 | EUR-80403 | Brown | Benmore 04 - Brown Wallcovering \| Nina Campbell |
+| NCW4393-05 | EUR-80404 | Grey | Benmore 05 - Grey Wallcovering \| Nina Campbell |
+| NCW4393-06 | EUR-80405 | Grey | Benmore 06 - Grey Wallcovering \| Nina Campbell |
+| NCW4394-01 | EUR-80406 | Pink | Posingford Leaves 01 - Blush Pink Wallcovering \| Nina Campbell |
+| NCW4394-02 | EUR-80407 | White | Posingford Leaves 02 - Ecru Wallcovering \| Nina Campbell |
+| NCW4394-03 | EUR-80408 | Turquoise | Posingford Leaves 03 - Seafoam Green Wallcovering \| Nina Campbell |
+| NCW4394-04 | EUR-80409 | Brown | Posingford Leaves 04 - Brown Wallcovering \| Nina Campbell |
+| NCW4394-05 | EUR-80410 | Green | Posingford Leaves 05 - Green Wallcovering \| Nina Campbell |
+| NCW4395-01 | EUR-80411 | Blue | Kingsley Fans 01 - Blue Wallcovering \| Nina Campbell |
+| NCW4395-02 | EUR-80412 | Brown | Kingsley Fans 02 - Umber Wallcovering \| Nina Campbell |
+| NCW4395-03 | EUR-80413 | Gold | Kingsley Fans 03 - Gold Wallcovering \| Nina Campbell |
+| NCW4395-04 | EUR-80414 | Beige | Kingsley Fans 04 - Neutral Wallcovering \| Nina Campbell |
+| NCW4395-05 | EUR-80415 | Grey | Kingsley Fans 05 - Grey Wallcovering \| Nina Campbell |
+| NCW4395-06 | EUR-80416 | Blue | Kingsley Fans 06 - Blue Wallcovering \| Nina Campbell |
+| NCW4396-01 | EUR-80417 | Grey | Ashdown Brideshead Grey - Grey Wallcovering \| Nina Campbell |
+| NCW4396-02 | EUR-80418 | Grey | Brideshead Scroll Damask 02 - Grey Wallcovering \| Nina Campbell |
+| NCW4396-03 | EUR-80419 | Blue | Brideshead Scroll Damask 03 - Blue Wallcovering \| Nina Campbell |
+| NCW4396-04 | EUR-80420 | White | Brideshead Scroll Damask 04 - Ecru Wallcovering \| Nina Campbell |
+| NCW4490-01 | EUR-80421 | Yellow | Foret 01 - Yellow Wallcovering \| Nina Campbell |
+| NCW4490-02 | EUR-80422 | Brown | Foret 02 - Brown Wallcovering \| Nina Campbell |
+| NCW4490-03 | EUR-80423 | Blue | Foret 03 - Blue Wallcovering \| Nina Campbell |
+| NCW4490-04 | EUR-80424 | Green | Foret 04 - Green Wallcovering \| Nina Campbell |
+| NCW4490-05 | EUR-80425 | Green | Foret 05 - Green Wallcovering \| Nina Campbell |
+| NCW4491-01 | EUR-80426 | Green | Almora 01 - Green Wallcovering \| Nina Campbell |
+| NCW4491-02 | EUR-80427 | Green | Almora 02 - Green Wallcovering \| Nina Campbell |
+| NCW4491-03 | EUR-80428 | Green | Almora 03 - Green Wallcovering \| Nina Campbell |
+| NCW4491-04 | EUR-80429 | Blue | Almora 04 - Blue Wallcovering \| Nina Campbell |
+| NCW4491-05 | EUR-80430 | Turquoise | Almora 05 - Seafoam Green Wallcovering \| Nina Campbell |
+| NCW4492-01 | EUR-80431 | Green | Sackville Stripe 01 - Green Wallcovering \| Nina Campbell |
+| NCW4492-02 | EUR-80432 | Blue | Sackville Stripe 02 - Blue Wallcovering \| Nina Campbell |
+| NCW4492-03 | EUR-80433 | White | Sackville Stripe 03 - White Wallcovering \| Nina Campbell |
+| NCW4492-04 | EUR-80434 | Brown | Sackville Stripe 04 - Brown Wallcovering \| Nina Campbell |
+| NCW4492-05 | EUR-80435 | Blue | Sackville Stripe 05 - Blue Wallcovering \| Nina Campbell |
+| NCW4493-01 | EUR-80436 | Green | Petit Dapuri Stripe 01 - Green Wallcovering \| Nina Campbell |
+| NCW4493-02 | EUR-80437 | Green | Petit Dapuri Stripe 02 - Green Wallcovering \| Nina Campbell |
+| NCW4493-03 | EUR-80438 | Blue | Petit Dapuri Stripe 03 - Blue Wallcovering \| Nina Campbell |
+| NCW4493-04 | EUR-80439 | Green | Petit Dapuri Stripe 04 - Green Wallcovering \| Nina Campbell |
+| NCW4494-01 | EUR-80441 | Brown | Meridor Stripe 01 - Brown Wallcovering \| Nina Campbell |
+| NCW4494-02 | EUR-80442 | Blue | Meridor Stripe 02 - Blue Wallcovering \| Nina Campbell |
+| NCW4494-03 | EUR-80443 | Green | Signature Meridor - Green Wallcovering \| Nina Campbell |
+| NCW4494-04 | EUR-80444 | Beige | Meridor Stripe 04 - Neutral Wallcovering \| Nina Campbell |
+| NCW4494-05 | EUR-80445 | Blue | Meridor Stripe 05 - Blue Wallcovering \| Nina Campbell |
+| NCW4494-06 | EUR-80446 | Blue | Meridor Stripe 06 - Blue Wallcovering \| Nina Campbell |
+| NCW4495-01 | EUR-80447 | Green | Signature Arber - Green Wallcovering \| Nina Campbell |
+| NCW4495-02 | EUR-80448 | Green | Arber Lattice Trellis 02 - Green Wallcovering \| Nina Campbell |
+| NCW4495-03 | EUR-80449 | Blue | Arber Lattice Trellis 03 - Blue Wallcovering \| Nina Campbell |
+| NCW4495-04 | EUR-80450 | Blue | Arber Lattice Trellis 04 - Blue Wallcovering \| Nina Campbell |
+| NCW4496-01 | EUR-80451 | Blue | Plumier Stripe 01 - Blue Wallcovering \| Nina Campbell |
+| NCW4496-02 | EUR-80452 | Blue | Plumier Stripe 02 - Blue Wallcovering \| Nina Campbell |
+| NCW4496-03 | EUR-80453 | Brown | Plumier Stripe 03 - Brown Wallcovering \| Nina Campbell |
+| NCW4496-04 | EUR-80454 | Brown | Plumier Stripe 04 - Brown Wallcovering \| Nina Campbell |
+| NCW4496-05 | EUR-80455 | Beige | Plumier Stripe 05 - Neutral Wallcovering \| Nina Campbell |
+| NCW4496-06 | EUR-80456 | Brown | Plumier Stripe 06 - Brown Wallcovering \| Nina Campbell |
+| NCW4497-01 | EUR-80457 | Brown | Toile Chinoise 01 - Brown Wallcovering \| Nina Campbell |
+| NCW4497-02 | EUR-80458 | Brown | Toile Chinoise 02 - Brown Wallcovering \| Nina Campbell |
+| NCW4497-03 | EUR-80459 | Blue | Toile Chinoise 03 - Blue Wallcovering \| Nina Campbell |
+| NCW4498-01 | EUR-80460 | Blue | Poiteau Bamboo Ferns 01 - Blue Wallcovering \| Nina Campbell |
+| NCW4498-02 | EUR-80461 | White | Poiteau Bamboo Ferns 02 - White Wallcovering \| Nina Campbell |
+| NCW4498-03 | EUR-80462 | Green | Poiteau Bamboo Ferns 03 - Green Wallcovering \| Nina Campbell |
+| NCW4498-04 | EUR-80463 | Blue | Poiteau Bamboo Ferns 04 - Blue Wallcovering \| Nina Campbell |
diff --git a/scripts/ncw-cleanup/ncw-old-to-new-sku-mapping.txt b/scripts/ncw-cleanup/ncw-old-to-new-sku-mapping.txt
new file mode 100644
index 00000000..c0e6c765
--- /dev/null
+++ b/scripts/ncw-cleanup/ncw-old-to-new-sku-mapping.txt
@@ -0,0 +1,124 @@
+Output format is aligned.
+Border style is 2.
++---------+----+----------------+--------------+-------------------+
+| pattern | cw |  old_DWC-NCW   | old_DWC-1001 | new_canonical_SKU |
++---------+----+----------------+--------------+-------------------+
+| NCW4300 | 01 | DWC-NCW4300-01 | DWC-1001555  | → EUR-80299       |
+| NCW4300 | 02 | DWC-NCW4300-02 | DWC-1001556  | → EUR-80300       |
+| NCW4300 | 03 | DWC-NCW4300-03 | DWC-1001557  | → EUR-80301       |
+| NCW4300 | 04 | DWC-NCW4300-04 | DWC-1001558  | → EUR-80302       |
+| NCW4300 | 05 | DWC-NCW4300-05 | DWC-1001559  | → EUR-80303       |
+| NCW4301 | 01 | DWC-NCW4301-01 | DWC-1001560  | → EUR-80304       |
+| NCW4301 | 02 | DWC-NCW4301-02 | DWC-1001561  | → EUR-80305       |
+| NCW4301 | 03 | DWC-NCW4301-03 | DWC-1001562  | → EUR-80306       |
+| NCW4301 | 04 | DWC-NCW4301-04 | DWC-1001563  | → EUR-80307       |
+| NCW4301 | 05 | DWC-NCW4301-05 | DWC-1001564  | → EUR-80308       |
+| NCW4301 | 06 | DWC-NCW4301-06 | DWC-1001565  | → EUR-80309       |
+| NCW4302 | 01 | DWC-NCW4302-01 | DWC-1001566  | → EUR-80311       |
+| NCW4302 | 02 | DWC-NCW4302-02 | DWC-1001567  | → EUR-80312       |
+| NCW4302 | 03 | DWC-NCW4302-03 | DWC-1001568  | → EUR-80313       |
+| NCW4302 | 04 | DWC-NCW4302-04 | DWC-1001569  | → EUR-80314       |
+| NCW4303 | 01 | DWC-NCW4303-01 | DWC-1001570  | → EUR-80315       |
+| NCW4303 | 02 | DWC-NCW4303-02 | DWC-1001571  | → EUR-80316       |
+| NCW4303 | 03 | DWC-NCW4303-03 | DWC-1001572  | → EUR-80317       |
+| NCW4303 | 04 | DWC-NCW4303-04 | DWC-1001573  | → EUR-80318       |
+| NCW4303 | 05 | DWC-NCW4303-05 | DWC-1001574  | → EUR-80319       |
+| NCW4304 | 01 | DWC-NCW4304-01 | DWC-1001575  | → EUR-80320       |
+| NCW4304 | 02 | DWC-NCW4304-02 | DWC-1001576  | → EUR-80321       |
+| NCW4304 | 03 | DWC-NCW4304-03 | DWC-1001577  | → EUR-80322       |
+| NCW4304 | 04 | DWC-NCW4304-04 | DWC-1001578  | → EUR-80323       |
+| NCW4304 | 05 | DWC-NCW4304-05 | DWC-1001579  | → EUR-80324       |
+| NCW4304 | 06 | DWC-NCW4304-06 | DWC-1001580  | → EUR-80325       |
+| NCW4305 | 01 | DWC-NCW4305-01 | DWC-1001581  | → EUR-80326       |
+| NCW4305 | 02 | DWC-NCW4305-02 | DWC-1001582  | → EUR-80327       |
+| NCW4305 | 03 | DWC-NCW4305-03 | DWC-1001583  | → EUR-80328       |
+| NCW4305 | 04 | DWC-NCW4305-04 | DWC-1001584  | → EUR-80329       |
+| NCW4305 | 05 | DWC-NCW4305-05 | DWC-1001585  | → EUR-80330       |
+| NCW4306 | 01 | DWC-NCW4306-01 | DWC-1001586  | → EUR-80331       |
+| NCW4306 | 02 | DWC-NCW4306-02 | DWC-1001587  | → EUR-80332       |
+| NCW4306 | 03 | DWC-NCW4306-03 | DWC-1001588  | → EUR-80333       |
+| NCW4306 | 04 | DWC-NCW4306-04 | DWC-1001589  | → EUR-80334       |
+| NCW4306 | 05 | DWC-NCW4306-05 | DWC-1001590  | → EUR-80335       |
+| NCW4307 | 01 | DWC-NCW4307-01 | DWC-1001591  | → EUR-80336       |
+| NCW4307 | 02 | DWC-NCW4307-02 | DWC-1001592  | → EUR-80337       |
+| NCW4307 | 03 | DWC-NCW4307-03 | DWC-1001593  | → EUR-80338       |
+| NCW4307 | 04 | DWC-NCW4307-04 | DWC-1001594  | → EUR-80339       |
+| NCW4308 | 01 | DWC-NCW4308-01 | DWC-1001595  | → EUR-80340       |
+| NCW4308 | 02 | DWC-NCW4308-02 | DWC-1001596  | → EUR-80341       |
+| NCW4308 | 03 | DWC-NCW4308-03 | DWC-1001597  | → EUR-80342       |
+| NCW4308 | 04 | DWC-NCW4308-04 | DWC-1001598  | → EUR-80343       |
+| NCW4350 | 01 | DWC-NCW4350-01 | DWC-1001599  | → EUR-80344       |
+| NCW4350 | 02 | DWC-NCW4350-02 | DWC-1001600  | → EUR-80345       |
+| NCW4350 | 03 | DWC-NCW4350-03 | DWC-1001601  | → EUR-80346       |
+| NCW4350 | 04 | DWC-NCW4350-04 | DWC-1001602  | → EUR-80347       |
+| NCW4350 | 05 | DWC-NCW4350-05 | DWC-1001603  | → EUR-80348       |
+| NCW4350 | 06 | DWC-NCW4350-06 | DWC-1001604  | → EUR-80349       |
+| NCW4351 | 01 | DWC-NCW4351-01 | DWC-1001605  | → EUR-80351       |
+| NCW4351 | 02 | DWC-NCW4351-02 | —            | → EUR-80352       |
+| NCW4351 | 03 | DWC-NCW4351-03 | DWC-1001607  | → EUR-80353       |
+| NCW4351 | 04 | DWC-NCW4351-04 | DWC-1001608  | → EUR-80354       |
+| NCW4351 | 05 | DWC-NCW4351-05 | DWC-1001609  | → EUR-80355       |
+| NCW4351 | 06 | DWC-NCW4351-06 | DWC-1001610  | → EUR-80356       |
+| NCW4352 | 01 | DWC-NCW4352-01 | DWC-1001611  | → EUR-80357       |
+| NCW4352 | 02 | DWC-NCW4352-02 | DWC-1001612  | → EUR-80358       |
+| NCW4352 | 03 | DWC-NCW4352-03 | DWC-1001613  | → EUR-80359       |
+| NCW4352 | 04 | DWC-NCW4352-04 | DWC-1001614  | → EUR-80360       |
+| NCW4352 | 05 | DWC-NCW4352-05 | DWC-1001615  | → EUR-80361       |
+| NCW4352 | 06 | DWC-NCW4352-06 | DWC-1001616  | → EUR-80362       |
+| NCW4353 | 01 | DWC-NCW4353-01 | DWC-1001617  | → EUR-80365       |
+| NCW4353 | 02 | DWC-NCW4353-02 | DWC-1001618  | → EUR-80366       |
+| NCW4353 | 03 | DWC-NCW4353-03 | DWC-1001619  | → EUR-80367       |
+| NCW4353 | 04 | DWC-NCW4353-04 | DWC-1001620  | → EUR-80368       |
+| NCW4353 | 05 | DWC-NCW4353-05 | DWC-1001621  | → EUR-80369       |
+| NCW4353 | 06 | DWC-NCW4353-06 | DWC-1001622  | → EUR-80370       |
+| NCW4354 | 01 | DWC-NCW4354-01 | DWC-1001623  | → EUR-80371       |
+| NCW4354 | 02 | DWC-NCW4354-02 | DWC-1001624  | → EUR-80372       |
+| NCW4354 | 03 | DWC-NCW4354-03 | DWC-1001625  | → EUR-80373       |
+| NCW4354 | 04 | DWC-NCW4354-04 | DWC-1001626  | → EUR-80374       |
+| NCW4354 | 05 | DWC-NCW4354-05 | DWC-1001627  | → EUR-80375       |
+| NCW4355 | 01 | DWC-NCW4355-01 | DWC-1001628  | → EUR-80377       |
+| NCW4355 | 02 | DWC-NCW4355-02 | DWC-1001629  | → EUR-80378       |
+| NCW4355 | 03 | DWC-NCW4355-03 | DWC-1001630  | → EUR-80379       |
+| NCW4356 | 01 | DWC-NCW4356-01 | DWC-1001631  | → EUR-80380       |
+| NCW4356 | 02 | DWC-NCW4356-02 | DWC-1001632  | → EUR-80381       |
+| NCW4356 | 03 | DWC-NCW4356-03 | DWC-1001633  | → EUR-80382       |
+| NCW4356 | 04 | DWC-NCW4356-04 | DWC-1001634  | → EUR-80383       |
+| NCW4356 | 05 | DWC-NCW4356-05 | DWC-1001635  | → EUR-80384       |
+| NCW4390 | 01 | DWC-NCW4390-01 | DWC-1001636  | → EUR-80386       |
+| NCW4390 | 02 | DWC-NCW4390-02 | DWC-1001637  | → EUR-80387       |
+| NCW4390 | 03 | DWC-NCW4390-03 | DWC-1001638  | → EUR-80388       |
+| NCW4390 | 04 | DWC-NCW4390-04 | DWC-1001639  | → EUR-80389       |
+| NCW4390 | 05 | DWC-NCW4390-05 | DWC-1001640  | → EUR-80390       |
+| NCW4391 | 01 | DWC-NCW4391-01 | DWC-1001641  | → EUR-80391       |
+| NCW4391 | 02 | DWC-NCW4391-02 | DWC-1001642  | → EUR-80392       |
+| NCW4391 | 03 | DWC-NCW4391-03 | DWC-1001643  | → EUR-80393       |
+| NCW4391 | 04 | DWC-NCW4391-04 | DWC-1001644  | → EUR-80394       |
+| NCW4392 | 01 | DWC-NCW4392-01 | DWC-1001645  | → EUR-80395       |
+| NCW4392 | 02 | DWC-NCW4392-02 | DWC-1001646  | → EUR-80396       |
+| NCW4392 | 03 | DWC-NCW4392-03 | DWC-1001647  | → EUR-80397       |
+| NCW4392 | 04 | DWC-NCW4392-04 | DWC-1001648  | → EUR-80398       |
+| NCW4392 | 05 | DWC-NCW4392-05 | DWC-1001649  | → EUR-80399       |
+| NCW4393 | 01 | DWC-NCW4393-01 | —            | → EUR-80400       |
+| NCW4393 | 02 | DWC-NCW4393-02 | DWC-1001651  | → EUR-80401       |
+| NCW4393 | 03 | DWC-NCW4393-03 | DWC-1001652  | → EUR-80402       |
+| NCW4393 | 04 | DWC-NCW4393-04 | DWC-1001653  | → EUR-80403       |
+| NCW4393 | 05 | DWC-NCW4393-05 | DWC-1001654  | → EUR-80404       |
+| NCW4393 | 06 | DWC-NCW4393-06 | DWC-1001655  | → EUR-80405       |
+| NCW4394 | 01 | DWC-NCW4394-01 | DWC-1001656  | → EUR-80406       |
+| NCW4394 | 02 | DWC-NCW4394-02 | DWC-1001657  | → EUR-80407       |
+| NCW4394 | 03 | DWC-NCW4394-03 | DWC-1001658  | → EUR-80408       |
+| NCW4394 | 04 | DWC-NCW4394-04 | DWC-1001659  | → EUR-80409       |
+| NCW4394 | 05 | DWC-NCW4394-05 | DWC-1001660  | → EUR-80410       |
+| NCW4395 | 01 | DWC-NCW4395-01 | DWC-1001661  | → EUR-80411       |
+| NCW4395 | 02 | DWC-NCW4395-02 | DWC-1001662  | → EUR-80412       |
+| NCW4395 | 03 | DWC-NCW4395-03 | DWC-1001663  | → EUR-80413       |
+| NCW4395 | 04 | DWC-NCW4395-04 | DWC-1001664  | → EUR-80414       |
+| NCW4395 | 05 | DWC-NCW4395-05 | —            | → EUR-80415       |
+| NCW4395 | 06 | DWC-NCW4395-06 | DWC-1001666  | → EUR-80416       |
+| NCW4396 | 01 | DWC-NCW4396-01 | DWC-1001667  | → EUR-80417       |
+| NCW4396 | 02 | DWC-NCW4396-02 | DWC-1001668  | → EUR-80418       |
+| NCW4396 | 03 | DWC-NCW4396-03 | DWC-1001669  | → EUR-80419       |
+| NCW4396 | 04 | DWC-NCW4396-04 | DWC-1001670  | → EUR-80420       |
++---------+----+----------------+--------------+-------------------+
+(116 rows)
+
diff --git a/scripts/ncw-cleanup/rename-variant-skus.js b/scripts/ncw-cleanup/rename-variant-skus.js
new file mode 100644
index 00000000..81056545
--- /dev/null
+++ b/scripts/ncw-cleanup/rename-variant-skus.js
@@ -0,0 +1,100 @@
+#!/usr/bin/env node
+// Rename variant SKUs on the 298 active NCW EUR canonicals from "DWC-NCW####"
+// (shared across colorways) to their unique "EUR-80###" form (postgres dw_sku).
+// Idempotent: skips products whose variant.sku already starts with EUR-.
+
+const path = require('path');
+const fs = require('fs');
+const envText = fs.readFileSync(path.join(__dirname, '../../.env'), 'utf8');
+const env = Object.fromEntries(envText.split('\n').map(l => l.match(/^([A-Z0-9_]+)=(.*)$/)).filter(Boolean).map(m => [m[1], m[2]]));
+const TOKEN = env.SHOPIFY_ADMIN_ACCESS_TOKEN;
+const GQL = `https://${env.SHOPIFY_STORE_DOMAIN}/admin/api/2024-10/graphql.json`;
+
+async function gql(q, v = {}) {
+  const r = await fetch(GQL, {
+    method: 'POST',
+    headers: { 'X-Shopify-Access-Token': TOKEN, 'Content-Type': 'application/json' },
+    body: JSON.stringify({ query: q, variables: v }),
+  });
+  return r.json();
+}
+
+const sleep = ms => new Promise(r => setTimeout(r, ms));
+
+(async () => {
+  const { Client } = require('pg');
+  const pg = new Client({ user: 'stevestudio2', database: 'dw_unified', host: '/tmp' });
+  await pg.connect();
+
+  const { rows } = await pg.query(`
+    SELECT shopify_id, dw_sku, mfr_sku, title
+    FROM shopify_products
+    WHERE mfr_sku ILIKE 'NCW%'
+      AND vendor IN ('Nina Campbell','Nina Campbell Wallcoverings')
+      AND dw_sku LIKE 'EUR-%'
+      AND status = 'ACTIVE'
+    ORDER BY dw_sku;
+  `);
+
+  console.log(`# Variant SKU rename — ${rows.length} candidates`);
+  let renamed = 0, alreadyEur = 0, errors = 0, missing = 0;
+  const audit = [];
+
+  for (let i = 0; i < rows.length; i++) {
+    const r = rows[i];
+    try {
+      const j = await gql(`{ product(id:"${r.shopify_id}"){ id status variants(first:5){ nodes{ id sku title } } } }`);
+      const p = j.data?.product;
+      if (!p || p.status !== 'ACTIVE') { missing++; continue; }
+      // Pick the Sample variant (or the only variant)
+      const variant = p.variants.nodes.find(v => /sample/i.test(v.title || '')) || p.variants.nodes[0];
+      if (!variant) { missing++; continue; }
+      const current = variant.sku || '';
+      if (/^EUR-/i.test(current)) { alreadyEur++; continue; }
+      const newSku = `${r.dw_sku}-Sample`;
+      // 2024-10: SKU moved to inventoryItem; productVariantUpdate is deprecated.
+      const m = await gql(
+        `mutation($pid:ID!,$variants:[ProductVariantsBulkInput!]!){
+          productVariantsBulkUpdate(productId:$pid, variants:$variants){
+            productVariants{ id sku }
+            userErrors{ field message }
+          }
+        }`,
+        { pid: r.shopify_id, variants: [{ id: variant.id, inventoryItem: { sku: newSku } }] }
+      );
+      const ue = m.data?.productVariantsBulkUpdate?.userErrors || [];
+      const updatedSku = m.data?.productVariantsBulkUpdate?.productVariants?.[0]?.sku;
+      if (!ue.length && updatedSku !== newSku) {
+        // Defensive: check that sku actually changed
+        ue.push({ message: `silent no-op: returned sku=${updatedSku}` });
+      }
+      if (ue.length) {
+        errors++;
+        audit.push({ ok: false, dw: r.dw_sku, current, attempted: newSku, err: ue });
+        console.log(`  ! ${r.dw_sku}: ${JSON.stringify(ue)}`);
+      } else {
+        renamed++;
+        audit.push({ ok: true, dw: r.dw_sku, from: current, to: newSku, title: r.title });
+      }
+      if ((renamed + alreadyEur) % 25 === 0) console.log(`  progress: renamed=${renamed} already_eur=${alreadyEur} errors=${errors} (${i + 1}/${rows.length})`);
+      await sleep(280);
+    } catch (e) {
+      errors++;
+      audit.push({ ok: false, dw: r.dw_sku, err: e.message });
+      console.log(`  ! ${r.dw_sku}: ${e.message}`);
+    }
+  }
+
+  console.log(`\n## Done`);
+  console.log(`  renamed       : ${renamed}/${rows.length}`);
+  console.log(`  already EUR-* : ${alreadyEur}`);
+  console.log(`  missing/draft : ${missing}`);
+  console.log(`  errors        : ${errors}`);
+
+  const ts = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
+  const out = path.join(__dirname, `audit-rename-${ts}.json`);
+  fs.writeFileSync(out, JSON.stringify({ renamed, alreadyEur, missing, errors, audit }, null, 2));
+  console.log(`  audit         : ${out}`);
+
+  await pg.end();
+})();
diff --git a/scripts/prl-ai-enrich.js b/scripts/prl-ai-enrich.js
index a8c35e4c..35f8023b 100644
--- a/scripts/prl-ai-enrich.js
+++ b/scripts/prl-ai-enrich.js
@@ -7,7 +7,7 @@
 const https = require('https');
 const { Client } = require('pg');
 
-const GEMINI_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_KEY = '${GOOGLE_API_KEY}';
 const GEMINI_MODEL = 'gemini-2.0-flash';
 const GEMINI_URL = `https://generativelanguage.googleapis.com/v1beta/models/${GEMINI_MODEL}:generateContent?key=${GEMINI_KEY}`;
 const BATCH_SIZE = 100;
@@ -215,7 +215,7 @@ async function main() {
   try {
     const slackBody = JSON.stringify({ text: slackMsg });
     await new Promise((resolve, reject) => {
-      const req = https.request('https://hooks.slack.com/services/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', {
+      const req = https.request('${SLACK_WEBHOOK_URL}', {
         method: 'POST',
         headers: { 'Content-Type': 'application/json' }
       }, resolve);
diff --git a/scripts/push-mfr-to-shopify.js b/scripts/push-mfr-to-shopify.js
index e37801e0..b34012b9 100644
--- a/scripts/push-mfr-to-shopify.js
+++ b/scripts/push-mfr-to-shopify.js
@@ -78,7 +78,7 @@ async function run() {
   console.log(`\n🏁 Done! Updated: ${updated}, Failed: ${failed}, Duration: ${duration}min`);
 
   // Slack
-  fetch('https://hooks.slack.com/services/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', {
+  fetch('${SLACK_WEBHOOK_URL}', {
     method: 'POST', headers: { 'Content-Type': 'application/json' },
     body: JSON.stringify({ text: `✅ *MFR Push to Shopify*: ${updated} products updated, ${failed} failed, ${duration}min` })
   }).catch(() => {});
diff --git a/scripts/ralph/prd-ralph-lauren-fabrics.json b/scripts/ralph/prd-ralph-lauren-fabrics.json
index acd9aeb6..e52be424 100644
--- a/scripts/ralph/prd-ralph-lauren-fabrics.json
+++ b/scripts/ralph/prd-ralph-lauren-fabrics.json
@@ -60,7 +60,7 @@
       "description": "As a system, I want to analyze fabric images with Gemini 3.0 to generate accurate color and style tags so that products are properly categorized.",
       "acceptanceCriteria": [
         "Uses Gemini 3.0 (gemini-2.0-flash) exclusively - NO Claude Vision",
-        "API Key: REDACTED_GEMINI_KEY",
+        "API Key: ${GOOGLE_API_KEY}",
         "Analyzes fabric images for dominant colors (max 3 per color family)",
         "Identifies style/period (Traditional, Contemporary, etc.)",
         "Identifies pattern type (Floral, Geometric, Damask, etc.)",
diff --git a/scripts/run-wallpaper-cleanup-remaining.sh b/scripts/run-wallpaper-cleanup-remaining.sh
index dbad12bc..7bd11d5e 100755
--- a/scripts/run-wallpaper-cleanup-remaining.sh
+++ b/scripts/run-wallpaper-cleanup-remaining.sh
@@ -17,4 +17,4 @@ echo "All phases complete."
 # Final slack notification
 curl -s -X POST -H 'Content-type: application/json' \
   --data '{"text":"✅ *ALL WALLPAPER CLEANUP PHASES COMPLETE*\nTitles, Tags, and Body HTML all processed.\nCheck /tmp/wallpaper-*.log for details."}' \
-  "https://hooks.slack.com/services/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"
+  "${SLACK_WEBHOOK_URL}"
diff --git a/scripts/rw-drapery-daily-cron.sh b/scripts/rw-drapery-daily-cron.sh
index 2698165e..87e395e2 100755
--- a/scripts/rw-drapery-daily-cron.sh
+++ b/scripts/rw-drapery-daily-cron.sh
@@ -32,7 +32,7 @@ WHERE spec_design LIKE '%Solid%'
 echo "Remaining without room settings: $REMAINING" >> "$LOG"
 
 # Send Slack notification
-SLACK_WEBHOOK="https://hooks.slack.com/services/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"
+SLACK_WEBHOOK="${SLACK_WEBHOOK_URL}"
 curl -s -X POST -H 'Content-type: application/json' \
   --data "{\"text\":\"🏠 *RW Drapery Room Settings Daily Run*\n• Total images: $TOTAL\n• Remaining: $REMAINING\n• Log: $LOG\"}" \
   "$SLACK_WEBHOOK" >> /dev/null 2>&1
diff --git a/scripts/rw-drapery-room-settings.js b/scripts/rw-drapery-room-settings.js
index c97459cb..db89ca24 100644
--- a/scripts/rw-drapery-room-settings.js
+++ b/scripts/rw-drapery-room-settings.js
@@ -15,7 +15,7 @@ const fs = require('fs');
 const path = require('path');
 
 // Config
-const GEMINI_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_KEY = '${GOOGLE_API_KEY}';
 const IMAGEN_MODEL = 'imagen-4.0-generate-001';
 const OUTPUT_DIR = '/root/Projects/Designer-Wallcoverings/room-settings/rw-drapery';
 const CONCURRENCY = 1;
diff --git a/scripts/standardize-product-types-bulk.js b/scripts/standardize-product-types-bulk.js
index 4aa87e87..d249d09c 100644
--- a/scripts/standardize-product-types-bulk.js
+++ b/scripts/standardize-product-types-bulk.js
@@ -12,7 +12,7 @@ const SHOPIFY_DOMAIN = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_TOKEN = '***REMOVED***';
 const API_VERSION = '2024-10';
 const GQL_URL = `https://${SHOPIFY_DOMAIN}/admin/api/${API_VERSION}/graphql.json`;
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
 const DRY_RUN = process.argv.includes('--dry-run');
 const fs = require('fs');
diff --git a/scripts/standardize-product-types.js b/scripts/standardize-product-types.js
index 6ce47b6d..94de3faa 100644
--- a/scripts/standardize-product-types.js
+++ b/scripts/standardize-product-types.js
@@ -12,7 +12,7 @@ const SHOPIFY_DOMAIN = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_TOKEN = '***REMOVED***';
 const API_VERSION = '2024-10';
 const GQL_URL = `https://${SHOPIFY_DOMAIN}/admin/api/${API_VERSION}/graphql.json`;
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
 const DRY_RUN = process.argv.includes('--dry-run');
 const BATCH_FILTER = process.argv.find(a => a.startsWith('--batch='))?.split('=')[1] || null;
diff --git a/scripts/supplier-mfr-bulk-push.js b/scripts/supplier-mfr-bulk-push.js
index 9a15b2c7..4ebb0d9f 100644
--- a/scripts/supplier-mfr-bulk-push.js
+++ b/scripts/supplier-mfr-bulk-push.js
@@ -84,7 +84,7 @@ async function run() {
   console.log(`\n🏁 Done! Updated: ${updated}, Failed: ${failed}, Duration: ${duration}min`);
 
   // Slack notification
-  await fetch('https://hooks.slack.com/services/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', {
+  await fetch('${SLACK_WEBHOOK_URL}', {
     method: 'POST',
     headers: { 'Content-Type': 'application/json' },
     body: JSON.stringify({ text: `🔥 *Supplier + MFR Bulk Push Complete*\n• Updated: ${updated}\n• Failed: ${failed}\n• Duration: ${duration} min` })
diff --git a/scripts/texture-repeat-classifier.js b/scripts/texture-repeat-classifier.js
index 2baa9275..aacaee64 100644
--- a/scripts/texture-repeat-classifier.js
+++ b/scripts/texture-repeat-classifier.js
@@ -10,9 +10,9 @@ const https = require('https');
 const http = require('http');
 
 const pool = new Pool({ connectionString: 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified' });
-const GEMINI_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_KEY = '${GOOGLE_API_KEY}';
 const GEMINI_URL = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${GEMINI_KEY}`;
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
 const PROMPT = `Is this wallcovering image a repeating pattern or a non-repeating texture? If it's a texture (grasscloth, linen, plain, solid, stucco, metallic, stone, concrete, weave, velvet, silk, etc.), respond 'TEXTURE'. If it has a visible repeating pattern (florals, stripes, damask, geometric, medallion, toile, scenic, mural, houndstooth, ikat, etc.), respond 'PATTERN'. Respond with only one word: TEXTURE or PATTERN.`;
 
diff --git a/scripts/us-007-ai-product-quality-analyzer.ts b/scripts/us-007-ai-product-quality-analyzer.ts
index 79147e95..a26f778e 100644
--- a/scripts/us-007-ai-product-quality-analyzer.ts
+++ b/scripts/us-007-ai-product-quality-analyzer.ts
@@ -12,7 +12,7 @@
 
 import { ManufacturerProductData } from './us-005-fetch-manufacturer-data';
 
-const GEMINI_API_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_API_KEY = '${GOOGLE_API_KEY}';
 const GEMINI_MODEL = 'gemini-2.0-flash';
 
 export interface ProductDataComparison {
diff --git a/shopify/.gitignore b/shopify/.gitignore
index 16876df9..9a1b829b 100644
--- a/shopify/.gitignore
+++ b/shopify/.gitignore
@@ -50,3 +50,9 @@ Thumbs.db
 
 # Claude
 .claude/
+node_modules/
+.env.*.local
+.env.*
+tmp/
+.next/
+*.bak
diff --git a/shopify/scripts/add-missing-samples-v2.js b/shopify/scripts/add-missing-samples-v2.js
index 4da4f9a7..aeabf4b7 100644
--- a/shopify/scripts/add-missing-samples-v2.js
+++ b/shopify/scripts/add-missing-samples-v2.js
@@ -22,7 +22,7 @@ const TOKEN = '***REMOVED***';
 const API_VER = '2024-10';
 const LOCATION_GID = 'gid://shopify/Location/5795643504';
 const PROGRESS_FILE = '/root/Projects/Designer-Wallcoverings/shopify/scripts/sample-v2-progress.json';
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 const DELAY_MS = 600; // ms between REST variant creates
 
 // ─── Helpers ───────────────────────────────────────────────────────────
diff --git a/shopify/scripts/arte-dashboard/server.js b/shopify/scripts/arte-dashboard/server.js
index f12c96db..df36a4dd 100644
--- a/shopify/scripts/arte-dashboard/server.js
+++ b/shopify/scripts/arte-dashboard/server.js
@@ -1552,7 +1552,7 @@ app.get('/api/stats', (req, res) => {
 });
 
 // Gemini 3.0 API for image analysis
-const GEMINI_API_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_API_KEY = '${GOOGLE_API_KEY}';
 
 // Clean Gemini response - remove "Label: " prefixes, keep only value after colon
 function cleanGeminiValue(value) {
diff --git a/shopify/scripts/batch-room-settings.py b/shopify/scripts/batch-room-settings.py
index b134b923..454d0f94 100644
--- a/shopify/scripts/batch-room-settings.py
+++ b/shopify/scripts/batch-room-settings.py
@@ -23,7 +23,7 @@ DB_URL = "postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified"
 ROOM_API = "http://localhost:3075/api/generate-room"
 SHOPIFY_STORE = "designer-laboratory-sandbox.myshopify.com"
 SHOPIFY_TOKEN = "***REMOVED***"
-SLACK_WEBHOOK = "https://hooks.slack.com/services/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"
+SLACK_WEBHOOK = "${SLACK_WEBHOOK_URL}"
 BATCH_SIZE = 500
 ROOM_OUTPUT_DIR = "/tmp/room-settings"
 
diff --git a/shopify/scripts/batch-room-settings/batch-room-generator.js b/shopify/scripts/batch-room-settings/batch-room-generator.js
index 343ee9c4..d2d1c0ac 100644
--- a/shopify/scripts/batch-room-settings/batch-room-generator.js
+++ b/shopify/scripts/batch-room-settings/batch-room-generator.js
@@ -22,10 +22,10 @@ const path = require('path');
 // ─── Config ────────────────────────────────────────────────────────────────
 const SHOPIFY_STORE = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_TOKEN = '***REMOVED***';
-const GEMINI_VISION_KEY = 'REDACTED_GEMINI_KEY';
-const GEMINI_IMAGE_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_VISION_KEY = '${GOOGLE_API_KEY}';
+const GEMINI_IMAGE_KEY = '${GOOGLE_API_KEY}';
 const ROOM_APP_URL = 'http://localhost:3075/api/generate-room';
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
 const COMMERCIAL_VENDORS = new Set([
   'koroseal', 'designtex', 'versa', 'knoll', 'wolf_gordon',
diff --git a/shopify/scripts/bespoke-updater/server.js b/shopify/scripts/bespoke-updater/server.js
index ef64a90e..d6a66e2f 100644
--- a/shopify/scripts/bespoke-updater/server.js
+++ b/shopify/scripts/bespoke-updater/server.js
@@ -21,7 +21,7 @@ app.use(express.json());
 const PORT = 9870;
 const SHOPIFY_DOMAIN = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_TOKEN = '***REMOVED***';
-const GEMINI_API_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_API_KEY = '${GOOGLE_API_KEY}';
 
 // Bespoke vendor variations
 const BESPOKE_VENDORS = [
diff --git a/shopify/scripts/classify-texture-pattern.js b/shopify/scripts/classify-texture-pattern.js
index 5eb0494b..83e2397c 100644
--- a/shopify/scripts/classify-texture-pattern.js
+++ b/shopify/scripts/classify-texture-pattern.js
@@ -7,7 +7,7 @@
 const { Pool } = require('pg');
 
 const pool = new Pool({ connectionString: 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified' });
-const GEMINI_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_KEY = '${GOOGLE_API_KEY}';
 const GEMINI_URL = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${GEMINI_KEY}`;
 
 const PROMPT = `Is this wallcovering image a repeating pattern or a non-repeating texture? If it's a texture (grasscloth, linen, plain, solid, stucco, metallic, stone, concrete, weave, etc.), respond 'TEXTURE'. If it has a visible repeating pattern (florals, stripes, damask, geometric, medallion, toile, animals, scenic, etc.), respond 'PATTERN'. Respond with only one word: TEXTURE or PATTERN.`;
diff --git a/shopify/scripts/cron-create-sample-variants.sh b/shopify/scripts/cron-create-sample-variants.sh
index 3ffe7f8d..96b04370 100755
--- a/shopify/scripts/cron-create-sample-variants.sh
+++ b/shopify/scripts/cron-create-sample-variants.sh
@@ -22,7 +22,7 @@ if [ -f "$PROGRESS_FILE" ]; then
     # Send Slack notification
     curl -s -X POST -H 'Content-type: application/json' \
       --data '{"text":"✅ *Sample Variant Fix Complete*\nAll 1,359 missing sample variants have been created and inventory set to 2026."}' \
-      "https://hooks.slack.com/services/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"
+      "${SLACK_WEBHOOK_URL}"
 
     exit 0
   fi
diff --git a/shopify/scripts/fix-missing-samples.js b/shopify/scripts/fix-missing-samples.js
index 24ce5b4e..17f2778b 100644
--- a/shopify/scripts/fix-missing-samples.js
+++ b/shopify/scripts/fix-missing-samples.js
@@ -278,7 +278,7 @@ async function main() {
   // Slack
   const msg = `${dailyLimit ? '⚠️' : '✅'} *Sample Variant Fix*\n• Scanned: ${totalScanned}\n• Missing: ${missing.length}\n• Fixed: ${fixedCount}\n• Errors: ${errorCount}${dailyLimit ? `\n• Remaining: ${missing.length - fixedCount}` : ''}`;
   try {
-    await fetch('https://hooks.slack.com/services/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', {
+    await fetch('${SLACK_WEBHOOK_URL}', {
       method: 'POST', headers: { 'Content-Type': 'application/json' },
       body: JSON.stringify({ text: msg }),
     });
diff --git a/shopify/scripts/fix-sample-inventory-only.js b/shopify/scripts/fix-sample-inventory-only.js
index f7e07faf..a2ecd85e 100644
--- a/shopify/scripts/fix-sample-inventory-only.js
+++ b/shopify/scripts/fix-sample-inventory-only.js
@@ -14,7 +14,7 @@ const LOCATION_GID = 'gid://shopify/Location/5795643504';
 const TARGET_QTY = 2026;
 const RESULTS_DIR = '/root/Projects/Designer-Wallcoverings/shopify/scripts';
 const REPORT_FILE = `${RESULTS_DIR}/sample-variant-audit-report.json`;
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
 function sleep(ms) { return new Promise(r => setTimeout(r, ms)); }
 
diff --git a/shopify/scripts/fix-samples-graphql.js b/shopify/scripts/fix-samples-graphql.js
index 0bfcd19f..27eac215 100644
--- a/shopify/scripts/fix-samples-graphql.js
+++ b/shopify/scripts/fix-samples-graphql.js
@@ -234,7 +234,7 @@ async function createSampleVariant(productId, optionName, baseSku) {
 }
 
 async function notifySlack(message) {
-  const webhook = 'https://hooks.slack.com/services/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';
+  const webhook = '${SLACK_WEBHOOK_URL}';
   return new Promise((resolve) => {
     const body = JSON.stringify({ text: message });
     const url = new URL(webhook);
diff --git a/shopify/scripts/fix-zero-inventory-samples.js b/shopify/scripts/fix-zero-inventory-samples.js
index 0735743c..d91b7a5b 100644
--- a/shopify/scripts/fix-zero-inventory-samples.js
+++ b/shopify/scripts/fix-zero-inventory-samples.js
@@ -149,7 +149,7 @@ async function main() {
     const msg = JSON.stringify({
       text: `📦 *Zero-Inv Sample Fix*\n• Fixed: ${fixed}/${all.length} → qty ${TARGET_QTY}\n• Failed: ${failed}\n• Duration: ${mins}m`
     });
-    const url = new URL('https://hooks.slack.com/services/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');
+    const url = new URL('${SLACK_WEBHOOK_URL}');
     const sr = https.request({
       hostname: url.hostname, path: url.pathname, method: 'POST',
       headers: { 'Content-Type': 'application/json' }
diff --git a/shopify/scripts/gemini-catalog-tagger.js b/shopify/scripts/gemini-catalog-tagger.js
index bb29f0a9..8234baf9 100644
--- a/shopify/scripts/gemini-catalog-tagger.js
+++ b/shopify/scripts/gemini-catalog-tagger.js
@@ -18,9 +18,9 @@ const nodeFetch = require('node-fetch');
 const fetch = typeof nodeFetch === 'function' ? nodeFetch : nodeFetch.default;
 
 // ── Config ──────────────────────────────────────────────────────────────────
-const GEMINI_API_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_API_KEY = '${GOOGLE_API_KEY}';
 const GEMINI_URL = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${GEMINI_API_KEY}`;
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
 const pool = new Pool({
   connectionString: 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified',
diff --git a/shopify/scripts/gemini-tag-engine/index.js b/shopify/scripts/gemini-tag-engine/index.js
index 122a425a..67efae76 100644
--- a/shopify/scripts/gemini-tag-engine/index.js
+++ b/shopify/scripts/gemini-tag-engine/index.js
@@ -14,7 +14,7 @@ const https = require('https');
 const http = require('http');
 
 // ─── Config ───────────────────────────────────────────────────────────────────
-const GEMINI_API_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_API_KEY = '${GOOGLE_API_KEY}';
 const GEMINI_MODEL = 'gemini-2.0-flash';
 const GEMINI_URL = `https://generativelanguage.googleapis.com/v1beta/models/${GEMINI_MODEL}:generateContent?key=${GEMINI_API_KEY}`;
 
@@ -22,7 +22,7 @@ const SHOPIFY_STORE = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_TOKEN = '***REMOVED***';
 const SHOPIFY_API_VERSION = '2024-10';
 
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
 const DB_URL = 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified';
 
diff --git a/shopify/scripts/import-missing-dwrr.ts b/shopify/scripts/import-missing-dwrr.ts
index 632189f2..30b4d341 100644
--- a/shopify/scripts/import-missing-dwrr.ts
+++ b/shopify/scripts/import-missing-dwrr.ts
@@ -8,7 +8,7 @@
 const SHOPIFY_STORE = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_ACCESS_TOKEN = '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';
 const API_VERSION = '2024-01';
-const GEMINI_API_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_API_KEY = '${GOOGLE_API_KEY}';
 
 interface Product {
   handle: string;
diff --git a/shopify/scripts/interior-design-tagger.js b/shopify/scripts/interior-design-tagger.js
index c5b5ce41..52d6487d 100644
--- a/shopify/scripts/interior-design-tagger.js
+++ b/shopify/scripts/interior-design-tagger.js
@@ -16,7 +16,7 @@ const https = require('https');
 const http = require('http');
 
 // ─── Config ──────────────────────────────────────────────────────────────────
-const GEMINI_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_KEY = '${GOOGLE_API_KEY}';
 const GEMINI_MODEL = 'gemini-2.0-flash';
 const GEMINI_URL = `https://generativelanguage.googleapis.com/v1beta/models/${GEMINI_MODEL}:generateContent?key=${GEMINI_KEY}`;
 
@@ -24,7 +24,7 @@ const SHOPIFY_STORE = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_TOKEN = '***REMOVED***';
 const API_VERSION = '2024-10';
 
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
 const pool = new Pool({
   connectionString: 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified'
diff --git a/shopify/scripts/koroseal-complete-update.ts b/shopify/scripts/koroseal-complete-update.ts
index 96dfbbe4..60de2a0f 100644
--- a/shopify/scripts/koroseal-complete-update.ts
+++ b/shopify/scripts/koroseal-complete-update.ts
@@ -11,7 +11,7 @@ const SHOPIFY_STORE = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_ACCESS_TOKEN = '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';
 const API_VERSION = '2024-01';
 const NAMESPACE = 'dwc';
-const GEMINI_API_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_API_KEY = '${GOOGLE_API_KEY}';
 
 interface Product {
   id: string;
diff --git a/shopify/scripts/koroseal-enhanced-update.js b/shopify/scripts/koroseal-enhanced-update.js
index fa629d58..9f14b128 100644
--- a/shopify/scripts/koroseal-enhanced-update.js
+++ b/shopify/scripts/koroseal-enhanced-update.js
@@ -63,7 +63,7 @@ const SHOPIFY_STORE = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_TOKEN = '***REMOVED***';
 const API_VERSION = '2024-01';
 // Gemini Configuration (MANDATORY - No Claude Vision)
-const GEMINI_API_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_API_KEY = '${GOOGLE_API_KEY}';
 const GEMINI_MODEL = 'gemini-2.0-flash';
 // Authentication credentials
 const AUTH_USER = 'admin';
diff --git a/shopify/scripts/koroseal-update.js b/shopify/scripts/koroseal-update.js
index 335fcd20..1046ac6b 100644
--- a/shopify/scripts/koroseal-update.js
+++ b/shopify/scripts/koroseal-update.js
@@ -11,7 +11,7 @@ const SHOPIFY_STORE = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_ACCESS_TOKEN = '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';
 const API_VERSION = '2024-01';
 const NAMESPACE = 'dwc';
-const GEMINI_API_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_API_KEY = '${GOOGLE_API_KEY}';
 
 // Resume from index (0-based) - pass as command line arg
 const START_INDEX = parseInt(process.argv[2]) || 0;
diff --git a/shopify/scripts/migrate-mckenzie-global-to-custom.js b/shopify/scripts/migrate-mckenzie-global-to-custom.js
new file mode 100644
index 00000000..dd3326fd
--- /dev/null
+++ b/shopify/scripts/migrate-mckenzie-global-to-custom.js
@@ -0,0 +1,136 @@
+#!/usr/bin/env node
+/**
+ * Brand McKenzie — migrate every global.* metafield to custom.*, then delete global.
+ * Idempotent. Mapping for differently-named pairs:
+ *   global.lead_time  -> custom.delivery_time   (already populated by prior run)
+ * For everything else, copies value to custom.<same key> only if custom.<key> is empty.
+ */
+
+const STORE = 'designer-laboratory-sandbox.myshopify.com';
+const TOKEN = process.env.SHOPIFY_ADMIN_TOKEN || '***REMOVED***';
+const VENDOR = 'Brand McKenzie';
+
+const KEY_REMAP = { lead_time: 'delivery_time' }; // global.<k> -> custom.<remap[k]||k>
+
+const log = (m) => console.log(`[${new Date().toLocaleTimeString()}] ${m}`);
+
+async function gql(query, variables = {}) {
+  const r = await fetch(`https://${STORE}/admin/api/2024-10/graphql.json`, {
+    method: 'POST',
+    headers: { 'Content-Type': 'application/json', 'X-Shopify-Access-Token': TOKEN },
+    body: JSON.stringify({ query, variables })
+  });
+  return r.json();
+}
+
+async function fetchProducts() {
+  const all = [];
+  let cursor = null;
+  while (true) {
+    const q = `
+      query($q: String!, $cursor: String) {
+        products(first: 50, query: $q, after: $cursor) {
+          edges { cursor node { id title metafields(first: 50) { edges { node { id namespace key value type } } } } }
+          pageInfo { hasNextPage endCursor }
+        }
+      }`;
+    const res = await gql(q, { q: `vendor:"${VENDOR}"`, cursor });
+    if (res.errors) throw new Error(JSON.stringify(res.errors));
+    for (const e of res.data.products.edges) all.push(e.node);
+    if (!res.data.products.pageInfo.hasNextPage) break;
+    cursor = res.data.products.pageInfo.endCursor;
+    await new Promise(r => setTimeout(r, 200));
+  }
+  return all;
+}
+
+async function setMetafields(productId, mfs) {
+  if (!mfs.length) return { ok: 0 };
+  const m = `
+    mutation($mfs: [MetafieldsSetInput!]!) {
+      metafieldsSet(metafields: $mfs) {
+        metafields { id }
+        userErrors { field message }
+      }
+    }`;
+  const inputs = mfs.map(f => ({
+    ownerId: productId,
+    namespace: f.namespace, key: f.key, type: f.type, value: f.value
+  }));
+  const res = await gql(m, { mfs: inputs });
+  const errs = res.errors || res.data?.metafieldsSet?.userErrors;
+  if (errs && errs.length) throw new Error('SET: ' + JSON.stringify(errs));
+  return { ok: res.data.metafieldsSet.metafields.length };
+}
+
+async function deleteMetafields(ids) {
+  if (!ids.length) return { ok: 0 };
+  const m = `
+    mutation($ids: [ID!]!) {
+      metafieldsDelete(metafields: $ids) {
+        deletedMetafields { key namespace }
+        userErrors { field message }
+      }
+    }`;
+  // Shopify's metafieldsDelete actually takes [MetafieldIdentifierInput!]!, but for products
+  // we can use metafieldDelete one-by-one. Use metafieldDelete loop.
+  let ok = 0;
+  for (const id of ids) {
+    const single = `
+      mutation($input: MetafieldDeleteInput!) {
+        metafieldDelete(input: $input) {
+          deletedId
+          userErrors { field message }
+        }
+      }`;
+    const res = await gql(single, { input: { id } });
+    const errs = res.errors || res.data?.metafieldDelete?.userErrors;
+    if (errs && errs.length) throw new Error('DEL: ' + JSON.stringify(errs));
+    ok++;
+    await new Promise(r => setTimeout(r, 120));
+  }
+  return { ok };
+}
+
+(async () => {
+  log(`Fetching products for vendor "${VENDOR}"…`);
+  const products = await fetchProducts();
+  log(`Found ${products.length} products.`);
+
+  let totalCopied = 0, totalDeleted = 0, totalSkippedNonGlobal = 0, fail = 0;
+
+  for (let i = 0; i < products.length; i++) {
+    const p = products[i];
+    const mfs = p.metafields.edges.map(e => e.node);
+    const globals = mfs.filter(m => m.namespace === 'global');
+    if (!globals.length) continue;
+
+    // Build set+delete plan
+    const toSet = [];
+    const toDelete = globals.map(g => g.id);
+
+    for (const g of globals) {
+      const targetKey = KEY_REMAP[g.key] || g.key;
+      const existingCustom = mfs.find(m => m.namespace === 'custom' && m.key === targetKey);
+      if (!existingCustom || !existingCustom.value || !existingCustom.value.trim()) {
+        toSet.push({ namespace: 'custom', key: targetKey, type: g.type, value: g.value });
+      }
+    }
+
+    try {
+      const setRes = await setMetafields(p.id, toSet);
+      const delRes = await deleteMetafields(toDelete);
+      totalCopied += setRes.ok;
+      totalDeleted += delRes.ok;
+      if (i % 10 === 0 || i === products.length - 1) {
+        log(`[${i+1}/${products.length}] ${p.title.substring(0,55)} — copied=${setRes.ok}, deleted=${delRes.ok}`);
+      }
+    } catch (e) {
+      fail++;
+      log(`FAIL ${p.title.substring(0,55)}: ${e.message.substring(0,200)}`);
+    }
+    await new Promise(r => setTimeout(r, 250));
+  }
+
+  log(`Done. copied=${totalCopied} deleted=${totalDeleted} fail=${fail}`);
+})().catch(e => { console.error('FATAL', e); process.exit(1); });
diff --git a/shopify/scripts/prl-ai-enrich.js b/shopify/scripts/prl-ai-enrich.js
index 1340244f..935556f1 100644
--- a/shopify/scripts/prl-ai-enrich.js
+++ b/shopify/scripts/prl-ai-enrich.js
@@ -5,7 +5,7 @@
  */
 const https = require('https');
 const { Pool } = require('pg');
-const GEMINI_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_KEY = '${GOOGLE_API_KEY}';
 const GEMINI_MODEL = 'gemini-2.0-flash';
 const GEMINI_URL = `https://generativelanguage.googleapis.com/v1beta/models/${GEMINI_MODEL}:generateContent?key=${GEMINI_KEY}`;
 const BATCH_LIMIT = 100;
@@ -189,7 +189,7 @@ async function main() {
       text: `🎨 *PRL AI Enrichment Complete*\n• Success: ${success} | Failed: ${failed}\n• Remaining: ${remaining[0].c}\n• Duration: ${elapsed} min`
     });
     await new Promise((resolve, reject) => {
-      const req = https.request('https://hooks.slack.com/services/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', {
+      const req = https.request('${SLACK_WEBHOOK_URL}', {
         method: 'POST',
         headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(slackMsg) }
       }, res => { res.resume(); resolve(); });
diff --git a/shopify/scripts/push-fire-rating-metafields.js b/shopify/scripts/push-fire-rating-metafields.js
index c1ca97da..027a1c31 100644
--- a/shopify/scripts/push-fire-rating-metafields.js
+++ b/shopify/scripts/push-fire-rating-metafields.js
@@ -212,7 +212,7 @@ async function main() {
   try {
     const slackPayload = JSON.stringify({ text: slackMsg });
     await new Promise((resolve, reject) => {
-      const url = new URL('https://hooks.slack.com/services/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');
+      const url = new URL('${SLACK_WEBHOOK_URL}');
       const opts = {
         hostname: url.hostname,
         path: url.pathname,
diff --git a/shopify/scripts/push-pattern-repeat-metafields.js b/shopify/scripts/push-pattern-repeat-metafields.js
index 4b165221..ca0bd010 100644
--- a/shopify/scripts/push-pattern-repeat-metafields.js
+++ b/shopify/scripts/push-pattern-repeat-metafields.js
@@ -22,7 +22,7 @@ const BATCH_SIZE = 25;
 const DELAY_MS = 500;
 const EXCLUDED_VENDORS = ['phillip_jeffries', 'cowtan_tout', 'colefax_fowler'];
 
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
 function sleep(ms) { return new Promise(r => setTimeout(r, ms)); }
 
diff --git a/shopify/scripts/resume-sample-variant-creation.js b/shopify/scripts/resume-sample-variant-creation.js
index 1b7ba6c3..29acccfd 100644
--- a/shopify/scripts/resume-sample-variant-creation.js
+++ b/shopify/scripts/resume-sample-variant-creation.js
@@ -23,7 +23,7 @@ const DELAY_MS = 400;
 const DIR = '/root/Projects/Designer-Wallcoverings/shopify/scripts';
 const AUDIT_FILE = `${DIR}/sample-variant-audit-report.json`;
 const PROGRESS_FILE = `${DIR}/sample-variant-creation-progress.json`;
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
 function sleep(ms) { return new Promise(r => setTimeout(r, ms)); }
 
diff --git a/shopify/scripts/revert-dwcy-pass2.js b/shopify/scripts/revert-dwcy-pass2.js
index eb27efc0..dd6e9b75 100644
--- a/shopify/scripts/revert-dwcy-pass2.js
+++ b/shopify/scripts/revert-dwcy-pass2.js
@@ -15,7 +15,7 @@ const ACCESS_TOKEN = '***REMOVED***';
 const API_VERSION = '2024-10';
 const GRAPHQL_URL = `https://${SHOPIFY_DOMAIN}/admin/api/${API_VERSION}/graphql.json`;
 const REST_URL = `https://${SHOPIFY_DOMAIN}/admin/api/${API_VERSION}`;
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
 const BATCH_SIZE = 2;
 const BATCH_DELAY_MS = 1100;
diff --git a/shopify/scripts/revert-dwcy-to-dwc.js b/shopify/scripts/revert-dwcy-to-dwc.js
index 88ffe4c8..4282bc03 100644
--- a/shopify/scripts/revert-dwcy-to-dwc.js
+++ b/shopify/scripts/revert-dwcy-to-dwc.js
@@ -17,7 +17,7 @@ const API_VERSION = '2024-10';
 const GRAPHQL_URL = `https://${SHOPIFY_DOMAIN}/admin/api/${API_VERSION}/graphql.json`;
 const REST_URL = `https://${SHOPIFY_DOMAIN}/admin/api/${API_VERSION}`;
 
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
 // Rate limiting for REST API (standard plan: 2/s, 40 bucket)
 const BATCH_SIZE = 2;
diff --git a/shopify/scripts/review-dwqw-images-descriptions.ts b/shopify/scripts/review-dwqw-images-descriptions.ts
index 50480c72..0e5ecc12 100644
--- a/shopify/scripts/review-dwqw-images-descriptions.ts
+++ b/shopify/scripts/review-dwqw-images-descriptions.ts
@@ -12,7 +12,7 @@
 const SHOPIFY_STORE = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_ACCESS_TOKEN = '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';
 const API_VERSION = '2024-01';
-const GEMINI_API_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_API_KEY = '${GOOGLE_API_KEY}';
 
 // DWQW Handle to MFR# mapping
 const DWQW_PRODUCTS: { [handle: string]: string } = {
diff --git a/shopify/scripts/romo-lookup.js b/shopify/scripts/romo-lookup.js
index 386f9d84..bb74cb0e 100644
--- a/shopify/scripts/romo-lookup.js
+++ b/shopify/scripts/romo-lookup.js
@@ -16,7 +16,7 @@ const SHOPIFY_DOMAIN = "designer-laboratory-sandbox.myshopify.com";
 const SHOPIFY_TOKEN = "***REMOVED***";
 const LOG_FILE = "/tmp/romo-lookup.log";
 const RESULTS_FILE = "/tmp/romo-lookup-results.json";
-const SLACK_WEBHOOK = "https://hooks.slack.com/services/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";
+const SLACK_WEBHOOK = "${SLACK_WEBHOOK_URL}";
 
 const UNMATCHED = {
   "Santiago Metal Stripe": ["73500"],
diff --git a/shopify/scripts/schumacher-price-scraper.js b/shopify/scripts/schumacher-price-scraper.js
index aa965f6b..63fef822 100644
--- a/shopify/scripts/schumacher-price-scraper.js
+++ b/shopify/scripts/schumacher-price-scraper.js
@@ -45,7 +45,7 @@ const CONFIG = {
   LOG_FILE: '/tmp/schumacher-price.log',
   PROGRESS_FILE: '/tmp/schumacher-price-progress.json',
 
-  SLACK_WEBHOOK: 'https://hooks.slack.com/services/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',
+  SLACK_WEBHOOK: '${SLACK_WEBHOOK_URL}',
 };
 
 // ─── Logging ─────────────────────────────────────────────────────────────────
diff --git a/shopify/scripts/set-texture-repeat-zero.js b/shopify/scripts/set-texture-repeat-zero.js
index 6f0150d7..b1d900d4 100644
--- a/shopify/scripts/set-texture-repeat-zero.js
+++ b/shopify/scripts/set-texture-repeat-zero.js
@@ -16,7 +16,7 @@ const { trackGeminiCall } = require('/root/DW-Agents/shared/gemini-cost-tracker'
 
 const pool = new Pool({ connectionString: 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified' });
 
-const GEMINI_API_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_API_KEY = '${GOOGLE_API_KEY}';
 const GEMINI_MODEL = 'gemini-2.0-flash';
 const GEMINI_URL = `https://generativelanguage.googleapis.com/v1beta/models/${GEMINI_MODEL}:generateContent?key=${GEMINI_API_KEY}`;
 
@@ -322,7 +322,7 @@ async function main() {
   try {
     const http = require('http');
     const slackData = JSON.stringify({ text: slackMsg });
-    const slackUrl = new URL('https://hooks.slack.com/services/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');
+    const slackUrl = new URL('${SLACK_WEBHOOK_URL}');
     await new Promise((resolve) => {
       const req = https.request({
         hostname: slackUrl.hostname,
diff --git a/shopify/scripts/texture-repeat-fixer.js b/shopify/scripts/texture-repeat-fixer.js
index 32b836b6..b43d846c 100644
--- a/shopify/scripts/texture-repeat-fixer.js
+++ b/shopify/scripts/texture-repeat-fixer.js
@@ -16,9 +16,9 @@ const https = require('https');
 const http = require('http');
 
 const DB_URL = 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified';
-const GEMINI_API_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_API_KEY = '${GOOGLE_API_KEY}';
 const GEMINI_URL = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${GEMINI_API_KEY}`;
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
 const TEXTURE_REGEX = /\b(grasscloth|texture[ds]?|linen|stucco|metallic|plain|solid|sisal|weave|burlap|faux\s|jute|suede|cork|hemp|raffia|sand|stone|concrete|plaster|canvas|liner|backing|primer|vinyl\s*texture|mica|pebble|slate|marble|travertine|leather|silk\s*texture|raw\s*silk|shantung|dupioni|chambray|satin\s*weave|twill|herringbone\s*weave|basket\s*weave|matte|brushed|hammered)\b/i;
 
diff --git a/shopify/scripts/thibaut-repeat-scraper.js b/shopify/scripts/thibaut-repeat-scraper.js
index c97dc2b4..fca27ca7 100644
--- a/shopify/scripts/thibaut-repeat-scraper.js
+++ b/shopify/scripts/thibaut-repeat-scraper.js
@@ -14,7 +14,7 @@ const pool = new Pool({
   connectionString: 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified'
 });
 
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 const BATCH_SIZE = 5;       // concurrent requests
 const DELAY_MS = 1500;      // delay between batches
 const MAX_PRODUCTS = 200;   // limit per run
diff --git a/shopify/scripts/update-all-malibu-architectural.ts b/shopify/scripts/update-all-malibu-architectural.ts
index 34e75100..16348f47 100644
--- a/shopify/scripts/update-all-malibu-architectural.ts
+++ b/shopify/scripts/update-all-malibu-architectural.ts
@@ -27,7 +27,7 @@ const PAPER_TAGS_TO_REMOVE = ['Paper', 'Non-woven', 'Non-Woven Paper', 'Uncoated
 
 const SHOPIFY_STORE = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_ACCESS_TOKEN = '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';
-const GEMINI_API_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_API_KEY = '${GOOGLE_API_KEY}';
 const PROGRESS_FILE = '/root/Projects/Designer-Wallcoverings/shopify/scripts/malibu-update-progress.json';
 
 // ONLY processing Type 2 Vinyls vendor
diff --git a/shopify/scripts/update-dwk-full-details.js b/shopify/scripts/update-dwk-full-details.js
index be5f7ad3..fef5e7c3 100644
--- a/shopify/scripts/update-dwk-full-details.js
+++ b/shopify/scripts/update-dwk-full-details.js
@@ -12,7 +12,7 @@ const cheerio = require('cheerio');
 
 const SHOPIFY_STORE = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_TOKEN = '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';
-const GEMINI_API_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_API_KEY = '${GOOGLE_API_KEY}';
 const KOROSEAL_BASE = 'https://koroseal.com';
 
 // Fetch products needing update
diff --git a/shopify/scripts/update-dwk-slow-seo.js b/shopify/scripts/update-dwk-slow-seo.js
index e2b4a4d5..32c99bae 100644
--- a/shopify/scripts/update-dwk-slow-seo.js
+++ b/shopify/scripts/update-dwk-slow-seo.js
@@ -14,7 +14,7 @@ const fs = require('fs');
 
 const SHOPIFY_STORE = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_TOKEN = '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';
-const GEMINI_API_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_API_KEY = '${GOOGLE_API_KEY}';
 const KOROSEAL_BASE = 'https://koroseal.com';
 
 const DELAY_BETWEEN_PRODUCTS = 6 * 60 * 1000; // 6 minutes
diff --git a/shopify/scripts/update-dwqw-complete.ts b/shopify/scripts/update-dwqw-complete.ts
index 70ed4c84..29d9f819 100644
--- a/shopify/scripts/update-dwqw-complete.ts
+++ b/shopify/scripts/update-dwqw-complete.ts
@@ -12,7 +12,7 @@
 const SHOPIFY_STORE = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_ACCESS_TOKEN = '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';
 const API_VERSION = '2024-01';
-const GEMINI_API_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_API_KEY = '${GOOGLE_API_KEY}';
 
 const DWQW_PRODUCTS: { [key: string]: string } = {
   'dwqw-56000-handle': 'MB30000', 'dwqw-56001-handle': 'MB30002', 'dwqw-56002-handle': 'MB30004',
diff --git a/shopify/scripts/update-dwqw-malibu-architectural.ts b/shopify/scripts/update-dwqw-malibu-architectural.ts
index cc70e39a..39892f84 100644
--- a/shopify/scripts/update-dwqw-malibu-architectural.ts
+++ b/shopify/scripts/update-dwqw-malibu-architectural.ts
@@ -13,7 +13,7 @@
 const SHOPIFY_STORE = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_ACCESS_TOKEN = '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';
 const API_VERSION = '2024-01';
-const GEMINI_API_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_API_KEY = '${GOOGLE_API_KEY}';
 
 // Handle to MFR# mapping from spreadsheet
 const HANDLE_TO_MFR: { [key: string]: string } = {
diff --git a/shopify/scripts/update-dwrr-descriptions-quantities.ts b/shopify/scripts/update-dwrr-descriptions-quantities.ts
index 30e11616..6fb07a2f 100644
--- a/shopify/scripts/update-dwrr-descriptions-quantities.ts
+++ b/shopify/scripts/update-dwrr-descriptions-quantities.ts
@@ -11,7 +11,7 @@ const SHOPIFY_STORE = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_ACCESS_TOKEN = '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';
 const API_VERSION = '2024-01';
 const NAMESPACE = 'dwc';
-const GEMINI_API_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_API_KEY = '${GOOGLE_API_KEY}';
 
 // Product data with pattern/color info
 const PRODUCTS = [
diff --git a/shopify/scripts/update-dwrr-gemini.ts b/shopify/scripts/update-dwrr-gemini.ts
index 916f27f2..7ecaff22 100644
--- a/shopify/scripts/update-dwrr-gemini.ts
+++ b/shopify/scripts/update-dwrr-gemini.ts
@@ -10,7 +10,7 @@ const SHOPIFY_STORE = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_ACCESS_TOKEN = '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';
 const API_VERSION = '2024-01';
 const NAMESPACE = 'dwc';
-const GEMINI_API_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_API_KEY = '${GOOGLE_API_KEY}';
 
 // Product data with colors from spreadsheet
 const PRODUCTS = [
diff --git a/shopify/scripts/update-koroseal-gemini.ts b/shopify/scripts/update-koroseal-gemini.ts
index f581c21c..64c6ebb6 100644
--- a/shopify/scripts/update-koroseal-gemini.ts
+++ b/shopify/scripts/update-koroseal-gemini.ts
@@ -8,7 +8,7 @@ const SHOPIFY_STORE = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_ACCESS_TOKEN = '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';
 const API_VERSION = '2024-01';
 const NAMESPACE = 'dwc';
-const GEMINI_API_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_API_KEY = '${GOOGLE_API_KEY}';
 
 interface Product {
   id: string;
diff --git a/shopify/scripts/update-mckenzie-delivery.js b/shopify/scripts/update-mckenzie-delivery.js
new file mode 100644
index 00000000..ee5e4789
--- /dev/null
+++ b/shopify/scripts/update-mckenzie-delivery.js
@@ -0,0 +1,94 @@
+#!/usr/bin/env node
+/**
+ * Brand McKenzie — set lead time to 4-6 Weeks.
+ * - Append <p><strong>4-6 Week Delivery</strong></p> to body (idempotent)
+ * - Set global.lead_time metafield to "4-6 Weeks"
+ */
+
+const STORE = 'designer-laboratory-sandbox.myshopify.com';
+const TOKEN = process.env.SHOPIFY_ADMIN_TOKEN || '***REMOVED***';
+const VENDOR = 'Brand McKenzie';
+const DELIVERY_HTML = '<p>&nbsp;<strong>2-4 Week Delivery</strong></p>';
+const LEAD_TIME = '2-4 Weeks';
+
+const log = (m) => console.log(`[${new Date().toLocaleTimeString()}] ${m}`);
+
+async function gql(query, variables = {}) {
+  const r = await fetch(`https://${STORE}/admin/api/2024-10/graphql.json`, {
+    method: 'POST',
+    headers: { 'Content-Type': 'application/json', 'X-Shopify-Access-Token': TOKEN },
+    body: JSON.stringify({ query, variables })
+  });
+  return r.json();
+}
+
+async function fetchAll() {
+  const all = [];
+  let cursor = null;
+  while (true) {
+    const q = `
+      query($q: String!, $cursor: String) {
+        products(first: 100, query: $q, after: $cursor) {
+          edges { cursor node { id title descriptionHtml metafield(namespace:"global", key:"lead_time"){ id value } } }
+          pageInfo { hasNextPage endCursor }
+        }
+      }`;
+    const res = await gql(q, { q: `vendor:"${VENDOR}"`, cursor });
+    if (res.errors) throw new Error(JSON.stringify(res.errors));
+    for (const e of res.data.products.edges) all.push(e.node);
+    if (!res.data.products.pageInfo.hasNextPage) break;
+    cursor = res.data.products.pageInfo.endCursor;
+  }
+  return all;
+}
+
+async function updateProduct(p) {
+  const hasLine = (p.descriptionHtml || '').toLowerCase().includes('4-6 week delivery');
+  let newBody = p.descriptionHtml || '';
+  if (!hasLine) newBody = `${newBody}\n${DELIVERY_HTML}`;
+  // Strip any existing "X-Y Week Delivery" lines (with or without leading &nbsp;) so we can append the canonical one
+  newBody = newBody.replace(/<p>(?:&nbsp;|\s)*<strong>\s*\d+\s*-\s*\d+\s*Week Delivery\s*<\/strong>\s*<\/p>\s*/gi, '');
+  newBody = `${newBody.replace(/\s+$/,'')}\n${DELIVERY_HTML}`;
+
+  const mutation = `
+    mutation($input: ProductInput!) {
+      productUpdate(input: $input) {
+        product { id }
+        userErrors { field message }
+      }
+    }`;
+  const input = {
+    id: p.id,
+    descriptionHtml: newBody,
+    metafields: [
+      { namespace: 'global', key: 'lead_time',     type: 'single_line_text_field', value: LEAD_TIME },
+      { namespace: 'custom', key: 'delivery_time', type: 'single_line_text_field', value: LEAD_TIME }
+    ]
+  };
+  const res = await gql(mutation, { input });
+  const errs = res.errors || res.data?.productUpdate?.userErrors;
+  if (errs && errs.length) throw new Error(JSON.stringify(errs));
+  return true;
+}
+
+(async () => {
+  log(`Fetching products for vendor "${VENDOR}"…`);
+  const products = await fetchAll();
+  log(`Found ${products.length} products.`);
+  let ok = 0, fail = 0;
+  for (let i = 0; i < products.length; i++) {
+    const p = products[i];
+    try {
+      await updateProduct(p);
+      ok++;
+      if (i % 10 === 0 || i === products.length - 1) {
+        log(`[${i + 1}/${products.length}] ${p.title.substring(0, 60)}`);
+      }
+    } catch (e) {
+      fail++;
+      log(`FAIL ${p.title.substring(0, 60)}: ${e.message.substring(0, 200)}`);
+    }
+    await new Promise(r => setTimeout(r, 350));
+  }
+  log(`Done. ok=${ok} fail=${fail}`);
+})().catch(e => { console.error('FATAL', e); process.exit(1); });
diff --git a/shopify/scripts/update-rop-mfr.py b/shopify/scripts/update-rop-mfr.py
index 2b418d5c..e8b25095 100644
--- a/shopify/scripts/update-rop-mfr.py
+++ b/shopify/scripts/update-rop-mfr.py
@@ -17,7 +17,7 @@ SHOPIFY_TOKEN = "***REMOVED***"
 API_VERSION = "2024-01"
 GRAPHQL_URL = f"https://{SHOPIFY_DOMAIN}/admin/api/{API_VERSION}/graphql.json"
 FMPRO_CSV = "/root/Projects/Designer-Wallcoverings/shopify/scripts/fmpro-master.csv"
-SLACK_WEBHOOK = "https://hooks.slack.com/services/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"
+SLACK_WEBHOOK = "${SLACK_WEBHOOK_URL}"
 
 LOG_FILE = "/tmp/rop-mfr-update.log"
 start_time = datetime.now()
diff --git a/shopify/scripts/wolf-gordon-shopify-push.js b/shopify/scripts/wolf-gordon-shopify-push.js
index bdb92891..bf3d2f3d 100644
--- a/shopify/scripts/wolf-gordon-shopify-push.js
+++ b/shopify/scripts/wolf-gordon-shopify-push.js
@@ -36,7 +36,7 @@ const VENDOR_CODE = 'wolf_gordon';
 const VENDOR_DISPLAY = 'Wolf Gordon';
 const DEFAULT_FIRE_RATING = 'Class A Fire Rated : Passes ASTM E84';
 const LAUNCH_PAD_BATCH = 25;
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 
 function toTitleCase(str) {
   if (!str) return '';
diff --git a/shopify/scripts/zoffany-full-monty-20.js b/shopify/scripts/zoffany-full-monty-20.js
index dcaf5eda..aaff1783 100644
--- a/shopify/scripts/zoffany-full-monty-20.js
+++ b/shopify/scripts/zoffany-full-monty-20.js
@@ -32,10 +32,10 @@ const DB_URL = 'postgresql://dw_admin:DW2024SecurePass@127.0.0.1:5432/dw_unified
 const SHOPIFY_STORE = 'designer-laboratory-sandbox.myshopify.com';
 const SHOPIFY_TOKEN = '***REMOVED***';
 const API_VERSION = '2024-10';
-const GEMINI_KEY = 'REDACTED_GEMINI_KEY';
+const GEMINI_KEY = '${GOOGLE_API_KEY}';
 const GEMINI_URL = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${GEMINI_KEY}`;
 const ROOM_API = 'http://127.0.0.1:3075/api/generate-room';
-const SLACK_WEBHOOK = 'https://hooks.slack.com/services/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';
+const SLACK_WEBHOOK = '${SLACK_WEBHOOK_URL}';
 const SPIN_BASE_DIR = '/root/DW-Agents/spins/zoffany';
 const SPIN_BASE_URL = 'http://45.61.58.125/spins/zoffany';
 const VENDOR_PREFIX = 'DWZF-';
diff --git a/tasks/.gitignore b/tasks/.gitignore
new file mode 100644
index 00000000..7e6a9c3e
--- /dev/null
+++ b/tasks/.gitignore
@@ -0,0 +1,12 @@
+node_modules/
+.env
+.env.local
+.env.*.local
+.env.*
+tmp/
+*.log
+.DS_Store
+dist/
+build/
+.next/
+*.bak
diff --git a/vendor-logos/.gitignore b/vendor-logos/.gitignore
new file mode 100644
index 00000000..7e6a9c3e
--- /dev/null
+++ b/vendor-logos/.gitignore
@@ -0,0 +1,12 @@
+node_modules/
+.env
+.env.local
+.env.*.local
+.env.*
+tmp/
+*.log
+.DS_Store
+dist/
+build/
+.next/
+*.bak

← 4a4a1040 wire archive-guard into 5 cron-driven Shopify activators  ·  back to Designer Wallcoverings  ·  snapshot: backup uncommitted work (4 files) 872619c1 →