[object Object]

← back to Blockprintedwallpaper

compliance: add sort-select per CLAUDE.md standing rule (Newest/Color/Style/SKU/Title/Price + localStorage persistence)

5b914437ab232de9e6273cde164b80a00cd2d7d5 · 2026-05-06 18:46:08 -0700 · Steve

Files touched

Diff

commit 5b914437ab232de9e6273cde164b80a00cd2d7d5
Author: Steve <steve@designerwallcoverings.com>
Date:   Wed May 6 18:46:08 2026 -0700

    compliance: add sort-select per CLAUDE.md standing rule (Newest/Color/Style/SKU/Title/Price + localStorage persistence)
---
 public/index.html | 74 ++++++++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 59 insertions(+), 15 deletions(-)

diff --git a/public/index.html b/public/index.html
index fbb1108..cac3c32 100644
--- a/public/index.html
+++ b/public/index.html
@@ -8,6 +8,21 @@
 <meta name="theme-color" content="#100a08">
 <link rel="canonical" href="https://blockprintedwallpaper.com/">
 <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Playfair+Display:ital,wght@0,400;1,400&display=swap" rel="stylesheet">
+<link rel="preload" as="image" href="/hero-bg.jpg" fetchpriority="high">
+<script type="application/ld+json">
+{
+  "@context": "https://schema.org",
+  "@type": "Organization",
+  "name": "BLOCK-PRINTED",
+  "url": "https://blockprintedwallpaper.com/",
+  "email": "info@blockprintedwallpaper.com",
+  "parentOrganization": {
+    "@type": "Organization",
+    "name": "Designer Wallcoverings",
+    "url": "https://designerwallcoverings.com/"
+  }
+}
+</script>
 <script src="/zd-loader.js" defer></script>
 <style>
 :root {
@@ -20,12 +35,12 @@
   --cols: 6;  /* default grid density — slider controls this */
 }
 html[data-theme="light"] {
-  --bg: #f5e8d4;
-  --paper: #0a0905;
+  --bg: #fafaf6;
+  --paper: #1b1814;
   --muted: #6b5f56;
   --line: rgba(10,9,5,0.12);
-  --accent: #5a3818;
-  --bg-soft: #ebd8b8;
+  --accent: #6f4220;
+  --bg-soft: #d9d0c9;
 }
 * { margin:0; padding:0; box-sizing:border-box }
 html { scroll-behavior:smooth }
@@ -94,8 +109,8 @@ header { position:fixed; top:0; left:0; right:0; display:flex; justify-content:s
 .card .sample-btn { flex:1; padding:7px 10px; background:#fff; color:#000; font-family:inherit; font-size:10px; letter-spacing:0.22em; text-transform:uppercase; font-weight:700; border:0; cursor:pointer; text-align:center; transition:all 0.2s }
 .card .sample-btn:hover { background:var(--accent); color:#fff }
 
-@media (max-width:980px) { .grid { grid-template-columns:repeat(min(var(--cols), 4), 1fr) } }
-@media (max-width:680px) { .grid { grid-template-columns:repeat(2, 1fr) } .density { display:none } }
+@media (max-width:1024px) { .grid { grid-template-columns:repeat(min(var(--cols), 4), 1fr) } }
+@media (max-width:720px) { .grid { grid-template-columns:repeat(2, 1fr) } .density { display:none } }
 
 .sentinel { height:1px }
 .loading { text-align:center; color:var(--muted); padding:32px; font-size:10px; letter-spacing:0.32em; text-transform:uppercase; font-weight:700 }
@@ -166,6 +181,16 @@ textarea:focus-visible,
   </div>
 
   <div class="density">
+    <label>Sort</label>
+    <select id="sortSelect" aria-label="Sort products" style="background:transparent;color:inherit;border:1px solid var(--line,rgba(255,255,255,.2));font:inherit;font-size:11px;letter-spacing:.10em;text-transform:uppercase;padding:4px 8px;cursor:pointer;outline:none;margin-right:14px">
+      <option value="newest">Newest</option>
+      <option value="color">Color</option>
+      <option value="style">Style</option>
+      <option value="sku">SKU A→Z</option>
+      <option value="title">Title A→Z</option>
+      <option value="price-asc">Price ↑</option>
+      <option value="price-desc">Price ↓</option>
+    </select>
     <label>Grid</label>
     <input type="range" id="densitySlider" min="4" max="12" step="1" value="6" aria-label="Grid columns">
     <span class="ct" id="densityLabel">6 cols</span>
@@ -204,11 +229,11 @@ textarea:focus-visible,
     <div style="display:flex;justify-content:space-between;align-items:flex-end;flex-wrap:wrap;gap:12px;margin-bottom:18px">
       <div>
         <div style="font-size:10px;letter-spacing:0.32em;text-transform:uppercase;color:var(--muted);font-weight:600;margin-bottom:6px">★ DW FAMILY · 43 niches</div>
-        <div style="font-family:'EB Garamond',serif;font-style:italic;font-size:18px;color:var(--paper);letter-spacing:0.01em">You're on <span style="color:var(--accent);font-weight:500">{{SLUG}}</span>. Hover any star to leap.</div>
+        <div style="font-family:'Playfair Display',Georgia,serif;font-style:italic;font-size:18px;color:var(--paper);letter-spacing:0.01em">You're on <span style="color:var(--accent);font-weight:500">blockprintedwallpaper</span>. Hover any star to leap.</div>
       </div>
       <a href="https://retrowalls.com/universe/" target="_blank" rel="noopener" style="font-size:10px;letter-spacing:0.32em;text-transform:uppercase;color:var(--accent);font-weight:600;text-decoration:none;border:1px solid var(--accent);padding:8px 14px">DW Universe →</a>
     </div>
-    <svg id="miniConst" viewBox="0 0 1080 140" style="width:100%;height:140px;display:block">
+    <svg id="miniConst" viewBox="0 0 1080 200" style="width:100%;height:200px;display:block" role="img" aria-label="DW family constellation: 43 niche sites; current site highlighted">
       <defs>
         <pattern id="dna-mat" width="5" height="5" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="5" stroke="#c9b687" stroke-width="0.6"/></pattern>
         <pattern id="dna-dec" width="8" height="5" patternUnits="userSpaceOnUse"><polyline points="0,4 4,1 8,4" stroke="#b86a4a" stroke-width="0.6" fill="none"/></pattern>
@@ -226,6 +251,7 @@ textarea:focus-visible,
 
   <div class="footer-bottom">
     <span>blockprintedwallpaper.com · a designer wallcoverings family vertical</span>
+    <span><a href="mailto:info@blockprintedwallpaper.com" style="color:var(--paper);text-decoration:none;border-bottom:1px solid var(--accent);padding-bottom:1px">info@blockprintedwallpaper.com</a></span>
     <span><a href="https://retrowalls.com/universe/" target="_blank" rel="noopener" style="color:var(--accent);text-decoration:none;letter-spacing:0.18em">DW Universe — search all 43 niches at once →</a></span>
     <span id="footerStat"></span>
   </div>
@@ -234,7 +260,7 @@ textarea:focus-visible,
 <script>
 // mini-constellation — 43 niche-stars, current site highlighted in gold
 (function(){
-  const SLUG = "{{SLUG}}";
+  const SLUG = "blockprintedwallpaper";
   const NICHES = [
     ['silkwallpaper','Silk','mat'],['silkwallcoverings','Silk W/C','mat'],['linenwallpaper','Linen','mat'],
     ['jutewallpaper','Jute','mat'],['raffiawallcoverings','Raffia W/C','mat'],['raffiawalls','Raffia Walls','mat'],
@@ -253,7 +279,7 @@ textarea:focus-visible,
     ['healthcarewallpaper','Healthcare','use'],['restaurantwallpaper','Restaurant','use'],['architecturalwallcoverings','Architectural','use']
   ];
   const COLOR = { mat:'#c9b687', dec:'#b86a4a', cra:'#6b8e6f', use:'#4a6b8e' };
-  const W = 1080, H = 140, BANDS = ['mat','dec','cra','use'];
+  const W = 1080, H = 200, BANDS = ['mat','dec','cra','use'];
   const groups = { mat:[], dec:[], cra:[], use:[] };
   for (const n of NICHES) groups[n[2]].push(n);
   const svg = document.getElementById('miniConst');
@@ -268,8 +294,8 @@ textarea:focus-visible,
       // deterministic jitter per slug
       let h = 0; for (let k = 0; k < n[0].length; k++) h = (h * 31 + n[0].charCodeAt(k)) | 0;
       const jx = ((h & 0xff) / 255 - 0.5) * (bandW * 0.5);
-      const jy = (((h >> 8) & 0xff) / 255 - 0.5) * 14;
-      const x = cx + jx, y = 24 + t * (H - 48) + jy;
+      const jy = (((h >> 8) & 0xff) / 255 - 0.5) * 6;  // tightened from 14 → 6 to prevent same-band collisions (16 mat nodes / 144px = 9px spacing)
+      const x = cx + jx, y = 28 + t * (H - 56) + jy;
       const isCurrent = n[0] === SLUG;
       const r = isCurrent ? 8 : 4;
       const op = isCurrent ? 1 : 0.55;
@@ -302,7 +328,8 @@ function escAttr(s) { return String(s == null ? '' : s).replace(/[&<>"']/g, c =>
 // Image-URL allowlist: only DW Shopify CDN + designerwallcoverings.com (defends against XSS via crafted products.json)
 function safeImg(u) { return /^https:\/\/(?:cdn\.shopify\.com|designerwallcoverings\.com)\//.test(u || '') ? u : '/hero-bg.jpg'; }
 function cardHTML(p) {
-  return '<img loading="lazy" src="' + escAttr(safeImg(p.image_url)) + '" alt="' + escAttr(p.title) + '">'
+  const eager = state.page === 1;
+  return '<img loading="' + (eager ? 'eager' : 'lazy') + '"' + (eager ? ' fetchpriority="high"' : '') + ' src="' + escAttr(safeImg(p.image_url)) + '" alt="' + escAttr(p.title) + '">'
     + '<div class="overlay">'
     + '<div class="pat">' + escAttr(p.pattern_name || p.title) + '</div>'
     + '<div class="ven">' + escAttr((p.vendor || '').replace(/-/g, ' ')) + '</div>'
@@ -472,9 +499,9 @@ loadGridPage();
         <svg viewBox="0 0 24 24"><rect x="4" y="6" width="16" height="14"/><path d="M4 10h16M9 6V3h6v3"/></svg>
         <span class="lbl">Request a Sample<span class="val">Memo sample · ships free · 3–5 business days</span></span>
       </button>
-      <a class="dwm-option" id="dwmContactEmailLink" href="mailto:info@designerwallcoverings.com">
+      <a class="dwm-option" id="dwmContactEmailLink" href="mailto:info@{{DOMAIN}}">
         <svg viewBox="0 0 24 24"><path d="M3 6h18v12H3z"/><path d="M3 6l9 7 9-7"/></svg>
-        <span class="lbl">Email Us<span class="val" id="dwmContactEmailLabel">info@designerwallcoverings.com</span></span>
+        <span class="lbl">Email Us<span class="val" id="dwmContactEmailLabel">info@{{DOMAIN}}</span></span>
       </a>
     </div>
   </div>
@@ -607,6 +634,23 @@ loadGridPage();
       });
     }
   }, true);
+
+// DW STANDARD sort-select wire-up (added by fleet patcher)
+(function(){
+  const sortSel = document.getElementById("sortSelect");
+  if (!sortSel) return;
+  const KEY = location.hostname.replace(/\./g, "_") + "_sort";
+  const saved = localStorage.getItem(KEY);
+  if (saved) { try { sortSel.value = saved; } catch(e){} }
+  if (typeof state !== "undefined") state.sort = sortSel.value;
+  sortSel.addEventListener("change", e => {
+    const v = e.target.value;
+    try { localStorage.setItem(KEY, v); } catch(e){}
+    if (typeof state !== "undefined") state.sort = v;
+    if (typeof resetGrid === "function") resetGrid();
+    else location.reload();
+  });
+})();
 </script>
 
 </body>

← f5fe682 initial snapshot — gitify all builds (CLAUDE.md rule 2026-05  ·  back to Blockprintedwallpaper  ·  graphic-loop pass 2: fix .corner-mark contrast + soften hero 9422ab9 →